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