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