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