Skip to content

Commit

Permalink
chore: refine listbox and native select, add support for items with k…
Browse files Browse the repository at this point in the history
…ey and label.
  • Loading branch information
josemarluedke committed Feb 18, 2024
1 parent 1f19a00 commit d1bbcea
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 161 deletions.
22 changes: 21 additions & 1 deletion packages/collections/src/components/listbox/listManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ class ListManager {
if (options.onSelectionChange) {
this.#onSelectionChange = options.onSelectionChange;
}

if (options.onNodesChange) {
this.#onNodesChange = options.onNodesChange;
}
}

selectActiveNode(): void {
Expand Down Expand Up @@ -346,6 +350,22 @@ class ListManager {
}
);
}
function keyAndLabelForItem(item: unknown): {
key: string;
label: string;
} {
if (typeof item === 'string' || typeof item === 'number') {
return { key: item.toString(), label: item.toString() };
} else if (typeof item === 'object' && item !== null) {
const typedItem = item as { key: string; label: string };
if ('key' in typedItem && 'label' in typedItem) {
return { key: typedItem.key, label: typedItem.label };
} else {
return { key: item.toString(), label: item.toString() };
}
}
return { key: '', label: '' };
}

export type { Node, NodeArgs, SelectionMode };
export { ListManager };
export { ListManager, keyAndLabelForItem };
67 changes: 38 additions & 29 deletions packages/collections/src/components/listbox/listbox.gts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import { hash } from '@ember/helper';
import { action } from '@ember/object';
import { on } from '@ember/modifier';
import { useStyles } from '@frontile/theme';
import { ListManager, type SelectionMode } from './listManager';
import {
ListManager,
keyAndLabelForItem,
type SelectionMode,
type Node
} from './listManager';
import { ListboxItem, type ListboxItemSignature } from './item';
import type { WithBoundArgs } from '@glint/template';

Expand Down Expand Up @@ -40,7 +45,7 @@ interface ListboxSignature<T = unknown> {
};
Element: HTMLUListElement;
Blocks: {
item: [{ item: T; Item: ItemCompBounded }];
item: [{ item: T; key: string; label: string; Item: ItemCompBounded }];
default: [{ Item: ItemCompBounded }];
};
}
Expand Down Expand Up @@ -132,33 +137,36 @@ class Listbox extends Component<ListboxSignature> {
...attributes
>
{{#each @items as |item|}}
{{#if (has-block "item")}}
{{yield
(hash
item=item
Item=(component
ListboxItem
manager=this.listManager
appearance=@appearance
intent=@intent
type=this.role
{{#let (keyAndLabelForItem item) as |keyLabel|}}
{{#if (has-block "item")}}
{{yield
(hash
item=item
key=keyLabel.key
label=keyLabel.label
Item=(component
ListboxItem
manager=this.listManager
appearance=@appearance
intent=@intent
type=this.role
key=keyLabel.key
)
)
)
to="item"
}}
{{else}}
<ListboxItem
@manager={{this.listManager}}
{{! @glint-expect-error: if we get to this option, we are assuming the option is primitive value}}
@key={{item}}
@appearance={{@appearance}}
@intent={{@intent}}
@type={{this.role}}
>
{{! @glint-expect-error: if we get to this option, we are assuming the option is primitive value}}
{{item}}
</ListboxItem>
{{/if}}
to="item"
}}
{{else}}
<ListboxItem
@manager={{this.listManager}}
@key={{keyLabel.key}}
@appearance={{@appearance}}
@intent={{@intent}}
@type={{this.role}}
>
{{keyLabel.label}}
</ListboxItem>
{{/if}}
{{/let}}
{{/each}}

{{yield
Expand All @@ -181,6 +189,7 @@ export {
Listbox,
ListboxItem,
type ListboxSignature,
type ListboxItemSignature
type ListboxItemSignature,
type Node as ListItemNode
};
export default Listbox;
80 changes: 28 additions & 52 deletions packages/collections/src/components/native-select.gts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ import { action } from '@ember/object';
import { on } from '@ember/modifier';
import { assert } from '@ember/debug';
import { useStyles } from '@frontile/theme';
import { ListManager, type Node } from './listbox/listManager';
import {
ListManager,
keyAndLabelForItem,
type Node
} from './listbox/listManager';
import type { WithBoundArgs } from '@glint/template';

type ItemCompBounded = WithBoundArgs<typeof NativeSelectItem, 'manager'>;

interface NativeSelectSignature<T = unknown> {
Args: {
/**
* @default 'listbox'
*/
type?: 'menu' | 'listbox';
selectionMode?: 'single' | 'multiple';
selectedKeys?: string[];
disabledKeys?: string[];
Expand All @@ -31,26 +31,14 @@ interface NativeSelectSignature<T = unknown> {
onAction?: (key: string) => void;
onSelectionChange?: (key: string[]) => void;

/**
* The appearance of each item
*
* @defaultValue 'default'
*/
appearance?: 'default' | 'outlined' | 'faded';

/**
* The intent of each item
*/
intent?: 'default' | 'primary' | 'success' | 'warning' | 'danger';

/**
* @internal
*/
onItemsChange?: (nodes: Node[], action: 'add' | 'remove') => void;
};
Element: HTMLUListElement | HTMLSelectElement;
Element: HTMLSelectElement;
Blocks: {
item: [{ item: T; Item: ItemCompBounded }];
item: [{ item: T; key: string; label: string; Item: ItemCompBounded }];
default: [{ Item: ItemCompBounded }];
};
}
Expand Down Expand Up @@ -124,42 +112,30 @@ class NativeSelect extends Component<NativeSelectSignature> {
</NativeSelectItem>
{{/if}}
{{#each @items as |item|}}
{{#if (has-block "item")}}
{{yield
(hash
item=item
Item=(component
NativeSelectItem
manager=this.listManager
appearance=@appearance
intent=@intent
{{#let (keyAndLabelForItem item) as |keyLabel|}}
{{#if (has-block "item")}}
{{yield
(hash
item=item
key=keyLabel.key
label=keyLabel.label
Item=(component NativeSelectItem manager=this.listManager)
)
)
to="item"
}}
{{else}}
<NativeSelectItem
@manager={{this.listManager}}
{{! @glint-expect-error: if we get to this option, we are assuming the option is primitive value}}
@key={{item}}
@appearance={{@appearance}}
@intent={{@intent}}
>
{{! @glint-expect-error: if we get to this option, we are assuming the option is primitive value}}
{{item}}
</NativeSelectItem>
{{/if}}
to="item"
}}
{{else}}
<NativeSelectItem
@manager={{this.listManager}}
@key={{keyLabel.key}}
>
{{keyLabel.label}}
</NativeSelectItem>
{{/if}}
{{/let}}
{{/each}}
{{yield
(hash
Item=(component
NativeSelectItem
manager=this.listManager
appearance=@appearance
intent=@intent
)
)
(hash Item=(component NativeSelectItem manager=this.listManager))
to="default"
}}
</select>
Expand All @@ -172,7 +148,7 @@ export interface SelectItemSignature {
key: string;
textValue?: string;
};
Element: HTMLOptionElement | HTMLLIElement;
Element: HTMLOptionElement;
Blocks: {
default: [];
selectedIcon: [];
Expand Down
1 change: 1 addition & 0 deletions packages/forms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@frontile/theme": "workspace:0.17.0-alpha.6",
"@frontile/overlays": "workspace:0.17.0-alpha.6",
"@frontile/collections": "workspace:0.17.0-alpha.6",
"@frontile/utilities": "workspace:0.17.0-alpha.6",
"@glint/template": "1.3.0"
},
"devDependencies": {
Expand Down
Loading

0 comments on commit d1bbcea

Please sign in to comment.