@iyulab/u-widgets 0.4.1

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.
@@ -0,0 +1,4073 @@
1
+ import { g as me } from "./formdown-BWJ6QGJs.js";
2
+ import { p as Ot, r as Pt } from "./formdown-BWJ6QGJs.js";
3
+ import { i as ve } from "./infer-CNOiD2dS.js";
4
+ import { t as b, n as be } from "./tokens-x1kDxgG8.js";
5
+ import { css as y, LitElement as w, nothing as c, html as o } from "lit";
6
+ import { property as h, customElement as x, state as S } from "lit/decorators.js";
7
+ const ye = /* @__PURE__ */ new Set([
8
+ "text",
9
+ "email",
10
+ "password",
11
+ "tel",
12
+ "url",
13
+ "textarea",
14
+ "number",
15
+ "select",
16
+ "multiselect",
17
+ "date",
18
+ "datetime",
19
+ "time",
20
+ "toggle",
21
+ "range",
22
+ "radio",
23
+ "checkbox"
24
+ ]), ae = 10, we = /* @__PURE__ */ new Set([
25
+ "stat-group",
26
+ "table",
27
+ "list",
28
+ "steps",
29
+ "gallery",
30
+ "chart.bar",
31
+ "chart.line",
32
+ "chart.area",
33
+ "chart.pie",
34
+ "chart.scatter",
35
+ "chart.radar",
36
+ "chart.heatmap",
37
+ "chart.box",
38
+ "chart.funnel",
39
+ "chart.waterfall",
40
+ "chart.treemap"
41
+ ]), xe = /* @__PURE__ */ new Set(["metric", "gauge", "progress", "header", "code", "rating", "video"]);
42
+ function Q(e, t = 0) {
43
+ const a = [], i = [];
44
+ if (t > ae)
45
+ return { valid: !1, errors: ["compose children exceed maximum nesting depth (" + ae + ")"], warnings: i };
46
+ if (e == null || typeof e != "object")
47
+ return { valid: !1, errors: ["Spec must be a non-null object"], warnings: i };
48
+ const r = e;
49
+ if (typeof r.widget != "string" || r.widget.length === 0)
50
+ return a.push('Required field "widget" must be a non-empty string'), { valid: !1, errors: a, warnings: i };
51
+ const n = r.widget;
52
+ if (r.type !== void 0 && r.type !== "u-widget" && a.push('"type" must be "u-widget" if specified'), r.fields !== void 0 && r.formdown !== void 0 && a.push('"fields" and "formdown" are mutually exclusive'), r.data !== void 0 && (we.has(n) && !Array.isArray(r.data) && a.push(`"${n}" expects "data" to be an array, got ${typeof r.data}`), xe.has(n) && (Array.isArray(r.data) || typeof r.data != "object") && a.push(`"${n}" expects "data" to be an object, got ${Array.isArray(r.data) ? "array" : typeof r.data}`)), n === "compose") {
53
+ if (!Array.isArray(r.children))
54
+ a.push('"compose" widget requires a "children" array');
55
+ else
56
+ for (let s = 0; s < r.children.length; s++) {
57
+ const l = r.children[s];
58
+ if (l == null || typeof l != "object" || typeof l.widget != "string")
59
+ a.push(`children[${s}] must be an object with a "widget" field`);
60
+ else {
61
+ const p = Q(l, t + 1);
62
+ p.valid || a.push(...p.errors.map((d) => `children[${s}]: ${d}`)), i.push(...p.warnings.map((d) => `children[${s}]: ${d}`));
63
+ }
64
+ }
65
+ if (r.layout !== void 0) {
66
+ const s = ["stack", "row", "grid"];
67
+ s.includes(r.layout) || a.push(`"layout" must be one of: ${s.join(", ")}`);
68
+ }
69
+ }
70
+ if (Array.isArray(r.fields))
71
+ for (let s = 0; s < r.fields.length; s++) {
72
+ const l = r.fields[s];
73
+ l == null || typeof l != "object" || typeof l.field != "string" ? a.push(`fields[${s}] must have a "field" string property`) : l.type != null && !ye.has(l.type) && i.push(`fields[${s}].type "${l.type}" is not a recognized field type`);
74
+ }
75
+ if (typeof r.formdown == "string" && r.formdown.length > 0 && !r.fields)
76
+ try {
77
+ me()(r.formdown);
78
+ } catch {
79
+ i.push("formdown string could not be parsed — check syntax");
80
+ }
81
+ if (Array.isArray(r.actions))
82
+ for (let s = 0; s < r.actions.length; s++) {
83
+ const l = r.actions[s];
84
+ (l == null || typeof l != "object" || typeof l.label != "string" || typeof l.action != "string") && a.push(`actions[${s}] must have "label" and "action" string properties`);
85
+ }
86
+ if (r.mapping && typeof r.mapping == "object" && r.data) {
87
+ const s = r.mapping, l = $e(r.data);
88
+ if (l)
89
+ for (const p of ["x", "y", "label", "value", "color", "size", "axis", "primary", "secondary", "icon", "avatar", "trailing"]) {
90
+ const d = s[p];
91
+ if (typeof d == "string" && !l.has(d) && i.push(`mapping.${p} references "${d}" which is not found in data keys [${[...l].join(", ")}]`), Array.isArray(d))
92
+ for (const g of d)
93
+ typeof g == "string" && !l.has(g) && i.push(`mapping.${p} references "${g}" which is not found in data keys [${[...l].join(", ")}]`);
94
+ }
95
+ }
96
+ return { valid: a.length === 0, errors: a, warnings: i };
97
+ }
98
+ function $e(e) {
99
+ if (Array.isArray(e) && e.length > 0 && e[0] && typeof e[0] == "object")
100
+ return new Set(Object.keys(e[0]));
101
+ if (e && typeof e == "object" && !Array.isArray(e))
102
+ return new Set(Object.keys(e));
103
+ }
104
+ function St(e) {
105
+ return Q(e).valid;
106
+ }
107
+ const ie = ["B", "KB", "MB", "GB", "TB"];
108
+ function _e(e, t, a) {
109
+ if (e == null) return "";
110
+ const [i, r] = t?.split(":") ?? [];
111
+ switch (i) {
112
+ case "number":
113
+ return ke(e, a);
114
+ case "currency":
115
+ return ze(e, r, a);
116
+ case "percent":
117
+ return Se(e, a);
118
+ case "date":
119
+ return Ae(e, a);
120
+ case "datetime":
121
+ return Ce(e, a);
122
+ case "bytes":
123
+ return je(e);
124
+ default:
125
+ return String(e);
126
+ }
127
+ }
128
+ function ke(e, t) {
129
+ const a = Number(e);
130
+ return isNaN(a) ? String(e) : new Intl.NumberFormat(t).format(a);
131
+ }
132
+ function ze(e, t, a) {
133
+ const i = Number(e);
134
+ if (isNaN(i)) return String(e);
135
+ try {
136
+ return new Intl.NumberFormat(a, {
137
+ style: "currency",
138
+ currency: t || "USD"
139
+ }).format(i);
140
+ } catch {
141
+ return new Intl.NumberFormat(a, {
142
+ style: "currency",
143
+ currency: "USD"
144
+ }).format(i);
145
+ }
146
+ }
147
+ function Se(e, t) {
148
+ const a = Number(e);
149
+ if (isNaN(a)) return String(e);
150
+ if (t)
151
+ try {
152
+ return new Intl.NumberFormat(t, {
153
+ style: "percent",
154
+ maximumFractionDigits: 2
155
+ }).format(a / 100);
156
+ } catch {
157
+ }
158
+ return a + "%";
159
+ }
160
+ function Ae(e, t) {
161
+ if (typeof e == "string" && /^\d{4}-\d{2}-\d{2}/.test(e)) {
162
+ if (t)
163
+ try {
164
+ const a = new Date(e);
165
+ if (!isNaN(a.getTime()))
166
+ return new Intl.DateTimeFormat(t, {
167
+ year: "numeric",
168
+ month: "2-digit",
169
+ day: "2-digit"
170
+ }).format(a);
171
+ } catch {
172
+ }
173
+ return e.slice(0, 10);
174
+ }
175
+ return String(e);
176
+ }
177
+ function Ce(e, t) {
178
+ if (typeof e == "string" && /^\d{4}-\d{2}-\d{2}/.test(e)) {
179
+ if (t)
180
+ try {
181
+ const a = new Date(e);
182
+ if (!isNaN(a.getTime()))
183
+ return new Intl.DateTimeFormat(t, {
184
+ year: "numeric",
185
+ month: "2-digit",
186
+ day: "2-digit",
187
+ hour: "2-digit",
188
+ minute: "2-digit"
189
+ }).format(a);
190
+ } catch {
191
+ }
192
+ return e.slice(0, 16).replace("T", " ");
193
+ }
194
+ return String(e);
195
+ }
196
+ function je(e) {
197
+ const t = Number(e);
198
+ if (isNaN(t)) return String(e);
199
+ const a = t < 0 ? "-" : "";
200
+ let i = Math.abs(t), r = 0;
201
+ for (; i >= 1024 && r < ie.length - 1; )
202
+ i /= 1024, r++;
203
+ return a + (r === 0 ? i : i.toFixed(1)) + " " + ie[r];
204
+ }
205
+ const De = [
206
+ "chart.bar",
207
+ "chart.line",
208
+ "chart.area",
209
+ "chart.pie",
210
+ "chart.scatter",
211
+ "chart.radar",
212
+ "chart.heatmap",
213
+ "chart.box",
214
+ "chart.funnel",
215
+ "chart.waterfall",
216
+ "chart.treemap",
217
+ "metric",
218
+ "stat-group",
219
+ "gauge",
220
+ "progress",
221
+ "table",
222
+ "list",
223
+ "form",
224
+ "confirm",
225
+ "compose",
226
+ "markdown",
227
+ "image",
228
+ "callout",
229
+ "kv",
230
+ "code",
231
+ "citation",
232
+ "status",
233
+ "steps",
234
+ "rating",
235
+ "video",
236
+ "gallery",
237
+ "actions",
238
+ "divider",
239
+ "header"
240
+ ];
241
+ function Oe(e) {
242
+ if (!e) return;
243
+ const t = e.toLowerCase();
244
+ let a, i = 1 / 0;
245
+ for (const n of De) {
246
+ const s = Pe(t, n);
247
+ s < i && (i = s, a = n);
248
+ }
249
+ const r = Math.min(3, Math.floor(t.length / 2));
250
+ if (i <= r && i > 0)
251
+ return a;
252
+ }
253
+ function Pe(e, t) {
254
+ const a = e.length, i = t.length;
255
+ if (a === 0) return i;
256
+ if (i === 0) return a;
257
+ const r = new Array(i + 1);
258
+ for (let n = 0; n <= i; n++) r[n] = n;
259
+ for (let n = 1; n <= a; n++) {
260
+ let s = n - 1;
261
+ r[0] = n;
262
+ for (let l = 1; l <= i; l++) {
263
+ const p = e[n - 1] === t[l - 1] ? 0 : 1, d = Math.min(
264
+ r[l] + 1,
265
+ // deletion
266
+ r[l - 1] + 1,
267
+ // insertion
268
+ s + p
269
+ // substitution
270
+ );
271
+ s = r[l], r[l] = d;
272
+ }
273
+ }
274
+ return r[i];
275
+ }
276
+ const R = {
277
+ // UI chrome
278
+ prev: "Prev",
279
+ next: "Next",
280
+ searchPlaceholder: "Search...",
281
+ // ARIA
282
+ searchTable: "Search table",
283
+ previousPage: "Previous page",
284
+ nextPage: "Next page",
285
+ tablePagination: "Table pagination",
286
+ dataTable: "Data table",
287
+ // Validation
288
+ required: "{label} is required",
289
+ minLength: "{label} must be at least {min} characters",
290
+ maxLength: "{label} must be at most {max} characters",
291
+ minValue: "{label} must be at least {min}",
292
+ maxValue: "{label} must be at most {max}",
293
+ invalidEmail: "{label} must be a valid email address",
294
+ invalidUrl: "{label} must be a valid URL",
295
+ invalidPattern: "{label} format is invalid"
296
+ }, L = /* @__PURE__ */ new Map();
297
+ function At(e, t) {
298
+ L.set(e.toLowerCase(), { ...R, ...t });
299
+ }
300
+ function de(e) {
301
+ if (!e) return R;
302
+ const t = e.toLowerCase();
303
+ if (L.has(t)) return L.get(t);
304
+ const a = t.split("-")[0];
305
+ return a !== t && L.has(a) ? L.get(a) : R;
306
+ }
307
+ function A(e, t) {
308
+ return e.replace(
309
+ /\{(\w+)\}/g,
310
+ (a, i) => t[i] != null ? String(t[i]) : `{${i}}`
311
+ );
312
+ }
313
+ function Ct() {
314
+ return { ...R };
315
+ }
316
+ var Ee = Object.defineProperty, Le = Object.getOwnPropertyDescriptor, pe = (e, t, a, i) => {
317
+ for (var r = i > 1 ? void 0 : i ? Le(t, a) : t, n = e.length - 1, s; n >= 0; n--)
318
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
319
+ return i && r && Ee(t, a, r), r;
320
+ };
321
+ function se(e) {
322
+ return {
323
+ value: e.value ?? 0,
324
+ label: e.label,
325
+ unit: e.unit,
326
+ prefix: e.prefix,
327
+ suffix: e.suffix,
328
+ change: e.change,
329
+ trend: e.trend,
330
+ icon: e.icon,
331
+ description: e.description
332
+ };
333
+ }
334
+ let q = class extends w {
335
+ constructor() {
336
+ super(...arguments), this.spec = null;
337
+ }
338
+ render() {
339
+ return this.spec?.data ? this.spec.widget === "stat-group" ? this.renderStatGroup() : this.renderMetric(se(this.spec.data)) : c;
340
+ }
341
+ renderStatGroup() {
342
+ const e = this.spec.data;
343
+ return Array.isArray(e) ? o`
344
+ <div class="stat-group" part="stat-group">
345
+ ${e.map((t) => this.renderMetric(se(t)))}
346
+ </div>
347
+ ` : c;
348
+ }
349
+ renderMetric(e) {
350
+ const t = e.trend === "up" ? "↑" : e.trend === "down" ? "↓" : e.trend === "flat" ? "→" : "", a = e.label ? `${e.label}: ${e.prefix ?? ""}${e.value}${e.unit ?? ""}${e.suffix ?? ""}` : void 0;
351
+ return o`
352
+ <div class="metric" part="metric" aria-label=${a ?? c}>
353
+ ${e.icon ? o`<div class="metric-icon" part="icon">${e.icon}</div>` : c}
354
+ ${e.label ? o`<div class="metric-label" part="label">${e.label}</div>` : c}
355
+ <div class="metric-value" part="value">
356
+ ${e.prefix ?? ""}${e.value}${e.unit ? o`<span class="metric-unit">${e.unit}</span>` : ""}${e.suffix ?? ""}
357
+ </div>
358
+ ${e.change != null ? o`<span class="metric-change" data-trend=${e.trend ?? "flat"} part="change"
359
+ >${t} ${e.change > 0 ? "+" : ""}${e.change}%</span
360
+ >` : c}
361
+ ${e.description ? o`<div class="metric-description" part="description">${e.description}</div>` : c}
362
+ </div>
363
+ `;
364
+ }
365
+ };
366
+ q.styles = [b, y`
367
+ :host {
368
+ display: block;
369
+ font-family: system-ui, -apple-system, sans-serif;
370
+ container: u-metric / inline-size;
371
+ }
372
+
373
+ /* ── metric (single) ── */
374
+ .metric {
375
+ display: flex;
376
+ flex-direction: column;
377
+ gap: 4px;
378
+ }
379
+
380
+ .metric-value {
381
+ font-size: 2rem;
382
+ font-weight: 700;
383
+ line-height: 1.1;
384
+ color: var(--u-widget-text, #1a1a2e);
385
+ }
386
+
387
+ @container u-metric (max-width: 30rem) {
388
+ .metric-value {
389
+ font-size: 1.5rem;
390
+ }
391
+ }
392
+
393
+ .metric-unit {
394
+ font-size: 0.875rem;
395
+ font-weight: 400;
396
+ color: var(--u-widget-text-secondary, #64748b);
397
+ margin-left: 4px;
398
+ }
399
+
400
+ .metric-change {
401
+ font-size: 0.8125rem;
402
+ font-weight: 500;
403
+ display: inline-flex;
404
+ align-items: center;
405
+ gap: 2px;
406
+ }
407
+
408
+ .metric-change[data-trend='up'] {
409
+ color: var(--u-widget-positive, #16a34a);
410
+ }
411
+
412
+ .metric-change[data-trend='down'] {
413
+ color: var(--u-widget-negative, #dc2626);
414
+ }
415
+
416
+ .metric-change[data-trend='flat'] {
417
+ color: var(--u-widget-text-secondary, #64748b);
418
+ }
419
+
420
+ .metric-label {
421
+ font-size: 0.8125rem;
422
+ color: var(--u-widget-text-secondary, #64748b);
423
+ font-weight: 500;
424
+ }
425
+
426
+ .metric-icon { font-size: 1.25rem; line-height: 1; margin-bottom: 2px; }
427
+ .metric-description { font-size: 0.75rem; color: var(--u-widget-text-secondary, #64748b); margin-top: 2px; line-height: 1.3; }
428
+
429
+ /* ── stat-group ── */
430
+ .stat-group {
431
+ display: flex;
432
+ flex-direction: row;
433
+ flex-wrap: wrap;
434
+ gap: 1.5rem;
435
+ }
436
+
437
+ .stat-group .metric {
438
+ flex: 1;
439
+ min-width: 100px;
440
+ }
441
+
442
+ .stat-group .metric + .metric {
443
+ border-left: 1px solid var(--u-widget-border, #e2e8f0);
444
+ padding-left: 1.5rem;
445
+ }
446
+
447
+ @container u-metric (max-width: 30rem) {
448
+ .stat-group {
449
+ flex-direction: column;
450
+ gap: 1rem;
451
+ }
452
+
453
+ .stat-group .metric {
454
+ flex: none;
455
+ min-width: 0;
456
+ }
457
+
458
+ .stat-group .metric + .metric {
459
+ border-left: none;
460
+ padding-left: 0;
461
+ border-top: 1px solid var(--u-widget-border, #e2e8f0);
462
+ padding-top: 1rem;
463
+ }
464
+ }
465
+ `];
466
+ pe([
467
+ h({ type: Object })
468
+ ], q.prototype, "spec", 2);
469
+ q = pe([
470
+ x("u-metric")
471
+ ], q);
472
+ var Ie = Object.defineProperty, Ne = Object.getOwnPropertyDescriptor, ue = (e, t, a, i) => {
473
+ for (var r = i > 1 ? void 0 : i ? Ne(t, a) : t, n = e.length - 1, s; n >= 0; n--)
474
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
475
+ return i && r && Ie(t, a, r), r;
476
+ };
477
+ const Te = {
478
+ min: 0,
479
+ max: 100,
480
+ unit: "",
481
+ thresholds: []
482
+ }, Fe = {
483
+ green: "#16a34a",
484
+ yellow: "#eab308",
485
+ orange: "#f97316",
486
+ red: "#dc2626",
487
+ blue: "#2563eb",
488
+ gray: "#6b7280"
489
+ };
490
+ function ne(e) {
491
+ return Fe[e] ?? e;
492
+ }
493
+ function oe(e, t, a, i, r) {
494
+ const n = (i - 90) * Math.PI / 180, s = (r - 90) * Math.PI / 180, l = e + a * Math.cos(n), p = t + a * Math.sin(n), d = e + a * Math.cos(s), g = t + a * Math.sin(s), f = r - i > 180 ? 1 : 0;
495
+ return `M ${l} ${p} A ${a} ${a} 0 ${f} 1 ${d} ${g}`;
496
+ }
497
+ let B = class extends w {
498
+ constructor() {
499
+ super(...arguments), this.spec = null;
500
+ }
501
+ render() {
502
+ return this.spec?.data ? this.spec.widget === "progress" ? this.renderProgress() : this.renderGauge() : c;
503
+ }
504
+ getOptions() {
505
+ const e = this.spec.options ?? {};
506
+ return { ...Te, ...e };
507
+ }
508
+ getValue() {
509
+ const e = this.spec.data;
510
+ return Number(e.value ?? 0);
511
+ }
512
+ renderGauge() {
513
+ const e = this.getOptions(), t = this.getValue(), a = e.max - e.min, i = a > 0 ? Math.max(0, Math.min(1, (t - e.min) / a)) : 0, r = this.getThresholdColor(t, e), n = 100, s = 100, l = 80, p = 150, d = 240, g = p + d * i, f = oe(n, s, l, p, p + d), u = i > 0 ? oe(n, s, l, p, g) : null, m = typeof this.spec.title == "string" ? this.spec.title : "Gauge", v = `${t}${e.unit}`;
514
+ return o`
515
+ <div class="gauge-container" part="gauge"
516
+ role="meter"
517
+ aria-valuenow=${t}
518
+ aria-valuemin=${e.min}
519
+ aria-valuemax=${e.max}
520
+ aria-label=${m}
521
+ aria-valuetext=${v}
522
+ >
523
+ <div class="gauge-wrapper">
524
+ <div class="gauge-center">
525
+ <div class="gauge-value" part="value">${t}</div>
526
+ ${e.unit ? o`<div class="gauge-unit" part="unit">${e.unit}</div>` : c}
527
+ </div>
528
+ <svg class="gauge-svg" viewBox="0 0 200 195" role="presentation" aria-hidden="true">
529
+ <path class="gauge-track" d="${f}" fill="none" stroke-width="12" stroke-linecap="round"></path>
530
+ <path class="gauge-fill" d="${u ?? "M0 0"}" fill="none" stroke="${u ? r : "none"}" stroke-width="12" stroke-linecap="round"></path>
531
+ </svg>
532
+ </div>
533
+ </div>
534
+ `;
535
+ }
536
+ renderProgress() {
537
+ const e = this.spec.data, t = Number(e.value ?? 0), a = Number(e.max ?? this.spec.options?.max ?? 100), i = a > 0 ? Math.max(0, Math.min(100, t / a * 100)) : 0, r = this.getOptions(), n = this.getThresholdColor(t, r), s = this.formatLabel(t, i), l = typeof this.spec.title == "string" ? this.spec.title : "Progress";
538
+ return o`
539
+ <div class="progress-container" part="progress"
540
+ role="progressbar"
541
+ aria-valuenow=${t}
542
+ aria-valuemin=${0}
543
+ aria-valuemax=${a}
544
+ aria-label=${l}
545
+ >
546
+ <div class="progress-bar-track">
547
+ <div
548
+ class="progress-bar-fill"
549
+ style="width:${i}%; background:${n || "var(--u-widget-primary, #4f46e5)"}"
550
+ part="progress-fill"
551
+ ></div>
552
+ </div>
553
+ <div class="progress-info">
554
+ <span>${s}</span>
555
+ <span>${Math.round(i)}%</span>
556
+ </div>
557
+ </div>
558
+ `;
559
+ }
560
+ formatLabel(e, t) {
561
+ const a = this.spec.options;
562
+ return a?.label ? String(a.label).replace("{value}", String(e)).replace("{percent}", String(Math.round(t))) : String(e);
563
+ }
564
+ getThresholdColor(e, t) {
565
+ if (!t.thresholds?.length) return "var(--u-widget-primary, #4f46e5)";
566
+ const a = [...t.thresholds].sort((i, r) => i.to - r.to);
567
+ for (const i of a)
568
+ if (e <= i.to) return ne(i.color);
569
+ return ne(a[a.length - 1].color);
570
+ }
571
+ };
572
+ B.styles = [b, y`
573
+ :host {
574
+ display: block;
575
+ font-family: system-ui, -apple-system, sans-serif;
576
+ container: u-gauge / inline-size;
577
+ }
578
+
579
+ .gauge-container {
580
+ position: relative;
581
+ display: flex;
582
+ flex-direction: column;
583
+ align-items: center;
584
+ }
585
+
586
+ .gauge-wrapper {
587
+ position: relative;
588
+ width: 100%;
589
+ max-width: var(--u-widget-gauge-size, 160px);
590
+ }
591
+
592
+ .gauge-svg {
593
+ display: block;
594
+ width: 100%;
595
+ }
596
+
597
+ .gauge-track {
598
+ stroke: var(--u-widget-border, #e2e8f0);
599
+ }
600
+
601
+ .gauge-center {
602
+ position: absolute;
603
+ /* Arc center (100,100) in viewBox 200×195 → 50% x, 51.3% y */
604
+ top: 51.3%;
605
+ left: 50%;
606
+ transform: translate(-50%, -50%);
607
+ text-align: center;
608
+ }
609
+
610
+ .gauge-value {
611
+ font-size: 1.75rem;
612
+ font-weight: 700;
613
+ line-height: 1.2;
614
+ color: var(--u-widget-text, #1a1a2e);
615
+ }
616
+
617
+ .gauge-unit {
618
+ font-size: 0.75rem;
619
+ color: var(--u-widget-text-secondary, #64748b);
620
+ }
621
+
622
+ /* ── progress bar ── */
623
+ .progress-container {
624
+ display: flex;
625
+ flex-direction: column;
626
+ gap: 6px;
627
+ }
628
+
629
+ .progress-bar-track {
630
+ width: 100%;
631
+ height: 8px;
632
+ background: var(--u-widget-border, #e2e8f0);
633
+ border-radius: 4px;
634
+ overflow: hidden;
635
+ }
636
+
637
+ .progress-bar-fill {
638
+ height: 100%;
639
+ border-radius: 4px;
640
+ transition: width 0.3s ease;
641
+ }
642
+
643
+ .progress-info {
644
+ display: flex;
645
+ justify-content: space-between;
646
+ font-size: 0.8125rem;
647
+ color: var(--u-widget-text-secondary, #64748b);
648
+ }
649
+
650
+ @container u-gauge (max-width: 10rem) {
651
+ .gauge-value {
652
+ font-size: 1.25rem;
653
+ }
654
+
655
+ .gauge-unit {
656
+ font-size: 0.625rem;
657
+ }
658
+
659
+ .progress-info {
660
+ font-size: 0.75rem;
661
+ }
662
+
663
+ .progress-bar-track {
664
+ height: 6px;
665
+ }
666
+ }
667
+ `];
668
+ ue([
669
+ h({ type: Object })
670
+ ], B.prototype, "spec", 2);
671
+ B = ue([
672
+ x("u-gauge")
673
+ ], B);
674
+ var Me = Object.defineProperty, Ue = Object.getOwnPropertyDescriptor, C = (e, t, a, i) => {
675
+ for (var r = i > 1 ? void 0 : i ? Ue(t, a) : t, n = e.length - 1, s; n >= 0; n--)
676
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
677
+ return i && r && Me(t, a, r), r;
678
+ };
679
+ let z = class extends w {
680
+ constructor() {
681
+ super(...arguments), this.spec = null, this._sortField = null, this._sortDir = null, this._page = 0, this._searchQuery = "", this._focusedIdx = 0, this._onTableKeydown = (e) => {
682
+ const a = e.target.closest("tr");
683
+ if (!a) return;
684
+ const i = a.parentElement;
685
+ if (!i) return;
686
+ const r = Array.from(i.querySelectorAll("tr")), n = r.indexOf(a);
687
+ let s = -1;
688
+ switch (e.key) {
689
+ case "ArrowDown":
690
+ s = Math.min(n + 1, r.length - 1);
691
+ break;
692
+ case "ArrowUp":
693
+ s = Math.max(n - 1, 0);
694
+ break;
695
+ case "Home":
696
+ s = 0;
697
+ break;
698
+ case "End":
699
+ s = r.length - 1;
700
+ break;
701
+ default:
702
+ return;
703
+ }
704
+ e.preventDefault(), s !== n && s >= 0 && (this._focusedIdx = s, this.updateComplete.then(() => {
705
+ this.shadowRoot?.querySelectorAll("tbody tr")?.[s]?.focus();
706
+ }));
707
+ }, this._onListKeydown = (e) => {
708
+ const a = e.target.closest(".list-item");
709
+ if (!a) return;
710
+ const i = a.parentElement;
711
+ if (!i) return;
712
+ const r = Array.from(i.querySelectorAll(".list-item")), n = r.indexOf(a);
713
+ let s = -1;
714
+ switch (e.key) {
715
+ case "ArrowDown":
716
+ s = Math.min(n + 1, r.length - 1);
717
+ break;
718
+ case "ArrowUp":
719
+ s = Math.max(n - 1, 0);
720
+ break;
721
+ case "Home":
722
+ s = 0;
723
+ break;
724
+ case "End":
725
+ s = r.length - 1;
726
+ break;
727
+ default:
728
+ return;
729
+ }
730
+ e.preventDefault(), s !== n && s >= 0 && (this._focusedIdx = s, this.updateComplete.then(() => {
731
+ this.shadowRoot?.querySelectorAll(".list-item")?.[s]?.focus();
732
+ }));
733
+ }, this._onSearch = (e) => {
734
+ this._searchQuery = e.target.value, this._page = 0;
735
+ };
736
+ }
737
+ willUpdate(e) {
738
+ e.has("spec") && (this._sortField = null, this._sortDir = null, this._page = 0, this._searchQuery = "", this._focusedIdx = 0);
739
+ }
740
+ render() {
741
+ return !this.spec?.data || !Array.isArray(this.spec.data) ? c : this.spec.widget === "list" ? this.renderList() : this.renderTable();
742
+ }
743
+ get _locale() {
744
+ const e = this.spec?.options?.locale;
745
+ return de(typeof e == "string" ? e : void 0);
746
+ }
747
+ renderTable() {
748
+ const e = this.spec.data, t = this.getColumns(e), a = this._locale, i = this.spec.options?.sortable !== !1, r = !!this.spec.options?.searchable, n = !!this.spec.options?.compact, s = Number(this.spec.options?.pageSize) || 0, l = this._searchQuery ? this.filterData(e, t) : e, p = this._sortField && this._sortDir ? this.sortData(l) : l, d = s > 0 ? Math.max(1, Math.ceil(p.length / s)) : 1, g = Math.min(this._page, d - 1), f = s > 0 ? p.slice(g * s, (g + 1) * s) : p, u = r ? o`
749
+ <div class="search-box" part="search">
750
+ <input
751
+ class="search-input"
752
+ type="text"
753
+ placeholder=${a.searchPlaceholder}
754
+ aria-label=${a.searchTable}
755
+ .value=${this._searchQuery}
756
+ @input=${this._onSearch}
757
+ />
758
+ </div>
759
+ ` : c, m = s > 0 && d > 1 ? o`
760
+ <nav class="pagination" part="pagination" aria-label=${a.tablePagination}>
761
+ <button aria-label=${a.previousPage} ?disabled=${g === 0} @click=${() => this._onPageChange(g - 1)}>${a.prev}</button>
762
+ <span aria-live="polite">${g + 1} / ${d}</span>
763
+ <button aria-label=${a.nextPage} ?disabled=${g >= d - 1} @click=${() => this._onPageChange(g + 1)}>${a.next}</button>
764
+ </nav>
765
+ ` : c;
766
+ return o`<div class="table-container${n ? " compact" : ""}">
767
+ ${u}
768
+ <div class="table-wrapper" part="table">
769
+ <table aria-label=${this.spec.title ?? a.dataTable}>
770
+ <thead>
771
+ <tr>
772
+ ${t.map(
773
+ (v) => o`<th
774
+ scope="col"
775
+ data-align=${v.align ?? "left"}
776
+ ?data-sortable=${i}
777
+ tabindex=${i ? "0" : c}
778
+ @click=${i ? () => this._onSort(v.field) : void 0}
779
+ @keydown=${i ? ($) => {
780
+ ($.key === "Enter" || $.key === " ") && ($.preventDefault(), this._onSort(v.field));
781
+ } : void 0}
782
+ aria-sort=${this._sortField === v.field && this._sortDir ? this._sortDir === "asc" ? "ascending" : "descending" : "none"}
783
+ part="th"
784
+ >${v.label ?? v.field}${this._sortField === v.field && this._sortDir ? o`<span class="sort-arrow">${this._sortDir === "asc" ? "▲" : "▼"}</span>` : c}</th>`
785
+ )}
786
+ </tr>
787
+ </thead>
788
+ <tbody @keydown=${this._onTableKeydown}>
789
+ ${f.map(
790
+ (v, $) => o`
791
+ <tr part="tr"
792
+ tabindex=${$ === this._focusedIdx ? "0" : "-1"}
793
+ @click=${() => this._onRowClick(v, s > 0 ? g * s + $ : $)}
794
+ @keydown=${(_) => {
795
+ (_.key === "Enter" || _.key === " ") && (_.preventDefault(), this._onRowClick(v, s > 0 ? g * s + $ : $));
796
+ }}
797
+ >
798
+ ${t.map(
799
+ (_) => o`<td data-align=${_.align ?? "left"} part="td"
800
+ >${_e(v[_.field], _.format, typeof this.spec.options?.locale == "string" ? this.spec.options.locale : void 0)}</td
801
+ >`
802
+ )}
803
+ </tr>
804
+ `
805
+ )}
806
+ </tbody>
807
+ </table>
808
+ </div>
809
+ ${m}
810
+ </div>`;
811
+ }
812
+ _onPageChange(e) {
813
+ this._page = e, this._focusedIdx = 0, this.updateComplete.then(() => {
814
+ this.shadowRoot?.querySelector('tbody tr[tabindex="0"]')?.focus();
815
+ });
816
+ }
817
+ filterData(e, t) {
818
+ const a = this._searchQuery.toLowerCase(), i = t.map((r) => r.field);
819
+ return e.filter(
820
+ (r) => i.some((n) => String(r[n] ?? "").toLowerCase().includes(a))
821
+ );
822
+ }
823
+ _onSort(e) {
824
+ this._sortField === e ? this._sortDir === "asc" ? this._sortDir = "desc" : (this._sortField = null, this._sortDir = null) : (this._sortField = e, this._sortDir = "asc");
825
+ }
826
+ sortData(e) {
827
+ const t = this._sortField, a = this._sortDir;
828
+ return [...e].sort((i, r) => {
829
+ const n = i[t], s = r[t];
830
+ if (n == null && s == null) return 0;
831
+ if (n == null) return 1;
832
+ if (s == null) return -1;
833
+ let l;
834
+ if (typeof n == "number" && typeof s == "number")
835
+ l = n - s;
836
+ else {
837
+ const p = Number(n), d = Number(s);
838
+ l = String(n) !== "" && String(s) !== "" && !isNaN(p) && !isNaN(d) ? p - d : String(n).localeCompare(String(s));
839
+ }
840
+ return a === "asc" ? l : -l;
841
+ });
842
+ }
843
+ renderList() {
844
+ const e = this.spec.data, t = this.spec.mapping, a = !!this.spec.options?.compact, i = t?.primary ?? this.inferPrimaryKey(e), r = t?.secondary, n = t?.icon, s = t?.avatar, l = t?.trailing, p = t?.badge;
845
+ return o`
846
+ <div class="list-container${a ? " compact" : ""}" part="list" @keydown=${this._onListKeydown}>
847
+ ${e.map(
848
+ (d, g) => o`
849
+ <div class="list-item" part="list-item"
850
+ tabindex=${g === this._focusedIdx ? "0" : "-1"}
851
+ @click=${() => this._onRowClick(d, g)}
852
+ @keydown=${(f) => {
853
+ (f.key === "Enter" || f.key === " ") && (f.preventDefault(), this._onRowClick(d, g));
854
+ }}
855
+ >
856
+ ${s && d[s] ? o`<img class="list-avatar" src=${String(d[s])} alt="" part="avatar" />` : n ? o`<div class="list-icon" part="icon">${this.getIconLetter(d[n])}</div>` : c}
857
+ <div class="list-content">
858
+ <div class="list-primary" part="primary">${d[i] ?? ""}</div>
859
+ ${r ? o`<div class="list-secondary" part="secondary">${d[r] ?? ""}</div>` : c}
860
+ </div>
861
+ ${p && d[p] != null ? o`<span class="list-badge" part="badge">${d[p]}</span>` : c}
862
+ ${l && d[l] != null ? o`<div class="list-trailing" part="trailing">${d[l]}</div>` : c}
863
+ </div>
864
+ `
865
+ )}
866
+ </div>
867
+ `;
868
+ }
869
+ _onRowClick(e, t) {
870
+ if (!this.spec) return;
871
+ const a = {
872
+ type: "select",
873
+ widget: this.spec.widget,
874
+ id: this.spec.id,
875
+ data: { ...e, _index: t }
876
+ };
877
+ this.dispatchEvent(
878
+ new CustomEvent("u-widget-internal", {
879
+ detail: a,
880
+ bubbles: !0,
881
+ composed: !0
882
+ })
883
+ );
884
+ }
885
+ getColumns(e) {
886
+ return this.spec.mapping?.columns ? this.spec.mapping.columns : e.length === 0 ? [] : Object.keys(e[0]).map((t) => ({ field: t }));
887
+ }
888
+ inferPrimaryKey(e) {
889
+ if (e.length === 0) return "";
890
+ const t = Object.keys(e[0]), a = ["name", "title", "label", "id", "key"];
891
+ for (const n of a)
892
+ if (t.includes(n)) return n;
893
+ const i = e[0];
894
+ return t.find((n) => typeof i[n] == "string") ?? t[0] ?? "";
895
+ }
896
+ getIconLetter(e) {
897
+ return String(e ?? "").charAt(0).toUpperCase();
898
+ }
899
+ };
900
+ z.styles = [b, y`
901
+ :host {
902
+ display: block;
903
+ font-family: system-ui, -apple-system, sans-serif;
904
+ container: u-table / inline-size;
905
+ }
906
+
907
+ /* ── table ── */
908
+ .table-wrapper {
909
+ overflow-x: auto;
910
+ scrollbar-width: thin;
911
+ scrollbar-color: var(--u-widget-border, #e2e8f0) transparent;
912
+ }
913
+ .table-wrapper::-webkit-scrollbar { height: 4px; }
914
+ .table-wrapper::-webkit-scrollbar-thumb {
915
+ background: var(--u-widget-border, #e2e8f0);
916
+ border-radius: 2px;
917
+ }
918
+
919
+ table {
920
+ width: 100%;
921
+ border-collapse: collapse;
922
+ font-size: 0.875rem;
923
+ }
924
+
925
+ th {
926
+ text-align: left;
927
+ font-weight: 600;
928
+ color: var(--u-widget-text-secondary, #64748b);
929
+ padding: 8px 12px;
930
+ border-bottom: 2px solid var(--u-widget-border, #e2e8f0);
931
+ white-space: nowrap;
932
+ font-size: 0.8125rem;
933
+ text-transform: uppercase;
934
+ letter-spacing: 0.025em;
935
+ }
936
+
937
+ th[data-sortable] {
938
+ cursor: pointer;
939
+ user-select: none;
940
+ }
941
+
942
+ th[data-sortable]:hover,
943
+ th[data-sortable]:focus-visible {
944
+ color: var(--u-widget-text, #1a1a2e);
945
+ outline: 2px solid var(--u-widget-primary, #4f46e5);
946
+ outline-offset: -2px;
947
+ }
948
+
949
+ .sort-arrow {
950
+ margin-left: 4px;
951
+ font-size: 0.6875rem;
952
+ }
953
+
954
+ td {
955
+ padding: 8px 12px;
956
+ border-bottom: 1px solid var(--u-widget-border, #e2e8f0);
957
+ color: var(--u-widget-text, #1a1a2e);
958
+ }
959
+
960
+ tbody tr {
961
+ cursor: pointer;
962
+ outline: none;
963
+ }
964
+
965
+ tbody tr:hover td {
966
+ background: var(--u-widget-surface, #f1f5f9);
967
+ }
968
+
969
+ tbody tr:focus td {
970
+ background: var(--u-widget-surface, #f1f5f9);
971
+ }
972
+
973
+ tbody tr:focus {
974
+ box-shadow: inset 3px 0 0 var(--u-widget-primary, #4f46e5);
975
+ }
976
+
977
+ tr:last-child td {
978
+ border-bottom: none;
979
+ }
980
+
981
+ th[data-align='center'],
982
+ td[data-align='center'] {
983
+ text-align: center;
984
+ }
985
+
986
+ th[data-align='right'],
987
+ td[data-align='right'] {
988
+ text-align: right;
989
+ }
990
+
991
+ /* ── list ── */
992
+ .list-container {
993
+ display: flex;
994
+ flex-direction: column;
995
+ }
996
+
997
+ .list-item {
998
+ display: flex;
999
+ align-items: center;
1000
+ gap: 12px;
1001
+ padding: 10px 0 10px 8px;
1002
+ border-bottom: 1px solid var(--u-widget-border, #e2e8f0);
1003
+ cursor: pointer;
1004
+ outline: none;
1005
+ }
1006
+
1007
+ .list-item:hover {
1008
+ background: var(--u-widget-surface, #f1f5f9);
1009
+ }
1010
+
1011
+ .list-item:focus {
1012
+ background: var(--u-widget-surface, #f1f5f9);
1013
+ box-shadow: inset 3px 0 0 var(--u-widget-primary, #4f46e5);
1014
+ }
1015
+
1016
+ .list-item:last-child {
1017
+ border-bottom: none;
1018
+ }
1019
+
1020
+ .list-icon {
1021
+ flex-shrink: 0;
1022
+ width: 32px;
1023
+ height: 32px;
1024
+ border-radius: 50%;
1025
+ background: var(--u-widget-surface, #f1f5f9);
1026
+ display: flex;
1027
+ align-items: center;
1028
+ justify-content: center;
1029
+ font-size: 0.75rem;
1030
+ color: var(--u-widget-text-secondary, #64748b);
1031
+ }
1032
+
1033
+ .list-avatar {
1034
+ flex-shrink: 0;
1035
+ width: 32px;
1036
+ height: 32px;
1037
+ border-radius: 50%;
1038
+ object-fit: cover;
1039
+ }
1040
+
1041
+ .list-content {
1042
+ flex: 1;
1043
+ min-width: 0;
1044
+ }
1045
+
1046
+ .list-primary {
1047
+ font-size: 0.875rem;
1048
+ font-weight: 500;
1049
+ color: var(--u-widget-text, #1a1a2e);
1050
+ }
1051
+
1052
+ .list-secondary {
1053
+ font-size: 0.8125rem;
1054
+ color: var(--u-widget-text-secondary, #64748b);
1055
+ margin-top: 2px;
1056
+ }
1057
+
1058
+ .list-trailing {
1059
+ flex-shrink: 0;
1060
+ font-size: 0.8125rem;
1061
+ font-weight: 500;
1062
+ color: var(--u-widget-text-secondary, #64748b);
1063
+ }
1064
+
1065
+ .list-badge {
1066
+ flex-shrink: 0;
1067
+ display: inline-flex;
1068
+ align-items: center;
1069
+ padding: 2px 8px;
1070
+ border-radius: 10px;
1071
+ font-size: 0.6875rem;
1072
+ font-weight: 500;
1073
+ background: var(--u-widget-surface, #f1f5f9);
1074
+ color: var(--u-widget-text-secondary, #64748b);
1075
+ white-space: nowrap;
1076
+ }
1077
+
1078
+ /* ── search ── */
1079
+ .search-box {
1080
+ margin-bottom: 8px;
1081
+ }
1082
+
1083
+ .search-input {
1084
+ width: 100%;
1085
+ box-sizing: border-box;
1086
+ padding: 6px 10px;
1087
+ font-size: 0.8125rem;
1088
+ border: 1px solid var(--u-widget-border, #e2e8f0);
1089
+ border-radius: 4px;
1090
+ outline: none;
1091
+ font-family: inherit;
1092
+ color: var(--u-widget-text, #1a1a2e);
1093
+ background: var(--u-widget-bg, #fff);
1094
+ }
1095
+
1096
+ .search-input:focus {
1097
+ border-color: var(--u-widget-primary, #4f46e5);
1098
+ }
1099
+
1100
+ /* ── pagination ── */
1101
+ .pagination {
1102
+ display: flex;
1103
+ align-items: center;
1104
+ justify-content: center;
1105
+ gap: 8px;
1106
+ margin-top: 8px;
1107
+ font-size: 0.8125rem;
1108
+ color: var(--u-widget-text-secondary, #64748b);
1109
+ }
1110
+
1111
+ .pagination button {
1112
+ padding: 4px 10px;
1113
+ border: 1px solid var(--u-widget-border, #e2e8f0);
1114
+ border-radius: 4px;
1115
+ background: var(--u-widget-bg, #fff);
1116
+ color: var(--u-widget-text, #1a1a2e);
1117
+ cursor: pointer;
1118
+ font-size: 0.75rem;
1119
+ font-family: inherit;
1120
+ }
1121
+
1122
+ .pagination button:hover:not(:disabled) {
1123
+ background: var(--u-widget-surface, #f1f5f9);
1124
+ }
1125
+
1126
+ .pagination button:disabled {
1127
+ opacity: 0.4;
1128
+ cursor: default;
1129
+ }
1130
+
1131
+ /* ── compact ── */
1132
+ .compact table {
1133
+ font-size: 0.75rem;
1134
+ }
1135
+
1136
+ .compact th {
1137
+ padding: 4px 8px;
1138
+ font-size: 0.6875rem;
1139
+ }
1140
+
1141
+ .compact td {
1142
+ padding: 4px 8px;
1143
+ }
1144
+
1145
+ .compact .list-item {
1146
+ padding: 6px 0 6px 8px;
1147
+ gap: 8px;
1148
+ }
1149
+
1150
+ .compact .list-icon {
1151
+ width: 24px;
1152
+ height: 24px;
1153
+ font-size: 0.625rem;
1154
+ }
1155
+
1156
+ .compact .list-avatar {
1157
+ width: 24px;
1158
+ height: 24px;
1159
+ }
1160
+
1161
+ .compact .list-primary {
1162
+ font-size: 0.75rem;
1163
+ }
1164
+
1165
+ .compact .list-secondary {
1166
+ font-size: 0.6875rem;
1167
+ }
1168
+
1169
+ .compact .list-trailing {
1170
+ font-size: 0.6875rem;
1171
+ }
1172
+
1173
+ /* ── container-query responsive ── */
1174
+ @container u-table (max-width: 30rem) {
1175
+ table {
1176
+ font-size: 0.75rem;
1177
+ }
1178
+
1179
+ th {
1180
+ padding: 4px 8px;
1181
+ font-size: 0.6875rem;
1182
+ }
1183
+
1184
+ td {
1185
+ padding: 4px 8px;
1186
+ }
1187
+
1188
+ .list-item {
1189
+ padding: 6px 0 6px 8px;
1190
+ gap: 8px;
1191
+ }
1192
+
1193
+ .list-icon,
1194
+ .list-avatar {
1195
+ width: 24px;
1196
+ height: 24px;
1197
+ }
1198
+
1199
+ .list-primary {
1200
+ font-size: 0.75rem;
1201
+ }
1202
+
1203
+ .list-secondary,
1204
+ .list-trailing {
1205
+ font-size: 0.6875rem;
1206
+ }
1207
+ }
1208
+ `];
1209
+ C([
1210
+ h({ type: Object })
1211
+ ], z.prototype, "spec", 2);
1212
+ C([
1213
+ S()
1214
+ ], z.prototype, "_sortField", 2);
1215
+ C([
1216
+ S()
1217
+ ], z.prototype, "_sortDir", 2);
1218
+ C([
1219
+ S()
1220
+ ], z.prototype, "_page", 2);
1221
+ C([
1222
+ S()
1223
+ ], z.prototype, "_searchQuery", 2);
1224
+ C([
1225
+ S()
1226
+ ], z.prototype, "_focusedIdx", 2);
1227
+ z = C([
1228
+ x("u-table")
1229
+ ], z);
1230
+ var Re = Object.defineProperty, qe = Object.getOwnPropertyDescriptor, K = (e, t, a, i) => {
1231
+ for (var r = i > 1 ? void 0 : i ? qe(t, a) : t, n = e.length - 1, s; n >= 0; n--)
1232
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
1233
+ return i && r && Re(t, a, r), r;
1234
+ };
1235
+ let D = class extends w {
1236
+ constructor() {
1237
+ super(...arguments), this.spec = null, this._formData = {}, this._errors = {}, this._onFormSubmit = (e) => {
1238
+ e.preventDefault();
1239
+ const t = (this.spec?.actions ?? []).find((a) => a.action === "submit");
1240
+ t ? this._onAction(t) : this._validate() && this._emitEvent({
1241
+ type: "submit",
1242
+ widget: this.spec.widget,
1243
+ id: this.spec.id,
1244
+ data: { ...this._formData }
1245
+ });
1246
+ }, this._onConfirmKeydown = (e) => {
1247
+ if (e.key === "Escape") {
1248
+ const t = (this.spec?.actions ?? []).find((a) => a.action === "cancel");
1249
+ t && this._onAction(t);
1250
+ }
1251
+ };
1252
+ }
1253
+ willUpdate(e) {
1254
+ e.has("spec") && this.spec && (this._formData = { ...this.spec.data ?? {} }, this._errors = {});
1255
+ }
1256
+ render() {
1257
+ return this.spec ? this.spec.widget === "confirm" ? this.renderConfirm() : this.renderForm() : c;
1258
+ }
1259
+ renderForm() {
1260
+ const e = this.spec.fields ?? [], t = this.spec.actions ?? [];
1261
+ return o`
1262
+ <form class="form-container" part="form" @submit=${this._onFormSubmit}>
1263
+ ${e.map((a) => this.renderField(a))}
1264
+ ${t.length > 0 ? this.renderActions(t) : c}
1265
+ </form>
1266
+ `;
1267
+ }
1268
+ renderConfirm() {
1269
+ const e = this.spec.description, t = this.spec.actions ?? [];
1270
+ return o`
1271
+ <div class="confirm-container" part="confirm" @keydown=${this._onConfirmKeydown}>
1272
+ ${e ? o`<div class="confirm-description" part="description">${e}</div>` : c}
1273
+ ${t.length > 0 ? this.renderActions(t) : c}
1274
+ </div>
1275
+ `;
1276
+ }
1277
+ renderField(e) {
1278
+ const t = this._formData[e.field], a = e.type ?? "text", i = this._errors[e.field], r = `err-${e.field}`;
1279
+ return o`
1280
+ <div class="field" part="field">
1281
+ ${e.label ? o`<label class="field-label" for=${`input-${e.field}`} part="label"
1282
+ >${e.label}${e.required ? o`<span class="required">*</span>` : c}</label
1283
+ >` : c}
1284
+ ${this.renderInput(e, a, t, i ? r : void 0)}
1285
+ ${i ? o`<div class="field-error" id=${r} role="alert" part="field-error">${i}</div>` : c}
1286
+ </div>
1287
+ `;
1288
+ }
1289
+ renderInput(e, t, a, i) {
1290
+ const r = !!this._errors[e.field];
1291
+ switch (t) {
1292
+ case "textarea":
1293
+ return o`<textarea
1294
+ id=${`input-${e.field}`}
1295
+ class=${r ? "invalid" : ""}
1296
+ .value=${String(a ?? "")}
1297
+ placeholder=${e.placeholder ?? ""}
1298
+ rows=${e.rows ?? 3}
1299
+ ?required=${e.required}
1300
+ minlength=${e.minLength ?? ""}
1301
+ maxlength=${e.maxLength ?? ""}
1302
+ aria-invalid=${r ? "true" : "false"}
1303
+ aria-describedby=${i ?? c}
1304
+ ?aria-required=${e.required}
1305
+ @input=${(n) => this._onChange(e.field, n.target.value)}
1306
+ part="input"
1307
+ ></textarea>`;
1308
+ case "select":
1309
+ return o`<select
1310
+ id=${`input-${e.field}`}
1311
+ class=${r ? "invalid" : ""}
1312
+ .value=${String(a ?? "")}
1313
+ ?required=${e.required}
1314
+ aria-invalid=${r ? "true" : "false"}
1315
+ aria-describedby=${i ?? c}
1316
+ @change=${(n) => this._onChange(e.field, n.target.value)}
1317
+ part="input"
1318
+ >
1319
+ <option value="">--</option>
1320
+ ${(e.options ?? []).map(
1321
+ (n) => o`<option value=${n}>${n}</option>`
1322
+ )}
1323
+ </select>`;
1324
+ case "multiselect":
1325
+ return o`<div class="multiselect-group" part="multiselect-group" role="group" aria-label=${e.label ?? e.field} aria-invalid=${r ? "true" : "false"} aria-describedby=${i ?? c}>
1326
+ ${(e.options ?? []).map(
1327
+ (n) => o`
1328
+ <label>
1329
+ <input
1330
+ type="checkbox"
1331
+ value=${n}
1332
+ ?checked=${Array.isArray(a) && a.includes(n)}
1333
+ @change=${(s) => {
1334
+ const l = s.target.checked, p = Array.isArray(a) ? [...a] : [];
1335
+ this._onChange(
1336
+ e.field,
1337
+ l ? [...p, n] : p.filter((d) => d !== n)
1338
+ );
1339
+ }}
1340
+ />
1341
+ ${n}
1342
+ </label>
1343
+ `
1344
+ )}
1345
+ </div>`;
1346
+ case "toggle":
1347
+ return o`<div class="toggle-wrapper">
1348
+ <div
1349
+ class="toggle-track"
1350
+ data-on=${!!a}
1351
+ role="switch"
1352
+ aria-checked=${!!a}
1353
+ aria-label=${e.label ?? e.field}
1354
+ tabindex="0"
1355
+ @click=${() => this._onChange(e.field, !a)}
1356
+ @keydown=${(n) => {
1357
+ (n.key === " " || n.key === "Enter") && (n.preventDefault(), this._onChange(e.field, !a));
1358
+ }}
1359
+ part="toggle"
1360
+ >
1361
+ <div class="toggle-thumb"></div>
1362
+ </div>
1363
+ </div>`;
1364
+ case "radio":
1365
+ return o`<div class="radio-group" part="radio-group" role="radiogroup" aria-label=${e.label ?? e.field} aria-invalid=${r ? "true" : "false"} aria-describedby=${i ?? c}>
1366
+ ${(e.options ?? []).map(
1367
+ (n) => o`
1368
+ <label>
1369
+ <input
1370
+ type="radio"
1371
+ name=${e.field}
1372
+ value=${n}
1373
+ ?checked=${a === n}
1374
+ @change=${() => this._onChange(e.field, n)}
1375
+ />
1376
+ ${n}
1377
+ </label>
1378
+ `
1379
+ )}
1380
+ </div>`;
1381
+ case "checkbox":
1382
+ return o`<div class="checkbox-group" part="checkbox-group" role="group" aria-label=${e.label ?? e.field} aria-invalid=${r ? "true" : "false"} aria-describedby=${i ?? c}>
1383
+ ${(e.options ?? []).map(
1384
+ (n) => o`
1385
+ <label>
1386
+ <input
1387
+ type="checkbox"
1388
+ value=${n}
1389
+ ?checked=${Array.isArray(a) && a.includes(n)}
1390
+ @change=${(s) => {
1391
+ const l = s.target.checked, p = Array.isArray(a) ? [...a] : [];
1392
+ this._onChange(
1393
+ e.field,
1394
+ l ? [...p, n] : p.filter((d) => d !== n)
1395
+ );
1396
+ }}
1397
+ />
1398
+ ${n}
1399
+ </label>
1400
+ `
1401
+ )}
1402
+ </div>`;
1403
+ default:
1404
+ return o`<input
1405
+ type=${t === "datetime" ? "datetime-local" : t}
1406
+ id=${`input-${e.field}`}
1407
+ class=${r ? "invalid" : ""}
1408
+ .value=${String(a ?? "")}
1409
+ placeholder=${e.placeholder ?? ""}
1410
+ ?required=${e.required}
1411
+ aria-invalid=${r ? "true" : "false"}
1412
+ aria-describedby=${i ?? c}
1413
+ ?aria-required=${e.required}
1414
+ min=${e.min ?? ""}
1415
+ max=${e.max ?? ""}
1416
+ step=${e.step ?? ""}
1417
+ minlength=${e.minLength ?? ""}
1418
+ maxlength=${e.maxLength ?? ""}
1419
+ pattern=${e.pattern ?? ""}
1420
+ @input=${(s) => {
1421
+ const l = s.target.value, p = (t === "number" || t === "range") && l !== "" ? Number(l) : l;
1422
+ this._onChange(e.field, p);
1423
+ }}
1424
+ part="input"
1425
+ />`;
1426
+ }
1427
+ }
1428
+ renderActions(e) {
1429
+ return o`
1430
+ <div class="actions" part="actions">
1431
+ ${e.map(
1432
+ (t) => o`
1433
+ <button
1434
+ type=${t.action === "submit" ? "submit" : "button"}
1435
+ data-style=${t.style ?? "default"}
1436
+ ?disabled=${t.disabled}
1437
+ @click=${(a) => {
1438
+ t.action === "submit" && a.preventDefault(), this._onAction(t);
1439
+ }}
1440
+ part="action-btn"
1441
+ >
1442
+ ${t.label}
1443
+ </button>
1444
+ `
1445
+ )}
1446
+ </div>
1447
+ `;
1448
+ }
1449
+ _onChange(e, t) {
1450
+ if (this._formData = { ...this._formData, [e]: t }, this._errors[e]) {
1451
+ const a = { ...this._errors };
1452
+ delete a[e], this._errors = a;
1453
+ }
1454
+ this._emitEvent({
1455
+ type: "change",
1456
+ widget: this.spec.widget,
1457
+ id: this.spec.id,
1458
+ data: { field: e, value: t }
1459
+ });
1460
+ }
1461
+ get _locale() {
1462
+ const e = this.spec?.options?.locale;
1463
+ return de(typeof e == "string" ? e : void 0);
1464
+ }
1465
+ _validate() {
1466
+ const e = this.spec?.fields ?? [], t = {}, a = this._locale;
1467
+ for (const i of e) {
1468
+ const r = this._formData[i.field], n = i.label ?? i.field;
1469
+ if (i.required && (r == null || r === "" || Array.isArray(r) && r.length === 0)) {
1470
+ t[i.field] = i.message ?? A(a.required, { label: n });
1471
+ continue;
1472
+ }
1473
+ if (!(r == null || r === "")) {
1474
+ if (i.maxLength != null && typeof r == "string" && r.length > i.maxLength && (t[i.field] = i.message ?? A(a.maxLength, { label: n, max: i.maxLength })), i.min != null && typeof r == "number" && r < Number(i.min) && (t[i.field] = i.message ?? A(a.minValue, { label: n, min: i.min })), i.max != null && typeof r == "number" && r > Number(i.max) && (t[i.field] = i.message ?? A(a.maxValue, { label: n, max: i.max })), i.minLength != null && typeof r == "string" && r.length < i.minLength) {
1475
+ t[i.field] = i.message ?? A(a.minLength, { label: n, min: i.minLength });
1476
+ continue;
1477
+ }
1478
+ if (i.type === "email" && typeof r == "string" && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r)) {
1479
+ t[i.field] = i.message ?? A(a.invalidEmail, { label: n });
1480
+ continue;
1481
+ }
1482
+ if (i.type === "url" && typeof r == "string" && !/^https?:\/\/.+/.test(r)) {
1483
+ t[i.field] = i.message ?? A(a.invalidUrl, { label: n });
1484
+ continue;
1485
+ }
1486
+ if (i.pattern && typeof r == "string")
1487
+ try {
1488
+ new RegExp(i.pattern).test(r) || (t[i.field] = i.message ?? A(a.invalidPattern, { label: n }));
1489
+ } catch {
1490
+ }
1491
+ }
1492
+ }
1493
+ return this._errors = t, Object.keys(t).length === 0;
1494
+ }
1495
+ _onAction(e) {
1496
+ if (e.action === "submit") {
1497
+ if (!this._validate()) return;
1498
+ this._emitEvent({
1499
+ type: "submit",
1500
+ widget: this.spec.widget,
1501
+ id: this.spec.id,
1502
+ data: { ...this._formData }
1503
+ });
1504
+ } else e.action === "cancel" ? this._emitEvent({
1505
+ type: "action",
1506
+ widget: this.spec.widget,
1507
+ id: this.spec.id,
1508
+ action: "cancel"
1509
+ }) : this._emitEvent({
1510
+ type: "action",
1511
+ widget: this.spec.widget,
1512
+ id: this.spec.id,
1513
+ action: e.action,
1514
+ data: { ...this._formData }
1515
+ });
1516
+ }
1517
+ _emitEvent(e) {
1518
+ this.dispatchEvent(
1519
+ new CustomEvent("u-widget-internal", {
1520
+ detail: e,
1521
+ bubbles: !0,
1522
+ composed: !0
1523
+ })
1524
+ );
1525
+ }
1526
+ };
1527
+ D.styles = [b, y`
1528
+ :host {
1529
+ display: block;
1530
+ font-family: system-ui, -apple-system, sans-serif;
1531
+ container: u-form / inline-size;
1532
+ }
1533
+
1534
+ .form-container {
1535
+ display: flex;
1536
+ flex-direction: column;
1537
+ gap: 16px;
1538
+ }
1539
+
1540
+ .field {
1541
+ display: flex;
1542
+ flex-direction: column;
1543
+ gap: 4px;
1544
+ }
1545
+
1546
+ .field-label {
1547
+ font-size: 0.8125rem;
1548
+ font-weight: 600;
1549
+ color: var(--u-widget-text, #1a1a2e);
1550
+ }
1551
+
1552
+ .field-label .required {
1553
+ color: var(--u-widget-negative, #dc2626);
1554
+ margin-left: 2px;
1555
+ }
1556
+
1557
+ input,
1558
+ textarea,
1559
+ select {
1560
+ padding: 8px 12px;
1561
+ border: 1px solid var(--u-widget-border, #e2e8f0);
1562
+ border-radius: 6px;
1563
+ font-size: 0.875rem;
1564
+ font-family: inherit;
1565
+ color: var(--u-widget-text, #1a1a2e);
1566
+ background: var(--u-widget-bg, #fff);
1567
+ outline: none;
1568
+ transition: border-color 0.15s;
1569
+ }
1570
+
1571
+ input:focus,
1572
+ textarea:focus,
1573
+ select:focus {
1574
+ border-color: var(--u-widget-primary, #4f46e5);
1575
+ box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
1576
+ }
1577
+
1578
+ textarea {
1579
+ resize: vertical;
1580
+ }
1581
+
1582
+ .toggle-wrapper {
1583
+ display: flex;
1584
+ align-items: center;
1585
+ gap: 8px;
1586
+ }
1587
+
1588
+ .toggle-track {
1589
+ width: 44px;
1590
+ height: 24px;
1591
+ border-radius: 12px;
1592
+ background: var(--u-widget-border, #e2e8f0);
1593
+ cursor: pointer;
1594
+ position: relative;
1595
+ transition: background 0.2s;
1596
+ }
1597
+
1598
+ .toggle-track[data-on='true'] {
1599
+ background: var(--u-widget-primary, #4f46e5);
1600
+ }
1601
+
1602
+ .toggle-thumb {
1603
+ width: 20px;
1604
+ height: 20px;
1605
+ border-radius: 50%;
1606
+ background: white;
1607
+ position: absolute;
1608
+ top: 2px;
1609
+ left: 2px;
1610
+ transition: transform 0.2s;
1611
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
1612
+ }
1613
+
1614
+ .toggle-track[data-on='true'] .toggle-thumb {
1615
+ transform: translateX(20px);
1616
+ }
1617
+
1618
+ .checkbox-group,
1619
+ .radio-group {
1620
+ display: flex;
1621
+ flex-direction: column;
1622
+ gap: 6px;
1623
+ }
1624
+
1625
+ .multiselect-group {
1626
+ display: flex;
1627
+ flex-direction: column;
1628
+ gap: 4px;
1629
+ border: 1px solid var(--u-widget-border, #e2e8f0);
1630
+ border-radius: 6px;
1631
+ padding: 8px;
1632
+ max-height: 180px;
1633
+ overflow-y: auto;
1634
+ }
1635
+
1636
+ .checkbox-group label,
1637
+ .radio-group label,
1638
+ .multiselect-group label {
1639
+ display: flex;
1640
+ align-items: center;
1641
+ gap: 8px;
1642
+ font-size: 0.875rem;
1643
+ cursor: pointer;
1644
+ }
1645
+
1646
+ .actions {
1647
+ display: flex;
1648
+ gap: 8px;
1649
+ justify-content: flex-end;
1650
+ padding-top: 8px;
1651
+ }
1652
+
1653
+ button {
1654
+ padding: 8px 20px;
1655
+ border-radius: 6px;
1656
+ font-size: 0.875rem;
1657
+ font-weight: 500;
1658
+ cursor: pointer;
1659
+ border: 1px solid var(--u-widget-border, #e2e8f0);
1660
+ background: var(--u-widget-bg, #fff);
1661
+ color: var(--u-widget-text, #1a1a2e);
1662
+ transition: all 0.15s;
1663
+ }
1664
+
1665
+ button:hover {
1666
+ background: var(--u-widget-surface, #f1f5f9);
1667
+ }
1668
+
1669
+ button[data-style='primary'] {
1670
+ background: var(--u-widget-primary, #4f46e5);
1671
+ color: white;
1672
+ border-color: transparent;
1673
+ }
1674
+
1675
+ button[data-style='primary']:hover {
1676
+ opacity: 0.9;
1677
+ }
1678
+
1679
+ button[data-style='danger'] {
1680
+ background: var(--u-widget-negative, #dc2626);
1681
+ color: white;
1682
+ border-color: transparent;
1683
+ }
1684
+
1685
+ .field-error {
1686
+ font-size: 0.75rem;
1687
+ color: var(--u-widget-negative, #dc2626);
1688
+ margin-top: 2px;
1689
+ }
1690
+
1691
+ input.invalid,
1692
+ textarea.invalid,
1693
+ select.invalid {
1694
+ border-color: var(--u-widget-negative, #dc2626);
1695
+ }
1696
+
1697
+ input.invalid:focus,
1698
+ textarea.invalid:focus,
1699
+ select.invalid:focus {
1700
+ box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);
1701
+ }
1702
+
1703
+ /* ── confirm ── */
1704
+ .confirm-container {
1705
+ display: flex;
1706
+ flex-direction: column;
1707
+ gap: 16px;
1708
+ }
1709
+
1710
+ .confirm-description {
1711
+ font-size: 0.9375rem;
1712
+ color: var(--u-widget-text, #1a1a2e);
1713
+ line-height: 1.5;
1714
+ }
1715
+
1716
+ @container u-form (max-width: 20rem) {
1717
+ .form-container {
1718
+ gap: 12px;
1719
+ }
1720
+
1721
+ .field-label {
1722
+ font-size: 0.75rem;
1723
+ }
1724
+
1725
+ input, textarea, select {
1726
+ font-size: 0.8125rem;
1727
+ padding: 6px 8px;
1728
+ }
1729
+
1730
+ .actions {
1731
+ flex-direction: column;
1732
+ }
1733
+
1734
+ .actions button {
1735
+ width: 100%;
1736
+ text-align: center;
1737
+ }
1738
+
1739
+ button {
1740
+ padding: 8px 14px;
1741
+ font-size: 0.8125rem;
1742
+ }
1743
+ }
1744
+ `];
1745
+ K([
1746
+ h({ type: Object })
1747
+ ], D.prototype, "spec", 2);
1748
+ K([
1749
+ S()
1750
+ ], D.prototype, "_formData", 2);
1751
+ K([
1752
+ S()
1753
+ ], D.prototype, "_errors", 2);
1754
+ D = K([
1755
+ x("u-form")
1756
+ ], D);
1757
+ var Be = Object.defineProperty, We = Object.getOwnPropertyDescriptor, Z = (e, t, a, i) => {
1758
+ for (var r = i > 1 ? void 0 : i ? We(t, a) : t, n = e.length - 1, s; n >= 0; n--)
1759
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
1760
+ return i && r && Be(t, a, r), r;
1761
+ };
1762
+ let I = class extends w {
1763
+ constructor() {
1764
+ super(...arguments), this.spec = null, this.theme = null;
1765
+ }
1766
+ render() {
1767
+ if (!this.spec) return c;
1768
+ const e = this.spec.layout ?? "stack", t = this.spec.columns ?? 2, a = this.spec.children ?? [], i = this.spec.title, r = a.map((s) => this._child(s)), n = i ? "region" : void 0;
1769
+ if (e === "row")
1770
+ return o`<div class="compose-container" part="compose" role=${n ?? c} aria-label=${i ?? c}>${i ? o`<div class="compose-title" part="title">${i}</div>` : c}<div class="layout-row" part="layout">${r}</div></div>`;
1771
+ if (e === "grid") {
1772
+ const s = this._gridColumns(t);
1773
+ return o`<div class="compose-container" part="compose" role=${n ?? c} aria-label=${i ?? c}>${i ? o`<div class="compose-title" part="title">${i}</div>` : c}<div class="layout-grid" part="layout" style="grid-template-columns: ${s}">${r}</div></div>`;
1774
+ }
1775
+ return o`<div class="compose-container" part="compose" role=${n ?? c} aria-label=${i ?? c}>${i ? o`<div class="compose-title" part="title">${i}</div>` : c}<div class="layout-stack" part="layout">${r}</div></div>`;
1776
+ }
1777
+ /** Compute grid-template-columns from options.widths or fallback to equal columns. */
1778
+ _gridColumns(e) {
1779
+ const a = (this.spec?.options ?? {}).widths;
1780
+ return !Array.isArray(a) || a.length === 0 ? `repeat(${e}, 1fr)` : a.map((i) => {
1781
+ if (i === "auto") return "auto";
1782
+ if (i === "stretch") return "1fr";
1783
+ const r = Number(i);
1784
+ return Number.isFinite(r) && r > 0 ? `${r}fr` : "1fr";
1785
+ }).join(" ");
1786
+ }
1787
+ _child(e) {
1788
+ const t = this.theme, a = e.span ? Math.max(1, Math.floor(Number(e.span) || 1)) : 0, i = a > 1 ? `grid-column: span ${a}` : "", n = !!(this.spec?.options ?? {}).card, s = o`<u-widget .spec=${e} theme=${t ?? c}></u-widget>`;
1789
+ if (e.collapsed) {
1790
+ const p = e.title || "Details";
1791
+ return o`
1792
+ <details class="child-collapsed" part="child" style=${i || c}>
1793
+ <summary part="collapsed-summary">${p}</summary>
1794
+ <div class="collapsed-content">${s}</div>
1795
+ </details>
1796
+ `;
1797
+ }
1798
+ const l = n ? "child child-card" : "child";
1799
+ return i ? o`<div class=${l} style=${i} part="child">${s}</div>` : o`<div class=${l} part="child">${s}</div>`;
1800
+ }
1801
+ };
1802
+ I.styles = [b, y`
1803
+ :host {
1804
+ display: block;
1805
+ container: u-compose / inline-size;
1806
+ }
1807
+
1808
+ .compose-container {
1809
+ display: flex;
1810
+ flex-direction: column;
1811
+ }
1812
+
1813
+ .compose-title {
1814
+ font-size: 1.125rem;
1815
+ font-weight: 600;
1816
+ color: var(--u-widget-text, #1a1a2e);
1817
+ margin-bottom: 12px;
1818
+ }
1819
+
1820
+ .layout-stack {
1821
+ display: flex;
1822
+ flex-direction: column;
1823
+ gap: var(--u-widget-gap, 16px);
1824
+ }
1825
+
1826
+ .layout-row {
1827
+ display: flex;
1828
+ flex-direction: row;
1829
+ gap: var(--u-widget-gap, 16px);
1830
+ }
1831
+
1832
+ .layout-row > * {
1833
+ flex: 1;
1834
+ min-width: 0;
1835
+ }
1836
+
1837
+ .layout-grid {
1838
+ display: grid;
1839
+ gap: var(--u-widget-gap, 16px);
1840
+ }
1841
+
1842
+ .child-card {
1843
+ padding: 16px 20px;
1844
+ border-radius: var(--u-widget-radius, 6px);
1845
+ border: 1px solid var(--u-widget-border, #e2e8f0);
1846
+ background: var(--u-widget-bg, #fff);
1847
+ box-shadow: var(--u-widget-shadow);
1848
+ transition: box-shadow 0.2s;
1849
+ }
1850
+
1851
+ /* ── collapsed child (details/summary) ── */
1852
+ details.child-collapsed {
1853
+ border: 1px solid var(--u-widget-border, #e2e8f0);
1854
+ border-radius: 6px;
1855
+ overflow: hidden;
1856
+ }
1857
+
1858
+ details.child-collapsed > summary {
1859
+ display: flex;
1860
+ align-items: center;
1861
+ gap: 6px;
1862
+ padding: 8px 12px;
1863
+ font-size: 0.875rem;
1864
+ font-weight: 500;
1865
+ color: var(--u-widget-text, #1a1a2e);
1866
+ cursor: pointer;
1867
+ user-select: none;
1868
+ list-style: none;
1869
+ background: var(--u-widget-surface, #f1f5f9);
1870
+ }
1871
+
1872
+ details.child-collapsed > summary::-webkit-details-marker { display: none; }
1873
+
1874
+ details.child-collapsed > summary::before {
1875
+ content: '\\25B6';
1876
+ font-size: 0.625rem;
1877
+ transition: transform 0.15s;
1878
+ }
1879
+
1880
+ details.child-collapsed[open] > summary::before {
1881
+ transform: rotate(90deg);
1882
+ }
1883
+
1884
+ details.child-collapsed > .collapsed-content {
1885
+ padding: 12px;
1886
+ }
1887
+
1888
+ /* ── container-query responsive ── */
1889
+ @container u-compose (max-width: 30rem) {
1890
+ .layout-row {
1891
+ flex-direction: column;
1892
+ }
1893
+
1894
+ .layout-grid {
1895
+ grid-template-columns: 1fr !important;
1896
+ }
1897
+ }
1898
+ `];
1899
+ Z([
1900
+ h({ type: Object })
1901
+ ], I.prototype, "spec", 2);
1902
+ Z([
1903
+ h({ type: String, reflect: !0 })
1904
+ ], I.prototype, "theme", 2);
1905
+ I = Z([
1906
+ x("u-compose")
1907
+ ], I);
1908
+ var He = Object.defineProperty, Ke = Object.getOwnPropertyDescriptor, ge = (e, t, a, i) => {
1909
+ for (var r = i > 1 ? void 0 : i ? Ke(t, a) : t, n = e.length - 1, s; n >= 0; n--)
1910
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
1911
+ return i && r && He(t, a, r), r;
1912
+ };
1913
+ let W = class extends w {
1914
+ constructor() {
1915
+ super(...arguments), this.spec = null;
1916
+ }
1917
+ render() {
1918
+ if (!this.spec) return c;
1919
+ switch (this.spec.widget) {
1920
+ case "markdown":
1921
+ return this.renderMarkdown();
1922
+ case "image":
1923
+ return this.renderImage();
1924
+ case "callout":
1925
+ return this.renderCallout();
1926
+ default:
1927
+ return c;
1928
+ }
1929
+ }
1930
+ renderMarkdown() {
1931
+ const e = this.spec.data, t = typeof e == "string" ? e : e?.content ?? "";
1932
+ return t ? o`<div class="markdown" part="markdown"
1933
+ .innerHTML=${this.parseMarkdown(t)}
1934
+ ></div>` : c;
1935
+ }
1936
+ renderImage() {
1937
+ const e = this.spec.data;
1938
+ if (!e) return c;
1939
+ const t = String(e.src ?? ""), a = String(e.alt ?? ""), i = e.caption, r = this.sanitizeUrl(t);
1940
+ return r ? o`<div class="image-container" part="image">
1941
+ <img src=${r} alt=${a} loading="lazy" />
1942
+ ${i ? o`<div class="image-caption" part="caption">${i}</div>` : c}
1943
+ </div>` : c;
1944
+ }
1945
+ renderCallout() {
1946
+ const e = this.spec.data;
1947
+ if (!e) return c;
1948
+ const t = String(e.message ?? ""), a = String(e.level ?? "info"), i = e.title, n = ["info", "warning", "error", "success"].includes(a) ? a : "info", s = n === "warning" || n === "error";
1949
+ return o`<div class="callout callout-${n}" part="callout" role=${s ? "alert" : "note"} aria-live=${s ? "assertive" : "polite"}>
1950
+ ${i ? o`<div class="callout-title" part="callout-title">${i}</div>` : c}
1951
+ <div part="callout-message">${t}</div>
1952
+ </div>`;
1953
+ }
1954
+ /**
1955
+ * Minimal markdown parser — handles the most common patterns.
1956
+ * Intentionally lightweight; does NOT pull in a full markdown library.
1957
+ */
1958
+ parseMarkdown(e) {
1959
+ let t = this.escapeHtml(e);
1960
+ return t = t.replace(/^#### (.+)$/gm, "<h4>$1</h4>"), t = t.replace(/^### (.+)$/gm, "<h3>$1</h3>"), t = t.replace(/^## (.+)$/gm, "<h2>$1</h2>"), t = t.replace(/^# (.+)$/gm, "<h1>$1</h1>"), t = t.replace(/^---$/gm, "<hr>"), t = t.replace(/```[\s\S]*?```/g, (a) => `<pre><code>${a.slice(3, -3).replace(/^\w*\n/, "")}</code></pre>`), t = t.replace(
1961
+ /^(\|.+\|)\n(\|[\s:|-]+\|)\n((?:\|.+\|\n?)+)/gm,
1962
+ (a, i, r, n) => {
1963
+ const s = (u) => u.split("|").slice(1, -1).map((m) => m.trim()), l = s(i), p = s(r).map((u) => u.startsWith(":") && u.endsWith(":") ? "center" : u.endsWith(":") ? "right" : "left"), d = n.trim().split(`
1964
+ `).map(s), g = l.map((u, m) => `<th scope="col" style="text-align:${p[m] ?? "left"}">${u}</th>`).join(""), f = d.map((u) => "<tr>" + u.map((m, v) => `<td style="text-align:${p[v] ?? "left"}">${m}</td>`).join("") + "</tr>").join("");
1965
+ return `<table><thead><tr>${g}</tr></thead><tbody>${f}</tbody></table>`;
1966
+ }
1967
+ ), t = t.replace(/`([^`]+)`/g, "<code>$1</code>"), t = t.replace(/\*\*\*(.+?)\*\*\*/g, "<strong><em>$1</em></strong>"), t = t.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>"), t = t.replace(/\*(.+?)\*/g, "<em>$1</em>"), t = t.replace(
1968
+ /\[([^\]]+)\]\(([^)]+)\)/g,
1969
+ (a, i, r) => `<a href="${this.sanitizeUrl(r)}" target="_blank" rel="noopener">${i}</a>`
1970
+ ), t = t.replace(/^&gt; (.+)$/gm, "<blockquote>$1</blockquote>"), t = t.replace(/^\d+\. (.+)$/gm, "<li data-ol>$1</li>"), t = t.replace(/(<li data-ol>.*<\/li>\n?)+/g, (a) => `<ol>${a.replace(/ data-ol/g, "")}</ol>`), t = t.replace(/^- (.+)$/gm, "<li>$1</li>"), t = t.replace(/(<li>.*<\/li>\n?)+/g, "<ul>$&</ul>"), t = t.replace(/\n\n+/g, "</p><p>"), !t.startsWith("<h") && !t.startsWith("<ul") && !t.startsWith("<ol") && !t.startsWith("<pre") && !t.startsWith("<blockquote") && !t.startsWith("<hr") && (t = `<p>${t}</p>`), t = t.replace(/<pre>[\s\S]*?<\/pre>/g, (a) => a.replace(/\n/g, "\0NL\0")), t = t.replace(/\n/g, "<br>"), t = t.replace(/\x00NL\x00/g, `
1971
+ `), t;
1972
+ }
1973
+ sanitizeUrl(e) {
1974
+ const t = e.replace(/[\s\u200B\u200C\u200D\uFEFF\u00AD\u200E\u200F]/g, "");
1975
+ return /^(javascript|data|vbscript):/i.test(t) ? "" : e;
1976
+ }
1977
+ escapeHtml(e) {
1978
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1979
+ }
1980
+ };
1981
+ W.styles = [b, y`
1982
+ :host {
1983
+ display: block;
1984
+ font-family: system-ui, -apple-system, sans-serif;
1985
+ container: u-content / inline-size;
1986
+ }
1987
+
1988
+ /* ── markdown ── */
1989
+ .markdown {
1990
+ font-size: 0.875rem;
1991
+ line-height: 1.6;
1992
+ color: var(--u-widget-text, #1a1a2e);
1993
+ }
1994
+
1995
+ .markdown p {
1996
+ margin: 0.5em 0;
1997
+ }
1998
+
1999
+ .markdown h1,
2000
+ .markdown h2,
2001
+ .markdown h3,
2002
+ .markdown h4 {
2003
+ margin: 0.75em 0 0.25em;
2004
+ font-weight: 600;
2005
+ color: var(--u-widget-text, #1a1a2e);
2006
+ }
2007
+
2008
+ .markdown h1 { font-size: 1.5rem; }
2009
+ .markdown h2 { font-size: 1.25rem; }
2010
+ .markdown h3 { font-size: 1.1rem; }
2011
+ .markdown h4 { font-size: 1rem; }
2012
+
2013
+ .markdown strong { font-weight: 600; }
2014
+ .markdown em { font-style: italic; }
2015
+
2016
+ .markdown code {
2017
+ background: var(--u-widget-surface, #f1f5f9);
2018
+ padding: 0.15em 0.4em;
2019
+ border-radius: 3px;
2020
+ font-size: 0.8125rem;
2021
+ font-family: 'SF Mono', 'Fira Code', monospace;
2022
+ }
2023
+
2024
+ .markdown pre {
2025
+ background: var(--u-widget-surface, #f1f5f9);
2026
+ padding: 12px;
2027
+ border-radius: 6px;
2028
+ overflow-x: auto;
2029
+ font-size: 0.8125rem;
2030
+ }
2031
+
2032
+ .markdown pre code {
2033
+ background: none;
2034
+ padding: 0;
2035
+ }
2036
+
2037
+ .markdown ul,
2038
+ .markdown ol {
2039
+ padding-left: 1.5em;
2040
+ margin: 0.5em 0;
2041
+ }
2042
+
2043
+ .markdown blockquote {
2044
+ border-left: 3px solid var(--u-widget-border, #e2e8f0);
2045
+ padding-left: 12px;
2046
+ margin: 0.5em 0;
2047
+ color: var(--u-widget-text-secondary, #64748b);
2048
+ }
2049
+
2050
+ .markdown a {
2051
+ color: var(--u-widget-primary, #4f46e5);
2052
+ text-decoration: none;
2053
+ }
2054
+
2055
+ .markdown a:hover {
2056
+ text-decoration: underline;
2057
+ }
2058
+
2059
+ .markdown table {
2060
+ width: 100%;
2061
+ border-collapse: collapse;
2062
+ margin: 0.5em 0;
2063
+ font-size: 0.8125rem;
2064
+ }
2065
+
2066
+ .markdown th,
2067
+ .markdown td {
2068
+ border: 1px solid var(--u-widget-border, #e2e8f0);
2069
+ padding: 6px 10px;
2070
+ }
2071
+
2072
+ .markdown th {
2073
+ background: var(--u-widget-surface, #f1f5f9);
2074
+ font-weight: 600;
2075
+ text-align: left;
2076
+ }
2077
+
2078
+ .markdown hr {
2079
+ border: none;
2080
+ border-top: 1px solid var(--u-widget-border, #e2e8f0);
2081
+ margin: 1em 0;
2082
+ }
2083
+
2084
+ /* ── image ── */
2085
+ .image-container {
2086
+ text-align: center;
2087
+ }
2088
+
2089
+ .image-container img {
2090
+ max-width: 100%;
2091
+ height: auto;
2092
+ border-radius: 6px;
2093
+ }
2094
+
2095
+ .image-caption {
2096
+ margin-top: 6px;
2097
+ font-size: 0.8125rem;
2098
+ color: var(--u-widget-text-secondary, #64748b);
2099
+ }
2100
+
2101
+ /* ── callout ── */
2102
+ .callout {
2103
+ padding: 12px 16px;
2104
+ border-radius: 6px;
2105
+ border-left: 4px solid;
2106
+ font-size: 0.875rem;
2107
+ line-height: 1.5;
2108
+ }
2109
+
2110
+ .callout-info {
2111
+ background: color-mix(in srgb, var(--u-widget-primary, #3b82f6) 12%, var(--u-widget-bg, #fff));
2112
+ border-left-color: var(--u-widget-primary, #3b82f6);
2113
+ color: var(--u-widget-text, #1a1a2e);
2114
+ }
2115
+
2116
+ .callout-warning {
2117
+ background: color-mix(in srgb, var(--u-widget-warning, #f59e0b) 12%, var(--u-widget-bg, #fff));
2118
+ border-left-color: var(--u-widget-warning, #f59e0b);
2119
+ color: var(--u-widget-text, #1a1a2e);
2120
+ }
2121
+
2122
+ .callout-error {
2123
+ background: color-mix(in srgb, var(--u-widget-negative, #ef4444) 12%, var(--u-widget-bg, #fff));
2124
+ border-left-color: var(--u-widget-negative, #ef4444);
2125
+ color: var(--u-widget-text, #1a1a2e);
2126
+ }
2127
+
2128
+ .callout-success {
2129
+ background: color-mix(in srgb, var(--u-widget-positive, #22c55e) 12%, var(--u-widget-bg, #fff));
2130
+ border-left-color: var(--u-widget-positive, #22c55e);
2131
+ color: var(--u-widget-text, #1a1a2e);
2132
+ }
2133
+
2134
+ .callout-title {
2135
+ font-weight: 600;
2136
+ margin-bottom: 4px;
2137
+ }
2138
+
2139
+ @container u-content (max-width: 20rem) {
2140
+ .markdown {
2141
+ font-size: 0.8125rem;
2142
+ }
2143
+
2144
+ .markdown h1 { font-size: 1.25rem; }
2145
+ .markdown h2 { font-size: 1.1rem; }
2146
+ .markdown h3 { font-size: 1rem; }
2147
+
2148
+ .callout {
2149
+ padding: 8px 12px;
2150
+ font-size: 0.8125rem;
2151
+ }
2152
+
2153
+ .image-caption {
2154
+ font-size: 0.75rem;
2155
+ }
2156
+ }
2157
+ `];
2158
+ ge([
2159
+ h({ type: Object })
2160
+ ], W.prototype, "spec", 2);
2161
+ W = ge([
2162
+ x("u-content")
2163
+ ], W);
2164
+ var Ve = Object.defineProperty, Ge = Object.getOwnPropertyDescriptor, fe = (e, t, a, i) => {
2165
+ for (var r = i > 1 ? void 0 : i ? Ge(t, a) : t, n = e.length - 1, s; n >= 0; n--)
2166
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
2167
+ return i && r && Ve(t, a, r), r;
2168
+ };
2169
+ let H = class extends w {
2170
+ constructor() {
2171
+ super(...arguments), this.spec = null;
2172
+ }
2173
+ render() {
2174
+ if (!this.spec) return c;
2175
+ const e = this._extractPairs();
2176
+ if (e.length === 0) return c;
2177
+ const t = this.spec.options ?? {}, a = String(t.layout ?? "vertical"), i = Number(t.columns ?? 2), r = a === "grid" ? `grid-template-columns: repeat(${i}, 1fr)` : "";
2178
+ return o`
2179
+ <div
2180
+ class=${`kv-${a === "grid" ? "grid" : a === "horizontal" ? "horizontal" : "vertical"}`}
2181
+ style=${r}
2182
+ part="kv"
2183
+ role="list"
2184
+ aria-label=${this.spec.title ?? "Key-value pairs"}
2185
+ >
2186
+ ${e.map(([n, s]) => o`
2187
+ <div class="kv-pair" part="kv-pair" role="listitem">
2188
+ <span class="kv-key" part="kv-key">${n}</span>
2189
+ <span class="kv-value" part="kv-value">${String(s)}</span>
2190
+ </div>
2191
+ `)}
2192
+ </div>
2193
+ `;
2194
+ }
2195
+ _extractPairs() {
2196
+ const e = this.spec?.data;
2197
+ return e ? Array.isArray(e) ? e.filter((t) => t != null && typeof t == "object" && "key" in t && "value" in t).map((t) => [String(t.key), t.value]) : typeof e == "object" ? Object.entries(e) : [] : [];
2198
+ }
2199
+ };
2200
+ H.styles = [b, y`
2201
+ :host {
2202
+ display: block;
2203
+ font-family: system-ui, -apple-system, sans-serif;
2204
+ container: u-kv / inline-size;
2205
+ }
2206
+
2207
+ .kv-vertical {
2208
+ display: grid;
2209
+ grid-template-columns: auto auto;
2210
+ gap: 8px 12px;
2211
+ justify-content: center;
2212
+ }
2213
+
2214
+ .kv-horizontal {
2215
+ display: flex;
2216
+ flex-wrap: wrap;
2217
+ gap: 8px 24px;
2218
+ }
2219
+
2220
+ .kv-grid {
2221
+ display: grid;
2222
+ gap: 8px 24px;
2223
+ }
2224
+
2225
+ .kv-pair {
2226
+ display: flex;
2227
+ gap: 8px;
2228
+ align-items: baseline;
2229
+ min-width: 0;
2230
+ }
2231
+
2232
+ .kv-vertical .kv-pair {
2233
+ display: contents;
2234
+ }
2235
+
2236
+ .kv-vertical .kv-key {
2237
+ text-align: right;
2238
+ }
2239
+
2240
+ .kv-vertical .kv-value {
2241
+ text-align: left;
2242
+ }
2243
+
2244
+ .kv-key {
2245
+ font-size: 0.8125rem;
2246
+ font-weight: 500;
2247
+ color: var(--u-widget-text-secondary, #64748b);
2248
+ flex-shrink: 0;
2249
+ }
2250
+
2251
+ .kv-value {
2252
+ font-size: 0.875rem;
2253
+ font-weight: 600;
2254
+ color: var(--u-widget-text, #1a1a2e);
2255
+ text-align: right;
2256
+ overflow: hidden;
2257
+ text-overflow: ellipsis;
2258
+ white-space: nowrap;
2259
+ }
2260
+
2261
+ .kv-horizontal .kv-pair {
2262
+ flex-direction: column;
2263
+ gap: 2px;
2264
+ }
2265
+
2266
+ .kv-horizontal .kv-value {
2267
+ text-align: left;
2268
+ }
2269
+
2270
+ .kv-grid .kv-pair {
2271
+ flex-direction: column;
2272
+ gap: 2px;
2273
+ }
2274
+
2275
+ .kv-grid .kv-value {
2276
+ text-align: left;
2277
+ }
2278
+
2279
+ @container u-kv (max-width: 20rem) {
2280
+ .kv-horizontal {
2281
+ flex-direction: column;
2282
+ gap: 8px;
2283
+ }
2284
+
2285
+ .kv-key {
2286
+ font-size: 0.75rem;
2287
+ }
2288
+
2289
+ .kv-value {
2290
+ font-size: 0.8125rem;
2291
+ }
2292
+ }
2293
+ `];
2294
+ fe([
2295
+ h({ type: Object })
2296
+ ], H.prototype, "spec", 2);
2297
+ H = fe([
2298
+ x("u-kv")
2299
+ ], H);
2300
+ var Je = Object.defineProperty, Qe = Object.getOwnPropertyDescriptor, V = (e, t, a, i) => {
2301
+ for (var r = i > 1 ? void 0 : i ? Qe(t, a) : t, n = e.length - 1, s; n >= 0; n--)
2302
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
2303
+ return i && r && Je(t, a, r), r;
2304
+ };
2305
+ const Ze = {
2306
+ javascript: ["//", ["/*", "*/"]],
2307
+ typescript: ["//", ["/*", "*/"]],
2308
+ python: ["#"],
2309
+ java: ["//", ["/*", "*/"]],
2310
+ csharp: ["//", ["/*", "*/"]],
2311
+ go: ["//", ["/*", "*/"]],
2312
+ rust: ["//", ["/*", "*/"]],
2313
+ sql: ["--", ["/*", "*/"]],
2314
+ bash: ["#"],
2315
+ css: [void 0, ["/*", "*/"]],
2316
+ html: [void 0, ["<!--", "-->"]]
2317
+ }, Xe = {
2318
+ javascript: "async await break case catch class const continue default delete do else export extends false finally for from function if import in instanceof let new null of return static super switch this throw true try typeof undefined var void while with yield",
2319
+ typescript: "abstract any as async await boolean break case catch class const continue declare default delete do else enum export extends false finally for from function if implements import in instanceof interface is keyof let namespace never new null number of override private protected public readonly return static string super switch this throw true try type typeof undefined var void while with yield",
2320
+ python: "False None True and as assert async await break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield",
2321
+ java: "abstract boolean break byte case catch char class continue default do double else enum extends false final finally float for if implements import instanceof int interface long new null package private protected public return short static super switch this throw throws true try void volatile while",
2322
+ csharp: "abstract as async await base bool break byte case catch char class const continue decimal default do double else enum false finally float for foreach if in int interface internal is lock long namespace new null object out override params private protected public readonly ref return sealed short static string struct switch this throw true try typeof var virtual void while yield",
2323
+ go: "break case chan const continue default defer else fallthrough false for func go goto if import interface map nil package range return select struct switch true type var",
2324
+ rust: "as async await break const continue crate dyn else enum extern false fn for if impl in let loop match mod move mut pub ref return self static struct super trait true type unsafe use where while",
2325
+ sql: "ALL ALTER AND AS ASC BETWEEN BY CASE CREATE DELETE DESC DISTINCT DROP ELSE END EXISTS FALSE FROM GROUP HAVING IF IN INDEX INSERT INTO IS JOIN LEFT LIKE LIMIT NOT NULL ON OR ORDER PRIMARY SELECT SET TABLE THEN TRUE UNION UPDATE VALUES WHERE",
2326
+ bash: "break case do done elif else esac fi for function if in local read return select then until while"
2327
+ }, Ye = {
2328
+ js: "javascript",
2329
+ ts: "typescript",
2330
+ py: "python",
2331
+ cs: "csharp",
2332
+ sh: "bash",
2333
+ shell: "bash",
2334
+ zsh: "bash",
2335
+ jsx: "javascript",
2336
+ tsx: "typescript",
2337
+ cpp: "java",
2338
+ c: "java",
2339
+ xml: "html",
2340
+ svg: "html",
2341
+ scss: "css",
2342
+ less: "css",
2343
+ jsonc: "json",
2344
+ psql: "sql",
2345
+ mysql: "sql"
2346
+ }, le = /* @__PURE__ */ new Map();
2347
+ function et(e) {
2348
+ let t = le.get(e);
2349
+ if (!t) {
2350
+ const a = Xe[e] || "";
2351
+ t = a ? new Set(a.split(" ")) : /* @__PURE__ */ new Set(), le.set(e, t);
2352
+ }
2353
+ return t;
2354
+ }
2355
+ function k(e) {
2356
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
2357
+ }
2358
+ function j(e, t) {
2359
+ const a = k(e);
2360
+ return a.includes(`
2361
+ `) ? a.split(`
2362
+ `).map((i) => `<span class="hl-${t}">${i}</span>`).join(`
2363
+ `) : `<span class="hl-${t}">${a}</span>`;
2364
+ }
2365
+ function he(e, t, a) {
2366
+ let i = t + 1;
2367
+ for (; i < e.length; ) {
2368
+ if (e[i] === "\\") {
2369
+ i += 2;
2370
+ continue;
2371
+ }
2372
+ if (e[i] === a) return i + 1;
2373
+ if (a !== "`" && e[i] === `
2374
+ `) return i;
2375
+ i++;
2376
+ }
2377
+ return e.length;
2378
+ }
2379
+ function tt(e, t) {
2380
+ if (!t) return k(e);
2381
+ const a = Ye[t] || t;
2382
+ if (a === "json") return rt(e);
2383
+ const i = et(a), r = Ze[a], n = r?.[0], s = r?.[1], l = a === "javascript" || a === "typescript";
2384
+ let p = "", d = 0;
2385
+ const g = e.length;
2386
+ for (; d < g; ) {
2387
+ if (s && e.startsWith(s[0], d)) {
2388
+ const u = e.indexOf(s[1], d + s[0].length), m = u === -1 ? e.slice(d) : e.slice(d, u + s[1].length);
2389
+ p += j(m, "c"), d += m.length;
2390
+ continue;
2391
+ }
2392
+ if (n && e.startsWith(n, d)) {
2393
+ const u = e.indexOf(`
2394
+ `, d), m = u === -1 ? e.slice(d) : e.slice(d, u);
2395
+ p += j(m, "c"), d += m.length;
2396
+ continue;
2397
+ }
2398
+ const f = e[d];
2399
+ if (f === '"' || f === "'" || f === "`" && l) {
2400
+ const u = he(e, d, f);
2401
+ p += j(e.slice(d, u), "s"), d = u;
2402
+ continue;
2403
+ }
2404
+ if (/\d/.test(f) && (d === 0 || !/[a-zA-Z_$]/.test(e[d - 1]))) {
2405
+ let u = d + 1;
2406
+ for (; u < g && /[0-9a-fA-FxXoObBeE._]/.test(e[u]); ) u++;
2407
+ p += j(e.slice(d, u), "n"), d = u;
2408
+ continue;
2409
+ }
2410
+ if (/[a-zA-Z_$]/.test(f)) {
2411
+ let u = d + 1;
2412
+ for (; u < g && /[a-zA-Z0-9_$]/.test(e[u]); ) u++;
2413
+ const m = e.slice(d, u);
2414
+ p += i.has(m) ? `<span class="hl-k">${k(m)}</span>` : k(m), d = u;
2415
+ continue;
2416
+ }
2417
+ if (a === "html" && f === "<" && d + 1 < g && /[a-zA-Z/!]/.test(e[d + 1])) {
2418
+ const u = e.indexOf(">", d);
2419
+ if (u !== -1) {
2420
+ p += `<span class="hl-k">${k(e.slice(d, u + 1))}</span>`, d = u + 1;
2421
+ continue;
2422
+ }
2423
+ }
2424
+ if (a === "css" && /[a-z-]/.test(f)) {
2425
+ let u = d + 1;
2426
+ for (; u < g && /[a-z-]/.test(e[u]); ) u++;
2427
+ const m = e.slice(d, u);
2428
+ e.slice(u).trimStart()[0] === ":" ? p += `<span class="hl-k">${k(m)}</span>` : p += k(m), d = u;
2429
+ continue;
2430
+ }
2431
+ p += k(f), d++;
2432
+ }
2433
+ return p;
2434
+ }
2435
+ function rt(e) {
2436
+ let t = "", a = 0;
2437
+ const i = e.length;
2438
+ for (; a < i; ) {
2439
+ const r = e[a];
2440
+ if (r === '"') {
2441
+ const s = he(e, a, '"'), l = e.slice(a, s), p = e.slice(s).trimStart();
2442
+ t += j(l, p[0] === ":" ? "k" : "s"), a = s;
2443
+ continue;
2444
+ }
2445
+ if (/[\d-]/.test(r) && (a === 0 || /[\s,:\[{]/.test(e[a - 1]))) {
2446
+ let s = a + 1;
2447
+ for (; s < i && /[0-9.eE+\-]/.test(e[s]); ) s++;
2448
+ t += j(e.slice(a, s), "n"), a = s;
2449
+ continue;
2450
+ }
2451
+ let n = !1;
2452
+ for (const s of ["true", "false", "null"])
2453
+ if (e.startsWith(s, a)) {
2454
+ t += `<span class="hl-k">${s}</span>`, a += s.length, n = !0;
2455
+ break;
2456
+ }
2457
+ n || (t += k(r), a++);
2458
+ }
2459
+ return t;
2460
+ }
2461
+ let O = class extends w {
2462
+ constructor() {
2463
+ super(...arguments), this.spec = null, this.theme = null, this._copied = !1;
2464
+ }
2465
+ render() {
2466
+ if (!this.spec) return c;
2467
+ const e = this.spec.data;
2468
+ if (!e) return c;
2469
+ const t = String(e.content ?? "");
2470
+ if (!t) return c;
2471
+ const a = String(e.language ?? "").toLowerCase(), i = this.spec.options ?? {}, r = i.lineNumbers !== !1, n = !!(i.wrap ?? !1), s = i.maxHeight ? String(i.maxHeight) : void 0, l = new Set(
2472
+ Array.isArray(i.highlight) ? i.highlight : []
2473
+ ), g = tt(t, a).split(`
2474
+ `).map((u, m) => {
2475
+ const v = m + 1, $ = l.has(v) ? " line-hl" : "", _ = r ? `<span class="line-no">${v}</span>` : "";
2476
+ return `<span class="line${$}">${_}${u || " "}</span>`;
2477
+ }).join(""), f = s ? `max-height: ${s}` : "";
2478
+ return o`
2479
+ <div class="code-block" part="code">
2480
+ <div class="code-header" part="code-header">
2481
+ <span class="code-lang">${a || "code"}</span>
2482
+ <button
2483
+ class="code-copy"
2484
+ part="code-copy"
2485
+ ?data-copied=${this._copied}
2486
+ @click=${this._copyCode}
2487
+ >${this._copied ? "Copied!" : "Copy"}</button>
2488
+ </div>
2489
+ <div class="code-body" part="code-body" style=${f}>
2490
+ <pre data-wrap=${String(n)}><code .innerHTML=${g}></code></pre>
2491
+ </div>
2492
+ </div>
2493
+ `;
2494
+ }
2495
+ async _copyCode() {
2496
+ const e = this.spec?.data, t = String(e?.content ?? "");
2497
+ if (t) {
2498
+ try {
2499
+ await navigator.clipboard.writeText(t);
2500
+ } catch {
2501
+ }
2502
+ this._copied = !0, setTimeout(() => {
2503
+ this._copied = !1;
2504
+ }, 2e3);
2505
+ }
2506
+ }
2507
+ };
2508
+ O.styles = [b, y`
2509
+ :host {
2510
+ display: block;
2511
+ font-family: system-ui, -apple-system, sans-serif;
2512
+ container: u-code / inline-size;
2513
+ }
2514
+
2515
+ .code-block {
2516
+ border: 1px solid var(--u-widget-border, #e2e8f0);
2517
+ border-radius: 6px;
2518
+ overflow: hidden;
2519
+ }
2520
+
2521
+ .code-header {
2522
+ display: flex;
2523
+ align-items: center;
2524
+ justify-content: space-between;
2525
+ padding: 6px 12px;
2526
+ background: var(--u-widget-surface, #f1f5f9);
2527
+ border-bottom: 1px solid var(--u-widget-border, #e2e8f0);
2528
+ }
2529
+
2530
+ .code-lang {
2531
+ font-size: 0.6875rem;
2532
+ font-weight: 600;
2533
+ color: var(--u-widget-text-secondary, #64748b);
2534
+ text-transform: uppercase;
2535
+ letter-spacing: 0.05em;
2536
+ }
2537
+
2538
+ .code-copy {
2539
+ padding: 2px 10px;
2540
+ border-radius: 4px;
2541
+ border: 1px solid var(--u-widget-border, #e2e8f0);
2542
+ background: var(--u-widget-bg, #fff);
2543
+ color: var(--u-widget-text-secondary, #64748b);
2544
+ cursor: pointer;
2545
+ font-size: 0.6875rem;
2546
+ font-family: inherit;
2547
+ transition: all 0.15s;
2548
+ }
2549
+ .code-copy:hover {
2550
+ background: var(--u-widget-bg, #fff);
2551
+ color: var(--u-widget-text, #1a1a2e);
2552
+ }
2553
+ .code-copy[data-copied] {
2554
+ color: var(--u-widget-positive, #16a34a);
2555
+ border-color: var(--u-widget-positive, #16a34a);
2556
+ }
2557
+
2558
+ .code-body {
2559
+ overflow: auto;
2560
+ background: var(--u-widget-bg, #fff);
2561
+ }
2562
+ :host([theme="dark"]) .code-body { background: #1e1e2e; }
2563
+
2564
+ pre {
2565
+ margin: 0;
2566
+ padding: 12px;
2567
+ font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Source Code Pro', Consolas, Monaco, monospace;
2568
+ font-size: 0.8125rem;
2569
+ line-height: 1.5;
2570
+ tab-size: 2;
2571
+ white-space: pre;
2572
+ }
2573
+ pre[data-wrap="true"] { white-space: pre-wrap; word-break: break-all; }
2574
+
2575
+ .line { display: block; }
2576
+
2577
+ .line-no {
2578
+ display: inline-block;
2579
+ width: 3ch;
2580
+ text-align: right;
2581
+ margin-right: 1.5ch;
2582
+ color: var(--u-widget-text-secondary, #94a3b8);
2583
+ user-select: none;
2584
+ opacity: 0.5;
2585
+ }
2586
+
2587
+ .line-hl {
2588
+ background: rgba(79, 70, 229, 0.08);
2589
+ margin: 0 -12px;
2590
+ padding: 0 12px;
2591
+ }
2592
+ :host([theme="dark"]) .line-hl { background: rgba(79, 70, 229, 0.15); }
2593
+
2594
+ /* Syntax token colors */
2595
+ .hl-k { color: #8b5cf6; } /* keyword — purple */
2596
+ .hl-s { color: #059669; } /* string — green */
2597
+ .hl-c { color: #94a3b8; font-style: italic; } /* comment — gray */
2598
+ .hl-n { color: #d97706; } /* number — amber */
2599
+
2600
+ :host([theme="dark"]) .hl-k { color: #a78bfa; }
2601
+ :host([theme="dark"]) .hl-s { color: #34d399; }
2602
+ :host([theme="dark"]) .hl-c { color: #64748b; }
2603
+ :host([theme="dark"]) .hl-n { color: #fbbf24; }
2604
+
2605
+ @container u-code (max-width: 20rem) {
2606
+ pre { font-size: 0.75rem; padding: 8px; }
2607
+ .code-header { padding: 4px 8px; }
2608
+ .line-no { width: 2.5ch; margin-right: 1ch; }
2609
+ }
2610
+ `];
2611
+ V([
2612
+ h({ type: Object })
2613
+ ], O.prototype, "spec", 2);
2614
+ V([
2615
+ h({ type: String, reflect: !0 })
2616
+ ], O.prototype, "theme", 2);
2617
+ V([
2618
+ S()
2619
+ ], O.prototype, "_copied", 2);
2620
+ O = V([
2621
+ x("u-code")
2622
+ ], O);
2623
+ var at = Object.defineProperty, it = Object.getOwnPropertyDescriptor, X = (e, t, a, i) => {
2624
+ for (var r = i > 1 ? void 0 : i ? it(t, a) : t, n = e.length - 1, s; n >= 0; n--)
2625
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
2626
+ return i && r && at(t, a, r), r;
2627
+ };
2628
+ let N = class extends w {
2629
+ constructor() {
2630
+ super(...arguments), this.spec = null, this.theme = null;
2631
+ }
2632
+ render() {
2633
+ if (!this.spec) return c;
2634
+ const e = this._extractItems();
2635
+ if (e.length === 0) return c;
2636
+ const t = this.spec.options ?? {}, a = !!(t.compact ?? !1), i = t.numbered !== !1;
2637
+ return o`
2638
+ <div class="citations" part="citations" ?data-compact=${a} role="list" aria-label=${this.spec.title ?? "Citations"}>
2639
+ ${e.map((r, n) => this._renderItem(r, n, i))}
2640
+ </div>
2641
+ `;
2642
+ }
2643
+ _renderItem(e, t, a) {
2644
+ const i = !!e.url, r = e.url ? this._extractDomain(e.url) : void 0;
2645
+ return o`
2646
+ <div
2647
+ class="cite-item"
2648
+ part="cite-item"
2649
+ role="listitem"
2650
+ ?data-link=${i}
2651
+ @click=${i ? () => this._handleClick(e) : void 0}
2652
+ >
2653
+ ${a ? o`<span class="cite-num" part="cite-num">${t + 1}</span>` : c}
2654
+ <div class="cite-body">
2655
+ <div class="cite-title" part="cite-title">${e.title}</div>
2656
+ ${r ? o`<div class="cite-url" part="cite-url">${r}</div>` : c}
2657
+ ${e.snippet ? o`<div class="cite-snippet" part="cite-snippet">${e.snippet}</div>` : c}
2658
+ ${e.source ? o`<div class="cite-source" part="cite-source">${e.source}</div>` : c}
2659
+ </div>
2660
+ </div>
2661
+ `;
2662
+ }
2663
+ _handleClick(e) {
2664
+ if (!e.url) return;
2665
+ const t = e.url.replace(/[\s\u200B-\u200F\uFEFF\u00AD]/g, "");
2666
+ /^(javascript|data|vbscript):/i.test(t) || (this.dispatchEvent(
2667
+ new CustomEvent("u-widget-internal", {
2668
+ detail: {
2669
+ type: "action",
2670
+ widget: "citation",
2671
+ id: this.spec?.id,
2672
+ action: "navigate",
2673
+ data: { url: t, title: e.title }
2674
+ },
2675
+ bubbles: !0,
2676
+ composed: !0
2677
+ })
2678
+ ), window.open(t, "_blank", "noopener"));
2679
+ }
2680
+ _extractDomain(e) {
2681
+ try {
2682
+ return new URL(e).hostname;
2683
+ } catch {
2684
+ return e;
2685
+ }
2686
+ }
2687
+ _extractItems() {
2688
+ const e = this.spec?.data;
2689
+ if (!e) return [];
2690
+ if (Array.isArray(e))
2691
+ return e.filter(
2692
+ (t) => t != null && typeof t == "object" && "title" in t
2693
+ ).map((t) => ({
2694
+ title: String(t.title ?? ""),
2695
+ url: t.url ? String(t.url) : void 0,
2696
+ snippet: t.snippet ? String(t.snippet) : void 0,
2697
+ source: t.source ? String(t.source) : void 0
2698
+ }));
2699
+ if (typeof e == "object" && "title" in e) {
2700
+ const t = e;
2701
+ return [{
2702
+ title: String(t.title ?? ""),
2703
+ url: t.url ? String(t.url) : void 0,
2704
+ snippet: t.snippet ? String(t.snippet) : void 0,
2705
+ source: t.source ? String(t.source) : void 0
2706
+ }];
2707
+ }
2708
+ return [];
2709
+ }
2710
+ };
2711
+ N.styles = [b, y`
2712
+ :host {
2713
+ display: block;
2714
+ font-family: system-ui, -apple-system, sans-serif;
2715
+ container: u-citation / inline-size;
2716
+ }
2717
+
2718
+ .citations {
2719
+ display: flex;
2720
+ flex-direction: column;
2721
+ gap: 8px;
2722
+ }
2723
+
2724
+ .cite-item {
2725
+ display: flex;
2726
+ gap: 10px;
2727
+ padding: 10px 14px;
2728
+ border-radius: 6px;
2729
+ border: 1px solid var(--u-widget-border, #e2e8f0);
2730
+ background: var(--u-widget-bg, #fff);
2731
+ cursor: default;
2732
+ transition: border-color 0.15s;
2733
+ }
2734
+ .cite-item[data-link] { cursor: pointer; }
2735
+ .cite-item[data-link]:hover {
2736
+ border-color: var(--u-widget-primary, #4f46e5);
2737
+ }
2738
+
2739
+ .cite-num {
2740
+ flex-shrink: 0;
2741
+ width: 22px;
2742
+ height: 22px;
2743
+ border-radius: 4px;
2744
+ background: var(--u-widget-surface, #f1f5f9);
2745
+ font-size: 0.6875rem;
2746
+ font-weight: 700;
2747
+ display: flex;
2748
+ align-items: center;
2749
+ justify-content: center;
2750
+ color: var(--u-widget-text-secondary, #64748b);
2751
+ }
2752
+
2753
+ .cite-body {
2754
+ flex: 1;
2755
+ min-width: 0;
2756
+ }
2757
+
2758
+ .cite-title {
2759
+ font-size: 0.875rem;
2760
+ font-weight: 600;
2761
+ color: var(--u-widget-text, #1a1a2e);
2762
+ overflow: hidden;
2763
+ text-overflow: ellipsis;
2764
+ white-space: nowrap;
2765
+ }
2766
+ .cite-item[data-link] .cite-title {
2767
+ color: var(--u-widget-primary, #4f46e5);
2768
+ }
2769
+
2770
+ .cite-url {
2771
+ font-size: 0.6875rem;
2772
+ color: var(--u-widget-text-secondary, #94a3b8);
2773
+ overflow: hidden;
2774
+ text-overflow: ellipsis;
2775
+ white-space: nowrap;
2776
+ margin-top: 1px;
2777
+ }
2778
+
2779
+ .cite-snippet {
2780
+ font-size: 0.8125rem;
2781
+ color: var(--u-widget-text-secondary, #64748b);
2782
+ margin-top: 4px;
2783
+ line-height: 1.4;
2784
+ display: -webkit-box;
2785
+ -webkit-line-clamp: 2;
2786
+ -webkit-box-orient: vertical;
2787
+ overflow: hidden;
2788
+ }
2789
+
2790
+ .cite-source {
2791
+ font-size: 0.6875rem;
2792
+ color: var(--u-widget-text-secondary, #94a3b8);
2793
+ margin-top: 4px;
2794
+ }
2795
+
2796
+ /* Compact mode */
2797
+ .citations[data-compact] .cite-item {
2798
+ padding: 6px 10px;
2799
+ }
2800
+ .citations[data-compact] .cite-snippet,
2801
+ .citations[data-compact] .cite-source { display: none; }
2802
+
2803
+ @container u-citation (max-width: 20rem) {
2804
+ .cite-title { font-size: 0.8125rem; }
2805
+ .cite-snippet { font-size: 0.75rem; }
2806
+ }
2807
+ `];
2808
+ X([
2809
+ h({ type: Object })
2810
+ ], N.prototype, "spec", 2);
2811
+ X([
2812
+ h({ type: String, reflect: !0 })
2813
+ ], N.prototype, "theme", 2);
2814
+ N = X([
2815
+ x("u-citation")
2816
+ ], N);
2817
+ var st = Object.defineProperty, nt = Object.getOwnPropertyDescriptor, Y = (e, t, a, i) => {
2818
+ for (var r = i > 1 ? void 0 : i ? nt(t, a) : t, n = e.length - 1, s; n >= 0; n--)
2819
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
2820
+ return i && r && st(t, a, r), r;
2821
+ };
2822
+ const ot = /* @__PURE__ */ new Set(["info", "success", "warning", "error", "neutral"]), lt = {
2823
+ info: "●",
2824
+ // ●
2825
+ success: "✓",
2826
+ // ✓
2827
+ warning: "▲",
2828
+ // ▲
2829
+ error: "✕",
2830
+ // ✕
2831
+ neutral: "○"
2832
+ // ○
2833
+ };
2834
+ let T = class extends w {
2835
+ constructor() {
2836
+ super(...arguments), this.spec = null, this.theme = null;
2837
+ }
2838
+ render() {
2839
+ if (!this.spec) return c;
2840
+ const e = this._extractItems();
2841
+ return e.length === 0 ? c : o`
2842
+ <div class="status-list" part="status" role="list" aria-label=${this.spec.title ?? "Status"}>
2843
+ ${e.map((t) => o`
2844
+ <div class="status-item" part="status-item" role="listitem" data-level=${t.level}>
2845
+ <span class="status-icon" part="status-icon" aria-hidden="true">${lt[t.level]}</span>
2846
+ <span class="status-label" part="status-label">${t.label}</span>
2847
+ <span class="status-value" part="status-value">${t.value}</span>
2848
+ </div>
2849
+ `)}
2850
+ </div>
2851
+ `;
2852
+ }
2853
+ _extractItems() {
2854
+ const e = this.spec?.data;
2855
+ if (!e) return [];
2856
+ if (Array.isArray(e))
2857
+ return e.filter(
2858
+ (t) => t != null && typeof t == "object" && "label" in t && "value" in t
2859
+ ).map((t) => ({
2860
+ label: String(t.label),
2861
+ value: String(t.value),
2862
+ level: this._resolveLevel(t.level)
2863
+ }));
2864
+ if (typeof e == "object" && "label" in e && "value" in e) {
2865
+ const t = e;
2866
+ return [{
2867
+ label: String(t.label),
2868
+ value: String(t.value),
2869
+ level: this._resolveLevel(t.level)
2870
+ }];
2871
+ }
2872
+ return [];
2873
+ }
2874
+ _resolveLevel(e) {
2875
+ const t = String(e ?? "info");
2876
+ return ot.has(t) ? t : "info";
2877
+ }
2878
+ };
2879
+ T.styles = [b, y`
2880
+ :host {
2881
+ display: block;
2882
+ font-family: system-ui, -apple-system, sans-serif;
2883
+ container: u-status / inline-size;
2884
+ }
2885
+
2886
+ .status-list {
2887
+ display: flex;
2888
+ flex-wrap: wrap;
2889
+ gap: 12px 24px;
2890
+ }
2891
+
2892
+ .status-item {
2893
+ display: flex;
2894
+ align-items: center;
2895
+ gap: 6px;
2896
+ font-size: 0.875rem;
2897
+ }
2898
+
2899
+ .status-icon {
2900
+ font-size: 0.75rem;
2901
+ flex-shrink: 0;
2902
+ }
2903
+
2904
+ .status-label {
2905
+ color: var(--u-widget-text-secondary, #64748b);
2906
+ font-weight: 500;
2907
+ }
2908
+
2909
+ .status-label::after {
2910
+ content: ':';
2911
+ }
2912
+
2913
+ .status-value {
2914
+ font-weight: 600;
2915
+ }
2916
+
2917
+ /* Level colors */
2918
+ [data-level="info"] .status-icon,
2919
+ [data-level="info"] .status-value {
2920
+ color: var(--u-widget-primary, #3b82f6);
2921
+ }
2922
+ [data-level="success"] .status-icon,
2923
+ [data-level="success"] .status-value {
2924
+ color: var(--u-widget-positive, #16a34a);
2925
+ }
2926
+ [data-level="warning"] .status-icon,
2927
+ [data-level="warning"] .status-value {
2928
+ color: var(--u-widget-warning, #f59e0b);
2929
+ }
2930
+ [data-level="error"] .status-icon,
2931
+ [data-level="error"] .status-value {
2932
+ color: var(--u-widget-negative, #dc2626);
2933
+ }
2934
+ [data-level="neutral"] .status-icon,
2935
+ [data-level="neutral"] .status-value {
2936
+ color: var(--u-widget-text-secondary, #64748b);
2937
+ }
2938
+
2939
+ @container u-status (max-width: 20rem) {
2940
+ .status-list { gap: 8px 16px; }
2941
+ .status-item { font-size: 0.8125rem; }
2942
+ }
2943
+ `];
2944
+ Y([
2945
+ h({ type: Object })
2946
+ ], T.prototype, "spec", 2);
2947
+ Y([
2948
+ h({ type: String, reflect: !0 })
2949
+ ], T.prototype, "theme", 2);
2950
+ T = Y([
2951
+ x("u-status")
2952
+ ], T);
2953
+ var ct = Object.defineProperty, dt = Object.getOwnPropertyDescriptor, ee = (e, t, a, i) => {
2954
+ for (var r = i > 1 ? void 0 : i ? dt(t, a) : t, n = e.length - 1, s; n >= 0; n--)
2955
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
2956
+ return i && r && ct(t, a, r), r;
2957
+ };
2958
+ const pt = /* @__PURE__ */ new Set(["done", "active", "pending", "error"]);
2959
+ function ce(e, t) {
2960
+ if (t) return o`<span class="step-icon-text">${t}</span>`;
2961
+ switch (e) {
2962
+ case "done":
2963
+ return o`<svg class="step-svg" viewBox="0 0 16 16" fill="currentColor"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.75.75 0 1 1 1.06-1.06L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>`;
2964
+ case "active":
2965
+ return o`<svg class="step-svg" viewBox="0 0 16 16" fill="currentColor"><circle cx="8" cy="8" r="5"/></svg>`;
2966
+ case "pending":
2967
+ return o`<svg class="step-svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="5"/></svg>`;
2968
+ case "error":
2969
+ return o`<svg class="step-svg" viewBox="0 0 16 16" fill="currentColor"><path d="M4.47 4.47a.75.75 0 0 1 1.06 0L8 6.94l2.47-2.47a.75.75 0 1 1 1.06 1.06L9.06 8l2.47 2.47a.75.75 0 1 1-1.06 1.06L8 9.06l-2.47 2.47a.75.75 0 0 1-1.06-1.06L6.94 8 4.47 5.53a.75.75 0 0 1 0-1.06Z"/></svg>`;
2970
+ }
2971
+ }
2972
+ let F = class extends w {
2973
+ constructor() {
2974
+ super(...arguments), this.spec = null, this.theme = null;
2975
+ }
2976
+ render() {
2977
+ if (!this.spec) return c;
2978
+ const e = this._extractItems();
2979
+ if (e.length === 0) return c;
2980
+ const t = this.spec.options ?? {}, a = String(t.layout ?? "vertical"), i = !!(t.compact ?? !1);
2981
+ return a === "horizontal" ? this._renderHorizontal(e, i) : this._renderVertical(e, i);
2982
+ }
2983
+ _renderVertical(e, t) {
2984
+ return o`
2985
+ <div class="steps-vertical" part="steps" ?data-compact=${t}
2986
+ role="list" aria-label=${this.spec?.title ?? "Steps"}>
2987
+ ${e.map((a) => o`
2988
+ <div class="step-v" part="step" role="listitem" data-status=${a.status}>
2989
+ <div class="step-track">
2990
+ <span class="step-icon" part="step-icon" aria-hidden="true">${ce(a.status, a.icon)}</span>
2991
+ <div class="step-line"></div>
2992
+ </div>
2993
+ <div class="step-body">
2994
+ <div class="step-label" part="step-label">${a.label}</div>
2995
+ ${a.description ? o`<div class="step-desc" part="step-desc">${a.description}</div>` : c}
2996
+ </div>
2997
+ </div>
2998
+ `)}
2999
+ </div>
3000
+ `;
3001
+ }
3002
+ _renderHorizontal(e, t) {
3003
+ return o`
3004
+ <div class="steps-horizontal" part="steps" ?data-compact=${t}
3005
+ role="list" aria-label=${this.spec?.title ?? "Steps"}>
3006
+ ${e.map((a, i) => {
3007
+ const r = i > 0 && e[i - 1].status === "done", n = a.status === "done";
3008
+ return o`
3009
+ <div class="step-h" part="step" role="listitem" data-status=${a.status}>
3010
+ <div class="step-h-top">
3011
+ <div class="step-h-line" ?data-done=${r}></div>
3012
+ <span class="step-icon" part="step-icon" aria-hidden="true">${ce(a.status, a.icon)}</span>
3013
+ <div class="step-h-line" ?data-done=${n}></div>
3014
+ </div>
3015
+ <div class="step-label" part="step-label">${a.label}</div>
3016
+ </div>
3017
+ `;
3018
+ })}
3019
+ </div>
3020
+ `;
3021
+ }
3022
+ _extractItems() {
3023
+ const e = this.spec?.data;
3024
+ return !e || !Array.isArray(e) ? [] : e.filter(
3025
+ (t) => t != null && typeof t == "object" && "label" in t
3026
+ ).map((t) => ({
3027
+ label: String(t.label),
3028
+ status: this._resolveStatus(t.status),
3029
+ description: t.description ? String(t.description) : void 0,
3030
+ icon: t.icon ? String(t.icon) : void 0
3031
+ }));
3032
+ }
3033
+ _resolveStatus(e) {
3034
+ const t = String(e ?? "pending");
3035
+ return pt.has(t) ? t : "pending";
3036
+ }
3037
+ };
3038
+ F.styles = [b, y`
3039
+ :host {
3040
+ display: block;
3041
+ font-family: system-ui, -apple-system, sans-serif;
3042
+ container: u-steps / inline-size;
3043
+ }
3044
+
3045
+ /* ── Vertical Layout ── */
3046
+ .steps-vertical {
3047
+ display: flex;
3048
+ flex-direction: column;
3049
+ gap: 0;
3050
+ }
3051
+
3052
+ .step-v {
3053
+ display: flex;
3054
+ gap: 12px;
3055
+ min-height: 48px;
3056
+ }
3057
+
3058
+ .step-v:last-child { min-height: auto; }
3059
+
3060
+ .step-track {
3061
+ display: flex;
3062
+ flex-direction: column;
3063
+ align-items: center;
3064
+ width: 24px;
3065
+ flex-shrink: 0;
3066
+ }
3067
+
3068
+ .step-icon {
3069
+ width: 24px;
3070
+ height: 24px;
3071
+ border-radius: 50%;
3072
+ display: flex;
3073
+ align-items: center;
3074
+ justify-content: center;
3075
+ font-size: 0.75rem;
3076
+ font-weight: 700;
3077
+ flex-shrink: 0;
3078
+ }
3079
+
3080
+ .step-svg { width: 14px; height: 14px; }
3081
+ .step-icon-text { font-size: 0.75rem; line-height: 1; }
3082
+
3083
+ .step-line {
3084
+ width: 2px;
3085
+ flex: 1;
3086
+ min-height: 12px;
3087
+ background: var(--u-widget-border, #e2e8f0);
3088
+ }
3089
+
3090
+ [data-status="pending"] .step-line {
3091
+ background: repeating-linear-gradient(
3092
+ to bottom,
3093
+ var(--u-widget-border, #e2e8f0) 0px,
3094
+ var(--u-widget-border, #e2e8f0) 3px,
3095
+ transparent 3px,
3096
+ transparent 6px
3097
+ );
3098
+ }
3099
+
3100
+ .step-v:last-child .step-line { display: none; }
3101
+
3102
+ .step-body {
3103
+ padding-bottom: 12px;
3104
+ flex: 1;
3105
+ min-width: 0;
3106
+ }
3107
+
3108
+ .step-v:last-child .step-body { padding-bottom: 0; }
3109
+
3110
+ .step-label {
3111
+ font-size: 0.875rem;
3112
+ font-weight: 500;
3113
+ line-height: 24px;
3114
+ }
3115
+
3116
+ .step-desc {
3117
+ font-size: 0.8125rem;
3118
+ color: var(--u-widget-text-secondary, #64748b);
3119
+ margin-top: 2px;
3120
+ line-height: 1.4;
3121
+ }
3122
+
3123
+ /* ── Horizontal Layout ── */
3124
+ .steps-horizontal {
3125
+ display: flex;
3126
+ align-items: flex-start;
3127
+ }
3128
+
3129
+ .step-h {
3130
+ display: flex;
3131
+ flex-direction: column;
3132
+ align-items: center;
3133
+ flex: 1;
3134
+ min-width: 0;
3135
+ position: relative;
3136
+ }
3137
+
3138
+ .step-h-top {
3139
+ display: flex;
3140
+ align-items: center;
3141
+ width: 100%;
3142
+ }
3143
+
3144
+ .step-h-line {
3145
+ flex: 1;
3146
+ height: 2px;
3147
+ background: var(--u-widget-border, #e2e8f0);
3148
+ }
3149
+
3150
+ .step-h:first-child .step-h-line:first-child,
3151
+ .step-h:last-child .step-h-line:last-child {
3152
+ visibility: hidden;
3153
+ }
3154
+
3155
+ .step-h-line[data-done] {
3156
+ background: var(--u-widget-positive, #16a34a);
3157
+ }
3158
+
3159
+ .step-h-line:not([data-done]) {
3160
+ background: repeating-linear-gradient(
3161
+ to right,
3162
+ var(--u-widget-border, #e2e8f0) 0px,
3163
+ var(--u-widget-border, #e2e8f0) 3px,
3164
+ transparent 3px,
3165
+ transparent 6px
3166
+ );
3167
+ }
3168
+
3169
+ .step-h .step-label {
3170
+ text-align: center;
3171
+ font-size: 0.75rem;
3172
+ line-height: 1.3;
3173
+ margin-top: 6px;
3174
+ max-width: 100%;
3175
+ overflow: hidden;
3176
+ text-overflow: ellipsis;
3177
+ white-space: nowrap;
3178
+ }
3179
+
3180
+ /* ── Status Colors ── */
3181
+ [data-status="done"] .step-icon {
3182
+ background: var(--u-widget-positive, #16a34a);
3183
+ color: white;
3184
+ }
3185
+ [data-status="done"] .step-label {
3186
+ color: var(--u-widget-text, #1a1a2e);
3187
+ }
3188
+ [data-status="done"] .step-line {
3189
+ background: var(--u-widget-positive, #16a34a);
3190
+ }
3191
+
3192
+ [data-status="active"] .step-icon {
3193
+ background: var(--u-widget-primary, #4f46e5);
3194
+ color: white;
3195
+ }
3196
+ [data-status="active"] .step-label {
3197
+ color: var(--u-widget-primary, #4f46e5);
3198
+ font-weight: 600;
3199
+ }
3200
+
3201
+ [data-status="pending"] .step-icon {
3202
+ background: var(--u-widget-surface, #f1f5f9);
3203
+ color: var(--u-widget-text-secondary, #64748b);
3204
+ }
3205
+ [data-status="pending"] .step-label {
3206
+ color: var(--u-widget-text-secondary, #64748b);
3207
+ }
3208
+
3209
+ [data-status="error"] .step-icon {
3210
+ background: var(--u-widget-negative, #dc2626);
3211
+ color: white;
3212
+ }
3213
+ [data-status="error"] .step-label {
3214
+ color: var(--u-widget-negative, #dc2626);
3215
+ }
3216
+
3217
+ /* ── Compact Mode ── */
3218
+ .steps-vertical[data-compact] .step-v { min-height: 36px; }
3219
+ .steps-vertical[data-compact] .step-desc { display: none; }
3220
+ .steps-vertical[data-compact] .step-body { padding-bottom: 6px; }
3221
+ .steps-vertical[data-compact] .step-line { min-height: 6px; }
3222
+
3223
+ .steps-horizontal[data-compact] .step-icon { width: 20px; height: 20px; font-size: 0.625rem; }
3224
+ .steps-horizontal[data-compact] .step-label { font-size: 0.6875rem; margin-top: 4px; }
3225
+
3226
+ @container u-steps (max-width: 20rem) {
3227
+ .step-label { font-size: 0.8125rem; }
3228
+ .step-desc { font-size: 0.75rem; }
3229
+
3230
+ /* horizontal → vertical auto-conversion on narrow containers */
3231
+ .steps-horizontal {
3232
+ flex-direction: column;
3233
+ align-items: stretch;
3234
+ }
3235
+
3236
+ .step-h {
3237
+ flex-direction: row;
3238
+ align-items: flex-start;
3239
+ gap: 12px;
3240
+ }
3241
+
3242
+ .step-h-top {
3243
+ flex-direction: column;
3244
+ width: 24px;
3245
+ flex-shrink: 0;
3246
+ align-items: center;
3247
+ }
3248
+
3249
+ .step-h-line {
3250
+ width: 2px;
3251
+ height: auto;
3252
+ flex: 1;
3253
+ min-height: 12px;
3254
+ }
3255
+
3256
+ .step-h:first-child .step-h-line:first-child,
3257
+ .step-h:last-child .step-h-line:last-child {
3258
+ display: none;
3259
+ }
3260
+
3261
+ .step-h .step-label {
3262
+ text-align: left;
3263
+ white-space: normal;
3264
+ margin-top: 0;
3265
+ line-height: 24px;
3266
+ font-size: 0.8125rem;
3267
+ }
3268
+ }
3269
+ `];
3270
+ ee([
3271
+ h({ type: Object })
3272
+ ], F.prototype, "spec", 2);
3273
+ ee([
3274
+ h({ type: String, reflect: !0 })
3275
+ ], F.prototype, "theme", 2);
3276
+ F = ee([
3277
+ x("u-steps")
3278
+ ], F);
3279
+ var ut = Object.defineProperty, gt = Object.getOwnPropertyDescriptor, G = (e, t, a, i) => {
3280
+ for (var r = i > 1 ? void 0 : i ? gt(t, a) : t, n = e.length - 1, s; n >= 0; n--)
3281
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
3282
+ return i && r && ut(t, a, r), r;
3283
+ };
3284
+ const ft = {
3285
+ star: ["☆", "★", "★"],
3286
+ // ☆, ★, ★
3287
+ heart: ["♡", "♥", "♥"],
3288
+ // ♡, ♥, ♥
3289
+ thumb: ["👍", "👍", "👍"]
3290
+ // 👍
3291
+ };
3292
+ let P = class extends w {
3293
+ constructor() {
3294
+ super(...arguments), this.spec = null, this.theme = null, this._hoverIdx = -1;
3295
+ }
3296
+ render() {
3297
+ if (!this.spec) return c;
3298
+ const e = this.spec.data ?? {}, t = this.spec.options ?? {}, a = typeof e.value == "number" ? e.value : 0, i = typeof t.max == "number" ? t.max : typeof e.max == "number" ? e.max : 5, r = !!(t.interactive ?? !1), n = this._resolveIcon(t.icon), s = typeof t.label == "string" ? t.label : void 0, l = typeof e.count == "number" ? e.count : void 0, p = ft[n], d = this._hoverIdx >= 0 ? this._hoverIdx + 1 : a;
3299
+ return o`
3300
+ <div class="rating" part="rating" role=${r ? "radiogroup" : "img"}
3301
+ aria-label=${this.spec.title ?? s ?? `Rating: ${a} out of ${i}`}>
3302
+ ${s ? o`<span class="rating-label" part="rating-label">${s}</span>` : c}
3303
+ <div class="rating-icons" part="rating-icons"
3304
+ @mouseleave=${r ? () => {
3305
+ this._hoverIdx = -1;
3306
+ } : void 0}>
3307
+ ${Array.from({ length: i }, (g, f) => this._renderIcon(f, d, p, n, r))}
3308
+ </div>
3309
+ ${!r && a > 0 ? o`<span class="rating-value" part="rating-value">${a}</span>` : c}
3310
+ ${l != null ? o`<span class="rating-count" part="rating-count">(${l})</span>` : c}
3311
+ </div>
3312
+ `;
3313
+ }
3314
+ _renderIcon(e, t, a, i, r) {
3315
+ const n = e + 1, s = r && this._hoverIdx >= 0 && n <= this._hoverIdx + 1;
3316
+ let l;
3317
+ s || n <= Math.floor(t) ? l = "full" : n === Math.ceil(t) && t % 1 >= 0.25 && t % 1 < 0.75 ? l = i === "thumb" ? t % 1 >= 0.5 ? "full" : "empty" : "half" : l = "empty";
3318
+ const p = l === "half" ? a[0] : l === "full" ? a[2] : a[0];
3319
+ return l === "half" ? o`
3320
+ <span class="rating-icon rating-icon-half"
3321
+ data-state="half" data-icon=${i}
3322
+ ?data-interactive=${r}
3323
+ ?data-preview=${s}
3324
+ role=${r ? "radio" : "presentation"}
3325
+ aria-label=${r ? `${n}` : c}
3326
+ @mouseenter=${r ? () => {
3327
+ this._hoverIdx = e;
3328
+ } : void 0}
3329
+ @click=${r ? () => this._select(n) : void 0}>
3330
+ <span aria-hidden="true">${a[0]}</span>
3331
+ <span class="half-overlay" aria-hidden="true">
3332
+ <span style="color: inherit">${a[2]}</span>
3333
+ </span>
3334
+ </span>
3335
+ ` : o`
3336
+ <span class="rating-icon"
3337
+ data-state=${l} data-icon=${i}
3338
+ ?data-interactive=${r}
3339
+ ?data-preview=${s}
3340
+ role=${r ? "radio" : "presentation"}
3341
+ aria-label=${r ? `${n}` : c}
3342
+ aria-checked=${r ? String(l === "full" && !s) : c}
3343
+ @mouseenter=${r ? () => {
3344
+ this._hoverIdx = e;
3345
+ } : void 0}
3346
+ @click=${r ? () => this._select(n) : void 0}>
3347
+ <span aria-hidden="true">${p}</span>
3348
+ </span>
3349
+ `;
3350
+ }
3351
+ _select(e) {
3352
+ this.dispatchEvent(
3353
+ new CustomEvent("u-widget-internal", {
3354
+ detail: {
3355
+ type: "submit",
3356
+ widget: "rating",
3357
+ id: this.spec?.id,
3358
+ data: { value: e }
3359
+ },
3360
+ bubbles: !0,
3361
+ composed: !0
3362
+ })
3363
+ );
3364
+ }
3365
+ _resolveIcon(e) {
3366
+ const t = String(e ?? "star");
3367
+ return t === "heart" || t === "thumb" ? t : "star";
3368
+ }
3369
+ };
3370
+ P.styles = [b, y`
3371
+ :host {
3372
+ display: block;
3373
+ font-family: system-ui, -apple-system, sans-serif;
3374
+ container: u-rating / inline-size;
3375
+ }
3376
+
3377
+ .rating {
3378
+ display: flex;
3379
+ align-items: center;
3380
+ gap: 8px;
3381
+ }
3382
+
3383
+ .rating-icons {
3384
+ display: flex;
3385
+ gap: 2px;
3386
+ }
3387
+
3388
+ .rating-icon {
3389
+ font-size: 1.25rem;
3390
+ cursor: default;
3391
+ user-select: none;
3392
+ transition: transform 0.1s;
3393
+ position: relative;
3394
+ line-height: 1;
3395
+ }
3396
+
3397
+ .rating-icon[data-interactive] {
3398
+ cursor: pointer;
3399
+ }
3400
+
3401
+ .rating-icon[data-interactive]:hover {
3402
+ transform: scale(1.2);
3403
+ }
3404
+
3405
+ /* Colors by state */
3406
+ .rating-icon[data-state="empty"] {
3407
+ color: var(--u-widget-text-secondary, #94a3b8);
3408
+ }
3409
+
3410
+ .rating-icon[data-state="full"] {
3411
+ color: #f59e0b;
3412
+ }
3413
+
3414
+ .rating-icon[data-state="half"] {
3415
+ color: #f59e0b;
3416
+ }
3417
+
3418
+ .rating-icon[data-icon="heart"][data-state="full"],
3419
+ .rating-icon[data-icon="heart"][data-state="half"] {
3420
+ color: #ef4444;
3421
+ }
3422
+
3423
+ .rating-icon[data-icon="thumb"][data-state="full"] {
3424
+ color: var(--u-widget-primary, #4f46e5);
3425
+ }
3426
+
3427
+ /* Half-star overlay */
3428
+ .rating-icon-half {
3429
+ position: relative;
3430
+ display: inline-block;
3431
+ }
3432
+
3433
+ .rating-icon-half .half-overlay {
3434
+ position: absolute;
3435
+ left: 0;
3436
+ top: 0;
3437
+ overflow: hidden;
3438
+ width: 50%;
3439
+ }
3440
+
3441
+ /* Value display */
3442
+ .rating-value {
3443
+ font-size: 0.875rem;
3444
+ font-weight: 600;
3445
+ color: var(--u-widget-text, #1a1a2e);
3446
+ }
3447
+
3448
+ .rating-count {
3449
+ font-size: 0.8125rem;
3450
+ color: var(--u-widget-text-secondary, #64748b);
3451
+ }
3452
+
3453
+ .rating-label {
3454
+ font-size: 0.8125rem;
3455
+ color: var(--u-widget-text-secondary, #64748b);
3456
+ }
3457
+
3458
+ /* Hover preview */
3459
+ .rating-icon[data-preview="true"] {
3460
+ color: #f59e0b;
3461
+ }
3462
+
3463
+ .rating-icon[data-icon="heart"][data-preview="true"] {
3464
+ color: #ef4444;
3465
+ }
3466
+
3467
+ .rating-icon[data-icon="thumb"][data-preview="true"] {
3468
+ color: var(--u-widget-primary, #4f46e5);
3469
+ }
3470
+
3471
+ @container u-rating (max-width: 20rem) {
3472
+ .rating-icon { font-size: 1rem; }
3473
+ .rating-value { font-size: 0.8125rem; }
3474
+ }
3475
+ `];
3476
+ G([
3477
+ h({ type: Object })
3478
+ ], P.prototype, "spec", 2);
3479
+ G([
3480
+ h({ type: String, reflect: !0 })
3481
+ ], P.prototype, "theme", 2);
3482
+ G([
3483
+ S()
3484
+ ], P.prototype, "_hoverIdx", 2);
3485
+ P = G([
3486
+ x("u-rating")
3487
+ ], P);
3488
+ var ht = Object.defineProperty, mt = Object.getOwnPropertyDescriptor, te = (e, t, a, i) => {
3489
+ for (var r = i > 1 ? void 0 : i ? mt(t, a) : t, n = e.length - 1, s; n >= 0; n--)
3490
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
3491
+ return i && r && ht(t, a, r), r;
3492
+ };
3493
+ let M = class extends w {
3494
+ constructor() {
3495
+ super(...arguments), this.spec = null, this.theme = null;
3496
+ }
3497
+ render() {
3498
+ if (!this.spec) return c;
3499
+ const e = this.spec.data;
3500
+ if (!e) return c;
3501
+ const t = String(e.src ?? ""), a = this._sanitizeUrl(t);
3502
+ if (!a) return c;
3503
+ const i = e.poster ? this._sanitizeUrl(String(e.poster)) : void 0, r = String(e.alt ?? ""), n = e.caption, s = this.spec.options ?? {}, l = s.controls !== !1, p = s.autoplay === !0, d = s.loop === !0, g = s.muted === !0 || p;
3504
+ return o`
3505
+ <div class="video-container" part="video">
3506
+ <video
3507
+ src=${a}
3508
+ poster=${i ?? c}
3509
+ aria-label=${r || c}
3510
+ ?controls=${l}
3511
+ ?autoplay=${p}
3512
+ ?loop=${d}
3513
+ ?muted=${g}
3514
+ playsinline
3515
+ preload="metadata"
3516
+ part="video-element"
3517
+ ></video>
3518
+ ${n ? o`<div class="video-caption" part="caption">${n}</div>` : c}
3519
+ </div>
3520
+ `;
3521
+ }
3522
+ _sanitizeUrl(e) {
3523
+ const t = e.replace(/[\s\u200B\u200C\u200D\uFEFF\u00AD\u200E\u200F]/g, "");
3524
+ return /^(javascript|data|vbscript):/i.test(t) ? "" : e;
3525
+ }
3526
+ };
3527
+ M.styles = [b, y`
3528
+ :host {
3529
+ display: block;
3530
+ font-family: system-ui, -apple-system, sans-serif;
3531
+ container: u-video / inline-size;
3532
+ }
3533
+
3534
+ .video-container {
3535
+ text-align: center;
3536
+ }
3537
+
3538
+ video {
3539
+ max-width: 100%;
3540
+ border-radius: 6px;
3541
+ background: #000;
3542
+ }
3543
+
3544
+ .video-caption {
3545
+ margin-top: 6px;
3546
+ font-size: 0.8125rem;
3547
+ color: var(--u-widget-text-secondary, #64748b);
3548
+ }
3549
+
3550
+ @container u-video (max-width: 20rem) {
3551
+ video {
3552
+ border-radius: 4px;
3553
+ }
3554
+
3555
+ .video-caption {
3556
+ font-size: 0.75rem;
3557
+ margin-top: 4px;
3558
+ }
3559
+ }
3560
+ `];
3561
+ te([
3562
+ h({ type: Object })
3563
+ ], M.prototype, "spec", 2);
3564
+ te([
3565
+ h({ type: String, reflect: !0 })
3566
+ ], M.prototype, "theme", 2);
3567
+ M = te([
3568
+ x("u-video")
3569
+ ], M);
3570
+ var vt = Object.defineProperty, bt = Object.getOwnPropertyDescriptor, re = (e, t, a, i) => {
3571
+ for (var r = i > 1 ? void 0 : i ? bt(t, a) : t, n = e.length - 1, s; n >= 0; n--)
3572
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
3573
+ return i && r && vt(t, a, r), r;
3574
+ };
3575
+ let U = class extends w {
3576
+ constructor() {
3577
+ super(...arguments), this.spec = null, this.theme = null;
3578
+ }
3579
+ render() {
3580
+ if (!this.spec) return c;
3581
+ const e = this.spec.data;
3582
+ if (!Array.isArray(e)) return c;
3583
+ const t = e.filter((p) => p && typeof p.src == "string" && p.src).map((p) => ({
3584
+ src: this._sanitizeUrl(String(p.src)),
3585
+ alt: p.alt ? String(p.alt) : void 0,
3586
+ caption: p.caption ? String(p.caption) : void 0
3587
+ })).filter((p) => p.src);
3588
+ if (t.length === 0) return c;
3589
+ const a = this.spec.options ?? {}, i = Number(a.columns) || 0, r = String(a.aspectRatio ?? "auto"), n = i > 0 ? `repeat(${i}, 1fr)` : "repeat(auto-fill, minmax(150px, 1fr))", s = r !== "auto" ? `aspect-ratio: ${r.replace(":", "/")};` : "", l = this.spec.title;
3590
+ return o`
3591
+ <div class="gallery-grid" part="gallery" role="list"
3592
+ aria-label=${l ?? "Gallery"}
3593
+ style="grid-template-columns: ${n}">
3594
+ ${t.map((p) => this._renderItem(p, s))}
3595
+ </div>
3596
+ `;
3597
+ }
3598
+ _renderItem(e, t) {
3599
+ return o`
3600
+ <figure class="gallery-item" part="gallery-item" role="listitem" style=${t || c}>
3601
+ <img
3602
+ src=${e.src}
3603
+ alt=${e.alt ?? ""}
3604
+ loading="lazy"
3605
+ part="gallery-image"
3606
+ />
3607
+ ${e.caption ? o`<figcaption class="gallery-caption" part="gallery-caption">${e.caption}</figcaption>` : c}
3608
+ </figure>
3609
+ `;
3610
+ }
3611
+ _sanitizeUrl(e) {
3612
+ const t = e.replace(/[\s\u200B\u200C\u200D\uFEFF\u00AD\u200E\u200F]/g, "");
3613
+ return /^(javascript|data|vbscript):/i.test(t) ? "" : e;
3614
+ }
3615
+ };
3616
+ U.styles = [b, y`
3617
+ :host {
3618
+ display: block;
3619
+ font-family: system-ui, -apple-system, sans-serif;
3620
+ container: u-gallery / inline-size;
3621
+ }
3622
+
3623
+ .gallery-grid {
3624
+ display: grid;
3625
+ gap: 8px;
3626
+ }
3627
+
3628
+ .gallery-item {
3629
+ overflow: hidden;
3630
+ border-radius: 6px;
3631
+ background: var(--u-widget-surface, #f1f5f9);
3632
+ }
3633
+
3634
+ .gallery-item img {
3635
+ display: block;
3636
+ width: 100%;
3637
+ height: 100%;
3638
+ object-fit: cover;
3639
+ }
3640
+
3641
+ .gallery-caption {
3642
+ padding: 4px 8px;
3643
+ font-size: 0.75rem;
3644
+ color: var(--u-widget-text-secondary, #64748b);
3645
+ background: var(--u-widget-surface, #f1f5f9);
3646
+ }
3647
+
3648
+ @container u-gallery (max-width: 20rem) {
3649
+ .gallery-grid {
3650
+ grid-template-columns: 1fr !important;
3651
+ }
3652
+ }
3653
+ `];
3654
+ re([
3655
+ h({ type: Object })
3656
+ ], U.prototype, "spec", 2);
3657
+ re([
3658
+ h({ type: String, reflect: !0 })
3659
+ ], U.prototype, "theme", 2);
3660
+ U = re([
3661
+ x("u-gallery")
3662
+ ], U);
3663
+ var yt = Object.defineProperty, wt = Object.getOwnPropertyDescriptor, J = (e, t, a, i) => {
3664
+ for (var r = i > 1 ? void 0 : i ? wt(t, a) : t, n = e.length - 1, s; n >= 0; n--)
3665
+ (s = e[n]) && (r = (i ? s(t, a, r) : s(r)) || r);
3666
+ return i && r && yt(t, a, r), r;
3667
+ };
3668
+ let E = class extends w {
3669
+ constructor() {
3670
+ super(...arguments), this.spec = null, this.theme = null, this.locale = null, this._handleInternalEvent = (e) => {
3671
+ e.stopPropagation(), this.dispatchEvent(
3672
+ new CustomEvent("u-widget-event", {
3673
+ detail: e.detail,
3674
+ bubbles: !0,
3675
+ composed: !0
3676
+ })
3677
+ );
3678
+ };
3679
+ }
3680
+ connectedCallback() {
3681
+ super.connectedCallback(), this.addEventListener("u-widget-internal", this._handleInternalEvent);
3682
+ }
3683
+ disconnectedCallback() {
3684
+ super.disconnectedCallback(), this.removeEventListener("u-widget-internal", this._handleInternalEvent);
3685
+ }
3686
+ render() {
3687
+ if (!this.spec)
3688
+ return o`<slot></slot>`;
3689
+ const e = Q(this.spec);
3690
+ if (!e.valid)
3691
+ return this.renderError(e.errors);
3692
+ const t = be(this.spec);
3693
+ return this.renderWidget(t);
3694
+ }
3695
+ renderWidget(e) {
3696
+ const t = e.widget, a = e.mapping ?? ve(t, e.data);
3697
+ let i = a ? { ...e, mapping: a } : e;
3698
+ this.locale && !i.options?.locale && (i = {
3699
+ ...i,
3700
+ options: { ...i.options, locale: this.locale }
3701
+ });
3702
+ const r = this.theme, s = t === "form" || t === "confirm" || t === "actions" ? [] : i.actions ?? [];
3703
+ let l;
3704
+ switch (t) {
3705
+ case "metric":
3706
+ case "stat-group":
3707
+ l = o`<u-metric .spec=${i} theme=${r ?? c}></u-metric>`;
3708
+ break;
3709
+ case "gauge":
3710
+ case "progress":
3711
+ l = o`<u-gauge .spec=${i} theme=${r ?? c}></u-gauge>`;
3712
+ break;
3713
+ case "table":
3714
+ case "list":
3715
+ l = o`<u-table .spec=${i} theme=${r ?? c}></u-table>`;
3716
+ break;
3717
+ case "form":
3718
+ case "confirm":
3719
+ l = o`<u-form .spec=${i} theme=${r ?? c}></u-form>`;
3720
+ break;
3721
+ case "compose":
3722
+ l = o`<u-compose .spec=${i} theme=${r ?? c}></u-compose>`;
3723
+ break;
3724
+ case "markdown":
3725
+ case "image":
3726
+ case "callout":
3727
+ l = o`<u-content .spec=${i} theme=${r ?? c}></u-content>`;
3728
+ break;
3729
+ case "kv":
3730
+ l = o`<u-kv .spec=${i} theme=${r ?? c}></u-kv>`;
3731
+ break;
3732
+ case "code":
3733
+ l = o`<u-code .spec=${i} theme=${r ?? c}></u-code>`;
3734
+ break;
3735
+ case "citation":
3736
+ l = o`<u-citation .spec=${i} theme=${r ?? c}></u-citation>`;
3737
+ break;
3738
+ case "status":
3739
+ l = o`<u-status .spec=${i} theme=${r ?? c}></u-status>`;
3740
+ break;
3741
+ case "steps":
3742
+ l = o`<u-steps .spec=${i} theme=${r ?? c}></u-steps>`;
3743
+ break;
3744
+ case "rating":
3745
+ l = o`<u-rating .spec=${i} theme=${r ?? c}></u-rating>`;
3746
+ break;
3747
+ case "video":
3748
+ l = o`<u-video .spec=${i} theme=${r ?? c}></u-video>`;
3749
+ break;
3750
+ case "gallery":
3751
+ l = o`<u-gallery .spec=${i} theme=${r ?? c}></u-gallery>`;
3752
+ break;
3753
+ case "actions":
3754
+ l = this.renderActionsWidget(i);
3755
+ break;
3756
+ case "divider":
3757
+ l = this.renderDivider(i);
3758
+ break;
3759
+ case "header":
3760
+ l = this.renderHeader(i);
3761
+ break;
3762
+ default:
3763
+ if (t.startsWith("chart.") && customElements.get("u-chart")) {
3764
+ l = o`<u-chart .spec=${i} theme=${r ?? c}></u-chart>`;
3765
+ break;
3766
+ }
3767
+ return this.renderFallback(i);
3768
+ }
3769
+ if (!!i.options?.card && (l = o`<div class="card-container" part="card">${l}</div>`), s.length > 0) {
3770
+ const d = s.map((g) => o`
3771
+ <button
3772
+ data-style=${g.style ?? "default"}
3773
+ ?disabled=${g.disabled}
3774
+ @click=${() => this._dispatchAction(i, g)}
3775
+ part="action-btn"
3776
+ >${g.label}</button>
3777
+ `);
3778
+ return o`<div part="widget-container">${l}<div class="global-actions" part="actions">${d}</div></div>`;
3779
+ }
3780
+ return l;
3781
+ }
3782
+ /** Render standalone "actions" widget — a group of action buttons. */
3783
+ renderActionsWidget(e) {
3784
+ const t = e.actions ?? [];
3785
+ if (t.length === 0) return c;
3786
+ const a = e.options ?? {}, i = String(a.layout ?? "wrap");
3787
+ return o`
3788
+ <div class="actions-widget" data-layout=${i} part="actions" role="group" aria-label=${e.title ?? "Actions"}>
3789
+ ${t.map((r) => o`
3790
+ <button
3791
+ data-style=${r.style ?? "default"}
3792
+ ?disabled=${r.disabled}
3793
+ @click=${() => this._dispatchAction(e, r)}
3794
+ part="action-btn"
3795
+ >${r.label}</button>
3796
+ `)}
3797
+ </div>
3798
+ `;
3799
+ }
3800
+ /** Render inline divider widget. */
3801
+ renderDivider(e) {
3802
+ const t = e.options ?? {}, a = t.label, i = String(t.spacing ?? "default");
3803
+ return o`
3804
+ <div class="divider divider-spacing-${i}" part="divider" role="separator">
3805
+ ${a ?? c}
3806
+ </div>
3807
+ `;
3808
+ }
3809
+ /** Render inline header widget. */
3810
+ renderHeader(e) {
3811
+ const t = e.data, a = String(t?.text ?? e.title ?? ""), i = String(t?.level ?? "2");
3812
+ return a ? o`
3813
+ <div class="header-widget" data-level=${i} part="header" role="heading" aria-level=${i}>
3814
+ ${a}
3815
+ </div>
3816
+ ` : c;
3817
+ }
3818
+ /** Dispatch an action event from the global action bar or actions widget. */
3819
+ _dispatchAction(e, t) {
3820
+ if (t.action === "navigate" && t.url) {
3821
+ window.open(t.url, "_blank", "noopener");
3822
+ return;
3823
+ }
3824
+ this.dispatchEvent(
3825
+ new CustomEvent("u-widget-event", {
3826
+ detail: {
3827
+ type: "action",
3828
+ widget: e.widget,
3829
+ id: e.id,
3830
+ action: t.action,
3831
+ data: t.url ? { url: t.url } : void 0
3832
+ },
3833
+ bubbles: !0,
3834
+ composed: !0
3835
+ })
3836
+ );
3837
+ }
3838
+ renderFallback(e) {
3839
+ const t = Oe(e.widget);
3840
+ return o`
3841
+ <div class="fallback-card" part="fallback">
3842
+ <div class="fallback-label">${e.title ?? `Unknown widget: ${e.widget}`}</div>
3843
+ ${t ? o`<div class="fallback-hint">Did you mean <strong>${t}</strong>?</div>` : ""}
3844
+ <pre part="json"><code>${JSON.stringify(e, null, 2)}</code></pre>
3845
+ </div>
3846
+ `;
3847
+ }
3848
+ renderError(e) {
3849
+ return o`
3850
+ <div class="error-card" part="error">
3851
+ <div class="error-header">
3852
+ <span aria-hidden="true">&#x26A0;</span>
3853
+ <span>Invalid widget spec</span>
3854
+ </div>
3855
+ <ul class="error-list">
3856
+ ${e.map((t) => o`<li>${t}</li>`)}
3857
+ </ul>
3858
+ </div>
3859
+ `;
3860
+ }
3861
+ };
3862
+ E.styles = [
3863
+ b,
3864
+ y`
3865
+ :host {
3866
+ display: block;
3867
+ container: u-widget / inline-size;
3868
+ }
3869
+
3870
+ .error-card {
3871
+ padding: 10px 14px;
3872
+ border-radius: 6px;
3873
+ border: 1px solid var(--u-widget-negative, #ef4444);
3874
+ background: color-mix(in srgb, var(--u-widget-negative, #ef4444) 8%, var(--u-widget-bg, #fff));
3875
+ font-size: 0.8125rem;
3876
+ }
3877
+
3878
+ .error-header { font-weight: 600; color: var(--u-widget-negative, #ef4444); margin-bottom: 4px; }
3879
+ .error-list { margin: 0; padding-left: 20px; color: var(--u-widget-text-secondary, #64748b); }
3880
+
3881
+ .fallback-card {
3882
+ padding: 10px 14px;
3883
+ border-radius: 6px;
3884
+ border: 1px dashed var(--u-widget-border, #e2e8f0);
3885
+ font-size: 0.8125rem;
3886
+ }
3887
+ .fallback-label { font-size: 0.6875rem; font-weight: 600; color: var(--u-widget-text-secondary, #64748b); margin-bottom: 6px; }
3888
+ .fallback-hint { font-size: 0.75rem; color: var(--u-widget-primary, #4f46e5); margin-bottom: 6px; }
3889
+ .fallback-card pre { margin: 0; white-space: pre-wrap; font-size: 0.75rem; color: var(--u-widget-text-secondary, #64748b); max-height: 200px; overflow-y: auto; }
3890
+
3891
+ .card-container {
3892
+ padding: 16px 20px;
3893
+ border-radius: var(--u-widget-radius, 6px);
3894
+ border: 1px solid var(--u-widget-border, #e2e8f0);
3895
+ background: var(--u-widget-bg, #fff);
3896
+ box-shadow: var(--u-widget-shadow);
3897
+ transition: box-shadow 0.2s;
3898
+ }
3899
+
3900
+ /* ── shared action button styles ── */
3901
+ [part="widget-container"] {
3902
+ display: contents;
3903
+ }
3904
+
3905
+ [part="action-btn"] {
3906
+ padding: 8px 20px;
3907
+ border-radius: 6px;
3908
+ font-size: 0.875rem;
3909
+ font-weight: 500;
3910
+ cursor: pointer;
3911
+ border: 1px solid var(--u-widget-border, #e2e8f0);
3912
+ background: var(--u-widget-bg, #fff);
3913
+ color: var(--u-widget-text, #1a1a2e);
3914
+ transition: all 0.15s;
3915
+ font-family: inherit;
3916
+ }
3917
+
3918
+ [part="action-btn"]:hover {
3919
+ background: var(--u-widget-surface, #f1f5f9);
3920
+ }
3921
+
3922
+ [part="action-btn"][data-style='primary'] {
3923
+ background: var(--u-widget-primary, #4f46e5);
3924
+ color: white;
3925
+ border-color: transparent;
3926
+ }
3927
+
3928
+ [part="action-btn"][data-style='primary']:hover {
3929
+ opacity: 0.9;
3930
+ }
3931
+
3932
+ [part="action-btn"][data-style='danger'] {
3933
+ background: var(--u-widget-negative, #dc2626);
3934
+ color: white;
3935
+ border-color: transparent;
3936
+ }
3937
+
3938
+ [part="action-btn"]:disabled {
3939
+ opacity: 0.5;
3940
+ cursor: default;
3941
+ }
3942
+
3943
+ /* ── global action bar ── */
3944
+ .global-actions {
3945
+ display: flex;
3946
+ gap: 8px;
3947
+ justify-content: flex-end;
3948
+ padding-top: 10px;
3949
+ flex-wrap: wrap;
3950
+ }
3951
+
3952
+ /* ── standalone actions widget ── */
3953
+ .actions-widget {
3954
+ display: flex;
3955
+ gap: 8px;
3956
+ flex-wrap: wrap;
3957
+ }
3958
+
3959
+ .actions-widget[data-layout='column'] {
3960
+ flex-direction: column;
3961
+ }
3962
+
3963
+ /* ── divider widget ── */
3964
+ .divider {
3965
+ display: flex;
3966
+ align-items: center;
3967
+ gap: 12px;
3968
+ color: var(--u-widget-text-secondary, #64748b);
3969
+ font-size: 0.75rem;
3970
+ }
3971
+
3972
+ .divider::before,
3973
+ .divider::after {
3974
+ content: '';
3975
+ flex: 1;
3976
+ border-top: 1px solid var(--u-widget-border, #e2e8f0);
3977
+ }
3978
+
3979
+ .divider:empty::after { display: none; }
3980
+ .divider:empty { border-top: 1px solid var(--u-widget-border, #e2e8f0); }
3981
+ .divider:empty::before { display: none; }
3982
+
3983
+ .divider-spacing-small { margin: 4px 0; }
3984
+ .divider-spacing-default { margin: 12px 0; }
3985
+ .divider-spacing-large { margin: 24px 0; }
3986
+
3987
+ /* ── header widget ── */
3988
+ .header-widget {
3989
+ font-weight: 600;
3990
+ color: var(--u-widget-text, #1a1a2e);
3991
+ margin: 0;
3992
+ }
3993
+
3994
+ .header-widget[data-level='1'] { font-size: 1.5rem; }
3995
+ .header-widget[data-level='2'] { font-size: 1.25rem; }
3996
+ .header-widget[data-level='3'] { font-size: 1.1rem; }
3997
+
3998
+ /* ── responsive: narrow container ── */
3999
+ @container u-widget (max-width: 20rem) {
4000
+ .global-actions {
4001
+ flex-direction: column;
4002
+ }
4003
+
4004
+ .global-actions [part="action-btn"] {
4005
+ width: 100%;
4006
+ text-align: center;
4007
+ }
4008
+
4009
+ .actions-widget:not([data-layout='column']) {
4010
+ flex-direction: column;
4011
+ }
4012
+
4013
+ .actions-widget [part="action-btn"] {
4014
+ width: 100%;
4015
+ text-align: center;
4016
+ }
4017
+
4018
+ .card-container {
4019
+ padding: 12px 14px;
4020
+ }
4021
+
4022
+ [part="action-btn"] {
4023
+ padding: 8px 14px;
4024
+ font-size: 0.8125rem;
4025
+ }
4026
+
4027
+ .header-widget[data-level='1'] { font-size: 1.25rem; }
4028
+ .header-widget[data-level='2'] { font-size: 1.1rem; }
4029
+ .header-widget[data-level='3'] { font-size: 1rem; }
4030
+ }
4031
+ `
4032
+ ];
4033
+ J([
4034
+ h({
4035
+ type: Object,
4036
+ converter: {
4037
+ fromAttribute(e) {
4038
+ if (!e) return null;
4039
+ try {
4040
+ return JSON.parse(e);
4041
+ } catch (t) {
4042
+ return console.warn("[u-widget] Invalid JSON in spec attribute:", t.message), null;
4043
+ }
4044
+ }
4045
+ }
4046
+ })
4047
+ ], E.prototype, "spec", 2);
4048
+ J([
4049
+ h({ type: String, reflect: !0 })
4050
+ ], E.prototype, "theme", 2);
4051
+ J([
4052
+ h({ type: String, reflect: !0 })
4053
+ ], E.prototype, "locale", 2);
4054
+ E = J([
4055
+ x("u-widget")
4056
+ ], E);
4057
+ export {
4058
+ E as UWidget,
4059
+ A as formatTemplate,
4060
+ _e as formatValue,
4061
+ Ct as getDefaultLocale,
4062
+ me as getFormdownParser,
4063
+ de as getLocaleStrings,
4064
+ ve as infer,
4065
+ St as isWidgetSpec,
4066
+ be as normalize,
4067
+ Ot as parseFormdown,
4068
+ Pt as registerFormdownParser,
4069
+ At as registerLocale,
4070
+ Oe as suggestWidget,
4071
+ Q as validate
4072
+ };
4073
+ //# sourceMappingURL=u-widgets.js.map