@xui/multi-select 2.0.0-alpha.20 → 2.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -18,19 +18,29 @@ import { XuiTag } from '@xui/tag';
|
|
|
18
18
|
* option toggles it (the popover stays open). `[(values)]` two-way binding.
|
|
19
19
|
*/
|
|
20
20
|
class XuiMultiSelect {
|
|
21
|
+
/** Extra classes, merged into the component's own rather than replacing them. */
|
|
21
22
|
class = input('', /* @ts-ignore */
|
|
22
23
|
...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
24
|
+
/** The options to choose from. */
|
|
23
25
|
items = input([], /* @ts-ignore */
|
|
24
26
|
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
27
|
+
/**
|
|
28
|
+
* How an item is labelled. Also what the default filter matches against, so give it the text the user would type.
|
|
29
|
+
*/
|
|
25
30
|
itemText = input((item) => (item == null ? '' : String(item)), /* @ts-ignore */
|
|
26
31
|
...(ngDevMode ? [{ debugName: "itemText" }] : /* istanbul ignore next */ []));
|
|
32
|
+
/** Custom filter for one item against the query. Defaults to a case-insensitive substring match on `itemText`. */
|
|
27
33
|
itemPredicate = input(/* @ts-ignore */
|
|
28
34
|
...(ngDevMode ? [undefined, { debugName: "itemPredicate" }] : /* istanbul ignore next */ []));
|
|
35
|
+
/** Which items cannot be selected. They stay in the list, greyed out. */
|
|
29
36
|
itemDisabled = input(() => false, /* @ts-ignore */
|
|
30
37
|
...(ngDevMode ? [{ debugName: "itemDisabled" }] : /* istanbul ignore next */ []));
|
|
38
|
+
/** Block interaction and dim the control. */
|
|
31
39
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
40
|
+
/** Text shown in the empty field. Hidden once anything is selected. */
|
|
32
41
|
placeholder = input('Select…', /* @ts-ignore */
|
|
33
42
|
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
43
|
+
/** Shown in place of the list when the query matches nothing. */
|
|
34
44
|
noResultsText = input('No results.', /* @ts-ignore */
|
|
35
45
|
...(ngDevMode ? [{ debugName: "noResultsText" }] : /* istanbul ignore next */ []));
|
|
36
46
|
/** The chosen items. Two-way bindable with `[(values)]`, or via `formControl`/`ngModel`. */
|
|
@@ -43,7 +53,9 @@ class XuiMultiSelect {
|
|
|
43
53
|
isDisabled = this.cva.disabled;
|
|
44
54
|
/** Whether the popover has ever been open — so the initial closed state is not "touched". */
|
|
45
55
|
hasOpened = false;
|
|
56
|
+
/** Emits the item that was just selected. */
|
|
46
57
|
itemAdded = output();
|
|
58
|
+
/** Emits the item that was just deselected. */
|
|
47
59
|
itemRemoved = output();
|
|
48
60
|
open = model(false, /* @ts-ignore */
|
|
49
61
|
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xui-multi-select.mjs","sources":["../../../../../../libs/ui/multi-select/xui/src/lib/multi-select.ts","../../../../../../libs/ui/multi-select/xui/src/index.ts","../../../../../../libs/ui/multi-select/xui/src/xui-multi-select.ts"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n effect,\n input,\n model,\n output,\n signal,\n untracked,\n ViewEncapsulation\n} from '@angular/core';\nimport type { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { matCheckRound } from '@ng-icons/material-icons/round';\nimport { xui } from '@xui/core';\nimport { createXValueAccessor, provideXValueAccessor } from '@xui/core/forms';\nimport { createXActiveOption, createXItemListPredicate, createXQueryList, trackXItem } from '@xui/core/query';\nimport { XuiIcon } from '@xui/icon';\nimport { XuiPopoverImports } from '@xui/popover';\nimport { XuiSelectOption } from '@xui/select';\nimport { XuiTag } from '@xui/tag';\nimport type { ClassValue } from 'clsx';\n\n/**\n * A filterable multi-select: an inline field of removable chips plus a query\n * input opens a popover of options with a check on the chosen ones. Clicking an\n * option toggles it (the popover stays open). `[(values)]` two-way binding.\n */\n@Component({\n selector: 'xui-multi-select',\n imports: [NgTemplateOutlet, NgIcon, XuiIcon, XuiTag, XuiPopoverImports],\n template: `\n <div\n [class]=\"controlClass()\"\n [xuiPopover]=\"panel\"\n [(open)]=\"open\"\n [role]=\"'listbox'\"\n [matchTargetWidth]=\"true\"\n [minimal]=\"true\"\n [disabled]=\"isDisabled()\"\n placement=\"bottom-start\"\n >\n @for (item of values(); track trackItem($index, item)) {\n <xui-tag minimal color=\"primary\" [removable]=\"!isDisabled()\" (removed)=\"remove(item)\">{{\n displayText(item)\n }}</xui-tag>\n }\n\n <input\n #search\n type=\"text\"\n class=\"text-foreground placeholder:text-foreground-subtle min-w-24 flex-1 bg-transparent py-1 outline-none\"\n [placeholder]=\"values().length ? '' : placeholder()\"\n [value]=\"query()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onQuery($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n </div>\n\n <ng-template #panel>\n <ul role=\"listbox\" aria-multiselectable=\"true\" class=\"m-0 max-h-60 list-none overflow-y-auto p-1 text-sm\">\n @for (item of list.filteredItems(); track trackItem($index, item)) {\n <!-- Keyboard navigation runs through the query input, so options are\n pointer targets rather than individual tab stops. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [class]=\"optionClass(item)\"\n [attr.aria-selected]=\"isSelected(item)\"\n (click)=\"toggle(item)\"\n (mouseenter)=\"list.setActiveItem(item)\"\n >\n <ng-icon xui name=\"matCheckRound\" size=\"sm\" [class]=\"isSelected(item) ? 'text-primary' : 'invisible'\" />\n @if (optionTemplate(); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl.template\"\n [ngTemplateOutletContext]=\"{\n $implicit: item,\n item: item,\n active: list.isActive(item),\n selected: isSelected(item),\n index: $index\n }\"\n />\n } @else {\n {{ displayText(item) }}\n }\n </li>\n } @empty {\n <li class=\"text-foreground-muted px-2 py-2\">{{ noResultsText() }}</li>\n }\n </ul>\n </ng-template>\n `,\n host: {\n '[class]': 'computedClass()'\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n viewProviders: [provideIcons({ matCheckRound })],\n providers: [provideXValueAccessor(() => XuiMultiSelect)]\n})\nexport class XuiMultiSelect<T> implements ControlValueAccessor {\n readonly class = input<ClassValue>('');\n\n readonly items = input<readonly T[]>([]);\n readonly itemText = input<(item: T) => string>((item: T) => (item == null ? '' : String(item)));\n readonly itemPredicate = input<(query: string, item: T) => boolean>();\n readonly itemDisabled = input<(item: T) => boolean>(() => false);\n\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n readonly placeholder = input<string>('Select…');\n readonly noResultsText = input<string>('No results.');\n\n /** The chosen items. Two-way bindable with `[(values)]`, or via `formControl`/`ngModel`. */\n readonly values = model<T[]>([]);\n\n protected readonly cva = createXValueAccessor<T[]>({\n onWrite: values => this.values.set(values ?? []),\n disabled: this.disabled\n });\n protected readonly isDisabled = this.cva.disabled;\n\n /** Whether the popover has ever been open — so the initial closed state is not \"touched\". */\n private hasOpened = false;\n\n readonly itemAdded = output<T>();\n readonly itemRemoved = output<T>();\n\n protected readonly open = model(false);\n protected readonly query = signal('');\n\n protected readonly optionTemplate = contentChild(XuiSelectOption<T>);\n\n protected readonly list = createXQueryList<T>({\n items: this.items,\n query: this.query,\n itemText: item => this.itemText()(item),\n itemDisabled: item => this.itemDisabled()(item),\n itemListPredicate: createXItemListPredicate({\n itemText: this.itemText,\n itemPredicate: this.itemPredicate\n })\n });\n\n // Keyboard navigation over the filtered list (ArrowDown re-opens the popover;\n // Enter toggles rather than selects).\n private readonly nav = createXActiveOption<T>({\n list: this.list,\n select: item => this.toggle(item),\n close: () => this.open.set(false),\n open: () => this.open.set(true)\n });\n\n protected readonly computedClass = computed(() => xui('block', this.class()));\n\n protected readonly controlClass = computed(() =>\n xui(\n 'border-border bg-surface-inset flex min-h-(--control-height-md) w-full flex-wrap items-center gap-1.5 rounded-lg border px-(--control-padding-sm) py-1 text-sm',\n 'focus-within:border-focus cursor-text transition-colors',\n this.isDisabled() && 'cursor-not-allowed opacity-50'\n )\n );\n\n constructor() {\n // Mark the control touched once the popover closes after having been open.\n effect(() => {\n if (this.open()) {\n this.hasOpened = true;\n } else if (this.hasOpened) {\n untracked(() => this.cva.markTouched());\n }\n });\n }\n\n protected displayText(item: T): string {\n return this.itemText()(item);\n }\n\n protected readonly trackItem = trackXItem;\n\n protected isSelected(item: T): boolean {\n return this.values().includes(item);\n }\n\n protected optionClass(item: T): string {\n return xui(\n 'flex cursor-pointer items-center gap-2 rounded px-2 py-1.5',\n this.list.isActive(item) && 'bg-primary/10',\n this.list.isDisabled(item) && 'pointer-events-none opacity-50'\n );\n }\n\n protected onQuery(event: Event): void {\n this.query.set((event.target as HTMLInputElement).value);\n this.open.set(true);\n this.list.activateFirst();\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (this.nav.onKeydown(event)) {\n return;\n }\n\n // Remove the last chip when Backspace is pressed on an empty query.\n if (event.key === 'Backspace' && this.query() === '' && this.values().length) {\n this.remove(this.values()[this.values().length - 1]);\n }\n }\n\n protected toggle(item: T): void {\n if (this.list.isDisabled(item)) {\n return;\n }\n\n this.isSelected(item) ? this.remove(item) : this.add(item);\n }\n\n private add(item: T): void {\n this.values.update(items => [...items, item]);\n this.cva.notifyChange(this.values());\n this.query.set('');\n this.itemAdded.emit(item);\n }\n\n protected remove(item: T): void {\n if (this.isDisabled()) {\n return;\n }\n\n this.values.update(items => items.filter(i => i !== item));\n this.cva.notifyChange(this.values());\n this.itemRemoved.emit(item);\n }\n\n readonly writeValue = this.cva.writeValue;\n readonly registerOnChange = this.cva.registerOnChange;\n readonly registerOnTouched = this.cva.registerOnTouched;\n readonly setDisabledState = this.cva.setDisabledState;\n}\n","import { XuiMultiSelect } from './lib/multi-select';\n\nexport * from './lib/multi-select';\n\nexport const XuiMultiSelectImports = [XuiMultiSelect] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"xui-multi-select.mjs","sources":["../../../../../../libs/ui/multi-select/xui/src/lib/multi-select.ts","../../../../../../libs/ui/multi-select/xui/src/index.ts","../../../../../../libs/ui/multi-select/xui/src/xui-multi-select.ts"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n effect,\n input,\n model,\n output,\n signal,\n untracked,\n ViewEncapsulation\n} from '@angular/core';\nimport type { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { matCheckRound } from '@ng-icons/material-icons/round';\nimport { xui } from '@xui/core';\nimport { createXValueAccessor, provideXValueAccessor } from '@xui/core/forms';\nimport { createXActiveOption, createXItemListPredicate, createXQueryList, trackXItem } from '@xui/core/query';\nimport { XuiIcon } from '@xui/icon';\nimport { XuiPopoverImports } from '@xui/popover';\nimport { XuiSelectOption } from '@xui/select';\nimport { XuiTag } from '@xui/tag';\nimport type { ClassValue } from 'clsx';\n\n/**\n * A filterable multi-select: an inline field of removable chips plus a query\n * input opens a popover of options with a check on the chosen ones. Clicking an\n * option toggles it (the popover stays open). `[(values)]` two-way binding.\n */\n@Component({\n selector: 'xui-multi-select',\n imports: [NgTemplateOutlet, NgIcon, XuiIcon, XuiTag, XuiPopoverImports],\n template: `\n <div\n [class]=\"controlClass()\"\n [xuiPopover]=\"panel\"\n [(open)]=\"open\"\n [role]=\"'listbox'\"\n [matchTargetWidth]=\"true\"\n [minimal]=\"true\"\n [disabled]=\"isDisabled()\"\n placement=\"bottom-start\"\n >\n @for (item of values(); track trackItem($index, item)) {\n <xui-tag minimal color=\"primary\" [removable]=\"!isDisabled()\" (removed)=\"remove(item)\">{{\n displayText(item)\n }}</xui-tag>\n }\n\n <input\n #search\n type=\"text\"\n class=\"text-foreground placeholder:text-foreground-subtle min-w-24 flex-1 bg-transparent py-1 outline-none\"\n [placeholder]=\"values().length ? '' : placeholder()\"\n [value]=\"query()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onQuery($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n </div>\n\n <ng-template #panel>\n <ul role=\"listbox\" aria-multiselectable=\"true\" class=\"m-0 max-h-60 list-none overflow-y-auto p-1 text-sm\">\n @for (item of list.filteredItems(); track trackItem($index, item)) {\n <!-- Keyboard navigation runs through the query input, so options are\n pointer targets rather than individual tab stops. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [class]=\"optionClass(item)\"\n [attr.aria-selected]=\"isSelected(item)\"\n (click)=\"toggle(item)\"\n (mouseenter)=\"list.setActiveItem(item)\"\n >\n <ng-icon xui name=\"matCheckRound\" size=\"sm\" [class]=\"isSelected(item) ? 'text-primary' : 'invisible'\" />\n @if (optionTemplate(); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl.template\"\n [ngTemplateOutletContext]=\"{\n $implicit: item,\n item: item,\n active: list.isActive(item),\n selected: isSelected(item),\n index: $index\n }\"\n />\n } @else {\n {{ displayText(item) }}\n }\n </li>\n } @empty {\n <li class=\"text-foreground-muted px-2 py-2\">{{ noResultsText() }}</li>\n }\n </ul>\n </ng-template>\n `,\n host: {\n '[class]': 'computedClass()'\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n viewProviders: [provideIcons({ matCheckRound })],\n providers: [provideXValueAccessor(() => XuiMultiSelect)]\n})\nexport class XuiMultiSelect<T> implements ControlValueAccessor {\n /** Extra classes, merged into the component's own rather than replacing them. */\n readonly class = input<ClassValue>('');\n\n /** The options to choose from. */\n readonly items = input<readonly T[]>([]);\n /**\n * How an item is labelled. Also what the default filter matches against, so give it the text the user would type.\n */\n readonly itemText = input<(item: T) => string>((item: T) => (item == null ? '' : String(item)));\n /** Custom filter for one item against the query. Defaults to a case-insensitive substring match on `itemText`. */\n readonly itemPredicate = input<(query: string, item: T) => boolean>();\n /** Which items cannot be selected. They stay in the list, greyed out. */\n readonly itemDisabled = input<(item: T) => boolean>(() => false);\n\n /** Block interaction and dim the control. */\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n /** Text shown in the empty field. Hidden once anything is selected. */\n readonly placeholder = input<string>('Select…');\n /** Shown in place of the list when the query matches nothing. */\n readonly noResultsText = input<string>('No results.');\n\n /** The chosen items. Two-way bindable with `[(values)]`, or via `formControl`/`ngModel`. */\n readonly values = model<T[]>([]);\n\n protected readonly cva = createXValueAccessor<T[]>({\n onWrite: values => this.values.set(values ?? []),\n disabled: this.disabled\n });\n protected readonly isDisabled = this.cva.disabled;\n\n /** Whether the popover has ever been open — so the initial closed state is not \"touched\". */\n private hasOpened = false;\n\n /** Emits the item that was just selected. */\n readonly itemAdded = output<T>();\n /** Emits the item that was just deselected. */\n readonly itemRemoved = output<T>();\n\n protected readonly open = model(false);\n protected readonly query = signal('');\n\n protected readonly optionTemplate = contentChild(XuiSelectOption<T>);\n\n protected readonly list = createXQueryList<T>({\n items: this.items,\n query: this.query,\n itemText: item => this.itemText()(item),\n itemDisabled: item => this.itemDisabled()(item),\n itemListPredicate: createXItemListPredicate({\n itemText: this.itemText,\n itemPredicate: this.itemPredicate\n })\n });\n\n // Keyboard navigation over the filtered list (ArrowDown re-opens the popover;\n // Enter toggles rather than selects).\n private readonly nav = createXActiveOption<T>({\n list: this.list,\n select: item => this.toggle(item),\n close: () => this.open.set(false),\n open: () => this.open.set(true)\n });\n\n protected readonly computedClass = computed(() => xui('block', this.class()));\n\n protected readonly controlClass = computed(() =>\n xui(\n 'border-border bg-surface-inset flex min-h-(--control-height-md) w-full flex-wrap items-center gap-1.5 rounded-lg border px-(--control-padding-sm) py-1 text-sm',\n 'focus-within:border-focus cursor-text transition-colors',\n this.isDisabled() && 'cursor-not-allowed opacity-50'\n )\n );\n\n constructor() {\n // Mark the control touched once the popover closes after having been open.\n effect(() => {\n if (this.open()) {\n this.hasOpened = true;\n } else if (this.hasOpened) {\n untracked(() => this.cva.markTouched());\n }\n });\n }\n\n protected displayText(item: T): string {\n return this.itemText()(item);\n }\n\n protected readonly trackItem = trackXItem;\n\n protected isSelected(item: T): boolean {\n return this.values().includes(item);\n }\n\n protected optionClass(item: T): string {\n return xui(\n 'flex cursor-pointer items-center gap-2 rounded px-2 py-1.5',\n this.list.isActive(item) && 'bg-primary/10',\n this.list.isDisabled(item) && 'pointer-events-none opacity-50'\n );\n }\n\n protected onQuery(event: Event): void {\n this.query.set((event.target as HTMLInputElement).value);\n this.open.set(true);\n this.list.activateFirst();\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (this.nav.onKeydown(event)) {\n return;\n }\n\n // Remove the last chip when Backspace is pressed on an empty query.\n if (event.key === 'Backspace' && this.query() === '' && this.values().length) {\n this.remove(this.values()[this.values().length - 1]);\n }\n }\n\n protected toggle(item: T): void {\n if (this.list.isDisabled(item)) {\n return;\n }\n\n this.isSelected(item) ? this.remove(item) : this.add(item);\n }\n\n private add(item: T): void {\n this.values.update(items => [...items, item]);\n this.cva.notifyChange(this.values());\n this.query.set('');\n this.itemAdded.emit(item);\n }\n\n protected remove(item: T): void {\n if (this.isDisabled()) {\n return;\n }\n\n this.values.update(items => items.filter(i => i !== item));\n this.cva.notifyChange(this.values());\n this.itemRemoved.emit(item);\n }\n\n readonly writeValue = this.cva.writeValue;\n readonly registerOnChange = this.cva.registerOnChange;\n readonly registerOnTouched = this.cva.registerOnTouched;\n readonly setDisabledState = this.cva.setDisabledState;\n}\n","import { XuiMultiSelect } from './lib/multi-select';\n\nexport * from './lib/multi-select';\n\nexport const XuiMultiSelectImports = [XuiMultiSelect] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xui/multi-select",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.21",
|
|
4
4
|
"description": "Modern Angular 22 UI Library based on TailwindCSS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -42,11 +42,11 @@
|
|
|
42
42
|
"@angular/forms": "22",
|
|
43
43
|
"@ng-icons/core": "34",
|
|
44
44
|
"@ng-icons/material-icons": "34",
|
|
45
|
-
"@xui/core": "2.0.0-alpha.
|
|
46
|
-
"@xui/icon": "2.0.0-alpha.
|
|
47
|
-
"@xui/popover": "2.0.0-alpha.
|
|
48
|
-
"@xui/select": "2.0.0-alpha.
|
|
49
|
-
"@xui/tag": "2.0.0-alpha.
|
|
45
|
+
"@xui/core": "2.0.0-alpha.21",
|
|
46
|
+
"@xui/icon": "2.0.0-alpha.21",
|
|
47
|
+
"@xui/popover": "2.0.0-alpha.21",
|
|
48
|
+
"@xui/select": "2.0.0-alpha.21",
|
|
49
|
+
"@xui/tag": "2.0.0-alpha.21",
|
|
50
50
|
"clsx": "^2.1.1"
|
|
51
51
|
},
|
|
52
52
|
"publishConfig": {
|
|
@@ -12,13 +12,23 @@ import { ClassValue } from 'clsx';
|
|
|
12
12
|
* option toggles it (the popover stays open). `[(values)]` two-way binding.
|
|
13
13
|
*/
|
|
14
14
|
declare class XuiMultiSelect<T> implements ControlValueAccessor {
|
|
15
|
+
/** Extra classes, merged into the component's own rather than replacing them. */
|
|
15
16
|
readonly class: _angular_core.InputSignal<ClassValue>;
|
|
17
|
+
/** The options to choose from. */
|
|
16
18
|
readonly items: _angular_core.InputSignal<readonly T[]>;
|
|
19
|
+
/**
|
|
20
|
+
* How an item is labelled. Also what the default filter matches against, so give it the text the user would type.
|
|
21
|
+
*/
|
|
17
22
|
readonly itemText: _angular_core.InputSignal<(item: T) => string>;
|
|
23
|
+
/** Custom filter for one item against the query. Defaults to a case-insensitive substring match on `itemText`. */
|
|
18
24
|
readonly itemPredicate: _angular_core.InputSignal<((query: string, item: T) => boolean) | undefined>;
|
|
25
|
+
/** Which items cannot be selected. They stay in the list, greyed out. */
|
|
19
26
|
readonly itemDisabled: _angular_core.InputSignal<(item: T) => boolean>;
|
|
27
|
+
/** Block interaction and dim the control. */
|
|
20
28
|
readonly disabled: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
29
|
+
/** Text shown in the empty field. Hidden once anything is selected. */
|
|
21
30
|
readonly placeholder: _angular_core.InputSignal<string>;
|
|
31
|
+
/** Shown in place of the list when the query matches nothing. */
|
|
22
32
|
readonly noResultsText: _angular_core.InputSignal<string>;
|
|
23
33
|
/** The chosen items. Two-way bindable with `[(values)]`, or via `formControl`/`ngModel`. */
|
|
24
34
|
readonly values: _angular_core.ModelSignal<T[]>;
|
|
@@ -26,7 +36,9 @@ declare class XuiMultiSelect<T> implements ControlValueAccessor {
|
|
|
26
36
|
protected readonly isDisabled: _angular_core.Signal<boolean>;
|
|
27
37
|
/** Whether the popover has ever been open — so the initial closed state is not "touched". */
|
|
28
38
|
private hasOpened;
|
|
39
|
+
/** Emits the item that was just selected. */
|
|
29
40
|
readonly itemAdded: _angular_core.OutputEmitterRef<T>;
|
|
41
|
+
/** Emits the item that was just deselected. */
|
|
30
42
|
readonly itemRemoved: _angular_core.OutputEmitterRef<T>;
|
|
31
43
|
protected readonly open: _angular_core.ModelSignal<boolean>;
|
|
32
44
|
protected readonly query: _angular_core.WritableSignal<string>;
|