@lion/ui 0.18.0-menu-system.6 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/collapsible.js +0 -1
  2. package/components/button/src/LionButton.js +0 -4
  3. package/components/button/test-suites/LionButton.suite.js +0 -1
  4. package/components/calendar/src/LionCalendar.js +1 -3
  5. package/components/combobox/test/lion-combobox.test.js +0 -1
  6. package/components/form-core/src/form-group/FormGroupMixin.js +0 -7
  7. package/components/form-core/src/registration/FormRegistrarMixin.js +0 -11
  8. package/components/form-core/test/FormControlMixin.test.js +0 -1
  9. package/components/form-core/test/validate/Validator.test.js +0 -2
  10. package/components/form-core/test-suites/ValidateMixin.suite.js +0 -2
  11. package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +0 -1
  12. package/components/input-datepicker/src/localizeNamespaceLoader.js +0 -1
  13. package/components/input-datepicker/test/lion-input-datepicker.test.js +6 -5
  14. package/components/listbox/test-suites/ListboxMixin.suite.js +1 -7
  15. package/components/localize/src/date/utils/normalizeIntlDate.js +2 -3
  16. package/components/localize/test/date/formatDate.test.js +2 -3
  17. package/components/overlays/src/OverlayController.js +110 -278
  18. package/components/overlays/src/OverlayMixin.js +11 -58
  19. package/components/overlays/src/OverlaysManager.js +2 -2
  20. package/components/overlays/src/configurations/withDropdownConfig.js +2 -22
  21. package/components/overlays/src/configurations/withPopoverConfig.js +32 -0
  22. package/components/overlays/src/utils/adopt-styles.js +5 -4
  23. package/components/overlays/src/utils/get-focusable-elements.js +0 -4
  24. package/components/overlays/src/utils/is-equal-config.js +6 -10
  25. package/components/overlays/test/OverlayController.test.js +21 -128
  26. package/components/overlays/test/utils-tests/is-equal-config.test.js +1 -1
  27. package/components/overlays/test-suites/OverlayMixin.suite.js +8 -8
  28. package/components/overlays/types/ArrowMixinTypes.ts +1 -3
  29. package/components/overlays/types/OverlayConfig.ts +5 -20
  30. package/components/select-rich/test/lion-select-rich.test.js +0 -3
  31. package/components/switch/src/LionSwitchButton.js +8 -3
  32. package/components/switch/test/lion-switch-button.test.js +38 -0
  33. package/custom-elements.json +17566 -30468
  34. package/dist-types/components/button/src/LionButton.d.ts +0 -1
  35. package/dist-types/components/button/src/LionButton.d.ts.map +1 -1
  36. package/dist-types/components/button/test-suites/LionButton.suite.d.ts.map +1 -1
  37. package/dist-types/components/calendar/src/LionCalendar.d.ts.map +1 -1
  38. package/dist-types/components/dialog/src/LionDialog.d.ts +1 -5
  39. package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
  40. package/dist-types/components/form-core/src/form-group/FormGroupMixin.d.ts.map +1 -1
  41. package/dist-types/components/form-core/src/registration/FormRegistrarMixin.d.ts.map +1 -1
  42. package/dist-types/components/form-core/test-suites/ValidateMixin.suite.d.ts.map +1 -1
  43. package/dist-types/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.d.ts.map +1 -1
  44. package/dist-types/components/input-datepicker/src/localizeNamespaceLoader.d.ts.map +1 -1
  45. package/dist-types/components/listbox/test-suites/ListboxMixin.suite.d.ts.map +1 -1
  46. package/dist-types/components/localize/src/date/utils/normalizeIntlDate.d.ts.map +1 -1
  47. package/dist-types/components/overlays/src/OverlayController.d.ts +12 -24
  48. package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
  49. package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
  50. package/dist-types/components/overlays/src/configurations/withDropdownConfig.d.ts +0 -1
  51. package/dist-types/components/overlays/src/configurations/withDropdownConfig.d.ts.map +1 -1
  52. package/dist-types/components/overlays/src/configurations/withPopoverConfig.d.ts +6 -0
  53. package/dist-types/components/overlays/src/configurations/withPopoverConfig.d.ts.map +1 -0
  54. package/dist-types/components/overlays/src/utils/get-focusable-elements.d.ts.map +1 -1
  55. package/dist-types/components/overlays/src/utils/is-equal-config.d.ts.map +1 -1
  56. package/dist-types/components/overlays/types/ArrowMixinTypes.d.ts.map +1 -1
  57. package/dist-types/components/overlays/types/OverlayConfig.d.ts +2 -12
  58. package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
  59. package/dist-types/components/select-rich/src/LionSelectRich.d.ts +2 -10
  60. package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
  61. package/dist-types/components/switch/src/LionSwitchButton.d.ts +6 -0
  62. package/dist-types/components/switch/src/LionSwitchButton.d.ts.map +1 -1
  63. package/dist-types/exports/overlays.d.ts +1 -3
  64. package/dist-types/exports/overlays.d.ts.map +1 -1
  65. package/dist-types/tsconfig.tsbuildinfo +1 -1
  66. package/docs/components/checkbox-group/overview.md +2 -2
  67. package/docs/components/collapsible/overview.md +1 -1
  68. package/docs/components/combobox/api-table.md +8 -21
  69. package/docs/components/combobox/overview.md +1 -1
  70. package/docs/components/combobox/use-cases.md +1 -1
  71. package/docs/components/dialog/api-table.md +6 -31
  72. package/docs/components/dialog/overview.md +1 -1
  73. package/docs/components/fieldset/overview.md +5 -5
  74. package/docs/components/form/overview.md +3 -3
  75. package/docs/components/form/use-cases.md +2 -2
  76. package/docs/components/icon/use-cases.md +1 -1
  77. package/docs/components/input/overview.md +1 -1
  78. package/docs/components/input-amount/overview.md +3 -3
  79. package/docs/components/input-date/overview.md +3 -3
  80. package/docs/components/input-datepicker/api-table.md +4 -21
  81. package/docs/components/input-datepicker/overview.md +5 -5
  82. package/docs/components/input-email/overview.md +2 -2
  83. package/docs/components/input-file/overview.md +1 -1
  84. package/docs/components/input-iban/overview.md +2 -2
  85. package/docs/components/input-range/overview.md +2 -2
  86. package/docs/components/input-stepper/overview.md +1 -1
  87. package/docs/components/input-tel/overview.md +1 -1
  88. package/docs/components/input-tel/use-cases.md +6 -6
  89. package/docs/components/input-tel-dropdown/overview.md +1 -1
  90. package/docs/components/listbox/use-cases.md +1 -1
  91. package/docs/components/radio-group/overview.md +3 -3
  92. package/docs/components/select/use-cases.md +1 -1
  93. package/docs/components/select-rich/api-table.md +5 -21
  94. package/docs/components/select-rich/use-cases.md +2 -2
  95. package/docs/components/switch/api-table.md +2 -0
  96. package/docs/components/tabs/examples.md +1 -1
  97. package/docs/components/tooltip/api-table.md +11 -36
  98. package/docs/fundamentals/index.md +4 -4
  99. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  100. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  101. package/docs/fundamentals/rationales/accessibility.md +1 -1
  102. package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
  103. package/docs/fundamentals/systems/core/overview.md +1 -1
  104. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  105. package/docs/fundamentals/systems/form/model-value.md +1 -1
  106. package/docs/fundamentals/systems/form/overview.md +28 -28
  107. package/docs/fundamentals/systems/form/validate.md +2 -2
  108. package/docs/fundamentals/systems/localize/overview.md +4 -4
  109. package/docs/fundamentals/systems/overlays/api-table.md +34 -36
  110. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  111. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  112. package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
  113. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  114. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  115. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  116. package/docs/guides/how-to/create-a-form.md +4 -4
  117. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  118. package/docs/guides/how-to/index.md +1 -1
  119. package/docs/guides/index.md +8 -8
  120. package/docs/guides/principles/index.md +5 -5
  121. package/docs/guides/principles/styling.md +1 -1
  122. package/exports/collapsible.js +0 -1
  123. package/exports/overlays.js +1 -6
  124. package/overlays.js +1 -6
  125. package/package.json +1 -1
  126. package/components/collapsible/src/DisclosureMixin.js +0 -313
  127. package/components/collapsible/test-suites/DisclosureMixin.suite.js +0 -30
  128. package/components/collapsible/types/DisclosureMixinTypes.ts +0 -48
  129. package/components/menu/CHANGELOG.md +0 -37
  130. package/components/menu/README.md +0 -335
  131. package/components/menu/index.js +0 -2
  132. package/components/menu/lion-menu-overlay.js +0 -3
  133. package/components/menu/lion-menu.js +0 -3
  134. package/components/menu/lion-spinbutton.js +0 -3
  135. package/components/menu/lion-toolbar.js +0 -3
  136. package/components/menu/lion-tree.js +0 -3
  137. package/components/menu/package.json +0 -46
  138. package/components/menu/requirements.temp.md +0 -12
  139. package/components/menu/src/InteractiveListMixin.js +0 -841
  140. package/components/menu/src/LionMenu.js +0 -250
  141. package/components/menu/src/LionMenuHybrid.js +0 -46
  142. package/components/menu/src/LionMenuOverlay.js +0 -155
  143. package/components/menu/src/LionSpinbutton.js +0 -213
  144. package/components/menu/src/LionToolbar.js +0 -94
  145. package/components/menu/src/LionTree.js +0 -52
  146. package/components/menu/src/MoreButtonMenuMixin.js +0 -278
  147. package/components/menu/src/MultiLevelListMixin.js +0 -274
  148. package/components/menu/src/utils/isInView.js +0 -26
  149. package/components/menu/src/utils/listItemInteractions.js +0 -124
  150. package/components/menu/src/utils/uuid.js +0 -3
  151. package/components/menu/test/lion-menu.test.js +0 -6
  152. package/components/menu/test-suites/InteractiveListMixin.suite.js +0 -642
  153. package/components/menu/test-suites/LionMenuHybrid.suite.js +0 -583
  154. package/components/menu/types/InteractiveListMixinTypes.d.ts +0 -82
  155. package/components/navigation-bar/README.md +0 -1
  156. package/components/navigation-bar/src/LionNavigationBar.js +0 -439
  157. package/components/navigation-bar/src/types.js +0 -41
  158. package/components/overlays/NEXT.md +0 -49
  159. package/dist-types/components/collapsible/src/DisclosureMixin.d.ts +0 -3
  160. package/dist-types/components/collapsible/src/DisclosureMixin.d.ts.map +0 -1
  161. package/dist-types/components/collapsible/test-suites/DisclosureMixin.suite.d.ts +0 -2
  162. package/dist-types/components/collapsible/test-suites/DisclosureMixin.suite.d.ts.map +0 -1
  163. package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts +0 -24
  164. package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts.map +0 -1
  165. package/dist-types/components/menu/index.d.ts +0 -3
  166. package/dist-types/components/menu/index.d.ts.map +0 -1
  167. package/dist-types/components/menu/lion-menu-overlay.d.ts +0 -2
  168. package/dist-types/components/menu/lion-menu-overlay.d.ts.map +0 -1
  169. package/dist-types/components/menu/lion-menu.d.ts +0 -2
  170. package/dist-types/components/menu/lion-menu.d.ts.map +0 -1
  171. package/dist-types/components/menu/lion-spinbutton.d.ts +0 -2
  172. package/dist-types/components/menu/lion-spinbutton.d.ts.map +0 -1
  173. package/dist-types/components/menu/lion-toolbar.d.ts +0 -2
  174. package/dist-types/components/menu/lion-toolbar.d.ts.map +0 -1
  175. package/dist-types/components/menu/lion-tree.d.ts +0 -2
  176. package/dist-types/components/menu/lion-tree.d.ts.map +0 -1
  177. package/dist-types/components/menu/src/InteractiveListMixin.d.ts +0 -617
  178. package/dist-types/components/menu/src/InteractiveListMixin.d.ts.map +0 -1
  179. package/dist-types/components/menu/src/LionMenu.d.ts +0 -565
  180. package/dist-types/components/menu/src/LionMenu.d.ts.map +0 -1
  181. package/dist-types/components/menu/src/LionMenuHybrid.d.ts +0 -19
  182. package/dist-types/components/menu/src/LionMenuHybrid.d.ts.map +0 -1
  183. package/dist-types/components/menu/src/LionMenuOverlay.d.ts +0 -1013
  184. package/dist-types/components/menu/src/LionMenuOverlay.d.ts.map +0 -1
  185. package/dist-types/components/menu/src/LionSpinbutton.d.ts +0 -58
  186. package/dist-types/components/menu/src/LionSpinbutton.d.ts.map +0 -1
  187. package/dist-types/components/menu/src/LionToolbar.d.ts +0 -8
  188. package/dist-types/components/menu/src/LionToolbar.d.ts.map +0 -1
  189. package/dist-types/components/menu/src/LionTree.d.ts +0 -447
  190. package/dist-types/components/menu/src/LionTree.d.ts.map +0 -1
  191. package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts +0 -39
  192. package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts.map +0 -1
  193. package/dist-types/components/menu/src/MultiLevelListMixin.d.ts +0 -495
  194. package/dist-types/components/menu/src/MultiLevelListMixin.d.ts.map +0 -1
  195. package/dist-types/components/menu/src/utils/isInView.d.ts +0 -9
  196. package/dist-types/components/menu/src/utils/isInView.d.ts.map +0 -1
  197. package/dist-types/components/menu/src/utils/listItemInteractions.d.ts +0 -48
  198. package/dist-types/components/menu/src/utils/listItemInteractions.d.ts.map +0 -1
  199. package/dist-types/components/menu/src/utils/uuid.d.ts +0 -2
  200. package/dist-types/components/menu/src/utils/uuid.d.ts.map +0 -1
  201. package/dist-types/components/menu/test/lion-menu.test.d.ts +0 -2
  202. package/dist-types/components/menu/test/lion-menu.test.d.ts.map +0 -1
  203. package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts +0 -14
  204. package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts.map +0 -1
  205. package/dist-types/components/menu/test-suites/LionMenuHybrid.suite.d.ts +0 -5
  206. package/dist-types/components/menu/test-suites/LionMenuHybrid.suite.d.ts.map +0 -1
  207. package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts +0 -238
  208. package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts.map +0 -1
  209. package/dist-types/components/navigation-bar/src/types.d.ts +0 -85
  210. package/dist-types/components/navigation-bar/src/types.d.ts.map +0 -1
  211. package/dist-types/exports/define/lion-item.d.ts +0 -2
  212. package/dist-types/exports/define/lion-item.d.ts.map +0 -1
  213. package/dist-types/exports/define/lion-menu-overlay.d.ts +0 -2
  214. package/dist-types/exports/define/lion-menu-overlay.d.ts.map +0 -1
  215. package/dist-types/exports/define/lion-menu.d.ts +0 -2
  216. package/dist-types/exports/define/lion-menu.d.ts.map +0 -1
  217. package/dist-types/exports/define/lion-navigation-bar.d.ts +0 -2
  218. package/dist-types/exports/define/lion-navigation-bar.d.ts.map +0 -1
  219. package/dist-types/exports/define/lion-toolbar.d.ts +0 -2
  220. package/dist-types/exports/define/lion-toolbar.d.ts.map +0 -1
  221. package/dist-types/exports/define/lion-tree.d.ts +0 -2
  222. package/dist-types/exports/define/lion-tree.d.ts.map +0 -1
  223. package/dist-types/exports/menu-test-suites.d.ts +0 -2
  224. package/dist-types/exports/menu-test-suites.d.ts.map +0 -1
  225. package/dist-types/exports/menu.d.ts +0 -7
  226. package/dist-types/exports/menu.d.ts.map +0 -1
  227. package/dist-types/exports/navigation-bar.d.ts +0 -2
  228. package/dist-types/exports/navigation-bar.d.ts.map +0 -1
  229. package/docs/components/menu/api-table.md +0 -455
  230. package/docs/components/menu/applyMenuDemoStyles.js +0 -173
  231. package/docs/components/menu/extensions.md +0 -262
  232. package/docs/components/menu/index.md +0 -13
  233. package/docs/components/menu/overview.md +0 -422
  234. package/exports/define/lion-item.js +0 -3
  235. package/exports/define/lion-menu-overlay.js +0 -3
  236. package/exports/define/lion-menu.js +0 -3
  237. package/exports/define/lion-navigation-bar.js +0 -3
  238. package/exports/define/lion-toolbar.js +0 -3
  239. package/exports/define/lion-tree.js +0 -3
  240. package/exports/menu-test-suites.js +0 -2
  241. package/exports/menu.js +0 -7
  242. package/exports/navigation-bar.js +0 -1
  243. package/menu-test-suites.js +0 -2
  244. package/menu.js +0 -7
  245. package/navigation-bar.js +0 -1
@@ -1,94 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- import { LionMenu } from './LionMenu.js';
3
- import { setChecked, toggleChecked } from './utils/listItemInteractions.js';
4
-
5
- /**
6
- * @typedef {import('../types/InteractiveListMixinTypes.js').InteractiveListItemRole} InteractiveListItemRole
7
- */
8
-
9
- export class LionToolbar extends LionMenu {
10
- constructor() {
11
- super();
12
-
13
- this._listRole = 'toolbar';
14
- this.bar = true;
15
- }
16
-
17
- /**
18
- * Allows groups ([role=radiogroup|checkboxgroup]) within one level.
19
- * In case we deal with [role=checkbox], we treat it as multiple choice group
20
- * @override InteractiveListMixin
21
- * @param {number} index
22
- */
23
- setCheckedIndex(index) {
24
- const item = this.listItems[index];
25
- if (item) {
26
- // @ts-ignore - InteractiveListItemRole type
27
- const role = /** @type {InteractiveListItemRole} */ (item.getAttribute('role'));
28
- let listItemsWithinGroup = this.listItems;
29
- let multiple = this.multipleChoice;
30
- if (role === 'radio' || role === 'checkbox') {
31
- /**
32
- * If index = 1 (radio 'Red'), closest group will be div[role=radiogroup]
33
- * @example
34
- * <lion-toolbar>
35
- * <div role="radiogroup" aria-label="Text Color">
36
- * <button role="radio" aria-checked="false">Blue</button>
37
- * <button role="radio" aria-checked="true">Red</button>
38
- * <button role="radio" aria-checked="false">Green</button>
39
- * </div>
40
- * <div role="separator"></div>
41
- * <div role="checkboxgroup" aria-label="Text Color">
42
- * <button role="checkbox" aria-checked="false">Blue</button>
43
- * <button role="checkbox" aria-checked="true">Red</button>
44
- * <button role="checkbox" aria-checked="false">Green</button>
45
- * </div>
46
- * </lion-toolbar>
47
- */
48
- let closestGroup;
49
- if (role === 'radio') {
50
- closestGroup = item.closest('[role="radiogroup"]');
51
- } else if (role === 'checkbox') {
52
- closestGroup = item.closest('[role="checkboxgroup"]');
53
- }
54
-
55
- const group = closestGroup && this.contains(closestGroup) ? closestGroup : this;
56
- listItemsWithinGroup = this.listItems.filter(listItem => group.contains(listItem));
57
- multiple = role === 'checkbox';
58
- }
59
-
60
- if (!multiple) {
61
- // Uncheck all
62
- listItemsWithinGroup.forEach(listItem => {
63
- setChecked(listItem, true);
64
- });
65
- setChecked(this.listItems[index]);
66
- } else {
67
- toggleChecked(this.listItems[index]);
68
- }
69
- }
70
- }
71
-
72
- /**
73
- * @param {*} newItems
74
- */
75
- _initListItems(newItems) {
76
- super._initListItems(newItems);
77
-
78
- // @ts-ignore - forEach parameter
79
- newItems.forEach(item => {
80
- if (
81
- item.getAttribute('role') === 'button' ||
82
- (item.tagName === 'BUTTON' && !item.hasAttribute('role'))
83
- ) {
84
- const initialAriaPressed = item.getAttribute('aria-pressed');
85
- item.setAttribute('aria-pressed', initialAriaPressed || 'false');
86
-
87
- item.addEventListener('click', () => {
88
- const ariaPressed = item.getAttribute('aria-pressed') === 'true';
89
- item.setAttribute('aria-pressed', `${!ariaPressed}`);
90
- });
91
- }
92
- });
93
- }
94
- }
@@ -1,52 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- import { LitElement } from 'lit';
3
- import { MultiLevelListMixin } from './MultiLevelListMixin.js';
4
-
5
- // @ts-ignore - class extension with mixin
6
- export class LionTree extends MultiLevelListMixin(LitElement) {
7
- constructor() {
8
- super();
9
-
10
- /** @configure InteractiveListMixin */
11
- this._listRole = 'tree';
12
- /** @configure InteractiveListMixin */
13
- this._activateOnTypedChars = true;
14
- /** @configure DisclosureMixin */
15
- this.invokerInteraction = 'click';
16
- }
17
-
18
- /**
19
- * @param {*} changedProperties
20
- */
21
- updated(changedProperties) {
22
- super.updated(changedProperties);
23
-
24
- if (changedProperties.has('level')) {
25
- if (this.level > 0) {
26
- this._listNode.setAttribute('role', 'group');
27
- }
28
- this.__setAriaLevelForListItems();
29
- }
30
- }
31
-
32
- /**
33
- * @param {*} newItems
34
- */
35
- _initListItems(newItems) {
36
- // @ts-ignore - parameter types
37
- super._initListItems(newItems);
38
-
39
- this.__setAriaLevelForListItems();
40
- // @ts-ignore - forEach parameters
41
- newItems.forEach((item, index) => {
42
- item.setAttribute('aria-posinset', `${index + 1}`);
43
- item.setAttribute('aria-setsize', `${this.listItems.length}`);
44
- });
45
- }
46
-
47
- __setAriaLevelForListItems() {
48
- this.listItems.forEach(item => {
49
- item.setAttribute?.('aria-level', `${this.level + 1}`);
50
- });
51
- }
52
- }
@@ -1,278 +0,0 @@
1
- // eslint-disable-next-line import/no-extraneous-dependencies
2
- import { css } from 'lit';
3
-
4
- const styles = css`
5
- /** More button is hidden by default */
6
- [data-more-button-wrapper] {
7
- display: none;
8
- }
9
-
10
- [data-more-button-menu][data-open]:not(:has([role='listitem'] [aria-expanded='true'])) {
11
- position: absolute;
12
- overflow: visible;
13
- height: auto;
14
- width: auto;
15
- top: 100%;
16
- }
17
-
18
- /** N.B. this is a simplified version of sr-only. when we move to overlayctrl, we should build this into overlayctrl */
19
- [data-more-button-menu] {
20
- overflow: hidden;
21
- height: 0;
22
- width: 0;
23
- }
24
-
25
- [role='list']:has(> [data-more-button-wrapper]) > [role='listitem'] > :is(button, a) {
26
- white-space: nowrap;
27
- }
28
- `;
29
-
30
- // @ts-ignore - JS mixin typing
31
- export const MoreButtonMenuMixin = superclass =>
32
- class MoreButtonMenuMixinClass extends superclass {
33
- constructor() {
34
- super();
35
- this.__resizeTimeout = null;
36
- this.isMoreButtonShown = null;
37
- this.handleResize = this.handleResize.bind(this);
38
- }
39
-
40
- disconnectedCallback() {
41
- window.removeEventListener('resize', this.handleResize);
42
- if (this.__resizeTimeout) {
43
- clearTimeout(this.__resizeTimeout);
44
- }
45
- super.disconnectedCallback?.();
46
- }
47
-
48
- _initMoreButtonMenu() {
49
- this._createMoreButtonWrapper();
50
- window.addEventListener('resize', this.handleResize);
51
- this.handleResize();
52
- }
53
-
54
- // eslint-disable-next-line class-methods-use-this
55
- _getDeepActiveElement() {
56
- let host = document.activeElement || document.body;
57
- while (host?.shadowRoot?.activeElement) {
58
- host = host.shadowRoot.activeElement;
59
- }
60
- return host;
61
- }
62
-
63
- _createMoreButtonWrapper() {
64
- const moreButtonWrapper = document.createElement('div');
65
- const style = document.createElement('style');
66
- style.textContent = styles.cssText;
67
- moreButtonWrapper.appendChild(style);
68
- moreButtonWrapper.setAttribute('data-more-button-wrapper', '');
69
- [...this.getMoreButtonSlotProjection().childNodes].forEach(node =>
70
- moreButtonWrapper.appendChild(node),
71
- );
72
- const moreButton = moreButtonWrapper.querySelector('button');
73
- moreButton?.setAttribute('data-more-button', '');
74
- moreButton?.setAttribute('tabindex', '-1');
75
- moreButton?.setAttribute('aria-expanded', 'false');
76
- const moreButtonMenu = document.createElement('div');
77
- moreButtonMenu.setAttribute('data-more-button-menu', '');
78
- moreButtonMenu.setAttribute('tabindex', '-1');
79
- moreButtonWrapper.appendChild(moreButtonMenu);
80
- this._listNode.appendChild(moreButtonWrapper);
81
-
82
- const isElementDirectFocusableItemUnderMoreButtonMenu = (/** @type {Element} */ element) =>
83
- (this.listItems.includes(element) && moreButtonMenu.contains(element)) ||
84
- element === moreButtonMenu;
85
-
86
- moreButtonMenu.addEventListener(
87
- 'focusin',
88
- /** @type {FocusEvent} */ event => {
89
- const target = /** @type {HTMLElement} */ (event?.target);
90
- if (!isElementDirectFocusableItemUnderMoreButtonMenu(target)) return;
91
-
92
- // If applicable hide any other L2 menus
93
- this.querySelector('[level="2"]:has([data-open])')?._overlayCtrl?.hide();
94
-
95
- // A user did `Shift + Tab` from L2 menu to More menu
96
- if (target?.getAttribute('aria-expanded') === 'true') {
97
- // close L2 menu
98
- target?.click();
99
- }
100
- moreButton?.setAttribute('aria-expanded', 'true');
101
- moreButtonMenu.setAttribute('data-open', '');
102
- },
103
- );
104
-
105
- moreButtonMenu.addEventListener('focusout', () => {
106
- // We need this timeout for Safari/WebKit.
107
- // Unfortunately, an in progress click gets canceled when overflow:hidden is applied.
108
- // Although mousedown would work instead, the consuming developer should have the freedom to apply all possible interaction pattterns.
109
- // Especially, we should be compatible with 'withClickInteraction'
110
- setTimeout(() => {
111
- if (isElementDirectFocusableItemUnderMoreButtonMenu(this._getDeepActiveElement())) return;
112
- moreButton?.setAttribute('aria-expanded', 'false');
113
-
114
- moreButtonMenu.removeAttribute('data-open');
115
- }, 100);
116
- });
117
-
118
- moreButton?.addEventListener('click', () => {
119
- if (moreButtonMenu.getAttribute('data-open') === null) {
120
- moreButtonMenu?.focus({ preventScroll: true });
121
- moreButtonMenu.setAttribute('data-open', '');
122
- }
123
- });
124
- }
125
-
126
- getMoreButtonSlotProjection() {
127
- return this.querySelector('[slot="more-button"]');
128
- }
129
-
130
- getMoreButtonMenu() {
131
- return this.querySelector('[data-more-button-menu]');
132
- }
133
-
134
- getMoreButtonMenuWrapper() {
135
- return this.querySelector('[data-more-button-wrapper]');
136
- }
137
-
138
- displayMoreButton() {
139
- this.getMoreButtonMenuWrapper().style.display = 'block';
140
- this.isMoreButtonShown = true;
141
- }
142
-
143
- hideMoreButton() {
144
- this.getMoreButtonMenuWrapper().style.display = 'none';
145
- this.isMoreButtonShown = false;
146
- }
147
-
148
- doItemsFit() {
149
- this.style.display = 'none';
150
- const parentWidth = this.parentElement.clientWidth;
151
- this.style.display = '';
152
- return (
153
- this._listNode.scrollWidth === this._listNode.clientWidth &&
154
- this._listNode.scrollWidth <= parentWidth
155
- );
156
- }
157
-
158
- getListItems() {
159
- const listNode = this._listNode;
160
- return Array.from(listNode.querySelectorAll(':scope > [role="listitem"]'));
161
- }
162
-
163
- /**
164
- * @param {Node} listItem
165
- */
166
- getListItemWithAdjacentNodes = listItem => {
167
- const markerNodeType = this.nodeType && Node.COMMENT_NODE;
168
- /** @param {Node | null | undefined} node */
169
- const isMarkerComment = node => node?.nodeType === markerNodeType && node?.nodeValue === '';
170
-
171
- const previousNodes = [];
172
- let { previousSibling } = listItem;
173
- while (previousSibling) {
174
- if (previousSibling.nodeType === Node.ELEMENT_NODE) {
175
- break;
176
- }
177
- previousNodes.unshift(previousSibling);
178
- if (isMarkerComment(previousSibling)) {
179
- break;
180
- }
181
- ({ previousSibling } = previousSibling);
182
- }
183
-
184
- const nextNodes = [];
185
- let { nextSibling } = listItem;
186
- while (nextSibling) {
187
- if (nextSibling.nodeType === Node.ELEMENT_NODE) {
188
- break;
189
- }
190
- nextNodes.push(nextSibling);
191
-
192
- if (isMarkerComment(nextSibling)) {
193
- break;
194
- }
195
-
196
- ({ nextSibling } = nextSibling);
197
- }
198
-
199
- const fragment = document.createDocumentFragment();
200
- const nodes = [...previousNodes, listItem, ...nextNodes];
201
- nodes.forEach(node => fragment.appendChild(node));
202
- return fragment;
203
- };
204
-
205
- /**
206
- * @param {{ moreButtonMenuElement: HTMLButtonElement, listItem: HTMLElement }} opts
207
- */
208
- moveItemToMoreButtonMenuFromMainMenu({ moreButtonMenuElement, listItem }) {
209
- const fragment = this.getListItemWithAdjacentNodes(listItem);
210
- moreButtonMenuElement.prepend(fragment);
211
- // eslint-disable-next-line no-param-reassign
212
- listItem.style.display = '';
213
- this.displayMoreButton();
214
- }
215
-
216
- moveAllItemsToMainMenuFromMoreButtonMenu() {
217
- const moreButtonMenu = this.getMoreButtonMenu();
218
- const moreButtonMenuWrapper = this.getMoreButtonMenuWrapper();
219
- if (moreButtonMenu.childNodes.length === 0) {
220
- return;
221
- }
222
- [...moreButtonMenu.childNodes].forEach(node => {
223
- moreButtonMenuWrapper.before(node);
224
- });
225
- }
226
-
227
- renderAllItemsInMainMenu() {
228
- this.moveAllItemsToMainMenuFromMoreButtonMenu();
229
- }
230
-
231
- hideItemsOneByOneInMainMenuUntilTheyFit() {
232
- let hiddenItemsCount = 0;
233
- const mainMenuItems = this.getListItems();
234
- for (let i = mainMenuItems.length - 1; i >= 0 && !this.doItemsFit(); i -= 1) {
235
- mainMenuItems[i].style.display = 'none';
236
- hiddenItemsCount += 1;
237
- }
238
- return hiddenItemsCount;
239
- }
240
-
241
- /**
242
- * @param {number} hiddenItemsCount
243
- */
244
- moveHiddenItemsFromMainMenuToMoreButtonMenu(hiddenItemsCount) {
245
- const moreButtonMenuElement = this.getMoreButtonMenu();
246
- const listItems = this._listNode.querySelectorAll(':scope > [role="listitem"]');
247
- for (let i = 0; i < hiddenItemsCount; i += 1) {
248
- const listItem = listItems[listItems.length - 1 - i];
249
- this.moveItemToMoreButtonMenuFromMainMenu({ moreButtonMenuElement, listItem });
250
- }
251
- }
252
-
253
- handleResize() {
254
- if (this.__resizeTimeout) {
255
- return;
256
- }
257
-
258
- this.style.visibility = 'hidden';
259
-
260
- this.__resizeTimeout = setTimeout(() => {
261
- this.__resizeTimeout = null;
262
-
263
- this.renderAllItemsInMainMenu();
264
- this.hideMoreButton();
265
-
266
- if (this.doItemsFit()) {
267
- this.style.visibility = '';
268
- return;
269
- }
270
-
271
- this.style.visibility = 'hidden';
272
- this.displayMoreButton();
273
- const hiddenItemsCount = this.hideItemsOneByOneInMainMenuUntilTheyFit();
274
- this.moveHiddenItemsFromMainMenuToMoreButtonMenu(hiddenItemsCount);
275
- this.style.visibility = '';
276
- }, 50);
277
- }
278
- };
@@ -1,274 +0,0 @@
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
-
7
- /**
8
- * @typedef {import('./InteractiveListMixin.js').LionItem} LionItem
9
- * @typedef {import('../types/InteractiveListMixinTypes.js').InteractiveListHost} InteractiveList
10
- */
11
-
12
- /**
13
- * All logic that is needed for interactive lists that are allowed to have multiple nested, collapsible levels
14
- * Applies to [role=menu] and [role=tree]
15
- */
16
- // @ts-ignore - mixin implementation
17
- const MultiLevelListMixinImplementation = superclass =>
18
- // @ts-ignore - mixin class extension
19
- class extends InteractiveListMixin(superclass) {
20
- render() {
21
- return html`
22
- <slot name="invoker"></slot>
23
- <slot name="list"></slot>
24
- <slot id="list-items-outlet"></slot>
25
- `;
26
- }
27
-
28
- static get properties() {
29
- return {
30
- invokerNode: Object,
31
- behaveAsAccordion: { type: Boolean, attribute: 'behave-as-accordion' },
32
- level: { type: Number, reflect: true },
33
- };
34
- }
35
-
36
- /**
37
- * @configure DisclosureMixin
38
- */
39
- get _invokerNode() {
40
- // @ts-ignore - accessing static method and super property
41
- return this.constructor._getFocusableInvokerEl(this.invokerNode) || super._invokerNode;
42
- }
43
-
44
- /**
45
- * @configure DisclosureMixin
46
- * This will be compatible with DisclosureMixin and OverlayMixin. It contains the invoked
47
- * InteractiveList widget (like menu|tree).
48
- */
49
- get _contentNode() {
50
- return this._listNode;
51
- }
52
-
53
- constructor() {
54
- super();
55
-
56
- /**
57
- * When an invokerNode is supplied (usually by a parent level menu), it will take precedence
58
- * over [slot=invoker] and previousElementSibling with [data-invoker] attribute
59
- * @type {HTMLElement}
60
- */
61
- // @ts-ignore - can be undefined initially
62
- this.invokerNode = undefined;
63
- /**
64
- * @configure DisclosureMixin
65
- */
66
- this.handleFocus = true;
67
- /**
68
- * The parent list if level > 1
69
- * @type {InteractiveList}
70
- */
71
- // @ts-ignore - can be undefined initially
72
- this.parentList = undefined;
73
- /**
74
- * When true, will have a maximum of one submenu open at a time
75
- */
76
- this.behaveAsAccordion = false;
77
- /**
78
- * The level of nested menus. Will be reflected as attribute for styling purposes
79
- */
80
- this.level = 1;
81
- /**
82
- * @configure InteractiveListMixin
83
- */
84
- this.noPreselect = true;
85
- /**
86
- * @configure InteractiveListMixin
87
- */
88
- this._activeMode = 'roving-tabindex';
89
- /**
90
- * @type {Map<HTMLElement|LionItem,InteractiveList>}
91
- */
92
- this._subListMap = new Map();
93
- }
94
-
95
- // /**
96
- // * @param {import('lit-element').PropertyValues } changedProperties
97
- // */
98
- // updated(changedProperties) {
99
- // super.updated(changedProperties);
100
-
101
- // if (changedProperties.has('invokerNode')) {
102
- // // TODO: update openableCtrl invokerNode once we make this a ctrl as well
103
- // }
104
- // }
105
-
106
- /**
107
- * Gets the child InteractiveList, based on item
108
- * @param {LionItem|HTMLElement} item can be sibling of or parent of InteractiveList
109
- */
110
- static _getSubInteractiveList(item) {
111
- /**
112
- * Note that, according to W3C spec, the sub level element with [role=menu|menubar|tree]
113
- * needs to be a sibling of the invoker element with
114
- * [role=menuitem|menuitemchecbox|menuitemradio|treeitem] (and not the parent)
115
- *
116
- * In the example below <lion-menu> is considered as item
117
- * @example
118
- * <lion-menuitem>
119
- * <button slot="invoker"></button>
120
- * <lion-menu> ... </lion-menu>
121
- * </lion-menuitem>
122
- */
123
- // @ts-ignore - isInteractiveList property check
124
- const siblingOfInvoker = item.nextElementSibling?.isInteractiveList;
125
- if (siblingOfInvoker) {
126
- return item.nextElementSibling;
127
- }
128
- /**
129
- * In the example below div[role=listitem] | [data-item] is considered as item
130
- * @example
131
- * <div role="listitem" data-item>
132
- * <button slot="invoker"></button>
133
- * <lion-menu> ... </lion-menu>
134
- * </div>
135
- */
136
- const childOfInvoker =
137
- item.getAttribute?.('role') === 'listitem' || item.hasAttribute?.('data-item');
138
- if (childOfInvoker) {
139
- // @ts-ignore - isInteractiveList check
140
- return Array.from(item.children).find(child => child.isInteractiveList);
141
- }
142
- return undefined;
143
- }
144
-
145
- /**
146
- * @param {*} newItems
147
- */
148
- _initListItems(newItems) {
149
- super._initListItems(newItems);
150
-
151
- const ctor = this.constructor;
152
- // @ts-ignore - forEach parameter types
153
- newItems.forEach(item => {
154
- // @ts-ignore - static method access
155
- const subList = ctor._getSubInteractiveList(item);
156
- if (subList) {
157
- this._subListMap.set(item, subList);
158
- subList.level = this.level + 1;
159
- subList.parentList = this;
160
- subList.invokerNode = item;
161
- // @ts-ignore - invokerInteraction property
162
- subList.invokerInteraction = this.invokerInteraction;
163
- subList._activeMode = this._activeMode;
164
- }
165
- });
166
- }
167
-
168
- /**
169
- * @enhance DisclosureMixin
170
- * @param {Event} [ev]
171
- */
172
- toggle(ev) {
173
- // @ts-ignore - target property
174
- if (ev && this._listNode.contains(ev.target)) {
175
- // prevent nested menus (inside invokers) from triggering invoker
176
- return;
177
- }
178
- // @ts-ignore - super.toggle method
179
- super.toggle();
180
- }
181
-
182
- /**
183
- * @enhance InteractiveListMixin
184
- * @param {*} ev
185
- */
186
- _onListKeyDown(ev) {
187
- const targetFromsubList = Array.from(this._subListMap).find(
188
- // @ts-ignore - contains method on InteractiveListHost
189
- ([, s]) => s === ev.target || s.contains(ev.target),
190
- );
191
-
192
- if (targetFromsubList) {
193
- return;
194
- }
195
-
196
- super._onListKeyDown(ev);
197
-
198
- const subListOfActiveItem = this._subListMap.get(this.activeItem);
199
- const parentListOfActiveItem = this.parentList;
200
- const { key } = ev;
201
-
202
- if (key === 'Escape' && parentListOfActiveItem) {
203
- // We need to stop here, or else we affect parent menu (handled by OverlayController)
204
- ev.stopPropagation();
205
- }
206
-
207
- switch (key) {
208
- case 'Enter':
209
- case ' ':
210
- // make it work like a button
211
- this.activeItem?.click();
212
- break;
213
- case 'ArrowDown':
214
- if (
215
- this.orientation === 'horizontal' &&
216
- subListOfActiveItem &&
217
- this._activeMode !== 'tabbable-disclosure'
218
- ) {
219
- this.activeItem.click();
220
- }
221
- break;
222
- case 'ArrowRight':
223
- if (this.orientation === 'vertical' && subListOfActiveItem) {
224
- this.activeItem.click();
225
- }
226
- break;
227
- case 'ArrowUp':
228
- if (this.orientation === 'horizontal' && parentListOfActiveItem) {
229
- // @ts-ignore - close method
230
- this.close();
231
- // @ts-ignore - _onOverlayShow method
232
- parentListOfActiveItem._onOverlayShow();
233
- }
234
- break;
235
- case 'ArrowLeft':
236
- if (this.orientation === 'vertical' && parentListOfActiveItem) {
237
- // @ts-ignore - close method
238
- this.close();
239
- // @ts-ignore - _onOverlayShow method
240
- parentListOfActiveItem._onOverlayShow();
241
- }
242
- break;
243
- /* no default */
244
- }
245
- }
246
-
247
- // /**
248
- // * @enhance DisclosureMixin
249
- // */
250
- // _setupDisclosure() {
251
- // if (!this._invokerNode) return;
252
-
253
- // super._setupDisclosure();
254
- // }
255
-
256
- // /**
257
- // * @enhance DisclosureMixin
258
- // */
259
- // _teardownDisclosure() {
260
- // if (!this._invokerNode) return;
261
-
262
- // super._teardownDisclosure();
263
- // }
264
-
265
- // /**
266
- // * @enhance DisclosureMixin
267
- // */
268
- // async _onOpenedChanged() {
269
- // if (!this._invokerNode) return;
270
-
271
- // await super._onOpenedChanged();
272
- // }
273
- };
274
- export const MultiLevelListMixin = dedupeMixin(MultiLevelListMixinImplementation);