@lion/ui 0.17.0-menu-system.1 → 0.17.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 (215) 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 +0 -2
  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/localize/test/date/formatDate.test.js +0 -1
  15. package/components/overlays/src/OverlayController.js +111 -244
  16. package/components/overlays/src/OverlayMixin.js +11 -58
  17. package/components/overlays/src/OverlaysManager.js +2 -2
  18. package/components/overlays/src/utils/adopt-styles.js +1 -2
  19. package/components/overlays/src/utils/get-focusable-elements.js +0 -4
  20. package/components/overlays/src/utils/is-equal-config.js +6 -10
  21. package/components/overlays/test/OverlayController.test.js +3 -5
  22. package/components/overlays/test/utils-tests/is-equal-config.test.js +1 -1
  23. package/components/overlays/test-suites/OverlayMixin.suite.js +8 -8
  24. package/components/overlays/types/OverlayConfig.ts +5 -16
  25. package/components/select-rich/test/lion-select-rich.test.js +0 -3
  26. package/custom-elements.json +1910 -13871
  27. package/dist-types/components/button/src/LionButton.d.ts +0 -1
  28. package/dist-types/components/button/src/LionButton.d.ts.map +1 -1
  29. package/dist-types/components/button/test-suites/LionButton.suite.d.ts.map +1 -1
  30. package/dist-types/components/calendar/src/LionCalendar.d.ts.map +1 -1
  31. package/dist-types/components/dialog/src/LionDialog.d.ts +1 -3
  32. package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
  33. package/dist-types/components/form-core/src/form-group/FormGroupMixin.d.ts.map +1 -1
  34. package/dist-types/components/form-core/src/registration/FormRegistrarMixin.d.ts.map +1 -1
  35. package/dist-types/components/form-core/test-suites/ValidateMixin.suite.d.ts.map +1 -1
  36. package/dist-types/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.d.ts.map +1 -1
  37. package/dist-types/components/input-datepicker/src/localizeNamespaceLoader.d.ts.map +1 -1
  38. package/dist-types/components/overlays/src/OverlayController.d.ts +13 -9
  39. package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
  40. package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
  41. package/dist-types/components/overlays/src/utils/get-focusable-elements.d.ts.map +1 -1
  42. package/dist-types/components/overlays/src/utils/is-equal-config.d.ts.map +1 -1
  43. package/dist-types/components/overlays/types/OverlayConfig.d.ts +2 -10
  44. package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
  45. package/dist-types/components/select-rich/src/LionSelectRich.d.ts +2 -8
  46. package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
  47. package/dist-types/exports/overlays.d.ts +0 -3
  48. package/dist-types/exports/overlays.d.ts.map +1 -1
  49. package/dist-types/tsconfig.tsbuildinfo +1 -1
  50. package/docs/components/checkbox-group/overview.md +2 -2
  51. package/docs/components/collapsible/overview.md +1 -1
  52. package/docs/components/combobox/api-table.md +8 -21
  53. package/docs/components/combobox/overview.md +1 -1
  54. package/docs/components/combobox/use-cases.md +1 -1
  55. package/docs/components/dialog/api-table.md +6 -31
  56. package/docs/components/dialog/overview.md +1 -1
  57. package/docs/components/fieldset/overview.md +5 -5
  58. package/docs/components/form/overview.md +3 -3
  59. package/docs/components/form/use-cases.md +2 -2
  60. package/docs/components/icon/use-cases.md +1 -1
  61. package/docs/components/input/overview.md +1 -1
  62. package/docs/components/input-amount/overview.md +3 -3
  63. package/docs/components/input-date/overview.md +3 -3
  64. package/docs/components/input-datepicker/api-table.md +4 -21
  65. package/docs/components/input-datepicker/overview.md +5 -5
  66. package/docs/components/input-email/overview.md +2 -2
  67. package/docs/components/input-file/overview.md +1 -1
  68. package/docs/components/input-iban/overview.md +2 -2
  69. package/docs/components/input-range/overview.md +2 -2
  70. package/docs/components/input-stepper/overview.md +1 -1
  71. package/docs/components/input-tel/overview.md +1 -1
  72. package/docs/components/input-tel/use-cases.md +6 -6
  73. package/docs/components/input-tel-dropdown/overview.md +1 -1
  74. package/docs/components/listbox/use-cases.md +1 -1
  75. package/docs/components/radio-group/overview.md +3 -3
  76. package/docs/components/select/use-cases.md +1 -1
  77. package/docs/components/select-rich/api-table.md +5 -21
  78. package/docs/components/select-rich/use-cases.md +2 -2
  79. package/docs/components/tabs/examples.md +1 -1
  80. package/docs/components/tooltip/api-table.md +11 -36
  81. package/docs/fundamentals/index.md +4 -4
  82. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  83. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  84. package/docs/fundamentals/rationales/accessibility.md +1 -1
  85. package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
  86. package/docs/fundamentals/systems/core/overview.md +1 -1
  87. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  88. package/docs/fundamentals/systems/form/model-value.md +1 -1
  89. package/docs/fundamentals/systems/form/overview.md +28 -28
  90. package/docs/fundamentals/systems/form/validate.md +2 -2
  91. package/docs/fundamentals/systems/localize/overview.md +4 -4
  92. package/docs/fundamentals/systems/overlays/api-table.md +34 -34
  93. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  94. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  95. package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
  96. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  97. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  98. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  99. package/docs/guides/how-to/create-a-form.md +4 -4
  100. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  101. package/docs/guides/how-to/index.md +1 -1
  102. package/docs/guides/index.md +8 -8
  103. package/docs/guides/principles/index.md +5 -5
  104. package/docs/guides/principles/styling.md +1 -1
  105. package/exports/collapsible.js +0 -1
  106. package/exports/overlays.js +0 -6
  107. package/overlays.js +0 -6
  108. package/package.json +1 -1
  109. package/components/collapsible/src/DisclosureMixin.js +0 -313
  110. package/components/collapsible/types/DisclosureMixinTypes.ts +0 -48
  111. package/components/menu/CHANGELOG.md +0 -37
  112. package/components/menu/README.md +0 -335
  113. package/components/menu/index.js +0 -2
  114. package/components/menu/lion-menu-overlay.js +0 -3
  115. package/components/menu/lion-menu.js +0 -3
  116. package/components/menu/lion-spinbutton.js +0 -3
  117. package/components/menu/lion-toolbar.js +0 -3
  118. package/components/menu/lion-tree.js +0 -3
  119. package/components/menu/package.json +0 -46
  120. package/components/menu/requirements.temp.md +0 -12
  121. package/components/menu/src/InteractiveListMixin.js +0 -796
  122. package/components/menu/src/LionMenu.js +0 -250
  123. package/components/menu/src/LionMenuHybrid.js +0 -46
  124. package/components/menu/src/LionMenuOverlay.js +0 -155
  125. package/components/menu/src/LionSpinbutton.js +0 -213
  126. package/components/menu/src/LionToolbar.js +0 -94
  127. package/components/menu/src/LionTree.js +0 -52
  128. package/components/menu/src/MultiLevelListMixin.js +0 -274
  129. package/components/menu/src/utils/isInView.js +0 -26
  130. package/components/menu/src/utils/listItemInteractions.js +0 -104
  131. package/components/menu/src/utils/uuid.js +0 -3
  132. package/components/menu/test/lion-menu.test.js +0 -3
  133. package/components/menu/test-suites/InteractiveListMixin.suite.js +0 -142
  134. package/components/menu/types/InteractiveListMixinTypes.d.ts +0 -82
  135. package/components/navigation-bar/README.md +0 -1
  136. package/components/navigation-bar/src/LionNavigationBar.js +0 -422
  137. package/components/navigation-bar/src/types.js +0 -41
  138. package/components/overlays/NEXT.md +0 -49
  139. package/dist-types/components/collapsible/src/DisclosureMixin.d.ts +0 -3
  140. package/dist-types/components/collapsible/src/DisclosureMixin.d.ts.map +0 -1
  141. package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts +0 -24
  142. package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts.map +0 -1
  143. package/dist-types/components/menu/index.d.ts +0 -3
  144. package/dist-types/components/menu/index.d.ts.map +0 -1
  145. package/dist-types/components/menu/lion-menu-overlay.d.ts +0 -2
  146. package/dist-types/components/menu/lion-menu-overlay.d.ts.map +0 -1
  147. package/dist-types/components/menu/lion-menu.d.ts +0 -2
  148. package/dist-types/components/menu/lion-menu.d.ts.map +0 -1
  149. package/dist-types/components/menu/lion-spinbutton.d.ts +0 -2
  150. package/dist-types/components/menu/lion-spinbutton.d.ts.map +0 -1
  151. package/dist-types/components/menu/lion-toolbar.d.ts +0 -2
  152. package/dist-types/components/menu/lion-toolbar.d.ts.map +0 -1
  153. package/dist-types/components/menu/lion-tree.d.ts +0 -2
  154. package/dist-types/components/menu/lion-tree.d.ts.map +0 -1
  155. package/dist-types/components/menu/src/InteractiveListMixin.d.ts +0 -611
  156. package/dist-types/components/menu/src/InteractiveListMixin.d.ts.map +0 -1
  157. package/dist-types/components/menu/src/LionMenu.d.ts +0 -563
  158. package/dist-types/components/menu/src/LionMenu.d.ts.map +0 -1
  159. package/dist-types/components/menu/src/LionMenuHybrid.d.ts +0 -19
  160. package/dist-types/components/menu/src/LionMenuHybrid.d.ts.map +0 -1
  161. package/dist-types/components/menu/src/LionMenuOverlay.d.ts +0 -1007
  162. package/dist-types/components/menu/src/LionMenuOverlay.d.ts.map +0 -1
  163. package/dist-types/components/menu/src/LionSpinbutton.d.ts +0 -58
  164. package/dist-types/components/menu/src/LionSpinbutton.d.ts.map +0 -1
  165. package/dist-types/components/menu/src/LionToolbar.d.ts +0 -8
  166. package/dist-types/components/menu/src/LionToolbar.d.ts.map +0 -1
  167. package/dist-types/components/menu/src/LionTree.d.ts +0 -445
  168. package/dist-types/components/menu/src/LionTree.d.ts.map +0 -1
  169. package/dist-types/components/menu/src/MultiLevelListMixin.d.ts +0 -493
  170. package/dist-types/components/menu/src/MultiLevelListMixin.d.ts.map +0 -1
  171. package/dist-types/components/menu/src/utils/isInView.d.ts +0 -9
  172. package/dist-types/components/menu/src/utils/isInView.d.ts.map +0 -1
  173. package/dist-types/components/menu/src/utils/listItemInteractions.d.ts +0 -42
  174. package/dist-types/components/menu/src/utils/listItemInteractions.d.ts.map +0 -1
  175. package/dist-types/components/menu/src/utils/uuid.d.ts +0 -2
  176. package/dist-types/components/menu/src/utils/uuid.d.ts.map +0 -1
  177. package/dist-types/components/menu/test/lion-menu.test.d.ts +0 -2
  178. package/dist-types/components/menu/test/lion-menu.test.d.ts.map +0 -1
  179. package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts +0 -13
  180. package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts.map +0 -1
  181. package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts +0 -238
  182. package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts.map +0 -1
  183. package/dist-types/components/navigation-bar/src/types.d.ts +0 -85
  184. package/dist-types/components/navigation-bar/src/types.d.ts.map +0 -1
  185. package/dist-types/exports/define/lion-item.d.ts +0 -2
  186. package/dist-types/exports/define/lion-item.d.ts.map +0 -1
  187. package/dist-types/exports/define/lion-menu-overlay.d.ts +0 -2
  188. package/dist-types/exports/define/lion-menu-overlay.d.ts.map +0 -1
  189. package/dist-types/exports/define/lion-menu.d.ts +0 -2
  190. package/dist-types/exports/define/lion-menu.d.ts.map +0 -1
  191. package/dist-types/exports/define/lion-navigation-bar.d.ts +0 -2
  192. package/dist-types/exports/define/lion-navigation-bar.d.ts.map +0 -1
  193. package/dist-types/exports/define/lion-toolbar.d.ts +0 -2
  194. package/dist-types/exports/define/lion-toolbar.d.ts.map +0 -1
  195. package/dist-types/exports/define/lion-tree.d.ts +0 -2
  196. package/dist-types/exports/define/lion-tree.d.ts.map +0 -1
  197. package/dist-types/exports/menu.d.ts +0 -7
  198. package/dist-types/exports/menu.d.ts.map +0 -1
  199. package/dist-types/exports/navigation-bar.d.ts +0 -2
  200. package/dist-types/exports/navigation-bar.d.ts.map +0 -1
  201. package/docs/components/menu/api-table.md +0 -450
  202. package/docs/components/menu/applyMenuDemoStyles.js +0 -173
  203. package/docs/components/menu/extensions.md +0 -216
  204. package/docs/components/menu/index.md +0 -13
  205. package/docs/components/menu/overview.md +0 -422
  206. package/exports/define/lion-item.js +0 -3
  207. package/exports/define/lion-menu-overlay.js +0 -3
  208. package/exports/define/lion-menu.js +0 -3
  209. package/exports/define/lion-navigation-bar.js +0 -3
  210. package/exports/define/lion-toolbar.js +0 -3
  211. package/exports/define/lion-tree.js +0 -3
  212. package/exports/menu.js +0 -6
  213. package/exports/navigation-bar.js +0 -1
  214. package/menu.js +0 -6
  215. package/navigation-bar.js +0 -1
@@ -1,142 +0,0 @@
1
- import { LitElement } from 'lit';
2
- import { expect, html, fixture, unsafeStatic, defineCE } from '@open-wc/testing';
3
- import { InteractiveListMixin } from '../src/InteractiveListMixin.js';
4
-
5
- class InteractiveListClass extends InteractiveListMixin(LitElement) {}
6
-
7
- /**
8
- * @typedef {import('../types/InteractiveListMixinTypes.js').InteractiveListItemRole} InteractiveListItemRole
9
- */
10
-
11
- /** @type {InteractiveListItemRole[]} */
12
- const supportedRoles = [
13
- 'menuitem',
14
- 'menuitemcheckbox',
15
- 'menuitemradio',
16
- 'option',
17
- 'treeitem',
18
- 'radio',
19
- 'checkbox',
20
- ];
21
-
22
- /**
23
- * @typedef {Object} TestConfig
24
- * @property {string} tagString
25
- */
26
-
27
- /**
28
- * @param {TestConfig} [customConfig]
29
- */
30
- export function runInteractiveListMixinSuite(customConfig) {
31
- const cfg = {
32
- tagString: customConfig?.tagString || defineCE(InteractiveListClass),
33
- };
34
-
35
- const { tagString } = cfg;
36
- const tag = unsafeStatic(tagString);
37
-
38
- describe('InteractiveListMixin', () => {
39
- it(`supports items with role="${supportedRoles.join('|')}"`, async () => {
40
- const el = await fixture(html`
41
- <${tag} name="foo">
42
- ${supportedRoles.map(role => html` <div role="${role}"></div> `)}
43
- </${tag}>
44
- `);
45
- // @ts-ignore - test element with InteractiveListMixin properties
46
- expect(el.listItems.length).to.equal(supportedRoles.length);
47
- supportedRoles.forEach((role, i) => {
48
- // @ts-ignore - test element with InteractiveListMixin properties
49
- expect(el.listItems[i].getAttribute('role')).to.equal(role);
50
- });
51
- });
52
-
53
- it('moves elements to a private [slot=list] for optimal DX and a11y', async () => {
54
- const el = await fixture(html`
55
- <${tag} name="foo">
56
- <div role="menuitem" id="item1">Item 1</div>
57
- <div role="menuitem" id="item2">Item 2</div>
58
- </${tag}>
59
- `);
60
- // @ts-ignore - test element with InteractiveListMixin properties
61
- const listSlotNode = Array.from(el.children).find(c => c.slot === 'list');
62
- // @ts-ignore - accessing children property
63
- const listItemEls = Array.from(listSlotNode.children);
64
- // @ts-ignore - test element with InteractiveListMixin properties
65
- expect(listItemEls.includes(el.listItems[0])).to.be.true;
66
- // @ts-ignore - test element with InteractiveListMixin properties
67
- expect(listItemEls.includes(el.listItems[1])).to.be.true;
68
- });
69
-
70
- it('inherits from DisclosureMixin', async () => {});
71
-
72
- describe('Active mode', async () => {
73
- it('supports "activedescendant" pattern', async () => {
74
- const el = await fixture(html`
75
- <${tag} name="foo" ._activeMode="${'activedescendant'}">
76
- <div role="menuitem" id="item1">Item 1</div>
77
- <div role="menuitem" id="item2">Item 2</div>
78
- </${tag}>
79
- `);
80
- // @ts-ignore - test element with InteractiveListMixin properties
81
- el.checkedIndex = 0;
82
- // @ts-ignore - test element with InteractiveListMixin properties
83
- const listSlotNode = Array.from(el.children).find(c => c.slot === 'list');
84
-
85
- // @ts-ignore - test element with InteractiveListMixin properties
86
- // @ts-ignore - test element with InteractiveListMixin properties
87
- expect(el.listItems[0].hasAttribute('id')).to.be.true;
88
- // @ts-ignore - test element with InteractiveListMixin properties
89
- expect(el.listItems[1].hasAttribute('id')).to.be.true;
90
- expect(listSlotNode?.hasAttribute('aria-activedescendant')).to.be.false;
91
- // @ts-ignore - test element with InteractiveListMixin properties
92
- el.activeIndex = 1;
93
- expect(listSlotNode?.hasAttribute('aria-activedescendant')).to.be.true;
94
- });
95
-
96
- it('supports "roving-tabindex" pattern', async () => {
97
- const el = await fixture(html`
98
- <${tag} name="foo" ._activeMode="${'roving-tabindex'}">
99
- <div role="menuitem" id="item1">Item 1</div>
100
- <div role="menuitem" id="item2">Item 2</div>
101
- </${tag}>
102
- `);
103
-
104
- // @ts-ignore - test element with InteractiveListMixin properties
105
- el.activeIndex = 0;
106
- // @ts-ignore - test element with InteractiveListMixin properties
107
- expect(el.listItems[0].getAttribute('tabindex')).to.equal('0');
108
- // @ts-ignore - test element with InteractiveListMixin properties
109
- expect(el.listItems[1].getAttribute('tabindex')).to.equal('-1');
110
-
111
- // @ts-ignore - test element with InteractiveListMixin properties
112
- el.activeIndex = 1;
113
- // @ts-ignore - test element with InteractiveListMixin properties
114
- expect(el.listItems[0].getAttribute('tabindex')).to.equal('-1');
115
- // @ts-ignore - test element with InteractiveListMixin properties
116
- expect(el.listItems[1].getAttribute('tabindex')).to.equal('0');
117
-
118
- // @ts-ignore - test element with InteractiveListMixin properties
119
- el.activeIndex = 1;
120
- // @ts-ignore - test element with InteractiveListMixin properties
121
- expect(document.activeElement).to.equal(el.listItems[1]);
122
- });
123
- });
124
-
125
- // Copy tests from ListboxMixin. Later, make this mixin a fundament of the ListboxMixin
126
-
127
- // orientation
128
- // multipleChoice
129
- // selectionFollowsFocus
130
- // rotateKeyboardNavigation
131
- // noPreselect
132
- // _scrollTargetNode
133
-
134
- describe('Widget extensions', () => {
135
- it('can be extended to [role=listbox]', async () => {});
136
- it('can be extended to [role=menu]', async () => {});
137
- it('can be extended to [role=menubar]', async () => {});
138
- it('can be extended to [role=toolbar]', async () => {});
139
- it('can be extended to [role=tree]', async () => {});
140
- });
141
- });
142
- }
@@ -1,82 +0,0 @@
1
- import { Constructor } from '@open-wc/dedupe-mixin';
2
- import { LitElement } from 'lit';
3
- import { SlotHost } from '../../core/types/SlotMixinTypes.js';
4
- import { DisabledHost } from '../../core/types/DisabledMixinTypes.js';
5
-
6
- export type InteractiveListItemRole =
7
- | 'menuitem'
8
- | 'menuitemcheckbox'
9
- | 'menuitemradio'
10
- | 'option'
11
- | 'treeitem'
12
- | 'radio'
13
- | 'checkbox';
14
-
15
- export declare class InteractiveListHost {
16
- /**
17
- * When true, will synchronize activedescendant and selected element on
18
- * arrow key navigation.
19
- * This behavior can usually be seen on <select> on the Windows platform.
20
- * Note that this behavior cannot be used when multiple-choice is true.
21
- * See: https://www.w3.org/TR/wai-aria-practices/#kbd_selection_follows_focus
22
- */
23
- public selectionFollowsFocus: Boolean;
24
- /**
25
- * Will give first option active state when navigated to the next option from
26
- * last option.
27
- */
28
- public rotateKeyboardNavigation: Boolean;
29
- /**
30
- * Informs screen reader and affects keyboard navigation.
31
- * By default 'vertical'
32
- */
33
- public orientation: 'vertical' | 'horizontal';
34
-
35
- public hasNoDefaultSelected: boolean;
36
-
37
- public singleOption: boolean;
38
-
39
- public checkedIndex: number | number[];
40
-
41
- public activeIndex: number;
42
-
43
- public listItems: HTMLElement[];
44
-
45
- public setCheckedIndex(index: number): void;
46
-
47
- protected _scrollTargetNode: HTMLElement;
48
-
49
- protected _listNode: HTMLElement;
50
-
51
- // private __setupListboxNode(): void;
52
-
53
- protected _getPreviousEnabledOption(currentIndex: number, offset?: number): number;
54
-
55
- protected _getNextEnabledOption(currentIndex: number, offset?: number): number;
56
-
57
- protected _onListKeyDown(ev: KeyboardEvent): void;
58
-
59
- protected _onListKeyUp(ev: KeyboardEvent): void;
60
-
61
- // protected _setupListboxNode(): void;
62
-
63
- // protected _teardownListboxNode(): void;
64
-
65
- protected _onListClick(ev: MouseEvent): void;
66
-
67
- // protected _setupListboxInteractions(): void;
68
-
69
- // protected _onChildActiveChanged(ev: Event): void;
70
- }
71
-
72
- export declare function InteractiveListHostImplementation<T extends Constructor<LitElement>>(
73
- superclass: T,
74
- ): T &
75
- Constructor<InteractiveListHost> &
76
- InteractiveListHost &
77
- Constructor<DisabledHost> &
78
- typeof DisabledHost &
79
- Constructor<SlotHost> &
80
- typeof SlotHost;
81
-
82
- export type InteractiveListMixin = typeof InteractiveListHostImplementation;
@@ -1 +0,0 @@
1
- N.B. api is very very beta
@@ -1,422 +0,0 @@
1
- // @ts-nocheck
2
- /* eslint-disable class-methods-use-this */
3
- import { LitElement, html, css } from 'lit';
4
- import { LionMenuHybrid } from '@lion/ui/menu.js';
5
- import { ScopedElementsMixin } from '../../core/src/ScopedElementsMixin.js';
6
-
7
- /**
8
- * @typedef {import('./types.js').NavBarResponsiveMode} NavBarResponsiveMode
9
- * @typedef {import('./types.js').MenuItem} MenuItem
10
- * @typedef {import('./types.js').CtaLink} CtaLink
11
- * @typedef {import('./types.js').Logo} Logo
12
- * @typedef {import('./types.js').LevelConfig} LevelConfig
13
- */
14
-
15
- export class LionNavigationBar extends ScopedElementsMixin(LitElement) {
16
- static get properties() {
17
- return {
18
- responsiveMode: { type: String, reflect: true, attribute: 'responsive-mode' },
19
- // logo: { type: String },
20
- menuItems: { type: Array },
21
- menuSupportItems: { type: Array },
22
- ctaPrimary: { type: Object },
23
- ctaSecondary: { type: Object },
24
- suggestions: { type: Array },
25
- showOnMobile: { type: Array, attribute: 'show-on-mobile', reflect: true },
26
-
27
- _levelCfg: { state: true },
28
- };
29
- }
30
-
31
- static get scopedElements() {
32
- return {
33
- // 'lion-menu-overlay': LionMenuOverlay,
34
- 'lion-menu-hybrid': LionMenuHybrid,
35
- };
36
- }
37
-
38
- static get styles() {
39
- return [
40
- css`
41
- /** specific styles */
42
-
43
- :host([responsive-mode='desktop']) [data-has-full-width-flyout] > [slot='list'] {
44
- /** make sure that we give the right styles */
45
- position: relative;
46
- }
47
-
48
- :host([responsive-mode='desktop'])
49
- [data-has-full-width-flyout]
50
- > [slot='list']
51
- [level='2']
52
- > [slot='list'] {
53
- position: absolute;
54
- width: 100%;
55
- left: 0;
56
- right: 0;
57
- min-height: 300px;
58
- padding: 1em;
59
- background-color: white;
60
- border: 1px solid gray;
61
- box-sizing: border-box;
62
- }
63
-
64
- :host([responsive-mode='desktop']) [level='3'] > [slot='list'] {
65
- position: absolute;
66
- left: 33.333%;
67
- width: 33.333%;
68
- top: 0;
69
- padding: 1em;
70
- background-color: white;
71
- box-sizing: border-box;
72
- height: 100%;
73
- }
74
-
75
- :host([responsive-mode='mobile']) nav {
76
- border: 1px solid black;
77
- display: block;
78
- position: fixed;
79
- top: 0;
80
- bottom: 0;
81
- right: 0;
82
- min-width: 500px;
83
- }
84
-
85
- :host([responsive-mode='mobile']) [level][opened] > [slot='list'] {
86
- left: 0;
87
- width: 100%;
88
- top: 0;
89
- box-sizing: border-box;
90
- }
91
-
92
- :host([responsive-mode='mobile']) [slot='list'] {
93
- position: relative;
94
- padding: 1em;
95
- background-color: white;
96
- }
97
-
98
- :host([responsive-mode='mobile']) [level='2'] > [slot='list'],
99
- :host([responsive-mode='mobile']) [level='3'] > [slot='list'] {
100
- position: absolute;
101
- left: 100%;
102
- top: 0;
103
- box-sizing: border-box;
104
- padding-bottom: 200%;
105
- }
106
-
107
- :host([responsive-mode='mobile']) nav {
108
- display: flex;
109
- flex-direction: column;
110
- /* height: 100%;
111
- justify-content: space-between; */
112
- }
113
-
114
- /* :host([responsive-mode='mobile']) .cta-items {
115
- position: absolute;
116
- bottom: 0;
117
- width: 100%;
118
- padding: 1em;
119
- background-color: white;
120
- box-sizing: border-box;
121
- } */
122
-
123
- :host([responsive-mode='mobile']) .logo-and-close {
124
- padding: 1em;
125
- }
126
- `,
127
- ];
128
- }
129
-
130
- constructor() {
131
- super();
132
-
133
- /** @type {Logo} */
134
- this.logo = { type: 'ing', alt: 'ING homepage', href: '/' };
135
- /** @type {MenuItem[]} */
136
- this.menuSupportItems = [];
137
- // /**
138
- // * @type {string[]}
139
- // * @description Choose which items to show on mobile when in default mode, maximum of two. Possible values: 'search', 'ctaPrimary', 'ctaSecondary', 'avatarMenu'
140
- // */
141
- // this.showOnMobile = [];
142
- /**
143
- * @type {CtaLink}
144
- */
145
- // @ts-ignore
146
- this.ctaPrimary = {};
147
- /**
148
- * @type {CtaLink}
149
- */
150
- // @ts-ignore
151
- this.ctaSecondary = {};
152
- /** @type {MenuItem[]} */
153
- this.menuItems = [];
154
- // /** @type {Boolean} */
155
- // this.searchDisabled = false;
156
- this.breakpointMin = 1400; // force desktop
157
- /** @type {string[]} */
158
- this.suggestions = [];
159
-
160
- this.prefilledSuggestion = '';
161
-
162
- const mql = window.matchMedia(`(width <= ${this.breakpointMin}px)`);
163
- /** @type {NavBarResponsiveMode} */
164
- this.responsiveMode = mql.matches ? 'mobile' : 'desktop';
165
- this._levelCfg = this._getLevelCfg(this.responsiveMode);
166
- this._levelSecondaryCfg = this._getSecondaryLevelCfg(this.responsiveMode);
167
-
168
- mql.addEventListener('change', () => {
169
- this.responsiveMode = mql.matches ? 'mobile' : 'desktop';
170
- this._levelCfg = this._getLevelCfg(this.responsiveMode);
171
- this._levelSecondaryCfg = this._getSecondaryLevelCfg(this.responsiveMode);
172
- });
173
-
174
- this.#storeLatestFocusedElementId();
175
- }
176
-
177
- /**
178
- * @param {NavBarResponsiveMode} responsiveMode
179
- */
180
- _getLevelCfg(responsiveMode) {
181
- // N.B. we're fighting some of the overlay configs provided by LionMenuOverlay here,
182
- // the idea is to take over all of that when depending on LionMenu, after removing LonMenuOverlay and LionMenuHybrid components altogether.
183
-
184
- if (responsiveMode === 'mobile') {
185
- return {
186
- l1: {
187
- isBar: false,
188
- openableConfig: {
189
- // We want to do the absolute positioning ourselves, popper is not suited for this...
190
- placementMode: 'custom',
191
- isOpenable: false,
192
- hidesOnOutsideClick: false,
193
- inheritsReferenceWidth: 'none',
194
- },
195
- },
196
- l2: {
197
- openableConfig: {
198
- // We want disclosure behavior
199
- placementMode: 'custom',
200
- hidesOnOutsideClick: false,
201
- inheritsReferenceWidth: 'none',
202
- },
203
- },
204
- l3: {
205
- openableConfig: {
206
- // We want disclosure behavior
207
- placementMode: 'custom',
208
- hidesOnOutsideClick: false,
209
- inheritsReferenceWidth: 'none',
210
- },
211
- },
212
- };
213
- }
214
-
215
- return {
216
- l1: {
217
- isBar: true,
218
- hasFullWidthFlyout: true,
219
- openableConfig: {
220
- // We want disclosure behavior
221
- placementMode: 'custom',
222
- // N.B. we don't have an invoker...
223
- isOpenable: false,
224
- inheritsReferenceWidth: 'none',
225
- focusContentOnOpen: true,
226
- },
227
- },
228
- l2: {
229
- openableConfig: {
230
- // We want disclosure behavior
231
- placementMode: 'custom',
232
- hidesOnOutsideClick: true,
233
- hidesOnEscape: true,
234
- inheritsReferenceWidth: 'none',
235
- focusContentOnOpen: true,
236
- },
237
- },
238
- l3: {
239
- openableConfig: {
240
- // We want disclosure behavior
241
- placementMode: 'custom',
242
- inheritsReferenceWidth: 'none',
243
- focusContentOnOpen: true,
244
- // TODO: implement in OverlayController
245
- hideVisually: true,
246
- },
247
- },
248
- };
249
- }
250
-
251
- _getSecondaryLevelCfg(responsiveMode) {
252
- if (responsiveMode === 'mobile') {
253
- return {
254
- l1: {
255
- isBar: true,
256
- },
257
- l2: {
258
- isBar: false,
259
- },
260
- };
261
- }
262
-
263
- return {
264
- l1: {
265
- isBar: true,
266
- },
267
- l2: {
268
- isBar: false,
269
- },
270
- };
271
- }
272
-
273
- /** @type {string | null} */
274
- #latestFocusedElementId = null;
275
-
276
- #storeLatestFocusedElementId() {
277
- this.addEventListener('focusin', ({ target }) => {
278
- // @ts-ignore
279
- this.#latestFocusedElementId = target.id;
280
- });
281
- }
282
-
283
- #syncLatestFocusedElementForNewResponsiveMode() {
284
- // We might show/hide or rerender some elements (with same ids) in different positions in the DOM.
285
- // As these are physically different elements, we must move focus (as otherwise it would be reset to body)
286
- if (!this.#latestFocusedElementId) return;
287
- const newFocusedElement = this.shadowRoot?.querySelector(`#${this.#latestFocusedElementId}`);
288
- if (newFocusedElement instanceof HTMLElement) {
289
- newFocusedElement.focus();
290
- }
291
- }
292
-
293
- /**
294
- * @param {import("./types.js").MenuItem}
295
- * @param {number} level
296
- */
297
- _getId(menuItem, level) {
298
- if (menuItem.id) return menuItem.id;
299
- const title = menuItem.title || menuItem.label || 'item';
300
- return `${
301
- Number.isInteger(level) ? `l${level}-${title}` : title
302
- }-${Math.random().toString(16).slice(2)}`;
303
- }
304
-
305
- /**
306
- * @param {import('lit').PropertyValues} changedProperties
307
- */
308
- updated(changedProperties) {
309
- if (changedProperties.has('responsiveMode')) {
310
- this._levelCfg = this._getLevelCfg(this.responsiveMode);
311
- this.#syncLatestFocusedElementForNewResponsiveMode();
312
- }
313
- }
314
-
315
- render() {
316
- return html`
317
- <nav>
318
- <div class="nav-header">
319
- <div class="logo-and-close">
320
- <a href="${this.logo.href || '#'}">
321
- <img src="${this.logo.src || ''}" alt="${this.logo.alt || ''}" />
322
- </a>
323
- ${this.responsiveMode === 'mobile'
324
- ? html`<button data-close data-level="1">✖️</button>`
325
- : ''}
326
- </div>
327
- ${this._searchTemplate()}
328
- </div>
329
- <div class="nav-body">
330
- ${this._menulevelTemplate(this.menuSupportItems, 1, '')}
331
- ${this.responsiveMode === 'desktop'
332
- ? this._ctasTemplate(this.ctaPrimary, this.ctaSecondary)
333
- : ''}
334
- ${this._menulevelTemplate(this.menuItems, 1, '')}
335
- </div>
336
- ${this.responsiveMode === 'mobile'
337
- ? html`<div class="nav-footer">
338
- ${this._ctasTemplate(this.ctaPrimary, this.ctaSecondary)}
339
- </div>`
340
- : ''}
341
- </nav>
342
- `;
343
- }
344
-
345
- /**
346
- * @param {string[]} suggestions
347
- * @returns {import('lit').TemplateResult}
348
- */
349
- _searchTemplate(suggestions = this.suggestions, prefilledSuggestion = this.prefilledSuggestion) {
350
- return html` <form role="search">
351
- <input
352
- type="search"
353
- list="search-list"
354
- placeholder="What are you looking for?"
355
- .value="${prefilledSuggestion}"
356
- />
357
- <datalist id="search-list">
358
- ${suggestions.map(suggestion => html`<option value="${suggestion}"></option>`)}
359
- </datalist>
360
- <input type="submit" value="Search" />
361
- </form>`;
362
- }
363
-
364
- /**
365
- * @param {CtaLink} ctaPrimary
366
- * @param {CtaLink} ctaSecondary
367
- * @returns {import('lit').TemplateResult}
368
- */
369
- _ctasTemplate(ctaPrimary, ctaSecondary) {
370
- return html`<div class="cta-items">
371
- ${ctaSecondary?.href
372
- ? html`<div class="cta-secondary">
373
- <a id="${this._getId(ctaSecondary)}" href="${ctaSecondary.href}"
374
- >${ctaSecondary.label}
375
- </a>
376
- </div>`
377
- : ''}
378
- ${ctaPrimary?.href
379
- ? html`<div class="cta-primary">
380
- <a id="${this._getId(ctaPrimary)}" href="${ctaPrimary.href}"> ${ctaPrimary.label}</a>
381
- </div>`
382
- : ''}
383
- </div>`;
384
- }
385
-
386
- /**
387
- * @param {MenuItem[]} menuItemsForLevel
388
- * @param {number} level
389
- * @returns {import('lit').TemplateResult}
390
- */
391
- _menulevelTemplate(menuItemsForLevel, level, prevText = '') {
392
- // @ts-ignore
393
- const cfgForLevel = this._levelCfg[`l${level}`];
394
-
395
- return html`<lion-menu-hybrid
396
- .config="${cfgForLevel.openableConfig || {}}"
397
- .bar="${cfgForLevel.isBar}"
398
- ?data-has-full-width-flyout="${cfgForLevel.hasFullWidthFlyout}"
399
- ._activeMode="${'tabbable-disclosure'}"
400
- >
401
- ${level > 1 && this.responsiveMode === 'mobile'
402
- ? html` <div role="listitem">
403
- <button data-close data-level="${level}">&lt; ${prevText}</button>
404
- </div>`
405
- : ''}
406
- ${menuItemsForLevel.map(
407
- menuItem => html`
408
- <div role="listitem">
409
- ${menuItem.sub
410
- ? html` <button id="${this._getId(menuItem)}" data-invoker>${menuItem.title}</button>
411
- ${menuItem.sub
412
- ? this._menulevelTemplate(menuItem.sub, level + 1, menuItem.title)
413
- : ''}`
414
- : html` <a id="${this._getId(menuItem)}" href="${menuItem.link || ''}"
415
- >${menuItem.title}</a
416
- >`}
417
- </div>
418
- `,
419
- )}
420
- </lion-menu-hybrid>`;
421
- }
422
- }
@@ -1,41 +0,0 @@
1
- /**
2
- * @typedef {'mobile' | 'desktop'} NavBarResponsiveMode
3
- * Responsive mode for the navigation bar
4
- */
5
-
6
- /**
7
- * @typedef {Object} MenuItem
8
- * Navigation menu item
9
- * @property {string} [id] - Optional unique identifier
10
- * @property {string} title - Display title of the menu item
11
- * @property {string} [link] - URL for the menu item (for leaf items)
12
- * @property {MenuItem[]} [sub] - Submenu items (for parent items)
13
- */
14
-
15
- /**
16
- * @typedef {Object} CtaLink
17
- * Call-to-action link
18
- * @property {string} [id] - Optional unique identifier
19
- * @property {string} [href] - URL for the CTA
20
- * @property {string} [text] - Display text for the CTA
21
- * @property {string} [label] - Accessible label for the CTA
22
- */
23
-
24
- /**
25
- * @typedef {Object} Logo
26
- * Logo configuration for the navigation bar
27
- * @property {string} type - Logo type (e.g., 'ing')
28
- * @property {string} alt - Alternative text for the logo
29
- * @property {string} href - URL the logo links to
30
- * @property {string} [src] - Optional custom logo source URL
31
- */
32
-
33
- /**
34
- * @typedef {Object} LevelConfig
35
- * Configuration for a menu level
36
- * @property {boolean} [isBar] - Whether this level is displayed as a bar
37
- * @property {boolean} [hasFullWidthFlyout] - Whether this level has a full-width flyout
38
- * @property {object} [openableConfig] - Configuration for the openable overlay
39
- */
40
-
41
- export {};