@lion/ui 0.22.0 → 0.24.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 (901) hide show
  1. package/README.md +65 -0
  2. package/components/accordion/src/LionAccordion.js +31 -42
  3. package/components/accordion/test/lion-accordion.test.js +108 -134
  4. package/components/button/src/LionButton.js +9 -12
  5. package/components/button/src/LionButtonReset.js +0 -5
  6. package/components/button/src/LionButtonSubmit.js +7 -12
  7. package/components/button/test/demos.screenshots-test.js +50 -11
  8. package/components/button/test/lion-button.test.js +0 -1
  9. package/components/button/test-suites/LionButton.suite.js +135 -145
  10. package/components/button/test-suites/LionButtonReset.suite.js +54 -72
  11. package/components/button/test-suites/LionButtonSubmit.suite.js +49 -68
  12. package/components/calendar/src/LionCalendar.js +151 -104
  13. package/components/calendar/src/calendarStyle.js +0 -1
  14. package/components/calendar/src/utils/createMonth.js +3 -4
  15. package/components/calendar/src/utils/createMultipleMonth.js +15 -7
  16. package/components/calendar/src/utils/createWeek.js +0 -2
  17. package/components/calendar/src/utils/dataTemplate.js +8 -4
  18. package/components/calendar/src/utils/dayTemplate.js +0 -6
  19. package/components/calendar/src/utils/getDayMonthYear.js +6 -2
  20. package/components/calendar/test/demos.screenshots-test.js +40 -9
  21. package/components/calendar/test/lion-calendar.test.js +171 -282
  22. package/components/calendar/test/utils/createMonth.test.js +61 -22
  23. package/components/calendar/test/utils/createMultipleMonth.test.js +14 -7
  24. package/components/calendar/test/utils/createWeek.test.js +51 -17
  25. package/components/calendar/test/utils/dataTemplate.test.js +3 -4
  26. package/components/calendar/test/utils/dayTemplate.test.js +106 -34
  27. package/components/calendar/test/utils/getFirstDayNextMonth.test.js +0 -1
  28. package/components/calendar/test/utils/getLastDayPreviousMonth.test.js +0 -1
  29. package/components/calendar/test/utils/isSameDate.test.js +0 -1
  30. package/components/calendar/test/utils/snapshots/monthTemplate_en-GB_Sunday_2018-12.js +1 -2
  31. package/components/calendar/test-helpers/CalendarObject.js +31 -62
  32. package/components/calendar/test-helpers/DayObject.js +7 -15
  33. package/components/calendar/test-suites/LionCalendar.suite.js +7 -9
  34. package/components/checkbox-group/src/LionCheckboxIndeterminate.js +17 -30
  35. package/components/checkbox-group/test/lion-checkbox-group-integrations.test.js +0 -1
  36. package/components/checkbox-group/test/lion-checkbox-group.test.js +21 -16
  37. package/components/checkbox-group/test/lion-checkbox-indeterminate-integrations.test.js +3 -3
  38. package/components/checkbox-group/test/lion-checkbox-integrations.test.js +3 -2
  39. package/components/checkbox-group/test/lion-checkbox.test.js +30 -16
  40. package/components/checkbox-group/test-suites/CheckboxIndeterminate.suite.js +147 -191
  41. package/components/collapsible/src/LionCollapsible.js +10 -15
  42. package/components/collapsible/test/lion-collapsible.test.js +4 -18
  43. package/components/combobox/src/LionCombobox.js +45 -55
  44. package/components/combobox/src/utils/makeMatchingTextBold.js +2 -5
  45. package/components/combobox/src/validators.js +0 -1
  46. package/components/combobox/test/lion-combobox-integrations.test.js +6 -6
  47. package/components/combobox/test/lion-combobox.test.js +598 -860
  48. package/components/combobox/test/validators.test.js +6 -13
  49. package/components/combobox/test-helpers/combobox-helpers.js +24 -11
  50. package/components/core/src/DisabledMixin.js +61 -66
  51. package/components/core/src/DisabledWithTabIndexMixin.js +76 -83
  52. package/components/core/src/EventTargetShim.js +1 -4
  53. package/components/core/src/ScopedElementsMixin.js +4 -15
  54. package/components/core/src/ScopedStylesController.js +1 -5
  55. package/components/core/src/SlotMixin.js +236 -239
  56. package/components/core/src/browserDetection.js +5 -12
  57. package/components/core/test/DisabledMixin.test.js +24 -39
  58. package/components/core/test/DisabledWithTabIndexMixin.test.js +21 -34
  59. package/components/core/test/EventTargetShim.test.js +0 -8
  60. package/components/core/test/ScopedElementsMixin.test.js +22 -38
  61. package/components/core/test/ScopedStylesController.test.js +11 -20
  62. package/components/core/test/SlotMixin.test.js +102 -154
  63. package/components/core/test-helpers/getCachedFixture.js +5 -11
  64. package/components/core/types/SlotMixinTypes.ts +8 -3
  65. package/components/dialog/src/LionDialog.js +4 -3
  66. package/components/dialog/test/lion-dialog.integration.test.js +10 -20
  67. package/components/dialog/test/lion-dialog.test.js +48 -62
  68. package/components/dialog/test-helpers/test-router.js +4 -6
  69. package/components/drawer/src/LionDrawer.js +18 -34
  70. package/components/drawer/src/drawerStyle.js +0 -1
  71. package/components/drawer/test/lion-drawer.test.js +1 -17
  72. package/components/fieldset/test/lion-fieldset.test.js +6 -4
  73. package/components/form/src/LionForm.js +18 -13
  74. package/components/form/test/lion-form.test.js +22 -52
  75. package/components/form-core/src/FocusMixin.js +172 -174
  76. package/components/form-core/src/FormControlMixin.js +811 -813
  77. package/components/form-core/src/FormatMixin.js +537 -537
  78. package/components/form-core/src/InteractionStateMixin.js +196 -183
  79. package/components/form-core/src/LionField.js +9 -5
  80. package/components/form-core/src/NativeTextFieldMixin.js +114 -116
  81. package/components/form-core/src/choice-group/ChoiceGroupMixin.js +322 -357
  82. package/components/form-core/src/choice-group/ChoiceInputMixin.js +306 -296
  83. package/components/form-core/src/choice-group/CustomChoiceGroupMixin.js +114 -139
  84. package/components/form-core/src/form-group/FormElementsHaveNoError.js +0 -2
  85. package/components/form-core/src/form-group/FormGroupMixin.js +551 -557
  86. package/components/form-core/src/registration/FormRegisteringMixin.js +72 -71
  87. package/components/form-core/src/registration/FormRegistrarMixin.js +201 -217
  88. package/components/form-core/src/registration/FormRegistrarPortalMixin.js +31 -37
  89. package/components/form-core/src/utils/SyncUpdatableMixin.js +106 -117
  90. package/components/form-core/src/utils/getAriaElementsInRightDomOrder.js +1 -2
  91. package/components/form-core/src/validate/LionValidationFeedback.js +12 -8
  92. package/components/form-core/src/validate/Unparseable.js +4 -2
  93. package/components/form-core/src/validate/ValidateMixin.js +829 -883
  94. package/components/form-core/src/validate/Validator.js +3 -6
  95. package/components/form-core/src/validate/resultValidators/DefaultSuccess.js +1 -2
  96. package/components/form-core/src/validate/validators/DateValidators.js +0 -5
  97. package/components/form-core/src/validate/validators/NumberValidators.js +1 -5
  98. package/components/form-core/src/validate/validators/Required.js +1 -1
  99. package/components/form-core/src/validate/validators/StringValidators.js +1 -8
  100. package/components/form-core/test/FocusMixin.test.js +96 -82
  101. package/components/form-core/test/FormControlMixin.test.js +120 -176
  102. package/components/form-core/test/FormRegistrationMixins.test.js +0 -2
  103. package/components/form-core/test/FormatMixin.test.js +0 -1
  104. package/components/form-core/test/InteractionStateMixin.test.js +0 -1
  105. package/components/form-core/test/NativeTextFieldMixin.test.js +0 -1
  106. package/components/form-core/test/choice-group/ChoiceGroupMixin.test.js +0 -1
  107. package/components/form-core/test/choice-group/ChoiceInputMixin.test.js +0 -1
  108. package/components/form-core/test/choice-group/CustomChoiceGroupMixin.integrations.test.js +6 -8
  109. package/components/form-core/test/choice-group/CustomChoiceGroupMixin.test.js +0 -3
  110. package/components/form-core/test/form-group/FormGroupMixin.test.js +0 -1
  111. package/components/form-core/test/lion-field.test.js +88 -98
  112. package/components/form-core/test/utils/SyncUpdatableMixin.test.js +51 -65
  113. package/components/form-core/test/utils/getAriaElementsInRightDomOrder.test.js +3 -3
  114. package/components/form-core/test/validate/DateValidators.test.js +5 -27
  115. package/components/form-core/test/validate/NumberValidators.test.js +4 -16
  116. package/components/form-core/test/validate/Required.test.js +8 -21
  117. package/components/form-core/test/validate/ResultValidator.test.js +1 -2
  118. package/components/form-core/test/validate/StringValidators.test.js +4 -35
  119. package/components/form-core/test/validate/ValidateMixin.test.js +0 -1
  120. package/components/form-core/test/validate/ValidateMixinFeedbackPart.test.js +0 -1
  121. package/components/form-core/test/validate/Validator.test.js +39 -34
  122. package/components/form-core/test/validate/lion-validation-feedback.test.js +81 -43
  123. package/components/form-core/test-helpers/ExampleValidators.js +0 -5
  124. package/components/form-core/test-helpers/getFormControlMembers.js +2 -2
  125. package/components/form-core/test-helpers/mimicUserInput.js +5 -1
  126. package/components/form-core/test-suites/FormRegistrationMixins.suite.js +65 -122
  127. package/components/form-core/test-suites/FormatMixin.suite.js +202 -227
  128. package/components/form-core/test-suites/InteractionStateMixin.suite.js +47 -60
  129. package/components/form-core/test-suites/NativeTextFieldMixin.suite.js +8 -11
  130. package/components/form-core/test-suites/ValidateMixin.suite.js +280 -359
  131. package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +112 -163
  132. package/components/form-core/test-suites/choice-group/ChoiceGroupMixin.suite.js +185 -218
  133. package/components/form-core/test-suites/choice-group/ChoiceInputMixin.suite.js +116 -109
  134. package/components/form-core/test-suites/choice-group/CustomChoiceGroupMixin.suite.js +36 -70
  135. package/components/form-core/test-suites/form-group/FormGroupMixin-input.suite.js +57 -65
  136. package/components/form-core/test-suites/form-group/FormGroupMixin.suite.js +664 -523
  137. package/components/form-core/translations/bg-BG.js +0 -1
  138. package/components/form-core/translations/cs-CZ.js +0 -1
  139. package/components/form-core/translations/de-DE.js +0 -1
  140. package/components/form-core/translations/en-AU.js +0 -1
  141. package/components/form-core/translations/en-GB.js +0 -1
  142. package/components/form-core/translations/en-US.js +0 -1
  143. package/components/form-core/translations/es-ES.js +0 -1
  144. package/components/form-core/translations/fr-BE.js +0 -1
  145. package/components/form-core/translations/fr-FR.js +0 -1
  146. package/components/form-core/translations/hu-HU.js +0 -1
  147. package/components/form-core/translations/it-IT.js +0 -1
  148. package/components/form-core/translations/nl-BE.js +0 -1
  149. package/components/form-core/translations/nl-NL.js +0 -1
  150. package/components/form-core/translations/pl-PL.js +0 -1
  151. package/components/form-core/translations/ro-RO.js +0 -1
  152. package/components/form-core/translations/ru-RU.js +0 -1
  153. package/components/form-core/translations/sk-SK.js +0 -1
  154. package/components/form-core/translations/tr-TR.js +0 -1
  155. package/components/form-core/translations/uk-UA.js +0 -1
  156. package/components/form-core/types/choice-group/ChoiceGroupMixinTypes.ts +5 -0
  157. package/components/form-integrations/test/dialog-integrations.test.js +1 -4
  158. package/components/form-integrations/test/form-group-methods.test.js +28 -31
  159. package/components/form-integrations/test/form-integrations.test.js +27 -28
  160. package/components/form-integrations/test/form-validation-integrations.test.js +21 -29
  161. package/components/form-integrations/test/helpers/umbrella-form.js +3 -5
  162. package/components/form-integrations/test/model-value-consistency.test.js +75 -77
  163. package/components/form-integrations/test/model-value-event.test.js +10 -20
  164. package/components/helpers/src/SbActionLogger.js +13 -17
  165. package/components/helpers/src/SbLocaleSwitcher.js +5 -5
  166. package/components/helpers/src/sortEachDepth.js +0 -2
  167. package/components/helpers/test/renderLitAsNode.test.js +0 -4
  168. package/components/helpers/test/sb-action-logger.test.js +24 -55
  169. package/components/icon/src/IconManager.js +0 -2
  170. package/components/icon/src/LionIcon.js +2 -7
  171. package/components/icon/src/icons.js +0 -2
  172. package/components/icon/test/IconManager.test.js +0 -15
  173. package/components/icon/test/hammer.svg.js +3 -4
  174. package/components/icon/test/heart.svg.js +3 -4
  175. package/components/icon/test/lion-icon.test.js +14 -43
  176. package/components/input/src/LionInput.js +2 -8
  177. package/components/input/test/input-integrations.test.js +0 -5
  178. package/components/input/test/lion-input-integrations.test.js +0 -4
  179. package/components/input/test/lion-input.test.js +28 -58
  180. package/components/input/test-helpers/getInputMembers.js +2 -2
  181. package/components/input-amount/src/LionInputAmount.js +37 -26
  182. package/components/input-amount/src/formatters.js +4 -5
  183. package/components/input-amount/src/parsers.js +0 -3
  184. package/components/input-amount/test/formatters.test.js +102 -80
  185. package/components/input-amount/test/lion-input-amount-integrations.test.js +0 -4
  186. package/components/input-amount/test/lion-input-amount.test.js +155 -164
  187. package/components/input-amount/test/parsers.test.js +33 -17
  188. package/components/input-amount/test/preprocessors.test.js +0 -3
  189. package/components/input-amount-dropdown/src/LionInputAmountDropdown.js +49 -59
  190. package/components/input-amount-dropdown/src/currencyUtil.js +8 -7
  191. package/components/input-amount-dropdown/src/parsers.js +0 -1
  192. package/components/input-amount-dropdown/src/validators.js +0 -1
  193. package/components/input-amount-dropdown/test/LionInputAmountDropdown.test.js +34 -36
  194. package/components/input-amount-dropdown/test/lion-input-amount-dropdown-integrations.test.js +18 -13
  195. package/components/input-amount-dropdown/test-helpers/mimicUserChangingDropdown.js +5 -1
  196. package/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.js +132 -107
  197. package/components/input-date/src/LionInputDate.js +4 -3
  198. package/components/input-date/test/lion-input-date-integrations.test.js +0 -3
  199. package/components/input-date/test/lion-input-date.test.js +19 -32
  200. package/components/input-datepicker/src/LionInputDatepicker.js +17 -29
  201. package/components/input-datepicker/src/localizeNamespaceLoader.js +1 -2
  202. package/components/input-datepicker/test/lion-input-datepicker-integrations.test.js +0 -3
  203. package/components/input-datepicker/test/lion-input-datepicker.test.js +88 -153
  204. package/components/input-datepicker/test-helpers/DatepickerInputObject.js +9 -12
  205. package/components/input-datepicker/test-suites/LionInputDatepicker.suite.js +6 -4
  206. package/components/input-datepicker/translations/bg-BG.js +0 -1
  207. package/components/input-datepicker/translations/cs-CZ.js +0 -1
  208. package/components/input-datepicker/translations/de-DE.js +0 -1
  209. package/components/input-datepicker/translations/en-AU.js +0 -1
  210. package/components/input-datepicker/translations/en-GB.js +0 -1
  211. package/components/input-datepicker/translations/en-US.js +0 -1
  212. package/components/input-datepicker/translations/es-ES.js +0 -1
  213. package/components/input-datepicker/translations/fr-BE.js +0 -1
  214. package/components/input-datepicker/translations/fr-FR.js +0 -1
  215. package/components/input-datepicker/translations/hu-HU.js +0 -1
  216. package/components/input-datepicker/translations/it-IT.js +0 -1
  217. package/components/input-datepicker/translations/nl-BE.js +0 -1
  218. package/components/input-datepicker/translations/nl-NL.js +0 -1
  219. package/components/input-datepicker/translations/pl-PL.js +0 -1
  220. package/components/input-datepicker/translations/ro-RO.js +0 -1
  221. package/components/input-datepicker/translations/ru-RU.js +0 -1
  222. package/components/input-datepicker/translations/sk-SK.js +0 -1
  223. package/components/input-datepicker/translations/tr-TR.js +0 -1
  224. package/components/input-datepicker/translations/uk-UA.js +0 -1
  225. package/components/input-email/test/lion-input-email-integrations.test.js +0 -2
  226. package/components/input-email/test/lion-input-email.test.js +1 -7
  227. package/components/input-file/src/FileHandle.js +0 -3
  228. package/components/input-file/src/LionInputFile.js +85 -83
  229. package/components/input-file/src/LionSelectedFileList.js +12 -12
  230. package/components/input-file/src/validators.js +10 -9
  231. package/components/input-file/test/FileValidators.test.js +170 -80
  232. package/components/input-file/test/lion-input-file.test.js +160 -244
  233. package/components/input-file/test/lion-selected-file-list.test.js +13 -22
  234. package/components/input-file/translations/bg-BG.js +0 -1
  235. package/components/input-file/translations/cs-CZ.js +0 -1
  236. package/components/input-file/translations/de-DE.js +0 -1
  237. package/components/input-file/translations/en-AU.js +0 -1
  238. package/components/input-file/translations/en-GB.js +0 -1
  239. package/components/input-file/translations/en-PH.js +0 -1
  240. package/components/input-file/translations/en-US.js +0 -1
  241. package/components/input-file/translations/en.js +2 -1
  242. package/components/input-file/translations/es-ES.js +0 -1
  243. package/components/input-file/translations/fr-BE.js +0 -1
  244. package/components/input-file/translations/fr-FR.js +0 -1
  245. package/components/input-file/translations/hu-HU.js +0 -1
  246. package/components/input-file/translations/id-ID.js +0 -1
  247. package/components/input-file/translations/id.js +2 -1
  248. package/components/input-file/translations/it-IT.js +0 -1
  249. package/components/input-file/translations/nl-BE.js +0 -1
  250. package/components/input-file/translations/nl-NL.js +0 -1
  251. package/components/input-file/translations/pl-PL.js +0 -1
  252. package/components/input-file/translations/ro-RO.js +0 -1
  253. package/components/input-file/translations/ru-RU.js +0 -1
  254. package/components/input-file/translations/sk-SK.js +0 -1
  255. package/components/input-file/translations/uk-UA.js +0 -1
  256. package/components/input-file/translations/zh-CN.js +0 -1
  257. package/components/input-iban/src/validators.js +6 -11
  258. package/components/input-iban/test/formatters.test.js +0 -3
  259. package/components/input-iban/test/lion-input-iban-integrations.test.js +0 -2
  260. package/components/input-iban/test/lion-input-iban.test.js +1 -9
  261. package/components/input-iban/test/parsers.test.js +0 -2
  262. package/components/input-iban/test/validators.test.js +0 -12
  263. package/components/input-iban/translations/bg-BG.js +0 -1
  264. package/components/input-iban/translations/cs-CZ.js +0 -1
  265. package/components/input-iban/translations/de-DE.js +0 -1
  266. package/components/input-iban/translations/en-AU.js +0 -1
  267. package/components/input-iban/translations/en-GB.js +0 -1
  268. package/components/input-iban/translations/en-US.js +0 -1
  269. package/components/input-iban/translations/es-ES.js +0 -1
  270. package/components/input-iban/translations/fr-BE.js +0 -1
  271. package/components/input-iban/translations/fr-FR.js +0 -1
  272. package/components/input-iban/translations/hu-HU.js +0 -1
  273. package/components/input-iban/translations/it-IT.js +0 -1
  274. package/components/input-iban/translations/nl-BE.js +0 -1
  275. package/components/input-iban/translations/nl-NL.js +0 -1
  276. package/components/input-iban/translations/pl-PL.js +0 -1
  277. package/components/input-iban/translations/ro-RO.js +0 -1
  278. package/components/input-iban/translations/ru-RU.js +0 -1
  279. package/components/input-iban/translations/sk-SK.js +0 -1
  280. package/components/input-iban/translations/uk-UA.js +0 -1
  281. package/components/input-range/src/LionInputRange.js +18 -19
  282. package/components/input-range/test/lion-input-range.test.js +23 -48
  283. package/components/input-range/translations/bg-BG.js +0 -1
  284. package/components/input-range/translations/cs-CZ.js +0 -1
  285. package/components/input-range/translations/de-DE.js +0 -1
  286. package/components/input-range/translations/en-AU.js +0 -1
  287. package/components/input-range/translations/en-GB.js +0 -1
  288. package/components/input-range/translations/en-PH.js +0 -1
  289. package/components/input-range/translations/en-US.js +0 -1
  290. package/components/input-range/translations/es-ES.js +0 -1
  291. package/components/input-range/translations/fr-BE.js +0 -1
  292. package/components/input-range/translations/fr-FR.js +0 -1
  293. package/components/input-range/translations/hu-HU.js +0 -1
  294. package/components/input-range/translations/it-IT.js +0 -1
  295. package/components/input-range/translations/nl-BE.js +0 -1
  296. package/components/input-range/translations/nl-NL.js +0 -1
  297. package/components/input-range/translations/pl-PL.js +0 -1
  298. package/components/input-range/translations/ro-RO.js +0 -1
  299. package/components/input-range/translations/ru-RU.js +0 -1
  300. package/components/input-range/translations/sk-SK.js +0 -1
  301. package/components/input-range/translations/uk-UA.js +0 -1
  302. package/components/input-range/translations/zh-CN.js +0 -1
  303. package/components/input-stepper/src/LionInputStepper.js +19 -38
  304. package/components/input-stepper/test/lion-input-stepper-integrations.test.js +0 -1
  305. package/components/input-stepper/test/lion-input-stepper.test.js +0 -1
  306. package/components/input-stepper/test-suites/lion-input-stepper.integration.suite.js +0 -2
  307. package/components/input-stepper/test-suites/lion-input-stepper.suite.js +56 -105
  308. package/components/input-stepper/translations/bg-BG.js +0 -1
  309. package/components/input-stepper/translations/cs-CZ.js +0 -1
  310. package/components/input-stepper/translations/de-DE.js +0 -1
  311. package/components/input-stepper/translations/en-AU.js +0 -1
  312. package/components/input-stepper/translations/en-GB.js +0 -1
  313. package/components/input-stepper/translations/en-US.js +0 -1
  314. package/components/input-stepper/translations/es-ES.js +0 -1
  315. package/components/input-stepper/translations/fr-BE.js +0 -1
  316. package/components/input-stepper/translations/fr-FR.js +0 -1
  317. package/components/input-stepper/translations/hu-HU.js +0 -1
  318. package/components/input-stepper/translations/it-IT.js +0 -1
  319. package/components/input-stepper/translations/nl-BE.js +0 -1
  320. package/components/input-stepper/translations/nl-NL.js +0 -1
  321. package/components/input-stepper/translations/pl-PL.js +0 -1
  322. package/components/input-stepper/translations/ro-RO.js +0 -1
  323. package/components/input-stepper/translations/ru-RU.js +0 -1
  324. package/components/input-stepper/translations/sk-SK.js +0 -1
  325. package/components/input-stepper/translations/uk-UA.js +0 -1
  326. package/components/input-tel/src/LionInputTel.js +53 -37
  327. package/components/input-tel/src/PhoneUtilManager.js +6 -4
  328. package/components/input-tel/src/formatters.js +12 -10
  329. package/components/input-tel/src/parsers.js +3 -3
  330. package/components/input-tel/src/preprocessors.js +15 -7
  331. package/components/input-tel/src/validators.js +4 -6
  332. package/components/input-tel/test/LionInputTel.test.js +4 -2
  333. package/components/input-tel/test/formatters.test.js +22 -10
  334. package/components/input-tel/test/parsers.test.js +40 -11
  335. package/components/input-tel/test/preprocessors.test.js +24 -13
  336. package/components/input-tel/test/validators.test.js +15 -13
  337. package/components/input-tel/test-helpers/mockPhoneUtilManager.js +7 -6
  338. package/components/input-tel/test-suites/LionInputTel.suite.js +33 -73
  339. package/components/input-tel/translations/bg-BG.js +0 -1
  340. package/components/input-tel/translations/cs-CZ.js +0 -1
  341. package/components/input-tel/translations/de-DE.js +0 -1
  342. package/components/input-tel/translations/en-AU.js +0 -1
  343. package/components/input-tel/translations/en-GB.js +0 -1
  344. package/components/input-tel/translations/en-US.js +0 -1
  345. package/components/input-tel/translations/es-ES.js +0 -1
  346. package/components/input-tel/translations/fr-BE.js +0 -1
  347. package/components/input-tel/translations/fr-FR.js +0 -1
  348. package/components/input-tel/translations/hu-HU.js +0 -1
  349. package/components/input-tel/translations/it-IT.js +0 -1
  350. package/components/input-tel/translations/nl-BE.js +0 -1
  351. package/components/input-tel/translations/nl-NL.js +0 -1
  352. package/components/input-tel/translations/pl-PL.js +0 -1
  353. package/components/input-tel/translations/ro-RO.js +0 -1
  354. package/components/input-tel/translations/ru-RU.js +0 -1
  355. package/components/input-tel/translations/sk-SK.js +0 -1
  356. package/components/input-tel/translations/uk-UA.js +0 -1
  357. package/components/input-tel-dropdown/src/LionInputTelDropdown.js +10 -28
  358. package/components/input-tel-dropdown/src/regionCodeToLocale.js +3 -1
  359. package/components/input-tel-dropdown/test/LionInputTelDropdown.test.js +31 -38
  360. package/components/input-tel-dropdown/test/regionCodeToLocale.test.js +0 -1
  361. package/components/input-tel-dropdown/test-helpers/mimicUserChangingDropdown.js +5 -1
  362. package/components/input-tel-dropdown/test-suites/LionInputTelDropdown--parentheses.suite.js +16 -11
  363. package/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js +54 -79
  364. package/components/listbox/src/LionListbox.js +4 -1
  365. package/components/listbox/src/LionOption.js +8 -7
  366. package/components/listbox/src/LionOptions.js +0 -3
  367. package/components/listbox/src/ListboxMixin.js +801 -819
  368. package/components/listbox/test/lion-listbox.test.js +0 -1
  369. package/components/listbox/test/lion-option.test.js +53 -64
  370. package/components/listbox/test/lion-options.test.js +3 -4
  371. package/components/listbox/test-helpers/getListboxMembers.js +6 -3
  372. package/components/listbox/test-suites/ListboxMixin.suite.js +101 -261
  373. package/components/listbox/types/ListboxMixinTypes.ts +7 -1
  374. package/components/localize/src/LocalizeManager.js +40 -40
  375. package/components/localize/src/LocalizeMixin.js +130 -157
  376. package/components/localize/src/date/formatDate.js +1 -5
  377. package/components/localize/src/date/getDateFormatBasedOnLocale.js +5 -3
  378. package/components/localize/src/date/getMonthNames.js +3 -5
  379. package/components/localize/src/date/getWeekdayNames.js +1 -5
  380. package/components/localize/src/date/parseDate.js +5 -20
  381. package/components/localize/src/date/utils/normalizeIntlDate.js +0 -7
  382. package/components/localize/src/getLocalizeManager.js +0 -3
  383. package/components/localize/src/number/formatNumber.js +3 -7
  384. package/components/localize/src/number/formatNumberToParts.js +52 -18
  385. package/components/localize/src/number/getCurrencyName.js +5 -5
  386. package/components/localize/src/number/getFractionDigits.js +4 -4
  387. package/components/localize/src/number/getSeparatorsFromNumber.js +1 -3
  388. package/components/localize/src/number/parseNumber.js +0 -3
  389. package/components/localize/src/number/utils/normalize-format-number-to-parts/forceAddGroupSeparators.js +0 -1
  390. package/components/localize/src/number/utils/normalize-format-number-to-parts/forceSpaceBetweenCurrencyCodeAndNumber.js +4 -1
  391. package/components/localize/test/LocalizeManager.test.js +385 -278
  392. package/components/localize/test/LocalizeMixin.test.js +28 -112
  393. package/components/localize/test/date/formatDate.test.js +18 -48
  394. package/components/localize/test/date/getDateFormatBasedOnLocale.test.js +0 -3
  395. package/components/localize/test/date/getMonthNames.test.js +27 -12
  396. package/components/localize/test/date/getWeekdayNames.test.js +93 -49
  397. package/components/localize/test/date/normalizeDateTime.test.js +0 -2
  398. package/components/localize/test/date/parseDate.test.js +12 -16
  399. package/components/localize/test/getLocalizeManager.test.js +0 -3
  400. package/components/localize/test/isLocalizeESModule.test.js +32 -13
  401. package/components/localize/test/localize.test.js +0 -4
  402. package/components/localize/test/number/formatNumber.test.js +215 -106
  403. package/components/localize/test/number/formatNumberToParts.test.js +31 -38
  404. package/components/localize/test/number/getCurrencyName.test.js +20 -6
  405. package/components/localize/test/number/getDecimalSeparator.test.js +5 -4
  406. package/components/localize/test/number/getFractionDigits.test.js +0 -2
  407. package/components/localize/test/number/getGroupSeparator.test.js +0 -2
  408. package/components/localize/test/number/getSeparatorsFromNumber.test.js +5 -3
  409. package/components/localize/test/number/parseNumber.test.js +123 -56
  410. package/components/localize/test/side-effect-free-entrypoint.test.js +0 -6
  411. package/components/localize/test-helpers/fake-imports.js +11 -6
  412. package/components/localize/test-helpers/localizeTearDown.js +0 -1
  413. package/components/menu/README.md +360 -0
  414. package/components/menu/src/InteractiveListMixin.js +866 -0
  415. package/components/menu/src/LionMenu.js +423 -0
  416. package/components/menu/src/MoreButtonMenuMixin.js +272 -0
  417. package/components/menu/src/MultiLevelListMixin.js +306 -0
  418. package/components/menu/src/utils/isInView.js +25 -0
  419. package/components/menu/src/utils/listItemInteractions.js +124 -0
  420. package/components/menu/test/InteractiveListMixin.test.js +2 -0
  421. package/components/menu/test/MoreButtonMenuMixin.test.js +5 -0
  422. package/components/menu/test/MultiLevelListMixin.test.js +2 -0
  423. package/components/menu/test/lion-menu-interactions.test.js +2 -0
  424. package/components/menu/test/lion-menu.test.js +18 -0
  425. package/components/menu/test-helpers/mimicKeyPress.js +19 -0
  426. package/components/menu/test-suites/InteractiveListMixin.suite.js +498 -0
  427. package/components/menu/test-suites/LionMenu.suite.js +107 -0
  428. package/components/menu/test-suites/LionMenuInteractions.suite.js +561 -0
  429. package/components/menu/test-suites/MoreButtonMenuMixin.suite.js +365 -0
  430. package/components/menu/test-suites/MultiLevelListMixin.suite.js +291 -0
  431. package/components/menu/types/InteractiveListMixinTypes.ts +126 -0
  432. package/components/menu/types/MoreButtonMenuMixinTypes.ts +51 -0
  433. package/components/menu/types/MultiLevelListMixinTypes.ts +28 -0
  434. package/components/menu/types/OverlayWithListInvokerMixinTypes.ts +61 -0
  435. package/components/overlays/NEXT.md +49 -0
  436. package/components/overlays/src/ArrowMixin.js +111 -127
  437. package/components/overlays/src/OverlayController.js +440 -246
  438. package/components/overlays/src/OverlayMixin.js +130 -68
  439. package/components/overlays/src/OverlaysManager.js +30 -32
  440. package/components/overlays/src/configurations/visibility-trigger-partials/withClickInteraction.js +0 -1
  441. package/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.js +11 -11
  442. package/components/overlays/src/configurations/withBottomSheetConfig.js +12 -13
  443. package/components/overlays/src/configurations/withDropdownConfig.js +4 -2
  444. package/components/overlays/src/configurations/withModalDialogConfig.js +12 -13
  445. package/components/overlays/src/configurations/withPopoverConfig.js +27 -25
  446. package/components/overlays/src/configurations/withTooltipConfig.js +15 -13
  447. package/components/overlays/src/overlayDocumentStyle.js +1 -1
  448. package/components/overlays/src/overlayShadowDomStyle.js +0 -1
  449. package/components/overlays/src/singleton.js +0 -2
  450. package/components/overlays/src/utils/adopt-styles.js +19 -19
  451. package/components/overlays/src/utils/deep-contains.js +7 -6
  452. package/components/overlays/src/utils/get-focusable-elements.js +7 -10
  453. package/components/overlays/src/utils/inert-siblings.js +2 -4
  454. package/components/overlays/src/utils/is-equal-config.js +14 -6
  455. package/components/overlays/src/utils/is-visible.js +0 -1
  456. package/components/overlays/src/utils/simulate-tab.js +1 -4
  457. package/components/overlays/src/utils/sort-by-tabindex.js +2 -4
  458. package/components/overlays/test/ArrowMixin.test.js +18 -30
  459. package/components/overlays/test/OverlayController.test.js +551 -533
  460. package/components/overlays/test/OverlayMixin.test.js +0 -2
  461. package/components/overlays/test/OverlaysManager.test.js +30 -35
  462. package/components/overlays/test/global-positioning.test.js +6 -10
  463. package/components/overlays/test/local-positioning.test.js +101 -103
  464. package/components/overlays/test/utils-tests/active-element.test.js +12 -27
  465. package/components/overlays/test/utils-tests/adopt-styles.test.js +25 -56
  466. package/components/overlays/test/utils-tests/deep-contains.test.js +73 -74
  467. package/components/overlays/test/utils-tests/get-focusable-elements.test.js +6 -23
  468. package/components/overlays/test/utils-tests/is-equal-config.test.js +32 -13
  469. package/components/overlays/test/utils-tests/visibility.test.js +44 -79
  470. package/components/overlays/test-helpers/createShadowHost.js +5 -3
  471. package/components/overlays/test-helpers/normalizeTransformStyle.js +2 -4
  472. package/components/overlays/test-suites/OverlayMixin.suite.js +159 -188
  473. package/components/overlays/test-suites/WithHoverInteraction.suite.js +96 -79
  474. package/components/overlays/translations/bg-BG.js +0 -1
  475. package/components/overlays/translations/cs-CZ.js +0 -1
  476. package/components/overlays/translations/de-DE.js +0 -1
  477. package/components/overlays/translations/en-AU.js +0 -1
  478. package/components/overlays/translations/en-GB.js +0 -1
  479. package/components/overlays/translations/en-US.js +0 -1
  480. package/components/overlays/translations/es-ES.js +0 -1
  481. package/components/overlays/translations/fr-BE.js +0 -1
  482. package/components/overlays/translations/fr-FR.js +0 -1
  483. package/components/overlays/translations/hu-HU.js +0 -1
  484. package/components/overlays/translations/it-IT.js +0 -1
  485. package/components/overlays/translations/nl-BE.js +0 -1
  486. package/components/overlays/translations/nl-NL.js +0 -1
  487. package/components/overlays/translations/pl-PL.js +0 -1
  488. package/components/overlays/translations/ro-RO.js +0 -1
  489. package/components/overlays/translations/ru-RU.js +0 -1
  490. package/components/overlays/translations/sk-SK.js +0 -1
  491. package/components/overlays/translations/tr-TR.js +0 -1
  492. package/components/overlays/translations/uk-UA.js +0 -1
  493. package/components/overlays/types/ArrowMixinTypes.ts +1 -3
  494. package/components/overlays/types/OverlayConfig.ts +20 -5
  495. package/components/overlays/types/OverlayMixinTypes.ts +2 -0
  496. package/components/pagination/src/LionPagination.js +9 -12
  497. package/components/pagination/test/lion-pagination.test.js +18 -50
  498. package/components/progress-indicator/src/LionProgressIndicator.js +10 -12
  499. package/components/progress-indicator/test/lion-progress-indicator.test.js +1 -22
  500. package/components/radio-group/src/LionRadioGroup.js +1 -2
  501. package/components/radio-group/test/lion-radio-group-integrations.test.js +0 -1
  502. package/components/radio-group/test/lion-radio-group.test.js +27 -27
  503. package/components/radio-group/test/lion-radio-integrations.test.js +3 -2
  504. package/components/radio-group/test/lion-radio.test.js +30 -16
  505. package/components/select/src/LionSelect.js +12 -13
  506. package/components/select/test/lion-select.test.js +7 -12
  507. package/components/select-rich/src/LionSelectInvoker.js +18 -11
  508. package/components/select-rich/src/LionSelectRich.js +32 -43
  509. package/components/select-rich/test/demos.screenshots-test.js +40 -9
  510. package/components/select-rich/test/lion-select-invoker.test.js +26 -43
  511. package/components/select-rich/test/lion-select-listbox-suite-integration.test.js +3 -3
  512. package/components/select-rich/test/lion-select-rich-dialog-integration.test.js +4 -9
  513. package/components/select-rich/test/lion-select-rich-interaction.test.js +154 -101
  514. package/components/select-rich/test/lion-select-rich-upgrade.test.js +26 -0
  515. package/components/select-rich/test/lion-select-rich.test.js +153 -195
  516. package/components/select-rich/test-helpers/getSelectRichMembers.js +4 -1
  517. package/components/steps/src/LionStep.js +21 -12
  518. package/components/steps/src/LionSteps.js +25 -25
  519. package/components/steps/test/lion-step.test.js +18 -25
  520. package/components/steps/test/lion-steps.test.js +45 -78
  521. package/components/switch/src/LionSwitch.js +2 -7
  522. package/components/switch/src/LionSwitchButton.js +5 -6
  523. package/components/switch/test/lion-switch-button.test.js +16 -28
  524. package/components/switch/test/lion-switch.test.js +17 -31
  525. package/components/tabs/src/LionTabs.js +25 -28
  526. package/components/tabs/test/lion-tabs.test.js +156 -154
  527. package/components/textarea/src/LionTextarea.js +4 -23
  528. package/components/textarea/test/lion-textarea-integrations.test.js +0 -5
  529. package/components/textarea/test/lion-textarea.test.js +2 -28
  530. package/components/tooltip/src/LionTooltip.js +6 -6
  531. package/components/tooltip/test/lion-tooltip.test.js +75 -102
  532. package/components/validate-messages/src/getLocalizedMessage.js +8 -7
  533. package/components/validate-messages/src/loadDefaultFeedbackMessages.js +3 -1
  534. package/components/validate-messages/src/loadDefaultFeedbackMessagesNoSideEffects.js +9 -5
  535. package/components/validate-messages/src/per-entrypoint/loadComboboxMessagesNoSideEffects.js +5 -2
  536. package/components/validate-messages/src/per-entrypoint/loadFormCoreMessagesNoSideEffects.js +99 -35
  537. package/components/validate-messages/src/per-entrypoint/loadInputTelMessagesNoSideEffects.js +4 -3
  538. package/components/validate-messages/test/loadDefaultFeedbackMessages.test.js +5 -3
  539. package/components/validate-messages/test/loadDefaultFeedbackMessagesNoSideEffects.test.js +80 -45
  540. package/components/validate-messages/translations/bg-BG.js +0 -1
  541. package/components/validate-messages/translations/cs-CZ.js +0 -1
  542. package/components/validate-messages/translations/de-DE.js +0 -1
  543. package/components/validate-messages/translations/en-AU.js +0 -1
  544. package/components/validate-messages/translations/en-GB.js +0 -1
  545. package/components/validate-messages/translations/en-PH.js +0 -1
  546. package/components/validate-messages/translations/en-US.js +0 -1
  547. package/components/validate-messages/translations/es-ES.js +0 -1
  548. package/components/validate-messages/translations/fr-BE.js +0 -1
  549. package/components/validate-messages/translations/fr-FR.js +0 -1
  550. package/components/validate-messages/translations/hu-HU.js +0 -1
  551. package/components/validate-messages/translations/it-IT.js +0 -1
  552. package/components/validate-messages/translations/nl-BE.js +0 -1
  553. package/components/validate-messages/translations/nl-NL.js +0 -1
  554. package/components/validate-messages/translations/pl-PL.js +0 -1
  555. package/components/validate-messages/translations/ro-RO.js +0 -1
  556. package/components/validate-messages/translations/ru-RU.js +0 -1
  557. package/components/validate-messages/translations/sk-SK.js +0 -1
  558. package/components/validate-messages/translations/tr-TR.js +0 -1
  559. package/components/validate-messages/translations/uk-UA.js +0 -1
  560. package/custom-elements.json +3312 -206
  561. package/dist-types/components/combobox/src/LionCombobox.d.ts +1 -1
  562. package/dist-types/components/combobox/src/LionCombobox.d.ts.map +1 -1
  563. package/dist-types/components/core/src/SlotMixin.d.ts +6 -1
  564. package/dist-types/components/core/src/SlotMixin.d.ts.map +1 -1
  565. package/dist-types/components/core/types/SlotMixinTypes.d.ts +5 -1
  566. package/dist-types/components/core/types/SlotMixinTypes.d.ts.map +1 -1
  567. package/dist-types/components/dialog/src/LionDialog.d.ts +6 -2
  568. package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
  569. package/dist-types/components/form-core/src/LionField.d.ts +3 -1
  570. package/dist-types/components/form-core/src/LionField.d.ts.map +1 -1
  571. package/dist-types/components/form-core/src/choice-group/ChoiceGroupMixin.d.ts.map +1 -1
  572. package/dist-types/components/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts +5 -0
  573. package/dist-types/components/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts.map +1 -1
  574. package/dist-types/components/input-amount/src/LionInputAmount.d.ts +3 -1
  575. package/dist-types/components/input-amount/src/LionInputAmount.d.ts.map +1 -1
  576. package/dist-types/components/input-amount/src/formatters.d.ts +6 -4
  577. package/dist-types/components/input-amount/src/formatters.d.ts.map +1 -1
  578. package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +1 -1
  579. package/dist-types/components/input-tel/src/LionInputTel.d.ts +6 -6
  580. package/dist-types/components/input-tel/src/LionInputTel.d.ts.map +1 -1
  581. package/dist-types/components/input-tel/src/PhoneUtilManager.d.ts +2 -2
  582. package/dist-types/components/input-tel/src/PhoneUtilManager.d.ts.map +1 -1
  583. package/dist-types/components/input-tel/src/formatters.d.ts +2 -2
  584. package/dist-types/components/input-tel/src/formatters.d.ts.map +1 -1
  585. package/dist-types/components/input-tel/src/preprocessors.d.ts +2 -2
  586. package/dist-types/components/input-tel/src/preprocessors.d.ts.map +1 -1
  587. package/dist-types/components/input-tel/test/validators.test.d.ts +1 -1
  588. package/dist-types/components/input-tel/test/validators.test.d.ts.map +1 -1
  589. package/dist-types/components/listbox/src/LionOption.d.ts +5 -2
  590. package/dist-types/components/listbox/src/LionOption.d.ts.map +1 -1
  591. package/dist-types/components/listbox/src/ListboxMixin.d.ts.map +1 -1
  592. package/dist-types/components/listbox/types/ListboxMixinTypes.d.ts +7 -1
  593. package/dist-types/components/listbox/types/ListboxMixinTypes.d.ts.map +1 -1
  594. package/dist-types/components/menu/src/InteractiveListMixin.d.ts +35 -0
  595. package/dist-types/components/menu/src/InteractiveListMixin.d.ts.map +1 -0
  596. package/dist-types/components/menu/src/LionMenu.d.ts +129 -0
  597. package/dist-types/components/menu/src/LionMenu.d.ts.map +1 -0
  598. package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts +8 -0
  599. package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts.map +1 -0
  600. package/dist-types/components/menu/src/MultiLevelListMixin.d.ts +7 -0
  601. package/dist-types/components/menu/src/MultiLevelListMixin.d.ts.map +1 -0
  602. package/dist-types/components/menu/src/utils/isInView.d.ts +9 -0
  603. package/dist-types/components/menu/src/utils/isInView.d.ts.map +1 -0
  604. package/dist-types/components/menu/src/utils/listItemInteractions.d.ts +48 -0
  605. package/dist-types/components/menu/src/utils/listItemInteractions.d.ts.map +1 -0
  606. package/dist-types/components/menu/test/InteractiveListMixin.test.d.ts +2 -0
  607. package/dist-types/components/menu/test/InteractiveListMixin.test.d.ts.map +1 -0
  608. package/dist-types/components/menu/test/MoreButtonMenuMixin.test.d.ts +2 -0
  609. package/dist-types/components/menu/test/MoreButtonMenuMixin.test.d.ts.map +1 -0
  610. package/dist-types/components/menu/test/MultiLevelListMixin.test.d.ts +2 -0
  611. package/dist-types/components/menu/test/MultiLevelListMixin.test.d.ts.map +1 -0
  612. package/dist-types/components/menu/test/lion-menu-interactions.test.d.ts +2 -0
  613. package/dist-types/components/menu/test/lion-menu-interactions.test.d.ts.map +1 -0
  614. package/dist-types/components/menu/test/lion-menu.test.d.ts +2 -0
  615. package/dist-types/components/menu/test/lion-menu.test.d.ts.map +1 -0
  616. package/dist-types/components/menu/test-helpers/mimicKeyPress.d.ts +7 -0
  617. package/dist-types/components/menu/test-helpers/mimicKeyPress.d.ts.map +1 -0
  618. package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts +11 -0
  619. package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts.map +1 -0
  620. package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts +9 -0
  621. package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts.map +1 -0
  622. package/dist-types/components/menu/test-suites/LionMenuInteractions.suite.d.ts +5 -0
  623. package/dist-types/components/menu/test-suites/LionMenuInteractions.suite.d.ts.map +1 -0
  624. package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts +11 -0
  625. package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts.map +1 -0
  626. package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts +11 -0
  627. package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts.map +1 -0
  628. package/dist-types/components/menu/types/InteractiveListMixinTypes.d.ts +72 -0
  629. package/dist-types/components/menu/types/InteractiveListMixinTypes.d.ts.map +1 -0
  630. package/dist-types/components/menu/types/MoreButtonMenuMixinTypes.d.ts +30 -0
  631. package/dist-types/components/menu/types/MoreButtonMenuMixinTypes.d.ts.map +1 -0
  632. package/dist-types/components/menu/types/MultiLevelListMixinTypes.d.ts +16 -0
  633. package/dist-types/components/menu/types/MultiLevelListMixinTypes.d.ts.map +1 -0
  634. package/dist-types/components/menu/types/OverlayWithListInvokerMixinTypes.d.ts +35 -0
  635. package/dist-types/components/menu/types/OverlayWithListInvokerMixinTypes.d.ts.map +1 -0
  636. package/dist-types/components/overlays/src/OverlayController.d.ts +22 -5
  637. package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
  638. package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
  639. package/dist-types/components/overlays/src/OverlaysManager.d.ts.map +1 -1
  640. package/dist-types/components/overlays/src/overlayDocumentStyle.d.ts.map +1 -1
  641. package/dist-types/components/overlays/src/utils/is-equal-config.d.ts.map +1 -1
  642. package/dist-types/components/overlays/types/ArrowMixinTypes.d.ts.map +1 -1
  643. package/dist-types/components/overlays/types/OverlayConfig.d.ts +12 -2
  644. package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
  645. package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts +1 -0
  646. package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts.map +1 -1
  647. package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts +3 -1
  648. package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts.map +1 -1
  649. package/dist-types/components/select-rich/src/LionSelectRich.d.ts +13 -2
  650. package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
  651. package/dist-types/components/select-rich/test/lion-select-rich-interaction.test.d.ts.map +1 -1
  652. package/dist-types/components/select-rich/test/lion-select-rich-upgrade.test.d.ts +2 -0
  653. package/dist-types/components/select-rich/test/lion-select-rich-upgrade.test.d.ts.map +1 -0
  654. package/dist-types/components/tooltip/src/LionTooltip.d.ts +1 -1
  655. package/dist-types/exports/define/lion-item.d.ts +2 -0
  656. package/dist-types/exports/define/lion-item.d.ts.map +1 -0
  657. package/dist-types/exports/define/lion-menu.d.ts +2 -0
  658. package/dist-types/exports/define/lion-menu.d.ts.map +1 -0
  659. package/dist-types/exports/define/lion-menuitem.d.ts +2 -0
  660. package/dist-types/exports/define/lion-menuitem.d.ts.map +1 -0
  661. package/dist-types/exports/menu-test-suites.d.ts +4 -0
  662. package/dist-types/exports/menu-test-suites.d.ts.map +1 -0
  663. package/dist-types/exports/menu.d.ts +3 -0
  664. package/dist-types/exports/menu.d.ts.map +1 -0
  665. package/dist-types/exports/overlays.d.ts +6 -0
  666. package/dist-types/exports/overlays.d.ts.map +1 -1
  667. package/dist-types/tsconfig.tsbuildinfo +1 -1
  668. package/docs/components/accordion/overview.md +2 -2
  669. package/docs/components/accordion/reference.md +2 -2
  670. package/docs/components/accordion/use-cases.md +2 -2
  671. package/docs/components/button/examples.md +2 -2
  672. package/docs/components/button/extensions.md +2 -2
  673. package/docs/components/button/overview.md +2 -2
  674. package/docs/components/button/use-cases.md +2 -2
  675. package/docs/components/calendar/overview.md +2 -2
  676. package/docs/components/calendar/use-cases.md +2 -2
  677. package/docs/components/checkbox-group/overview.md +4 -4
  678. package/docs/components/checkbox-group/use-cases.md +2 -2
  679. package/docs/components/collapsible/examples.md +2 -2
  680. package/docs/components/collapsible/overview.md +3 -3
  681. package/docs/components/collapsible/use-cases.md +2 -2
  682. package/docs/components/combobox/api-table.md +53 -39
  683. package/docs/components/combobox/extensions.md +2 -2
  684. package/docs/components/combobox/overview.md +3 -3
  685. package/docs/components/combobox/use-cases.md +3 -3
  686. package/docs/components/dialog/api-table.md +32 -6
  687. package/docs/components/dialog/overview.md +3 -3
  688. package/docs/components/dialog/use-cases.md +2 -2
  689. package/docs/components/drawer/overview.md +2 -2
  690. package/docs/components/drawer/use-cases.md +2 -2
  691. package/docs/components/fieldset/overview.md +7 -7
  692. package/docs/components/fieldset/use-cases.md +2 -2
  693. package/docs/components/form/overview.md +5 -5
  694. package/docs/components/form/use-cases.md +4 -4
  695. package/docs/components/icon/overview.md +2 -2
  696. package/docs/components/icon/use-cases.md +3 -3
  697. package/docs/components/input/overview.md +3 -3
  698. package/docs/components/input/use-cases.md +2 -2
  699. package/docs/components/input-amount/api-table.md +9 -7
  700. package/docs/components/input-amount/overview.md +5 -5
  701. package/docs/components/input-amount/use-cases.md +17 -6
  702. package/docs/components/input-amount-dropdown/api-table.md +2 -0
  703. package/docs/components/input-amount-dropdown/use-cases.md +2 -2
  704. package/docs/components/input-date/overview.md +5 -5
  705. package/docs/components/input-date/use-cases.md +2 -2
  706. package/docs/components/input-datepicker/api-table.md +63 -45
  707. package/docs/components/input-datepicker/overview.md +7 -7
  708. package/docs/components/input-datepicker/use-cases.md +2 -2
  709. package/docs/components/input-email/overview.md +4 -4
  710. package/docs/components/input-email/use-cases.md +2 -2
  711. package/docs/components/input-file/overview.md +3 -3
  712. package/docs/components/input-file/use-cases.md +2 -2
  713. package/docs/components/input-iban/overview.md +4 -4
  714. package/docs/components/input-iban/use-cases.md +2 -2
  715. package/docs/components/input-range/overview.md +4 -4
  716. package/docs/components/input-range/use-cases.md +2 -2
  717. package/docs/components/input-stepper/overview.md +3 -3
  718. package/docs/components/input-stepper/use-cases.md +2 -2
  719. package/docs/components/input-tel/overview.md +3 -3
  720. package/docs/components/input-tel/use-cases.md +8 -8
  721. package/docs/components/input-tel-dropdown/extensions.md +2 -2
  722. package/docs/components/input-tel-dropdown/overview.md +3 -3
  723. package/docs/components/input-tel-dropdown/use-cases.md +2 -2
  724. package/docs/components/listbox/overview.md +2 -2
  725. package/docs/components/listbox/use-cases.md +3 -3
  726. package/docs/components/menu/api-table.md +44 -0
  727. package/docs/components/menu/applyMenuDemoStyles.js +173 -0
  728. package/docs/components/menu/extensions.md +262 -0
  729. package/docs/components/menu/index.md +13 -0
  730. package/docs/components/menu/migration.md +129 -0
  731. package/docs/components/menu/overview.md +448 -0
  732. package/docs/components/menu/src/DemoNavigationBar.js +441 -0
  733. package/docs/components/menu/src/DemoSpinButton.js +215 -0
  734. package/docs/components/menu/src/DemoToolbar.js +101 -0
  735. package/docs/components/menu/src/DemoTree.js +55 -0
  736. package/docs/components/menu/src/navigation-bar-types.js +41 -0
  737. package/docs/components/menu/use-cases.md +74 -0
  738. package/docs/components/pagination/overview.md +2 -2
  739. package/docs/components/pagination/use-cases.md +2 -2
  740. package/docs/components/progress-indicator/examples.md +2 -2
  741. package/docs/components/progress-indicator/overview.md +2 -2
  742. package/docs/components/radio-group/overview.md +5 -5
  743. package/docs/components/radio-group/use-cases.md +2 -2
  744. package/docs/components/select/overview.md +2 -2
  745. package/docs/components/select/use-cases.md +3 -3
  746. package/docs/components/select-rich/api-table.md +51 -33
  747. package/docs/components/select-rich/examples.md +2 -2
  748. package/docs/components/select-rich/overview.md +2 -2
  749. package/docs/components/select-rich/use-cases.md +4 -4
  750. package/docs/components/steps/overview.md +2 -2
  751. package/docs/components/steps/use-cases.md +2 -2
  752. package/docs/components/switch/overview.md +2 -2
  753. package/docs/components/switch/reference.md +2 -2
  754. package/docs/components/switch/use-cases.md +2 -2
  755. package/docs/components/tabs/examples.md +3 -3
  756. package/docs/components/tabs/overview.md +2 -2
  757. package/docs/components/tabs/use-cases.md +2 -2
  758. package/docs/components/textarea/overview.md +2 -2
  759. package/docs/components/textarea/use-cases.md +2 -2
  760. package/docs/components/tooltip/api-table.md +33 -7
  761. package/docs/components/tooltip/examples.md +2 -2
  762. package/docs/components/tooltip/overview.md +2 -2
  763. package/docs/components/tooltip/use-cases.md +2 -2
  764. package/docs/fundamentals/index.md +4 -4
  765. package/docs/fundamentals/node-tools/babel-plugin-extend-docs/index.md +2 -2
  766. package/docs/fundamentals/node-tools/babel-plugin-extend-docs/overview.md +2 -2
  767. package/docs/fundamentals/node-tools/providence-analytics/index.md +2 -2
  768. package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
  769. package/docs/fundamentals/node-tools/publish-docs/index.md +2 -2
  770. package/docs/fundamentals/node-tools/publish-docs/overview.md +5 -5
  771. package/docs/fundamentals/node-tools/remark-extend/index.md +2 -2
  772. package/docs/fundamentals/node-tools/remark-extend/overview.md +2 -2
  773. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/index.md +2 -2
  774. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +4 -4
  775. package/docs/fundamentals/rationales/TypeScript.md +62 -2
  776. package/docs/fundamentals/rationales/accessibility.md +5 -5
  777. package/docs/fundamentals/rationales/side-effects.md +2 -2
  778. package/docs/fundamentals/rationales/versioning.md +2 -2
  779. package/docs/fundamentals/systems/core/SlotMixin.md +3 -3
  780. package/docs/fundamentals/systems/core/index.md +2 -2
  781. package/docs/fundamentals/systems/core/overview.md +3 -3
  782. package/docs/fundamentals/systems/form/formatting-and-parsing.md +6 -6
  783. package/docs/fundamentals/systems/form/index.md +2 -2
  784. package/docs/fundamentals/systems/form/interaction-states.md +2 -2
  785. package/docs/fundamentals/systems/form/model-value.md +3 -3
  786. package/docs/fundamentals/systems/form/overview.md +30 -30
  787. package/docs/fundamentals/systems/form/styling.md +2 -2
  788. package/docs/fundamentals/systems/form/use-cases.md +2 -2
  789. package/docs/fundamentals/systems/form/validate.md +4 -4
  790. package/docs/fundamentals/systems/icon/index.md +2 -2
  791. package/docs/fundamentals/systems/icon/overview.md +2 -2
  792. package/docs/fundamentals/systems/localize/dates.md +2 -2
  793. package/docs/fundamentals/systems/localize/index.md +2 -2
  794. package/docs/fundamentals/systems/localize/numbers.md +2 -2
  795. package/docs/fundamentals/systems/localize/overview.md +6 -6
  796. package/docs/fundamentals/systems/localize/rationale.md +2 -2
  797. package/docs/fundamentals/systems/localize/text.md +2 -2
  798. package/docs/fundamentals/systems/localize/use-cases.md +2 -2
  799. package/docs/fundamentals/systems/overlays/_edge-cases.md +2 -2
  800. package/docs/fundamentals/systems/overlays/api-table.md +46 -43
  801. package/docs/fundamentals/systems/overlays/configuration.md +4 -4
  802. package/docs/fundamentals/systems/overlays/index.md +2 -2
  803. package/docs/fundamentals/systems/overlays/overview.md +7 -7
  804. package/docs/fundamentals/systems/overlays/rationale.md +2 -2
  805. package/docs/fundamentals/systems/overlays/use-cases.md +4 -4
  806. package/docs/fundamentals/tools/ajax/index.md +2 -2
  807. package/docs/fundamentals/tools/ajax/overview.md +2 -2
  808. package/docs/fundamentals/tools/ajax/use-cases.md +2 -2
  809. package/docs/fundamentals/tools/helpers/action-logger.md +2 -2
  810. package/docs/fundamentals/tools/helpers/index.md +2 -2
  811. package/docs/fundamentals/tools/helpers/overview.md +3 -3
  812. package/docs/fundamentals/tools/singleton-manager/example-complex/index.md +2 -2
  813. package/docs/fundamentals/tools/singleton-manager/example-fail/index.md +2 -2
  814. package/docs/fundamentals/tools/singleton-manager/example-success/index.md +2 -2
  815. package/docs/fundamentals/tools/singleton-manager/index.md +2 -2
  816. package/docs/fundamentals/tools/singleton-manager/overview.md +6 -6
  817. package/docs/guides/how-to/create-a-custom-field.md +7 -7
  818. package/docs/guides/how-to/create-a-form.md +6 -6
  819. package/docs/guides/how-to/extend-a-native-input.md +4 -4
  820. package/docs/guides/how-to/get-started.md +2 -2
  821. package/docs/guides/how-to/index.md +1 -1
  822. package/docs/guides/index.md +8 -8
  823. package/docs/guides/principles/definitions-and-terms.md +2 -2
  824. package/docs/guides/principles/index.md +5 -5
  825. package/docs/guides/principles/scoped-elements.md +2 -2
  826. package/docs/guides/principles/styling.md +3 -3
  827. package/docs/guides/principles/subclasser-apis.md +2 -2
  828. package/exports/define/lion-accordion.js +0 -1
  829. package/exports/define/lion-button-reset.js +0 -1
  830. package/exports/define/lion-button-submit.js +0 -1
  831. package/exports/define/lion-button.js +0 -1
  832. package/exports/define/lion-calendar.js +0 -1
  833. package/exports/define/lion-checkbox-group.js +0 -1
  834. package/exports/define/lion-checkbox-indeterminate.js +0 -1
  835. package/exports/define/lion-checkbox.js +0 -1
  836. package/exports/define/lion-collapsible.js +0 -1
  837. package/exports/define/lion-combobox.js +0 -1
  838. package/exports/define/lion-dialog.js +0 -1
  839. package/exports/define/lion-drawer.js +0 -1
  840. package/exports/define/lion-field.js +0 -1
  841. package/exports/define/lion-fieldset.js +0 -1
  842. package/exports/define/lion-form.js +0 -1
  843. package/exports/define/lion-icon.js +0 -1
  844. package/exports/define/lion-input-amount-dropdown.js +0 -1
  845. package/exports/define/lion-input-amount.js +0 -1
  846. package/exports/define/lion-input-date.js +0 -1
  847. package/exports/define/lion-input-datepicker.js +0 -1
  848. package/exports/define/lion-input-email.js +0 -1
  849. package/exports/define/lion-input-file.js +0 -1
  850. package/exports/define/lion-input-iban.js +0 -1
  851. package/exports/define/lion-input-range.js +0 -1
  852. package/exports/define/lion-input-stepper.js +0 -1
  853. package/exports/define/lion-input-tel-dropdown.js +0 -1
  854. package/exports/define/lion-input-tel.js +0 -1
  855. package/exports/define/lion-input.js +0 -1
  856. package/exports/define/lion-item.js +2 -0
  857. package/exports/define/lion-listbox.js +0 -1
  858. package/exports/define/lion-menu.js +2 -0
  859. package/exports/define/lion-menuitem.js +2 -0
  860. package/exports/define/lion-option.js +0 -1
  861. package/exports/define/lion-options.js +0 -1
  862. package/exports/define/lion-pagination.js +0 -1
  863. package/exports/define/lion-progress-indicator.js +0 -1
  864. package/exports/define/lion-radio-group.js +0 -1
  865. package/exports/define/lion-radio.js +0 -1
  866. package/exports/define/lion-select-invoker.js +0 -1
  867. package/exports/define/lion-select-rich.js +0 -1
  868. package/exports/define/lion-select.js +0 -1
  869. package/exports/define/lion-selected-file-list.js +0 -1
  870. package/exports/define/lion-step.js +0 -1
  871. package/exports/define/lion-steps.js +0 -1
  872. package/exports/define/lion-switch-button.js +0 -1
  873. package/exports/define/lion-switch.js +0 -1
  874. package/exports/define/lion-tabs.js +0 -1
  875. package/exports/define/lion-textarea.js +0 -1
  876. package/exports/define/lion-tooltip.js +0 -1
  877. package/exports/define/lion-validation-feedback.js +0 -1
  878. package/exports/define-helpers/sb-action-logger.js +0 -1
  879. package/exports/define-helpers/sb-locale-switcher.js +0 -1
  880. package/exports/form-core.js +0 -8
  881. package/exports/localize-no-side-effects.js +0 -1
  882. package/exports/localize.js +0 -2
  883. package/exports/menu-test-suites.js +4 -0
  884. package/exports/menu.js +3 -0
  885. package/exports/overlays.js +6 -4
  886. package/generated/awesome-phonenumber/LICENSE +22 -0
  887. package/generated/awesome-phonenumber/LICENSE.closure-library +176 -0
  888. package/generated/awesome-phonenumber/LICENSE.libphonenumber +176 -0
  889. package/generated/awesome-phonenumber/checksums.json +6 -0
  890. package/generated/awesome-phonenumber/index-esm.mjs +817 -0
  891. package/generated/awesome-phonenumber/index.d.ts +227 -0
  892. package/generated/awesome-phonenumber/index.js +45 -0
  893. package/generated/awesome-phonenumber/lib/index.js +710 -0
  894. package/generated/awesome-phonenumber/package.json +9 -0
  895. package/generated/awesome-phonenumber/provenance.json +13 -0
  896. package/menu-test-suites.js +4 -0
  897. package/menu.js +3 -0
  898. package/overlays.js +6 -0
  899. package/package.json +35 -6
  900. package/vscode.html-custom-data.json +76 -8
  901. package/web-types.json +202 -17
@@ -6,9 +6,21 @@ import { ScopedElementsMixin } from '../../core/src/ScopedElementsMixin.js';
6
6
  import { LionOptions } from './LionOptions.js';
7
7
  import { moveUserProvidedDefaultSlottablesToTarget } from '../../core/src/SlotMixin.js';
8
8
 
9
- // TODO: extract ListNavigationWithActiveDescendantMixin that can be reused in [role="menu"]
10
- // having children with [role="menuitem|menuitemcheckbox|menuitemradio|option"] and
11
- // list items that can be found via MutationObserver or registration (.formElements)
9
+ // TODO: make this mixin reuse the interactive-list implementation instead of its own copy of the
10
+ // navigation logic. The extraction this TODO used to ask for ("ListNavigationWithActiveDescendantMixin
11
+ // that can be reused in [role="menu"]") now exists as `InteractiveListMixin`, the base of the menu
12
+ // components (packages/ui/components/menu). Rebasing this mixin on it is also what makes the next step
13
+ // possible, without breaking consumers in between:
14
+ // - rename the api to the focusgroup/platform vocabulary the menu already speaks:
15
+ // `orientation` ('vertical'/'horizontal') -> `axis` ('block'/'inline'),
16
+ // `rotateKeyboardNavigation` -> `wrap`, `multipleChoice` -> `multiple`
17
+ // - map the new axis values to the ARIA ones where `aria-orientation` is set (block -> vertical,
18
+ // inline -> horizontal); ARIA does not know the focusgroup tokens
19
+ // - keep the old properties and attributes working in the same release: add the new property with
20
+ // its own attribute, turn the old one into a deprecated alias that delegates to it (with a
21
+ // dev-only deprecation warning) and mark it `@deprecated` in ListboxMixinTypes, then remove the
22
+ // aliases in the next major
23
+ // - `hasNoDefaultSelected` and `selectionFollowsFocus` can stay: the menu uses those names too
12
24
 
13
25
  /**
14
26
  * @typedef {import('../../form-core/types/FormControlMixinTypes.js').HTMLElementWithValue} HTMLElementWithValue
@@ -27,38 +39,37 @@ import { moveUserProvidedDefaultSlottablesToTarget } from '../../core/src/SlotMi
27
39
  * @param {import('@open-wc/dedupe-mixin').Constructor<import('lit').LitElement>} superclass
28
40
  */
29
41
  // prettier-ignore
30
- const ListboxMixinImplementation = /** @type {ListboxMixin} */ (superclass =>
31
- class ListboxMixin extends FormControlMixin(
32
- ScopedElementsMixin(ChoiceGroupMixin(SlotMixin(FormRegistrarMixin(superclass)))),
33
- ) {
34
- /** @type {any} */
35
- static get properties() {
36
- return {
37
- orientation: String,
38
- selectionFollowsFocus: {
39
- type: Boolean,
40
- attribute: 'selection-follows-focus',
41
- },
42
- rotateKeyboardNavigation: {
43
- type: Boolean,
44
- attribute: 'rotate-keyboard-navigation',
45
- },
46
- hasNoDefaultSelected: {
47
- type: Boolean,
48
- reflect: true,
49
- attribute: 'has-no-default-selected',
50
- },
51
- _noTypeAhead: {
52
- type: Boolean,
53
- },
54
- };
55
- }
56
-
57
- static get styles() {
58
- return [
59
- // @ts-ignore [ts7-2855] TS7 rejects field access via super (the parent declares this as a field). Dot form kept deliberately: bracket access is exempt from property mangling (terser keep_quoted), which could split this property into two names. Upstream fix: declare an accessor in the parent type
60
- ...(super.styles || []),
61
- css`
42
+ const ListboxMixinImplementation = /** @type {ListboxMixin} */superclass => class ListboxMixin extends FormControlMixin(ScopedElementsMixin(ChoiceGroupMixin(SlotMixin(FormRegistrarMixin(superclass))))) {
43
+ /** @type {any} */
44
+ static get properties() {
45
+ return {
46
+ // TODO: rename to `axis` with the values 'block'|'inline' (see the TODO at the top of this
47
+ // file); keep `orientation`/`orientation="vertical"|"horizontal"` working as a deprecated alias
48
+ orientation: String,
49
+ selectionFollowsFocus: {
50
+ type: Boolean,
51
+ attribute: 'selection-follows-focus'
52
+ },
53
+ // TODO: rename to `wrap` (see the TODO at the top of this file); keep the old property and
54
+ // attribute working as a deprecated alias
55
+ rotateKeyboardNavigation: {
56
+ type: Boolean,
57
+ attribute: 'rotate-keyboard-navigation'
58
+ },
59
+ hasNoDefaultSelected: {
60
+ type: Boolean,
61
+ reflect: true,
62
+ attribute: 'has-no-default-selected'
63
+ },
64
+ _noTypeAhead: {
65
+ type: Boolean
66
+ }
67
+ };
68
+ }
69
+ static get styles() {
70
+ return [
71
+ // @ts-ignore [ts7-2855] TS7 rejects field access via super (the parent declares this as a field). Dot form kept deliberately: bracket access is exempt from property mangling (terser keep_quoted), which could split this property into two names. Upstream fix: declare an accessor in the parent type
72
+ ...(super.styles || []), css`
62
73
  :host {
63
74
  display: block;
64
75
  }
@@ -74,493 +85,479 @@ const ListboxMixinImplementation = /** @type {ListboxMixin} */ (superclass =>
74
85
  :host([orientation='horizontal']) ::slotted([role='listbox']) {
75
86
  display: flex;
76
87
  }
77
- `,
78
- ];
79
- }
80
-
81
- /**
82
- * @override FormControlMixin
83
- * @protected
84
- */
85
- // eslint-disable-next-line
86
- _inputGroupInputTemplate() {
87
- return html`
88
+ `];
89
+ }
90
+
91
+ /**
92
+ * @override FormControlMixin
93
+ * @protected
94
+ */
95
+ // eslint-disable-next-line
96
+ _inputGroupInputTemplate() {
97
+ return html`
88
98
  <div class="input-group__input">
89
99
  <slot name="input"></slot>
90
100
  <slot id="options-outlet"></slot>
91
101
  </div>
92
102
  `;
93
- }
94
-
95
- static get scopedElements() {
96
- return {
97
- // @ts-expect-error [external] fix types scopedElements
98
- ...super.scopedElements,
99
- 'lion-options': LionOptions,
100
- };
101
- }
102
-
103
- get slots() {
104
- return {
105
- ...super.slots,
106
- input: () => {
107
- const lionOptions = /** @type {import('./LionOptions.js').LionOptions} */ (
108
- this.createScopedElement('lion-options')
109
- );
110
- lionOptions.setAttribute('data-tag-name', 'lion-options');
111
- lionOptions.registrationTarget = this;
112
- return lionOptions;
113
- },
114
- };
115
- }
116
-
117
- /**
118
- * @configure FormControlMixin
103
+ }
104
+ static get scopedElements() {
105
+ return {
106
+ // @ts-expect-error [external] fix types scopedElements
107
+ ...super.scopedElements,
108
+ 'lion-options': LionOptions
109
+ };
110
+ }
111
+ get slots() {
112
+ return {
113
+ ...super.slots,
114
+ input: () => {
115
+ const lionOptions = /** @type {import('./LionOptions.js').LionOptions} */
116
+ this.createScopedElement('lion-options');
117
+ lionOptions.setAttribute('data-tag-name', 'lion-options');
118
+ lionOptions.registrationTarget = this;
119
+ return lionOptions;
120
+ }
121
+ };
122
+ }
123
+
124
+ /**
125
+ * @configure FormControlMixin
126
+ */
127
+ get _inputNode() {
128
+ return /** @type {HTMLElementWithValue} */this.querySelector('[slot="input"]');
129
+ }
130
+
131
+ /**
132
+ * @overridable
133
+ */
134
+ get _listboxNode() {
135
+ // Cast to unknown first, since HTMLElementWithValue is not compatible with LionOptions
136
+ return /** @type {LionOptions} */ /** @type {unknown} */this._inputNode;
137
+ }
138
+
139
+ /**
140
+ * @overridable
141
+ * @type {HTMLElement}
142
+ */
143
+ get _listboxActiveDescendantNode() {
144
+ return /** @type {HTMLElement} */this._listboxNode.querySelector(`#${this._listboxActiveDescendant}`);
145
+ }
146
+
147
+ /**
148
+ * @overridable
149
+ * @type {HTMLElement}
150
+ */
151
+ get _listboxSlot() {
152
+ return /** @type {HTMLElement} */ /** @type {ShadowRoot} */this.shadowRoot.querySelector('slot[name=input]');
153
+ }
154
+
155
+ /**
156
+ * @overridable
157
+ * @type {HTMLElement}
158
+ */
159
+ get _scrollTargetNode() {
160
+ return this._listboxNode;
161
+ }
162
+
163
+ /**
164
+ * @overridable
165
+ * @type {HTMLElement}
166
+ */
167
+ get _activeDescendantOwnerNode() {
168
+ return this._listboxNode;
169
+ }
170
+ get activeIndex() {
171
+ return this.formElements.findIndex(el => el.active === true);
172
+ }
173
+ set activeIndex(index) {
174
+ if (this.formElements[index]) {
175
+ const el = this.formElements[index];
176
+ this.__setChildActive(el);
177
+ } else {
178
+ this.__setChildActive(null);
179
+ }
180
+ }
181
+
182
+ /**
183
+ * @type {number | number[]}
184
+ */
185
+ get checkedIndex() {
186
+ const options = this.formElements;
187
+ if (!this.multipleChoice) {
188
+ return options.indexOf(options.find(o => o.checked));
189
+ }
190
+ return options.filter(o => o.checked).map(o => options.indexOf(o));
191
+ }
192
+
193
+ /**
194
+ * @deprecated
195
+ * This setter exists for backwards compatibility of single choice groups.
196
+ * A setter api would be confusing for a multipleChoice group. Use `setCheckedIndex` instead.
197
+ * @param {number|number[]} index
198
+ */
199
+ set checkedIndex(index) {
200
+ this.setCheckedIndex(index);
201
+ }
202
+ constructor() {
203
+ super();
204
+ /**
205
+ * When setting this to true, on initial render, no option will be selected.
206
+ * It is advisable to override `_noSelectionTemplate` method in the select-invoker
207
+ * to render some kind of placeholder initially
208
+ */
209
+ this.hasNoDefaultSelected = false;
210
+ /**
211
+ * Informs screen reader and affects keyboard navigation.
212
+ * By default 'vertical'
213
+ */
214
+ this.orientation = 'vertical';
215
+ /**
216
+ * Will give first option active state when navigated to the next option from
217
+ * last option.
218
+ */
219
+ this.rotateKeyboardNavigation = false;
220
+ /**
221
+ * When true, will synchronize activedescendant and selected element on
222
+ * arrow key navigation.
223
+ * This behavior can usually be seen on <select> on the Windows platform.
224
+ * Note that this behavior cannot be used when multiple-choice is true.
225
+ * See: https://www.w3.org/TR/wai-aria-practices/#kbd_selection_follows_focus
226
+ */
227
+ this.selectionFollowsFocus = false;
228
+ /**
229
+ * When false, a user can type on which the focus will jump to the matching option
230
+ */
231
+ this._noTypeAhead = false;
232
+ /**
233
+ * The pending char sequence that will set active list item
234
+ * @type {number}
235
+ * @protected
119
236
  */
120
- get _inputNode() {
121
- return /** @type {HTMLElementWithValue} */ (this.querySelector('[slot="input"]'));
122
- }
123
-
237
+ this._typeAheadTimeout = 1000;
124
238
  /**
125
- * @overridable
239
+ * @type {number | null}
240
+ * @protected
126
241
  */
127
- get _listboxNode() {
128
- // Cast to unknown first, since HTMLElementWithValue is not compatible with LionOptions
129
- return /** @type {LionOptions} */ (/** @type {unknown} */ (this._inputNode));
130
- }
131
-
242
+ this._listboxActiveDescendant = null;
243
+ /** @private */
244
+ this.__hasInitialSelectedFormElement = false;
132
245
  /**
133
- * @overridable
134
- * @type {HTMLElement}
246
+ * @type {'fieldset' | 'child' | 'choice-group'}
247
+ * @protected
135
248
  */
136
- get _listboxActiveDescendantNode() {
137
- return /** @type {HTMLElement} */ (
138
- this._listboxNode.querySelector(`#${this._listboxActiveDescendant}`)
139
- );
140
- }
141
-
249
+ this._repropagationRole = 'choice-group'; // configures FormControlMixin
142
250
  /**
143
- * @overridable
144
- * @type {HTMLElement}
251
+ * When listbox is coupled to a textbox (in case we are dealing with a combobox),
252
+ * spaces should not select an element (they need to be put in the textbox)
253
+ * @protected
145
254
  */
146
- get _listboxSlot() {
147
- return /** @type {HTMLElement} */ (
148
- /** @type {ShadowRoot} */ (this.shadowRoot).querySelector('slot[name=input]')
149
- );
150
- }
255
+ this._listboxReceivesNoFocus = false;
151
256
 
152
257
  /**
153
- * @overridable
154
- * @type {HTMLElement}
258
+ * @type {string | string[] | undefined}
259
+ * @protected
155
260
  */
156
- get _scrollTargetNode() {
157
- return this._listboxNode;
158
- }
261
+ this._oldModelValue = undefined;
159
262
 
160
263
  /**
161
- * @overridable
162
- * @type {HTMLElement}
264
+ * @type {EventListener}
265
+ * @protected
163
266
  */
164
- get _activeDescendantOwnerNode() {
165
- return this._listboxNode;
166
- }
167
-
168
- get activeIndex() {
169
- return this.formElements.findIndex(el => el.active === true);
170
- }
171
-
172
- set activeIndex(index) {
173
- if (this.formElements[index]) {
174
- const el = this.formElements[index];
175
- this.__setChildActive(el);
176
- } else {
177
- this.__setChildActive(null);
178
- }
179
- }
180
-
267
+ this._listboxOnKeyDown = this._listboxOnKeyDown.bind(this);
181
268
  /**
182
- * @type {number | number[]}
269
+ * @type {EventListener}
270
+ * @protected
183
271
  */
184
- get checkedIndex() {
185
- const options = this.formElements;
186
- if (!this.multipleChoice) {
187
- return options.indexOf(options.find(o => o.checked));
188
- }
189
- return options.filter(o => o.checked).map(o => options.indexOf(o));
190
- }
191
-
272
+ this._listboxOnClick = this._listboxOnClick.bind(this);
192
273
  /**
193
- * @deprecated
194
- * This setter exists for backwards compatibility of single choice groups.
195
- * A setter api would be confusing for a multipleChoice group. Use `setCheckedIndex` instead.
196
- * @param {number|number[]} index
274
+ * @type {EventListener}
275
+ * @protected
197
276
  */
198
- set checkedIndex(index) {
199
- this.setCheckedIndex(index);
200
- }
201
-
202
- constructor() {
203
- super();
204
- /**
205
- * When setting this to true, on initial render, no option will be selected.
206
- * It is advisable to override `_noSelectionTemplate` method in the select-invoker
207
- * to render some kind of placeholder initially
208
- */
209
- this.hasNoDefaultSelected = false;
210
- /**
211
- * Informs screen reader and affects keyboard navigation.
212
- * By default 'vertical'
213
- */
214
- this.orientation = 'vertical';
215
- /**
216
- * Will give first option active state when navigated to the next option from
217
- * last option.
218
- */
219
- this.rotateKeyboardNavigation = false;
220
- /**
221
- * When true, will synchronize activedescendant and selected element on
222
- * arrow key navigation.
223
- * This behavior can usually be seen on <select> on the Windows platform.
224
- * Note that this behavior cannot be used when multiple-choice is true.
225
- * See: https://www.w3.org/TR/wai-aria-practices/#kbd_selection_follows_focus
226
- */
227
- this.selectionFollowsFocus = false;
228
- /**
229
- * When false, a user can type on which the focus will jump to the matching option
230
- */
231
- this._noTypeAhead = false;
232
- /**
233
- * The pending char sequence that will set active list item
234
- * @type {number}
235
- * @protected
236
- */
237
- this._typeAheadTimeout = 1000;
238
- /**
239
- * @type {number | null}
240
- * @protected
241
- */
242
- this._listboxActiveDescendant = null;
243
- /** @private */
244
- this.__hasInitialSelectedFormElement = false;
245
- /**
246
- * @type {'fieldset' | 'child' | 'choice-group'}
247
- * @protected
248
- */
249
- this._repropagationRole = 'choice-group'; // configures FormControlMixin
250
- /**
251
- * When listbox is coupled to a textbox (in case we are dealing with a combobox),
252
- * spaces should not select an element (they need to be put in the textbox)
253
- * @protected
254
- */
255
- this._listboxReceivesNoFocus = false;
256
-
257
- /**
258
- * @type {string | string[] | undefined}
259
- * @protected
260
- */
261
- this._oldModelValue = undefined;
262
-
263
- /**
264
- * @type {EventListener}
265
- * @protected
266
- */
267
- this._listboxOnKeyDown = this._listboxOnKeyDown.bind(this);
268
- /**
269
- * @type {EventListener}
270
- * @protected
271
- */
272
- this._listboxOnClick = this._listboxOnClick.bind(this);
273
- /**
274
- * @type {EventListener}
275
- * @protected
276
- */
277
- this._listboxOnKeyUp = this._listboxOnKeyUp.bind(this);
278
- /**
279
- * @type {EventListener}
280
- * @protected
281
- */
282
- this._onChildActiveChanged = this._onChildActiveChanged.bind(this);
283
- /**
284
- * @type {EventListener}
285
- * @private
286
- */
287
- this.__proxyChildModelValueChanged = this.__proxyChildModelValueChanged.bind(this);
288
- /**
289
- * @type {EventListener}
290
- * @private
291
- */
292
- this.__preventScrollingWithArrowKeys = this.__preventScrollingWithArrowKeys.bind(this);
293
- /**
294
- * @type {string[]}
295
- * @private
296
- */
297
- this.__typedChars = [];
298
- }
299
-
300
- connectedCallback() {
301
- if (this._listboxNode) {
302
- // if there is none yet, it will be supplied via 'get slots'
303
- this._listboxNode.registrationTarget = this;
304
- }
305
- super.connectedCallback();
306
- this._setupListboxNode();
307
- this.__setupEventListeners();
308
-
309
- // TODO: should this be handled at a more generic level?
310
- this.registrationComplete.then(() => {
311
- this.__initInteractionStates();
312
- });
313
- }
314
-
277
+ this._listboxOnKeyUp = this._listboxOnKeyUp.bind(this);
315
278
  /**
316
- * @param {import('lit').PropertyValues } changedProperties
279
+ * @type {EventListener}
280
+ * @protected
317
281
  */
318
- firstUpdated(changedProperties) {
319
- super.firstUpdated(changedProperties);
320
- this.__moveOptionsToListboxNode();
321
- this.registrationComplete.then(() => {
322
- /** @type {any[]} */
323
- this._initialModelValue = this.modelValue;
324
- });
325
-
326
- // Every time new options are rendered from outside context, notify our parents
327
- const observer = new MutationObserver(() => {
328
- this._onListboxContentChanged();
329
- });
330
- observer.observe(this._listboxNode, { childList: true });
331
- }
332
-
282
+ this._onChildActiveChanged = this._onChildActiveChanged.bind(this);
333
283
  /**
334
- * @param {import('lit').PropertyValues } changedProperties
284
+ * @type {EventListener}
285
+ * @private
335
286
  */
336
- updated(changedProperties) {
337
- super.updated(changedProperties);
338
-
339
- if (changedProperties.has('disabled')) {
340
- if (this.disabled) {
341
- this.__requestOptionsToBeDisabled();
342
- } else {
343
- this.__retractRequestOptionsToBeDisabled();
344
- }
345
- }
346
- }
347
-
348
- disconnectedCallback() {
349
- super.disconnectedCallback();
350
-
351
- this._teardownListboxNode();
352
- this.__teardownEventListeners();
353
- }
354
-
287
+ this.__proxyChildModelValueChanged = this.__proxyChildModelValueChanged.bind(this);
355
288
  /**
356
- * If an array is passed for multiple-choice, it will check the indexes in array, and uncheck the rest
357
- * If a number is passed, the item with the passed index is checked without unchecking others
358
- * For single choice, __onChildCheckedChanged we ensure that we uncheck siblings
359
- * @param {number|number[]} index
289
+ * @type {EventListener}
290
+ * @private
360
291
  */
361
- setCheckedIndex(index) {
362
- if (this.multipleChoice && Array.isArray(index)) {
363
- this._uncheckChildren(this.formElements.filter(i => i === index));
364
- index.forEach(i => {
365
- if (this.formElements[i]) {
366
- this.formElements[i].checked = !this.formElements[i].checked;
367
- }
368
- });
369
- return;
370
- }
371
-
372
- if (typeof index === 'number') {
373
- if (index === -1) {
374
- this._uncheckChildren();
375
- }
376
- if (this.formElements[index]) {
377
- if (this.formElements[index].disabled) {
378
- this._uncheckChildren();
379
- } else if (this.multipleChoice) {
380
- this.formElements[index].checked = !this.formElements[index].checked;
381
- } else {
382
- this.formElements[index].checked = true;
383
- }
384
- }
385
- }
386
- }
387
-
292
+ this.__preventScrollingWithArrowKeys = this.__preventScrollingWithArrowKeys.bind(this);
388
293
  /**
389
- * @enhance FormRegistrarMixin: make sure children have specific default states when added
390
- * @param {FormControlHost & LionOption} child
391
- * @param {Number} indexToInsertAt
294
+ * @type {string[]}
295
+ * @private
392
296
  */
393
- addFormElement(child, indexToInsertAt) {
394
- super.addFormElement(/** @type {FormControl} */ child, indexToInsertAt);
395
- // we need to adjust the elements being registered
396
- /* eslint-disable no-param-reassign */
397
- child.id = child.id || `${this.localName}-option-${uuid()}`;
398
-
297
+ this.__typedChars = [];
298
+ }
299
+ connectedCallback() {
300
+ if (this._listboxNode) {
301
+ // if there is none yet, it will be supplied via 'get slots'
302
+ this._listboxNode.registrationTarget = this;
303
+ }
304
+ super.connectedCallback();
305
+ this._setupListboxNode();
306
+ this.__setupEventListeners();
307
+
308
+ // TODO: should this be handled at a more generic level?
309
+ this.registrationComplete.then(() => {
310
+ this.__initInteractionStates();
311
+ });
312
+ }
313
+
314
+ /**
315
+ * @param {import('lit').PropertyValues } changedProperties
316
+ */
317
+ firstUpdated(changedProperties) {
318
+ super.firstUpdated(changedProperties);
319
+ this.__moveOptionsToListboxNode();
320
+ this.registrationComplete.then(() => {
321
+ /** @type {any[]} */
322
+ this._initialModelValue = this.modelValue;
323
+ });
324
+
325
+ // Every time new options are rendered from outside context, notify our parents
326
+ const observer = new MutationObserver(() => {
327
+ this._onListboxContentChanged();
328
+ });
329
+ observer.observe(this._listboxNode, {
330
+ childList: true
331
+ });
332
+ }
333
+
334
+ /**
335
+ * @param {import('lit').PropertyValues } changedProperties
336
+ */
337
+ updated(changedProperties) {
338
+ super.updated(changedProperties);
339
+ if (changedProperties.has('disabled')) {
399
340
  if (this.disabled) {
400
- child.makeRequestToBeDisabled();
341
+ this.__requestOptionsToBeDisabled();
342
+ } else {
343
+ this.__retractRequestOptionsToBeDisabled();
401
344
  }
402
-
403
- // TODO: small perf improvement could be made if logic below would be scheduled to next update,
404
- // so it occurs once for all options
405
- this.__setAttributeForAllFormElements('aria-setsize', this.formElements.length);
406
- this.formElements.forEach((el, idx) => {
407
- el.setAttribute('aria-posinset', idx + 1);
408
- });
409
-
410
- this.__proxyChildModelValueChanged(
411
- /** @type {CustomEvent & { target: FormControlHost & LionOption; }} */ ({ target: child }),
412
- );
413
- this.resetInteractionState();
414
- /* eslint-enable no-param-reassign */
415
- }
416
-
417
- resetInteractionState() {
418
- super.resetInteractionState();
419
- this.submitted = false;
420
345
  }
421
-
422
- reset() {
423
- this.modelValue = this._initialModelValue;
424
- this.activeIndex = -1;
425
- this.resetInteractionState();
426
- }
427
-
428
- clear() {
429
- super.clear();
430
- this.setCheckedIndex(-1);
431
- }
432
-
433
- /**
434
- * @param {KeyboardEvent} ev
435
- * @param {{setAsChecked:boolean}} options
436
- * @protected
437
- */
438
- _handleTypeAhead(ev, { setAsChecked }) {
439
- const { key, code } = ev;
440
-
441
- if (code.startsWith('Key') || code.startsWith('Digit') || code.startsWith('Numpad')) {
442
- ev.preventDefault();
443
- this.__typedChars.push(key);
444
- const chars = this.__typedChars.join('');
445
- const matchedItemIndex =
446
- // TODO: consider making this condition overridable for Subclassers by extracting it into protected method
447
- this.formElements.findIndex(el => el.modelValue.value.toLowerCase().startsWith(chars));
448
- if (matchedItemIndex >= 0) {
449
- if (setAsChecked) {
450
- this.setCheckedIndex(matchedItemIndex);
451
- }
452
- this.activeIndex = matchedItemIndex;
346
+ }
347
+ disconnectedCallback() {
348
+ super.disconnectedCallback();
349
+ this._teardownListboxNode();
350
+ this.__teardownEventListeners();
351
+ }
352
+
353
+ /**
354
+ * If an array is passed for multiple-choice, it will check the indexes in array, and uncheck the rest
355
+ * If a number is passed, the item with the passed index is checked without unchecking others
356
+ * For single choice, __onChildCheckedChanged we ensure that we uncheck siblings
357
+ * @param {number|number[]} index
358
+ */
359
+ setCheckedIndex(index) {
360
+ if (this.multipleChoice && Array.isArray(index)) {
361
+ this._uncheckChildren(this.formElements.filter(i => i === index));
362
+ index.forEach(i => {
363
+ if (this.formElements[i]) {
364
+ this.formElements[i].checked = !this.formElements[i].checked;
453
365
  }
454
- if (this.__pendingTypeAheadTimeout) {
455
- // Prevent that pending timeouts 'intersect' with new 'typeahead sessions'
456
- // @ts-ignore
457
- window.clearTimeout(this.__pendingTypeAheadTimeout);
458
- }
459
- this.__pendingTypeAheadTimeout = setTimeout(() => {
460
- // schedule a timeout to reset __typedChars
461
- this.__typedChars = [];
462
- }, this._typeAheadTimeout);
463
- }
464
- }
465
-
466
- /**
467
- * @override ChoiceGroupMixin: in the select disabled options are still going to a possible
468
- * value, for example when prefilling or programmatically setting it.
469
- * @protected
470
- */
471
- _getCheckedElements() {
472
- return this.formElements.filter(el => el.checked);
366
+ });
367
+ return;
473
368
  }
474
-
475
- /** @protected */
476
- _setupListboxNode() {
477
- if (this._listboxNode) {
478
- this.__setupListboxNodeInteractions();
479
- } else if (this._listboxSlot) {
480
- /**
481
- * For ShadyDom the listboxNode is available right from the start so we can add those events
482
- * immediately.
483
- * For native ShadowDom the select gets rendered before the listboxNode is available so we
484
- * will add an event to the slotchange and add the events once available.
485
- */
486
- this._listboxSlot.addEventListener('slotchange', () => {
487
- this.__setupListboxNodeInteractions();
488
- });
369
+ if (typeof index === 'number') {
370
+ if (index === -1) {
371
+ this._uncheckChildren();
489
372
  }
490
- }
491
-
492
- /**
493
- * A Subclasser can perform additional logic whenever the elements inside the listbox are
494
- * updated. For instance, when a combobox does server side autocomplete, we want to
495
- * match highlighted parts client side.
496
- * @configurable
497
- */
498
- // eslint-disable-next-line class-methods-use-this
499
- _onListboxContentChanged() {}
500
-
501
- _teardownListboxNode() {
502
- if (this._listboxNode) {
503
- this._listboxNode.removeEventListener('keydown', this._listboxOnKeyDown);
504
- this._listboxNode.removeEventListener('click', this._listboxOnClick);
505
- this._listboxNode.removeEventListener('keyup', this._listboxOnKeyUp);
373
+ if (this.formElements[index]) {
374
+ if (this.formElements[index].disabled) {
375
+ this._uncheckChildren();
376
+ } else if (this.multipleChoice) {
377
+ this.formElements[index].checked = !this.formElements[index].checked;
378
+ } else {
379
+ this.formElements[index].checked = true;
380
+ }
506
381
  }
507
382
  }
508
-
509
- /**
510
- * @param {number} currentIndex
511
- * @param {number} [offset=1]
512
- * @protected
513
- */
514
- _getNextEnabledOption(currentIndex, offset = 1) {
515
- return this.__getEnabledOption(currentIndex, offset);
516
- }
517
-
518
- /**
519
- * @param {number} currentIndex
520
- * @param {number} [offset=-1]
521
- * @protected
522
- */
523
- _getPreviousEnabledOption(currentIndex, offset = -1) {
524
- return this.__getEnabledOption(currentIndex, offset);
525
- }
526
-
527
- /**
528
- * @overridable
529
- * @param {Event & { target: LionOption }} ev
530
- * @protected
531
- */
532
- // eslint-disable-next-line no-unused-vars, class-methods-use-this
533
- _onChildActiveChanged({ target }) {
534
- if (target.active === true) {
535
- this.__setChildActive(target);
383
+ }
384
+
385
+ /**
386
+ * @enhance FormRegistrarMixin: make sure children have specific default states when added
387
+ * @param {FormControlHost & LionOption} child
388
+ * @param {Number} indexToInsertAt
389
+ */
390
+ addFormElement(child, indexToInsertAt) {
391
+ super.addFormElement(/** @type {FormControl} */child, indexToInsertAt);
392
+ // we need to adjust the elements being registered
393
+ /* eslint-disable no-param-reassign */
394
+ child.id = child.id || `${this.localName}-option-${uuid()}`;
395
+ if (this.disabled) {
396
+ child.makeRequestToBeDisabled();
397
+ }
398
+
399
+ // TODO: small perf improvement could be made if logic below would be scheduled to next update,
400
+ // so it occurs once for all options
401
+ this.__setAttributeForAllFormElements('aria-setsize', this.formElements.length);
402
+ this.formElements.forEach((el, idx) => {
403
+ el.setAttribute('aria-posinset', idx + 1);
404
+ });
405
+ this.__proxyChildModelValueChanged(/** @type {CustomEvent & { target: FormControlHost & LionOption; }} */{
406
+ target: child
407
+ });
408
+ this.resetInteractionState();
409
+ /* eslint-enable no-param-reassign */
410
+ }
411
+ resetInteractionState() {
412
+ super.resetInteractionState();
413
+ this.submitted = false;
414
+ }
415
+ reset() {
416
+ this.modelValue = this._initialModelValue;
417
+ this.activeIndex = -1;
418
+ this.resetInteractionState();
419
+ }
420
+ clear() {
421
+ super.clear();
422
+ this.setCheckedIndex(-1);
423
+ }
424
+
425
+ /**
426
+ * @param {KeyboardEvent} ev
427
+ * @param {{setAsChecked:boolean}} options
428
+ * @protected
429
+ */
430
+ _handleTypeAhead(ev, {
431
+ setAsChecked
432
+ }) {
433
+ const {
434
+ key,
435
+ code
436
+ } = ev;
437
+ if (code.startsWith('Key') || code.startsWith('Digit') || code.startsWith('Numpad')) {
438
+ ev.preventDefault();
439
+ this.__typedChars.push(key);
440
+ const chars = this.__typedChars.join('');
441
+ const matchedItemIndex =
442
+ // TODO: consider making this condition overridable for Subclassers by extracting it into protected method
443
+ this.formElements.findIndex(el => el.modelValue.value.toLowerCase().startsWith(chars));
444
+ if (matchedItemIndex >= 0) {
445
+ if (setAsChecked) {
446
+ this.setCheckedIndex(matchedItemIndex);
447
+ }
448
+ this.activeIndex = matchedItemIndex;
536
449
  }
537
- }
538
-
539
- /**
540
- * @desc
541
- * Handle various keyboard controls; UP/DOWN will shift focus; SPACE selects
542
- * an item.
543
- *
544
- * @param {KeyboardEvent} ev - the keydown event object
545
- * @protected
546
- */
547
- _listboxOnKeyDown(ev) {
548
- if (this.disabled) {
549
- return;
450
+ if (this.__pendingTypeAheadTimeout) {
451
+ // Prevent that pending timeouts 'intersect' with new 'typeahead sessions'
452
+ // @ts-ignore
453
+ window.clearTimeout(this.__pendingTypeAheadTimeout);
550
454
  }
551
-
552
- this._isHandlingUserInput = true;
553
- setTimeout(() => {
554
- // Since we can't control when subclasses are done handling keyboard input, we
555
- // schedule a timeout to reset _isHandlingUserInput
556
- this._isHandlingUserInput = false;
455
+ this.__pendingTypeAheadTimeout = setTimeout(() => {
456
+ // schedule a timeout to reset __typedChars
457
+ this.__typedChars = [];
458
+ }, this._typeAheadTimeout);
459
+ }
460
+ }
461
+
462
+ /**
463
+ * @override ChoiceGroupMixin: in the select disabled options are still going to a possible
464
+ * value, for example when prefilling or programmatically setting it.
465
+ * @protected
466
+ */
467
+ _getCheckedElements() {
468
+ return this.formElements.filter(el => el.checked);
469
+ }
470
+
471
+ /** @protected */
472
+ _setupListboxNode() {
473
+ if (this._listboxNode) {
474
+ this.__setupListboxNodeInteractions();
475
+ } else if (this._listboxSlot) {
476
+ /**
477
+ * For ShadyDom the listboxNode is available right from the start so we can add those events
478
+ * immediately.
479
+ * For native ShadowDom the select gets rendered before the listboxNode is available so we
480
+ * will add an event to the slotchange and add the events once available.
481
+ */
482
+ this._listboxSlot.addEventListener('slotchange', () => {
483
+ this.__setupListboxNodeInteractions();
557
484
  });
558
-
559
- const { key } = ev;
560
-
561
- switch (key) {
562
- case ' ':
563
- case 'Enter': {
485
+ }
486
+ }
487
+
488
+ /**
489
+ * A Subclasser can perform additional logic whenever the elements inside the listbox are
490
+ * updated. For instance, when a combobox does server side autocomplete, we want to
491
+ * match highlighted parts client side.
492
+ * @configurable
493
+ */
494
+ // eslint-disable-next-line class-methods-use-this
495
+ _onListboxContentChanged() {}
496
+ _teardownListboxNode() {
497
+ if (this._listboxNode) {
498
+ this._listboxNode.removeEventListener('keydown', this._listboxOnKeyDown);
499
+ this._listboxNode.removeEventListener('click', this._listboxOnClick);
500
+ this._listboxNode.removeEventListener('keyup', this._listboxOnKeyUp);
501
+ }
502
+ }
503
+
504
+ /**
505
+ * @param {number} currentIndex
506
+ * @param {number} [offset=1]
507
+ * @protected
508
+ */
509
+ _getNextEnabledOption(currentIndex, offset = 1) {
510
+ return this.__getEnabledOption(currentIndex, offset);
511
+ }
512
+
513
+ /**
514
+ * @param {number} currentIndex
515
+ * @param {number} [offset=-1]
516
+ * @protected
517
+ */
518
+ _getPreviousEnabledOption(currentIndex, offset = -1) {
519
+ return this.__getEnabledOption(currentIndex, offset);
520
+ }
521
+
522
+ /**
523
+ * @overridable
524
+ * @param {Event & { target: LionOption }} ev
525
+ * @protected
526
+ */
527
+ // eslint-disable-next-line no-unused-vars, class-methods-use-this
528
+ _onChildActiveChanged({
529
+ target
530
+ }) {
531
+ if (target.active === true) {
532
+ this.__setChildActive(target);
533
+ }
534
+ }
535
+
536
+ /**
537
+ * @desc
538
+ * Handle various keyboard controls; UP/DOWN will shift focus; SPACE selects
539
+ * an item.
540
+ *
541
+ * @param {KeyboardEvent} ev - the keydown event object
542
+ * @protected
543
+ */
544
+ _listboxOnKeyDown(ev) {
545
+ if (this.disabled) {
546
+ return;
547
+ }
548
+ this._isHandlingUserInput = true;
549
+ setTimeout(() => {
550
+ // Since we can't control when subclasses are done handling keyboard input, we
551
+ // schedule a timeout to reset _isHandlingUserInput
552
+ this._isHandlingUserInput = false;
553
+ });
554
+ const {
555
+ key
556
+ } = ev;
557
+ switch (key) {
558
+ case ' ':
559
+ case 'Enter':
560
+ {
564
561
  if (key === ' ' && this._listboxReceivesNoFocus) {
565
562
  return;
566
563
  }
@@ -570,368 +567,353 @@ const ListboxMixinImplementation = /** @type {ListboxMixin} */ (superclass =>
570
567
  if (!this.formElements[this.activeIndex]) {
571
568
  return;
572
569
  }
573
-
574
570
  if (this.formElements[this.activeIndex].disabled) {
575
571
  return;
576
572
  }
577
-
578
573
  if (this.formElements[this.activeIndex].href) {
579
574
  this.formElements[this.activeIndex].click();
580
575
  }
581
-
582
576
  this.setCheckedIndex(this.activeIndex);
583
577
  break;
584
578
  }
585
- case 'ArrowUp':
586
- ev.preventDefault();
587
- if (this.orientation === 'vertical') {
588
- this.activeIndex = this._getPreviousEnabledOption(this.activeIndex);
589
- }
590
- break;
591
- case 'ArrowLeft':
592
- if (this._listboxReceivesNoFocus) {
593
- return;
594
- }
595
- ev.preventDefault();
596
- if (this.orientation === 'horizontal') {
597
- this.activeIndex = this._getPreviousEnabledOption(this.activeIndex);
598
- }
599
- break;
600
- case 'ArrowDown':
601
- ev.preventDefault();
602
- if (this.orientation === 'vertical') {
603
- this.activeIndex = this._getNextEnabledOption(this.activeIndex);
604
- }
605
- break;
606
- case 'ArrowRight':
607
- if (this._listboxReceivesNoFocus) {
608
- return;
609
- }
610
- ev.preventDefault();
611
- if (this.orientation === 'horizontal') {
612
- this.activeIndex = this._getNextEnabledOption(this.activeIndex);
613
- }
614
- break;
615
- case 'Home':
616
- if (this._listboxReceivesNoFocus) {
617
- return;
618
- }
619
- ev.preventDefault();
620
- this.activeIndex = this._getNextEnabledOption(0, 0);
621
- break;
622
- case 'End':
623
- if (this._listboxReceivesNoFocus) {
624
- return;
625
- }
626
- ev.preventDefault();
627
- this.activeIndex = this._getPreviousEnabledOption(this.formElements.length - 1, 0);
628
- break;
629
- default:
630
- if (!this._noTypeAhead) {
631
- this._handleTypeAhead(ev, {
632
- setAsChecked: this.selectionFollowsFocus && !this.multipleChoice,
633
- });
634
- }
635
- }
636
-
637
- const keys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End'];
638
- if (keys.includes(key) && this.selectionFollowsFocus && !this.multipleChoice) {
639
- this.setCheckedIndex(this.activeIndex);
640
- }
641
- }
642
-
643
- /**
644
- * @overridable
645
- * @param {MouseEvent} ev
646
- * @protected
647
- */
648
- // eslint-disable-next-line class-methods-use-this, no-unused-vars
649
- _listboxOnClick(ev) {
650
- /**
651
- For now we disable, handling click interactions via delegated click handlers, since
652
- LionOption detects clicks itself and could now potentially be checked as offline dom.
653
- When we enable both methods in multiple choice mode, we would 'cancel out' each other.
654
- TODO: If we want to allow 'less smart' options (think of role=menu), we should enable this
655
- again and disable click handling inside LionOption (since there would be no use case for
656
- 'orphan' options)
657
- */
658
- // const option = /** @type {HTMLElement} */ (ev.target).closest('[role=option]');
659
- // const foundIndex = this.formElements.indexOf(option);
660
- // if (foundIndex > -1) {
661
- // this.activeIndex = foundIndex;
662
- // this.setCheckedIndex(foundIndex, 'toggle', );
663
- // }
664
- }
665
-
666
- /**
667
- * @overridable
668
- * @param {KeyboardEvent} ev
669
- * @protected
670
- */
671
- // eslint-disable-next-line class-methods-use-this, no-unused-vars
672
- _listboxOnKeyUp(ev) {
673
- if (this.disabled) {
674
- return;
675
- }
676
-
677
- this._isHandlingUserInput = true;
678
- setTimeout(() => {
679
- // Since we can't control when subclasses are done handling keyboard input, we
680
- // schedule a timeout to reset _isHandlingUserInput
681
- this._isHandlingUserInput = false;
682
- });
683
-
684
- const { key } = ev;
685
- // eslint-disable-next-line default-case
686
- switch (key) {
687
- case 'ArrowUp':
688
- case 'ArrowDown':
689
- case 'Home':
690
- case 'End':
691
- case 'Enter':
692
- ev.preventDefault();
693
- }
694
- }
695
-
696
- /**
697
- * @configure FormControlMixin
698
- * @protected
699
- */
700
- _onLabelClick() {
701
- this._listboxNode.focus();
702
- }
703
-
704
- /**
705
- * @param {HTMLElement} el element
706
- * @param {HTMLElement} [scrollTargetEl] container
707
- * @protected
708
- * @description allow Subclassers to adjust the animation: like non smooth behavior, different timing etc.
709
- */
710
- // eslint-disable-next-line class-methods-use-this, no-unused-vars
711
- _scrollIntoView(el, scrollTargetEl) {
712
- el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
713
- }
714
-
715
- /** @private */
716
- __setupEventListeners() {
717
- this._listboxNode.addEventListener(
718
- 'active-changed',
719
- /** @type {EventListener} */ (this._onChildActiveChanged),
720
- );
721
- this._listboxNode.addEventListener(
722
- 'model-value-changed',
723
- /** @type {EventListener} */ (this.__proxyChildModelValueChanged),
724
- );
725
- }
726
-
727
- /** @private */
728
- __teardownEventListeners() {
729
- this._listboxNode.removeEventListener(
730
- 'active-changed',
731
- /** @type {EventListener} */ (this._onChildActiveChanged),
732
- );
733
- this._listboxNode.removeEventListener(
734
- 'model-value-changed',
735
- /** @type {EventListener} */ (this.__proxyChildModelValueChanged),
736
- );
737
- }
738
-
739
- /**
740
- * @param {LionOption | null} el
741
- * @private
742
- */
743
- __setChildActive(el) {
744
- this.formElements.forEach(formElement => {
745
- // eslint-disable-next-line no-param-reassign
746
- formElement.active = el === formElement;
747
- });
748
- if (!el) {
749
- this._activeDescendantOwnerNode.removeAttribute('aria-activedescendant');
750
- return;
751
- }
752
- this._activeDescendantOwnerNode.setAttribute('aria-activedescendant', el.id);
753
-
754
- this._scrollIntoView(el, this._scrollTargetNode);
755
- }
756
-
757
- /**
758
- * @param {LionOption|LionOption[]} [exclude]
759
- * @protected
760
- */
761
- _uncheckChildren(exclude = []) {
762
- const excludes = Array.isArray(exclude) ? exclude : [exclude];
763
- this.formElements.forEach(option => {
764
- if (!excludes.includes(option)) {
765
- // eslint-disable-next-line no-param-reassign
766
- option.checked = false;
579
+ case 'ArrowUp':
580
+ ev.preventDefault();
581
+ if (this.orientation === 'vertical') {
582
+ this.activeIndex = this._getPreviousEnabledOption(this.activeIndex);
583
+ }
584
+ break;
585
+ case 'ArrowLeft':
586
+ if (this._listboxReceivesNoFocus) {
587
+ return;
588
+ }
589
+ ev.preventDefault();
590
+ if (this.orientation === 'horizontal') {
591
+ this.activeIndex = this._getPreviousEnabledOption(this.activeIndex);
592
+ }
593
+ break;
594
+ case 'ArrowDown':
595
+ ev.preventDefault();
596
+ if (this.orientation === 'vertical') {
597
+ this.activeIndex = this._getNextEnabledOption(this.activeIndex);
598
+ }
599
+ break;
600
+ case 'ArrowRight':
601
+ if (this._listboxReceivesNoFocus) {
602
+ return;
603
+ }
604
+ ev.preventDefault();
605
+ if (this.orientation === 'horizontal') {
606
+ this.activeIndex = this._getNextEnabledOption(this.activeIndex);
607
+ }
608
+ break;
609
+ case 'Home':
610
+ if (this._listboxReceivesNoFocus) {
611
+ return;
612
+ }
613
+ ev.preventDefault();
614
+ this.activeIndex = this._getNextEnabledOption(0, 0);
615
+ break;
616
+ case 'End':
617
+ if (this._listboxReceivesNoFocus) {
618
+ return;
619
+ }
620
+ ev.preventDefault();
621
+ this.activeIndex = this._getPreviousEnabledOption(this.formElements.length - 1, 0);
622
+ break;
623
+ default:
624
+ if (!this._noTypeAhead) {
625
+ this._handleTypeAhead(ev, {
626
+ setAsChecked: this.selectionFollowsFocus && !this.multipleChoice
627
+ });
767
628
  }
768
- });
769
- }
770
-
771
- /**
772
- * @param {Event & { target: LionOption }} cfgOrEvent
773
- * @private
774
- */
775
- __onChildCheckedChanged(cfgOrEvent) {
776
- const { target } = cfgOrEvent;
777
- if (cfgOrEvent.stopPropagation) {
778
- cfgOrEvent.stopPropagation();
779
- }
780
- if (target.checked && !this.multipleChoice) {
781
- this._uncheckChildren(target);
782
- }
783
629
  }
784
-
785
- /**
786
- * // TODO: add to choiceGroup
787
- * @param {string} attribute
788
- * @param {number} value
789
- * @private
790
- */
791
- __setAttributeForAllFormElements(attribute, value) {
792
- this.formElements.forEach(formElement => {
793
- formElement.setAttribute(attribute, value);
794
- });
630
+ const keys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End'];
631
+ if (keys.includes(key) && this.selectionFollowsFocus && !this.multipleChoice) {
632
+ this.setCheckedIndex(this.activeIndex);
633
+ }
634
+ }
635
+
636
+ /**
637
+ * @overridable
638
+ * @param {MouseEvent} ev
639
+ * @protected
640
+ */
641
+ // eslint-disable-next-line class-methods-use-this, no-unused-vars
642
+ _listboxOnClick(ev) {
643
+ /**
644
+ For now we disable, handling click interactions via delegated click handlers, since
645
+ LionOption detects clicks itself and could now potentially be checked as offline dom.
646
+ When we enable both methods in multiple choice mode, we would 'cancel out' each other.
647
+ TODO: If we want to allow 'less smart' options (think of role=menu), we should enable this
648
+ again and disable click handling inside LionOption (since there would be no use case for
649
+ 'orphan' options)
650
+ */
651
+ // const option = /** @type {HTMLElement} */ (ev.target).closest('[role=option]');
652
+ // const foundIndex = this.formElements.indexOf(option);
653
+ // if (foundIndex > -1) {
654
+ // this.activeIndex = foundIndex;
655
+ // this.setCheckedIndex(foundIndex, 'toggle', );
656
+ // }
657
+ }
658
+
659
+ /**
660
+ * @overridable
661
+ * @param {KeyboardEvent} ev
662
+ * @protected
663
+ */
664
+ // eslint-disable-next-line class-methods-use-this, no-unused-vars
665
+ _listboxOnKeyUp(ev) {
666
+ if (this.disabled) {
667
+ return;
668
+ }
669
+ this._isHandlingUserInput = true;
670
+ setTimeout(() => {
671
+ // Since we can't control when subclasses are done handling keyboard input, we
672
+ // schedule a timeout to reset _isHandlingUserInput
673
+ this._isHandlingUserInput = false;
674
+ });
675
+ const {
676
+ key
677
+ } = ev;
678
+ // eslint-disable-next-line default-case
679
+ switch (key) {
680
+ case 'ArrowUp':
681
+ case 'ArrowDown':
682
+ case 'Home':
683
+ case 'End':
684
+ case 'Enter':
685
+ ev.preventDefault();
795
686
  }
796
-
797
- /**
798
- * @param {CustomEvent & { target: LionOption; }} ev
799
- * @private
800
- */
801
- __proxyChildModelValueChanged(ev) {
802
- // We need to redispatch the model-value-changed event on 'this', so it will
803
- // align with FormControl.__repropagateChildrenValues method. Also, this makes
804
- // it act like a portal, in case the listbox is put in a modal overlay on body level.
805
- if (ev.stopPropagation) {
806
- ev.stopPropagation();
687
+ }
688
+
689
+ /**
690
+ * @configure FormControlMixin
691
+ * @protected
692
+ */
693
+ _onLabelClick() {
694
+ this._listboxNode.focus();
695
+ }
696
+
697
+ /**
698
+ * @param {HTMLElement} el element
699
+ * @param {HTMLElement} [scrollTargetEl] container
700
+ * @protected
701
+ * @description allow Subclassers to adjust the animation: like non smooth behavior, different timing etc.
702
+ */
703
+ // eslint-disable-next-line class-methods-use-this, no-unused-vars
704
+ _scrollIntoView(el, scrollTargetEl) {
705
+ el.scrollIntoView({
706
+ behavior: 'smooth',
707
+ block: 'nearest'
708
+ });
709
+ }
710
+
711
+ /** @private */
712
+ __setupEventListeners() {
713
+ this._listboxNode.addEventListener('active-changed', /** @type {EventListener} */this._onChildActiveChanged);
714
+ this._listboxNode.addEventListener('model-value-changed', /** @type {EventListener} */this.__proxyChildModelValueChanged);
715
+ }
716
+
717
+ /** @private */
718
+ __teardownEventListeners() {
719
+ this._listboxNode.removeEventListener('active-changed', /** @type {EventListener} */this._onChildActiveChanged);
720
+ this._listboxNode.removeEventListener('model-value-changed', /** @type {EventListener} */this.__proxyChildModelValueChanged);
721
+ }
722
+
723
+ /**
724
+ * @param {LionOption | null} el
725
+ * @private
726
+ */
727
+ __setChildActive(el) {
728
+ this.formElements.forEach(formElement => {
729
+ // eslint-disable-next-line no-param-reassign
730
+ formElement.active = el === formElement;
731
+ });
732
+ if (!el) {
733
+ this._activeDescendantOwnerNode.removeAttribute('aria-activedescendant');
734
+ return;
735
+ }
736
+ this._activeDescendantOwnerNode.setAttribute('aria-activedescendant', el.id);
737
+ this._scrollIntoView(el, this._scrollTargetNode);
738
+ }
739
+
740
+ /**
741
+ * @param {LionOption|LionOption[]} [exclude]
742
+ * @protected
743
+ */
744
+ _uncheckChildren(exclude = []) {
745
+ const excludes = Array.isArray(exclude) ? exclude : [exclude];
746
+ this.formElements.forEach(option => {
747
+ if (!excludes.includes(option)) {
748
+ // eslint-disable-next-line no-param-reassign
749
+ option.checked = false;
807
750
  }
808
- this.__onChildCheckedChanged(ev);
809
-
810
- // don't send this.modelValue as oldValue, since it will take modelValue getter which takes it from child elements, which is already the updated value
811
- this.requestUpdate('modelValue', this._oldModelValue);
812
- // only send model-value-changed if the event is caused by one of its children
813
- if (ev.detail && ev.detail.formPath) {
814
- this.dispatchEvent(
815
- new CustomEvent('model-value-changed', {
816
- detail: /** @type {ModelValueEventDetails} */ ({
817
- formPath: ev.detail.formPath,
818
- isTriggeredByUser: ev.detail.isTriggeredByUser || this._isHandlingUserInput,
819
- element: ev.target,
820
- }),
821
- }),
822
- );
751
+ });
752
+ }
753
+
754
+ /**
755
+ * @param {Event & { target: LionOption }} cfgOrEvent
756
+ * @private
757
+ */
758
+ __onChildCheckedChanged(cfgOrEvent) {
759
+ const {
760
+ target
761
+ } = cfgOrEvent;
762
+ if (cfgOrEvent.stopPropagation) {
763
+ cfgOrEvent.stopPropagation();
764
+ }
765
+ if (target.checked && !this.multipleChoice) {
766
+ this._uncheckChildren(target);
767
+ }
768
+ }
769
+
770
+ /**
771
+ * // TODO: add to choiceGroup
772
+ * @param {string} attribute
773
+ * @param {number} value
774
+ * @private
775
+ */
776
+ __setAttributeForAllFormElements(attribute, value) {
777
+ this.formElements.forEach(formElement => {
778
+ formElement.setAttribute(attribute, value);
779
+ });
780
+ }
781
+
782
+ /**
783
+ * @param {CustomEvent & { target: LionOption; }} ev
784
+ * @private
785
+ */
786
+ __proxyChildModelValueChanged(ev) {
787
+ // We need to redispatch the model-value-changed event on 'this', so it will
788
+ // align with FormControl.__repropagateChildrenValues method. Also, this makes
789
+ // it act like a portal, in case the listbox is put in a modal overlay on body level.
790
+ if (ev.stopPropagation) {
791
+ ev.stopPropagation();
792
+ }
793
+ this.__onChildCheckedChanged(ev);
794
+
795
+ // don't send this.modelValue as oldValue, since it will take modelValue getter which takes it from child elements, which is already the updated value
796
+ this.requestUpdate('modelValue', this._oldModelValue);
797
+ // only send model-value-changed if the event is caused by one of its children
798
+ if (ev.detail && ev.detail.formPath) {
799
+ this.dispatchEvent(new CustomEvent('model-value-changed', {
800
+ detail: (/** @type {ModelValueEventDetails} */{
801
+ formPath: ev.detail.formPath,
802
+ isTriggeredByUser: ev.detail.isTriggeredByUser || this._isHandlingUserInput,
803
+ element: ev.target
804
+ })
805
+ }));
806
+ }
807
+ this._oldModelValue = this.modelValue;
808
+ }
809
+
810
+ /**
811
+ * @param {number} currentIndex
812
+ * @param {number} offset
813
+ * @private
814
+ */
815
+ __getEnabledOption(currentIndex, offset) {
816
+ /**
817
+ * @param {number} i
818
+ */
819
+ const until = i => offset === 1 ? i < this.formElements.length : i >= 0;
820
+
821
+ // Try to find the next / previous option
822
+ for (let i = currentIndex + offset; until(i); i += offset) {
823
+ if (this.formElements[i] && !this.formElements[i].hasAttribute('aria-hidden')) {
824
+ return i;
823
825
  }
824
- this._oldModelValue = this.modelValue;
825
826
  }
826
827
 
827
- /**
828
- * @param {number} currentIndex
829
- * @param {number} offset
830
- * @private
831
- */
832
- __getEnabledOption(currentIndex, offset) {
833
- /**
834
- * @param {number} i
835
- */
836
- const until = i => (offset === 1 ? i < this.formElements.length : i >= 0);
837
-
838
- // Try to find the next / previous option
839
- for (let i = currentIndex + offset; until(i); i += offset) {
828
+ // If above was unsuccessful, try to find the next/previous either
829
+ // from end --> start or start --> end
830
+ if (this.rotateKeyboardNavigation) {
831
+ const startIndex = offset === -1 ? this.formElements.length - 1 : 0;
832
+ for (let i = startIndex; until(i); i += offset) {
840
833
  if (this.formElements[i] && !this.formElements[i].hasAttribute('aria-hidden')) {
841
834
  return i;
842
835
  }
843
836
  }
844
-
845
- // If above was unsuccessful, try to find the next/previous either
846
- // from end --> start or start --> end
847
- if (this.rotateKeyboardNavigation) {
848
- const startIndex = offset === -1 ? this.formElements.length - 1 : 0;
849
- for (let i = startIndex; until(i); i += offset) {
850
- if (this.formElements[i] && !this.formElements[i].hasAttribute('aria-hidden')) {
851
- return i;
852
- }
853
- }
854
- }
855
-
856
- // If above was unsuccessful, return currentIndex that we started with
857
- return currentIndex;
858
837
  }
859
838
 
860
- /**
861
- * Moves options put in unnamed slot to slot with [role="listbox"]
862
- * @private
863
- */
864
- __moveOptionsToListboxNode() {
865
- const slot = /** @type {HTMLSlotElement} */ (
866
- /** @type {ShadowRoot} */ (this.shadowRoot).getElementById('options-outlet')
867
- );
868
-
869
- if (slot) {
839
+ // If above was unsuccessful, return currentIndex that we started with
840
+ return currentIndex;
841
+ }
842
+
843
+ /**
844
+ * Moves options put in unnamed slot to slot with [role="listbox"]
845
+ * @private
846
+ */
847
+ __moveOptionsToListboxNode() {
848
+ const slot = /** @type {HTMLSlotElement} */
849
+ /** @type {ShadowRoot} */this.shadowRoot.getElementById('options-outlet');
850
+ if (slot) {
851
+ moveUserProvidedDefaultSlottablesToTarget(this, this._listboxNode);
852
+ slot.addEventListener('slotchange', () => {
870
853
  moveUserProvidedDefaultSlottablesToTarget(this, this._listboxNode);
871
- slot.addEventListener('slotchange', () => {
872
- moveUserProvidedDefaultSlottablesToTarget(this, this._listboxNode);
873
- });
874
- }
854
+ });
875
855
  }
876
-
877
- /**
878
- * @param {KeyboardEvent} ev
879
- * @private
880
- */
881
- __preventScrollingWithArrowKeys(ev) {
882
- if (this.disabled) {
883
- return;
856
+ }
857
+
858
+ /**
859
+ * @param {KeyboardEvent} ev
860
+ * @private
861
+ */
862
+ __preventScrollingWithArrowKeys(ev) {
863
+ if (this.disabled) {
864
+ return;
865
+ }
866
+ const {
867
+ key
868
+ } = ev;
869
+ switch (key) {
870
+ case 'ArrowUp':
871
+ case 'ArrowDown':
872
+ case 'Home':
873
+ case 'End':
874
+ ev.preventDefault();
875
+ /* no default */
876
+ }
877
+ }
878
+
879
+ /**
880
+ * Helper method used within `._setupListboxNode`
881
+ * @private
882
+ */
883
+ __setupListboxNodeInteractions() {
884
+ this._listboxNode.setAttribute('role', 'listbox');
885
+ this._listboxNode.setAttribute('aria-orientation', this.orientation);
886
+ this._listboxNode.setAttribute('aria-multiselectable', `${this.multipleChoice}`);
887
+ this._listboxNode.setAttribute('tabindex', '0');
888
+ this._listboxNode.addEventListener('click', this._listboxOnClick);
889
+ this._listboxNode.addEventListener('keyup', this._listboxOnKeyUp);
890
+ this._listboxNode.addEventListener('keydown', this._listboxOnKeyDown);
891
+ /** Since _scrollTargetNode can be _listboxNode, handle here */
892
+ this._scrollTargetNode.addEventListener('keydown', this.__preventScrollingWithArrowKeys);
893
+ }
894
+
895
+ // TODO: move to ChoiceGroupMixin?
896
+ /** @private */
897
+ __requestOptionsToBeDisabled() {
898
+ this.formElements.forEach(el => {
899
+ if (el.makeRequestToBeDisabled) {
900
+ el.makeRequestToBeDisabled();
884
901
  }
885
- const { key } = ev;
886
- switch (key) {
887
- case 'ArrowUp':
888
- case 'ArrowDown':
889
- case 'Home':
890
- case 'End':
891
- ev.preventDefault();
892
- /* no default */
902
+ });
903
+ }
904
+
905
+ /** @private */
906
+ __retractRequestOptionsToBeDisabled() {
907
+ this.formElements.forEach(el => {
908
+ if (el.retractRequestToBeDisabled) {
909
+ el.retractRequestToBeDisabled();
893
910
  }
894
- }
895
-
896
- /**
897
- * Helper method used within `._setupListboxNode`
898
- * @private
899
- */
900
- __setupListboxNodeInteractions() {
901
- this._listboxNode.setAttribute('role', 'listbox');
902
- this._listboxNode.setAttribute('aria-orientation', this.orientation);
903
- this._listboxNode.setAttribute('aria-multiselectable', `${this.multipleChoice}`);
904
- this._listboxNode.setAttribute('tabindex', '0');
905
- this._listboxNode.addEventListener('click', this._listboxOnClick);
906
- this._listboxNode.addEventListener('keyup', this._listboxOnKeyUp);
907
- this._listboxNode.addEventListener('keydown', this._listboxOnKeyDown);
908
- /** Since _scrollTargetNode can be _listboxNode, handle here */
909
- this._scrollTargetNode.addEventListener('keydown', this.__preventScrollingWithArrowKeys);
910
- }
911
-
912
- // TODO: move to ChoiceGroupMixin?
913
- /** @private */
914
- __requestOptionsToBeDisabled() {
915
- this.formElements.forEach(el => {
916
- if (el.makeRequestToBeDisabled) {
917
- el.makeRequestToBeDisabled();
918
- }
919
- });
920
- }
921
-
922
- /** @private */
923
- __retractRequestOptionsToBeDisabled() {
924
- this.formElements.forEach(el => {
925
- if (el.retractRequestToBeDisabled) {
926
- el.retractRequestToBeDisabled();
927
- }
928
- });
929
- }
930
-
931
- /** @private */
932
- __initInteractionStates() {
933
- this.initInteractionState();
934
- }
935
- });
936
-
911
+ });
912
+ }
913
+
914
+ /** @private */
915
+ __initInteractionStates() {
916
+ this.initInteractionState();
917
+ }
918
+ };
937
919
  export const ListboxMixin = dedupeMixin(ListboxMixinImplementation);