Skip to content

Commit

Permalink
use fallback sort when using in-element
Browse files Browse the repository at this point in the history
  • Loading branch information
amk221 committed Jan 23, 2025
1 parent dc3579d commit d4ee5e3
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 38 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 17.1.4

- Account for custom markup when sorting options internally

## 17.1.3

- Miniscule performance improvement
Expand Down
11 changes: 11 additions & 0 deletions addon/-private/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,14 @@ export function startsWithString(string, query) {
const b = removeDiacritics(normalise(query));
return a.startsWith(b);
}

export function sortOptionsFast(elements) {
return (a, b) => elements.indexOf(a.element) - elements.indexOf(b.element);
}

export function sortOptionsSlow(a, b) {
return a.element.compareDocumentPosition(b.element) ===
Node.DOCUMENT_POSITION_FOLLOWING
? -1
: 1;
}
44 changes: 16 additions & 28 deletions addon/components/select-box/index.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { on } from '@ember/modifier';
import { scheduleOnce } from '@ember/runloop';
import {
startsWithString,
pressingModifier
pressingModifier,
sortOptionsFast,
sortOptionsSlow
} from '@zestia/ember-select-box/-private/utils';
import { task } from 'ember-concurrency';
import { tracked } from 'tracked-built-ins';
Expand Down Expand Up @@ -183,35 +185,21 @@ export default class SelectBox extends Component {
return this.interactiveElement === document.activeElement;
}

@cached
get optionElements() {
return [
...new Set(this._options.map((option) => option.element.parentElement))
].reduce((optionElements, parentElement) => {
optionElements.push(
...parentElement.querySelectorAll('.select-box__option')
);
return optionElements;
}, []);
}

@cached
get options() {
return this._options
.filter((option) => !option.isDisabled)
.sort((a, b) => {
// Preferred sort is too slow:
//
// return a.element.compareDocumentPosition(b.element) ===
// Node.DOCUMENT_POSITION_FOLLOWING
// ? -1
// : 1;

return (
this.optionElements.indexOf(a.element) -
this.optionElements.indexOf(b.element)
);
});
if (!this.element) {
return [];
}

const options = this._options.filter((option) => !option.isDisabled);
const disconnected = options.some((option) => !option.isConnected);

if (disconnected) {
return options.sort(sortOptionsSlow);
} else {
const els = [...this.element.querySelectorAll('.select-box__option')];
return options.sort(sortOptionsFast(els));
}
}

@action
Expand Down
4 changes: 4 additions & 0 deletions addon/components/select-box/option.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export default class SelectBoxOption extends Component {
return this.args.value === this.args.selectBox.value;
}

get isConnected() {
return !!this.element.closest('.select-box');
}

@action
handleInsertElement(element) {
this.element = element;
Expand Down
22 changes: 12 additions & 10 deletions tests/integration/components/select-box/index/in-element-test.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,18 @@ module('select-box (in-element)', function (hooks) {
</sb.Option>
{{/each}}
</sb.Options>
<sb.Option @value={{null}} as |option|>
{{option.index}}
{{~" "~}}
qux
</sb.Option>
<sb.Option @value={{null}} as |option|>
{{option.index}}
{{~" "~}}
norf
</sb.Option>
<div class="wrapper">
<sb.Option @value={{null}} as |option|>
{{option.index}}
{{~" "~}}
qux
</sb.Option>
<sb.Option @value={{null}} as |option|>
{{option.index}}
{{~" "~}}
norf
</sb.Option>
</div>
</sb.Content>
</sb.Dropdown>
</SelectBox>
Expand Down

0 comments on commit d4ee5e3

Please sign in to comment.