@desktalk/miniapp-note 0.1.0-alpha.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,3795 @@
1
+ (() => {
2
+ if (typeof document === 'undefined') return;
3
+ const styleId = "desktalk-style-desktalk-miniapp-note-emi3yz";
4
+ if (document.getElementById(styleId)) return;
5
+ const style = document.createElement('style');
6
+ style.id = styleId;
7
+ style.textContent = "/* src/styles/NoteApp.module.css */\n.NoteApp_root {\n display: flex;\n height: 100%;\n overflow: hidden;\n background: var(--dt-window-body);\n color: var(--dt-text);\n font-family: var(--font-sans);\n}\n.NoteApp_rootCompact {\n flex-direction: column;\n}\n.NoteApp_rootCompact .NoteApp_listPanel {\n width: 100%;\n min-width: 0;\n max-height: 180px;\n flex-direction: row;\n border-right: none;\n border-bottom: 1px solid var(--dt-border);\n}\n.NoteApp_rootCompact .NoteApp_listHeader {\n width: 140px;\n min-width: 140px;\n flex-direction: column;\n padding: 10px;\n gap: 8px;\n border-bottom: none;\n border-right: 1px solid var(--dt-border-subtle);\n}\n.NoteApp_rootCompact .NoteApp_searchInput {\n width: 100%;\n}\n.NoteApp_rootCompact .NoteApp_newNoteBtn {\n width: 100%;\n}\n.NoteApp_rootCompact .NoteApp_noteList {\n flex: 1;\n overflow-x: auto;\n overflow-y: hidden;\n display: flex;\n padding: 8px;\n gap: 8px;\n}\n.NoteApp_rootCompact .NoteApp_noteItem,\n.NoteApp_rootCompact .NoteApp_noteItemActive {\n min-width: 160px;\n max-width: 200px;\n flex-shrink: 0;\n border-bottom: none;\n border-radius: 6px;\n background: var(--dt-surface);\n}\n.NoteApp_rootCompact .NoteApp_noteItemActive {\n border-left: none;\n padding-left: 10px;\n border: 1px solid var(--dt-accent);\n background: color-mix(in oklab, var(--dt-accent) 8%, var(--dt-surface));\n}\n.NoteApp_rootCompact .NoteApp_emptyState {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n}\n.NoteApp_listPanel {\n display: flex;\n width: 260px;\n min-width: 200px;\n flex-direction: column;\n overflow: hidden;\n border-right: 1px solid var(--dt-border);\n}\n.NoteApp_listHeader {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--dt-border);\n}\n.NoteApp_searchInput {\n flex: 1;\n padding: 6px 10px;\n border: 1px solid var(--dt-border);\n border-radius: 6px;\n background: var(--dt-surface);\n color: var(--dt-text);\n font-family: inherit;\n font-size: 13px;\n outline: none;\n transition: border-color 0.15s;\n}\n.NoteApp_searchInput::placeholder {\n color: var(--dt-text-muted);\n}\n.NoteApp_searchInput:focus {\n border-color: var(--dt-accent);\n}\n.NoteApp_newNoteBtn {\n display: flex;\n width: 30px;\n height: 30px;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--dt-border);\n border-radius: 6px;\n background: var(--dt-surface);\n color: var(--dt-text);\n cursor: pointer;\n font-size: 18px;\n line-height: 1;\n transition:\n background 0.15s,\n border-color 0.15s,\n color 0.15s;\n}\n.NoteApp_newNoteBtn:hover {\n border-color: var(--dt-accent);\n background: var(--dt-surface-hover);\n color: var(--dt-accent);\n}\n.NoteApp_noteList {\n flex: 1;\n overflow-y: auto;\n}\n.NoteApp_noteItem {\n padding: 10px 14px;\n border-bottom: 1px solid var(--dt-border);\n cursor: pointer;\n transition: background 0.1s;\n}\n.NoteApp_noteItem:hover {\n background: var(--dt-surface-hover);\n}\n.NoteApp_noteItemActive {\n padding-left: 11px;\n border-left: 3px solid var(--dt-accent);\n background: var(--dt-surface);\n}\n.NoteApp_noteTitle {\n overflow: hidden;\n margin-bottom: 4px;\n font-size: 14px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.NoteApp_notePreview {\n overflow: hidden;\n margin-bottom: 4px;\n color: var(--dt-text-muted);\n font-size: 12px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.NoteApp_noteDate {\n color: var(--dt-text-muted);\n opacity: 0.7;\n font-size: 11px;\n}\n.NoteApp_emptyState {\n padding: 24px 14px;\n color: var(--dt-text-muted);\n font-size: 13px;\n text-align: center;\n}\n.NoteApp_editorPanel {\n display: flex;\n min-width: 0;\n flex: 1;\n flex-direction: column;\n overflow: hidden;\n}\n.NoteApp_editorHeader {\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: space-between;\n padding: 10px 16px;\n border-bottom: 1px solid var(--dt-border);\n}\n.NoteApp_editorTitle {\n font-size: 16px;\n font-weight: 600;\n}\n.NoteApp_editorTags {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n.NoteApp_editorTag {\n padding: 2px 8px;\n border: 1px solid var(--dt-border);\n border-radius: 4px;\n background: var(--dt-surface);\n color: var(--dt-accent);\n font-size: 11px;\n}\n.NoteApp_editorBody {\n position: relative;\n flex: 1;\n overflow-y: auto;\n}\n.NoteApp_editorPlaceholder {\n display: flex;\n height: 100%;\n align-items: center;\n justify-content: center;\n color: var(--dt-text-muted);\n font-size: 14px;\n}\n.NoteApp_editorBody .milkdown {\n height: 100%;\n background: transparent;\n color: var(--dt-text);\n}\n.NoteApp_editorBody .milkdown .editor {\n min-height: 100%;\n padding: 16px 20px;\n outline: none;\n font-family: var(--font-sans);\n font-size: 14px;\n line-height: 1.65;\n}\n.NoteApp_editorBody .milkdown .editor h1 {\n margin: 0.8em 0 0.4em;\n font-size: 1.6em;\n}\n.NoteApp_editorBody .milkdown .editor h2 {\n margin: 0.7em 0 0.35em;\n font-size: 1.35em;\n}\n.NoteApp_editorBody .milkdown .editor h3 {\n margin: 0.6em 0 0.3em;\n font-size: 1.15em;\n}\n.NoteApp_editorBody .milkdown .editor p {\n margin: 0.5em 0;\n}\n.NoteApp_editorBody .milkdown .editor code {\n padding: 2px 5px;\n border-radius: 3px;\n background: var(--dt-surface);\n font-family: var(--font-mono);\n font-size: 0.9em;\n}\n.NoteApp_editorBody .milkdown .editor pre {\n overflow-x: auto;\n margin: 0.8em 0;\n padding: 12px 16px;\n border: 1px solid var(--dt-border);\n border-radius: 6px;\n background: var(--dt-surface);\n}\n.NoteApp_editorBody .milkdown .editor pre code {\n padding: 0;\n border-radius: 0;\n background: transparent;\n}\n.NoteApp_editorBody .milkdown .editor blockquote {\n margin: 0.8em 0;\n padding-left: 14px;\n border-left: 3px solid var(--dt-accent);\n color: var(--dt-text-muted);\n}\n.NoteApp_editorBody .milkdown .editor a {\n color: var(--dt-accent);\n text-decoration: none;\n}\n.NoteApp_editorBody .milkdown .editor a:hover {\n text-decoration: underline;\n}\n.NoteApp_editorBody .milkdown .editor hr {\n margin: 1.5em 0;\n border: none;\n border-top: 1px solid var(--dt-border);\n}\n.NoteApp_editorBody .milkdown .editor ul,\n.NoteApp_editorBody .milkdown .editor ol {\n margin: 0.5em 0;\n padding-left: 24px;\n}\n.NoteApp_editorBody .milkdown .editor li {\n margin: 0.2em 0;\n}\n.NoteApp_editorBody .milkdown .editor img {\n max-width: 100%;\n border-radius: 6px;\n}\n.NoteApp_editorBody dt-markdown-editor {\n display: block;\n height: 100%;\n}\n.NoteApp_saveStatus {\n color: var(--dt-text-muted);\n opacity: 0.7;\n font-size: 11px;\n}\n.NoteApp_saveStatusSaving {\n color: var(--dt-warning);\n}\n/*# sourceMappingURL=frontend.css.map */\n";
8
+ document.head.appendChild(style);
9
+ })();
10
+
11
+ // desktalk-global:react
12
+ var _mod = window.React;
13
+ var Children = _mod.Children;
14
+ var Component = _mod.Component;
15
+ var Fragment = _mod.Fragment;
16
+ var Profiler = _mod.Profiler;
17
+ var PureComponent = _mod.PureComponent;
18
+ var StrictMode = _mod.StrictMode;
19
+ var Suspense = _mod.Suspense;
20
+ var cloneElement = _mod.cloneElement;
21
+ var createContext = _mod.createContext;
22
+ var createElement = _mod.createElement;
23
+ var createRef = _mod.createRef;
24
+ var forwardRef = _mod.forwardRef;
25
+ var isValidElement = _mod.isValidElement;
26
+ var lazy = _mod.lazy;
27
+ var memo = _mod.memo;
28
+ var startTransition = _mod.startTransition;
29
+ var useCallback = _mod.useCallback;
30
+ var useContext = _mod.useContext;
31
+ var useDebugValue = _mod.useDebugValue;
32
+ var useDeferredValue = _mod.useDeferredValue;
33
+ var useEffect = _mod.useEffect;
34
+ var useId = _mod.useId;
35
+ var useImperativeHandle = _mod.useImperativeHandle;
36
+ var useInsertionEffect = _mod.useInsertionEffect;
37
+ var useLayoutEffect = _mod.useLayoutEffect;
38
+ var useMemo = _mod.useMemo;
39
+ var useReducer = _mod.useReducer;
40
+ var useRef = _mod.useRef;
41
+ var useState = _mod.useState;
42
+ var useSyncExternalStore = _mod.useSyncExternalStore;
43
+ var useTransition = _mod.useTransition;
44
+ var version = _mod.version;
45
+
46
+ // desktalk-global:react-dom/client
47
+ var _mod2 = window.ReactDOM;
48
+ var createRoot = _mod2.createRoot;
49
+ var hydrateRoot = _mod2.hydrateRoot;
50
+
51
+ // src/frontend.tsx
52
+ import { useCommand as useCommand2, MiniAppIdProvider, WindowIdProvider } from "@desktalk/sdk";
53
+
54
+ // src/styles/NoteApp.module.css
55
+ var NoteApp_default = {
56
+ root: "NoteApp_root",
57
+ rootCompact: "NoteApp_rootCompact",
58
+ listPanel: "NoteApp_listPanel",
59
+ listHeader: "NoteApp_listHeader",
60
+ searchInput: "NoteApp_searchInput",
61
+ newNoteBtn: "NoteApp_newNoteBtn",
62
+ noteList: "NoteApp_noteList",
63
+ noteItem: "NoteApp_noteItem",
64
+ noteItemActive: "NoteApp_noteItem NoteApp_noteItemActive",
65
+ emptyState: "NoteApp_emptyState",
66
+ noteTitle: "NoteApp_noteTitle",
67
+ notePreview: "NoteApp_notePreview",
68
+ noteDate: "NoteApp_noteDate",
69
+ editorPanel: "NoteApp_editorPanel",
70
+ editorHeader: "NoteApp_editorHeader",
71
+ editorTitle: "NoteApp_editorTitle",
72
+ editorTags: "NoteApp_editorTags",
73
+ editorTag: "NoteApp_editorTag",
74
+ editorBody: "NoteApp_editorBody",
75
+ editorPlaceholder: "NoteApp_editorPlaceholder",
76
+ saveStatus: "NoteApp_saveStatus",
77
+ saveStatusSaving: "NoteApp_saveStatus NoteApp_saveStatusSaving"
78
+ };
79
+
80
+ // desktalk-global:react/jsx-runtime
81
+ var _mod3 = window.__desktalk_jsx_runtime;
82
+ var jsx = _mod3.jsx;
83
+ var jsxs = _mod3.jsxs;
84
+ var jsxDEV = _mod3.jsxDEV;
85
+ var Fragment2 = _mod3.Fragment;
86
+
87
+ // src/components/NoteList.tsx
88
+ function formatDate(iso) {
89
+ try {
90
+ const d = new Date(iso);
91
+ const now = /* @__PURE__ */ new Date();
92
+ const diffMs = now.getTime() - d.getTime();
93
+ const diffMins = Math.floor(diffMs / 6e4);
94
+ if (diffMins < 1) return "just now";
95
+ if (diffMins < 60) return `${diffMins}m ago`;
96
+ const diffHours = Math.floor(diffMins / 60);
97
+ if (diffHours < 24) return `${diffHours}h ago`;
98
+ const diffDays = Math.floor(diffHours / 24);
99
+ if (diffDays < 7) return `${diffDays}d ago`;
100
+ return d.toLocaleDateString(void 0, { month: "short", day: "numeric" });
101
+ } catch {
102
+ return "";
103
+ }
104
+ }
105
+ function NoteList({
106
+ notes,
107
+ selectedId,
108
+ onSelect,
109
+ onCreate,
110
+ searchQuery,
111
+ onSearchChange
112
+ }) {
113
+ const inputRef = useRef(null);
114
+ return /* @__PURE__ */ jsxs("div", { className: NoteApp_default.listPanel, children: [
115
+ /* @__PURE__ */ jsxs("div", { className: NoteApp_default.listHeader, children: [
116
+ /* @__PURE__ */ jsx(
117
+ "input",
118
+ {
119
+ ref: inputRef,
120
+ type: "text",
121
+ className: NoteApp_default.searchInput,
122
+ placeholder: "Search notes...",
123
+ value: searchQuery,
124
+ onChange: (e) => onSearchChange(e.target.value)
125
+ }
126
+ ),
127
+ /* @__PURE__ */ jsx("button", { className: NoteApp_default.newNoteBtn, onClick: onCreate, title: "New note", children: "+" })
128
+ ] }),
129
+ /* @__PURE__ */ jsx("div", { className: NoteApp_default.noteList, children: notes.length === 0 ? /* @__PURE__ */ jsx("div", { className: NoteApp_default.emptyState, children: searchQuery ? "No notes match your search" : "No notes yet" }) : notes.map((note) => /* @__PURE__ */ jsxs(
130
+ "div",
131
+ {
132
+ className: note.id === selectedId ? NoteApp_default.noteItemActive : NoteApp_default.noteItem,
133
+ onClick: () => onSelect(note.id),
134
+ children: [
135
+ /* @__PURE__ */ jsx("div", { className: NoteApp_default.noteTitle, children: note.title }),
136
+ /* @__PURE__ */ jsx("div", { className: NoteApp_default.notePreview, children: note.preview }),
137
+ /* @__PURE__ */ jsx("div", { className: NoteApp_default.noteDate, children: formatDate(note.updatedAt) })
138
+ ]
139
+ },
140
+ note.id
141
+ )) })
142
+ ] });
143
+ }
144
+
145
+ // ../ui/dist/index.js
146
+ var J = `.dt-tooltip-popup {
147
+ position: fixed;
148
+ z-index: 2147483647;
149
+ padding: 6px 10px;
150
+ border: 1px solid var(--dt-accent);
151
+ border-radius: 2px;
152
+ background: var(--dt-surface);
153
+ color: var(--dt-text-secondary);
154
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
155
+ font-size: 12px;
156
+ font-weight: 500;
157
+ line-height: 1.4;
158
+ white-space: nowrap;
159
+ pointer-events: none;
160
+ user-select: none;
161
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
162
+ }
163
+
164
+ /* Tech corner accents */
165
+ .dt-tooltip-popup::before {
166
+ content: '';
167
+ position: absolute;
168
+ top: -1px;
169
+ left: -1px;
170
+ width: 4px;
171
+ height: 4px;
172
+ border-top: 1px solid var(--dt-accent);
173
+ border-left: 1px solid var(--dt-accent);
174
+ }
175
+
176
+ .dt-tooltip-popup::after {
177
+ content: '';
178
+ position: absolute;
179
+ bottom: -1px;
180
+ right: -1px;
181
+ width: 4px;
182
+ height: 4px;
183
+ border-bottom: 1px solid var(--dt-accent);
184
+ border-right: 1px solid var(--dt-accent);
185
+ }
186
+
187
+ /* Arrow styling - tech/minimal */
188
+ .dt-tooltip-popup[data-actual-placement='top'] {
189
+ transform: translateX(-50%);
190
+ }
191
+
192
+ .dt-tooltip-popup[data-actual-placement='top']::before {
193
+ top: auto;
194
+ bottom: -4px;
195
+ left: 50%;
196
+ transform: translateX(-50%);
197
+ width: 0;
198
+ height: 0;
199
+ border: 4px solid transparent;
200
+ border-top-color: var(--dt-accent);
201
+ border-left: none;
202
+ border-right: none;
203
+ }
204
+
205
+ .dt-tooltip-popup[data-actual-placement='bottom'] {
206
+ transform: translateX(-50%);
207
+ }
208
+
209
+ .dt-tooltip-popup[data-actual-placement='bottom']::before {
210
+ bottom: auto;
211
+ top: -4px;
212
+ left: 50%;
213
+ transform: translateX(-50%);
214
+ width: 0;
215
+ height: 0;
216
+ border: 4px solid transparent;
217
+ border-bottom-color: var(--dt-accent);
218
+ border-left: none;
219
+ border-right: none;
220
+ }
221
+
222
+ .dt-tooltip-popup[data-actual-placement='left'] {
223
+ transform: translateY(-50%);
224
+ }
225
+
226
+ .dt-tooltip-popup[data-actual-placement='left']::before {
227
+ left: auto;
228
+ top: 50%;
229
+ right: -4px;
230
+ transform: translateY(-50%);
231
+ width: 0;
232
+ height: 0;
233
+ border: 4px solid transparent;
234
+ border-left-color: var(--dt-accent);
235
+ border-top: none;
236
+ border-bottom: none;
237
+ }
238
+
239
+ .dt-tooltip-popup[data-actual-placement='right'] {
240
+ transform: translateY(-50%);
241
+ }
242
+
243
+ .dt-tooltip-popup[data-actual-placement='right']::before {
244
+ right: auto;
245
+ top: 50%;
246
+ left: -4px;
247
+ transform: translateY(-50%);
248
+ width: 0;
249
+ height: 0;
250
+ border: 4px solid transparent;
251
+ border-right-color: var(--dt-accent);
252
+ border-top: none;
253
+ border-bottom: none;
254
+ }
255
+ `;
256
+ var vt = "dt-tooltip-popup";
257
+ var u = 8;
258
+ var W = false;
259
+ function ft() {
260
+ if (W) return;
261
+ let r = document.createElement("style");
262
+ r.setAttribute("data-dt-tooltip", ""), r.textContent = J, document.head.appendChild(r), W = true;
263
+ }
264
+ var x = class extends HTMLElement {
265
+ _popup = null;
266
+ _showTimeout = null;
267
+ _tooltipId = "";
268
+ _visible = false;
269
+ static get observedAttributes() {
270
+ return ["content", "placement", "delay", "disabled"];
271
+ }
272
+ get content() {
273
+ return this.getAttribute("content") ?? "";
274
+ }
275
+ set content(t) {
276
+ this.setAttribute("content", t);
277
+ }
278
+ get placement() {
279
+ let t = this.getAttribute("placement");
280
+ return t === "bottom" || t === "left" || t === "right" ? t : "top";
281
+ }
282
+ set placement(t) {
283
+ this.setAttribute("placement", t);
284
+ }
285
+ get delay() {
286
+ let t = Number(this.getAttribute("delay"));
287
+ return Number.isFinite(t) && t > 0 ? t : 0;
288
+ }
289
+ set delay(t) {
290
+ this.setAttribute("delay", String(t));
291
+ }
292
+ get disabled() {
293
+ return this.hasAttribute("disabled");
294
+ }
295
+ set disabled(t) {
296
+ t ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
297
+ }
298
+ constructor() {
299
+ super();
300
+ let t = this.attachShadow({ mode: "open" });
301
+ t.innerHTML = "<slot></slot>", this._tooltipId = `dt-tip-${Math.random().toString(36).slice(2, 9)}`;
302
+ }
303
+ connectedCallback() {
304
+ ft(), this.addEventListener("mouseenter", this._onEnter), this.addEventListener("mouseleave", this._onLeave), this.addEventListener("focusin", this._onEnter), this.addEventListener("focusout", this._onLeave);
305
+ }
306
+ disconnectedCallback() {
307
+ this.removeEventListener("mouseenter", this._onEnter), this.removeEventListener("mouseleave", this._onLeave), this.removeEventListener("focusin", this._onEnter), this.removeEventListener("focusout", this._onLeave), this._hide();
308
+ }
309
+ attributeChangedCallback(t, e, n) {
310
+ t === "disabled" && this.disabled && this._hide(), t === "content" && this._popup && (this._popup.textContent = this.content);
311
+ }
312
+ _onEnter = () => {
313
+ if (this.disabled || !this.content) return;
314
+ this._showTimeout !== null && clearTimeout(this._showTimeout);
315
+ let t = () => {
316
+ this._createPopup(), this._position(), this._visible = true;
317
+ };
318
+ this.delay > 0 ? this._showTimeout = setTimeout(t, this.delay) : t();
319
+ };
320
+ _onLeave = () => {
321
+ this._hide();
322
+ };
323
+ _createPopup() {
324
+ if (this._popup) return;
325
+ let t = document.createElement("div");
326
+ t.className = vt, t.id = this._tooltipId, t.setAttribute("role", "tooltip"), t.textContent = this.content, document.body.appendChild(t), this._popup = t;
327
+ let e = this._getTrigger();
328
+ e && e.setAttribute("aria-describedby", this._tooltipId);
329
+ }
330
+ _hide() {
331
+ if (this._showTimeout !== null && (clearTimeout(this._showTimeout), this._showTimeout = null), this._popup) {
332
+ let t = this._getTrigger();
333
+ t && t.removeAttribute("aria-describedby"), this._popup.remove(), this._popup = null, this._visible = false;
334
+ }
335
+ }
336
+ _getTrigger() {
337
+ let e = this.shadowRoot?.querySelector("slot")?.assignedElements();
338
+ return e && e.length > 0 ? e[0] : null;
339
+ }
340
+ _position() {
341
+ let t = this._popup;
342
+ if (!t) return;
343
+ let e = this.getBoundingClientRect(), n = t.getBoundingClientRect(), i = window.innerWidth, s = window.innerHeight, o = this.placement;
344
+ o === "top" && e.top - n.height - u < 0 ? o = "bottom" : o === "bottom" && e.bottom + n.height + u > s ? o = "top" : o === "left" && e.left - n.width - u < 0 ? o = "right" : o === "right" && e.right + n.width + u > i && (o = "left"), t.setAttribute("data-actual-placement", o);
345
+ let a, d;
346
+ switch (o) {
347
+ case "top":
348
+ d = e.left + e.width / 2, a = e.top - n.height - u;
349
+ break;
350
+ case "bottom":
351
+ d = e.left + e.width / 2, a = e.bottom + u;
352
+ break;
353
+ case "left":
354
+ d = e.left - n.width - u, a = e.top + e.height / 2;
355
+ break;
356
+ case "right":
357
+ d = e.right + u, a = e.top + e.height / 2;
358
+ break;
359
+ }
360
+ t.style.left = `${d}px`, t.style.top = `${a}px`;
361
+ }
362
+ };
363
+ var G = `:host {
364
+ display: block;
365
+ margin-bottom: 12px;
366
+ }
367
+
368
+ .dt-card-inner {
369
+ background: var(--dt-surface);
370
+ border: 1px solid var(--dt-accent);
371
+ border-radius: 2px;
372
+ padding: 12px;
373
+ color: var(--dt-text);
374
+ font-family: var(--font-ui, 'Work Sans', system-ui, sans-serif);
375
+ position: relative;
376
+ height: 100%;
377
+ }
378
+
379
+ /* Corner accents for sci-fi feel */
380
+ .dt-card-inner::before {
381
+ content: '';
382
+ position: absolute;
383
+ top: -1px;
384
+ left: -1px;
385
+ width: 8px;
386
+ height: 8px;
387
+ border-top: 2px solid var(--dt-accent);
388
+ border-left: 2px solid var(--dt-accent);
389
+ }
390
+
391
+ .dt-card-inner::after {
392
+ content: '';
393
+ position: absolute;
394
+ bottom: -1px;
395
+ right: -1px;
396
+ width: 8px;
397
+ height: 8px;
398
+ border-bottom: 2px solid var(--dt-accent);
399
+ border-right: 2px solid var(--dt-accent);
400
+ }
401
+
402
+ :host([variant='outlined']) .dt-card-inner {
403
+ background: transparent;
404
+ border-style: dashed;
405
+ }
406
+
407
+ :host([variant='filled']) .dt-card-inner {
408
+ background: var(--dt-accent-subtle);
409
+ border-style: solid;
410
+ }
411
+
412
+ ::slotted(h1),
413
+ ::slotted(h2),
414
+ ::slotted(h3),
415
+ ::slotted(h4),
416
+ ::slotted(h5),
417
+ ::slotted(h6) {
418
+ color: var(--dt-accent);
419
+ margin: 0 0 6px;
420
+ line-height: 1.2;
421
+ font-family: var(--font-display, 'Sora', system-ui, sans-serif);
422
+ font-weight: 600;
423
+ text-transform: uppercase;
424
+ letter-spacing: 0.1em;
425
+ font-size: 0.85rem;
426
+ }
427
+
428
+ ::slotted(p) {
429
+ color: var(--dt-text-secondary);
430
+ margin: 0 0 6px;
431
+ line-height: 1.4;
432
+ font-family: var(--font-ui, 'Work Sans', system-ui, sans-serif);
433
+ font-size: 0.8125rem;
434
+ }
435
+
436
+ ::slotted(p:last-child) {
437
+ margin-bottom: 0;
438
+ }
439
+ `;
440
+ var _t = "dt-card-inner";
441
+ var w = class extends HTMLElement {
442
+ static get observedAttributes() {
443
+ return ["variant"];
444
+ }
445
+ get variant() {
446
+ let t = this.getAttribute("variant");
447
+ return t === "outlined" || t === "filled" ? t : "default";
448
+ }
449
+ set variant(t) {
450
+ this.setAttribute("variant", t);
451
+ }
452
+ constructor() {
453
+ super();
454
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
455
+ e.textContent = G, t.appendChild(e);
456
+ let n = document.createElement("div");
457
+ n.className = _t, n.innerHTML = "<slot></slot>", t.appendChild(n);
458
+ }
459
+ };
460
+ var j = `.dt-select-menu {
461
+ position: fixed;
462
+ z-index: 2147483646;
463
+ display: flex;
464
+ min-width: 200px;
465
+ max-width: min(300px, 72vw);
466
+ max-height: 240px;
467
+ flex-direction: column;
468
+ overflow-y: auto;
469
+ border: 1px solid var(--dt-accent);
470
+ border-radius: 2px;
471
+ background: var(--dt-surface);
472
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
473
+ opacity: 0;
474
+ pointer-events: none;
475
+ transition: opacity 100ms ease;
476
+ }
477
+
478
+ .dt-select-menu[data-open] {
479
+ opacity: 1;
480
+ pointer-events: auto;
481
+ }
482
+
483
+ .dt-select-option {
484
+ display: flex;
485
+ width: 100%;
486
+ align-items: center;
487
+ justify-content: space-between;
488
+ padding: 8px 10px;
489
+ border: 0;
490
+ border-bottom: 1px solid var(--dt-border-subtle);
491
+ background: transparent;
492
+ color: var(--dt-text);
493
+ font-family: var(
494
+ --font-mono,
495
+ 'SF Mono',
496
+ Monaco,
497
+ 'Cascadia Code',
498
+ 'Roboto Mono',
499
+ Consolas,
500
+ monospace
501
+ );
502
+ font-size: 0.8125rem;
503
+ font-weight: 600;
504
+ letter-spacing: 0.04em;
505
+ text-align: left;
506
+ cursor: pointer;
507
+ transition: all 0.1s ease;
508
+ user-select: none;
509
+ }
510
+
511
+ .dt-select-option:last-child {
512
+ border-bottom: none;
513
+ }
514
+
515
+ .dt-select-option:hover {
516
+ background: var(--dt-accent);
517
+ color: var(--dt-text-on-accent);
518
+ }
519
+
520
+ .dt-select-option.dt-select-option--active {
521
+ background: var(--dt-accent-subtle);
522
+ color: var(--dt-accent);
523
+ }
524
+
525
+ .dt-select-option span {
526
+ overflow: hidden;
527
+ text-overflow: ellipsis;
528
+ white-space: nowrap;
529
+ }
530
+ `;
531
+ var q = `:host {
532
+ display: block;
533
+ width: 100%;
534
+ min-width: 0;
535
+ position: relative;
536
+ }
537
+
538
+ :host([disabled]) .dt-select-trigger {
539
+ cursor: not-allowed;
540
+ opacity: 0.4;
541
+ }
542
+
543
+ .dt-select-trigger {
544
+ display: flex;
545
+ width: 100%;
546
+ min-width: 0;
547
+ max-width: 100%;
548
+ box-sizing: border-box;
549
+ align-items: center;
550
+ gap: 6px;
551
+ padding: 6px 10px;
552
+ border: 1px solid var(--dt-accent);
553
+ border-radius: 2px;
554
+ background: var(--dt-surface);
555
+ color: var(--dt-text);
556
+ font-family: var(
557
+ --font-mono,
558
+ 'SF Mono',
559
+ Monaco,
560
+ 'Cascadia Code',
561
+ 'Roboto Mono',
562
+ Consolas,
563
+ monospace
564
+ );
565
+ font-size: 0.8125rem;
566
+ font-weight: 600;
567
+ letter-spacing: 0.04em;
568
+ line-height: 1;
569
+ cursor: pointer;
570
+ transition: all 0.1s ease;
571
+ user-select: none;
572
+ position: relative;
573
+ }
574
+
575
+ /* Corner accents */
576
+ .dt-select-trigger::before {
577
+ content: '';
578
+ position: absolute;
579
+ top: 0;
580
+ left: 0;
581
+ width: 4px;
582
+ height: 4px;
583
+ border-top: 1px solid var(--dt-accent);
584
+ border-left: 1px solid var(--dt-accent);
585
+ }
586
+
587
+ .dt-select-trigger::after {
588
+ content: '';
589
+ position: absolute;
590
+ bottom: 0;
591
+ right: 0;
592
+ width: 4px;
593
+ height: 4px;
594
+ border-bottom: 1px solid var(--dt-accent);
595
+ border-right: 1px solid var(--dt-accent);
596
+ }
597
+
598
+ .dt-select-trigger:hover:not([disabled]) {
599
+ background: var(--dt-accent);
600
+ color: var(--dt-text-on-accent);
601
+ }
602
+
603
+ .dt-select-trigger:hover:not([disabled])::before,
604
+ .dt-select-trigger:hover:not([disabled])::after {
605
+ border-color: var(--dt-text-on-accent);
606
+ }
607
+
608
+ .dt-select-trigger[aria-expanded='true'] {
609
+ background: var(--dt-accent);
610
+ color: var(--dt-text-on-accent);
611
+ }
612
+
613
+ .dt-select-trigger[aria-expanded='true']::before,
614
+ .dt-select-trigger[aria-expanded='true']::after {
615
+ border-color: var(--dt-text-on-accent);
616
+ }
617
+
618
+ .dt-select-label {
619
+ overflow: hidden;
620
+ text-overflow: ellipsis;
621
+ white-space: nowrap;
622
+ }
623
+
624
+ .dt-select-chevron {
625
+ color: currentColor;
626
+ font-size: 10px;
627
+ transition: transform 140ms ease;
628
+ opacity: 0.7;
629
+ }
630
+
631
+ .dt-select-trigger[aria-expanded='true'] .dt-select-chevron {
632
+ transform: rotate(180deg);
633
+ }
634
+ `;
635
+ var xt = "dt-select-trigger";
636
+ var K = "dt-select-label";
637
+ var wt = "dt-select-chevron";
638
+ var yt = "dt-select-menu";
639
+ var kt = "dt-select-option";
640
+ var Ct = "dt-select-option--active";
641
+ var U = false;
642
+ function Et() {
643
+ if (U) return;
644
+ let r = document.createElement("style");
645
+ r.setAttribute("data-dt-select", ""), r.textContent = j, document.head.appendChild(r), U = true;
646
+ }
647
+ var y = class extends HTMLElement {
648
+ _menu = null;
649
+ _trigger = null;
650
+ _options = [];
651
+ _open = false;
652
+ _menuId = "";
653
+ static get observedAttributes() {
654
+ return ["value", "placeholder", "disabled", "align"];
655
+ }
656
+ get value() {
657
+ return this.getAttribute("value") ?? "";
658
+ }
659
+ set value(t) {
660
+ this.setAttribute("value", t);
661
+ }
662
+ get placeholder() {
663
+ return this.getAttribute("placeholder") ?? "Select\u2026";
664
+ }
665
+ set placeholder(t) {
666
+ this.setAttribute("placeholder", t);
667
+ }
668
+ get disabled() {
669
+ return this.hasAttribute("disabled");
670
+ }
671
+ set disabled(t) {
672
+ t ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
673
+ }
674
+ get align() {
675
+ return this.getAttribute("align") === "right" ? "right" : "left";
676
+ }
677
+ set align(t) {
678
+ this.setAttribute("align", t);
679
+ }
680
+ get options() {
681
+ return this._options;
682
+ }
683
+ set options(t) {
684
+ this._options = t, this._updateLabel(), this._open && this._renderMenuItems();
685
+ }
686
+ constructor() {
687
+ super();
688
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
689
+ e.textContent = q, t.appendChild(e);
690
+ let n = document.createElement("button");
691
+ n.type = "button", n.className = xt, n.setAttribute("aria-haspopup", "listbox"), n.setAttribute("aria-expanded", "false");
692
+ let i = document.createElement("span");
693
+ i.className = K, n.appendChild(i);
694
+ let s = document.createElement("span");
695
+ s.className = wt, s.setAttribute("aria-hidden", "true"), s.textContent = "\u25BE", n.appendChild(s), t.appendChild(n), this._trigger = n, this._menuId = `dt-sel-${Math.random().toString(36).slice(2, 9)}`;
696
+ }
697
+ connectedCallback() {
698
+ Et(), this._trigger.addEventListener("click", this._onTriggerClick), this._updateLabel();
699
+ }
700
+ disconnectedCallback() {
701
+ this._trigger.removeEventListener("click", this._onTriggerClick), this._close();
702
+ }
703
+ attributeChangedCallback(t) {
704
+ t === "value" && (this._updateLabel(), this._open && this._renderMenuItems()), t === "placeholder" && !this.value && this._updateLabel(), t === "disabled" && this.disabled && this._close();
705
+ }
706
+ _updateLabel() {
707
+ let t = this._trigger.querySelector(`.${K}`), e = this._options.find((n) => n.value === this.value);
708
+ t.textContent = e?.label ?? this.placeholder;
709
+ }
710
+ _onTriggerClick = () => {
711
+ this.disabled || (this._open ? this._close() : this._openMenu());
712
+ };
713
+ _openMenu() {
714
+ if (this._open) return;
715
+ let t = document.createElement("div");
716
+ t.className = yt, t.id = this._menuId, t.setAttribute("role", "listbox"), document.body.appendChild(t), this._menu = t, this._renderMenuItems(), this._position(), requestAnimationFrame(() => {
717
+ t.setAttribute("data-open", "");
718
+ }), this._open = true, this._trigger.setAttribute("aria-expanded", "true"), requestAnimationFrame(() => {
719
+ document.addEventListener("mousedown", this._onOutsideClick), document.addEventListener("keydown", this._onKeyDown);
720
+ });
721
+ }
722
+ _close() {
723
+ if (this._open) {
724
+ if (document.removeEventListener("mousedown", this._onOutsideClick), document.removeEventListener("keydown", this._onKeyDown), this._menu) {
725
+ this._menu.removeAttribute("data-open");
726
+ let t = this._menu;
727
+ setTimeout(() => t.remove(), 140), this._menu = null;
728
+ }
729
+ this._open = false, this._trigger.setAttribute("aria-expanded", "false");
730
+ }
731
+ }
732
+ _onOutsideClick = (t) => {
733
+ let e = t.target;
734
+ this._menu?.contains(e) || this.contains(e) || this._close();
735
+ };
736
+ _onKeyDown = (t) => {
737
+ t.key === "Escape" && (this._close(), this._trigger.focus());
738
+ };
739
+ _renderMenuItems() {
740
+ let t = this._menu;
741
+ if (t) {
742
+ t.innerHTML = "";
743
+ for (let e of this._options) {
744
+ let n = document.createElement("button");
745
+ n.type = "button", n.className = kt, n.setAttribute("role", "option"), n.setAttribute("aria-selected", String(e.value === this.value)), e.value === this.value && n.classList.add(Ct);
746
+ let i = document.createElement("span");
747
+ i.textContent = e.label, n.appendChild(i), n.addEventListener("click", () => {
748
+ this._selectValue(e.value);
749
+ }), t.appendChild(n);
750
+ }
751
+ }
752
+ }
753
+ _selectValue(t) {
754
+ let e = this.value;
755
+ this.value = t, this._updateLabel(), this._close(), t !== e && this.dispatchEvent(new CustomEvent("dt-change", { detail: { value: t }, bubbles: true, composed: true }));
756
+ }
757
+ _position() {
758
+ let t = this._menu;
759
+ if (!t) return;
760
+ let e = this.getBoundingClientRect(), n = 10, i = Math.max(e.width, 240), s = e.bottom + n, o = t.scrollHeight || 260, a = window.innerHeight;
761
+ if (s + o > a && e.top - o - n > 0 && (s = e.top - o - n), t.style.minWidth = `${i}px`, this.align === "right") {
762
+ let d = window.innerWidth;
763
+ t.style.right = `${d - e.right}px`, t.style.left = "auto";
764
+ } else t.style.left = `${e.left}px`, t.style.right = "auto";
765
+ t.style.top = `${s}px`;
766
+ }
767
+ };
768
+ var Y = `:host {
769
+ display: block;
770
+ margin-bottom: 12px;
771
+ }
772
+
773
+ .dt-grid-inner {
774
+ display: grid;
775
+ gap: var(--grid-gap, 12px);
776
+ grid-template-columns: repeat(auto-fit, minmax(var(--min-width, 220px), 1fr));
777
+ }
778
+
779
+ :host([cols='1']) .dt-grid-inner {
780
+ grid-template-columns: repeat(1, 1fr);
781
+ }
782
+
783
+ :host([cols='2']) .dt-grid-inner {
784
+ grid-template-columns: repeat(2, 1fr);
785
+ }
786
+
787
+ :host([cols='3']) .dt-grid-inner {
788
+ grid-template-columns: repeat(3, 1fr);
789
+ }
790
+
791
+ :host([cols='4']) .dt-grid-inner {
792
+ grid-template-columns: repeat(4, 1fr);
793
+ }
794
+
795
+ :host([cols='5']) .dt-grid-inner {
796
+ grid-template-columns: repeat(5, 1fr);
797
+ }
798
+
799
+ :host([cols='6']) .dt-grid-inner {
800
+ grid-template-columns: repeat(6, 1fr);
801
+ }
802
+
803
+ @media (max-width: 480px) {
804
+ :host([cols='2']) .dt-grid-inner,
805
+ :host([cols='3']) .dt-grid-inner,
806
+ :host([cols='4']) .dt-grid-inner,
807
+ :host([cols='5']) .dt-grid-inner,
808
+ :host([cols='6']) .dt-grid-inner {
809
+ grid-template-columns: 1fr;
810
+ }
811
+ }
812
+
813
+ :host([gap='0']) .dt-grid-inner {
814
+ --grid-gap: 0;
815
+ }
816
+ :host([gap='4']) .dt-grid-inner {
817
+ --grid-gap: 4px;
818
+ }
819
+ :host([gap='8']) .dt-grid-inner {
820
+ --grid-gap: 8px;
821
+ }
822
+ :host([gap='12']) .dt-grid-inner {
823
+ --grid-gap: 12px;
824
+ }
825
+ :host([gap='16']) .dt-grid-inner {
826
+ --grid-gap: 16px;
827
+ }
828
+ :host([gap='20']) .dt-grid-inner {
829
+ --grid-gap: 20px;
830
+ }
831
+ :host([gap='24']) .dt-grid-inner {
832
+ --grid-gap: 24px;
833
+ }
834
+ :host([gap='32']) .dt-grid-inner {
835
+ --grid-gap: 32px;
836
+ }
837
+
838
+ :host([min-width='150']) .dt-grid-inner {
839
+ --min-width: 150px;
840
+ }
841
+ :host([min-width='180']) .dt-grid-inner {
842
+ --min-width: 180px;
843
+ }
844
+ :host([min-width='200']) .dt-grid-inner {
845
+ --min-width: 200px;
846
+ }
847
+ :host([min-width='220']) .dt-grid-inner {
848
+ --min-width: 220px;
849
+ }
850
+ :host([min-width='260']) .dt-grid-inner {
851
+ --min-width: 260px;
852
+ }
853
+ :host([min-width='300']) .dt-grid-inner {
854
+ --min-width: 300px;
855
+ }
856
+
857
+ ::slotted(*) {
858
+ min-width: 0;
859
+ }
860
+ `;
861
+ var St = "dt-grid-inner";
862
+ var k = class extends HTMLElement {
863
+ static get observedAttributes() {
864
+ return ["cols", "gap", "min-width"];
865
+ }
866
+ get cols() {
867
+ let t = this.getAttribute("cols");
868
+ return t === "1" || t === "2" || t === "3" || t === "4" || t === "5" || t === "6" ? t : null;
869
+ }
870
+ set cols(t) {
871
+ t === null ? this.removeAttribute("cols") : this.setAttribute("cols", t);
872
+ }
873
+ get gap() {
874
+ let t = this.getAttribute("gap");
875
+ return t === "0" || t === "4" || t === "8" || t === "12" || t === "20" || t === "24" || t === "32" ? t : "16";
876
+ }
877
+ set gap(t) {
878
+ this.setAttribute("gap", t);
879
+ }
880
+ get minWidth() {
881
+ let t = this.getAttribute("min-width");
882
+ return t === "150" || t === "180" || t === "200" || t === "260" || t === "300" ? t : "220";
883
+ }
884
+ set minWidth(t) {
885
+ this.setAttribute("min-width", t);
886
+ }
887
+ constructor() {
888
+ super();
889
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
890
+ e.textContent = Y, t.appendChild(e);
891
+ let n = document.createElement("div");
892
+ n.className = St, n.innerHTML = "<slot></slot>", t.appendChild(n);
893
+ }
894
+ };
895
+ var Z = `:host {
896
+ display: block;
897
+ margin-bottom: 12px;
898
+ }
899
+
900
+ .dt-stack-inner {
901
+ display: flex;
902
+ flex-direction: var(--flex-direction, column);
903
+ gap: var(--stack-gap, 12px);
904
+ align-items: var(--align-items, stretch);
905
+ }
906
+
907
+ :host([direction='column']) .dt-stack-inner {
908
+ --flex-direction: column;
909
+ }
910
+ :host([direction='row']) .dt-stack-inner {
911
+ --flex-direction: row;
912
+ }
913
+
914
+ :host([gap='0']) .dt-stack-inner {
915
+ --stack-gap: 0;
916
+ }
917
+ :host([gap='4']) .dt-stack-inner {
918
+ --stack-gap: 4px;
919
+ }
920
+ :host([gap='8']) .dt-stack-inner {
921
+ --stack-gap: 8px;
922
+ }
923
+ :host([gap='12']) .dt-stack-inner {
924
+ --stack-gap: 12px;
925
+ }
926
+ :host([gap='16']) .dt-stack-inner {
927
+ --stack-gap: 16px;
928
+ }
929
+ :host([gap='20']) .dt-stack-inner {
930
+ --stack-gap: 20px;
931
+ }
932
+ :host([gap='24']) .dt-stack-inner {
933
+ --stack-gap: 24px;
934
+ }
935
+ :host([gap='32']) .dt-stack-inner {
936
+ --stack-gap: 32px;
937
+ }
938
+
939
+ :host([align='start']) .dt-stack-inner {
940
+ --align-items: flex-start;
941
+ }
942
+ :host([align='center']) .dt-stack-inner {
943
+ --align-items: center;
944
+ }
945
+ :host([align='end']) .dt-stack-inner {
946
+ --align-items: flex-end;
947
+ }
948
+ :host([align='stretch']) .dt-stack-inner {
949
+ --align-items: stretch;
950
+ }
951
+
952
+ @media (max-width: 480px) {
953
+ :host([direction='row']) .dt-stack-inner {
954
+ --flex-direction: column;
955
+ }
956
+ }
957
+
958
+ ::slotted(*) {
959
+ min-width: 0;
960
+ }
961
+ `;
962
+ var Dt = "dt-stack-inner";
963
+ function $(r) {
964
+ return r === "row" || r === "horizontal" ? "row" : "column";
965
+ }
966
+ var C = class extends HTMLElement {
967
+ static get observedAttributes() {
968
+ return ["direction", "gap", "align"];
969
+ }
970
+ get direction() {
971
+ return $(this.getAttribute("direction"));
972
+ }
973
+ set direction(t) {
974
+ this.setAttribute("direction", $(t));
975
+ }
976
+ get gap() {
977
+ let t = this.getAttribute("gap");
978
+ return t === "0" || t === "4" || t === "8" || t === "12" || t === "20" || t === "24" || t === "32" ? t : "16";
979
+ }
980
+ set gap(t) {
981
+ this.setAttribute("gap", t);
982
+ }
983
+ get align() {
984
+ let t = this.getAttribute("align");
985
+ return t === "start" || t === "center" || t === "end" ? t : "stretch";
986
+ }
987
+ set align(t) {
988
+ this.setAttribute("align", t);
989
+ }
990
+ connectedCallback() {
991
+ this.#t();
992
+ }
993
+ attributeChangedCallback(t) {
994
+ t === "direction" && this.#t();
995
+ }
996
+ constructor() {
997
+ super();
998
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
999
+ e.textContent = Z, t.appendChild(e);
1000
+ let n = document.createElement("div");
1001
+ n.className = Dt, n.innerHTML = "<slot></slot>", t.appendChild(n);
1002
+ }
1003
+ #t() {
1004
+ let t = this.getAttribute("direction"), e = $(t);
1005
+ t !== null && t !== e && this.setAttribute("direction", e);
1006
+ }
1007
+ };
1008
+ var Q = `:host {
1009
+ display: block;
1010
+ }
1011
+
1012
+ .dt-stat-inner {
1013
+ background: var(--dt-surface);
1014
+ border: 1px solid var(--dt-accent);
1015
+ border-radius: 2px;
1016
+ padding: 12px;
1017
+ font-family: var(--font-ui, 'Work Sans', system-ui, sans-serif);
1018
+ display: flex;
1019
+ flex-direction: column;
1020
+ gap: 4px;
1021
+ position: relative;
1022
+ }
1023
+
1024
+ /* Corner accents */
1025
+ .dt-stat-inner::before {
1026
+ content: '';
1027
+ position: absolute;
1028
+ top: 0;
1029
+ left: 0;
1030
+ width: 6px;
1031
+ height: 6px;
1032
+ border-top: 1px solid var(--dt-accent);
1033
+ border-left: 1px solid var(--dt-accent);
1034
+ }
1035
+
1036
+ .dt-stat-inner .label {
1037
+ font-size: 0.625rem;
1038
+ font-weight: 600;
1039
+ color: var(--dt-text-muted);
1040
+ text-transform: uppercase;
1041
+ letter-spacing: 0.12em;
1042
+ }
1043
+
1044
+ .dt-stat-inner .value {
1045
+ font-size: 1.5rem;
1046
+ font-weight: 600;
1047
+ color: var(--dt-accent);
1048
+ line-height: 1.1;
1049
+ white-space: nowrap;
1050
+ overflow: hidden;
1051
+ text-overflow: ellipsis;
1052
+ font-family: var(--font-display, 'Sora', system-ui, sans-serif);
1053
+ }
1054
+
1055
+ .dt-stat-inner .description {
1056
+ font-size: 0.75rem;
1057
+ color: var(--dt-text-secondary);
1058
+ line-height: 1.3;
1059
+ }
1060
+
1061
+ /* Size variants */
1062
+ :host([size='sm']) .dt-stat-inner .value {
1063
+ font-size: 1.125rem;
1064
+ }
1065
+
1066
+ :host([size='sm']) .dt-stat-inner {
1067
+ padding: 8px;
1068
+ }
1069
+
1070
+ :host([size='lg']) .dt-stat-inner .value {
1071
+ font-size: 2rem;
1072
+ }
1073
+
1074
+ :host([size='lg']) .dt-stat-inner {
1075
+ padding: 16px;
1076
+ }
1077
+
1078
+ /* Variant: outlined */
1079
+ :host([variant='outlined']) .dt-stat-inner {
1080
+ background: transparent;
1081
+ border-style: dashed;
1082
+ }
1083
+
1084
+ /* Variant: filled */
1085
+ :host([variant='filled']) .dt-stat-inner {
1086
+ background: var(--dt-accent-subtle);
1087
+ border-style: solid;
1088
+ }
1089
+
1090
+ /* Trend indicators */
1091
+ .dt-stat-inner .trend {
1092
+ display: inline-flex;
1093
+ align-items: center;
1094
+ gap: 3px;
1095
+ font-size: 0.6875rem;
1096
+ font-weight: 600;
1097
+ margin-top: 2px;
1098
+ text-transform: uppercase;
1099
+ letter-spacing: 0.05em;
1100
+ }
1101
+
1102
+ .dt-stat-inner .trend.positive {
1103
+ color: var(--dt-success);
1104
+ }
1105
+
1106
+ .dt-stat-inner .trend.negative {
1107
+ color: var(--dt-danger);
1108
+ }
1109
+
1110
+ .dt-stat-inner .trend.neutral {
1111
+ color: var(--dt-text-muted);
1112
+ }
1113
+ `;
1114
+ var At = "dt-stat-inner";
1115
+ var E = class extends HTMLElement {
1116
+ static get observedAttributes() {
1117
+ return ["label", "value", "description", "size", "variant", "trend", "trend-value"];
1118
+ }
1119
+ _container;
1120
+ _labelEl;
1121
+ _valueEl;
1122
+ _descEl;
1123
+ _trendEl;
1124
+ get label() {
1125
+ return this.getAttribute("label");
1126
+ }
1127
+ set label(t) {
1128
+ t === null ? this.removeAttribute("label") : this.setAttribute("label", t);
1129
+ }
1130
+ get value() {
1131
+ return this.getAttribute("value");
1132
+ }
1133
+ set value(t) {
1134
+ t === null ? this.removeAttribute("value") : this.setAttribute("value", t);
1135
+ }
1136
+ get description() {
1137
+ return this.getAttribute("description");
1138
+ }
1139
+ set description(t) {
1140
+ t === null ? this.removeAttribute("description") : this.setAttribute("description", t);
1141
+ }
1142
+ get size() {
1143
+ let t = this.getAttribute("size");
1144
+ return t === "sm" || t === "lg" ? t : "md";
1145
+ }
1146
+ set size(t) {
1147
+ this.setAttribute("size", t);
1148
+ }
1149
+ get variant() {
1150
+ let t = this.getAttribute("variant");
1151
+ return t === "outlined" || t === "filled" ? t : "default";
1152
+ }
1153
+ set variant(t) {
1154
+ this.setAttribute("variant", t);
1155
+ }
1156
+ get trend() {
1157
+ let t = this.getAttribute("trend");
1158
+ return t === "up" || t === "down" || t === "neutral" ? t : null;
1159
+ }
1160
+ set trend(t) {
1161
+ t === null ? this.removeAttribute("trend") : this.setAttribute("trend", t);
1162
+ }
1163
+ get trendValue() {
1164
+ return this.getAttribute("trend-value");
1165
+ }
1166
+ set trendValue(t) {
1167
+ t === null ? this.removeAttribute("trend-value") : this.setAttribute("trend-value", t);
1168
+ }
1169
+ constructor() {
1170
+ super();
1171
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
1172
+ e.textContent = Q, t.appendChild(e), this._container = document.createElement("div"), this._container.className = At, this._labelEl = document.createElement("div"), this._labelEl.className = "label", this._container.appendChild(this._labelEl), this._valueEl = document.createElement("div"), this._valueEl.className = "value", this._container.appendChild(this._valueEl), this._descEl = document.createElement("div"), this._descEl.className = "description", this._container.appendChild(this._descEl), this._trendEl = document.createElement("div"), this._trendEl.className = "trend", this._container.appendChild(this._trendEl), t.appendChild(this._container), this._render();
1173
+ }
1174
+ attributeChangedCallback(t, e, n) {
1175
+ (t === "label" || t === "value" || t === "description" || t === "size" || t === "variant" || t === "trend" || t === "trend-value") && this._render();
1176
+ }
1177
+ _render() {
1178
+ this._labelEl.textContent = this.label ?? "", this._labelEl.style.display = this.label ? "block" : "none", this._valueEl.textContent = this.value ?? "", this._valueEl.style.display = this.value ? "block" : "none", this._descEl.textContent = this.description ?? "", this._descEl.style.display = this.description ? "block" : "none";
1179
+ let t = this.trend, e = this.trendValue;
1180
+ if (t && e) {
1181
+ this._trendEl.style.display = "inline-flex", this._trendEl.className = `trend ${t === "up" ? "positive" : t === "down" ? "negative" : "neutral"}`;
1182
+ let n = "";
1183
+ t === "up" ? n = "\u2191" : t === "down" ? n = "\u2193" : n = "\u2192", this._trendEl.textContent = `${n} ${e}`;
1184
+ } else this._trendEl.style.display = "none";
1185
+ }
1186
+ };
1187
+ var tt = `:host {
1188
+ display: inline-flex;
1189
+ vertical-align: middle;
1190
+ }
1191
+
1192
+ .dt-badge-inner {
1193
+ display: inline-flex;
1194
+ align-items: center;
1195
+ padding: 2px 6px;
1196
+ border: 1px solid;
1197
+ border-radius: 2px;
1198
+ font-size: 0.6875rem;
1199
+ font-weight: 600;
1200
+ font-family: var(
1201
+ --font-mono,
1202
+ 'SF Mono',
1203
+ Monaco,
1204
+ 'Cascadia Code',
1205
+ 'Roboto Mono',
1206
+ Consolas,
1207
+ monospace
1208
+ );
1209
+ line-height: 1.2;
1210
+ white-space: nowrap;
1211
+ text-transform: uppercase;
1212
+ letter-spacing: 0.1em;
1213
+ }
1214
+
1215
+ /* Variant: accent (default) */
1216
+ :host([variant='accent']) .dt-badge-inner,
1217
+ .dt-badge-inner {
1218
+ background: var(--dt-accent-subtle);
1219
+ border-color: var(--dt-accent);
1220
+ color: var(--dt-accent);
1221
+ }
1222
+
1223
+ /* Variant: success */
1224
+ :host([variant='success']) .dt-badge-inner {
1225
+ background: var(--dt-success-subtle);
1226
+ border-color: var(--dt-success);
1227
+ color: var(--dt-success);
1228
+ }
1229
+
1230
+ /* Variant: danger */
1231
+ :host([variant='danger']) .dt-badge-inner {
1232
+ background: var(--dt-danger-subtle);
1233
+ border-color: var(--dt-danger);
1234
+ color: var(--dt-danger);
1235
+ }
1236
+
1237
+ /* Variant: warning */
1238
+ :host([variant='warning']) .dt-badge-inner {
1239
+ background: var(--dt-warning-subtle);
1240
+ border-color: var(--dt-warning);
1241
+ color: var(--dt-warning);
1242
+ }
1243
+
1244
+ /* Variant: info */
1245
+ :host([variant='info']) .dt-badge-inner {
1246
+ background: var(--dt-info-subtle);
1247
+ border-color: var(--dt-info);
1248
+ color: var(--dt-info);
1249
+ }
1250
+
1251
+ /* Variant: default/neutral */
1252
+ :host([variant='default']) .dt-badge-inner,
1253
+ :host([variant='neutral']) .dt-badge-inner {
1254
+ background: transparent;
1255
+ border-color: var(--dt-border);
1256
+ color: var(--dt-text-secondary);
1257
+ }
1258
+
1259
+ /* Size variants */
1260
+ :host([size='sm']) .dt-badge-inner {
1261
+ padding: 1px 4px;
1262
+ font-size: 0.625rem;
1263
+ }
1264
+
1265
+ :host([size='lg']) .dt-badge-inner {
1266
+ padding: 3px 8px;
1267
+ font-size: 0.75rem;
1268
+ }
1269
+ `;
1270
+ var Mt = "dt-badge-inner";
1271
+ var S = class extends HTMLElement {
1272
+ static get observedAttributes() {
1273
+ return ["variant", "size", "text"];
1274
+ }
1275
+ _container;
1276
+ _slot;
1277
+ get variant() {
1278
+ let t = this.getAttribute("variant");
1279
+ return t === "success" || t === "danger" || t === "warning" || t === "info" || t === "default" || t === "neutral" ? t : "accent";
1280
+ }
1281
+ set variant(t) {
1282
+ this.setAttribute("variant", t);
1283
+ }
1284
+ get size() {
1285
+ let t = this.getAttribute("size");
1286
+ return t === "sm" || t === "lg" ? t : "md";
1287
+ }
1288
+ set size(t) {
1289
+ this.setAttribute("size", t);
1290
+ }
1291
+ get text() {
1292
+ return this.getAttribute("text");
1293
+ }
1294
+ set text(t) {
1295
+ t === null ? this.removeAttribute("text") : this.setAttribute("text", t);
1296
+ }
1297
+ constructor() {
1298
+ super();
1299
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
1300
+ e.textContent = tt, t.appendChild(e), this._container = document.createElement("span"), this._container.className = Mt;
1301
+ let n = this.text;
1302
+ n !== null ? this._container.textContent = n : (this._slot = document.createElement("slot"), this._container.appendChild(this._slot)), t.appendChild(this._container);
1303
+ }
1304
+ attributeChangedCallback(t, e, n) {
1305
+ t === "text" && this._render();
1306
+ }
1307
+ _render() {
1308
+ let t = this.text;
1309
+ t !== null && (this._container.textContent = t);
1310
+ }
1311
+ };
1312
+ var et = `:host {
1313
+ display: inline-flex;
1314
+ vertical-align: middle;
1315
+ }
1316
+
1317
+ .dt-button-inner {
1318
+ display: inline-flex;
1319
+ align-items: center;
1320
+ justify-content: center;
1321
+ gap: 4px;
1322
+ padding: 6px 12px;
1323
+ border: 1px solid var(--dt-accent);
1324
+ border-radius: 2px;
1325
+ font-size: 0.8125rem;
1326
+ font-weight: 600;
1327
+ font-family: var(--font-ui, 'Work Sans', system-ui, sans-serif);
1328
+ line-height: 1.2;
1329
+ cursor: pointer;
1330
+ transition: all 0.1s ease;
1331
+ background: var(--dt-surface);
1332
+ color: var(--dt-accent);
1333
+ text-transform: uppercase;
1334
+ letter-spacing: 0.08em;
1335
+ position: relative;
1336
+ }
1337
+
1338
+ /* Corner accents */
1339
+ .dt-button-inner::before {
1340
+ content: '';
1341
+ position: absolute;
1342
+ top: 0;
1343
+ left: 0;
1344
+ width: 4px;
1345
+ height: 4px;
1346
+ border-top: 1px solid var(--dt-accent);
1347
+ border-left: 1px solid var(--dt-accent);
1348
+ }
1349
+
1350
+ .dt-button-inner::after {
1351
+ content: '';
1352
+ position: absolute;
1353
+ bottom: 0;
1354
+ right: 0;
1355
+ width: 4px;
1356
+ height: 4px;
1357
+ border-bottom: 1px solid var(--dt-accent);
1358
+ border-right: 1px solid var(--dt-accent);
1359
+ }
1360
+
1361
+ .dt-button-inner:hover:not(:disabled) {
1362
+ background: var(--dt-accent);
1363
+ color: var(--dt-text-on-accent);
1364
+ }
1365
+
1366
+ .dt-button-inner:hover:not(:disabled)::before,
1367
+ .dt-button-inner:hover:not(:disabled)::after {
1368
+ border-color: var(--dt-text-on-accent);
1369
+ }
1370
+
1371
+ .dt-button-inner:active:not(:disabled) {
1372
+ background: var(--dt-accent-active);
1373
+ }
1374
+
1375
+ .dt-button-inner:disabled {
1376
+ opacity: 0.4;
1377
+ cursor: not-allowed;
1378
+ border-color: var(--dt-border);
1379
+ color: var(--dt-text-muted);
1380
+ }
1381
+
1382
+ .dt-button-inner:disabled::before,
1383
+ .dt-button-inner:disabled::after {
1384
+ border-color: var(--dt-border);
1385
+ }
1386
+
1387
+ /* Variant: primary - filled accent */
1388
+ :host([variant='primary']) .dt-button-inner {
1389
+ background: var(--dt-accent);
1390
+ color: var(--dt-text-on-accent);
1391
+ }
1392
+
1393
+ :host([variant='primary']) .dt-button-inner:hover:not(:disabled) {
1394
+ background: var(--dt-accent-hover);
1395
+ }
1396
+
1397
+ /* Variant: secondary - outlined */
1398
+ :host([variant='secondary']) .dt-button-inner {
1399
+ background: transparent;
1400
+ border-color: var(--dt-border);
1401
+ color: var(--dt-text);
1402
+ }
1403
+
1404
+ :host([variant='secondary']) .dt-button-inner:hover:not(:disabled) {
1405
+ background: var(--dt-surface-hover);
1406
+ border-color: var(--dt-accent);
1407
+ color: var(--dt-accent);
1408
+ }
1409
+
1410
+ /* Variant: ghost - minimal */
1411
+ :host([variant='ghost']) .dt-button-inner {
1412
+ background: transparent;
1413
+ border-color: transparent;
1414
+ color: var(--dt-text-secondary);
1415
+ }
1416
+
1417
+ :host([variant='ghost']) .dt-button-inner:hover:not(:disabled) {
1418
+ background: var(--dt-surface);
1419
+ border-color: var(--dt-border);
1420
+ color: var(--dt-text);
1421
+ }
1422
+
1423
+ :host([variant='ghost']) .dt-button-inner::before,
1424
+ :host([variant='ghost']) .dt-button-inner::after {
1425
+ display: none;
1426
+ }
1427
+
1428
+ /* Variant: danger */
1429
+ :host([variant='danger']) .dt-button-inner {
1430
+ background: transparent;
1431
+ border-color: var(--dt-danger);
1432
+ color: var(--dt-danger);
1433
+ }
1434
+
1435
+ :host([variant='danger']) .dt-button-inner:hover:not(:disabled) {
1436
+ background: var(--dt-danger);
1437
+ color: var(--dt-text-on-accent);
1438
+ }
1439
+
1440
+ :host([variant='danger']) .dt-button-inner::before,
1441
+ :host([variant='danger']) .dt-button-inner::after {
1442
+ border-color: var(--dt-danger);
1443
+ }
1444
+
1445
+ :host([variant='danger']) .dt-button-inner:hover:not(:disabled)::before,
1446
+ :host([variant='danger']) .dt-button-inner:hover:not(:disabled)::after {
1447
+ border-color: var(--dt-text-on-accent);
1448
+ }
1449
+
1450
+ /* Size: sm */
1451
+ :host([size='sm']) .dt-button-inner {
1452
+ padding: 4px 8px;
1453
+ font-size: 0.75rem;
1454
+ }
1455
+
1456
+ /* Size: lg */
1457
+ :host([size='lg']) .dt-button-inner {
1458
+ padding: 8px 16px;
1459
+ font-size: 0.875rem;
1460
+ }
1461
+
1462
+ :host([fullwidth]) .dt-button-inner {
1463
+ width: 100%;
1464
+ }
1465
+
1466
+ ::slotted([slot='icon']) {
1467
+ display: inline-flex;
1468
+ width: 1em;
1469
+ height: 1em;
1470
+ }
1471
+ `;
1472
+ var Tt = "dt-button-inner";
1473
+ var D = class extends HTMLElement {
1474
+ static get observedAttributes() {
1475
+ return ["variant", "size", "disabled", "fullwidth", "type"];
1476
+ }
1477
+ _button;
1478
+ _slot;
1479
+ get variant() {
1480
+ let t = this.getAttribute("variant");
1481
+ return t === "secondary" || t === "ghost" || t === "danger" ? t : "primary";
1482
+ }
1483
+ set variant(t) {
1484
+ this.setAttribute("variant", t);
1485
+ }
1486
+ get size() {
1487
+ let t = this.getAttribute("size");
1488
+ return t === "sm" || t === "lg" ? t : "md";
1489
+ }
1490
+ set size(t) {
1491
+ this.setAttribute("size", t);
1492
+ }
1493
+ get disabled() {
1494
+ return this.hasAttribute("disabled");
1495
+ }
1496
+ set disabled(t) {
1497
+ t ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
1498
+ }
1499
+ get fullwidth() {
1500
+ return this.hasAttribute("fullwidth");
1501
+ }
1502
+ set fullwidth(t) {
1503
+ t ? this.setAttribute("fullwidth", "") : this.removeAttribute("fullwidth");
1504
+ }
1505
+ get type() {
1506
+ let t = this.getAttribute("type");
1507
+ return t === "submit" || t === "reset" ? t : "button";
1508
+ }
1509
+ set type(t) {
1510
+ this.setAttribute("type", t);
1511
+ }
1512
+ constructor() {
1513
+ super();
1514
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
1515
+ e.textContent = et, t.appendChild(e), this._button = document.createElement("button"), this._button.className = Tt, this._button.type = this.type, this._button.disabled = this.disabled, this._slot = document.createElement("slot"), this._button.appendChild(this._slot), t.appendChild(this._button);
1516
+ }
1517
+ attributeChangedCallback(t, e, n) {
1518
+ switch (t) {
1519
+ case "disabled":
1520
+ this._button.disabled = this.disabled;
1521
+ break;
1522
+ case "type":
1523
+ this._button.type = this.type;
1524
+ break;
1525
+ }
1526
+ }
1527
+ };
1528
+ var nt = `:host {
1529
+ display: block;
1530
+ }
1531
+
1532
+ .dt-divider-inner {
1533
+ border: none;
1534
+ margin: 0;
1535
+ flex-shrink: 0;
1536
+ }
1537
+
1538
+ /* Horizontal (default) */
1539
+ :host([direction='horizontal']) .dt-divider-inner,
1540
+ .dt-divider-inner {
1541
+ width: 100%;
1542
+ height: 1px;
1543
+ background: var(--dt-accent);
1544
+ opacity: 0.5;
1545
+ }
1546
+
1547
+ /* Vertical */
1548
+ :host([direction='vertical']) .dt-divider-inner {
1549
+ width: 1px;
1550
+ height: 100%;
1551
+ min-height: 1em;
1552
+ background: var(--dt-accent);
1553
+ opacity: 0.5;
1554
+ }
1555
+
1556
+ /* Style variants */
1557
+ :host([style-variant='subtle']) .dt-divider-inner {
1558
+ background: var(--dt-border);
1559
+ opacity: 1;
1560
+ }
1561
+
1562
+ :host([style-variant='strong']) .dt-divider-inner {
1563
+ background: var(--dt-accent);
1564
+ opacity: 1;
1565
+ height: 2px;
1566
+ }
1567
+
1568
+ :host([direction='vertical'][style-variant='strong']) .dt-divider-inner {
1569
+ width: 2px;
1570
+ height: 100%;
1571
+ }
1572
+
1573
+ /* Spacing */
1574
+ :host([spacing='sm']) .dt-divider-inner {
1575
+ margin: 6px 0;
1576
+ }
1577
+ :host([spacing='md']) .dt-divider-inner {
1578
+ margin: 12px 0;
1579
+ }
1580
+ :host([spacing='lg']) .dt-divider-inner {
1581
+ margin: 18px 0;
1582
+ }
1583
+
1584
+ :host([direction='vertical'][spacing='sm']) .dt-divider-inner {
1585
+ margin: 0 6px;
1586
+ }
1587
+ :host([direction='vertical'][spacing='md']) .dt-divider-inner {
1588
+ margin: 0 12px;
1589
+ }
1590
+ :host([direction='vertical'][spacing='lg']) .dt-divider-inner {
1591
+ margin: 0 18px;
1592
+ }
1593
+ `;
1594
+ var zt = "dt-divider-inner";
1595
+ var A = class extends HTMLElement {
1596
+ static get observedAttributes() {
1597
+ return ["direction", "style-variant", "spacing"];
1598
+ }
1599
+ get direction() {
1600
+ return this.getAttribute("direction") === "vertical" ? "vertical" : "horizontal";
1601
+ }
1602
+ set direction(t) {
1603
+ this.setAttribute("direction", t);
1604
+ }
1605
+ get styleVariant() {
1606
+ let t = this.getAttribute("style-variant");
1607
+ return t === "subtle" || t === "strong" ? t : "default";
1608
+ }
1609
+ set styleVariant(t) {
1610
+ this.setAttribute("style-variant", t);
1611
+ }
1612
+ get spacing() {
1613
+ let t = this.getAttribute("spacing");
1614
+ return t === "sm" || t === "md" || t === "lg" ? t : null;
1615
+ }
1616
+ set spacing(t) {
1617
+ t === null ? this.removeAttribute("spacing") : this.setAttribute("spacing", t);
1618
+ }
1619
+ constructor() {
1620
+ super();
1621
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
1622
+ e.textContent = nt, t.appendChild(e);
1623
+ let n = document.createElement("hr");
1624
+ n.className = zt, t.appendChild(n);
1625
+ }
1626
+ };
1627
+ var rt = `:host {
1628
+ display: block;
1629
+ min-height: 180px;
1630
+ color: var(--dt-text);
1631
+ font-family: var(
1632
+ --font-mono,
1633
+ 'SF Mono',
1634
+ Monaco,
1635
+ 'Cascadia Code',
1636
+ 'Roboto Mono',
1637
+ Consolas,
1638
+ monospace
1639
+ );
1640
+ }
1641
+
1642
+ .dt-table-view {
1643
+ display: flex;
1644
+ flex-direction: column;
1645
+ min-height: inherit;
1646
+ height: 100%;
1647
+ overflow: hidden;
1648
+ background: var(--dt-surface);
1649
+ border: 1px solid var(--dt-border);
1650
+ border-radius: 2px;
1651
+ position: relative;
1652
+ }
1653
+
1654
+ .dt-table-view::before,
1655
+ .dt-table-view::after {
1656
+ content: '';
1657
+ position: absolute;
1658
+ width: 8px;
1659
+ height: 8px;
1660
+ pointer-events: none;
1661
+ z-index: 3;
1662
+ }
1663
+
1664
+ .dt-table-view::before {
1665
+ top: -1px;
1666
+ left: -1px;
1667
+ border-top: 2px solid var(--dt-accent);
1668
+ border-left: 2px solid var(--dt-accent);
1669
+ }
1670
+
1671
+ .dt-table-view::after {
1672
+ right: -1px;
1673
+ bottom: -1px;
1674
+ border-right: 2px solid var(--dt-accent);
1675
+ border-bottom: 2px solid var(--dt-accent);
1676
+ }
1677
+
1678
+ .dt-table-scroll {
1679
+ min-height: inherit;
1680
+ height: 100%;
1681
+ overflow: auto;
1682
+ }
1683
+
1684
+ .dt-table-header,
1685
+ .dt-table-row {
1686
+ display: grid;
1687
+ grid-template-columns: var(--dt-table-columns, minmax(0, 1fr));
1688
+ min-width: fit-content;
1689
+ }
1690
+
1691
+ .dt-table-header {
1692
+ position: sticky;
1693
+ top: 0;
1694
+ z-index: 2;
1695
+ background: color-mix(in srgb, var(--dt-surface) 88%, var(--dt-accent) 12%);
1696
+ border-bottom: 1px solid var(--dt-border);
1697
+ }
1698
+
1699
+ .dt-table-header-cell,
1700
+ .dt-table-cell {
1701
+ min-width: 0;
1702
+ padding: 10px 12px;
1703
+ overflow: hidden;
1704
+ text-overflow: ellipsis;
1705
+ white-space: nowrap;
1706
+ font-size: 0.8125rem;
1707
+ }
1708
+
1709
+ .dt-table-header-cell {
1710
+ color: var(--dt-accent);
1711
+ font-size: 0.75rem;
1712
+ font-weight: 600;
1713
+ letter-spacing: 0.1em;
1714
+ text-transform: uppercase;
1715
+ }
1716
+
1717
+ .dt-table-header-cell--sortable {
1718
+ cursor: pointer;
1719
+ user-select: none;
1720
+ }
1721
+
1722
+ .dt-table-header-cell--sortable:hover {
1723
+ background: var(--dt-surface-hover);
1724
+ }
1725
+
1726
+ .dt-table-header-label {
1727
+ display: inline-flex;
1728
+ align-items: center;
1729
+ gap: 6px;
1730
+ }
1731
+
1732
+ .dt-table-sort-indicator {
1733
+ color: var(--dt-text-secondary);
1734
+ font-size: 0.7rem;
1735
+ }
1736
+
1737
+ .dt-table-body {
1738
+ position: relative;
1739
+ }
1740
+
1741
+ .dt-table-canvas {
1742
+ position: relative;
1743
+ }
1744
+
1745
+ .dt-table-row {
1746
+ position: absolute;
1747
+ left: 0;
1748
+ right: 0;
1749
+ border-bottom: 1px solid var(--dt-border-subtle);
1750
+ }
1751
+
1752
+ .dt-table-row--clickable {
1753
+ cursor: pointer;
1754
+ }
1755
+
1756
+ .dt-table-row--clickable:hover {
1757
+ background: var(--dt-surface-hover);
1758
+ }
1759
+
1760
+ :host([striped]) .dt-table-row:nth-child(even) {
1761
+ background: color-mix(in srgb, var(--dt-surface) 92%, var(--dt-accent) 8%);
1762
+ }
1763
+
1764
+ :host([bordered]) .dt-table-header-cell,
1765
+ :host([bordered]) .dt-table-cell {
1766
+ border-right: 1px solid var(--dt-border-subtle);
1767
+ }
1768
+
1769
+ :host([bordered]) .dt-table-header-cell:last-child,
1770
+ :host([bordered]) .dt-table-cell:last-child {
1771
+ border-right: 0;
1772
+ }
1773
+
1774
+ .dt-table-cell[data-align='center'],
1775
+ .dt-table-header-cell[data-align='center'] {
1776
+ text-align: center;
1777
+ }
1778
+
1779
+ .dt-table-cell[data-align='right'],
1780
+ .dt-table-header-cell[data-align='right'] {
1781
+ text-align: right;
1782
+ }
1783
+
1784
+ .dt-table-empty {
1785
+ display: flex;
1786
+ align-items: center;
1787
+ justify-content: center;
1788
+ min-height: 140px;
1789
+ padding: 20px;
1790
+ color: var(--dt-text-muted);
1791
+ text-transform: uppercase;
1792
+ letter-spacing: 0.08em;
1793
+ font-size: 0.75rem;
1794
+ }
1795
+ `;
1796
+ function Lt(r) {
1797
+ return r == null || r === false ? null : r === true ? "" : String(r);
1798
+ }
1799
+ function Ht(r, t) {
1800
+ let e = r.querySelectorAll("*");
1801
+ for (let n of e) {
1802
+ let i = n.getAttribute("data-field");
1803
+ if (i) {
1804
+ let s = t[i];
1805
+ n.textContent = s == null ? "" : String(s);
1806
+ }
1807
+ for (let s of n.getAttributeNames()) {
1808
+ if (s === "data-field" || !s.startsWith("data-field-")) continue;
1809
+ let o = s.slice(11);
1810
+ if (!o) continue;
1811
+ let a = n.getAttribute(s);
1812
+ if (!a) continue;
1813
+ let d = Lt(t[a]);
1814
+ d === null ? n.removeAttribute(o) : n.setAttribute(o, d);
1815
+ }
1816
+ }
1817
+ }
1818
+ function M(r, t) {
1819
+ let e = r.content.cloneNode(true);
1820
+ return Ht(e, t), e;
1821
+ }
1822
+ var m = class {
1823
+ _count = 0;
1824
+ _estimateSize = 56;
1825
+ _overscan = 5;
1826
+ _fixedSize = null;
1827
+ _viewportHeight = 0;
1828
+ _scrollTop = 0;
1829
+ _sizes = /* @__PURE__ */ new Map();
1830
+ constructor(t = {}) {
1831
+ this._count = t.count ?? 0, this._estimateSize = t.estimateSize ?? 56, this._overscan = t.overscan ?? 5, this._fixedSize = t.fixedSize ?? null;
1832
+ }
1833
+ setCount(t) {
1834
+ this._count = Math.max(0, t);
1835
+ for (let e of this._sizes.keys()) e >= this._count && this._sizes.delete(e);
1836
+ }
1837
+ setViewportHeight(t) {
1838
+ this._viewportHeight = Math.max(0, t);
1839
+ }
1840
+ setScrollTop(t) {
1841
+ this._scrollTop = Math.max(0, t);
1842
+ }
1843
+ setEstimateSize(t) {
1844
+ this._estimateSize = Math.max(1, t);
1845
+ }
1846
+ setFixedSize(t) {
1847
+ this._fixedSize = t && t > 0 ? t : null;
1848
+ }
1849
+ resetMeasurements() {
1850
+ this._sizes.clear();
1851
+ }
1852
+ measure(t, e) {
1853
+ if (this._fixedSize !== null || t < 0 || t >= this._count) return 0;
1854
+ let n = Math.max(1, Math.round(e)), i = this._sizes.get(t);
1855
+ return i === n ? 0 : (this._sizes.set(t, n), this.getOffset(t + 1) <= this._scrollTop ? n - (i ?? this._estimateSize) : 0);
1856
+ }
1857
+ getOffset(t) {
1858
+ if (t <= 0) return 0;
1859
+ let e = Math.min(t, this._count);
1860
+ if (this._fixedSize !== null) return e * this._fixedSize;
1861
+ let n = 0;
1862
+ for (let i = 0; i < e; i += 1) n += this._sizes.get(i) ?? this._estimateSize;
1863
+ return n;
1864
+ }
1865
+ getTotalHeight() {
1866
+ return this.getOffset(this._count);
1867
+ }
1868
+ getRange() {
1869
+ if (this._count === 0) return { start: 0, end: 0, paddingTop: 0, paddingBottom: 0, totalHeight: 0 };
1870
+ if (this._fixedSize !== null) {
1871
+ let d = Math.max(1, Math.ceil(this._viewportHeight / this._fixedSize)), c = Math.max(0, Math.floor(this._scrollTop / this._fixedSize) - this._overscan), l = Math.min(this._count, c + d + this._overscan * 2), f = c * this._fixedSize, _ = this._count * this._fixedSize, h = Math.max(0, _ - f - (l - c) * this._fixedSize);
1872
+ return { start: c, end: l, paddingTop: f, paddingBottom: h, totalHeight: _ };
1873
+ }
1874
+ let t = 0, e = 0;
1875
+ for (; t < this._count; ) {
1876
+ let d = this._sizes.get(t) ?? this._estimateSize;
1877
+ if (e + d > this._scrollTop) break;
1878
+ e += d, t += 1;
1879
+ }
1880
+ t = Math.max(0, t - this._overscan);
1881
+ let n = this.getOffset(t), i = t, s = 0;
1882
+ for (; i < this._count && s < this._viewportHeight; ) s += this._sizes.get(i) ?? this._estimateSize, i += 1;
1883
+ i = Math.min(this._count, i + this._overscan);
1884
+ let o = this.getTotalHeight(), a = Math.max(0, o - this.getOffset(i));
1885
+ return { start: t, end: i, paddingTop: n, paddingBottom: a, totalHeight: o };
1886
+ }
1887
+ };
1888
+ function Rt(r) {
1889
+ return r && typeof r == "object" ? r : { value: r };
1890
+ }
1891
+ function Vt(r) {
1892
+ return r === "center" || r === "right" ? r : "left";
1893
+ }
1894
+ var b = class extends HTMLElement {
1895
+ static get observedAttributes() {
1896
+ return ["field", "header", "width", "min-width", "align"];
1897
+ }
1898
+ get field() {
1899
+ return this.getAttribute("field") ?? "";
1900
+ }
1901
+ get header() {
1902
+ return this.getAttribute("header") ?? this.field;
1903
+ }
1904
+ get width() {
1905
+ return this.getAttribute("width") ?? "auto";
1906
+ }
1907
+ get minWidth() {
1908
+ return this.getAttribute("min-width") ?? "0";
1909
+ }
1910
+ get align() {
1911
+ return Vt(this.getAttribute("align"));
1912
+ }
1913
+ connectedCallback() {
1914
+ this.hidden = true;
1915
+ }
1916
+ attributeChangedCallback() {
1917
+ this.dispatchEvent(new CustomEvent("dt-column-change", { bubbles: true, composed: true }));
1918
+ }
1919
+ };
1920
+ var T = class extends HTMLElement {
1921
+ _rows = [];
1922
+ _columns = [];
1923
+ _virtualizer = new m({ estimateSize: 40, overscan: 5, fixedSize: 40 });
1924
+ _root;
1925
+ _scroll;
1926
+ _header;
1927
+ _body;
1928
+ _canvas;
1929
+ _emptyState;
1930
+ _resizeObserver = null;
1931
+ _mutationObserver = null;
1932
+ _sortField = null;
1933
+ _sortDirection = "asc";
1934
+ static get observedAttributes() {
1935
+ return ["row-height", "sortable", "striped", "bordered", "empty-text"];
1936
+ }
1937
+ get rows() {
1938
+ return this._rows;
1939
+ }
1940
+ set rows(t) {
1941
+ this._rows = Array.isArray(t) ? t : [], this._virtualizer.setCount(this._rows.length), this._render();
1942
+ }
1943
+ get rowHeight() {
1944
+ let t = Number(this.getAttribute("row-height") ?? "40");
1945
+ return Number.isFinite(t) && t > 0 ? t : 40;
1946
+ }
1947
+ set rowHeight(t) {
1948
+ this.setAttribute("row-height", String(t));
1949
+ }
1950
+ get sortable() {
1951
+ return this.hasAttribute("sortable");
1952
+ }
1953
+ get emptyText() {
1954
+ return this.getAttribute("empty-text") ?? "No data";
1955
+ }
1956
+ constructor() {
1957
+ super();
1958
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
1959
+ e.textContent = rt, t.appendChild(e), this._root = document.createElement("div"), this._root.className = "dt-table-view", this._scroll = document.createElement("div"), this._scroll.className = "dt-table-scroll", this._scroll.addEventListener("scroll", this._onScroll, { passive: true }), this._header = document.createElement("div"), this._header.className = "dt-table-header", this._body = document.createElement("div"), this._body.className = "dt-table-body", this._canvas = document.createElement("div"), this._canvas.className = "dt-table-canvas", this._emptyState = document.createElement("div"), this._emptyState.className = "dt-table-empty", this._body.append(this._canvas, this._emptyState), this._scroll.append(this._header, this._body), this._root.appendChild(this._scroll), t.appendChild(this._root);
1960
+ }
1961
+ connectedCallback() {
1962
+ this._virtualizer.setFixedSize(this.rowHeight), this._virtualizer.setEstimateSize(this.rowHeight), this._syncColumns(), this._resizeObserver = new ResizeObserver((t) => {
1963
+ for (let e of t) if (e.target === this._scroll) {
1964
+ let n = this._header.offsetHeight;
1965
+ this._virtualizer.setViewportHeight(Math.max(0, e.contentRect.height - n)), this._render();
1966
+ }
1967
+ }), this._resizeObserver.observe(this._scroll), this._mutationObserver = new MutationObserver(() => {
1968
+ this._syncColumns(), this._render();
1969
+ }), this._mutationObserver.observe(this, { childList: true, subtree: true, attributes: true, attributeFilter: ["field", "header", "width", "min-width", "align"] }), this._virtualizer.setCount(this._rows.length), this._virtualizer.setViewportHeight(Math.max(0, this._scroll.clientHeight - this._header.offsetHeight)), this._render();
1970
+ }
1971
+ disconnectedCallback() {
1972
+ this._scroll.removeEventListener("scroll", this._onScroll), this._resizeObserver?.disconnect(), this._mutationObserver?.disconnect(), this._resizeObserver = null, this._mutationObserver = null;
1973
+ }
1974
+ attributeChangedCallback(t) {
1975
+ t === "row-height" && (this._virtualizer.setFixedSize(this.rowHeight), this._virtualizer.setEstimateSize(this.rowHeight)), this._render();
1976
+ }
1977
+ _onScroll = () => {
1978
+ this._virtualizer.setScrollTop(Math.max(0, this._scroll.scrollTop - this._header.offsetHeight)), this._renderBody();
1979
+ };
1980
+ _syncColumns() {
1981
+ this._columns = Array.from(this.children).filter((t) => t instanceof b).map((t) => ({ field: t.field, header: t.header, width: t.width, minWidth: t.minWidth, align: t.align, template: Array.from(t.children).find((e) => e instanceof HTMLTemplateElement) ?? null })).filter((t) => t.field);
1982
+ }
1983
+ _render() {
1984
+ if (!this.isConnected) return;
1985
+ this._emptyState.textContent = this.emptyText;
1986
+ let t = this._columns.length > 0 ? this._columns.map((e) => this._toGridColumn(e)).join(" ") : "minmax(0, 1fr)";
1987
+ this._header.style.setProperty("--dt-table-columns", t), this._canvas.style.setProperty("--dt-table-columns", t), this._renderHeader(), this._renderBody();
1988
+ }
1989
+ _renderHeader() {
1990
+ let t = document.createDocumentFragment();
1991
+ for (let e of this._columns) {
1992
+ let n = document.createElement("div");
1993
+ n.className = "dt-table-header-cell", n.dataset.align = e.align, this.sortable && (n.classList.add("dt-table-header-cell--sortable"), n.tabIndex = 0, n.setAttribute("role", "button"), n.setAttribute("aria-label", `Sort by ${e.header}`), n.addEventListener("click", () => this._requestSort(e.field)), n.addEventListener("keydown", (s) => {
1994
+ (s.key === "Enter" || s.key === " ") && (s.preventDefault(), this._requestSort(e.field));
1995
+ }));
1996
+ let i = document.createElement("span");
1997
+ if (i.className = "dt-table-header-label", i.textContent = e.header, this.sortable) {
1998
+ let s = document.createElement("span");
1999
+ s.className = "dt-table-sort-indicator", this._sortField === e.field ? s.textContent = this._sortDirection === "asc" ? "\u25B2" : "\u25BC" : s.textContent = "\u2195", i.appendChild(s);
2000
+ }
2001
+ n.appendChild(i), t.appendChild(n);
2002
+ }
2003
+ this._header.replaceChildren(t);
2004
+ }
2005
+ _renderBody() {
2006
+ if (this._rows.length === 0 || this._columns.length === 0) {
2007
+ this._emptyState.hidden = false, this._canvas.replaceChildren(), this._body.style.height = "140px", this._canvas.style.height = "0px";
2008
+ return;
2009
+ }
2010
+ this._emptyState.hidden = true, this._virtualizer.setCount(this._rows.length), this._virtualizer.setScrollTop(Math.max(0, this._scroll.scrollTop - this._header.offsetHeight)), this._virtualizer.setViewportHeight(Math.max(0, this._scroll.clientHeight - this._header.offsetHeight));
2011
+ let t = this._virtualizer.getRange();
2012
+ this._body.style.height = `${Math.max(t.totalHeight, this._scroll.clientHeight - this._header.offsetHeight)}px`, this._canvas.style.height = `${t.totalHeight}px`;
2013
+ let e = document.createDocumentFragment();
2014
+ for (let n = t.start; n < t.end; n += 1) e.appendChild(this._renderRow(n));
2015
+ this._canvas.replaceChildren(e);
2016
+ }
2017
+ _renderRow(t) {
2018
+ let e = this._rows[t], n = document.createElement("div");
2019
+ n.className = "dt-table-row dt-table-row--clickable", n.style.top = `${this._virtualizer.getOffset(t)}px`, n.style.height = `${this.rowHeight}px`, n.style.setProperty("--dt-table-columns", this._header.style.getPropertyValue("--dt-table-columns")), n.addEventListener("click", () => {
2020
+ this.dispatchEvent(new CustomEvent("dt-row-click", { detail: { row: e, index: t }, bubbles: true, composed: true }));
2021
+ });
2022
+ let i = Rt(e);
2023
+ for (let s of this._columns) {
2024
+ let o = document.createElement("div");
2025
+ if (o.className = "dt-table-cell", o.dataset.align = s.align, s.template) o.appendChild(M(s.template, i));
2026
+ else {
2027
+ let a = i[s.field];
2028
+ o.textContent = a == null ? "" : String(a);
2029
+ }
2030
+ n.appendChild(o);
2031
+ }
2032
+ return n;
2033
+ }
2034
+ _requestSort(t) {
2035
+ this._sortField === t ? this._sortDirection = this._sortDirection === "asc" ? "desc" : "asc" : (this._sortField = t, this._sortDirection = "asc"), this._renderHeader(), this.dispatchEvent(new CustomEvent("dt-sort", { detail: { field: t, direction: this._sortDirection }, bubbles: true, composed: true }));
2036
+ }
2037
+ _toGridColumn(t) {
2038
+ let e = /^\d+$/.test(t.minWidth) ? `${t.minWidth}px` : t.minWidth;
2039
+ if (t.width === "auto") return `minmax(${e}, 1fr)`;
2040
+ let n = /^\d+$/.test(t.width) ? `${t.width}px` : t.width;
2041
+ return `minmax(${e}, ${n})`;
2042
+ }
2043
+ };
2044
+ var it = `:host {
2045
+ display: block;
2046
+ min-height: 120px;
2047
+ color: var(--dt-text);
2048
+ font-family: var(
2049
+ --font-mono,
2050
+ 'SF Mono',
2051
+ Monaco,
2052
+ 'Cascadia Code',
2053
+ 'Roboto Mono',
2054
+ Consolas,
2055
+ monospace
2056
+ );
2057
+ }
2058
+
2059
+ .dt-list-view {
2060
+ position: relative;
2061
+ display: block;
2062
+ min-height: inherit;
2063
+ height: 100%;
2064
+ overflow: auto;
2065
+ background: var(--dt-surface);
2066
+ border: 1px solid var(--dt-border);
2067
+ border-radius: 2px;
2068
+ }
2069
+
2070
+ .dt-list-view::before,
2071
+ .dt-list-view::after {
2072
+ content: '';
2073
+ position: sticky;
2074
+ z-index: 2;
2075
+ width: 8px;
2076
+ height: 8px;
2077
+ pointer-events: none;
2078
+ }
2079
+
2080
+ .dt-list-view::before {
2081
+ top: 0;
2082
+ left: 0;
2083
+ display: block;
2084
+ border-top: 2px solid var(--dt-accent);
2085
+ border-left: 2px solid var(--dt-accent);
2086
+ }
2087
+
2088
+ .dt-list-view::after {
2089
+ right: 0;
2090
+ bottom: 0;
2091
+ float: right;
2092
+ border-right: 2px solid var(--dt-accent);
2093
+ border-bottom: 2px solid var(--dt-accent);
2094
+ }
2095
+
2096
+ .dt-list-spacer {
2097
+ position: relative;
2098
+ min-height: 100%;
2099
+ }
2100
+
2101
+ .dt-list-items {
2102
+ position: relative;
2103
+ }
2104
+
2105
+ .dt-list-item {
2106
+ box-sizing: border-box;
2107
+ width: 100%;
2108
+ padding: 12px;
2109
+ color: inherit;
2110
+ }
2111
+
2112
+ .dt-list-item--interactive {
2113
+ cursor: pointer;
2114
+ }
2115
+
2116
+ .dt-list-item--interactive:hover {
2117
+ background: var(--dt-surface-hover);
2118
+ }
2119
+
2120
+ .dt-list-item--selected {
2121
+ background: var(--dt-accent-subtle);
2122
+ }
2123
+
2124
+ :host([dividers]) .dt-list-item {
2125
+ border-bottom: 1px solid var(--dt-border-subtle);
2126
+ }
2127
+
2128
+ :host([dividers]) .dt-list-item:last-child {
2129
+ border-bottom: 0;
2130
+ }
2131
+
2132
+ .dt-list-empty {
2133
+ display: flex;
2134
+ align-items: center;
2135
+ justify-content: center;
2136
+ min-height: 120px;
2137
+ padding: 20px;
2138
+ color: var(--dt-text-muted);
2139
+ text-transform: uppercase;
2140
+ letter-spacing: 0.08em;
2141
+ font-size: 0.75rem;
2142
+ }
2143
+ `;
2144
+ var st = 56;
2145
+ function Pt(r) {
2146
+ return r && typeof r == "object" ? r : { value: r };
2147
+ }
2148
+ var z = class extends HTMLElement {
2149
+ _items = [];
2150
+ _selectedIndices = /* @__PURE__ */ new Set();
2151
+ _renderItem = null;
2152
+ _virtualizer = new m({ estimateSize: st, overscan: 5 });
2153
+ _viewport;
2154
+ _spacer;
2155
+ _itemsLayer;
2156
+ _emptyState;
2157
+ _resizeObserver = null;
2158
+ _itemResizeObserver = null;
2159
+ static get observedAttributes() {
2160
+ return ["item-height", "dividers", "selectable", "empty-text"];
2161
+ }
2162
+ get items() {
2163
+ return this._items;
2164
+ }
2165
+ set items(t) {
2166
+ this._items = Array.isArray(t) ? t : [], this._selectedIndices = new Set([...this._selectedIndices].filter((e) => e < this._items.length)), this._virtualizer.setCount(this._items.length), this._syncSizingMode(true), this._render();
2167
+ }
2168
+ get selectedItems() {
2169
+ return [...this._selectedIndices].sort((t, e) => t - e).map((t) => this._items[t]);
2170
+ }
2171
+ get renderItem() {
2172
+ return this._renderItem;
2173
+ }
2174
+ set renderItem(t) {
2175
+ this._renderItem = typeof t == "function" ? t : null, this._render();
2176
+ }
2177
+ get itemHeight() {
2178
+ let t = this.getAttribute("item-height");
2179
+ if (!t) return null;
2180
+ let e = Number(t);
2181
+ return Number.isFinite(e) && e > 0 ? e : null;
2182
+ }
2183
+ set itemHeight(t) {
2184
+ if (t === null || t <= 0) {
2185
+ this.removeAttribute("item-height");
2186
+ return;
2187
+ }
2188
+ this.setAttribute("item-height", String(t));
2189
+ }
2190
+ get selectable() {
2191
+ let t = this.getAttribute("selectable");
2192
+ return t === "single" || t === "multi" ? t : "none";
2193
+ }
2194
+ set selectable(t) {
2195
+ this.setAttribute("selectable", t);
2196
+ }
2197
+ get emptyText() {
2198
+ return this.getAttribute("empty-text") ?? "No items";
2199
+ }
2200
+ set emptyText(t) {
2201
+ this.setAttribute("empty-text", t);
2202
+ }
2203
+ constructor() {
2204
+ super();
2205
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
2206
+ e.textContent = it, t.appendChild(e), this._viewport = document.createElement("div"), this._viewport.className = "dt-list-view", this._viewport.addEventListener("scroll", this._onScroll, { passive: true }), this._spacer = document.createElement("div"), this._spacer.className = "dt-list-spacer", this._itemsLayer = document.createElement("div"), this._itemsLayer.className = "dt-list-items", this._emptyState = document.createElement("div"), this._emptyState.className = "dt-list-empty", this._spacer.append(this._itemsLayer, this._emptyState), this._viewport.appendChild(this._spacer), t.appendChild(this._viewport);
2207
+ }
2208
+ connectedCallback() {
2209
+ this._resizeObserver = new ResizeObserver((t) => {
2210
+ for (let e of t) e.target === this._viewport && (this._virtualizer.setViewportHeight(e.contentRect.height), this._render());
2211
+ }), this._resizeObserver.observe(this._viewport), this._itemResizeObserver = new ResizeObserver((t) => {
2212
+ let e = 0;
2213
+ for (let n of t) {
2214
+ let i = n.target, s = Number(i.dataset.index);
2215
+ Number.isFinite(s) && (e += this._virtualizer.measure(s, n.contentRect.height));
2216
+ }
2217
+ e !== 0 && (this._viewport.scrollTop += e), t.length > 0 && this._render();
2218
+ }), this._virtualizer.setCount(this._items.length), this._virtualizer.setViewportHeight(this._viewport.clientHeight), this._syncSizingMode(false), this._render();
2219
+ }
2220
+ disconnectedCallback() {
2221
+ this._viewport.removeEventListener("scroll", this._onScroll), this._resizeObserver?.disconnect(), this._itemResizeObserver?.disconnect(), this._resizeObserver = null, this._itemResizeObserver = null;
2222
+ }
2223
+ attributeChangedCallback(t) {
2224
+ t === "item-height" && this._syncSizingMode(true), t === "selectable" && this.selectable === "none" && this._selectedIndices.size > 0 && (this._selectedIndices.clear(), this._emitSelectionChange()), this._render();
2225
+ }
2226
+ _onScroll = () => {
2227
+ this._virtualizer.setScrollTop(this._viewport.scrollTop), this._render();
2228
+ };
2229
+ _syncSizingMode(t) {
2230
+ let e = this.itemHeight;
2231
+ this._virtualizer.setFixedSize(e), this._virtualizer.setEstimateSize(e ?? st), t && this._virtualizer.resetMeasurements();
2232
+ }
2233
+ _render() {
2234
+ if (!this.isConnected) return;
2235
+ if (this._emptyState.textContent = this.emptyText, this._emptyState.hidden = this._items.length > 0, this._items.length === 0) {
2236
+ this._itemsLayer.replaceChildren(), this._spacer.style.height = "100%";
2237
+ return;
2238
+ }
2239
+ this._virtualizer.setScrollTop(this._viewport.scrollTop), this._virtualizer.setViewportHeight(this._viewport.clientHeight), this._virtualizer.setCount(this._items.length);
2240
+ let t = this._virtualizer.getRange();
2241
+ this._spacer.style.height = `${Math.max(t.totalHeight, this._viewport.clientHeight)}px`, this._itemsLayer.style.transform = `translateY(${t.paddingTop}px)`;
2242
+ let e = document.createDocumentFragment();
2243
+ for (let n = t.start; n < t.end; n += 1) e.appendChild(this._renderVisibleItem(n));
2244
+ this._itemsLayer.replaceChildren(e);
2245
+ }
2246
+ _renderVisibleItem(t) {
2247
+ let e = this._items[t], n = document.createElement("div");
2248
+ if (n.className = "dt-list-item", n.dataset.index = String(t), this.selectable !== "none" && (n.classList.add("dt-list-item--interactive"), n.setAttribute("role", "option"), n.setAttribute("aria-selected", String(this._selectedIndices.has(t))), n.tabIndex = 0), this._selectedIndices.has(t) && n.classList.add("dt-list-item--selected"), this.itemHeight !== null && (n.style.minHeight = `${this.itemHeight}px`), this._renderItem) this._renderItem(e, n, t);
2249
+ else {
2250
+ let i = this._getTemplate();
2251
+ i ? n.appendChild(M(i, Pt(e))) : n.textContent = String(e ?? "");
2252
+ }
2253
+ return n.addEventListener("click", () => this._handleItemClick(t)), n.addEventListener("keydown", (i) => {
2254
+ (i.key === "Enter" || i.key === " ") && (i.preventDefault(), this._handleItemClick(t));
2255
+ }), this.itemHeight === null && this._itemResizeObserver?.observe(n), n;
2256
+ }
2257
+ _handleItemClick(t) {
2258
+ let e = this._items[t], n = this.selectable;
2259
+ n === "single" ? (this._selectedIndices = /* @__PURE__ */ new Set([t]), this._emitSelectionChange(), this._render()) : n === "multi" && (this._selectedIndices.has(t) ? this._selectedIndices.delete(t) : this._selectedIndices.add(t), this._emitSelectionChange(), this._render()), this.dispatchEvent(new CustomEvent("dt-item-click", { detail: { item: e, index: t }, bubbles: true, composed: true }));
2260
+ }
2261
+ _emitSelectionChange() {
2262
+ this.dispatchEvent(new CustomEvent("dt-selection-change", { detail: { selected: this.selectedItems }, bubbles: true, composed: true }));
2263
+ }
2264
+ _getTemplate() {
2265
+ for (let t of Array.from(this.children)) if (t instanceof HTMLTemplateElement) return t;
2266
+ return null;
2267
+ }
2268
+ };
2269
+ var ot = `:host {
2270
+ display: block;
2271
+ min-height: 220px;
2272
+ color: var(--dt-text);
2273
+ font-family: var(
2274
+ --font-mono,
2275
+ 'SF Mono',
2276
+ Monaco,
2277
+ 'Cascadia Code',
2278
+ 'Roboto Mono',
2279
+ Consolas,
2280
+ monospace
2281
+ );
2282
+ }
2283
+
2284
+ .dt-chart {
2285
+ position: relative;
2286
+ display: block;
2287
+ min-height: inherit;
2288
+ height: 100%;
2289
+ overflow: hidden;
2290
+ border: 1px solid var(--dt-border);
2291
+ border-radius: 2px;
2292
+ background:
2293
+ radial-gradient(
2294
+ circle at top left,
2295
+ color-mix(in srgb, var(--dt-accent) 16%, transparent),
2296
+ transparent 42%
2297
+ ),
2298
+ linear-gradient(
2299
+ 180deg,
2300
+ color-mix(in srgb, var(--dt-surface) 90%, var(--dt-accent) 10%),
2301
+ var(--dt-surface)
2302
+ );
2303
+ }
2304
+
2305
+ .dt-chart::before,
2306
+ .dt-chart::after {
2307
+ content: '';
2308
+ position: absolute;
2309
+ z-index: 3;
2310
+ width: 8px;
2311
+ height: 8px;
2312
+ pointer-events: none;
2313
+ }
2314
+
2315
+ .dt-chart::before {
2316
+ top: -1px;
2317
+ left: -1px;
2318
+ border-top: 2px solid var(--dt-accent);
2319
+ border-left: 2px solid var(--dt-accent);
2320
+ }
2321
+
2322
+ .dt-chart::after {
2323
+ right: -1px;
2324
+ bottom: -1px;
2325
+ border-right: 2px solid var(--dt-accent);
2326
+ border-bottom: 2px solid var(--dt-accent);
2327
+ }
2328
+
2329
+ .dt-chart__canvas {
2330
+ position: relative;
2331
+ z-index: 1;
2332
+ display: block;
2333
+ width: 100%;
2334
+ height: 100%;
2335
+ }
2336
+
2337
+ .dt-chart__status {
2338
+ position: absolute;
2339
+ inset: 0;
2340
+ z-index: 2;
2341
+ display: flex;
2342
+ align-items: center;
2343
+ justify-content: center;
2344
+ padding: 20px;
2345
+ color: var(--dt-text-muted);
2346
+ font-size: 0.75rem;
2347
+ letter-spacing: 0.08em;
2348
+ text-align: center;
2349
+ text-transform: uppercase;
2350
+ background: color-mix(in srgb, var(--dt-surface) 72%, transparent);
2351
+ }
2352
+
2353
+ .dt-chart__status[hidden] {
2354
+ display: none;
2355
+ }
2356
+ `;
2357
+ var L = null;
2358
+ function at() {
2359
+ return window.__DtChart ? Promise.resolve(window.__DtChart) : L || (L = new Promise((r, t) => {
2360
+ let e = document.createElement("script");
2361
+ e.src = "/api/ui/chart.umd.js", e.async = true, e.dataset.dtChart = "true", e.onload = () => {
2362
+ if (window.__DtChart) {
2363
+ r(window.__DtChart);
2364
+ return;
2365
+ }
2366
+ t(new Error("Chart runtime loaded without a __DtChart export."));
2367
+ }, e.onerror = () => t(new Error("Failed to load the Chart.js runtime bundle.")), document.head.appendChild(e);
2368
+ }), L);
2369
+ }
2370
+ function v(r, t, e) {
2371
+ return Math.min(e, Math.max(t, r));
2372
+ }
2373
+ function It(r) {
2374
+ return r ? r.split(",").map((t) => t.trim()).filter(Boolean) : [];
2375
+ }
2376
+ function X(r) {
2377
+ let t = r.trim().match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
2378
+ if (t) {
2379
+ let i = t[1], s = i.length === 3 ? i.split("").map((c) => `${c}${c}`).join("") : i, o = parseInt(s.slice(0, 2), 16) / 255, a = parseInt(s.slice(2, 4), 16) / 255, d = parseInt(s.slice(4, 6), 16) / 255;
2380
+ return dt(o, a, d);
2381
+ }
2382
+ let e = r.trim().match(/^rgba?\((\d+(?:\.\d+)?)[,\s]+(\d+(?:\.\d+)?)[,\s]+(\d+(?:\.\d+)?)(?:[,/\s]+[\d.]+)?\)$/i);
2383
+ if (e) return dt(Number(e[1]) / 255, Number(e[2]) / 255, Number(e[3]) / 255);
2384
+ let n = r.trim().match(/^hsla?\(([-\d.]+)(?:deg)?[,\s]+([\d.]+)%[,\s]+([\d.]+)%(?:[,/\s]+[\d.]+)?\)$/i);
2385
+ return n ? { h: (Number(n[1]) % 360 + 360) % 360, s: v(Number(n[2]), 0, 100), l: v(Number(n[3]), 0, 100) } : null;
2386
+ }
2387
+ function dt(r, t, e) {
2388
+ let n = Math.max(r, t, e), i = Math.min(r, t, e), s = n - i, o = 0, a = (n + i) / 2, d = s === 0 ? 0 : s / (1 - Math.abs(2 * a - 1));
2389
+ if (s !== 0) switch (n) {
2390
+ case r:
2391
+ o = 60 * ((t - e) / s % 6);
2392
+ break;
2393
+ case t:
2394
+ o = 60 * ((e - r) / s + 2);
2395
+ break;
2396
+ default:
2397
+ o = 60 * ((r - t) / s + 4);
2398
+ break;
2399
+ }
2400
+ return { h: (o + 360) % 360, s: Math.round(d * 100), l: Math.round(a * 100) };
2401
+ }
2402
+ function g(r, t = 1) {
2403
+ return `hsla(${Math.round(r.h)} ${Math.round(r.s)}% ${Math.round(r.l)}% / ${t})`;
2404
+ }
2405
+ function Nt(r) {
2406
+ let t = X(r) ?? { h: 185, s: 88, l: 56 };
2407
+ return [0, 32, 68, 118, 164, 212, 258, 304].map((n, i) => ({ h: (t.h + n) % 360, s: v(t.s - i * 2, 55, 90), l: v(t.l + (i % 2 === 0 ? 0 : 6) - i, 38, 66) }));
2408
+ }
2409
+ function H(r) {
2410
+ return !!r && typeof r == "object" && !Array.isArray(r);
2411
+ }
2412
+ function lt(r, t) {
2413
+ if (!H(r) || !H(t)) return t ?? r;
2414
+ let e = { ...r };
2415
+ for (let [n, i] of Object.entries(t)) {
2416
+ let s = e[n];
2417
+ e[n] = H(s) && H(i) ? lt(s, i) : i;
2418
+ }
2419
+ return e;
2420
+ }
2421
+ function Ft(r) {
2422
+ return r === "top" || r === "bottom" || r === "left" || r === "right" ? r : "none";
2423
+ }
2424
+ function Ot(r) {
2425
+ return r === "bar" || r === "line" || r === "area" || r === "pie" || r === "doughnut" || r === "radar" || r === "scatter" || r === "bubble" ? r : "bar";
2426
+ }
2427
+ function Bt(r) {
2428
+ return r === "bar" || r === "line" || r === "area" || r === "scatter" || r === "bubble";
2429
+ }
2430
+ function $t(r) {
2431
+ return r.map((t) => t.trim()).filter(Boolean);
2432
+ }
2433
+ var R = class extends HTMLElement {
2434
+ _canvas;
2435
+ _status;
2436
+ _runtime = null;
2437
+ _loadPromise = null;
2438
+ _chart = null;
2439
+ _renderedType = null;
2440
+ _dataInput = null;
2441
+ _optionsOverride = null;
2442
+ _syncFrame = 0;
2443
+ static get observedAttributes() {
2444
+ return ["type", "legend", "stacked", "labels"];
2445
+ }
2446
+ get type() {
2447
+ return Ot(this.getAttribute("type"));
2448
+ }
2449
+ set type(t) {
2450
+ this.setAttribute("type", t);
2451
+ }
2452
+ get legend() {
2453
+ return Ft(this.getAttribute("legend"));
2454
+ }
2455
+ set legend(t) {
2456
+ this.setAttribute("legend", t);
2457
+ }
2458
+ get stacked() {
2459
+ return this.hasAttribute("stacked");
2460
+ }
2461
+ set stacked(t) {
2462
+ this.toggleAttribute("stacked", t);
2463
+ }
2464
+ get labels() {
2465
+ return $t(It(this.getAttribute("labels")));
2466
+ }
2467
+ set labels(t) {
2468
+ this.setAttribute("labels", t.join(","));
2469
+ }
2470
+ get data() {
2471
+ return this._dataInput;
2472
+ }
2473
+ set data(t) {
2474
+ this._dataInput = t ? structuredClone(t) : null, this._scheduleSync();
2475
+ }
2476
+ get options() {
2477
+ return this._optionsOverride;
2478
+ }
2479
+ set options(t) {
2480
+ this._optionsOverride = t ? structuredClone(t) : null, this._renderChart();
2481
+ }
2482
+ constructor() {
2483
+ super();
2484
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
2485
+ e.textContent = ot, t.appendChild(e);
2486
+ let n = document.createElement("div");
2487
+ n.className = "dt-chart", this._canvas = document.createElement("canvas"), this._canvas.className = "dt-chart__canvas", this._status = document.createElement("div"), this._status.className = "dt-chart__status", this._status.textContent = "Loading chart", n.append(this._canvas, this._status), t.appendChild(n);
2488
+ }
2489
+ connectedCallback() {
2490
+ this._canvas.addEventListener("click", this._handleCanvasClick), this._ensureRuntime().then(() => this._renderChart()), this._scheduleSync();
2491
+ }
2492
+ disconnectedCallback() {
2493
+ this._canvas.removeEventListener("click", this._handleCanvasClick), this._syncFrame !== 0 && (cancelAnimationFrame(this._syncFrame), this._syncFrame = 0), this._chart?.destroy(), this._chart = null, this._renderedType = null;
2494
+ }
2495
+ attributeChangedCallback() {
2496
+ this._scheduleSync();
2497
+ }
2498
+ _handleCanvasClick = (t) => {
2499
+ if (!this._chart) return;
2500
+ let n = this._chart.getElementsAtEventForMode(t, "nearest", { intersect: true }, true)[0];
2501
+ if (!n) return;
2502
+ let i = Array.isArray(this._chart.data.labels) ? this._chart.data.labels[n.index] ?? null : null, s = this._chart.data.datasets[n.datasetIndex], o = Array.isArray(s?.data) ? s.data[n.index] : void 0;
2503
+ this.dispatchEvent(new CustomEvent("dt-chart-click", { bubbles: true, composed: true, detail: { label: i, datasetIndex: n.datasetIndex, index: n.index, value: o } }));
2504
+ };
2505
+ _scheduleSync() {
2506
+ this._syncFrame === 0 && (this._syncFrame = requestAnimationFrame(() => {
2507
+ this._syncFrame = 0, this._syncFromCurrentSource();
2508
+ }));
2509
+ }
2510
+ _syncFromCurrentSource() {
2511
+ this._renderChart();
2512
+ }
2513
+ async _ensureRuntime() {
2514
+ return this._runtime ? this._runtime : (this._loadPromise || (this._loadPromise = at().then((t) => (this._runtime = t, t))), this._loadPromise);
2515
+ }
2516
+ async _renderChart() {
2517
+ let t = this._dataInput;
2518
+ if (!t) {
2519
+ this._setStatus("Waiting for data");
2520
+ return;
2521
+ }
2522
+ let e = await this._ensureRuntime(), n = this._buildConfig(e, t), i = n.type;
2523
+ !this._chart || this._renderedType !== i ? (this._chart?.destroy(), this._chart = new e.Chart(this._canvas, n), this._renderedType = i) : (this._chart.data = n.data, this._chart.options = n.options, this._chart.update()), this._setStatus(t.datasets.length > 0 ? null : "Waiting for data");
2524
+ }
2525
+ _buildConfig(t, e) {
2526
+ let n = getComputedStyle(this), i = n.getPropertyValue("--dt-accent").trim() || "#42d4ff", s = n.getPropertyValue("--dt-text").trim() || "#d6ebff", o = n.getPropertyValue("--dt-text-muted").trim() || "#7b93a6", a = n.getPropertyValue("--dt-border").trim() || "rgba(123, 147, 166, 0.3)", d = n.getPropertyValue("--font-mono").trim() || "'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace", c = Nt(i), l = this.type === "area" ? "line" : this.type, f = { labels: e.labels ?? this.labels, datasets: e.datasets.map((h, gt) => {
2527
+ let F = c[gt % c.length], p = h.color ?? g(F, 1), O = { label: h.label ?? "", data: h.data, backgroundColor: l === "line" || l === "radar" || l === "scatter" ? g(F, l === "scatter" ? 0.95 : 0.24) : p, borderColor: p, pointBackgroundColor: p, pointBorderColor: p, pointHoverBackgroundColor: p, pointRadius: this.type === "line" || this.type === "area" ? 3 : 4, pointHoverRadius: this.type === "line" || this.type === "area" ? 5 : 6, borderWidth: 2, tension: l === "line" || this.type === "area" ? 0.32 : void 0, fill: this.type === "area" };
2528
+ return l === "pie" || l === "doughnut" ? { ...O, backgroundColor: Array.isArray(h.data) ? h.data.map((bt, B) => g(c[B % c.length], 0.86)) : p, borderColor: Array.isArray(h.data) ? h.data.map((bt, B) => g(c[B % c.length], 1)) : p, borderWidth: 1 } : l === "scatter" || l === "bubble" ? { ...O, showLine: false, backgroundColor: g(F, 0.78) } : O;
2529
+ }) }, _ = { responsive: true, maintainAspectRatio: false, animation: { duration: 320 }, interaction: { mode: "nearest", intersect: true }, plugins: { legend: { display: this.legend !== "none", position: this.legend === "none" ? "top" : this.legend, labels: { color: s, boxWidth: 12, boxHeight: 12, padding: 14, font: { family: d, size: 11 } } }, tooltip: { backgroundColor: "rgba(10, 18, 24, 0.92)", borderColor: Xt(a, i, 0.35), borderWidth: 1, titleColor: s, bodyColor: s, footerColor: o, titleFont: { family: d, size: 11 }, bodyFont: { family: d, size: 11 }, padding: 10 } }, scales: Bt(this.type) ? { x: { stacked: this.stacked, grid: { display: false, color: a }, border: { color: a }, ticks: { color: o, font: { family: d, size: 11 } } }, y: { stacked: this.stacked, beginAtZero: true, grid: { display: false, color: a }, border: { color: a }, ticks: { color: o, font: { family: d, size: 11 } } } } : l === "radar" ? { r: { angleLines: { color: a }, grid: { color: a }, pointLabels: { color: o, font: { family: d, size: 11 } }, ticks: { color: o, backdropColor: "transparent", font: { family: d, size: 10 } } } } : void 0 };
2530
+ return { type: l, data: f, options: lt(_, this._optionsOverride ?? {}) };
2531
+ }
2532
+ _setStatus(t) {
2533
+ if (!t) {
2534
+ this._status.hidden = true;
2535
+ return;
2536
+ }
2537
+ this._status.hidden = false, this._status.textContent = t;
2538
+ }
2539
+ };
2540
+ function Xt(r, t, e) {
2541
+ let n = X(r), i = X(t);
2542
+ if (!n || !i) return r;
2543
+ let s = v(e, 0, 1), o = ((i.h - n.h) % 360 + 540) % 360 - 180;
2544
+ return g({ h: (n.h + o * s + 360) % 360, s: n.s + (i.s - n.s) * s, l: n.l + (i.l - n.l) * s });
2545
+ }
2546
+ var ct = `:host {
2547
+ display: block;
2548
+ color: var(--dt-text);
2549
+ font-family: var(--font-sans, 'Inter', sans-serif);
2550
+ }
2551
+
2552
+ .dt-markdown {
2553
+ color: inherit;
2554
+ line-height: 1.7;
2555
+ word-break: break-word;
2556
+ }
2557
+
2558
+ .dt-markdown > :first-child {
2559
+ margin-top: 0;
2560
+ }
2561
+
2562
+ .dt-markdown > :last-child {
2563
+ margin-bottom: 0;
2564
+ }
2565
+
2566
+ .dt-markdown :is(h1, h2, h3, h4, h5, h6) {
2567
+ margin: 1.2em 0 0.55em;
2568
+ color: var(--dt-text);
2569
+ font-family: var(--font-sans, 'Inter', sans-serif);
2570
+ line-height: 1.2;
2571
+ }
2572
+
2573
+ .dt-markdown h1 {
2574
+ color: var(--dt-accent);
2575
+ font-size: 1.6rem;
2576
+ letter-spacing: 0.08em;
2577
+ text-transform: uppercase;
2578
+ }
2579
+
2580
+ .dt-markdown h2 {
2581
+ font-size: 1.3rem;
2582
+ }
2583
+
2584
+ .dt-markdown h3 {
2585
+ font-size: 1.1rem;
2586
+ }
2587
+
2588
+ .dt-markdown p,
2589
+ .dt-markdown ul,
2590
+ .dt-markdown ol,
2591
+ .dt-markdown blockquote,
2592
+ .dt-markdown pre,
2593
+ .dt-markdown table {
2594
+ margin: 0.8em 0;
2595
+ }
2596
+
2597
+ .dt-markdown ul,
2598
+ .dt-markdown ol {
2599
+ padding-left: 1.4rem;
2600
+ }
2601
+
2602
+ .dt-markdown li + li {
2603
+ margin-top: 0.28em;
2604
+ }
2605
+
2606
+ .dt-markdown strong {
2607
+ color: var(--dt-text);
2608
+ }
2609
+
2610
+ .dt-markdown a,
2611
+ .dt-markdown .dt-md-link {
2612
+ color: var(--dt-accent);
2613
+ text-decoration: none;
2614
+ }
2615
+
2616
+ .dt-markdown a:hover,
2617
+ .dt-markdown .dt-md-link:hover {
2618
+ text-decoration: underline;
2619
+ }
2620
+
2621
+ .dt-markdown code {
2622
+ padding: 0.12rem 0.35rem;
2623
+ border-radius: 2px;
2624
+ background: color-mix(in srgb, var(--dt-surface) 88%, var(--dt-accent) 12%);
2625
+ color: var(--dt-accent);
2626
+ font-family: var(
2627
+ --font-mono,
2628
+ 'SF Mono',
2629
+ Monaco,
2630
+ 'Cascadia Code',
2631
+ 'Roboto Mono',
2632
+ Consolas,
2633
+ monospace
2634
+ );
2635
+ font-size: 0.92em;
2636
+ }
2637
+
2638
+ .dt-md-pre {
2639
+ overflow-x: auto;
2640
+ padding: 14px 16px;
2641
+ border: 1px solid var(--dt-border);
2642
+ border-radius: 2px;
2643
+ background: var(--dt-surface);
2644
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--dt-surface) 85%, var(--dt-accent) 15%);
2645
+ }
2646
+
2647
+ .dt-md-pre code {
2648
+ display: block;
2649
+ padding: 0;
2650
+ background: transparent;
2651
+ color: var(--dt-text);
2652
+ }
2653
+
2654
+ .dt-md-blockquote {
2655
+ margin: 0.9em 0;
2656
+ padding: 0.15rem 0 0.15rem 1rem;
2657
+ border-left: 3px solid var(--dt-accent);
2658
+ color: var(--dt-text-muted);
2659
+ }
2660
+
2661
+ .dt-md-table {
2662
+ width: 100%;
2663
+ border-collapse: collapse;
2664
+ border: 1px solid var(--dt-border);
2665
+ background: var(--dt-surface);
2666
+ }
2667
+
2668
+ .dt-md-table th,
2669
+ .dt-md-table td {
2670
+ padding: 0.6rem 0.8rem;
2671
+ border: 1px solid var(--dt-border-subtle, var(--dt-border));
2672
+ text-align: left;
2673
+ vertical-align: top;
2674
+ }
2675
+
2676
+ .dt-md-table th {
2677
+ color: var(--dt-accent);
2678
+ background: color-mix(in srgb, var(--dt-surface) 88%, var(--dt-accent) 12%);
2679
+ font-size: 0.75rem;
2680
+ letter-spacing: 0.08em;
2681
+ text-transform: uppercase;
2682
+ }
2683
+
2684
+ .dt-markdown hr {
2685
+ border: 0;
2686
+ border-top: 1px solid var(--dt-border);
2687
+ }
2688
+
2689
+ .dt-md-image {
2690
+ display: block;
2691
+ max-width: 100%;
2692
+ border: 1px solid var(--dt-border);
2693
+ border-radius: 2px;
2694
+ }
2695
+
2696
+ .dt-markdown__caret {
2697
+ display: inline-block;
2698
+ margin-left: 0.15rem;
2699
+ color: var(--dt-accent);
2700
+ animation: dt-markdown-caret 0.9s steps(1) infinite;
2701
+ }
2702
+
2703
+ .dt-markdown__caret[hidden] {
2704
+ display: none;
2705
+ }
2706
+
2707
+ @keyframes dt-markdown-caret {
2708
+ 0%,
2709
+ 49% {
2710
+ opacity: 1;
2711
+ }
2712
+
2713
+ 50%,
2714
+ 100% {
2715
+ opacity: 0;
2716
+ }
2717
+ }
2718
+ `;
2719
+ var V = null;
2720
+ function ht() {
2721
+ return window.__DtMarked ? Promise.resolve(window.__DtMarked) : V || (V = new Promise((r, t) => {
2722
+ let e = document.createElement("script");
2723
+ e.src = "/api/ui/marked.js", e.async = true, e.dataset.dtMarked = "true", e.onload = () => {
2724
+ if (window.__DtMarked) {
2725
+ r(window.__DtMarked);
2726
+ return;
2727
+ }
2728
+ t(new Error("Marked runtime loaded without a __DtMarked export."));
2729
+ }, e.onerror = () => t(new Error("Failed to load the marked runtime bundle.")), document.head.appendChild(e);
2730
+ }), V);
2731
+ }
2732
+ function ut(r) {
2733
+ return r.replaceAll(`\r
2734
+ `, `
2735
+ `);
2736
+ }
2737
+ function Jt(r) {
2738
+ let t = ut(r).split(`
2739
+ `);
2740
+ for (; t.length > 0 && t[0].trim() === ""; ) t.shift();
2741
+ for (; t.length > 0 && t[t.length - 1].trim() === ""; ) t.pop();
2742
+ let e = t.filter((i) => i.trim() !== "").map((i) => i.match(/^\s*/)?.[0].length ?? 0), n = e.length > 0 ? Math.min(...e) : 0;
2743
+ return n === 0 ? t.join(`
2744
+ `) : t.map((i) => i.slice(n)).join(`
2745
+ `);
2746
+ }
2747
+ function Wt(r) {
2748
+ let t = ut(r);
2749
+ if ((t.match(/(^|\n)(```|~~~)/g) ?? []).length % 2 === 0) return t;
2750
+ let n = t.includes("~~~") && !t.includes("```") ? "~~~" : "```";
2751
+ return `${t}
2752
+ ${n}`;
2753
+ }
2754
+ var P = class extends HTMLElement {
2755
+ _body;
2756
+ _caret;
2757
+ _contentOverride = null;
2758
+ _runtime = null;
2759
+ _loadPromise = null;
2760
+ _observer = null;
2761
+ _renderFrame = 0;
2762
+ static get observedAttributes() {
2763
+ return ["streaming", "unsafe-html"];
2764
+ }
2765
+ get content() {
2766
+ return this._contentOverride ?? this._readInlineMarkdown();
2767
+ }
2768
+ set content(t) {
2769
+ this._contentOverride = String(t ?? ""), this._scheduleRender();
2770
+ }
2771
+ get streaming() {
2772
+ return this.hasAttribute("streaming");
2773
+ }
2774
+ set streaming(t) {
2775
+ this.toggleAttribute("streaming", t);
2776
+ }
2777
+ get unsafeHtml() {
2778
+ return this.hasAttribute("unsafe-html");
2779
+ }
2780
+ set unsafeHtml(t) {
2781
+ this.toggleAttribute("unsafe-html", t);
2782
+ }
2783
+ constructor() {
2784
+ super();
2785
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
2786
+ e.textContent = ct, t.appendChild(e), this._body = document.createElement("div"), this._body.className = "dt-markdown", this._body.addEventListener("click", this._onLinkClick), this._caret = document.createElement("span"), this._caret.className = "dt-markdown__caret", this._caret.textContent = "\u258C", this._caret.hidden = true, t.append(this._body, this._caret);
2787
+ }
2788
+ connectedCallback() {
2789
+ this._observer || (this._observer = new MutationObserver(() => {
2790
+ this._contentOverride === null && this._scheduleRender();
2791
+ }), this._observer.observe(this, { childList: true, characterData: true, subtree: true })), this._ensureRuntime(), this._scheduleRender();
2792
+ }
2793
+ disconnectedCallback() {
2794
+ this._observer?.disconnect(), this._observer = null, this._renderFrame !== 0 && (cancelAnimationFrame(this._renderFrame), this._renderFrame = 0);
2795
+ }
2796
+ attributeChangedCallback() {
2797
+ this._scheduleRender();
2798
+ }
2799
+ _onLinkClick = (t) => {
2800
+ let n = t.composedPath().find((i) => i instanceof HTMLAnchorElement);
2801
+ n && (t.preventDefault(), this.dispatchEvent(new CustomEvent("dt-link-click", { bubbles: true, composed: true, detail: { href: n.getAttribute("href") ?? "#" } })));
2802
+ };
2803
+ _readInlineMarkdown() {
2804
+ return Jt(this.textContent ?? "");
2805
+ }
2806
+ _scheduleRender() {
2807
+ this._renderFrame === 0 && (this._renderFrame = requestAnimationFrame(() => {
2808
+ this._renderFrame = 0, this._render();
2809
+ }));
2810
+ }
2811
+ async _ensureRuntime() {
2812
+ return this._runtime ? this._runtime : (this._loadPromise || (this._loadPromise = ht().then((t) => (this._runtime = t, t))), this._loadPromise);
2813
+ }
2814
+ async _render() {
2815
+ let t = await this._ensureRuntime(), e = this.content;
2816
+ this.streaming && (e = Wt(e)), this._body.innerHTML = t.render(e, { unsafeHtml: this.unsafeHtml }), this._caret.hidden = !this.streaming;
2817
+ }
2818
+ };
2819
+ var pt = `:host {
2820
+ display: block;
2821
+ min-height: 240px;
2822
+ color: var(--dt-text);
2823
+ font-family: var(--font-sans, 'Inter', sans-serif);
2824
+ }
2825
+
2826
+ .dt-markdown-editor {
2827
+ position: relative;
2828
+ height: 100%;
2829
+ min-height: inherit;
2830
+ overflow: hidden;
2831
+ border: 1px solid var(--dt-border);
2832
+ border-radius: 2px;
2833
+ }
2834
+
2835
+ .dt-markdown-editor::before,
2836
+ .dt-markdown-editor::after {
2837
+ content: '';
2838
+ position: absolute;
2839
+ z-index: 3;
2840
+ width: 8px;
2841
+ height: 8px;
2842
+ pointer-events: none;
2843
+ }
2844
+
2845
+ .dt-markdown-editor::before {
2846
+ top: -1px;
2847
+ left: -1px;
2848
+ border-top: 2px solid var(--dt-accent);
2849
+ border-left: 2px solid var(--dt-accent);
2850
+ }
2851
+
2852
+ .dt-markdown-editor::after {
2853
+ right: -1px;
2854
+ bottom: -1px;
2855
+ border-right: 2px solid var(--dt-accent);
2856
+ border-bottom: 2px solid var(--dt-accent);
2857
+ }
2858
+
2859
+ .dt-markdown-editor__surface {
2860
+ height: 100%;
2861
+ min-height: inherit;
2862
+ }
2863
+
2864
+ .dt-markdown-editor__content {
2865
+ height: 100%;
2866
+ min-height: inherit;
2867
+ }
2868
+
2869
+ .dt-markdown-editor__status {
2870
+ position: absolute;
2871
+ inset: 0;
2872
+ display: flex;
2873
+ align-items: center;
2874
+ justify-content: center;
2875
+ padding: 20px;
2876
+ background: color-mix(in srgb, var(--dt-surface) 84%, transparent);
2877
+ color: var(--dt-text-muted);
2878
+ font-size: 0.75rem;
2879
+ letter-spacing: 0.08em;
2880
+ text-transform: uppercase;
2881
+ }
2882
+
2883
+ .dt-markdown-editor__status[hidden] {
2884
+ display: none;
2885
+ }
2886
+
2887
+ .milkdown {
2888
+ --crepe-color-background: transparent;
2889
+ --crepe-color-on-background: var(--dt-text);
2890
+ --crepe-color-surface: var(--dt-surface);
2891
+ --crepe-color-surface-low: color-mix(in srgb, var(--dt-surface) 94%, var(--dt-accent) 6%);
2892
+ --crepe-color-on-surface: var(--dt-text);
2893
+ --crepe-color-on-surface-variant: var(--dt-text-muted);
2894
+ --crepe-color-outline: var(--dt-border);
2895
+ --crepe-color-primary: var(--dt-accent);
2896
+ --crepe-color-secondary: color-mix(in srgb, var(--dt-surface) 84%, var(--dt-accent) 16%);
2897
+ --crepe-color-on-secondary: var(--dt-text);
2898
+ --crepe-color-inverse: var(--dt-text);
2899
+ --crepe-color-on-inverse: var(--dt-surface);
2900
+ --crepe-color-inline-code: var(--dt-accent);
2901
+ --crepe-color-error: var(--dt-danger, #ff6a6a);
2902
+ --crepe-color-hover: var(--dt-surface-hover);
2903
+ --crepe-color-selected: color-mix(in srgb, var(--dt-surface) 82%, var(--dt-accent) 18%);
2904
+ --crepe-color-inline-area: color-mix(in srgb, var(--dt-surface) 90%, var(--dt-accent) 10%);
2905
+ --crepe-font-title: var(--font-sans, 'Inter', sans-serif);
2906
+ --crepe-font-default: var(--font-sans, 'Inter', sans-serif);
2907
+ --crepe-font-code: var(
2908
+ --font-mono,
2909
+ 'SF Mono',
2910
+ Monaco,
2911
+ 'Cascadia Code',
2912
+ 'Roboto Mono',
2913
+ Consolas,
2914
+ monospace
2915
+ );
2916
+ --crepe-shadow-1: 0 0 0 1px color-mix(in srgb, var(--dt-surface) 82%, var(--dt-accent) 18%);
2917
+ --crepe-shadow-2:
2918
+ 0 0 0 1px color-mix(in srgb, var(--dt-surface) 78%, var(--dt-accent) 22%),
2919
+ 0 8px 24px color-mix(in srgb, var(--dt-accent) 12%, transparent);
2920
+
2921
+ height: 100%;
2922
+ background: transparent;
2923
+ color: var(--dt-text);
2924
+ }
2925
+
2926
+ .milkdown .editor {
2927
+ min-height: 100%;
2928
+ padding: 16px 18px 20px;
2929
+ outline: none;
2930
+ color: var(--dt-text);
2931
+ font-family: var(--font-sans, 'Inter', sans-serif);
2932
+ font-size: 14px;
2933
+ line-height: 1.7;
2934
+ }
2935
+
2936
+ .milkdown .editor > :first-child {
2937
+ margin-top: 0;
2938
+ }
2939
+
2940
+ .milkdown .editor h1,
2941
+ .milkdown .editor h2,
2942
+ .milkdown .editor h3,
2943
+ .milkdown .editor h4,
2944
+ .milkdown .editor h5,
2945
+ .milkdown .editor h6 {
2946
+ margin: 0.95em 0 0.45em;
2947
+ line-height: 1.2;
2948
+ }
2949
+
2950
+ .milkdown .editor h1 {
2951
+ color: var(--dt-accent);
2952
+ font-size: 1.6rem;
2953
+ letter-spacing: 0.08em;
2954
+ text-transform: uppercase;
2955
+ }
2956
+
2957
+ .milkdown .editor h2 {
2958
+ font-size: 1.28rem;
2959
+ }
2960
+
2961
+ .milkdown .editor h3 {
2962
+ font-size: 1.08rem;
2963
+ }
2964
+
2965
+ .milkdown .editor p {
2966
+ margin: 0.65em 0;
2967
+ }
2968
+
2969
+ .milkdown .editor code {
2970
+ padding: 2px 5px;
2971
+ border-radius: 2px;
2972
+ background: color-mix(in srgb, var(--dt-surface) 88%, var(--dt-accent) 12%);
2973
+ font-family: var(
2974
+ --font-mono,
2975
+ 'SF Mono',
2976
+ Monaco,
2977
+ 'Cascadia Code',
2978
+ 'Roboto Mono',
2979
+ Consolas,
2980
+ monospace
2981
+ );
2982
+ font-size: 0.9em;
2983
+ }
2984
+
2985
+ .milkdown .editor pre {
2986
+ overflow-x: auto;
2987
+ margin: 0.9em 0;
2988
+ padding: 12px 14px;
2989
+ border: 1px solid var(--dt-border);
2990
+ border-radius: 2px;
2991
+ background: var(--dt-surface);
2992
+ }
2993
+
2994
+ .milkdown .editor pre code {
2995
+ padding: 0;
2996
+ background: transparent;
2997
+ }
2998
+
2999
+ .milkdown .editor blockquote {
3000
+ margin: 0.9em 0;
3001
+ padding-left: 12px;
3002
+ border-left: 3px solid var(--dt-accent);
3003
+ color: var(--dt-text-muted);
3004
+ }
3005
+
3006
+ .milkdown .editor a {
3007
+ color: var(--dt-accent);
3008
+ text-decoration: none;
3009
+ }
3010
+
3011
+ .milkdown .editor a:hover {
3012
+ text-decoration: underline;
3013
+ }
3014
+
3015
+ .milkdown .editor hr {
3016
+ border: 0;
3017
+ border-top: 1px solid var(--dt-border);
3018
+ }
3019
+
3020
+ .milkdown .editor ul,
3021
+ .milkdown .editor ol {
3022
+ padding-left: 1.5rem;
3023
+ }
3024
+
3025
+ .milkdown .editor img {
3026
+ max-width: 100%;
3027
+ border-radius: 2px;
3028
+ }
3029
+
3030
+ .milkdown .editor table {
3031
+ width: 100%;
3032
+ border-collapse: collapse;
3033
+ }
3034
+
3035
+ .milkdown .editor th,
3036
+ .milkdown .editor td {
3037
+ border: 1px solid var(--dt-border);
3038
+ }
3039
+ `;
3040
+ var I = null;
3041
+ function mt() {
3042
+ return window.__DtMilkdown ? Promise.resolve(window.__DtMilkdown) : I || (I = new Promise((r, t) => {
3043
+ let e = document.createElement("script");
3044
+ e.src = "/api/ui/milkdown.umd.js", e.async = true, e.dataset.dtMilkdown = "true", e.onload = () => {
3045
+ if (window.__DtMilkdown) {
3046
+ r(window.__DtMilkdown);
3047
+ return;
3048
+ }
3049
+ t(new Error("Milkdown runtime loaded without a __DtMilkdown export."));
3050
+ }, e.onerror = () => t(new Error("Failed to load the Milkdown runtime bundle.")), document.head.appendChild(e);
3051
+ }), I);
3052
+ }
3053
+ var N = class extends HTMLElement {
3054
+ _runtimeStyle;
3055
+ _surface;
3056
+ _content;
3057
+ _status;
3058
+ _runtime = null;
3059
+ _loadPromise = null;
3060
+ _editor = null;
3061
+ _pendingValue = "";
3062
+ _changeTimer = null;
3063
+ _setupToken = 0;
3064
+ _suppressNextChange = false;
3065
+ static get observedAttributes() {
3066
+ return ["placeholder", "readonly"];
3067
+ }
3068
+ get placeholder() {
3069
+ return this.getAttribute("placeholder") ?? "";
3070
+ }
3071
+ set placeholder(t) {
3072
+ this.setAttribute("placeholder", t);
3073
+ }
3074
+ get readonly() {
3075
+ return this.hasAttribute("readonly");
3076
+ }
3077
+ set readonly(t) {
3078
+ this.toggleAttribute("readonly", t);
3079
+ }
3080
+ get value() {
3081
+ return this._editor && (this._pendingValue = this._editor.getMarkdown()), this._pendingValue;
3082
+ }
3083
+ set value(t) {
3084
+ let e = String(t ?? "");
3085
+ this._pendingValue = e, this._editor && this._runtime && this._editor.getMarkdown() !== e && (this._suppressNextChange = true, this._editor.editor.action(this._runtime.replaceAll(e)));
3086
+ }
3087
+ constructor() {
3088
+ super();
3089
+ let t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
3090
+ e.textContent = pt, t.appendChild(e), this._runtimeStyle = document.createElement("style"), t.appendChild(this._runtimeStyle), this._surface = document.createElement("div"), this._surface.className = "dt-markdown-editor", this._content = document.createElement("div"), this._content.className = "dt-markdown-editor__surface";
3091
+ let n = document.createElement("div");
3092
+ n.className = "dt-markdown-editor__content", this._content.appendChild(n), this._status = document.createElement("div"), this._status.className = "dt-markdown-editor__status", this._status.textContent = "Loading editor", this._surface.append(this._content, this._status), t.appendChild(this._surface);
3093
+ }
3094
+ connectedCallback() {
3095
+ this._initializeEditor();
3096
+ }
3097
+ disconnectedCallback() {
3098
+ this._setupToken += 1, this._clearChangeTimer(), this._destroyEditor();
3099
+ }
3100
+ attributeChangedCallback(t) {
3101
+ if (t === "readonly") {
3102
+ this._editor?.setReadonly(this.readonly);
3103
+ return;
3104
+ }
3105
+ t === "placeholder" && this.isConnected && this._initializeEditor(true);
3106
+ }
3107
+ async _ensureRuntime() {
3108
+ return this._runtime ? this._runtime : (this._loadPromise || (this._loadPromise = mt().then((t) => (this._runtime = t, this._runtimeStyle.textContent = t.cssText, t))), this._loadPromise);
3109
+ }
3110
+ async _initializeEditor(t = false) {
3111
+ let e = ++this._setupToken;
3112
+ if (this._setStatus("Loading editor"), t) await this._destroyEditor();
3113
+ else if (this._editor) {
3114
+ this._setStatus(null);
3115
+ return;
3116
+ }
3117
+ try {
3118
+ let n = await this._ensureRuntime();
3119
+ if (!this.isConnected || e !== this._setupToken) return;
3120
+ this._content.replaceChildren();
3121
+ let i = document.createElement("div");
3122
+ i.className = "dt-markdown-editor__content", this._content.appendChild(i);
3123
+ let s = new n.Crepe({ root: i, defaultValue: this._pendingValue, features: { [n.Crepe.Feature.CodeMirror]: false, [n.Crepe.Feature.ImageBlock]: false, [n.Crepe.Feature.Latex]: false }, featureConfigs: { [n.Crepe.Feature.Placeholder]: { text: this.placeholder, mode: "doc" } } });
3124
+ if (s.on((o) => {
3125
+ o.markdownUpdated((a, d) => {
3126
+ if (this._pendingValue = d, this._suppressNextChange) {
3127
+ this._suppressNextChange = false;
3128
+ return;
3129
+ }
3130
+ this._queueChange(d);
3131
+ }), o.focus(() => {
3132
+ this.dispatchEvent(new CustomEvent("dt-focus", { bubbles: true, composed: true }));
3133
+ }), o.blur(() => {
3134
+ this.dispatchEvent(new CustomEvent("dt-blur", { bubbles: true, composed: true }));
3135
+ });
3136
+ }), await s.create(), !this.isConnected || e !== this._setupToken) {
3137
+ await s.destroy();
3138
+ return;
3139
+ }
3140
+ this._editor = s, this._editor.setReadonly(this.readonly), this._pendingValue = this._editor.getMarkdown(), this._setStatus(null);
3141
+ } catch {
3142
+ e === this._setupToken && this._setStatus("Failed to load editor");
3143
+ }
3144
+ }
3145
+ async _destroyEditor() {
3146
+ let t = this._editor;
3147
+ if (this._editor = null, !!t) try {
3148
+ await t.destroy();
3149
+ } catch {
3150
+ }
3151
+ }
3152
+ _queueChange(t) {
3153
+ this._clearChangeTimer(), this._changeTimer = setTimeout(() => {
3154
+ this._changeTimer = null, this.dispatchEvent(new CustomEvent("dt-change", { bubbles: true, composed: true, detail: { value: t } }));
3155
+ }, 300);
3156
+ }
3157
+ _clearChangeTimer() {
3158
+ this._changeTimer && (clearTimeout(this._changeTimer), this._changeTimer = null);
3159
+ }
3160
+ _setStatus(t) {
3161
+ if (t) {
3162
+ this._status.hidden = false, this._status.textContent = t;
3163
+ return;
3164
+ }
3165
+ this._status.hidden = true;
3166
+ }
3167
+ };
3168
+ customElements.get("dt-tooltip") || customElements.define("dt-tooltip", x);
3169
+ customElements.get("dt-card") || customElements.define("dt-card", w);
3170
+ customElements.get("dt-select") || customElements.define("dt-select", y);
3171
+ customElements.get("dt-grid") || customElements.define("dt-grid", k);
3172
+ customElements.get("dt-stack") || customElements.define("dt-stack", C);
3173
+ customElements.get("dt-stat") || customElements.define("dt-stat", E);
3174
+ customElements.get("dt-badge") || customElements.define("dt-badge", S);
3175
+ customElements.get("dt-button") || customElements.define("dt-button", D);
3176
+ customElements.get("dt-divider") || customElements.define("dt-divider", A);
3177
+ customElements.get("dt-list-view") || customElements.define("dt-list-view", z);
3178
+ customElements.get("dt-table-view") || customElements.define("dt-table-view", T);
3179
+ customElements.get("dt-column") || customElements.define("dt-column", b);
3180
+ customElements.get("dt-chart") || customElements.define("dt-chart", R);
3181
+ customElements.get("dt-markdown") || customElements.define("dt-markdown", P);
3182
+ customElements.get("dt-markdown-editor") || customElements.define("dt-markdown-editor", N);
3183
+
3184
+ // src/components/NoteEditor.tsx
3185
+ function stripFrontMatter(raw) {
3186
+ const match = raw.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?([\s\S]*)$/);
3187
+ return match ? match[1] : raw;
3188
+ }
3189
+ var NoteEditor = forwardRef(function NoteEditor2({ note, loading, onSave }, ref) {
3190
+ const editorRef = useRef(null);
3191
+ const [saveStatus, setSaveStatus] = useState("idle");
3192
+ const saveTimerRef = useRef(null);
3193
+ const onSaveRef = useRef(onSave);
3194
+ onSaveRef.current = onSave;
3195
+ useEffect(() => {
3196
+ if (editorRef.current && note) {
3197
+ const bodyContent = stripFrontMatter(note.content);
3198
+ editorRef.current.value = bodyContent;
3199
+ }
3200
+ }, [note?.id]);
3201
+ useEffect(() => {
3202
+ const editor = editorRef.current;
3203
+ if (!editor) return;
3204
+ const handleChange = (e) => {
3205
+ const detail = e.detail;
3206
+ if (!detail) return;
3207
+ if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
3208
+ setSaveStatus("saving");
3209
+ saveTimerRef.current = setTimeout(() => {
3210
+ onSaveRef.current(detail.value);
3211
+ setSaveStatus("saved");
3212
+ }, 500);
3213
+ };
3214
+ editor.addEventListener("dt-change", handleChange);
3215
+ return () => editor.removeEventListener("dt-change", handleChange);
3216
+ }, []);
3217
+ useEffect(() => {
3218
+ return () => {
3219
+ if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
3220
+ };
3221
+ }, []);
3222
+ useImperativeHandle(
3223
+ ref,
3224
+ () => ({
3225
+ getMarkdown() {
3226
+ return editorRef.current?.value ?? null;
3227
+ },
3228
+ setMarkdown(markdown) {
3229
+ if (editorRef.current) {
3230
+ editorRef.current.value = markdown;
3231
+ }
3232
+ },
3233
+ getCursorLine() {
3234
+ return 1;
3235
+ },
3236
+ getSelectedText() {
3237
+ return "";
3238
+ }
3239
+ }),
3240
+ []
3241
+ );
3242
+ if (!note) {
3243
+ return /* @__PURE__ */ jsx("div", { className: NoteApp_default.editorPanel, children: /* @__PURE__ */ jsx("div", { className: NoteApp_default.editorPlaceholder, children: loading ? "Loading..." : "Select a note or create a new one" }) });
3244
+ }
3245
+ return /* @__PURE__ */ jsxs("div", { className: NoteApp_default.editorPanel, children: [
3246
+ /* @__PURE__ */ jsxs("div", { className: NoteApp_default.editorHeader, children: [
3247
+ /* @__PURE__ */ jsxs("div", { children: [
3248
+ /* @__PURE__ */ jsx("div", { className: NoteApp_default.editorTitle, children: note.title }),
3249
+ note.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: NoteApp_default.editorTags, children: note.tags.map((tag) => /* @__PURE__ */ jsx("span", { className: NoteApp_default.editorTag, children: tag }, tag)) })
3250
+ ] }),
3251
+ /* @__PURE__ */ jsx("span", { className: saveStatus === "saving" ? NoteApp_default.saveStatusSaving : NoteApp_default.saveStatus, children: saveStatus === "saving" ? "Saving..." : saveStatus === "saved" ? "Saved" : "" })
3252
+ ] }),
3253
+ /* @__PURE__ */ jsx("div", { className: NoteApp_default.editorBody, children: /* @__PURE__ */ jsx(
3254
+ "dt-markdown-editor",
3255
+ {
3256
+ ref: editorRef,
3257
+ placeholder: "Start writing...",
3258
+ style: { height: "100%" }
3259
+ }
3260
+ ) })
3261
+ ] });
3262
+ });
3263
+
3264
+ // src/components/NoteActions.tsx
3265
+ import { ActionsProvider, Action, useCommand } from "@desktalk/sdk";
3266
+
3267
+ // src/lib/frontmatter.ts
3268
+ var FM_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
3269
+ function parseFrontMatter(raw) {
3270
+ const match = raw.match(FM_REGEX);
3271
+ if (!match) {
3272
+ const heading = raw.match(/^#\s+(.+)$/m);
3273
+ return { title: heading ? heading[1].trim() : "Untitled", tags: [], created: null, body: raw };
3274
+ }
3275
+ const yaml = match[1];
3276
+ const body = match[2];
3277
+ let title = "Untitled";
3278
+ let tags = [];
3279
+ let created = null;
3280
+ let inTags = false;
3281
+ for (const line of yaml.split("\n")) {
3282
+ const trimmed = line.trim();
3283
+ if (trimmed.startsWith("title:")) {
3284
+ title = trimmed.slice(6).trim().replace(/^["']|["']$/g, "");
3285
+ inTags = false;
3286
+ } else if (trimmed.startsWith("created:")) {
3287
+ created = trimmed.slice(8).trim();
3288
+ inTags = false;
3289
+ } else if (trimmed.startsWith("tags:")) {
3290
+ inTags = true;
3291
+ const inline = trimmed.slice(5).trim();
3292
+ if (inline.startsWith("[") && inline.endsWith("]")) {
3293
+ tags = inline.slice(1, -1).split(",").map((t) => t.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
3294
+ inTags = false;
3295
+ }
3296
+ } else if (inTags && trimmed.startsWith("- ")) {
3297
+ tags.push(
3298
+ trimmed.slice(2).trim().replace(/^["']|["']$/g, "")
3299
+ );
3300
+ } else {
3301
+ inTags = false;
3302
+ }
3303
+ }
3304
+ return { title, tags, created, body };
3305
+ }
3306
+ function serializeFrontMatter(title, tags, created, body) {
3307
+ const lines = ["---", `title: "${title.replace(/"/g, '\\"')}"`];
3308
+ if (tags.length > 0) {
3309
+ lines.push("tags:");
3310
+ for (const tag of tags) lines.push(` - ${tag}`);
3311
+ }
3312
+ lines.push(`created: ${created}`, "---", "", body);
3313
+ return lines.join("\n");
3314
+ }
3315
+
3316
+ // src/components/NoteActions.tsx
3317
+ function computeDiff(oldContent, newContent, oldText, newText, matchIndex) {
3318
+ const linesBefore = oldContent.substring(0, matchIndex).split("\n");
3319
+ const firstChangedLine = linesBefore.length;
3320
+ const oldLines = oldText.split("\n");
3321
+ const newLines = newText.split("\n");
3322
+ const contextStart = Math.max(0, firstChangedLine - 4);
3323
+ const allOldLines = oldContent.split("\n");
3324
+ const allNewLines = newContent.split("\n");
3325
+ const lines = [];
3326
+ lines.push(
3327
+ `@@ -${firstChangedLine},${oldLines.length} +${firstChangedLine},${newLines.length} @@`
3328
+ );
3329
+ for (let i = contextStart; i < firstChangedLine - 1; i++) {
3330
+ lines.push(` ${allOldLines[i]}`);
3331
+ }
3332
+ for (const l of oldLines) {
3333
+ lines.push(`-${l}`);
3334
+ }
3335
+ for (const l of newLines) {
3336
+ lines.push(`+${l}`);
3337
+ }
3338
+ const afterStart = firstChangedLine - 1 + oldLines.length;
3339
+ const afterEnd = Math.min(allNewLines.length, afterStart + 3);
3340
+ for (let i = afterStart; i < afterEnd; i++) {
3341
+ if (allNewLines[i] !== void 0) {
3342
+ lines.push(` ${allNewLines[i]}`);
3343
+ }
3344
+ }
3345
+ return { diff: lines.join("\n"), firstChangedLine };
3346
+ }
3347
+ function NoteActions({
3348
+ children,
3349
+ selectedNoteId,
3350
+ selectedNote,
3351
+ notes,
3352
+ editorRef,
3353
+ onNoteCreated,
3354
+ onNoteDeleted,
3355
+ onSearch,
3356
+ onNoteUpdated,
3357
+ onSelectNote,
3358
+ onRefresh: _onRefresh
3359
+ }) {
3360
+ const createNote = useCommand("notes.create");
3361
+ const deleteNote = useCommand("notes.delete");
3362
+ const searchNotes = useCommand("notes.search");
3363
+ const updateNote = useCommand(
3364
+ "notes.update"
3365
+ );
3366
+ const handleCreate = useCallback(
3367
+ async (params) => {
3368
+ const note = await createNote({
3369
+ title: params?.title || void 0,
3370
+ content: params?.content || void 0,
3371
+ tags: params?.tags || void 0,
3372
+ path: params?.path || void 0
3373
+ });
3374
+ onNoteCreated(note);
3375
+ return note;
3376
+ },
3377
+ [createNote, onNoteCreated]
3378
+ );
3379
+ const handleDelete = useCallback(async () => {
3380
+ if (!selectedNoteId) return;
3381
+ await deleteNote({ id: selectedNoteId });
3382
+ onNoteDeleted(selectedNoteId);
3383
+ }, [deleteNote, selectedNoteId, onNoteDeleted]);
3384
+ const handleSearch = useCallback(
3385
+ async (params) => {
3386
+ const query = params?.query || "";
3387
+ onSearch(query);
3388
+ const results = await searchNotes({ query });
3389
+ return results;
3390
+ },
3391
+ [searchNotes, onSearch]
3392
+ );
3393
+ const getRawContent = useCallback(() => {
3394
+ if (!selectedNote) return null;
3395
+ const handle = editorRef.current;
3396
+ if (!handle) return null;
3397
+ const body = handle.getMarkdown();
3398
+ if (body === null) return null;
3399
+ return serializeFrontMatter(
3400
+ selectedNote.title,
3401
+ selectedNote.tags,
3402
+ selectedNote.createdAt,
3403
+ body
3404
+ );
3405
+ }, [selectedNote, editorRef]);
3406
+ const handleListNotes = useCallback(async () => {
3407
+ const listed = notes.slice(0, 20).map((n) => ({
3408
+ id: n.id,
3409
+ title: n.title,
3410
+ updatedAt: n.updatedAt,
3411
+ selected: n.id === selectedNoteId
3412
+ }));
3413
+ return { notes: listed };
3414
+ }, [notes, selectedNoteId]);
3415
+ const handleSelectNote = useCallback(
3416
+ async (params) => {
3417
+ const id = params?.id;
3418
+ if (!id) {
3419
+ return { success: false, error: "id parameter is required" };
3420
+ }
3421
+ const found = notes.find((n) => n.id === id);
3422
+ if (!found) {
3423
+ return { success: false, error: `Note not found: ${id}` };
3424
+ }
3425
+ await onSelectNote(id);
3426
+ return { success: true };
3427
+ },
3428
+ [notes, onSelectNote]
3429
+ );
3430
+ const handleGetEditingContext = useCallback(async () => {
3431
+ if (!selectedNoteId || !selectedNote) {
3432
+ return { error: "No note is currently open" };
3433
+ }
3434
+ const handle = editorRef.current;
3435
+ if (!handle) {
3436
+ return { error: "Editor is not ready" };
3437
+ }
3438
+ const content = getRawContent();
3439
+ if (content === null) {
3440
+ return { error: "Editor is not ready" };
3441
+ }
3442
+ return {
3443
+ id: selectedNote.id,
3444
+ title: selectedNote.title,
3445
+ content,
3446
+ cursorLine: handle.getCursorLine(),
3447
+ selectedText: handle.getSelectedText()
3448
+ };
3449
+ }, [selectedNoteId, selectedNote, editorRef, getRawContent]);
3450
+ const handleEditNote = useCallback(
3451
+ async (params) => {
3452
+ if (!selectedNoteId || !selectedNote) {
3453
+ return { success: false, error: "No note is currently open" };
3454
+ }
3455
+ const handle = editorRef.current;
3456
+ if (!handle) {
3457
+ return { success: false, error: "Editor is not ready" };
3458
+ }
3459
+ const oldText = params?.old_text;
3460
+ const newText = params?.new_text;
3461
+ if (oldText === void 0 || newText === void 0) {
3462
+ return { success: false, error: "Both old_text and new_text are required" };
3463
+ }
3464
+ const currentRaw = getRawContent();
3465
+ if (currentRaw === null) {
3466
+ return { success: false, error: "Editor is not ready" };
3467
+ }
3468
+ let newRaw;
3469
+ let matchIndex;
3470
+ if (oldText === "") {
3471
+ newRaw = newText + currentRaw;
3472
+ matchIndex = 0;
3473
+ } else {
3474
+ const firstIndex = currentRaw.indexOf(oldText);
3475
+ if (firstIndex === -1) {
3476
+ return { success: false, error: "Text not found in note" };
3477
+ }
3478
+ const secondIndex = currentRaw.indexOf(oldText, firstIndex + 1);
3479
+ if (secondIndex !== -1) {
3480
+ let count = 2;
3481
+ let searchFrom = secondIndex + 1;
3482
+ while (true) {
3483
+ const idx = currentRaw.indexOf(oldText, searchFrom);
3484
+ if (idx === -1) break;
3485
+ count++;
3486
+ searchFrom = idx + 1;
3487
+ }
3488
+ return {
3489
+ success: false,
3490
+ error: `Text appears ${count} times; provide more surrounding context to make it unique`
3491
+ };
3492
+ }
3493
+ newRaw = currentRaw.substring(0, firstIndex) + newText + currentRaw.substring(firstIndex + oldText.length);
3494
+ matchIndex = firstIndex;
3495
+ }
3496
+ const parsed = parseFrontMatter(newRaw);
3497
+ handle.setMarkdown(parsed.body);
3498
+ const tagsChanged = parsed.tags.length !== selectedNote.tags.length || parsed.tags.some((t, i) => t !== selectedNote.tags[i]);
3499
+ const titleChanged = parsed.title !== selectedNote.title;
3500
+ if (tagsChanged || titleChanged) {
3501
+ const updated = await updateNote({
3502
+ id: selectedNoteId,
3503
+ tags: parsed.tags,
3504
+ // Send the full content so backend can parse the new title
3505
+ content: parsed.body
3506
+ });
3507
+ onNoteUpdated(updated);
3508
+ }
3509
+ const { diff, firstChangedLine } = computeDiff(
3510
+ currentRaw,
3511
+ newRaw,
3512
+ oldText,
3513
+ newText,
3514
+ matchIndex
3515
+ );
3516
+ return { success: true, diff, firstChangedLine };
3517
+ },
3518
+ [selectedNoteId, selectedNote, editorRef, getRawContent, updateNote, onNoteUpdated]
3519
+ );
3520
+ return /* @__PURE__ */ jsxs(ActionsProvider, { children: [
3521
+ /* @__PURE__ */ jsx(
3522
+ Action,
3523
+ {
3524
+ name: "Create Note",
3525
+ description: "Create a new note with optional title, content, and path",
3526
+ params: {
3527
+ title: { type: "string", description: "Note title", required: false },
3528
+ content: { type: "string", description: "Note content in Markdown", required: false },
3529
+ tags: { type: "string", description: "Comma-separated tags", required: false },
3530
+ path: {
3531
+ type: "string",
3532
+ description: 'Relative path for the note (e.g. "work/meeting-notes"). Becomes the note ID. Auto-generated if omitted.',
3533
+ required: false
3534
+ }
3535
+ },
3536
+ handler: handleCreate
3537
+ }
3538
+ ),
3539
+ /* @__PURE__ */ jsx(
3540
+ Action,
3541
+ {
3542
+ name: "Delete Note",
3543
+ description: "Delete the currently selected note",
3544
+ handler: handleDelete
3545
+ }
3546
+ ),
3547
+ /* @__PURE__ */ jsx(
3548
+ Action,
3549
+ {
3550
+ name: "Search Notes",
3551
+ description: "Search notes by keyword",
3552
+ params: {
3553
+ query: { type: "string", description: "Search query", required: true }
3554
+ },
3555
+ handler: handleSearch
3556
+ }
3557
+ ),
3558
+ /* @__PURE__ */ jsx(
3559
+ Action,
3560
+ {
3561
+ name: "List Notes",
3562
+ description: "Return the 20 most recent notes with selection status",
3563
+ handler: handleListNotes
3564
+ }
3565
+ ),
3566
+ /* @__PURE__ */ jsx(
3567
+ Action,
3568
+ {
3569
+ name: "Select Note",
3570
+ description: "Select a note by ID and open it in the editor",
3571
+ params: {
3572
+ id: {
3573
+ type: "string",
3574
+ description: "Note ID (relative path without .md)",
3575
+ required: true
3576
+ }
3577
+ },
3578
+ handler: handleSelectNote
3579
+ }
3580
+ ),
3581
+ /* @__PURE__ */ jsx(
3582
+ Action,
3583
+ {
3584
+ name: "Get Editing Context",
3585
+ description: "Return the current editor state for the selected note including content, cursor position, and selected text",
3586
+ handler: handleGetEditingContext
3587
+ }
3588
+ ),
3589
+ /* @__PURE__ */ jsx(
3590
+ Action,
3591
+ {
3592
+ name: "Edit Note",
3593
+ description: "Apply a text replacement to the current note content including front matter. Use old_text to find exact text and new_text to replace it. To edit tags or title, modify the YAML front matter directly.",
3594
+ params: {
3595
+ old_text: {
3596
+ type: "string",
3597
+ description: "Exact text to find in the note content (must appear exactly once). Searches the full content including YAML front matter. Use empty string to insert at beginning.",
3598
+ required: true
3599
+ },
3600
+ new_text: {
3601
+ type: "string",
3602
+ description: "Replacement text",
3603
+ required: true
3604
+ }
3605
+ },
3606
+ handler: handleEditNote
3607
+ }
3608
+ ),
3609
+ children
3610
+ ] });
3611
+ }
3612
+
3613
+ // src/frontend.tsx
3614
+ var COMPACT_WIDTH = 720;
3615
+ function NoteApp() {
3616
+ const [notes, setNotes] = useState([]);
3617
+ const [selectedId, setSelectedId] = useState(null);
3618
+ const [currentNote, setCurrentNote] = useState(null);
3619
+ const [searchQuery, setSearchQuery] = useState("");
3620
+ const [loadingNote, setLoadingNote] = useState(false);
3621
+ const [compact, setCompact] = useState(false);
3622
+ const editorRef = useRef(null);
3623
+ const rootRef = useRef(null);
3624
+ const listNotes = useCommand2("notes.list");
3625
+ const getNote = useCommand2("notes.get");
3626
+ const updateNote = useCommand2(
3627
+ "notes.update"
3628
+ );
3629
+ const searchNotes = useCommand2("notes.search");
3630
+ const createNote = useCommand2(
3631
+ "notes.create"
3632
+ );
3633
+ const fetchNotes = useCallback(async () => {
3634
+ try {
3635
+ let result;
3636
+ if (searchQuery) {
3637
+ result = await searchNotes({ query: searchQuery });
3638
+ } else {
3639
+ result = await listNotes();
3640
+ }
3641
+ setNotes(result);
3642
+ } catch (err) {
3643
+ console.error("Failed to fetch notes:", err);
3644
+ }
3645
+ }, [listNotes, searchNotes, searchQuery]);
3646
+ const refresh = useCallback(() => {
3647
+ fetchNotes();
3648
+ }, [fetchNotes]);
3649
+ useEffect(() => {
3650
+ refresh();
3651
+ }, [refresh]);
3652
+ useEffect(() => {
3653
+ if (!rootRef.current) return;
3654
+ const updateLayout = (width) => {
3655
+ setCompact(width <= COMPACT_WIDTH);
3656
+ };
3657
+ updateLayout(rootRef.current.clientWidth);
3658
+ const observer = new ResizeObserver((entries) => {
3659
+ const entry = entries[0];
3660
+ if (!entry) return;
3661
+ updateLayout(entry.contentRect.width);
3662
+ });
3663
+ observer.observe(rootRef.current);
3664
+ return () => observer.disconnect();
3665
+ }, []);
3666
+ const selectNote = useCallback(
3667
+ async (id) => {
3668
+ setSelectedId(id);
3669
+ setLoadingNote(true);
3670
+ try {
3671
+ const note = await getNote({ id });
3672
+ setCurrentNote(note);
3673
+ } catch (err) {
3674
+ console.error("Failed to load note:", err);
3675
+ setCurrentNote(null);
3676
+ } finally {
3677
+ setLoadingNote(false);
3678
+ }
3679
+ },
3680
+ [getNote]
3681
+ );
3682
+ const searchTimerRef = useRef(null);
3683
+ const handleSearchChange = useCallback((query) => {
3684
+ setSearchQuery(query);
3685
+ if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
3686
+ searchTimerRef.current = setTimeout(() => {
3687
+ }, 300);
3688
+ }, []);
3689
+ const handleEditorSave = useCallback(
3690
+ async (markdown) => {
3691
+ if (!selectedId || !currentNote) return;
3692
+ try {
3693
+ const updated = await updateNote({
3694
+ id: selectedId,
3695
+ content: markdown
3696
+ });
3697
+ setCurrentNote(updated);
3698
+ fetchNotes();
3699
+ } catch (err) {
3700
+ console.error("Failed to save note:", err);
3701
+ }
3702
+ },
3703
+ [selectedId, currentNote, updateNote, fetchNotes]
3704
+ );
3705
+ const handleNoteCreated = useCallback(
3706
+ (note) => {
3707
+ refresh();
3708
+ setSelectedId(note.id);
3709
+ setCurrentNote(note);
3710
+ },
3711
+ [refresh]
3712
+ );
3713
+ const handleNoteDeleted = useCallback(
3714
+ (id) => {
3715
+ if (selectedId === id) {
3716
+ setSelectedId(null);
3717
+ setCurrentNote(null);
3718
+ }
3719
+ refresh();
3720
+ },
3721
+ [selectedId, refresh]
3722
+ );
3723
+ const handleNoteUpdated = useCallback(
3724
+ (note) => {
3725
+ if (selectedId === note.id) {
3726
+ setCurrentNote(note);
3727
+ }
3728
+ refresh();
3729
+ },
3730
+ [selectedId, refresh]
3731
+ );
3732
+ const handleSearch = useCallback((query) => {
3733
+ setSearchQuery(query);
3734
+ }, []);
3735
+ const handleCreate = useCallback(async () => {
3736
+ try {
3737
+ const note = await createNote({});
3738
+ handleNoteCreated(note);
3739
+ } catch (err) {
3740
+ console.error("Failed to create note:", err);
3741
+ }
3742
+ }, [createNote, handleNoteCreated]);
3743
+ return /* @__PURE__ */ jsx(
3744
+ NoteActions,
3745
+ {
3746
+ selectedNoteId: selectedId,
3747
+ selectedNote: currentNote,
3748
+ notes,
3749
+ editorRef,
3750
+ onNoteCreated: handleNoteCreated,
3751
+ onNoteDeleted: handleNoteDeleted,
3752
+ onSearch: handleSearch,
3753
+ onNoteUpdated: handleNoteUpdated,
3754
+ onSelectNote: selectNote,
3755
+ onRefresh: refresh,
3756
+ children: /* @__PURE__ */ jsxs("div", { ref: rootRef, className: `${NoteApp_default.root}${compact ? ` ${NoteApp_default.rootCompact}` : ""}`, children: [
3757
+ /* @__PURE__ */ jsx(
3758
+ NoteList,
3759
+ {
3760
+ notes,
3761
+ selectedId,
3762
+ onSelect: selectNote,
3763
+ onCreate: handleCreate,
3764
+ searchQuery,
3765
+ onSearchChange: handleSearchChange
3766
+ }
3767
+ ),
3768
+ /* @__PURE__ */ jsx(
3769
+ NoteEditor,
3770
+ {
3771
+ ref: editorRef,
3772
+ note: currentNote,
3773
+ loading: loadingNote,
3774
+ onSave: handleEditorSave
3775
+ }
3776
+ )
3777
+ ] })
3778
+ }
3779
+ );
3780
+ }
3781
+ function activate(ctx) {
3782
+ const root = createRoot(ctx.root);
3783
+ root.render(
3784
+ /* @__PURE__ */ jsx(WindowIdProvider, { windowId: ctx.windowId, children: /* @__PURE__ */ jsx(MiniAppIdProvider, { miniAppId: ctx.miniAppId, children: /* @__PURE__ */ jsx(NoteApp, {}) }) })
3785
+ );
3786
+ return {
3787
+ deactivate() {
3788
+ root.unmount();
3789
+ }
3790
+ };
3791
+ }
3792
+ export {
3793
+ activate
3794
+ };
3795
+ //# sourceMappingURL=frontend.js.map