@marianmeres/stuic 1.20.0 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/actions/autogrow.d.ts +8 -0
  2. package/dist/actions/autogrow.js +22 -0
  3. package/dist/actions/trim.d.ts +4 -0
  4. package/dist/actions/trim.js +18 -0
  5. package/dist/actions/validate.d.ts +22 -0
  6. package/dist/actions/validate.js +80 -0
  7. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +463 -0
  8. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +104 -0
  9. package/dist/components/AlertConfirmPrompt/acp-icons.d.ts +7 -0
  10. package/dist/components/AlertConfirmPrompt/acp-icons.js +134 -0
  11. package/dist/components/AlertConfirmPrompt/alert-confirm-prompt.d.ts +55 -0
  12. package/dist/components/AlertConfirmPrompt/alert-confirm-prompt.js +126 -0
  13. package/dist/components/Button/Button.svelte +18 -9
  14. package/dist/components/Button/Button.svelte.d.ts +1 -1
  15. package/dist/components/Input/Field.svelte +179 -0
  16. package/dist/components/Input/Field.svelte.d.ts +63 -0
  17. package/dist/components/Input/FieldCheckbox.svelte +102 -0
  18. package/dist/components/Input/FieldCheckbox.svelte.d.ts +34 -0
  19. package/dist/components/Input/FieldRadios.svelte +51 -0
  20. package/dist/components/Input/FieldRadios.svelte.d.ts +31 -0
  21. package/dist/components/Input/FieldSelect.svelte +125 -0
  22. package/dist/components/Input/FieldSelect.svelte.d.ts +47 -0
  23. package/dist/components/Input/Fieldset.svelte +27 -0
  24. package/dist/components/Input/Fieldset.svelte.d.ts +20 -0
  25. package/dist/components/Input/XFieldRadioInternal.svelte +102 -0
  26. package/dist/components/Input/XFieldRadioInternal.svelte.d.ts +33 -0
  27. package/dist/components/Switch/Switch.svelte.d.ts +1 -1
  28. package/dist/components/Thc/Thc.svelte +15 -0
  29. package/dist/components/Thc/Thc.svelte.d.ts +28 -0
  30. package/dist/index.d.ts +11 -0
  31. package/dist/index.js +13 -0
  32. package/package.json +3 -2
@@ -0,0 +1,8 @@
1
+ export declare function increaseHeightToScrollHeight(el: HTMLElement, max?: number, min?: number): void;
2
+ export declare function autogrow(el: HTMLTextAreaElement, options?: Partial<{
3
+ max: number;
4
+ min: number;
5
+ allowed: boolean;
6
+ }> | null): {
7
+ destroy: () => void;
8
+ } | undefined;
@@ -0,0 +1,22 @@
1
+ // actual worker
2
+ export function increaseHeightToScrollHeight(el, max = 0, min = 16) {
3
+ //
4
+ let h = max ? Math.min(max, el.scrollHeight) : el.scrollHeight;
5
+ h = Math.max(min, h);
6
+ // only increase size
7
+ if (el.getBoundingClientRect().height < h) {
8
+ el.style.height = `${h}px`;
9
+ }
10
+ }
11
+ // action wrap
12
+ export function autogrow(el, options = null) {
13
+ const { max, min, allowed } = { max: 250, min: 64, allowed: true, ...(options || {}) };
14
+ if (!allowed)
15
+ return;
16
+ const _doGrow = () => increaseHeightToScrollHeight(el, max, min);
17
+ _doGrow(); // resize asap (on mount) as well...
18
+ el.addEventListener('input', _doGrow);
19
+ return {
20
+ destroy: () => el.removeEventListener('input', _doGrow),
21
+ };
22
+ }
@@ -0,0 +1,4 @@
1
+ export declare const trim: (el: HTMLInputElement | HTMLTextAreaElement, enabled?: boolean) => {
2
+ update(enabledFlag?: boolean): void;
3
+ destroy(): void;
4
+ };
@@ -0,0 +1,18 @@
1
+ export const trim = (el, enabled = true) => {
2
+ const trim = (e) => {
3
+ if (enabled && typeof el.value === 'string') {
4
+ el.value = el.value.trim();
5
+ }
6
+ };
7
+ el.addEventListener('change', trim);
8
+ return {
9
+ update(enabledFlag) {
10
+ if (enabledFlag !== undefined) {
11
+ enabled = !!enabled;
12
+ }
13
+ },
14
+ destroy() {
15
+ el.removeEventListener('change', trim);
16
+ },
17
+ };
18
+ };
@@ -0,0 +1,22 @@
1
+ export interface ValidationResult {
2
+ validity: ValidityState;
3
+ reasons: (keyof ValidityStateFlags)[];
4
+ valid: boolean;
5
+ message: string;
6
+ }
7
+ type ReasonTranslate = (reason: keyof ValidityStateFlags, value: any, fallback: string) => string;
8
+ export interface ValidateOptions {
9
+ context?: Record<string, any>;
10
+ customValidator?: (value: any, context: Record<string, any> | undefined, el: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement) => string | undefined;
11
+ on?: 'input' | 'change';
12
+ setValidationResult?: (res: ValidationResult) => void;
13
+ t?: false | ReasonTranslate;
14
+ }
15
+ export declare const validate: {
16
+ (el: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement, options: undefined | ValidateOptions): {
17
+ update(newOptions: undefined | ValidateOptions): void;
18
+ destroy(): void;
19
+ };
20
+ t: null;
21
+ };
22
+ export {};
@@ -0,0 +1,80 @@
1
+ export const validate = (el, options) => {
2
+ let _doValidate = !!options;
3
+ let context = options?.context;
4
+ let customValidator = options?.customValidator;
5
+ let onEventName = options?.on || 'change';
6
+ const t = (reason, value, fallback) => {
7
+ if (!reason || options?.t === false)
8
+ return fallback;
9
+ // local t (if any)
10
+ if (typeof options?.t === 'function')
11
+ return options.t(reason, value, fallback);
12
+ // global t (if any)
13
+ if (typeof validate.t === 'function')
14
+ return validate.t(reason, value, fallback);
15
+ //
16
+ return fallback;
17
+ };
18
+ const doValidate = (event) => {
19
+ if (!_doValidate)
20
+ return;
21
+ el.checkValidity();
22
+ if (typeof customValidator === 'function') {
23
+ el.setCustomValidity(customValidator(el.value, context, el) || '');
24
+ }
25
+ // toto trigerne bubble
26
+ // el.reportValidity();
27
+ const validityState = el.validity;
28
+ // prettier-ignore
29
+ const reasons = [
30
+ 'badInput', 'customError', 'patternMismatch', 'rangeOverflow', 'rangeUnderflow',
31
+ 'stepMismatch', 'tooLong', 'tooShort', 'typeMismatch', 'valueMissing'
32
+ ].reduce((m, k) => {
33
+ if (validityState[k])
34
+ m.push(k);
35
+ return m;
36
+ }, []);
37
+ if (typeof options?.setValidationResult === 'function') {
38
+ options.setValidationResult({
39
+ validity: validityState,
40
+ reasons,
41
+ valid: validityState?.valid,
42
+ // use translate fn for first reason (if fn provided and allowed),
43
+ // otherwise fallback to native msg
44
+ message: t(reasons?.[0], el.value, el.validationMessage),
45
+ });
46
+ }
47
+ };
48
+ el.addEventListener(onEventName, doValidate);
49
+ //
50
+ let _touchCount = 0;
51
+ const onFocus = (e) => _touchCount++;
52
+ el.addEventListener('focus', onFocus);
53
+ // also validate on first blur
54
+ const onBlur = (e) => _touchCount === 1 && doValidate(e);
55
+ el.addEventListener('blur', onBlur);
56
+ //
57
+ // const onChange = (e) => doValidate(e);
58
+ // el.addEventListener('change', onChange);
59
+ //
60
+ // const onInput = (e) => _touchCount > 1 && doValidate(e);
61
+ // el.addEventListener('input', onInput);
62
+ //
63
+ return {
64
+ update(newOptions) {
65
+ _doValidate = !!newOptions;
66
+ // allow only context to update
67
+ context = newOptions?.context;
68
+ },
69
+ destroy() {
70
+ el.removeEventListener(onEventName, doValidate);
71
+ el.removeEventListener('focus', onFocus);
72
+ el.removeEventListener('blur', onBlur);
73
+ // el.removeEventListener('change', onChange);
74
+ // el.removeEventListener('input', onInput);
75
+ },
76
+ };
77
+ };
78
+ // ReasonTranslate
79
+ const t = null;
80
+ validate.t = t;
@@ -0,0 +1,463 @@
1
+ <script context="module">import { onMount } from "svelte";
2
+ import { Button, focusTrap } from "../../index.js";
3
+ import Thc from "../Thc/Thc.svelte";
4
+ import {
5
+ AlertConfirmPromptType
6
+ } from "./alert-confirm-prompt.js";
7
+ import { twMerge } from "tailwind-merge";
8
+ import { Field } from "../../index.js";
9
+ import { acpDefaultIcons } from "./acp-icons.js";
10
+ import { createClog } from "@marianmeres/clog";
11
+ export class AlertConfirmPromptConfig {
12
+ // sane defaults which perhaps should stay untouched
13
+ static preset = {
14
+ dialog: `
15
+ relative
16
+ w-full sm:max-w-xl
17
+ mx-auto
18
+ p-5 sm:p-6
19
+ bg-white text-black
20
+ dark:bg-black dark:text-white
21
+ rounded-lg
22
+ transition-all
23
+ shadow-xl
24
+ focus-within:outline-0 focus-within:ring-0
25
+ `.trim(),
26
+ icon: `
27
+ size-12 sm:size-10
28
+ mt-1 mb-4 sm:my-0
29
+ mx-auto
30
+ flex flex-shrink-0 items-center justify-center
31
+ rounded-full
32
+ bg-neutral-100 text-black/50
33
+ `.trim(),
34
+ contentBlock: `
35
+ mt-3 sm:ml-4 sm:mt-0 sm:flex-1
36
+ `.trim(),
37
+ title: `
38
+ text-center sm:text-left
39
+ text-base font-semibold leading-6 text-black/90
40
+ `.trim(),
41
+ content: `
42
+ mt-2 mx-3 sm:mx-0
43
+ text-center sm:text-left
44
+ text-sm text-black/75
45
+ `.trim(),
46
+ inputBox: `
47
+ mt-3
48
+ `.trim(),
49
+ inputField: `
50
+ m-0
51
+ `.trim(),
52
+ menu: `
53
+ mt-6
54
+ sm:flex sm:space-x-4 justify-end
55
+ space-y-3 sm:space-y-0
56
+ `.trim(),
57
+ menuLi: `
58
+ flex-1 sm:flex-none w-full sm:w-auto sm:inline-block
59
+ `.trim(),
60
+ button: `
61
+ w-full min-w-24 text-center inline-block
62
+ `.trim(),
63
+ spinnerBox: `
64
+ absolute inset-0 flex justify-center items-center
65
+ rounded-lg
66
+ bg-white/50
67
+ `.trim()
68
+ };
69
+ // main userland configuration
70
+ static classDialog = "";
71
+ static classIcon = "";
72
+ static classTitle = "";
73
+ static classContentBlock = "";
74
+ static classContent = "";
75
+ static classInputBox = "";
76
+ static classInputField = "";
77
+ static classMenu = "";
78
+ static classMenuLi = "";
79
+ static classButton = "";
80
+ static classSpinnerBox = "";
81
+ // 'info' | 'success' | 'warn' | 'error'
82
+ // userlang variant fine tuning
83
+ static variant = {
84
+ info: {
85
+ dialog: "",
86
+ icon: "",
87
+ contentBlock: "",
88
+ title: "",
89
+ content: "",
90
+ inputBox: "",
91
+ inputField: "",
92
+ menu: "",
93
+ menuLi: "",
94
+ button: "",
95
+ spinnerBox: ""
96
+ },
97
+ success: {
98
+ dialog: "",
99
+ icon: "",
100
+ contentBlock: "",
101
+ title: "",
102
+ content: "",
103
+ inputBox: "",
104
+ inputField: "",
105
+ menu: "",
106
+ menuLi: "",
107
+ button: "",
108
+ spinnerBox: ""
109
+ },
110
+ warn: {
111
+ dialog: "",
112
+ icon: "",
113
+ contentBlock: "",
114
+ title: "",
115
+ content: "",
116
+ inputBox: "",
117
+ inputField: "",
118
+ menu: "",
119
+ menuLi: "",
120
+ button: "",
121
+ spinnerBox: ""
122
+ },
123
+ error: {
124
+ dialog: "",
125
+ icon: "",
126
+ contentBlock: "",
127
+ title: "",
128
+ content: "",
129
+ inputBox: "",
130
+ inputField: "",
131
+ menu: "",
132
+ menuLi: "",
133
+ button: "",
134
+ spinnerBox: ""
135
+ }
136
+ };
137
+ static iconFn = {
138
+ info: void 0,
139
+ success: void 0,
140
+ warn: void 0,
141
+ error: void 0,
142
+ spinner: void 0
143
+ };
144
+ }
145
+ const _isFn = (v) => typeof v === "function";
146
+ const { ALERT, CONFIRM, PROMPT } = AlertConfirmPromptType;
147
+ </script>
148
+
149
+ <script>const clog = createClog("AlertConfirmPrompt");
150
+ export let acp;
151
+ $:
152
+ dialog = $acp[0];
153
+ let _dialogEl;
154
+ let value = null;
155
+ let isPending = false;
156
+ $:
157
+ if (dialog?.type === PROMPT) {
158
+ if (value === null)
159
+ value = dialog.value;
160
+ } else {
161
+ value = null;
162
+ }
163
+ $:
164
+ if (dialog && _dialogEl)
165
+ !_dialogEl.hasAttribute("open") && _dialogEl.showModal();
166
+ $:
167
+ if (!dialog && _dialogEl)
168
+ _dialogEl.close("cleanup");
169
+ const onKeyDown = (e) => {
170
+ if (!dialog)
171
+ return;
172
+ if (e.key === "Escape") {
173
+ e.stopPropagation();
174
+ if (!isPending)
175
+ return acp.escape();
176
+ }
177
+ };
178
+ onMount(() => {
179
+ _dialogEl.addEventListener("close", async () => {
180
+ if (_dialogEl.returnValue === "") {
181
+ acp.escape();
182
+ }
183
+ });
184
+ _dialogEl.addEventListener("cancel", (event) => event.preventDefault());
185
+ document.addEventListener("keydown", onKeyDown, true);
186
+ return () => document.removeEventListener("keydown", onKeyDown, true);
187
+ });
188
+ $:
189
+ _dialogClass = twMerge(`
190
+ ${AlertConfirmPromptConfig.preset.dialog}
191
+ ${AlertConfirmPromptConfig.classDialog}
192
+ ${dialog?.class?.dialog || ""}
193
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.dialog || ""}
194
+ `);
195
+ $:
196
+ _iconClass = twMerge(`
197
+ ${AlertConfirmPromptConfig.preset.icon}
198
+ ${AlertConfirmPromptConfig.classIcon}
199
+ ${dialog?.class?.icon || ""}
200
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.icon || ""}
201
+ `);
202
+ $:
203
+ _contentBlockClass = twMerge(`
204
+ ${AlertConfirmPromptConfig.preset.contentBlock}
205
+ ${AlertConfirmPromptConfig.classContentBlock}
206
+ ${dialog?.class?.contentBlock || ""}
207
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.contentBlock || ""}
208
+ `);
209
+ $:
210
+ _titleClass = twMerge(`
211
+ ${AlertConfirmPromptConfig.preset.title}
212
+ ${AlertConfirmPromptConfig.classTitle}
213
+ ${dialog?.class?.title || ""}
214
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.title || ""}
215
+ `);
216
+ $:
217
+ _contentClass = twMerge(`
218
+ ${AlertConfirmPromptConfig.preset.content}
219
+ ${AlertConfirmPromptConfig.classContent}
220
+ ${dialog?.class?.content || ""}
221
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.content || ""}
222
+ `);
223
+ $:
224
+ _inputBoxClass = twMerge(`
225
+ ${AlertConfirmPromptConfig.preset.inputBox}
226
+ ${AlertConfirmPromptConfig.classInputBox}
227
+ ${dialog?.class?.inputBox || ""}
228
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.inputBox || ""}
229
+ `);
230
+ $:
231
+ _inputFieldClass = twMerge(`
232
+ ${AlertConfirmPromptConfig.preset.inputField}
233
+ ${AlertConfirmPromptConfig.classInputField}
234
+ ${dialog?.class?.inputField || ""}
235
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.inputField || ""}
236
+ `);
237
+ $:
238
+ _menuClass = twMerge(`
239
+ ${AlertConfirmPromptConfig.preset.menu}
240
+ ${AlertConfirmPromptConfig.classMenu}
241
+ ${dialog?.class?.menu || ""}
242
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.menu || ""}
243
+ `);
244
+ $:
245
+ _menuLiClass = twMerge(`
246
+ ${AlertConfirmPromptConfig.preset.menuLi}
247
+ ${AlertConfirmPromptConfig.classMenuLi}
248
+ ${dialog?.class?.menuLi || ""}
249
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.menuLi || ""}
250
+ `);
251
+ $:
252
+ _buttonClass = twMerge(`
253
+ ${AlertConfirmPromptConfig.preset.button}
254
+ ${AlertConfirmPromptConfig.classButton}
255
+ ${dialog?.class?.button || ""}
256
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.button || ""}
257
+ `);
258
+ $:
259
+ _spinnerBoxClass = twMerge(`
260
+ ${AlertConfirmPromptConfig.preset.spinnerBox}
261
+ ${AlertConfirmPromptConfig.classSpinnerBox}
262
+ ${dialog?.class?.spinnerBox || ""}
263
+ ${AlertConfirmPromptConfig.variant?.[dialog?.variant]?.spinnerBox || ""}
264
+ `);
265
+ let iconFn = false;
266
+ $:
267
+ if (dialog?.iconFn === true) {
268
+ iconFn = // either runtime config
269
+ AlertConfirmPromptConfig.iconFn[dialog?.variant] || // or fixed default
270
+ acpDefaultIcons[dialog?.variant];
271
+ } else if (dialog?.iconFn) {
272
+ iconFn = dialog.iconFn;
273
+ } else {
274
+ iconFn = false;
275
+ }
276
+ $:
277
+ clog(dialog);
278
+ </script>
279
+
280
+ <dialog
281
+ bind:this={_dialogEl}
282
+ data-acp-type={dialog?.type}
283
+ data-acp-variant={dialog?.variant}
284
+ data-acp-is-pending={isPending}
285
+ class="bg-transparent w-full focus-within:outline-0 focus-within:ring-0"
286
+ tabindex="-1"
287
+ >
288
+ {#if dialog}
289
+ <!--since we're not using the native form submit, the <form> is not necessary-->
290
+ <form
291
+ method="dialog"
292
+ use:focusTrap={{ autoFocusFirst: false }}
293
+ tabindex="-1"
294
+ data-acp-type={dialog?.type}
295
+ data-acp-variant={dialog?.variant}
296
+ data-acp-is-pending={isPending}
297
+ class={_dialogClass}
298
+ >
299
+ <!-- this sm:flex is not configurable -->
300
+ <div class="sm:flex sm:items-start">
301
+ {#if _isFn(iconFn)}
302
+ <div
303
+ class={_iconClass}
304
+ data-acp-type={dialog?.type}
305
+ data-acp-variant={dialog?.variant}
306
+ data-acp-is-pending={isPending}
307
+ >
308
+ {@html iconFn()}
309
+ </div>
310
+ {/if}
311
+ <div class={_contentBlockClass}>
312
+ <h1
313
+ class={_titleClass}
314
+ data-acp-type={dialog?.type}
315
+ data-acp-variant={dialog?.variant}
316
+ data-acp-is-pending={isPending}
317
+ >
318
+ <Thc thc={dialog.title} />
319
+ </h1>
320
+ {#if dialog.content}
321
+ <div
322
+ class={_contentClass}
323
+ data-acp-type={dialog?.type}
324
+ data-acp-variant={dialog?.variant}
325
+ data-acp-is-pending={isPending}
326
+ >
327
+ <Thc thc={dialog.content} />
328
+ </div>
329
+ {/if}
330
+ {#if dialog.type === PROMPT}
331
+ <div
332
+ class={_inputBoxClass}
333
+ data-acp-type={dialog?.type}
334
+ data-acp-variant={dialog?.variant}
335
+ data-acp-is-pending={isPending}
336
+ >
337
+ <Field
338
+ class={_inputFieldClass}
339
+ bind:value
340
+ data-acp-type={dialog?.type}
341
+ data-acp-variant={dialog?.variant}
342
+ data-acp-is-pending={isPending}
343
+ on:input_mounted={({ detail }) => detail.focus()}
344
+ size="sm"
345
+ />
346
+ </div>
347
+ {/if}
348
+ </div>
349
+ </div>
350
+ <menu
351
+ class={_menuClass}
352
+ data-acp-type={dialog?.type}
353
+ data-acp-variant={dialog?.variant}
354
+ data-acp-is-pending={isPending}
355
+ >
356
+ {#if dialog.type !== ALERT}
357
+ <li
358
+ class={_menuLiClass}
359
+ data-acp-dialog-type={dialog?.type}
360
+ data-acp-variant={dialog?.variant}
361
+ data-acp-is-pending={isPending}
362
+ >
363
+ <Button
364
+ class={_buttonClass}
365
+ on:click={async (e) => {
366
+ e.preventDefault();
367
+ isPending = true;
368
+ await Promise.resolve(dialog.onCancel(false));
369
+ isPending = false;
370
+ value = null;
371
+ }}
372
+ type="reset"
373
+ data-acp-button-type="cancel"
374
+ data-acp-dialog-type={dialog?.type}
375
+ data-acp-variant={dialog?.variant}
376
+ data-acp-is-pending={isPending}
377
+ disabled={isPending}
378
+ >
379
+ <Thc thc={dialog.labelCancel} />
380
+ </Button>
381
+ </li>
382
+ {/if}
383
+ {#if dialog.labelCustom && _isFn(dialog.onCustom)}
384
+ <li
385
+ class={_menuLiClass}
386
+ data-acp-dialog-type={dialog?.type}
387
+ data-acp-variant={dialog?.variant}
388
+ data-acp-is-pending={isPending}
389
+ >
390
+ <Button
391
+ class={_buttonClass}
392
+ on:click={async (e) => {
393
+ e.preventDefault();
394
+ isPending = true;
395
+ await Promise.resolve(dialog.onCustom(value));
396
+ isPending = false;
397
+ value = null;
398
+ }}
399
+ type="button"
400
+ data-acp-button-type="custom"
401
+ data-acp-dialog-type={dialog?.type}
402
+ data-acp-variant={dialog?.variant}
403
+ data-acp-is-pending={isPending}
404
+ disabled={isPending}
405
+ >
406
+ <Thc thc={dialog.labelCustom} />
407
+ </Button>
408
+ </li>
409
+ {/if}
410
+ <li
411
+ class={_menuLiClass}
412
+ data-acp-type={dialog?.type}
413
+ data-acp-variant={dialog?.variant}
414
+ data-acp-is-pending={isPending}
415
+ >
416
+ <Button
417
+ class={_buttonClass}
418
+ type="submit"
419
+ value="OK"
420
+ data-acp-button-type="ok"
421
+ data-acp-dialog-type={dialog?.type}
422
+ data-acp-variant={dialog?.variant}
423
+ data-acp-is-pending={isPending}
424
+ on:click={async (e) => {
425
+ e.preventDefault();
426
+ isPending = true;
427
+ await Promise.resolve(dialog.onOk(dialog.type === PROMPT ? value : true));
428
+ isPending = false;
429
+ value = null;
430
+ }}
431
+ disabled={isPending}
432
+ variant="primary"
433
+ >
434
+ <Thc thc={dialog.labelOk} />
435
+ </Button>
436
+ </li>
437
+ </menu>
438
+ {#if isPending}
439
+ <div
440
+ class={_spinnerBoxClass}
441
+ data-acp-type={dialog?.type}
442
+ data-acp-variant={dialog?.variant}
443
+ >
444
+ <div class="rotating-cw">
445
+ {@html acpDefaultIcons.spinner()}
446
+ </div>
447
+ </div>
448
+ {/if}
449
+ </form>
450
+ {/if}
451
+ </dialog>
452
+
453
+ <style>@keyframes -global-rotating-cw {
454
+ from {
455
+ transform: rotate(0deg);
456
+ }
457
+ to {
458
+ transform: rotate(360deg);
459
+ }
460
+ }
461
+ .rotating-cw {
462
+ animation: rotating-cw 0.6s linear infinite;
463
+ }</style>