@vonage/vivid 4.5.0 → 4.7.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.
Files changed (173) hide show
  1. package/custom-elements.json +947 -79
  2. package/elevation/index.cjs +1 -1
  3. package/elevation/index.js +1 -1
  4. package/index.cjs +62 -56
  5. package/index.js +20 -19
  6. package/lib/components.d.ts +1 -0
  7. package/lib/dialog/dialog.d.ts +0 -1
  8. package/lib/menu/menu.d.ts +2 -1
  9. package/lib/number-field/number-field.d.ts +3 -1
  10. package/lib/searchable-select/definition.d.ts +4 -0
  11. package/lib/searchable-select/locale.d.ts +9 -0
  12. package/lib/searchable-select/option-tag.d.ts +14 -0
  13. package/lib/searchable-select/option-tag.template.d.ts +4 -0
  14. package/lib/searchable-select/searchable-select.d.ts +29 -0
  15. package/lib/searchable-select/searchable-select.form-associated.d.ts +10 -0
  16. package/lib/searchable-select/searchable-select.template.d.ts +4 -0
  17. package/lib/select/select.d.ts +3 -1
  18. package/lib/tab/locale.d.ts +3 -0
  19. package/lib/tab/tab.d.ts +5 -1
  20. package/lib/tag/definition.d.ts +1 -0
  21. package/lib/text-field/text-field.d.ts +3 -1
  22. package/locales/de-DE.cjs +24 -0
  23. package/locales/de-DE.js +24 -0
  24. package/locales/en-GB.cjs +24 -0
  25. package/locales/en-GB.js +24 -0
  26. package/locales/en-US.cjs +24 -0
  27. package/locales/en-US.js +24 -0
  28. package/locales/ja-JP.cjs +24 -0
  29. package/locales/ja-JP.js +24 -0
  30. package/locales/zh-CN.cjs +24 -0
  31. package/locales/zh-CN.js +24 -0
  32. package/package.json +1 -1
  33. package/popup/index.cjs +1 -1
  34. package/popup/index.js +1 -1
  35. package/searchable-select/index.cjs +5 -0
  36. package/searchable-select/index.js +3 -0
  37. package/select/index.cjs +1 -1
  38. package/select/index.js +1 -1
  39. package/selectable-box/index.cjs +1 -1
  40. package/selectable-box/index.js +1 -1
  41. package/shared/definition11.cjs +1 -1
  42. package/shared/definition11.js +1 -1
  43. package/shared/definition14.cjs +1 -1
  44. package/shared/definition14.js +1 -1
  45. package/shared/definition16.cjs +1 -1
  46. package/shared/definition16.js +1 -1
  47. package/shared/definition18.cjs +2 -2
  48. package/shared/definition18.js +2 -2
  49. package/shared/definition19.cjs +2 -2
  50. package/shared/definition19.js +2 -2
  51. package/shared/definition20.cjs +14 -34
  52. package/shared/definition20.js +14 -34
  53. package/shared/definition21.cjs +2 -19
  54. package/shared/definition21.js +2 -19
  55. package/shared/definition26.cjs +1 -1
  56. package/shared/definition26.js +1 -1
  57. package/shared/definition29.cjs +4 -0
  58. package/shared/definition29.js +4 -0
  59. package/shared/definition30.cjs +2 -1
  60. package/shared/definition30.js +2 -1
  61. package/shared/definition35.cjs +12 -7
  62. package/shared/definition35.js +12 -7
  63. package/shared/definition36.cjs +50 -207
  64. package/shared/definition36.js +51 -207
  65. package/shared/definition4.cjs +1 -1
  66. package/shared/definition4.js +1 -1
  67. package/shared/definition42.cjs +1 -1
  68. package/shared/definition42.js +1 -1
  69. package/shared/definition43.cjs +1018 -647
  70. package/shared/definition43.js +1014 -644
  71. package/shared/definition44.cjs +723 -112
  72. package/shared/definition44.js +722 -111
  73. package/shared/definition45.cjs +121 -80
  74. package/shared/definition45.js +119 -78
  75. package/shared/definition46.cjs +81 -614
  76. package/shared/definition46.js +80 -612
  77. package/shared/definition47.cjs +608 -114
  78. package/shared/definition47.js +606 -113
  79. package/shared/definition48.cjs +116 -134
  80. package/shared/definition48.js +115 -133
  81. package/shared/definition49.cjs +149 -19
  82. package/shared/definition49.js +148 -18
  83. package/shared/definition5.cjs +1 -1
  84. package/shared/definition5.js +1 -1
  85. package/shared/definition50.cjs +21 -82
  86. package/shared/definition50.js +20 -81
  87. package/shared/definition51.cjs +77 -539
  88. package/shared/definition51.js +76 -538
  89. package/shared/definition52.cjs +568 -28
  90. package/shared/definition52.js +567 -27
  91. package/shared/definition53.cjs +28 -123
  92. package/shared/definition53.js +26 -122
  93. package/shared/definition54.cjs +115 -295
  94. package/shared/definition54.js +114 -294
  95. package/shared/definition55.cjs +251 -311
  96. package/shared/definition55.js +251 -311
  97. package/shared/definition56.cjs +299 -780
  98. package/shared/definition56.js +298 -779
  99. package/shared/definition57.cjs +800 -102
  100. package/shared/definition57.js +799 -101
  101. package/shared/definition58.cjs +92 -63
  102. package/shared/definition58.js +91 -62
  103. package/shared/definition59.cjs +117 -75
  104. package/shared/definition59.js +116 -74
  105. package/shared/definition60.cjs +70 -285
  106. package/shared/definition60.js +71 -286
  107. package/shared/definition61.cjs +274 -66146
  108. package/shared/definition61.js +273 -66145
  109. package/shared/definition62.cjs +66160 -27
  110. package/shared/definition62.js +66158 -25
  111. package/shared/definition63.cjs +24 -1952
  112. package/shared/definition63.js +23 -1950
  113. package/shared/definition64.cjs +1976 -0
  114. package/shared/definition64.js +1971 -0
  115. package/shared/listbox-option.cjs +204 -0
  116. package/shared/listbox-option.js +201 -0
  117. package/shared/listbox.cjs +3 -3
  118. package/shared/listbox.js +1 -1
  119. package/shared/localization/Locale.d.ts +4 -0
  120. package/shared/presentationDate.cjs +2 -2
  121. package/shared/presentationDate.js +2 -2
  122. package/shared/scrollIntoView.cjs +51 -0
  123. package/shared/scrollIntoView.js +49 -0
  124. package/shared/slider.template.cjs +1 -1
  125. package/shared/slider.template.js +1 -1
  126. package/shared/text-field.cjs +1 -1
  127. package/shared/text-field.js +1 -1
  128. package/shared/utils/scrollIntoView.d.ts +1 -0
  129. package/side-drawer/index.cjs +1 -1
  130. package/side-drawer/index.js +1 -1
  131. package/slider/index.cjs +1 -1
  132. package/slider/index.js +1 -1
  133. package/split-button/index.cjs +1 -1
  134. package/split-button/index.js +1 -1
  135. package/styles/core/all.css +1 -1
  136. package/styles/core/theme.css +1 -1
  137. package/styles/core/typography.css +1 -1
  138. package/styles/tokens/theme-dark.css +4 -4
  139. package/styles/tokens/theme-light.css +4 -4
  140. package/styles/tokens/vivid-2-compat.css +1 -1
  141. package/switch/index.cjs +1 -1
  142. package/switch/index.js +1 -1
  143. package/tab/index.cjs +1 -1
  144. package/tab/index.js +1 -1
  145. package/tab-panel/index.cjs +1 -1
  146. package/tab-panel/index.js +1 -1
  147. package/tabs/index.cjs +1 -1
  148. package/tabs/index.js +1 -1
  149. package/tag/index.cjs +1 -1
  150. package/tag/index.js +1 -1
  151. package/tag-group/index.cjs +1 -1
  152. package/tag-group/index.js +1 -1
  153. package/text-area/index.cjs +1 -1
  154. package/text-area/index.js +1 -1
  155. package/text-field/index.cjs +1 -1
  156. package/text-field/index.js +1 -1
  157. package/time-picker/index.cjs +1 -1
  158. package/time-picker/index.js +1 -1
  159. package/toggletip/index.cjs +1 -1
  160. package/toggletip/index.js +1 -1
  161. package/tooltip/index.cjs +1 -1
  162. package/tooltip/index.js +1 -1
  163. package/tree-item/index.cjs +1 -1
  164. package/tree-item/index.js +1 -1
  165. package/tree-view/index.cjs +1 -1
  166. package/tree-view/index.js +1 -1
  167. package/video-player/index.cjs +1 -1
  168. package/video-player/index.js +1 -1
  169. package/vivid.api.json +295 -0
  170. package/api-extractor.json +0 -25
  171. package/shared/dialog-polyfill.esm.cjs +0 -862
  172. package/shared/dialog-polyfill.esm.js +0 -858
  173. package/tsdoc-metadata.json +0 -11
@@ -1,753 +1,1123 @@
1
- import { D as DOM, O as Observable, _ as __decorate, a as attr, v as volatile, o as observable, h as html, r as registerFactory } from './index.js';
2
- import { P as Popup, p as popupRegistries } from './definition63.js';
1
+ import { F as FoundationElement, O as Observable, D as DOM, a as attr, n as nullableNumberConverter, o as observable, h as html, r as registerFactory } from './index.js';
2
+ import { c as chevronTemplateFactory, a as buttonRegistries } from './definition11.js';
3
+ import { P as Popup, p as popupRegistries } from './definition64.js';
3
4
  import { a as iconRegistries } from './definition27.js';
4
- import { L as ListboxOption, a as listboxOptionRegistries } from './definition36.js';
5
- import { L as ListboxElement, b as Listbox, D as DelegatesARIAListbox, a as Listbox$1 } from './listbox.js';
6
5
  import { a as applyMixinsWithObservables } from './applyMixinsWithObservables.js';
7
- import { S as StartEnd } from './start-end.js';
8
- import { a as applyMixins } from './apply-mixins.js';
6
+ import { s as scrollIntoView } from './scrollIntoView.js';
9
7
  import { F as FormAssociated } from './form-associated.js';
10
- import { S as SelectPosition } from './select.options.js';
11
- import { u as uniqueId } from './strings.js';
12
- import { c as keyTab, b as keyEscape, k as keyEnter, d as keyEnd, g as keyHome, a as keySpace, f as keyArrowDown, e as keyArrowUp } from './key-codes.js';
13
8
  import { b as AffixIconWithTrailing, a as affixIconTemplateFactory, I as IconWrapper } from './affix.js';
14
9
  import { e as errorText, f as formElements, F as FormElementSuccessText, a as FormElementHelperText, g as getFeedbackTemplate } from './form-elements.js';
15
- import { c as chevronTemplateFactory } from './definition11.js';
16
- import { h as handleEscapeKeyAndStopPropogation } from './index2.js';
17
- import { r as ref } from './ref.js';
10
+ import { L as Localized } from './localized.js';
11
+ import { a as Listbox } from './listbox.js';
12
+ import { a as applyMixins } from './apply-mixins.js';
18
13
  import { w as when } from './when.js';
14
+ import { r as ref } from './ref.js';
19
15
  import { s as slotted } from './slotted.js';
16
+ import { B as Button$1 } from './button.js';
17
+ import { r as repeat } from './repeat.js';
20
18
  import { c as classNames } from './class-names.js';
19
+ import { I as Icon } from './icon.js';
20
+
21
+ const styles = ".chevron{display:flex;flex-shrink:0;font:var(--vvd-typography-base-extended);transform:rotate(0);transition:transform .2s}:host([aria-expanded=true]) .chevron,:host([open]) .chevron{transform:rotate(180deg)}:host(:focus-visible){outline:none}:host{display:inline-block;inline-size:300px;--_low-ink-color: var(--vvd-color-neutral-600)}:host([disabled]){--_low-ink-color: var(--vvd-color-neutral-400);cursor:not-allowed}.control-wrapper{display:flex;flex-direction:column;gap:4px}.label{color:var(--vvd-color-canvas-text);font:var(--vvd-typography-base)}.fieldset{--_connotation-color-primary: var(--vvd-searchable-select-accent-primary, var(--vvd-color-canvas-text));--_connotation-color-primary-text: var(--vvd-searchable-select-accent-primary-text, var(--vvd-color-canvas));--_connotation-color-primary-increment: var(--vvd-searchable-select-accent-primary-increment, var(--vvd-color-neutral-800));--_connotation-color-intermediate: var(--vvd-searchable-select-accent-intermediate, var(--vvd-color-neutral-500));--_connotation-color-faint: var(--vvd-searchable-select-accent-faint, var(--vvd-color-neutral-50));--_connotation-color-soft: var(--vvd-searchable-select-accent-soft, var(--vvd-color-neutral-100));--_connotation-color-firm: var(--vvd-searchable-select-accent-firm, var(--vvd-color-canvas-text));--_connotation-color-fierce: var(--vvd-searchable-select-accent-fierce, var(--vvd-color-neutral-700))}.fieldset{--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-intermediate)}.fieldset.appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.fieldset:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-fierce)}.fieldset:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)).appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: transparent}.fieldset:where(.disabled,:disabled){--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: var(--vvd-color-neutral-100);--_appearance-color-outline: var(--vvd-color-neutral-300)}.fieldset:where(.disabled,:disabled).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.fieldset:where(.readonly):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-neutral-200);--_appearance-color-outline: var(--vvd-color-neutral-400)}.fieldset:where(.readonly):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-600);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.fieldset:where(.error):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: var(--vvd-color-alert-500)}.fieldset:where(.error):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: transparent}.fieldset:where(.success):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: var(--vvd-color-success-500)}.fieldset:where(.success):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: transparent}.fieldset{display:flex;align-items:center;justify-content:space-between;background-color:var(--_appearance-color-fill);box-shadow:inset 0 0 0 1px var(--_appearance-color-outline);color:var(--_appearance-color-text);font:var(--vvd-typography-base);gap:8px;padding-block:8px;padding-inline:16px;transition:box-shadow .2s,background-color .2s}.fieldset:focus-within{box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px));--focus-stroke-gap-color: transparent}:host(:not([shape=pill])) .fieldset{border-radius:8px}:host([shape=pill]) .fieldset{border-radius:24px}.popup-wrapper{position:relative}.content-area{display:flex;overflow:hidden;flex:1;flex-direction:column;gap:8px;min-block-size:24px}.tag-row{display:flex;gap:8px;inline-size:100%}.tag-row.contains-only-input:not(:focus-within){display:contents}.tag-wrapper{overflow:hidden}.tag{max-inline-size:100%}input{box-sizing:border-box;flex:1;border:none;background:none;block-size:24px;font:var(--vvd-typography-base);max-inline-size:100%;min-inline-size:100px;outline:none}.contains-only-input input:not(:focus){position:absolute;block-size:0;inline-size:0;min-inline-size:0;opacity:0;pointer-events:none}.listbox{display:flex;flex-direction:column;padding:4px;gap:2px;max-block-size:var(--searchable-select-height, 408px);overflow-y:auto}.empty-message{display:flex;align-items:center;justify-content:center;color:var(--vvd-color-neutral-300);min-block-size:40px;text-align:center}::part(popup-base){inline-size:max-content;min-inline-size:100%}slot[name=icon]{font-size:20px}.visually-hidden{position:absolute;overflow:hidden;width:1px;height:1px;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}";
22
+
23
+ const optionTagStyles = ".base{--_connotation-color-contrast: var(--vvd-option-tag-accent-contrast, var(--vvd-color-neutral-800))}.base{position:relative;display:inline-flex;box-sizing:border-box;align-items:center;background-color:var(--fill-color);block-size:calc(1px*(24 + 4*clamp(-1,var(--vvd-size-density, 0),2)));box-shadow:inset 0 0 0 1px var(--outline-color);color:var(--text-color);column-gap:8px;font:var(--vvd-typography-base-bold);max-inline-size:100%;padding-inline:8px;user-select:none;vertical-align:middle}.base:not(.disabled){--text-color: var(--_connotation-color-contrast);--fill-color: color-mix( in srgb, var(--_connotation-color-contrast), transparent 87.5% );--outline-color: transparent}.base.disabled{--text-color: var(--vvd-color-neutral-300);--fill-color: color-mix( in srgb, var(--vvd-color-neutral-800), transparent 87.5% );--outline-color: transparent}.base:not(.shape-pill){border-radius:4px}.base.shape-pill{border-radius:16px}.label{overflow:hidden;max-inline-size:100%;text-overflow:ellipsis;white-space:nowrap}slot[name=icon]{font-size:calc(calc(1px*(24 + 4*clamp(-1,var(--vvd-size-density, 0),2))) / 1.5);line-height:1}.icon-placeholder{inline-size:calc(calc(1px*(24 + 4*clamp(-1,var(--vvd-size-density, 0),2))) / 1.5)}.remove-button{display:flex;align-items:center;border-radius:inherit;cursor:pointer;outline:none}.disabled .remove-button{pointer-events:none}.remove-button:focus-visible:before{--focus-stroke-gap-color: transparent;box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px));position:absolute;z-index:1;display:block;border-radius:inherit;content:\"\";inset:0;pointer-events:none}";
21
24
 
22
- class _Select extends ListboxElement {
25
+ class _SearchableSelect extends FoundationElement {
23
26
  }
24
- /**
25
- * A form-associated base class for the {@link @microsoft/fast-foundation#(Select:class)} component.
26
- *
27
- * @internal
28
- */
29
- class FormAssociatedSelect extends FormAssociated(_Select) {
30
- constructor() {
31
- super(...arguments);
32
- this.proxy = document.createElement("select");
33
- }
27
+ class FormAssociatedSearchableSelect extends FormAssociated(
28
+ _SearchableSelect
29
+ ) {
30
+ constructor() {
31
+ super(...arguments);
32
+ this.proxy = document.createElement("input");
33
+ }
34
34
  }
35
35
 
36
- /**
37
- * A Select Custom HTML Element.
38
- * Implements the {@link https://www.w3.org/TR/wai-aria-1.1/#select | ARIA select }.
39
- *
40
- * @slot start - Content which can be provided before the button content
41
- * @slot end - Content which can be provided after the button content
42
- * @slot button-container - The element representing the select button
43
- * @slot selected-value - The selected value
44
- * @slot indicator - The visual indicator for the expand/collapse state of the button
45
- * @slot - The default slot for slotted options
46
- * @csspart control - The element representing the select invoking element
47
- * @csspart selected-value - The element wrapping the selected value
48
- * @csspart indicator - The element wrapping the visual indicator
49
- * @csspart listbox - The listbox element
50
- * @fires input - Fires a custom 'input' event when the value updates
51
- * @fires change - Fires a custom 'change' event when the value updates
52
- *
53
- * @public
54
- */
55
- let Select$1 = class Select extends FormAssociatedSelect {
56
- constructor() {
57
- super(...arguments);
58
- /**
59
- * The open attribute.
60
- *
61
- * @public
62
- * @remarks
63
- * HTML Attribute: open
64
- */
65
- this.open = false;
66
- /**
67
- * Indicates the initial state of the position attribute.
68
- *
69
- * @internal
70
- */
71
- this.forcedPosition = false;
72
- /**
73
- * The unique id for the internal listbox element.
74
- *
75
- * @internal
76
- */
77
- this.listboxId = uniqueId("listbox-");
78
- /**
79
- * The max height for the listbox when opened.
80
- *
81
- * @internal
82
- */
83
- this.maxHeight = 0;
84
- }
36
+ var __defProp$1 = Object.defineProperty;
37
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
38
+ var __typeError = (msg) => {
39
+ throw TypeError(msg);
40
+ };
41
+ var __decorateClass$1 = (decorators, target, key, kind) => {
42
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
43
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
44
+ if (decorator = decorators[i])
45
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
46
+ if (kind && result) __defProp$1(target, key, result);
47
+ return result;
48
+ };
49
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
50
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
51
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
52
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
53
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
54
+ var _SearchableSelect_instances, updateValuesThroughUserInteraction_fn, updateValuesWhileMaintainingOrder_fn, isValidValue_fn, _slottedOptionsChangeHandler, updateSelectedOnSlottedOptions_fn, handleOptionInteraction_fn, _clonedTagIcons, tagIconOfOption_fn, updateClonedTagIconOfOption_fn, _suppressFilter, updateFilteredOptions_fn, transitionHighlightedOptionTo_fn, selectHighlightedOption_fn, highlightFirstOption_fn, highlightLastOption_fn, highlightPrevPage_fn, highlightNextPage_fn, highlightPreviousOption_fn, highlightNextOption_fn, textForValue_fn, measureTagWidth_fn, updateTagLayout_fn, moveTagFocusTo_fn, nextTagIndexLeft_fn, nextTagIndexRight_fn, nextTagIndexForRemoved_fn, determineInitialValues_fn, updateFormValue_fn, _resizeObserver;
55
+ const TagGapPx = 8;
56
+ const InputMinWidthPx = 100;
57
+ const PageSize = 10;
58
+ const isFormAssociatedTryingToSetFormValue = (value) => typeof value === "string";
59
+ let SearchableSelect = class extends FormAssociatedSearchableSelect {
60
+ constructor() {
61
+ super(...arguments);
62
+ __privateAdd(this, _SearchableSelect_instances);
63
+ this.fixedDropdown = false;
64
+ this.open = false;
65
+ this.multiple = false;
66
+ this.externalTags = false;
67
+ this.maxLines = null;
68
+ this.values = [];
69
+ this.initialValues = [];
70
+ this._inputValue = "";
71
+ // --- Slotted options ---
85
72
  /**
86
- * Sets focus and synchronizes ARIA attributes when the open property changes.
87
- *
88
- * @param prev - the previous open value
89
- * @param next - the current open value
90
- *
91
73
  * @internal
92
74
  */
93
- openChanged(prev, next) {
94
- if (!this.collapsible) {
95
- return;
96
- }
97
- if (this.open) {
98
- this.ariaControls = this.listboxId;
99
- this.ariaExpanded = "true";
100
- this.setPositioning();
101
- this.focusAndScrollOptionIntoView();
102
- this.indexWhenOpened = this.selectedIndex;
103
- // focus is directed to the element when `open` is changed programmatically
104
- DOM.queueUpdate(() => this.focus());
105
- return;
75
+ this._areOptionsInitialized = false;
76
+ __privateAdd(this, _slottedOptionsChangeHandler, {
77
+ handleChange: (source, _) => {
78
+ if (source.selected && !this.values.includes(source.value)) {
79
+ this.values = [...this.values, source.value];
80
+ } else if (!source.selected && this.values.includes(source.value)) {
81
+ this.values = this.values.filter((option) => option !== source.value);
106
82
  }
107
- this.ariaControls = "";
108
- this.ariaExpanded = "false";
83
+ }
84
+ });
85
+ // --- Option tag icons ---
86
+ __privateAdd(this, _clonedTagIcons, /* @__PURE__ */ new Map());
87
+ this._filteredOptions = [];
88
+ this._filteredEnabledOptions = [];
89
+ __privateAdd(this, _suppressFilter, false);
90
+ this._highlightedOptionIndex = null;
91
+ this._numElidedTags = 0;
92
+ this._tagRows = [];
93
+ this._lastTagRow = [];
94
+ this.clearable = false;
95
+ this.setFormValue = (value, state) => {
96
+ if (isFormAssociatedTryingToSetFormValue(value)) {
97
+ return;
98
+ }
99
+ super.setFormValue(value, state);
100
+ };
101
+ this._changeDescription = "";
102
+ // --- Core ---
103
+ __privateAdd(this, _resizeObserver, new ResizeObserver(() => {
104
+ __privateMethod(this, _SearchableSelect_instances, updateTagLayout_fn).call(this);
105
+ }));
106
+ }
107
+ /**
108
+ * @internal
109
+ */
110
+ openChanged() {
111
+ if (!this.open) {
112
+ __privateMethod(this, _SearchableSelect_instances, transitionHighlightedOptionTo_fn).call(this, null);
109
113
  }
110
- /**
111
- * The component is collapsible when in single-selection mode with no size attribute.
112
- *
113
- * @internal
114
- */
115
- get collapsible() {
116
- return !(this.multiple || typeof this.size === "number");
114
+ }
115
+ /**
116
+ * @internal
117
+ */
118
+ valuesChanged() {
119
+ if (!this._areOptionsInitialized) {
120
+ return;
117
121
  }
118
- /**
119
- * The value property.
120
- *
121
- * @public
122
- */
123
- get value() {
124
- Observable.track(this, "value");
125
- return this._value;
126
- }
127
- set value(next) {
128
- var _a, _b, _c, _d, _e, _f, _g;
129
- const prev = `${this._value}`;
130
- if ((_a = this._options) === null || _a === void 0 ? void 0 : _a.length) {
131
- const selectedIndex = this._options.findIndex(el => el.value === next);
132
- const prevSelectedValue = (_c = (_b = this._options[this.selectedIndex]) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : null;
133
- const nextSelectedValue = (_e = (_d = this._options[selectedIndex]) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : null;
134
- if (selectedIndex === -1 || prevSelectedValue !== nextSelectedValue) {
135
- next = "";
136
- this.selectedIndex = selectedIndex;
137
- }
138
- next = (_g = (_f = this.firstSelectedOption) === null || _f === void 0 ? void 0 : _f.value) !== null && _g !== void 0 ? _g : next;
139
- }
140
- if (prev !== next) {
141
- this._value = next;
142
- super.valueChanged(prev, next);
143
- Observable.notify(this, "value");
144
- this.updateDisplayValue();
145
- }
122
+ if (!this.multiple && this.values.length > 1) {
123
+ this.values = [this.values[0]];
124
+ return;
146
125
  }
147
- /**
148
- * Sets the value and display value to match the first selected option.
149
- *
150
- * @param shouldEmit - if true, the input and change events will be emitted
151
- *
152
- * @internal
153
- */
154
- updateValue(shouldEmit) {
155
- var _a, _b;
156
- if (this.$fastController.isConnected) {
157
- this.value = (_b = (_a = this.firstSelectedOption) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "";
158
- }
159
- if (shouldEmit) {
160
- this.$emit("input");
161
- this.$emit("change", this, {
162
- bubbles: true,
163
- composed: undefined,
164
- });
165
- }
126
+ if (this.values.some((value) => !__privateMethod(this, _SearchableSelect_instances, isValidValue_fn).call(this, value))) {
127
+ this.values = this.values.filter((value) => __privateMethod(this, _SearchableSelect_instances, isValidValue_fn).call(this, value));
128
+ return;
166
129
  }
167
- /**
168
- * Updates the proxy value when the selected index changes.
169
- *
170
- * @param prev - the previous selected index
171
- * @param next - the next selected index
172
- *
173
- * @internal
174
- */
175
- selectedIndexChanged(prev, next) {
176
- super.selectedIndexChanged(prev, next);
177
- this.updateValue();
130
+ if (!this.multiple) {
131
+ if (this.values.length) {
132
+ __privateSet(this, _suppressFilter, true);
133
+ this._inputValue = __privateMethod(this, _SearchableSelect_instances, textForValue_fn).call(this, this.values[0]);
134
+ } else {
135
+ this._inputValue = "";
136
+ }
178
137
  }
179
- positionChanged(prev, next) {
180
- this.positionAttribute = next;
181
- this.setPositioning();
138
+ this.value = this.values.length ? this.values[0] : "";
139
+ __privateMethod(this, _SearchableSelect_instances, updateSelectedOnSlottedOptions_fn).call(this);
140
+ if (this.$fastController.isConnected) {
141
+ __privateMethod(this, _SearchableSelect_instances, updateTagLayout_fn).call(this);
182
142
  }
183
- /**
184
- * Calculate and apply listbox positioning based on available viewport space.
185
- *
186
- * @public
187
- */
188
- setPositioning() {
189
- const currentBox = this.getBoundingClientRect();
190
- const viewportHeight = window.innerHeight;
191
- const availableBottom = viewportHeight - currentBox.bottom;
192
- this.position = this.forcedPosition
193
- ? this.positionAttribute
194
- : currentBox.top > availableBottom
195
- ? SelectPosition.above
196
- : SelectPosition.below;
197
- this.positionAttribute = this.forcedPosition
198
- ? this.positionAttribute
199
- : this.position;
200
- this.maxHeight =
201
- this.position === SelectPosition.above ? ~~currentBox.top : ~~availableBottom;
143
+ __privateMethod(this, _SearchableSelect_instances, updateFormValue_fn).call(this);
144
+ }
145
+ /**
146
+ * @internal
147
+ */
148
+ initialValuesChanged() {
149
+ if (!this.dirtyValue) {
150
+ this.values = this.initialValues;
151
+ this.dirtyValue = false;
202
152
  }
203
- /**
204
- * The value displayed on the button.
205
- *
206
- * @public
207
- */
208
- get displayValue() {
209
- var _a, _b;
210
- Observable.track(this, "displayValue");
211
- return (_b = (_a = this.firstSelectedOption) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : "";
153
+ }
154
+ /**
155
+ * @internal
156
+ */
157
+ valueChanged(prev, next) {
158
+ super.valueChanged(prev, next);
159
+ if (!this._areOptionsInitialized) {
160
+ return;
212
161
  }
213
- /**
214
- * Synchronize the `aria-disabled` property when the `disabled` property changes.
215
- *
216
- * @param prev - The previous disabled value
217
- * @param next - The next disabled value
218
- *
219
- * @internal
220
- */
221
- disabledChanged(prev, next) {
222
- if (super.disabledChanged) {
223
- super.disabledChanged(prev, next);
224
- }
225
- this.ariaDisabled = this.disabled ? "true" : "false";
162
+ const isValidValue = this._slottedOptions.some(
163
+ (option) => option.value === next
164
+ );
165
+ if (this.values[0] !== next) {
166
+ this.values = isValidValue ? [next] : [];
226
167
  }
227
- /**
228
- * Reset the element to its first selectable option when its parent form is reset.
229
- *
230
- * @internal
231
- */
232
- formResetCallback() {
233
- this.setProxyOptions();
234
- // Call the base class's implementation setDefaultSelectedOption instead of the select's
235
- // override, in order to reset the selectedIndex without using the value property.
236
- super.setDefaultSelectedOption();
237
- if (this.selectedIndex === -1) {
238
- this.selectedIndex = 0;
239
- }
168
+ }
169
+ get selectedIndex() {
170
+ if (this.values.length) {
171
+ return this._slottedOptions.findIndex(
172
+ (option) => option.value === this.values[0]
173
+ );
174
+ } else {
175
+ return -1;
240
176
  }
241
- /**
242
- * Handle opening and closing the listbox when the select is clicked.
243
- *
244
- * @param e - the mouse event
245
- * @internal
246
- */
247
- clickHandler(e) {
248
- // do nothing if the select is disabled
249
- if (this.disabled) {
250
- return;
177
+ }
178
+ set selectedIndex(index) {
179
+ this.value = this._slottedOptions[index]?.value ?? "";
180
+ }
181
+ get options() {
182
+ return [...this._slottedOptions];
183
+ }
184
+ get selectedOptions() {
185
+ return this._slottedOptions.filter(
186
+ (option) => this.values.includes(option.value)
187
+ );
188
+ }
189
+ /**
190
+ * @internal
191
+ */
192
+ _inputValueChanged() {
193
+ __privateMethod(this, _SearchableSelect_instances, updateFilteredOptions_fn).call(this);
194
+ }
195
+ /**
196
+ * @internal
197
+ */
198
+ _onInputInput(event) {
199
+ __privateSet(this, _suppressFilter, false);
200
+ this._inputValue = event.target.value;
201
+ }
202
+ /**
203
+ * @internal
204
+ */
205
+ _onInputFocus(_) {
206
+ __privateSet(this, _suppressFilter, true);
207
+ __privateMethod(this, _SearchableSelect_instances, updateFilteredOptions_fn).call(this);
208
+ this.open = true;
209
+ }
210
+ /**
211
+ * @internal
212
+ */
213
+ _onInputBlur(_) {
214
+ this.open = false;
215
+ if (this.multiple) {
216
+ this._inputValue = "";
217
+ } else {
218
+ if (this.values.length === 0) {
219
+ this._inputValue = "";
220
+ } else {
221
+ this._inputValue = __privateMethod(this, _SearchableSelect_instances, textForValue_fn).call(this, this.values[0]);
222
+ }
223
+ }
224
+ this._changeDescription = "";
225
+ }
226
+ /**
227
+ * @internal
228
+ */
229
+ _onInputKeydown(e) {
230
+ if (e.ctrlKey || e.shiftKey) {
231
+ return true;
232
+ }
233
+ switch (e.key) {
234
+ case "Enter":
235
+ __privateMethod(this, _SearchableSelect_instances, selectHighlightedOption_fn).call(this);
236
+ return false;
237
+ case "Escape":
238
+ this.open = false;
239
+ break;
240
+ case "Home":
241
+ if (!this.open) {
242
+ this.open = true;
243
+ break;
251
244
  }
252
- if (this.open) {
253
- const captured = e.target.closest(`option,[role=option]`);
254
- if (captured && captured.disabled) {
255
- return;
256
- }
245
+ __privateMethod(this, _SearchableSelect_instances, highlightFirstOption_fn).call(this);
246
+ return false;
247
+ case "End":
248
+ if (!this.open) {
249
+ this.open = true;
250
+ break;
257
251
  }
258
- super.clickHandler(e);
259
- this.open = this.collapsible && !this.open;
260
- if (!this.open && this.indexWhenOpened !== this.selectedIndex) {
261
- this.updateValue(true);
252
+ __privateMethod(this, _SearchableSelect_instances, highlightLastOption_fn).call(this);
253
+ return false;
254
+ case "PageUp":
255
+ if (!this.open) {
256
+ this.open = true;
257
+ break;
262
258
  }
263
- return true;
264
- }
265
- /**
266
- * Handles focus state when the element or its children lose focus.
267
- *
268
- * @param e - The focus event
269
- * @internal
270
- */
271
- focusoutHandler(e) {
272
- var _a;
273
- super.focusoutHandler(e);
259
+ __privateMethod(this, _SearchableSelect_instances, highlightPrevPage_fn).call(this);
260
+ return false;
261
+ case "PageDown":
274
262
  if (!this.open) {
275
- return true;
263
+ this.open = true;
264
+ break;
276
265
  }
277
- const focusTarget = e.relatedTarget;
278
- if (this.isSameNode(focusTarget)) {
279
- this.focus();
280
- return;
266
+ __privateMethod(this, _SearchableSelect_instances, highlightNextPage_fn).call(this);
267
+ return false;
268
+ case "ArrowUp":
269
+ if (!this.open) {
270
+ this.open = true;
271
+ break;
281
272
  }
282
- if (!((_a = this.options) === null || _a === void 0 ? void 0 : _a.includes(focusTarget))) {
283
- this.open = false;
284
- if (this.indexWhenOpened !== this.selectedIndex) {
285
- this.updateValue(true);
286
- }
273
+ __privateMethod(this, _SearchableSelect_instances, highlightPreviousOption_fn).call(this);
274
+ return false;
275
+ case "ArrowDown":
276
+ if (!this.open) {
277
+ this.open = true;
278
+ break;
287
279
  }
288
- }
289
- /**
290
- * Updates the value when an option's value changes.
291
- *
292
- * @param source - the source object
293
- * @param propertyName - the property to evaluate
294
- *
295
- * @internal
296
- * @override
297
- */
298
- handleChange(source, propertyName) {
299
- super.handleChange(source, propertyName);
300
- if (propertyName === "value") {
301
- this.updateValue();
280
+ __privateMethod(this, _SearchableSelect_instances, highlightNextOption_fn).call(this);
281
+ return false;
282
+ case "ArrowLeft":
283
+ if (this.multiple && this._inputValue === "" && this.values.length && !this.externalTags) {
284
+ __privateMethod(this, _SearchableSelect_instances, moveTagFocusTo_fn).call(this, __privateMethod(this, _SearchableSelect_instances, nextTagIndexLeft_fn).call(this, this.values.length));
285
+ return false;
302
286
  }
287
+ return true;
288
+ case "Backspace":
289
+ if (this.multiple && this._inputValue === "" && this.values.length) {
290
+ this._onTagRemoved(this.values[this.values.length - 1]);
291
+ return false;
292
+ }
293
+ return true;
294
+ default:
295
+ if (!this.open) {
296
+ this.open = true;
297
+ }
298
+ return true;
303
299
  }
304
- /**
305
- * Synchronize the form-associated proxy and updates the value property of the element.
306
- *
307
- * @param prev - the previous collection of slotted option elements
308
- * @param next - the next collection of slotted option elements
309
- *
310
- * @internal
311
- */
312
- slottedOptionsChanged(prev, next) {
313
- this.options.forEach(o => {
314
- const notifier = Observable.getNotifier(o);
315
- notifier.unsubscribe(this, "value");
316
- });
317
- super.slottedOptionsChanged(prev, next);
318
- this.options.forEach(o => {
319
- const notifier = Observable.getNotifier(o);
320
- notifier.subscribe(this, "value");
321
- });
322
- this.setProxyOptions();
323
- this.updateValue();
300
+ return true;
301
+ }
302
+ /**
303
+ * @internal
304
+ */
305
+ _slottedOptionsChanged(oldValue, newValue) {
306
+ const hasSlottedOptions = Boolean(
307
+ this.querySelectorAll(`:not([slot])`).length
308
+ );
309
+ if (!newValue.length && hasSlottedOptions) {
310
+ return;
324
311
  }
325
- /**
326
- * Prevents focus when size is set and a scrollbar is clicked.
327
- *
328
- * @param e - the mouse event object
329
- *
330
- * @override
331
- * @internal
332
- */
333
- mousedownHandler(e) {
334
- var _a;
335
- if (e.offsetX >= 0 && e.offsetX <= ((_a = this.listbox) === null || _a === void 0 ? void 0 : _a.scrollWidth)) {
336
- return super.mousedownHandler(e);
337
- }
338
- return this.collapsible;
312
+ this._areOptionsInitialized = true;
313
+ if (oldValue) {
314
+ for (const option of oldValue) {
315
+ const notifier = Observable.getNotifier(option);
316
+ notifier.unsubscribe(__privateGet(this, _slottedOptionsChangeHandler), "selected");
317
+ }
339
318
  }
340
- /**
341
- * Sets the multiple property on the proxy element.
342
- *
343
- * @param prev - the previous multiple value
344
- * @param next - the current multiple value
345
- */
346
- multipleChanged(prev, next) {
347
- super.multipleChanged(prev, next);
348
- if (this.proxy) {
349
- this.proxy.multiple = next;
350
- }
319
+ if (newValue) {
320
+ for (const option of newValue) {
321
+ option._displayCheckmark = true;
322
+ const notifier = Observable.getNotifier(option);
323
+ notifier.subscribe(__privateGet(this, _slottedOptionsChangeHandler), "selected");
324
+ }
351
325
  }
352
- /**
353
- * Updates the selectedness of each option when the list of selected options changes.
354
- *
355
- * @param prev - the previous list of selected options
356
- * @param next - the current list of selected options
357
- *
358
- * @override
359
- * @internal
360
- */
361
- selectedOptionsChanged(prev, next) {
362
- var _a;
363
- super.selectedOptionsChanged(prev, next);
364
- (_a = this.options) === null || _a === void 0 ? void 0 : _a.forEach((o, i) => {
365
- var _a;
366
- const proxyOption = (_a = this.proxy) === null || _a === void 0 ? void 0 : _a.options.item(i);
367
- if (proxyOption) {
368
- proxyOption.selected = o.selected;
369
- }
370
- });
326
+ const values = [];
327
+ for (const option of this._slottedOptions) {
328
+ if (option.selected || option.value === this.value || this.values.includes(option.value)) {
329
+ values.push(option.value);
330
+ }
371
331
  }
372
- /**
373
- * Sets the selected index to match the first option with the selected attribute, or
374
- * the first selectable option.
375
- *
376
- * @override
377
- * @internal
378
- */
379
- setDefaultSelectedOption() {
380
- var _a;
381
- const options = (_a = this.options) !== null && _a !== void 0 ? _a : Array.from(this.children).filter(Listbox.slottedOptionFilter);
382
- const selectedIndex = options === null || options === void 0 ? void 0 : options.findIndex(el => el.hasAttribute("selected") || el.selected || el.value === this.value);
383
- if (selectedIndex !== -1) {
384
- this.selectedIndex = selectedIndex;
385
- return;
386
- }
387
- this.selectedIndex = 0;
332
+ __privateMethod(this, _SearchableSelect_instances, updateValuesWhileMaintainingOrder_fn).call(this, values);
333
+ __privateMethod(this, _SearchableSelect_instances, updateFilteredOptions_fn).call(this);
334
+ }
335
+ /**
336
+ * @internal
337
+ */
338
+ _tagIconSlotName(value) {
339
+ return `_tag-icon-${this.values.indexOf(value)}`;
340
+ }
341
+ // --- Tags ---
342
+ /**
343
+ * @internal
344
+ */
345
+ _tagLabelForValue(value) {
346
+ const option = this._slottedOptions.find(
347
+ (option2) => option2.value === value
348
+ );
349
+ return option.label;
350
+ }
351
+ /**
352
+ * @internal
353
+ */
354
+ _isTagDisabled(value) {
355
+ const option = this._slottedOptions.find(
356
+ (option2) => option2.value === value
357
+ );
358
+ return this.disabled || option.disabled;
359
+ }
360
+ /**
361
+ * @internal
362
+ */
363
+ _onTagRemoved(value) {
364
+ __privateMethod(this, _SearchableSelect_instances, updateValuesThroughUserInteraction_fn).call(this, this.values.filter((option) => option !== value));
365
+ __privateMethod(this, _SearchableSelect_instances, updateFilteredOptions_fn).call(this);
366
+ }
367
+ /**
368
+ * @internal
369
+ */
370
+ _onTagKeydown(event) {
371
+ const tagIndex = parseInt(event.target.dataset.index);
372
+ switch (event.key) {
373
+ case "Backspace":
374
+ case "Delete":
375
+ case "Enter":
376
+ case " ": {
377
+ this._onTagRemoved(this.values[tagIndex]);
378
+ DOM.processUpdates();
379
+ __privateMethod(this, _SearchableSelect_instances, moveTagFocusTo_fn).call(this, __privateMethod(this, _SearchableSelect_instances, nextTagIndexForRemoved_fn).call(this, tagIndex));
380
+ break;
381
+ }
382
+ case "ArrowLeft":
383
+ __privateMethod(this, _SearchableSelect_instances, moveTagFocusTo_fn).call(this, __privateMethod(this, _SearchableSelect_instances, nextTagIndexLeft_fn).call(this, tagIndex) ?? tagIndex);
384
+ break;
385
+ case "ArrowRight":
386
+ __privateMethod(this, _SearchableSelect_instances, moveTagFocusTo_fn).call(this, __privateMethod(this, _SearchableSelect_instances, nextTagIndexRight_fn).call(this, tagIndex));
387
+ break;
388
388
  }
389
- /**
390
- * Resets and fills the proxy to match the component's options.
391
- *
392
- * @internal
393
- */
394
- setProxyOptions() {
395
- if (this.proxy instanceof HTMLSelectElement && this.options) {
396
- this.proxy.options.length = 0;
397
- this.options.forEach(option => {
398
- const proxyOption = option.proxy ||
399
- (option instanceof HTMLOptionElement ? option.cloneNode() : null);
400
- if (proxyOption) {
401
- this.proxy.options.add(proxyOption);
402
- }
403
- });
404
- }
389
+ return true;
390
+ }
391
+ /**
392
+ * @internal
393
+ */
394
+ _onListboxClick(e) {
395
+ if (this.disabled) {
396
+ return;
405
397
  }
406
- /**
407
- * Handle keyboard interaction for the select.
408
- *
409
- * @param e - the keyboard event
410
- * @internal
411
- */
412
- keydownHandler(e) {
413
- super.keydownHandler(e);
414
- const key = e.key || e.key.charCodeAt(0);
415
- switch (key) {
416
- case keySpace: {
417
- e.preventDefault();
418
- if (this.collapsible && this.typeAheadExpired) {
419
- this.open = !this.open;
420
- }
421
- break;
422
- }
423
- case keyHome:
424
- case keyEnd: {
425
- e.preventDefault();
426
- break;
427
- }
428
- case keyEnter: {
429
- e.preventDefault();
430
- this.open = !this.open;
431
- break;
432
- }
433
- case keyEscape: {
434
- if (this.collapsible && this.open) {
435
- e.preventDefault();
436
- this.open = false;
437
- }
438
- break;
439
- }
440
- case keyTab: {
441
- if (this.collapsible && this.open) {
442
- e.preventDefault();
443
- this.open = false;
444
- }
445
- return true;
446
- }
447
- }
448
- if (!this.open && this.indexWhenOpened !== this.selectedIndex) {
449
- this.updateValue(true);
450
- this.indexWhenOpened = this.selectedIndex;
451
- }
452
- return !(key === keyArrowDown || key === keyArrowUp);
398
+ const capturedOption = e.target.closest(
399
+ `option,[role=option]`
400
+ );
401
+ if (capturedOption && !capturedOption.disabled) {
402
+ __privateMethod(this, _SearchableSelect_instances, handleOptionInteraction_fn).call(this, capturedOption);
403
+ }
404
+ }
405
+ /**
406
+ * @internal
407
+ */
408
+ get _shouldShowClearButton() {
409
+ return this.clearable && this.values.length > 0;
410
+ }
411
+ /**
412
+ * @internal
413
+ */
414
+ _onClearButtonClick() {
415
+ __privateMethod(this, _SearchableSelect_instances, updateValuesThroughUserInteraction_fn).call(this, this.selectedOptions.filter((option) => option.disabled).map((option) => option.value));
416
+ }
417
+ /**
418
+ * @internal
419
+ */
420
+ nameChanged(previous, next) {
421
+ super.nameChanged(previous, next);
422
+ __privateMethod(this, _SearchableSelect_instances, updateFormValue_fn).call(this);
423
+ }
424
+ /**
425
+ * @internal
426
+ */
427
+ formResetCallback() {
428
+ super.formResetCallback();
429
+ __privateMethod(this, _SearchableSelect_instances, updateValuesThroughUserInteraction_fn).call(this, __privateMethod(this, _SearchableSelect_instances, determineInitialValues_fn).call(this));
430
+ }
431
+ /**
432
+ * @internal
433
+ */
434
+ _onFieldsetClick(e) {
435
+ if (this.disabled) {
436
+ return;
453
437
  }
454
- connectedCallback() {
455
- super.connectedCallback();
456
- this.forcedPosition = !!this.positionAttribute;
457
- this.addEventListener("contentchange", this.updateDisplayValue);
438
+ if (!e.defaultPrevented) {
439
+ this._input.focus();
458
440
  }
459
- disconnectedCallback() {
460
- this.removeEventListener("contentchange", this.updateDisplayValue);
461
- super.disconnectedCallback();
441
+ }
442
+ connectedCallback() {
443
+ super.connectedCallback();
444
+ if (!this.values.length) {
445
+ this.values = __privateMethod(this, _SearchableSelect_instances, determineInitialValues_fn).call(this);
462
446
  }
463
- /**
464
- * Updates the proxy's size property when the size attribute changes.
465
- *
466
- * @param prev - the previous size
467
- * @param next - the current size
468
- *
469
- * @override
470
- * @internal
471
- */
472
- sizeChanged(prev, next) {
473
- super.sizeChanged(prev, next);
474
- if (this.proxy) {
475
- this.proxy.size = next;
476
- }
447
+ __privateGet(this, _resizeObserver).observe(this._contentArea);
448
+ }
449
+ disconnectedCallback() {
450
+ super.disconnectedCallback();
451
+ __privateGet(this, _resizeObserver).disconnect();
452
+ }
453
+ /**
454
+ * @internal
455
+ */
456
+ validate() {
457
+ super.validate(this._input ?? void 0);
458
+ }
459
+ };
460
+ _SearchableSelect_instances = new WeakSet();
461
+ updateValuesThroughUserInteraction_fn = function(newValues) {
462
+ this.values = newValues;
463
+ this.$emit("change", void 0, {
464
+ bubbles: false
465
+ });
466
+ this.$emit("input", void 0, {
467
+ bubbles: false
468
+ });
469
+ };
470
+ updateValuesWhileMaintainingOrder_fn = function(newValues) {
471
+ const oldSet = new Set(this.values);
472
+ const newSet = new Set(newValues);
473
+ this.values = [...this.values].filter((v) => newSet.has(v)).concat([...newValues].filter((v) => !oldSet.has(v)));
474
+ };
475
+ isValidValue_fn = function(value) {
476
+ return this._slottedOptions.some((option) => option.value === value);
477
+ };
478
+ _slottedOptionsChangeHandler = new WeakMap();
479
+ updateSelectedOnSlottedOptions_fn = function() {
480
+ for (const option of this._slottedOptions) {
481
+ option.selected = this.values.includes(option.value);
482
+ __privateMethod(this, _SearchableSelect_instances, updateClonedTagIconOfOption_fn).call(this, option);
483
+ }
484
+ };
485
+ handleOptionInteraction_fn = function(option) {
486
+ const value = option.value;
487
+ let newValues;
488
+ const isSelection = !this.values.includes(value);
489
+ if (this.multiple) {
490
+ if (isSelection) {
491
+ newValues = [...this.values, value];
492
+ } else {
493
+ newValues = this.values.filter((option2) => option2 !== value);
477
494
  }
478
- /**
479
- *
480
- * @internal
481
- */
482
- updateDisplayValue() {
483
- if (this.collapsible) {
484
- Observable.notify(this, "displayValue");
485
- }
495
+ this._inputValue = "";
496
+ } else {
497
+ if (isSelection) {
498
+ newValues = [value];
499
+ this._inputValue = option.text;
500
+ } else {
501
+ newValues = [];
486
502
  }
503
+ this.open = false;
504
+ }
505
+ this._changeDescription = isSelection ? this.locale.searchableSelect.optionSelectedMessage(option.text) : this.locale.searchableSelect.optionDeselectedMessage(option.text);
506
+ __privateMethod(this, _SearchableSelect_instances, updateValuesThroughUserInteraction_fn).call(this, newValues);
487
507
  };
488
- __decorate([
489
- attr({ attribute: "open", mode: "boolean" })
490
- ], Select$1.prototype, "open", void 0);
491
- __decorate([
492
- volatile
493
- ], Select$1.prototype, "collapsible", null);
494
- __decorate([
495
- observable
496
- ], Select$1.prototype, "control", void 0);
497
- __decorate([
498
- attr({ attribute: "position" })
499
- ], Select$1.prototype, "positionAttribute", void 0);
500
- __decorate([
501
- observable
502
- ], Select$1.prototype, "position", void 0);
503
- __decorate([
504
- observable
505
- ], Select$1.prototype, "maxHeight", void 0);
506
- /**
507
- * Includes ARIA states and properties relating to the ARIA select role.
508
- *
509
- * @public
510
- */
511
- class DelegatesARIASelect {
512
- }
513
- __decorate([
514
- observable
515
- ], DelegatesARIASelect.prototype, "ariaControls", void 0);
516
- applyMixins(DelegatesARIASelect, DelegatesARIAListbox);
517
- applyMixins(Select$1, StartEnd, DelegatesARIASelect);
518
-
519
- const styles = ".chevron{display:flex;flex-shrink:0;font:var(--vvd-typography-base-extended);transform:rotate(0);transition:transform .2s}:host([aria-expanded=true]) .chevron{transform:rotate(180deg)}:host(:focus-visible){outline:none}:host{display:inline-flex;flex-direction:column;gap:4px;--_low-ink-color: var(--vvd-color-neutral-600);--focus-stroke-gap-color: transparent}:host([disabled]){--_low-ink-color: var(--vvd-color-neutral-400);cursor:not-allowed}.label{color:var(--vvd-color-canvas-text);contain:inline-size;font:var(--vvd-typography-base)}.control{--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-intermediate)}.control.appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.control:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-fierce)}.control:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)).appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: transparent}.control:where(.disabled,:disabled){--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: var(--vvd-color-neutral-100);--_appearance-color-outline: var(--vvd-color-neutral-300)}.control:where(.disabled,:disabled).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.control:where(.readonly):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-neutral-200);--_appearance-color-outline: var(--vvd-color-neutral-400)}.control:where(.readonly):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-600);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.control:where(.error):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: var(--vvd-color-alert-500)}.control:where(.error):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: transparent}.control:where(.success):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: var(--vvd-color-success-500)}.control:where(.success):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: transparent}.control{--_connotation-color-primary: var(--vvd-select-accent-primary, var(--vvd-color-canvas-text));--_connotation-color-primary-text: var(--vvd-select-accent-primary-text, var(--vvd-color-canvas));--_connotation-color-primary-increment: var(--vvd-select-accent-primary-increment, var(--vvd-color-neutral-800));--_connotation-color-intermediate: var(--vvd-select-accent-intermediate, var(--vvd-color-neutral-500));--_connotation-color-faint: var(--vvd-select-accent-faint, var(--vvd-color-neutral-50));--_connotation-color-soft: var(--vvd-select-accent-soft, var(--vvd-color-neutral-100));--_connotation-color-firm: var(--vvd-select-accent-firm, var(--vvd-color-canvas-text));--_connotation-color-fierce: var(--vvd-select-accent-fierce, var(--vvd-color-neutral-700))}.control{display:flex;align-items:center;justify-content:space-between;border-radius:var(--_select-control-border-radius);background-color:var(--_appearance-color-fill);block-size:calc(1px*(40 + 4*clamp(-1,var(--vvd-size-density, 0),2)));box-shadow:inset 0 0 0 1px var(--_appearance-color-outline);color:var(--_appearance-color-text);font:var(--vvd-typography-base);gap:8px;padding-inline:16px;transition:box-shadow .2s,background-color .2s}.control-wrapper{position:relative}.control:not(.disabled){cursor:pointer}.control.disabled{pointer-events:none}.control:not(.shape-pill){--_select-control-border-radius: 8px}.control.shape-pill{--_select-control-border-radius: 24px}:host(:focus-visible) .control{box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px))}.listbox{display:flex;max-height:var(--select-height, 408px);flex-direction:column;padding:4px;gap:2px;overflow-y:auto}:host([multiple]:focus-visible) .listbox{box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px));border-radius:8px}.selected-value{display:flex;overflow:hidden;flex-grow:1;align-items:center;column-gap:12px;white-space:nowrap}.selected-value .text{overflow:hidden;max-inline-size:100%;text-overflow:ellipsis}.control.shows-placeholder .selected-value .text{color:var(--vvd-color-neutral-600)}.selected-value slot[name=icon]{flex:0 0 20px;font-size:20px;line-height:1}.control.has-meta .selected-value{padding-inline-end:8px}.feedback-wrapper{display:contents}::part(popup-base){inline-size:max-content;min-inline-size:var(--_select-fixed-width, 100%)}:host([multiple]) ::part(popup-base){position:static}";
520
-
521
- var __defProp = Object.defineProperty;
522
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
523
- var __decorateClass = (decorators, target, key, kind) => {
524
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
525
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
526
- if (decorator = decorators[i])
527
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
528
- if (kind && result) __defProp(target, key, result);
529
- return result;
508
+ _clonedTagIcons = new WeakMap();
509
+ tagIconOfOption_fn = function(option) {
510
+ return option.querySelector('[slot="tag-icon"]');
530
511
  };
531
- let Select = class extends Select$1 {
532
- constructor() {
533
- super(...arguments);
534
- this.fixedDropdown = false;
535
- this.placeholderOption = null;
536
- this._feedbackWrapper = null;
512
+ updateClonedTagIconOfOption_fn = function(option) {
513
+ if (option.selected && __privateMethod(this, _SearchableSelect_instances, tagIconOfOption_fn).call(this, option)) {
514
+ let clone = __privateGet(this, _clonedTagIcons).get(option);
515
+ if (!clone) {
516
+ clone = __privateMethod(this, _SearchableSelect_instances, tagIconOfOption_fn).call(this, option).cloneNode(true);
517
+ __privateGet(this, _clonedTagIcons).set(option, clone);
518
+ }
519
+ clone.slot = this._tagIconSlotName(option.value);
520
+ this.appendChild(clone);
521
+ } else {
522
+ const clone = __privateGet(this, _clonedTagIcons).get(option);
523
+ if (clone) {
524
+ clone.remove();
525
+ __privateGet(this, _clonedTagIcons).delete(option);
526
+ }
537
527
  }
538
- labelChanged() {
539
- if (!this.ariaLabel) {
540
- this.ariaLabel = this.label;
528
+ };
529
+ _suppressFilter = new WeakMap();
530
+ updateFilteredOptions_fn = function() {
531
+ const newFilteredOptions = [];
532
+ for (const option of this._slottedOptions ?? []) {
533
+ if (__privateGet(this, _suppressFilter) || this._inputValue === "") {
534
+ option.hidden = false;
535
+ option._matchedRange = null;
536
+ } else {
537
+ const matchIndex = option.text.toLowerCase().indexOf(this._inputValue.toLowerCase());
538
+ const matchedRange = matchIndex === -1 ? null : { from: matchIndex, to: matchIndex + this._inputValue.length };
539
+ option.hidden = !matchedRange;
540
+ option._matchedRange = matchedRange;
541
+ }
542
+ if (!option.hidden) {
543
+ newFilteredOptions.push(option);
541
544
  }
542
545
  }
543
- connectedCallback() {
544
- super.connectedCallback();
546
+ __privateMethod(this, _SearchableSelect_instances, transitionHighlightedOptionTo_fn).call(this, null);
547
+ this._filteredOptions = newFilteredOptions;
548
+ this._filteredEnabledOptions = newFilteredOptions.filter(
549
+ (option) => !option.disabled
550
+ );
551
+ };
552
+ transitionHighlightedOptionTo_fn = function(index) {
553
+ if (typeof this._highlightedOptionIndex === "number") {
554
+ this._filteredEnabledOptions[this._highlightedOptionIndex]._highlighted = false;
545
555
  }
546
- get displayValue() {
547
- Observable.track(this, "displayValue");
548
- return this.firstSelectedOption?.getAttribute("label") ?? this.firstSelectedOption?.text ?? this.placeholder ?? "";
556
+ if (typeof index === "number") {
557
+ if (!this._filteredEnabledOptions.length) {
558
+ index = null;
559
+ } else {
560
+ index = Math.max(
561
+ 0,
562
+ Math.min(this._filteredEnabledOptions.length - 1, index)
563
+ );
564
+ }
549
565
  }
550
- setDefaultSelectedOption() {
551
- const options = Array.from(this.children).filter(
552
- Listbox$1.slottedOptionFilter
553
- );
554
- const selectedIndex = options.findIndex(
555
- (el) => el.hasAttribute("selected") || el.selected || el.value === this.value
566
+ this._highlightedOptionIndex = index;
567
+ if (typeof this._highlightedOptionIndex === "number") {
568
+ const highlightedOption = this._filteredEnabledOptions[this._highlightedOptionIndex];
569
+ highlightedOption._highlighted = true;
570
+ scrollIntoView(highlightedOption, this._listbox, "nearest");
571
+ this._changeDescription = this.locale.searchableSelect.optionFocusedMessage(
572
+ highlightedOption.text,
573
+ this._highlightedOptionIndex + 1,
574
+ this._filteredEnabledOptions.length
556
575
  );
557
- if (selectedIndex === -1 && !this.placeholderOption) {
558
- this.selectedIndex = 0;
559
- return;
576
+ }
577
+ };
578
+ selectHighlightedOption_fn = function() {
579
+ if (this._highlightedOptionIndex === null) {
580
+ return;
581
+ }
582
+ __privateMethod(this, _SearchableSelect_instances, handleOptionInteraction_fn).call(this, this._filteredEnabledOptions[this._highlightedOptionIndex]);
583
+ };
584
+ highlightFirstOption_fn = function() {
585
+ __privateMethod(this, _SearchableSelect_instances, transitionHighlightedOptionTo_fn).call(this, 0);
586
+ };
587
+ highlightLastOption_fn = function() {
588
+ __privateMethod(this, _SearchableSelect_instances, transitionHighlightedOptionTo_fn).call(this, this._filteredEnabledOptions.length - 1);
589
+ };
590
+ highlightPrevPage_fn = function() {
591
+ __privateMethod(this, _SearchableSelect_instances, transitionHighlightedOptionTo_fn).call(this, (this._highlightedOptionIndex ?? this._filteredEnabledOptions.length) - PageSize);
592
+ };
593
+ highlightNextPage_fn = function() {
594
+ __privateMethod(this, _SearchableSelect_instances, transitionHighlightedOptionTo_fn).call(this, (this._highlightedOptionIndex ?? -1) + PageSize);
595
+ };
596
+ highlightPreviousOption_fn = function() {
597
+ __privateMethod(this, _SearchableSelect_instances, transitionHighlightedOptionTo_fn).call(this, (this._highlightedOptionIndex ?? this._filteredEnabledOptions.length) - 1);
598
+ };
599
+ highlightNextOption_fn = function() {
600
+ __privateMethod(this, _SearchableSelect_instances, transitionHighlightedOptionTo_fn).call(this, (this._highlightedOptionIndex ?? -1) + 1);
601
+ };
602
+ textForValue_fn = function(value) {
603
+ const option = this._slottedOptions.find(
604
+ (option2) => option2.value === value
605
+ );
606
+ return option.text;
607
+ };
608
+ /**
609
+ * @internal
610
+ */
611
+ measureTagWidth_fn = function(label, removable, hasIcon) {
612
+ const tag = document.createElement(this._optionTagTagName);
613
+ tag.label = label;
614
+ tag.removable = removable;
615
+ tag.style.cssText = "position: absolute; visibility: hidden;";
616
+ tag.hasIconPlaceholder = hasIcon;
617
+ this.shadowRoot.appendChild(tag);
618
+ const width = tag.getBoundingClientRect().width;
619
+ tag.remove();
620
+ return width;
621
+ };
622
+ updateTagLayout_fn = function() {
623
+ if (!this.multiple) {
624
+ this._numElidedTags = 0;
625
+ this._tagRows = [];
626
+ this._lastTagRow = [];
627
+ return;
628
+ }
629
+ if (this.externalTags) {
630
+ this._numElidedTags = this.values.length;
631
+ this._tagRows = [];
632
+ this._lastTagRow = [];
633
+ return;
634
+ }
635
+ const rowWidth = this._contentArea.getBoundingClientRect().width;
636
+ const rows = [[]];
637
+ let currentRowIndex = 0;
638
+ let currentRowWidth = InputMinWidthPx;
639
+ let i;
640
+ for (i = this.values.length - 1; i >= 0; i--) {
641
+ const isLastRow = this.maxLines && currentRowIndex === this.maxLines - 1;
642
+ const tagWidth = __privateMethod(this, _SearchableSelect_instances, measureTagWidth_fn).call(this, this._tagLabelForValue(this.values[i]), true, __privateMethod(this, _SearchableSelect_instances, tagIconOfOption_fn).call(this, this.selectedOptions[i]) !== null);
643
+ const entry = {
644
+ value: this.values[i],
645
+ width: tagWidth
646
+ };
647
+ let elidedTagCounterWidth = 0;
648
+ if (isLastRow) {
649
+ const numElidedTags = i;
650
+ if (numElidedTags) {
651
+ elidedTagCounterWidth = TagGapPx + __privateMethod(this, _SearchableSelect_instances, measureTagWidth_fn).call(this, numElidedTags.toString(), false, false);
652
+ }
560
653
  }
561
- if (selectedIndex !== -1 || this.placeholder !== "") {
562
- this.selectedIndex = selectedIndex;
563
- return;
654
+ const totalWidthNeeded = currentRowWidth + TagGapPx + tagWidth + elidedTagCounterWidth;
655
+ if (totalWidthNeeded > rowWidth) {
656
+ if (isLastRow) {
657
+ if (i === this.values.length - 1) {
658
+ rows[currentRowIndex].unshift(entry);
659
+ currentRowWidth += TagGapPx + tagWidth;
660
+ } else {
661
+ break;
662
+ }
663
+ } else {
664
+ rows.push([]);
665
+ currentRowIndex++;
666
+ rows[currentRowIndex].unshift(entry);
667
+ currentRowWidth = tagWidth;
668
+ }
669
+ continue;
564
670
  }
671
+ rows[currentRowIndex].unshift(entry);
672
+ currentRowWidth += TagGapPx + tagWidth;
565
673
  }
566
- /*
567
- * @internal
568
- */
569
- slottedOptionsChanged(prev, next) {
570
- super.slottedOptionsChanged(prev, next);
571
- this.proxy.value = this.value;
572
- this.validate();
674
+ this._numElidedTags = i + 1;
675
+ rows.reverse();
676
+ for (let i2 = 0; i2 < rows.length - 1; i2++) {
677
+ let lineWidth = rows[i2].map((e) => e.width).reduce((a, b) => a + b, 0) + (rows[i2].length - 1) * TagGapPx;
678
+ if (i2 === 0 && this._numElidedTags) {
679
+ lineWidth += TagGapPx + __privateMethod(this, _SearchableSelect_instances, measureTagWidth_fn).call(this, this._numElidedTags.toString(), false, false);
680
+ }
681
+ while (rows[i2 + 1].length && lineWidth + TagGapPx + rows[i2 + 1][0].width <= rowWidth) {
682
+ const nextTag = rows[i2 + 1].shift();
683
+ rows[i2].push(nextTag);
684
+ lineWidth += TagGapPx + nextTag.width;
685
+ }
573
686
  }
574
- formResetCallback() {
575
- super.formResetCallback();
576
- if (this.placeholder) {
577
- this.selectedIndex = -1;
687
+ const rowValues = rows.map((line) => line.map((entry) => entry.value));
688
+ this._tagRows = rowValues.slice(0, -1);
689
+ this._lastTagRow = rowValues.slice(-1)[0];
690
+ };
691
+ moveTagFocusTo_fn = function(index) {
692
+ if (index === null) {
693
+ this._input.focus();
694
+ } else {
695
+ this.shadowRoot.querySelector(`[data-index="${index}"]`)?.focus();
696
+ }
697
+ };
698
+ nextTagIndexLeft_fn = function(index) {
699
+ if (!this.values.length) {
700
+ return null;
701
+ }
702
+ for (let i = index - 1; i >= 0; i--) {
703
+ if (!this._isTagDisabled(this.values[i])) {
704
+ return i;
578
705
  }
579
706
  }
707
+ return null;
580
708
  };
581
- __decorateClass([
582
- observable
583
- ], Select.prototype, "_anchor", 2);
584
- __decorateClass([
709
+ nextTagIndexRight_fn = function(index) {
710
+ if (!this.values.length) {
711
+ return null;
712
+ }
713
+ for (let i = index + 1; i < this.values.length; i++) {
714
+ if (!this._isTagDisabled(this.values[i])) {
715
+ return i;
716
+ }
717
+ }
718
+ return null;
719
+ };
720
+ nextTagIndexForRemoved_fn = function(index) {
721
+ return __privateMethod(this, _SearchableSelect_instances, nextTagIndexRight_fn).call(this, index - 1) ?? __privateMethod(this, _SearchableSelect_instances, nextTagIndexLeft_fn).call(this, index);
722
+ };
723
+ // --- Form handling ---
724
+ determineInitialValues_fn = function() {
725
+ return this.initialValues.length ? this.initialValues : this.initialValue ? [this.initialValue] : [];
726
+ };
727
+ updateFormValue_fn = function() {
728
+ if (!this.name) {
729
+ this.setFormValue(null);
730
+ } else {
731
+ const formData = new FormData();
732
+ for (const value of this.values) {
733
+ formData.append(this.name, value);
734
+ }
735
+ this.setFormValue(formData);
736
+ }
737
+ };
738
+ _resizeObserver = new WeakMap();
739
+ __decorateClass$1([
585
740
  attr
586
- ], Select.prototype, "appearance", 2);
587
- __decorateClass([
741
+ ], SearchableSelect.prototype, "appearance", 2);
742
+ __decorateClass$1([
588
743
  attr
589
- ], Select.prototype, "shape", 2);
590
- __decorateClass([
744
+ ], SearchableSelect.prototype, "shape", 2);
745
+ __decorateClass$1([
591
746
  attr({ mode: "boolean", attribute: "fixed-dropdown" })
592
- ], Select.prototype, "fixedDropdown", 2);
593
- __decorateClass([
747
+ ], SearchableSelect.prototype, "fixedDropdown", 2);
748
+ __decorateClass$1([
594
749
  attr
595
- ], Select.prototype, "placeholder", 2);
596
- __decorateClass([
750
+ ], SearchableSelect.prototype, "placeholder", 2);
751
+ __decorateClass$1([
752
+ attr({ mode: "boolean" })
753
+ ], SearchableSelect.prototype, "open", 2);
754
+ __decorateClass$1([
755
+ attr({ mode: "boolean" })
756
+ ], SearchableSelect.prototype, "multiple", 2);
757
+ __decorateClass$1([
758
+ attr({ attribute: "external-tags", mode: "boolean" })
759
+ ], SearchableSelect.prototype, "externalTags", 2);
760
+ __decorateClass$1([
761
+ attr({ attribute: "max-lines", converter: nullableNumberConverter })
762
+ ], SearchableSelect.prototype, "maxLines", 2);
763
+ __decorateClass$1([
597
764
  observable
598
- ], Select.prototype, "placeholderOption", 2);
599
- __decorateClass([
765
+ ], SearchableSelect.prototype, "values", 2);
766
+ __decorateClass$1([
600
767
  observable
601
- ], Select.prototype, "_feedbackWrapper", 2);
602
- __decorateClass([
768
+ ], SearchableSelect.prototype, "initialValues", 2);
769
+ __decorateClass$1([
770
+ observable
771
+ ], SearchableSelect.prototype, "_input", 2);
772
+ __decorateClass$1([
773
+ observable
774
+ ], SearchableSelect.prototype, "_inputValue", 2);
775
+ __decorateClass$1([
776
+ observable
777
+ ], SearchableSelect.prototype, "_slottedOptions", 2);
778
+ __decorateClass$1([
603
779
  observable
604
- ], Select.prototype, "metaSlottedContent", 2);
605
- Select = __decorateClass([
780
+ ], SearchableSelect.prototype, "_filteredOptions", 2);
781
+ __decorateClass$1([
782
+ observable
783
+ ], SearchableSelect.prototype, "_filteredEnabledOptions", 2);
784
+ __decorateClass$1([
785
+ observable
786
+ ], SearchableSelect.prototype, "_highlightedOptionIndex", 2);
787
+ __decorateClass$1([
788
+ observable
789
+ ], SearchableSelect.prototype, "_contentArea", 2);
790
+ __decorateClass$1([
791
+ observable
792
+ ], SearchableSelect.prototype, "_numElidedTags", 2);
793
+ __decorateClass$1([
794
+ observable
795
+ ], SearchableSelect.prototype, "_tagRows", 2);
796
+ __decorateClass$1([
797
+ observable
798
+ ], SearchableSelect.prototype, "_lastTagRow", 2);
799
+ __decorateClass$1([
800
+ observable
801
+ ], SearchableSelect.prototype, "_listbox", 2);
802
+ __decorateClass$1([
803
+ attr({ mode: "boolean" })
804
+ ], SearchableSelect.prototype, "clearable", 2);
805
+ __decorateClass$1([
806
+ observable
807
+ ], SearchableSelect.prototype, "_changeDescription", 2);
808
+ __decorateClass$1([
809
+ observable
810
+ ], SearchableSelect.prototype, "_anchor", 2);
811
+ SearchableSelect = __decorateClass$1([
606
812
  errorText,
607
813
  formElements
608
- ], Select);
814
+ ], SearchableSelect);
609
815
  applyMixinsWithObservables(
610
- Select,
816
+ SearchableSelect,
611
817
  AffixIconWithTrailing,
612
818
  FormElementHelperText,
613
- FormElementSuccessText
819
+ FormElementSuccessText,
820
+ Localized
614
821
  );
615
822
 
616
- const getStateClasses = ({
617
- shape,
618
- disabled,
619
- appearance,
620
- metaSlottedContent,
621
- errorValidationMessage,
622
- successText,
623
- placeholder,
624
- value
625
- }) => classNames(
626
- ["disabled", disabled],
627
- [`appearance-${appearance}`, Boolean(appearance)],
628
- [`shape-${shape}`, Boolean(shape)],
629
- ["has-meta", Boolean(metaSlottedContent?.length)],
630
- ["error", Boolean(errorValidationMessage)],
631
- ["success", !!successText],
632
- ["has-meta", Boolean(metaSlottedContent?.length)],
633
- ["shows-placeholder", Boolean(placeholder) && !value]
823
+ var __defProp = Object.defineProperty;
824
+ var __decorateClass = (decorators, target, key, kind) => {
825
+ var result = void 0 ;
826
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
827
+ if (decorator = decorators[i])
828
+ result = (decorator(target, key, result) ) || result;
829
+ if (result) __defProp(target, key, result);
830
+ return result;
831
+ };
832
+ class OptionTag extends FoundationElement {
833
+ constructor() {
834
+ super(...arguments);
835
+ this.removable = false;
836
+ this.disabled = false;
837
+ this.hasIconPlaceholder = false;
838
+ }
839
+ _onClickRemove() {
840
+ this.$emit("remove", void 0, {
841
+ bubbles: false
842
+ });
843
+ }
844
+ }
845
+ __decorateClass([
846
+ attr
847
+ ], OptionTag.prototype, "shape");
848
+ __decorateClass([
849
+ attr
850
+ ], OptionTag.prototype, "label");
851
+ __decorateClass([
852
+ attr({ mode: "boolean" })
853
+ ], OptionTag.prototype, "removable");
854
+ __decorateClass([
855
+ attr({ mode: "boolean" })
856
+ ], OptionTag.prototype, "disabled");
857
+ __decorateClass([
858
+ observable
859
+ ], OptionTag.prototype, "hasIconPlaceholder");
860
+ applyMixins(OptionTag, Localized);
861
+
862
+ const getStateClasses = (x) => classNames(
863
+ ["disabled", x.disabled],
864
+ [`appearance-${x.appearance}`, Boolean(x.appearance)],
865
+ [`shape-${x.shape}`, Boolean(x.shape)],
866
+ ["error", Boolean(x.errorValidationMessage)],
867
+ ["success", !!x.successText]
634
868
  );
635
869
  function renderLabel() {
636
- return html` <label for="control" class="label" id="label">
637
- ${(x) => x.label}
638
- </label>`;
639
- }
640
- function renderPlaceholder(context) {
641
- const optionTag = context.tagFor(ListboxOption);
642
870
  return html`
643
- <${optionTag} ${ref("placeholderOption")}
644
- text="${(x) => x.placeholder}" hidden disabled>
645
- </${optionTag}>`;
871
+ <label for="control" class="label" id="label"> ${(x) => x.label} </label>
872
+ `;
646
873
  }
647
- function selectValue(context) {
874
+ const tagTemplateFactory = (context, getComponent) => {
875
+ const optionTagTag = context.tagFor(OptionTag);
876
+ return html`
877
+ <div class="tag-wrapper">
878
+ <${optionTagTag}
879
+ class="tag"
880
+ tabindex="-1"
881
+ data-index="${(x, c) => getComponent(c).values.indexOf(x)}"
882
+ removable
883
+ :label="${(x, c) => getComponent(c)._tagLabelForValue(x)}"
884
+ :shape="${(_, c) => getComponent(c).shape}"
885
+ ?disabled="${(x, c) => getComponent(c)._isTagDisabled(x)}"
886
+ @remove="${(x, c) => getComponent(c)._onTagRemoved(x)}"
887
+ @keydown="${(_, c) => getComponent(c)._onTagKeydown(c.event)}"
888
+ @mousedown="${() => false}">
889
+ <slot slot="icon" name="${(x, c) => getComponent(c)._tagIconSlotName(x)}"></slot>
890
+ </${optionTagTag}>
891
+ </div>
892
+ `;
893
+ };
894
+ const elidedTagTemplateFactory = (context, getComponent) => {
895
+ const optionTagTag = context.tagFor(OptionTag);
896
+ return html`
897
+ <${optionTagTag}
898
+ class="tag"
899
+ tabindex="-1"
900
+ :label="${(x, c) => getComponent(x, c)._numElidedTags.toString()}"
901
+ :shape="${(x, c) => getComponent(x, c).shape}"
902
+ ?disabled="${(x, c) => getComponent(x, c).disabled}"
903
+ @mousedown="${() => false}">
904
+ </${optionTagTag}>
905
+ `;
906
+ };
907
+ function renderFieldset(context) {
908
+ const buttonTag = context.tagFor(Button$1);
648
909
  const affixIconTemplate = affixIconTemplateFactory(context);
649
910
  const chevronTemplate = chevronTemplateFactory(context);
650
- return html` <div
651
- class="control ${getStateClasses}"
652
- ${ref("_anchor")}
653
- id="control"
654
- ?disabled="${(x) => x.disabled}"
655
- >
656
- <div class="selected-value">
911
+ const tagTemplate = tagTemplateFactory(context, (c) => c.parent);
912
+ const nestedTagTemplate = tagTemplateFactory(
913
+ context,
914
+ (c) => c.parentContext.parent
915
+ );
916
+ const elidedTagTemplate = elidedTagTemplateFactory(context, (x, _) => x);
917
+ const nestedElidedTagTemplate = elidedTagTemplateFactory(
918
+ context,
919
+ (_, c) => c.parent
920
+ );
921
+ return html`
922
+ <div
923
+ class="fieldset ${getStateClasses}"
924
+ @click="${(x, c) => x._onFieldsetClick(c.event)}"
925
+ ${ref("_anchor")}
926
+ >
657
927
  ${(x) => affixIconTemplate(x.icon, IconWrapper.Slot)}
658
- <span class="text">${(x) => x.displayValue}</span>
659
- <slot name="meta" ${slotted("metaSlottedContent")}></slot>
928
+ <div class="content-area" ${ref("_contentArea")}>
929
+ ${repeat(
930
+ (x) => x._tagRows,
931
+ html`
932
+ <div class="tag-row">
933
+ ${when(
934
+ (_, c) => c.isFirst && c.parent._numElidedTags,
935
+ nestedElidedTagTemplate
936
+ )}
937
+ ${repeat((x) => x, nestedTagTemplate)}
938
+ </div>
939
+ `,
940
+ { positioning: true }
941
+ )}
942
+ <div
943
+ class="tag-row ${(x) => classNames([
944
+ "contains-only-input",
945
+ x._tagRows.length > 0 && x._lastTagRow.length === 0
946
+ ])}"
947
+ >
948
+ ${when(
949
+ (x) => x._tagRows.length === 0 && x._numElidedTags,
950
+ elidedTagTemplate
951
+ )}
952
+ ${repeat((x) => x._lastTagRow, tagTemplate)}
953
+ <input
954
+ id="control"
955
+ class="control"
956
+ autofocus
957
+ autocomplete="off"
958
+ aria-autocomplete="list"
959
+ aria-expanded="${(x) => x.open}"
960
+ aria-haspopup="listbox"
961
+ aria-controls="listbox"
962
+ placeholder="${(x) => x.multiple && x.values.length ? "" : x.placeholder}"
963
+ role="combobox"
964
+ type="text"
965
+ ?disabled="${(x) => x.disabled}"
966
+ :value="${(x) => x._inputValue}"
967
+ @input="${(x, c) => x._onInputInput(c.event)}"
968
+ @focus="${(x, c) => x._onInputFocus(c.event)}"
969
+ @blur="${(x, c) => x._onInputBlur(c.event)}"
970
+ @keydown="${(x, c) => x._onInputKeydown(c.event)}"
971
+ ${ref("_input")}
972
+ />
973
+ </div>
974
+ </div>
975
+ <slot name="meta"></slot>
976
+ ${when(
977
+ (x) => x._shouldShowClearButton,
978
+ html`<${buttonTag}
979
+ aria-label="${(x) => x.locale.searchableSelect.clearButtonLabel}"
980
+ @click="${(x) => x._onClearButtonClick()}"
981
+ @mousedown="${() => false}"
982
+ ?disabled="${(x) => x.disabled}"
983
+ :shape="${(x) => x.shape}"
984
+ size="super-condensed"
985
+ icon="close-line"
986
+ appearance="ghost-light"
987
+ tabindex="-1"
988
+ ></${buttonTag}>`
989
+ )}
990
+ ${chevronTemplate}
660
991
  </div>
661
- ${chevronTemplate}
662
- </div>`;
663
- }
664
- function setFixedDropdownVarWidth(x) {
665
- return x.open && x.fixedDropdown ? `--_select-fixed-width: ${Math.round(x.getBoundingClientRect().width)}px` : null;
992
+ `;
666
993
  }
667
994
  function renderControl(context) {
668
995
  const popupTag = context.tagFor(Popup);
669
996
  return html`
670
- ${when((x) => x.label, renderLabel())}
671
- <div class="control-wrapper">
672
- ${when((x) => !x.multiple, selectValue(context))}
673
- <${popupTag} class="popup"
674
- style="${setFixedDropdownVarWidth}"
675
- ?open="${(x) => x.collapsible ? x.open : true}"
997
+ ${when((x) => x.label, renderLabel())}
998
+ <span aria-live="assertive" aria-relevant="text" class="visually-hidden">
999
+ ${(x) => x._changeDescription}
1000
+ </span>
1001
+ <div>
1002
+ ${renderFieldset(context)}
1003
+ <div class="popup-wrapper">
1004
+ <${popupTag}
676
1005
  :anchor="${(x) => x._anchor}"
1006
+ :open="${(x) => x.open}"
1007
+ class="popup"
677
1008
  placement="bottom-start"
678
- strategy="${(x) => x.fixedDropdown ? null : "absolute"}">
679
- <div class="listbox"
680
- id="${(x) => x.listboxId}"
1009
+ strategy="${(x) => x.fixedDropdown ? "fixed" : "absolute"}">
1010
+ <div
1011
+ class="listbox"
681
1012
  role="listbox"
682
- ?disabled="${(x) => x.disabled}"
683
- ?hidden="${(x) => x.collapsible ? !x.open : false}"
684
- ${ref("listbox")}>
685
- ${when((x) => x.placeholder, renderPlaceholder(context))}
1013
+ aria-multiselectable="${(x) => x.multiple}"
1014
+ aria-required="${(x) => x.required}"
1015
+ ${ref("_listbox")}
1016
+ @click="${(x, c) => x._onListboxClick(c.event)}"
1017
+ @mousedown="${() => false}"
1018
+ >
686
1019
  <slot
687
1020
  ${slotted({
688
- filter: Listbox$1.slottedOptionFilter,
1021
+ filter: Listbox.slottedOptionFilter,
689
1022
  flatten: true,
690
- property: "slottedOptions"
1023
+ property: "_slottedOptions"
691
1024
  })}>
692
1025
  </slot>
693
- </div>
1026
+ ${when(
1027
+ (x) => x._filteredOptions.length === 0,
1028
+ html`<div class="empty-message">
1029
+ ${when(
1030
+ (x) => x._inputValue === "",
1031
+ html`<slot name="no-options">
1032
+ ${(x) => x.locale.searchableSelect.noOptionsMessage}
1033
+ </slot>`
1034
+ )}
1035
+ ${when(
1036
+ (x) => x._inputValue !== "",
1037
+ html`<slot name="no-matches">
1038
+ ${(x) => x.locale.searchableSelect.noMatchesMessage}
1039
+ </slot>`
1040
+ )}
1041
+ </div>`
1042
+ )}
1043
+ </div>
694
1044
  </${popupTag}>
695
1045
  </div>
696
- `;
697
- }
698
- function ifNotFromFeedback(handler) {
699
- return (x, c) => {
700
- if (!c.event.composedPath().includes(x._feedbackWrapper)) {
701
- return handler(x, c.event);
702
- }
703
- return true;
704
- };
1046
+ </div>
1047
+ `;
705
1048
  }
706
- const SelectTemplate = (context) => {
1049
+ const SearchableSelectTemplate = (context) => {
1050
+ const optionTagTag = context.tagFor(OptionTag);
707
1051
  return html`
708
- <template
709
- class="base"
710
- aria-label="${(x) => x.ariaLabel}"
711
- aria-activedescendant="${(x) => x.ariaActiveDescendant}"
712
- aria-controls="${(x) => x.ariaControls}"
713
- aria-disabled="${(x) => x.ariaDisabled}"
714
- aria-expanded="${(x) => x.ariaExpanded}"
715
- aria-haspopup="${(x) => x.collapsible ? "listbox" : null}"
716
- aria-multiselectable="${(x) => x.ariaMultiSelectable}"
717
- role="combobox"
718
- tabindex="${(x) => !x.disabled ? "0" : null}"
719
- @click="${ifNotFromFeedback((x, e) => x.clickHandler(e))}"
720
- @focusin="${ifNotFromFeedback((x, e) => x.focusinHandler(e))}"
721
- @focusout="${ifNotFromFeedback(
722
- (x, e) => x.focusoutHandler(e)
723
- )}"
724
- @keydown="${ifNotFromFeedback((x, e) => {
725
- x.open && handleEscapeKeyAndStopPropogation(e);
726
- return x.keydownHandler(e);
727
- })}"
728
- @mousedown="${ifNotFromFeedback(
729
- (x, e) => x.mousedownHandler(e)
730
- )}"
731
- >
732
- ${renderControl(context)}
733
- <div class="feedback-wrapper" ${ref("_feedbackWrapper")}>
734
- ${getFeedbackTemplate(context)}
1052
+ <template :_optionTagTagName="${() => optionTagTag}">
1053
+ <div class="control-wrapper">
1054
+ ${renderControl(context)} ${getFeedbackTemplate(context)}
735
1055
  </div>
736
1056
  </template>
737
1057
  `;
738
1058
  };
739
1059
 
740
- const selectDefinition = Select.compose({
741
- baseName: "select",
742
- template: SelectTemplate,
743
- styles
1060
+ const getClasses = ({ shape, disabled, removable }) => classNames(
1061
+ "base",
1062
+ ["disabled", disabled],
1063
+ ["removable", removable],
1064
+ [`shape-${shape}`, Boolean(shape)]
1065
+ );
1066
+ function renderRemoveButton(iconTag) {
1067
+ return html`
1068
+ <span
1069
+ class="remove-button"
1070
+ aria-label="${(x) => x.locale.searchableSelect.removeTagButtonLabel(x.label)}"
1071
+ role="button"
1072
+ tabindex="${(x) => x.disabled ? null : 0}"
1073
+ @click="${(x) => x._onClickRemove()}"
1074
+ >
1075
+ <${iconTag} name="close-line"></${iconTag}>
1076
+ </span>
1077
+ `;
1078
+ }
1079
+ const optionTagTemplate = (context) => {
1080
+ const iconTag = context.tagFor(Icon);
1081
+ return html`<span class="${getClasses}" aria-disabled="${(x) => x.disabled}">
1082
+ <slot name="icon" aria-hidden="true">
1083
+ ${when(
1084
+ (x) => x.hasIconPlaceholder,
1085
+ html`<div class="icon-placeholder"></div>`
1086
+ )}
1087
+ </slot>
1088
+ ${when(
1089
+ (x) => x.label,
1090
+ (x) => html`<span class="label">${x.label}</span>`
1091
+ )}
1092
+ ${when((x) => x.removable, renderRemoveButton(iconTag))}
1093
+ </span>`;
1094
+ };
1095
+
1096
+ const optionTagDefinition = OptionTag.compose({
1097
+ baseName: "option-tag",
1098
+ template: optionTagTemplate,
1099
+ styles: [optionTagStyles],
1100
+ shadowOptions: {
1101
+ delegatesFocus: true
1102
+ }
744
1103
  });
745
- const selectRegistries = [
746
- selectDefinition(),
1104
+ const searchableSelectDefinition = SearchableSelect.compose({
1105
+ baseName: "searchable-select",
1106
+ template: SearchableSelectTemplate,
1107
+ styles: [styles],
1108
+ shadowOptions: {
1109
+ delegatesFocus: true
1110
+ }
1111
+ });
1112
+ const searchableSelectRegistries = [
1113
+ ...buttonRegistries,
747
1114
  ...popupRegistries,
748
1115
  ...iconRegistries,
749
- ...listboxOptionRegistries
1116
+ optionTagDefinition(),
1117
+ searchableSelectDefinition()
750
1118
  ];
751
- const registerSelect = registerFactory(selectRegistries);
1119
+ const registerSearchableSelect = registerFactory(
1120
+ searchableSelectRegistries
1121
+ );
752
1122
 
753
- export { selectRegistries as a, registerSelect as r, selectDefinition as s };
1123
+ export { searchableSelectRegistries as a, optionTagDefinition as o, registerSearchableSelect as r, searchableSelectDefinition as s };