@lion/ui 0.18.1 → 0.20.0-menu-system.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 (279) hide show
  1. package/collapsible.js +1 -0
  2. package/components/button/src/LionButton.js +4 -0
  3. package/components/button/test-suites/LionButton.suite.js +1 -0
  4. package/components/calendar/src/LionCalendar.js +2 -0
  5. package/components/collapsible/src/DisclosureMixin.js +313 -0
  6. package/components/collapsible/test-suites/DisclosureMixin.suite.js +30 -0
  7. package/components/collapsible/types/DisclosureMixinTypes.ts +48 -0
  8. package/components/combobox/test/lion-combobox.test.js +1 -0
  9. package/components/form-core/src/form-group/FormGroupMixin.js +7 -0
  10. package/components/form-core/src/registration/FormRegistrarMixin.js +11 -0
  11. package/components/form-core/test/FormControlMixin.test.js +1 -0
  12. package/components/form-core/test/validate/Validator.test.js +2 -0
  13. package/components/form-core/test-suites/ValidateMixin.suite.js +2 -0
  14. package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +1 -0
  15. package/components/input-amount-dropdown/src/LionInputAmountDropdown.js +6 -4
  16. package/components/input-amount-dropdown/test/LionInputAmountDropdown.test.js +20 -1
  17. package/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.js +24 -0
  18. package/components/input-datepicker/src/localizeNamespaceLoader.js +1 -0
  19. package/components/input-datepicker/test/lion-input-datepicker.test.js +5 -6
  20. package/components/localize/test/date/formatDate.test.js +1 -0
  21. package/components/menu/CHANGELOG.md +37 -0
  22. package/components/menu/README.md +335 -0
  23. package/components/menu/index.js +2 -0
  24. package/components/menu/lion-menu-overlay.js +3 -0
  25. package/components/menu/lion-menu.js +3 -0
  26. package/components/menu/lion-spinbutton.js +3 -0
  27. package/components/menu/lion-toolbar.js +3 -0
  28. package/components/menu/lion-tree.js +3 -0
  29. package/components/menu/package.json +46 -0
  30. package/components/menu/requirements.temp.md +12 -0
  31. package/components/menu/src/InteractiveListMixin.js +840 -0
  32. package/components/menu/src/LionMenu.js +250 -0
  33. package/components/menu/src/LionMenuHybrid.js +46 -0
  34. package/components/menu/src/LionMenuOverlay.js +155 -0
  35. package/components/menu/src/LionSpinbutton.js +213 -0
  36. package/components/menu/src/LionToolbar.js +94 -0
  37. package/components/menu/src/LionTree.js +52 -0
  38. package/components/menu/src/MoreButtonMenuMixin.js +278 -0
  39. package/components/menu/src/MultiLevelListMixin.js +311 -0
  40. package/components/menu/src/utils/isInView.js +26 -0
  41. package/components/menu/src/utils/listItemInteractions.js +124 -0
  42. package/components/menu/test/InteractiveListMixin.test.js +3 -0
  43. package/components/menu/test/MoreButtonMenuMixin.test.js +4 -0
  44. package/components/menu/test/MultiLevelListMixin.test.js +3 -0
  45. package/components/menu/test/lion-menu-hybrid.test.js +3 -0
  46. package/components/menu/test/lion-menu.test.js +11 -0
  47. package/components/menu/test/lion-toolbar.test.js +8 -0
  48. package/components/menu/test/lion-tree.test.js +7 -0
  49. package/components/menu/test-helpers/mimicKeyPress.js +9 -0
  50. package/components/menu/test-suites/InteractiveListMixin.suite.js +454 -0
  51. package/components/menu/test-suites/LionMenu.suite.js +113 -0
  52. package/components/menu/test-suites/LionMenuHybrid.suite.js +583 -0
  53. package/components/menu/test-suites/MoreButtonMenuMixin.suite.js +372 -0
  54. package/components/menu/test-suites/MultiLevelListMixin.suite.js +303 -0
  55. package/components/menu/types/InteractiveListMixinTypes.d.ts +84 -0
  56. package/components/navigation-bar/README.md +1 -0
  57. package/components/navigation-bar/src/LionNavigationBar.js +439 -0
  58. package/components/navigation-bar/src/types.js +41 -0
  59. package/components/overlays/NEXT.md +49 -0
  60. package/components/overlays/src/OverlayController.js +278 -110
  61. package/components/overlays/src/OverlayMixin.js +58 -11
  62. package/components/overlays/src/OverlaysManager.js +2 -2
  63. package/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.js +100 -26
  64. package/components/overlays/src/utils/adopt-styles.js +3 -2
  65. package/components/overlays/src/utils/get-focusable-elements.js +4 -0
  66. package/components/overlays/src/utils/is-equal-config.js +10 -6
  67. package/components/overlays/test/OverlayController.test.js +127 -14
  68. package/components/overlays/test/utils-tests/is-equal-config.test.js +1 -1
  69. package/components/overlays/test/withHoverInteraction.test.js +90 -0
  70. package/components/overlays/test-suites/OverlayMixin.suite.js +8 -8
  71. package/components/overlays/types/ArrowMixinTypes.ts +3 -1
  72. package/components/overlays/types/OverlayConfig.ts +20 -5
  73. package/components/overlays/types/OverlayMixinTypes.ts +2 -0
  74. package/components/select-rich/test/lion-select-rich.test.js +3 -0
  75. package/custom-elements.json +30446 -17381
  76. package/dist-types/components/button/src/LionButton.d.ts +1 -0
  77. package/dist-types/components/button/src/LionButton.d.ts.map +1 -1
  78. package/dist-types/components/button/test-suites/LionButton.suite.d.ts.map +1 -1
  79. package/dist-types/components/calendar/src/LionCalendar.d.ts.map +1 -1
  80. package/dist-types/components/collapsible/src/DisclosureMixin.d.ts +3 -0
  81. package/dist-types/components/collapsible/src/DisclosureMixin.d.ts.map +1 -0
  82. package/dist-types/components/collapsible/test-suites/DisclosureMixin.suite.d.ts +2 -0
  83. package/dist-types/components/collapsible/test-suites/DisclosureMixin.suite.d.ts.map +1 -0
  84. package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts +24 -0
  85. package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts.map +1 -0
  86. package/dist-types/components/combobox/src/LionCombobox.d.ts +1 -1
  87. package/dist-types/components/dialog/src/LionDialog.d.ts +6 -2
  88. package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
  89. package/dist-types/components/form-core/src/form-group/FormGroupMixin.d.ts.map +1 -1
  90. package/dist-types/components/form-core/src/registration/FormRegistrarMixin.d.ts.map +1 -1
  91. package/dist-types/components/form-core/test-suites/ValidateMixin.suite.d.ts.map +1 -1
  92. package/dist-types/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.d.ts.map +1 -1
  93. package/dist-types/components/input-amount-dropdown/src/LionInputAmountDropdown.d.ts +0 -9
  94. package/dist-types/components/input-amount-dropdown/src/LionInputAmountDropdown.d.ts.map +1 -1
  95. package/dist-types/components/input-amount-dropdown/test/LionInputAmountDropdown.test.d.ts.map +1 -1
  96. package/dist-types/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.d.ts.map +1 -1
  97. package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +1 -1
  98. package/dist-types/components/input-datepicker/src/localizeNamespaceLoader.d.ts.map +1 -1
  99. package/dist-types/components/menu/index.d.ts +3 -0
  100. package/dist-types/components/menu/index.d.ts.map +1 -0
  101. package/dist-types/components/menu/lion-menu-overlay.d.ts +2 -0
  102. package/dist-types/components/menu/lion-menu-overlay.d.ts.map +1 -0
  103. package/dist-types/components/menu/lion-menu.d.ts +2 -0
  104. package/dist-types/components/menu/lion-menu.d.ts.map +1 -0
  105. package/dist-types/components/menu/lion-spinbutton.d.ts +2 -0
  106. package/dist-types/components/menu/lion-spinbutton.d.ts.map +1 -0
  107. package/dist-types/components/menu/lion-toolbar.d.ts +2 -0
  108. package/dist-types/components/menu/lion-toolbar.d.ts.map +1 -0
  109. package/dist-types/components/menu/lion-tree.d.ts +2 -0
  110. package/dist-types/components/menu/lion-tree.d.ts.map +1 -0
  111. package/dist-types/components/menu/src/InteractiveListMixin.d.ts +617 -0
  112. package/dist-types/components/menu/src/InteractiveListMixin.d.ts.map +1 -0
  113. package/dist-types/components/menu/src/LionMenu.d.ts +635 -0
  114. package/dist-types/components/menu/src/LionMenu.d.ts.map +1 -0
  115. package/dist-types/components/menu/src/LionMenuHybrid.d.ts +19 -0
  116. package/dist-types/components/menu/src/LionMenuHybrid.d.ts.map +1 -0
  117. package/dist-types/components/menu/src/LionMenuOverlay.d.ts +1015 -0
  118. package/dist-types/components/menu/src/LionMenuOverlay.d.ts.map +1 -0
  119. package/dist-types/components/menu/src/LionSpinbutton.d.ts +58 -0
  120. package/dist-types/components/menu/src/LionSpinbutton.d.ts.map +1 -0
  121. package/dist-types/components/menu/src/LionToolbar.d.ts +8 -0
  122. package/dist-types/components/menu/src/LionToolbar.d.ts.map +1 -0
  123. package/dist-types/components/menu/src/LionTree.d.ts +447 -0
  124. package/dist-types/components/menu/src/LionTree.d.ts.map +1 -0
  125. package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts +39 -0
  126. package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts.map +1 -0
  127. package/dist-types/components/menu/src/MultiLevelListMixin.d.ts +503 -0
  128. package/dist-types/components/menu/src/MultiLevelListMixin.d.ts.map +1 -0
  129. package/dist-types/components/menu/src/utils/isInView.d.ts +9 -0
  130. package/dist-types/components/menu/src/utils/isInView.d.ts.map +1 -0
  131. package/dist-types/components/menu/src/utils/listItemInteractions.d.ts +48 -0
  132. package/dist-types/components/menu/src/utils/listItemInteractions.d.ts.map +1 -0
  133. package/dist-types/components/menu/test/InteractiveListMixin.test.d.ts +2 -0
  134. package/dist-types/components/menu/test/InteractiveListMixin.test.d.ts.map +1 -0
  135. package/dist-types/components/menu/test/MoreButtonMenuMixin.test.d.ts +2 -0
  136. package/dist-types/components/menu/test/MoreButtonMenuMixin.test.d.ts.map +1 -0
  137. package/dist-types/components/menu/test/MultiLevelListMixin.test.d.ts +2 -0
  138. package/dist-types/components/menu/test/MultiLevelListMixin.test.d.ts.map +1 -0
  139. package/dist-types/components/menu/test/lion-menu-hybrid.test.d.ts +2 -0
  140. package/dist-types/components/menu/test/lion-menu-hybrid.test.d.ts.map +1 -0
  141. package/dist-types/components/menu/test/lion-menu.test.d.ts +2 -0
  142. package/dist-types/components/menu/test/lion-menu.test.d.ts.map +1 -0
  143. package/dist-types/components/menu/test/lion-toolbar.test.d.ts +2 -0
  144. package/dist-types/components/menu/test/lion-toolbar.test.d.ts.map +1 -0
  145. package/dist-types/components/menu/test/lion-tree.test.d.ts +2 -0
  146. package/dist-types/components/menu/test/lion-tree.test.d.ts.map +1 -0
  147. package/dist-types/components/menu/test-helpers/mimicKeyPress.d.ts +7 -0
  148. package/dist-types/components/menu/test-helpers/mimicKeyPress.d.ts.map +1 -0
  149. package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts +14 -0
  150. package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts.map +1 -0
  151. package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts +9 -0
  152. package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts.map +1 -0
  153. package/dist-types/components/menu/test-suites/LionMenuHybrid.suite.d.ts +5 -0
  154. package/dist-types/components/menu/test-suites/LionMenuHybrid.suite.d.ts.map +1 -0
  155. package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts +14 -0
  156. package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts.map +1 -0
  157. package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts +11 -0
  158. package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts.map +1 -0
  159. package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts +238 -0
  160. package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts.map +1 -0
  161. package/dist-types/components/navigation-bar/src/types.d.ts +85 -0
  162. package/dist-types/components/navigation-bar/src/types.d.ts.map +1 -0
  163. package/dist-types/components/overlays/src/OverlayController.d.ts +24 -12
  164. package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
  165. package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
  166. package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts +8 -2
  167. package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts.map +1 -1
  168. package/dist-types/components/overlays/src/utils/get-focusable-elements.d.ts.map +1 -1
  169. package/dist-types/components/overlays/src/utils/is-equal-config.d.ts.map +1 -1
  170. package/dist-types/components/overlays/test/withHoverInteraction.test.d.ts +2 -0
  171. package/dist-types/components/overlays/test/withHoverInteraction.test.d.ts.map +1 -0
  172. package/dist-types/components/overlays/types/ArrowMixinTypes.d.ts.map +1 -1
  173. package/dist-types/components/overlays/types/OverlayConfig.d.ts +12 -2
  174. package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
  175. package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts +1 -0
  176. package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts.map +1 -1
  177. package/dist-types/components/select-rich/src/LionSelectRich.d.ts +11 -3
  178. package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
  179. package/dist-types/components/tooltip/src/LionTooltip.d.ts +1 -1
  180. package/dist-types/exports/define/lion-item.d.ts +2 -0
  181. package/dist-types/exports/define/lion-item.d.ts.map +1 -0
  182. package/dist-types/exports/define/lion-menu-overlay.d.ts +2 -0
  183. package/dist-types/exports/define/lion-menu-overlay.d.ts.map +1 -0
  184. package/dist-types/exports/define/lion-menu.d.ts +2 -0
  185. package/dist-types/exports/define/lion-menu.d.ts.map +1 -0
  186. package/dist-types/exports/define/lion-navigation-bar.d.ts +2 -0
  187. package/dist-types/exports/define/lion-navigation-bar.d.ts.map +1 -0
  188. package/dist-types/exports/define/lion-toolbar.d.ts +2 -0
  189. package/dist-types/exports/define/lion-toolbar.d.ts.map +1 -0
  190. package/dist-types/exports/define/lion-tree.d.ts +2 -0
  191. package/dist-types/exports/define/lion-tree.d.ts.map +1 -0
  192. package/dist-types/exports/menu-test-suites.d.ts +4 -0
  193. package/dist-types/exports/menu-test-suites.d.ts.map +1 -0
  194. package/dist-types/exports/menu.d.ts +7 -0
  195. package/dist-types/exports/menu.d.ts.map +1 -0
  196. package/dist-types/exports/navigation-bar.d.ts +2 -0
  197. package/dist-types/exports/navigation-bar.d.ts.map +1 -0
  198. package/dist-types/exports/overlays.d.ts +3 -0
  199. package/dist-types/exports/overlays.d.ts.map +1 -1
  200. package/dist-types/tsconfig.tsbuildinfo +1 -1
  201. package/docs/components/checkbox-group/overview.md +2 -2
  202. package/docs/components/collapsible/overview.md +1 -1
  203. package/docs/components/combobox/api-table.md +21 -8
  204. package/docs/components/combobox/overview.md +1 -1
  205. package/docs/components/combobox/use-cases.md +1 -1
  206. package/docs/components/dialog/api-table.md +31 -6
  207. package/docs/components/dialog/overview.md +1 -1
  208. package/docs/components/fieldset/overview.md +5 -5
  209. package/docs/components/form/overview.md +3 -3
  210. package/docs/components/form/use-cases.md +2 -2
  211. package/docs/components/icon/use-cases.md +1 -1
  212. package/docs/components/input/overview.md +1 -1
  213. package/docs/components/input-amount/overview.md +3 -3
  214. package/docs/components/input-amount-dropdown/api-table.md +1 -1
  215. package/docs/components/input-date/overview.md +3 -3
  216. package/docs/components/input-datepicker/api-table.md +21 -4
  217. package/docs/components/input-datepicker/overview.md +5 -5
  218. package/docs/components/input-email/overview.md +2 -2
  219. package/docs/components/input-file/overview.md +1 -1
  220. package/docs/components/input-iban/overview.md +2 -2
  221. package/docs/components/input-range/overview.md +2 -2
  222. package/docs/components/input-stepper/overview.md +1 -1
  223. package/docs/components/input-tel/overview.md +1 -1
  224. package/docs/components/input-tel/use-cases.md +6 -6
  225. package/docs/components/input-tel-dropdown/overview.md +1 -1
  226. package/docs/components/listbox/use-cases.md +1 -1
  227. package/docs/components/menu/api-table.md +460 -0
  228. package/docs/components/menu/applyMenuDemoStyles.js +173 -0
  229. package/docs/components/menu/extensions.md +262 -0
  230. package/docs/components/menu/index.md +13 -0
  231. package/docs/components/menu/overview.md +422 -0
  232. package/docs/components/menu/use-cases.md +77 -0
  233. package/docs/components/radio-group/overview.md +3 -3
  234. package/docs/components/select/use-cases.md +1 -1
  235. package/docs/components/select-rich/api-table.md +21 -5
  236. package/docs/components/select-rich/use-cases.md +2 -2
  237. package/docs/components/tabs/examples.md +1 -1
  238. package/docs/components/tooltip/api-table.md +36 -11
  239. package/docs/components/tooltip/use-cases.md +22 -0
  240. package/docs/fundamentals/index.md +4 -4
  241. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  242. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  243. package/docs/fundamentals/rationales/accessibility.md +1 -1
  244. package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
  245. package/docs/fundamentals/systems/core/overview.md +1 -1
  246. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  247. package/docs/fundamentals/systems/form/model-value.md +1 -1
  248. package/docs/fundamentals/systems/form/overview.md +28 -28
  249. package/docs/fundamentals/systems/form/validate.md +2 -2
  250. package/docs/fundamentals/systems/localize/overview.md +4 -4
  251. package/docs/fundamentals/systems/overlays/api-table.md +36 -34
  252. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  253. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  254. package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
  255. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  256. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  257. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  258. package/docs/guides/how-to/create-a-form.md +4 -4
  259. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  260. package/docs/guides/how-to/index.md +1 -1
  261. package/docs/guides/index.md +8 -8
  262. package/docs/guides/principles/index.md +5 -5
  263. package/docs/guides/principles/styling.md +1 -1
  264. package/exports/collapsible.js +1 -0
  265. package/exports/define/lion-item.js +3 -0
  266. package/exports/define/lion-menu-overlay.js +3 -0
  267. package/exports/define/lion-menu.js +3 -0
  268. package/exports/define/lion-navigation-bar.js +3 -0
  269. package/exports/define/lion-toolbar.js +3 -0
  270. package/exports/define/lion-tree.js +3 -0
  271. package/exports/menu-test-suites.js +4 -0
  272. package/exports/menu.js +7 -0
  273. package/exports/navigation-bar.js +1 -0
  274. package/exports/overlays.js +6 -0
  275. package/menu-test-suites.js +4 -0
  276. package/menu.js +7 -0
  277. package/navigation-bar.js +1 -0
  278. package/overlays.js +6 -0
  279. package/package.json +1 -1
@@ -0,0 +1,311 @@
1
+ /* eslint-disable import/no-extraneous-dependencies */
2
+ import { html } from 'lit';
3
+ import { dedupeMixin } from '@open-wc/dedupe-mixin';
4
+ // import { DisclosureMixin } from '@lion/ui/collapsible.js';
5
+ import { InteractiveListMixin } from './InteractiveListMixin.js';
6
+ import { isChecked, setChecked } from './utils/listItemInteractions.js';
7
+ /**
8
+ * @typedef {import('./InteractiveListMixin.js').LionItem} LionItem
9
+ * @typedef {import('../types/InteractiveListMixinTypes.js').InteractiveListHost} InteractiveList
10
+ * @typedef {typeof import('../../overlays/types/OverlayMixinTypes.js').OverlayHost} OverlayHost
11
+ * @typedef {import('./LionMenuOverlay.js').LionMenuOverlay} LionMenuOverlay
12
+ */
13
+
14
+ /**
15
+ * All logic that is needed for interactive lists that are allowed to have multiple nested, collapsible levels
16
+ * Applies to [role=menu] and [role=tree]
17
+ */
18
+ // @ts-ignore - mixin implementation
19
+ const MultiLevelListMixinImplementation = superclass =>
20
+ // @ts-ignore - mixin class extension
21
+ class extends InteractiveListMixin(superclass) {
22
+ render() {
23
+ return html`
24
+ <slot name="invoker"></slot>
25
+ <slot name="list"></slot>
26
+ <slot id="list-items-outlet"></slot>
27
+ `;
28
+ }
29
+
30
+ static get properties() {
31
+ return {
32
+ invokerNode: Object,
33
+ behaveAsAccordion: { type: Boolean, attribute: 'behave-as-accordion' },
34
+ level: { type: Number, reflect: true },
35
+ };
36
+ }
37
+
38
+ /**
39
+ * @configure DisclosureMixin
40
+ */
41
+ get _invokerNode() {
42
+ const ctor = /** @type {OverlayHost} */ (this.constructor);
43
+ if (ctor._getFocusableInvokerEl && this.invokerNode) {
44
+ // @ts-ignore - accessing static method and super property
45
+ return ctor._getFocusableInvokerEl(this.invokerNode);
46
+ }
47
+ // @ts-ignore
48
+ return super._invokerNode;
49
+ }
50
+
51
+ /**
52
+ * @configure DisclosureMixin
53
+ * This will be compatible with DisclosureMixin and OverlayMixin. It contains the invoked
54
+ * InteractiveList widget (like menu|tree).
55
+ */
56
+ get _contentNode() {
57
+ return this._listNode;
58
+ }
59
+
60
+ constructor() {
61
+ super();
62
+
63
+ /**
64
+ * When an invokerNode is supplied (usually by a parent level menu), it will take precedence
65
+ * over [slot=invoker] and previousElementSibling with [data-invoker] attribute
66
+ * @type {HTMLElement}
67
+ */
68
+ // @ts-ignore - can be undefined initially
69
+ this.invokerNode = undefined;
70
+ /**
71
+ * @configure DisclosureMixin
72
+ */
73
+ this.handleFocus = true;
74
+ /**
75
+ * The parent list if level > 1
76
+ * @type {InteractiveList}
77
+ */
78
+ // @ts-ignore - can be undefined initially
79
+ this.parentList = undefined;
80
+ /**
81
+ * When true, will have a maximum of one submenu open at a time
82
+ */
83
+ this.behaveAsAccordion = false;
84
+ /**
85
+ * The level of nested menus. Will be reflected as attribute for styling purposes
86
+ */
87
+ this.level = 1;
88
+ /**
89
+ * @configure InteractiveListMixin
90
+ */
91
+ this.noPreselect = true;
92
+ /**
93
+ * @configure InteractiveListMixin
94
+ * @type {'activedescendant'|'roving-tabindex'|'tabbable-disclosure'}
95
+ */
96
+ this._activeMode = 'roving-tabindex';
97
+ /**
98
+ * @type {Map<HTMLElement|LionItem,InteractiveList>}
99
+ */
100
+ this._subListMap = new Map();
101
+ }
102
+
103
+ // /**
104
+ // * @param {import('lit-element').PropertyValues } changedProperties
105
+ // */
106
+ // updated(changedProperties) {
107
+ // super.updated(changedProperties);
108
+
109
+ // if (changedProperties.has('invokerNode')) {
110
+ // // TODO: update openableCtrl invokerNode once we make this a ctrl as well
111
+ // }
112
+ // }
113
+
114
+ /**
115
+ * Gets the child InteractiveList, based on item
116
+ * @param {LionItem|HTMLElement} item can be sibling of or parent of InteractiveList
117
+ */
118
+ static _getSubInteractiveList(item) {
119
+ /**
120
+ * Note that, according to W3C spec, the sub level element with [role=menu|menubar|tree]
121
+ * needs to be a sibling of the invoker element with
122
+ * [role=menuitem|menuitemchecbox|menuitemradio|treeitem] (and not the parent)
123
+ *
124
+ * In the example below <lion-menu> is considered as item
125
+ * @example
126
+ * <lion-menuitem>
127
+ * <button slot="invoker"></button>
128
+ * <lion-menu> ... </lion-menu>
129
+ * </lion-menuitem>
130
+ */
131
+ // @ts-ignore - isInteractiveList property check
132
+ const siblingOfInvoker = item.nextElementSibling?.isInteractiveList;
133
+ if (siblingOfInvoker) {
134
+ return item.nextElementSibling;
135
+ }
136
+ /**
137
+ * In the example below div[role=listitem] | [data-item] is considered as item
138
+ * @example
139
+ * <div role="listitem" data-item>
140
+ * <button slot="invoker"></button>
141
+ * <lion-menu> ... </lion-menu>
142
+ * </div>
143
+ */
144
+ const childOfInvoker =
145
+ item.getAttribute?.('role') === 'listitem' || item.hasAttribute?.('data-item');
146
+ if (childOfInvoker) {
147
+ // @ts-ignore - isInteractiveList check
148
+ return Array.from(item.children).find(child => child.isInteractiveList);
149
+ }
150
+ return undefined;
151
+ }
152
+
153
+ /**
154
+ * @param {*} newItems
155
+ */
156
+ _initListItems(newItems) {
157
+ super._initListItems(newItems);
158
+
159
+ const ctor = this.constructor;
160
+ // @ts-ignore - forEach parameter types
161
+ newItems.forEach(item => {
162
+ // @ts-ignore - static method access
163
+ const subList = ctor._getSubInteractiveList(item);
164
+ if (subList) {
165
+ this._subListMap.set(item, subList);
166
+ subList.level = this.level + 1;
167
+ subList.parentList = this;
168
+ subList.invokerNode = item;
169
+ // @ts-ignore - invokerInteraction property
170
+ subList.invokerInteraction = this.invokerInteraction;
171
+ subList._activeMode = this._activeMode;
172
+ }
173
+ });
174
+ }
175
+
176
+ /**
177
+ * @enhance DisclosureMixin
178
+ * @param {Event} [ev]
179
+ */
180
+ toggle(ev) {
181
+ // @ts-ignore - target property
182
+ if (ev && this._listNode.contains(ev.target)) {
183
+ // prevent nested menus (inside invokers) from triggering invoker
184
+ return;
185
+ }
186
+ // @ts-ignore - super.toggle method
187
+ super.toggle();
188
+ }
189
+
190
+ /**
191
+ * @enhance InteractiveListMixin
192
+ * @param {*} ev
193
+ */
194
+ _onListKeyDown(ev) {
195
+ const targetFromSubList = Array.from(this._subListMap).find(
196
+ // @ts-ignore - contains method on InteractiveListHost
197
+ ([, s]) => s === ev.target || s.contains(ev.target),
198
+ );
199
+
200
+ if (targetFromSubList) {
201
+ return;
202
+ }
203
+
204
+ super._onListKeyDown(ev);
205
+
206
+ const subListOfActiveItem = this._subListMap.get(this.activeItem);
207
+ const parentListOfActiveItem = this.parentList;
208
+ const { key } = ev;
209
+
210
+ if (key === 'Escape' && parentListOfActiveItem) {
211
+ // We need to stop here, or else we affect parent menu (handled by OverlayController)
212
+ ev.stopPropagation();
213
+ }
214
+
215
+ switch (key) {
216
+ case 'Enter':
217
+ case ' ':
218
+ // make it work like a button
219
+ this.activeItem?.click();
220
+ break;
221
+ case 'ArrowDown':
222
+ if (
223
+ this.orientation === 'horizontal' &&
224
+ subListOfActiveItem &&
225
+ this._activeMode !== 'tabbable-disclosure'
226
+ ) {
227
+ this.activeItem.click();
228
+ }
229
+ break;
230
+ case 'ArrowRight':
231
+ if (this.orientation === 'vertical' && subListOfActiveItem) {
232
+ this.activeItem.click();
233
+ }
234
+ break;
235
+ case 'ArrowUp':
236
+ if (this.orientation === 'horizontal' && parentListOfActiveItem) {
237
+ // @ts-ignore - close method
238
+ this.close();
239
+ if (
240
+ /** @type {InteractiveList & LionMenuOverlay} */ (parentListOfActiveItem)
241
+ ._onOverlayShow
242
+ ) {
243
+ // @ts-ignore - _onOverlayShow method
244
+ /** @type {OverlayHost} */ (parentListOfActiveItem)._onOverlayShow();
245
+ }
246
+ }
247
+ break;
248
+ case 'ArrowLeft':
249
+ if (this.orientation === 'vertical' && parentListOfActiveItem) {
250
+ // @ts-ignore - close method
251
+ this.close();
252
+ if (
253
+ /** @type {InteractiveList & LionMenuOverlay} */ (parentListOfActiveItem)
254
+ ._onOverlayShow
255
+ ) {
256
+ // @ts-ignore - _onOverlayShow method
257
+ /** @type {OverlayHost} */ (parentListOfActiveItem)._onOverlayShow();
258
+ }
259
+ }
260
+ break;
261
+ /* no default */
262
+ }
263
+ }
264
+
265
+ /**
266
+ * @param {Location} location
267
+ */
268
+ _syncCurrentPageWithLocationHref(location) {
269
+ super._syncCurrentPageWithLocationHref(location);
270
+
271
+ this._subListMap.forEach(subList => {
272
+ subList.listItems.forEach(
273
+ /** @param {LionItem|HTMLElement} item */ item => {
274
+ // @ts-ignore
275
+ if (isChecked(item) && subList._invokerNode) {
276
+ // @ts-ignore
277
+ setChecked(subList._invokerNode);
278
+ }
279
+ },
280
+ );
281
+ });
282
+ }
283
+
284
+ // /**
285
+ // * @enhance DisclosureMixin
286
+ // */
287
+ // _setupDisclosure() {
288
+ // if (!this._invokerNode) return;
289
+
290
+ // super._setupDisclosure();
291
+ // }
292
+
293
+ // /**
294
+ // * @enhance DisclosureMixin
295
+ // */
296
+ // _teardownDisclosure() {
297
+ // if (!this._invokerNode) return;
298
+
299
+ // super._teardownDisclosure();
300
+ // }
301
+
302
+ // /**
303
+ // * @enhance DisclosureMixin
304
+ // */
305
+ // async _onOpenedChanged() {
306
+ // if (!this._invokerNode) return;
307
+
308
+ // await super._onOpenedChanged();
309
+ // }
310
+ };
311
+ export const MultiLevelListMixin = dedupeMixin(MultiLevelListMixinImplementation);
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Determines whether element is visible within container
3
+ *
4
+ * @param {HTMLElement} container
5
+ * @param {HTMLElement} element
6
+ * @param {Boolean} [partial]
7
+ */
8
+ export function isInView(container, element, partial = false) {
9
+ const cTop = container.scrollTop;
10
+ const cBottom = cTop + container.clientHeight;
11
+ const eTop = element.offsetTop;
12
+ const eBottom = eTop + element.clientHeight;
13
+ const isTotal = eTop >= cTop && eBottom <= cBottom;
14
+ let isPartial;
15
+
16
+ if (partial === true) {
17
+ isPartial = (eTop < cTop && eBottom > cTop) || (eBottom > cBottom && eTop < cBottom);
18
+ } else if (typeof partial === 'number') {
19
+ if (eTop < cTop && eBottom > cTop) {
20
+ isPartial = ((eBottom - cTop) * 100) / element.clientHeight > partial;
21
+ } else if (eBottom > cBottom && eTop < cBottom) {
22
+ isPartial = ((cBottom - eTop) * 100) / element.clientHeight > partial;
23
+ }
24
+ }
25
+ return isTotal || isPartial;
26
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Set of universal interactive list item state methods that are both compatible with
3
+ * 'smart' (LionOption) and 'regular' items
4
+ */
5
+
6
+ /**
7
+ * @typedef {import('@lion/ui/checkbox-group.js').LionCheckboxIndeterminate} LionCheckboxIndeterminate
8
+ */
9
+
10
+ /**
11
+ * @param {HTMLElement} item
12
+ */
13
+ export function isDisabled(item) {
14
+ return item.hasAttribute('disabled') || item.getAttribute('aria-disabled') === 'true';
15
+ }
16
+
17
+ /**
18
+ * @param {HTMLElement} item
19
+ */
20
+ export function setDisabled(item, unset = false) {
21
+ if (unset) {
22
+ item.removeAttribute('disabled');
23
+ item.setAttribute('aria-disabled', 'false');
24
+ } else {
25
+ item.setAttribute('disabled', '');
26
+ item.setAttribute('aria-disabled', 'true');
27
+ }
28
+ }
29
+
30
+ /**
31
+ * @param {HTMLElement} item
32
+ */
33
+ export function toggleDisabled(item) {
34
+ setDisabled(item, isDisabled(item));
35
+ }
36
+
37
+ /**
38
+ * @param {HTMLElement} item
39
+ */
40
+ export function isChecked(item) {
41
+ return item.hasAttribute('checked');
42
+ }
43
+
44
+ /**
45
+ * @param {HTMLElement} item
46
+ * @param {Object} [options]
47
+ * @param {boolean} [options.unset=false]
48
+ * @param {'page'|'mixed'} [options.text] - optional text to set for aria-checked/aria-selected/aria-current (e.g. "mixed")
49
+ */
50
+ export function setChecked(item, unset = false) {
51
+ const role = item.getAttribute('role');
52
+ let ariaAttr = 'current';
53
+ if (role?.endsWith('checkbox') || role?.endsWith('radio')) {
54
+ ariaAttr = 'checked';
55
+ } else if (role === 'option' || role === 'treeitem') {
56
+ ariaAttr = 'selected';
57
+ }
58
+ let text;
59
+ if (/** @type {HTMLAnchorElement} */ (item).href) {
60
+ text = 'page';
61
+ }
62
+ if (/** @type {LionCheckboxIndeterminate} */ (item).mixedState) {
63
+ text = 'mixed';
64
+ }
65
+ if (!unset) {
66
+ item.setAttribute('checked', '');
67
+ item.setAttribute(`aria-${ariaAttr}`, text || 'true');
68
+ } else {
69
+ item.removeAttribute('checked');
70
+ item.setAttribute(`aria-${ariaAttr}`, 'false');
71
+ }
72
+ }
73
+
74
+ /**
75
+ * @param {HTMLElement} item
76
+ */
77
+ export function toggleChecked(item) {
78
+ const shouldUnset = isChecked(item);
79
+ setChecked(item, shouldUnset);
80
+ }
81
+
82
+ /**
83
+ * @param {HTMLElement} item
84
+ */
85
+ export function isActive(item) {
86
+ return item.hasAttribute('active');
87
+ }
88
+
89
+ /**
90
+ * @param {HTMLElement} item
91
+ */
92
+ export function setActive(item, unset = false) {
93
+ if (unset) {
94
+ item.removeAttribute('active');
95
+ } else {
96
+ item.setAttribute('active', '');
97
+ }
98
+ }
99
+
100
+ /**
101
+ * @param {HTMLElement} item
102
+ */
103
+ function getDirectTextContent(item) {
104
+ return Array.from(item.childNodes)
105
+ .filter(n => n.nodeName === '#text')
106
+ .map(n => n.textContent)
107
+ .join('')
108
+ .trim();
109
+ }
110
+
111
+ /**
112
+ * @param {HTMLElement} item
113
+ */
114
+ export function getValue(item) {
115
+ return (
116
+ // @ts-ignore - choiceValue is a custom property
117
+ item.choiceValue ||
118
+ // @ts-ignore - value might not exist on all HTMLElements
119
+ item.value ||
120
+ item.getAttribute('value') ||
121
+ item.getAttribute('data-value') ||
122
+ getDirectTextContent(item)
123
+ );
124
+ }
@@ -0,0 +1,3 @@
1
+ import { runInteractiveListMixinSuite } from '../test-suites/InteractiveListMixin.suite.js';
2
+
3
+ runInteractiveListMixinSuite();
@@ -0,0 +1,4 @@
1
+ import { runMoreButtonMenuMixinSuite } from '../test-suites/MoreButtonMenuMixin.suite.js';
2
+ import '@lion/ui/define/lion-menu.js';
3
+
4
+ runMoreButtonMenuMixinSuite({ tagString: 'lion-menu' });
@@ -0,0 +1,3 @@
1
+ import { runMultiLevelListMixinSuite } from '../test-suites/MultiLevelListMixin.suite.js';
2
+
3
+ runMultiLevelListMixinSuite();
@@ -0,0 +1,3 @@
1
+ import { runLionMenuHybridSuite } from '../test-suites/LionMenuHybrid.suite.js';
2
+
3
+ runLionMenuHybridSuite();
@@ -0,0 +1,11 @@
1
+ import { runInteractiveListMixinSuite } from '../test-suites/InteractiveListMixin.suite.js';
2
+ import { runMultiLevelListMixinSuite } from '../test-suites/MultiLevelListMixin.suite.js';
3
+ import { runMoreButtonMenuMixinSuite } from '../test-suites/MoreButtonMenuMixin.suite.js';
4
+ import { runLionMenuSuite } from '../test-suites/LionMenu.suite.js';
5
+ import '@lion/ui/define/lion-menu.js';
6
+ import '@lion/ui/define/lion-menu-overlay.js';
7
+
8
+ runInteractiveListMixinSuite({ tagString: 'lion-menu' });
9
+ runMultiLevelListMixinSuite({ tagString: 'lion-menu', tagChildString: 'lion-menu-overlay' });
10
+ runMoreButtonMenuMixinSuite({ tagString: 'lion-menu' });
11
+ runLionMenuSuite({ tagString: 'lion-menu' });
@@ -0,0 +1,8 @@
1
+ // import { runInteractiveListMixinSuite } from '../test-suites/InteractiveListMixin.suite.js';
2
+ // import { runMultiLevelListMixinSuite } from '../test-suites/MultiLevelListMixin.suite.js';
3
+ import { runMoreButtonMenuMixinSuite } from '../test-suites/MoreButtonMenuMixin.suite.js';
4
+ import '@lion/ui/define/lion-toolbar.js';
5
+
6
+ // runInteractiveListMixinSuite({ tagString: 'lion-toolbar' }); // 1 test fails
7
+ // runMultiLevelListMixinSuite({ tagString: 'lion-toolbar', tagChildString: 'lion-toolbar' }); // hangs
8
+ runMoreButtonMenuMixinSuite({ tagString: 'lion-toolbar' });
@@ -0,0 +1,7 @@
1
+ import { runInteractiveListMixinSuite } from '../test-suites/InteractiveListMixin.suite.js';
2
+ // import { runMultiLevelListMixinSuite } from '../test-suites/MultiLevelListMixin.suite.js';
3
+ import '@lion/ui/define/lion-tree.js';
4
+
5
+ runInteractiveListMixinSuite({ tagString: 'lion-tree' });
6
+ // TODO: fix failing tests. LionTree is missing a close function, should this be coming from the DisclosureMixin?
7
+ // runMultiLevelListMixinSuite({ tagString: 'lion-tree', tagChildString: 'lion-tree' });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @param {HTMLElement} el
3
+ * @param {string} key
4
+ * @param {string} code
5
+ */
6
+ export function mimicKeyPress(el, key, code = '') {
7
+ el.dispatchEvent(new KeyboardEvent('keydown', { key, code }));
8
+ el.dispatchEvent(new KeyboardEvent('keyup', { key, code }));
9
+ }