@nectary/components 5.38.0 → 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.
- package/bundle.d.ts +2 -0
- package/bundle.js +1756 -267
- package/bundle.ts +2 -0
- package/package.json +3 -3
- package/progress-stepper-item-v2/global/index.d.ts +1 -0
- package/progress-stepper-item-v2/global/index.js +2 -0
- package/progress-stepper-item-v2/index.d.ts +23 -0
- package/progress-stepper-item-v2/index.js +187 -0
- package/progress-stepper-item-v2/types.d.ts +69 -0
- package/progress-stepper-item-v2/types.js +1 -0
- package/progress-stepper-item-v2/utils.d.ts +22 -0
- package/progress-stepper-item-v2/utils.js +88 -0
- package/progress-stepper-v2/compact-format.d.ts +22 -0
- package/progress-stepper-v2/compact-format.js +56 -0
- package/progress-stepper-v2/compact.d.ts +26 -0
- package/progress-stepper-v2/compact.js +330 -0
- package/progress-stepper-v2/global/index.d.ts +1 -0
- package/progress-stepper-v2/global/index.js +2 -0
- package/progress-stepper-v2/index.d.ts +31 -0
- package/progress-stepper-v2/index.js +618 -0
- package/progress-stepper-v2/model.d.ts +32 -0
- package/progress-stepper-v2/model.js +59 -0
- package/progress-stepper-v2/orientation.d.ts +8 -0
- package/progress-stepper-v2/orientation.js +24 -0
- package/progress-stepper-v2/separators.d.ts +1 -0
- package/progress-stepper-v2/separators.js +48 -0
- package/progress-stepper-v2/step-chip.d.ts +9 -0
- package/progress-stepper-v2/step-chip.js +126 -0
- package/progress-stepper-v2/types.d.ts +66 -0
- package/progress-stepper-v2/types.js +1 -0
- package/standalone.d.ts +2 -0
- package/standalone.js +2 -0
- package/standalone.ts +2 -0
- package/toast/index.js +4 -2
- package/toast/types.d.ts +1 -1
- package/toast-manager/index.js +22 -7
- package/utils/component-names.d.ts +2 -2
- package/utils/component-names.js +2 -0
- package/utils/dom.d.ts +1 -0
- package/utils/dom.js +9 -0
- package/utils/element.d.ts +2 -0
- package/utils/index.js +2 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
function deriveStepStatuses(items, params) {
|
|
2
|
+
const { noCompletionOrder, progressValue } = params;
|
|
3
|
+
if (noCompletionOrder) {
|
|
4
|
+
return items.map((item) => {
|
|
5
|
+
if (item.disabled) {
|
|
6
|
+
return "inactive";
|
|
7
|
+
}
|
|
8
|
+
if (item.complete) {
|
|
9
|
+
return "complete";
|
|
10
|
+
}
|
|
11
|
+
return "incomplete";
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
let progressIndex = items.findIndex((it) => it.value === progressValue);
|
|
15
|
+
if (progressIndex < 0 && items.length > 0) {
|
|
16
|
+
progressIndex = 0;
|
|
17
|
+
}
|
|
18
|
+
return items.map((_, i) => {
|
|
19
|
+
if (progressIndex < 0 || progressIndex < i) {
|
|
20
|
+
return "inactive";
|
|
21
|
+
}
|
|
22
|
+
if (progressIndex > i) {
|
|
23
|
+
return "complete";
|
|
24
|
+
}
|
|
25
|
+
return "incomplete";
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function computeOrientationLayout(params) {
|
|
29
|
+
const {
|
|
30
|
+
noAutoOrientation,
|
|
31
|
+
containerWidth,
|
|
32
|
+
wrapperScrollWidth
|
|
33
|
+
} = params;
|
|
34
|
+
if (noAutoOrientation) {
|
|
35
|
+
return {
|
|
36
|
+
isHorizontal: true,
|
|
37
|
+
dataOrientation: "horizontal",
|
|
38
|
+
mode: "horizontal"
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const safeWidth = Math.max(containerWidth, 1);
|
|
42
|
+
const isHorizontal = wrapperScrollWidth <= safeWidth;
|
|
43
|
+
if (isHorizontal) {
|
|
44
|
+
return {
|
|
45
|
+
isHorizontal: true,
|
|
46
|
+
dataOrientation: "horizontal",
|
|
47
|
+
mode: "horizontal"
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
isHorizontal: false,
|
|
52
|
+
dataOrientation: "vertical",
|
|
53
|
+
mode: "compact"
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
computeOrientationLayout,
|
|
58
|
+
deriveStepStatuses
|
|
59
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class OrientationScheduler {
|
|
2
|
+
constructor(run) {
|
|
3
|
+
this.run = run;
|
|
4
|
+
}
|
|
5
|
+
#rafId = null;
|
|
6
|
+
schedule() {
|
|
7
|
+
if (this.#rafId !== null) {
|
|
8
|
+
cancelAnimationFrame(this.#rafId);
|
|
9
|
+
}
|
|
10
|
+
this.#rafId = requestAnimationFrame(() => {
|
|
11
|
+
this.#rafId = null;
|
|
12
|
+
this.run();
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
cancel() {
|
|
16
|
+
if (this.#rafId !== null) {
|
|
17
|
+
cancelAnimationFrame(this.#rafId);
|
|
18
|
+
this.#rafId = null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
OrientationScheduler
|
|
24
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function syncStepSeparators(host: HTMLElement, itemTagName: string): void;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { createScopedElement } from "../utils/dom.js";
|
|
2
|
+
const TAG_STEP_SEPARATOR_ICON = "sinch-icon";
|
|
3
|
+
const ATTR_STEP_SEPARATOR = "data-nectary-progress-stepper-v2-separator";
|
|
4
|
+
function isStepSeparatorNode(el) {
|
|
5
|
+
return el instanceof HTMLElement && el.tagName.toLowerCase() === TAG_STEP_SEPARATOR_ICON && el.hasAttribute(ATTR_STEP_SEPARATOR);
|
|
6
|
+
}
|
|
7
|
+
function separatorsPlacementValid(items) {
|
|
8
|
+
for (let i = 0; i < items.length - 1; i++) {
|
|
9
|
+
const between = items[i].nextElementSibling;
|
|
10
|
+
if (!isStepSeparatorNode(between)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
if (between.nextElementSibling !== items[i + 1]) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
function createStepSeparator(anchor) {
|
|
20
|
+
const icon = createScopedElement(anchor, TAG_STEP_SEPARATOR_ICON);
|
|
21
|
+
icon.setAttribute(ATTR_STEP_SEPARATOR, "");
|
|
22
|
+
icon.setAttribute("icons-version", "2");
|
|
23
|
+
icon.setAttribute("name", "fa-chevron-right");
|
|
24
|
+
icon.setAttribute("aria-hidden", "true");
|
|
25
|
+
icon.setAttribute("tabindex", "-1");
|
|
26
|
+
return icon;
|
|
27
|
+
}
|
|
28
|
+
function syncStepSeparators(host, itemTagName) {
|
|
29
|
+
const normalizedItemTagName = itemTagName.toLowerCase();
|
|
30
|
+
const items = [...host.children].filter(
|
|
31
|
+
(el) => el.tagName.toLowerCase() === normalizedItemTagName
|
|
32
|
+
);
|
|
33
|
+
const separators = [...host.children].filter(isStepSeparatorNode);
|
|
34
|
+
if (items.length <= 1) {
|
|
35
|
+
separators.forEach((n) => n.remove());
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (separators.length === items.length - 1 && separatorsPlacementValid(items)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
separators.forEach((n) => n.remove());
|
|
42
|
+
for (let i = 0; i < items.length - 1; i++) {
|
|
43
|
+
items[i].insertAdjacentElement("afterend", createStepSeparator(host));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
syncStepSeparators
|
|
48
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import '../icon';
|
|
2
|
+
export type TSinchProgressStepperStepChipModel = {
|
|
3
|
+
/** Resolved step label (e.g. `"3"`). */
|
|
4
|
+
stepIndexDisplay: string;
|
|
5
|
+
status: string;
|
|
6
|
+
invalid: boolean;
|
|
7
|
+
checked: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare const fillProgressStepperStepChipHost: (host: HTMLElement, model: TSinchProgressStepperStepChipModel) => void;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import "../icon/index.js";
|
|
2
|
+
import { createScopedElement } from "../utils/dom.js";
|
|
3
|
+
const STEP_CHIP_TOKEN = "--sinch-comp-progress-stepper-v2-step";
|
|
4
|
+
const chipStyles = new CSSStyleSheet();
|
|
5
|
+
chipStyles.replaceSync(`
|
|
6
|
+
.step-chip {
|
|
7
|
+
display: inline-grid;
|
|
8
|
+
place-items: center;
|
|
9
|
+
width: 24px;
|
|
10
|
+
height: 24px;
|
|
11
|
+
border-radius: var(${STEP_CHIP_TOKEN}-shape-radius-indicator);
|
|
12
|
+
flex-shrink: 0;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
vertical-align: middle;
|
|
15
|
+
line-height: var(--sinch-comp-text-line-height);
|
|
16
|
+
font: var(--sinch-sys-font-body-s);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.step-chip[data-checked] {
|
|
20
|
+
font: var(--sinch-sys-font-body-emphasize-s);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.step-chip[data-status="incomplete"] {
|
|
24
|
+
background: var(${STEP_CHIP_TOKEN}-color-incomplete-icon-container-initial);
|
|
25
|
+
color: var(${STEP_CHIP_TOKEN}-color-incomplete-icon-initial);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.step-chip[data-status="incomplete"][data-checked] {
|
|
29
|
+
background: var(${STEP_CHIP_TOKEN}-color-incomplete-icon-container-current);
|
|
30
|
+
color: var(${STEP_CHIP_TOKEN}-color-incomplete-icon-current);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.step-chip[data-status="complete"] {
|
|
34
|
+
background: var(${STEP_CHIP_TOKEN}-color-complete-icon-container-initial);
|
|
35
|
+
color: var(${STEP_CHIP_TOKEN}-color-complete-icon-initial);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.step-chip[data-status="complete"][data-checked] {
|
|
39
|
+
background: var(${STEP_CHIP_TOKEN}-color-complete-icon-container-current);
|
|
40
|
+
color: var(${STEP_CHIP_TOKEN}-color-complete-icon-current);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.step-chip[data-invalid] {
|
|
44
|
+
background: var(${STEP_CHIP_TOKEN}-color-invalid-icon-container-initial);
|
|
45
|
+
color: var(${STEP_CHIP_TOKEN}-color-invalid-icon-initial);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.step-chip[data-invalid][data-checked] {
|
|
49
|
+
background: var(${STEP_CHIP_TOKEN}-color-invalid-icon-container-current);
|
|
50
|
+
color: var(${STEP_CHIP_TOKEN}-color-invalid-icon-current);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.step-chip__num,
|
|
54
|
+
.step-chip__check,
|
|
55
|
+
.step-chip__warn {
|
|
56
|
+
grid-area: 1 / 1;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.step-chip__check,
|
|
60
|
+
.step-chip__warn {
|
|
61
|
+
display: none;
|
|
62
|
+
--sinch-global-size-icon: 20px;
|
|
63
|
+
--sinch-global-color-icon: currentcolor;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.step-chip[data-invalid] .step-chip__num,
|
|
67
|
+
.step-chip[data-status="complete"] .step-chip__num {
|
|
68
|
+
display: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.step-chip[data-invalid] .step-chip__warn {
|
|
72
|
+
display: block;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.step-chip[data-status="complete"]:not([data-invalid]) .step-chip__check {
|
|
76
|
+
display: block;
|
|
77
|
+
}
|
|
78
|
+
`);
|
|
79
|
+
const adoptChipStylesOnce = (root) => {
|
|
80
|
+
if (!root.adoptedStyleSheets.includes(chipStyles)) {
|
|
81
|
+
root.adoptedStyleSheets = [...root.adoptedStyleSheets, chipStyles];
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const ensureChipStyles = (host) => {
|
|
85
|
+
const root = host.getRootNode();
|
|
86
|
+
if (root instanceof ShadowRoot || root instanceof Document) {
|
|
87
|
+
adoptChipStylesOnce(root);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const buildProgressStepperStepChip = (anchor) => {
|
|
91
|
+
const chip = document.createElement("span");
|
|
92
|
+
chip.className = "step-chip";
|
|
93
|
+
chip.setAttribute("aria-hidden", "true");
|
|
94
|
+
const num = document.createElement("span");
|
|
95
|
+
num.className = "step-chip__num";
|
|
96
|
+
const check = createScopedElement(anchor, "sinch-icon");
|
|
97
|
+
check.className = "step-chip__check";
|
|
98
|
+
check.setAttribute("icons-version", "2");
|
|
99
|
+
check.setAttribute("name", "fa-check");
|
|
100
|
+
check.setAttribute("aria-hidden", "true");
|
|
101
|
+
const warn = createScopedElement(anchor, "sinch-icon");
|
|
102
|
+
warn.className = "step-chip__warn";
|
|
103
|
+
warn.setAttribute("icons-version", "2");
|
|
104
|
+
warn.setAttribute("name", "triangle-exclamation");
|
|
105
|
+
warn.setAttribute("aria-hidden", "true");
|
|
106
|
+
chip.append(num, check, warn);
|
|
107
|
+
return chip;
|
|
108
|
+
};
|
|
109
|
+
const fillProgressStepperStepChipHost = (host, model) => {
|
|
110
|
+
ensureChipStyles(host);
|
|
111
|
+
let chip = host.querySelector(":scope > .step-chip");
|
|
112
|
+
if (!(chip instanceof HTMLElement)) {
|
|
113
|
+
chip = buildProgressStepperStepChip(host);
|
|
114
|
+
host.appendChild(chip);
|
|
115
|
+
}
|
|
116
|
+
chip.toggleAttribute("data-invalid", model.invalid);
|
|
117
|
+
chip.toggleAttribute("data-checked", model.checked);
|
|
118
|
+
chip.setAttribute(
|
|
119
|
+
"data-status",
|
|
120
|
+
model.status === "inactive" ? "incomplete" : model.status
|
|
121
|
+
);
|
|
122
|
+
chip.querySelector(".step-chip__num").textContent = model.stepIndexDisplay;
|
|
123
|
+
};
|
|
124
|
+
export {
|
|
125
|
+
fillProgressStepperStepChipHost
|
|
126
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { NectaryComponentReactByType, NectaryComponentVanillaByType, NectaryComponentReact, NectaryComponentVanilla } from '../types';
|
|
2
|
+
export type TSinchProgressStepperV2Props = {
|
|
3
|
+
/** Current selected item value */
|
|
4
|
+
value: string;
|
|
5
|
+
/**
|
|
6
|
+
* Accessible name for the stepper. Recommended when the layout collapses to compact
|
|
7
|
+
* (short widget name for the listbox/popover). When omitted in compact mode, the
|
|
8
|
+
* menu and popover use the same derived name as the trigger (`{current} of {total}, {step}`).
|
|
9
|
+
*/
|
|
10
|
+
'aria-label'?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Template for the compact trigger counter badge.
|
|
13
|
+
* Placeholders: `{current}`, `{total}`.
|
|
14
|
+
* Default when unset: `{current} of {total}`.
|
|
15
|
+
*/
|
|
16
|
+
'compact-counter-format'?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Template for the compact trigger `aria-label`.
|
|
19
|
+
* Placeholders: `{label}`, `{current}`, `{total}`, `{step}`.
|
|
20
|
+
* Default when unset: `{label}, {current} of {total}, {step}` if `aria-label` is set,
|
|
21
|
+
* otherwise `{current} of {total}, {step}`.
|
|
22
|
+
*/
|
|
23
|
+
'compact-trigger-aria-label-format'?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Current progress value used to derive each item's status in ordered mode (default).
|
|
26
|
+
* Ignored when `noCompletionOrder` is set.
|
|
27
|
+
*/
|
|
28
|
+
progressValue?: string;
|
|
29
|
+
/**
|
|
30
|
+
* When set, step statuses are controlled by per-item `complete` / `disabled` attributes
|
|
31
|
+
* instead of deriving order from `progressValue`.
|
|
32
|
+
*/
|
|
33
|
+
noCompletionOrder?: boolean;
|
|
34
|
+
/** When set, orientation stays horizontal and does not auto-switch to vertical on overflow. */
|
|
35
|
+
noAutoOrientation?: boolean;
|
|
36
|
+
};
|
|
37
|
+
export type TSinchProgressStepperV2Events = {
|
|
38
|
+
/** Change selected value event */
|
|
39
|
+
'-change'?: (e: CustomEvent<string>) => void;
|
|
40
|
+
};
|
|
41
|
+
export type TSinchProgressStepperV2 = {
|
|
42
|
+
props: TSinchProgressStepperV2Props;
|
|
43
|
+
events: TSinchProgressStepperV2Events;
|
|
44
|
+
};
|
|
45
|
+
export type TSinchProgressStepperV2Element = NectaryComponentVanillaByType<TSinchProgressStepperV2>;
|
|
46
|
+
export type TSinchProgressStepperV2React = NectaryComponentReactByType<TSinchProgressStepperV2>;
|
|
47
|
+
declare global {
|
|
48
|
+
interface NectaryComponentMap {
|
|
49
|
+
'sinch-progress-stepper-v2': TSinchProgressStepperV2;
|
|
50
|
+
}
|
|
51
|
+
interface HTMLElementTagNameMap {
|
|
52
|
+
'sinch-progress-stepper-v2': NectaryComponentVanilla<'sinch-progress-stepper-v2'>;
|
|
53
|
+
}
|
|
54
|
+
namespace JSX {
|
|
55
|
+
interface IntrinsicElements {
|
|
56
|
+
'sinch-progress-stepper-v2': NectaryComponentReact<'sinch-progress-stepper-v2'>;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
declare module 'react' {
|
|
61
|
+
namespace JSX {
|
|
62
|
+
interface IntrinsicElements extends globalThis.JSX.IntrinsicElements {
|
|
63
|
+
'sinch-progress-stepper-v2': NectaryComponentReact<'sinch-progress-stepper-v2'>;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
package/standalone.d.ts
CHANGED
|
@@ -43,7 +43,9 @@ import './pagination/index.js';
|
|
|
43
43
|
import './persistent-overlay/index.js';
|
|
44
44
|
import './pop/index.js';
|
|
45
45
|
import './popover/index.js';
|
|
46
|
+
import './progress-stepper-item-v2/index.js';
|
|
46
47
|
import './progress-stepper-item/index.js';
|
|
48
|
+
import './progress-stepper-v2/index.js';
|
|
47
49
|
import './progress-stepper/index.js';
|
|
48
50
|
import './progress/index.js';
|
|
49
51
|
import './radio-option/index.js';
|
package/standalone.js
CHANGED
|
@@ -44,7 +44,9 @@ import "./pagination/index.js";
|
|
|
44
44
|
import "./persistent-overlay/index.js";
|
|
45
45
|
import "./pop/index.js";
|
|
46
46
|
import "./popover/index.js";
|
|
47
|
+
import "./progress-stepper-item-v2/index.js";
|
|
47
48
|
import "./progress-stepper-item/index.js";
|
|
49
|
+
import "./progress-stepper-v2/index.js";
|
|
48
50
|
import "./progress-stepper/index.js";
|
|
49
51
|
import "./progress/index.js";
|
|
50
52
|
import "./radio-option/index.js";
|
package/standalone.ts
CHANGED
|
@@ -51,7 +51,9 @@ import './pagination/index.js'
|
|
|
51
51
|
import './persistent-overlay/index.js'
|
|
52
52
|
import './pop/index.js'
|
|
53
53
|
import './popover/index.js'
|
|
54
|
+
import './progress-stepper-item-v2/index.js'
|
|
54
55
|
import './progress-stepper-item/index.js'
|
|
56
|
+
import './progress-stepper-v2/index.js'
|
|
55
57
|
import './progress-stepper/index.js'
|
|
56
58
|
import './progress/index.js'
|
|
57
59
|
import './radio-option/index.js'
|
package/toast/index.js
CHANGED
|
@@ -29,7 +29,7 @@ class Toast extends NectaryElement {
|
|
|
29
29
|
this.#clearTimeout();
|
|
30
30
|
}
|
|
31
31
|
static get observedAttributes() {
|
|
32
|
-
return ["text", "persistent"];
|
|
32
|
+
return ["text", "type", "persistent"];
|
|
33
33
|
}
|
|
34
34
|
attributeChangedCallback(name, oldVal, newVal) {
|
|
35
35
|
switch (name) {
|
|
@@ -37,6 +37,7 @@ class Toast extends NectaryElement {
|
|
|
37
37
|
updateAttribute(this.#$text, name, newVal);
|
|
38
38
|
break;
|
|
39
39
|
}
|
|
40
|
+
case "type":
|
|
40
41
|
case "persistent": {
|
|
41
42
|
this.#updateTimeout();
|
|
42
43
|
break;
|
|
@@ -62,7 +63,8 @@ class Toast extends NectaryElement {
|
|
|
62
63
|
updateBooleanAttribute(this, "persistent", isPersistent);
|
|
63
64
|
}
|
|
64
65
|
#updateTimeout() {
|
|
65
|
-
|
|
66
|
+
const type = getAttribute(this, "type");
|
|
67
|
+
if (this.persistent || type === "error" || type === "warn") {
|
|
66
68
|
this.#clearTimeout();
|
|
67
69
|
return;
|
|
68
70
|
}
|
package/toast/types.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type TSinchToastProps = {
|
|
|
5
5
|
type: TSinchToastType;
|
|
6
6
|
/** Text */
|
|
7
7
|
text: string;
|
|
8
|
-
/** Persistent, i.e. doesn't automatically
|
|
8
|
+
/** Persistent, i.e. doesn't automatically disappear after 5s. Error and warn toasts are always persistent. */
|
|
9
9
|
persistent?: boolean;
|
|
10
10
|
};
|
|
11
11
|
export type TSinchToastEvents = {
|
package/toast-manager/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { shouldReduceMotion, getLiteralAttribute, updateLiteralAttribute, cloneN
|
|
|
5
5
|
import { defineCustomElement, NectaryElement } from "../utils/element.js";
|
|
6
6
|
import { getRect } from "../utils/rect.js";
|
|
7
7
|
import { originValues } from "./utils.js";
|
|
8
|
-
const templateHTML = '<style>:host{display:block}#items{display:block;width:0;height:0;visibility:hidden;overflow:hidden}#list{display:flex;flex-direction:column;position:fixed;z-index:1;bottom:0;right:16px}:host([origin=top-right]) #list{flex-direction:column-reverse;bottom:unset;top:16px}.item-wrapper{height:0;opacity:0;position:relative}.item-wrapper[data-deleting]::after{content:"";position:absolute;top:0;left:0;bottom:0;right:0}</style><slot id="items"></slot><div id="list" aria-live="polite"></div>';
|
|
8
|
+
const templateHTML = '<style>:host{display:block}#items{display:block;width:0;height:0;visibility:hidden;overflow:hidden}#list{display:flex;flex-direction:column;position:fixed;z-index:1;bottom:0;right:16px}:host([origin=top-right]) #list{flex-direction:column-reverse;bottom:unset;top:16px}.item-wrapper{height:0;opacity:0;position:relative}.item-wrapper[data-deleting]::after{content:"";position:absolute;top:0;left:0;bottom:0;right:0}</style><slot id="items"></slot><div id="list" role="status" aria-live="polite" aria-atomic="false"></div>';
|
|
9
9
|
const DURATION_ADD = 250;
|
|
10
10
|
const DURATION_REMOVE = 250;
|
|
11
11
|
const ITEMS_GAP = 16;
|
|
@@ -116,6 +116,27 @@ class ToastManager extends NectaryElement {
|
|
|
116
116
|
this.#onAnimateRemove(item, removeIndex);
|
|
117
117
|
++removeIndex;
|
|
118
118
|
}
|
|
119
|
+
let hasNewItems = false;
|
|
120
|
+
let isAssertive = false;
|
|
121
|
+
for (const item of slotItems) {
|
|
122
|
+
if (this.#map.has(item)) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
hasNewItems = true;
|
|
126
|
+
if (item instanceof Toast) {
|
|
127
|
+
const type = item.type;
|
|
128
|
+
if (type === "error" || type === "warn") {
|
|
129
|
+
isAssertive = true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (slotItems.length === 0) {
|
|
134
|
+
this.#$list.setAttribute("role", "status");
|
|
135
|
+
this.#$list.setAttribute("aria-live", "polite");
|
|
136
|
+
} else if (hasNewItems) {
|
|
137
|
+
this.#$list.setAttribute("role", isAssertive ? "alert" : "status");
|
|
138
|
+
this.#$list.setAttribute("aria-live", isAssertive ? "assertive" : "polite");
|
|
139
|
+
}
|
|
119
140
|
let addIndex = 0;
|
|
120
141
|
for (const item of slotItems) {
|
|
121
142
|
if (this.#map.has(item)) {
|
|
@@ -124,12 +145,6 @@ class ToastManager extends NectaryElement {
|
|
|
124
145
|
const cloned = cloneNode(item, true);
|
|
125
146
|
const rect = item.getBoundingClientRect();
|
|
126
147
|
const wrapper = document.createElement("div");
|
|
127
|
-
if (item instanceof Toast) {
|
|
128
|
-
if (item.hasAttribute("type")) {
|
|
129
|
-
const type = item.type;
|
|
130
|
-
this.#$list.setAttribute("aria-live", type === "error" || type === "warn" ? "assertive" : "polite");
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
148
|
wrapper.className = "item-wrapper";
|
|
134
149
|
wrapper.appendChild(cloned);
|
|
135
150
|
this.#$list.appendChild(wrapper);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const BASE_COMPONENT_NAMES_LIST: readonly ["accordion-item", "accordion", "action-menu-option", "action-menu", "alert", "avatar", "badge", "button-group-item", "button-group", "button", "card-container", "card-v2-title", "card-v2", "checkbox", "chip", "code-tag", "color-menu-option", "color-menu", "color-swatch", "date-picker", "dialog", "emoji-picker", "emoji", "field", "field-v2", "file-drop", "file-picker", "file-status", "flag", "floating-panel", "floating-panel-button", "floating-panel-icon-button", "grid-item", "grid", "help-tooltip", "icon", "inline-alert", "input", "link", "list-item", "list", "pagination", "persistent-overlay", "pop", "popover", "progress-stepper-item", "progress-stepper", "progress", "radio-option", "radio", "rich-text", "rich-textarea", "rich-textarea-chip", "segment-collapse", "segmented-control-option", "segmented-control", "segmented-icon-control-option", "segmented-icon-control", "select-button", "select-menu-option", "select-menu", "sheet", "sheet-title", "skeleton-item", "skeleton", "spinner", "stop-events", "table-body", "table-cell", "table-head-cell", "table-head", "table-row", "table", "tabs-icon-option", "tabs-option", "tabs", "tag", "text", "textarea", "time-picker", "title", "toast-manager", "toast", "toggle", "tooltip"];
|
|
2
|
-
export declare const BASE_COMPONENT_NAMES: Set<"pop" | "button" | "dialog" | "input" | "link" | "progress" | "table" | "textarea" | "title" | "accordion-item" | "accordion" | "action-menu-option" | "action-menu" | "alert" | "avatar" | "badge" | "button-group-item" | "button-group" | "card-container" | "card-v2-title" | "card-v2" | "checkbox" | "
|
|
1
|
+
export declare const BASE_COMPONENT_NAMES_LIST: readonly ["accordion-item", "accordion", "action-menu-option", "action-menu", "alert", "avatar", "badge", "button-group-item", "button-group", "button", "card-container", "card-v2-title", "card-v2", "checkbox", "chip", "code-tag", "color-menu-option", "color-menu", "color-swatch", "date-picker", "dialog", "emoji-picker", "emoji", "field", "field-v2", "file-drop", "file-picker", "file-status", "flag", "floating-panel", "floating-panel-button", "floating-panel-icon-button", "grid-item", "grid", "help-tooltip", "icon", "inline-alert", "input", "link", "list-item", "list", "pagination", "persistent-overlay", "pop", "popover", "progress-stepper-item-v2", "progress-stepper-item", "progress-stepper-v2", "progress-stepper", "progress", "radio-option", "radio", "rich-text", "rich-textarea", "rich-textarea-chip", "segment-collapse", "segmented-control-option", "segmented-control", "segmented-icon-control-option", "segmented-icon-control", "select-button", "select-menu-option", "select-menu", "sheet", "sheet-title", "skeleton-item", "skeleton", "spinner", "stop-events", "table-body", "table-cell", "table-head-cell", "table-head", "table-row", "table", "tabs-icon-option", "tabs-option", "tabs", "tag", "text", "textarea", "time-picker", "title", "toast-manager", "toast", "toggle", "tooltip"];
|
|
2
|
+
export declare const BASE_COMPONENT_NAMES: Set<"pop" | "button" | "dialog" | "input" | "link" | "progress" | "table" | "textarea" | "title" | "popover" | "text" | "icon" | "chip" | "accordion-item" | "accordion" | "action-menu-option" | "action-menu" | "alert" | "avatar" | "badge" | "button-group-item" | "button-group" | "card-container" | "card-v2-title" | "card-v2" | "checkbox" | "code-tag" | "color-menu-option" | "color-menu" | "color-swatch" | "date-picker" | "emoji-picker" | "emoji" | "field" | "field-v2" | "file-drop" | "file-picker" | "file-status" | "flag" | "floating-panel" | "floating-panel-button" | "floating-panel-icon-button" | "grid-item" | "grid" | "help-tooltip" | "inline-alert" | "list-item" | "list" | "pagination" | "persistent-overlay" | "progress-stepper-item-v2" | "progress-stepper-item" | "progress-stepper-v2" | "progress-stepper" | "radio-option" | "radio" | "rich-text" | "rich-textarea" | "rich-textarea-chip" | "segment-collapse" | "segmented-control-option" | "segmented-control" | "segmented-icon-control-option" | "segmented-icon-control" | "select-button" | "select-menu-option" | "select-menu" | "sheet" | "sheet-title" | "skeleton-item" | "skeleton" | "spinner" | "stop-events" | "table-body" | "table-cell" | "table-head-cell" | "table-head" | "table-row" | "tabs-icon-option" | "tabs-option" | "tabs" | "tag" | "time-picker" | "toast-manager" | "toast" | "toggle" | "tooltip">;
|
|
3
3
|
export type ComponentName = `sinch-${typeof BASE_COMPONENT_NAMES_LIST[number]}`;
|
package/utils/component-names.js
CHANGED
package/utils/dom.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export declare const getDeepActiveElement: (ownerDocument?: Document) => Element
|
|
|
35
35
|
export declare const composedContains: (container: Node, node: Node | null) => boolean;
|
|
36
36
|
export declare const isAttrEqual: (oldVal: string | null, newVal: string | null) => boolean;
|
|
37
37
|
export declare const getScrollableParents: (node: HTMLElement | null) => (HTMLElement | Document)[];
|
|
38
|
+
export declare const createScopedElement: <K extends keyof HTMLElementTagNameMap>(anchor: Element, tag: K) => HTMLElementTagNameMap[K];
|
|
38
39
|
export declare const isTransformedElement: (element: HTMLElement | null) => element is HTMLElement;
|
|
39
40
|
export declare const getTransformedAncestor: (node: HTMLElement | null) => HTMLElement | null;
|
|
40
41
|
export {};
|
package/utils/dom.js
CHANGED
|
@@ -179,6 +179,14 @@ const getScrollableParents = (node) => {
|
|
|
179
179
|
scrollableParents.push(document);
|
|
180
180
|
return scrollableParents;
|
|
181
181
|
};
|
|
182
|
+
const createScopedElement = (anchor, tag) => {
|
|
183
|
+
const root = anchor.getRootNode();
|
|
184
|
+
const shadowCreateElement = root.createElement;
|
|
185
|
+
if (typeof shadowCreateElement === "function") {
|
|
186
|
+
return shadowCreateElement.call(root, tag);
|
|
187
|
+
}
|
|
188
|
+
return document.createElement(tag);
|
|
189
|
+
};
|
|
182
190
|
const isTransformedElement = (element) => {
|
|
183
191
|
if (element == null) {
|
|
184
192
|
return false;
|
|
@@ -217,6 +225,7 @@ export {
|
|
|
217
225
|
clampNumber,
|
|
218
226
|
cloneNode,
|
|
219
227
|
composedContains,
|
|
228
|
+
createScopedElement,
|
|
220
229
|
getAttribute,
|
|
221
230
|
getBooleanAttribute,
|
|
222
231
|
getCssVar,
|
package/utils/element.d.ts
CHANGED
package/utils/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Context, subscribeContext } from "./context.js";
|
|
2
2
|
import { CSV_DELIMITER, getFirstCsvValue, packCsv, unpackCsv, updateCsv } from "./csv.js";
|
|
3
|
-
import { attrValueToInteger, attrValueToPixels, clampNumber, cloneNode, composedContains, getAttribute, getBooleanAttribute, getCssVar, getCssVars, getDeepActiveElement, getIntegerAttribute, getLiteralAttribute, getScrollableParents, getTransformedAncestor, hasClass, isAttrEqual, isAttrTrue, isLiteralValue, isTransformedElement, setClass, shouldReduceMotion, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateIntegerAttribute, updateLiteralAttribute } from "./dom.js";
|
|
3
|
+
import { attrValueToInteger, attrValueToPixels, clampNumber, cloneNode, composedContains, createScopedElement, getAttribute, getBooleanAttribute, getCssVar, getCssVars, getDeepActiveElement, getIntegerAttribute, getLiteralAttribute, getScrollableParents, getTransformedAncestor, hasClass, isAttrEqual, isAttrTrue, isLiteralValue, isTransformedElement, setClass, shouldReduceMotion, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateIntegerAttribute, updateLiteralAttribute } from "./dom.js";
|
|
4
4
|
import { NectaryElement, defineCustomElement, pascalToKebabCase, registerComponent, resetNectaryRegistry, setNectaryRegistry } from "./element.js";
|
|
5
5
|
import { getRect, getTargetRect, rectOverlap } from "./rect.js";
|
|
6
6
|
import { getFirstFocusableElement, getFirstSlotElement, isElementFocused } from "./slot.js";
|
|
@@ -20,6 +20,7 @@ export {
|
|
|
20
20
|
clampNumber,
|
|
21
21
|
cloneNode,
|
|
22
22
|
composedContains,
|
|
23
|
+
createScopedElement,
|
|
23
24
|
debounceAnimationFrame,
|
|
24
25
|
debounceTimeout,
|
|
25
26
|
defineCustomElement,
|