@ds-mo/ui 8.3.1 → 9.1.0
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.
- package/README.md +28 -3
- package/dist/.build-stamp +1 -1
- package/dist/agent-patterns.json +233 -0
- package/dist/agent.json +155 -174
- package/dist/angular/ds-menu.d.ts +6 -1
- package/dist/angular/ds-menu.js +7 -4
- package/dist/angular/ds-swatch-picker.d.ts +15 -0
- package/dist/angular/{ds-pagination.js → ds-swatch-picker.js} +15 -15
- package/dist/angular/index.d.ts +1 -1
- package/dist/angular/index.js +1 -2
- package/dist/angular/proxies.d.ts +1 -2
- package/dist/angular/proxies.js +1 -2
- package/dist/components/ds-app-shell.js +1 -1
- package/dist/components/ds-badge.js +1 -1
- package/dist/components/ds-banner.js +1 -1
- package/dist/components/ds-bar-nav.js +1 -1
- package/dist/components/ds-bar-nav.js.map +1 -1
- package/dist/components/ds-button-filled.js +1 -1
- package/dist/components/ds-button-unfilled.js +1 -1
- package/dist/components/ds-card-data-viz-donut.js +1 -1
- package/dist/components/ds-card-setting.js +1 -1
- package/dist/components/ds-card-shell-data-viz.js +1 -1
- package/dist/components/ds-card.js +1 -1
- package/dist/components/ds-chart-bar.js +1 -1
- package/dist/components/ds-chart-bar.js.map +1 -1
- package/dist/components/ds-chart-donut.js +1 -1
- package/dist/components/ds-chart-legend.js +1 -1
- package/dist/components/ds-chart-line.js +1 -1
- package/dist/components/ds-checkbox.js +1 -1
- package/dist/components/ds-chip.js +1 -1
- package/dist/components/ds-empty-state.js +1 -1
- package/dist/components/ds-field.js +1 -1
- package/dist/components/ds-input.js +1 -1
- package/dist/components/ds-menu.js +1 -1
- package/dist/components/ds-modal.js +1 -1
- package/dist/components/ds-panel-nav.js +1 -1
- package/dist/components/ds-panel-nav.js.map +1 -1
- package/dist/components/ds-panel-sub-nav.js +1 -1
- package/dist/components/ds-panel-tools.js +1 -1
- package/dist/components/ds-radio.js +1 -1
- package/dist/components/ds-select-multi.js +1 -1
- package/dist/components/ds-select-multi.js.map +1 -1
- package/dist/components/ds-select.js +1 -1
- package/dist/components/ds-select.js.map +1 -1
- package/dist/components/ds-shell-gradient-picker.js +1 -1
- package/dist/components/ds-shell-gradient-picker.js.map +1 -1
- package/dist/components/ds-shell-gradient-swatch.js +1 -1
- package/dist/components/ds-shell-gradient-swatch.js.map +1 -1
- package/dist/components/ds-skeleton.js +1 -1
- package/dist/components/ds-skeleton.js.map +1 -1
- package/dist/components/ds-slider.js +1 -1
- package/dist/components/ds-slider.js.map +1 -1
- package/dist/components/{ds-pagination.d.ts → ds-swatch-picker.d.ts} +4 -4
- package/dist/components/ds-swatch-picker.js +2 -0
- package/dist/components/ds-swatch-picker.js.map +1 -0
- package/dist/components/ds-tab-group.js +1 -1
- package/dist/components/ds-tag.js +1 -1
- package/dist/components/ds-text.js +1 -1
- package/dist/components/ds-tooltip-data-viz.js +1 -1
- package/dist/components/ds-tooltip.js +1 -1
- package/dist/components/{p-CysJosvS.js → p-B-zhgAvL.js} +2 -2
- package/dist/components/{p-C21sIElQ.js → p-BLzivrE3.js} +2 -2
- package/dist/components/{p-DAuadHYu.js → p-BbV68F23.js} +2 -2
- package/dist/components/{p-_y99wWNU.js → p-C7RObioO.js} +2 -2
- package/dist/components/{p-DxQ4gzbA.js → p-CZ9wemOA.js} +2 -2
- package/dist/components/{p-BKA6houZ.js → p-CbS_WWs2.js} +2 -2
- package/dist/components/p-D1HFMTdC.js +2 -0
- package/dist/components/p-D1HFMTdC.js.map +1 -0
- package/dist/components/{p-BGcSrHKl.js → p-DT2MK8Kt.js} +2 -2
- package/dist/components/{p-DV23KMU-.js → p-DyZj3k9S.js} +2 -2
- package/dist/components/p-HBIxvS5C.js +2 -0
- package/dist/components/p-HBIxvS5C.js.map +1 -0
- package/dist/components/{p-D6hvtWDk.js → p-KRGBGTu5.js} +2 -2
- package/dist/components/p-l6PmnW_P.js +2 -0
- package/dist/components/p-l6PmnW_P.js.map +1 -0
- package/dist/components/p-tQ1QHeOE.js +2 -0
- package/dist/components/p-tQ1QHeOE.js.map +1 -0
- package/dist/docs/components.json +546 -1024
- package/dist/lib/components/Menu/menu-placement.d.ts +6 -3
- package/dist/lib/shell/index.d.ts +2 -2
- package/dist/lib/shell/index.js +40 -39
- package/dist/lib/shell/index.js.map +3 -3
- package/dist/lib/shell/shell-gradient-presets.d.ts +15 -0
- package/dist/lib/utils/choice-popup-alignment.d.ts +20 -0
- package/dist/lib/utils/index.d.ts +2 -0
- package/dist/lib/utils/index.js +16 -0
- package/dist/lib/utils/index.js.map +3 -3
- package/dist/mcp/cli.js +31409 -0
- package/dist/mcp-data/registry/app-shell.json +210 -0
- package/dist/mcp-data/registry/badge.json +289 -0
- package/dist/mcp-data/registry/banner.json +206 -0
- package/dist/mcp-data/registry/bar-nav.json +341 -0
- package/dist/mcp-data/registry/button-filled.json +386 -0
- package/dist/mcp-data/registry/button-unfilled.json +537 -0
- package/dist/mcp-data/registry/card-data-viz-donut.json +143 -0
- package/dist/mcp-data/registry/card-setting.json +194 -0
- package/dist/mcp-data/registry/card-shell-data-viz.json +173 -0
- package/dist/mcp-data/registry/card.json +126 -0
- package/dist/mcp-data/registry/chart-bar.json +121 -0
- package/dist/mcp-data/registry/chart-donut.json +257 -0
- package/dist/mcp-data/registry/chart-legend.json +209 -0
- package/dist/mcp-data/registry/chart-line.json +153 -0
- package/dist/mcp-data/registry/checkbox.json +361 -0
- package/dist/mcp-data/registry/chip.json +276 -0
- package/dist/mcp-data/registry/divider.json +225 -0
- package/dist/mcp-data/registry/empty-state.json +197 -0
- package/dist/mcp-data/registry/field.json +222 -0
- package/dist/mcp-data/registry/icon.json +242 -0
- package/dist/mcp-data/registry/input.json +597 -0
- package/dist/mcp-data/registry/loader.json +192 -0
- package/dist/mcp-data/registry/menu.json +459 -0
- package/dist/mcp-data/registry/modal.json +150 -0
- package/dist/mcp-data/registry/panel-nav.json +622 -0
- package/dist/mcp-data/registry/panel-sub-nav.json +249 -0
- package/dist/mcp-data/registry/panel-tools.json +374 -0
- package/dist/mcp-data/registry/radio.json +374 -0
- package/dist/mcp-data/registry/registry.json +5389 -0
- package/dist/mcp-data/registry/select-multi.json +755 -0
- package/dist/mcp-data/registry/select.json +740 -0
- package/dist/mcp-data/registry/shell-gradient-picker.json +195 -0
- package/dist/mcp-data/registry/shell-gradient-swatch.json +215 -0
- package/dist/mcp-data/registry/skeleton.json +282 -0
- package/dist/mcp-data/registry/slider.json +657 -0
- package/dist/mcp-data/registry/swatch-picker.json +231 -0
- package/dist/mcp-data/registry/switch.json +361 -0
- package/dist/mcp-data/registry/tab-group.json +255 -0
- package/dist/mcp-data/registry/tag.json +352 -0
- package/dist/mcp-data/registry/text.json +371 -0
- package/dist/mcp-data/registry/tooltip-data-viz.json +158 -0
- package/dist/mcp-data/registry/tooltip.json +311 -0
- package/dist/react/components.d.ts +1 -2
- package/dist/react/components.js +1 -2
- package/dist/react/ds-menu.d.ts +1 -0
- package/dist/react/ds-menu.js +2 -1
- package/dist/react/ds-swatch-picker.d.ts +12 -0
- package/dist/react/ds-swatch-picker.js +12 -0
- package/dist/types/components/Menu/Menu.d.ts +7 -1
- package/dist/types/components/Menu/menu-placement.d.ts +6 -3
- package/dist/types/components/Menu/menu-types.d.ts +14 -1
- package/dist/types/components/ShellGradientPicker/ShellGradientPicker.d.ts +2 -5
- package/dist/types/components/ShellGradientSwatch/ShellGradientSwatch.d.ts +1 -0
- package/dist/types/components/SwatchPicker/SwatchPicker.d.ts +21 -0
- package/dist/types/components/SwatchPicker/swatch-picker-types.d.ts +26 -0
- package/dist/types/components.d.ts +117 -237
- package/dist/types/shell/index.d.ts +2 -2
- package/dist/types/shell/shell-gradient-presets.d.ts +15 -0
- package/dist/types/utils/choice-popup-alignment.d.ts +21 -0
- package/dist/types/utils/index.d.ts +2 -0
- package/package.json +6 -2
- package/dist/angular/ds-pagination.d.ts +0 -15
- package/dist/angular/ds-table.d.ts +0 -33
- package/dist/angular/ds-table.js +0 -48
- package/dist/components/ds-pagination.js +0 -2
- package/dist/components/ds-pagination.js.map +0 -1
- package/dist/components/ds-table.d.ts +0 -11
- package/dist/components/ds-table.js +0 -2
- package/dist/components/ds-table.js.map +0 -1
- package/dist/components/p-CKV6rOGa.js +0 -2
- package/dist/components/p-CKV6rOGa.js.map +0 -1
- package/dist/components/p-CSTr2132.js +0 -2
- package/dist/components/p-CSTr2132.js.map +0 -1
- package/dist/components/p-C_cu-HIT.js +0 -2
- package/dist/components/p-C_cu-HIT.js.map +0 -1
- package/dist/components/p-D0B9uDTP.js +0 -2
- package/dist/components/p-D0B9uDTP.js.map +0 -1
- package/dist/components/p-DhxWfdX0.js +0 -2
- package/dist/components/p-DhxWfdX0.js.map +0 -1
- package/dist/components/p-Pip-LNhl.js +0 -2
- package/dist/components/p-Pip-LNhl.js.map +0 -1
- package/dist/react/ds-pagination.d.ts +0 -12
- package/dist/react/ds-pagination.js +0 -12
- package/dist/react/ds-table.d.ts +0 -21
- package/dist/react/ds-table.js +0 -16
- package/dist/types/components/Pagination/Pagination.d.ts +0 -14
- package/dist/types/components/Table/Table.d.ts +0 -56
- /package/dist/components/{p-CysJosvS.js.map → p-B-zhgAvL.js.map} +0 -0
- /package/dist/components/{p-C21sIElQ.js.map → p-BLzivrE3.js.map} +0 -0
- /package/dist/components/{p-DAuadHYu.js.map → p-BbV68F23.js.map} +0 -0
- /package/dist/components/{p-_y99wWNU.js.map → p-C7RObioO.js.map} +0 -0
- /package/dist/components/{p-DxQ4gzbA.js.map → p-CZ9wemOA.js.map} +0 -0
- /package/dist/components/{p-BKA6houZ.js.map → p-CbS_WWs2.js.map} +0 -0
- /package/dist/components/{p-BGcSrHKl.js.map → p-DT2MK8Kt.js.map} +0 -0
- /package/dist/components/{p-DV23KMU-.js.map → p-DyZj3k9S.js.map} +0 -0
- /package/dist/components/{p-D6hvtWDk.js.map → p-KRGBGTu5.js.map} +0 -0
|
@@ -0,0 +1,755 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "select-multi",
|
|
4
|
+
"title": "SelectMulti",
|
|
5
|
+
"description": "Form-associated multi-value select with a persistent trigger label, inline selected count, local search, rich flat options, grouped sections, loading, and clear-all behavior.",
|
|
6
|
+
"type": "registry:ui",
|
|
7
|
+
"meta": {
|
|
8
|
+
"library": "@ds-mo/ui",
|
|
9
|
+
"distribution": "npm",
|
|
10
|
+
"storybook": "https://zainadeel.github.io/compomo/?path=/story/select-multi",
|
|
11
|
+
"source": "src/wc/components/SelectMulti/SelectMulti.tsx",
|
|
12
|
+
"intentStatus": "complete",
|
|
13
|
+
"intent": {
|
|
14
|
+
"audience": "general",
|
|
15
|
+
"status": "stable",
|
|
16
|
+
"summary": "Form-associated multi-value select with a persistent trigger label, inline selected count, local search, rich flat options, grouped sections, loading, and clear-all behavior.",
|
|
17
|
+
"useWhen": [
|
|
18
|
+
"The user may choose several independent values from one finite set.",
|
|
19
|
+
"A compact trigger should summarize selection with the field label and a count.",
|
|
20
|
+
"The option set benefits from local search, subtext, grouping, or disabled choices.",
|
|
21
|
+
"The choice set has more than roughly 20 options, comes from a user-managed listing, or represents a large domain where search materially improves retrieval."
|
|
22
|
+
],
|
|
23
|
+
"avoidWhen": [
|
|
24
|
+
"Exactly one value may be selected.",
|
|
25
|
+
"Selected values must remain individually removable as persistent tags outside the popup.",
|
|
26
|
+
"The choices form a hierarchy with cascading parent selection.",
|
|
27
|
+
"The customer task benefits more from keeping every choice and checkbox directly visible; choose between SelectMulti and a visible checkbox list from the use-case context rather than a fixed option-count threshold."
|
|
28
|
+
],
|
|
29
|
+
"alternatives": [
|
|
30
|
+
{
|
|
31
|
+
"when": "Exactly one value may be selected.",
|
|
32
|
+
"component": "component:ds-select",
|
|
33
|
+
"reason": "Select owns scalar form value and single-select listbox behavior."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"when": "The popup contains actions rather than values.",
|
|
37
|
+
"component": "component:ds-menu",
|
|
38
|
+
"reason": "Menu uses command semantics and closes according to action-menu expectations."
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"commonlyComposedWith": [
|
|
42
|
+
"component:ds-text",
|
|
43
|
+
"component:ds-checkbox",
|
|
44
|
+
"component:ds-empty-state",
|
|
45
|
+
"component:ds-loader"
|
|
46
|
+
],
|
|
47
|
+
"accessibility": [
|
|
48
|
+
"In forms, provide a persistent visible external field label. In a compact filter bar, the trigger's visible persistent label and count may supply the accessible name.",
|
|
49
|
+
"The popup is a listbox with aria-multiselectable and every option exposes its independent aria-selected state.",
|
|
50
|
+
"Disabled options expose aria-disabled and are skipped by keyboard navigation and typeahead.",
|
|
51
|
+
"Keyboard navigation keeps the aria-activedescendant option scrolled into the visible listbox viewport.",
|
|
52
|
+
"Each row uses a medium-size presentation-only ds-checkbox indicator; multi-select option rows never add a prefix icon alongside it, and the option remains the sole selection semantic and interaction target.",
|
|
53
|
+
"The trigger keeps its field label visible and appends the current selected count; an explicit aria-label or aria-labelledby remains the authoritative accessible name when supplied.",
|
|
54
|
+
"Use errorMessage with error so the trigger is described by the rendered alert."
|
|
55
|
+
],
|
|
56
|
+
"states": [
|
|
57
|
+
"Values is a controlled JavaScript array; dsChange emits a new array after each user toggle.",
|
|
58
|
+
"Required SelectMulti controls begin without an automatic selection and require the user to make an explicit choice.",
|
|
59
|
+
"Selecting an option keeps the popup open so additional values can be toggled.",
|
|
60
|
+
"The trigger label stays left-aligned at every width; every option row uses the same leading medium Checkbox indicator. The default control size is md in both forms and filter bars.",
|
|
61
|
+
"The selected count always follows the persistent label as plain text separated by a centered dot, including for one selection, and counts every selected value even when search or grouping hides it. Never replace the count with selected option names.",
|
|
62
|
+
"Create sections only for categories that are meaningful to customers, not merely to break a long list into arbitrary chunks.",
|
|
63
|
+
"When any option supplies subtext, every row uses the same subtext structure and missing values render an em dash. Subtext should disambiguate or add decision-helpful information.",
|
|
64
|
+
"Option labels stay on one line and truncate when constrained. Option subtext may wrap to at most two lines.",
|
|
65
|
+
"The optional prefix icon and chevron always use the parent surface's secondary foreground color, including when selection promotes the label and count to primary.",
|
|
66
|
+
"The shared popup search control stays md at every trigger size, using body-medium text, a 20px icon, and the same internal spacing as a borderless Select trigger. Its container uses menu-item padding on every side and owns a 1px bottom divider that becomes a 1.5px bold-brand stroke while search has focus. Search placeholder text is secondary at rest and quaternary while focused because it becomes decorative once the editable field is active.",
|
|
67
|
+
"When search contains text, the shared control shows a rounded sm icon-only ButtonUnfilled with the Cross icon and no border. It clears the local term, stays hidden for an empty term, and returns focus to search.",
|
|
68
|
+
"The shared summary-and-clear footer mirrors the search region's sizing: menu-item padding surrounds an md-height borderless row, and both texts use the same row and label insets as option text. The outer footer owns a 1px top divider.",
|
|
69
|
+
"An empty filtered list composes the message-only body variant of EmptyState. Keep the default neutral no-results message unless localized product guidance makes the outcome clearer.",
|
|
70
|
+
"Enable searchable for more than roughly 20 options, user-managed listings, large domains such as addresses, or sets users cannot efficiently scan. Local matching includes option labels, subtext, and section headings; the owner resolves remote data before assigning options.",
|
|
71
|
+
"When allowClear is enabled, clear-all appears only after at least one value exists. Clearing is valid for optional and required fields; a required field becomes invalid until the user selects again.",
|
|
72
|
+
"Clear-all emits an empty dsChange and dsClear while preserving useful popup or search focus.",
|
|
73
|
+
"Loading keeps the trigger visible, marks the control busy, and makes selection interaction temporarily unavailable without presenting the control as inactive.",
|
|
74
|
+
"SelectMulti has no maximum-selection behavior; every available non-inactive option may be selected.",
|
|
75
|
+
"Validation timing belongs to the form owner and may be immediate or deferred until blur or submit; the component exposes validity and error presentation without imposing that policy.",
|
|
76
|
+
"The error trigger uses a 1.5px bold-negative inset stroke so invalid state remains distinguishable from the normal 1px border without changing control geometry.",
|
|
77
|
+
"An initially empty option set is not an expected SelectMulti use case. The no-results state describes a search with no matches, not a source with no choices.",
|
|
78
|
+
"Native form submission emits one entry per selected value under the component name.",
|
|
79
|
+
"Use options for a flat list or sections for grouped choices. Multi-select option contracts intentionally exclude icons because the leading checkbox owns that row zone; hierarchical parent selection is deferred."
|
|
80
|
+
],
|
|
81
|
+
"responsiveBehavior": [
|
|
82
|
+
"Use width fill for form fields and width hug for compact filter bars; the persistent trigger label avoids variable-width selected labels.",
|
|
83
|
+
"The popup matches the trigger minimum width, may grow for content, and clamps to the viewport.",
|
|
84
|
+
"Long option collections scroll inside the popup; virtualization and remote search are not part of this version."
|
|
85
|
+
],
|
|
86
|
+
"frameworkCaveats": {
|
|
87
|
+
"customElements": [
|
|
88
|
+
"Assign values, options, and sections through JavaScript properties; array values cannot be represented safely as attributes."
|
|
89
|
+
],
|
|
90
|
+
"react": [
|
|
91
|
+
"Pass values, options, and sections as wrapper props and handle onDsChange, onDsClear, and onDsOpenChange."
|
|
92
|
+
],
|
|
93
|
+
"angular": [
|
|
94
|
+
"Import DsSelectMulti and SelectMultiValueAccessor when integrating with Angular Forms."
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
"references": [
|
|
98
|
+
{
|
|
99
|
+
"label": "Storybook examples",
|
|
100
|
+
"path": "src/wc/components/SelectMulti/SelectMulti.stories.ts"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"label": "Selection patterns",
|
|
104
|
+
"path": "src/docs/SelectionPatterns.mdx"
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"api": {
|
|
109
|
+
"props": {
|
|
110
|
+
"activeFill": {
|
|
111
|
+
"type": "boolean",
|
|
112
|
+
"resolvedType": "boolean",
|
|
113
|
+
"attribute": "active-fill",
|
|
114
|
+
"default": "true",
|
|
115
|
+
"required": false,
|
|
116
|
+
"mutable": false,
|
|
117
|
+
"description": "Show the selected interaction fill when at least one value exists."
|
|
118
|
+
},
|
|
119
|
+
"allowClear": {
|
|
120
|
+
"type": "boolean",
|
|
121
|
+
"resolvedType": "boolean",
|
|
122
|
+
"attribute": "allow-clear",
|
|
123
|
+
"default": "true",
|
|
124
|
+
"required": false,
|
|
125
|
+
"mutable": false,
|
|
126
|
+
"description": "Show the clear-all footer action when values exist."
|
|
127
|
+
},
|
|
128
|
+
"ariaDescribedby": {
|
|
129
|
+
"type": "string | undefined",
|
|
130
|
+
"resolvedType": "string | undefined",
|
|
131
|
+
"attribute": "aria-describedby",
|
|
132
|
+
"required": false,
|
|
133
|
+
"mutable": false,
|
|
134
|
+
"description": "Additional IDs that describe the combobox."
|
|
135
|
+
},
|
|
136
|
+
"ariaLabel": {
|
|
137
|
+
"type": "string | null",
|
|
138
|
+
"resolvedType": "null | string",
|
|
139
|
+
"attribute": "aria-label",
|
|
140
|
+
"default": "null",
|
|
141
|
+
"required": false,
|
|
142
|
+
"mutable": false,
|
|
143
|
+
"description": "Direct accessible name when no external label is available."
|
|
144
|
+
},
|
|
145
|
+
"ariaLabelledby": {
|
|
146
|
+
"type": "string | undefined",
|
|
147
|
+
"resolvedType": "string | undefined",
|
|
148
|
+
"attribute": "aria-labelledby",
|
|
149
|
+
"required": false,
|
|
150
|
+
"mutable": false,
|
|
151
|
+
"description": "IDs of elements that label the combobox."
|
|
152
|
+
},
|
|
153
|
+
"background": {
|
|
154
|
+
"type": "SelectMultiBackground | undefined",
|
|
155
|
+
"resolvedType": "\"always-dark\" | \"bold\" | \"faint\" | \"inverted\" | \"media\" | \"medium\" | \"strong\" | \"translucent\" | undefined",
|
|
156
|
+
"attribute": "background",
|
|
157
|
+
"required": false,
|
|
158
|
+
"mutable": false,
|
|
159
|
+
"description": "Actual parent surface context; omit on primary and secondary surfaces."
|
|
160
|
+
},
|
|
161
|
+
"clearLabel": {
|
|
162
|
+
"type": "string",
|
|
163
|
+
"resolvedType": "string",
|
|
164
|
+
"attribute": "clear-label",
|
|
165
|
+
"default": "'Clear'",
|
|
166
|
+
"required": false,
|
|
167
|
+
"mutable": false,
|
|
168
|
+
"description": "Localized clear-all action label."
|
|
169
|
+
},
|
|
170
|
+
"disabled": {
|
|
171
|
+
"type": "boolean",
|
|
172
|
+
"resolvedType": "boolean",
|
|
173
|
+
"attribute": "disabled",
|
|
174
|
+
"default": "false",
|
|
175
|
+
"required": false,
|
|
176
|
+
"mutable": false,
|
|
177
|
+
"description": "Native disabled state."
|
|
178
|
+
},
|
|
179
|
+
"error": {
|
|
180
|
+
"type": "boolean",
|
|
181
|
+
"resolvedType": "boolean",
|
|
182
|
+
"attribute": "error",
|
|
183
|
+
"default": "false",
|
|
184
|
+
"required": false,
|
|
185
|
+
"mutable": false,
|
|
186
|
+
"description": "Show invalid visual state."
|
|
187
|
+
},
|
|
188
|
+
"errorMessage": {
|
|
189
|
+
"type": "string | undefined",
|
|
190
|
+
"resolvedType": "string | undefined",
|
|
191
|
+
"attribute": "error-message",
|
|
192
|
+
"required": false,
|
|
193
|
+
"mutable": false,
|
|
194
|
+
"description": "Error text rendered below the trigger when error is true."
|
|
195
|
+
},
|
|
196
|
+
"hasBorder": {
|
|
197
|
+
"type": "boolean",
|
|
198
|
+
"resolvedType": "boolean",
|
|
199
|
+
"attribute": "has-border",
|
|
200
|
+
"default": "true",
|
|
201
|
+
"required": false,
|
|
202
|
+
"mutable": false,
|
|
203
|
+
"description": "Show the surface-aware inset border."
|
|
204
|
+
},
|
|
205
|
+
"icon": {
|
|
206
|
+
"type": "string | undefined",
|
|
207
|
+
"resolvedType": "string | undefined",
|
|
208
|
+
"attribute": "icon",
|
|
209
|
+
"required": false,
|
|
210
|
+
"mutable": false,
|
|
211
|
+
"description": "Optional trigger prefix icon name."
|
|
212
|
+
},
|
|
213
|
+
"inputId": {
|
|
214
|
+
"type": "string | undefined",
|
|
215
|
+
"resolvedType": "string | undefined",
|
|
216
|
+
"attribute": "input-id",
|
|
217
|
+
"required": false,
|
|
218
|
+
"mutable": false,
|
|
219
|
+
"description": "ID applied to the internal combobox trigger for external labels."
|
|
220
|
+
},
|
|
221
|
+
"isInactive": {
|
|
222
|
+
"type": "boolean",
|
|
223
|
+
"resolvedType": "boolean",
|
|
224
|
+
"attribute": "is-inactive",
|
|
225
|
+
"default": "false",
|
|
226
|
+
"required": false,
|
|
227
|
+
"mutable": false,
|
|
228
|
+
"description": "Shared inactive treatment; removes interaction and form submission."
|
|
229
|
+
},
|
|
230
|
+
"isLoading": {
|
|
231
|
+
"type": "boolean",
|
|
232
|
+
"resolvedType": "boolean",
|
|
233
|
+
"attribute": "is-loading",
|
|
234
|
+
"default": "false",
|
|
235
|
+
"required": false,
|
|
236
|
+
"mutable": false,
|
|
237
|
+
"description": "Replace the prefix with a loader and disable option interaction."
|
|
238
|
+
},
|
|
239
|
+
"loadingLabel": {
|
|
240
|
+
"type": "string",
|
|
241
|
+
"resolvedType": "string",
|
|
242
|
+
"attribute": "loading-label",
|
|
243
|
+
"default": "'Loading'",
|
|
244
|
+
"required": false,
|
|
245
|
+
"mutable": false,
|
|
246
|
+
"description": "Accessible loading status label."
|
|
247
|
+
},
|
|
248
|
+
"name": {
|
|
249
|
+
"type": "string | undefined",
|
|
250
|
+
"resolvedType": "string | undefined",
|
|
251
|
+
"attribute": "name",
|
|
252
|
+
"required": false,
|
|
253
|
+
"mutable": false,
|
|
254
|
+
"description": "Native form field name used for each repeated selected-value entry."
|
|
255
|
+
},
|
|
256
|
+
"noResultsText": {
|
|
257
|
+
"type": "string",
|
|
258
|
+
"resolvedType": "string",
|
|
259
|
+
"attribute": "no-results-text",
|
|
260
|
+
"default": "'No results found'",
|
|
261
|
+
"required": false,
|
|
262
|
+
"mutable": false,
|
|
263
|
+
"description": "Localized empty-filter result text."
|
|
264
|
+
},
|
|
265
|
+
"open": {
|
|
266
|
+
"type": "boolean",
|
|
267
|
+
"resolvedType": "boolean",
|
|
268
|
+
"attribute": "open",
|
|
269
|
+
"default": "false",
|
|
270
|
+
"required": false,
|
|
271
|
+
"mutable": true,
|
|
272
|
+
"description": "Controlled popup visibility."
|
|
273
|
+
},
|
|
274
|
+
"options": {
|
|
275
|
+
"type": "SelectMultiOption[]",
|
|
276
|
+
"resolvedType": "SelectMultiOption[]",
|
|
277
|
+
"default": "[]",
|
|
278
|
+
"required": false,
|
|
279
|
+
"mutable": false,
|
|
280
|
+
"description": "Flat choices. Assign arrays through the JavaScript property."
|
|
281
|
+
},
|
|
282
|
+
"placeholder": {
|
|
283
|
+
"type": "string",
|
|
284
|
+
"resolvedType": "string",
|
|
285
|
+
"attribute": "placeholder",
|
|
286
|
+
"default": "'Select'",
|
|
287
|
+
"required": false,
|
|
288
|
+
"mutable": false,
|
|
289
|
+
"description": "Persistent trigger label; selected option labels never replace it."
|
|
290
|
+
},
|
|
291
|
+
"required": {
|
|
292
|
+
"type": "boolean",
|
|
293
|
+
"resolvedType": "boolean",
|
|
294
|
+
"attribute": "required",
|
|
295
|
+
"default": "false",
|
|
296
|
+
"required": false,
|
|
297
|
+
"mutable": false,
|
|
298
|
+
"description": "Require at least one valid selected value."
|
|
299
|
+
},
|
|
300
|
+
"requiredMessage": {
|
|
301
|
+
"type": "string",
|
|
302
|
+
"resolvedType": "string",
|
|
303
|
+
"attribute": "required-message",
|
|
304
|
+
"default": "'This field is required.'",
|
|
305
|
+
"required": false,
|
|
306
|
+
"mutable": false,
|
|
307
|
+
"description": "Validation message used when required is missing."
|
|
308
|
+
},
|
|
309
|
+
"searchPlaceholder": {
|
|
310
|
+
"type": "string",
|
|
311
|
+
"resolvedType": "string",
|
|
312
|
+
"attribute": "search-placeholder",
|
|
313
|
+
"default": "'Search'",
|
|
314
|
+
"required": false,
|
|
315
|
+
"mutable": false,
|
|
316
|
+
"description": "Localized search-field placeholder and accessible name."
|
|
317
|
+
},
|
|
318
|
+
"searchable": {
|
|
319
|
+
"type": "boolean",
|
|
320
|
+
"resolvedType": "boolean",
|
|
321
|
+
"attribute": "searchable",
|
|
322
|
+
"default": "false",
|
|
323
|
+
"required": false,
|
|
324
|
+
"mutable": false,
|
|
325
|
+
"description": "Show immediate local filtering over option labels, subtext, and section headings."
|
|
326
|
+
},
|
|
327
|
+
"sections": {
|
|
328
|
+
"type": "SelectMultiSection[]",
|
|
329
|
+
"resolvedType": "SelectMultiSection[]",
|
|
330
|
+
"default": "[]",
|
|
331
|
+
"required": false,
|
|
332
|
+
"mutable": false,
|
|
333
|
+
"description": "Grouped choices; takes precedence over options. Assign through JavaScript."
|
|
334
|
+
},
|
|
335
|
+
"selectedLabel": {
|
|
336
|
+
"type": "string",
|
|
337
|
+
"resolvedType": "string",
|
|
338
|
+
"attribute": "selected-label",
|
|
339
|
+
"default": "'selected'",
|
|
340
|
+
"required": false,
|
|
341
|
+
"mutable": false,
|
|
342
|
+
"description": "Localized noun displayed after the selected count."
|
|
343
|
+
},
|
|
344
|
+
"size": {
|
|
345
|
+
"type": "SelectMultiSize",
|
|
346
|
+
"resolvedType": "\"md\" | \"sm\" | \"xs\"",
|
|
347
|
+
"attribute": "size",
|
|
348
|
+
"default": "'md'",
|
|
349
|
+
"required": false,
|
|
350
|
+
"mutable": false,
|
|
351
|
+
"description": "Control density."
|
|
352
|
+
},
|
|
353
|
+
"values": {
|
|
354
|
+
"type": "string[]",
|
|
355
|
+
"resolvedType": "string[]",
|
|
356
|
+
"default": "[]",
|
|
357
|
+
"required": false,
|
|
358
|
+
"mutable": true,
|
|
359
|
+
"description": "Selected values. Assign arrays through the JavaScript property."
|
|
360
|
+
},
|
|
361
|
+
"width": {
|
|
362
|
+
"type": "SelectMultiWidth",
|
|
363
|
+
"resolvedType": "\"fill\" | \"hug\"",
|
|
364
|
+
"attribute": "width",
|
|
365
|
+
"default": "'hug'",
|
|
366
|
+
"required": false,
|
|
367
|
+
"mutable": false,
|
|
368
|
+
"description": "Width fit — hug content (default) or fill the parent."
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
"events": [
|
|
372
|
+
{
|
|
373
|
+
"name": "dsChange",
|
|
374
|
+
"detail": "string[]",
|
|
375
|
+
"bubbles": true,
|
|
376
|
+
"cancelable": true,
|
|
377
|
+
"composed": true,
|
|
378
|
+
"description": "Emitted after user toggles or clearing with a new values array."
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
"name": "dsClear",
|
|
382
|
+
"detail": "void",
|
|
383
|
+
"bubbles": true,
|
|
384
|
+
"cancelable": true,
|
|
385
|
+
"composed": true,
|
|
386
|
+
"description": "Emitted after the footer clear-all action."
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
"name": "dsOpenChange",
|
|
390
|
+
"detail": "boolean",
|
|
391
|
+
"bubbles": true,
|
|
392
|
+
"cancelable": true,
|
|
393
|
+
"composed": true,
|
|
394
|
+
"description": "Emitted whenever popup visibility changes."
|
|
395
|
+
}
|
|
396
|
+
],
|
|
397
|
+
"methods": [
|
|
398
|
+
{
|
|
399
|
+
"name": "setFocus",
|
|
400
|
+
"signature": "setFocus() => Promise<void>"
|
|
401
|
+
}
|
|
402
|
+
],
|
|
403
|
+
"slots": []
|
|
404
|
+
},
|
|
405
|
+
"props": {
|
|
406
|
+
"activeFill": {
|
|
407
|
+
"type": "boolean",
|
|
408
|
+
"resolvedType": "boolean",
|
|
409
|
+
"attribute": "active-fill",
|
|
410
|
+
"default": "true",
|
|
411
|
+
"required": false,
|
|
412
|
+
"mutable": false,
|
|
413
|
+
"description": "Show the selected interaction fill when at least one value exists."
|
|
414
|
+
},
|
|
415
|
+
"allowClear": {
|
|
416
|
+
"type": "boolean",
|
|
417
|
+
"resolvedType": "boolean",
|
|
418
|
+
"attribute": "allow-clear",
|
|
419
|
+
"default": "true",
|
|
420
|
+
"required": false,
|
|
421
|
+
"mutable": false,
|
|
422
|
+
"description": "Show the clear-all footer action when values exist."
|
|
423
|
+
},
|
|
424
|
+
"ariaDescribedby": {
|
|
425
|
+
"type": "string | undefined",
|
|
426
|
+
"resolvedType": "string | undefined",
|
|
427
|
+
"attribute": "aria-describedby",
|
|
428
|
+
"required": false,
|
|
429
|
+
"mutable": false,
|
|
430
|
+
"description": "Additional IDs that describe the combobox."
|
|
431
|
+
},
|
|
432
|
+
"ariaLabel": {
|
|
433
|
+
"type": "string | null",
|
|
434
|
+
"resolvedType": "null | string",
|
|
435
|
+
"attribute": "aria-label",
|
|
436
|
+
"default": "null",
|
|
437
|
+
"required": false,
|
|
438
|
+
"mutable": false,
|
|
439
|
+
"description": "Direct accessible name when no external label is available."
|
|
440
|
+
},
|
|
441
|
+
"ariaLabelledby": {
|
|
442
|
+
"type": "string | undefined",
|
|
443
|
+
"resolvedType": "string | undefined",
|
|
444
|
+
"attribute": "aria-labelledby",
|
|
445
|
+
"required": false,
|
|
446
|
+
"mutable": false,
|
|
447
|
+
"description": "IDs of elements that label the combobox."
|
|
448
|
+
},
|
|
449
|
+
"background": {
|
|
450
|
+
"type": "SelectMultiBackground | undefined",
|
|
451
|
+
"resolvedType": "\"always-dark\" | \"bold\" | \"faint\" | \"inverted\" | \"media\" | \"medium\" | \"strong\" | \"translucent\" | undefined",
|
|
452
|
+
"attribute": "background",
|
|
453
|
+
"required": false,
|
|
454
|
+
"mutable": false,
|
|
455
|
+
"description": "Actual parent surface context; omit on primary and secondary surfaces."
|
|
456
|
+
},
|
|
457
|
+
"clearLabel": {
|
|
458
|
+
"type": "string",
|
|
459
|
+
"resolvedType": "string",
|
|
460
|
+
"attribute": "clear-label",
|
|
461
|
+
"default": "'Clear'",
|
|
462
|
+
"required": false,
|
|
463
|
+
"mutable": false,
|
|
464
|
+
"description": "Localized clear-all action label."
|
|
465
|
+
},
|
|
466
|
+
"disabled": {
|
|
467
|
+
"type": "boolean",
|
|
468
|
+
"resolvedType": "boolean",
|
|
469
|
+
"attribute": "disabled",
|
|
470
|
+
"default": "false",
|
|
471
|
+
"required": false,
|
|
472
|
+
"mutable": false,
|
|
473
|
+
"description": "Native disabled state."
|
|
474
|
+
},
|
|
475
|
+
"error": {
|
|
476
|
+
"type": "boolean",
|
|
477
|
+
"resolvedType": "boolean",
|
|
478
|
+
"attribute": "error",
|
|
479
|
+
"default": "false",
|
|
480
|
+
"required": false,
|
|
481
|
+
"mutable": false,
|
|
482
|
+
"description": "Show invalid visual state."
|
|
483
|
+
},
|
|
484
|
+
"errorMessage": {
|
|
485
|
+
"type": "string | undefined",
|
|
486
|
+
"resolvedType": "string | undefined",
|
|
487
|
+
"attribute": "error-message",
|
|
488
|
+
"required": false,
|
|
489
|
+
"mutable": false,
|
|
490
|
+
"description": "Error text rendered below the trigger when error is true."
|
|
491
|
+
},
|
|
492
|
+
"hasBorder": {
|
|
493
|
+
"type": "boolean",
|
|
494
|
+
"resolvedType": "boolean",
|
|
495
|
+
"attribute": "has-border",
|
|
496
|
+
"default": "true",
|
|
497
|
+
"required": false,
|
|
498
|
+
"mutable": false,
|
|
499
|
+
"description": "Show the surface-aware inset border."
|
|
500
|
+
},
|
|
501
|
+
"icon": {
|
|
502
|
+
"type": "string | undefined",
|
|
503
|
+
"resolvedType": "string | undefined",
|
|
504
|
+
"attribute": "icon",
|
|
505
|
+
"required": false,
|
|
506
|
+
"mutable": false,
|
|
507
|
+
"description": "Optional trigger prefix icon name."
|
|
508
|
+
},
|
|
509
|
+
"inputId": {
|
|
510
|
+
"type": "string | undefined",
|
|
511
|
+
"resolvedType": "string | undefined",
|
|
512
|
+
"attribute": "input-id",
|
|
513
|
+
"required": false,
|
|
514
|
+
"mutable": false,
|
|
515
|
+
"description": "ID applied to the internal combobox trigger for external labels."
|
|
516
|
+
},
|
|
517
|
+
"isInactive": {
|
|
518
|
+
"type": "boolean",
|
|
519
|
+
"resolvedType": "boolean",
|
|
520
|
+
"attribute": "is-inactive",
|
|
521
|
+
"default": "false",
|
|
522
|
+
"required": false,
|
|
523
|
+
"mutable": false,
|
|
524
|
+
"description": "Shared inactive treatment; removes interaction and form submission."
|
|
525
|
+
},
|
|
526
|
+
"isLoading": {
|
|
527
|
+
"type": "boolean",
|
|
528
|
+
"resolvedType": "boolean",
|
|
529
|
+
"attribute": "is-loading",
|
|
530
|
+
"default": "false",
|
|
531
|
+
"required": false,
|
|
532
|
+
"mutable": false,
|
|
533
|
+
"description": "Replace the prefix with a loader and disable option interaction."
|
|
534
|
+
},
|
|
535
|
+
"loadingLabel": {
|
|
536
|
+
"type": "string",
|
|
537
|
+
"resolvedType": "string",
|
|
538
|
+
"attribute": "loading-label",
|
|
539
|
+
"default": "'Loading'",
|
|
540
|
+
"required": false,
|
|
541
|
+
"mutable": false,
|
|
542
|
+
"description": "Accessible loading status label."
|
|
543
|
+
},
|
|
544
|
+
"name": {
|
|
545
|
+
"type": "string | undefined",
|
|
546
|
+
"resolvedType": "string | undefined",
|
|
547
|
+
"attribute": "name",
|
|
548
|
+
"required": false,
|
|
549
|
+
"mutable": false,
|
|
550
|
+
"description": "Native form field name used for each repeated selected-value entry."
|
|
551
|
+
},
|
|
552
|
+
"noResultsText": {
|
|
553
|
+
"type": "string",
|
|
554
|
+
"resolvedType": "string",
|
|
555
|
+
"attribute": "no-results-text",
|
|
556
|
+
"default": "'No results found'",
|
|
557
|
+
"required": false,
|
|
558
|
+
"mutable": false,
|
|
559
|
+
"description": "Localized empty-filter result text."
|
|
560
|
+
},
|
|
561
|
+
"open": {
|
|
562
|
+
"type": "boolean",
|
|
563
|
+
"resolvedType": "boolean",
|
|
564
|
+
"attribute": "open",
|
|
565
|
+
"default": "false",
|
|
566
|
+
"required": false,
|
|
567
|
+
"mutable": true,
|
|
568
|
+
"description": "Controlled popup visibility."
|
|
569
|
+
},
|
|
570
|
+
"options": {
|
|
571
|
+
"type": "SelectMultiOption[]",
|
|
572
|
+
"resolvedType": "SelectMultiOption[]",
|
|
573
|
+
"default": "[]",
|
|
574
|
+
"required": false,
|
|
575
|
+
"mutable": false,
|
|
576
|
+
"description": "Flat choices. Assign arrays through the JavaScript property."
|
|
577
|
+
},
|
|
578
|
+
"placeholder": {
|
|
579
|
+
"type": "string",
|
|
580
|
+
"resolvedType": "string",
|
|
581
|
+
"attribute": "placeholder",
|
|
582
|
+
"default": "'Select'",
|
|
583
|
+
"required": false,
|
|
584
|
+
"mutable": false,
|
|
585
|
+
"description": "Persistent trigger label; selected option labels never replace it."
|
|
586
|
+
},
|
|
587
|
+
"required": {
|
|
588
|
+
"type": "boolean",
|
|
589
|
+
"resolvedType": "boolean",
|
|
590
|
+
"attribute": "required",
|
|
591
|
+
"default": "false",
|
|
592
|
+
"required": false,
|
|
593
|
+
"mutable": false,
|
|
594
|
+
"description": "Require at least one valid selected value."
|
|
595
|
+
},
|
|
596
|
+
"requiredMessage": {
|
|
597
|
+
"type": "string",
|
|
598
|
+
"resolvedType": "string",
|
|
599
|
+
"attribute": "required-message",
|
|
600
|
+
"default": "'This field is required.'",
|
|
601
|
+
"required": false,
|
|
602
|
+
"mutable": false,
|
|
603
|
+
"description": "Validation message used when required is missing."
|
|
604
|
+
},
|
|
605
|
+
"searchPlaceholder": {
|
|
606
|
+
"type": "string",
|
|
607
|
+
"resolvedType": "string",
|
|
608
|
+
"attribute": "search-placeholder",
|
|
609
|
+
"default": "'Search'",
|
|
610
|
+
"required": false,
|
|
611
|
+
"mutable": false,
|
|
612
|
+
"description": "Localized search-field placeholder and accessible name."
|
|
613
|
+
},
|
|
614
|
+
"searchable": {
|
|
615
|
+
"type": "boolean",
|
|
616
|
+
"resolvedType": "boolean",
|
|
617
|
+
"attribute": "searchable",
|
|
618
|
+
"default": "false",
|
|
619
|
+
"required": false,
|
|
620
|
+
"mutable": false,
|
|
621
|
+
"description": "Show immediate local filtering over option labels, subtext, and section headings."
|
|
622
|
+
},
|
|
623
|
+
"sections": {
|
|
624
|
+
"type": "SelectMultiSection[]",
|
|
625
|
+
"resolvedType": "SelectMultiSection[]",
|
|
626
|
+
"default": "[]",
|
|
627
|
+
"required": false,
|
|
628
|
+
"mutable": false,
|
|
629
|
+
"description": "Grouped choices; takes precedence over options. Assign through JavaScript."
|
|
630
|
+
},
|
|
631
|
+
"selectedLabel": {
|
|
632
|
+
"type": "string",
|
|
633
|
+
"resolvedType": "string",
|
|
634
|
+
"attribute": "selected-label",
|
|
635
|
+
"default": "'selected'",
|
|
636
|
+
"required": false,
|
|
637
|
+
"mutable": false,
|
|
638
|
+
"description": "Localized noun displayed after the selected count."
|
|
639
|
+
},
|
|
640
|
+
"size": {
|
|
641
|
+
"type": "SelectMultiSize",
|
|
642
|
+
"resolvedType": "\"md\" | \"sm\" | \"xs\"",
|
|
643
|
+
"attribute": "size",
|
|
644
|
+
"default": "'md'",
|
|
645
|
+
"required": false,
|
|
646
|
+
"mutable": false,
|
|
647
|
+
"description": "Control density."
|
|
648
|
+
},
|
|
649
|
+
"values": {
|
|
650
|
+
"type": "string[]",
|
|
651
|
+
"resolvedType": "string[]",
|
|
652
|
+
"default": "[]",
|
|
653
|
+
"required": false,
|
|
654
|
+
"mutable": true,
|
|
655
|
+
"description": "Selected values. Assign arrays through the JavaScript property."
|
|
656
|
+
},
|
|
657
|
+
"width": {
|
|
658
|
+
"type": "SelectMultiWidth",
|
|
659
|
+
"resolvedType": "\"fill\" | \"hug\"",
|
|
660
|
+
"attribute": "width",
|
|
661
|
+
"default": "'hug'",
|
|
662
|
+
"required": false,
|
|
663
|
+
"mutable": false,
|
|
664
|
+
"description": "Width fit — hug content (default) or fill the parent."
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
"events": [
|
|
668
|
+
{
|
|
669
|
+
"name": "dsChange",
|
|
670
|
+
"detail": "string[]",
|
|
671
|
+
"bubbles": true,
|
|
672
|
+
"cancelable": true,
|
|
673
|
+
"composed": true,
|
|
674
|
+
"description": "Emitted after user toggles or clearing with a new values array."
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
"name": "dsClear",
|
|
678
|
+
"detail": "void",
|
|
679
|
+
"bubbles": true,
|
|
680
|
+
"cancelable": true,
|
|
681
|
+
"composed": true,
|
|
682
|
+
"description": "Emitted after the footer clear-all action."
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
"name": "dsOpenChange",
|
|
686
|
+
"detail": "boolean",
|
|
687
|
+
"bubbles": true,
|
|
688
|
+
"cancelable": true,
|
|
689
|
+
"composed": true,
|
|
690
|
+
"description": "Emitted whenever popup visibility changes."
|
|
691
|
+
}
|
|
692
|
+
],
|
|
693
|
+
"methods": [
|
|
694
|
+
{
|
|
695
|
+
"name": "setFocus",
|
|
696
|
+
"signature": "setFocus() => Promise<void>"
|
|
697
|
+
}
|
|
698
|
+
],
|
|
699
|
+
"slots": [],
|
|
700
|
+
"exports": {
|
|
701
|
+
"customElement": "ds-select-multi",
|
|
702
|
+
"react": "DsSelectMulti",
|
|
703
|
+
"angular": "DsSelectMulti"
|
|
704
|
+
},
|
|
705
|
+
"consumption": {
|
|
706
|
+
"install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
|
|
707
|
+
"cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
|
|
708
|
+
"customElements": {
|
|
709
|
+
"import": "import '@ds-mo/ui/dist/components/ds-select-multi.js';",
|
|
710
|
+
"example": "<ds-select-multi></ds-select-multi>"
|
|
711
|
+
},
|
|
712
|
+
"react": {
|
|
713
|
+
"import": "import { DsSelectMulti } from '@ds-mo/ui/react';",
|
|
714
|
+
"example": "<DsSelectMulti />"
|
|
715
|
+
},
|
|
716
|
+
"angular": {
|
|
717
|
+
"import": "import { DsSelectMulti } from '@ds-mo/ui/angular/ds-select-multi';",
|
|
718
|
+
"example": "<ds-select-multi></ds-select-multi>"
|
|
719
|
+
},
|
|
720
|
+
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: options, sections, values.",
|
|
721
|
+
"peerDependencies": {
|
|
722
|
+
"required": [
|
|
723
|
+
"@ds-mo/tokens ^3.1.1",
|
|
724
|
+
"@ds-mo/icons ^6.2.0"
|
|
725
|
+
],
|
|
726
|
+
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
},
|
|
730
|
+
"dependencies": [
|
|
731
|
+
"@ds-mo/ui",
|
|
732
|
+
"@ds-mo/tokens",
|
|
733
|
+
"@ds-mo/icons"
|
|
734
|
+
],
|
|
735
|
+
"registryDependencies": [
|
|
736
|
+
"button-unfilled",
|
|
737
|
+
"checkbox",
|
|
738
|
+
"empty-state",
|
|
739
|
+
"icon",
|
|
740
|
+
"loader",
|
|
741
|
+
"text"
|
|
742
|
+
],
|
|
743
|
+
"files": [
|
|
744
|
+
{
|
|
745
|
+
"path": "src/wc/components/SelectMulti/SelectMulti.css",
|
|
746
|
+
"content": "@import '../Select/Select.css';\n",
|
|
747
|
+
"type": "registry:ui"
|
|
748
|
+
},
|
|
749
|
+
{
|
|
750
|
+
"path": "src/wc/components/SelectMulti/SelectMulti.tsx",
|
|
751
|
+
"content": "import {\n AttachInternals,\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\nimport {\n controlWidthClass,\n CONTROL_TEXT_VARIANT,\n choicePopupMinWidth,\n resolveCssLengthPx,\n resolveCssTimeMs,\n resolveChoicePopupAlignOffset,\n TOKEN_DEFAULTS,\n type ControlWidth,\n} from '../../utils';\nimport { computeAnchoredPopupPosition } from '../../utils/anchored-popup';\nimport { ChoiceFooter, ChoiceOptionRow, ChoiceSearch } from '../../utils/choice-list-parts';\nimport {\n choiceBackgroundClassMap,\n choiceListUsesSubtext,\n enabledChoiceIndexes,\n filterChoiceSections,\n findChoiceTypeaheadMatch,\n flattenChoiceSections,\n moveChoiceIndex,\n resolveChoiceSections,\n} from '../../utils/choice-list';\nimport type {\n SelectBackground,\n SelectOption,\n SelectSection,\n SelectSize,\n} from '../Select/Select';\n\nexport type SelectMultiOption = Omit<SelectOption, 'icon'>;\nexport type SelectMultiSection = Omit<SelectSection, 'options'> & {\n options: SelectMultiOption[];\n};\nexport type SelectMultiBackground = SelectBackground;\nexport type SelectMultiSize = SelectSize;\nexport type SelectMultiWidth = ControlWidth;\n\nconst ICON_SIZE: Record<SelectMultiSize, 'md' | 'sm' | 'xs'> = {\n md: 'md',\n sm: 'sm',\n xs: 'xs',\n};\n\nlet selectMultiId = 0;\n/** rAF retries while the conditionally rendered popup mounts. */\nconst POSITION_RETRY_BUDGET = 8;\n\n@Component({\n tag: 'ds-select-multi',\n styleUrl: 'SelectMulti.css',\n scoped: true,\n formAssociated: true,\n})\nexport class SelectMulti {\n @Element() el!: HTMLElement;\n @AttachInternals() internals!: ElementInternals;\n\n /** Flat choices. Assign arrays through the JavaScript property. */\n @Prop() options: SelectMultiOption[] = [];\n /** Grouped choices; takes precedence over options. Assign through JavaScript. */\n @Prop() sections: SelectMultiSection[] = [];\n /** Selected values. Assign arrays through the JavaScript property. */\n @Prop({ mutable: true }) values: string[] = [];\n /** Controlled popup visibility. */\n @Prop({ mutable: true, reflect: true }) open: boolean = false;\n /** Native form field name used for each repeated selected-value entry. */\n @Prop({ reflect: true }) name: string | undefined;\n /** Native disabled state. */\n @Prop({ reflect: true }) disabled: boolean = false;\n /** Require at least one valid selected value. */\n @Prop({ reflect: true }) required: boolean = false;\n /** Validation message used when required is missing. */\n @Prop() requiredMessage: string = 'This field is required.';\n /** Persistent trigger label; selected option labels never replace it. */\n @Prop() placeholder: string = 'Select';\n /** Control density. */\n @Prop() size: SelectMultiSize = 'md';\n /** Width fit — hug content (default) or fill the parent. */\n @Prop() width: SelectMultiWidth = 'hug';\n /** Shared inactive treatment; removes interaction and form submission. */\n @Prop() isInactive: boolean = false;\n /** Replace the prefix with a loader and disable option interaction. */\n @Prop() isLoading: boolean = false;\n /** Show the selected interaction fill when at least one value exists. */\n @Prop() activeFill: boolean = true;\n /** Show the surface-aware inset border. */\n @Prop() hasBorder: boolean = true;\n /** Optional trigger prefix icon name. */\n @Prop() icon: string | undefined;\n /** Show the clear-all footer action when values exist. */\n @Prop() allowClear: boolean = true;\n /** Localized clear-all action label. */\n @Prop() clearLabel: string = 'Clear';\n /** Localized noun displayed after the selected count. */\n @Prop() selectedLabel: string = 'selected';\n /** Show immediate local filtering over option labels, subtext, and section headings. */\n @Prop() searchable: boolean = false;\n /** Localized search-field placeholder and accessible name. */\n @Prop() searchPlaceholder: string = 'Search';\n /** Localized empty-filter result text. */\n @Prop() noResultsText: string = 'No results found';\n /** Accessible loading status label. */\n @Prop() loadingLabel: string = 'Loading';\n /** Actual parent surface context; omit on primary and secondary surfaces. */\n @Prop() background: SelectMultiBackground | undefined;\n /** Show invalid visual state. */\n @Prop() error: boolean = false;\n /** Error text rendered below the trigger when error is true. */\n @Prop() errorMessage: string | undefined;\n /** ID applied to the internal combobox trigger for external labels. */\n @Prop() inputId: string | undefined;\n /** Direct accessible name when no external label is available. */\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | null = null;\n /** IDs of elements that label the combobox. */\n @Prop({ attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined;\n /** Additional IDs that describe the combobox. */\n @Prop({ attribute: 'aria-describedby' }) ariaDescribedby: string | undefined;\n\n /** Emitted after user toggles or clearing with a new values array. */\n @Event() dsChange!: EventEmitter<string[]>;\n /** Emitted after the footer clear-all action. */\n @Event() dsClear!: EventEmitter<void>;\n /** Emitted whenever popup visibility changes. */\n @Event() dsOpenChange!: EventEmitter<boolean>;\n\n @State() private activeIndex = -1;\n @State() private searchTerm = '';\n @State() private formDisabled = false;\n @State() private position = { x: 0, y: 0 };\n @State() private positionReady = false;\n @State() private focusRingVisible = false;\n\n private readonly generatedId = `ds-select-multi-${++selectMultiId}`;\n private readonly listboxId = `${this.generatedId}-listbox`;\n private readonly errorId = `${this.generatedId}-error`;\n private triggerEl: HTMLButtonElement | null = null;\n private popupEl: HTMLDivElement | null = null;\n private searchEl: HTMLInputElement | null = null;\n private initialValues: string[] = [];\n private typeahead = '';\n private typeaheadTimer: ReturnType<typeof setTimeout> | null = null;\n private outsideHandler: ((event: MouseEvent) => void) | null = null;\n private repositionHandler: (() => void) | null = null;\n private positionRetryRaf: number | null = null;\n\n componentWillLoad() {\n this.initialValues = [...this.values];\n this.syncFormValue();\n }\n\n componentDidLoad() {\n if (this.open) this.onOpenChange(true);\n }\n\n disconnectedCallback() {\n this.cancelPositionRetry();\n this.unbindPopupListeners();\n if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);\n }\n\n @Watch('values')\n @Watch('disabled')\n @Watch('isInactive')\n @Watch('required')\n @Watch('name')\n @Watch('options')\n @Watch('sections')\n syncFormValue() {\n const resolvedValues = this.resolvedValues;\n if (this.isDisabled || !this.name || resolvedValues.length === 0) {\n this.internals.setFormValue(null);\n } else {\n const data = new FormData();\n resolvedValues.forEach(value => data.append(this.name as string, value));\n this.internals.setFormValue(data, JSON.stringify(resolvedValues));\n }\n const missing = this.required && !this.isDisabled && resolvedValues.length === 0;\n this.internals.setValidity(missing ? { valueMissing: true } : {}, missing ? this.requiredMessage : '');\n if (this.open) {\n const enabled = enabledChoiceIndexes(this.visibleOptions);\n if (!enabled.includes(this.activeIndex)) this.activeIndex = enabled[0] ?? -1;\n requestAnimationFrame(() => this.updatePosition());\n }\n }\n\n @Watch('isLoading')\n onLoadingChange() {\n if (this.open) requestAnimationFrame(() => this.updatePosition());\n }\n\n @Watch('open')\n onOpenChange(open: boolean) {\n this.dsOpenChange.emit(open);\n if (open) {\n this.bindPopupListeners();\n this.schedulePositionUpdate(() => {\n this.scrollActiveOptionIntoView();\n if (this.searchable) this.searchEl?.focus();\n });\n } else {\n this.cancelPositionRetry();\n this.unbindPopupListeners();\n this.searchTerm = '';\n this.positionReady = false;\n }\n }\n\n @Watch('searchTerm')\n onSearchTermChange() {\n this.activeIndex = enabledChoiceIndexes(this.visibleOptions)[0] ?? -1;\n requestAnimationFrame(() => {\n this.updatePosition();\n this.scrollActiveOptionIntoView();\n });\n }\n\n @Watch('activeIndex')\n onActiveIndexChange() {\n requestAnimationFrame(() => this.scrollActiveOptionIntoView());\n }\n\n formDisabledCallback(disabled: boolean) {\n this.formDisabled = disabled;\n this.syncFormValue();\n }\n\n formResetCallback() {\n this.values = [...this.initialValues];\n this.closePopup();\n }\n\n formStateRestoreCallback(state: string | File | FormData | null) {\n if (typeof state !== 'string') {\n this.values = [];\n return;\n }\n try {\n const restored = JSON.parse(state);\n this.values = Array.isArray(restored)\n ? restored.filter((value): value is string => typeof value === 'string')\n : [];\n } catch {\n this.values = [];\n }\n }\n\n @Method()\n async setFocus() {\n this.triggerEl?.focus();\n }\n\n private get isDisabled(): boolean {\n return this.disabled || this.isInactive || this.formDisabled;\n }\n\n private get allSections(): SelectMultiSection[] {\n return resolveChoiceSections(this.options, this.sections);\n }\n\n private get allOptions(): SelectMultiOption[] {\n return flattenChoiceSections(this.allSections);\n }\n\n private get visibleSections(): SelectMultiSection[] {\n return this.searchable\n ? filterChoiceSections(this.allSections, this.searchTerm)\n : this.allSections;\n }\n\n private get visibleOptions(): SelectMultiOption[] {\n return flattenChoiceSections(this.visibleSections);\n }\n\n private get resolvedValues(): string[] {\n const valid = new Set(this.allOptions.map(option => option.value));\n return [...new Set(this.values.filter(value => valid.has(value)))];\n }\n\n private get hasSelection(): boolean {\n return this.resolvedValues.length > 0;\n }\n\n private get activeOptionId(): string | undefined {\n return !this.isLoading && this.activeIndex >= 0\n ? `${this.generatedId}-option-${this.activeIndex}`\n : undefined;\n }\n\n private scrollActiveOptionIntoView() {\n if (!this.open || !this.activeOptionId) return;\n this.el\n .querySelector<HTMLElement>(`#${this.activeOptionId}`)\n ?.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n }\n\n private bindPopupListeners() {\n this.unbindPopupListeners();\n this.outsideHandler = event => {\n if (this.el.contains(event.target as Node)) return;\n this.closePopup();\n };\n this.repositionHandler = () => this.updatePosition();\n document.addEventListener('mousedown', this.outsideHandler, true);\n window.addEventListener('scroll', this.repositionHandler, true);\n window.addEventListener('resize', this.repositionHandler);\n }\n\n private unbindPopupListeners() {\n if (this.outsideHandler) {\n document.removeEventListener('mousedown', this.outsideHandler, true);\n this.outsideHandler = null;\n }\n if (this.repositionHandler) {\n window.removeEventListener('scroll', this.repositionHandler, true);\n window.removeEventListener('resize', this.repositionHandler);\n this.repositionHandler = null;\n }\n }\n\n private cancelPositionRetry() {\n if (this.positionRetryRaf !== null) {\n cancelAnimationFrame(this.positionRetryRaf);\n this.positionRetryRaf = null;\n }\n }\n\n /** Retry until the conditionally rendered popup is mounted and measurable. */\n private schedulePositionUpdate(onReady?: () => void) {\n if (!this.open) return;\n\n this.cancelPositionRetry();\n this.positionReady = false;\n let remaining = POSITION_RETRY_BUDGET;\n\n const attempt = () => {\n this.positionRetryRaf = null;\n if (!this.open) return;\n\n if (this.updatePosition()) {\n onReady?.();\n return;\n }\n\n if (remaining > 0) {\n remaining -= 1;\n this.positionRetryRaf = requestAnimationFrame(attempt);\n }\n };\n\n this.positionRetryRaf = requestAnimationFrame(attempt);\n }\n\n /** @returns `true` when the current popup was found and positioned. */\n private updatePosition(): boolean {\n if (\n !this.open ||\n !this.triggerEl ||\n !this.popupEl ||\n !this.popupEl.isConnected ||\n !this.el.contains(this.popupEl)\n ) return false;\n const sectionPadding = resolveCssLengthPx(TOKEN_DEFAULTS.space050, TOKEN_DEFAULTS.space050);\n this.popupEl.style.minWidth = `${choicePopupMinWidth(this.triggerEl.offsetWidth, sectionPadding)}px`;\n this.position = computeAnchoredPopupPosition({\n anchorRect: this.triggerEl.getBoundingClientRect(),\n popupWidth: this.popupEl.offsetWidth,\n popupHeight: this.popupEl.offsetHeight,\n side: 'bottom',\n align: 'start',\n sideOffsetPx: sectionPadding,\n alignOffsetPx: resolveChoicePopupAlignOffset({\n align: 'start',\n alignOffsetPx: 0,\n sectionInsetPx: sectionPadding,\n }),\n viewportPadPx: sectionPadding,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n });\n this.positionReady = true;\n return true;\n }\n\n private openPopup(focusVisible: boolean, edge?: 'first' | 'last') {\n if (this.isDisabled || (!this.allOptions.length && !this.isLoading)) return;\n const enabled = enabledChoiceIndexes(this.visibleOptions);\n this.activeIndex =\n edge === 'last'\n ? (enabled[enabled.length - 1] ?? -1)\n : (enabled[0] ?? -1);\n this.focusRingVisible = focusVisible;\n this.open = true;\n }\n\n private closePopup(restoreFocus = false) {\n if (!this.open) return;\n this.open = false;\n if (restoreFocus) requestAnimationFrame(() => this.triggerEl?.focus());\n }\n\n private toggleOption(option: SelectMultiOption) {\n if (option.isInactive || this.isLoading) return;\n const current = this.resolvedValues;\n const next = current.includes(option.value)\n ? current.filter(value => value !== option.value)\n : [...current, option.value];\n this.values = next;\n this.dsChange.emit([...next]);\n }\n\n private clearSelection = (event: Event) => {\n event.preventDefault();\n event.stopPropagation();\n this.values = [];\n this.dsChange.emit([]);\n this.dsClear.emit();\n requestAnimationFrame(() => (this.searchable ? this.searchEl?.focus() : this.triggerEl?.focus()));\n };\n\n private handleTypeahead(key: string) {\n if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);\n this.focusRingVisible = true;\n const normalized = key.toLocaleLowerCase();\n const repeatedCharacter =\n this.typeahead.length > 0 &&\n [...this.typeahead].every(character => character === normalized);\n this.typeahead = repeatedCharacter ? normalized : `${this.typeahead}${normalized}`;\n const match = findChoiceTypeaheadMatch(this.visibleOptions, this.typeahead, this.activeIndex);\n if (match >= 0) this.activeIndex = match;\n const resetMs = resolveCssTimeMs(\n TOKEN_DEFAULTS.animationDurationMedium1,\n TOKEN_DEFAULTS.animationDurationMedium1,\n );\n this.typeaheadTimer = setTimeout(() => {\n this.typeahead = '';\n this.typeaheadTimer = null;\n }, resetMs);\n }\n\n private handleListKeyDown(event: KeyboardEvent) {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.focusRingVisible = true;\n this.activeIndex = moveChoiceIndex(this.visibleOptions, this.activeIndex, 1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.focusRingVisible = true;\n this.activeIndex = moveChoiceIndex(this.visibleOptions, this.activeIndex, -1);\n break;\n case 'Home':\n event.preventDefault();\n this.focusRingVisible = true;\n this.activeIndex = enabledChoiceIndexes(this.visibleOptions)[0] ?? -1;\n break;\n case 'End': {\n event.preventDefault();\n this.focusRingVisible = true;\n const enabled = enabledChoiceIndexes(this.visibleOptions);\n this.activeIndex = enabled[enabled.length - 1] ?? -1;\n break;\n }\n case 'Enter':\n case ' ': {\n if (event.key === ' ' && this.searchable && event.target === this.searchEl) break;\n event.preventDefault();\n const option = this.visibleOptions[this.activeIndex];\n if (option) this.toggleOption(option);\n break;\n }\n case 'Escape':\n event.preventDefault();\n this.closePopup(true);\n break;\n case 'Tab':\n this.closePopup();\n break;\n default:\n if (!this.searchable && event.key.length === 1 && !event.metaKey && !event.ctrlKey && !event.altKey) {\n this.handleTypeahead(event.key);\n }\n }\n }\n\n private handleTriggerKeyDown = (event: KeyboardEvent) => {\n if (!this.open) {\n if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(event.key)) {\n event.preventDefault();\n this.openPopup(true, event.key === 'ArrowUp' ? 'last' : 'first');\n } else if (event.key.length === 1 && !event.metaKey && !event.ctrlKey && !event.altKey) {\n event.preventDefault();\n this.openPopup(true);\n if (this.searchable) this.searchTerm = event.key;\n else this.handleTypeahead(event.key);\n }\n return;\n }\n this.handleListKeyDown(event);\n };\n\n private renderOption(option: SelectMultiOption, index: number, usesSubtext: boolean) {\n const selected = this.values.includes(option.value);\n const active = this.activeIndex === index;\n return (\n <ChoiceOptionRow\n id={`${this.generatedId}-option-${index}`}\n option={option}\n selected={selected}\n active={active}\n focusRingVisible={this.focusRingVisible}\n usesSubtext={usesSubtext}\n leading={(\n <span class=\"ds-choice-item__icon ds-interaction-fill__content\" aria-hidden=\"true\">\n <ds-checkbox\n class=\"select-option__checkbox\"\n label=\"\"\n size=\"md\"\n checked={selected}\n presentation\n />\n </span>\n )}\n onHover={() => {\n this.focusRingVisible = false;\n this.activeIndex = index;\n }}\n onSelect={() => this.toggleOption(option)}\n />\n );\n }\n\n render() {\n const inactive = this.isDisabled;\n const count = this.resolvedValues.length;\n const textVariant = CONTROL_TEXT_VARIANT[this.size];\n const iconSize = ICON_SIZE[this.size];\n const usesOptionSubtext = choiceListUsesSubtext(this.allOptions);\n const showError = this.error && Boolean(this.errorMessage);\n const describedBy = [this.ariaDescribedby, showError ? this.errorId : undefined]\n .filter(Boolean)\n .join(' ') || undefined;\n const popupStyle = {\n position: 'fixed',\n left: '0',\n top: '0',\n transform: `translate(${Math.round(this.position.x)}px, ${Math.round(this.position.y)}px)`,\n zIndex: 'var(--dimension-z-index-floating)',\n visibility: this.positionReady ? 'visible' : 'hidden',\n };\n let flatIndex = 0;\n\n return (\n <Host\n class={{\n 'select-host': true,\n 'ds-control-inactive': inactive,\n 'ds-control--md': this.size === 'md',\n 'ds-control--sm': this.size === 'sm',\n 'ds-control--xs': this.size === 'xs',\n ...controlWidthClass(this.width),\n [`select-host--background-${this.background}`]: !!this.background,\n }}\n >\n <button\n ref={element => {\n this.triggerEl = (element as HTMLButtonElement) ?? null;\n }}\n id={this.inputId ?? this.generatedId}\n type=\"button\"\n class={{\n trigger: true,\n 'ds-focus-ring-inset': true,\n 'ds-interaction-fill': true,\n 'ds-interaction-fill--selected':\n !inactive && this.activeFill && this.hasSelection,\n 'trigger--bordered': this.hasBorder || this.error,\n 'trigger--has-value': this.hasSelection,\n 'wrapper--error': this.error,\n [`ds-control--${this.size}`]: true,\n ...choiceBackgroundClassMap(this.background),\n }}\n disabled={inactive}\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={String(this.open)}\n aria-controls={this.open ? this.listboxId : undefined}\n aria-activedescendant={this.open && !this.searchable ? this.activeOptionId : undefined}\n aria-label={this.ariaLabel}\n aria-labelledby={this.ariaLabelledby}\n aria-describedby={describedBy}\n aria-invalid={this.error ? 'true' : undefined}\n aria-required={this.required || undefined}\n aria-busy={this.isLoading ? 'true' : undefined}\n onClick={() => (this.open ? this.closePopup() : this.openPopup(false))}\n onKeyDown={this.handleTriggerKeyDown}\n >\n {(this.icon || this.isLoading) && (\n <span class=\"trigger__prefix ds-interaction-fill__content\" aria-hidden=\"true\">\n {this.isLoading ? (\n <ds-loader size={iconSize} color=\"inherit\" />\n ) : (\n <ds-icon name={this.icon} size={iconSize} color=\"inherit\" />\n )}\n </span>\n )}\n <ds-text\n class=\"trigger__label ds-interaction-fill__content\"\n as=\"span\"\n variant={textVariant}\n color=\"inherit\"\n lineTruncation={1}\n >\n {`${this.placeholder}${count > 0 ? ` · ${count}` : ''}`}\n </ds-text>\n <span class=\"trigger__chevron ds-interaction-fill__content\" aria-hidden=\"true\">\n <ds-icon name=\"ChevronDown\" size={iconSize} color=\"inherit\" />\n </span>\n </button>\n\n {this.open && (\n <div\n ref={element => {\n this.popupEl = (element as HTMLDivElement) ?? null;\n }}\n class=\"select-popup ds-choice-popup\"\n style={popupStyle}\n >\n {this.searchable && (\n <ChoiceSearch\n value={this.searchTerm}\n placeholder={this.searchPlaceholder}\n controls={this.listboxId}\n activeDescendant={this.activeOptionId}\n inputRef={element => {\n this.searchEl = element;\n }}\n clearLabel={this.clearLabel}\n onValueChange={value => {\n this.searchTerm = value;\n }}\n onKeyDown={event => this.handleListKeyDown(event)}\n />\n )}\n <div\n id={this.listboxId}\n class=\"ds-choice-list\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n aria-label={this.ariaLabel ?? this.placeholder}\n aria-busy={this.isLoading ? 'true' : undefined}\n >\n {this.isLoading ? (\n <div\n class=\"ds-choice-loading\"\n role=\"option\"\n aria-selected=\"false\"\n aria-disabled=\"true\"\n aria-label={this.loadingLabel}\n aria-live=\"polite\"\n >\n <ds-loader size=\"md\" color=\"inherit\" />\n </div>\n ) : this.visibleOptions.length === 0 ? (\n <div\n class=\"ds-choice-empty\"\n role=\"option\"\n aria-selected=\"false\"\n aria-disabled=\"true\"\n aria-label={this.noResultsText}\n aria-live=\"polite\"\n >\n <ds-empty-state body={this.noResultsText} />\n </div>\n ) : (\n this.visibleSections.map(section => (\n <div\n class={{\n 'ds-choice-section': true,\n 'ds-choice-section--divided': !!section.divider,\n }}\n role={section.header ? 'group' : undefined}\n aria-label={section.header}\n >\n {section.header && (\n <ds-text\n class=\"ds-choice-section__header ds-control--md\"\n as=\"span\"\n variant=\"text-body-small\"\n emphasis\n color=\"primary\"\n aria-hidden=\"true\"\n >\n {section.header}\n </ds-text>\n )}\n {section.options.map(option => this.renderOption(\n option,\n flatIndex++,\n usesOptionSubtext,\n ))}\n </div>\n ))\n )}\n </div>\n {this.allowClear && this.hasSelection && !this.isLoading && (\n <ChoiceFooter\n summary={`${count} ${this.selectedLabel}`}\n clearLabel={this.clearLabel}\n onClear={this.clearSelection}\n />\n )}\n </div>\n )}\n\n {showError && (\n <ds-text\n class=\"error-text\"\n as=\"div\"\n variant=\"text-body-small\"\n color=\"negative\"\n textId={this.errorId}\n role=\"alert\"\n >\n {this.errorMessage}\n </ds-text>\n )}\n </Host>\n );\n }\n}\n",
|
|
752
|
+
"type": "registry:ui"
|
|
753
|
+
}
|
|
754
|
+
]
|
|
755
|
+
}
|