@hjmds/design-contracts 0.8.2
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/README.md +208 -0
- package/dist/alert-dialog.d.ts +102 -0
- package/dist/alert-dialog.d.ts.map +1 -0
- package/dist/alert-dialog.js +136 -0
- package/dist/alert-dialog.js.map +1 -0
- package/dist/base-recipes.d.ts +184 -0
- package/dist/base-recipes.d.ts.map +1 -0
- package/dist/base-recipes.js +129 -0
- package/dist/base-recipes.js.map +1 -0
- package/dist/behaviors.d.ts +1254 -0
- package/dist/behaviors.d.ts.map +1 -0
- package/dist/behaviors.js +972 -0
- package/dist/behaviors.js.map +1 -0
- package/dist/bottom-navigation-defaults.d.ts +13 -0
- package/dist/bottom-navigation-defaults.d.ts.map +1 -0
- package/dist/bottom-navigation-defaults.js +10 -0
- package/dist/bottom-navigation-defaults.js.map +1 -0
- package/dist/bottom-navigation.d.ts +114 -0
- package/dist/bottom-navigation.d.ts.map +1 -0
- package/dist/bottom-navigation.js +223 -0
- package/dist/bottom-navigation.js.map +1 -0
- package/dist/breadcrumb.d.ts +97 -0
- package/dist/breadcrumb.d.ts.map +1 -0
- package/dist/breadcrumb.js +99 -0
- package/dist/breadcrumb.js.map +1 -0
- package/dist/calendar.d.ts +285 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +297 -0
- package/dist/calendar.js.map +1 -0
- package/dist/card.d.ts +39 -0
- package/dist/card.d.ts.map +1 -0
- package/dist/card.js +50 -0
- package/dist/card.js.map +1 -0
- package/dist/carousel.d.ts +180 -0
- package/dist/carousel.d.ts.map +1 -0
- package/dist/carousel.js +172 -0
- package/dist/carousel.js.map +1 -0
- package/dist/catalog.d.ts +7158 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +220 -0
- package/dist/catalog.js.map +1 -0
- package/dist/collection.d.ts +123 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +211 -0
- package/dist/collection.js.map +1 -0
- package/dist/color-references.d.ts +46 -0
- package/dist/color-references.d.ts.map +1 -0
- package/dist/color-references.js +39 -0
- package/dist/color-references.js.map +1 -0
- package/dist/colors.d.ts +56 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +90 -0
- package/dist/colors.js.map +1 -0
- package/dist/command-palette.d.ts +240 -0
- package/dist/command-palette.d.ts.map +1 -0
- package/dist/command-palette.js +97 -0
- package/dist/command-palette.js.map +1 -0
- package/dist/component-contracts.d.ts +137 -0
- package/dist/component-contracts.d.ts.map +1 -0
- package/dist/component-contracts.js +53 -0
- package/dist/component-contracts.js.map +1 -0
- package/dist/component-definitions.d.ts +135 -0
- package/dist/component-definitions.d.ts.map +1 -0
- package/dist/component-definitions.js +142 -0
- package/dist/component-definitions.js.map +1 -0
- package/dist/component-recipes.d.ts +3583 -0
- package/dist/component-recipes.d.ts.map +1 -0
- package/dist/component-recipes.js +1503 -0
- package/dist/component-recipes.js.map +1 -0
- package/dist/component-references.d.ts +416 -0
- package/dist/component-references.d.ts.map +1 -0
- package/dist/component-references.js +140 -0
- package/dist/component-references.js.map +1 -0
- package/dist/content-state.d.ts +104 -0
- package/dist/content-state.d.ts.map +1 -0
- package/dist/content-state.js +116 -0
- package/dist/content-state.js.map +1 -0
- package/dist/counter-badge-recipe.d.ts +80 -0
- package/dist/counter-badge-recipe.d.ts.map +1 -0
- package/dist/counter-badge-recipe.js +44 -0
- package/dist/counter-badge-recipe.js.map +1 -0
- package/dist/counter-badge.d.ts +12 -0
- package/dist/counter-badge.d.ts.map +1 -0
- package/dist/counter-badge.js +21 -0
- package/dist/counter-badge.js.map +1 -0
- package/dist/data-table.d.ts +203 -0
- package/dist/data-table.d.ts.map +1 -0
- package/dist/data-table.js +182 -0
- package/dist/data-table.js.map +1 -0
- package/dist/date-picker.d.ts +268 -0
- package/dist/date-picker.d.ts.map +1 -0
- package/dist/date-picker.js +168 -0
- package/dist/date-picker.js.map +1 -0
- package/dist/description-list.d.ts +68 -0
- package/dist/description-list.d.ts.map +1 -0
- package/dist/description-list.js +85 -0
- package/dist/description-list.js.map +1 -0
- package/dist/design-system-provider.d.ts +80 -0
- package/dist/design-system-provider.d.ts.map +1 -0
- package/dist/design-system-provider.js +147 -0
- package/dist/design-system-provider.js.map +1 -0
- package/dist/evidence.d.ts +49 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +133 -0
- package/dist/evidence.js.map +1 -0
- package/dist/file-picker.d.ts +183 -0
- package/dist/file-picker.d.ts.map +1 -0
- package/dist/file-picker.js +224 -0
- package/dist/file-picker.js.map +1 -0
- package/dist/floating-action-button.d.ts +143 -0
- package/dist/floating-action-button.d.ts.map +1 -0
- package/dist/floating-action-button.js +149 -0
- package/dist/floating-action-button.js.map +1 -0
- package/dist/form.d.ts +143 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +206 -0
- package/dist/form.js.map +1 -0
- package/dist/foundations.d.ts +300 -0
- package/dist/foundations.d.ts.map +1 -0
- package/dist/foundations.js +238 -0
- package/dist/foundations.js.map +1 -0
- package/dist/grid.d.ts +75 -0
- package/dist/grid.d.ts.map +1 -0
- package/dist/grid.js +133 -0
- package/dist/grid.js.map +1 -0
- package/dist/icon-button-recipe.d.ts +99 -0
- package/dist/icon-button-recipe.d.ts.map +1 -0
- package/dist/icon-button-recipe.js +53 -0
- package/dist/icon-button-recipe.js.map +1 -0
- package/dist/icon.d.ts +41 -0
- package/dist/icon.d.ts.map +1 -0
- package/dist/icon.js +147 -0
- package/dist/icon.js.map +1 -0
- package/dist/image.d.ts +82 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +100 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +118 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +118 -0
- package/dist/layout.js.map +1 -0
- package/dist/link.d.ts +57 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +142 -0
- package/dist/link.js.map +1 -0
- package/dist/load-more.d.ts +64 -0
- package/dist/load-more.d.ts.map +1 -0
- package/dist/load-more.js +124 -0
- package/dist/load-more.js.map +1 -0
- package/dist/mentions.d.ts +67 -0
- package/dist/mentions.d.ts.map +1 -0
- package/dist/mentions.js +107 -0
- package/dist/mentions.js.map +1 -0
- package/dist/number-field.d.ts +208 -0
- package/dist/number-field.d.ts.map +1 -0
- package/dist/number-field.js +247 -0
- package/dist/number-field.js.map +1 -0
- package/dist/otp-field.d.ts +152 -0
- package/dist/otp-field.d.ts.map +1 -0
- package/dist/otp-field.js +117 -0
- package/dist/otp-field.js.map +1 -0
- package/dist/pagination.d.ts +181 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +226 -0
- package/dist/pagination.js.map +1 -0
- package/dist/password-field.d.ts +187 -0
- package/dist/password-field.d.ts.map +1 -0
- package/dist/password-field.js +120 -0
- package/dist/password-field.js.map +1 -0
- package/dist/popover.d.ts +152 -0
- package/dist/popover.d.ts.map +1 -0
- package/dist/popover.js +137 -0
- package/dist/popover.js.map +1 -0
- package/dist/progress-recipe.d.ts +43 -0
- package/dist/progress-recipe.d.ts.map +1 -0
- package/dist/progress-recipe.js +16 -0
- package/dist/progress-recipe.js.map +1 -0
- package/dist/recipes.d.ts +31 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/recipes.js +46 -0
- package/dist/recipes.js.map +1 -0
- package/dist/responsive.d.ts +27 -0
- package/dist/responsive.d.ts.map +1 -0
- package/dist/responsive.js +66 -0
- package/dist/responsive.js.map +1 -0
- package/dist/result.d.ts +111 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +97 -0
- package/dist/result.js.map +1 -0
- package/dist/selection-helpers.d.ts +16 -0
- package/dist/selection-helpers.d.ts.map +1 -0
- package/dist/selection-helpers.js +52 -0
- package/dist/selection-helpers.js.map +1 -0
- package/dist/semantic-colors.d.ts +275 -0
- package/dist/semantic-colors.d.ts.map +1 -0
- package/dist/semantic-colors.js +84 -0
- package/dist/semantic-colors.js.map +1 -0
- package/dist/sheet.d.ts +51 -0
- package/dist/sheet.d.ts.map +1 -0
- package/dist/sheet.js +69 -0
- package/dist/sheet.js.map +1 -0
- package/dist/showcase.d.ts +153 -0
- package/dist/showcase.d.ts.map +1 -0
- package/dist/showcase.js +210 -0
- package/dist/showcase.js.map +1 -0
- package/dist/side-panel.d.ts +199 -0
- package/dist/side-panel.d.ts.map +1 -0
- package/dist/side-panel.js +111 -0
- package/dist/side-panel.js.map +1 -0
- package/dist/slider.d.ts +138 -0
- package/dist/slider.d.ts.map +1 -0
- package/dist/slider.js +150 -0
- package/dist/slider.js.map +1 -0
- package/dist/splitter.d.ts +113 -0
- package/dist/splitter.d.ts.map +1 -0
- package/dist/splitter.js +99 -0
- package/dist/splitter.js.map +1 -0
- package/dist/statistic.d.ts +41 -0
- package/dist/statistic.d.ts.map +1 -0
- package/dist/statistic.js +76 -0
- package/dist/statistic.js.map +1 -0
- package/dist/steps.d.ts +196 -0
- package/dist/steps.d.ts.map +1 -0
- package/dist/steps.js +160 -0
- package/dist/steps.js.map +1 -0
- package/dist/tag.d.ts +128 -0
- package/dist/tag.d.ts.map +1 -0
- package/dist/tag.js +93 -0
- package/dist/tag.js.map +1 -0
- package/dist/timeline.d.ts +147 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +127 -0
- package/dist/timeline.js.map +1 -0
- package/dist/toast.d.ts +164 -0
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +529 -0
- package/dist/toast.js.map +1 -0
- package/dist/tokens.d.ts +9 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +9 -0
- package/dist/tokens.js.map +1 -0
- package/dist/tooltip.d.ts +44 -0
- package/dist/tooltip.d.ts.map +1 -0
- package/dist/tooltip.js +88 -0
- package/dist/tooltip.js.map +1 -0
- package/dist/tour.d.ts +218 -0
- package/dist/tour.d.ts.map +1 -0
- package/dist/tour.js +211 -0
- package/dist/tour.js.map +1 -0
- package/dist/transfer-list.d.ts +207 -0
- package/dist/transfer-list.d.ts.map +1 -0
- package/dist/transfer-list.js +193 -0
- package/dist/transfer-list.js.map +1 -0
- package/dist/tree-select.d.ts +78 -0
- package/dist/tree-select.d.ts.map +1 -0
- package/dist/tree-select.js +132 -0
- package/dist/tree-select.js.map +1 -0
- package/dist/tree.d.ts +206 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +223 -0
- package/dist/tree.js.map +1 -0
- package/dist/upload-item.d.ts +173 -0
- package/dist/upload-item.d.ts.map +1 -0
- package/dist/upload-item.js +156 -0
- package/dist/upload-item.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/docs/affix.md +63 -0
- package/docs/anchor.md +59 -0
- package/docs/ant-design-coverage.md +119 -0
- package/docs/app-provider.md +50 -0
- package/docs/app-rn-adoption.md +227 -0
- package/docs/architecture.md +320 -0
- package/docs/authoring-brief.md +87 -0
- package/docs/border-beam.md +66 -0
- package/docs/bottom-navigation.md +127 -0
- package/docs/breadcrumb.md +82 -0
- package/docs/calendar.md +154 -0
- package/docs/carousel.md +130 -0
- package/docs/cascader.md +93 -0
- package/docs/catalog-decision-status.md +306 -0
- package/docs/color-picker.md +72 -0
- package/docs/command-palette.md +116 -0
- package/docs/confirm-popover.md +93 -0
- package/docs/consistency-audit.md +383 -0
- package/docs/consumer-release-gate.md +90 -0
- package/docs/content-state.md +156 -0
- package/docs/context-panel.md +88 -0
- package/docs/cross-platform-core-normalization.md +118 -0
- package/docs/data-table.md +79 -0
- package/docs/date-picker.md +84 -0
- package/docs/description-list.md +75 -0
- package/docs/design-system-provider.md +139 -0
- package/docs/dropdown.md +78 -0
- package/docs/expansion-roadmap.md +285 -0
- package/docs/file-picker.md +59 -0
- package/docs/floating-action-button.md +111 -0
- package/docs/form.md +134 -0
- package/docs/generated/component-maturity.md +103 -0
- package/docs/generated/renderer-evidence.json +5597 -0
- package/docs/generated/renderer-evidence.md +132 -0
- package/docs/generated/showcase-manifest.json +3732 -0
- package/docs/icon.md +22 -0
- package/docs/identity.md +121 -0
- package/docs/image.md +84 -0
- package/docs/implementation-0.5.md +85 -0
- package/docs/layout-primitives.md +107 -0
- package/docs/layout.md +83 -0
- package/docs/library-reference-decisions.md +123 -0
- package/docs/link.md +67 -0
- package/docs/load-more.md +31 -0
- package/docs/mentions.md +82 -0
- package/docs/migration-0.2.md +108 -0
- package/docs/migration-0.3.md +72 -0
- package/docs/migration-0.5.md +82 -0
- package/docs/migration-0.6.md +197 -0
- package/docs/notification.md +54 -0
- package/docs/number-field.md +82 -0
- package/docs/otp-field.md +103 -0
- package/docs/pagination.md +139 -0
- package/docs/password-field.md +98 -0
- package/docs/popover.md +124 -0
- package/docs/promotion-candidates.md +169 -0
- package/docs/qr-code.md +69 -0
- package/docs/rating.md +58 -0
- package/docs/responsive-grid.md +90 -0
- package/docs/result.md +96 -0
- package/docs/showcase.md +97 -0
- package/docs/side-panel.md +71 -0
- package/docs/slider.md +79 -0
- package/docs/splitter.md +55 -0
- package/docs/statistic.md +16 -0
- package/docs/steps.md +115 -0
- package/docs/tag.md +57 -0
- package/docs/time-picker.md +88 -0
- package/docs/timeline.md +146 -0
- package/docs/toast.md +127 -0
- package/docs/tooltip.md +58 -0
- package/docs/tour.md +136 -0
- package/docs/transfer-list.md +94 -0
- package/docs/tree-select.md +101 -0
- package/docs/tree.md +123 -0
- package/docs/upload-item.md +68 -0
- package/docs/utility.md +53 -0
- package/docs/virtual-list.md +70 -0
- package/docs/watermark.md +58 -0
- package/package.json +402 -0
package/dist/toast.js
ADDED
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
export const toastBehaviorDefaults = {
|
|
2
|
+
durationMs: 5000,
|
|
3
|
+
minimumDurationMs: 5000,
|
|
4
|
+
priority: "normal",
|
|
5
|
+
dismissOnAction: true,
|
|
6
|
+
maxVisible: 1,
|
|
7
|
+
maxQueued: 20,
|
|
8
|
+
duplicatePolicy: "update",
|
|
9
|
+
timerUpdatePolicy: "preserve",
|
|
10
|
+
overflowPolicy: "discard-oldest",
|
|
11
|
+
};
|
|
12
|
+
const toastTones = [
|
|
13
|
+
"neutral",
|
|
14
|
+
"info",
|
|
15
|
+
"success",
|
|
16
|
+
"warning",
|
|
17
|
+
"danger",
|
|
18
|
+
];
|
|
19
|
+
function assertCopy(value, field) {
|
|
20
|
+
if (value.trim().length === 0) {
|
|
21
|
+
throw new TypeError(`Toast ${field} must not be empty`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Rejects ambiguous identity and inaccessible copy before anything is queued. */
|
|
25
|
+
export function validateToastDescriptor(descriptor) {
|
|
26
|
+
assertCopy(descriptor.id, "id");
|
|
27
|
+
if (descriptor.id !== descriptor.id.trim()) {
|
|
28
|
+
throw new TypeError("Toast id must not start or end with whitespace");
|
|
29
|
+
}
|
|
30
|
+
assertCopy(descriptor.description, "description");
|
|
31
|
+
assertCopy(descriptor.closeLabel, "closeLabel");
|
|
32
|
+
if (descriptor.title !== undefined)
|
|
33
|
+
assertCopy(descriptor.title, "title");
|
|
34
|
+
if (descriptor.announcement !== undefined) {
|
|
35
|
+
assertCopy(descriptor.announcement, "announcement");
|
|
36
|
+
}
|
|
37
|
+
if (descriptor.tone !== undefined && !toastTones.includes(descriptor.tone)) {
|
|
38
|
+
throw new TypeError(`Unsupported Toast tone: ${String(descriptor.tone)}`);
|
|
39
|
+
}
|
|
40
|
+
if (descriptor.priority !== undefined &&
|
|
41
|
+
descriptor.priority !== "normal" &&
|
|
42
|
+
descriptor.priority !== "high") {
|
|
43
|
+
throw new TypeError(`Unsupported Toast priority: ${String(descriptor.priority)}`);
|
|
44
|
+
}
|
|
45
|
+
if (descriptor.durationMs !== undefined && descriptor.durationMs !== null) {
|
|
46
|
+
if (!Number.isFinite(descriptor.durationMs) || descriptor.durationMs <= 0) {
|
|
47
|
+
throw new RangeError("Toast durationMs must be a positive finite number or null");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (descriptor.action) {
|
|
51
|
+
assertCopy(descriptor.action.label, "action.label");
|
|
52
|
+
if (descriptor.action.accessibilityLabel !== undefined) {
|
|
53
|
+
assertCopy(descriptor.action.accessibilityLabel, "action.accessibilityLabel");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Actionable notifications persist by default; every timer has a five-second floor. */
|
|
58
|
+
export function resolveToastDuration(descriptor) {
|
|
59
|
+
validateToastDescriptor(descriptor);
|
|
60
|
+
if (descriptor.durationMs === null)
|
|
61
|
+
return null;
|
|
62
|
+
if (descriptor.durationMs === undefined) {
|
|
63
|
+
return descriptor.action ? null : toastBehaviorDefaults.durationMs;
|
|
64
|
+
}
|
|
65
|
+
return Math.max(descriptor.durationMs, toastBehaviorDefaults.minimumDurationMs);
|
|
66
|
+
}
|
|
67
|
+
export function resolveToastDescriptor(descriptor) {
|
|
68
|
+
validateToastDescriptor(descriptor);
|
|
69
|
+
const title = descriptor.title ?? null;
|
|
70
|
+
const announcement = descriptor.announcement ??
|
|
71
|
+
(title === null ? descriptor.description : `${title}. ${descriptor.description}`);
|
|
72
|
+
const action = descriptor.action
|
|
73
|
+
? {
|
|
74
|
+
label: descriptor.action.label,
|
|
75
|
+
accessibilityLabel: descriptor.action.accessibilityLabel ?? descriptor.action.label,
|
|
76
|
+
onAction: descriptor.action.onAction,
|
|
77
|
+
dismissOnAction: descriptor.action.dismissOnAction ?? toastBehaviorDefaults.dismissOnAction,
|
|
78
|
+
}
|
|
79
|
+
: null;
|
|
80
|
+
return {
|
|
81
|
+
id: descriptor.id,
|
|
82
|
+
title,
|
|
83
|
+
description: descriptor.description,
|
|
84
|
+
tone: descriptor.tone ?? "neutral",
|
|
85
|
+
priority: descriptor.priority ?? toastBehaviorDefaults.priority,
|
|
86
|
+
announcement,
|
|
87
|
+
durationMs: resolveToastDuration(descriptor),
|
|
88
|
+
action,
|
|
89
|
+
closeLabel: descriptor.closeLabel,
|
|
90
|
+
onDismiss: descriptor.onDismiss ?? null,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export function resolveToastAnnouncement(descriptor) {
|
|
94
|
+
const resolved = resolveToastDescriptor(descriptor);
|
|
95
|
+
return { message: resolved.announcement, priority: resolved.priority };
|
|
96
|
+
}
|
|
97
|
+
function assertElapsedTime(elapsedMs) {
|
|
98
|
+
if (!Number.isFinite(elapsedMs) || elapsedMs < 0) {
|
|
99
|
+
throw new RangeError("Toast elapsed time must be a non-negative finite number");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Owns one notification's action, timer, and dismiss lifecycle exactly once. */
|
|
103
|
+
export function createToastSession(descriptor) {
|
|
104
|
+
let resolved = resolveToastDescriptor(descriptor);
|
|
105
|
+
let phase = "queued";
|
|
106
|
+
let revision = 0;
|
|
107
|
+
let elapsedMs = 0;
|
|
108
|
+
let actionInvoked = false;
|
|
109
|
+
let dismissReason = null;
|
|
110
|
+
let dismissNotified = false;
|
|
111
|
+
let cachedSnapshot = null;
|
|
112
|
+
const pausedBy = new Set();
|
|
113
|
+
const listeners = new Set();
|
|
114
|
+
const notify = () => {
|
|
115
|
+
cachedSnapshot = null;
|
|
116
|
+
for (const listener of listeners)
|
|
117
|
+
listener();
|
|
118
|
+
};
|
|
119
|
+
const timerSnapshot = () => {
|
|
120
|
+
if (resolved.durationMs === null) {
|
|
121
|
+
return {
|
|
122
|
+
status: "persistent",
|
|
123
|
+
durationMs: null,
|
|
124
|
+
remainingMs: null,
|
|
125
|
+
pausedBy: [...pausedBy],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const remainingMs = Math.max(0, resolved.durationMs - elapsedMs);
|
|
129
|
+
const status = phase === "queued"
|
|
130
|
+
? "waiting"
|
|
131
|
+
: phase !== "visible"
|
|
132
|
+
? "stopped"
|
|
133
|
+
: pausedBy.size > 0
|
|
134
|
+
? "paused"
|
|
135
|
+
: "running";
|
|
136
|
+
return {
|
|
137
|
+
status,
|
|
138
|
+
durationMs: resolved.durationMs,
|
|
139
|
+
remainingMs,
|
|
140
|
+
pausedBy: [...pausedBy],
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
const snapshot = () => {
|
|
144
|
+
cachedSnapshot ??= {
|
|
145
|
+
revision,
|
|
146
|
+
phase,
|
|
147
|
+
descriptor: resolved,
|
|
148
|
+
timer: timerSnapshot(),
|
|
149
|
+
actionInvoked,
|
|
150
|
+
dismissReason,
|
|
151
|
+
};
|
|
152
|
+
return cachedSnapshot;
|
|
153
|
+
};
|
|
154
|
+
const announceDismiss = (reason) => {
|
|
155
|
+
if (dismissNotified)
|
|
156
|
+
return;
|
|
157
|
+
dismissNotified = true;
|
|
158
|
+
resolved.onDismiss?.(reason);
|
|
159
|
+
};
|
|
160
|
+
const finishImmediately = (reason) => {
|
|
161
|
+
if (phase === "closed")
|
|
162
|
+
return false;
|
|
163
|
+
phase = "closed";
|
|
164
|
+
dismissReason = reason;
|
|
165
|
+
pausedBy.clear();
|
|
166
|
+
notify();
|
|
167
|
+
announceDismiss(reason);
|
|
168
|
+
return true;
|
|
169
|
+
};
|
|
170
|
+
const session = {
|
|
171
|
+
getSnapshot: snapshot,
|
|
172
|
+
subscribe(listener) {
|
|
173
|
+
listeners.add(listener);
|
|
174
|
+
return () => listeners.delete(listener);
|
|
175
|
+
},
|
|
176
|
+
show() {
|
|
177
|
+
if (phase !== "queued")
|
|
178
|
+
return false;
|
|
179
|
+
phase = "visible";
|
|
180
|
+
notify();
|
|
181
|
+
return true;
|
|
182
|
+
},
|
|
183
|
+
update(nextDescriptor, timerPolicy = toastBehaviorDefaults.timerUpdatePolicy) {
|
|
184
|
+
if (phase === "closing" || phase === "closed")
|
|
185
|
+
return false;
|
|
186
|
+
if (nextDescriptor.id !== resolved.id) {
|
|
187
|
+
throw new TypeError("A Toast session cannot change its stable id");
|
|
188
|
+
}
|
|
189
|
+
if (timerPolicy !== "preserve" && timerPolicy !== "restart") {
|
|
190
|
+
throw new TypeError(`Unsupported Toast timer update policy: ${String(timerPolicy)}`);
|
|
191
|
+
}
|
|
192
|
+
const next = resolveToastDescriptor(nextDescriptor);
|
|
193
|
+
resolved = next;
|
|
194
|
+
revision += 1;
|
|
195
|
+
actionInvoked = false;
|
|
196
|
+
dismissReason = null;
|
|
197
|
+
dismissNotified = false;
|
|
198
|
+
if (phase === "queued" || timerPolicy === "restart")
|
|
199
|
+
elapsedMs = 0;
|
|
200
|
+
if (phase === "visible" &&
|
|
201
|
+
resolved.durationMs !== null &&
|
|
202
|
+
elapsedMs >= resolved.durationMs) {
|
|
203
|
+
elapsedMs = resolved.durationMs;
|
|
204
|
+
phase = "closing";
|
|
205
|
+
dismissReason = "timeout";
|
|
206
|
+
}
|
|
207
|
+
notify();
|
|
208
|
+
return true;
|
|
209
|
+
},
|
|
210
|
+
pause(reason) {
|
|
211
|
+
if (phase !== "visible" || pausedBy.has(reason))
|
|
212
|
+
return false;
|
|
213
|
+
pausedBy.add(reason);
|
|
214
|
+
notify();
|
|
215
|
+
return true;
|
|
216
|
+
},
|
|
217
|
+
resume(reason) {
|
|
218
|
+
if (phase !== "visible" || !pausedBy.delete(reason))
|
|
219
|
+
return false;
|
|
220
|
+
notify();
|
|
221
|
+
return true;
|
|
222
|
+
},
|
|
223
|
+
advanceTime(deltaMs) {
|
|
224
|
+
assertElapsedTime(deltaMs);
|
|
225
|
+
if (deltaMs === 0 ||
|
|
226
|
+
phase !== "visible" ||
|
|
227
|
+
resolved.durationMs === null ||
|
|
228
|
+
pausedBy.size > 0) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
elapsedMs = Math.min(resolved.durationMs, elapsedMs + deltaMs);
|
|
232
|
+
if (elapsedMs >= resolved.durationMs) {
|
|
233
|
+
phase = "closing";
|
|
234
|
+
dismissReason = "timeout";
|
|
235
|
+
}
|
|
236
|
+
notify();
|
|
237
|
+
return true;
|
|
238
|
+
},
|
|
239
|
+
invokeAction() {
|
|
240
|
+
const action = resolved.action;
|
|
241
|
+
if (phase !== "visible" || action === null || actionInvoked)
|
|
242
|
+
return false;
|
|
243
|
+
const invokedRevision = revision;
|
|
244
|
+
actionInvoked = true;
|
|
245
|
+
notify();
|
|
246
|
+
try {
|
|
247
|
+
action.onAction();
|
|
248
|
+
}
|
|
249
|
+
finally {
|
|
250
|
+
if (action.dismissOnAction &&
|
|
251
|
+
phase === "visible" &&
|
|
252
|
+
revision === invokedRevision) {
|
|
253
|
+
phase = "closing";
|
|
254
|
+
dismissReason = "action";
|
|
255
|
+
pausedBy.clear();
|
|
256
|
+
notify();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return true;
|
|
260
|
+
},
|
|
261
|
+
dismiss(reason) {
|
|
262
|
+
if (phase === "closing" || phase === "closed")
|
|
263
|
+
return false;
|
|
264
|
+
if (phase === "queued")
|
|
265
|
+
return finishImmediately(reason);
|
|
266
|
+
phase = "closing";
|
|
267
|
+
dismissReason = reason;
|
|
268
|
+
pausedBy.clear();
|
|
269
|
+
notify();
|
|
270
|
+
return true;
|
|
271
|
+
},
|
|
272
|
+
completeExit() {
|
|
273
|
+
if (phase !== "closing" || dismissReason === null)
|
|
274
|
+
return false;
|
|
275
|
+
return finishImmediately(dismissReason);
|
|
276
|
+
},
|
|
277
|
+
interrupt() {
|
|
278
|
+
if (phase === "closed")
|
|
279
|
+
return false;
|
|
280
|
+
return finishImmediately("interrupted");
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
return session;
|
|
284
|
+
}
|
|
285
|
+
function resolveStoreOptions(options) {
|
|
286
|
+
const resolved = {
|
|
287
|
+
maxVisible: options.maxVisible ?? toastBehaviorDefaults.maxVisible,
|
|
288
|
+
maxQueued: options.maxQueued ?? toastBehaviorDefaults.maxQueued,
|
|
289
|
+
duplicatePolicy: options.duplicatePolicy ?? toastBehaviorDefaults.duplicatePolicy,
|
|
290
|
+
timerUpdatePolicy: options.timerUpdatePolicy ?? toastBehaviorDefaults.timerUpdatePolicy,
|
|
291
|
+
overflowPolicy: options.overflowPolicy ?? toastBehaviorDefaults.overflowPolicy,
|
|
292
|
+
};
|
|
293
|
+
if (!Number.isInteger(resolved.maxVisible) || resolved.maxVisible < 1) {
|
|
294
|
+
throw new RangeError("Toast maxVisible must be an integer of at least one");
|
|
295
|
+
}
|
|
296
|
+
if (!Number.isInteger(resolved.maxQueued) || resolved.maxQueued < 0) {
|
|
297
|
+
throw new RangeError("Toast maxQueued must be a non-negative integer");
|
|
298
|
+
}
|
|
299
|
+
if (resolved.duplicatePolicy !== "update" && resolved.duplicatePolicy !== "ignore") {
|
|
300
|
+
throw new TypeError(`Unsupported Toast duplicate policy: ${String(resolved.duplicatePolicy)}`);
|
|
301
|
+
}
|
|
302
|
+
if (resolved.timerUpdatePolicy !== "preserve" &&
|
|
303
|
+
resolved.timerUpdatePolicy !== "restart") {
|
|
304
|
+
throw new TypeError(`Unsupported Toast timer update policy: ${String(resolved.timerUpdatePolicy)}`);
|
|
305
|
+
}
|
|
306
|
+
if (resolved.overflowPolicy !== "discard-oldest" &&
|
|
307
|
+
resolved.overflowPolicy !== "discard-newest") {
|
|
308
|
+
throw new TypeError(`Unsupported Toast overflow policy: ${String(resolved.overflowPolicy)}`);
|
|
309
|
+
}
|
|
310
|
+
return resolved;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Bounded FIFO coordinator. Visible items keep their slot through exit motion;
|
|
314
|
+
* queued items begin timing only after promotion into a vacated slot.
|
|
315
|
+
*/
|
|
316
|
+
export function createToastStore(options = {}) {
|
|
317
|
+
const configuration = resolveStoreOptions(options);
|
|
318
|
+
const sessions = new Map();
|
|
319
|
+
const unsubscribers = new Map();
|
|
320
|
+
const visibleIds = [];
|
|
321
|
+
const queuedIds = [];
|
|
322
|
+
const listeners = new Set();
|
|
323
|
+
const globalPauseReasons = new Set();
|
|
324
|
+
let disposed = false;
|
|
325
|
+
let cachedSnapshot = null;
|
|
326
|
+
const notify = () => {
|
|
327
|
+
cachedSnapshot = null;
|
|
328
|
+
for (const listener of listeners)
|
|
329
|
+
listener();
|
|
330
|
+
};
|
|
331
|
+
const positionOf = (id) => visibleIds.includes(id) ? "visible" : "queued";
|
|
332
|
+
const snapshot = () => {
|
|
333
|
+
cachedSnapshot ??= {
|
|
334
|
+
visible: visibleIds
|
|
335
|
+
.map((id) => sessions.get(id)?.getSnapshot())
|
|
336
|
+
.filter((entry) => entry !== undefined),
|
|
337
|
+
queued: queuedIds
|
|
338
|
+
.map((id) => sessions.get(id)?.getSnapshot())
|
|
339
|
+
.filter((entry) => entry !== undefined),
|
|
340
|
+
};
|
|
341
|
+
return cachedSnapshot;
|
|
342
|
+
};
|
|
343
|
+
const removeId = (ids, id) => {
|
|
344
|
+
const index = ids.indexOf(id);
|
|
345
|
+
if (index >= 0)
|
|
346
|
+
ids.splice(index, 1);
|
|
347
|
+
};
|
|
348
|
+
const detachWithoutPromotion = (id) => {
|
|
349
|
+
const session = sessions.get(id);
|
|
350
|
+
removeId(visibleIds, id);
|
|
351
|
+
removeId(queuedIds, id);
|
|
352
|
+
sessions.delete(id);
|
|
353
|
+
unsubscribers.get(id)?.();
|
|
354
|
+
unsubscribers.delete(id);
|
|
355
|
+
cachedSnapshot = null;
|
|
356
|
+
return session;
|
|
357
|
+
};
|
|
358
|
+
const promote = () => {
|
|
359
|
+
while (!disposed && visibleIds.length < configuration.maxVisible) {
|
|
360
|
+
const id = queuedIds.shift();
|
|
361
|
+
if (id === undefined)
|
|
362
|
+
return;
|
|
363
|
+
const session = sessions.get(id);
|
|
364
|
+
if (!session)
|
|
365
|
+
continue;
|
|
366
|
+
visibleIds.push(id);
|
|
367
|
+
session.show();
|
|
368
|
+
for (const reason of globalPauseReasons)
|
|
369
|
+
session.pause(reason);
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
const removeClosed = (id) => {
|
|
373
|
+
removeId(visibleIds, id);
|
|
374
|
+
removeId(queuedIds, id);
|
|
375
|
+
sessions.delete(id);
|
|
376
|
+
unsubscribers.get(id)?.();
|
|
377
|
+
unsubscribers.delete(id);
|
|
378
|
+
promote();
|
|
379
|
+
};
|
|
380
|
+
const attach = (session) => {
|
|
381
|
+
const id = session.getSnapshot().descriptor.id;
|
|
382
|
+
sessions.set(id, session);
|
|
383
|
+
const unsubscribe = session.subscribe(() => {
|
|
384
|
+
if (session.getSnapshot().phase === "closed")
|
|
385
|
+
removeClosed(id);
|
|
386
|
+
notify();
|
|
387
|
+
});
|
|
388
|
+
unsubscribers.set(id, unsubscribe);
|
|
389
|
+
};
|
|
390
|
+
const discard = (descriptor) => {
|
|
391
|
+
createToastSession(descriptor).dismiss("queue-overflow");
|
|
392
|
+
return { outcome: "discarded", id: descriptor.id, reason: "queue-overflow" };
|
|
393
|
+
};
|
|
394
|
+
const assertActive = () => {
|
|
395
|
+
if (disposed)
|
|
396
|
+
throw new Error("Cannot use a disposed Toast store");
|
|
397
|
+
};
|
|
398
|
+
const store = {
|
|
399
|
+
getSnapshot: snapshot,
|
|
400
|
+
subscribe(listener) {
|
|
401
|
+
listeners.add(listener);
|
|
402
|
+
return () => listeners.delete(listener);
|
|
403
|
+
},
|
|
404
|
+
publish(descriptor, publishOptions = {}) {
|
|
405
|
+
assertActive();
|
|
406
|
+
validateToastDescriptor(descriptor);
|
|
407
|
+
const existing = sessions.get(descriptor.id);
|
|
408
|
+
if (existing) {
|
|
409
|
+
if (existing.getSnapshot().phase === "closing") {
|
|
410
|
+
return { outcome: "ignored", id: descriptor.id, reason: "closing" };
|
|
411
|
+
}
|
|
412
|
+
const duplicatePolicy = publishOptions.duplicatePolicy ?? configuration.duplicatePolicy;
|
|
413
|
+
if (duplicatePolicy !== "update" && duplicatePolicy !== "ignore") {
|
|
414
|
+
throw new TypeError(`Unsupported Toast duplicate policy: ${String(duplicatePolicy)}`);
|
|
415
|
+
}
|
|
416
|
+
if (duplicatePolicy === "ignore") {
|
|
417
|
+
return { outcome: "ignored", id: descriptor.id, reason: "duplicate" };
|
|
418
|
+
}
|
|
419
|
+
existing.update(descriptor, publishOptions.timerUpdatePolicy ?? configuration.timerUpdatePolicy);
|
|
420
|
+
return {
|
|
421
|
+
outcome: "updated",
|
|
422
|
+
id: descriptor.id,
|
|
423
|
+
position: positionOf(descriptor.id),
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
if (visibleIds.length >= configuration.maxVisible) {
|
|
427
|
+
if (configuration.maxQueued === 0)
|
|
428
|
+
return discard(descriptor);
|
|
429
|
+
if (queuedIds.length >= configuration.maxQueued) {
|
|
430
|
+
if (configuration.overflowPolicy === "discard-newest") {
|
|
431
|
+
return discard(descriptor);
|
|
432
|
+
}
|
|
433
|
+
const oldestQueuedId = queuedIds[0];
|
|
434
|
+
if (oldestQueuedId !== undefined) {
|
|
435
|
+
const oldestQueued = detachWithoutPromotion(oldestQueuedId);
|
|
436
|
+
let dismissedWithoutError = false;
|
|
437
|
+
try {
|
|
438
|
+
oldestQueued?.dismiss("queue-overflow");
|
|
439
|
+
dismissedWithoutError = true;
|
|
440
|
+
}
|
|
441
|
+
finally {
|
|
442
|
+
// A throwing onDismiss must not leave external-store consumers
|
|
443
|
+
// with a stale snapshot of the removed queue entry.
|
|
444
|
+
if (!dismissedWithoutError)
|
|
445
|
+
notify();
|
|
446
|
+
}
|
|
447
|
+
// onDismiss/store subscribers may synchronously publish or dispose.
|
|
448
|
+
// Restart from the public entry point so capacity, duplicates, and
|
|
449
|
+
// disposed state use the actual post-callback store.
|
|
450
|
+
return store.publish(descriptor, publishOptions);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
const session = createToastSession(descriptor);
|
|
455
|
+
attach(session);
|
|
456
|
+
if (visibleIds.length < configuration.maxVisible) {
|
|
457
|
+
visibleIds.push(descriptor.id);
|
|
458
|
+
session.show();
|
|
459
|
+
for (const reason of globalPauseReasons)
|
|
460
|
+
session.pause(reason);
|
|
461
|
+
return { outcome: "added", id: descriptor.id, position: "visible" };
|
|
462
|
+
}
|
|
463
|
+
queuedIds.push(descriptor.id);
|
|
464
|
+
notify();
|
|
465
|
+
return { outcome: "added", id: descriptor.id, position: "queued" };
|
|
466
|
+
},
|
|
467
|
+
invokeAction(id) {
|
|
468
|
+
assertActive();
|
|
469
|
+
return sessions.get(id)?.invokeAction() ?? false;
|
|
470
|
+
},
|
|
471
|
+
dismiss(id, reason) {
|
|
472
|
+
assertActive();
|
|
473
|
+
return sessions.get(id)?.dismiss(reason) ?? false;
|
|
474
|
+
},
|
|
475
|
+
close(id) {
|
|
476
|
+
assertActive();
|
|
477
|
+
return sessions.get(id)?.dismiss("programmatic") ?? false;
|
|
478
|
+
},
|
|
479
|
+
pause(id, reason) {
|
|
480
|
+
assertActive();
|
|
481
|
+
return sessions.get(id)?.pause(reason) ?? false;
|
|
482
|
+
},
|
|
483
|
+
resume(id, reason) {
|
|
484
|
+
assertActive();
|
|
485
|
+
return sessions.get(id)?.resume(reason) ?? false;
|
|
486
|
+
},
|
|
487
|
+
pauseAll(reason) {
|
|
488
|
+
assertActive();
|
|
489
|
+
globalPauseReasons.add(reason);
|
|
490
|
+
return [...visibleIds].reduce((count, id) => count + (sessions.get(id)?.pause(reason) ? 1 : 0), 0);
|
|
491
|
+
},
|
|
492
|
+
resumeAll(reason) {
|
|
493
|
+
assertActive();
|
|
494
|
+
globalPauseReasons.delete(reason);
|
|
495
|
+
return [...visibleIds].reduce((count, id) => count + (sessions.get(id)?.resume(reason) ? 1 : 0), 0);
|
|
496
|
+
},
|
|
497
|
+
advanceTime(deltaMs) {
|
|
498
|
+
assertActive();
|
|
499
|
+
assertElapsedTime(deltaMs);
|
|
500
|
+
return [...visibleIds].reduce((count, id) => count + (sessions.get(id)?.advanceTime(deltaMs) ? 1 : 0), 0);
|
|
501
|
+
},
|
|
502
|
+
completeExit(id) {
|
|
503
|
+
assertActive();
|
|
504
|
+
return sessions.get(id)?.completeExit() ?? false;
|
|
505
|
+
},
|
|
506
|
+
dispose() {
|
|
507
|
+
if (disposed)
|
|
508
|
+
return false;
|
|
509
|
+
disposed = true;
|
|
510
|
+
globalPauseReasons.clear();
|
|
511
|
+
let firstError;
|
|
512
|
+
for (const session of [...sessions.values()]) {
|
|
513
|
+
try {
|
|
514
|
+
session.interrupt();
|
|
515
|
+
}
|
|
516
|
+
catch (error) {
|
|
517
|
+
firstError ??= error;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
notify();
|
|
521
|
+
listeners.clear();
|
|
522
|
+
if (firstError !== undefined)
|
|
523
|
+
throw firstError;
|
|
524
|
+
return true;
|
|
525
|
+
},
|
|
526
|
+
};
|
|
527
|
+
return store;
|
|
528
|
+
}
|
|
529
|
+
//# sourceMappingURL=toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast.js","sourceRoot":"","sources":["../src/toast.ts"],"names":[],"mappings":"AA8EA,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,UAAU,EAAE,IAAI;IAChB,iBAAiB,EAAE,IAAI;IACvB,QAAQ,EAAE,QAAQ;IAClB,eAAe,EAAE,IAAI;IACrB,UAAU,EAAE,CAAC;IACb,SAAS,EAAE,EAAE;IACb,eAAe,EAAE,QAAQ;IACzB,iBAAiB,EAAE,UAAU;IAC7B,cAAc,EAAE,gBAAgB;CAWhC,CAAC;AAEH,MAAM,UAAU,GAAyB;IACvC,SAAS;IACT,MAAM;IACN,SAAS;IACT,SAAS;IACT,QAAQ;CACT,CAAC;AAEF,SAAS,UAAU,CAAC,KAAa,EAAE,KAAa;IAC9C,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CAAC,SAAS,KAAK,oBAAoB,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,uBAAuB,CAAC,UAA2B;IACjE,UAAU,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAChC,IAAI,UAAU,CAAC,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IACxE,CAAC;IACD,UAAU,CAAC,UAAU,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IAClD,UAAU,CAAC,UAAU,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAChD,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS;QAAE,UAAU,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1E,IAAI,UAAU,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QAC1C,UAAU,CAAC,UAAU,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,SAAS,CAAC,2BAA2B,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,IACE,UAAU,CAAC,QAAQ,KAAK,SAAS;QACjC,UAAU,CAAC,QAAQ,KAAK,QAAQ;QAChC,UAAU,CAAC,QAAQ,KAAK,MAAM,EAC9B,CAAC;QACD,MAAM,IAAI,SAAS,CAAC,+BAA+B,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC1E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC;YAC1E,MAAM,IAAI,UAAU,CAAC,2DAA2D,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACtB,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QACpD,IAAI,UAAU,CAAC,MAAM,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;YACvD,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,kBAAkB,EAAE,2BAA2B,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;AACH,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,oBAAoB,CAAC,UAA2B;IAC9D,uBAAuB,CAAC,UAAU,CAAC,CAAC;IACpC,IAAI,UAAU,CAAC,UAAU,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChD,IAAI,UAAU,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,qBAAqB,CAAC,UAAU,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,UAA2B;IAE3B,uBAAuB,CAAC,UAAU,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,IAAI,IAAI,CAAC;IACvC,MAAM,YAAY,GAChB,UAAU,CAAC,YAAY;QACvB,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IACpF,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM;QAC9B,CAAC,CAAC;YACE,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK;YAC9B,kBAAkB,EAChB,UAAU,CAAC,MAAM,CAAC,kBAAkB,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK;YACjE,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,QAAQ;YACpC,eAAe,EACb,UAAU,CAAC,MAAM,CAAC,eAAe,IAAI,qBAAqB,CAAC,eAAe;SAC7E;QACH,CAAC,CAAC,IAAI,CAAC;IAET,OAAO;QACL,EAAE,EAAE,UAAU,CAAC,EAAE;QACjB,KAAK;QACL,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,IAAI,EAAE,UAAU,CAAC,IAAI,IAAI,SAAS;QAClC,QAAQ,EAAE,UAAU,CAAC,QAAQ,IAAI,qBAAqB,CAAC,QAAQ;QAC/D,YAAY;QACZ,UAAU,EAAE,oBAAoB,CAAC,UAAU,CAAC;QAC5C,MAAM;QACN,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,SAAS,EAAE,UAAU,CAAC,SAAS,IAAI,IAAI;KACxC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,UAA2B;IAE3B,MAAM,QAAQ,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;IACpD,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC;AACzE,CAAC;AA2CD,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,UAAU,CAAC,yDAAyD,CAAC,CAAC;IAClF,CAAC;AACH,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,kBAAkB,CAAC,UAA2B;IAC5D,IAAI,QAAQ,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAClD,IAAI,KAAK,GAAe,QAAQ,CAAC;IACjC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,aAAa,GAA8B,IAAI,CAAC;IACpD,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,cAAc,GAAgC,IAAI,CAAC;IACvD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IAExC,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,cAAc,GAAG,IAAI,CAAC;QACtB,KAAK,MAAM,QAAQ,IAAI,SAAS;YAAE,QAAQ,EAAE,CAAC;IAC/C,CAAC,CAAC;IACF,MAAM,aAAa,GAAG,GAAuB,EAAE;QAC7C,IAAI,QAAQ,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YACjC,OAAO;gBACL,MAAM,EAAE,YAAY;gBACpB,UAAU,EAAE,IAAI;gBAChB,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC;aACxB,CAAC;QACJ,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;QACjE,MAAM,MAAM,GACV,KAAK,KAAK,QAAQ;YAChB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,KAAK,KAAK,SAAS;gBACnB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC;oBACjB,CAAC,CAAC,QAAQ;oBACV,CAAC,CAAC,SAAS,CAAC;QACpB,OAAO;YACL,MAAM;YACN,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,WAAW;YACX,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC;SACxB,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,GAAyB,EAAE;QAC1C,cAAc,KAAK;YACjB,QAAQ;YACR,KAAK;YACL,UAAU,EAAE,QAAQ;YACpB,KAAK,EAAE,aAAa,EAAE;YACtB,aAAa;YACb,aAAa;SACd,CAAC;QACF,OAAO,cAAc,CAAC;IACxB,CAAC,CAAC;IACF,MAAM,eAAe,GAAG,CAAC,MAA0B,EAAE,EAAE;QACrD,IAAI,eAAe;YAAE,OAAO;QAC5B,eAAe,GAAG,IAAI,CAAC;QACvB,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC,CAAC;IACF,MAAM,iBAAiB,GAAG,CAAC,MAA0B,EAAW,EAAE;QAChE,IAAI,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACrC,KAAK,GAAG,QAAQ,CAAC;QACjB,aAAa,GAAG,MAAM,CAAC;QACvB,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,EAAE,CAAC;QACT,eAAe,CAAC,MAAM,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,OAAO,GAAiB;QAC5B,WAAW,EAAE,QAAQ;QACrB,SAAS,CAAC,QAAQ;YAChB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;QACD,IAAI;YACF,IAAI,KAAK,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YACrC,KAAK,GAAG,SAAS,CAAC;YAClB,MAAM,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,CAAC,cAAc,EAAE,WAAW,GAAG,qBAAqB,CAAC,iBAAiB;YAC1E,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC5D,IAAI,cAAc,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;YACrE,CAAC;YACD,IAAI,WAAW,KAAK,UAAU,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC5D,MAAM,IAAI,SAAS,CAAC,0CAA0C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;YACvF,CAAC;YACD,MAAM,IAAI,GAAG,sBAAsB,CAAC,cAAc,CAAC,CAAC;YACpD,QAAQ,GAAG,IAAI,CAAC;YAChB,QAAQ,IAAI,CAAC,CAAC;YACd,aAAa,GAAG,KAAK,CAAC;YACtB,aAAa,GAAG,IAAI,CAAC;YACrB,eAAe,GAAG,KAAK,CAAC;YACxB,IAAI,KAAK,KAAK,QAAQ,IAAI,WAAW,KAAK,SAAS;gBAAE,SAAS,GAAG,CAAC,CAAC;YAEnE,IACE,KAAK,KAAK,SAAS;gBACnB,QAAQ,CAAC,UAAU,KAAK,IAAI;gBAC5B,SAAS,IAAI,QAAQ,CAAC,UAAU,EAChC,CAAC;gBACD,SAAS,GAAG,QAAQ,CAAC,UAAU,CAAC;gBAChC,KAAK,GAAG,SAAS,CAAC;gBAClB,aAAa,GAAG,SAAS,CAAC;YAC5B,CAAC;YACD,MAAM,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,CAAC,MAAM;YACV,IAAI,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC9D,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,CAAC,MAAM;YACX,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;gBAAE,OAAO,KAAK,CAAC;YAClE,MAAM,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QACD,WAAW,CAAC,OAAO;YACjB,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC3B,IACE,OAAO,KAAK,CAAC;gBACb,KAAK,KAAK,SAAS;gBACnB,QAAQ,CAAC,UAAU,KAAK,IAAI;gBAC5B,QAAQ,CAAC,IAAI,GAAG,CAAC,EACjB,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC;YACD,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;YAC/D,IAAI,SAAS,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACrC,KAAK,GAAG,SAAS,CAAC;gBAClB,aAAa,GAAG,SAAS,CAAC;YAC5B,CAAC;YACD,MAAM,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QACD,YAAY;YACV,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC/B,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,aAAa;gBAAE,OAAO,KAAK,CAAC;YAC1E,MAAM,eAAe,GAAG,QAAQ,CAAC;YACjC,aAAa,GAAG,IAAI,CAAC;YACrB,MAAM,EAAE,CAAC;YACT,IAAI,CAAC;gBACH,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,CAAC;oBAAS,CAAC;gBACT,IACE,MAAM,CAAC,eAAe;oBACtB,KAAK,KAAK,SAAS;oBACnB,QAAQ,KAAK,eAAe,EAC5B,CAAC;oBACD,KAAK,GAAG,SAAS,CAAC;oBAClB,aAAa,GAAG,QAAQ,CAAC;oBACzB,QAAQ,CAAC,KAAK,EAAE,CAAC;oBACjB,MAAM,EAAE,CAAC;gBACX,CAAC;YACH,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,CAAC,MAAM;YACZ,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC5D,IAAI,KAAK,KAAK,QAAQ;gBAAE,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;YACzD,KAAK,GAAG,SAAS,CAAC;YAClB,aAAa,GAAG,MAAM,CAAC;YACvB,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QACD,YAAY;YACV,IAAI,KAAK,KAAK,SAAS,IAAI,aAAa,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YAChE,OAAO,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAC1C,CAAC;QACD,SAAS;YACP,IAAI,KAAK,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YACrC,OAAO,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC;AAoDD,SAAS,mBAAmB,CAAC,OAA0B;IACrD,MAAM,QAAQ,GAAG;QACf,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,qBAAqB,CAAC,UAAU;QAClE,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,qBAAqB,CAAC,SAAS;QAC/D,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,qBAAqB,CAAC,eAAe;QACjF,iBAAiB,EACf,OAAO,CAAC,iBAAiB,IAAI,qBAAqB,CAAC,iBAAiB;QACtE,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,qBAAqB,CAAC,cAAc;KAC/E,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,UAAU,CAAC,qDAAqD,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,UAAU,CAAC,gDAAgD,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,QAAQ,CAAC,eAAe,KAAK,QAAQ,IAAI,QAAQ,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;QACnF,MAAM,IAAI,SAAS,CACjB,uCAAuC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAC1E,CAAC;IACJ,CAAC;IACD,IACE,QAAQ,CAAC,iBAAiB,KAAK,UAAU;QACzC,QAAQ,CAAC,iBAAiB,KAAK,SAAS,EACxC,CAAC;QACD,MAAM,IAAI,SAAS,CACjB,0CAA0C,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAC/E,CAAC;IACJ,CAAC;IACD,IACE,QAAQ,CAAC,cAAc,KAAK,gBAAgB;QAC5C,QAAQ,CAAC,cAAc,KAAK,gBAAgB,EAC5C,CAAC;QACD,MAAM,IAAI,SAAS,CACjB,sCAAsC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAA6B,EAAE;IAC9D,MAAM,aAAa,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;IAClD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAuB,CAAC;IACrD,MAAM,UAAU,GAAc,EAAE,CAAC;IACjC,MAAM,SAAS,GAAc,EAAE,CAAC;IAChC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IACxC,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAoB,CAAC;IACvD,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,cAAc,GAA8B,IAAI,CAAC;IAErD,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,cAAc,GAAG,IAAI,CAAC;QACtB,KAAK,MAAM,QAAQ,IAAI,SAAS;YAAE,QAAQ,EAAE,CAAC;IAC/C,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,EAAW,EAAwB,EAAE,CACvD,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;IACjD,MAAM,QAAQ,GAAG,GAAuB,EAAE;QACxC,cAAc,KAAK;YACjB,OAAO,EAAE,UAAU;iBAChB,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;iBAC5C,MAAM,CAAC,CAAC,KAAK,EAAiC,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;YACxE,MAAM,EAAE,SAAS;iBACd,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;iBAC5C,MAAM,CAAC,CAAC,KAAK,EAAiC,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;SACzE,CAAC;QACF,OAAO,cAAc,CAAC;IACxB,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,CAAC,GAAc,EAAE,EAAW,EAAE,EAAE;QAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,KAAK,IAAI,CAAC;YAAE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC;IACF,MAAM,sBAAsB,GAAG,CAAC,EAAW,EAA4B,EAAE;QACvE,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACzB,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpB,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1B,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACzB,cAAc,GAAG,IAAI,CAAC;QACtB,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,OAAO,CAAC,QAAQ,IAAI,UAAU,CAAC,MAAM,GAAG,aAAa,CAAC,UAAU,EAAE,CAAC;YACjE,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC;YAC7B,IAAI,EAAE,KAAK,SAAS;gBAAE,OAAO;YAC7B,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,KAAK,MAAM,MAAM,IAAI,kBAAkB;gBAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjE,CAAC;IACH,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,CAAC,EAAW,EAAE,EAAE;QACnC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACzB,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpB,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1B,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,OAAqB,EAAE,EAAE;QACvC,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC1B,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE;YACzC,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,KAAK,QAAQ;gBAAE,YAAY,CAAC,EAAE,CAAC,CAAC;YAC/D,MAAM,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;QACH,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;IACrC,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,CAAC,UAA2B,EAAsB,EAAE;QAClE,kBAAkB,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACzD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC/E,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,IAAI,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACrE,CAAC,CAAC;IAEF,MAAM,KAAK,GAAe;QACxB,WAAW,EAAE,QAAQ;QACrB,SAAS,CAAC,QAAQ;YAChB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,CAAC,UAAU,EAAE,cAAc,GAAG,EAAE;YACrC,YAAY,EAAE,CAAC;YACf,uBAAuB,CAAC,UAAU,CAAC,CAAC;YACpC,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YAC7C,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC/C,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;gBACtE,CAAC;gBACD,MAAM,eAAe,GACnB,cAAc,CAAC,eAAe,IAAI,aAAa,CAAC,eAAe,CAAC;gBAClE,IAAI,eAAe,KAAK,QAAQ,IAAI,eAAe,KAAK,QAAQ,EAAE,CAAC;oBACjE,MAAM,IAAI,SAAS,CACjB,uCAAuC,MAAM,CAAC,eAAe,CAAC,EAAE,CACjE,CAAC;gBACJ,CAAC;gBACD,IAAI,eAAe,KAAK,QAAQ,EAAE,CAAC;oBACjC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;gBACxE,CAAC;gBACD,QAAQ,CAAC,MAAM,CACb,UAAU,EACV,cAAc,CAAC,iBAAiB,IAAI,aAAa,CAAC,iBAAiB,CACpE,CAAC;gBACF,OAAO;oBACL,OAAO,EAAE,SAAS;oBAClB,EAAE,EAAE,UAAU,CAAC,EAAE;oBACjB,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;iBACpC,CAAC;YACJ,CAAC;YAED,IAAI,UAAU,CAAC,MAAM,IAAI,aAAa,CAAC,UAAU,EAAE,CAAC;gBAClD,IAAI,aAAa,CAAC,SAAS,KAAK,CAAC;oBAAE,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC9D,IAAI,SAAS,CAAC,MAAM,IAAI,aAAa,CAAC,SAAS,EAAE,CAAC;oBAChD,IAAI,aAAa,CAAC,cAAc,KAAK,gBAAgB,EAAE,CAAC;wBACtD,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;oBAC7B,CAAC;oBACD,MAAM,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;oBACpC,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;wBACjC,MAAM,YAAY,GAAG,sBAAsB,CAAC,cAAc,CAAC,CAAC;wBAC5D,IAAI,qBAAqB,GAAG,KAAK,CAAC;wBAClC,IAAI,CAAC;4BACH,YAAY,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;4BACxC,qBAAqB,GAAG,IAAI,CAAC;wBAC/B,CAAC;gCAAS,CAAC;4BACT,+DAA+D;4BAC/D,oDAAoD;4BACpD,IAAI,CAAC,qBAAqB;gCAAE,MAAM,EAAE,CAAC;wBACvC,CAAC;wBACD,oEAAoE;wBACpE,mEAAmE;wBACnE,qDAAqD;wBACrD,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;oBACnD,CAAC;gBACH,CAAC;YACH,CAAC;YAED,MAAM,OAAO,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;YAC/C,MAAM,CAAC,OAAO,CAAC,CAAC;YAChB,IAAI,UAAU,CAAC,MAAM,GAAG,aAAa,CAAC,UAAU,EAAE,CAAC;gBACjD,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;gBAC/B,OAAO,CAAC,IAAI,EAAE,CAAC;gBACf,KAAK,MAAM,MAAM,IAAI,kBAAkB;oBAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC/D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;YACtE,CAAC;YACD,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YAC9B,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;QACrE,CAAC;QACD,YAAY,CAAC,EAAE;YACb,YAAY,EAAE,CAAC;YACf,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,KAAK,CAAC;QACnD,CAAC;QACD,OAAO,CAAC,EAAE,EAAE,MAAM;YAChB,YAAY,EAAE,CAAC;YACf,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;QACpD,CAAC;QACD,KAAK,CAAC,EAAE;YACN,YAAY,EAAE,CAAC;YACf,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC;QAC5D,CAAC;QACD,KAAK,CAAC,EAAE,EAAE,MAAM;YACd,YAAY,EAAE,CAAC;YACf,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;QAClD,CAAC;QACD,MAAM,CAAC,EAAE,EAAE,MAAM;YACf,YAAY,EAAE,CAAC;YACf,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;QACnD,CAAC;QACD,QAAQ,CAAC,MAAM;YACb,YAAY,EAAE,CAAC;YACf,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC/B,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,CAC3B,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAChE,CAAC,CACF,CAAC;QACJ,CAAC;QACD,SAAS,CAAC,MAAM;YACd,YAAY,EAAE,CAAC;YACf,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAClC,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,CAC3B,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACjE,CAAC,CACF,CAAC;QACJ,CAAC;QACD,WAAW,CAAC,OAAO;YACjB,YAAY,EAAE,CAAC;YACf,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC3B,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,CAC3B,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACvE,CAAC,CACF,CAAC;QACJ,CAAC;QACD,YAAY,CAAC,EAAE;YACb,YAAY,EAAE,CAAC;YACf,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,KAAK,CAAC;QACnD,CAAC;QACD,OAAO;YACL,IAAI,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC3B,QAAQ,GAAG,IAAI,CAAC;YAChB,kBAAkB,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,UAAmB,CAAC;YACxB,KAAK,MAAM,OAAO,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;gBAC7C,IAAI,CAAC;oBACH,OAAO,CAAC,SAAS,EAAE,CAAC;gBACtB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,UAAU,KAAK,KAAK,CAAC;gBACvB,CAAC;YACH,CAAC;YACD,MAAM,EAAE,CAAC;YACT,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,UAAU,KAAK,SAAS;gBAAE,MAAM,UAAU,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;IAEF,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import type { ToastTone } from \"./component-recipes.js\";\n\nexport type ToastId = string;\nexport type ToastAnnouncementPriority = \"normal\" | \"high\";\nexport type ToastPauseReason =\n | \"pointer\"\n | \"focus\"\n | \"window\"\n | \"gesture\"\n | \"programmatic\";\nexport type ToastDismissReason =\n | \"timeout\"\n | \"action\"\n | \"close-action\"\n | \"escape\"\n | \"swipe\"\n | \"programmatic\"\n | \"queue-overflow\"\n | \"interrupted\";\nexport type ToastDuplicatePolicy = \"update\" | \"ignore\";\nexport type ToastTimerUpdatePolicy = \"preserve\" | \"restart\";\nexport type ToastOverflowPolicy = \"discard-oldest\" | \"discard-newest\";\n\nexport type ToastActionDescriptor = Readonly<{\n label: string;\n accessibilityLabel?: string;\n onAction(): void;\n dismissOnAction?: boolean;\n}>;\n\n/**\n * Renderer-neutral copy and behavior for one notification. Copy stays plain\n * text so Web and Native can announce the exact same message without accepting\n * renderer nodes in the core package.\n */\nexport type ToastDescriptor = Readonly<{\n /** Stable product-owned identity used for in-place de-duplication. */\n id: ToastId;\n title?: string;\n description: string;\n tone?: ToastTone;\n /** High priority interrupts; normal priority waits for a graceful announcement. */\n priority?: ToastAnnouncementPriority;\n /** Optional localized announcement when visible copy needs extra context. */\n announcement?: string;\n /** `null` is persistent. Values below the accessible minimum are clamped. */\n durationMs?: number | null;\n action?: ToastActionDescriptor;\n /** Required localized name for the icon-only close affordance. */\n closeLabel: string;\n onDismiss?: (reason: ToastDismissReason) => void;\n}>;\n\nexport type ResolvedToastActionDescriptor = Readonly<{\n label: string;\n accessibilityLabel: string;\n onAction(): void;\n dismissOnAction: boolean;\n}>;\n\nexport type ResolvedToastDescriptor = Readonly<{\n id: ToastId;\n title: string | null;\n description: string;\n tone: ToastTone;\n priority: ToastAnnouncementPriority;\n announcement: string;\n durationMs: number | null;\n action: ResolvedToastActionDescriptor | null;\n closeLabel: string;\n onDismiss: ((reason: ToastDismissReason) => void) | null;\n}>;\n\nexport type ToastAnnouncement = Readonly<{\n message: string;\n priority: ToastAnnouncementPriority;\n}>;\n\nexport const toastBehaviorDefaults = {\n durationMs: 5000,\n minimumDurationMs: 5000,\n priority: \"normal\",\n dismissOnAction: true,\n maxVisible: 1,\n maxQueued: 20,\n duplicatePolicy: \"update\",\n timerUpdatePolicy: \"preserve\",\n overflowPolicy: \"discard-oldest\",\n} as const satisfies Readonly<{\n durationMs: number;\n minimumDurationMs: number;\n priority: ToastAnnouncementPriority;\n dismissOnAction: boolean;\n maxVisible: number;\n maxQueued: number;\n duplicatePolicy: ToastDuplicatePolicy;\n timerUpdatePolicy: ToastTimerUpdatePolicy;\n overflowPolicy: ToastOverflowPolicy;\n}>;\n\nconst toastTones: readonly ToastTone[] = [\n \"neutral\",\n \"info\",\n \"success\",\n \"warning\",\n \"danger\",\n];\n\nfunction assertCopy(value: string, field: string): void {\n if (value.trim().length === 0) {\n throw new TypeError(`Toast ${field} must not be empty`);\n }\n}\n\n/** Rejects ambiguous identity and inaccessible copy before anything is queued. */\nexport function validateToastDescriptor(descriptor: ToastDescriptor): void {\n assertCopy(descriptor.id, \"id\");\n if (descriptor.id !== descriptor.id.trim()) {\n throw new TypeError(\"Toast id must not start or end with whitespace\");\n }\n assertCopy(descriptor.description, \"description\");\n assertCopy(descriptor.closeLabel, \"closeLabel\");\n if (descriptor.title !== undefined) assertCopy(descriptor.title, \"title\");\n if (descriptor.announcement !== undefined) {\n assertCopy(descriptor.announcement, \"announcement\");\n }\n if (descriptor.tone !== undefined && !toastTones.includes(descriptor.tone)) {\n throw new TypeError(`Unsupported Toast tone: ${String(descriptor.tone)}`);\n }\n if (\n descriptor.priority !== undefined &&\n descriptor.priority !== \"normal\" &&\n descriptor.priority !== \"high\"\n ) {\n throw new TypeError(`Unsupported Toast priority: ${String(descriptor.priority)}`);\n }\n if (descriptor.durationMs !== undefined && descriptor.durationMs !== null) {\n if (!Number.isFinite(descriptor.durationMs) || descriptor.durationMs <= 0) {\n throw new RangeError(\"Toast durationMs must be a positive finite number or null\");\n }\n }\n if (descriptor.action) {\n assertCopy(descriptor.action.label, \"action.label\");\n if (descriptor.action.accessibilityLabel !== undefined) {\n assertCopy(descriptor.action.accessibilityLabel, \"action.accessibilityLabel\");\n }\n }\n}\n\n/** Actionable notifications persist by default; every timer has a five-second floor. */\nexport function resolveToastDuration(descriptor: ToastDescriptor): number | null {\n validateToastDescriptor(descriptor);\n if (descriptor.durationMs === null) return null;\n if (descriptor.durationMs === undefined) {\n return descriptor.action ? null : toastBehaviorDefaults.durationMs;\n }\n return Math.max(descriptor.durationMs, toastBehaviorDefaults.minimumDurationMs);\n}\n\nexport function resolveToastDescriptor(\n descriptor: ToastDescriptor,\n): ResolvedToastDescriptor {\n validateToastDescriptor(descriptor);\n const title = descriptor.title ?? null;\n const announcement =\n descriptor.announcement ??\n (title === null ? descriptor.description : `${title}. ${descriptor.description}`);\n const action = descriptor.action\n ? {\n label: descriptor.action.label,\n accessibilityLabel:\n descriptor.action.accessibilityLabel ?? descriptor.action.label,\n onAction: descriptor.action.onAction,\n dismissOnAction:\n descriptor.action.dismissOnAction ?? toastBehaviorDefaults.dismissOnAction,\n }\n : null;\n\n return {\n id: descriptor.id,\n title,\n description: descriptor.description,\n tone: descriptor.tone ?? \"neutral\",\n priority: descriptor.priority ?? toastBehaviorDefaults.priority,\n announcement,\n durationMs: resolveToastDuration(descriptor),\n action,\n closeLabel: descriptor.closeLabel,\n onDismiss: descriptor.onDismiss ?? null,\n };\n}\n\nexport function resolveToastAnnouncement(\n descriptor: ToastDescriptor,\n): ToastAnnouncement {\n const resolved = resolveToastDescriptor(descriptor);\n return { message: resolved.announcement, priority: resolved.priority };\n}\n\nexport type ToastPhase = \"queued\" | \"visible\" | \"closing\" | \"closed\";\nexport type ToastTimerStatus =\n | \"waiting\"\n | \"running\"\n | \"paused\"\n | \"persistent\"\n | \"stopped\";\n\nexport type ToastTimerSnapshot = Readonly<{\n status: ToastTimerStatus;\n durationMs: number | null;\n remainingMs: number | null;\n pausedBy: readonly ToastPauseReason[];\n}>;\n\nexport type ToastSessionSnapshot = Readonly<{\n revision: number;\n phase: ToastPhase;\n descriptor: ResolvedToastDescriptor;\n timer: ToastTimerSnapshot;\n actionInvoked: boolean;\n dismissReason: ToastDismissReason | null;\n}>;\n\nexport type ToastSession = Readonly<{\n getSnapshot(): ToastSessionSnapshot;\n subscribe(listener: () => void): () => void;\n /** Starts visibility and the timer. Queued time is never counted. */\n show(): boolean;\n update(descriptor: ToastDescriptor, timerPolicy?: ToastTimerUpdatePolicy): boolean;\n pause(reason: ToastPauseReason): boolean;\n resume(reason: ToastPauseReason): boolean;\n /** Advances a renderer-owned clock; no global timer or Date dependency exists. */\n advanceTime(elapsedMs: number): boolean;\n invokeAction(): boolean;\n dismiss(reason: ToastDismissReason): boolean;\n /** Renderers call this once exit motion or immediate reduced-motion exit finishes. */\n completeExit(): boolean;\n interrupt(): boolean;\n}>;\n\nfunction assertElapsedTime(elapsedMs: number): void {\n if (!Number.isFinite(elapsedMs) || elapsedMs < 0) {\n throw new RangeError(\"Toast elapsed time must be a non-negative finite number\");\n }\n}\n\n/** Owns one notification's action, timer, and dismiss lifecycle exactly once. */\nexport function createToastSession(descriptor: ToastDescriptor): ToastSession {\n let resolved = resolveToastDescriptor(descriptor);\n let phase: ToastPhase = \"queued\";\n let revision = 0;\n let elapsedMs = 0;\n let actionInvoked = false;\n let dismissReason: ToastDismissReason | null = null;\n let dismissNotified = false;\n let cachedSnapshot: ToastSessionSnapshot | null = null;\n const pausedBy = new Set<ToastPauseReason>();\n const listeners = new Set<() => void>();\n\n const notify = () => {\n cachedSnapshot = null;\n for (const listener of listeners) listener();\n };\n const timerSnapshot = (): ToastTimerSnapshot => {\n if (resolved.durationMs === null) {\n return {\n status: \"persistent\",\n durationMs: null,\n remainingMs: null,\n pausedBy: [...pausedBy],\n };\n }\n const remainingMs = Math.max(0, resolved.durationMs - elapsedMs);\n const status: ToastTimerStatus =\n phase === \"queued\"\n ? \"waiting\"\n : phase !== \"visible\"\n ? \"stopped\"\n : pausedBy.size > 0\n ? \"paused\"\n : \"running\";\n return {\n status,\n durationMs: resolved.durationMs,\n remainingMs,\n pausedBy: [...pausedBy],\n };\n };\n const snapshot = (): ToastSessionSnapshot => {\n cachedSnapshot ??= {\n revision,\n phase,\n descriptor: resolved,\n timer: timerSnapshot(),\n actionInvoked,\n dismissReason,\n };\n return cachedSnapshot;\n };\n const announceDismiss = (reason: ToastDismissReason) => {\n if (dismissNotified) return;\n dismissNotified = true;\n resolved.onDismiss?.(reason);\n };\n const finishImmediately = (reason: ToastDismissReason): boolean => {\n if (phase === \"closed\") return false;\n phase = \"closed\";\n dismissReason = reason;\n pausedBy.clear();\n notify();\n announceDismiss(reason);\n return true;\n };\n\n const session: ToastSession = {\n getSnapshot: snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n show() {\n if (phase !== \"queued\") return false;\n phase = \"visible\";\n notify();\n return true;\n },\n update(nextDescriptor, timerPolicy = toastBehaviorDefaults.timerUpdatePolicy) {\n if (phase === \"closing\" || phase === \"closed\") return false;\n if (nextDescriptor.id !== resolved.id) {\n throw new TypeError(\"A Toast session cannot change its stable id\");\n }\n if (timerPolicy !== \"preserve\" && timerPolicy !== \"restart\") {\n throw new TypeError(`Unsupported Toast timer update policy: ${String(timerPolicy)}`);\n }\n const next = resolveToastDescriptor(nextDescriptor);\n resolved = next;\n revision += 1;\n actionInvoked = false;\n dismissReason = null;\n dismissNotified = false;\n if (phase === \"queued\" || timerPolicy === \"restart\") elapsedMs = 0;\n\n if (\n phase === \"visible\" &&\n resolved.durationMs !== null &&\n elapsedMs >= resolved.durationMs\n ) {\n elapsedMs = resolved.durationMs;\n phase = \"closing\";\n dismissReason = \"timeout\";\n }\n notify();\n return true;\n },\n pause(reason) {\n if (phase !== \"visible\" || pausedBy.has(reason)) return false;\n pausedBy.add(reason);\n notify();\n return true;\n },\n resume(reason) {\n if (phase !== \"visible\" || !pausedBy.delete(reason)) return false;\n notify();\n return true;\n },\n advanceTime(deltaMs) {\n assertElapsedTime(deltaMs);\n if (\n deltaMs === 0 ||\n phase !== \"visible\" ||\n resolved.durationMs === null ||\n pausedBy.size > 0\n ) {\n return false;\n }\n elapsedMs = Math.min(resolved.durationMs, elapsedMs + deltaMs);\n if (elapsedMs >= resolved.durationMs) {\n phase = \"closing\";\n dismissReason = \"timeout\";\n }\n notify();\n return true;\n },\n invokeAction() {\n const action = resolved.action;\n if (phase !== \"visible\" || action === null || actionInvoked) return false;\n const invokedRevision = revision;\n actionInvoked = true;\n notify();\n try {\n action.onAction();\n } finally {\n if (\n action.dismissOnAction &&\n phase === \"visible\" &&\n revision === invokedRevision\n ) {\n phase = \"closing\";\n dismissReason = \"action\";\n pausedBy.clear();\n notify();\n }\n }\n return true;\n },\n dismiss(reason) {\n if (phase === \"closing\" || phase === \"closed\") return false;\n if (phase === \"queued\") return finishImmediately(reason);\n phase = \"closing\";\n dismissReason = reason;\n pausedBy.clear();\n notify();\n return true;\n },\n completeExit() {\n if (phase !== \"closing\" || dismissReason === null) return false;\n return finishImmediately(dismissReason);\n },\n interrupt() {\n if (phase === \"closed\") return false;\n return finishImmediately(\"interrupted\");\n },\n };\n\n return session;\n}\n\nexport type ToastStoreOptions = Readonly<{\n maxVisible?: number;\n maxQueued?: number;\n duplicatePolicy?: ToastDuplicatePolicy;\n timerUpdatePolicy?: ToastTimerUpdatePolicy;\n overflowPolicy?: ToastOverflowPolicy;\n}>;\n\ntype ResolvedToastStoreOptions = Readonly<{\n maxVisible: number;\n maxQueued: number;\n duplicatePolicy: ToastDuplicatePolicy;\n timerUpdatePolicy: ToastTimerUpdatePolicy;\n overflowPolicy: ToastOverflowPolicy;\n}>;\n\nexport type ToastPublishOptions = Readonly<{\n duplicatePolicy?: ToastDuplicatePolicy;\n timerUpdatePolicy?: ToastTimerUpdatePolicy;\n}>;\n\nexport type ToastPublishResult =\n | Readonly<{ outcome: \"added\"; id: ToastId; position: \"visible\" | \"queued\" }>\n | Readonly<{ outcome: \"updated\"; id: ToastId; position: \"visible\" | \"queued\" }>\n | Readonly<{ outcome: \"ignored\"; id: ToastId; reason: \"duplicate\" | \"closing\" }>\n | Readonly<{ outcome: \"discarded\"; id: ToastId; reason: \"queue-overflow\" }>;\n\nexport type ToastStoreSnapshot = Readonly<{\n visible: readonly ToastSessionSnapshot[];\n queued: readonly ToastSessionSnapshot[];\n}>;\n\nexport type ToastStore = Readonly<{\n getSnapshot(): ToastStoreSnapshot;\n subscribe(listener: () => void): () => void;\n publish(descriptor: ToastDescriptor, options?: ToastPublishOptions): ToastPublishResult;\n invokeAction(id: ToastId): boolean;\n dismiss(id: ToastId, reason: ToastDismissReason): boolean;\n /** Stable-id programmatic close shortcut. */\n close(id: ToastId): boolean;\n pause(id: ToastId, reason: ToastPauseReason): boolean;\n resume(id: ToastId, reason: ToastPauseReason): boolean;\n pauseAll(reason: ToastPauseReason): number;\n resumeAll(reason: ToastPauseReason): number;\n advanceTime(elapsedMs: number): number;\n completeExit(id: ToastId): boolean;\n /** Provider teardown closes every item exactly once without waiting for motion. */\n dispose(): boolean;\n}>;\n\nfunction resolveStoreOptions(options: ToastStoreOptions): ResolvedToastStoreOptions {\n const resolved = {\n maxVisible: options.maxVisible ?? toastBehaviorDefaults.maxVisible,\n maxQueued: options.maxQueued ?? toastBehaviorDefaults.maxQueued,\n duplicatePolicy: options.duplicatePolicy ?? toastBehaviorDefaults.duplicatePolicy,\n timerUpdatePolicy:\n options.timerUpdatePolicy ?? toastBehaviorDefaults.timerUpdatePolicy,\n overflowPolicy: options.overflowPolicy ?? toastBehaviorDefaults.overflowPolicy,\n };\n if (!Number.isInteger(resolved.maxVisible) || resolved.maxVisible < 1) {\n throw new RangeError(\"Toast maxVisible must be an integer of at least one\");\n }\n if (!Number.isInteger(resolved.maxQueued) || resolved.maxQueued < 0) {\n throw new RangeError(\"Toast maxQueued must be a non-negative integer\");\n }\n if (resolved.duplicatePolicy !== \"update\" && resolved.duplicatePolicy !== \"ignore\") {\n throw new TypeError(\n `Unsupported Toast duplicate policy: ${String(resolved.duplicatePolicy)}`,\n );\n }\n if (\n resolved.timerUpdatePolicy !== \"preserve\" &&\n resolved.timerUpdatePolicy !== \"restart\"\n ) {\n throw new TypeError(\n `Unsupported Toast timer update policy: ${String(resolved.timerUpdatePolicy)}`,\n );\n }\n if (\n resolved.overflowPolicy !== \"discard-oldest\" &&\n resolved.overflowPolicy !== \"discard-newest\"\n ) {\n throw new TypeError(\n `Unsupported Toast overflow policy: ${String(resolved.overflowPolicy)}`,\n );\n }\n return resolved;\n}\n\n/**\n * Bounded FIFO coordinator. Visible items keep their slot through exit motion;\n * queued items begin timing only after promotion into a vacated slot.\n */\nexport function createToastStore(options: ToastStoreOptions = {}): ToastStore {\n const configuration = resolveStoreOptions(options);\n const sessions = new Map<ToastId, ToastSession>();\n const unsubscribers = new Map<ToastId, () => void>();\n const visibleIds: ToastId[] = [];\n const queuedIds: ToastId[] = [];\n const listeners = new Set<() => void>();\n const globalPauseReasons = new Set<ToastPauseReason>();\n let disposed = false;\n let cachedSnapshot: ToastStoreSnapshot | null = null;\n\n const notify = () => {\n cachedSnapshot = null;\n for (const listener of listeners) listener();\n };\n const positionOf = (id: ToastId): \"visible\" | \"queued\" =>\n visibleIds.includes(id) ? \"visible\" : \"queued\";\n const snapshot = (): ToastStoreSnapshot => {\n cachedSnapshot ??= {\n visible: visibleIds\n .map((id) => sessions.get(id)?.getSnapshot())\n .filter((entry): entry is ToastSessionSnapshot => entry !== undefined),\n queued: queuedIds\n .map((id) => sessions.get(id)?.getSnapshot())\n .filter((entry): entry is ToastSessionSnapshot => entry !== undefined),\n };\n return cachedSnapshot;\n };\n const removeId = (ids: ToastId[], id: ToastId) => {\n const index = ids.indexOf(id);\n if (index >= 0) ids.splice(index, 1);\n };\n const detachWithoutPromotion = (id: ToastId): ToastSession | undefined => {\n const session = sessions.get(id);\n removeId(visibleIds, id);\n removeId(queuedIds, id);\n sessions.delete(id);\n unsubscribers.get(id)?.();\n unsubscribers.delete(id);\n cachedSnapshot = null;\n return session;\n };\n const promote = () => {\n while (!disposed && visibleIds.length < configuration.maxVisible) {\n const id = queuedIds.shift();\n if (id === undefined) return;\n const session = sessions.get(id);\n if (!session) continue;\n visibleIds.push(id);\n session.show();\n for (const reason of globalPauseReasons) session.pause(reason);\n }\n };\n const removeClosed = (id: ToastId) => {\n removeId(visibleIds, id);\n removeId(queuedIds, id);\n sessions.delete(id);\n unsubscribers.get(id)?.();\n unsubscribers.delete(id);\n promote();\n };\n const attach = (session: ToastSession) => {\n const id = session.getSnapshot().descriptor.id;\n sessions.set(id, session);\n const unsubscribe = session.subscribe(() => {\n if (session.getSnapshot().phase === \"closed\") removeClosed(id);\n notify();\n });\n unsubscribers.set(id, unsubscribe);\n };\n const discard = (descriptor: ToastDescriptor): ToastPublishResult => {\n createToastSession(descriptor).dismiss(\"queue-overflow\");\n return { outcome: \"discarded\", id: descriptor.id, reason: \"queue-overflow\" };\n };\n const assertActive = () => {\n if (disposed) throw new Error(\"Cannot use a disposed Toast store\");\n };\n\n const store: ToastStore = {\n getSnapshot: snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n publish(descriptor, publishOptions = {}) {\n assertActive();\n validateToastDescriptor(descriptor);\n const existing = sessions.get(descriptor.id);\n if (existing) {\n if (existing.getSnapshot().phase === \"closing\") {\n return { outcome: \"ignored\", id: descriptor.id, reason: \"closing\" };\n }\n const duplicatePolicy =\n publishOptions.duplicatePolicy ?? configuration.duplicatePolicy;\n if (duplicatePolicy !== \"update\" && duplicatePolicy !== \"ignore\") {\n throw new TypeError(\n `Unsupported Toast duplicate policy: ${String(duplicatePolicy)}`,\n );\n }\n if (duplicatePolicy === \"ignore\") {\n return { outcome: \"ignored\", id: descriptor.id, reason: \"duplicate\" };\n }\n existing.update(\n descriptor,\n publishOptions.timerUpdatePolicy ?? configuration.timerUpdatePolicy,\n );\n return {\n outcome: \"updated\",\n id: descriptor.id,\n position: positionOf(descriptor.id),\n };\n }\n\n if (visibleIds.length >= configuration.maxVisible) {\n if (configuration.maxQueued === 0) return discard(descriptor);\n if (queuedIds.length >= configuration.maxQueued) {\n if (configuration.overflowPolicy === \"discard-newest\") {\n return discard(descriptor);\n }\n const oldestQueuedId = queuedIds[0];\n if (oldestQueuedId !== undefined) {\n const oldestQueued = detachWithoutPromotion(oldestQueuedId);\n let dismissedWithoutError = false;\n try {\n oldestQueued?.dismiss(\"queue-overflow\");\n dismissedWithoutError = true;\n } finally {\n // A throwing onDismiss must not leave external-store consumers\n // with a stale snapshot of the removed queue entry.\n if (!dismissedWithoutError) notify();\n }\n // onDismiss/store subscribers may synchronously publish or dispose.\n // Restart from the public entry point so capacity, duplicates, and\n // disposed state use the actual post-callback store.\n return store.publish(descriptor, publishOptions);\n }\n }\n }\n\n const session = createToastSession(descriptor);\n attach(session);\n if (visibleIds.length < configuration.maxVisible) {\n visibleIds.push(descriptor.id);\n session.show();\n for (const reason of globalPauseReasons) session.pause(reason);\n return { outcome: \"added\", id: descriptor.id, position: \"visible\" };\n }\n queuedIds.push(descriptor.id);\n notify();\n return { outcome: \"added\", id: descriptor.id, position: \"queued\" };\n },\n invokeAction(id) {\n assertActive();\n return sessions.get(id)?.invokeAction() ?? false;\n },\n dismiss(id, reason) {\n assertActive();\n return sessions.get(id)?.dismiss(reason) ?? false;\n },\n close(id) {\n assertActive();\n return sessions.get(id)?.dismiss(\"programmatic\") ?? false;\n },\n pause(id, reason) {\n assertActive();\n return sessions.get(id)?.pause(reason) ?? false;\n },\n resume(id, reason) {\n assertActive();\n return sessions.get(id)?.resume(reason) ?? false;\n },\n pauseAll(reason) {\n assertActive();\n globalPauseReasons.add(reason);\n return [...visibleIds].reduce(\n (count, id) => count + (sessions.get(id)?.pause(reason) ? 1 : 0),\n 0,\n );\n },\n resumeAll(reason) {\n assertActive();\n globalPauseReasons.delete(reason);\n return [...visibleIds].reduce(\n (count, id) => count + (sessions.get(id)?.resume(reason) ? 1 : 0),\n 0,\n );\n },\n advanceTime(deltaMs) {\n assertActive();\n assertElapsedTime(deltaMs);\n return [...visibleIds].reduce(\n (count, id) => count + (sessions.get(id)?.advanceTime(deltaMs) ? 1 : 0),\n 0,\n );\n },\n completeExit(id) {\n assertActive();\n return sessions.get(id)?.completeExit() ?? false;\n },\n dispose() {\n if (disposed) return false;\n disposed = true;\n globalPauseReasons.clear();\n let firstError: unknown;\n for (const session of [...sessions.values()]) {\n try {\n session.interrupt();\n } catch (error) {\n firstError ??= error;\n }\n }\n notify();\n listeners.clear();\n if (firstError !== undefined) throw firstError;\n return true;\n },\n };\n\n return store;\n}\n"]}
|
package/dist/tokens.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderer-neutral token entry point for consumers that do not need component
|
|
3
|
+
* metadata, showcase data, or behavior registries in their Metro/Web graph.
|
|
4
|
+
*/
|
|
5
|
+
export * from "./colors.js";
|
|
6
|
+
export * from "./color-references.js";
|
|
7
|
+
export * from "./foundations.js";
|
|
8
|
+
export * from "./semantic-colors.js";
|
|
9
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC"}
|
package/dist/tokens.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderer-neutral token entry point for consumers that do not need component
|
|
3
|
+
* metadata, showcase data, or behavior registries in their Metro/Web graph.
|
|
4
|
+
*/
|
|
5
|
+
export * from "./colors.js";
|
|
6
|
+
export * from "./color-references.js";
|
|
7
|
+
export * from "./foundations.js";
|
|
8
|
+
export * from "./semantic-colors.js";
|
|
9
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC","sourcesContent":["/**\n * Renderer-neutral token entry point for consumers that do not need component\n * metadata, showcase data, or behavior registries in their Metro/Web graph.\n */\nexport * from \"./colors.js\";\nexport * from \"./color-references.js\";\nexport * from \"./foundations.js\";\nexport * from \"./semantic-colors.js\";\n"]}
|