@nvidia-elements/core 2.0.1 → 2.0.3
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.
- package/CHANGELOG.md +45 -0
- package/README.md +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.132.0/helpers → _@oxc-project_runtime@0.133.0/helpers/esm}/decorate.js +1 -1
- package/dist/accordion/accordion2.js +5 -5
- package/dist/alert/alert-group2.js +2 -2
- package/dist/alert/alert2.js +2 -2
- package/dist/avatar/avatar-group2.js +1 -1
- package/dist/avatar/avatar.examples.js.map +1 -1
- package/dist/avatar/avatar.examples.json +1 -1
- package/dist/avatar/avatar2.js +2 -2
- package/dist/badge/badge2.js +2 -2
- package/dist/breadcrumb/breadcrumb2.js +2 -2
- package/dist/bundles/index.d.ts +6 -17
- package/dist/bundles/index.js +6 -6
- package/dist/button/button2.js +2 -2
- package/dist/button-group/button-group2.js +2 -2
- package/dist/card/card.examples.js.map +1 -1
- package/dist/card/card.examples.json +1 -1
- package/dist/card/card2.js +5 -5
- package/dist/chat-message/chat-message.d.ts +0 -2
- package/dist/chat-message/chat-message2.js +2 -2
- package/dist/chat-message/chat-message2.js.map +1 -1
- package/dist/checkbox/checkbox-group2.js +2 -2
- package/dist/checkbox/checkbox2.js +2 -2
- package/dist/color/color2.js +2 -2
- package/dist/combobox/combobox2.js +8 -8
- package/dist/copy-button/copy-button2.js +2 -2
- package/dist/custom-elements.json +155 -720
- package/dist/data.html.json +26 -3
- package/dist/data.snippets.json +27 -27
- package/dist/date/date2.js +2 -2
- package/dist/datetime/datetime2.js +2 -2
- package/dist/dialog/dialog-footer2.js +2 -2
- package/dist/dialog/dialog-header2.js +2 -2
- package/dist/dialog/dialog2.js +2 -2
- package/dist/divider/divider2.js +2 -2
- package/dist/dot/dot2.js +2 -2
- package/dist/drawer/drawer-content2.js +2 -2
- package/dist/drawer/drawer-footer2.js +2 -2
- package/dist/drawer/drawer-header2.js +2 -2
- package/dist/drawer/drawer2.js +2 -2
- package/dist/dropdown/dropdown-footer2.js +2 -2
- package/dist/dropdown/dropdown-header2.js +2 -2
- package/dist/dropdown/dropdown2.js +2 -2
- package/dist/dropdown-group/dropdown-group.d.ts +0 -1
- package/dist/dropdown-group/dropdown-group.js +2 -2
- package/dist/dropdown-group/dropdown-group.js.map +1 -1
- package/dist/dropzone/dropzone.d.ts +0 -1
- package/dist/dropzone/dropzone2.js +2 -2
- package/dist/dropzone/dropzone2.js.map +1 -1
- package/dist/file/file2.js +1 -1
- package/dist/format-datetime/format-datetime.d.ts +1 -0
- package/dist/format-datetime/format-datetime2.js +2 -2
- package/dist/format-datetime/format-datetime2.js.map +1 -1
- package/dist/format-number/format-number.d.ts +1 -0
- package/dist/format-number/format-number2.js +2 -2
- package/dist/format-number/format-number2.js.map +1 -1
- package/dist/format-relative-time/format-relative-time.d.ts +1 -0
- package/dist/format-relative-time/format-relative-time2.js +6 -3
- package/dist/format-relative-time/format-relative-time2.js.map +1 -1
- package/dist/forms/control/control.js +1 -1
- package/dist/forms/control/control.js.map +1 -1
- package/dist/forms/control/control2.js +39 -21
- package/dist/forms/control/control2.js.map +1 -1
- package/dist/forms/control-group/control-group.js +1 -1
- package/dist/forms/control-group/control-group.js.map +1 -1
- package/dist/forms/control-group/control-group2.js +2 -2
- package/dist/forms/control-group/control-group2.js.map +1 -1
- package/dist/forms/control-message/control-message2.js +2 -2
- package/dist/forms/utils/states.d.ts +6 -3
- package/dist/forms/utils/states.js +40 -32
- package/dist/forms/utils/states.js.map +1 -1
- package/dist/grid/cell/cell2.js +1 -1
- package/dist/grid/column/column2.js +2 -2
- package/dist/grid/footer/footer2.js +2 -2
- package/dist/grid/grid2.js +2 -2
- package/dist/grid/header/header2.js +2 -2
- package/dist/grid/placeholder/placeholder2.js +1 -1
- package/dist/grid/row/row2.js +2 -2
- package/dist/icon/icon2.js +3 -3
- package/dist/icon-button/icon-button2.js +2 -2
- package/dist/index.js +1 -1
- package/dist/input/input-group2.js +1 -1
- package/dist/input/input2.js +2 -2
- package/dist/internal/controllers/keynav-grid.controller.js +22 -18
- package/dist/internal/controllers/keynav-grid.controller.js.map +1 -1
- package/dist/internal/controllers/keynav-list.controller.d.ts +1 -0
- package/dist/internal/controllers/keynav-list.controller.js +6 -1
- package/dist/internal/controllers/keynav-list.controller.js.map +1 -1
- package/dist/internal/controllers/type-native-popover.controller.js +70 -40
- package/dist/internal/controllers/type-native-popover.controller.js.map +1 -1
- package/dist/internal/index.d.ts +0 -9
- package/dist/internal/index.js +20 -29
- package/dist/internal/services/global.service.js +1 -1
- package/dist/internal/services/log.service.js +1 -1
- package/dist/internal/services/log.service.js.map +1 -1
- package/dist/internal/types/index.d.ts +3 -0
- package/dist/internal/types/index.js.map +1 -1
- package/dist/internal/utils/dom.d.ts +1 -1
- package/dist/internal/utils/dom.js +71 -54
- package/dist/internal/utils/dom.js.map +1 -1
- package/dist/logo/logo2.js +2 -2
- package/dist/menu/menu-item2.js +2 -2
- package/dist/menu/menu2.js +2 -2
- package/dist/month/month2.js +2 -2
- package/dist/notification/notification-group2.js +2 -2
- package/dist/notification/notification2.js +2 -2
- package/dist/page/page-panel/page-panel-content2.js +1 -1
- package/dist/page/page-panel/page-panel-footer2.js +2 -2
- package/dist/page/page-panel/page-panel-header2.js +2 -2
- package/dist/page/page-panel/page-panel2.js +2 -2
- package/dist/page/page.examples.js.map +1 -1
- package/dist/page/page.examples.json +1 -1
- package/dist/page/page2.js +2 -2
- package/dist/page-header/page-header2.js +1 -1
- package/dist/page-loader/page-loader2.js +2 -2
- package/dist/pagination/pagination2.js +2 -2
- package/dist/panel/panel2.js +5 -5
- package/dist/password/password2.js +2 -2
- package/dist/preferences-input/preferences-input.js +1 -1
- package/dist/preferences-input/preferences-input.js.map +1 -1
- package/dist/preferences-input/preferences-input2.js +2 -2
- package/dist/progress-bar/progress-bar2.js +2 -2
- package/dist/progress-ring/progress-ring2.js +2 -2
- package/dist/progressive-filter-chip/progressive-filter-chip.examples.js.map +1 -1
- package/dist/progressive-filter-chip/progressive-filter-chip.examples.json +1 -1
- package/dist/progressive-filter-chip/progressive-filter-chip2.js +2 -2
- package/dist/pulse/pulse2.js +2 -2
- package/dist/radio/radio-group2.js +2 -2
- package/dist/radio/radio2.js +2 -2
- package/dist/range/range2.js +2 -2
- package/dist/resize-handle/resize-handle2.js +2 -2
- package/dist/search/search2.js +2 -2
- package/dist/select/select2.js +35 -21
- package/dist/select/select2.js.map +1 -1
- package/dist/skeleton/skeleton2.js +2 -2
- package/dist/sort-button/sort-button2.js +2 -2
- package/dist/sparkline/sparkline.utils.js +4 -2
- package/dist/sparkline/sparkline.utils.js.map +1 -1
- package/dist/sparkline/sparkline2.js +2 -2
- package/dist/star-rating/star-rating2.js +2 -2
- package/dist/steps/steps2.js +3 -3
- package/dist/switch/switch-group2.js +2 -2
- package/dist/switch/switch2.js +2 -2
- package/dist/tabs/tabs-group2.js +2 -2
- package/dist/tabs/tabs.examples.js.map +1 -1
- package/dist/tabs/tabs.examples.json +1 -1
- package/dist/tabs/tabs2.js +3 -3
- package/dist/tag/tag2.js +2 -2
- package/dist/textarea/textarea2.js +1 -1
- package/dist/time/time2.js +2 -2
- package/dist/toast/toast2.js +2 -2
- package/dist/toggletip/toggletip-footer.d.ts +1 -1
- package/dist/toggletip/toggletip-footer2.js +2 -2
- package/dist/toggletip/toggletip-footer2.js.map +1 -1
- package/dist/toggletip/toggletip-header.d.ts +1 -1
- package/dist/toggletip/toggletip-header2.js +2 -2
- package/dist/toggletip/toggletip-header2.js.map +1 -1
- package/dist/toggletip/toggletip2.js +2 -2
- package/dist/toolbar/toolbar2.js +2 -2
- package/dist/tooltip/tooltip2.js +2 -2
- package/dist/tree/tree-node2.js +2 -2
- package/dist/tree/tree2.js +2 -2
- package/dist/week/week2.js +2 -2
- package/package.json +8 -8
- package/dist/internal/controllers/state-active.controller.d.ts +0 -18
- package/dist/internal/controllers/state-active.controller.js +0 -29
- package/dist/internal/controllers/state-active.controller.js.map +0 -1
- package/dist/internal/controllers/state-current.controller.d.ts +0 -18
- package/dist/internal/controllers/state-current.controller.js +0 -28
- package/dist/internal/controllers/state-current.controller.js.map +0 -1
- package/dist/internal/controllers/state-disabled.controller.d.ts +0 -18
- package/dist/internal/controllers/state-disabled.controller.js +0 -20
- package/dist/internal/controllers/state-disabled.controller.js.map +0 -1
- package/dist/internal/controllers/state-pressed.controller.d.ts +0 -18
- package/dist/internal/controllers/state-pressed.controller.js +0 -20
- package/dist/internal/controllers/state-pressed.controller.js.map +0 -1
- package/dist/internal/controllers/type-button.controller.d.ts +0 -18
- package/dist/internal/controllers/type-button.controller.examples.js +0 -6
- package/dist/internal/controllers/type-button.controller.examples.js.map +0 -1
- package/dist/internal/controllers/type-button.controller.examples.json +0 -16
- package/dist/internal/controllers/type-button.controller.js +0 -21
- package/dist/internal/controllers/type-button.controller.js.map +0 -1
- package/dist/internal/controllers/type-command.controller.d.ts +0 -25
- package/dist/internal/controllers/type-command.controller.js +0 -38
- package/dist/internal/controllers/type-command.controller.js.map +0 -1
- package/dist/internal/controllers/type-interest.controller.d.ts +0 -23
- package/dist/internal/controllers/type-interest.controller.js +0 -51
- package/dist/internal/controllers/type-interest.controller.js.map +0 -1
- package/dist/internal/controllers/type-native-popover-trigger.controller.d.ts +0 -16
- package/dist/internal/controllers/type-native-popover-trigger.controller.js +0 -25
- package/dist/internal/controllers/type-native-popover-trigger.controller.js.map +0 -1
- package/dist/internal/controllers/type-submit.controller.d.ts +0 -22
- package/dist/internal/controllers/type-submit.controller.js +0 -49
- package/dist/internal/controllers/type-submit.controller.js.map +0 -1
|
@@ -3,66 +3,74 @@ import { ControlMessage as i } from "../control-message/control-message2.js";
|
|
|
3
3
|
//#region src/forms/utils/states.ts
|
|
4
4
|
var a = "input, select, selectmenu, textarea, [nve-control]";
|
|
5
5
|
function o(e, t) {
|
|
6
|
+
let n = [];
|
|
6
7
|
if (!e.input.form?.noValidate && !e.input.formNoValidate && !e.input.hasAttribute("formnovalidate")) {
|
|
7
|
-
|
|
8
|
-
let
|
|
9
|
-
e.input.validity?.valid && (e._internals.states.delete("invalid"), e._internals.states.add("valid"), e.status = null),
|
|
10
|
-
},
|
|
11
|
-
e.status = null, e._internals.states.delete("valid"), e._internals.states.delete("invalid"),
|
|
8
|
+
m(t);
|
|
9
|
+
let r = () => {
|
|
10
|
+
e.input.validity?.valid && (e._internals.states.delete("invalid"), e._internals.states.add("valid"), e.status = null), g(e, t);
|
|
11
|
+
}, i = () => {
|
|
12
|
+
e.status = null, e._internals.states.delete("valid"), e._internals.states.delete("invalid"), m(t);
|
|
12
13
|
};
|
|
13
|
-
e.input
|
|
14
|
-
e.input.checkValidity(),
|
|
15
|
-
}), e.input
|
|
16
|
-
|
|
17
|
-
}), e.input
|
|
18
|
-
t.find((e) => e.error) && (
|
|
19
|
-
}), e
|
|
14
|
+
n.push(f(e.input, "blur", () => {
|
|
15
|
+
e.input.checkValidity(), r();
|
|
16
|
+
}), f(e.input, "input", () => {
|
|
17
|
+
r();
|
|
18
|
+
}), f(e.input, "invalid", () => {
|
|
19
|
+
t.find((e) => e.error) && (m(t), h(e, t)), e.status = "error", e._internals.states.delete("valid"), e._internals.states.add("invalid");
|
|
20
|
+
}), f(e, "reset", i)), e.input.form && n.push(f(e.input.form, "reset", i));
|
|
20
21
|
}
|
|
21
|
-
e.shadowRoot
|
|
22
|
+
return n.push(f(e.shadowRoot, "slotchange", () => {
|
|
22
23
|
let t = Array.from(e.querySelectorAll(i.metadata.tag));
|
|
23
24
|
e._internals.states.delete("valid"), e._internals.states.delete("invalid"), t.find((e) => !e.hidden && (e.status === "error" || e.error)) ? e._internals.states.add("invalid") : e._internals.states.add("valid");
|
|
24
|
-
});
|
|
25
|
+
})), n;
|
|
25
26
|
}
|
|
26
27
|
function s(e) {
|
|
27
28
|
let t = [], r = e._internals.states;
|
|
28
|
-
return e.input.checked ? r.add("checked") : r.delete("checked"), e.input.indeterminate ? r.add("indeterminate") : r.delete("indeterminate"), e.input
|
|
29
|
+
return e.input.checked ? r.add("checked") : r.delete("checked"), e.input.indeterminate ? r.add("indeterminate") : r.delete("indeterminate"), t.push(...c(e)), t.push(n(e.input, "readonly", (e) => e === "" || e ? r.add("readonly") : r.delete("readonly")), n(e.input, "checked", () => e.input.checked ? r.add("checked") : r.delete("checked")), n(e.input, "disabled", (e) => e === "" || e ? r.add("disabled") : r.delete("disabled")), n(e.input, "indeterminate", () => e.input.indeterminate ? r.add("indeterminate") : r.delete("indeterminate"))), t;
|
|
30
|
+
}
|
|
31
|
+
function c(e) {
|
|
32
|
+
let t = [], n = e._internals.states;
|
|
33
|
+
return t.push(f(e.input, "focus", () => e._internals.states.add("focus")), f(e.input, "input", () => e._internals.states.add("dirty")), f(e.input, "blur", () => {
|
|
29
34
|
e._internals.states.add("touched"), e._internals.states.delete("focus");
|
|
30
|
-
}), e.input.getRootNode()
|
|
31
|
-
t.target.name === e.input?.name && (e.input.checked ?
|
|
32
|
-
}), e.input.form
|
|
35
|
+
}), f(e.input.getRootNode(), "change", (t) => {
|
|
36
|
+
t.target.name === e.input?.name && (e.input.checked ? n.add("checked") : n.delete("checked"));
|
|
37
|
+
})), e.input.form && t.push(f(e.input.form, "reset", () => {
|
|
33
38
|
e._internals.states.delete("touched"), e._internals.states.delete("dirty"), e._internals.states.delete("error"), e._internals.states.delete("success"), e.requestUpdate();
|
|
34
|
-
})
|
|
39
|
+
})), t;
|
|
35
40
|
}
|
|
36
|
-
function
|
|
37
|
-
return
|
|
41
|
+
function l(t) {
|
|
42
|
+
return u(t), e(t, "disabled", () => u(t));
|
|
38
43
|
}
|
|
39
|
-
function
|
|
44
|
+
function u(e) {
|
|
40
45
|
Array.from(e.inputs).find((e) => e.disabled) ? e._internals.states.add("disabled") : e._internals.states.delete("disabled");
|
|
41
46
|
}
|
|
42
|
-
function
|
|
43
|
-
|
|
47
|
+
function d(e, n) {
|
|
48
|
+
p(e, n.find((e) => !e.hidden));
|
|
44
49
|
let a = [];
|
|
45
50
|
return a.push(t(e, ["hidden", "status"], (t) => {
|
|
46
51
|
let n = t.target;
|
|
47
|
-
r(n, i) &&
|
|
48
|
-
})), e.shadowRoot
|
|
52
|
+
r(n, i) && p(e, n);
|
|
53
|
+
})), a.push(f(e.shadowRoot, "slotchange", () => {
|
|
49
54
|
let t = Array.from(e.querySelectorAll(i.metadata.tag)).find((e) => e.status && !e.hidden);
|
|
50
55
|
e._internals.states.delete("error"), e._internals.states.delete("success"), t && e._internals.states.add(t.status);
|
|
51
|
-
}), a;
|
|
56
|
+
})), a;
|
|
57
|
+
}
|
|
58
|
+
function f(e, t, n) {
|
|
59
|
+
return e.addEventListener(t, n), { disconnect: () => e.removeEventListener(t, n) };
|
|
52
60
|
}
|
|
53
|
-
function
|
|
61
|
+
function p(e, t) {
|
|
54
62
|
e._internals.states.delete("error"), e._internals.states.delete("success"), t?.status?.length && !t?.hidden && e._internals.states.add(t.status);
|
|
55
63
|
}
|
|
56
|
-
function
|
|
64
|
+
function m(e) {
|
|
57
65
|
e.filter((e) => e.hasAttribute("error")).forEach((e) => e.setAttribute("hidden", ""));
|
|
58
66
|
}
|
|
59
|
-
function
|
|
67
|
+
function h(e, t) {
|
|
60
68
|
t.find((t) => t.error && e.input.validity[t.error])?.removeAttribute("hidden");
|
|
61
69
|
}
|
|
62
|
-
function
|
|
70
|
+
function g(e, t) {
|
|
63
71
|
t.find((e) => e.error) && e.input.validity.valid && t.filter((t) => t.error && !e.input.validity[t.error]).forEach((e) => e.setAttribute("hidden", ""));
|
|
64
72
|
}
|
|
65
73
|
//#endregion
|
|
66
|
-
export { a as inputQuery,
|
|
74
|
+
export { a as inputQuery, l as setupControlGroupStates, s as setupControlStates, d as setupControlStatusStates, o as setupControlValidationStates };
|
|
67
75
|
|
|
68
76
|
//# sourceMappingURL=states.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"states.js","names":[],"sources":["../../../src/forms/utils/states.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n getAttributeChanges,\n getAttributeListChanges,\n getElementUpdate,\n matchesElementName\n} from '@nvidia-elements/core/internal';\nimport type { ControlGroup } from '../control-group/control-group.js';\nimport { ControlMessage } from '../control-message/control-message.js';\nimport type { Control } from '../control/control.js';\n\nexport const inputQuery = 'input, select, selectmenu, textarea, [nve-control]';\n\n/**\n * Adds validation states to custom element\n * :state(valid) form control is in a valid state\n * :state(invalid) form control is in a invalid state\n */\n// eslint-disable-next-line max-lines-per-function\nexport function setupControlValidationStates(control: Control, messages: ControlMessage[]) {\n if (\n !control.input.form?.noValidate &&\n !control.input.formNoValidate &&\n !control.input.hasAttribute('formnovalidate')\n ) {\n hideAllValidationMessages(messages);\n\n /**\n * updateValidityState() logic triggered by input blur() or input() change events\n */\n const updateValidityState = () => {\n if (control.input.validity?.valid) {\n control._internals.states.delete('invalid');\n control._internals.states.add('valid');\n control.status = null!;\n }\n\n hideInactiveValidationMessages(control, messages);\n };\n\n const resetValidityState = () => {\n control.status = null!;\n control._internals.states.delete('valid');\n control._internals.states.delete('invalid');\n hideAllValidationMessages(messages);\n };\n\n control.input.addEventListener('blur', () => {\n control.input.checkValidity();\n updateValidityState();\n });\n\n control.input.addEventListener('input', () => {\n updateValidityState();\n });\n\n control.input.addEventListener('invalid', () => {\n if (messages.find(m => m.error)) {\n hideAllValidationMessages(messages);\n showActiveValidationMessages(control, messages);\n }\n\n control.status = 'error';\n control._internals.states.delete('valid');\n control._internals.states.add('invalid');\n });\n\n control.addEventListener('reset', () => resetValidityState());\n control.input.form?.addEventListener('reset', () => resetValidityState());\n }\n\n control.shadowRoot!.addEventListener('slotchange', () => {\n const current = Array.from(control.querySelectorAll<ControlMessage>(ControlMessage.metadata.tag));\n control._internals.states.delete('valid');\n control._internals.states.delete('invalid');\n if (current.find(m => !m.hidden && (m.status === 'error' || m.error))) {\n control._internals.states.add('invalid');\n } else {\n control._internals.states.add('valid');\n }\n });\n}\n\n/**\n * Adds control interaction states to custom element\n * :state(checked) form control is in a checked state\n * :state(disabled) form control is in a disabled state\n * :state(readonly) form control is in a readonly state\n * :state(touched) form control received focus and then blurred\n * :state(dirty) user modified the form control\n */\nexport function setupControlStates(control: Control) {\n const observers: MutationObserver[] = [];\n const states = control._internals.states;\n control.input.checked ? states.add('checked') : states.delete('checked');\n control.input.indeterminate ? states.add('indeterminate') : states.delete('indeterminate');\n control.input.addEventListener('focus', () => control._internals.states.add('focus'));\n control.input.addEventListener('input', () => control._internals.states.add('dirty'));\n control.input.addEventListener('blur', () => {\n control._internals.states.add('touched');\n control._internals.states.delete('focus');\n });\n\n control.input.getRootNode().addEventListener('change', (e: Event) => {\n if ((e.target as HTMLInputElement).name === control.input?.name) {\n control.input.checked ? states.add('checked') : states.delete('checked');\n }\n });\n\n control.input.form?.addEventListener('reset', () => {\n control._internals.states.delete('touched');\n control._internals.states.delete('dirty');\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n control.requestUpdate();\n });\n\n observers.push(\n getElementUpdate(control.input, 'readonly', value =>\n (value === '' ? true : value) ? states.add('readonly') : states.delete('readonly')\n ),\n getElementUpdate(control.input, 'checked', () =>\n control.input.checked ? states.add('checked') : states.delete('checked')\n ),\n getElementUpdate(control.input, 'disabled', value =>\n (value === '' ? true : value) ? states.add('disabled') : states.delete('disabled')\n ),\n getElementUpdate(control.input, 'indeterminate', () =>\n control.input.indeterminate ? states.add('indeterminate') : states.delete('indeterminate')\n )\n );\n return observers;\n}\n\n/**\n * Adds control group interaction states to custom element\n * :state(disabled) any form control within group is in a disabled state\n */\nexport function setupControlGroupStates(controlGroup: ControlGroup) {\n toggleControlGroupDisabledState(controlGroup);\n return getAttributeChanges(controlGroup, 'disabled', () => toggleControlGroupDisabledState(controlGroup));\n}\n\nfunction toggleControlGroupDisabledState(controlGroup: ControlGroup) {\n if (Array.from(controlGroup.inputs).find(i => i.disabled)) {\n controlGroup._internals.states.add('disabled');\n } else {\n controlGroup._internals.states.delete('disabled');\n }\n}\n\n/**\n * Adds control status states to custom element\n * :state(error) form control is in a error state\n * :state(success) form control is in a success state\n */\nexport function setupControlStatusStates(control: Control | ControlGroup, messages: ControlMessage[]) {\n updateControlStatusState(control, messages.find(m => !m.hidden)!);\n const observers: MutationObserver[] = [];\n observers.push(\n getAttributeListChanges(control, ['hidden', 'status'], mutation => {\n const target = mutation.target as ControlMessage;\n if (matchesElementName(target, ControlMessage)) {\n updateControlStatusState(control, target);\n }\n })\n );\n\n control.shadowRoot!.addEventListener('slotchange', () => {\n const current = Array.from(control.querySelectorAll<ControlMessage>(ControlMessage.metadata.tag));\n const message = current.find(m => m.status && !m.hidden);\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n if (message) {\n control._internals.states.add(message.status!);\n }\n });\n\n return observers;\n}\n\nexport function updateControlStatusState(control: Control | ControlGroup, message: ControlMessage) {\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n\n if (message?.status?.length && !message?.hidden) {\n control._internals.states.add(message.status);\n }\n}\n\nexport function showNonValidationMessages(messages: ControlMessage[]) {\n messages.filter(m => !m.hasAttribute('error')).forEach(m => m.removeAttribute('hidden'));\n}\n\nexport function hideAllValidationMessages(messages: ControlMessage[]) {\n messages.filter(m => m.hasAttribute('error')).forEach(m => m.setAttribute('hidden', ''));\n}\n\nexport function showActiveValidationMessages(control: Control, messages: ControlMessage[]) {\n messages.find(m => m.error && control.input.validity[m.error])?.removeAttribute('hidden');\n}\n\nexport function hideInactiveValidationMessages(control: Control, messages: ControlMessage[]) {\n if (messages.find(m => m.error) && control.input.validity.valid) {\n messages.filter(m => m.error && !control.input.validity[m.error!]).forEach(m => m.setAttribute('hidden', ''));\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"states.js","names":[],"sources":["../../../src/forms/utils/states.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n getAttributeChanges,\n getAttributeListChanges,\n getElementUpdate,\n matchesElementName\n} from '@nvidia-elements/core/internal';\nimport type { ControlGroup } from '../control-group/control-group.js';\nimport { ControlMessage } from '../control-message/control-message.js';\nimport type { Control } from '../control/control.js';\n\nexport const inputQuery = 'input, select, selectmenu, textarea, [nve-control]';\nexport interface ControlStateCleanup {\n disconnect: () => void;\n}\n\n/**\n * Adds validation states to custom element\n * :state(valid) form control is in a valid state\n * :state(invalid) form control is in a invalid state\n */\n// eslint-disable-next-line max-lines-per-function\nexport function setupControlValidationStates(control: Control, messages: ControlMessage[]) {\n const cleanups: ControlStateCleanup[] = [];\n\n if (\n !control.input.form?.noValidate &&\n !control.input.formNoValidate &&\n !control.input.hasAttribute('formnovalidate')\n ) {\n hideAllValidationMessages(messages);\n\n /**\n * updateValidityState() logic triggered by input blur() or input() change events\n */\n const updateValidityState = () => {\n if (control.input.validity?.valid) {\n control._internals.states.delete('invalid');\n control._internals.states.add('valid');\n control.status = null!;\n }\n\n hideInactiveValidationMessages(control, messages);\n };\n\n const resetValidityState = () => {\n control.status = null!;\n control._internals.states.delete('valid');\n control._internals.states.delete('invalid');\n hideAllValidationMessages(messages);\n };\n\n const onBlur = () => {\n control.input.checkValidity();\n updateValidityState();\n };\n\n const onInput = () => {\n updateValidityState();\n };\n\n const onInvalid = () => {\n if (messages.find(m => m.error)) {\n hideAllValidationMessages(messages);\n showActiveValidationMessages(control, messages);\n }\n\n control.status = 'error';\n control._internals.states.delete('valid');\n control._internals.states.add('invalid');\n };\n\n cleanups.push(\n addCleanupListener(control.input, 'blur', onBlur),\n addCleanupListener(control.input, 'input', onInput),\n addCleanupListener(control.input, 'invalid', onInvalid),\n addCleanupListener(control, 'reset', resetValidityState)\n );\n\n if (control.input.form) {\n cleanups.push(addCleanupListener(control.input.form, 'reset', resetValidityState));\n }\n }\n\n const onSlotChange = () => {\n const current = Array.from(control.querySelectorAll<ControlMessage>(ControlMessage.metadata.tag));\n control._internals.states.delete('valid');\n control._internals.states.delete('invalid');\n if (current.find(m => !m.hidden && (m.status === 'error' || m.error))) {\n control._internals.states.add('invalid');\n } else {\n control._internals.states.add('valid');\n }\n };\n cleanups.push(addCleanupListener(control.shadowRoot!, 'slotchange', onSlotChange));\n\n return cleanups;\n}\n\n/**\n * Adds control interaction states to custom element\n * :state(checked) form control is in a checked state\n * :state(disabled) form control is in a disabled state\n * :state(readonly) form control is in a readonly state\n * :state(touched) form control received focus and then blurred\n * :state(dirty) user modified the form control\n */\nexport function setupControlStates(control: Control) {\n const observers: ControlStateCleanup[] = [];\n const states = control._internals.states;\n control.input.checked ? states.add('checked') : states.delete('checked');\n control.input.indeterminate ? states.add('indeterminate') : states.delete('indeterminate');\n\n observers.push(...addControlInteractionListeners(control));\n observers.push(\n getElementUpdate(control.input, 'readonly', value =>\n (value === '' ? true : value) ? states.add('readonly') : states.delete('readonly')\n ),\n getElementUpdate(control.input, 'checked', () =>\n control.input.checked ? states.add('checked') : states.delete('checked')\n ),\n getElementUpdate(control.input, 'disabled', value =>\n (value === '' ? true : value) ? states.add('disabled') : states.delete('disabled')\n ),\n getElementUpdate(control.input, 'indeterminate', () =>\n control.input.indeterminate ? states.add('indeterminate') : states.delete('indeterminate')\n )\n );\n return observers;\n}\n\nfunction addControlInteractionListeners(control: Control): ControlStateCleanup[] {\n const cleanups: ControlStateCleanup[] = [];\n const states = control._internals.states;\n const onFocus = () => control._internals.states.add('focus');\n const onInput = () => control._internals.states.add('dirty');\n const onBlur = () => {\n control._internals.states.add('touched');\n control._internals.states.delete('focus');\n };\n\n const onRootChange = (e: Event) => {\n if ((e.target as HTMLInputElement).name === control.input?.name) {\n control.input.checked ? states.add('checked') : states.delete('checked');\n }\n };\n\n const onFormReset = () => {\n control._internals.states.delete('touched');\n control._internals.states.delete('dirty');\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n control.requestUpdate();\n };\n\n cleanups.push(\n addCleanupListener(control.input, 'focus', onFocus),\n addCleanupListener(control.input, 'input', onInput),\n addCleanupListener(control.input, 'blur', onBlur),\n addCleanupListener(control.input.getRootNode(), 'change', onRootChange)\n );\n\n if (control.input.form) {\n cleanups.push(addCleanupListener(control.input.form, 'reset', onFormReset));\n }\n\n return cleanups;\n}\n\n/**\n * Adds control group interaction states to custom element\n * :state(disabled) any form control within group is in a disabled state\n */\nexport function setupControlGroupStates(controlGroup: ControlGroup) {\n toggleControlGroupDisabledState(controlGroup);\n return getAttributeChanges(controlGroup, 'disabled', () => toggleControlGroupDisabledState(controlGroup));\n}\n\nfunction toggleControlGroupDisabledState(controlGroup: ControlGroup) {\n if (Array.from(controlGroup.inputs).find(i => i.disabled)) {\n controlGroup._internals.states.add('disabled');\n } else {\n controlGroup._internals.states.delete('disabled');\n }\n}\n\n/**\n * Adds control status states to custom element\n * :state(error) form control is in a error state\n * :state(success) form control is in a success state\n */\nexport function setupControlStatusStates(control: Control | ControlGroup, messages: ControlMessage[]) {\n updateControlStatusState(control, messages.find(m => !m.hidden)!);\n const observers: ControlStateCleanup[] = [];\n observers.push(\n getAttributeListChanges(control, ['hidden', 'status'], mutation => {\n const target = mutation.target as ControlMessage;\n if (matchesElementName(target, ControlMessage)) {\n updateControlStatusState(control, target);\n }\n })\n );\n\n const onSlotChange = () => {\n const current = Array.from(control.querySelectorAll<ControlMessage>(ControlMessage.metadata.tag));\n const message = current.find(m => m.status && !m.hidden);\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n if (message) {\n control._internals.states.add(message.status!);\n }\n };\n observers.push(addCleanupListener(control.shadowRoot!, 'slotchange', onSlotChange));\n\n return observers;\n}\n\nfunction addCleanupListener(target: EventTarget, type: string, listener: EventListener): ControlStateCleanup {\n target.addEventListener(type, listener);\n return {\n disconnect: () => target.removeEventListener(type, listener)\n };\n}\n\nexport function updateControlStatusState(control: Control | ControlGroup, message: ControlMessage) {\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n\n if (message?.status?.length && !message?.hidden) {\n control._internals.states.add(message.status);\n }\n}\n\nexport function showNonValidationMessages(messages: ControlMessage[]) {\n messages.filter(m => !m.hasAttribute('error')).forEach(m => m.removeAttribute('hidden'));\n}\n\nexport function hideAllValidationMessages(messages: ControlMessage[]) {\n messages.filter(m => m.hasAttribute('error')).forEach(m => m.setAttribute('hidden', ''));\n}\n\nexport function showActiveValidationMessages(control: Control, messages: ControlMessage[]) {\n messages.find(m => m.error && control.input.validity[m.error])?.removeAttribute('hidden');\n}\n\nexport function hideInactiveValidationMessages(control: Control, messages: ControlMessage[]) {\n if (messages.find(m => m.error) && control.input.validity.valid) {\n messages.filter(m => m.error && !control.input.validity[m.error!]).forEach(m => m.setAttribute('hidden', ''));\n }\n}\n"],"mappings":"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"}
|
package/dist/grid/cell/cell2.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { appendRootNodeStyle as e } from "../../internal/utils/dom.js";
|
|
2
2
|
import { attachInternals as t } from "../../internal/utils/a11y.js";
|
|
3
3
|
import { useStyles as n } from "../../internal/styles/index.js";
|
|
4
|
-
import { __decorate as r } from "../../_virtual/_@oxc-project_runtime@0.
|
|
4
|
+
import { __decorate as r } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
5
5
|
import i from "./column.js";
|
|
6
6
|
import { LitElement as a, html as o } from "lit";
|
|
7
7
|
import { property as s } from "lit/decorators/property.js";
|
|
@@ -13,7 +13,7 @@ var c = class r extends a {
|
|
|
13
13
|
static {
|
|
14
14
|
this.metadata = {
|
|
15
15
|
tag: "nve-grid-column",
|
|
16
|
-
version: "2.0.
|
|
16
|
+
version: "2.0.3"
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
get #e() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { attachInternals as e } from "../../internal/utils/a11y.js";
|
|
2
2
|
import { hostAttr as t } from "../../internal/decorators/host-attr.js";
|
|
3
3
|
import { useStyles as n } from "../../internal/styles/index.js";
|
|
4
|
-
import { __decorate as r } from "../../_virtual/_@oxc-project_runtime@0.
|
|
4
|
+
import { __decorate as r } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
5
5
|
import i from "./footer.js";
|
|
6
6
|
import { LitElement as a, html as o } from "lit";
|
|
7
7
|
//#region src/grid/footer/footer.ts
|
|
@@ -15,7 +15,7 @@ var s = class extends a {
|
|
|
15
15
|
static {
|
|
16
16
|
this.metadata = {
|
|
17
17
|
tag: "nve-grid-footer",
|
|
18
|
-
version: "2.0.
|
|
18
|
+
version: "2.0.3"
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
static {
|
package/dist/grid/grid2.js
CHANGED
|
@@ -4,7 +4,7 @@ import { keyNavigationGrid as r } from "../internal/controllers/keynav-grid.cont
|
|
|
4
4
|
import { attachInternals as i } from "../internal/utils/a11y.js";
|
|
5
5
|
import { stateScroll as a } from "../internal/controllers/state-scroll.controller.js";
|
|
6
6
|
import { useStyles as o } from "../internal/styles/index.js";
|
|
7
|
-
import { __decorate as s } from "../_virtual/_@oxc-project_runtime@0.
|
|
7
|
+
import { __decorate as s } from "../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
8
8
|
import { GridPlaceholder as c } from "./placeholder/placeholder2.js";
|
|
9
9
|
import { GridColumn as l } from "./column/column2.js";
|
|
10
10
|
import { GridCell as u } from "./cell/cell2.js";
|
|
@@ -23,7 +23,7 @@ var y = class extends g {
|
|
|
23
23
|
static {
|
|
24
24
|
this.metadata = {
|
|
25
25
|
tag: "nve-grid",
|
|
26
|
-
version: "2.0.
|
|
26
|
+
version: "2.0.3",
|
|
27
27
|
children: [
|
|
28
28
|
d.metadata.tag,
|
|
29
29
|
f.metadata.tag,
|
|
@@ -4,7 +4,7 @@ import { debounce as n } from "../../internal/utils/events.js";
|
|
|
4
4
|
import { LogService as r } from "../../internal/services/log.service.js";
|
|
5
5
|
import { attachInternals as i } from "../../internal/utils/a11y.js";
|
|
6
6
|
import { useStyles as a } from "../../internal/styles/index.js";
|
|
7
|
-
import { __decorate as o } from "../../_virtual/_@oxc-project_runtime@0.
|
|
7
|
+
import { __decorate as o } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
8
8
|
import s from "./header.js";
|
|
9
9
|
import { GridColumn as c } from "../column/column2.js";
|
|
10
10
|
import { GridCell as l } from "../cell/cell2.js";
|
|
@@ -19,7 +19,7 @@ var m = class extends d {
|
|
|
19
19
|
static {
|
|
20
20
|
this.metadata = {
|
|
21
21
|
tag: "nve-grid-header",
|
|
22
|
-
version: "2.0.
|
|
22
|
+
version: "2.0.3",
|
|
23
23
|
children: [c.metadata.tag]
|
|
24
24
|
};
|
|
25
25
|
}
|
package/dist/grid/row/row2.js
CHANGED
|
@@ -2,7 +2,7 @@ import { audit as e } from "../../internal/controllers/audit.controller.js";
|
|
|
2
2
|
import { attachInternals as t } from "../../internal/utils/a11y.js";
|
|
3
3
|
import { stateSelected as n } from "../../internal/controllers/state-selected.controller.js";
|
|
4
4
|
import { useStyles as r } from "../../internal/styles/index.js";
|
|
5
|
-
import { __decorate as i } from "../../_virtual/_@oxc-project_runtime@0.
|
|
5
|
+
import { __decorate as i } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
6
6
|
import { GridCell as a } from "../cell/cell2.js";
|
|
7
7
|
import o from "./row.js";
|
|
8
8
|
import { LitElement as s, html as c } from "lit";
|
|
@@ -15,7 +15,7 @@ var u = class extends s {
|
|
|
15
15
|
static {
|
|
16
16
|
this.metadata = {
|
|
17
17
|
tag: "nve-grid-row",
|
|
18
|
-
version: "2.0.
|
|
18
|
+
version: "2.0.3",
|
|
19
19
|
children: [a.metadata.tag]
|
|
20
20
|
};
|
|
21
21
|
}
|
package/dist/icon/icon2.js
CHANGED
|
@@ -3,7 +3,7 @@ import { attachInternals as t } from "../internal/utils/a11y.js";
|
|
|
3
3
|
import { useStyles as n } from "../internal/styles/index.js";
|
|
4
4
|
import { ICON_IMPORTS as r } from "./icons.js";
|
|
5
5
|
import i from "./icon.js";
|
|
6
|
-
import { __decorate as a } from "../_virtual/_@oxc-project_runtime@0.
|
|
6
|
+
import { __decorate as a } from "../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
7
7
|
import { LitElement as o, html as s, isServer as c } from "lit";
|
|
8
8
|
import { property as l } from "lit/decorators/property.js";
|
|
9
9
|
import { unsafeSVG as u } from "lit/directives/unsafe-svg.js";
|
|
@@ -16,7 +16,7 @@ var f = class e extends o {
|
|
|
16
16
|
static {
|
|
17
17
|
this.metadata = {
|
|
18
18
|
tag: "nve-icon",
|
|
19
|
-
version: "2.0.
|
|
19
|
+
version: "2.0.3"
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
static {
|
|
@@ -94,7 +94,7 @@ a([l({
|
|
|
94
94
|
})], f.prototype, "name", void 0), a([d()], f.prototype, "svg", void 0);
|
|
95
95
|
function p(t) {
|
|
96
96
|
if (typeof globalThis.customElements?.get == "function") {
|
|
97
|
-
let n = e(t.metadata.version), i = e("2.0.
|
|
97
|
+
let n = e(t.metadata.version), i = e("2.0.3");
|
|
98
98
|
n.minor <= i.minor && n.major <= i.major && (t._icons = {
|
|
99
99
|
...t._icons,
|
|
100
100
|
...r
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { removeEmptySlotWhitespace as e } from "../internal/utils/dom.js";
|
|
2
2
|
import { scopedRegistry as t } from "../internal/decorators/scoped-registry.js";
|
|
3
3
|
import { useStyles as n } from "../internal/styles/index.js";
|
|
4
|
-
import { __decorate as r } from "../_virtual/_@oxc-project_runtime@0.
|
|
4
|
+
import { __decorate as r } from "../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
5
5
|
import { Icon as i } from "../icon/icon2.js";
|
|
6
6
|
import { Button as a } from "../button/button2.js";
|
|
7
7
|
import o from "./icon-button.js";
|
|
@@ -15,7 +15,7 @@ var l = class extends a {
|
|
|
15
15
|
static {
|
|
16
16
|
this.metadata = {
|
|
17
17
|
tag: "nve-icon-button",
|
|
18
|
-
version: "2.0.
|
|
18
|
+
version: "2.0.3"
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
static {
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { I18nService as e } from "./internal/services/i18n.service.js";
|
|
|
2
2
|
import { getThemeTokens as t } from "./internal/utils/dom.js";
|
|
3
3
|
import { statusIcons as n } from "./internal/types/index.js";
|
|
4
4
|
//#region src/index.ts
|
|
5
|
-
var r = "2.0.
|
|
5
|
+
var r = "2.0.3", i = "@nvidia-elements";
|
|
6
6
|
//#endregion
|
|
7
7
|
export { e as I18nService, i as SCOPE, r as VERSION, t as getThemeTokens, n as statusIcons };
|
|
8
8
|
|
package/dist/input/input2.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useStyles as e } from "../internal/styles/index.js";
|
|
2
|
-
import { __decorate as t } from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
+
import { __decorate as t } from "../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
3
3
|
import { Control as n } from "../forms/control/control2.js";
|
|
4
4
|
import r from "./input.js";
|
|
5
5
|
import { property as i } from "lit/decorators/property.js";
|
|
@@ -14,7 +14,7 @@ var a = r, o = class extends n {
|
|
|
14
14
|
static {
|
|
15
15
|
this.metadata = {
|
|
16
16
|
tag: "nve-input",
|
|
17
|
-
version: "2.0.
|
|
17
|
+
version: "2.0.3"
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
};
|
|
@@ -9,36 +9,37 @@ function h() {
|
|
|
9
9
|
}
|
|
10
10
|
var g = class {
|
|
11
11
|
#e = [];
|
|
12
|
-
|
|
12
|
+
#t;
|
|
13
|
+
get #n() {
|
|
13
14
|
return {
|
|
14
15
|
grid: this.host,
|
|
15
16
|
...this.host.keynavGridConfig
|
|
16
17
|
};
|
|
17
18
|
}
|
|
18
|
-
get #n() {
|
|
19
|
-
let e = Array.from(this.#t.rows);
|
|
20
|
-
return this.#t.columnRow && e.unshift(this.#t.columnRow), e;
|
|
21
|
-
}
|
|
22
19
|
get #r() {
|
|
23
|
-
|
|
20
|
+
let e = Array.from(this.#n.rows);
|
|
21
|
+
return this.#n.columnRow && e.unshift(this.#n.columnRow), e;
|
|
22
|
+
}
|
|
23
|
+
get #i() {
|
|
24
|
+
return [...Array.from(this.#n.columns ?? []), ...Array.from(this.#n.cells)];
|
|
24
25
|
}
|
|
25
26
|
constructor(e) {
|
|
26
27
|
this.host = e, this.host.addController(this);
|
|
27
28
|
}
|
|
28
29
|
async hostConnected() {
|
|
29
|
-
await this.host.updateComplete, o(this.#
|
|
30
|
+
await this.host.updateComplete, this.host.isConnected && (this.#t = this.#n.grid, o(this.#i), this.#t.addEventListener("keyup", this.#l), this.#t.addEventListener("keydown", this.#u), this.#t.addEventListener("mouseup", this.#d), this.#e.push(t(this.host, n(() => o(this.#i), 500))));
|
|
30
31
|
}
|
|
31
32
|
hostDisconnected() {
|
|
32
|
-
this.#e.forEach((e) => e?.disconnect());
|
|
33
|
+
this.#e.forEach((e) => e?.disconnect()), this.#e.length = 0, this.#t?.removeEventListener("keyup", this.#l), this.#t?.removeEventListener("keydown", this.#u), this.#t?.removeEventListener("mouseup", this.#d), this.#t = void 0;
|
|
33
34
|
}
|
|
34
|
-
#
|
|
35
|
+
#a(e) {
|
|
35
36
|
if (!p(e)) {
|
|
36
|
-
let t = e.composedPath()[0], n = this.#
|
|
37
|
-
n && this.#
|
|
37
|
+
let t = e.composedPath()[0], n = this.#i.find((e) => e === t) ? t : null;
|
|
38
|
+
n && this.#s(e, n);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
|
-
#
|
|
41
|
-
let n = Array.from(this.#
|
|
41
|
+
#o(t) {
|
|
42
|
+
let n = Array.from(this.#r), i = Array.from(this.#i);
|
|
42
43
|
if (e.state.env !== "production" && f(n)) {
|
|
43
44
|
r.warn("Invalid grid structure, all rows must have the same number of cells");
|
|
44
45
|
return;
|
|
@@ -49,11 +50,11 @@ var g = class {
|
|
|
49
50
|
ctrlKey: t.ctrlKey,
|
|
50
51
|
dir: this.host.dir
|
|
51
52
|
}), a = Array.from(u(n[r])).filter((e) => !!i.find((t) => t === e))[e];
|
|
52
|
-
this.#
|
|
53
|
+
this.#s(t, a), t.preventDefault();
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
|
-
#
|
|
56
|
-
c(this.#
|
|
56
|
+
#s(e, t) {
|
|
57
|
+
c(this.#i, t);
|
|
57
58
|
let n = d(t), r = n.filter((e) => s(e));
|
|
58
59
|
r.length === 1 && n.length === 1 ? i(r[0]) : i(t);
|
|
59
60
|
let a = {
|
|
@@ -67,10 +68,13 @@ var g = class {
|
|
|
67
68
|
detail: a
|
|
68
69
|
}));
|
|
69
70
|
}
|
|
70
|
-
#
|
|
71
|
-
let t = Array.from(this.#
|
|
71
|
+
#c(e) {
|
|
72
|
+
let t = Array.from(this.#i).find((e) => e.tabIndex === 0);
|
|
72
73
|
e.code === "Escape" && t?.focus(), e.code === "Enter" && t === e.composedPath()[0] && d(t)[0]?.focus();
|
|
73
74
|
}
|
|
75
|
+
#l = (e) => this.#c(e);
|
|
76
|
+
#u = (e) => this.#o(e);
|
|
77
|
+
#d = (e) => this.#a(e);
|
|
74
78
|
};
|
|
75
79
|
function _(e, t) {
|
|
76
80
|
let n = t === "rtl" ? l.ArrowRight : l.ArrowLeft, r = t === "rtl" ? l.ArrowLeft : l.ArrowRight;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keynav-grid.controller.js","names":["#config","#hostRows","#hostCells","#updateCellActivation","#keynavCell","#clickCell","#observers","#setActiveCell"],"sources":["../../../src/internal/controllers/keynav-grid.controller.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ReactiveController, ReactiveElement } from 'lit';\nimport type { LegacyDecoratorTarget } from '../types/index.js';\nimport { onChildListMutation, throttle } from '../utils/events.js';\nimport { GlobalStateService } from '../services/global.service.js';\nimport { LogService } from '../services/log.service.js';\nimport {\n validKeyNavigationCode,\n isContextMenuClick,\n getFlattenedDOMTree,\n getFlattenedFocusableItems,\n KeynavCode,\n hasInvalidDOMGrid\n} from '../utils/dom.js';\nimport {\n focusElement,\n getActiveElement,\n initializeKeyListItems,\n setActiveKeyListItem,\n isSimpleFocusable\n} from '../utils/focus.js';\n\nexport interface KeynavGridConfig {\n grid?: HTMLElement;\n columnRow?: HTMLElement;\n columns?: NodeListOf<HTMLElement> | HTMLElement[];\n rows: NodeListOf<HTMLElement> | HTMLElement[];\n cells: NodeListOf<HTMLElement> | HTMLElement[];\n}\n\nexport interface KeynavGridElement {\n keynavGridConfig: KeynavGridConfig;\n}\n\n/**\n * https://w3c.github.io/aria-practices/#gridNav_focus\n */\nexport function keyNavigationGrid<T extends ReactiveElement & KeynavGridElement>(): ClassDecorator {\n return (target: LegacyDecoratorTarget) =>\n target.addInitializer!((instance: T) => new KeyNavigationGridController(instance));\n}\n\nexport class KeyNavigationGridController<T extends ReactiveElement & KeynavGridElement> implements ReactiveController {\n #observers: MutationObserver[] = [];\n\n get #config() {\n return {\n grid: this.host,\n ...this.host.keynavGridConfig\n };\n }\n\n get #hostRows() {\n const rows = Array.from(this.#config.rows);\n\n if (this.#config.columnRow) {\n rows.unshift(this.#config.columnRow);\n }\n\n return rows;\n }\n\n get #hostCells() {\n return [...Array.from(this.#config.columns ?? []), ...Array.from(this.#config.cells)];\n }\n\n constructor(private host: T) {\n this.host.addController(this);\n }\n\n async hostConnected() {\n await this.host.updateComplete;\n initializeKeyListItems(this.#hostCells);\n this.#config.grid.addEventListener('keyup', (e: KeyboardEvent) => this.#updateCellActivation(e));\n this.#config.grid.addEventListener('keydown', (e: KeyboardEvent) => this.#keynavCell(e));\n this.#config.grid.addEventListener('mouseup', (e: MouseEvent) => this.#clickCell(e));\n this.#observers.push(\n onChildListMutation(\n this.host,\n throttle(() => initializeKeyListItems(this.#hostCells), 500)\n )\n );\n }\n\n hostDisconnected() {\n this.#observers.forEach(o => o?.disconnect());\n }\n\n #clickCell(e: MouseEvent) {\n if (!isContextMenuClick(e)) {\n const focusedElement = e.composedPath()[0] as HTMLElement;\n const activeCell = this.#hostCells.find(i => i === focusedElement) ? focusedElement : null;\n if (activeCell) {\n this.#setActiveCell(e, activeCell as HTMLElement);\n }\n }\n }\n\n #keynavCell(e: KeyboardEvent) {\n const rows = Array.from(this.#hostRows);\n const cells = Array.from(this.#hostCells);\n\n if (GlobalStateService.state.env !== 'production' && hasInvalidDOMGrid(rows)) {\n LogService.warn('Invalid grid structure, all rows must have the same number of cells');\n return;\n }\n\n if (validKeyNavigationCode(e) && isSimpleFocusable(getActiveElement() as Element)) {\n const { x, y } = getNextKeyGridItem(cells, rows, {\n code: e.code,\n ctrlKey: e.ctrlKey,\n dir: this.host.dir\n });\n\n const nextCell = Array.from(getFlattenedDOMTree(rows[y]!)).filter(c => !!cells.find(i => i === c))[\n x\n ] as HTMLElement;\n this.#setActiveCell(e, nextCell);\n e.preventDefault();\n }\n }\n\n #setActiveCell(e: KeyboardEvent | MouseEvent, activeCell: HTMLElement) {\n setActiveKeyListItem(this.#hostCells, activeCell);\n\n const items = getFlattenedFocusableItems(activeCell);\n const simpleItems = items.filter(i => isSimpleFocusable(i));\n\n if (simpleItems.length === 1 && items.length === 1) {\n focusElement(simpleItems[0]!);\n } else {\n focusElement(activeCell);\n }\n\n const detail = { code: e instanceof KeyboardEvent ? e.code : null, shiftKey: e.shiftKey, activeItem: activeCell };\n activeCell.dispatchEvent(new CustomEvent('nve-key-change', { bubbles: true, composed: true, detail }));\n }\n\n #updateCellActivation(e: KeyboardEvent) {\n const activeCell = Array.from(this.#hostCells).find(i => i.tabIndex === 0) as HTMLElement;\n if (e.code === 'Escape') {\n activeCell?.focus();\n }\n\n if (e.code === 'Enter' && activeCell === e.composedPath()[0]) {\n getFlattenedFocusableItems(activeCell as HTMLElement)[0]?.focus();\n }\n }\n}\n\nfunction getGridDelta(code: KeynavCode | string, dir: string): { dx: number; dy: number } | null {\n const start = dir === 'rtl' ? KeynavCode.ArrowRight : KeynavCode.ArrowLeft;\n const end = dir === 'rtl' ? KeynavCode.ArrowLeft : KeynavCode.ArrowRight;\n\n if (code === KeynavCode.ArrowUp) return { dx: 0, dy: -1 };\n if (code === KeynavCode.ArrowDown) return { dx: 0, dy: 1 };\n if (code === start) return { dx: -1, dy: 0 };\n if (code === end) return { dx: 1, dy: 0 };\n if (code === KeynavCode.PageUp) return { dx: 0, dy: -4 };\n if (code === KeynavCode.PageDown) return { dx: 0, dy: 4 };\n return null;\n}\n\nfunction applyGridHomeEnd(\n code: KeynavCode | string,\n position: { x: number; y: number },\n bounds: { columnCount: number; rowCount: number; ctrlKey: boolean }\n) {\n const { x, y } = position;\n const { columnCount, rowCount, ctrlKey } = bounds;\n if (code === KeynavCode.End) {\n return { x: columnCount, y: ctrlKey ? rowCount : y };\n }\n\n if (code === KeynavCode.Home) {\n return { x: 0, y: ctrlKey ? 0 : y };\n }\n\n return { x, y };\n}\n\nexport function getNextKeyGridItem(\n cells: HTMLElement[],\n rows: HTMLElement[],\n config: { code: KeynavCode | string; ctrlKey: boolean; dir: string }\n) {\n const currentCell = cells.find(i => i.tabIndex === 0) as HTMLElement;\n const currentRow = rows.find(r => getFlattenedDOMTree(r).find(c => c === currentCell)) as HTMLElement;\n const currentRowCells = Array.from(getFlattenedDOMTree(currentRow)).filter(c => !!cells.find(i => i === c));\n const rowCount = rows.length - 1;\n const columnCount = currentRowCells.length - 1;\n\n let x = currentRowCells.indexOf(currentCell);\n let y = rows.indexOf(currentRow);\n\n const delta = getGridDelta(config.code, config.dir);\n if (delta) {\n x = Math.max(0, Math.min(columnCount, x + delta.dx));\n y = Math.max(0, Math.min(rowCount, y + delta.dy));\n } else {\n ({ x, y } = applyGridHomeEnd(config.code, { x, y }, { columnCount, rowCount, ctrlKey: config.ctrlKey }));\n }\n\n return { x, y };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"keynav-grid.controller.js","names":["#config","#hostRows","#hostCells","#grid","#onKeyUp","#onKeyDown","#onMouseUp","#observers","#setActiveCell","#updateCellActivation","#keynavCell","#clickCell"],"sources":["../../../src/internal/controllers/keynav-grid.controller.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ReactiveController, ReactiveElement } from 'lit';\nimport type { LegacyDecoratorTarget } from '../types/index.js';\nimport { onChildListMutation, throttle } from '../utils/events.js';\nimport { GlobalStateService } from '../services/global.service.js';\nimport { LogService } from '../services/log.service.js';\nimport {\n validKeyNavigationCode,\n isContextMenuClick,\n getFlattenedDOMTree,\n getFlattenedFocusableItems,\n KeynavCode,\n hasInvalidDOMGrid\n} from '../utils/dom.js';\nimport {\n focusElement,\n getActiveElement,\n initializeKeyListItems,\n setActiveKeyListItem,\n isSimpleFocusable\n} from '../utils/focus.js';\n\nexport interface KeynavGridConfig {\n grid?: HTMLElement;\n columnRow?: HTMLElement;\n columns?: NodeListOf<HTMLElement> | HTMLElement[];\n rows: NodeListOf<HTMLElement> | HTMLElement[];\n cells: NodeListOf<HTMLElement> | HTMLElement[];\n}\n\nexport interface KeynavGridElement {\n keynavGridConfig: KeynavGridConfig;\n}\n\n/**\n * https://w3c.github.io/aria-practices/#gridNav_focus\n */\nexport function keyNavigationGrid<T extends ReactiveElement & KeynavGridElement>(): ClassDecorator {\n return (target: LegacyDecoratorTarget) =>\n target.addInitializer!((instance: T) => new KeyNavigationGridController(instance));\n}\n\nexport class KeyNavigationGridController<T extends ReactiveElement & KeynavGridElement> implements ReactiveController {\n #observers: MutationObserver[] = [];\n #grid?: HTMLElement;\n\n get #config() {\n return {\n grid: this.host,\n ...this.host.keynavGridConfig\n };\n }\n\n get #hostRows() {\n const rows = Array.from(this.#config.rows);\n\n if (this.#config.columnRow) {\n rows.unshift(this.#config.columnRow);\n }\n\n return rows;\n }\n\n get #hostCells() {\n return [...Array.from(this.#config.columns ?? []), ...Array.from(this.#config.cells)];\n }\n\n constructor(private host: T) {\n this.host.addController(this);\n }\n\n async hostConnected() {\n await this.host.updateComplete;\n if (!this.host.isConnected) return;\n\n this.#grid = this.#config.grid;\n initializeKeyListItems(this.#hostCells);\n this.#grid.addEventListener('keyup', this.#onKeyUp);\n this.#grid.addEventListener('keydown', this.#onKeyDown);\n this.#grid.addEventListener('mouseup', this.#onMouseUp);\n this.#observers.push(\n onChildListMutation(\n this.host,\n throttle(() => initializeKeyListItems(this.#hostCells), 500)\n )\n );\n }\n\n hostDisconnected() {\n this.#observers.forEach(o => o?.disconnect());\n this.#observers.length = 0;\n this.#grid?.removeEventListener('keyup', this.#onKeyUp);\n this.#grid?.removeEventListener('keydown', this.#onKeyDown);\n this.#grid?.removeEventListener('mouseup', this.#onMouseUp);\n this.#grid = undefined;\n }\n\n #clickCell(e: MouseEvent) {\n if (!isContextMenuClick(e)) {\n const focusedElement = e.composedPath()[0] as HTMLElement;\n const activeCell = this.#hostCells.find(i => i === focusedElement) ? focusedElement : null;\n if (activeCell) {\n this.#setActiveCell(e, activeCell as HTMLElement);\n }\n }\n }\n\n #keynavCell(e: KeyboardEvent) {\n const rows = Array.from(this.#hostRows);\n const cells = Array.from(this.#hostCells);\n\n if (GlobalStateService.state.env !== 'production' && hasInvalidDOMGrid(rows)) {\n LogService.warn('Invalid grid structure, all rows must have the same number of cells');\n return;\n }\n\n if (validKeyNavigationCode(e) && isSimpleFocusable(getActiveElement() as Element)) {\n const { x, y } = getNextKeyGridItem(cells, rows, {\n code: e.code,\n ctrlKey: e.ctrlKey,\n dir: this.host.dir\n });\n\n const nextCell = Array.from(getFlattenedDOMTree(rows[y]!)).filter(c => !!cells.find(i => i === c))[\n x\n ] as HTMLElement;\n this.#setActiveCell(e, nextCell);\n e.preventDefault();\n }\n }\n\n #setActiveCell(e: KeyboardEvent | MouseEvent, activeCell: HTMLElement) {\n setActiveKeyListItem(this.#hostCells, activeCell);\n\n const items = getFlattenedFocusableItems(activeCell);\n const simpleItems = items.filter(i => isSimpleFocusable(i));\n\n if (simpleItems.length === 1 && items.length === 1) {\n focusElement(simpleItems[0]!);\n } else {\n focusElement(activeCell);\n }\n\n const detail = { code: e instanceof KeyboardEvent ? e.code : null, shiftKey: e.shiftKey, activeItem: activeCell };\n activeCell.dispatchEvent(new CustomEvent('nve-key-change', { bubbles: true, composed: true, detail }));\n }\n\n #updateCellActivation(e: KeyboardEvent) {\n const activeCell = Array.from(this.#hostCells).find(i => i.tabIndex === 0) as HTMLElement;\n if (e.code === 'Escape') {\n activeCell?.focus();\n }\n\n if (e.code === 'Enter' && activeCell === e.composedPath()[0]) {\n getFlattenedFocusableItems(activeCell as HTMLElement)[0]?.focus();\n }\n }\n\n #onKeyUp = (e: KeyboardEvent) => this.#updateCellActivation(e);\n\n #onKeyDown = (e: KeyboardEvent) => this.#keynavCell(e);\n\n #onMouseUp = (e: MouseEvent) => this.#clickCell(e);\n}\n\nfunction getGridDelta(code: KeynavCode | string, dir: string): { dx: number; dy: number } | null {\n const start = dir === 'rtl' ? KeynavCode.ArrowRight : KeynavCode.ArrowLeft;\n const end = dir === 'rtl' ? KeynavCode.ArrowLeft : KeynavCode.ArrowRight;\n\n if (code === KeynavCode.ArrowUp) return { dx: 0, dy: -1 };\n if (code === KeynavCode.ArrowDown) return { dx: 0, dy: 1 };\n if (code === start) return { dx: -1, dy: 0 };\n if (code === end) return { dx: 1, dy: 0 };\n if (code === KeynavCode.PageUp) return { dx: 0, dy: -4 };\n if (code === KeynavCode.PageDown) return { dx: 0, dy: 4 };\n return null;\n}\n\nfunction applyGridHomeEnd(\n code: KeynavCode | string,\n position: { x: number; y: number },\n bounds: { columnCount: number; rowCount: number; ctrlKey: boolean }\n) {\n const { x, y } = position;\n const { columnCount, rowCount, ctrlKey } = bounds;\n if (code === KeynavCode.End) {\n return { x: columnCount, y: ctrlKey ? rowCount : y };\n }\n\n if (code === KeynavCode.Home) {\n return { x: 0, y: ctrlKey ? 0 : y };\n }\n\n return { x, y };\n}\n\nexport function getNextKeyGridItem(\n cells: HTMLElement[],\n rows: HTMLElement[],\n config: { code: KeynavCode | string; ctrlKey: boolean; dir: string }\n) {\n const currentCell = cells.find(i => i.tabIndex === 0) as HTMLElement;\n const currentRow = rows.find(r => getFlattenedDOMTree(r).find(c => c === currentCell)) as HTMLElement;\n const currentRowCells = Array.from(getFlattenedDOMTree(currentRow)).filter(c => !!cells.find(i => i === c));\n const rowCount = rows.length - 1;\n const columnCount = currentRowCells.length - 1;\n\n let x = currentRowCells.indexOf(currentCell);\n let y = rows.indexOf(currentRow);\n\n const delta = getGridDelta(config.code, config.dir);\n if (delta) {\n x = Math.max(0, Math.min(columnCount, x + delta.dx));\n y = Math.max(0, Math.min(rowCount, y + delta.dy));\n } else {\n ({ x, y } = applyGridHomeEnd(config.code, { x, y }, { columnCount, rowCount, ctrlKey: config.ctrlKey }));\n }\n\n return { x, y };\n}\n"],"mappings":"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"}
|
|
@@ -23,7 +23,10 @@ var o = class {
|
|
|
23
23
|
return this.host.hasAttribute("nve-keynav-disabled");
|
|
24
24
|
}
|
|
25
25
|
async hostConnected() {
|
|
26
|
-
await this.host.updateComplete, this.#n(), this.host.addEventListener("pointerup",
|
|
26
|
+
await this.host.updateComplete, this.host.isConnected && (this.#n(), this.host.addEventListener("pointerup", this.#s), this.host.addEventListener("keydown", this.#c));
|
|
27
|
+
}
|
|
28
|
+
hostDisconnected() {
|
|
29
|
+
this.host.removeEventListener("pointerup", this.#s), this.host.removeEventListener("keydown", this.#c);
|
|
27
30
|
}
|
|
28
31
|
#n() {
|
|
29
32
|
let { manageFocus: e, manageTabindex: n, items: r } = this.#e;
|
|
@@ -67,6 +70,8 @@ var o = class {
|
|
|
67
70
|
detail: c
|
|
68
71
|
}));
|
|
69
72
|
}
|
|
73
|
+
#s = (e) => this.#r(e);
|
|
74
|
+
#c = (e) => this.#i(e);
|
|
70
75
|
};
|
|
71
76
|
function s(e) {
|
|
72
77
|
let { code: t, layout: n, dir: i } = e, a = i === "rtl" ? r.ArrowRight : r.ArrowLeft, o = i === "rtl" ? r.ArrowLeft : r.ArrowRight;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keynav-list.controller.js","names":["#config","#keynavDisabled","#initializeTabIndex","#
|
|
1
|
+
{"version":3,"file":"keynav-list.controller.js","names":["#config","#keynavDisabled","#initializeTabIndex","#onPointerUp","#onKeyDown","#getActiveItem","#setActiveItem","#clickItem","#focusItem"],"sources":["../../../src/internal/controllers/keynav-list.controller.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ReactiveController, ReactiveElement } from 'lit';\nimport type { LegacyDecoratorTarget } from '../types/index.js';\nimport { focusElement, initializeKeyListItems, setActiveKeyListItem } from '../utils/focus.js';\nimport { KeynavCode, validKeyNavigationCode } from '../utils/dom.js';\n\nexport interface KeynavListConfig {\n items: NodeListOf<HTMLElement> | HTMLElement[];\n layout?: 'both' | 'horizontal' | 'vertical';\n manageFocus?: boolean;\n manageTabindex?: boolean;\n loop?: boolean;\n dir?: string | null;\n}\n\nexport interface KeynavListElement {\n keynavListConfig: KeynavListConfig;\n}\n\n/** https://webaim.org/techniques/keyboard/ */\nexport function keyNavigationList<T extends ReactiveElement & KeynavListElement>(): ClassDecorator {\n return (target: LegacyDecoratorTarget) =>\n target.addInitializer!((instance: T) => new KeyNavigationListController(instance));\n}\n\nexport class KeyNavigationListController<T extends ReactiveElement & KeynavListElement> implements ReactiveController {\n get #config(): KeynavListConfig & { items: HTMLElement[] } {\n return {\n layout: 'horizontal',\n manageFocus: true,\n manageTabindex: true,\n loop: false,\n dir: this.host.getAttribute('rtl'),\n ...this.host.keynavListConfig,\n items: Array.from(this.host.keynavListConfig.items).filter(\n (i: HTMLElement & { disabled?: boolean }) => !i.disabled\n )\n };\n }\n\n constructor(private host: T) {\n this.host.addController(this);\n }\n\n /** @private attr nve-keynav-disabled is an internal API for advanced use cases only */\n get #keynavDisabled() {\n return this.host.hasAttribute('nve-keynav-disabled');\n }\n\n async hostConnected() {\n await this.host.updateComplete;\n if (!this.host.isConnected) return;\n this.#initializeTabIndex();\n this.host.addEventListener('pointerup', this.#onPointerUp);\n this.host.addEventListener('keydown', this.#onKeyDown);\n }\n\n hostDisconnected() {\n this.host.removeEventListener('pointerup', this.#onPointerUp);\n this.host.removeEventListener('keydown', this.#onKeyDown);\n }\n\n #initializeTabIndex() {\n const { manageFocus, manageTabindex, items } = this.#config;\n if (manageFocus && manageTabindex && !this.#keynavDisabled) {\n initializeKeyListItems(items);\n }\n }\n\n #clickItem(e: PointerEvent) {\n const item = this.#getActiveItem(e, this.#config.items);\n if (item) {\n this.#setActiveItem(e, item);\n }\n }\n\n #focusItem(e: KeyboardEvent) {\n if (validKeyNavigationCode(e) && !this.#keynavDisabled) {\n const { loop, layout, dir, items } = this.#config;\n const activeItem = this.#getActiveItem(e, items);\n if (activeItem) {\n const { next, previous } = getNextKeyListItem(activeItem, Array.from(items), {\n loop,\n layout,\n dir,\n code: e.code as KeynavCode\n });\n\n if (next !== previous) {\n this.#setActiveItem(e, items[next]!, items[previous]);\n }\n }\n }\n }\n\n #getActiveItem(e: Event, items: HTMLElement[]) {\n const focusedElement = e.composedPath()[0] as HTMLElement;\n return items.find(i => i === focusedElement) ? focusedElement : null;\n }\n\n #setActiveItem(e: KeyboardEvent | PointerEvent, activeItem: HTMLElement, previousItem?: HTMLElement) {\n const { manageFocus, manageTabindex, items } = this.#config;\n if (manageFocus) {\n if (manageTabindex) {\n setActiveKeyListItem(items, activeItem);\n }\n\n focusElement(activeItem);\n e.preventDefault();\n }\n\n const detail = {\n activeItem,\n previousItem,\n code: e instanceof KeyboardEvent ? e.code : null,\n metaKey: e.ctrlKey || e.metaKey,\n items\n };\n activeItem.dispatchEvent(new CustomEvent('nve-key-change', { bubbles: true, composed: true, detail }));\n }\n\n #onPointerUp = (e: PointerEvent) => this.#clickItem(e);\n\n #onKeyDown = (e: KeyboardEvent) => this.#focusItem(e);\n}\n\ninterface KeyListConfig {\n code: KeynavCode;\n loop?: boolean;\n layout?: 'horizontal' | 'vertical' | 'both';\n dir: string | null | undefined;\n}\n\nfunction resolveArrowDirection(config: KeyListConfig): 'backward' | 'forward' | null {\n const { code, layout, dir } = config;\n const start = dir === 'rtl' ? KeynavCode.ArrowRight : KeynavCode.ArrowLeft;\n const end = dir === 'rtl' ? KeynavCode.ArrowLeft : KeynavCode.ArrowRight;\n\n if (layout !== 'horizontal') {\n if (code === KeynavCode.ArrowUp) return 'backward';\n if (code === KeynavCode.ArrowDown) return 'forward';\n }\n\n if (layout !== 'vertical') {\n if (code === start) return 'backward';\n if (code === end) return 'forward';\n }\n\n return null;\n}\n\nfunction resolveSpecialKey(code: KeynavCode): 'home' | 'end' | 'pageup' | 'pagedown' | null {\n if (code === KeynavCode.End) return 'end';\n if (code === KeynavCode.Home) return 'home';\n if (code === KeynavCode.PageUp) return 'pageup';\n if (code === KeynavCode.PageDown) return 'pagedown';\n return null;\n}\n\nfunction navigateWithLoop(current: number, step: number, options: { limit: number; loop: boolean | undefined }) {\n const { limit, loop } = options;\n const next = current + step;\n if (next >= 0 && next <= limit) return next;\n return loop ? (step < 0 ? limit : 0) : current;\n}\n\nexport function getNextKeyListItem(item: HTMLElement, items: HTMLElement[], config: KeyListConfig) {\n let next = items.indexOf(item);\n const previous = next;\n const itemCount = items.length - 1;\n const direction = resolveArrowDirection(config);\n\n switch (direction ?? resolveSpecialKey(config.code)) {\n case 'backward':\n next = navigateWithLoop(next, -1, { limit: itemCount, loop: config.loop });\n break;\n case 'forward':\n next = navigateWithLoop(next, 1, { limit: itemCount, loop: config.loop });\n break;\n case 'end':\n next = itemCount;\n break;\n case 'home':\n next = 0;\n break;\n case 'pageup':\n next = Math.max(0, next - 4);\n break;\n case 'pagedown':\n next = Math.min(itemCount, next + 4);\n break;\n case null:\n break;\n }\n\n return { next, previous };\n}\n"],"mappings":";;;AAsBA,SAAgB,IAAmF;CACjG,QAAQ,MACN,EAAO,gBAAiB,MAAgB,IAAI,EAA4B,CAAQ,CAAC;AACrF;AAEA,IAAa,IAAb,MAAsH;CACpH,IAAIA,KAAuD;EACzD,OAAO;GACL,QAAQ;GACR,aAAa;GACb,gBAAgB;GAChB,MAAM;GACN,KAAK,KAAK,KAAK,aAAa,KAAK;GACjC,GAAG,KAAK,KAAK;GACb,OAAO,MAAM,KAAK,KAAK,KAAK,iBAAiB,KAAK,EAAE,QACjD,MAA4C,CAAC,EAAE,QAClD;EACF;CACF;CAEA,YAAY,GAAiB;EAC3B,AADkB,KAAA,OAAA,GAClB,KAAK,KAAK,cAAc,IAAI;CAC9B;CAGA,IAAIC,KAAkB;EACpB,OAAO,KAAK,KAAK,aAAa,qBAAqB;CACrD;CAEA,MAAM,gBAAgB;EACpB,MAAM,KAAK,KAAK,gBACX,KAAK,KAAK,gBACf,KAAKC,GAAoB,GACzB,KAAK,KAAK,iBAAiB,aAAa,KAAKC,EAAY,GACzD,KAAK,KAAK,iBAAiB,WAAW,KAAKC,EAAU;CACvD;CAEA,mBAAmB;EAEjB,AADA,KAAK,KAAK,oBAAoB,aAAa,KAAKD,EAAY,GAC5D,KAAK,KAAK,oBAAoB,WAAW,KAAKC,EAAU;CAC1D;CAEA,KAAsB;EACpB,IAAM,EAAE,gBAAa,mBAAgB,aAAU,KAAKJ;EACpD,AAAI,KAAe,KAAkB,CAAC,KAAKC,MACzC,EAAuB,CAAK;CAEhC;CAEA,GAAW,GAAiB;EAC1B,IAAM,IAAO,KAAKI,GAAe,GAAG,KAAKL,GAAQ,KAAK;EACtD,AAAI,KACF,KAAKM,GAAe,GAAG,CAAI;CAE/B;CAEA,GAAW,GAAkB;EAC3B,IAAI,EAAuB,CAAC,KAAK,CAAC,KAAKL,IAAiB;GACtD,IAAM,EAAE,SAAM,WAAQ,QAAK,aAAU,KAAKD,IACpC,IAAa,KAAKK,GAAe,GAAG,CAAK;GAC/C,IAAI,GAAY;IACd,IAAM,EAAE,SAAM,gBAAa,EAAmB,GAAY,MAAM,KAAK,CAAK,GAAG;KAC3E;KACA;KACA;KACA,MAAM,EAAE;IACV,CAAC;IAED,AAAI,MAAS,KACX,KAAKC,GAAe,GAAG,EAAM,IAAQ,EAAM,EAAS;GAExD;EACF;CACF;CAEA,GAAe,GAAU,GAAsB;EAC7C,IAAM,IAAiB,EAAE,aAAa,EAAE;EACxC,OAAO,EAAM,MAAK,MAAK,MAAM,CAAc,IAAI,IAAiB;CAClE;CAEA,GAAe,GAAiC,GAAyB,GAA4B;EACnG,IAAM,EAAE,gBAAa,mBAAgB,aAAU,KAAKN;EACpD,AAAI,MACE,KACF,EAAqB,GAAO,CAAU,GAGxC,EAAa,CAAU,GACvB,EAAE,eAAe;EAGnB,IAAM,IAAS;GACb;GACA;GACA,MAAM,aAAa,gBAAgB,EAAE,OAAO;GAC5C,SAAS,EAAE,WAAW,EAAE;GACxB;EACF;EACA,EAAW,cAAc,IAAI,YAAY,kBAAkB;GAAE,SAAS;GAAM,UAAU;GAAM;EAAO,CAAC,CAAC;CACvG;CAEA,MAAgB,MAAoB,KAAKO,GAAW,CAAC;CAErD,MAAc,MAAqB,KAAKC,GAAW,CAAC;AACtD;AASA,SAAS,EAAsB,GAAsD;CACnF,IAAM,EAAE,SAAM,WAAQ,WAAQ,GACxB,IAAQ,MAAQ,QAAQ,EAAW,aAAa,EAAW,WAC3D,IAAM,MAAQ,QAAQ,EAAW,YAAY,EAAW;CAE9D,IAAI,MAAW,cAAc;EAC3B,IAAI,MAAS,EAAW,SAAS,OAAO;EACxC,IAAI,MAAS,EAAW,WAAW,OAAO;CAC5C;CAEA,IAAI,MAAW,YAAY;EACzB,IAAI,MAAS,GAAO,OAAO;EAC3B,IAAI,MAAS,GAAK,OAAO;CAC3B;CAEA,OAAO;AACT;AAEA,SAAS,EAAkB,GAAiE;CAK1F,OAJI,MAAS,EAAW,MAAY,QAChC,MAAS,EAAW,OAAa,SACjC,MAAS,EAAW,SAAe,WACnC,MAAS,EAAW,WAAiB,aAClC;AACT;AAEA,SAAS,EAAiB,GAAiB,GAAc,GAAuD;CAC9G,IAAM,EAAE,UAAO,YAAS,GAClB,IAAO,IAAU;CAEvB,OADI,KAAQ,KAAK,KAAQ,IAAc,IAChC,IAAQ,IAAO,IAAI,IAAQ,IAAK;AACzC;AAEA,SAAgB,EAAmB,GAAmB,GAAsB,GAAuB;CACjG,IAAI,IAAO,EAAM,QAAQ,CAAI,GACvB,IAAW,GACX,IAAY,EAAM,SAAS;CAGjC,QAFkB,EAAsB,CAEhC,KAAa,EAAkB,EAAO,IAAI,GAAlD;EACE,KAAK;GACH,IAAO,EAAiB,GAAM,IAAI;IAAE,OAAO;IAAW,MAAM,EAAO;GAAK,CAAC;GACzE;EACF,KAAK;GACH,IAAO,EAAiB,GAAM,GAAG;IAAE,OAAO;IAAW,MAAM,EAAO;GAAK,CAAC;GACxE;EACF,KAAK;GACH,IAAO;GACP;EACF,KAAK;GACH,IAAO;GACP;EACF,KAAK;GACH,IAAO,KAAK,IAAI,GAAG,IAAO,CAAC;GAC3B;EACF,KAAK;GACH,IAAO,KAAK,IAAI,GAAW,IAAO,CAAC;GACnC;EACF,KAAK,MACH;CACJ;CAEA,OAAO;EAAE;EAAM;CAAS;AAC1B"}
|