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