@proyecto-viviana/solid-stately 0.0.6 → 0.1.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/README.md +312 -0
- package/dist/index.d.ts +3363 -6
- package/dist/index.js +6194 -19
- package/dist/index.js.map +1 -1
- package/package.json +52 -48
- package/src/autocomplete/createAutocompleteState.d.ts +46 -0
- package/src/autocomplete/createAutocompleteState.d.ts.map +1 -0
- package/src/autocomplete/createAutocompleteState.ts +90 -0
- package/src/autocomplete/index.d.ts +2 -0
- package/src/autocomplete/index.d.ts.map +1 -0
- package/src/autocomplete/index.ts +5 -0
- package/src/calendar/createCalendarState.d.ts +130 -0
- package/src/calendar/createCalendarState.d.ts.map +1 -0
- package/src/calendar/createCalendarState.ts +461 -0
- package/src/calendar/createDateFieldState.d.ts +110 -0
- package/src/calendar/createDateFieldState.d.ts.map +1 -0
- package/src/calendar/createDateFieldState.ts +562 -0
- package/src/calendar/createRangeCalendarState.d.ts +146 -0
- package/src/calendar/createRangeCalendarState.d.ts.map +1 -0
- package/src/calendar/createRangeCalendarState.ts +535 -0
- package/src/calendar/createTimeFieldState.d.ts +95 -0
- package/src/calendar/createTimeFieldState.d.ts.map +1 -0
- package/src/calendar/createTimeFieldState.ts +483 -0
- package/src/calendar/index.d.ts +7 -0
- package/src/calendar/index.d.ts.map +1 -0
- package/src/calendar/index.ts +81 -0
- package/{dist → src}/checkbox/createCheckboxGroupState.d.ts +1 -0
- package/src/checkbox/createCheckboxGroupState.d.ts.map +1 -0
- package/{dist → src}/checkbox/index.d.ts +1 -0
- package/src/checkbox/index.d.ts.map +1 -0
- package/src/collections/ListCollection.d.ts +37 -0
- package/src/collections/ListCollection.d.ts.map +1 -0
- package/src/collections/ListCollection.ts +146 -0
- package/src/collections/createListState.d.ts +79 -0
- package/src/collections/createListState.d.ts.map +1 -0
- package/src/collections/createListState.ts +264 -0
- package/src/collections/createMenuState.d.ts +50 -0
- package/src/collections/createMenuState.d.ts.map +1 -0
- package/src/collections/createMenuState.ts +106 -0
- package/src/collections/createSelectionState.d.ts +76 -0
- package/src/collections/createSelectionState.d.ts.map +1 -0
- package/src/collections/createSelectionState.ts +336 -0
- package/src/collections/index.d.ts +6 -0
- package/src/collections/index.d.ts.map +1 -0
- package/src/collections/index.ts +46 -0
- package/src/collections/types.d.ts +147 -0
- package/src/collections/types.d.ts.map +1 -0
- package/src/collections/types.ts +169 -0
- package/src/color/Color.d.ts +28 -0
- package/src/color/Color.d.ts.map +1 -0
- package/src/color/Color.ts +951 -0
- package/src/color/createColorAreaState.d.ts +76 -0
- package/src/color/createColorAreaState.d.ts.map +1 -0
- package/src/color/createColorAreaState.ts +293 -0
- package/src/color/createColorFieldState.d.ts +55 -0
- package/src/color/createColorFieldState.d.ts.map +1 -0
- package/src/color/createColorFieldState.ts +292 -0
- package/src/color/createColorSliderState.d.ts +67 -0
- package/src/color/createColorSliderState.d.ts.map +1 -0
- package/src/color/createColorSliderState.ts +241 -0
- package/src/color/createColorWheelState.d.ts +51 -0
- package/src/color/createColorWheelState.d.ts.map +1 -0
- package/src/color/createColorWheelState.ts +211 -0
- package/src/color/index.d.ts +10 -0
- package/src/color/index.d.ts.map +1 -0
- package/src/color/index.ts +47 -0
- package/src/color/types.d.ts +106 -0
- package/src/color/types.d.ts.map +1 -0
- package/src/color/types.ts +127 -0
- package/src/combobox/createComboBoxState.d.ts +125 -0
- package/src/combobox/createComboBoxState.d.ts.map +1 -0
- package/src/combobox/createComboBoxState.ts +703 -0
- package/src/combobox/index.d.ts +5 -0
- package/src/combobox/index.d.ts.map +1 -0
- package/src/combobox/index.ts +13 -0
- package/src/disclosure/createDisclosureState.d.ts +64 -0
- package/src/disclosure/createDisclosureState.d.ts.map +1 -0
- package/src/disclosure/createDisclosureState.ts +193 -0
- package/src/disclosure/index.d.ts +2 -0
- package/src/disclosure/index.d.ts.map +1 -0
- package/src/disclosure/index.ts +9 -0
- package/src/dnd/createDragState.d.ts +59 -0
- package/src/dnd/createDragState.d.ts.map +1 -0
- package/src/dnd/createDragState.ts +153 -0
- package/src/dnd/createDraggableCollectionState.d.ts +57 -0
- package/src/dnd/createDraggableCollectionState.d.ts.map +1 -0
- package/src/dnd/createDraggableCollectionState.ts +165 -0
- package/src/dnd/createDropState.d.ts +61 -0
- package/src/dnd/createDropState.d.ts.map +1 -0
- package/src/dnd/createDropState.ts +212 -0
- package/src/dnd/createDroppableCollectionState.d.ts +78 -0
- package/src/dnd/createDroppableCollectionState.d.ts.map +1 -0
- package/src/dnd/createDroppableCollectionState.ts +357 -0
- package/src/dnd/index.d.ts +11 -0
- package/src/dnd/index.d.ts.map +1 -0
- package/src/dnd/index.ts +76 -0
- package/src/dnd/types.d.ts +264 -0
- package/src/dnd/types.d.ts.map +1 -0
- package/src/dnd/types.ts +317 -0
- package/src/form/createFormValidationState.d.ts +100 -0
- package/src/form/createFormValidationState.d.ts.map +1 -0
- package/src/form/createFormValidationState.ts +389 -0
- package/src/form/index.d.ts +2 -0
- package/src/form/index.d.ts.map +1 -0
- package/src/form/index.ts +15 -0
- package/src/grid/createGridState.d.ts +12 -0
- package/src/grid/createGridState.d.ts.map +1 -0
- package/src/grid/createGridState.ts +327 -0
- package/src/grid/index.d.ts +7 -0
- package/src/grid/index.d.ts.map +1 -0
- package/src/grid/index.ts +13 -0
- package/src/grid/types.d.ts +156 -0
- package/src/grid/types.d.ts.map +1 -0
- package/src/grid/types.ts +179 -0
- package/src/index.d.ts +26 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.ts +350 -1
- package/src/numberfield/createNumberFieldState.d.ts +65 -0
- package/src/numberfield/createNumberFieldState.d.ts.map +1 -0
- package/src/numberfield/createNumberFieldState.ts +383 -0
- package/src/numberfield/index.d.ts +2 -0
- package/src/numberfield/index.d.ts.map +1 -0
- package/src/numberfield/index.ts +5 -0
- package/src/overlays/createOverlayTriggerState.d.ts +32 -0
- package/src/overlays/createOverlayTriggerState.d.ts.map +1 -0
- package/src/overlays/createOverlayTriggerState.ts +67 -0
- package/src/overlays/index.d.ts +2 -0
- package/src/overlays/index.d.ts.map +1 -0
- package/src/overlays/index.ts +5 -0
- package/{dist → src}/radio/createRadioGroupState.d.ts +1 -0
- package/src/radio/createRadioGroupState.d.ts.map +1 -0
- package/{dist → src}/radio/index.d.ts +1 -0
- package/src/radio/index.d.ts.map +1 -0
- package/src/searchfield/createSearchFieldState.d.ts +25 -0
- package/src/searchfield/createSearchFieldState.d.ts.map +1 -0
- package/src/searchfield/createSearchFieldState.ts +62 -0
- package/src/searchfield/index.d.ts +3 -0
- package/src/searchfield/index.d.ts.map +1 -0
- package/src/searchfield/index.ts +5 -0
- package/src/select/createSelectState.d.ts +73 -0
- package/src/select/createSelectState.d.ts.map +1 -0
- package/src/select/createSelectState.ts +181 -0
- package/src/select/index.d.ts +2 -0
- package/src/select/index.d.ts.map +1 -0
- package/src/select/index.ts +5 -0
- package/src/slider/createSliderState.d.ts +72 -0
- package/src/slider/createSliderState.d.ts.map +1 -0
- package/src/slider/createSliderState.ts +211 -0
- package/src/slider/index.d.ts +3 -0
- package/src/slider/index.d.ts.map +1 -0
- package/src/slider/index.ts +6 -0
- package/{dist → src}/ssr/index.d.ts +5 -0
- package/src/ssr/index.d.ts.map +1 -0
- package/src/ssr/index.ts +6 -1
- package/src/table/TableCollection.d.ts +52 -0
- package/src/table/TableCollection.d.ts.map +1 -0
- package/src/table/TableCollection.ts +388 -0
- package/src/table/createTableState.d.ts +12 -0
- package/src/table/createTableState.d.ts.map +1 -0
- package/src/table/createTableState.ts +127 -0
- package/src/table/index.d.ts +8 -0
- package/src/table/index.d.ts.map +1 -0
- package/src/table/index.ts +18 -0
- package/src/table/types.d.ts +139 -0
- package/src/table/types.d.ts.map +1 -0
- package/src/table/types.ts +150 -0
- package/src/tabs/createTabListState.d.ts +68 -0
- package/src/tabs/createTabListState.d.ts.map +1 -0
- package/src/tabs/createTabListState.ts +240 -0
- package/src/tabs/index.d.ts +2 -0
- package/src/tabs/index.d.ts.map +1 -0
- package/src/tabs/index.ts +7 -0
- package/{dist → src}/textfield/createTextFieldState.d.ts +1 -0
- package/src/textfield/createTextFieldState.d.ts.map +1 -0
- package/{dist → src}/textfield/index.d.ts +1 -0
- package/src/textfield/index.d.ts.map +1 -0
- package/src/toast/createToastState.d.ts +118 -0
- package/src/toast/createToastState.d.ts.map +1 -0
- package/src/toast/createToastState.ts +316 -0
- package/src/toast/index.d.ts +2 -0
- package/src/toast/index.d.ts.map +1 -0
- package/src/toast/index.ts +11 -0
- package/{dist → src}/toggle/createToggleState.d.ts +1 -0
- package/src/toggle/createToggleState.d.ts.map +1 -0
- package/{dist → src}/toggle/index.d.ts +1 -0
- package/src/toggle/index.d.ts.map +1 -0
- package/src/tooltip/createTooltipTriggerState.d.ts +39 -0
- package/src/tooltip/createTooltipTriggerState.d.ts.map +1 -0
- package/src/tooltip/createTooltipTriggerState.ts +183 -0
- package/src/tooltip/index.d.ts +2 -0
- package/src/tooltip/index.d.ts.map +1 -0
- package/src/tooltip/index.ts +6 -0
- package/src/tree/TreeCollection.d.ts +40 -0
- package/src/tree/TreeCollection.d.ts.map +1 -0
- package/src/tree/TreeCollection.ts +175 -0
- package/src/tree/createTreeState.d.ts +14 -0
- package/src/tree/createTreeState.d.ts.map +1 -0
- package/src/tree/createTreeState.ts +392 -0
- package/src/tree/index.d.ts +7 -0
- package/src/tree/index.d.ts.map +1 -0
- package/src/tree/index.ts +13 -0
- package/src/tree/types.d.ts +157 -0
- package/src/tree/types.d.ts.map +1 -0
- package/src/tree/types.ts +174 -0
- package/{dist → src}/utils/index.d.ts +1 -0
- package/src/utils/index.d.ts.map +1 -0
- package/{dist → src}/utils/reactivity.d.ts +1 -0
- package/src/utils/reactivity.d.ts.map +1 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toast state management for SolidJS
|
|
3
|
+
* Based on @react-stately/toast useToastState
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createSignal, onCleanup, type Accessor } from 'solid-js';
|
|
7
|
+
|
|
8
|
+
// ============================================
|
|
9
|
+
// TYPES
|
|
10
|
+
// ============================================
|
|
11
|
+
|
|
12
|
+
export interface ToastOptions {
|
|
13
|
+
/** A timeout to automatically close the toast, in milliseconds. */
|
|
14
|
+
timeout?: number;
|
|
15
|
+
/** The priority of the toast relative to other toasts. */
|
|
16
|
+
priority?: number;
|
|
17
|
+
/** Handler called when the toast is closed. */
|
|
18
|
+
onClose?: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface QueuedToast<T> {
|
|
22
|
+
/** The content of the toast. */
|
|
23
|
+
content: T;
|
|
24
|
+
/** A unique key for the toast. */
|
|
25
|
+
key: string;
|
|
26
|
+
/** The timer for the toast. */
|
|
27
|
+
timer: Timer | null;
|
|
28
|
+
/** Whether the toast should be animated. */
|
|
29
|
+
animation?: 'entering' | 'exiting' | 'queued';
|
|
30
|
+
/** The priority of the toast. */
|
|
31
|
+
priority: number;
|
|
32
|
+
/** Handler called when the toast is closed. */
|
|
33
|
+
onClose?: () => void;
|
|
34
|
+
/** The timeout for the toast. */
|
|
35
|
+
timeout?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ToastQueueOptions {
|
|
39
|
+
/** The maximum number of toasts to display at once. */
|
|
40
|
+
maxVisibleToasts?: number;
|
|
41
|
+
/** Whether toasts should stack (true) or queue (false). */
|
|
42
|
+
hasExitAnimation?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ToastStateProps<T> {
|
|
46
|
+
/** The toast queue to use. */
|
|
47
|
+
queue: ToastQueue<T>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ToastState<T> {
|
|
51
|
+
/** The currently visible toasts. */
|
|
52
|
+
visibleToasts: Accessor<QueuedToast<T>[]>;
|
|
53
|
+
/** Adds a toast to the queue. */
|
|
54
|
+
add: (content: T, options?: ToastOptions) => string;
|
|
55
|
+
/** Closes a toast by key. */
|
|
56
|
+
close: (key: string) => void;
|
|
57
|
+
/** Pauses all toast timers. */
|
|
58
|
+
pauseAll: () => void;
|
|
59
|
+
/** Resumes all toast timers. */
|
|
60
|
+
resumeAll: () => void;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ============================================
|
|
64
|
+
// TIMER CLASS
|
|
65
|
+
// ============================================
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* A Timer that supports pause and resume.
|
|
69
|
+
*/
|
|
70
|
+
export class Timer {
|
|
71
|
+
private timerId: number | null = null;
|
|
72
|
+
private startTime: number = 0;
|
|
73
|
+
private remaining: number;
|
|
74
|
+
private callback: () => void;
|
|
75
|
+
|
|
76
|
+
constructor(callback: () => void, delay: number) {
|
|
77
|
+
this.callback = callback;
|
|
78
|
+
this.remaining = delay;
|
|
79
|
+
this.resume();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
pause() {
|
|
83
|
+
if (this.timerId === null) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
clearTimeout(this.timerId);
|
|
87
|
+
this.timerId = null;
|
|
88
|
+
this.remaining -= Date.now() - this.startTime;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
resume() {
|
|
92
|
+
if (this.timerId !== null) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.startTime = Date.now();
|
|
96
|
+
this.timerId = window.setTimeout(() => {
|
|
97
|
+
this.timerId = null;
|
|
98
|
+
this.callback();
|
|
99
|
+
}, this.remaining);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
reset(delay: number) {
|
|
103
|
+
this.pause();
|
|
104
|
+
this.remaining = delay;
|
|
105
|
+
this.resume();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
cancel() {
|
|
109
|
+
if (this.timerId !== null) {
|
|
110
|
+
clearTimeout(this.timerId);
|
|
111
|
+
this.timerId = null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ============================================
|
|
117
|
+
// TOAST QUEUE CLASS
|
|
118
|
+
// ============================================
|
|
119
|
+
|
|
120
|
+
type SubscribeCallback<T> = (toasts: QueuedToast<T>[]) => void;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* A queue that manages toast notifications.
|
|
124
|
+
* Can be created once and shared across the app (singleton pattern).
|
|
125
|
+
*/
|
|
126
|
+
export class ToastQueue<T> {
|
|
127
|
+
private queue: QueuedToast<T>[] = [];
|
|
128
|
+
private subscriptions = new Set<SubscribeCallback<T>>();
|
|
129
|
+
private maxVisibleToasts: number;
|
|
130
|
+
private hasExitAnimation: boolean;
|
|
131
|
+
private keyCounter = 0;
|
|
132
|
+
|
|
133
|
+
constructor(options: ToastQueueOptions = {}) {
|
|
134
|
+
this.maxVisibleToasts = options.maxVisibleToasts ?? 5;
|
|
135
|
+
this.hasExitAnimation = options.hasExitAnimation ?? false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Subscribe to queue changes.
|
|
140
|
+
*/
|
|
141
|
+
subscribe(callback: SubscribeCallback<T>): () => void {
|
|
142
|
+
this.subscriptions.add(callback);
|
|
143
|
+
return () => {
|
|
144
|
+
this.subscriptions.delete(callback);
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Add a toast to the queue.
|
|
150
|
+
*/
|
|
151
|
+
add(content: T, options: ToastOptions = {}): string {
|
|
152
|
+
const key = String(this.keyCounter++);
|
|
153
|
+
|
|
154
|
+
const toast: QueuedToast<T> = {
|
|
155
|
+
content,
|
|
156
|
+
key,
|
|
157
|
+
timer: null,
|
|
158
|
+
priority: options.priority ?? 0,
|
|
159
|
+
onClose: options.onClose,
|
|
160
|
+
timeout: options.timeout,
|
|
161
|
+
animation: 'entering',
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Find insertion point based on priority
|
|
165
|
+
let low = 0;
|
|
166
|
+
let high = this.queue.length;
|
|
167
|
+
while (low < high) {
|
|
168
|
+
const mid = Math.floor((low + high) / 2);
|
|
169
|
+
if (toast.priority > this.queue[mid].priority) {
|
|
170
|
+
high = mid;
|
|
171
|
+
} else {
|
|
172
|
+
low = mid + 1;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Insert at the correct position
|
|
177
|
+
this.queue = [
|
|
178
|
+
...this.queue.slice(0, low),
|
|
179
|
+
toast,
|
|
180
|
+
...this.queue.slice(low),
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
// Start timer for visible toasts
|
|
184
|
+
this.updateVisibility();
|
|
185
|
+
|
|
186
|
+
return key;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Close a toast by key.
|
|
191
|
+
*/
|
|
192
|
+
close(key: string): void {
|
|
193
|
+
const toast = this.queue.find((t) => t.key === key);
|
|
194
|
+
if (!toast) return;
|
|
195
|
+
|
|
196
|
+
// Cancel any existing timer
|
|
197
|
+
toast.timer?.cancel();
|
|
198
|
+
toast.timer = null;
|
|
199
|
+
|
|
200
|
+
if (this.hasExitAnimation && toast.animation !== 'queued') {
|
|
201
|
+
// Mark as exiting for animation
|
|
202
|
+
toast.animation = 'exiting';
|
|
203
|
+
this.notify();
|
|
204
|
+
} else {
|
|
205
|
+
// Remove immediately
|
|
206
|
+
this.remove(key);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Remove a toast after exit animation completes.
|
|
212
|
+
*/
|
|
213
|
+
remove(key: string): void {
|
|
214
|
+
const toast = this.queue.find((t) => t.key === key);
|
|
215
|
+
if (toast) {
|
|
216
|
+
toast.onClose?.();
|
|
217
|
+
toast.timer?.cancel();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
this.queue = this.queue.filter((t) => t.key !== key);
|
|
221
|
+
this.updateVisibility();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Pause all toast timers.
|
|
226
|
+
*/
|
|
227
|
+
pauseAll(): void {
|
|
228
|
+
for (const toast of this.queue) {
|
|
229
|
+
toast.timer?.pause();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Resume all toast timers.
|
|
235
|
+
*/
|
|
236
|
+
resumeAll(): void {
|
|
237
|
+
for (const toast of this.queue) {
|
|
238
|
+
toast.timer?.resume();
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private updateVisibility(): void {
|
|
243
|
+
// Mark toasts as visible or queued based on maxVisibleToasts
|
|
244
|
+
const visibleCount = this.queue.filter(
|
|
245
|
+
(t) => t.animation !== 'queued' && t.animation !== 'exiting'
|
|
246
|
+
).length;
|
|
247
|
+
|
|
248
|
+
let promoted = 0;
|
|
249
|
+
for (const toast of this.queue) {
|
|
250
|
+
if (toast.animation === 'queued' && visibleCount + promoted < this.maxVisibleToasts) {
|
|
251
|
+
toast.animation = 'entering';
|
|
252
|
+
promoted++;
|
|
253
|
+
}
|
|
254
|
+
if (toast.animation === 'queued') continue;
|
|
255
|
+
|
|
256
|
+
// Start timer for visible toasts
|
|
257
|
+
if (toast.timeout != null && toast.timer === null && toast.animation !== 'exiting') {
|
|
258
|
+
toast.timer = new Timer(() => {
|
|
259
|
+
this.close(toast.key);
|
|
260
|
+
}, toast.timeout);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
this.notify();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private notify(): void {
|
|
268
|
+
const toasts = [...this.queue];
|
|
269
|
+
for (const callback of this.subscriptions) {
|
|
270
|
+
callback(toasts);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// ============================================
|
|
276
|
+
// HOOK
|
|
277
|
+
// ============================================
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Creates reactive toast state from a ToastQueue.
|
|
281
|
+
* Use this hook to subscribe to toast changes in your component.
|
|
282
|
+
*/
|
|
283
|
+
export function createToastState<T>(props: ToastStateProps<T>): ToastState<T> {
|
|
284
|
+
const [visibleToasts, setVisibleToasts] = createSignal<QueuedToast<T>[]>([]);
|
|
285
|
+
|
|
286
|
+
// Subscribe to queue changes
|
|
287
|
+
const unsubscribe = props.queue.subscribe((toasts) => {
|
|
288
|
+
setVisibleToasts(toasts);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
onCleanup(() => {
|
|
292
|
+
unsubscribe();
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
return {
|
|
296
|
+
visibleToasts,
|
|
297
|
+
add: (content, options) => props.queue.add(content, options),
|
|
298
|
+
close: (key) => props.queue.close(key),
|
|
299
|
+
pauseAll: () => props.queue.pauseAll(),
|
|
300
|
+
resumeAll: () => props.queue.resumeAll(),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// ============================================
|
|
305
|
+
// CONVENIENCE HOOKS
|
|
306
|
+
// ============================================
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Creates a new ToastQueue and returns reactive state.
|
|
310
|
+
* Use this if you don't need a global queue.
|
|
311
|
+
*/
|
|
312
|
+
export function createToastQueue<T>(options?: ToastQueueOptions): ToastState<T> & { queue: ToastQueue<T> } {
|
|
313
|
+
const queue = new ToastQueue<T>(options);
|
|
314
|
+
const state = createToastState({ queue });
|
|
315
|
+
return { ...state, queue };
|
|
316
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,KAAK,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC"}
|
|
@@ -31,3 +31,4 @@ export interface ToggleState {
|
|
|
31
31
|
* Provides state management for toggle components like checkboxes and switches.
|
|
32
32
|
*/
|
|
33
33
|
export declare function createToggleState(props?: MaybeAccessor<ToggleStateOptions>): ToggleState;
|
|
34
|
+
//# sourceMappingURL=createToggleState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createToggleState.d.ts","sourceRoot":"","sources":["createToggleState.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAgB,QAAQ,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,KAAK,aAAa,EAAU,MAAM,UAAU,CAAC;AAMtD,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wEAAwE;IACxE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACvC,iDAAiD;IACjD,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,+BAA+B;IAC/B,WAAW,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IACvC,kCAAkC;IAClC,MAAM,IAAI,IAAI,CAAC;CAChB;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,GAAE,aAAa,CAAC,kBAAkB,CAAM,GAAG,WAAW,CAiD5F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,WAAW,GACjB,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages state for a tooltip trigger.
|
|
3
|
+
* Based on @react-stately/tooltip useTooltipTriggerState.
|
|
4
|
+
*
|
|
5
|
+
* Tracks whether the tooltip is open, and provides methods to toggle this state.
|
|
6
|
+
* Ensures only one tooltip is open at a time and controls the delay for showing a tooltip.
|
|
7
|
+
*/
|
|
8
|
+
import { type Accessor } from 'solid-js';
|
|
9
|
+
import { type OverlayTriggerProps } from '../overlays';
|
|
10
|
+
export interface TooltipTriggerProps extends OverlayTriggerProps {
|
|
11
|
+
/** The delay time in milliseconds for the tooltip to show up. */
|
|
12
|
+
delay?: number;
|
|
13
|
+
/** The delay time in milliseconds for the tooltip to close. */
|
|
14
|
+
closeDelay?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface TooltipTriggerState {
|
|
17
|
+
/** Whether the tooltip is currently showing. */
|
|
18
|
+
readonly isOpen: Accessor<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* Shows the tooltip. By default, the tooltip becomes visible after a delay
|
|
21
|
+
* depending on a global warmup timer. The `immediate` option shows the
|
|
22
|
+
* tooltip immediately instead.
|
|
23
|
+
*/
|
|
24
|
+
open(immediate?: boolean): void;
|
|
25
|
+
/** Hides the tooltip. */
|
|
26
|
+
close(immediate?: boolean): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resets the global tooltip state. Useful for testing.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export declare function resetTooltipState(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Manages state for a tooltip trigger. Tracks whether the tooltip is open, and provides
|
|
35
|
+
* methods to toggle this state. Ensures only one tooltip is open at a time and controls
|
|
36
|
+
* the delay for showing a tooltip.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createTooltipTriggerState(props?: TooltipTriggerProps): TooltipTriggerState;
|
|
39
|
+
//# sourceMappingURL=createTooltipTriggerState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTooltipTriggerState.d.ts","sourceRoot":"","sources":["createTooltipTriggerState.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAA2B,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAOlF,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACnC;;;;OAIG;IACH,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,yBAAyB;IACzB,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAClC;AASD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAYxC;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,GAAE,mBAAwB,GAC9B,mBAAmB,CAkHrB"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages state for a tooltip trigger.
|
|
3
|
+
* Based on @react-stately/tooltip useTooltipTriggerState.
|
|
4
|
+
*
|
|
5
|
+
* Tracks whether the tooltip is open, and provides methods to toggle this state.
|
|
6
|
+
* Ensures only one tooltip is open at a time and controls the delay for showing a tooltip.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createSignal, onCleanup, type Accessor } from 'solid-js';
|
|
10
|
+
import { createOverlayTriggerState, type OverlayTriggerProps } from '../overlays';
|
|
11
|
+
import { isServer } from '../ssr';
|
|
12
|
+
|
|
13
|
+
// Default delays (in ms)
|
|
14
|
+
const TOOLTIP_DELAY = 1500;
|
|
15
|
+
const TOOLTIP_COOLDOWN = 500;
|
|
16
|
+
|
|
17
|
+
export interface TooltipTriggerProps extends OverlayTriggerProps {
|
|
18
|
+
/** The delay time in milliseconds for the tooltip to show up. */
|
|
19
|
+
delay?: number;
|
|
20
|
+
/** The delay time in milliseconds for the tooltip to close. */
|
|
21
|
+
closeDelay?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface TooltipTriggerState {
|
|
25
|
+
/** Whether the tooltip is currently showing. */
|
|
26
|
+
readonly isOpen: Accessor<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* Shows the tooltip. By default, the tooltip becomes visible after a delay
|
|
29
|
+
* depending on a global warmup timer. The `immediate` option shows the
|
|
30
|
+
* tooltip immediately instead.
|
|
31
|
+
*/
|
|
32
|
+
open(immediate?: boolean): void;
|
|
33
|
+
/** Hides the tooltip. */
|
|
34
|
+
close(immediate?: boolean): void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Global state for coordinating tooltips
|
|
38
|
+
let tooltips: Record<string, (immediate?: boolean) => void> = {};
|
|
39
|
+
let tooltipId = 0;
|
|
40
|
+
let globalWarmedUp = false;
|
|
41
|
+
let globalWarmUpTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
42
|
+
let globalCooldownTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Resets the global tooltip state. Useful for testing.
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
export function resetTooltipState(): void {
|
|
49
|
+
tooltips = {};
|
|
50
|
+
tooltipId = 0;
|
|
51
|
+
globalWarmedUp = false;
|
|
52
|
+
if (globalWarmUpTimeout) {
|
|
53
|
+
clearTimeout(globalWarmUpTimeout);
|
|
54
|
+
globalWarmUpTimeout = null;
|
|
55
|
+
}
|
|
56
|
+
if (globalCooldownTimeout) {
|
|
57
|
+
clearTimeout(globalCooldownTimeout);
|
|
58
|
+
globalCooldownTimeout = null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Manages state for a tooltip trigger. Tracks whether the tooltip is open, and provides
|
|
64
|
+
* methods to toggle this state. Ensures only one tooltip is open at a time and controls
|
|
65
|
+
* the delay for showing a tooltip.
|
|
66
|
+
*/
|
|
67
|
+
export function createTooltipTriggerState(
|
|
68
|
+
props: TooltipTriggerProps = {}
|
|
69
|
+
): TooltipTriggerState {
|
|
70
|
+
const delay = () => props.delay ?? TOOLTIP_DELAY;
|
|
71
|
+
const closeDelay = () => props.closeDelay ?? TOOLTIP_COOLDOWN;
|
|
72
|
+
|
|
73
|
+
const overlayState = createOverlayTriggerState(props);
|
|
74
|
+
const id = `tooltip-${++tooltipId}`;
|
|
75
|
+
|
|
76
|
+
let closeTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
77
|
+
const [closeCallback, setCloseCallback] = createSignal<() => void>(() => overlayState.close());
|
|
78
|
+
|
|
79
|
+
const ensureTooltipEntry = () => {
|
|
80
|
+
tooltips[id] = hideTooltip;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const closeOpenTooltips = () => {
|
|
84
|
+
for (const hideTooltipId in tooltips) {
|
|
85
|
+
if (hideTooltipId !== id) {
|
|
86
|
+
tooltips[hideTooltipId](true);
|
|
87
|
+
delete tooltips[hideTooltipId];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const showTooltip = () => {
|
|
93
|
+
if (closeTimeout) {
|
|
94
|
+
clearTimeout(closeTimeout);
|
|
95
|
+
closeTimeout = null;
|
|
96
|
+
}
|
|
97
|
+
closeOpenTooltips();
|
|
98
|
+
ensureTooltipEntry();
|
|
99
|
+
globalWarmedUp = true;
|
|
100
|
+
overlayState.open();
|
|
101
|
+
|
|
102
|
+
if (globalWarmUpTimeout) {
|
|
103
|
+
clearTimeout(globalWarmUpTimeout);
|
|
104
|
+
globalWarmUpTimeout = null;
|
|
105
|
+
}
|
|
106
|
+
if (globalCooldownTimeout) {
|
|
107
|
+
clearTimeout(globalCooldownTimeout);
|
|
108
|
+
globalCooldownTimeout = null;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const hideTooltip = (immediate?: boolean) => {
|
|
113
|
+
if (immediate || closeDelay() <= 0) {
|
|
114
|
+
if (closeTimeout) {
|
|
115
|
+
clearTimeout(closeTimeout);
|
|
116
|
+
closeTimeout = null;
|
|
117
|
+
}
|
|
118
|
+
closeCallback()();
|
|
119
|
+
} else if (!closeTimeout) {
|
|
120
|
+
closeTimeout = setTimeout(() => {
|
|
121
|
+
closeTimeout = null;
|
|
122
|
+
closeCallback()();
|
|
123
|
+
}, closeDelay());
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (globalWarmUpTimeout) {
|
|
127
|
+
clearTimeout(globalWarmUpTimeout);
|
|
128
|
+
globalWarmUpTimeout = null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (globalWarmedUp) {
|
|
132
|
+
if (globalCooldownTimeout) {
|
|
133
|
+
clearTimeout(globalCooldownTimeout);
|
|
134
|
+
}
|
|
135
|
+
globalCooldownTimeout = setTimeout(() => {
|
|
136
|
+
delete tooltips[id];
|
|
137
|
+
globalCooldownTimeout = null;
|
|
138
|
+
globalWarmedUp = false;
|
|
139
|
+
}, Math.max(TOOLTIP_COOLDOWN, closeDelay()));
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const warmupTooltip = () => {
|
|
144
|
+
closeOpenTooltips();
|
|
145
|
+
ensureTooltipEntry();
|
|
146
|
+
|
|
147
|
+
if (!overlayState.isOpen() && !globalWarmUpTimeout && !globalWarmedUp) {
|
|
148
|
+
globalWarmUpTimeout = setTimeout(() => {
|
|
149
|
+
globalWarmUpTimeout = null;
|
|
150
|
+
globalWarmedUp = true;
|
|
151
|
+
showTooltip();
|
|
152
|
+
}, delay());
|
|
153
|
+
} else if (!overlayState.isOpen()) {
|
|
154
|
+
showTooltip();
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// Update close callback when overlayState.close changes
|
|
159
|
+
setCloseCallback(() => overlayState.close);
|
|
160
|
+
|
|
161
|
+
// Cleanup on unmount
|
|
162
|
+
onCleanup(() => {
|
|
163
|
+
if (closeTimeout) {
|
|
164
|
+
clearTimeout(closeTimeout);
|
|
165
|
+
}
|
|
166
|
+
if (tooltips[id]) {
|
|
167
|
+
delete tooltips[id];
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
isOpen: overlayState.isOpen,
|
|
173
|
+
open: (immediate?: boolean) => {
|
|
174
|
+
if (isServer) return;
|
|
175
|
+
if (!immediate && delay() > 0 && !closeTimeout) {
|
|
176
|
+
warmupTooltip();
|
|
177
|
+
} else {
|
|
178
|
+
showTooltip();
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
close: hideTooltip,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TreeCollection implementation.
|
|
3
|
+
* Based on @react-stately/tree/TreeCollection.
|
|
4
|
+
*
|
|
5
|
+
* A flattened view of tree nodes that respects expanded state.
|
|
6
|
+
* Only visible nodes (root + expanded children) are included in iteration.
|
|
7
|
+
*/
|
|
8
|
+
import type { Key } from '../collections/types';
|
|
9
|
+
import type { TreeCollection as ITreeCollection, TreeNode, TreeItemData } from './types';
|
|
10
|
+
/**
|
|
11
|
+
* Creates a TreeCollection from hierarchical data.
|
|
12
|
+
* The collection is flattened based on expanded keys.
|
|
13
|
+
*/
|
|
14
|
+
export declare class TreeCollection<T> implements ITreeCollection<T> {
|
|
15
|
+
private keyMap;
|
|
16
|
+
private visibleKeys;
|
|
17
|
+
private _rows;
|
|
18
|
+
constructor(items: TreeItemData<T>[], expandedKeys: Set<Key>);
|
|
19
|
+
private buildCollection;
|
|
20
|
+
get size(): number;
|
|
21
|
+
get rows(): TreeNode<T>[];
|
|
22
|
+
get rowCount(): number;
|
|
23
|
+
getKeys(): Iterable<Key>;
|
|
24
|
+
getItem(key: Key): TreeNode<T> | null;
|
|
25
|
+
at(index: number): TreeNode<T> | null;
|
|
26
|
+
getKeyBefore(key: Key): Key | null;
|
|
27
|
+
getKeyAfter(key: Key): Key | null;
|
|
28
|
+
getFirstKey(): Key | null;
|
|
29
|
+
getLastKey(): Key | null;
|
|
30
|
+
getChildren(key: Key): Iterable<TreeNode<T>>;
|
|
31
|
+
getTextValue(key: Key): string;
|
|
32
|
+
getParentKey(key: Key): Key | null;
|
|
33
|
+
[Symbol.iterator](): Iterator<TreeNode<T>>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Factory function to create a TreeCollection.
|
|
37
|
+
* Useful for the collectionFactory pattern in TreeStateOptions.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createTreeCollection<T>(items: TreeItemData<T>[], expandedKeys: Set<Key>): TreeCollection<T>;
|
|
40
|
+
//# sourceMappingURL=TreeCollection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeCollection.d.ts","sourceRoot":"","sources":["TreeCollection.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,IAAI,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEzF;;;GAGG;AACH,qBAAa,cAAc,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,MAAM,CAAoC;IAClD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,KAAK,CAAqB;gBAGhC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EACxB,YAAY,EAAE,GAAG,CAAC,GAAG,CAAC;IAKxB,OAAO,CAAC,eAAe;IAqEvB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,IAAI,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAExB;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAID,OAAO,IAAI,QAAQ,CAAC,GAAG,CAAC;IAIxB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;IAIrC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;IAOrC,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI;IAMlC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI;IAMjC,WAAW,IAAI,GAAG,GAAG,IAAI;IAIzB,UAAU,IAAI,GAAG,GAAG,IAAI;IAIxB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAK5C,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM;IAK9B,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI;IAKlC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;CAG3C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EACxB,YAAY,EAAE,GAAG,CAAC,GAAG,CAAC,GACrB,cAAc,CAAC,CAAC,CAAC,CAEnB"}
|