@lion/ui 0.24.0 → 0.26.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 (789) hide show
  1. package/README.md +25 -7
  2. package/accordion-test-suites.js +2 -0
  3. package/collapsible-test-suites.js +1 -0
  4. package/combobox-test-suites.js +2 -0
  5. package/components/accordion/test/lion-accordion.test.js +2 -565
  6. package/components/accordion/test-suites/lion-accordion.suite.js +596 -0
  7. package/components/button/test-suites/LionButton.suite.js +13 -11
  8. package/components/button/test-suites/LionButtonReset.suite.js +11 -3
  9. package/components/button/test-suites/LionButtonSubmit.suite.js +11 -3
  10. package/components/calendar/test/lion-calendar.test.js +1 -1570
  11. package/components/calendar/test-suites/LionCalendar.suite.js +1617 -5
  12. package/components/checkbox-group/test/lion-checkbox-group-integrations.test.js +5 -2
  13. package/components/checkbox-group/test/lion-checkbox-indeterminate-integrations.test.js +13 -4
  14. package/components/checkbox-group/test/lion-checkbox-integrations.test.js +4 -1
  15. package/components/checkbox-group/test-suites/CheckboxIndeterminate.suite.js +54 -54
  16. package/components/collapsible/test/lion-collapsible.test.js +2 -126
  17. package/components/collapsible/test-suites/LionCollapsible.suite.js +147 -0
  18. package/components/combobox/test/lion-combobox-integrations.test.js +11 -4
  19. package/components/combobox/test/lion-combobox.test.js +2 -3622
  20. package/components/combobox/test-suites/lion-combobox.suite.js +3665 -0
  21. package/components/core/src/ScopedElementsMixin.js +16 -1
  22. package/components/core/test-helpers/isElementVisible.js +21 -0
  23. package/components/core/test-helpers/resolveSuiteTag.js +97 -0
  24. package/components/core/types/TestSuiteTypes.ts +43 -0
  25. package/components/dialog/test/lion-dialog.integration.test.js +9 -10
  26. package/components/dialog/test/lion-dialog.test.js +2 -399
  27. package/components/dialog/test-suites/lion-dialog.suite.js +412 -0
  28. package/components/drawer/test/lion-drawer.test.js +2 -84
  29. package/components/drawer/test-suites/LionDrawer.suite.js +108 -0
  30. package/components/fieldset/test/lion-fieldset.test.js +7 -2
  31. package/components/form/test/lion-form.test.js +2 -348
  32. package/components/form/test-suites/lion-form.suite.js +398 -0
  33. package/components/form-core/test/FormatMixin.test.js +4 -1
  34. package/components/form-core/test/choice-group/CustomChoiceGroupMixin.integrations.test.js +13 -0
  35. package/components/form-core/test-suites/FormRegistrationMixins.suite.js +21 -26
  36. package/components/form-core/test-suites/FormatMixin.suite.js +45 -43
  37. package/components/form-core/test-suites/InteractionStateMixin.suite.js +19 -15
  38. package/components/form-core/test-suites/NativeTextFieldMixin.suite.js +8 -9
  39. package/components/form-core/test-suites/ValidateMixin.suite.js +14 -10
  40. package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +15 -2
  41. package/components/form-core/test-suites/choice-group/ChoiceGroupMixin.suite.js +55 -33
  42. package/components/form-core/test-suites/choice-group/ChoiceInputMixin.suite.js +7 -6
  43. package/components/form-core/test-suites/choice-group/CustomChoiceGroupMixin.suite.js +19 -22
  44. package/components/form-core/test-suites/form-group/FormGroupMixin-input.suite.js +14 -5
  45. package/components/form-core/test-suites/form-group/FormGroupMixin.suite.js +13 -4
  46. package/components/icon/test/lion-icon.test.js +2 -188
  47. package/components/icon/test-suites/lion-icon.suite.js +206 -0
  48. package/components/input/test/input-integrations.test.js +18 -15
  49. package/components/input/test/lion-input-integrations.test.js +7 -3
  50. package/components/input/test/lion-input.test.js +2 -198
  51. package/components/input/test-suites/lion-input.suite.js +214 -0
  52. package/components/input-amount/src/parsers.js +5 -1
  53. package/components/input-amount/test/lion-input-amount-integrations.test.js +7 -3
  54. package/components/input-amount/test/lion-input-amount.test.js +2 -421
  55. package/components/input-amount/test/parsers.test.js +12 -0
  56. package/components/input-amount/test-suites/lion-input-amount.suite.js +418 -0
  57. package/components/input-amount-dropdown/test/LionInputAmountDropdown.test.js +3 -2
  58. package/components/input-amount-dropdown/test/lion-input-amount-dropdown-integrations.test.js +4 -2
  59. package/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.js +6 -4
  60. package/components/input-date/test/lion-input-date-integrations.test.js +7 -3
  61. package/components/input-date/test/lion-input-date.test.js +2 -177
  62. package/components/input-date/test-suites/lion-input-date.suite.js +195 -0
  63. package/components/input-datepicker/test/lion-input-datepicker-integrations.test.js +7 -3
  64. package/components/input-datepicker/test/lion-input-datepicker.test.js +1 -844
  65. package/components/input-datepicker/test-helpers/DatepickerInputObject.js +26 -0
  66. package/components/input-datepicker/test-suites/LionInputDatepicker.suite.js +899 -14
  67. package/components/input-email/test/lion-input-email-integrations.test.js +4 -2
  68. package/components/input-email/test/lion-input-email.test.js +2 -46
  69. package/components/input-email/test-suites/lion-input-email.suite.js +63 -0
  70. package/components/input-file/test/lion-input-file.test.js +2 -1274
  71. package/components/input-file/test-suites/lion-input-file.suite.js +1505 -0
  72. package/components/input-iban/test/lion-input-iban-integrations.test.js +4 -2
  73. package/components/input-iban/test/lion-input-iban.test.js +2 -73
  74. package/components/input-iban/test-suites/lion-input-iban.suite.js +88 -0
  75. package/components/input-range/test/lion-input-range.test.js +2 -176
  76. package/components/input-range/test-suites/lion-input-range.suite.js +195 -0
  77. package/components/input-stepper/test-suites/lion-input-stepper.integration.suite.js +14 -3
  78. package/components/input-stepper/test-suites/lion-input-stepper.suite.js +14 -10
  79. package/components/input-tel/test/LionInputTel.test.js +3 -1
  80. package/components/input-tel/test/parsers.test.js +87 -0
  81. package/components/input-tel/test-helpers/mockPhoneUtilManager.js +14 -3
  82. package/components/input-tel/test-suites/LionInputTel.suite.js +9 -4
  83. package/components/input-tel-dropdown/test/LionInputTelDropdown.test.js +6 -4
  84. package/components/input-tel-dropdown/test-suites/LionInputTelDropdown--parentheses.suite.js +10 -13
  85. package/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js +6 -5
  86. package/components/listbox/src/LionListbox.js +1 -1
  87. package/components/listbox/test-suites/ListboxMixin.suite.js +19 -19
  88. package/components/menu/test-suites/InteractiveListMixin.suite.js +6 -9
  89. package/components/menu/test-suites/LionMenu.suite.js +6 -10
  90. package/components/menu/test-suites/LionMenuInteractions.suite.js +13 -4
  91. package/components/menu/test-suites/MoreButtonMenuMixin.suite.js +6 -9
  92. package/components/menu/test-suites/MultiLevelListMixin.suite.js +15 -11
  93. package/components/overlays/src/OverlayController.js +7 -2
  94. package/components/overlays/src/OverlayMixin.js +3 -6
  95. package/components/overlays/test/OverlayController.test.js +37 -1
  96. package/components/overlays/test/invoker-compatibility.test.js +37 -0
  97. package/components/overlays/test-suites/OverlayMixin.suite.js +3 -5
  98. package/components/pagination/test/lion-pagination.test.js +2 -176
  99. package/components/pagination/test-suites/LionPagination.suite.js +201 -0
  100. package/components/progress-indicator/test/lion-progress-indicator.test.js +2 -203
  101. package/components/progress-indicator/test-suites/lion-progress-indicator.suite.js +214 -0
  102. package/components/radio-group/test/lion-radio-group.test.js +2 -162
  103. package/components/radio-group/test/lion-radio.test.js +2 -54
  104. package/components/radio-group/test-suites/lion-radio-group.suite.js +173 -0
  105. package/components/radio-group/test-suites/lion-radio.suite.js +70 -0
  106. package/components/select/test/lion-select.test.js +2 -79
  107. package/components/select/test-suites/LionSelect.suite.js +94 -0
  108. package/components/select-rich/src/LionSelectRich.js +2 -1
  109. package/components/select-rich/test/lion-select-invoker.test.js +2 -86
  110. package/components/select-rich/test/lion-select-rich-interaction.test.js +2 -430
  111. package/components/select-rich/test/lion-select-rich.test.js +2 -1193
  112. package/components/select-rich/test-suites/lion-select-invoker.suite.js +98 -0
  113. package/components/select-rich/test-suites/lion-select-rich-interaction.suite.js +452 -0
  114. package/components/select-rich/test-suites/lion-select-rich.suite.js +1236 -0
  115. package/components/steps/test/lion-step.test.js +2 -97
  116. package/components/steps/test/lion-steps.test.js +2 -433
  117. package/components/steps/test-suites/lion-step.suite.js +113 -0
  118. package/components/steps/test-suites/lion-steps.suite.js +445 -0
  119. package/components/switch/test/lion-switch.test.js +2 -232
  120. package/components/switch/test-suites/lion-switch.suite.js +450 -0
  121. package/components/tabs/test/lion-tabs.test.js +2 -596
  122. package/components/tabs/test-suites/lion-tabs.suite.js +617 -0
  123. package/components/textarea/src/LionTextarea.js +5 -2
  124. package/components/textarea/test/lion-textarea.test.js +2 -159
  125. package/components/textarea/test-suites/lion-textarea.suite.js +192 -0
  126. package/components/tooltip/test/lion-tooltip.test.js +2 -393
  127. package/components/tooltip/test-suites/lion-tooltip.suite.js +409 -0
  128. package/custom-elements.json +14890 -10187
  129. package/dialog-test-suites.js +2 -0
  130. package/dist-types/components/accordion/test/lion-accordion.test.d.ts +1 -2
  131. package/dist-types/components/accordion/test/lion-accordion.test.d.ts.map +1 -1
  132. package/dist-types/components/accordion/test-suites/lion-accordion.suite.d.ts +18 -0
  133. package/dist-types/components/accordion/test-suites/lion-accordion.suite.d.ts.map +1 -0
  134. package/dist-types/components/button/test-suites/LionButton.suite.d.ts +10 -4
  135. package/dist-types/components/button/test-suites/LionButton.suite.d.ts.map +1 -1
  136. package/dist-types/components/button/test-suites/LionButtonReset.suite.d.ts +10 -4
  137. package/dist-types/components/button/test-suites/LionButtonReset.suite.d.ts.map +1 -1
  138. package/dist-types/components/button/test-suites/LionButtonSubmit.suite.d.ts +10 -4
  139. package/dist-types/components/button/test-suites/LionButtonSubmit.suite.d.ts.map +1 -1
  140. package/dist-types/components/calendar/test/lion-calendar.test.d.ts +1 -3
  141. package/dist-types/components/calendar/test/lion-calendar.test.d.ts.map +1 -1
  142. package/dist-types/components/calendar/test-suites/LionCalendar.suite.d.ts +13 -4
  143. package/dist-types/components/calendar/test-suites/LionCalendar.suite.d.ts.map +1 -1
  144. package/dist-types/components/checkbox-group/test/lion-checkbox-group-integrations.test.d.ts.map +1 -1
  145. package/dist-types/components/checkbox-group/test/lion-checkbox-integrations.test.d.ts.map +1 -1
  146. package/dist-types/components/checkbox-group/test-suites/CheckboxIndeterminate.suite.d.ts +12 -9
  147. package/dist-types/components/checkbox-group/test-suites/CheckboxIndeterminate.suite.d.ts.map +1 -1
  148. package/dist-types/components/collapsible/test/lion-collapsible.test.d.ts +1 -3
  149. package/dist-types/components/collapsible/test/lion-collapsible.test.d.ts.map +1 -1
  150. package/dist-types/components/collapsible/test-suites/LionCollapsible.suite.d.ts +18 -0
  151. package/dist-types/components/collapsible/test-suites/LionCollapsible.suite.d.ts.map +1 -0
  152. package/dist-types/components/combobox/test/lion-combobox.test.d.ts +1 -5
  153. package/dist-types/components/combobox/test/lion-combobox.test.d.ts.map +1 -1
  154. package/dist-types/components/combobox/test-suites/lion-combobox.suite.d.ts +17 -0
  155. package/dist-types/components/combobox/test-suites/lion-combobox.suite.d.ts.map +1 -0
  156. package/dist-types/components/core/src/ScopedElementsMixin.d.ts.map +1 -1
  157. package/dist-types/components/core/test-helpers/isElementVisible.d.ts +12 -0
  158. package/dist-types/components/core/test-helpers/isElementVisible.d.ts.map +1 -0
  159. package/dist-types/components/core/test-helpers/resolveSuiteTag.d.ts +29 -0
  160. package/dist-types/components/core/test-helpers/resolveSuiteTag.d.ts.map +1 -0
  161. package/dist-types/components/core/types/TestSuiteTypes.d.ts +40 -0
  162. package/dist-types/components/core/types/TestSuiteTypes.d.ts.map +1 -0
  163. package/dist-types/components/dialog/test/lion-dialog.integration.test.d.ts.map +1 -1
  164. package/dist-types/components/dialog/test/lion-dialog.test.d.ts +1 -5
  165. package/dist-types/components/dialog/test/lion-dialog.test.d.ts.map +1 -1
  166. package/dist-types/components/dialog/test-suites/lion-dialog.suite.d.ts +19 -0
  167. package/dist-types/components/dialog/test-suites/lion-dialog.suite.d.ts.map +1 -0
  168. package/dist-types/components/drawer/test/lion-drawer.test.d.ts +1 -3
  169. package/dist-types/components/drawer/test/lion-drawer.test.d.ts.map +1 -1
  170. package/dist-types/components/drawer/test-suites/LionDrawer.suite.d.ts +20 -0
  171. package/dist-types/components/drawer/test-suites/LionDrawer.suite.d.ts.map +1 -0
  172. package/dist-types/components/fieldset/test/lion-fieldset.test.d.ts.map +1 -1
  173. package/dist-types/components/form/test/lion-form.test.d.ts +1 -12
  174. package/dist-types/components/form/test/lion-form.test.d.ts.map +1 -1
  175. package/dist-types/components/form/test-suites/lion-form.suite.d.ts +39 -0
  176. package/dist-types/components/form/test-suites/lion-form.suite.d.ts.map +1 -0
  177. package/dist-types/components/form-core/test-suites/FormRegistrationMixins.suite.d.ts +14 -17
  178. package/dist-types/components/form-core/test-suites/FormRegistrationMixins.suite.d.ts.map +1 -1
  179. package/dist-types/components/form-core/test-suites/FormatMixin.suite.d.ts +22 -38
  180. package/dist-types/components/form-core/test-suites/FormatMixin.suite.d.ts.map +1 -1
  181. package/dist-types/components/form-core/test-suites/InteractionStateMixin.suite.d.ts +11 -5
  182. package/dist-types/components/form-core/test-suites/InteractionStateMixin.suite.d.ts.map +1 -1
  183. package/dist-types/components/form-core/test-suites/NativeTextFieldMixin.suite.d.ts +9 -4
  184. package/dist-types/components/form-core/test-suites/NativeTextFieldMixin.suite.d.ts.map +1 -1
  185. package/dist-types/components/form-core/test-suites/ValidateMixin.suite.d.ts +9 -4
  186. package/dist-types/components/form-core/test-suites/ValidateMixin.suite.d.ts.map +1 -1
  187. package/dist-types/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.d.ts +10 -1
  188. package/dist-types/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.d.ts.map +1 -1
  189. package/dist-types/components/form-core/test-suites/choice-group/ChoiceGroupMixin.suite.d.ts +17 -6
  190. package/dist-types/components/form-core/test-suites/choice-group/ChoiceGroupMixin.suite.d.ts.map +1 -1
  191. package/dist-types/components/form-core/test-suites/choice-group/ChoiceInputMixin.suite.d.ts +5 -2
  192. package/dist-types/components/form-core/test-suites/choice-group/ChoiceInputMixin.suite.d.ts.map +1 -1
  193. package/dist-types/components/form-core/test-suites/choice-group/CustomChoiceGroupMixin.suite.d.ts +10 -5
  194. package/dist-types/components/form-core/test-suites/choice-group/CustomChoiceGroupMixin.suite.d.ts.map +1 -1
  195. package/dist-types/components/form-core/test-suites/form-group/FormGroupMixin-input.suite.d.ts +10 -5
  196. package/dist-types/components/form-core/test-suites/form-group/FormGroupMixin-input.suite.d.ts.map +1 -1
  197. package/dist-types/components/form-core/test-suites/form-group/FormGroupMixin.suite.d.ts +10 -5
  198. package/dist-types/components/form-core/test-suites/form-group/FormGroupMixin.suite.d.ts.map +1 -1
  199. package/dist-types/components/icon/test/lion-icon.test.d.ts +1 -4
  200. package/dist-types/components/icon/test/lion-icon.test.d.ts.map +1 -1
  201. package/dist-types/components/icon/test-suites/lion-icon.suite.d.ts +16 -0
  202. package/dist-types/components/icon/test-suites/lion-icon.suite.d.ts.map +1 -0
  203. package/dist-types/components/input/test/lion-input-integrations.test.d.ts.map +1 -1
  204. package/dist-types/components/input/test/lion-input.test.d.ts +1 -2
  205. package/dist-types/components/input/test/lion-input.test.d.ts.map +1 -1
  206. package/dist-types/components/input/test-suites/lion-input.suite.d.ts +17 -0
  207. package/dist-types/components/input/test-suites/lion-input.suite.d.ts.map +1 -0
  208. package/dist-types/components/input-amount/src/parsers.d.ts.map +1 -1
  209. package/dist-types/components/input-amount/test/lion-input-amount-integrations.test.d.ts.map +1 -1
  210. package/dist-types/components/input-amount/test/lion-input-amount.test.d.ts +1 -2
  211. package/dist-types/components/input-amount/test/lion-input-amount.test.d.ts.map +1 -1
  212. package/dist-types/components/input-amount/test-suites/lion-input-amount.suite.d.ts +19 -0
  213. package/dist-types/components/input-amount/test-suites/lion-input-amount.suite.d.ts.map +1 -0
  214. package/dist-types/components/input-amount-dropdown/test/lion-input-amount-dropdown-integrations.test.d.ts.map +1 -1
  215. package/dist-types/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.d.ts +7 -3
  216. package/dist-types/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.d.ts.map +1 -1
  217. package/dist-types/components/input-date/test/lion-input-date-integrations.test.d.ts.map +1 -1
  218. package/dist-types/components/input-date/test/lion-input-date.test.d.ts +1 -3
  219. package/dist-types/components/input-date/test/lion-input-date.test.d.ts.map +1 -1
  220. package/dist-types/components/input-date/test-suites/lion-input-date.suite.d.ts +15 -0
  221. package/dist-types/components/input-date/test-suites/lion-input-date.suite.d.ts.map +1 -0
  222. package/dist-types/components/input-datepicker/test/lion-input-datepicker-integrations.test.d.ts.map +1 -1
  223. package/dist-types/components/input-datepicker/test/lion-input-datepicker.test.d.ts +1 -2
  224. package/dist-types/components/input-datepicker/test/lion-input-datepicker.test.d.ts.map +1 -1
  225. package/dist-types/components/input-datepicker/test-helpers/DatepickerInputObject.d.ts +8 -0
  226. package/dist-types/components/input-datepicker/test-helpers/DatepickerInputObject.d.ts.map +1 -1
  227. package/dist-types/components/input-datepicker/test-suites/LionInputDatepicker.suite.d.ts +15 -5
  228. package/dist-types/components/input-datepicker/test-suites/LionInputDatepicker.suite.d.ts.map +1 -1
  229. package/dist-types/components/input-email/test/lion-input-email-integrations.test.d.ts.map +1 -1
  230. package/dist-types/components/input-email/test/lion-input-email.test.d.ts +1 -3
  231. package/dist-types/components/input-email/test/lion-input-email.test.d.ts.map +1 -1
  232. package/dist-types/components/input-email/test-suites/lion-input-email.suite.d.ts +15 -0
  233. package/dist-types/components/input-email/test-suites/lion-input-email.suite.d.ts.map +1 -0
  234. package/dist-types/components/input-file/test/lion-input-file.test.d.ts +1 -5
  235. package/dist-types/components/input-file/test/lion-input-file.test.d.ts.map +1 -1
  236. package/dist-types/components/input-file/test-suites/lion-input-file.suite.d.ts +19 -0
  237. package/dist-types/components/input-file/test-suites/lion-input-file.suite.d.ts.map +1 -0
  238. package/dist-types/components/input-iban/test/lion-input-iban-integrations.test.d.ts.map +1 -1
  239. package/dist-types/components/input-iban/test/lion-input-iban.test.d.ts +1 -3
  240. package/dist-types/components/input-iban/test/lion-input-iban.test.d.ts.map +1 -1
  241. package/dist-types/components/input-iban/test-suites/lion-input-iban.suite.d.ts +15 -0
  242. package/dist-types/components/input-iban/test-suites/lion-input-iban.suite.d.ts.map +1 -0
  243. package/dist-types/components/input-range/test/lion-input-range.test.d.ts +1 -3
  244. package/dist-types/components/input-range/test/lion-input-range.test.d.ts.map +1 -1
  245. package/dist-types/components/input-range/test-suites/lion-input-range.suite.d.ts +15 -0
  246. package/dist-types/components/input-range/test-suites/lion-input-range.suite.d.ts.map +1 -0
  247. package/dist-types/components/input-stepper/test-suites/lion-input-stepper.integration.suite.d.ts +10 -2
  248. package/dist-types/components/input-stepper/test-suites/lion-input-stepper.integration.suite.d.ts.map +1 -1
  249. package/dist-types/components/input-stepper/test-suites/lion-input-stepper.suite.d.ts +10 -2
  250. package/dist-types/components/input-stepper/test-suites/lion-input-stepper.suite.d.ts.map +1 -1
  251. package/dist-types/components/input-tel/test-helpers/mockPhoneUtilManager.d.ts +5 -0
  252. package/dist-types/components/input-tel/test-helpers/mockPhoneUtilManager.d.ts.map +1 -1
  253. package/dist-types/components/input-tel/test-suites/LionInputTel.suite.d.ts +6 -4
  254. package/dist-types/components/input-tel/test-suites/LionInputTel.suite.d.ts.map +1 -1
  255. package/dist-types/components/input-tel-dropdown/test-suites/LionInputTelDropdown--parentheses.suite.d.ts +7 -3
  256. package/dist-types/components/input-tel-dropdown/test-suites/LionInputTelDropdown--parentheses.suite.d.ts.map +1 -1
  257. package/dist-types/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.d.ts +7 -3
  258. package/dist-types/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.d.ts.map +1 -1
  259. package/dist-types/components/listbox/src/LionListbox.d.ts +2 -2
  260. package/dist-types/components/listbox/src/LionListbox.d.ts.map +1 -1
  261. package/dist-types/components/listbox/test-suites/ListboxMixin.suite.d.ts +3 -4
  262. package/dist-types/components/listbox/test-suites/ListboxMixin.suite.d.ts.map +1 -1
  263. package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts +6 -5
  264. package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts.map +1 -1
  265. package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts +6 -5
  266. package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts.map +1 -1
  267. package/dist-types/components/menu/test-suites/LionMenuInteractions.suite.d.ts +10 -4
  268. package/dist-types/components/menu/test-suites/LionMenuInteractions.suite.d.ts.map +1 -1
  269. package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts +6 -5
  270. package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts.map +1 -1
  271. package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts +7 -6
  272. package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts.map +1 -1
  273. package/dist-types/components/overlays/src/OverlayController.d.ts +3 -1
  274. package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
  275. package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
  276. package/dist-types/components/overlays/test/invoker-compatibility.test.d.ts +3 -0
  277. package/dist-types/components/overlays/test/invoker-compatibility.test.d.ts.map +1 -0
  278. package/dist-types/components/overlays/test-suites/OverlayMixin.suite.d.ts.map +1 -1
  279. package/dist-types/components/pagination/test/lion-pagination.test.d.ts +1 -3
  280. package/dist-types/components/pagination/test/lion-pagination.test.d.ts.map +1 -1
  281. package/dist-types/components/pagination/test-suites/LionPagination.suite.d.ts +18 -0
  282. package/dist-types/components/pagination/test-suites/LionPagination.suite.d.ts.map +1 -0
  283. package/dist-types/components/progress-indicator/test/lion-progress-indicator.test.d.ts +1 -3
  284. package/dist-types/components/progress-indicator/test/lion-progress-indicator.test.d.ts.map +1 -1
  285. package/dist-types/components/progress-indicator/test-suites/lion-progress-indicator.suite.d.ts +15 -0
  286. package/dist-types/components/progress-indicator/test-suites/lion-progress-indicator.suite.d.ts.map +1 -0
  287. package/dist-types/components/radio-group/test/lion-radio-group.test.d.ts +1 -5
  288. package/dist-types/components/radio-group/test/lion-radio-group.test.d.ts.map +1 -1
  289. package/dist-types/components/radio-group/test/lion-radio.test.d.ts +1 -2
  290. package/dist-types/components/radio-group/test/lion-radio.test.d.ts.map +1 -1
  291. package/dist-types/components/radio-group/test-suites/lion-radio-group.suite.d.ts +19 -0
  292. package/dist-types/components/radio-group/test-suites/lion-radio-group.suite.d.ts.map +1 -0
  293. package/dist-types/components/radio-group/test-suites/lion-radio.suite.d.ts +17 -0
  294. package/dist-types/components/radio-group/test-suites/lion-radio.suite.d.ts.map +1 -0
  295. package/dist-types/components/select/test/lion-select.test.d.ts +1 -2
  296. package/dist-types/components/select/test/lion-select.test.d.ts.map +1 -1
  297. package/dist-types/components/select/test-suites/LionSelect.suite.d.ts +16 -0
  298. package/dist-types/components/select/test-suites/LionSelect.suite.d.ts.map +1 -0
  299. package/dist-types/components/select-rich/src/LionSelectRich.d.ts +5 -4
  300. package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
  301. package/dist-types/components/select-rich/test/lion-select-invoker.test.d.ts +1 -2
  302. package/dist-types/components/select-rich/test/lion-select-invoker.test.d.ts.map +1 -1
  303. package/dist-types/components/select-rich/test/lion-select-rich-interaction.test.d.ts +1 -5
  304. package/dist-types/components/select-rich/test/lion-select-rich-interaction.test.d.ts.map +1 -1
  305. package/dist-types/components/select-rich/test/lion-select-rich.test.d.ts +1 -8
  306. package/dist-types/components/select-rich/test/lion-select-rich.test.d.ts.map +1 -1
  307. package/dist-types/components/select-rich/test-suites/lion-select-invoker.suite.d.ts +19 -0
  308. package/dist-types/components/select-rich/test-suites/lion-select-invoker.suite.d.ts.map +1 -0
  309. package/dist-types/components/select-rich/test-suites/lion-select-rich-interaction.suite.d.ts +19 -0
  310. package/dist-types/components/select-rich/test-suites/lion-select-rich-interaction.suite.d.ts.map +1 -0
  311. package/dist-types/components/select-rich/test-suites/lion-select-rich.suite.d.ts +21 -0
  312. package/dist-types/components/select-rich/test-suites/lion-select-rich.suite.d.ts.map +1 -0
  313. package/dist-types/components/steps/test/lion-step.test.d.ts +1 -2
  314. package/dist-types/components/steps/test/lion-step.test.d.ts.map +1 -1
  315. package/dist-types/components/steps/test/lion-steps.test.d.ts +1 -8
  316. package/dist-types/components/steps/test/lion-steps.test.d.ts.map +1 -1
  317. package/dist-types/components/steps/test-suites/lion-step.suite.d.ts +17 -0
  318. package/dist-types/components/steps/test-suites/lion-step.suite.d.ts.map +1 -0
  319. package/dist-types/components/steps/test-suites/lion-steps.suite.d.ts +22 -0
  320. package/dist-types/components/steps/test-suites/lion-steps.suite.d.ts.map +1 -0
  321. package/dist-types/components/switch/test/lion-switch.test.d.ts +1 -4
  322. package/dist-types/components/switch/test/lion-switch.test.d.ts.map +1 -1
  323. package/dist-types/components/switch/test-suites/lion-switch.suite.d.ts +17 -0
  324. package/dist-types/components/switch/test-suites/lion-switch.suite.d.ts.map +1 -0
  325. package/dist-types/components/tabs/test/lion-tabs.test.d.ts +1 -5
  326. package/dist-types/components/tabs/test/lion-tabs.test.d.ts.map +1 -1
  327. package/dist-types/components/tabs/test-suites/lion-tabs.suite.d.ts +17 -0
  328. package/dist-types/components/tabs/test-suites/lion-tabs.suite.d.ts.map +1 -0
  329. package/dist-types/components/textarea/src/LionTextarea.d.ts.map +1 -1
  330. package/dist-types/components/textarea/test/lion-textarea.test.d.ts +1 -3
  331. package/dist-types/components/textarea/test/lion-textarea.test.d.ts.map +1 -1
  332. package/dist-types/components/textarea/test-suites/lion-textarea.suite.d.ts +15 -0
  333. package/dist-types/components/textarea/test-suites/lion-textarea.suite.d.ts.map +1 -0
  334. package/dist-types/components/tooltip/test/lion-tooltip.test.d.ts +1 -3
  335. package/dist-types/components/tooltip/test/lion-tooltip.test.d.ts.map +1 -1
  336. package/dist-types/components/tooltip/test-suites/lion-tooltip.suite.d.ts +19 -0
  337. package/dist-types/components/tooltip/test-suites/lion-tooltip.suite.d.ts.map +1 -0
  338. package/dist-types/exports/accordion-test-suites.d.ts +2 -0
  339. package/dist-types/exports/accordion-test-suites.d.ts.map +1 -0
  340. package/dist-types/exports/collapsible-test-suites.d.ts +2 -0
  341. package/dist-types/exports/collapsible-test-suites.d.ts.map +1 -0
  342. package/dist-types/exports/combobox-test-suites.d.ts +2 -0
  343. package/dist-types/exports/combobox-test-suites.d.ts.map +1 -0
  344. package/dist-types/exports/dialog-test-suites.d.ts +2 -0
  345. package/dist-types/exports/dialog-test-suites.d.ts.map +1 -0
  346. package/dist-types/exports/drawer-test-suites.d.ts +2 -0
  347. package/dist-types/exports/drawer-test-suites.d.ts.map +1 -0
  348. package/dist-types/exports/form-test-suites.d.ts +2 -0
  349. package/dist-types/exports/form-test-suites.d.ts.map +1 -0
  350. package/dist-types/exports/icon-test-suites.d.ts +2 -0
  351. package/dist-types/exports/icon-test-suites.d.ts.map +1 -0
  352. package/dist-types/exports/input-amount-test-suites.d.ts +2 -0
  353. package/dist-types/exports/input-amount-test-suites.d.ts.map +1 -0
  354. package/dist-types/exports/input-date-test-suites.d.ts +2 -0
  355. package/dist-types/exports/input-date-test-suites.d.ts.map +1 -0
  356. package/dist-types/exports/input-email-test-suites.d.ts +2 -0
  357. package/dist-types/exports/input-email-test-suites.d.ts.map +1 -0
  358. package/dist-types/exports/input-file-test-suites.d.ts +2 -0
  359. package/dist-types/exports/input-file-test-suites.d.ts.map +1 -0
  360. package/dist-types/exports/input-iban-test-suites.d.ts +2 -0
  361. package/dist-types/exports/input-iban-test-suites.d.ts.map +1 -0
  362. package/dist-types/exports/input-range-test-suites.d.ts +2 -0
  363. package/dist-types/exports/input-range-test-suites.d.ts.map +1 -0
  364. package/dist-types/exports/input-stepper-suites.d.ts +7 -2
  365. package/dist-types/exports/input-stepper-suites.d.ts.map +1 -1
  366. package/dist-types/exports/input-test-suites.d.ts +2 -0
  367. package/dist-types/exports/input-test-suites.d.ts.map +1 -0
  368. package/dist-types/exports/menu-test-suites.d.ts.map +1 -1
  369. package/dist-types/exports/pagination-test-suites.d.ts +2 -0
  370. package/dist-types/exports/pagination-test-suites.d.ts.map +1 -0
  371. package/dist-types/exports/progress-indicator-test-suites.d.ts +2 -0
  372. package/dist-types/exports/progress-indicator-test-suites.d.ts.map +1 -0
  373. package/dist-types/exports/radio-group-test-suites.d.ts +3 -0
  374. package/dist-types/exports/radio-group-test-suites.d.ts.map +1 -0
  375. package/dist-types/exports/select-rich-test-suites.d.ts +4 -0
  376. package/dist-types/exports/select-rich-test-suites.d.ts.map +1 -0
  377. package/dist-types/exports/select-test-suites.d.ts +2 -0
  378. package/dist-types/exports/select-test-suites.d.ts.map +1 -0
  379. package/dist-types/exports/steps-test-suites.d.ts +3 -0
  380. package/dist-types/exports/steps-test-suites.d.ts.map +1 -0
  381. package/dist-types/exports/switch-test-suites.d.ts +2 -0
  382. package/dist-types/exports/switch-test-suites.d.ts.map +1 -0
  383. package/dist-types/exports/tabs-test-suites.d.ts +2 -0
  384. package/dist-types/exports/tabs-test-suites.d.ts.map +1 -0
  385. package/dist-types/exports/textarea-test-suites.d.ts +2 -0
  386. package/dist-types/exports/textarea-test-suites.d.ts.map +1 -0
  387. package/dist-types/exports/tooltip-test-suites.d.ts +2 -0
  388. package/dist-types/exports/tooltip-test-suites.d.ts.map +1 -0
  389. package/dist-types/exports/types/test-suites.d.ts +4 -0
  390. package/dist-types/exports/types/test-suites.d.ts.map +1 -0
  391. package/dist-types/tsconfig.tsbuildinfo +1 -1
  392. package/drawer-test-suites.js +1 -0
  393. package/exports/accordion-test-suites.js +2 -0
  394. package/exports/collapsible-test-suites.js +1 -0
  395. package/exports/combobox-test-suites.js +2 -0
  396. package/exports/dialog-test-suites.js +2 -0
  397. package/exports/drawer-test-suites.js +1 -0
  398. package/exports/form-test-suites.js +2 -0
  399. package/exports/icon-test-suites.js +2 -0
  400. package/exports/input-amount-test-suites.js +2 -0
  401. package/exports/input-date-test-suites.js +2 -0
  402. package/exports/input-email-test-suites.js +2 -0
  403. package/exports/input-file-test-suites.js +2 -0
  404. package/exports/input-iban-test-suites.js +2 -0
  405. package/exports/input-range-test-suites.js +2 -0
  406. package/exports/input-stepper-suites.js +18 -4
  407. package/exports/input-test-suites.js +2 -0
  408. package/exports/menu-test-suites.js +3 -0
  409. package/exports/pagination-test-suites.js +1 -0
  410. package/exports/progress-indicator-test-suites.js +2 -0
  411. package/exports/radio-group-test-suites.js +3 -0
  412. package/exports/select-rich-test-suites.js +4 -0
  413. package/exports/select-test-suites.js +1 -0
  414. package/exports/steps-test-suites.js +3 -0
  415. package/exports/switch-test-suites.js +2 -0
  416. package/exports/tabs-test-suites.js +2 -0
  417. package/exports/textarea-test-suites.js +2 -0
  418. package/exports/tooltip-test-suites.js +2 -0
  419. package/exports/types/test-suites.ts +3 -0
  420. package/form-test-suites.js +2 -0
  421. package/generated/awesome-phonenumber/provenance.json +1 -1
  422. package/icon-test-suites.js +2 -0
  423. package/input-amount-test-suites.js +2 -0
  424. package/input-date-test-suites.js +2 -0
  425. package/input-email-test-suites.js +2 -0
  426. package/input-file-test-suites.js +2 -0
  427. package/input-iban-test-suites.js +2 -0
  428. package/input-range-test-suites.js +2 -0
  429. package/input-stepper-suites.js +18 -4
  430. package/input-test-suites.js +2 -0
  431. package/menu-test-suites.js +3 -0
  432. package/package.json +11 -7
  433. package/pagination-test-suites.js +1 -0
  434. package/progress-indicator-test-suites.js +2 -0
  435. package/radio-group-test-suites.js +3 -0
  436. package/select-rich-test-suites.js +4 -0
  437. package/select-test-suites.js +1 -0
  438. package/steps-test-suites.js +3 -0
  439. package/switch-test-suites.js +2 -0
  440. package/tabs-test-suites.js +2 -0
  441. package/textarea-test-suites.js +2 -0
  442. package/tooltip-test-suites.js +2 -0
  443. package/vscode.html-custom-data.json +60 -5
  444. package/web-types.json +219 -1
  445. package/components/button/test/demos.screenshots-test.js +0 -100
  446. package/components/calendar/test/demos.screenshots-test.js +0 -118
  447. package/components/input-file/test/lion-selected-file-list.test.js +0 -199
  448. package/components/select-rich/test/demos.screenshots-test.js +0 -168
  449. package/components/switch/test/lion-switch-button.test.js +0 -204
  450. package/dist-types/components/button/test/demos.screenshots-test.d.ts +0 -2
  451. package/dist-types/components/button/test/demos.screenshots-test.d.ts.map +0 -1
  452. package/dist-types/components/calendar/test/demos.screenshots-test.d.ts +0 -2
  453. package/dist-types/components/calendar/test/demos.screenshots-test.d.ts.map +0 -1
  454. package/dist-types/components/input-file/test/lion-selected-file-list.test.d.ts +0 -5
  455. package/dist-types/components/input-file/test/lion-selected-file-list.test.d.ts.map +0 -1
  456. package/dist-types/components/select-rich/test/demos.screenshots-test.d.ts +0 -2
  457. package/dist-types/components/select-rich/test/demos.screenshots-test.d.ts.map +0 -1
  458. package/dist-types/components/switch/test/lion-switch-button.test.d.ts +0 -4
  459. package/dist-types/components/switch/test/lion-switch-button.test.d.ts.map +0 -1
  460. package/docs/components/accordion/api-table.md +0 -53
  461. package/docs/components/accordion/index.md +0 -13
  462. package/docs/components/accordion/overview.md +0 -141
  463. package/docs/components/accordion/reference.md +0 -59
  464. package/docs/components/accordion/use-cases.md +0 -303
  465. package/docs/components/button/api-table.md +0 -84
  466. package/docs/components/button/assets/bootstrap-button.js +0 -245
  467. package/docs/components/button/examples.md +0 -42
  468. package/docs/components/button/extensions.md +0 -42
  469. package/docs/components/button/index.md +0 -13
  470. package/docs/components/button/overview.md +0 -42
  471. package/docs/components/button/src/icon.svg.js +0 -5
  472. package/docs/components/button/use-cases.md +0 -121
  473. package/docs/components/calendar/api-table.md +0 -56
  474. package/docs/components/calendar/index.md +0 -13
  475. package/docs/components/calendar/overview.md +0 -61
  476. package/docs/components/calendar/use-cases.md +0 -243
  477. package/docs/components/checkbox-group/api-table.md +0 -117
  478. package/docs/components/checkbox-group/index.md +0 -13
  479. package/docs/components/checkbox-group/overview.md +0 -51
  480. package/docs/components/checkbox-group/use-cases.md +0 -192
  481. package/docs/components/collapsible/api-table.md +0 -55
  482. package/docs/components/collapsible/assets/CustomCollapsible.js +0 -117
  483. package/docs/components/collapsible/assets/applyDemoCollapsibleStyles.js +0 -41
  484. package/docs/components/collapsible/examples.md +0 -95
  485. package/docs/components/collapsible/index.md +0 -13
  486. package/docs/components/collapsible/overview.md +0 -51
  487. package/docs/components/collapsible/use-cases.md +0 -91
  488. package/docs/components/combobox/api-table.md +0 -122
  489. package/docs/components/combobox/extensions.md +0 -174
  490. package/docs/components/combobox/index.md +0 -13
  491. package/docs/components/combobox/overview.md +0 -74
  492. package/docs/components/combobox/src/LinkMixin.js +0 -60
  493. package/docs/components/combobox/src/demo-selection-display.js +0 -164
  494. package/docs/components/combobox/src/gh-combobox/gh-button.js +0 -71
  495. package/docs/components/combobox/src/gh-combobox/gh-combobox.js +0 -515
  496. package/docs/components/combobox/src/google-combobox/assets/google-clear-icon.js +0 -9
  497. package/docs/components/combobox/src/google-combobox/assets/google-search-icon.js +0 -9
  498. package/docs/components/combobox/src/google-combobox/assets/google-voice-search-icon.js +0 -19
  499. package/docs/components/combobox/src/google-combobox/google-combobox.js +0 -461
  500. package/docs/components/combobox/src/lazyRender.js +0 -29
  501. package/docs/components/combobox/src/levenshtein.js +0 -95
  502. package/docs/components/combobox/src/md-combobox/MdFieldMixin.js +0 -345
  503. package/docs/components/combobox/src/md-combobox/md-combobox.js +0 -91
  504. package/docs/components/combobox/src/md-combobox/md-input.js +0 -5
  505. package/docs/components/combobox/src/md-combobox/style/load-roboto.js +0 -6
  506. package/docs/components/combobox/src/md-combobox/style/md-ripple.js +0 -82
  507. package/docs/components/combobox/src/wa-combobox/wa-combobox.js +0 -375
  508. package/docs/components/combobox/use-cases.md +0 -561
  509. package/docs/components/dialog/api-table.md +0 -61
  510. package/docs/components/dialog/index.md +0 -13
  511. package/docs/components/dialog/overview.md +0 -71
  512. package/docs/components/dialog/src/demoStyle.js +0 -57
  513. package/docs/components/dialog/src/external-dialog.js +0 -32
  514. package/docs/components/dialog/src/slots-dialog-content.js +0 -32
  515. package/docs/components/dialog/src/styled-dialog-content.js +0 -38
  516. package/docs/components/dialog/use-cases.md +0 -199
  517. package/docs/components/drawer/api-table.md +0 -64
  518. package/docs/components/drawer/index.md +0 -13
  519. package/docs/components/drawer/overview.md +0 -80
  520. package/docs/components/drawer/src/demoStyle.js +0 -71
  521. package/docs/components/drawer/use-cases.md +0 -206
  522. package/docs/components/fieldset/api-table.md +0 -24
  523. package/docs/components/fieldset/index.md +0 -13
  524. package/docs/components/fieldset/overview.md +0 -61
  525. package/docs/components/fieldset/use-cases.md +0 -203
  526. package/docs/components/form/api-table.md +0 -12
  527. package/docs/components/form/index.md +0 -13
  528. package/docs/components/form/overview.md +0 -66
  529. package/docs/components/form/use-cases.md +0 -230
  530. package/docs/components/icon/api-table.md +0 -41
  531. package/docs/components/icon/assets/bugs/bug01.svg.js +0 -2
  532. package/docs/components/icon/assets/bugs/bug02.svg.js +0 -2
  533. package/docs/components/icon/assets/bugs/bug05.svg.js +0 -2
  534. package/docs/components/icon/assets/bugs/bug06.svg.js +0 -2
  535. package/docs/components/icon/assets/bugs/bug08.svg.js +0 -2
  536. package/docs/components/icon/assets/bugs/bug12.svg.js +0 -2
  537. package/docs/components/icon/assets/bugs/bug19.svg.js +0 -2
  538. package/docs/components/icon/assets/bugs/bug23.svg.js +0 -2
  539. package/docs/components/icon/assets/bugs/bug24.svg.js +0 -2
  540. package/docs/components/icon/assets/iconset-bugs.js +0 -11
  541. package/docs/components/icon/assets/iconset-misc.js +0 -3
  542. package/docs/components/icon/assets/iconset-space.js +0 -31
  543. package/docs/components/icon/assets/misc/arrowLeft.svg.js +0 -6
  544. package/docs/components/icon/assets/space/aliens-spaceship.svg.js +0 -2
  545. package/docs/components/icon/assets/space/meteor.svg.js +0 -2
  546. package/docs/components/icon/assets/space/moon-flag.svg.js +0 -2
  547. package/docs/components/icon/assets/space/moon.svg.js +0 -2
  548. package/docs/components/icon/assets/space/night.svg.js +0 -2
  549. package/docs/components/icon/assets/space/orbit.svg.js +0 -2
  550. package/docs/components/icon/assets/space/planet.svg.js +0 -2
  551. package/docs/components/icon/assets/space/robot.svg.js +0 -2
  552. package/docs/components/icon/assets/space/rocket.svg.js +0 -2
  553. package/docs/components/icon/assets/space/satellite.svg.js +0 -2
  554. package/docs/components/icon/assets/space/signal.svg.js +0 -2
  555. package/docs/components/icon/assets/space/space-helmet.svg.js +0 -2
  556. package/docs/components/icon/assets/space/sun.svg.js +0 -2
  557. package/docs/components/icon/assets/space/telescope.svg.js +0 -2
  558. package/docs/components/icon/index.md +0 -13
  559. package/docs/components/icon/overview.md +0 -52
  560. package/docs/components/icon/use-cases.md +0 -92
  561. package/docs/components/index.md +0 -17
  562. package/docs/components/input/api-table.md +0 -52
  563. package/docs/components/input/index.md +0 -13
  564. package/docs/components/input/overview.md +0 -48
  565. package/docs/components/input/use-cases.md +0 -90
  566. package/docs/components/input-amount/api-table.md +0 -66
  567. package/docs/components/input-amount/index.md +0 -13
  568. package/docs/components/input-amount/overview.md +0 -61
  569. package/docs/components/input-amount/use-cases.md +0 -147
  570. package/docs/components/input-amount-dropdown/api-table.md +0 -87
  571. package/docs/components/input-amount-dropdown/index.md +0 -13
  572. package/docs/components/input-amount-dropdown/use-cases.md +0 -103
  573. package/docs/components/input-date/api-table.md +0 -58
  574. package/docs/components/input-date/index.md +0 -13
  575. package/docs/components/input-date/overview.md +0 -51
  576. package/docs/components/input-date/use-cases.md +0 -96
  577. package/docs/components/input-datepicker/api-table.md +0 -99
  578. package/docs/components/input-datepicker/index.md +0 -13
  579. package/docs/components/input-datepicker/overview.md +0 -54
  580. package/docs/components/input-datepicker/use-cases.md +0 -117
  581. package/docs/components/input-email/api-table.md +0 -53
  582. package/docs/components/input-email/index.md +0 -13
  583. package/docs/components/input-email/overview.md +0 -44
  584. package/docs/components/input-email/use-cases.md +0 -60
  585. package/docs/components/input-file/api-table.md +0 -157
  586. package/docs/components/input-file/index.md +0 -13
  587. package/docs/components/input-file/overview.md +0 -44
  588. package/docs/components/input-file/use-cases.md +0 -454
  589. package/docs/components/input-iban/api-table.md +0 -54
  590. package/docs/components/input-iban/index.md +0 -13
  591. package/docs/components/input-iban/overview.md +0 -49
  592. package/docs/components/input-iban/use-cases.md +0 -114
  593. package/docs/components/input-range/api-table.md +0 -71
  594. package/docs/components/input-range/index.md +0 -13
  595. package/docs/components/input-range/overview.md +0 -44
  596. package/docs/components/input-range/use-cases.md +0 -126
  597. package/docs/components/input-stepper/api-table.md +0 -74
  598. package/docs/components/input-stepper/index.md +0 -13
  599. package/docs/components/input-stepper/overview.md +0 -48
  600. package/docs/components/input-stepper/use-cases.md +0 -155
  601. package/docs/components/input-tel/api-table.md +0 -77
  602. package/docs/components/input-tel/index.md +0 -13
  603. package/docs/components/input-tel/overview.md +0 -74
  604. package/docs/components/input-tel/src/h-region-code-table.js +0 -109
  605. package/docs/components/input-tel/use-cases.md +0 -319
  606. package/docs/components/input-tel-dropdown/api-table.md +0 -85
  607. package/docs/components/input-tel-dropdown/extensions.md +0 -44
  608. package/docs/components/input-tel-dropdown/index.md +0 -13
  609. package/docs/components/input-tel-dropdown/overview.md +0 -50
  610. package/docs/components/input-tel-dropdown/src/intl-input-tel-dropdown.js +0 -138
  611. package/docs/components/input-tel-dropdown/use-cases.md +0 -171
  612. package/docs/components/listbox/api-table.md +0 -65
  613. package/docs/components/listbox/index.md +0 -13
  614. package/docs/components/listbox/overview.md +0 -54
  615. package/docs/components/listbox/src/listboxData.js +0 -131
  616. package/docs/components/listbox/use-cases.md +0 -154
  617. package/docs/components/menu/api-table.md +0 -44
  618. package/docs/components/menu/applyMenuDemoStyles.js +0 -173
  619. package/docs/components/menu/extensions.md +0 -262
  620. package/docs/components/menu/index.md +0 -13
  621. package/docs/components/menu/migration.md +0 -129
  622. package/docs/components/menu/overview.md +0 -448
  623. package/docs/components/menu/src/DemoNavigationBar.js +0 -441
  624. package/docs/components/menu/src/DemoSpinButton.js +0 -215
  625. package/docs/components/menu/src/DemoToolbar.js +0 -101
  626. package/docs/components/menu/src/DemoTree.js +0 -55
  627. package/docs/components/menu/src/navigation-bar-types.js +0 -41
  628. package/docs/components/menu/use-cases.md +0 -74
  629. package/docs/components/pagination/api-table.md +0 -45
  630. package/docs/components/pagination/index.md +0 -13
  631. package/docs/components/pagination/overview.md +0 -41
  632. package/docs/components/pagination/use-cases.md +0 -113
  633. package/docs/components/progress-indicator/api-table.md +0 -48
  634. package/docs/components/progress-indicator/assets/my-determinate-progress-bar.js +0 -30
  635. package/docs/components/progress-indicator/assets/my-indeterminate-progress-spinner.js +0 -55
  636. package/docs/components/progress-indicator/examples.md +0 -137
  637. package/docs/components/progress-indicator/index.md +0 -13
  638. package/docs/components/progress-indicator/overview.md +0 -48
  639. package/docs/components/radio-group/api-table.md +0 -63
  640. package/docs/components/radio-group/index.md +0 -13
  641. package/docs/components/radio-group/overview.md +0 -58
  642. package/docs/components/radio-group/use-cases.md +0 -146
  643. package/docs/components/select/api-table.md +0 -51
  644. package/docs/components/select/index.md +0 -13
  645. package/docs/components/select/overview.md +0 -56
  646. package/docs/components/select/use-cases.md +0 -128
  647. package/docs/components/select-rich/api-table.md +0 -123
  648. package/docs/components/select-rich/examples.md +0 -43
  649. package/docs/components/select-rich/index.md +0 -13
  650. package/docs/components/select-rich/overview.md +0 -55
  651. package/docs/components/select-rich/src/flagStyles.js +0 -1250
  652. package/docs/components/select-rich/src/intl-select-rich.js +0 -194
  653. package/docs/components/select-rich/src/regionMetaList.js +0 -1717
  654. package/docs/components/select-rich/use-cases.md +0 -387
  655. package/docs/components/steps/api-table.md +0 -92
  656. package/docs/components/steps/index.md +0 -13
  657. package/docs/components/steps/overview.md +0 -77
  658. package/docs/components/steps/use-cases.md +0 -181
  659. package/docs/components/switch/api-table.md +0 -82
  660. package/docs/components/switch/index.md +0 -13
  661. package/docs/components/switch/overview.md +0 -87
  662. package/docs/components/switch/reference.md +0 -51
  663. package/docs/components/switch/use-cases.md +0 -88
  664. package/docs/components/tabs/api-table.md +0 -51
  665. package/docs/components/tabs/examples.md +0 -35
  666. package/docs/components/tabs/index.md +0 -13
  667. package/docs/components/tabs/overview.md +0 -60
  668. package/docs/components/tabs/src/lea-tab-panel.js +0 -26
  669. package/docs/components/tabs/src/lea-tab.js +0 -50
  670. package/docs/components/tabs/src/lea-tabs.js +0 -28
  671. package/docs/components/tabs/use-cases.md +0 -231
  672. package/docs/components/textarea/api-table.md +0 -57
  673. package/docs/components/textarea/index.md +0 -13
  674. package/docs/components/textarea/overview.md +0 -47
  675. package/docs/components/textarea/use-cases.md +0 -107
  676. package/docs/components/tooltip/api-table.md +0 -62
  677. package/docs/components/tooltip/examples.md +0 -51
  678. package/docs/components/tooltip/index.md +0 -13
  679. package/docs/components/tooltip/overview.md +0 -56
  680. package/docs/components/tooltip/use-cases.md +0 -275
  681. package/docs/fundamentals/index.md +0 -19
  682. package/docs/fundamentals/node-tools/babel-plugin-extend-docs/index.md +0 -13
  683. package/docs/fundamentals/node-tools/babel-plugin-extend-docs/overview.md +0 -246
  684. package/docs/fundamentals/node-tools/index.md +0 -11
  685. package/docs/fundamentals/node-tools/providence-analytics/index.md +0 -13
  686. package/docs/fundamentals/node-tools/providence-analytics/overview.md +0 -108
  687. package/docs/fundamentals/node-tools/publish-docs/index.md +0 -13
  688. package/docs/fundamentals/node-tools/publish-docs/overview.md +0 -149
  689. package/docs/fundamentals/node-tools/remark-extend/index.md +0 -13
  690. package/docs/fundamentals/node-tools/remark-extend/overview.md +0 -287
  691. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/index.md +0 -13
  692. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +0 -298
  693. package/docs/fundamentals/rationales/TypeScript.md +0 -123
  694. package/docs/fundamentals/rationales/accessibility.md +0 -40
  695. package/docs/fundamentals/rationales/index.md +0 -11
  696. package/docs/fundamentals/rationales/side-effects.md +0 -215
  697. package/docs/fundamentals/rationales/versioning.md +0 -47
  698. package/docs/fundamentals/systems/core/SlotMixin.md +0 -168
  699. package/docs/fundamentals/systems/core/api-table.md +0 -43
  700. package/docs/fundamentals/systems/core/index.md +0 -15
  701. package/docs/fundamentals/systems/core/overview.md +0 -98
  702. package/docs/fundamentals/systems/form/api-table.md +0 -40
  703. package/docs/fundamentals/systems/form/assets/h-output.js +0 -156
  704. package/docs/fundamentals/systems/form/formatting-and-parsing.md +0 -258
  705. package/docs/fundamentals/systems/form/index.md +0 -15
  706. package/docs/fundamentals/systems/form/interaction-states.md +0 -195
  707. package/docs/fundamentals/systems/form/model-value.md +0 -57
  708. package/docs/fundamentals/systems/form/overview.md +0 -95
  709. package/docs/fundamentals/systems/form/styling.md +0 -92
  710. package/docs/fundamentals/systems/form/use-cases.md +0 -187
  711. package/docs/fundamentals/systems/form/validate.md +0 -985
  712. package/docs/fundamentals/systems/icon/index.md +0 -15
  713. package/docs/fundamentals/systems/icon/overview.md +0 -137
  714. package/docs/fundamentals/systems/index.md +0 -11
  715. package/docs/fundamentals/systems/localize/api-table.md +0 -72
  716. package/docs/fundamentals/systems/localize/assets/all-locales.js +0 -437
  717. package/docs/fundamentals/systems/localize/assets/en-AU.js +0 -6
  718. package/docs/fundamentals/systems/localize/assets/en-GB.js +0 -6
  719. package/docs/fundamentals/systems/localize/assets/en-US.js +0 -6
  720. package/docs/fundamentals/systems/localize/assets/en.js +0 -4
  721. package/docs/fundamentals/systems/localize/assets/nl-BE.js +0 -6
  722. package/docs/fundamentals/systems/localize/assets/nl-NL.js +0 -6
  723. package/docs/fundamentals/systems/localize/assets/nl.js +0 -4
  724. package/docs/fundamentals/systems/localize/dates.md +0 -208
  725. package/docs/fundamentals/systems/localize/index.md +0 -15
  726. package/docs/fundamentals/systems/localize/numbers.md +0 -230
  727. package/docs/fundamentals/systems/localize/overview.md +0 -61
  728. package/docs/fundamentals/systems/localize/rationale.md +0 -75
  729. package/docs/fundamentals/systems/localize/text.md +0 -139
  730. package/docs/fundamentals/systems/localize/use-cases.md +0 -334
  731. package/docs/fundamentals/systems/overlays/_configuration-positioning.md +0 -118
  732. package/docs/fundamentals/systems/overlays/_edge-cases.md +0 -149
  733. package/docs/fundamentals/systems/overlays/api-table.md +0 -174
  734. package/docs/fundamentals/systems/overlays/assets/applyDemoOverlayStyles.js +0 -23
  735. package/docs/fundamentals/systems/overlays/assets/demo-el-using-overlaymixin.js +0 -104
  736. package/docs/fundamentals/systems/overlays/assets/demo-overlay-backdrop.js +0 -47
  737. package/docs/fundamentals/systems/overlays/assets/demo-overlay-positioning.mjs +0 -537
  738. package/docs/fundamentals/systems/overlays/assets/umbrella-form.js +0 -140
  739. package/docs/fundamentals/systems/overlays/configuration.md +0 -516
  740. package/docs/fundamentals/systems/overlays/index.md +0 -15
  741. package/docs/fundamentals/systems/overlays/overview.md +0 -126
  742. package/docs/fundamentals/systems/overlays/rationale.md +0 -242
  743. package/docs/fundamentals/systems/overlays/use-cases.md +0 -717
  744. package/docs/fundamentals/tools/ajax/index.md +0 -15
  745. package/docs/fundamentals/tools/ajax/overview.md +0 -269
  746. package/docs/fundamentals/tools/ajax/use-cases.md +0 -469
  747. package/docs/fundamentals/tools/helpers/action-logger.md +0 -175
  748. package/docs/fundamentals/tools/helpers/index.md +0 -15
  749. package/docs/fundamentals/tools/helpers/overview.md +0 -43
  750. package/docs/fundamentals/tools/index.md +0 -11
  751. package/docs/fundamentals/tools/singleton-manager/example-complex/demo-app.js +0 -95
  752. package/docs/fundamentals/tools/singleton-manager/example-complex/index.md +0 -34
  753. package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/overlays/index.js +0 -30
  754. package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/overlays/instance.js +0 -4
  755. package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/page-a/page-a.js +0 -35
  756. package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/page-b/node_modules/overlays/index.js +0 -30
  757. package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/page-b/node_modules/overlays/instance.js +0 -4
  758. package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/page-b/page-b.js +0 -49
  759. package/docs/fundamentals/tools/singleton-manager/example-complex/overlayCompatibility.js +0 -69
  760. package/docs/fundamentals/tools/singleton-manager/example-fail/demo-app.js +0 -93
  761. package/docs/fundamentals/tools/singleton-manager/example-fail/index.md +0 -32
  762. package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/overlays/index.js +0 -30
  763. package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/overlays/instance.js +0 -3
  764. package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/page-c/page-c.js +0 -34
  765. package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/page-d/node_modules/overlays/index.js +0 -30
  766. package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/page-d/node_modules/overlays/instance.js +0 -3
  767. package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/page-d/page-d.js +0 -34
  768. package/docs/fundamentals/tools/singleton-manager/example-success/demo-app.js +0 -95
  769. package/docs/fundamentals/tools/singleton-manager/example-success/index.md +0 -31
  770. package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/overlays/index.js +0 -30
  771. package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/overlays/instance.js +0 -4
  772. package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/page-e/page-e.js +0 -33
  773. package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/page-f/node_modules/overlays/index.js +0 -30
  774. package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/page-f/node_modules/overlays/instance.js +0 -4
  775. package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/page-f/page-f.js +0 -34
  776. package/docs/fundamentals/tools/singleton-manager/example-success/overlayCompatibility.js +0 -23
  777. package/docs/fundamentals/tools/singleton-manager/index.md +0 -15
  778. package/docs/fundamentals/tools/singleton-manager/overview.md +0 -317
  779. package/docs/guides/how-to/create-a-custom-field.md +0 -212
  780. package/docs/guides/how-to/create-a-form.md +0 -101
  781. package/docs/guides/how-to/extend-a-native-input.md +0 -78
  782. package/docs/guides/how-to/get-started.md +0 -116
  783. package/docs/guides/how-to/index.md +0 -25
  784. package/docs/guides/index.md +0 -44
  785. package/docs/guides/principles/definitions-and-terms.md +0 -53
  786. package/docs/guides/principles/index.md +0 -36
  787. package/docs/guides/principles/scoped-elements.md +0 -119
  788. package/docs/guides/principles/styling.md +0 -43
  789. package/docs/guides/principles/subclasser-apis.md +0 -40
@@ -1,11 +1,54 @@
1
- import { LionCalendar } from '@lion/ui/calendar.js';
2
- import { expect, html, fixture, waitUntil, unsafeStatic, defineCE } from '@open-wc/testing';
3
- import sinon from 'sinon';
1
+ import { html } from 'lit/static-html.js';
2
+ import { LionCalendar, isSameDate } from '@lion/ui/calendar.js';
3
+ import { expect, fixture, fixture as _fixture, unsafeStatic, waitUntil } from '@open-wc/testing';
4
4
  import '@lion/ui/define/lion-calendar.js';
5
5
  import { sendKeys } from '@web/test-runner-commands';
6
- export function runCalendarSuite({ klass = LionCalendar } = {}) {
7
- const tagStringCalendar = defineCE(class extends klass {});
6
+ import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
7
+ import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
8
+ import {
9
+ CalendarObject as DefaultCalendarObject,
10
+ DayObject,
11
+ } from '@lion/ui/calendar-test-helpers.js';
12
+ import sinon from 'sinon';
13
+ import { resolveSuiteTag } from '../../core/test-helpers/resolveSuiteTag.js';
14
+
15
+ /**
16
+ * Runs the `LionCalendar` behavioural suite. The caller hands the element to run against; anything
17
+ * left out keeps `LionCalendar`.
18
+ * @typedef {import('@lion/ui/types/test-suites.js').SuiteElement} SuiteElement
19
+ * @param {import('@lion/ui/types/test-suites.js').SuiteConfig<{host: SuiteElement}, {CalendarObject?: typeof DefaultCalendarObject}>} [customConfig]
20
+ */
21
+ export function runCalendarSuite({
22
+ classes = {},
23
+ tagString,
24
+ // The tests address the calendar through this page object; an extension layer whose navigation
25
+ // markup differs (ING renders its own button element) passes its own subclass overriding the node
26
+ // getters instead of the suite learning about that markup.
27
+ CalendarObject = DefaultCalendarObject,
28
+ } = {}) {
29
+ const tagStringCalendar = resolveSuiteTag(classes.host, tagString, LionCalendar);
8
30
  const tagCalendar = unsafeStatic(tagStringCalendar);
31
+
32
+ /**
33
+ * The accessible name of a node, whatever mechanism carries it (`title`, `aria-label`, or a
34
+ * `label` on the node itself or a child element).
35
+ * @param {Element|null|undefined} node
36
+ * @returns {string|null}
37
+ */
38
+ function accessibleName(node) {
39
+ return (
40
+ node?.getAttribute('title') ||
41
+ node?.getAttribute('aria-label') ||
42
+ node?.getAttribute('label') ||
43
+ node?.querySelector?.('[label]')?.getAttribute('label') ||
44
+ node?.shadowRoot?.querySelector?.('[label]')?.getAttribute('label') ||
45
+ null
46
+ );
47
+ }
48
+
49
+ // A failing test that never reaches its `clock.restore()` used to leak fake timers into the
50
+ // next test, which then awaited a timer that never fires and wedged the rest of the file.
51
+ afterEach(() => sinon.restore());
9
52
  it('should fire keyboard press events on keyup and not on keydown', async () => {
10
53
  /**
11
54
  * This test covers a corner case where `keydown`, `keyup`, and `focus` events happen across different elements.
@@ -74,4 +117,1573 @@ export function runCalendarSuite({ klass = LionCalendar } = {}) {
74
117
  });
75
118
  expect(keyUpSpy.called).to.equal(false);
76
119
  });
120
+ /**
121
+ * @typedef {import('../src/LionCalendar.js').LionCalendar} LionCalendar
122
+ * @typedef {import('lit').TemplateResult} TemplateResult
123
+ */
124
+
125
+ const fixtureForSuite = /** @type {(arg: TemplateResult) => Promise<LionCalendar>} */ _fixture;
126
+ /**
127
+ * @param {HTMLElement} el
128
+ * @returns {HTMLElement | null | undefined}
129
+ */
130
+ const getSelectedDateEl = (el) =>
131
+ el?.shadowRoot?.querySelector('.calendar__day-button[selected]');
132
+ /**
133
+ * @param {HTMLElement} el
134
+ * @returns {void}
135
+ */
136
+ const focusSelectedDate = (el) => getSelectedDateEl(el)?.focus();
137
+ describe('<lion-calendar>', () => {
138
+ const localizeManager = getLocalizeManager();
139
+ beforeEach(() => {
140
+ localizeTearDown();
141
+ });
142
+ describe('Structure', () => {
143
+ it('implements BEM structure', async () => {
144
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
145
+ const elObj = new CalendarObject(el);
146
+ expect(elObj.rootEl).to.exist;
147
+ expect(elObj.headerEl).to.exist;
148
+ expect(elObj.previousYearButtonEl).to.exist;
149
+ expect(elObj.nextYearButtonEl).to.exist;
150
+ expect(elObj.yearHeadingEl).to.exist;
151
+ expect(elObj.gridEl).to.exist;
152
+ });
153
+ it('has heading with month and year', async () => {
154
+ const clock = sinon.useFakeTimers({
155
+ now: new Date('2000/12/01').getTime(),
156
+ });
157
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
158
+ expect(el.shadowRoot?.querySelector('#year')).dom.to.equal(`
159
+ <h2
160
+ id="year"
161
+ class="calendar__navigation-heading"
162
+ aria-atomic="true"
163
+ >
164
+ 2000
165
+ </h2>
166
+ `);
167
+ expect(el.shadowRoot?.querySelector('#month')).dom.to.equal(`
168
+ <h2
169
+ id="month"
170
+ class="calendar__navigation-heading"
171
+ aria-atomic="true"
172
+ >
173
+ December
174
+ </h2>
175
+ `);
176
+ clock.restore();
177
+ });
178
+ it('has previous year button', async () => {
179
+ const el = await fixtureForSuite(
180
+ html`<${tagCalendar} .centralDate=${new Date('2019/11/20')}></${tagCalendar}>`,
181
+ );
182
+ expect(accessibleName(new CalendarObject(el).previousYearButtonEl)).to.equal(
183
+ 'Previous year, November 2018',
184
+ );
185
+ });
186
+ it('has next year button', async () => {
187
+ const el = await fixtureForSuite(
188
+ html`<${tagCalendar} .centralDate=${new Date('2019/11/20')}></${tagCalendar}>`,
189
+ );
190
+ expect(accessibleName(new CalendarObject(el).nextYearButtonEl)).to.equal(
191
+ 'Next year, November 2020',
192
+ );
193
+ });
194
+ it('has previous month button', async () => {
195
+ const el = await fixtureForSuite(
196
+ html`<${tagCalendar} .centralDate=${new Date('2019/11/20')}></${tagCalendar}>`,
197
+ );
198
+ expect(accessibleName(new CalendarObject(el).previousMonthButtonEl)).to.equal(
199
+ 'Previous month, October 2019',
200
+ );
201
+ });
202
+ it('has next month button', async () => {
203
+ const el = await fixtureForSuite(
204
+ html`<${tagCalendar} .centralDate=${new Date('2019/11/20')}></${tagCalendar}>`,
205
+ );
206
+ expect(accessibleName(new CalendarObject(el).nextMonthButtonEl)).to.equal(
207
+ 'Next month, December 2019',
208
+ );
209
+ });
210
+ });
211
+ describe('Public API', () => {
212
+ it('has property "centralDate" that determines currently visible month', async () => {
213
+ const elObj = new CalendarObject(
214
+ await fixtureForSuite(html`
215
+ <${tagCalendar} .centralDate="${new Date('2014/05/15')}"></${tagCalendar}>
216
+ `),
217
+ );
218
+ expect(elObj.activeMonth).to.equal('May');
219
+ expect(elObj.activeYear).to.equal('2014');
220
+ });
221
+ it('sets "centralDate" to today by default', async () => {
222
+ const clock = sinon.useFakeTimers({
223
+ now: new Date('2013/03/15').getTime(),
224
+ });
225
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
226
+ const elObj = new CalendarObject(el);
227
+ expect(isSameDate(el.centralDate, new Date())).to.be.true;
228
+ expect(elObj.activeMonth).to.equal('March');
229
+ expect(elObj.activeYear).to.equal('2013');
230
+ clock.restore();
231
+ });
232
+ it('determines the date focusable with keyboard from "centralDate"', async () => {
233
+ const elObj = new CalendarObject(
234
+ await fixtureForSuite(html`
235
+ <${tagCalendar} .centralDate="${new Date('2017/07/05')}"></${tagCalendar}>
236
+ `),
237
+ );
238
+ expect(
239
+ elObj.checkForAllDayObjs(
240
+ /** @param {DayObject} o */ (o) => o.buttonEl.getAttribute('tabindex') === '0',
241
+ /** @param {number} n */ (n) => n === 5,
242
+ ),
243
+ ).to.be.true;
244
+ expect(
245
+ elObj.checkForAllDayObjs(
246
+ /** @param {DayObject} o */ (o) => o.buttonEl.getAttribute('tabindex') === '-1',
247
+ /** @param {number} n */ (n) => n !== 5,
248
+ ),
249
+ ).to.be.true;
250
+ });
251
+ it('has property "selectedDate" for the selected date', async () => {
252
+ const el = await fixtureForSuite(html`
253
+ <${tagCalendar} .selectedDate="${new Date('2019/06/15')}"></${tagCalendar}>
254
+ `);
255
+ const elObj = new CalendarObject(el);
256
+ expect(elObj.getDayObj(15).isSelected).to.equal(true);
257
+ expect(elObj.getDayObj(16).isSelected).to.equal(false);
258
+ expect(elObj.getDayObj(14).isSelected).to.equal(false);
259
+ el.selectedDate = new Date('2019/06/16');
260
+ await el.updateComplete;
261
+ expect(elObj.getDayObj(15).isSelected).to.equal(false);
262
+ });
263
+ it('gives priority to "centralDate" to display the month when "selectedDate" is also defined', async () => {
264
+ const elObj = new CalendarObject(
265
+ await fixtureForSuite(html`
266
+ <${tagCalendar}
267
+ .centralDate="${new Date('2018/06/01')}"
268
+ .selectedDate="${new Date('2018/07/15')}"
269
+ ></${tagCalendar}>
270
+ `),
271
+ );
272
+ expect(elObj.activeMonth).to.equal('June');
273
+ expect(elObj.activeYear).to.equal('2018');
274
+ });
275
+ it('changes "centralDate" from default to "selectedDate" on first render if no other custom "centralDate" is provided', async () => {
276
+ const clock = sinon.useFakeTimers({
277
+ now: new Date('2010/01/01').getTime(),
278
+ });
279
+ const el = await fixtureForSuite(html`
280
+ <${tagCalendar} .selectedDate="${new Date('2016/10/20')}"></${tagCalendar}>
281
+ `);
282
+ const elObj = new CalendarObject(el);
283
+ expect(isSameDate(el.centralDate, new Date('2016/10/20'))).to.be.true;
284
+ expect(elObj.activeMonth).to.equal('October');
285
+ expect(elObj.activeYear).to.equal('2016');
286
+ clock.restore();
287
+ });
288
+ it('does not change "centralDate" to "selectedDate" when new date is provided programmatically', async () => {
289
+ const el = await fixtureForSuite(html`
290
+ <${tagCalendar}
291
+ .centralDate="${new Date('2018/06/01')}"
292
+ .selectedDate="${new Date('2018/06/02')}"
293
+ ></${tagCalendar}>
294
+ `);
295
+ expect(isSameDate(el.centralDate, new Date('2018/06/01'))).to.be.true;
296
+ el.selectedDate = new Date('2018/06/03');
297
+ await el.updateComplete;
298
+ expect(isSameDate(el.centralDate, new Date('2018/06/01'))).to.be.true;
299
+ });
300
+ it('does not set "selectedDate" by default', async () => {
301
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
302
+ const elObj = new CalendarObject(el);
303
+ const today = new Date();
304
+ expect(el.selectedDate).to.equal(undefined);
305
+ expect(elObj.getDayObj(today.getDate()).isSelected).to.equal(false);
306
+ });
307
+ it('allows to reset "selectedDate"', async () => {
308
+ const el = await fixtureForSuite(html`
309
+ <${tagCalendar} .selectedDate="${new Date('2019/06/15')}"></${tagCalendar}>
310
+ `);
311
+ const elObj = new CalendarObject(el);
312
+ el.selectedDate = undefined;
313
+ await el.updateComplete;
314
+ expect(elObj.selectedDayObj).to.be.undefined;
315
+ });
316
+ it('recalculates "centralDate" when "selectedDate" is reset', async () => {
317
+ const el = await fixtureForSuite(html`
318
+ <${tagCalendar} .selectedDate="${new Date('2019/06/15')}"></${tagCalendar}>
319
+ `);
320
+ const elObj = new CalendarObject(el);
321
+ el.selectedDate = undefined;
322
+ await el.updateComplete;
323
+ expect(elObj.selectedDayObj).to.be.undefined;
324
+ expect(isSameDate(el.centralDate, new Date('2019/06/15'))).to.be.true;
325
+ });
326
+ it('sends event "user-selected-date-changed" when user selects a date via mouse', async () => {
327
+ const dateChangedSpy = sinon.spy();
328
+ const el = await fixtureForSuite(html`
329
+ <${tagCalendar}
330
+ .selectedDate="${new Date('2000/12/12')}"
331
+ @user-selected-date-changed="${dateChangedSpy}"
332
+ ></${tagCalendar}>
333
+ `);
334
+ const elObj = new CalendarObject(el);
335
+ expect(dateChangedSpy.called).to.equal(false);
336
+ elObj.getDayEl(15).click();
337
+ await el.updateComplete;
338
+ expect(dateChangedSpy.calledOnce).to.equal(true);
339
+ expect(
340
+ isSameDate(dateChangedSpy.args[0][0].detail.selectedDate, new Date('2000/12/15')),
341
+ ).to.equal(true);
342
+ });
343
+ it('doesn\'t send event "user-selected-date-changed" when user selects a disabled date via mouse', async () => {
344
+ const dateChangedSpy = sinon.spy();
345
+ const disable15th = /** @param {Date} d */ (d) => d.getDate() === 15;
346
+ const el = await fixtureForSuite(html`
347
+ <${tagCalendar}
348
+ .selectedDate="${new Date('2000/12/12')}"
349
+ @user-selected-date-changed="${dateChangedSpy}"
350
+ .disableDates=${disable15th}
351
+ ></${tagCalendar}>
352
+ `);
353
+ const elObj = new CalendarObject(el);
354
+ elObj.getDayEl(15).click();
355
+ await el.updateComplete;
356
+ expect(dateChangedSpy.called).to.equal(false);
357
+ expect(isSameDate(/** @type {Date} */ el.selectedDate, new Date('2000/12/12'))).to.be.true;
358
+ });
359
+ it.skip('sends event "user-selected-date-changed" when user selects a date via [Enter]', async () => {
360
+ /**
361
+ * TODO fix me
362
+ * The dispatchEvent of [Enter] should has to be on contentWrapperElement to be called
363
+ * But to get "selected" a check is done if the action comes from a button.
364
+ */
365
+ const dateChangedSpy = sinon.spy();
366
+ const el = await fixtureForSuite(html`
367
+ <${tagCalendar}
368
+ .selectedDate="${new Date('2000/10/12')}"
369
+ @user-selected-date-changed="${dateChangedSpy}"
370
+ ></${tagCalendar}>
371
+ `);
372
+ const elObj = new CalendarObject(el);
373
+ el.__contentWrapperElement?.dispatchEvent(
374
+ new KeyboardEvent('keydown', {
375
+ key: 'ArrowLeft',
376
+ }),
377
+ );
378
+ await el.updateComplete;
379
+ expect(elObj.activeMonth).to.equal('October');
380
+ expect(elObj.activeYear).to.equal('2000');
381
+ expect(elObj.focusedDayObj?.monthday).to.equal(11);
382
+ el.__contentWrapperElement?.dispatchEvent(
383
+ new KeyboardEvent('keydown', {
384
+ key: 'Enter',
385
+ }),
386
+ );
387
+ await el.updateComplete;
388
+ expect(isSameDate(/** @type {Date} */ el.selectedDate, new Date('2000/10/11'))).to.be.true;
389
+ expect(dateChangedSpy.called).to.equal(true);
390
+ });
391
+ it('doesn\'t send event "user-selected-date-changed" when user selects a disabled date via [Enter]', async () => {
392
+ const dateChangedSpy = sinon.spy();
393
+ const el = await fixtureForSuite(html`
394
+ <${tagCalendar}
395
+ .selectedDate="${new Date('2000/10/12')}"
396
+ .minDate="${new Date('2000/10/12')}"
397
+ @user-selected-date-changed="${dateChangedSpy}"
398
+ ></${tagCalendar}>
399
+ `);
400
+ const elObj = new CalendarObject(el);
401
+ focusSelectedDate(el);
402
+ await sendKeys({
403
+ press: 'ArrowLeft',
404
+ });
405
+ await el.updateComplete;
406
+ expect(elObj.activeMonth).to.equal('October');
407
+ expect(elObj.activeYear).to.equal('2000');
408
+ expect(elObj.focusedDayObj?.monthday).to.equal(11);
409
+ await sendKeys({
410
+ press: 'Enter',
411
+ });
412
+ await el.updateComplete;
413
+ expect(isSameDate(/** @type {Date} */ el.selectedDate, new Date('2000/10/12'))).to.be.true;
414
+ expect(dateChangedSpy.called).to.equal(false);
415
+ });
416
+ it('exposes focusedDate getter', async () => {
417
+ const el = await fixtureForSuite(html`
418
+ <${tagCalendar} .centralDate="${new Date('2019/06/01')}"></${tagCalendar}>
419
+ `);
420
+ const elObj = new CalendarObject(el);
421
+ expect(el.focusedDate).to.be.null;
422
+ elObj.getDayEl(15).click();
423
+ expect(isSameDate(/** @type {Date} */ el.focusedDate, new Date('2019/06/15'))).to.equal(
424
+ true,
425
+ );
426
+ });
427
+ it('has a focusDate() method to focus an arbitrary date', async () => {
428
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
429
+ const elObj = new CalendarObject(el);
430
+ await el.focusDate(new Date('2016/06/10'));
431
+ expect(isSameDate(/** @type {Date} */ el.focusedDate, new Date('2016/06/10'))).to.be.true;
432
+ expect(elObj.getDayObj(10).isFocused).to.be.true;
433
+ });
434
+ it('has a focusCentralDate() method to focus the central date', async () => {
435
+ const el = await fixtureForSuite(html`
436
+ <${tagCalendar}
437
+ .centralDate="${new Date('2015/12/02')}"
438
+ .selectedDate="${new Date('2015/12/04')}"
439
+ ></${tagCalendar}>
440
+ `);
441
+ const elObj = new CalendarObject(el);
442
+ el.focusCentralDate();
443
+ expect(isSameDate(/** @type {Date} */ el.focusedDate, new Date('2015/12/02'))).to.be.true;
444
+ expect(elObj.getDayObj(2).isFocused).to.be.true;
445
+ });
446
+ it('has a focusSelectedDate() method to focus the selected date', async () => {
447
+ const el = await fixtureForSuite(html`
448
+ <${tagCalendar}
449
+ .centralDate="${new Date('2014/07/05')}"
450
+ .selectedDate="${new Date('2014/07/07')}"
451
+ ></${tagCalendar}>
452
+ `);
453
+ const elObj = new CalendarObject(el);
454
+ await el.focusSelectedDate();
455
+ expect(isSameDate(/** @type {Date} */ el.focusedDate, new Date('2014/07/07'))).to.be.true;
456
+ expect(elObj.getDayObj(7).isFocused).to.be.true;
457
+ });
458
+ it('has a initCentralDate() method for external contexts like datepickers', async () => {
459
+ const initialCentralDate = new Date('2014/07/05');
460
+ const initialSelectedDate = new Date('2014/07/07');
461
+ const el = await fixtureForSuite(html`<${tagCalendar}
462
+ .centralDate="${initialCentralDate}"
463
+ .selectedDate="${initialSelectedDate}"
464
+ ></${tagCalendar}>`);
465
+ expect(el.selectedDate).to.equal(initialSelectedDate);
466
+ expect(el.centralDate).to.equal(initialCentralDate);
467
+ const newSelectedDate = new Date('2015/07/05');
468
+ el.selectedDate = newSelectedDate;
469
+ el.initCentralDate();
470
+ expect(el.centralDate).to.equal(newSelectedDate);
471
+ el.selectedDate = undefined;
472
+ el.initCentralDate();
473
+ expect(el.centralDate).to.equal(initialCentralDate);
474
+ });
475
+ describe('Enabled Dates', () => {
476
+ it('disables all days before "minDate" property', async () => {
477
+ const el = await fixtureForSuite(html`
478
+ <${tagCalendar}
479
+ .selectedDate="${new Date('2000/12/31')}"
480
+ .minDate="${new Date('2000/12/09')}"
481
+ >
482
+ </${tagCalendar}>
483
+ `);
484
+ const elObj = new CalendarObject(el);
485
+ expect(elObj.getDayObj(15).isDisabled).to.equal(false);
486
+ elObj.dayEls.forEach((d, i) => {
487
+ const shouldBeDisabled = i < 8;
488
+ expect(new DayObject(d).isDisabled).to.equal(shouldBeDisabled);
489
+ });
490
+ });
491
+ it('disables all days after "maxDate" property', async () => {
492
+ const el = await fixtureForSuite(html`
493
+ <${tagCalendar}
494
+ .selectedDate="${new Date('2000/12/01')}"
495
+ .maxDate="${new Date('2000/12/09')}"
496
+ >
497
+ </${tagCalendar}>
498
+ `);
499
+ const elObj = new CalendarObject(el);
500
+ expect(elObj.getDayObj(5).isDisabled).to.equal(false);
501
+ elObj.dayEls.forEach((d, i) => {
502
+ const shouldBeDisabled = i > 8;
503
+ expect(new DayObject(d).isDisabled).to.equal(shouldBeDisabled);
504
+ });
505
+ });
506
+ it('disables a date with disableDates function', async () => {
507
+ /** @param {Date} d */
508
+ const disable15th = (d) => d.getDate() === 15;
509
+ const el = await fixtureForSuite(html`
510
+ <${tagCalendar}
511
+ .selectedDate="${new Date('2000/12/01')}"
512
+ .disableDates=${disable15th}
513
+ ></${tagCalendar}>
514
+ `);
515
+ const elObj = new CalendarObject(el);
516
+ elObj.dayEls.forEach((d, i) => {
517
+ const shouldBeDisabled = i === 15 - 1;
518
+ expect(new DayObject(d).isDisabled).to.equal(shouldBeDisabled);
519
+ });
520
+ el.selectedDate = new Date('2000/11/01'); // When month view updates, it should still work
521
+ await el.updateComplete;
522
+ elObj.dayEls.forEach((d, i) => {
523
+ const shouldBeDisabled = i === 15 - 1;
524
+ expect(new DayObject(d).isDisabled).to.equal(shouldBeDisabled);
525
+ });
526
+ });
527
+ it('does not prevent initializing "centralDate" from "selectedDate" when today is disabled', async () => {
528
+ const clock = sinon.useFakeTimers({
529
+ now: new Date('2019/06/03').getTime(),
530
+ });
531
+ const el = await fixtureForSuite(html`
532
+ <${tagCalendar}
533
+ .selectedDate="${new Date('2001/01/08')}"
534
+ .disableDates=${/** @param {Date} date */ (date) => date.getDate() === 3}
535
+ ></${tagCalendar}>
536
+ `);
537
+ const elObj = new CalendarObject(el);
538
+ expect(isSameDate(el.centralDate, new Date('2001/01/08'))).to.be.true;
539
+ expect(elObj.activeMonth).to.equal('January');
540
+ expect(elObj.activeYear).to.equal('2001');
541
+ clock.restore();
542
+ });
543
+ it('requires the user to set an appropriate centralDate even when minDate and maxDate are equal', async () => {
544
+ const clock = sinon.useFakeTimers({
545
+ now: new Date('2019/06/03').getTime(),
546
+ });
547
+ const el = await fixtureForSuite(html`
548
+ <${tagCalendar}
549
+ .minDate="${new Date('2019/07/03')}"
550
+ .maxDate="${new Date('2019/07/03')}"
551
+ ></${tagCalendar}>
552
+ `);
553
+ const elSetting = await fixtureForSuite(html`
554
+ <${tagCalendar}
555
+ .centralDate="${new Date('2019/07/03')}"
556
+ .minDate="${new Date('2019/07/03')}"
557
+ .maxDate="${new Date('2019/07/03')}"
558
+ ></${tagCalendar}>
559
+ `);
560
+ clock.restore();
561
+ expect(isSameDate(el.centralDate, new Date('2019/07/03'))).to.be.true;
562
+ expect(isSameDate(elSetting.centralDate, new Date('2019/07/03'))).to.be.true;
563
+ });
564
+ describe('Normalization', () => {
565
+ it('normalizes all generated dates', async () => {
566
+ /** @param {Date} d */
567
+ function isNormalizedDate(d) {
568
+ return d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0;
569
+ }
570
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
571
+ // The central date will be today's date: it's the date all other
572
+ // dates in the month view will be derived from.
573
+ expect(isNormalizedDate(el.centralDate)).to.be.true;
574
+ });
575
+ it('normalizes dates in date comparisons', async () => {
576
+ const selectedDate = new Date('2000-11-04T03:00:00');
577
+ // without normalization, selectedDate > maxDate would wrongfully be disabled
578
+ const maxDate = new Date('2000-11-29T02:00:00');
579
+ // without normalization, selectedDate < minDate would wrongfully be disabled
580
+ const minDate = new Date('2000-11-02T04:00:00');
581
+ const el = await fixtureForSuite(html`
582
+ <${tagCalendar}
583
+ .selectedDate="${selectedDate}"
584
+ .minDate="${minDate}"
585
+ .maxDate="${maxDate}"
586
+ ></${tagCalendar}>
587
+ `);
588
+ const elObj = new CalendarObject(el);
589
+ expect(elObj.getDayObj(29).isDisabled).to.equal(false);
590
+ expect(elObj.getDayObj(30).isDisabled).to.equal(true);
591
+ expect(elObj.getDayObj(2).isDisabled).to.equal(false);
592
+ expect(elObj.getDayObj(1).isDisabled).to.equal(true);
593
+ });
594
+ });
595
+ });
596
+ });
597
+ describe('Calendar navigation', () => {
598
+ describe('Title', () => {
599
+ it('contains secondary title displaying the current month and year in focus', async () => {
600
+ const el = await fixtureForSuite(html`<${tagCalendar}
601
+
602
+ .selectedDate="${new Date('2000/12/12')}"
603
+ ></${tagCalendar}>`);
604
+ const elObj = new CalendarObject(el);
605
+ expect(elObj.activeMonth).to.equal('December');
606
+ expect(elObj.activeYear).to.equal('2000');
607
+ });
608
+ it('updates the secondary title when the displayed month/year changes', async () => {
609
+ const el = await fixtureForSuite(
610
+ html`<${tagCalendar} .centralDate="${new Date('2000/12/12')}"></${tagCalendar}>`,
611
+ );
612
+ const elObj = new CalendarObject(el);
613
+ el.centralDate = new Date('1999/10/12');
614
+ await el.updateComplete;
615
+ expect(elObj.activeMonth).to.equal('October');
616
+ expect(elObj.activeYear).to.equal('1999');
617
+ });
618
+ describe('Accessibility', () => {
619
+ it('has aria-atomic="true" set on the secondary title', async () => {
620
+ const elObj = new CalendarObject(
621
+ await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`),
622
+ );
623
+ expect(elObj.monthHeadingEl?.getAttribute('aria-atomic')).to.equal('true');
624
+ });
625
+ });
626
+ });
627
+ describe('Navigation', () => {
628
+ describe('finding enabled dates', () => {
629
+ it('has helper for `findNextEnabledDate()`, `findPreviousEnabledDate()`, `findNearestEnabledDate()`', async () => {
630
+ const el = await fixtureForSuite(html`
631
+ <${tagCalendar}
632
+ .selectedDate="${new Date('2001/01/02')}"
633
+ .disableDates=${/** @param {Date} date */ (date) => date.getDate() === 3 || date.getDate() === 4}
634
+ ></${tagCalendar}>
635
+ `);
636
+ const elObj = new CalendarObject(el);
637
+ el.focusDate(el.findNextEnabledDate());
638
+ await el.updateComplete;
639
+ expect(elObj.focusedDayObj?.monthday).to.equal(5);
640
+ el.focusDate(el.findPreviousEnabledDate());
641
+ await el.updateComplete;
642
+ expect(elObj.focusedDayObj?.monthday).to.equal(2);
643
+ el.focusDate(el.findNearestEnabledDate());
644
+ await el.updateComplete;
645
+ expect(elObj.focusedDayObj?.monthday).to.equal(1);
646
+ });
647
+ it('future dates take precedence over past dates when "distance" between dates is equal', async () => {
648
+ const clock = sinon.useFakeTimers({
649
+ now: new Date('2000/12/15').getTime(),
650
+ });
651
+ const el = await fixtureForSuite(html`
652
+ <${tagCalendar}
653
+ .disableDates="${/** @param {Date} d */ (d) => d.getDate() === 15}"
654
+ ></${tagCalendar}>
655
+ `);
656
+ el.focusDate(el.findNearestEnabledDate(new Date()));
657
+ await el.updateComplete;
658
+ const elObj = new CalendarObject(el);
659
+ expect(elObj.centralDayObj?.monthday).to.equal(16);
660
+ clock.restore();
661
+ });
662
+ it('will search 750 days in the past', async () => {
663
+ const clock = sinon.useFakeTimers({
664
+ now: new Date('2000/12/15').getTime(),
665
+ });
666
+ const el = await fixtureForSuite(html`
667
+ <${tagCalendar}
668
+ .disableDates="${/** @param {Date} d */ (d) => d.getFullYear() > 1998}"
669
+ ></${tagCalendar}>
670
+ `);
671
+ el.focusDate(el.findNearestEnabledDate(new Date()));
672
+ await el.updateComplete;
673
+ expect(el.centralDate.getFullYear()).to.equal(1998);
674
+ expect(el.centralDate.getMonth()).to.equal(11);
675
+ expect(el.centralDate.getDate()).to.equal(31);
676
+ clock.restore();
677
+ });
678
+ it('will search 750 days in the future', async () => {
679
+ const clock = sinon.useFakeTimers({
680
+ now: new Date('2000/12/15').getTime(),
681
+ });
682
+ const el = await fixtureForSuite(html`
683
+ <${tagCalendar}
684
+ .disableDates="${/** @param {Date} d */ (d) => d.getFullYear() < 2002}"
685
+ ></${tagCalendar}>
686
+ `);
687
+ el.focusDate(el.findNearestEnabledDate(new Date()));
688
+ await el.updateComplete;
689
+ expect(el.centralDate.getFullYear()).to.equal(2002);
690
+ expect(el.centralDate.getMonth()).to.equal(0);
691
+ expect(el.centralDate.getDate()).to.equal(1);
692
+ clock.restore();
693
+ });
694
+ it('throws if no available date can be found within +/- 750 days', async () => {
695
+ const el = await fixtureForSuite(html`
696
+ <${tagCalendar}
697
+ .disableDates="${/** @param {Date} d */ (d) => d.getFullYear() < 2002}"
698
+ ></${tagCalendar}>
699
+ `);
700
+ expect(() => {
701
+ el.findNextEnabledDate(new Date('1900/01/01'));
702
+ }).to.throw(Error, 'Could not find a selectable date within +/- 750 day for 1900/1/1');
703
+ });
704
+ });
705
+ describe('Year', () => {
706
+ it('has a button for navigation to previous year', async () => {
707
+ const el = await fixtureForSuite(
708
+ html`<${tagCalendar} .selectedDate="${new Date('2001/01/01')}"></${tagCalendar}>`,
709
+ );
710
+ const elObj = new CalendarObject(el);
711
+ expect(elObj.previousYearButtonEl).not.to.equal(null);
712
+ expect(elObj.activeMonth).to.equal('January');
713
+ expect(elObj.activeYear).to.equal('2001');
714
+
715
+ /** @type {HTMLElement} */
716
+ elObj.previousYearButtonEl.click();
717
+ await el.updateComplete;
718
+ expect(elObj.activeMonth).to.equal('January');
719
+ expect(elObj.activeYear).to.equal('2000');
720
+
721
+ /** @type {HTMLElement} */
722
+ elObj.previousYearButtonEl.click();
723
+ await el.updateComplete;
724
+ expect(elObj.activeMonth).to.equal('January');
725
+ expect(elObj.activeYear).to.equal('1999');
726
+ });
727
+ it('has a button for navigation to next year', async () => {
728
+ const el = await fixtureForSuite(
729
+ html`<${tagCalendar} .selectedDate="${new Date('2000/12/12')}"></${tagCalendar}>`,
730
+ );
731
+ const elObj = new CalendarObject(el);
732
+ expect(elObj.nextYearButtonEl).not.to.equal(null);
733
+ expect(elObj.activeMonth).to.equal('December');
734
+ expect(elObj.activeYear).to.equal('2000');
735
+
736
+ /** @type {HTMLElement} */
737
+ elObj.nextYearButtonEl.click();
738
+ await el.updateComplete;
739
+ expect(elObj.activeMonth).to.equal('December');
740
+ expect(elObj.activeYear).to.equal('2001');
741
+
742
+ /** @type {HTMLElement} */
743
+ elObj.nextYearButtonEl.click();
744
+ await el.updateComplete;
745
+ expect(elObj.activeMonth).to.equal('December');
746
+ expect(elObj.activeYear).to.equal('2002');
747
+ });
748
+ it('disables previousYearButton and nextYearButton based on disabled days accordingly', async () => {
749
+ const el = await fixtureForSuite(html`
750
+ <${tagCalendar} .selectedDate="${new Date('2000/06/12')}"></${tagCalendar}>
751
+ `);
752
+ const elObj = new CalendarObject(el);
753
+ expect(elObj.activeMonth).to.equal('June');
754
+ expect(elObj.activeYear).to.equal('2000');
755
+ expect(elObj.previousYearButtonEl?.hasAttribute('disabled')).to.equal(false);
756
+ expect(elObj.nextYearButtonEl?.hasAttribute('disabled')).to.equal(false);
757
+ el.minDate = new Date('2000/01/01');
758
+ el.maxDate = new Date('2000/12/31');
759
+ await el.updateComplete;
760
+ expect(elObj.previousYearButtonEl?.hasAttribute('disabled')).to.equal(true);
761
+ expect(elObj.nextYearButtonEl?.hasAttribute('disabled')).to.equal(true);
762
+
763
+ /** @type {HTMLElement} */
764
+ elObj.previousYearButtonEl.click();
765
+ await el.updateComplete;
766
+ expect(elObj.activeMonth).to.equal('June');
767
+ expect(elObj.activeYear).to.equal('2000');
768
+ el.minDate = new Date('1999/12/31');
769
+ el.maxDate = new Date('2001/01/01');
770
+ await el.updateComplete;
771
+ expect(elObj.previousYearButtonEl?.hasAttribute('disabled')).to.equal(false);
772
+ expect(elObj.nextYearButtonEl?.hasAttribute('disabled')).to.equal(false);
773
+ });
774
+ it('sets label to correct month previousYearButton and nextYearButton based on disabled days accordingly', async () => {
775
+ const el = await fixtureForSuite(html`
776
+ <${tagCalendar} .selectedDate="${new Date('2000/06/12')}"></${tagCalendar}>
777
+ `);
778
+ const elObj = new CalendarObject(el);
779
+ el.minDate = new Date('1999/07/12');
780
+ el.maxDate = new Date('2001/05/12');
781
+ await el.updateComplete;
782
+ expect(elObj.previousYearButtonEl?.hasAttribute('disabled')).to.equal(false);
783
+ expect(accessibleName(elObj.previousYearButtonEl)).to.equal('Previous year, July 1999');
784
+ expect(elObj.nextYearButtonEl?.hasAttribute('disabled')).to.equal(false);
785
+ expect(accessibleName(elObj.nextYearButtonEl)).to.equal('Next year, May 2001');
786
+ });
787
+ });
788
+ describe('Month', () => {
789
+ it('has a button for navigation to previous month', async () => {
790
+ const el = await fixtureForSuite(
791
+ html`<${tagCalendar} .selectedDate="${new Date('2001/01/01')}"></${tagCalendar}>`,
792
+ );
793
+ const elObj = new CalendarObject(el);
794
+ expect(elObj.previousMonthButtonEl).not.to.equal(null);
795
+ expect(elObj.activeMonth).to.equal('January');
796
+ expect(elObj.activeYear).to.equal('2001');
797
+
798
+ /** @type {HTMLElement} */
799
+ elObj.previousMonthButtonEl.click();
800
+ await el.updateComplete;
801
+ expect(elObj.activeMonth).to.equal('December');
802
+ expect(elObj.activeYear).to.equal('2000');
803
+
804
+ /** @type {HTMLElement} */
805
+ elObj.previousMonthButtonEl.click();
806
+ await el.updateComplete;
807
+ expect(elObj.activeMonth).to.equal('November');
808
+ expect(elObj.activeYear).to.equal('2000');
809
+ });
810
+ it('has a button for navigation to next month', async () => {
811
+ const el = await fixtureForSuite(
812
+ html`<${tagCalendar} .selectedDate="${new Date('2000/12/12')}"></${tagCalendar}>`,
813
+ );
814
+ const elObj = new CalendarObject(el);
815
+ expect(elObj.nextMonthButtonEl).not.to.equal(null);
816
+ expect(elObj.activeMonth).to.equal('December');
817
+ expect(elObj.activeYear).to.equal('2000');
818
+ /** @type {HTMLElement} */
819
+ elObj.nextMonthButtonEl.click();
820
+ await el.updateComplete;
821
+ expect(elObj.activeMonth).to.equal('January');
822
+ expect(elObj.activeYear).to.equal('2001');
823
+
824
+ /** @type {HTMLElement} */
825
+ elObj.nextMonthButtonEl.click();
826
+ await el.updateComplete;
827
+ expect(elObj.activeMonth).to.equal('February');
828
+ expect(elObj.activeYear).to.equal('2001');
829
+ });
830
+ it('disables previousMonthButton and nextMonthButton based on disabled days accordingly', async () => {
831
+ const el = await fixtureForSuite(html`
832
+ <${tagCalendar} .selectedDate="${new Date('2000/12/12')}"></${tagCalendar}>
833
+ `);
834
+ const elObj = new CalendarObject(el);
835
+ expect(elObj.activeMonth).to.equal('December');
836
+ expect(elObj.activeYear).to.equal('2000');
837
+ expect(elObj.previousMonthButtonEl?.hasAttribute('disabled')).to.equal(false);
838
+ expect(elObj.nextMonthButtonEl?.hasAttribute('disabled')).to.equal(false);
839
+ el.minDate = new Date('2000/12/01');
840
+ el.maxDate = new Date('2000/12/31');
841
+ await el.updateComplete;
842
+ expect(elObj.previousMonthButtonEl?.hasAttribute('disabled')).to.equal(true);
843
+ expect(elObj.nextMonthButtonEl?.hasAttribute('disabled')).to.equal(true);
844
+ /** @type {HTMLElement} */
845
+ elObj.previousMonthButtonEl.click();
846
+ await el.updateComplete;
847
+ expect(elObj.activeMonth).to.equal('December');
848
+ expect(elObj.activeYear).to.equal('2000');
849
+ /** @type {HTMLElement} */
850
+ elObj.previousMonthButtonEl.click();
851
+ await el.updateComplete;
852
+ expect(elObj.activeMonth).to.equal('December');
853
+ expect(elObj.activeYear).to.equal('2000');
854
+ });
855
+ it('handles switch to previous month when dates are disabled', async () => {
856
+ const clock = sinon.useFakeTimers({
857
+ now: new Date('2000/12/15').getTime(),
858
+ });
859
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
860
+ const elObj = new CalendarObject(el);
861
+ expect(elObj.activeMonth).to.equal('December');
862
+ expect(elObj.activeYear).to.equal('2000');
863
+ el.minDate = new Date('2000/11/20');
864
+ await el.updateComplete;
865
+ expect(elObj.previousMonthButtonEl?.hasAttribute('disabled')).to.equal(false);
866
+ expect(isSameDate(el.centralDate, new Date('2000/12/15'))).to.be.true;
867
+
868
+ /** @type {HTMLElement} */
869
+ elObj.previousMonthButtonEl.click();
870
+ await el.updateComplete;
871
+ expect(elObj.activeMonth).to.equal('November');
872
+ expect(elObj.activeYear).to.equal('2000');
873
+ expect(isSameDate(el.centralDate, new Date('2000/11/15'))).to.be.true;
874
+ clock.restore();
875
+ });
876
+ it('handles switch to next month when dates are disabled', async () => {
877
+ const clock = sinon.useFakeTimers({
878
+ now: new Date('2000/12/15').getTime(),
879
+ });
880
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
881
+ const elObj = new CalendarObject(el);
882
+ expect(elObj.activeMonth).to.equal('December');
883
+ expect(elObj.activeYear).to.equal('2000');
884
+ el.maxDate = new Date('2001/01/10');
885
+ await el.updateComplete;
886
+ expect(elObj.nextMonthButtonEl?.hasAttribute('disabled')).to.equal(false);
887
+ expect(isSameDate(el.centralDate, new Date('2000/12/15'))).to.be.true;
888
+ /** @type {HTMLElement} */
889
+ elObj.nextMonthButtonEl.click();
890
+ await el.updateComplete;
891
+ expect(elObj.activeMonth).to.equal('January');
892
+ expect(elObj.activeYear).to.equal('2001');
893
+ expect(isSameDate(el.centralDate, new Date('2001/01/15'))).to.be.true;
894
+ clock.restore();
895
+ });
896
+ it('supports navigating from larger months to smaller ones (day counts)', async () => {
897
+ // given
898
+ const inputDate = new Date('2019/08/31');
899
+ const element = await fixtureForSuite(html`
900
+ <${tagCalendar} .centralDate="${inputDate}"> </${tagCalendar}>
901
+ `);
902
+ // when
903
+ const remote = new CalendarObject(element);
904
+ /** @type {HTMLElement} */
905
+ remote.nextMonthButtonEl.click();
906
+ await element.updateComplete;
907
+ // then
908
+ expect(remote.activeMonth).to.equal('September');
909
+ expect(remote.activeYear).to.equal('2019');
910
+ expect(remote.centralDayObj?.el).dom.to.equal(`
911
+ <div
912
+ class="calendar__day-button"
913
+ aria-disabled="false"
914
+ role="button"
915
+ tabindex="0"
916
+ aria-pressed="false"
917
+ past=""
918
+ current-month="">
919
+ <span class="calendar__day-button__text">
920
+ 30
921
+ </span>
922
+ <span class="u-sr-only">
923
+ September 2019 Monday
924
+ </span>
925
+ </div>
926
+ `);
927
+ });
928
+ });
929
+ describe('Accessibility', () => {
930
+ it('navigate buttons have a aria-label and title attribute with accessible label', async () => {
931
+ const el = await fixtureForSuite(html`
932
+ <${tagCalendar} .selectedDate="${new Date('2000/12/12')}"></${tagCalendar}>
933
+ `);
934
+ const elObj = new CalendarObject(el);
935
+ // month
936
+ expect(accessibleName(elObj.previousMonthButtonEl)).to.equal(
937
+ 'Previous month, November 2000',
938
+ );
939
+ expect(accessibleName(elObj.previousMonthButtonEl)).to.equal(
940
+ 'Previous month, November 2000',
941
+ );
942
+ expect(accessibleName(elObj.nextMonthButtonEl)).to.equal('Next month, January 2001');
943
+ expect(accessibleName(elObj.nextMonthButtonEl)).to.equal('Next month, January 2001');
944
+
945
+ // year
946
+ expect(accessibleName(elObj.previousYearButtonEl)).to.equal(
947
+ 'Previous year, December 1999',
948
+ );
949
+ expect(accessibleName(elObj.previousYearButtonEl)).to.equal(
950
+ 'Previous year, December 1999',
951
+ );
952
+ expect(accessibleName(elObj.nextYearButtonEl)).to.equal('Next year, December 2001');
953
+ expect(accessibleName(elObj.nextYearButtonEl)).to.equal('Next year, December 2001');
954
+ });
955
+ it('disables a date with disableDates function provide a correct message', async () => {
956
+ /** @param {Date} d */
957
+ const disable15th = (d) => d.getDate() === 15;
958
+ const el = await fixtureForSuite(html`
959
+ <${tagCalendar}
960
+ .selectedDate="${new Date('2000/12/01')}"
961
+ .disableDates=${disable15th}
962
+ ></${tagCalendar}>
963
+ `);
964
+ const elObj = new CalendarObject(el);
965
+ expect(elObj.getDayObj(15).isDisabled).to.equal(true);
966
+ expect(elObj.getDayObj(15).el).dom.to.equal(`
967
+ <div
968
+ class="calendar__day-button"
969
+ aria-disabled="true"
970
+ role="button"
971
+ tabindex="-1"
972
+ aria-pressed="false"
973
+ past=""
974
+ current-month="">
975
+ <span class="calendar__day-button__text">
976
+ 15
977
+ </span>
978
+ <span class="u-sr-only">
979
+ December 2000 Friday This date is unavailable. Please choose another date.
980
+ </span>
981
+ </div>
982
+ `);
983
+ });
984
+ it('disables days before "minDate" property provide a correct message', async () => {
985
+ const el = await fixtureForSuite(html`
986
+ <${tagCalendar}
987
+ .selectedDate="${new Date('2000/12/31')}"
988
+ .minDate="${new Date('2000/12/09')}"
989
+ >
990
+ </${tagCalendar}>
991
+ `);
992
+ const elObj = new CalendarObject(el);
993
+ expect(elObj.getDayObj(1).isDisabled).to.equal(true);
994
+ expect(elObj.getDayObj(1).el).dom.to.equal(`
995
+ <div
996
+ class="calendar__day-button"
997
+ aria-disabled="true"
998
+ role="button"
999
+ tabindex="-1"
1000
+ aria-pressed="false"
1001
+ past=""
1002
+ current-month="">
1003
+ <span class="calendar__day-button__text">
1004
+ 1
1005
+ </span>
1006
+ <span class="u-sr-only">
1007
+ December 2000 Friday This date is unavailable. Earliest available date is 9 December 2000. Please choose another date.
1008
+ </span>
1009
+ </div>
1010
+ `);
1011
+ });
1012
+ it('disables days after "maxDate" property provide a correct message', async () => {
1013
+ const el = await fixtureForSuite(html`
1014
+ <${tagCalendar}
1015
+ .selectedDate="${new Date('2000/12/31')}"
1016
+ .maxDate="${new Date('2000/12/09')}"
1017
+ >
1018
+ </${tagCalendar}>
1019
+ `);
1020
+ const elObj = new CalendarObject(el);
1021
+ expect(elObj.getDayObj(30).isDisabled).to.equal(true);
1022
+ expect(elObj.getDayObj(30).el).dom.to.equal(`
1023
+ <div
1024
+ class="calendar__day-button"
1025
+ aria-disabled="true"
1026
+ role="button"
1027
+ tabindex="-1"
1028
+ aria-pressed="false"
1029
+ past=""
1030
+ current-month="">
1031
+ <span class="calendar__day-button__text">
1032
+ 30
1033
+ </span>
1034
+ <span class="u-sr-only">
1035
+ December 2000 Saturday This date is unavailable. Latest available date is 9 December 2000. Please choose another date.
1036
+ </span>
1037
+ </div>
1038
+ `);
1039
+ });
1040
+ });
1041
+ });
1042
+ });
1043
+ describe('Calendar body (months view)', () => {
1044
+ it('renders the days of the week as table headers', async () => {
1045
+ const el = await fixtureForSuite(html`<${tagCalendar}
1046
+ .firstDayOfWeek=${0}
1047
+ .selectedDate="${new Date('2000/12/12')}"
1048
+ ></${tagCalendar}>`);
1049
+ const elObj = new CalendarObject(el);
1050
+ expect(elObj.weekdayHeaderEls.map((h) => h.textContent?.trim())).to.deep.equal([
1051
+ 'Sun',
1052
+ 'Mon',
1053
+ 'Tue',
1054
+ 'Wed',
1055
+ 'Thu',
1056
+ 'Fri',
1057
+ 'Sat',
1058
+ ]);
1059
+ });
1060
+ describe('Day view', () => {
1061
+ it('adds "today" attribute if date is today', async () => {
1062
+ const clock = sinon.useFakeTimers({
1063
+ now: new Date('2000/12/15').getTime(),
1064
+ });
1065
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
1066
+ const elObj = new CalendarObject(el);
1067
+ expect(elObj.getDayEl(15).hasAttribute('today')).to.be.true;
1068
+ expect(
1069
+ elObj.checkForAllDayObjs(/** @param {DayObject} d */ (d) => d.isToday, [15]),
1070
+ ).to.equal(true);
1071
+ clock.restore();
1072
+ });
1073
+ it('adds "selected" attribute to the selected date', async () => {
1074
+ const el = await fixtureForSuite(
1075
+ html`<${tagCalendar} .selectedDate="${new Date('2000/12/12')}"></${tagCalendar}>`,
1076
+ );
1077
+ const elObj = new CalendarObject(el);
1078
+ expect(
1079
+ elObj.checkForAllDayObjs(
1080
+ /** @param {DayObject} obj */ (obj) => obj.el.hasAttribute('selected'),
1081
+ [12],
1082
+ ),
1083
+ ).to.equal(true);
1084
+ el.selectedDate = new Date('2000/12/15');
1085
+ await el.updateComplete;
1086
+ expect(
1087
+ elObj.checkForAllDayObjs(
1088
+ /** @param {DayObject} obj */ (obj) => obj.el.hasAttribute('selected'),
1089
+ [15],
1090
+ ),
1091
+ ).to.equal(true);
1092
+ });
1093
+ it('adds aria-disabled="true" attribute to disabled dates', async () => {
1094
+ const clock = sinon.useFakeTimers({
1095
+ now: new Date('2000/12/15').getTime(),
1096
+ });
1097
+ const el = await fixtureForSuite(html`
1098
+ <${tagCalendar}
1099
+ .selectedDate="${new Date('2000/12/10')}"
1100
+ .minDate="${new Date('2000/12/03')}"
1101
+ .maxDate="${new Date('2000/12/29')}"
1102
+ >
1103
+ </${tagCalendar}>
1104
+ `);
1105
+ const elObj = new CalendarObject(el);
1106
+ expect(
1107
+ elObj.checkForAllDayObjs(
1108
+ /** @param {DayObject} d */ (d) => d.el.getAttribute('aria-disabled') === 'true',
1109
+ [1, 2, 30, 31],
1110
+ ),
1111
+ ).to.equal(true);
1112
+ clock.restore();
1113
+ });
1114
+ });
1115
+ describe('User Interaction', () => {
1116
+ // For implementation, base on: https://www.w3.org/TR/2017/NOTE-wai-aria-practices-1.1-20171214/examples/grid/js/dataGrid.js
1117
+
1118
+ describe('Keyboard Navigation', () => {
1119
+ it('focused day is reachable via tab (tabindex="0")', async () => {
1120
+ const el = await fixtureForSuite(html`
1121
+ <${tagCalendar} .selectedDate="${new Date('2000/12/12')}"></${tagCalendar}>
1122
+ `);
1123
+ const elObj = new CalendarObject(el);
1124
+ expect(
1125
+ elObj.checkForAllDayObjs(
1126
+ /** @param {DayObject} d */ (d) => d.buttonEl.getAttribute('tabindex') === '0',
1127
+ [12],
1128
+ ),
1129
+ ).to.equal(true);
1130
+ });
1131
+ it('non focused days are not reachable via tab (have tabindex="-1")', async () => {
1132
+ const el = await fixtureForSuite(html`
1133
+ <${tagCalendar} .selectedDate="${new Date('2000/12/12')}"></${tagCalendar}>
1134
+ `);
1135
+ const elObj = new CalendarObject(el);
1136
+ expect(
1137
+ elObj.checkForAllDayObjs(
1138
+ /** @param {DayObject} d */ (d) => d.buttonEl.getAttribute('tabindex') === '-1',
1139
+ /** @param {number} dayNumber */ (dayNumber) => dayNumber !== 12,
1140
+ ),
1141
+ ).to.equal(true);
1142
+ });
1143
+ it('blocks navigation to disabled days', async () => {
1144
+ const el = await fixtureForSuite(html`
1145
+ <${tagCalendar}
1146
+ .selectedDate="${new Date('2000/12/31')}"
1147
+ .minDate="${new Date('2000/12/09')}"
1148
+ >
1149
+ </${tagCalendar}>
1150
+ `);
1151
+ const elObj = new CalendarObject(el);
1152
+ expect(
1153
+ elObj.checkForAllDayObjs(
1154
+ /** @param {DayObject} d */ (d) => d.buttonEl.getAttribute('tabindex') === '-1',
1155
+ /** @param {number} dayNumber */ (dayNumber) => dayNumber < 9,
1156
+ ),
1157
+ ).to.equal(true);
1158
+ });
1159
+ it('navigates through months with [pageup] [pagedown] keys', async () => {
1160
+ const el = await fixtureForSuite(html`
1161
+ <${tagCalendar} .selectedDate="${new Date('2001/01/02')}"></${tagCalendar}>
1162
+ `);
1163
+ const elObj = new CalendarObject(el);
1164
+ expect(elObj.activeMonth).to.equal('January');
1165
+ expect(elObj.activeYear).to.equal('2001');
1166
+ focusSelectedDate(el);
1167
+ await sendKeys({
1168
+ press: 'PageUp',
1169
+ });
1170
+ await el.updateComplete;
1171
+ expect(elObj.activeMonth).to.equal('December');
1172
+ expect(elObj.activeYear).to.equal('2000');
1173
+ await sendKeys({
1174
+ press: 'PageDown',
1175
+ });
1176
+ await el.updateComplete;
1177
+ expect(elObj.activeMonth).to.equal('January');
1178
+ expect(elObj.activeYear).to.equal('2001');
1179
+ });
1180
+ it('navigates through years with [alt + pageup] [alt + pagedown] keys', async () => {
1181
+ const el = await fixtureForSuite(html`
1182
+ <${tagCalendar} .selectedDate="${new Date('2001/01/02')}"></${tagCalendar}>
1183
+ `);
1184
+ focusSelectedDate(el);
1185
+ const elObj = new CalendarObject(el);
1186
+ expect(elObj.activeMonth).to.equal('January');
1187
+ expect(elObj.activeYear).to.equal('2001');
1188
+ await sendKeys({
1189
+ down: 'Alt',
1190
+ });
1191
+ await sendKeys({
1192
+ press: 'PageDown',
1193
+ });
1194
+ await sendKeys({
1195
+ up: 'Alt',
1196
+ });
1197
+ await el.updateComplete;
1198
+ focusSelectedDate(el);
1199
+ expect(elObj.activeMonth).to.equal('January');
1200
+ expect(elObj.activeYear).to.equal('2002');
1201
+ await sendKeys({
1202
+ down: 'Alt',
1203
+ });
1204
+ await sendKeys({
1205
+ press: 'PageUp',
1206
+ });
1207
+ await sendKeys({
1208
+ up: 'Alt',
1209
+ });
1210
+ await el.updateComplete;
1211
+ expect(elObj.activeMonth).to.equal('January');
1212
+ expect(elObj.activeYear).to.equal('2001');
1213
+ });
1214
+ describe('Arrow keys', () => {
1215
+ it('navigates (sets focus) to next row item via [arrow down] key', async () => {
1216
+ const el = await fixtureForSuite(html`
1217
+ <${tagCalendar} .selectedDate="${new Date('2001/01/02')}"></${tagCalendar}>
1218
+ `);
1219
+ const elObj = new CalendarObject(el);
1220
+ focusSelectedDate(el);
1221
+ await sendKeys({
1222
+ press: 'ArrowDown',
1223
+ });
1224
+ await el.updateComplete;
1225
+ expect(elObj.focusedDayObj?.monthday).to.equal(2 + 7);
1226
+ });
1227
+ it('navigates (sets focus) to previous row item via [arrow up] key', async () => {
1228
+ const el = await fixtureForSuite(html`
1229
+ <${tagCalendar} .selectedDate="${new Date('2001/01/02')}"></${tagCalendar}>
1230
+ `);
1231
+ const elObj = new CalendarObject(el);
1232
+ focusSelectedDate(el);
1233
+ await sendKeys({
1234
+ press: 'ArrowUp',
1235
+ });
1236
+ await el.updateComplete;
1237
+ expect(elObj.focusedDayObj?.monthday).to.equal(26); // of month before
1238
+ });
1239
+ it('navigates (sets focus) to previous column item via [arrow left] key', async () => {
1240
+ // 2000-12-12 is Tuesday; at 2nd of row
1241
+ const el = await fixtureForSuite(html`
1242
+ <${tagCalendar} .selectedDate="${new Date('2000/12/12')}"></${tagCalendar}>
1243
+ `);
1244
+ const elObj = new CalendarObject(el);
1245
+ focusSelectedDate(el);
1246
+ await sendKeys({
1247
+ press: 'ArrowLeft',
1248
+ });
1249
+ await el.updateComplete;
1250
+ expect(elObj.focusedDayObj?.monthday).to.equal(12 - 1);
1251
+ });
1252
+ it('navigates (sets focus) to next column item via [arrow right] key', async () => {
1253
+ // 2000-12-12 is Tuesday; at 2nd of row
1254
+ const el = await fixtureForSuite(html`
1255
+ <${tagCalendar} .selectedDate="${new Date('2000/12/12')}"></${tagCalendar}>
1256
+ `);
1257
+ const elObj = new CalendarObject(el);
1258
+ focusSelectedDate(el);
1259
+ await sendKeys({
1260
+ press: 'ArrowRight',
1261
+ });
1262
+ await el.updateComplete;
1263
+ expect(elObj.focusedDayObj?.monthday).to.equal(12 + 1);
1264
+ });
1265
+ it('navigates (sets focus) to next column item via [arrow right] key', async () => {
1266
+ const el = await fixtureForSuite(html`
1267
+ <${tagCalendar}
1268
+ .selectedDate="${new Date('2001/01/02')}"
1269
+ .disableDates=${/** @param {Date} date */ (date) => date.getDate() === 3 || date.getDate() === 4}
1270
+ ></${tagCalendar}>
1271
+ `);
1272
+ const elObj = new CalendarObject(el);
1273
+ focusSelectedDate(el);
1274
+ await sendKeys({
1275
+ press: 'ArrowRight',
1276
+ });
1277
+ await el.updateComplete;
1278
+ expect(elObj.focusedDayObj?.monthday).to.equal(3);
1279
+ });
1280
+ it('navigates (sets focus) to next row via [arrow right] key if last item in row', async () => {
1281
+ const el = await fixtureForSuite(html`
1282
+ <${tagCalendar}
1283
+ .firstDayOfWeek=${0}
1284
+ .selectedDate="${new Date('2019/01/05')}"
1285
+ ></${tagCalendar}>
1286
+ `);
1287
+ const elObj = new CalendarObject(el);
1288
+ expect(elObj.centralDayObj?.weekdayNameShort).to.equal('Sat');
1289
+ focusSelectedDate(el);
1290
+ await sendKeys({
1291
+ press: 'ArrowRight',
1292
+ });
1293
+ await el.updateComplete;
1294
+ expect(elObj.focusedDayObj?.monthday).to.equal(6);
1295
+ expect(elObj.focusedDayObj?.weekdayNameShort).to.equal('Sun');
1296
+ });
1297
+ it('navigates (sets focus) to previous row via [arrow left] key if first item in row', async () => {
1298
+ const el = await fixtureForSuite(html`
1299
+ <${tagCalendar}
1300
+ .firstDayOfWeek=${0}
1301
+ .selectedDate="${new Date('2019/01/06')}"
1302
+ ></${tagCalendar}>
1303
+ `);
1304
+ const elObj = new CalendarObject(el);
1305
+ expect(elObj.centralDayObj?.weekdayNameShort).to.equal('Sun');
1306
+ focusSelectedDate(el);
1307
+ await sendKeys({
1308
+ press: 'ArrowLeft',
1309
+ });
1310
+ await el.updateComplete;
1311
+ expect(elObj.focusedDayObj?.monthday).to.equal(5);
1312
+ expect(elObj.focusedDayObj?.weekdayNameShort).to.equal('Sat');
1313
+ });
1314
+ it('navigates to next month via [arrow right] key if last day of month', async () => {
1315
+ const el = await fixtureForSuite(html`
1316
+ <${tagCalendar} .selectedDate="${new Date('2000/12/31')}"></${tagCalendar}>
1317
+ `);
1318
+ const elObj = new CalendarObject(el);
1319
+ expect(elObj.activeMonth).to.equal('December');
1320
+ expect(elObj.activeYear).to.equal('2000');
1321
+ focusSelectedDate(el);
1322
+ await sendKeys({
1323
+ press: 'ArrowRight',
1324
+ });
1325
+ await el.updateComplete;
1326
+ expect(elObj.activeMonth).to.equal('January');
1327
+ expect(elObj.activeYear).to.equal('2001');
1328
+ expect(elObj.focusedDayObj?.monthday).to.equal(1);
1329
+ });
1330
+ it('navigates to previous month via [arrow left] key if first day of month', async () => {
1331
+ const el = await fixtureForSuite(html`
1332
+ <${tagCalendar} .selectedDate="${new Date('2001/01/01')}"></${tagCalendar}>
1333
+ `);
1334
+ const elObj = new CalendarObject(el);
1335
+ expect(elObj.activeMonth).to.equal('January');
1336
+ expect(elObj.activeYear).to.equal('2001');
1337
+ focusSelectedDate(el);
1338
+ await sendKeys({
1339
+ press: 'ArrowLeft',
1340
+ });
1341
+ await el.updateComplete;
1342
+ expect(elObj.activeMonth).to.equal('December');
1343
+ expect(elObj.activeYear).to.equal('2000');
1344
+ expect(elObj.focusedDayObj?.monthday).to.equal(31);
1345
+ });
1346
+ it('navigates to next month via [arrow down] key if last row of month', async () => {
1347
+ const el = await fixtureForSuite(html`
1348
+ <${tagCalendar} .selectedDate="${new Date('2000/12/30')}"></${tagCalendar}>
1349
+ `);
1350
+ const elObj = new CalendarObject(el);
1351
+ expect(elObj.activeMonth).to.equal('December');
1352
+ expect(elObj.activeYear).to.equal('2000');
1353
+ focusSelectedDate(el);
1354
+ await sendKeys({
1355
+ press: 'ArrowDown',
1356
+ });
1357
+ await el.updateComplete;
1358
+ expect(elObj.activeMonth).to.equal('January');
1359
+ expect(elObj.activeYear).to.equal('2001');
1360
+ expect(elObj.focusedDayObj?.monthday).to.equal(6);
1361
+ });
1362
+ it('navigates to previous month via [arrow up] key if first row of month', async () => {
1363
+ const el = await fixtureForSuite(html`
1364
+ <${tagCalendar} .selectedDate="${new Date('2001/01/02')}"></${tagCalendar}>
1365
+ `);
1366
+ const elObj = new CalendarObject(el);
1367
+ expect(elObj.activeMonth).to.equal('January');
1368
+ expect(elObj.activeYear).to.equal('2001');
1369
+ focusSelectedDate(el);
1370
+ await sendKeys({
1371
+ press: 'ArrowUp',
1372
+ });
1373
+ await el.updateComplete;
1374
+ expect(elObj.activeMonth).to.equal('December');
1375
+ expect(elObj.activeYear).to.equal('2000');
1376
+ expect(elObj.focusedDayObj?.monthday).to.equal(26);
1377
+ });
1378
+ });
1379
+ });
1380
+ describe('Initial central', () => {
1381
+ it('is based on "selectedDate"', async () => {
1382
+ const el = await fixtureForSuite(html`
1383
+ <${tagCalendar} .selectedDate=${new Date('2019/06/15')}></${tagCalendar}>
1384
+ `);
1385
+ const elObj = new CalendarObject(el);
1386
+ expect(elObj.centralDayObj?.monthday).to.equal(15);
1387
+ });
1388
+ it('is today if no selected date is available', async () => {
1389
+ const clock = sinon.useFakeTimers({
1390
+ now: new Date('2000/12/15').getTime(),
1391
+ });
1392
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
1393
+ const elObj = new CalendarObject(el);
1394
+ expect(elObj.centralDayObj?.monthday).to.equal(15);
1395
+ clock.restore();
1396
+ });
1397
+ it('is nearest to today if no selected date is available and today is disabled', async () => {
1398
+ const clock = sinon.useFakeTimers({
1399
+ now: new Date('2000/12/15').getTime(),
1400
+ });
1401
+ const calWithMin = await fixtureForSuite(
1402
+ html`<${tagCalendar} .minDate=${new Date('2000/12/25')}></${tagCalendar}>`,
1403
+ );
1404
+ const calObjWithMin = new CalendarObject(calWithMin);
1405
+ expect(calObjWithMin.centralDayObj?.monthday).to.equal(25);
1406
+ const calWithMax = await fixtureForSuite(
1407
+ html`<${tagCalendar} .maxDate=${new Date('2000/12/05')}></${tagCalendar}>`,
1408
+ );
1409
+ const calObjWithMax = new CalendarObject(calWithMax);
1410
+ expect(calObjWithMax.centralDayObj?.monthday).to.equal(5);
1411
+ const calWithDisabled = await fixtureForSuite(html`<${tagCalendar}
1412
+ .disableDates=${/** @param {Date} date */ (date) => date.getDate() === 15}
1413
+ ></${tagCalendar}>`);
1414
+ await calWithDisabled.updateComplete;
1415
+ const calObjWithDisabled = new CalendarObject(calWithDisabled);
1416
+ expect(calObjWithDisabled.centralDayObj?.monthday).to.equal(16);
1417
+ clock.restore();
1418
+ });
1419
+ });
1420
+
1421
+ /**
1422
+ * Not in scope:
1423
+ * - (virtual) scrolling: still under discussion. Wait for UX
1424
+ */
1425
+ });
1426
+ describe('Accessibility', () => {
1427
+ // Based on:
1428
+ // - https://codepen.io/erikkroes/pen/jJEWpR
1429
+
1430
+ // Navigation and day labels based on:
1431
+ // - https://dequeuniversity.com/library/aria/date-pickers/sf-date-picker
1432
+ // (recommended in W3C Editors Draft)
1433
+
1434
+ // For implementation, base on:
1435
+ // https://www.w3.org/TR/2017/NOTE-wai-aria-practices-1.1-20171214/examples/grid/js/dataGrid.js
1436
+ // As an enhancement, we detect when grid boundaries day are exceeded, so we move to
1437
+ // next/previous month.
1438
+ it('has role="application" to activate keyboard navigation', async () => {
1439
+ const elObj = new CalendarObject(
1440
+ await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`),
1441
+ );
1442
+ expect(elObj.rootEl?.getAttribute('role')).to.equal('application');
1443
+ });
1444
+ it(`renders the calendar as a table element with role="grid", aria-readonly="true" and
1445
+ a caption (month + year)`, async () => {
1446
+ const elObj = new CalendarObject(
1447
+ await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`),
1448
+ );
1449
+ expect(elObj.gridEl?.getAttribute('role')).to.equal('grid');
1450
+ expect(elObj.gridEl?.getAttribute('aria-readonly')).to.equal('true');
1451
+ });
1452
+ it('adds aria-labels to the weekday table headers', async () => {
1453
+ const elObj = new CalendarObject(
1454
+ await fixtureForSuite(html`<${tagCalendar} .firstDayOfWeek=${0}></${tagCalendar}>`),
1455
+ );
1456
+ expect(elObj.weekdayHeaderEls.map((h) => accessibleName(h))).to.eql([
1457
+ 'Sunday',
1458
+ 'Monday',
1459
+ 'Tuesday',
1460
+ 'Wednesday',
1461
+ 'Thursday',
1462
+ 'Friday',
1463
+ 'Saturday',
1464
+ ]);
1465
+ });
1466
+ it('renders each day as a button inside a table cell', async () => {
1467
+ const elObj = new CalendarObject(
1468
+ await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`),
1469
+ );
1470
+ const hasBtn = /** @param {DayObject} d */ (d) =>
1471
+ d.el.tagName === 'DIV' && d.el.getAttribute('role') === 'button';
1472
+ expect(elObj.checkForAllDayObjs(hasBtn)).to.equal(true);
1473
+ });
1474
+ it('renders days for previous and next months', async () => {
1475
+ const elObj = new CalendarObject(
1476
+ await fixtureForSuite(html`
1477
+ <${tagCalendar}
1478
+ .firstDayOfWeek=${0}
1479
+ .selectedDate="${new Date('2000/11/12')}"
1480
+ ></${tagCalendar}>
1481
+ `),
1482
+ );
1483
+ const { previousMonthDayObjs, nextMonthDayObjs } = elObj;
1484
+ expect(previousMonthDayObjs.length).to.equal(3);
1485
+ expect(previousMonthDayObjs[0].cellIndex).to.equal(0);
1486
+ expect(previousMonthDayObjs[0].monthday).to.equal(29);
1487
+ expect(previousMonthDayObjs[1].cellIndex).to.equal(1);
1488
+ expect(previousMonthDayObjs[1].monthday).to.equal(30);
1489
+ expect(previousMonthDayObjs[2].cellIndex).to.equal(2);
1490
+ expect(previousMonthDayObjs[2].monthday).to.equal(31);
1491
+ expect(nextMonthDayObjs.length).to.equal(9);
1492
+ expect(nextMonthDayObjs[0].cellIndex).to.equal(5);
1493
+ expect(nextMonthDayObjs[0].monthday).to.equal(1);
1494
+ expect(nextMonthDayObjs[1].cellIndex).to.equal(6);
1495
+ expect(nextMonthDayObjs[1].monthday).to.equal(2);
1496
+ expect(nextMonthDayObjs[2].cellIndex).to.equal(0);
1497
+ expect(nextMonthDayObjs[2].monthday).to.equal(3);
1498
+ expect(nextMonthDayObjs[3].cellIndex).to.equal(1);
1499
+ expect(nextMonthDayObjs[3].monthday).to.equal(4);
1500
+ expect(nextMonthDayObjs[4].cellIndex).to.equal(2);
1501
+ expect(nextMonthDayObjs[4].monthday).to.equal(5);
1502
+ expect(nextMonthDayObjs[5].cellIndex).to.equal(3);
1503
+ expect(nextMonthDayObjs[5].monthday).to.equal(6);
1504
+ expect(nextMonthDayObjs[6].cellIndex).to.equal(4);
1505
+ expect(nextMonthDayObjs[6].monthday).to.equal(7);
1506
+ expect(nextMonthDayObjs[7].cellIndex).to.equal(5);
1507
+ expect(nextMonthDayObjs[7].monthday).to.equal(8);
1508
+ expect(nextMonthDayObjs[8].cellIndex).to.equal(6);
1509
+ expect(nextMonthDayObjs[8].monthday).to.equal(9);
1510
+ });
1511
+ it('renders days for next months in the last month of the year', async () => {
1512
+ const elObj = new CalendarObject(
1513
+ await fixtureForSuite(html`
1514
+ <${tagCalendar}
1515
+ .firstDayOfWeek=${0}
1516
+ .selectedDate="${new Date('2020/12/12')}"
1517
+ ></${tagCalendar}>
1518
+ `),
1519
+ );
1520
+ const { nextMonthDayObjs } = elObj;
1521
+ expect(nextMonthDayObjs.length).to.equal(9);
1522
+ expect(nextMonthDayObjs[0].cellIndex).to.equal(5);
1523
+ expect(nextMonthDayObjs[0].monthday).to.equal(1);
1524
+ expect(nextMonthDayObjs[1].cellIndex).to.equal(6);
1525
+ expect(nextMonthDayObjs[1].monthday).to.equal(2);
1526
+ expect(nextMonthDayObjs[2].cellIndex).to.equal(0);
1527
+ expect(nextMonthDayObjs[2].monthday).to.equal(3);
1528
+ expect(nextMonthDayObjs[3].cellIndex).to.equal(1);
1529
+ expect(nextMonthDayObjs[3].monthday).to.equal(4);
1530
+ expect(nextMonthDayObjs[4].cellIndex).to.equal(2);
1531
+ expect(nextMonthDayObjs[4].monthday).to.equal(5);
1532
+ expect(nextMonthDayObjs[5].cellIndex).to.equal(3);
1533
+ expect(nextMonthDayObjs[5].monthday).to.equal(6);
1534
+ expect(nextMonthDayObjs[6].cellIndex).to.equal(4);
1535
+ expect(nextMonthDayObjs[6].monthday).to.equal(7);
1536
+ expect(nextMonthDayObjs[7].cellIndex).to.equal(5);
1537
+ expect(nextMonthDayObjs[7].monthday).to.equal(8);
1538
+ expect(nextMonthDayObjs[8].cellIndex).to.equal(6);
1539
+ expect(nextMonthDayObjs[8].monthday).to.equal(9);
1540
+ });
1541
+ it('renders days for previous months in the first month of the year', async () => {
1542
+ const elObj = new CalendarObject(
1543
+ await fixtureForSuite(html`
1544
+ <${tagCalendar}
1545
+ .firstDayOfWeek=${0}
1546
+ .selectedDate="${new Date('2020/01/12')}"
1547
+ ></${tagCalendar}>
1548
+ `),
1549
+ );
1550
+ const { previousMonthDayObjs } = elObj;
1551
+ expect(previousMonthDayObjs.length).to.equal(3);
1552
+ expect(previousMonthDayObjs[0].cellIndex).to.equal(0);
1553
+ expect(previousMonthDayObjs[0].monthday).to.equal(29);
1554
+ expect(previousMonthDayObjs[1].cellIndex).to.equal(1);
1555
+ expect(previousMonthDayObjs[1].monthday).to.equal(30);
1556
+ expect(previousMonthDayObjs[2].cellIndex).to.equal(2);
1557
+ expect(previousMonthDayObjs[2].monthday).to.equal(31);
1558
+ });
1559
+ it('sets aria-current="date" to todays button', async () => {
1560
+ const elObj = new CalendarObject(
1561
+ await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`),
1562
+ );
1563
+ const hasAriaCurrent = /** @param {DayObject} d */ (d) =>
1564
+ d.buttonEl.getAttribute('aria-current') === 'date';
1565
+ const monthday = new Date().getDate();
1566
+ expect(elObj.checkForAllDayObjs(hasAriaCurrent, [monthday])).to.equal(true);
1567
+ });
1568
+ it('sets aria-pressed="true" on selected date button', async () => {
1569
+ const elObj = new CalendarObject(
1570
+ await fixtureForSuite(html`
1571
+ <${tagCalendar} .selectedDate="${new Date('2000/11/12')}"></${tagCalendar}>
1572
+ `),
1573
+ );
1574
+ const hasAriaPressed = /** @param {DayObject} d */ (d) =>
1575
+ d.buttonEl.getAttribute('aria-pressed') === 'true';
1576
+ expect(elObj.checkForAllDayObjs(hasAriaPressed, [12])).to.equal(true);
1577
+ });
1578
+
1579
+ /**
1580
+ * Not in scope:
1581
+ * - reads the new focused day on month navigation"
1582
+ */
1583
+ });
1584
+
1585
+ /**
1586
+ * Not in scope:
1587
+ * - show week numbers
1588
+ */
1589
+ });
1590
+ describe('Localization', () => {
1591
+ it('supports custom locale with a fallback to a global locale', async () => {
1592
+ const el = await fixtureForSuite(html`
1593
+ <${tagCalendar} .selectedDate="${new Date('2019/12/20')}"></${tagCalendar}>
1594
+ `);
1595
+ const elObj = new CalendarObject(el);
1596
+ expect(elObj.activeMonth).to.equal('December');
1597
+ el.locale = 'fr-FR';
1598
+ await el.updateComplete;
1599
+ expect(elObj.activeMonth).to.equal('décembre');
1600
+ localizeManager.locale = 'cs-CZ';
1601
+ await el.updateComplete;
1602
+ expect(elObj.activeMonth).to.equal('décembre');
1603
+ el.locale = '';
1604
+ await el.updateComplete;
1605
+ expect(elObj.activeMonth).to.equal('prosinec');
1606
+ });
1607
+ it('displays the right translations according to locale', async () => {
1608
+ const el = await fixtureForSuite(html`
1609
+ <${tagCalendar}
1610
+ .firstDayOfWeek=${0}
1611
+ .centralDate=${new Date('2019/11/20')}
1612
+ ></${tagCalendar}>
1613
+ `);
1614
+ const elObj = new CalendarObject(el);
1615
+ expect(accessibleName(elObj.nextMonthButtonEl)).to.equal('Next month, December 2019');
1616
+ expect(accessibleName(elObj.previousMonthButtonEl)).to.equal(
1617
+ 'Previous month, October 2019',
1618
+ );
1619
+ expect(elObj.weekdayHeaderEls.map((h) => accessibleName(h))).to.eql([
1620
+ 'Sunday',
1621
+ 'Monday',
1622
+ 'Tuesday',
1623
+ 'Wednesday',
1624
+ 'Thursday',
1625
+ 'Friday',
1626
+ 'Saturday',
1627
+ ]);
1628
+ expect(elObj.weekdayHeaderEls.map((h) => h.textContent?.trim())).to.deep.equal([
1629
+ 'Sun',
1630
+ 'Mon',
1631
+ 'Tue',
1632
+ 'Wed',
1633
+ 'Thu',
1634
+ 'Fri',
1635
+ 'Sat',
1636
+ ]);
1637
+ localizeManager.locale = 'nl-NL';
1638
+ await el.localizeNamespacesLoaded;
1639
+ await el.updateComplete;
1640
+ expect(accessibleName(elObj.nextMonthButtonEl)).to.equal('Volgende maand, december 2019');
1641
+ expect(accessibleName(elObj.previousMonthButtonEl)).to.equal('Vorige maand, oktober 2019');
1642
+ expect(elObj.weekdayHeaderEls.map((h) => accessibleName(h))).to.eql([
1643
+ 'zondag',
1644
+ 'maandag',
1645
+ 'dinsdag',
1646
+ 'woensdag',
1647
+ 'donderdag',
1648
+ 'vrijdag',
1649
+ 'zaterdag',
1650
+ ]);
1651
+ expect(elObj.weekdayHeaderEls.map((h) => h.textContent?.trim())).to.deep.equal([
1652
+ 'zo',
1653
+ 'ma',
1654
+ 'di',
1655
+ 'wo',
1656
+ 'do',
1657
+ 'vr',
1658
+ 'za',
1659
+ ]);
1660
+ });
1661
+ });
1662
+ describe('Accessibility', () => {
1663
+ it('is accessible', async () => {
1664
+ const el = await fixtureForSuite(html`<${tagCalendar}></${tagCalendar}>`);
1665
+ await expect(el).to.be.accessible();
1666
+ });
1667
+ it('is accessible with a date selected', async () => {
1668
+ const today = new Date();
1669
+ const selectedDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
1670
+ const el = await fixtureForSuite(
1671
+ html`<${tagCalendar} .selectedDate="${selectedDate}"></${tagCalendar}>`,
1672
+ );
1673
+ await expect(el).to.be.accessible();
1674
+ });
1675
+ it('is accessible with disabled dates', async () => {
1676
+ const el = await fixtureForSuite(html`
1677
+ <${tagCalendar}
1678
+ .disableDates=${/** @param {Date} date */ (date) => date.getDay() === 6 || date.getDay() === 0}
1679
+ ></${tagCalendar}>
1680
+ `);
1681
+ await expect(el).to.be.accessible();
1682
+ });
1683
+ it('is hidden when attribute hidden is true', async () => {
1684
+ const el = await fixtureForSuite(html`<${tagCalendar} hidden></${tagCalendar}>`);
1685
+ expect(el).not.to.be.displayed;
1686
+ });
1687
+ });
1688
+ });
77
1689
  }