@api-client/ui 0.5.32 → 0.5.34

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 (45) hide show
  1. package/build/src/core/ApplicationRoute.d.ts.map +1 -1
  2. package/build/src/core/ApplicationRoute.js +3 -0
  3. package/build/src/core/ApplicationRoute.js.map +1 -1
  4. package/build/src/elements/navigation/internals/Navigation.d.ts +68 -0
  5. package/build/src/elements/navigation/internals/Navigation.d.ts.map +1 -0
  6. package/build/src/elements/navigation/internals/Navigation.js +205 -0
  7. package/build/src/elements/navigation/internals/Navigation.js.map +1 -0
  8. package/build/src/elements/navigation/internals/Navigation.styles.d.ts +3 -0
  9. package/build/src/elements/navigation/internals/Navigation.styles.d.ts.map +1 -0
  10. package/build/src/elements/navigation/internals/Navigation.styles.js +24 -0
  11. package/build/src/elements/navigation/internals/Navigation.styles.js.map +1 -0
  12. package/build/src/elements/navigation/internals/NavigationItem.d.ts +62 -2
  13. package/build/src/elements/navigation/internals/NavigationItem.d.ts.map +1 -1
  14. package/build/src/elements/navigation/internals/NavigationItem.js +88 -20
  15. package/build/src/elements/navigation/internals/NavigationItem.js.map +1 -1
  16. package/build/src/elements/navigation/ui-navigation.d.ts +11 -0
  17. package/build/src/elements/navigation/ui-navigation.d.ts.map +1 -0
  18. package/build/src/elements/navigation/ui-navigation.js +27 -0
  19. package/build/src/elements/navigation/ui-navigation.js.map +1 -0
  20. package/build/src/md/input/Input.d.ts +2 -0
  21. package/build/src/md/input/Input.d.ts.map +1 -1
  22. package/build/src/types/aria.d.ts +28 -0
  23. package/build/src/types/aria.d.ts.map +1 -0
  24. package/build/src/types/aria.js +2 -0
  25. package/build/src/types/aria.js.map +1 -0
  26. package/build/src/types/role.d.ts +1 -16
  27. package/build/src/types/role.d.ts.map +1 -1
  28. package/build/src/types/role.js.map +1 -1
  29. package/build/test/elements/navigation/Navigation.test.d.ts +3 -0
  30. package/build/test/elements/navigation/Navigation.test.d.ts.map +1 -0
  31. package/build/test/elements/navigation/Navigation.test.js +113 -0
  32. package/build/test/elements/navigation/Navigation.test.js.map +1 -0
  33. package/demo/elements/index.html +2 -0
  34. package/demo/elements/navigation/navigation.html +20 -0
  35. package/demo/elements/navigation/navigation.ts +45 -0
  36. package/package.json +1 -1
  37. package/src/core/ApplicationRoute.ts +4 -1
  38. package/src/elements/navigation/internals/Navigation.styles.ts +24 -0
  39. package/src/elements/navigation/internals/Navigation.ts +181 -0
  40. package/src/elements/navigation/internals/NavigationItem.ts +79 -5
  41. package/src/elements/navigation/ui-navigation.ts +15 -0
  42. package/src/types/aria.ts +141 -0
  43. package/src/types/role.ts +1 -129
  44. package/test/elements/navigation/Navigation.test.ts +120 -0
  45. package/tsconfig.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ApplicationRoute.d.ts","sourceRoot":"","sources":["../../../src/core/ApplicationRoute.ts"],"names":[],"mappings":"AAkDA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,SAAS,CAWhH;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,YAAY,SAAK,GAAG,MAAM,CAUlD;AAkBD,wBAAgB,UAAU,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAIrD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAItE;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAIlE"}
1
+ {"version":3,"file":"ApplicationRoute.d.ts","sourceRoot":"","sources":["../../../src/core/ApplicationRoute.ts"],"names":[],"mappings":"AAqDA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,SAAS,CAWhH;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,YAAY,SAAK,GAAG,MAAM,CAUlD;AAkBD,wBAAgB,UAAU,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAIrD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAItE;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAIlE"}
@@ -32,6 +32,9 @@ function parseParams(pattern, uri) {
32
32
  if (groups) {
33
33
  Object.keys(groups).forEach((key) => {
34
34
  let value = groups[key];
35
+ if (value === undefined) {
36
+ return;
37
+ }
35
38
  if (value[0] === '/') {
36
39
  value = value.substring(1);
37
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ApplicationRoute.js","sourceRoot":"","sources":["../../../src/core/ApplicationRoute.ts"],"names":[],"mappings":"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","sourcesContent":["const compiled = new Map<string, RegExp>()\n\n/**\n * @param value The pattern to evaluate\n */\nfunction getPattern(value: string): RegExp {\n if (compiled.has(value)) {\n return compiled.get(value) as RegExp\n }\n const result = new RegExp(`^${value}$`)\n compiled.set(value, result)\n return result\n}\n\n/**\n * @param uri The path value of the current URL.\n * @param pattern The pattern to evaluate\n */\nfunction testRoute(uri: string, pattern: string): boolean {\n return getPattern(pattern).test(uri)\n}\n\n/**\n * @param pattern The pattern to evaluate\n * @param uri The path value of the current URL.\n */\nfunction parseParams(pattern: string, uri: string): Record<string, string | string[]> | undefined {\n const r = getPattern(pattern)\n const match = r.exec(uri)\n if (!match) {\n return undefined\n }\n const { groups } = match\n const result: Record<string, string | string[]> = {}\n if (groups) {\n Object.keys(groups).forEach((key) => {\n let value = groups[key] as string\n if (value[0] === '/') {\n value = value.substring(1)\n }\n if (value.includes('/')) {\n result[key] = value.split('/').map((i) => decodeURIComponent(i))\n } else {\n result[key] = decodeURIComponent(value)\n }\n })\n }\n return result\n}\n\n/**\n * Reads params from the route for given patterns.\n * @param patterns The list of patterns to consider\n * @param route The current route\n * @returns A list of read parameters or undefined when there's no matching route or params.\n *\n * @example\n *\n * ```typescript\n * const patterns = ['/my/path/:id']\n * const route = '/my/path/1234'\n * const params = readRouteParams(patterns, route)\n * // -> { id: '1234' }\n * ```\n */\nexport function readRouteParams(patterns: string[], route: string): Record<string, string | string[]> | undefined {\n for (const pattern of patterns) {\n if (!testRoute(route, pattern)) {\n continue\n }\n const params = parseParams(pattern, route)\n if (params) {\n return params\n }\n }\n return undefined\n}\n\n/**\n * Reads the current route as everything that is past the `#`\n * @param defaultRoute The route that would be considered a default route for the activity.\n * @returns The current route.\n */\nexport function getRoute(defaultRoute = ''): string {\n const url = new URL(window.location.href)\n let path = url.hash.replace('#', '')\n if (!path) {\n path = defaultRoute\n }\n if (!path.startsWith('/')) {\n path = `/${path}`\n }\n return path\n}\n\nfunction createHash(...route: string[]): string {\n const atoms: string[] = []\n for (const atom of route) {\n if (atom.includes('/')) {\n atoms.push(...atom.split('/').filter((i) => !!i))\n } else {\n atoms.push(atom)\n }\n }\n let hash = atoms.map(encodeURIComponent).join('/')\n if (!hash.startsWith('/')) {\n hash = `/${hash}`\n }\n return hash\n}\n\nexport function buildRoute(...route: string[]): string {\n const url = new URL(window.location.href)\n url.hash = createHash(...route)\n return url.toString()\n}\n\n/**\n * Navigates to an internal route.\n *\n * @param route Optional route params to add to the hash part of the url.\n */\nexport function navigateScreen(...route: string[]): void {\n window.location.href = buildRoute(...route)\n}\n\n/**\n * Navigates to another application.\n *\n * @param htmlFile The relative location of the target HTML file.\n * @param route Optional route params to add to the has part of the url.\n */\nexport function navigateApp(htmlFile: string, ...route: string[]): void {\n const url = new URL(htmlFile, window.location.href)\n url.hash = createHash(...route)\n window.location.href = url.toString()\n}\n\n/**\n * Navigates to another application.\n *\n * @param htmlFile The relative location of the target HTML file.\n * @param route Optional route params to add to the has part of the url.\n */\nexport function openApp(htmlFile: string, ...route: string[]): void {\n const url = new URL(htmlFile, window.location.href)\n url.hash = createHash(...route)\n window.open(url.toString(), '_blank')\n}\n"]}
1
+ {"version":3,"file":"ApplicationRoute.js","sourceRoot":"","sources":["../../../src/core/ApplicationRoute.ts"],"names":[],"mappings":"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","sourcesContent":["const compiled = new Map<string, RegExp>()\n\n/**\n * @param value The pattern to evaluate\n */\nfunction getPattern(value: string): RegExp {\n if (compiled.has(value)) {\n return compiled.get(value) as RegExp\n }\n const result = new RegExp(`^${value}$`)\n compiled.set(value, result)\n return result\n}\n\n/**\n * @param uri The path value of the current URL.\n * @param pattern The pattern to evaluate\n */\nfunction testRoute(uri: string, pattern: string): boolean {\n return getPattern(pattern).test(uri)\n}\n\n/**\n * @param pattern The pattern to evaluate\n * @param uri The path value of the current URL.\n */\nfunction parseParams(pattern: string, uri: string): Record<string, string | string[]> | undefined {\n const r = getPattern(pattern)\n const match = r.exec(uri)\n if (!match) {\n return undefined\n }\n const { groups } = match\n const result: Record<string, string | string[]> = {}\n if (groups) {\n Object.keys(groups).forEach((key) => {\n let value = groups[key] as string | undefined\n if (value === undefined) {\n return\n }\n if (value[0] === '/') {\n value = value.substring(1)\n }\n if (value.includes('/')) {\n result[key] = value.split('/').map((i) => decodeURIComponent(i))\n } else {\n result[key] = decodeURIComponent(value)\n }\n })\n }\n return result\n}\n\n/**\n * Reads params from the route for given patterns.\n * @param patterns The list of patterns to consider\n * @param route The current route\n * @returns A list of read parameters or undefined when there's no matching route or params.\n *\n * @example\n *\n * ```typescript\n * const patterns = ['/my/path/:id']\n * const route = '/my/path/1234'\n * const params = readRouteParams(patterns, route)\n * // -> { id: '1234' }\n * ```\n */\nexport function readRouteParams(patterns: string[], route: string): Record<string, string | string[]> | undefined {\n for (const pattern of patterns) {\n if (!testRoute(route, pattern)) {\n continue\n }\n const params = parseParams(pattern, route)\n if (params) {\n return params\n }\n }\n return undefined\n}\n\n/**\n * Reads the current route as everything that is past the `#`\n * @param defaultRoute The route that would be considered a default route for the activity.\n * @returns The current route.\n */\nexport function getRoute(defaultRoute = ''): string {\n const url = new URL(window.location.href)\n let path = url.hash.replace('#', '')\n if (!path) {\n path = defaultRoute\n }\n if (!path.startsWith('/')) {\n path = `/${path}`\n }\n return path\n}\n\nfunction createHash(...route: string[]): string {\n const atoms: string[] = []\n for (const atom of route) {\n if (atom.includes('/')) {\n atoms.push(...atom.split('/').filter((i) => !!i))\n } else {\n atoms.push(atom)\n }\n }\n let hash = atoms.map(encodeURIComponent).join('/')\n if (!hash.startsWith('/')) {\n hash = `/${hash}`\n }\n return hash\n}\n\nexport function buildRoute(...route: string[]): string {\n const url = new URL(window.location.href)\n url.hash = createHash(...route)\n return url.toString()\n}\n\n/**\n * Navigates to an internal route.\n *\n * @param route Optional route params to add to the hash part of the url.\n */\nexport function navigateScreen(...route: string[]): void {\n window.location.href = buildRoute(...route)\n}\n\n/**\n * Navigates to another application.\n *\n * @param htmlFile The relative location of the target HTML file.\n * @param route Optional route params to add to the has part of the url.\n */\nexport function navigateApp(htmlFile: string, ...route: string[]): void {\n const url = new URL(htmlFile, window.location.href)\n url.hash = createHash(...route)\n window.location.href = url.toString()\n}\n\n/**\n * Navigates to another application.\n *\n * @param htmlFile The relative location of the target HTML file.\n * @param route Optional route params to add to the has part of the url.\n */\nexport function openApp(htmlFile: string, ...route: string[]): void {\n const url = new URL(htmlFile, window.location.href)\n url.hash = createHash(...route)\n window.open(url.toString(), '_blank')\n}\n"]}
@@ -0,0 +1,68 @@
1
+ import { LitElement, type TemplateResult } from 'lit';
2
+ import type NavigationItem from './NavigationItem.js';
3
+ import { AriaCurrent } from '../../../types/aria.js';
4
+ /**
5
+ * NavigationList
6
+ *
7
+ * A semantic, accessible navigation container for `ui-navigation-item` elements.
8
+ * Handles keyboard navigation (roving tabindex), focus management, and ARIA roles.
9
+ *
10
+ * ## Usage Example
11
+ *
12
+ * ```html
13
+ * <ui-navigation aria-label="Main navigation" current="page">
14
+ * <ui-navigation-item selected>
15
+ * <span slot="icon" aria-hidden="true">🏠</span>
16
+ * Home
17
+ * </ui-navigation-item>
18
+ * <ui-navigation-item>
19
+ * <span slot="icon" aria-hidden="true">🔍</span>
20
+ * Search
21
+ * </ui-navigation-item>
22
+ * <ui-navigation-item>
23
+ * <span slot="icon" aria-hidden="true">📁</span>
24
+ * Files
25
+ * </ui-navigation-item>
26
+ * <ui-navigation-item iconOnly disabled aria-disabled="true" tabindex="-1">
27
+ * <span slot="icon" aria-hidden="true">⚙️</span>
28
+ * </ui-navigation-item>
29
+ * </ui-navigation>
30
+ * ```
31
+ *
32
+ * @slot - Place `ui-navigation-item` elements as direct children.
33
+ * @fires select - Dispatched when an item is selected via click or keyboard.
34
+ * The `detail` object contains the selected `item`.
35
+ */
36
+ export default class Navigation extends LitElement {
37
+ /**
38
+ * Orientation of the navigation: 'horizontal' or 'vertical'.
39
+ * @attribute
40
+ */
41
+ accessor orientation: 'horizontal' | 'vertical';
42
+ /**
43
+ * The current item in the navigation, used for ARIA attributes.
44
+ * Can be 'page', 'step', 'location', 'date', 'time', 'true', 'false', or ''.
45
+ * @attribute
46
+ */
47
+ accessor current: AriaCurrent;
48
+ /**
49
+ * Query all ui-navigation-item children
50
+ */
51
+ accessor _items: NavigationItem[];
52
+ render(): TemplateResult;
53
+ constructor();
54
+ firstUpdated(): void;
55
+ private _onSlotChange;
56
+ /**
57
+ * Sets the initial `tabindex` for the items. The first selected item,
58
+ * or the first item if none are selected, receives `tabindex="0"`.
59
+ * All other items receive `tabindex="-1"`.
60
+ */
61
+ private _setTabIndexes;
62
+ private _getEnabledItems;
63
+ private _onClick;
64
+ private _selectItem;
65
+ private _updateFocus;
66
+ private _onKeyDown;
67
+ }
68
+ //# sourceMappingURL=Navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Navigation.d.ts","sourceRoot":"","sources":["../../../../../src/elements/navigation/internals/Navigation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,KAAK,CAAA;AAE3D,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,UAAU;IAChD;;;OAGG;IACwC,QAAQ,CAAC,WAAW,EAAE,YAAY,GAAG,UAAU,CAAa;IAEvG;;;;OAIG;IACwC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAK;IAE7E;;OAEG;IACuC,QAAQ,CAAC,MAAM,EAAG,cAAc,EAAE,CAAA;IAEnE,MAAM,IAAI,cAAc;;IAcxB,YAAY;IAIrB,OAAO,CAAC,aAAa,CAEpB;IAED;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,QAAQ,CAMf;IAED,OAAO,CAAC,WAAW;IA0BnB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,UAAU;CAyCnB"}
@@ -0,0 +1,205 @@
1
+ import { __esDecorate, __runInitializers } from "tslib";
2
+ import { html, LitElement } from 'lit';
3
+ import { property, queryAssignedElements } from 'lit/decorators.js';
4
+ let Navigation = (() => {
5
+ let _classSuper = LitElement;
6
+ let _orientation_decorators;
7
+ let _orientation_initializers = [];
8
+ let _orientation_extraInitializers = [];
9
+ let _current_decorators;
10
+ let _current_initializers = [];
11
+ let _current_extraInitializers = [];
12
+ let __items_decorators;
13
+ let __items_initializers = [];
14
+ let __items_extraInitializers = [];
15
+ return class Navigation extends _classSuper {
16
+ static {
17
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
18
+ _orientation_decorators = [property({ type: String, reflect: true })];
19
+ _current_decorators = [property({ type: String, reflect: true })];
20
+ __items_decorators = [queryAssignedElements({ flatten: true })];
21
+ __esDecorate(this, null, _orientation_decorators, { kind: "accessor", name: "orientation", static: false, private: false, access: { has: obj => "orientation" in obj, get: obj => obj.orientation, set: (obj, value) => { obj.orientation = value; } }, metadata: _metadata }, _orientation_initializers, _orientation_extraInitializers);
22
+ __esDecorate(this, null, _current_decorators, { kind: "accessor", name: "current", static: false, private: false, access: { has: obj => "current" in obj, get: obj => obj.current, set: (obj, value) => { obj.current = value; } }, metadata: _metadata }, _current_initializers, _current_extraInitializers);
23
+ __esDecorate(this, null, __items_decorators, { kind: "accessor", name: "_items", static: false, private: false, access: { has: obj => "_items" in obj, get: obj => obj._items, set: (obj, value) => { obj._items = value; } }, metadata: _metadata }, __items_initializers, __items_extraInitializers);
24
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
25
+ }
26
+ #orientation_accessor_storage = __runInitializers(this, _orientation_initializers, 'vertical'
27
+ /**
28
+ * The current item in the navigation, used for ARIA attributes.
29
+ * Can be 'page', 'step', 'location', 'date', 'time', 'true', 'false', or ''.
30
+ * @attribute
31
+ */
32
+ );
33
+ /**
34
+ * Orientation of the navigation: 'horizontal' or 'vertical'.
35
+ * @attribute
36
+ */
37
+ get orientation() { return this.#orientation_accessor_storage; }
38
+ set orientation(value) { this.#orientation_accessor_storage = value; }
39
+ #current_accessor_storage = (__runInitializers(this, _orientation_extraInitializers), __runInitializers(this, _current_initializers, ''
40
+ /**
41
+ * Query all ui-navigation-item children
42
+ */
43
+ ));
44
+ /**
45
+ * The current item in the navigation, used for ARIA attributes.
46
+ * Can be 'page', 'step', 'location', 'date', 'time', 'true', 'false', or ''.
47
+ * @attribute
48
+ */
49
+ get current() { return this.#current_accessor_storage; }
50
+ set current(value) { this.#current_accessor_storage = value; }
51
+ #_items_accessor_storage = (__runInitializers(this, _current_extraInitializers), __runInitializers(this, __items_initializers, void 0));
52
+ /**
53
+ * Query all ui-navigation-item children
54
+ */
55
+ get _items() { return this.#_items_accessor_storage; }
56
+ set _items(value) { this.#_items_accessor_storage = value; }
57
+ render() {
58
+ return html `
59
+ <nav aria-label="${this.getAttribute('aria-label') || 'Navigation'}">
60
+ <slot @slotchange="${this._onSlotChange}"></slot>
61
+ </nav>
62
+ `;
63
+ }
64
+ constructor() {
65
+ super();
66
+ this.addEventListener('keydown', this._onKeyDown.bind(this));
67
+ this.addEventListener('click', this._onClick.bind(this));
68
+ }
69
+ firstUpdated() {
70
+ this._setTabIndexes();
71
+ }
72
+ _onSlotChange = (__runInitializers(this, __items_extraInitializers), () => {
73
+ this._setTabIndexes();
74
+ });
75
+ /**
76
+ * Sets the initial `tabindex` for the items. The first selected item,
77
+ * or the first item if none are selected, receives `tabindex="0"`.
78
+ * All other items receive `tabindex="-1"`.
79
+ */
80
+ _setTabIndexes() {
81
+ const items = this._getEnabledItems();
82
+ if (!items.length) {
83
+ return;
84
+ }
85
+ items.forEach((item) => {
86
+ if (item.disabled) {
87
+ return;
88
+ }
89
+ item.setAttribute('tabindex', item.selected ? '0' : '-1');
90
+ });
91
+ }
92
+ _getEnabledItems() {
93
+ return (this._items || []).filter((item) => !item.disabled);
94
+ }
95
+ _onClick = (e) => {
96
+ const target = e.target;
97
+ const item = target.closest('ui-navigation-item');
98
+ if (item && this._items.includes(item)) {
99
+ this._selectItem(item);
100
+ }
101
+ };
102
+ _selectItem(itemToSelect) {
103
+ if (itemToSelect.disabled) {
104
+ return;
105
+ }
106
+ this._items.forEach((item) => {
107
+ item.selected = item === itemToSelect;
108
+ if (item.hasAttribute('aria-current')) {
109
+ item.removeAttribute('aria-current');
110
+ }
111
+ });
112
+ if (this.current) {
113
+ itemToSelect.setAttribute('aria-current', this.current);
114
+ }
115
+ this._updateFocus(itemToSelect);
116
+ this.dispatchEvent(new CustomEvent('select', {
117
+ detail: { item: itemToSelect },
118
+ bubbles: false,
119
+ composed: true,
120
+ }));
121
+ }
122
+ _updateFocus(itemToFocus) {
123
+ this._setTabIndexes();
124
+ itemToFocus.focus();
125
+ }
126
+ _onKeyDown(e) {
127
+ const items = this._getEnabledItems();
128
+ if (!items.length) {
129
+ return;
130
+ }
131
+ const activeElement = this.getRootNode().activeElement;
132
+ if (!activeElement) {
133
+ return;
134
+ }
135
+ // Find which of our items is the host of the active element.
136
+ // This is necessary because of focus delegation in ui-navigation-item.
137
+ const activeItem = items.find((item) => item === activeElement || item.shadowRoot?.contains(activeElement));
138
+ if (!activeItem) {
139
+ return;
140
+ }
141
+ if (e.key === 'Enter' || e.key === ' ') {
142
+ e.preventDefault();
143
+ this._selectItem(activeItem);
144
+ return;
145
+ }
146
+ const idx = items.indexOf(activeItem);
147
+ let nextIdx = idx;
148
+ if (this.orientation === 'horizontal') {
149
+ if (e.key === 'ArrowRight')
150
+ nextIdx = (idx + 1) % items.length;
151
+ if (e.key === 'ArrowLeft')
152
+ nextIdx = (idx - 1 + items.length) % items.length;
153
+ }
154
+ else {
155
+ if (e.key === 'ArrowDown')
156
+ nextIdx = (idx + 1) % items.length;
157
+ if (e.key === 'ArrowUp')
158
+ nextIdx = (idx - 1 + items.length) % items.length;
159
+ }
160
+ if (e.key === 'Home')
161
+ nextIdx = 0;
162
+ if (e.key === 'End')
163
+ nextIdx = items.length - 1;
164
+ if (nextIdx !== idx) {
165
+ items[nextIdx].focus();
166
+ items.forEach((item, i) => item.setAttribute('tabindex', i === nextIdx ? '0' : '-1'));
167
+ e.preventDefault();
168
+ }
169
+ }
170
+ };
171
+ })();
172
+ /**
173
+ * NavigationList
174
+ *
175
+ * A semantic, accessible navigation container for `ui-navigation-item` elements.
176
+ * Handles keyboard navigation (roving tabindex), focus management, and ARIA roles.
177
+ *
178
+ * ## Usage Example
179
+ *
180
+ * ```html
181
+ * <ui-navigation aria-label="Main navigation" current="page">
182
+ * <ui-navigation-item selected>
183
+ * <span slot="icon" aria-hidden="true">🏠</span>
184
+ * Home
185
+ * </ui-navigation-item>
186
+ * <ui-navigation-item>
187
+ * <span slot="icon" aria-hidden="true">🔍</span>
188
+ * Search
189
+ * </ui-navigation-item>
190
+ * <ui-navigation-item>
191
+ * <span slot="icon" aria-hidden="true">📁</span>
192
+ * Files
193
+ * </ui-navigation-item>
194
+ * <ui-navigation-item iconOnly disabled aria-disabled="true" tabindex="-1">
195
+ * <span slot="icon" aria-hidden="true">⚙️</span>
196
+ * </ui-navigation-item>
197
+ * </ui-navigation>
198
+ * ```
199
+ *
200
+ * @slot - Place `ui-navigation-item` elements as direct children.
201
+ * @fires select - Dispatched when an item is selected via click or keyboard.
202
+ * The `detail` object contains the selected `item`.
203
+ */
204
+ export default Navigation;
205
+ //# sourceMappingURL=Navigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Navigation.js","sourceRoot":"","sources":["../../../../../src/elements/navigation/internals/Navigation.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, type TemplateResult } from 'lit'\nimport { property, queryAssignedElements } from 'lit/decorators.js'\nimport type NavigationItem from './NavigationItem.js'\nimport { AriaCurrent } from '../../../types/aria.js'\n\n/**\n * NavigationList\n *\n * A semantic, accessible navigation container for `ui-navigation-item` elements.\n * Handles keyboard navigation (roving tabindex), focus management, and ARIA roles.\n *\n * ## Usage Example\n *\n * ```html\n * <ui-navigation aria-label=\"Main navigation\" current=\"page\">\n * <ui-navigation-item selected>\n * <span slot=\"icon\" aria-hidden=\"true\">🏠</span>\n * Home\n * </ui-navigation-item>\n * <ui-navigation-item>\n * <span slot=\"icon\" aria-hidden=\"true\">🔍</span>\n * Search\n * </ui-navigation-item>\n * <ui-navigation-item>\n * <span slot=\"icon\" aria-hidden=\"true\">📁</span>\n * Files\n * </ui-navigation-item>\n * <ui-navigation-item iconOnly disabled aria-disabled=\"true\" tabindex=\"-1\">\n * <span slot=\"icon\" aria-hidden=\"true\">⚙️</span>\n * </ui-navigation-item>\n * </ui-navigation>\n * ```\n *\n * @slot - Place `ui-navigation-item` elements as direct children.\n * @fires select - Dispatched when an item is selected via click or keyboard.\n * The `detail` object contains the selected `item`.\n */\nexport default class Navigation extends LitElement {\n /**\n * Orientation of the navigation: 'horizontal' or 'vertical'.\n * @attribute\n */\n @property({ type: String, reflect: true }) accessor orientation: 'horizontal' | 'vertical' = 'vertical'\n\n /**\n * The current item in the navigation, used for ARIA attributes.\n * Can be 'page', 'step', 'location', 'date', 'time', 'true', 'false', or ''.\n * @attribute\n */\n @property({ type: String, reflect: true }) accessor current: AriaCurrent = ''\n\n /**\n * Query all ui-navigation-item children\n */\n @queryAssignedElements({ flatten: true }) accessor _items!: NavigationItem[]\n\n override render(): TemplateResult {\n return html`\n <nav aria-label=\"${this.getAttribute('aria-label') || 'Navigation'}\">\n <slot @slotchange=\"${this._onSlotChange}\"></slot>\n </nav>\n `\n }\n\n constructor() {\n super()\n this.addEventListener('keydown', this._onKeyDown.bind(this))\n this.addEventListener('click', this._onClick.bind(this))\n }\n\n override firstUpdated() {\n this._setTabIndexes()\n }\n\n private _onSlotChange = () => {\n this._setTabIndexes()\n }\n\n /**\n * Sets the initial `tabindex` for the items. The first selected item,\n * or the first item if none are selected, receives `tabindex=\"0\"`.\n * All other items receive `tabindex=\"-1\"`.\n */\n private _setTabIndexes() {\n const items = this._getEnabledItems()\n if (!items.length) {\n return\n }\n items.forEach((item) => {\n if (item.disabled) {\n return\n }\n item.setAttribute('tabindex', item.selected ? '0' : '-1')\n })\n }\n\n private _getEnabledItems(): NavigationItem[] {\n return (this._items || []).filter((item) => !item.disabled)\n }\n\n private _onClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n const item = target.closest('ui-navigation-item')\n if (item && this._items.includes(item)) {\n this._selectItem(item)\n }\n }\n\n private _selectItem(itemToSelect: NavigationItem) {\n if (itemToSelect.disabled) {\n return\n }\n\n this._items.forEach((item) => {\n item.selected = item === itemToSelect\n if (item.hasAttribute('aria-current')) {\n item.removeAttribute('aria-current')\n }\n })\n\n if (this.current) {\n itemToSelect.setAttribute('aria-current', this.current)\n }\n this._updateFocus(itemToSelect)\n\n this.dispatchEvent(\n new CustomEvent('select', {\n detail: { item: itemToSelect },\n bubbles: false,\n composed: true,\n })\n )\n }\n\n private _updateFocus(itemToFocus: NavigationItem) {\n this._setTabIndexes()\n itemToFocus.focus()\n }\n\n private _onKeyDown(e: KeyboardEvent) {\n const items = this._getEnabledItems()\n if (!items.length) {\n return\n }\n\n const activeElement = (this.getRootNode() as Document | ShadowRoot).activeElement\n if (!activeElement) {\n return\n }\n\n // Find which of our items is the host of the active element.\n // This is necessary because of focus delegation in ui-navigation-item.\n const activeItem = items.find((item) => item === activeElement || item.shadowRoot?.contains(activeElement))\n if (!activeItem) {\n return\n }\n\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this._selectItem(activeItem)\n return\n }\n\n const idx = items.indexOf(activeItem)\n let nextIdx = idx\n if (this.orientation === 'horizontal') {\n if (e.key === 'ArrowRight') nextIdx = (idx + 1) % items.length\n if (e.key === 'ArrowLeft') nextIdx = (idx - 1 + items.length) % items.length\n } else {\n if (e.key === 'ArrowDown') nextIdx = (idx + 1) % items.length\n if (e.key === 'ArrowUp') nextIdx = (idx - 1 + items.length) % items.length\n }\n if (e.key === 'Home') nextIdx = 0\n if (e.key === 'End') nextIdx = items.length - 1\n if (nextIdx !== idx) {\n items[nextIdx].focus()\n items.forEach((item, i) => item.setAttribute('tabindex', i === nextIdx ? '0' : '-1'))\n e.preventDefault()\n }\n }\n}\n"]}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("lit").CSSResult;
2
+ export default _default;
3
+ //# sourceMappingURL=Navigation.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Navigation.styles.d.ts","sourceRoot":"","sources":["../../../../../src/elements/navigation/internals/Navigation.styles.ts"],"names":[],"mappings":";AAEA,wBAqBC"}
@@ -0,0 +1,24 @@
1
+ import { css } from 'lit';
2
+ export default css `
3
+ :host {
4
+ display: block;
5
+ outline: none;
6
+ }
7
+
8
+ nav {
9
+ display: flex;
10
+ gap: 8px;
11
+ list-style: none;
12
+ padding: 0;
13
+ margin: 0;
14
+ }
15
+
16
+ :host([orientation='horizontal']) nav {
17
+ flex-direction: row;
18
+ }
19
+
20
+ :host([orientation='vertical']) nav {
21
+ flex-direction: column;
22
+ }
23
+ `;
24
+ //# sourceMappingURL=Navigation.styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Navigation.styles.js","sourceRoot":"","sources":["../../../../../src/elements/navigation/internals/Navigation.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;CAqBjB,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport default css`\n :host {\n display: block;\n outline: none;\n }\n\n nav {\n display: flex;\n gap: 8px;\n list-style: none;\n padding: 0;\n margin: 0;\n }\n\n :host([orientation='horizontal']) nav {\n flex-direction: row;\n }\n\n :host([orientation='vertical']) nav {\n flex-direction: column;\n }\n`\n"]}
@@ -1,12 +1,67 @@
1
1
  import { TemplateResult } from 'lit';
2
2
  import { UiElement } from '../../../md/UiElement.js';
3
+ /**
4
+ * NavigationItem
5
+ *
6
+ * An element to be placed inside a navigation bar. This component is designed for use with navigation bars and supports
7
+ * icon-only, selected, and disabled states. It is built with accessibility and composability in mind.
8
+ *
9
+ * ## Accessibility
10
+ *
11
+ * - Uses a native `<button>` element for proper semantics and keyboard accessibility.
12
+ * - The icon is marked with `role="presentation"` to indicate it is decorative.
13
+ * - Focus ring and ripple effects are included for visual feedback.
14
+ *
15
+ * ## Usage Example
16
+ *
17
+ * ### Accessible Navigation Example
18
+ *
19
+ * ```html
20
+ * <nav aria-label="Main navigation">
21
+ * <ul style="display: flex; gap: 8px; list-style: none; padding: 0; margin: 0;">
22
+ * <li>
23
+ * <navigation-item selected aria-current="page">
24
+ * <span slot="icon" aria-hidden="true">🏠</span>
25
+ * Home
26
+ * </navigation-item>
27
+ * </li>
28
+ * <li>
29
+ * <navigation-item>
30
+ * <span slot="icon" aria-hidden="true">🔍</span>
31
+ * Search
32
+ * </navigation-item>
33
+ * </li>
34
+ * <li>
35
+ * <navigation-item>
36
+ * <span slot="icon" aria-hidden="true">📁</span>
37
+ * Files
38
+ * </navigation-item>
39
+ * </li>
40
+ * <li>
41
+ * <navigation-item iconOnly disabled aria-disabled="true" tabindex="-1">
42
+ * <span slot="icon" aria-hidden="true">⚙️</span>
43
+ * </navigation-item>
44
+ * </li>
45
+ * </ul>
46
+ * </nav>
47
+ * ```
48
+ *
49
+ * This example demonstrates a horizontal navigation bar using semantic HTML. Each `navigation-item`
50
+ * is placed inside a list item for proper structure. The `aria-current="page"` attribute marks the current
51
+ * page, and `aria-disabled="true"` with `tabindex="-1"` ensures the disabled item is not focusable.
52
+ * Icons use `aria-hidden="true"` for accessibility.
53
+ *
54
+ * @slot icon - A slot for the icon element
55
+ * @slot - The default slot for the label
56
+ */
3
57
  export default class NavigationItem extends UiElement {
4
58
  static shadowRootOptions: ShadowRootInit;
59
+ get disabled(): boolean;
5
60
  /**
6
- * When set, the button is a disabled state.
61
+ * When set, the navigation item is in a disabled state.
7
62
  * @attribute
8
63
  */
9
- accessor disabled: boolean;
64
+ set disabled(value: boolean);
10
65
  /**
11
66
  * Whether the navigation item is selected.
12
67
  * @attribute
@@ -18,6 +73,11 @@ export default class NavigationItem extends UiElement {
18
73
  * @attribute
19
74
  */
20
75
  accessor iconOnly: boolean;
76
+ /**
77
+ * The reference of the navigation item to the target.
78
+ * @attribute
79
+ */
80
+ accessor href: string | undefined;
21
81
  /**
22
82
  * Determines when the element has an icon in the "icon" slot.
23
83
  */
@@ -1 +1 @@
1
- {"version":3,"file":"NavigationItem.d.ts","sourceRoot":"","sources":["../../../../../src/elements/navigation/internals/NavigationItem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,MAAM,KAAK,CAAA;AAG1C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAEpD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,SAAS;IACnD,OAAgB,iBAAiB,EAAE,cAAc,CAGhD;IAED;;;OAGG;IACyC,QAAQ,CAAC,QAAQ,UAAQ;IAErE;;;OAGG;IACyC,QAAQ,CAAC,QAAQ,UAAQ;IACrE;;;;OAIG;IACyC,QAAQ,CAAC,QAAQ,UAAQ;IAErE;;OAEG;IACM,SAAS,CAAC,QAAQ,CAAC,OAAO,UAAQ;IAE3C;;OAEG;IACH,SAAS,CAAC,oBAAoB,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;cAK3B,MAAM,IAAI,cAAc;IAiB3C,SAAS,CAAC,UAAU,IAAI,cAAc;CAKvC"}
1
+ {"version":3,"file":"NavigationItem.d.ts","sourceRoot":"","sources":["../../../../../src/elements/navigation/internals/NavigationItem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAW,MAAM,KAAK,CAAA;AAInD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAGpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,SAAS;IACnD,OAAgB,iBAAiB,EAAE,cAAc,CAGhD;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;;OAGG;IACH,IACI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAI1B;IAED;;;OAGG;IACyC,QAAQ,CAAC,QAAQ,UAAQ;IACrE;;;;OAIG;IACyC,QAAQ,CAAC,QAAQ,UAAQ;IACrE;;;OAGG;IACwC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IAE5E;;OAEG;IACM,SAAS,CAAC,QAAQ,CAAC,OAAO,UAAQ;IAE3C;;OAEG;IACH,SAAS,CAAC,oBAAoB,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;cAK3B,MAAM,IAAI,cAAc;IAqB3C,SAAS,CAAC,UAAU,IAAI,cAAc;CAKvC"}