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