@nectary/components 5.38.1 → 5.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/bundle.d.ts +2 -0
  2. package/bundle.js +1689 -217
  3. package/bundle.ts +2 -0
  4. package/package.json +3 -3
  5. package/progress-stepper-item-v2/global/index.d.ts +1 -0
  6. package/progress-stepper-item-v2/global/index.js +2 -0
  7. package/progress-stepper-item-v2/index.d.ts +23 -0
  8. package/progress-stepper-item-v2/index.js +187 -0
  9. package/progress-stepper-item-v2/types.d.ts +69 -0
  10. package/progress-stepper-item-v2/types.js +1 -0
  11. package/progress-stepper-item-v2/utils.d.ts +22 -0
  12. package/progress-stepper-item-v2/utils.js +88 -0
  13. package/progress-stepper-v2/compact-format.d.ts +22 -0
  14. package/progress-stepper-v2/compact-format.js +56 -0
  15. package/progress-stepper-v2/compact.d.ts +26 -0
  16. package/progress-stepper-v2/compact.js +330 -0
  17. package/progress-stepper-v2/global/index.d.ts +1 -0
  18. package/progress-stepper-v2/global/index.js +2 -0
  19. package/progress-stepper-v2/index.d.ts +31 -0
  20. package/progress-stepper-v2/index.js +618 -0
  21. package/progress-stepper-v2/model.d.ts +32 -0
  22. package/progress-stepper-v2/model.js +59 -0
  23. package/progress-stepper-v2/orientation.d.ts +8 -0
  24. package/progress-stepper-v2/orientation.js +24 -0
  25. package/progress-stepper-v2/separators.d.ts +1 -0
  26. package/progress-stepper-v2/separators.js +48 -0
  27. package/progress-stepper-v2/step-chip.d.ts +9 -0
  28. package/progress-stepper-v2/step-chip.js +126 -0
  29. package/progress-stepper-v2/types.d.ts +66 -0
  30. package/progress-stepper-v2/types.js +1 -0
  31. package/standalone.d.ts +2 -0
  32. package/standalone.js +2 -0
  33. package/standalone.ts +2 -0
  34. package/utils/component-names.d.ts +2 -2
  35. package/utils/component-names.js +2 -0
  36. package/utils/dom.d.ts +1 -0
  37. package/utils/dom.js +9 -0
  38. package/utils/element.d.ts +2 -0
  39. package/utils/index.js +2 -1
package/bundle.ts CHANGED
@@ -44,7 +44,9 @@ export * from './pagination/index.js'
44
44
  export * from './persistent-overlay/index.js'
45
45
  export * from './pop/index.js'
46
46
  export * from './popover/index.js'
47
+ export * from './progress-stepper-item-v2/index.js'
47
48
  export * from './progress-stepper-item/index.js'
49
+ export * from './progress-stepper-v2/index.js'
48
50
  export * from './progress-stepper/index.js'
49
51
  export * from './progress/index.js'
50
52
  export * from './radio-option/index.js'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nectary/components",
3
- "version": "5.38.1",
3
+ "version": "5.39.0",
4
4
  "files": [
5
5
  "**/*/*.css",
6
6
  "**/*/*.json",
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@babel/runtime": "^7.22.15",
27
- "@nectary/assets": "3.6.13"
27
+ "@nectary/assets": "3.6.14"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@babel/cli": "^7.22.15",
@@ -40,6 +40,6 @@
40
40
  "vite": "^7.0.6"
41
41
  },
42
42
  "peerDependencies": {
43
- "@nectary/theme-base": "1.16.2"
43
+ "@nectary/theme-base": "1.17.0"
44
44
  }
45
45
  }
@@ -0,0 +1 @@
1
+ export * from '../types';
@@ -0,0 +1,2 @@
1
+ import { defineCustomElement } from "../../utils/element.js";
2
+ defineCustomElement("sinch-progress-stepper-item-v2");
@@ -0,0 +1,23 @@
1
+ import '../icon';
2
+ import '../text';
3
+ import { NectaryElement } from '../utils';
4
+ export * from './types';
5
+ export declare class ProgressStepperItemV2 extends NectaryElement {
6
+ #private;
7
+ constructor();
8
+ connectedCallback(): void;
9
+ disconnectedCallback(): void;
10
+ static get observedAttributes(): string[];
11
+ attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null): void;
12
+ set value(value: string);
13
+ get value(): string;
14
+ set text(value: string);
15
+ get text(): string;
16
+ set invalid(isInvalid: boolean);
17
+ get invalid(): boolean;
18
+ set complete(value: boolean);
19
+ get complete(): boolean;
20
+ set disabled(value: boolean);
21
+ get disabled(): boolean;
22
+ get focusable(): boolean;
23
+ }
@@ -0,0 +1,187 @@
1
+ import "../icon/index.js";
2
+ import "../text/index.js";
3
+ import { fillProgressStepperStepChipHost } from "../progress-stepper-v2/step-chip.js";
4
+ import { isAttrEqual, updateBooleanAttribute, isAttrTrue, updateExplicitBooleanAttribute, updateAttribute, getAttribute, getBooleanAttribute } from "../utils/dom.js";
5
+ import { defineCustomElement, NectaryElement } from "../utils/element.js";
6
+ import { TAG_PROGRESS_STEPPER_ITEM, ATTR_PROGRESS_STEPPER_ITEM_STATUS, ATTR_PROGRESS_STEPPER_ITEM_CHECKED, syncProgressStepperItemsRovingTabIndexes } from "./utils.js";
7
+ const templateHTML = '<style>:host{display:grid;grid-template-columns:minmax(0,max-content);grid-template-rows:minmax(0,1fr);min-height:0;min-width:0;outline:0}#button{position:relative;grid-area:1/1;align-self:stretch;justify-self:stretch;display:flex;flex-direction:column;justify-content:center;gap:0;width:100%;min-width:100%;min-height:0;padding:8px 4px;box-sizing:border-box;cursor:pointer;border-radius:var(--sinch-comp-progress-stepper-v2-step-shape-radius-container)}:host([data-stepper-layout=horizontal]) #button{padding:8px 12px 8px 10px}#label-bar{position:relative;width:100%;min-width:0}:host([data-status=inactive])>#button{cursor:default}:host([data-status=incomplete]:hover)>#button{background-color:var(--sinch-comp-progress-stepper-v2-step-color-incomplete-background-hover)}:host([data-status=complete]:hover)>#button{background-color:var(--sinch-comp-progress-stepper-v2-step-color-complete-background-hover)}:host([invalid]:not([data-status=inactive]):hover)>#button{background-color:var(--sinch-comp-progress-stepper-v2-step-color-invalid-background-hover)}#outline{position:absolute;inset:-2px;border:2px solid var(--sinch-comp-progress-stepper-v2-step-color-outline-focus);border-radius:calc(var(--sinch-comp-progress-stepper-v2-step-shape-radius-container) + 2px);pointer-events:none;opacity:0}:host(:focus-visible) #outline,:host([data-force-focus-visible]) #outline{opacity:1}#text{flex-shrink:1;flex-basis:auto;min-width:0;transition:color .25s ease-out}#label-content{display:flex;align-items:center;gap:8px;min-width:0}:host([invalid]) #text{--sinch-global-color-text:var(--sinch-comp-progress-stepper-v2-step-color-invalid-label-initial);--sinch-comp-text-font:var(--sinch-comp-progress-stepper-v2-step-font-label-initial)}:host(:is([data-status=incomplete],[data-status=inactive]):not([invalid])) #text{--sinch-global-color-text:var(--sinch-comp-progress-stepper-v2-step-color-incomplete-label-initial);--sinch-comp-text-font:var(--sinch-comp-progress-stepper-v2-step-font-label-initial)}:host([data-status=complete]:not([invalid])) #text{--sinch-global-color-text:var(--sinch-comp-progress-stepper-v2-step-color-complete-label-initial);--sinch-comp-text-font:var(--sinch-comp-progress-stepper-v2-step-font-label-initial)}:host([invalid][data-checked]) #text{--sinch-global-color-text:var(--sinch-comp-progress-stepper-v2-step-color-invalid-label-current);--sinch-comp-text-font:var(--sinch-comp-progress-stepper-v2-step-font-label-current)}:host(:is([data-status=incomplete],[data-status=inactive]):not([invalid])[data-checked]) #text{--sinch-global-color-text:var(--sinch-comp-progress-stepper-v2-step-color-incomplete-label-current);--sinch-comp-text-font:var(--sinch-comp-progress-stepper-v2-step-font-label-current)}:host([data-status=complete]:not([invalid])[data-checked]) #text{--sinch-global-color-text:var(--sinch-comp-progress-stepper-v2-step-color-complete-label-current);--sinch-comp-text-font:var(--sinch-comp-progress-stepper-v2-step-font-label-current)}</style><div id="button"><div id="label-bar"><div id="label-content"><span id="index" aria-hidden="true"></span><sinch-text id="text" type="m"></sinch-text></div></div><div id="outline"></div></div>';
8
+ const template = document.createElement("template");
9
+ template.innerHTML = templateHTML;
10
+ class ProgressStepperItemV2 extends NectaryElement {
11
+ #$text;
12
+ #$indicator;
13
+ constructor() {
14
+ super();
15
+ const shadowRoot = this.attachShadow({ delegatesFocus: false });
16
+ shadowRoot.appendChild(template.content.cloneNode(true));
17
+ this.#$text = shadowRoot.querySelector("#text");
18
+ this.#$indicator = shadowRoot.querySelector("#index");
19
+ }
20
+ connectedCallback() {
21
+ this.setAttribute("role", "tab");
22
+ this.#syncAriaDisabled();
23
+ this.#syncStepIndex();
24
+ this.#updateTabIndex();
25
+ }
26
+ disconnectedCallback() {
27
+ }
28
+ static get observedAttributes() {
29
+ return [
30
+ "text",
31
+ "data-step-index",
32
+ "invalid",
33
+ "complete",
34
+ "disabled",
35
+ ATTR_PROGRESS_STEPPER_ITEM_STATUS,
36
+ ATTR_PROGRESS_STEPPER_ITEM_CHECKED
37
+ ];
38
+ }
39
+ attributeChangedCallback(name, oldVal, newVal) {
40
+ switch (name) {
41
+ case "text": {
42
+ this.#$text.textContent = newVal;
43
+ break;
44
+ }
45
+ case "data-step-index": {
46
+ this.#syncIndicatorAttributes();
47
+ break;
48
+ }
49
+ case ATTR_PROGRESS_STEPPER_ITEM_CHECKED: {
50
+ updateExplicitBooleanAttribute(
51
+ this,
52
+ "aria-selected",
53
+ isAttrTrue(newVal)
54
+ );
55
+ this.#syncIndicatorAttributes();
56
+ this.#updateTabIndex();
57
+ break;
58
+ }
59
+ case ATTR_PROGRESS_STEPPER_ITEM_STATUS: {
60
+ this.#syncAriaDisabled();
61
+ this.#updateTabIndex();
62
+ this.#syncIndicatorAttributes();
63
+ break;
64
+ }
65
+ case "invalid": {
66
+ if (isAttrEqual(oldVal, newVal)) {
67
+ return;
68
+ }
69
+ const isInvalid = isAttrTrue(newVal);
70
+ updateExplicitBooleanAttribute(this, "aria-invalid", isInvalid);
71
+ updateBooleanAttribute(this, "invalid", isInvalid);
72
+ this.#syncIndicatorAttributes();
73
+ break;
74
+ }
75
+ case "disabled": {
76
+ if (isAttrEqual(oldVal, newVal)) {
77
+ return;
78
+ }
79
+ updateBooleanAttribute(this, "disabled", isAttrTrue(newVal));
80
+ this.#syncAriaDisabled();
81
+ this.#updateTabIndex();
82
+ break;
83
+ }
84
+ case "complete": {
85
+ if (isAttrEqual(oldVal, newVal)) {
86
+ return;
87
+ }
88
+ updateBooleanAttribute(this, "complete", isAttrTrue(newVal));
89
+ break;
90
+ }
91
+ }
92
+ }
93
+ set value(value) {
94
+ updateAttribute(this, "value", value);
95
+ }
96
+ get value() {
97
+ return getAttribute(this, "value", "");
98
+ }
99
+ set text(value) {
100
+ updateAttribute(this, "text", value);
101
+ }
102
+ get text() {
103
+ return getAttribute(this, "text", "");
104
+ }
105
+ set invalid(isInvalid) {
106
+ updateBooleanAttribute(this, "invalid", isInvalid);
107
+ }
108
+ get invalid() {
109
+ return getBooleanAttribute(this, "invalid");
110
+ }
111
+ set complete(value) {
112
+ updateBooleanAttribute(this, "complete", value);
113
+ }
114
+ get complete() {
115
+ return getBooleanAttribute(this, "complete");
116
+ }
117
+ set disabled(value) {
118
+ updateBooleanAttribute(this, "disabled", value);
119
+ }
120
+ get disabled() {
121
+ return getBooleanAttribute(this, "disabled");
122
+ }
123
+ get focusable() {
124
+ return true;
125
+ }
126
+ #syncAriaDisabled() {
127
+ const status = getAttribute(this, ATTR_PROGRESS_STEPPER_ITEM_STATUS, "");
128
+ const isUnavailable = getBooleanAttribute(this, "disabled") || status === "inactive";
129
+ updateExplicitBooleanAttribute(this, "aria-disabled", isUnavailable);
130
+ }
131
+ #syncIndicatorAttributes() {
132
+ let stepIndexDisplay = getAttribute(this, "data-step-index", "");
133
+ if (stepIndexDisplay === "") {
134
+ const fallback = this.#computeFallbackIndex();
135
+ if (fallback > 0) {
136
+ stepIndexDisplay = String(fallback);
137
+ }
138
+ }
139
+ fillProgressStepperStepChipHost(this.#$indicator, {
140
+ stepIndexDisplay,
141
+ status: getAttribute(this, ATTR_PROGRESS_STEPPER_ITEM_STATUS, "incomplete"),
142
+ invalid: getBooleanAttribute(this, "invalid"),
143
+ checked: getBooleanAttribute(this, ATTR_PROGRESS_STEPPER_ITEM_CHECKED)
144
+ });
145
+ }
146
+ #updateTabIndex() {
147
+ const parent = this.parentElement;
148
+ if (parent === null) {
149
+ return;
150
+ }
151
+ const items = [...parent.children].filter(
152
+ (el) => el.tagName.toLowerCase() === TAG_PROGRESS_STEPPER_ITEM
153
+ );
154
+ syncProgressStepperItemsRovingTabIndexes(items);
155
+ }
156
+ #syncStepIndex() {
157
+ let index = getAttribute(this, "data-step-index", "");
158
+ if (index === "") {
159
+ const fallback = this.#computeFallbackIndex();
160
+ if (fallback > 0) {
161
+ index = String(fallback);
162
+ this.setAttribute("data-step-index", index);
163
+ }
164
+ }
165
+ this.#syncIndicatorAttributes();
166
+ }
167
+ #computeFallbackIndex() {
168
+ const parent = this.parentElement;
169
+ if (parent === null) {
170
+ return -1;
171
+ }
172
+ let index = 0;
173
+ for (const sibling of Array.from(parent.children)) {
174
+ if (sibling.tagName.toLowerCase() === TAG_PROGRESS_STEPPER_ITEM) {
175
+ index += 1;
176
+ }
177
+ if (sibling === this) {
178
+ return index;
179
+ }
180
+ }
181
+ return -1;
182
+ }
183
+ }
184
+ defineCustomElement(TAG_PROGRESS_STEPPER_ITEM, ProgressStepperItemV2);
185
+ export {
186
+ ProgressStepperItemV2
187
+ };
@@ -0,0 +1,69 @@
1
+ import type { NectaryComponentReactByType, NectaryComponentVanillaByType, NectaryComponentReact, NectaryComponentVanilla } from '../types';
2
+ export type TSinchProgressStepperItemV2Props = {
3
+ /** Value */
4
+ value: string;
5
+ /** Text */
6
+ text: string;
7
+ /** Invalid */
8
+ invalid?: boolean;
9
+ /** Mark step complete (only applies when parent `sinch-progress-stepper-v2` has `noCompletionOrder`. Ignored in ordered mode). */
10
+ complete?: boolean;
11
+ /** Mark step inactive / not selectable (only applies when parent `sinch-progress-stepper-v2` has `noCompletionOrder`. Ignored in ordered mode). */
12
+ disabled?: boolean;
13
+ };
14
+ export type TSinchProgressStepperItemV2Style = {
15
+ '--sinch-comp-progress-stepper-v2-step-shape-radius-container'?: string;
16
+ '--sinch-comp-progress-stepper-v2-step-shape-radius-indicator'?: string;
17
+ '--sinch-comp-progress-stepper-v2-step-color-outline-focus'?: string;
18
+ '--sinch-comp-progress-stepper-v2-step-color-compact-background'?: string;
19
+ '--sinch-comp-progress-stepper-v2-step-color-compact-border'?: string;
20
+ '--sinch-comp-progress-stepper-v2-step-color-incomplete-background-hover'?: string;
21
+ '--sinch-comp-progress-stepper-v2-step-color-incomplete-label-initial'?: string;
22
+ '--sinch-comp-progress-stepper-v2-step-color-incomplete-label-current'?: string;
23
+ '--sinch-comp-progress-stepper-v2-step-color-incomplete-icon-initial'?: string;
24
+ '--sinch-comp-progress-stepper-v2-step-color-incomplete-icon-current'?: string;
25
+ '--sinch-comp-progress-stepper-v2-step-color-incomplete-icon-container-initial'?: string;
26
+ '--sinch-comp-progress-stepper-v2-step-color-incomplete-icon-container-current'?: string;
27
+ '--sinch-comp-progress-stepper-v2-step-color-complete-background-hover'?: string;
28
+ '--sinch-comp-progress-stepper-v2-step-color-complete-label-initial'?: string;
29
+ '--sinch-comp-progress-stepper-v2-step-color-complete-label-current'?: string;
30
+ '--sinch-comp-progress-stepper-v2-step-color-complete-icon-initial'?: string;
31
+ '--sinch-comp-progress-stepper-v2-step-color-complete-icon-current'?: string;
32
+ '--sinch-comp-progress-stepper-v2-step-color-complete-icon-container-initial'?: string;
33
+ '--sinch-comp-progress-stepper-v2-step-color-complete-icon-container-current'?: string;
34
+ '--sinch-comp-progress-stepper-v2-step-color-invalid-background-hover'?: string;
35
+ '--sinch-comp-progress-stepper-v2-step-color-invalid-label-initial'?: string;
36
+ '--sinch-comp-progress-stepper-v2-step-color-invalid-label-current'?: string;
37
+ '--sinch-comp-progress-stepper-v2-step-color-invalid-icon-initial'?: string;
38
+ '--sinch-comp-progress-stepper-v2-step-color-invalid-icon-current'?: string;
39
+ '--sinch-comp-progress-stepper-v2-step-color-invalid-icon-container-initial'?: string;
40
+ '--sinch-comp-progress-stepper-v2-step-color-invalid-icon-container-current'?: string;
41
+ '--sinch-comp-progress-stepper-v2-step-font-label-initial'?: string;
42
+ '--sinch-comp-progress-stepper-v2-step-font-label-current'?: string;
43
+ };
44
+ export type TSinchProgressStepperItemV2 = {
45
+ props: TSinchProgressStepperItemV2Props;
46
+ style: TSinchProgressStepperItemV2Style;
47
+ };
48
+ export type TSinchProgressStepperItemV2Element = NectaryComponentVanillaByType<TSinchProgressStepperItemV2>;
49
+ export type TSinchProgressStepperItemV2React = NectaryComponentReactByType<TSinchProgressStepperItemV2>;
50
+ declare global {
51
+ interface NectaryComponentMap {
52
+ 'sinch-progress-stepper-item-v2': TSinchProgressStepperItemV2;
53
+ }
54
+ interface HTMLElementTagNameMap {
55
+ 'sinch-progress-stepper-item-v2': NectaryComponentVanilla<'sinch-progress-stepper-item-v2'>;
56
+ }
57
+ namespace JSX {
58
+ interface IntrinsicElements {
59
+ 'sinch-progress-stepper-item-v2': NectaryComponentReact<'sinch-progress-stepper-item-v2'>;
60
+ }
61
+ }
62
+ }
63
+ declare module 'react' {
64
+ namespace JSX {
65
+ interface IntrinsicElements extends globalThis.JSX.IntrinsicElements {
66
+ 'sinch-progress-stepper-item-v2': NectaryComponentReact<'sinch-progress-stepper-item-v2'>;
67
+ }
68
+ }
69
+ }
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,22 @@
1
+ type TSinchProgressStepperItemStatus = 'inactive' | 'incomplete' | 'invalid' | 'complete';
2
+ export declare const TAG_PROGRESS_STEPPER = "sinch-progress-stepper-v2";
3
+ export declare const TAG_PROGRESS_STEPPER_ITEM = "sinch-progress-stepper-item-v2";
4
+ export declare const ATTR_PROGRESS_STEPPER_ITEM_CHECKED = "data-checked";
5
+ export declare const ATTR_PROGRESS_STEPPER_ITEM_STATUS = "data-status";
6
+ /** Set by `sinch-progress-stepper-v2` on default-slot items for layout-specific styling. */
7
+ export declare const ATTR_PROGRESS_STEPPER_ITEM_LAYOUT = "data-stepper-layout";
8
+ export declare const isProgressStepperItemChecked: ($el: Element) => boolean;
9
+ export declare const setProgressStepperItemChecked: ($el: Element, isChecked: boolean) => void;
10
+ export declare const isProgressStepperItemActive: ($el: Element) => boolean;
11
+ export declare const setProgressStepperItemStatus: ($el: Element, status: TSinchProgressStepperItemStatus) => void;
12
+ /**
13
+ * Nested shadow trees (e.g. `sinch-text` inside a step) break `shadowRoot.contains(active)` —
14
+ * walk up through shadow boundaries, and optionally use `composedPath()` from the key event.
15
+ */
16
+ export declare const getProgressStepperFocusedItemIndex: (items: HTMLElement[], active: Element | null, fromEvent?: Event) => number;
17
+ /**
18
+ * APG roving tabs: one `tabIndex === 0`. Prefer the item that actually has focus (arrow moves);
19
+ * otherwise the selected (`data-checked`) item; otherwise the first focusable.
20
+ */
21
+ export declare const syncProgressStepperItemsRovingTabIndexes: (items: HTMLElement[]) => void;
22
+ export {};
@@ -0,0 +1,88 @@
1
+ import { getBooleanAttribute, getAttribute, updateBooleanAttribute, updateAttribute } from "../utils/dom.js";
2
+ const TAG_PROGRESS_STEPPER = "sinch-progress-stepper-v2";
3
+ const TAG_PROGRESS_STEPPER_ITEM = "sinch-progress-stepper-item-v2";
4
+ const ATTR_PROGRESS_STEPPER_ITEM_CHECKED = "data-checked";
5
+ const ATTR_PROGRESS_STEPPER_ITEM_STATUS = "data-status";
6
+ const ATTR_PROGRESS_STEPPER_ITEM_LAYOUT = "data-stepper-layout";
7
+ const isProgressStepperItemChecked = ($el) => getBooleanAttribute($el, ATTR_PROGRESS_STEPPER_ITEM_CHECKED);
8
+ const setProgressStepperItemChecked = ($el, isChecked) => updateBooleanAttribute($el, ATTR_PROGRESS_STEPPER_ITEM_CHECKED, isChecked);
9
+ const isProgressStepperItemActive = ($el) => {
10
+ const attrValue = getAttribute($el, ATTR_PROGRESS_STEPPER_ITEM_STATUS);
11
+ if (attrValue === null || attrValue === "") {
12
+ return true;
13
+ }
14
+ return attrValue !== "inactive";
15
+ };
16
+ const setProgressStepperItemStatus = ($el, status) => updateAttribute($el, ATTR_PROGRESS_STEPPER_ITEM_STATUS, status);
17
+ const isStepperTabFocusable = (item) => !getBooleanAttribute(item, "disabled") && isProgressStepperItemActive(item);
18
+ const getProgressStepperFocusedItemIndex = (items, active, fromEvent) => {
19
+ if (fromEvent != null && typeof fromEvent.composedPath === "function") {
20
+ for (const node of fromEvent.composedPath()) {
21
+ if (node instanceof HTMLElement) {
22
+ const i = items.indexOf(node);
23
+ if (i >= 0) {
24
+ return i;
25
+ }
26
+ }
27
+ }
28
+ }
29
+ if (active === null) {
30
+ return -1;
31
+ }
32
+ let n = active;
33
+ while (n != null) {
34
+ if (n instanceof HTMLElement) {
35
+ const i = items.indexOf(n);
36
+ if (i >= 0) {
37
+ return i;
38
+ }
39
+ }
40
+ const parentNode = n.parentNode;
41
+ if (parentNode != null) {
42
+ n = parentNode;
43
+ continue;
44
+ }
45
+ const root = n.getRootNode();
46
+ if (root instanceof ShadowRoot && root.host instanceof HTMLElement) {
47
+ n = root.host;
48
+ continue;
49
+ }
50
+ break;
51
+ }
52
+ return -1;
53
+ };
54
+ const syncProgressStepperItemsRovingTabIndexes = (items) => {
55
+ const focusIdx = getProgressStepperFocusedItemIndex(items, document.activeElement);
56
+ let primaryIdx = -1;
57
+ if (focusIdx >= 0 && isStepperTabFocusable(items[focusIdx])) {
58
+ primaryIdx = focusIdx;
59
+ } else {
60
+ const checkedIdx = items.findIndex((s) => getBooleanAttribute(s, ATTR_PROGRESS_STEPPER_ITEM_CHECKED));
61
+ if (checkedIdx >= 0 && isStepperTabFocusable(items[checkedIdx])) {
62
+ primaryIdx = checkedIdx;
63
+ } else {
64
+ primaryIdx = items.findIndex(isStepperTabFocusable);
65
+ }
66
+ }
67
+ for (let i = 0; i < items.length; i++) {
68
+ const item = items[i];
69
+ if (!isStepperTabFocusable(item)) {
70
+ item.tabIndex = -1;
71
+ continue;
72
+ }
73
+ item.tabIndex = i === primaryIdx ? 0 : -1;
74
+ }
75
+ };
76
+ export {
77
+ ATTR_PROGRESS_STEPPER_ITEM_CHECKED,
78
+ ATTR_PROGRESS_STEPPER_ITEM_LAYOUT,
79
+ ATTR_PROGRESS_STEPPER_ITEM_STATUS,
80
+ TAG_PROGRESS_STEPPER,
81
+ TAG_PROGRESS_STEPPER_ITEM,
82
+ getProgressStepperFocusedItemIndex,
83
+ isProgressStepperItemActive,
84
+ isProgressStepperItemChecked,
85
+ setProgressStepperItemChecked,
86
+ setProgressStepperItemStatus,
87
+ syncProgressStepperItemsRovingTabIndexes
88
+ };
@@ -0,0 +1,22 @@
1
+ export type TCompactFormatVars = {
2
+ current: number | string;
3
+ total: number | string;
4
+ step: string;
5
+ label: string;
6
+ };
7
+ /** Visible compact counter badge when `compact-counter-format` is unset. */
8
+ export declare const DEFAULT_COMPACT_COUNTER_FORMAT = "{current} of {total}";
9
+ /** Compact trigger `aria-label` when host `aria-label` is set and format attr is unset. */
10
+ export declare const DEFAULT_COMPACT_TRIGGER_ARIA_LABEL_FORMAT_WITH_LABEL = "{label}, {current} of {total}, {step}";
11
+ /** Compact trigger `aria-label` when host `aria-label` is unset and format attr is unset. */
12
+ export declare const DEFAULT_COMPACT_TRIGGER_ARIA_LABEL_FORMAT = "{current} of {total}, {step}";
13
+ export declare function formatCompactTemplate(template: string, vars: TCompactFormatVars): string;
14
+ export declare function resolveCompactCounterFormat(explicit: string): string;
15
+ export declare function resolveCompactTriggerAriaLabelFormat(explicit: string, hostAriaLabel: string | null): string;
16
+ /** Accessible name for the compact trigger button. */
17
+ export declare function resolveCompactTriggerAriaLabel(compactTriggerAriaLabelFormat: string, hostAriaLabel: string | null, vars: TCompactFormatVars): string;
18
+ /**
19
+ * Accessible name for compact `sinch-action-menu` / `sinch-pop`.
20
+ * Uses host `aria-label` when set; otherwise matches the derived trigger name.
21
+ */
22
+ export declare function resolveCompactMenuAndPopAriaLabel(hostAriaLabel: string | null, compactTriggerAriaLabelFormat: string, vars: TCompactFormatVars): string;
@@ -0,0 +1,56 @@
1
+ const DEFAULT_COMPACT_COUNTER_FORMAT = "{current} of {total}";
2
+ const DEFAULT_COMPACT_TRIGGER_ARIA_LABEL_FORMAT_WITH_LABEL = "{label}, {current} of {total}, {step}";
3
+ const DEFAULT_COMPACT_TRIGGER_ARIA_LABEL_FORMAT = "{current} of {total}, {step}";
4
+ function formatCompactTemplate(template, vars) {
5
+ return template.replace(/\{(\w+)\}/g, (_, key) => {
6
+ const value = vars[key];
7
+ return value != null ? String(value) : "";
8
+ });
9
+ }
10
+ function resolveCompactCounterFormat(explicit) {
11
+ return explicit !== "" ? explicit : DEFAULT_COMPACT_COUNTER_FORMAT;
12
+ }
13
+ function resolveCompactTriggerAriaLabelFormat(explicit, hostAriaLabel) {
14
+ if (explicit !== "") {
15
+ return explicit;
16
+ }
17
+ if (hostAriaLabel != null && hostAriaLabel !== "") {
18
+ return DEFAULT_COMPACT_TRIGGER_ARIA_LABEL_FORMAT_WITH_LABEL;
19
+ }
20
+ return DEFAULT_COMPACT_TRIGGER_ARIA_LABEL_FORMAT;
21
+ }
22
+ function adjustDefaultTriggerFormatForEmptyStep(format, stepEmpty) {
23
+ if (!stepEmpty) {
24
+ return format;
25
+ }
26
+ if (format === DEFAULT_COMPACT_TRIGGER_ARIA_LABEL_FORMAT) {
27
+ return "{current} of {total}";
28
+ }
29
+ if (format === DEFAULT_COMPACT_TRIGGER_ARIA_LABEL_FORMAT_WITH_LABEL) {
30
+ return "{label}, {current} of {total}";
31
+ }
32
+ return format;
33
+ }
34
+ function resolveCompactTriggerAriaLabel(compactTriggerAriaLabelFormat, hostAriaLabel, vars) {
35
+ let format = resolveCompactTriggerAriaLabelFormat(compactTriggerAriaLabelFormat, hostAriaLabel);
36
+ if (compactTriggerAriaLabelFormat === "") {
37
+ format = adjustDefaultTriggerFormatForEmptyStep(format, vars.step === "");
38
+ }
39
+ return formatCompactTemplate(format, vars);
40
+ }
41
+ function resolveCompactMenuAndPopAriaLabel(hostAriaLabel, compactTriggerAriaLabelFormat, vars) {
42
+ if (hostAriaLabel != null && hostAriaLabel !== "") {
43
+ return hostAriaLabel;
44
+ }
45
+ return resolveCompactTriggerAriaLabel(compactTriggerAriaLabelFormat, hostAriaLabel, vars);
46
+ }
47
+ export {
48
+ DEFAULT_COMPACT_COUNTER_FORMAT,
49
+ DEFAULT_COMPACT_TRIGGER_ARIA_LABEL_FORMAT,
50
+ DEFAULT_COMPACT_TRIGGER_ARIA_LABEL_FORMAT_WITH_LABEL,
51
+ formatCompactTemplate,
52
+ resolveCompactCounterFormat,
53
+ resolveCompactMenuAndPopAriaLabel,
54
+ resolveCompactTriggerAriaLabel,
55
+ resolveCompactTriggerAriaLabelFormat
56
+ };
@@ -0,0 +1,26 @@
1
+ type TCompactElements = {
2
+ actionMenu: HTMLElementTagNameMap['sinch-action-menu'];
3
+ pop: HTMLElementTagNameMap['sinch-pop'];
4
+ trigger: HTMLButtonElement;
5
+ label: HTMLElement;
6
+ counter: HTMLElement;
7
+ };
8
+ type TCompactSyncParams = {
9
+ usesCompactActionMenu: boolean;
10
+ items: HTMLElement[];
11
+ hostAriaLabel: string | null;
12
+ compactCounterFormat: string;
13
+ compactTriggerAriaLabelFormat: string;
14
+ getCheckedItemIndex: () => number;
15
+ getFirstActiveItemIndex: () => number;
16
+ onChange: (value: string) => void;
17
+ };
18
+ export declare class ProgressStepperCompactController {
19
+ #private;
20
+ constructor(elements: TCompactElements);
21
+ connect(signal: AbortSignal): void;
22
+ onTriggerClick(usesCompactActionMenu: boolean): void;
23
+ onPopoverClose(): void;
24
+ sync(params: TCompactSyncParams): void;
25
+ }
26
+ export {};