@konomi-app/ui 2.3.0 → 4.0.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/dist/index.js CHANGED
@@ -1,5 +1,1158 @@
1
- export * from './loading-overlay';
2
- export * from './task-list-overlay';
3
- export * from './modal';
4
- export * from './utilities';
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __typeError = (msg) => {
4
+ throw TypeError(msg);
5
+ };
6
+ var __decorateClass = (decorators, target, key, kind) => {
7
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
8
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
9
+ if (decorator = decorators[i])
10
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
11
+ if (kind && result) __defProp(target, key, result);
12
+ return result;
13
+ };
14
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
15
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
16
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
17
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
18
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
19
+
20
+ // src/types.ts
21
+ var createInitialState = () => ({
22
+ open: false,
23
+ dialogType: "loading",
24
+ icon: null,
25
+ label: "",
26
+ description: "",
27
+ html: "",
28
+ progress: null,
29
+ showConfirmButton: true,
30
+ showCancelButton: false,
31
+ confirmButtonText: "OK",
32
+ cancelButtonText: "\u30AD\u30E3\u30F3\u30BB\u30EB",
33
+ allowOutsideClick: true,
34
+ allowEscapeKey: true,
35
+ queues: [],
36
+ steps: [],
37
+ timer: null
38
+ });
39
+
40
+ // src/controller.ts
41
+ var _state, _listeners, _resolver, _timerId, _DialogController_instances, emit_fn, update_fn, createPromise_fn, resolve_fn, clearTimer_fn, updateItemStatus_fn;
42
+ var DialogController = class {
43
+ constructor() {
44
+ __privateAdd(this, _DialogController_instances);
45
+ __privateAdd(this, _state);
46
+ __privateAdd(this, _listeners, /* @__PURE__ */ new Set());
47
+ __privateAdd(this, _resolver, null);
48
+ __privateAdd(this, _timerId, null);
49
+ __privateSet(this, _state, createInitialState());
50
+ }
51
+ // ─── Observable ──────────────────────────────────────────
52
+ get state() {
53
+ return __privateGet(this, _state);
54
+ }
55
+ subscribe(fn) {
56
+ __privateGet(this, _listeners).add(fn);
57
+ return () => __privateGet(this, _listeners).delete(fn);
58
+ }
59
+ // ─── Core ────────────────────────────────────────────────
60
+ show(options = { type: "loading" }) {
61
+ __privateMethod(this, _DialogController_instances, clearTimer_fn).call(this);
62
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, {
63
+ open: true,
64
+ dialogType: options.type,
65
+ label: options.label ?? "",
66
+ description: options.description ?? "",
67
+ icon: options.icon ?? null,
68
+ progress: options.progress ?? null,
69
+ allowOutsideClick: options.allowOutsideClick ?? false,
70
+ showConfirmButton: false,
71
+ showCancelButton: false
72
+ });
73
+ }
74
+ hide() {
75
+ __privateMethod(this, _DialogController_instances, clearTimer_fn).call(this);
76
+ const wasOpen = __privateGet(this, _state).open;
77
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, { ...createInitialState(), open: false });
78
+ if (wasOpen && __privateGet(this, _resolver)) {
79
+ __privateMethod(this, _DialogController_instances, resolve_fn).call(this, { isConfirmed: false, isCanceled: false, isDismissed: true });
80
+ }
81
+ }
82
+ // ─── Alert ───────────────────────────────────────────────
83
+ alert(optionsOrLabel) {
84
+ __privateMethod(this, _DialogController_instances, clearTimer_fn).call(this);
85
+ const opts = typeof optionsOrLabel === "string" ? { label: optionsOrLabel } : optionsOrLabel;
86
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, {
87
+ open: true,
88
+ dialogType: "alert",
89
+ icon: opts.type ?? "info",
90
+ label: opts.label ?? "",
91
+ description: opts.description ?? "",
92
+ html: opts.html ?? "",
93
+ showConfirmButton: true,
94
+ showCancelButton: opts.showCancelButton ?? false,
95
+ confirmButtonText: opts.confirmButtonText ?? "OK",
96
+ cancelButtonText: opts.cancelButtonText ?? "\u30AD\u30E3\u30F3\u30BB\u30EB",
97
+ allowOutsideClick: opts.allowOutsideClick ?? true,
98
+ allowEscapeKey: opts.allowEscapeKey ?? true,
99
+ progress: null,
100
+ timer: opts.timer ?? null
101
+ });
102
+ return __privateMethod(this, _DialogController_instances, createPromise_fn).call(this, opts.timer ?? null);
103
+ }
104
+ // ─── Confirm ─────────────────────────────────────────────
105
+ confirm(optionsOrLabel) {
106
+ __privateMethod(this, _DialogController_instances, clearTimer_fn).call(this);
107
+ const opts = typeof optionsOrLabel === "string" ? { label: optionsOrLabel } : optionsOrLabel;
108
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, {
109
+ open: true,
110
+ dialogType: "confirm",
111
+ icon: opts.type ?? "warning",
112
+ label: opts.label ?? "",
113
+ description: opts.description ?? "",
114
+ showConfirmButton: true,
115
+ showCancelButton: true,
116
+ confirmButtonText: opts.confirmButtonText ?? "OK",
117
+ cancelButtonText: opts.cancelButtonText ?? "\u30AD\u30E3\u30F3\u30BB\u30EB",
118
+ allowOutsideClick: opts.allowOutsideClick ?? false,
119
+ allowEscapeKey: opts.allowEscapeKey ?? true,
120
+ progress: null,
121
+ timer: null
122
+ });
123
+ return __privateMethod(this, _DialogController_instances, createPromise_fn).call(this, null).then((r) => r.isConfirmed);
124
+ }
125
+ // ─── Loading helpers ─────────────────────────────────────
126
+ loading(label) {
127
+ this.show({ type: "loading", label });
128
+ }
129
+ progress(percent) {
130
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, { progress: percent });
131
+ }
132
+ label(label) {
133
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, { label });
134
+ }
135
+ description(description) {
136
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, { description });
137
+ }
138
+ // ─── Queue ───────────────────────────────────────────────
139
+ setQueues(labels) {
140
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, {
141
+ queues: labels.map((label) => ({ label, status: "pending" }))
142
+ });
143
+ }
144
+ queue(labels) {
145
+ this.setQueues(labels);
146
+ this.show({ type: "queue" });
147
+ }
148
+ startQueue(label) {
149
+ __privateMethod(this, _DialogController_instances, updateItemStatus_fn).call(this, "queues", label, "active");
150
+ }
151
+ finishQueue(label) {
152
+ __privateMethod(this, _DialogController_instances, updateItemStatus_fn).call(this, "queues", label, "done");
153
+ }
154
+ skipQueue(label) {
155
+ __privateMethod(this, _DialogController_instances, updateItemStatus_fn).call(this, "queues", label, "skipped");
156
+ }
157
+ errorQueue(label) {
158
+ __privateMethod(this, _DialogController_instances, updateItemStatus_fn).call(this, "queues", label, "error");
159
+ }
160
+ clearQueues() {
161
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, { queues: [] });
162
+ }
163
+ // ─── Steps ───────────────────────────────────────────────
164
+ setSteps(labels) {
165
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, {
166
+ steps: labels.map((label) => ({ label, status: "pending" }))
167
+ });
168
+ }
169
+ steps(labels) {
170
+ this.setSteps(labels);
171
+ this.show({ type: "steps" });
172
+ }
173
+ startStep(label) {
174
+ __privateMethod(this, _DialogController_instances, updateItemStatus_fn).call(this, "steps", label, "active");
175
+ }
176
+ finishStep(label) {
177
+ __privateMethod(this, _DialogController_instances, updateItemStatus_fn).call(this, "steps", label, "done");
178
+ }
179
+ skipStep(label) {
180
+ __privateMethod(this, _DialogController_instances, updateItemStatus_fn).call(this, "steps", label, "skipped");
181
+ }
182
+ errorStep(label) {
183
+ __privateMethod(this, _DialogController_instances, updateItemStatus_fn).call(this, "steps", label, "error");
184
+ }
185
+ clearSteps() {
186
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, { steps: [] });
187
+ }
188
+ // ─── Button actions (called from the component) ──────────
189
+ onConfirm() {
190
+ __privateMethod(this, _DialogController_instances, clearTimer_fn).call(this);
191
+ const r = { isConfirmed: true, isCanceled: false, isDismissed: false };
192
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, { ...createInitialState(), open: false });
193
+ __privateMethod(this, _DialogController_instances, resolve_fn).call(this, r);
194
+ }
195
+ onCancel() {
196
+ __privateMethod(this, _DialogController_instances, clearTimer_fn).call(this);
197
+ const r = { isConfirmed: false, isCanceled: true, isDismissed: false };
198
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, { ...createInitialState(), open: false });
199
+ __privateMethod(this, _DialogController_instances, resolve_fn).call(this, r);
200
+ }
201
+ onOutsideClick() {
202
+ if (!__privateGet(this, _state).allowOutsideClick) return;
203
+ this.onCancel();
204
+ }
205
+ onEscapeKey() {
206
+ if (!__privateGet(this, _state).allowEscapeKey) return;
207
+ this.onCancel();
208
+ }
209
+ };
210
+ _state = new WeakMap();
211
+ _listeners = new WeakMap();
212
+ _resolver = new WeakMap();
213
+ _timerId = new WeakMap();
214
+ _DialogController_instances = new WeakSet();
215
+ emit_fn = function() {
216
+ const snapshot = { ...__privateGet(this, _state) };
217
+ for (const fn of __privateGet(this, _listeners)) fn(snapshot);
218
+ };
219
+ update_fn = function(patch) {
220
+ Object.assign(__privateGet(this, _state), patch);
221
+ __privateMethod(this, _DialogController_instances, emit_fn).call(this);
222
+ };
223
+ // ─── Internal ────────────────────────────────────────────
224
+ createPromise_fn = function(timer) {
225
+ return new Promise((resolve) => {
226
+ __privateSet(this, _resolver, resolve);
227
+ if (timer != null && timer > 0) {
228
+ __privateSet(this, _timerId, setTimeout(() => {
229
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, { ...createInitialState(), open: false });
230
+ resolve({ isConfirmed: false, isCanceled: false, isDismissed: true });
231
+ __privateSet(this, _resolver, null);
232
+ }, timer));
233
+ }
234
+ });
235
+ };
236
+ resolve_fn = function(result) {
237
+ const resolver = __privateGet(this, _resolver);
238
+ __privateSet(this, _resolver, null);
239
+ resolver?.(result);
240
+ };
241
+ clearTimer_fn = function() {
242
+ if (__privateGet(this, _timerId) != null) {
243
+ clearTimeout(__privateGet(this, _timerId));
244
+ __privateSet(this, _timerId, null);
245
+ }
246
+ };
247
+ updateItemStatus_fn = function(key, label, status) {
248
+ const items = [...__privateGet(this, _state)[key]];
249
+ const idx = items.findIndex((i) => i.label === label);
250
+ if (idx >= 0) {
251
+ items[idx] = { ...items[idx], status };
252
+ __privateMethod(this, _DialogController_instances, update_fn).call(this, { [key]: items });
253
+ }
254
+ };
255
+
256
+ // src/overlay-dialog.ts
257
+ import { LitElement, html, nothing } from "lit";
258
+ import { customElement, property, state } from "lit/decorators.js";
259
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
260
+
261
+ // src/styles.ts
262
+ import { css } from "lit";
263
+ var overlayStyles = css`
264
+ :host {
265
+ /* ─── Customizable CSS Variables ─── */
266
+ --dialog-font-family:
267
+ 'Yu Gothic Medium', '游ゴシック', YuGothic, 'メイリオ', 'Hiragino Kaku Gothic ProN', Meiryo,
268
+ sans-serif;
269
+ --dialog-text-color: #356;
270
+ --dialog-font-size: 14px;
271
+ --dialog-font-size-desktop: 16px;
272
+ --dialog-z-index: 1000;
273
+ --dialog-backdrop-color: rgb(255 255 255 / 0.73);
274
+ --dialog-backdrop-blur: 4px;
275
+ --dialog-transition-duration: 250ms;
276
+
277
+ /* Card */
278
+ --dialog-card-bg: #fff;
279
+ --dialog-card-border: #f3f4f6;
280
+ --dialog-card-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
281
+ --dialog-card-radius: 4px;
282
+ --dialog-card-width: 400px;
283
+ --dialog-card-min-height: 200px;
284
+ --dialog-card-padding: 24px;
285
+ --dialog-card-padding-desktop: 32px;
286
+
287
+ /* Colors */
288
+ --dialog-primary: #3b82f6;
289
+ --dialog-primary-hover: #2563eb;
290
+ --dialog-success: #22c55e;
291
+ --dialog-error: #ef4444;
292
+ --dialog-warning: #f59e0b;
293
+ --dialog-info: #3b82f6;
294
+
295
+ /* Progress */
296
+ --dialog-progress-height: 2px;
297
+ --dialog-progress-color: var(--dialog-primary-hover);
298
+ --dialog-progress-transition: all 350ms ease;
299
+
300
+ /* Button */
301
+ --dialog-btn-radius: 6px;
302
+ --dialog-btn-padding: 8px 24px;
303
+ --dialog-btn-font-size: 14px;
304
+
305
+ /* Spinner */
306
+ --dialog-spinner-size: 60px;
307
+ --dialog-spinner-track: rgb(59 130 246 / 0.2);
308
+ --dialog-spinner-arc: var(--dialog-primary);
309
+
310
+ display: contents;
311
+ font-family: var(--dialog-font-family);
312
+ color: var(--dialog-text-color);
313
+ font-size: var(--dialog-font-size);
314
+ }
315
+
316
+ /* ─── Backdrop ─── */
317
+
318
+ .backdrop {
319
+ position: fixed;
320
+ inset: 0;
321
+ width: 100vw;
322
+ height: 100vh;
323
+ display: grid;
324
+ place-items: end stretch;
325
+ z-index: var(--dialog-z-index);
326
+ overflow: hidden;
327
+ background-color: var(--dialog-backdrop-color);
328
+ backdrop-filter: blur(var(--dialog-backdrop-blur));
329
+ box-sizing: border-box;
330
+ transition: opacity var(--dialog-transition-duration) ease;
331
+ opacity: 0;
332
+ pointer-events: none;
333
+ }
334
+
335
+ .backdrop[data-open] {
336
+ opacity: 1;
337
+ pointer-events: all;
338
+ }
339
+
340
+ @media (min-width: 640px) {
341
+ :host {
342
+ font-size: var(--dialog-font-size-desktop);
343
+ }
344
+ .backdrop {
345
+ place-items: center;
346
+ }
347
+ }
348
+
349
+ /* ─── Card ─── */
350
+
351
+ .card {
352
+ display: flex;
353
+ flex-direction: column;
354
+ align-items: center;
355
+ justify-content: center;
356
+ gap: 16px;
357
+ padding: var(--dialog-card-padding);
358
+ background-color: var(--dialog-card-bg);
359
+ border-radius: 0;
360
+ box-shadow: var(--dialog-card-shadow);
361
+ border: 1px solid var(--dialog-card-border);
362
+ min-height: var(--dialog-card-min-height);
363
+ position: relative;
364
+ overflow: hidden;
365
+ transition: all var(--dialog-transition-duration) ease;
366
+ }
367
+
368
+ @media (min-width: 640px) {
369
+ .card {
370
+ width: var(--dialog-card-width);
371
+ max-width: 90vw;
372
+ border-radius: var(--dialog-card-radius);
373
+ padding: var(--dialog-card-padding-desktop);
374
+ }
375
+ }
376
+
377
+ /* ─── Spinner ─── */
378
+
379
+ .spinner {
380
+ font-size: var(--dialog-spinner-size);
381
+ width: 1em;
382
+ height: 1em;
383
+ border-radius: 50%;
384
+ box-shadow: inset 0 0 0 1px var(--dialog-spinner-track);
385
+ position: relative;
386
+ animation: spin 1.2s infinite linear;
387
+ }
388
+
389
+ .spinner-half {
390
+ position: absolute;
391
+ left: 50%;
392
+ top: 50%;
393
+ width: 0.5em;
394
+ height: 1em;
395
+ margin-left: -0.5em;
396
+ margin-top: -0.5em;
397
+ overflow: hidden;
398
+ transform-origin: 0.5em 0.5em;
399
+ mask-image: linear-gradient(to bottom, #000f, #0000);
400
+ -webkit-mask-image: linear-gradient(to bottom, #000f, #0000);
401
+ }
402
+
403
+ .spinner-inner {
404
+ width: 1em;
405
+ height: 1em;
406
+ border-radius: 50%;
407
+ box-shadow: inset 0 0 0 1px var(--dialog-spinner-arc);
408
+ }
409
+
410
+ @keyframes spin {
411
+ 0% {
412
+ transform: rotate(0deg);
413
+ }
414
+ 100% {
415
+ transform: rotate(360deg);
416
+ }
417
+ }
418
+
419
+ /* ─── Icon ─── */
420
+
421
+ .icon-container {
422
+ width: 64px;
423
+ height: 64px;
424
+ border-radius: 50%;
425
+ display: flex;
426
+ align-items: center;
427
+ justify-content: center;
428
+ flex-shrink: 0;
429
+ }
430
+
431
+ .icon-container svg {
432
+ width: 36px;
433
+ height: 36px;
434
+ }
435
+
436
+ .icon-success {
437
+ background-color: rgb(34 197 94 / 0.1);
438
+ color: var(--dialog-success);
439
+ }
440
+
441
+ .icon-error {
442
+ background-color: rgb(239 68 68 / 0.1);
443
+ color: var(--dialog-error);
444
+ }
445
+
446
+ .icon-warning {
447
+ background-color: rgb(245 158 11 / 0.1);
448
+ color: var(--dialog-warning);
449
+ }
450
+
451
+ .icon-info {
452
+ background-color: rgb(59 130 246 / 0.1);
453
+ color: var(--dialog-info);
454
+ }
455
+
456
+ /* ─── Check Animation ─── */
457
+
458
+ .check-circle {
459
+ width: 64px;
460
+ height: 64px;
461
+ border-radius: 50%;
462
+ stroke-width: 2;
463
+ stroke: var(--dialog-success);
464
+ fill: none;
465
+ stroke-dasharray: 200;
466
+ stroke-dashoffset: 200;
467
+ animation: check-circle-draw 0.6s ease forwards;
468
+ }
469
+
470
+ .check-mark {
471
+ stroke: var(--dialog-success);
472
+ stroke-width: 3;
473
+ stroke-linecap: round;
474
+ stroke-linejoin: round;
475
+ fill: none;
476
+ stroke-dasharray: 50;
477
+ stroke-dashoffset: 50;
478
+ animation: check-mark-draw 0.4s 0.4s ease forwards;
479
+ }
480
+
481
+ @keyframes check-circle-draw {
482
+ to {
483
+ stroke-dashoffset: 0;
484
+ }
485
+ }
486
+
487
+ @keyframes check-mark-draw {
488
+ to {
489
+ stroke-dashoffset: 0;
490
+ }
491
+ }
492
+
493
+ /* ─── Text ─── */
494
+
495
+ .label {
496
+ font-size: 18px;
497
+ font-weight: 600;
498
+ color: #1f2937;
499
+ text-align: center;
500
+ margin: 0;
501
+ word-break: break-word;
502
+ }
503
+
504
+ .description {
505
+ font-size: 14px;
506
+ color: #6b7280;
507
+ text-align: center;
508
+ margin: 0;
509
+ word-break: break-word;
510
+ line-height: 1.6;
511
+ }
512
+
513
+ .html-content {
514
+ font-size: 14px;
515
+ color: #6b7280;
516
+ text-align: center;
517
+ word-break: break-word;
518
+ line-height: 1.6;
519
+ width: 100%;
520
+ }
521
+
522
+ /* ─── Progress ─── */
523
+
524
+ .progress-bar {
525
+ position: absolute;
526
+ bottom: 0;
527
+ left: 0;
528
+ width: 0%;
529
+ height: var(--dialog-progress-height);
530
+ background-color: var(--dialog-progress-color);
531
+ transition: var(--dialog-progress-transition);
532
+ }
533
+
534
+ /* ─── Buttons ─── */
535
+
536
+ .actions {
537
+ display: flex;
538
+ flex-direction: column;
539
+ gap: 8px;
540
+ width: 100%;
541
+ margin-top: 8px;
542
+ }
543
+
544
+ @media (min-width: 640px) {
545
+ .actions {
546
+ flex-direction: row;
547
+ justify-content: center;
548
+ }
549
+ }
550
+
551
+ .btn {
552
+ padding: var(--dialog-btn-padding);
553
+ font-size: var(--dialog-btn-font-size);
554
+ font-family: inherit;
555
+ border: none;
556
+ border-radius: var(--dialog-btn-radius);
557
+ cursor: pointer;
558
+ font-weight: 500;
559
+ transition:
560
+ background-color 150ms ease,
561
+ transform 80ms ease;
562
+ min-width: 100px;
563
+ text-align: center;
564
+ }
565
+
566
+ .btn:active {
567
+ transform: scale(0.97);
568
+ }
569
+
570
+ .btn-confirm {
571
+ background-color: var(--dialog-primary);
572
+ color: #fff;
573
+ }
574
+
575
+ .btn-confirm:hover {
576
+ background-color: var(--dialog-primary-hover);
577
+ }
578
+
579
+ .btn-cancel {
580
+ background-color: #f3f4f6;
581
+ color: #374151;
582
+ }
583
+
584
+ .btn-cancel:hover {
585
+ background-color: #e5e7eb;
586
+ }
587
+
588
+ /* ─── Queue / Steps list ─── */
589
+
590
+ .task-list {
591
+ display: flex;
592
+ flex-direction: column;
593
+ gap: 12px;
594
+ width: 100%;
595
+ padding: 0;
596
+ margin: 0;
597
+ list-style: none;
598
+ }
599
+
600
+ .task-item {
601
+ display: flex;
602
+ align-items: center;
603
+ gap: 12px;
604
+ font-size: 14px;
605
+ }
606
+
607
+ .task-icon {
608
+ width: 24px;
609
+ height: 24px;
610
+ display: flex;
611
+ align-items: center;
612
+ justify-content: center;
613
+ flex-shrink: 0;
614
+ }
615
+
616
+ .task-icon svg {
617
+ width: 20px;
618
+ height: 20px;
619
+ }
620
+
621
+ .task-icon .mini-spinner {
622
+ font-size: 20px;
623
+ width: 1em;
624
+ height: 1em;
625
+ border-radius: 50%;
626
+ box-shadow: inset 0 0 0 1px var(--dialog-spinner-track);
627
+ position: relative;
628
+ animation: spin 1.2s infinite linear;
629
+ }
630
+
631
+ .task-icon .mini-spinner-half {
632
+ position: absolute;
633
+ left: 50%;
634
+ top: 50%;
635
+ width: 0.5em;
636
+ height: 1em;
637
+ margin-left: -0.5em;
638
+ margin-top: -0.5em;
639
+ overflow: hidden;
640
+ transform-origin: 0.5em 0.5em;
641
+ mask-image: linear-gradient(to bottom, #000f, #0000);
642
+ -webkit-mask-image: linear-gradient(to bottom, #000f, #0000);
643
+ }
644
+
645
+ .task-icon .mini-spinner-inner {
646
+ width: 1em;
647
+ height: 1em;
648
+ border-radius: 50%;
649
+ box-shadow: inset 0 0 0 1px var(--dialog-spinner-arc);
650
+ }
651
+
652
+ .task-label {
653
+ color: #6b7280;
654
+ }
655
+
656
+ .task-label[data-status='active'] {
657
+ color: var(--dialog-text-color);
658
+ font-weight: 500;
659
+ }
660
+
661
+ .task-label[data-status='done'] {
662
+ color: var(--dialog-success);
663
+ }
664
+
665
+ .task-label[data-status='error'] {
666
+ color: var(--dialog-error);
667
+ }
668
+
669
+ .task-label[data-status='skipped'] {
670
+ color: #9ca3af;
671
+ text-decoration: line-through;
672
+ }
673
+
674
+ /* ─── Queue ellipsis ─── */
675
+
676
+ .queue-ellipsis {
677
+ display: flex;
678
+ flex-direction: column;
679
+ align-items: center;
680
+ gap: 3px;
681
+ padding: 4px 0;
682
+ /* アイコン列 (24px) の中央に配置: (24px - 4px dot) / 2 = 10px */
683
+ padding-left: 10px;
684
+ align-self: flex-start;
685
+ list-style: none;
686
+ }
687
+
688
+ .queue-ellipsis span {
689
+ display: block;
690
+ width: 4px;
691
+ height: 4px;
692
+ border-radius: 50%;
693
+ background-color: #d1d5db;
694
+ }
695
+
696
+ /* ─── Steps indicator ─── */
697
+
698
+ .steps-header {
699
+ display: flex;
700
+ align-items: center;
701
+ gap: 4px;
702
+ width: 100%;
703
+ justify-content: center;
704
+ margin-bottom: 8px;
705
+ }
706
+
707
+ .step-dot {
708
+ width: 8px;
709
+ height: 8px;
710
+ border-radius: 50%;
711
+ background-color: #d1d5db;
712
+ transition: background-color 200ms ease;
713
+ }
714
+
715
+ .step-dot[data-status='active'] {
716
+ background-color: var(--dialog-primary);
717
+ box-shadow: 0 0 0 3px rgb(59 130 246 / 0.2);
718
+ }
719
+
720
+ .step-dot[data-status='done'] {
721
+ background-color: var(--dialog-success);
722
+ }
723
+
724
+ .step-dot[data-status='error'] {
725
+ background-color: var(--dialog-error);
726
+ }
727
+
728
+ .step-dot[data-status='skipped'] {
729
+ background-color: #9ca3af;
730
+ }
731
+
732
+ .step-connector {
733
+ flex: 1;
734
+ max-width: 24px;
735
+ height: 2px;
736
+ background-color: #e5e7eb;
737
+ }
738
+ `;
739
+
740
+ // src/overlay-dialog.ts
741
+ var OverlayDialog = class extends LitElement {
742
+ constructor() {
743
+ super(...arguments);
744
+ this._state = createInitialState();
745
+ this._beforeUnloadHandler = (e) => e.preventDefault();
746
+ this._onKeyDown = (e) => {
747
+ if (e.key === "Escape" && this._state.open) {
748
+ this.controller.onEscapeKey();
749
+ }
750
+ };
751
+ }
752
+ connectedCallback() {
753
+ super.connectedCallback();
754
+ if (this.controller) {
755
+ this._state = { ...this.controller.state };
756
+ this._unsubscribe = this.controller.subscribe((s) => {
757
+ const wasOpen = this._state.open;
758
+ this._state = s;
759
+ this._syncBodyScroll(s.open);
760
+ if (s.open && !wasOpen) {
761
+ window.addEventListener("beforeunload", this._beforeUnloadHandler);
762
+ } else if (!s.open && wasOpen) {
763
+ window.removeEventListener("beforeunload", this._beforeUnloadHandler);
764
+ }
765
+ });
766
+ }
767
+ window.addEventListener("keydown", this._onKeyDown);
768
+ }
769
+ disconnectedCallback() {
770
+ super.disconnectedCallback();
771
+ this._unsubscribe?.();
772
+ this._syncBodyScroll(false);
773
+ window.removeEventListener("beforeunload", this._beforeUnloadHandler);
774
+ window.removeEventListener("keydown", this._onKeyDown);
775
+ }
776
+ _syncBodyScroll(lock) {
777
+ if (lock) {
778
+ document.body.style.overflow = "hidden";
779
+ } else {
780
+ document.body.style.overflow = "";
781
+ }
782
+ }
783
+ // ─── Event Handlers ──────────────────────────────────────
784
+ _onBackdropClick(e) {
785
+ if (e.target === e.currentTarget) {
786
+ this.controller.onOutsideClick();
787
+ }
788
+ }
789
+ // ─── Render Helpers ──────────────────────────────────────
790
+ _renderIcon(icon) {
791
+ if (!icon) return nothing;
792
+ if (icon === "success") {
793
+ return html`
794
+ <svg
795
+ class="icon-container"
796
+ viewBox="0 0 64 64"
797
+ style="width:64px;height:64px;background:none;"
798
+ >
799
+ <circle class="check-circle" cx="32" cy="32" r="30" />
800
+ <polyline class="check-mark" points="20,34 28,42 44,24" />
801
+ </svg>
802
+ `;
803
+ }
804
+ const paths = {
805
+ error: html`<svg
806
+ viewBox="0 0 24 24"
807
+ fill="none"
808
+ stroke="currentColor"
809
+ stroke-width="2"
810
+ stroke-linecap="round"
811
+ stroke-linejoin="round"
812
+ >
813
+ <circle cx="12" cy="12" r="10" />
814
+ <line x1="15" y1="9" x2="9" y2="15" />
815
+ <line x1="9" y1="9" x2="15" y2="15" />
816
+ </svg>`,
817
+ warning: html`<svg
818
+ viewBox="0 0 24 24"
819
+ fill="none"
820
+ stroke="currentColor"
821
+ stroke-width="2"
822
+ stroke-linecap="round"
823
+ stroke-linejoin="round"
824
+ >
825
+ <path
826
+ d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"
827
+ />
828
+ <line x1="12" y1="9" x2="12" y2="13" />
829
+ <line x1="12" y1="17" x2="12.01" y2="17" />
830
+ </svg>`,
831
+ info: html`<svg
832
+ viewBox="0 0 24 24"
833
+ fill="none"
834
+ stroke="currentColor"
835
+ stroke-width="2"
836
+ stroke-linecap="round"
837
+ stroke-linejoin="round"
838
+ >
839
+ <circle cx="12" cy="12" r="10" />
840
+ <line x1="12" y1="16" x2="12" y2="12" />
841
+ <line x1="12" y1="8" x2="12.01" y2="8" />
842
+ </svg>`
843
+ };
844
+ return html` <div class="icon-container icon-${icon}">${paths[icon] ?? nothing}</div> `;
845
+ }
846
+ _renderSpinner() {
847
+ return html`
848
+ <div class="spinner">
849
+ <div class="spinner-half">
850
+ <div class="spinner-inner"></div>
851
+ </div>
852
+ </div>
853
+ `;
854
+ }
855
+ _renderTaskIcon(status) {
856
+ switch (status) {
857
+ case "active":
858
+ return html`
859
+ <div class="mini-spinner">
860
+ <div class="mini-spinner-half">
861
+ <div class="mini-spinner-inner"></div>
862
+ </div>
863
+ </div>
864
+ `;
865
+ case "done":
866
+ return html`<svg
867
+ viewBox="0 0 24 24"
868
+ fill="none"
869
+ stroke="#22c55e"
870
+ stroke-width="2"
871
+ stroke-linecap="round"
872
+ stroke-linejoin="round"
873
+ >
874
+ <circle cx="12" cy="12" r="10" />
875
+ <polyline points="9,12 11,14 15,10" />
876
+ </svg>`;
877
+ case "error":
878
+ return html`<svg
879
+ viewBox="0 0 24 24"
880
+ fill="none"
881
+ stroke="#ef4444"
882
+ stroke-width="2"
883
+ stroke-linecap="round"
884
+ stroke-linejoin="round"
885
+ >
886
+ <circle cx="12" cy="12" r="10" />
887
+ <line x1="15" y1="9" x2="9" y2="15" />
888
+ <line x1="9" y1="9" x2="15" y2="15" />
889
+ </svg>`;
890
+ case "skipped":
891
+ return html`<svg
892
+ viewBox="0 0 24 24"
893
+ fill="none"
894
+ stroke="#9ca3af"
895
+ stroke-width="2"
896
+ stroke-linecap="round"
897
+ stroke-linejoin="round"
898
+ >
899
+ <circle cx="12" cy="12" r="10" />
900
+ <line x1="8" y1="12" x2="16" y2="12" />
901
+ </svg>`;
902
+ case "pending":
903
+ default:
904
+ return html`<svg
905
+ viewBox="0 0 24 24"
906
+ fill="none"
907
+ stroke="#d1d5db"
908
+ stroke-width="2"
909
+ stroke-linecap="round"
910
+ stroke-linejoin="round"
911
+ >
912
+ <circle cx="12" cy="12" r="10" />
913
+ </svg>`;
914
+ }
915
+ }
916
+ _getQueueWindow(items) {
917
+ const WINDOW = 3;
918
+ const total = items.length;
919
+ if (total <= WINDOW) return { start: 0, end: total - 1 };
920
+ let centerIdx = items.findIndex((i) => i.status === "active");
921
+ if (centerIdx < 0) {
922
+ const finishedStatuses = /* @__PURE__ */ new Set(["done", "skipped", "error"]);
923
+ const lastFinishedIdx = items.reduce(
924
+ (acc, item, i) => finishedStatuses.has(item.status) ? i : acc,
925
+ -1
926
+ );
927
+ centerIdx = lastFinishedIdx >= 0 ? Math.min(lastFinishedIdx + 1, total - 1) : 0;
928
+ }
929
+ const start = Math.max(0, Math.min(centerIdx - 1, total - WINDOW));
930
+ const end = Math.min(total - 1, start + WINDOW - 1);
931
+ return { start, end };
932
+ }
933
+ _renderQueueList(items) {
934
+ const total = items.length;
935
+ const { start, end } = this._getQueueWindow(items);
936
+ const visible = items.slice(start, end + 1);
937
+ return html`
938
+ <ul class="task-list">
939
+ ${start > 0 ? html`<li class="queue-ellipsis" aria-hidden="true">
940
+ <span></span><span></span><span></span>
941
+ </li>` : nothing}
942
+ ${visible.map(
943
+ (item) => html`
944
+ <li class="task-item">
945
+ <span class="task-icon">${this._renderTaskIcon(item.status)}</span>
946
+ <span class="task-label" data-status=${item.status}>${item.label}</span>
947
+ </li>
948
+ `
949
+ )}
950
+ ${end < total - 1 ? html`<li class="queue-ellipsis" aria-hidden="true">
951
+ <span></span><span></span><span></span>
952
+ </li>` : nothing}
953
+ </ul>
954
+ `;
955
+ }
956
+ _renderStepsHeader(items) {
957
+ const fragments = [];
958
+ items.forEach((item, i) => {
959
+ if (i > 0) {
960
+ fragments.push(html`<div class="step-connector"></div>`);
961
+ }
962
+ fragments.push(html`<div class="step-dot" data-status=${item.status}></div>`);
963
+ });
964
+ return html`<div class="steps-header">${fragments}</div>`;
965
+ }
966
+ _renderStepsList(items) {
967
+ return html`
968
+ ${this._renderStepsHeader(items)}
969
+ <ul class="task-list">
970
+ ${items.map(
971
+ (item) => html`
972
+ <li class="task-item">
973
+ <span class="task-icon">${this._renderTaskIcon(item.status)}</span>
974
+ <span class="task-label" data-status=${item.status}>${item.label}</span>
975
+ </li>
976
+ `
977
+ )}
978
+ </ul>
979
+ `;
980
+ }
981
+ _renderButtons() {
982
+ const s = this._state;
983
+ if (!s.showConfirmButton && !s.showCancelButton) return nothing;
984
+ return html`
985
+ <div class="actions">
986
+ ${s.showConfirmButton ? html`<button class="btn btn-confirm" @click=${() => this.controller.onConfirm()}>
987
+ ${s.confirmButtonText}
988
+ </button>` : nothing}
989
+ ${s.showCancelButton ? html`<button class="btn btn-cancel" @click=${() => this.controller.onCancel()}>
990
+ ${s.cancelButtonText}
991
+ </button>` : nothing}
992
+ </div>
993
+ `;
994
+ }
995
+ _renderBody() {
996
+ const s = this._state;
997
+ switch (s.dialogType) {
998
+ case "loading":
999
+ return html`
1000
+ ${this._renderSpinner()} ${s.label ? html`<p class="label">${s.label}</p>` : nothing}
1001
+ ${s.description ? html`<p class="description">${s.description}</p>` : nothing}
1002
+ `;
1003
+ case "alert":
1004
+ case "confirm":
1005
+ return html`
1006
+ ${this._renderIcon(s.icon)} ${s.label ? html`<p class="label">${s.label}</p>` : nothing}
1007
+ ${s.description ? html`<p class="description">${s.description}</p>` : nothing}
1008
+ ${s.html ? html`<div class="html-content">${unsafeHTML(s.html)}</div>` : nothing}
1009
+ ${this._renderButtons()}
1010
+ `;
1011
+ case "queue":
1012
+ return html`
1013
+ ${s.label ? html`<p class="label">${s.label}</p>` : nothing}
1014
+ ${this._renderQueueList(s.queues)}
1015
+ `;
1016
+ case "steps":
1017
+ return html`
1018
+ ${s.label ? html`<p class="label">${s.label}</p>` : nothing}
1019
+ ${this._renderStepsList(s.steps)}
1020
+ `;
1021
+ default:
1022
+ return html`${nothing}`;
1023
+ }
1024
+ }
1025
+ render() {
1026
+ const s = this._state;
1027
+ return html`
1028
+ <div class="backdrop" ?data-open=${s.open} @click=${this._onBackdropClick}>
1029
+ <div class="card">
1030
+ ${this._renderBody()}
1031
+ <div
1032
+ class="progress-bar"
1033
+ style="width:${s.progress ?? 0}%;opacity:${s.progress !== null ? 1 : 0}"
1034
+ ></div>
1035
+ </div>
1036
+ </div>
1037
+ `;
1038
+ }
1039
+ };
1040
+ OverlayDialog.styles = overlayStyles;
1041
+ __decorateClass([
1042
+ property({ attribute: false })
1043
+ ], OverlayDialog.prototype, "controller", 2);
1044
+ __decorateClass([
1045
+ state()
1046
+ ], OverlayDialog.prototype, "_state", 2);
1047
+ OverlayDialog = __decorateClass([
1048
+ customElement("overlay-dialog")
1049
+ ], OverlayDialog);
1050
+
1051
+ // src/dialog.ts
1052
+ var _controller, _element, _DialogSingleton_instances, ensureElement_fn;
1053
+ var DialogSingleton = class {
1054
+ constructor() {
1055
+ __privateAdd(this, _DialogSingleton_instances);
1056
+ __privateAdd(this, _controller, new DialogController());
1057
+ __privateAdd(this, _element, null);
1058
+ }
1059
+ // ─── Core ────────────────────────────────────────────────
1060
+ show(options) {
1061
+ __privateMethod(this, _DialogSingleton_instances, ensureElement_fn).call(this);
1062
+ __privateGet(this, _controller).show(options);
1063
+ }
1064
+ hide() {
1065
+ __privateGet(this, _controller).hide();
1066
+ }
1067
+ // ─── Alert / Confirm ─────────────────────────────────────
1068
+ alert(optionsOrLabel) {
1069
+ __privateMethod(this, _DialogSingleton_instances, ensureElement_fn).call(this);
1070
+ return __privateGet(this, _controller).alert(optionsOrLabel);
1071
+ }
1072
+ confirm(optionsOrLabel) {
1073
+ __privateMethod(this, _DialogSingleton_instances, ensureElement_fn).call(this);
1074
+ return __privateGet(this, _controller).confirm(optionsOrLabel);
1075
+ }
1076
+ // ─── Loading helpers ─────────────────────────────────────
1077
+ loading(label) {
1078
+ __privateMethod(this, _DialogSingleton_instances, ensureElement_fn).call(this);
1079
+ __privateGet(this, _controller).loading(label);
1080
+ }
1081
+ progress(percent) {
1082
+ __privateGet(this, _controller).progress(percent);
1083
+ }
1084
+ label(label) {
1085
+ __privateGet(this, _controller).label(label);
1086
+ }
1087
+ description(description) {
1088
+ __privateGet(this, _controller).description(description);
1089
+ }
1090
+ // ─── Queue ───────────────────────────────────────────────
1091
+ setQueues(labels) {
1092
+ __privateGet(this, _controller).setQueues(labels);
1093
+ }
1094
+ queue(labels) {
1095
+ __privateMethod(this, _DialogSingleton_instances, ensureElement_fn).call(this);
1096
+ __privateGet(this, _controller).queue(labels);
1097
+ }
1098
+ startQueue(label) {
1099
+ __privateGet(this, _controller).startQueue(label);
1100
+ }
1101
+ finishQueue(label) {
1102
+ __privateGet(this, _controller).finishQueue(label);
1103
+ }
1104
+ skipQueue(label) {
1105
+ __privateGet(this, _controller).skipQueue(label);
1106
+ }
1107
+ errorQueue(label) {
1108
+ __privateGet(this, _controller).errorQueue(label);
1109
+ }
1110
+ clearQueues() {
1111
+ __privateGet(this, _controller).clearQueues();
1112
+ }
1113
+ // ─── Steps ───────────────────────────────────────────────
1114
+ setSteps(labels) {
1115
+ __privateGet(this, _controller).setSteps(labels);
1116
+ }
1117
+ steps(labels) {
1118
+ __privateMethod(this, _DialogSingleton_instances, ensureElement_fn).call(this);
1119
+ __privateGet(this, _controller).steps(labels);
1120
+ }
1121
+ startStep(label) {
1122
+ __privateGet(this, _controller).startStep(label);
1123
+ }
1124
+ finishStep(label) {
1125
+ __privateGet(this, _controller).finishStep(label);
1126
+ }
1127
+ skipStep(label) {
1128
+ __privateGet(this, _controller).skipStep(label);
1129
+ }
1130
+ errorStep(label) {
1131
+ __privateGet(this, _controller).errorStep(label);
1132
+ }
1133
+ clearSteps() {
1134
+ __privateGet(this, _controller).clearSteps();
1135
+ }
1136
+ // ─── Advanced ────────────────────────────────────────────
1137
+ get controller() {
1138
+ return __privateGet(this, _controller);
1139
+ }
1140
+ };
1141
+ _controller = new WeakMap();
1142
+ _element = new WeakMap();
1143
+ _DialogSingleton_instances = new WeakSet();
1144
+ ensureElement_fn = function() {
1145
+ if (__privateGet(this, _element)) return;
1146
+ if (typeof document === "undefined") return;
1147
+ const el = document.createElement("overlay-dialog");
1148
+ el.controller = __privateGet(this, _controller);
1149
+ document.body.appendChild(el);
1150
+ __privateSet(this, _element, el);
1151
+ };
1152
+ var dialog = new DialogSingleton();
1153
+ export {
1154
+ DialogController,
1155
+ OverlayDialog,
1156
+ dialog
1157
+ };
5
1158
  //# sourceMappingURL=index.js.map