@reopt-ai/opt-ui 1.4.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/COMPONENT_CATALOG.md +374 -84
  2. package/README.md +28 -7
  3. package/dist/app.css +146 -0
  4. package/dist/core/index.cjs +164 -324
  5. package/dist/core/index.d.cts +3 -5
  6. package/dist/core/index.d.ts +3 -5
  7. package/dist/core/index.js +3 -323
  8. package/dist/docs/01-getting-started.md +25 -5
  9. package/dist/docs/02-components/01-core.md +192 -46
  10. package/dist/docs/02-components/02-visuals.md +1 -1
  11. package/dist/docs/02-components/03-shells.md +177 -42
  12. package/dist/docs/02-components/04-surfaces.md +1 -1
  13. package/dist/docs/02-components/index.md +1 -1
  14. package/dist/docs/03-recipes/03-layouts.md +20 -12
  15. package/dist/docs/04-theming.md +3 -1
  16. package/dist/docs/05-migration/01-breaking-changes.md +28 -0
  17. package/dist/id-registry.cjs +1899 -1872
  18. package/dist/id-registry.d.cts +13 -10
  19. package/dist/id-registry.d.cts.map +1 -0
  20. package/dist/id-registry.d.ts +13 -10
  21. package/dist/id-registry.d.ts.map +1 -0
  22. package/dist/id-registry.js +1897 -1871
  23. package/dist/id-registry.js.map +1 -0
  24. package/dist/id-registry.json +44 -44
  25. package/dist/index.cjs +8294 -9613
  26. package/dist/index.d.cts +1486 -1438
  27. package/dist/index.d.cts.map +1 -0
  28. package/dist/index.d.ts +1486 -1438
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +7933 -9600
  31. package/dist/index.js.map +1 -0
  32. package/dist/meta.cjs +7461 -6765
  33. package/dist/meta.d.cts.map +1 -0
  34. package/dist/meta.d.ts.map +1 -0
  35. package/dist/meta.js +7460 -6736
  36. package/dist/meta.js.map +1 -0
  37. package/dist/pagination-By7Ozv3U.js +3788 -0
  38. package/dist/pagination-By7Ozv3U.js.map +1 -0
  39. package/dist/pagination-Uv3CnGJz.cjs +4677 -0
  40. package/dist/shader-surface-BK1GMt5_.d.cts +1788 -0
  41. package/dist/shader-surface-BK1GMt5_.d.cts.map +1 -0
  42. package/dist/shader-surface-BWhO2xkk.js +3715 -0
  43. package/dist/shader-surface-BWhO2xkk.js.map +1 -0
  44. package/dist/shader-surface-DIVWtpFl.d.ts +1788 -0
  45. package/dist/shader-surface-DIVWtpFl.d.ts.map +1 -0
  46. package/dist/shader-surface-DxLLfrE6.cjs +4108 -0
  47. package/dist/shells/index.cjs +51 -65
  48. package/dist/shells/index.d.cts +4 -5
  49. package/dist/shells/index.d.ts +4 -5
  50. package/dist/shells/index.js +3 -64
  51. package/dist/tailwind.css +54 -5
  52. package/dist/theme/presets/default.css +12 -12
  53. package/dist/theme/server.cjs +310 -0
  54. package/dist/theme/server.d.cts +117 -0
  55. package/dist/theme/server.d.cts.map +1 -0
  56. package/dist/theme/server.d.ts +117 -0
  57. package/dist/theme/server.d.ts.map +1 -0
  58. package/dist/theme/server.js +287 -0
  59. package/dist/theme/server.js.map +1 -0
  60. package/dist/types-D0FlcYnM.d.cts +301 -0
  61. package/dist/types-D0FlcYnM.d.cts.map +1 -0
  62. package/dist/types-D0FlcYnM.d.ts +301 -0
  63. package/dist/types-D0FlcYnM.d.ts.map +1 -0
  64. package/dist/visuals/index.cjs +10 -4
  65. package/dist/visuals/index.d.cts +2 -1
  66. package/dist/visuals/index.d.ts +2 -1
  67. package/dist/visuals/index.js +1 -2
  68. package/dist/workflow-canvas-3Jeevkgy.cjs +2599 -0
  69. package/dist/workflow-canvas-BGBAcjf-.js +2403 -0
  70. package/dist/workflow-canvas-BGBAcjf-.js.map +1 -0
  71. package/dist/workflow-canvas-Bar_O2SQ.d.ts +494 -0
  72. package/dist/workflow-canvas-Bar_O2SQ.d.ts.map +1 -0
  73. package/dist/workflow-canvas-DghDRtHn.d.cts +494 -0
  74. package/dist/workflow-canvas-DghDRtHn.d.cts.map +1 -0
  75. package/package.json +24 -8
  76. package/dist/chunk-3GWWZKX7.js +0 -38
  77. package/dist/chunk-AFF2HPE5.cjs +0 -5008
  78. package/dist/chunk-ELWICXYY.js +0 -4745
  79. package/dist/chunk-N4NDU5ET.cjs +0 -4745
  80. package/dist/chunk-ONE3C5RV.cjs +0 -38
  81. package/dist/chunk-QWBHD54V.js +0 -3218
  82. package/dist/chunk-RBM2RNC2.js +0 -5008
  83. package/dist/chunk-X5WCXJAF.cjs +0 -3218
  84. package/dist/index-BZ_lBlO1.d.ts +0 -474
  85. package/dist/index-BuvxoWHf.d.cts +0 -474
  86. package/dist/index-DlAcuvQp.d.cts +0 -1686
  87. package/dist/index-Slu5hOj1.d.ts +0 -1686
  88. package/dist/types-D4-0lwaE.d.cts +0 -298
  89. package/dist/types-D4-0lwaE.d.ts +0 -298
@@ -1,3218 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }"use client";
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
- var _chunkAFF2HPE5cjs = require('./chunk-AFF2HPE5.cjs');
97
-
98
-
99
-
100
-
101
- var _chunkONE3C5RVcjs = require('./chunk-ONE3C5RV.cjs');
102
-
103
- // src/core/command.tsx
104
- var _lucidereact = require('lucide-react');
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
- var _optuiprimitives = require('@reopt-ai/opt-ui-primitives');
114
- var _jsxruntime = require('react/jsx-runtime');
115
- function Command(_a) {
116
- var _b = _a, { className } = _b, props = _chunkONE3C5RVcjs.__objRest.call(void 0, _b, ["className"]);
117
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
118
- _optuiprimitives.CommandRoot,
119
- _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {
120
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
121
- "bg-surface text-text-primary flex w-full flex-col overflow-hidden rounded-xl",
122
- className
123
- )
124
- }, props), {
125
- "data-opt-id": "4FYBW",
126
- "data-opt-slug": "command.Command"
127
- })
128
- );
129
- }
130
- function CommandDialog({
131
- open,
132
- onOpenChange,
133
- title = "Command Palette",
134
- description = "\uAC80\uC0C9 \uD6C4 Enter \uB610\uB294 \uD074\uB9AD\uC73C\uB85C \uBA85\uB839\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
135
- className,
136
- commandClassName,
137
- shouldFilter,
138
- filter,
139
- children
140
- }) {
141
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
142
- _chunkAFF2HPE5cjs.DialogRoot,
143
- {
144
- open,
145
- onOpenChange,
146
- "data-opt-id": "DVRSX",
147
- "data-opt-slug": "command.CommandDialog",
148
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
149
- _chunkAFF2HPE5cjs.DialogPanel,
150
- {
151
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
152
- "top-[20%] left-1/2 -translate-x-1/2",
153
- "w-full max-w-lg overflow-hidden p-0 shadow-2xl",
154
- className
155
- ),
156
- children: [
157
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.DialogHeading, { className: "sr-only", children: title }),
158
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.DialogDescription, { className: "sr-only", children: description }),
159
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
160
- Command,
161
- {
162
- shouldFilter,
163
- filter,
164
- className: commandClassName,
165
- children
166
- }
167
- )
168
- ]
169
- }
170
- )
171
- }
172
- );
173
- }
174
- function CommandInput(_a) {
175
- var _b = _a, {
176
- className,
177
- trailing,
178
- wrapperClassName,
179
- placeholder,
180
- "aria-label": ariaLabel
181
- } = _b, props = _chunkONE3C5RVcjs.__objRest.call(void 0, _b, [
182
- "className",
183
- "trailing",
184
- "wrapperClassName",
185
- "placeholder",
186
- "aria-label"
187
- ]);
188
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
189
- "div",
190
- {
191
- "data-slot": "command-input-wrapper",
192
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
193
- "border-border-subtle gap-element flex h-12 items-center border-b px-3",
194
- wrapperClassName
195
- ),
196
- "data-opt-id": "HB1K3",
197
- "data-opt-slug": "command.CommandInput",
198
- children: [
199
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.SearchIcon, { "aria-hidden": true, className: "text-text-tertiary size-4 shrink-0" }),
200
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
201
- _optuiprimitives.CommandInput,
202
- _chunkONE3C5RVcjs.__spreadValues.call(void 0, {
203
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
204
- // cmdk 컨벤션 — input 자체는 ring 없이 자연스러운 검색 경험.
205
- // 포커스 표시는 wrapper(border-b)가 시각적 컨텍스트로 제공.
206
- "text-text-primary placeholder:text-text-tertiary flex h-full w-full bg-transparent text-sm outline-none focus-visible:ring-0 focus-visible:outline-none",
207
- "disabled:cursor-not-allowed disabled:opacity-50",
208
- className
209
- ),
210
- placeholder,
211
- "aria-label": ariaLabel != null ? ariaLabel : typeof placeholder === "string" ? placeholder : "Command search"
212
- }, props)
213
- ),
214
- trailing
215
- ]
216
- }
217
- );
218
- }
219
- function CommandList(_a) {
220
- var _b = _a, {
221
- className,
222
- "aria-label": ariaLabel
223
- } = _b, props = _chunkONE3C5RVcjs.__objRest.call(void 0, _b, [
224
- "className",
225
- "aria-label"
226
- ]);
227
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
228
- _optuiprimitives.CommandList,
229
- _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {
230
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
231
- "max-h-80 scroll-py-1 overflow-x-hidden overflow-y-auto p-1",
232
- className
233
- ),
234
- "aria-label": ariaLabel != null ? ariaLabel : "Commands"
235
- }, props), {
236
- "data-opt-id": "NPXC5",
237
- "data-opt-slug": "command.CommandList"
238
- })
239
- );
240
- }
241
- function CommandEmpty(_a) {
242
- var _b = _a, { className } = _b, props = _chunkONE3C5RVcjs.__objRest.call(void 0, _b, ["className"]);
243
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
244
- _optuiprimitives.CommandEmpty,
245
- _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {
246
- className: _chunkAFF2HPE5cjs.cn.call(void 0, "text-text-tertiary py-6 text-center text-sm", className)
247
- }, props), {
248
- "data-opt-id": "A8BZM",
249
- "data-opt-slug": "command.CommandEmpty"
250
- })
251
- );
252
- }
253
- function CommandGroup(_a) {
254
- var _b = _a, {
255
- className,
256
- heading
257
- } = _b, props = _chunkONE3C5RVcjs.__objRest.call(void 0, _b, [
258
- "className",
259
- "heading"
260
- ]);
261
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
262
- _optuiprimitives.CommandGroup,
263
- _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {
264
- heading: heading != null ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-text-tertiary px-2 py-1.5 text-xs font-medium", children: heading }) : void 0,
265
- className: _chunkAFF2HPE5cjs.cn.call(void 0, "py-1", className)
266
- }, props), {
267
- "data-opt-id": "JPK1Y",
268
- "data-opt-slug": "command.CommandGroup"
269
- })
270
- );
271
- }
272
- function CommandSeparator(_a) {
273
- var _b = _a, {
274
- className
275
- } = _b, props = _chunkONE3C5RVcjs.__objRest.call(void 0, _b, [
276
- "className"
277
- ]);
278
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
279
- _optuiprimitives.CommandSeparator,
280
- _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {
281
- className: _chunkAFF2HPE5cjs.cn.call(void 0, "bg-border-subtle -mx-1 my-1 h-px", className)
282
- }, props), {
283
- "data-opt-id": "10P0E",
284
- "data-opt-slug": "command.CommandSeparator"
285
- })
286
- );
287
- }
288
- function CommandItem(_a) {
289
- var _b = _a, { className } = _b, props = _chunkONE3C5RVcjs.__objRest.call(void 0, _b, ["className"]);
290
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
291
- _optuiprimitives.CommandItem,
292
- _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {
293
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
294
- "text-text-primary flex cursor-pointer items-center gap-2 rounded-md px-2 py-2 text-sm select-none",
295
- "data-[active-item]:bg-accent data-[active-item]:text-accent-fg",
296
- "data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50",
297
- "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
298
- className
299
- )
300
- }, props), {
301
- "data-opt-id": "K674W",
302
- "data-opt-slug": "command.CommandItem"
303
- })
304
- );
305
- }
306
- function CommandShortcut(_a) {
307
- var _b = _a, {
308
- className
309
- } = _b, props = _chunkONE3C5RVcjs.__objRest.call(void 0, _b, [
310
- "className"
311
- ]);
312
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
313
- "span",
314
- _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {
315
- "data-slot": "command-shortcut",
316
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
317
- "text-text-tertiary ml-auto text-xs tracking-widest",
318
- "data-[active-item]:text-accent-fg/80",
319
- className
320
- )
321
- }, props), {
322
- "data-opt-id": "75CQK",
323
- "data-opt-slug": "command.CommandShortcut"
324
- })
325
- );
326
- }
327
-
328
- // src/shells/command-palette.tsx
329
- var _react = require('react'); var React = _interopRequireWildcard(_react);
330
-
331
- var DEFAULT_LABELS = {
332
- title: "Command Palette",
333
- description: "\uAC80\uC0C9 \uD6C4 Enter \uB610\uB294 \uD074\uB9AD\uC73C\uB85C \uBA85\uB839\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
334
- input: "\uBA85\uB839\uC5B4 \uAC80\uC0C9",
335
- placeholder: "\uBA85\uB839\uC5B4\uB97C \uAC80\uC0C9\uD558\uC138\uC694...",
336
- list: "\uBA85\uB839\uC5B4 \uBAA9\uB85D",
337
- empty: "\uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
338
- escape: "ESC"
339
- };
340
- function CommandPalette({
341
- commands,
342
- open,
343
- onOpenChange,
344
- onSelect,
345
- inline = false,
346
- labels,
347
- footer,
348
- empty,
349
- inputTrailing,
350
- className
351
- }) {
352
- const resolvedLabels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, DEFAULT_LABELS), labels);
353
- const hasCommands = commands.length > 0;
354
- const grouped = _react.useMemo.call(void 0, () => {
355
- var _a;
356
- const map = /* @__PURE__ */ new Map();
357
- for (const cmd of commands) {
358
- const list = (_a = map.get(cmd.group)) != null ? _a : [];
359
- list.push(cmd);
360
- map.set(cmd.group, list);
361
- }
362
- return map;
363
- }, [commands]);
364
- const handleSelect = (cmdId) => {
365
- const cmd = commands.find((c) => c.id === cmdId);
366
- if (!cmd) return;
367
- onSelect == null ? void 0 : onSelect(cmd);
368
- onOpenChange(false);
369
- };
370
- const handleInputKeyDown = (e) => {
371
- if (e.key === "Escape" && !inline) {
372
- e.preventDefault();
373
- onOpenChange(false);
374
- }
375
- };
376
- const body = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
377
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
378
- CommandInput,
379
- {
380
- "aria-label": resolvedLabels.input,
381
- placeholder: resolvedLabels.placeholder,
382
- onKeyDown: handleInputKeyDown,
383
- trailing: inputTrailing != null ? inputTrailing : !inline ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.Kbd, { children: resolvedLabels.escape }) : void 0
384
- }
385
- ),
386
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, CommandList, { "aria-label": resolvedLabels.list, children: [
387
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CommandEmpty, { children: empty != null ? empty : resolvedLabels.empty }),
388
- hasCommands ? Array.from(grouped.entries()).map(([group, items]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CommandGroup, { heading: group, children: items.map((cmd) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
389
- CommandItem,
390
- {
391
- value: cmd.id,
392
- keywords: [
393
- cmd.label,
394
- cmd.group,
395
- ...cmd.shortcut ? [cmd.shortcut] : []
396
- ],
397
- onSelect: handleSelect,
398
- children: [
399
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: cmd.label }),
400
- cmd.shortcut && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CommandShortcut, { children: cmd.shortcut })
401
- ]
402
- },
403
- cmd.id
404
- )) }, group)) : null
405
- ] }),
406
- footer
407
- ] });
408
- if (inline) {
409
- if (!open) return null;
410
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
411
- Command,
412
- {
413
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
414
- "border-border bg-surface w-full max-w-lg border shadow-lg",
415
- className
416
- ),
417
- "data-opt-id": "ATTF5",
418
- "data-opt-slug": "command-palette.CommandPalette",
419
- children: body
420
- }
421
- );
422
- }
423
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
424
- CommandDialog,
425
- {
426
- open,
427
- onOpenChange,
428
- title: resolvedLabels.title,
429
- description: resolvedLabels.description,
430
- className,
431
- "data-opt-id": "ATTF5",
432
- "data-opt-slug": "command-palette.CommandPalette",
433
- children: body
434
- }
435
- );
436
- }
437
-
438
- // src/shells/command-palette-trigger.tsx
439
-
440
-
441
- function CommandPaletteTrigger({
442
- commands,
443
- onSelect,
444
- labels
445
- }) {
446
- if (commands.length === 0) return null;
447
- const [open, setOpen] = _react.useState.call(void 0, false);
448
- const handleKeyDown = _react.useCallback.call(void 0, (e) => {
449
- if ((e.metaKey || e.ctrlKey) && e.key === "k") {
450
- e.preventDefault();
451
- setOpen(true);
452
- }
453
- }, []);
454
- _react.useEffect.call(void 0, () => {
455
- document.addEventListener("keydown", handleKeyDown);
456
- return () => document.removeEventListener("keydown", handleKeyDown);
457
- }, [handleKeyDown]);
458
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
459
- CommandPalette,
460
- {
461
- commands,
462
- open,
463
- onOpenChange: setOpen,
464
- onSelect,
465
- labels,
466
- "data-opt-id": "4FCDB",
467
- "data-opt-slug": "command-palette-trigger.CommandPaletteTrigger"
468
- }
469
- );
470
- }
471
-
472
- // src/shells/dashboard-grid.tsx
473
-
474
- var defaultLabels = {
475
- ariaLabel: "\uB300\uC2DC\uBCF4\uB4DC \uD1B5\uACC4"
476
- };
477
- var MIN_DASHBOARD_COLUMNS = 1;
478
- var MAX_DASHBOARD_COLUMNS = 12;
479
- function normalizeDashboardColumns(columns) {
480
- if (!Number.isFinite(columns)) return MIN_DASHBOARD_COLUMNS;
481
- return Math.min(
482
- MAX_DASHBOARD_COLUMNS,
483
- Math.max(MIN_DASHBOARD_COLUMNS, Math.floor(columns))
484
- );
485
- }
486
- function DashboardGrid({
487
- stats,
488
- columns = 3,
489
- labels: customLabels
490
- }) {
491
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels), customLabels);
492
- const columnCount = normalizeDashboardColumns(columns);
493
- const rowStyle = {
494
- "--opt-dashboard-grid-columns": `repeat(${columnCount}, minmax(0, 1fr))`
495
- };
496
- const rows = [];
497
- for (let i = 0; i < stats.length; i += columnCount) {
498
- rows.push(stats.slice(i, i + columnCount));
499
- }
500
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
501
- _chunkAFF2HPE5cjs.CompositeProvider,
502
- {
503
- focusLoop: true,
504
- focusWrap: true,
505
- "data-opt-id": "BM7NA",
506
- "data-opt-slug": "dashboard-grid.DashboardGrid",
507
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
508
- _chunkAFF2HPE5cjs.Composite,
509
- {
510
- role: "grid",
511
- "aria-label": labels.ariaLabel,
512
- className: "gap-group flex flex-col",
513
- children: rows.map((row, ri) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
514
- _chunkAFF2HPE5cjs.CompositeRow,
515
- {
516
- className: "gap-group grid grid-cols-1 sm:[grid-template-columns:var(--opt-dashboard-grid-columns)]",
517
- style: rowStyle,
518
- children: row.map((stat) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
519
- _chunkAFF2HPE5cjs.CompositeItem,
520
- {
521
- className: "data-[active-item]:ring-ring data-[active-item]:ring-offset-ring-offset data-[focus-visible]:ring-ring data-[focus-visible]:ring-offset-ring-offset rounded-xl outline-none data-[active-item]:ring-2 data-[active-item]:ring-offset-2 data-[focus-visible]:ring-2 data-[focus-visible]:ring-offset-2",
522
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { role: "gridcell" }),
523
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.StatCard, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, stat))
524
- },
525
- stat.id
526
- ))
527
- },
528
- ri
529
- ))
530
- }
531
- )
532
- }
533
- );
534
- }
535
-
536
- // src/shells/search-combobox.tsx
537
- var _matchsorter = require('match-sorter');
538
-
539
-
540
- var defaultLabels2 = {
541
- noResults: "\uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
542
- loading: "Loading\u2026"
543
- };
544
- function SearchCombobox({
545
- items,
546
- placeholder = "\uAC80\uC0C9...",
547
- label = "\uAC80\uC0C9",
548
- onSelect,
549
- labels: customLabels,
550
- async: isAsync = false,
551
- onSearch,
552
- debounceMs = 300
553
- }) {
554
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels2), customLabels);
555
- const inputId = _react.useId.call(void 0, );
556
- const [query, setQuery] = _react.useState.call(void 0, "");
557
- const [asyncResults, setAsyncResults] = _react.useState.call(void 0, []);
558
- const [loading, setLoading] = _react.useState.call(void 0, false);
559
- const timerRef = _react.useRef.call(void 0, void 0);
560
- const searchGenerationRef = _react.useRef.call(void 0, 0);
561
- const syncMatches = _react.useMemo.call(void 0, () => {
562
- if (isAsync) return [];
563
- if (!query) return items;
564
- return _matchsorter.matchSorter.call(void 0, items, query);
565
- }, [query, items, isAsync]);
566
- const handleInput = (event) => {
567
- searchGenerationRef.current += 1;
568
- setQuery(event.currentTarget.value);
569
- };
570
- const handleValueChange = (item) => {
571
- searchGenerationRef.current += 1;
572
- setQuery(item);
573
- onSelect == null ? void 0 : onSelect(item);
574
- };
575
- _react.useEffect.call(void 0, () => {
576
- const generation = ++searchGenerationRef.current;
577
- if (timerRef.current) clearTimeout(timerRef.current);
578
- if (!isAsync || !onSearch) {
579
- setLoading(false);
580
- return;
581
- }
582
- if (!query) {
583
- setAsyncResults([]);
584
- setLoading(false);
585
- return;
586
- }
587
- setLoading(true);
588
- timerRef.current = setTimeout(async () => {
589
- try {
590
- const results = await onSearch(query);
591
- if (searchGenerationRef.current !== generation) {
592
- return;
593
- }
594
- setAsyncResults(results);
595
- } finally {
596
- if (searchGenerationRef.current === generation) {
597
- setLoading(false);
598
- }
599
- }
600
- }, debounceMs);
601
- return () => {
602
- if (timerRef.current) clearTimeout(timerRef.current);
603
- };
604
- }, [query, isAsync, onSearch, debounceMs]);
605
- const matches = isAsync ? asyncResults : syncMatches;
606
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
607
- "div",
608
- {
609
- className: "gap-element flex flex-col",
610
- "data-opt-id": "KH4TQ",
611
- "data-opt-slug": "search-combobox.SearchCombobox",
612
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.ComboboxRoot, { onValueChange: handleValueChange, children: [
613
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { htmlFor: inputId, className: _chunkAFF2HPE5cjs.OPT_TEXT_LABEL, children: label }),
614
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
615
- _chunkAFF2HPE5cjs.ComboboxInput,
616
- {
617
- id: inputId,
618
- placeholder,
619
- className: "max-w-xs",
620
- "aria-busy": loading || void 0,
621
- onInput: handleInput
622
- }
623
- ),
624
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.ComboboxPopover, { className: "max-w-xs", children: isAsync && loading ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
625
- "div",
626
- {
627
- className: "text-text-secondary gap-element flex items-center px-3 py-2 text-sm",
628
- role: "status",
629
- "aria-live": "polite",
630
- "aria-busy": "true",
631
- children: [
632
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.Spinner, { size: "sm", "aria-hidden": "true" }),
633
- labels.loading
634
- ]
635
- }
636
- ) : matches.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.ComboboxEmpty, { children: labels.noResults }) : matches.map((item) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.ComboboxItem, { value: item, children: item }, item)) })
637
- ] })
638
- }
639
- );
640
- }
641
-
642
- // src/shells/status-select.tsx
643
-
644
-
645
- var defaultLabels3 = {
646
- selectLabel: "\uC0C1\uD0DC",
647
- emptyMessage: "\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uC0C1\uD0DC \uC635\uC158\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
648
- };
649
- function StatusSelect({
650
- options,
651
- value: controlledValue,
652
- onChange,
653
- label,
654
- labels: customLabels
655
- }) {
656
- var _a, _b;
657
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels3), customLabels);
658
- const resolvedLabel = label != null ? label : labels.selectLabel;
659
- const [internalValue, setInternalValue] = _react.useState.call(void 0, (_b = (_a = options[0]) == null ? void 0 : _a.value) != null ? _b : "");
660
- const value = controlledValue != null ? controlledValue : internalValue;
661
- const selected = options.find((s) => s.value === value);
662
- if (options.length === 0) {
663
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
664
- "div",
665
- {
666
- className: "gap-element flex flex-col",
667
- "data-opt-id": "R46E6",
668
- "data-opt-slug": "status-select.StatusSelect",
669
- children: [
670
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _chunkAFF2HPE5cjs.OPT_TEXT_LABEL, children: resolvedLabel }),
671
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-text-tertiary text-sm", children: labels.emptyMessage })
672
- ]
673
- }
674
- );
675
- }
676
- const handleChange = (v) => {
677
- var _a2;
678
- const next = Array.isArray(v) ? (_a2 = v[0]) != null ? _a2 : "" : v;
679
- if (onChange) onChange(next);
680
- else setInternalValue(next);
681
- };
682
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
683
- "div",
684
- {
685
- className: "gap-element flex flex-col",
686
- "data-opt-id": "R46E6",
687
- "data-opt-slug": "status-select.StatusSelect",
688
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.SelectRoot, { value, onValueChange: handleChange, children: [
689
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.SelectLabel, { className: _chunkAFF2HPE5cjs.OPT_TEXT_LABEL, children: resolvedLabel }),
690
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
691
- _chunkAFF2HPE5cjs.SelectTrigger,
692
- {
693
- className: `${_chunkAFF2HPE5cjs.OPT_INPUT} max-w-xs items-center justify-between ${_chunkAFF2HPE5cjs.OPT_FOCUS}`,
694
- children: [
695
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "gap-element flex items-center", children: [
696
- (selected == null ? void 0 : selected.color) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `h-2 w-2 rounded-full ${selected.color}` }),
697
- selected == null ? void 0 : selected.label
698
- ] }),
699
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
700
- "svg",
701
- {
702
- className: "text-text-tertiary h-4 w-4",
703
- fill: "none",
704
- viewBox: "0 0 24 24",
705
- stroke: "currentColor",
706
- strokeWidth: 2,
707
- "aria-hidden": "true",
708
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
709
- "path",
710
- {
711
- strokeLinecap: "round",
712
- strokeLinejoin: "round",
713
- d: "m19.5 8.25-7.5 7.5-7.5-7.5"
714
- }
715
- )
716
- }
717
- )
718
- ]
719
- }
720
- ),
721
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
722
- _chunkAFF2HPE5cjs.SelectPopover,
723
- {
724
- className: `${_chunkAFF2HPE5cjs.OPT_SURFACE_POPOVER} ${_chunkAFF2HPE5cjs.OPT_ANIMATE_ENTER_EXIT} max-w-xs`,
725
- children: options.map((option) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.SelectItem, { value: option.value, children: [
726
- option.color && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `h-2 w-2 rounded-full ${option.color}` }),
727
- option.label
728
- ] }, option.value))
729
- }
730
- )
731
- ] })
732
- }
733
- );
734
- }
735
-
736
- // src/shells/app-menubar.tsx
737
-
738
- var defaultLabels4 = {
739
- ariaLabel: "Application menu"
740
- };
741
- function MenuSection({ menu }) {
742
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.MenuRoot, { children: [
743
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.MenuTrigger, { children: [
744
- menu.label,
745
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.MenuButtonArrow, {})
746
- ] }),
747
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.MenuPopover, { children: menu.items.map((item, i) => {
748
- var _a, _b, _c, _d;
749
- if (item.type === "separator") {
750
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.MenuSeparator, {}, `sep-${i}`);
751
- }
752
- if (item.type === "checkbox") {
753
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
754
- _chunkAFF2HPE5cjs.MenuItemCheckbox,
755
- {
756
- name: (_a = item.name) != null ? _a : item.id,
757
- value: (_b = item.value) != null ? _b : item.id,
758
- checked: item.checked,
759
- onChange: item.onChange,
760
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "gap-element flex items-center", children: [
761
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-4 text-center", children: item.checked ? "\u2713" : "" }),
762
- item.label
763
- ] })
764
- },
765
- item.id
766
- );
767
- }
768
- if (item.type === "radio") {
769
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
770
- _chunkAFF2HPE5cjs.MenuItemRadio,
771
- {
772
- name: (_c = item.name) != null ? _c : "",
773
- value: (_d = item.value) != null ? _d : "",
774
- checked: item.checked,
775
- onChange: item.onChange,
776
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "gap-element flex items-center", children: [
777
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-4 text-center", children: item.checked ? "\u25CF" : "" }),
778
- item.label
779
- ] })
780
- },
781
- item.id
782
- );
783
- }
784
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.MenuItem, { onClick: item.onClick, children: [
785
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: item.label }),
786
- item.shortcut && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.Kbd, { children: item.shortcut })
787
- ] }, item.id);
788
- }) })
789
- ] });
790
- }
791
- function AppMenubar({ menus, labels: customLabels }) {
792
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels4), customLabels);
793
- if (menus.length === 0) return null;
794
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.MenubarRoot, { "data-opt-id": "BGKHW", "data-opt-slug": "app-menubar.AppMenubar", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.MenubarContainer, { "aria-label": labels.ariaLabel, children: menus.map((menu) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MenuSection, { menu }, menu.id)) }) });
795
- }
796
- AppMenubar.displayName = "AppMenubar";
797
-
798
- // src/shells/sidebar-nav.tsx
799
- var _link = require('next/link'); var _link2 = _interopRequireDefault(_link);
800
- var _navigation = require('next/navigation');
801
-
802
-
803
- var NAV_ID_PREFIX = "sidebar-nav-";
804
- function domId(id) {
805
- return `${NAV_ID_PREFIX}${id}`;
806
- }
807
- var sectionStyles = {
808
- // 한글 키
809
- \uC2DC\uC791\uD558\uAE30: "text-accent",
810
- "\uD575\uC2EC \uAC1C\uB150": "text-info-fg",
811
- "\uAD6C\uCD95\xB7\uC6B4\uC601": "text-success-fg",
812
- \uB3C4\uAD6C: "text-warning-fg",
813
- DataGrid: "text-accent",
814
- "\uCEF4\uD3EC\uB10C\uD2B8 \xB7 Core": "text-accent",
815
- "\uCEF4\uD3EC\uB10C\uD2B8 \xB7 Visuals": "text-success-fg",
816
- "\uCEF4\uD3EC\uB10C\uD2B8 \xB7 Shells": "text-warning-fg",
817
- "\uCEF4\uD3EC\uB10C\uD2B8 \xB7 Surfaces": "text-info-fg",
818
- "\uAE30\uBCF8 \uCEF4\uD3EC\uB10C\uD2B8": "text-accent",
819
- "\uBE14\uB85D \uCEF4\uD3EC\uB10C\uD2B8": "text-info-fg",
820
- "\uC870\uD569 \uCEF4\uD3EC\uB10C\uD2B8": "text-warning-fg",
821
- \uD15C\uD50C\uB9BF: "text-text-tertiary",
822
- \uB9B4\uB9AC\uC988: "text-text-tertiary",
823
- // 영문 키 (하위 호환)
824
- Primitives: "text-accent",
825
- Blocks: "text-info-fg",
826
- Compositions: "text-warning-fg",
827
- Templates: "text-text-tertiary"
828
- };
829
- var defaultSectionStyle = "text-text-secondary";
830
- var defaultLabels5 = {
831
- ariaLabel: "\uBB38\uC11C \uB124\uBE44\uAC8C\uC774\uC158"
832
- };
833
- function SidebarNav({ items, labels: customLabels }) {
834
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels5), customLabels);
835
- if (items.length === 0) {
836
- return null;
837
- }
838
- const pathname = _navigation.usePathname.call(void 0, );
839
- const activeItem = items.find((item) => item.href === pathname);
840
- const [activeId, setActiveId] = _react.useState.call(void 0,
841
- activeItem ? domId(activeItem.id) : void 0
842
- );
843
- _react.useEffect.call(void 0, () => {
844
- const match = items.find((item) => item.href === pathname);
845
- if (match) {
846
- setActiveId(domId(match.id));
847
- }
848
- }, [pathname, items]);
849
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
850
- _chunkAFF2HPE5cjs.CompositeProvider,
851
- {
852
- focusLoop: true,
853
- orientation: "vertical",
854
- activeId,
855
- onActiveIdChange: setActiveId,
856
- "data-opt-id": "1FZNH",
857
- "data-opt-slug": "sidebar-nav.SidebarNav",
858
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
859
- _chunkAFF2HPE5cjs.Composite,
860
- {
861
- role: "navigation",
862
- "aria-label": labels.ariaLabel,
863
- className: "flex flex-col",
864
- children: items.map((item, index) => {
865
- var _a, _b;
866
- const isSelected = pathname === item.href;
867
- const isFirstItem = index === 0;
868
- const sectionTextStyle = item.sectionLabel ? (_a = sectionStyles[item.sectionLabel]) != null ? _a : defaultSectionStyle : defaultSectionStyle;
869
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
870
- item.separator && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkAFF2HPE5cjs.cn.call(void 0, "mb-2 pt-2", !isFirstItem && "mt-7"), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
871
- "span",
872
- {
873
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
874
- "px-2 text-[11px] font-semibold tracking-wider uppercase",
875
- sectionTextStyle
876
- ),
877
- children: (_b = item.sectionLabel) != null ? _b : ""
878
- }
879
- ) }),
880
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
881
- _chunkAFF2HPE5cjs.CompositeItem,
882
- {
883
- id: domId(item.id),
884
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
885
- _link2.default,
886
- {
887
- href: item.href,
888
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
889
- // Base styles
890
- "group relative block rounded-md px-2 py-1.5 text-[13px] leading-snug outline-none",
891
- "transition-all duration-150",
892
- // Default state
893
- !isSelected && [
894
- "text-text-secondary",
895
- // Hover
896
- "hover:bg-bg-subtle hover:text-text-primary"
897
- ],
898
- // Selected (current page)
899
- isSelected && [
900
- "bg-bg-subtle text-text-primary font-medium"
901
- ],
902
- // Keyboard navigation focus (roving tabindex active)
903
- "data-[active-item]:bg-accent-subtle data-[active-item]:text-accent",
904
- // Focus visible (actual keyboard focus indicator)
905
- "data-[focus-visible]:ring-ring data-[focus-visible]:ring-2",
906
- "data-[focus-visible]:ring-offset-ring-offset data-[focus-visible]:ring-offset-2",
907
- // Combined: selected + keyboard active
908
- isSelected && [
909
- "data-[active-item]:bg-accent-subtle data-[active-item]:text-accent"
910
- ]
911
- )
912
- }
913
- ),
914
- children: [
915
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
916
- "span",
917
- {
918
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
919
- "absolute top-1/2 left-0 h-4 w-0.5 -translate-y-1/2 rounded-full transition-all duration-150",
920
- // Selected: solid accent bar
921
- isSelected && "bg-accent",
922
- // Keyboard active (not selected): lighter bar
923
- !isSelected && "group-data-[active-item]:bg-accent bg-transparent",
924
- // Focus visible: ensure bar is visible
925
- "group-data-[focus-visible]:bg-accent"
926
- )
927
- }
928
- ),
929
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "pl-2", children: item.label })
930
- ]
931
- }
932
- )
933
- ] }, item.id);
934
- })
935
- }
936
- )
937
- }
938
- );
939
- }
940
-
941
- // src/shells/editor-toolbar.tsx
942
-
943
- var defaultLabels6 = {
944
- ariaLabel: "\uD14D\uC2A4\uD2B8 \uD3B8\uC9D1\uAE30 \uD234\uBC14"
945
- };
946
- function ToolbarButtonWithTooltip({
947
- button,
948
- active,
949
- onAction
950
- }) {
951
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.TooltipProvider, { children: [
952
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.TooltipAnchor, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
953
- _chunkAFF2HPE5cjs.ToolbarButton,
954
- {
955
- className: `text-text-primary data-[active-item]:bg-bg-subtle data-[focus-visible]:ring-ring rounded-md p-2 transition-colors outline-none data-[focus-visible]:ring-2 ${active ? "bg-bg-muted" : "hover:bg-bg-subtle"}`,
956
- onClick: () => onAction == null ? void 0 : onAction(button.id),
957
- children: button.icon
958
- }
959
- ) }),
960
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.Tooltip, { children: button.label })
961
- ] });
962
- }
963
- function EditorToolbar({
964
- buttons,
965
- onAction,
966
- activeButtons = [],
967
- labels: customLabels
968
- }) {
969
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels6), customLabels);
970
- const groups = [];
971
- let current = [];
972
- for (const btn of buttons) {
973
- if (btn.separator) {
974
- groups.push(current);
975
- current = [];
976
- }
977
- current.push(btn);
978
- }
979
- if (current.length) groups.push(current);
980
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
981
- _chunkAFF2HPE5cjs.ToolbarRoot,
982
- {
983
- "data-opt-id": "Z73K6",
984
- "data-opt-slug": "editor-toolbar.EditorToolbar",
985
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.ToolbarContainer, { "aria-label": labels.ariaLabel, children: groups.map((group, gi) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "contents", children: [
986
- gi > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.ToolbarSeparator, {}),
987
- group.map((item) => {
988
- if (item === "separator") return null;
989
- const btn = item;
990
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
991
- ToolbarButtonWithTooltip,
992
- {
993
- button: btn,
994
- active: activeButtons.includes(btn.id),
995
- onAction
996
- },
997
- btn.id
998
- );
999
- })
1000
- ] }, gi)) })
1001
- }
1002
- );
1003
- }
1004
-
1005
- // src/shells/content-tabs.tsx
1006
-
1007
-
1008
- var defaultLabels7 = {
1009
- ariaLabel: "\uCF58\uD150\uCE20 \uD0ED",
1010
- emptyMessage: "\uD45C\uC2DC\uD560 \uD0ED\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
1011
- };
1012
- function ContentTabs({
1013
- tabs,
1014
- defaultTabId,
1015
- labels: customLabels
1016
- }) {
1017
- var _a, _b;
1018
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels7), customLabels);
1019
- if (tabs.length === 0) {
1020
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1021
- "div",
1022
- {
1023
- className: "text-text-secondary text-sm",
1024
- "data-opt-id": "9W97K",
1025
- "data-opt-slug": "content-tabs.ContentTabs",
1026
- children: labels.emptyMessage
1027
- }
1028
- );
1029
- }
1030
- const [selectedTabId, setSelectedTabId] = _react.useState.call(void 0,
1031
- defaultTabId != null ? defaultTabId : (_a = tabs[0]) == null ? void 0 : _a.id
1032
- );
1033
- const handleSelectedTabId = (nextId) => {
1034
- var _a2;
1035
- setSelectedTabId(nextId != null ? nextId : (_a2 = tabs[0]) == null ? void 0 : _a2.id);
1036
- };
1037
- const activeTab = (_b = tabs.find((tab) => tab.id === selectedTabId)) != null ? _b : tabs[0];
1038
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1039
- _chunkAFF2HPE5cjs.TabsRoot,
1040
- {
1041
- selectedId: selectedTabId,
1042
- onSelectedIdChange: handleSelectedTabId,
1043
- "data-opt-id": "9W97K",
1044
- "data-opt-slug": "content-tabs.ContentTabs",
1045
- children: [
1046
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.TabList, { "aria-label": labels.ariaLabel, children: tabs.map((tab) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.Tab, { id: tab.id, children: tab.label }, tab.id)) }),
1047
- activeTab && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.TabPanel, { tabId: activeTab.id, children: activeTab.content })
1048
- ]
1049
- }
1050
- );
1051
- }
1052
-
1053
- // src/shells/faq-accordion.tsx
1054
-
1055
- var defaultLabels8 = {
1056
- ariaLabel: "\uC790\uC8FC \uBB3B\uB294 \uC9C8\uBB38",
1057
- emptyMessage: "\uB4F1\uB85D\uB41C FAQ\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
1058
- };
1059
- function FaqAccordion({
1060
- items,
1061
- labels: customLabels
1062
- }) {
1063
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels8), customLabels);
1064
- if (items.length === 0) {
1065
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1066
- "div",
1067
- {
1068
- className: "text-text-secondary text-sm",
1069
- "data-opt-id": "QRBHV",
1070
- "data-opt-slug": "faq-accordion.FaqAccordion",
1071
- children: labels.emptyMessage
1072
- }
1073
- );
1074
- }
1075
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1076
- _chunkAFF2HPE5cjs.CompositeProvider,
1077
- {
1078
- focusLoop: true,
1079
- orientation: "vertical",
1080
- "data-opt-id": "QRBHV",
1081
- "data-opt-slug": "faq-accordion.FaqAccordion",
1082
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1083
- _chunkAFF2HPE5cjs.Composite,
1084
- {
1085
- role: "region",
1086
- "aria-label": labels.ariaLabel,
1087
- className: "divide-border-subtle border-border divide-y rounded-lg border",
1088
- children: items.map((faq) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.DisclosureRoot, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
1089
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.CompositeItem, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.DisclosureTrigger, {}), children: [
1090
- faq.question,
1091
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1092
- "svg",
1093
- {
1094
- className: "text-text-tertiary h-4 w-4 shrink-0 transition-transform [[data-open]>&]:rotate-180",
1095
- fill: "none",
1096
- viewBox: "0 0 24 24",
1097
- stroke: "currentColor",
1098
- strokeWidth: 2,
1099
- "aria-hidden": "true",
1100
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1101
- "path",
1102
- {
1103
- strokeLinecap: "round",
1104
- strokeLinejoin: "round",
1105
- d: "m19.5 8.25-7.5 7.5-7.5-7.5"
1106
- }
1107
- )
1108
- }
1109
- )
1110
- ] }),
1111
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.DisclosureContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-text-secondary px-4 pt-2 pb-4 text-sm", children: faq.answer }) })
1112
- ] }) }, faq.id))
1113
- }
1114
- )
1115
- }
1116
- );
1117
- }
1118
-
1119
- // src/shells/settings-form.tsx
1120
-
1121
-
1122
- var defaultLabels9 = {
1123
- formAriaLabel: "\uC124\uC815 \uD3FC",
1124
- submitButton: "\uC800\uC7A5",
1125
- successMessage: "\uC124\uC815\uC774 \uC800\uC7A5\uB418\uC5C8\uC2B5\uB2C8\uB2E4."
1126
- };
1127
- function SettingsForm({
1128
- fields,
1129
- onSubmit,
1130
- labels: customLabels
1131
- }) {
1132
- var _a;
1133
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels9), customLabels);
1134
- const [submitted, setSubmitted] = _react.useState.call(void 0, false);
1135
- if (fields.length === 0) {
1136
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1137
- _chunkAFF2HPE5cjs.EmptyState,
1138
- {
1139
- title: "\uC124\uC815 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
1140
- description: "\uD45C\uC2DC\uD560 \uC124\uC815 \uD544\uB4DC\uB97C \uCD94\uAC00\uD558\uBA74 \uC774 \uD3FC\uC774 \uB80C\uB354\uB9C1\uB429\uB2C8\uB2E4.",
1141
- "data-opt-id": "9TEEJ",
1142
- "data-opt-slug": "settings-form.SettingsForm"
1143
- }
1144
- );
1145
- }
1146
- const defaultValues = {};
1147
- for (const field of fields) {
1148
- defaultValues[field.name] = (_a = field.defaultValue) != null ? _a : field.type === "switch" || field.type === "checkbox" ? false : field.type === "tags" ? [] : "";
1149
- }
1150
- const form = _chunkAFF2HPE5cjs.useFormStore.call(void 0, {
1151
- defaultValues,
1152
- validate: (values) => {
1153
- var _a2;
1154
- const errors = {};
1155
- for (const field of fields) {
1156
- if (field.required) {
1157
- const value = values[field.name];
1158
- if (!value || typeof value === "string" && !value.trim()) {
1159
- errors[field.name] = (_a2 = field.requiredMessage) != null ? _a2 : `${field.label}\uC744(\uB97C) \uC785\uB825\uD574\uC8FC\uC138\uC694.`;
1160
- }
1161
- }
1162
- if (field.validate) {
1163
- const value = values[field.name];
1164
- const error = field.validate(value);
1165
- if (error) {
1166
- errors[field.name] = error;
1167
- }
1168
- }
1169
- }
1170
- return errors;
1171
- },
1172
- onSubmit: (values) => {
1173
- setSubmitted(true);
1174
- onSubmit == null ? void 0 : onSubmit(values);
1175
- }
1176
- });
1177
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1178
- "div",
1179
- {
1180
- className: "gap-group flex flex-col",
1181
- "data-opt-id": "9TEEJ",
1182
- "data-opt-slug": "settings-form.SettingsForm",
1183
- children: [
1184
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.FormRoot, { store: form, "aria-label": labels.formAriaLabel, children: [
1185
- fields.map((field) => {
1186
- var _a2, _b, _c, _d, _e;
1187
- if (field.visible !== void 0) {
1188
- const currentValues = form.getValues();
1189
- const isVisible = typeof field.visible === "function" ? field.visible(currentValues) : field.visible;
1190
- if (!isVisible) return null;
1191
- }
1192
- if (field.type === "tags") {
1193
- const rawValue = form.getValue(field.name);
1194
- const tags = Array.isArray(rawValue) ? rawValue : [];
1195
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "gap-element flex flex-col", children: [
1196
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormLabel, { name: field.name, children: field.label }),
1197
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1198
- _chunkAFF2HPE5cjs.TagInput,
1199
- {
1200
- value: tags,
1201
- onChange: (next) => form.setValue(field.name, next),
1202
- placeholder: field.placeholder
1203
- }
1204
- ),
1205
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormError, { name: field.name })
1206
- ] }, field.name);
1207
- }
1208
- if (field.type === "radio") {
1209
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "fieldset", { className: "gap-element flex flex-col", children: [
1210
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "legend", { className: "text-text-primary text-sm font-medium", children: field.label }),
1211
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormRadioGroup, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "gap-group flex", children: (_a2 = field.options) == null ? void 0 : _a2.map((option) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1212
- "label",
1213
- {
1214
- className: "text-text-primary gap-element flex items-center text-sm",
1215
- children: [
1216
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormRadio, { name: field.name, value: option.value }),
1217
- option.label
1218
- ]
1219
- },
1220
- option.value
1221
- )) }) }),
1222
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormError, { name: field.name })
1223
- ] }, field.name);
1224
- }
1225
- if (field.type === "checkbox") {
1226
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "gap-element flex flex-col", children: [
1227
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "text-text-primary gap-element flex items-center text-sm", children: [
1228
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormCheckbox, { name: field.name }),
1229
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: field.label })
1230
- ] }),
1231
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormError, { name: field.name })
1232
- ] }, field.name);
1233
- }
1234
- if (field.type === "textarea") {
1235
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "gap-element flex flex-col", children: [
1236
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormLabel, { name: field.name, children: field.label }),
1237
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1238
- _chunkAFF2HPE5cjs.FormTextarea,
1239
- {
1240
- name: field.name,
1241
- placeholder: field.placeholder,
1242
- rows: (_b = field.rows) != null ? _b : 4,
1243
- resize: (_c = field.resize) != null ? _c : "vertical",
1244
- className: field.font === "mono" ? "font-mono text-sm" : void 0
1245
- }
1246
- ),
1247
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormError, { name: field.name })
1248
- ] }, field.name);
1249
- }
1250
- if (field.type === "select") {
1251
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "gap-element flex flex-col", children: [
1252
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormLabel, { name: field.name, children: field.label }),
1253
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormSelect, { name: field.name, placeholder: field.placeholder, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormSelectPopover, { children: (_d = field.options) == null ? void 0 : _d.map((option) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormSelectItem, { value: option.value, children: option.label }, option.value)) }) }),
1254
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormError, { name: field.name })
1255
- ] }, field.name);
1256
- }
1257
- if (field.type === "switch") {
1258
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "gap-group flex items-center", children: [
1259
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormSwitch, { name: field.name }),
1260
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col", children: [
1261
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-text-primary text-sm font-medium", children: field.label }),
1262
- field.description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-text-secondary text-sm", children: field.description })
1263
- ] })
1264
- ] }, field.name);
1265
- }
1266
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "gap-element flex flex-col", children: [
1267
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormLabel, { name: field.name, children: field.label }),
1268
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1269
- _chunkAFF2HPE5cjs.FormInput,
1270
- {
1271
- name: field.name,
1272
- type: (_e = field.type) != null ? _e : "text",
1273
- placeholder: field.placeholder
1274
- }
1275
- ),
1276
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormError, { name: field.name })
1277
- ] }, field.name);
1278
- }),
1279
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.FormSubmit, { children: labels.submitButton })
1280
- ] }),
1281
- submitted && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "border-success bg-success-subtle text-success-fg rounded-lg border p-3 text-sm", children: labels.successMessage })
1282
- ]
1283
- }
1284
- );
1285
- }
1286
-
1287
- // src/shells/deployment-timeline.tsx
1288
-
1289
- var statusIcon = {
1290
- success: "\u25CF",
1291
- pending: "\u25CC",
1292
- running: "\u27F3",
1293
- error: "\u2717",
1294
- skipped: "\u25CB"
1295
- };
1296
- var statusColor = {
1297
- success: "text-success-fg",
1298
- pending: _chunkAFF2HPE5cjs.OPT_TEXT_TERTIARY,
1299
- running: "text-accent",
1300
- error: "text-danger-fg",
1301
- skipped: "text-text-tertiary"
1302
- };
1303
- var statusBadge = {
1304
- success: _chunkAFF2HPE5cjs.OPT_BADGE_GREEN,
1305
- pending: _chunkAFF2HPE5cjs.OPT_BADGE_NEUTRAL,
1306
- running: "inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium bg-info-subtle text-info-fg",
1307
- error: _chunkAFF2HPE5cjs.OPT_BADGE_RED,
1308
- skipped: _chunkAFF2HPE5cjs.OPT_BADGE_NEUTRAL
1309
- };
1310
- var statusLabel = {
1311
- success: "\uC131\uACF5",
1312
- pending: "\uB300\uAE30",
1313
- running: "\uC2E4\uD589 \uC911",
1314
- error: "\uC5D0\uB7EC",
1315
- skipped: "\uAC74\uB108\uB700"
1316
- };
1317
- function DeploymentTimeline({
1318
- steps,
1319
- title = "\uBC30\uD3EC \uD0C0\uC784\uB77C\uC778"
1320
- }) {
1321
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1322
- "div",
1323
- {
1324
- className: "gap-group flex flex-col",
1325
- "data-opt-id": "XXVQ2",
1326
- "data-opt-slug": "deployment-timeline.DeploymentTimeline",
1327
- children: [
1328
- title && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: `text-sm font-semibold ${_chunkAFF2HPE5cjs.OPT_TEXT_PRIMARY}`, children: title }),
1329
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.CompositeProvider, { focusLoop: true, orientation: "vertical", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.Composite, { role: "list", "aria-label": title, className: "relative", children: steps.map((step, i) => {
1330
- const isLast = i === steps.length - 1;
1331
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1332
- _chunkAFF2HPE5cjs.CompositeItem,
1333
- {
1334
- className: `group gap-group relative flex w-full scroll-m-2 rounded-lg px-3 py-2 ${_chunkAFF2HPE5cjs.OPT_FOCUS} data-[active-item]:bg-accent-subtle`,
1335
- role: "listitem",
1336
- children: [
1337
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center", children: [
1338
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1339
- "span",
1340
- {
1341
- className: `text-lg leading-none ${statusColor[step.status]}`,
1342
- "aria-label": statusLabel[step.status],
1343
- children: statusIcon[step.status]
1344
- }
1345
- ),
1346
- !isLast && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-border-subtle mt-1 w-px flex-1" })
1347
- ] }),
1348
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 pb-3", children: [
1349
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "gap-element flex items-center", children: [
1350
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `text-sm font-medium ${_chunkAFF2HPE5cjs.OPT_TEXT_PRIMARY}`, children: step.name }),
1351
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: statusBadge[step.status], children: statusLabel[step.status] }),
1352
- step.duration && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `text-xs ${_chunkAFF2HPE5cjs.OPT_TEXT_TERTIARY}`, children: step.duration })
1353
- ] }),
1354
- step.detail && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: `mt-0.5 text-xs ${_chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY}`, children: step.detail })
1355
- ] })
1356
- ]
1357
- },
1358
- step.id
1359
- );
1360
- }) }) })
1361
- ]
1362
- }
1363
- );
1364
- }
1365
-
1366
- // src/shells/project-switcher.tsx
1367
-
1368
-
1369
-
1370
- var statusDot = {
1371
- active: _chunkAFF2HPE5cjs.OPT_DOT_GREEN,
1372
- paused: _chunkAFF2HPE5cjs.OPT_DOT_YELLOW,
1373
- error: _chunkAFF2HPE5cjs.OPT_DOT_RED
1374
- };
1375
- function ProjectSwitcher({
1376
- projects,
1377
- value,
1378
- onChange,
1379
- placeholder = "\uD504\uB85C\uC81D\uD2B8 \uAC80\uC0C9..."
1380
- }) {
1381
- const [search, setSearch] = _react.useState.call(void 0, "");
1382
- const matches = _react.useMemo.call(void 0, () => {
1383
- if (!search) return projects;
1384
- return _matchsorter.matchSorter.call(void 0, projects, search, { keys: ["name", "framework"] });
1385
- }, [search, projects]);
1386
- const selected = projects.find((p) => p.id === value);
1387
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1388
- "div",
1389
- {
1390
- className: "gap-element flex flex-col",
1391
- "data-opt-id": "5R3AG",
1392
- "data-opt-slug": "project-switcher.ProjectSwitcher",
1393
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.ComboboxRoot, { onValueChange: setSearch, children: [
1394
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { className: _chunkAFF2HPE5cjs.OPT_TEXT_LABEL, children: "\uD504\uB85C\uC81D\uD2B8" }),
1395
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1396
- _chunkAFF2HPE5cjs.ComboboxInput,
1397
- {
1398
- placeholder: selected ? selected.name : placeholder,
1399
- className: _chunkAFF2HPE5cjs.OPT_INPUT
1400
- }
1401
- ),
1402
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.ComboboxPopover, { className: "max-h-72 overflow-y-auto", children: [
1403
- matches.length === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: `py-6 text-center text-sm ${_chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY}`, children: "\uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." }),
1404
- matches.map((project) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1405
- _chunkAFF2HPE5cjs.ComboboxItem,
1406
- {
1407
- value: project.name,
1408
- onClick: () => onChange == null ? void 0 : onChange(project.id),
1409
- className: `gap-element flex scroll-m-2 items-center ${_chunkAFF2HPE5cjs.OPT_ITEM_BASE} ${_chunkAFF2HPE5cjs.OPT_ACTIVE_ITEM}`,
1410
- children: [
1411
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `shrink-0 ${statusDot[project.status]}` }),
1412
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "flex-1 truncate font-medium", children: project.name }),
1413
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _chunkAFF2HPE5cjs.OPT_BADGE_NEUTRAL, children: project.framework }),
1414
- project.domain && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1415
- "span",
1416
- {
1417
- className: `truncate text-xs ${_chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY} data-[active-item]:text-accent-fg/70`,
1418
- children: project.domain
1419
- }
1420
- )
1421
- ]
1422
- },
1423
- project.id
1424
- ))
1425
- ] })
1426
- ] })
1427
- }
1428
- );
1429
- }
1430
- ProjectSwitcher.displayName = "ProjectSwitcher";
1431
-
1432
- // src/shells/env-panel.tsx
1433
-
1434
- var defaultLabels10 = {
1435
- varCount: (count) => `${count}\uAC1C \uBCC0\uC218`,
1436
- envVarsLabel: (env) => `${env} \uD658\uACBD \uBCC0\uC218`,
1437
- secretBadge: "secret"
1438
- };
1439
- var envDot = {
1440
- Production: _chunkAFF2HPE5cjs.OPT_DOT_RED,
1441
- Preview: _chunkAFF2HPE5cjs.OPT_DOT_YELLOW,
1442
- Development: _chunkAFF2HPE5cjs.OPT_DOT_GREEN
1443
- };
1444
- function EnvPanel({ groups, labels: customLabels }) {
1445
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels10), customLabels);
1446
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1447
- "div",
1448
- {
1449
- className: `rounded-lg ${_chunkAFF2HPE5cjs.OPT_BORDER} divide-y ${_chunkAFF2HPE5cjs.OPT_DIVIDER} bg-surface`,
1450
- "data-opt-id": "ZBDWK",
1451
- "data-opt-slug": "env-panel.EnvPanel",
1452
- children: groups.map((group) => {
1453
- var _a;
1454
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1455
- _chunkAFF2HPE5cjs.DisclosureRoot,
1456
- {
1457
- defaultOpen: group.env === "Production",
1458
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
1459
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.DisclosureTrigger, { className: _chunkAFF2HPE5cjs.OPT_DISCLOSURE_TRIGGER, children: [
1460
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "gap-element flex items-center", children: [
1461
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1462
- "span",
1463
- {
1464
- className: (_a = envDot[group.env]) != null ? _a : "bg-bg-muted h-2 w-2 rounded-full"
1465
- }
1466
- ),
1467
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium", children: group.env }),
1468
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `text-xs ${_chunkAFF2HPE5cjs.OPT_TEXT_TERTIARY}`, children: labels.varCount(group.vars.length) })
1469
- ] }),
1470
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1471
- "svg",
1472
- {
1473
- className: "text-text-tertiary h-4 w-4 shrink-0 transition-transform [[data-open]>&]:rotate-180",
1474
- fill: "none",
1475
- viewBox: "0 0 24 24",
1476
- stroke: "currentColor",
1477
- strokeWidth: 2,
1478
- "aria-hidden": "true",
1479
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1480
- "path",
1481
- {
1482
- strokeLinecap: "round",
1483
- strokeLinejoin: "round",
1484
- d: "m19.5 8.25-7.5 7.5-7.5-7.5"
1485
- }
1486
- )
1487
- }
1488
- )
1489
- ] }),
1490
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.DisclosureContent, { className: _chunkAFF2HPE5cjs.OPT_DISCLOSURE_CONTENT, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.CompositeProvider, { focusLoop: true, orientation: "vertical", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1491
- _chunkAFF2HPE5cjs.Composite,
1492
- {
1493
- role: "list",
1494
- "aria-label": labels.envVarsLabel(group.env),
1495
- className: "px-4 pb-3",
1496
- children: group.vars.map((v) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1497
- _chunkAFF2HPE5cjs.CompositeItem,
1498
- {
1499
- role: "listitem",
1500
- className: `gap-group flex scroll-m-2 items-center rounded px-2 py-1.5 text-sm ${_chunkAFF2HPE5cjs.OPT_FOCUS} data-[active-item]:bg-accent-subtle`,
1501
- children: [
1502
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1503
- "span",
1504
- {
1505
- className: `w-44 shrink-0 truncate font-mono text-xs font-medium ${_chunkAFF2HPE5cjs.OPT_TEXT_PRIMARY}`,
1506
- children: v.key
1507
- }
1508
- ),
1509
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1510
- "span",
1511
- {
1512
- className: `flex-1 truncate font-mono text-xs ${_chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY}`,
1513
- children: v.isSecret ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : v.value
1514
- }
1515
- ),
1516
- v.isSecret && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _chunkAFF2HPE5cjs.OPT_BADGE_NEUTRAL, children: labels.secretBadge })
1517
- ]
1518
- },
1519
- v.key
1520
- ))
1521
- }
1522
- ) }) })
1523
- ] })
1524
- },
1525
- group.env
1526
- );
1527
- })
1528
- }
1529
- );
1530
- }
1531
-
1532
- // src/shells/branch-select.tsx
1533
-
1534
-
1535
- var defaultLabels11 = {
1536
- selectLabel: "\uBE0C\uB79C\uCE58",
1537
- emptySelectionLabel: "\uC120\uD0DD...",
1538
- emptyMessage: "\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uBE0C\uB79C\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
1539
- defaultBadge: "default"
1540
- };
1541
- function BranchSelect({
1542
- branches,
1543
- value: controlledValue,
1544
- onChange,
1545
- label,
1546
- labels: customLabels
1547
- }) {
1548
- var _a, _b, _c, _d;
1549
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels11), customLabels);
1550
- const resolvedLabel = label != null ? label : labels.selectLabel;
1551
- const defaultBranch = branches.find((b) => b.isDefault);
1552
- const [internalValue, setInternalValue] = _react.useState.call(void 0,
1553
- (_c = (_b = defaultBranch == null ? void 0 : defaultBranch.name) != null ? _b : (_a = branches[0]) == null ? void 0 : _a.name) != null ? _c : ""
1554
- );
1555
- const value = controlledValue != null ? controlledValue : internalValue;
1556
- const selected = branches.find((b) => b.name === value);
1557
- if (branches.length === 0) {
1558
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1559
- "div",
1560
- {
1561
- className: "gap-element flex flex-col",
1562
- "data-opt-id": "7EDEP",
1563
- "data-opt-slug": "branch-select.BranchSelect",
1564
- children: [
1565
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _chunkAFF2HPE5cjs.OPT_TEXT_LABEL, children: resolvedLabel }),
1566
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _chunkAFF2HPE5cjs.OPT_TEXT_TERTIARY, children: labels.emptyMessage })
1567
- ]
1568
- }
1569
- );
1570
- }
1571
- const handleChange = (v) => {
1572
- var _a2;
1573
- const next = Array.isArray(v) ? (_a2 = v[0]) != null ? _a2 : "" : v;
1574
- if (onChange) onChange(next);
1575
- else setInternalValue(next);
1576
- };
1577
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1578
- "div",
1579
- {
1580
- className: "gap-element flex flex-col",
1581
- "data-opt-id": "7EDEP",
1582
- "data-opt-slug": "branch-select.BranchSelect",
1583
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.SelectRoot, { value, onValueChange: handleChange, children: [
1584
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.SelectLabel, { className: _chunkAFF2HPE5cjs.OPT_TEXT_LABEL, children: resolvedLabel }),
1585
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1586
- _chunkAFF2HPE5cjs.SelectTrigger,
1587
- {
1588
- className: `${_chunkAFF2HPE5cjs.OPT_INPUT} max-w-xs items-center justify-between gap-1`,
1589
- children: [
1590
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "gap-element flex items-center truncate", children: [
1591
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1592
- "svg",
1593
- {
1594
- className: "text-text-tertiary h-4 w-4 shrink-0",
1595
- fill: "none",
1596
- viewBox: "0 0 24 24",
1597
- stroke: "currentColor",
1598
- strokeWidth: 2,
1599
- "aria-hidden": "true",
1600
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1601
- "path",
1602
- {
1603
- strokeLinecap: "round",
1604
- strokeLinejoin: "round",
1605
- d: "M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"
1606
- }
1607
- )
1608
- }
1609
- ),
1610
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "truncate", children: (_d = selected == null ? void 0 : selected.name) != null ? _d : labels.emptySelectionLabel }),
1611
- (selected == null ? void 0 : selected.isDefault) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _chunkAFF2HPE5cjs.OPT_BADGE_BLUE, children: labels.defaultBadge })
1612
- ] }),
1613
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1614
- "svg",
1615
- {
1616
- className: "text-text-tertiary h-4 w-4 shrink-0",
1617
- fill: "none",
1618
- viewBox: "0 0 24 24",
1619
- stroke: "currentColor",
1620
- strokeWidth: 2,
1621
- "aria-hidden": "true",
1622
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1623
- "path",
1624
- {
1625
- strokeLinecap: "round",
1626
- strokeLinejoin: "round",
1627
- d: "m19.5 8.25-7.5 7.5-7.5-7.5"
1628
- }
1629
- )
1630
- }
1631
- )
1632
- ]
1633
- }
1634
- ),
1635
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.SelectPopover, { className: "max-w-xs", children: branches.map((branch) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1636
- _chunkAFF2HPE5cjs.SelectItem,
1637
- {
1638
- value: branch.name,
1639
- className: `gap-element flex scroll-m-2 items-center ${_chunkAFF2HPE5cjs.OPT_ITEM_BASE} ${_chunkAFF2HPE5cjs.OPT_ACTIVE_ITEM}`,
1640
- children: [
1641
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "flex-1 truncate", children: branch.name }),
1642
- branch.isDefault && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "bg-accent-subtle text-accent data-[active-item]:bg-accent-fg/20 data-[active-item]:text-accent-fg rounded-full px-2 py-0.5 text-[11px] font-medium", children: labels.defaultBadge }),
1643
- branch.lastCommit && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1644
- "span",
1645
- {
1646
- className: `font-mono text-xs ${_chunkAFF2HPE5cjs.OPT_TEXT_TERTIARY} data-[active-item]:text-accent-fg/60`,
1647
- children: branch.lastCommit
1648
- }
1649
- ),
1650
- branch.author && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1651
- "span",
1652
- {
1653
- className: `text-xs ${_chunkAFF2HPE5cjs.OPT_TEXT_TERTIARY} data-[active-item]:text-accent-fg/60`,
1654
- children: branch.author
1655
- }
1656
- )
1657
- ]
1658
- },
1659
- branch.name
1660
- )) })
1661
- ] })
1662
- }
1663
- );
1664
- }
1665
- BranchSelect.displayName = "BranchSelect";
1666
-
1667
- // src/shells/domain-table.tsx
1668
-
1669
- var defaultLabels12 = {
1670
- domain: "Domain",
1671
- status: "Status",
1672
- ssl: "SSL",
1673
- redirect: "Redirect",
1674
- added: "Added",
1675
- emptyMessage: "No domains configured"
1676
- };
1677
- var statusBadge2 = {
1678
- active: _chunkAFF2HPE5cjs.OPT_BADGE_GREEN,
1679
- pending: _chunkAFF2HPE5cjs.OPT_BADGE_YELLOW,
1680
- error: _chunkAFF2HPE5cjs.OPT_BADGE_RED
1681
- };
1682
- var sslBadge = {
1683
- valid: _chunkAFF2HPE5cjs.OPT_BADGE_GREEN,
1684
- pending: _chunkAFF2HPE5cjs.OPT_BADGE_YELLOW,
1685
- expired: _chunkAFF2HPE5cjs.OPT_BADGE_RED
1686
- };
1687
- var statusLabel2 = {
1688
- active: "Active",
1689
- pending: "Pending",
1690
- error: "Error"
1691
- };
1692
- var sslLabel = {
1693
- valid: "Valid",
1694
- pending: "Pending",
1695
- expired: "Expired"
1696
- };
1697
- function DomainTable({
1698
- domains,
1699
- title = "\uB3C4\uBA54\uC778",
1700
- labels: customLabels
1701
- }) {
1702
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels12), customLabels);
1703
- if (domains.length === 0) {
1704
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1705
- "div",
1706
- {
1707
- className: "gap-group flex flex-col",
1708
- "data-opt-id": "A7SRM",
1709
- "data-opt-slug": "domain-table.DomainTable",
1710
- children: [
1711
- title && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: `text-sm font-semibold ${_chunkAFF2HPE5cjs.OPT_TEXT_PRIMARY}`, children: title }),
1712
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1713
- "div",
1714
- {
1715
- className: `rounded-lg px-4 py-6 text-sm ${_chunkAFF2HPE5cjs.OPT_BORDER} ${_chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY} bg-surface`,
1716
- children: labels.emptyMessage
1717
- }
1718
- )
1719
- ]
1720
- }
1721
- );
1722
- }
1723
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1724
- "div",
1725
- {
1726
- className: "gap-group flex flex-col",
1727
- "data-opt-id": "A7SRM",
1728
- "data-opt-slug": "domain-table.DomainTable",
1729
- children: [
1730
- title && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: `text-sm font-semibold ${_chunkAFF2HPE5cjs.OPT_TEXT_PRIMARY}`, children: title }),
1731
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `overflow-x-auto rounded-lg ${_chunkAFF2HPE5cjs.OPT_BORDER} bg-surface`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.CompositeProvider, { focusLoop: true, focusWrap: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1732
- _chunkAFF2HPE5cjs.Composite,
1733
- {
1734
- role: "grid",
1735
- "aria-label": title,
1736
- className: "w-full",
1737
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "table", {}),
1738
- children: [
1739
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "thead", { className: "border-border-subtle bg-surface-inset border-b", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "tr", { children: [
1740
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { className: _chunkAFF2HPE5cjs.OPT_TH, children: labels.domain }),
1741
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { className: _chunkAFF2HPE5cjs.OPT_TH, children: labels.status }),
1742
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { className: _chunkAFF2HPE5cjs.OPT_TH, children: labels.ssl }),
1743
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { className: _chunkAFF2HPE5cjs.OPT_TH, children: labels.redirect }),
1744
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { className: _chunkAFF2HPE5cjs.OPT_TH, children: labels.added })
1745
- ] }) }),
1746
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { className: `divide-y ${_chunkAFF2HPE5cjs.OPT_DIVIDER}`, children: domains.map((d) => {
1747
- var _a, _b;
1748
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkAFF2HPE5cjs.CompositeRow, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", {}), children: [
1749
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1750
- _chunkAFF2HPE5cjs.CompositeItem,
1751
- {
1752
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1753
- "td",
1754
- {
1755
- className: `${_chunkAFF2HPE5cjs.OPT_TD} font-mono font-medium`,
1756
- role: "gridcell"
1757
- }
1758
- ),
1759
- className: _chunkAFF2HPE5cjs.OPT_TABLE_ROW_ACTIVE,
1760
- children: d.domain
1761
- }
1762
- ),
1763
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1764
- _chunkAFF2HPE5cjs.CompositeItem,
1765
- {
1766
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { className: _chunkAFF2HPE5cjs.OPT_TD, role: "gridcell" }),
1767
- className: _chunkAFF2HPE5cjs.OPT_TABLE_ROW_ACTIVE,
1768
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: statusBadge2[d.status], children: statusLabel2[d.status] })
1769
- }
1770
- ),
1771
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1772
- _chunkAFF2HPE5cjs.CompositeItem,
1773
- {
1774
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { className: _chunkAFF2HPE5cjs.OPT_TD, role: "gridcell" }),
1775
- className: _chunkAFF2HPE5cjs.OPT_TABLE_ROW_ACTIVE,
1776
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: sslBadge[d.ssl], children: sslLabel[d.ssl] })
1777
- }
1778
- ),
1779
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1780
- _chunkAFF2HPE5cjs.CompositeItem,
1781
- {
1782
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { className: _chunkAFF2HPE5cjs.OPT_TD, role: "gridcell" }),
1783
- className: _chunkAFF2HPE5cjs.OPT_TABLE_ROW_ACTIVE,
1784
- children: (_a = d.redirect) != null ? _a : "\u2014"
1785
- }
1786
- ),
1787
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1788
- _chunkAFF2HPE5cjs.CompositeItem,
1789
- {
1790
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { className: _chunkAFF2HPE5cjs.OPT_TD_MUTED, role: "gridcell" }),
1791
- className: _chunkAFF2HPE5cjs.OPT_TABLE_ROW_ACTIVE,
1792
- children: (_b = d.addedAt) != null ? _b : "\u2014"
1793
- }
1794
- )
1795
- ] }, d.domain);
1796
- }) })
1797
- ]
1798
- }
1799
- ) }) })
1800
- ]
1801
- }
1802
- );
1803
- }
1804
-
1805
- // src/shells/data-table.tsx
1806
-
1807
-
1808
-
1809
-
1810
-
1811
-
1812
-
1813
- var MIN_COLUMN_WIDTH = 40;
1814
- var DEFAULT_COLUMN_RESIZE_MAX = 1200;
1815
- var alignmentClass = {
1816
- left: "text-left",
1817
- center: "text-center",
1818
- right: "text-right"
1819
- };
1820
- function getCellValue(row, accessor) {
1821
- if (typeof accessor === "function") {
1822
- try {
1823
- return accessor(row);
1824
- } catch (e) {
1825
- return "\u2014";
1826
- }
1827
- }
1828
- const value = row[accessor];
1829
- if (value === null || value === void 0 || typeof value === "number" && !Number.isFinite(value)) {
1830
- return "\u2014";
1831
- }
1832
- return String(value);
1833
- }
1834
- function getRawValue(row, accessor) {
1835
- if (typeof accessor === "function") {
1836
- return accessor(row);
1837
- }
1838
- return row[accessor];
1839
- }
1840
- function isMissingSortValue(value) {
1841
- return value == null || typeof value === "number" && !Number.isFinite(value);
1842
- }
1843
- function compareSortValues(aVal, bVal, dir) {
1844
- const aMissing = isMissingSortValue(aVal);
1845
- const bMissing = isMissingSortValue(bVal);
1846
- if (aMissing && bMissing) return 0;
1847
- if (aMissing) return 1;
1848
- if (bMissing) return -1;
1849
- const cmp = typeof aVal === "number" && typeof bVal === "number" ? aVal - bVal : String(aVal).localeCompare(String(bVal));
1850
- return dir === "desc" ? -cmp : cmp;
1851
- }
1852
- function clampPercent(ratio) {
1853
- if (!Number.isFinite(ratio)) return 0;
1854
- return Math.min(100, Math.max(0, Math.round(ratio * 100)));
1855
- }
1856
- function getResizeHandleValue(currentWidth, configuredWidth) {
1857
- if (typeof currentWidth === "number" && Number.isFinite(currentWidth)) {
1858
- return Math.max(MIN_COLUMN_WIDTH, Math.round(currentWidth));
1859
- }
1860
- const pxWidth = configuredWidth == null ? void 0 : configuredWidth.trim().match(/^(\d+(?:\.\d+)?)px$/);
1861
- if (pxWidth) {
1862
- return Math.max(MIN_COLUMN_WIDTH, Math.round(Number(pxWidth[1])));
1863
- }
1864
- return MIN_COLUMN_WIDTH;
1865
- }
1866
- function DataTableProgressBar({
1867
- value,
1868
- barColor,
1869
- label
1870
- }) {
1871
- const percent = clampPercent(value);
1872
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1873
- "div",
1874
- {
1875
- className: "bg-bg-subtle mt-1 h-1.5 w-full overflow-hidden rounded-full",
1876
- role: "progressbar",
1877
- "aria-valuenow": percent,
1878
- "aria-valuemin": 0,
1879
- "aria-valuemax": 100,
1880
- "aria-valuetext": `${percent}%`,
1881
- "aria-label": label,
1882
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1883
- "div",
1884
- {
1885
- className: _chunkAFF2HPE5cjs.cn.call(void 0, "h-full rounded-full transition-all", barColor),
1886
- style: { width: `${percent}%` }
1887
- }
1888
- )
1889
- }
1890
- );
1891
- }
1892
- function DataTable({
1893
- data,
1894
- columns,
1895
- keyExtractor,
1896
- title = "Data Table",
1897
- onRowClick,
1898
- emptyMessage = "No data available",
1899
- activeRowId,
1900
- sortable = false,
1901
- selectable = false,
1902
- selectedKeys,
1903
- onSelectionChange,
1904
- expandable = false,
1905
- renderExpanded,
1906
- pageSize,
1907
- stickyHeader = false,
1908
- resizableColumns = false,
1909
- onSort: onSortExternal,
1910
- className
1911
- }) {
1912
- const [sortCol, setSortCol] = _react.useState.call(void 0, null);
1913
- const [sortDir, setSortDir] = _react.useState.call(void 0, null);
1914
- const [expandedKeys, setExpandedKeys] = _react.useState.call(void 0, /* @__PURE__ */ new Set());
1915
- const [page, setPage] = _react.useState.call(void 0, 0);
1916
- const [colWidths, setColWidths] = _react.useState.call(void 0, {});
1917
- const sortedData = _react.useMemo.call(void 0, () => {
1918
- if (!sortable || !sortCol || !sortDir) return data;
1919
- const col = columns.find((c) => c.id === sortCol);
1920
- if (!col) return data;
1921
- return [...data].sort((a, b) => {
1922
- const aVal = getRawValue(a, col.accessor);
1923
- const bVal = getRawValue(b, col.accessor);
1924
- return compareSortValues(aVal, bVal, sortDir);
1925
- });
1926
- }, [data, sortable, sortCol, sortDir, columns]);
1927
- const totalPages = pageSize ? Math.ceil(sortedData.length / pageSize) : 1;
1928
- const pagedData = pageSize ? sortedData.slice(page * pageSize, (page + 1) * pageSize) : sortedData;
1929
- const handleSort = _react.useCallback.call(void 0,
1930
- (colId) => {
1931
- if (!sortable) return;
1932
- let nextDir;
1933
- if (sortCol === colId) {
1934
- nextDir = sortDir === "asc" ? "desc" : sortDir === "desc" ? null : "asc";
1935
- setSortDir(nextDir);
1936
- if (nextDir === null) setSortCol(null);
1937
- } else {
1938
- setSortCol(colId);
1939
- setSortDir("asc");
1940
- nextDir = "asc";
1941
- }
1942
- setPage(0);
1943
- if (onSortExternal) {
1944
- onSortExternal(colId, nextDir);
1945
- }
1946
- },
1947
- [sortable, sortCol, sortDir, onSortExternal]
1948
- );
1949
- const toggleExpand = _react.useCallback.call(void 0, (key) => {
1950
- setExpandedKeys((prev) => {
1951
- const next = new Set(prev);
1952
- if (next.has(key)) next.delete(key);
1953
- else next.add(key);
1954
- return next;
1955
- });
1956
- }, []);
1957
- const selected = selectedKeys != null ? selectedKeys : [];
1958
- const selectedSet = _react.useMemo.call(void 0,
1959
- () => new Set(selectedKeys != null ? selectedKeys : []),
1960
- [selectedKeys]
1961
- );
1962
- const allKeys = data.map(keyExtractor);
1963
- const allSelected = allKeys.length > 0 && allKeys.every((k) => selectedSet.has(k));
1964
- const toggleSelectAll = _react.useCallback.call(void 0, () => {
1965
- if (!onSelectionChange) return;
1966
- onSelectionChange(allSelected ? [] : allKeys);
1967
- }, [allSelected, allKeys, onSelectionChange]);
1968
- const toggleSelectRow = _react.useCallback.call(void 0,
1969
- (key) => {
1970
- if (!onSelectionChange) return;
1971
- onSelectionChange(
1972
- selectedSet.has(key) ? selected.filter((k) => k !== key) : [...selected, key]
1973
- );
1974
- },
1975
- [selected, selectedSet, onSelectionChange]
1976
- );
1977
- const sortIndicator = (colId) => {
1978
- if (sortCol !== colId) return null;
1979
- return sortDir === "asc" ? " \u25B2" : sortDir === "desc" ? " \u25BC" : null;
1980
- };
1981
- const colCount = columns.length + (selectable ? 1 : 0) + (expandable ? 1 : 0);
1982
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1983
- "div",
1984
- {
1985
- className: _chunkAFF2HPE5cjs.cn.call(void 0, "gap-group flex flex-col", className),
1986
- "data-opt-id": "J1KN4",
1987
- "data-opt-slug": "data-table.DataTable",
1988
- children: [
1989
- title && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: _chunkAFF2HPE5cjs.cn.call(void 0, "text-sm font-semibold", _chunkAFF2HPE5cjs.OPT_TEXT_PRIMARY), children: title }),
1990
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1991
- "div",
1992
- {
1993
- className: _chunkAFF2HPE5cjs.cn.call(void 0, "overflow-x-auto rounded-lg", _chunkAFF2HPE5cjs.OPT_BORDER, "bg-surface"),
1994
- children: data.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1995
- "div",
1996
- {
1997
- className: _chunkAFF2HPE5cjs.cn.call(void 0, "px-4 py-8 text-center text-sm", _chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY),
1998
- children: emptyMessage
1999
- }
2000
- ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.CompositeProvider, { focusLoop: true, focusWrap: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2001
- _chunkAFF2HPE5cjs.Composite,
2002
- {
2003
- role: "grid",
2004
- "aria-label": title,
2005
- className: "w-full",
2006
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "table", {}),
2007
- children: [
2008
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2009
- "thead",
2010
- {
2011
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2012
- "border-border-subtle bg-surface-inset border-b",
2013
- stickyHeader && "sticky top-0 z-10"
2014
- ),
2015
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "tr", { children: [
2016
- selectable && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { className: _chunkAFF2HPE5cjs.cn.call(void 0, _chunkAFF2HPE5cjs.OPT_TH, "w-10"), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2017
- _chunkAFF2HPE5cjs.Checkbox,
2018
- {
2019
- checked: allSelected,
2020
- onChange: toggleSelectAll,
2021
- "aria-label": "Select all"
2022
- }
2023
- ) }),
2024
- expandable && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { className: _chunkAFF2HPE5cjs.cn.call(void 0, _chunkAFF2HPE5cjs.OPT_TH, "w-10") }),
2025
- columns.map((col) => {
2026
- var _a;
2027
- const isSortable = sortable && col.sortable !== false;
2028
- const resizeValue = getResizeHandleValue(
2029
- colWidths[col.id],
2030
- col.width
2031
- );
2032
- const resizeMax = Math.max(
2033
- DEFAULT_COLUMN_RESIZE_MAX,
2034
- resizeValue
2035
- );
2036
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2037
- "th",
2038
- {
2039
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2040
- _chunkAFF2HPE5cjs.OPT_TH,
2041
- "relative",
2042
- alignmentClass[(_a = col.align) != null ? _a : "left"],
2043
- isSortable && "hover:text-text-primary cursor-pointer select-none"
2044
- ),
2045
- style: {
2046
- width: colWidths[col.id] || col.width || void 0
2047
- },
2048
- onClick: isSortable ? () => handleSort(col.id) : void 0,
2049
- "aria-sort": sortCol === col.id && sortDir ? sortDir === "asc" ? "ascending" : "descending" : void 0,
2050
- children: [
2051
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "flex items-center", children: [
2052
- col.header,
2053
- sortIndicator(col.id)
2054
- ] }),
2055
- resizableColumns && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2056
- "span",
2057
- {
2058
- role: "separator",
2059
- "aria-orientation": "vertical",
2060
- "aria-label": `Resize ${col.header}`,
2061
- "aria-valuemin": MIN_COLUMN_WIDTH,
2062
- "aria-valuemax": resizeMax,
2063
- "aria-valuenow": resizeValue,
2064
- tabIndex: 0,
2065
- className: "bg-border absolute top-0 right-0 bottom-0 w-1 cursor-col-resize opacity-0 hover:opacity-100",
2066
- onKeyDown: (e) => {
2067
- if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") {
2068
- return;
2069
- }
2070
- e.preventDefault();
2071
- e.stopPropagation();
2072
- const delta = e.shiftKey ? 40 : 10;
2073
- const direction = e.key === "ArrowRight" ? 1 : -1;
2074
- setColWidths((prev) => {
2075
- const current = getResizeHandleValue(
2076
- prev[col.id],
2077
- col.width
2078
- );
2079
- return _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, prev), {
2080
- [col.id]: Math.max(
2081
- MIN_COLUMN_WIDTH,
2082
- current + direction * delta
2083
- )
2084
- });
2085
- });
2086
- },
2087
- onMouseDown: (e) => {
2088
- e.preventDefault();
2089
- e.stopPropagation();
2090
- const startX = e.clientX;
2091
- const th = e.target.parentElement;
2092
- const startW = th.offsetWidth;
2093
- const onMove = (ev) => {
2094
- const newW = Math.max(
2095
- MIN_COLUMN_WIDTH,
2096
- startW + ev.clientX - startX
2097
- );
2098
- setColWidths((prev) => _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, prev), {
2099
- [col.id]: newW
2100
- }));
2101
- };
2102
- const onUp = () => {
2103
- document.removeEventListener(
2104
- "mousemove",
2105
- onMove
2106
- );
2107
- document.removeEventListener("mouseup", onUp);
2108
- };
2109
- document.addEventListener("mousemove", onMove);
2110
- document.addEventListener("mouseup", onUp);
2111
- }
2112
- }
2113
- )
2114
- ]
2115
- },
2116
- col.id
2117
- );
2118
- })
2119
- ] })
2120
- }
2121
- ),
2122
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { className: _chunkAFF2HPE5cjs.cn.call(void 0, "divide-y", _chunkAFF2HPE5cjs.OPT_DIVIDER), children: pagedData.map((row) => {
2123
- const key = keyExtractor(row);
2124
- const isExpanded = expandedKeys.has(key);
2125
- const isSelected = selectedSet.has(key);
2126
- const isActive = activeRowId === key;
2127
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _react.Fragment, { children: [
2128
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2129
- _chunkAFF2HPE5cjs.CompositeRow,
2130
- {
2131
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2132
- "tr",
2133
- {
2134
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2135
- onRowClick ? "cursor-pointer" : void 0,
2136
- (isSelected || isActive) && "bg-accent-subtle"
2137
- ),
2138
- onClick: onRowClick ? () => onRowClick(row) : void 0
2139
- }
2140
- ),
2141
- children: [
2142
- selectable && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2143
- _chunkAFF2HPE5cjs.CompositeItem,
2144
- {
2145
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2146
- "td",
2147
- {
2148
- className: _chunkAFF2HPE5cjs.cn.call(void 0, _chunkAFF2HPE5cjs.OPT_TD, "w-10"),
2149
- role: "gridcell"
2150
- }
2151
- ),
2152
- className: _chunkAFF2HPE5cjs.OPT_TABLE_ROW_ACTIVE,
2153
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2154
- _chunkAFF2HPE5cjs.Checkbox,
2155
- {
2156
- checked: isSelected,
2157
- onChange: () => toggleSelectRow(key),
2158
- "aria-label": `Select row ${key}`
2159
- }
2160
- )
2161
- }
2162
- ),
2163
- expandable && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2164
- _chunkAFF2HPE5cjs.CompositeItem,
2165
- {
2166
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2167
- "td",
2168
- {
2169
- className: _chunkAFF2HPE5cjs.cn.call(void 0, _chunkAFF2HPE5cjs.OPT_TD, "w-10"),
2170
- role: "gridcell"
2171
- }
2172
- ),
2173
- className: _chunkAFF2HPE5cjs.OPT_TABLE_ROW_ACTIVE,
2174
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2175
- "button",
2176
- {
2177
- type: "button",
2178
- onClick: (e) => {
2179
- e.stopPropagation();
2180
- toggleExpand(key);
2181
- },
2182
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2183
- "rounded p-0.5 text-sm transition-transform",
2184
- _chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY,
2185
- _chunkAFF2HPE5cjs.OPT_FOCUS_VISIBLE,
2186
- isExpanded && "rotate-90"
2187
- ),
2188
- "aria-expanded": isExpanded,
2189
- "aria-label": "Expand row",
2190
- children: "\u25B6"
2191
- }
2192
- )
2193
- }
2194
- ),
2195
- columns.map((col, colIndex) => {
2196
- var _a, _b;
2197
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2198
- _chunkAFF2HPE5cjs.CompositeItem,
2199
- {
2200
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2201
- "td",
2202
- {
2203
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2204
- _chunkAFF2HPE5cjs.OPT_TD,
2205
- alignmentClass[(_a = col.align) != null ? _a : "left"],
2206
- colIndex === 0 ? "font-medium" : ""
2207
- ),
2208
- role: "gridcell"
2209
- }
2210
- ),
2211
- className: _chunkAFF2HPE5cjs.OPT_TABLE_ROW_ACTIVE,
2212
- children: [
2213
- getCellValue(row, col.accessor),
2214
- col.bar && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2215
- DataTableProgressBar,
2216
- {
2217
- value: col.bar(row),
2218
- barColor: (_b = col.barColor) != null ? _b : "bg-accent",
2219
- label: col.header
2220
- }
2221
- )
2222
- ]
2223
- },
2224
- col.id
2225
- );
2226
- })
2227
- ]
2228
- }
2229
- ),
2230
- expandable && isExpanded && renderExpanded && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2231
- "td",
2232
- {
2233
- colSpan: colCount,
2234
- className: "border-border-subtle bg-surface-inset border-t px-4 py-3",
2235
- children: renderExpanded(row)
2236
- }
2237
- ) })
2238
- ] }, key);
2239
- }) })
2240
- ]
2241
- }
2242
- ) })
2243
- }
2244
- ),
2245
- pageSize && totalPages > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2246
- _chunkAFF2HPE5cjs.Pagination,
2247
- {
2248
- totalItems: sortedData.length,
2249
- pageSize,
2250
- currentPage: page + 1,
2251
- onPageChange: (p) => setPage(p - 1)
2252
- }
2253
- )
2254
- ]
2255
- }
2256
- );
2257
- }
2258
-
2259
- // src/shells/notification-toast.tsx
2260
-
2261
-
2262
-
2263
-
2264
-
2265
-
2266
-
2267
-
2268
-
2269
-
2270
- var toastCounter = 0;
2271
- var toasts = [];
2272
- var listeners = /* @__PURE__ */ new Set();
2273
- function emitChange() {
2274
- for (const l of listeners) l();
2275
- }
2276
- var toastStore = {
2277
- subscribe(listener) {
2278
- listeners.add(listener);
2279
- return () => {
2280
- listeners.delete(listener);
2281
- };
2282
- },
2283
- getSnapshot() {
2284
- return toasts;
2285
- },
2286
- add(input) {
2287
- var _a;
2288
- const id = `toast-${++toastCounter}`;
2289
- toasts = [...toasts, _chunkONE3C5RVcjs.__spreadValues.call(void 0, { id, variant: (_a = input.variant) != null ? _a : "info" }, input)];
2290
- emitChange();
2291
- return id;
2292
- },
2293
- dismiss(id) {
2294
- const next = toasts.filter((t) => t.id !== id);
2295
- if (next.length !== toasts.length) {
2296
- toasts = next;
2297
- emitChange();
2298
- }
2299
- },
2300
- clear() {
2301
- if (toasts.length) {
2302
- toasts = [];
2303
- emitChange();
2304
- }
2305
- }
2306
- };
2307
- function makeVariant(variant) {
2308
- return (message, options) => toastStore.add(_chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, options), { message, variant }));
2309
- }
2310
- var toast = Object.assign(
2311
- (options) => toastStore.add(options),
2312
- {
2313
- info: makeVariant("info"),
2314
- success: makeVariant("success"),
2315
- warning: makeVariant("warning"),
2316
- error: makeVariant("error"),
2317
- dismiss: (id) => toastStore.dismiss(id),
2318
- clear: () => toastStore.clear()
2319
- }
2320
- );
2321
- var ToastContext = _react.createContext.call(void 0, null);
2322
- var positionStyles = {
2323
- "top-right": "top-4 right-4",
2324
- "top-left": "top-4 left-4",
2325
- "bottom-right": "bottom-4 right-4",
2326
- "bottom-left": "bottom-4 left-4"
2327
- };
2328
- function ToastProvider({
2329
- children,
2330
- position = "top-right",
2331
- defaultDuration = 5e3,
2332
- stackLimit = 5
2333
- }) {
2334
- const allToasts = _react.useSyncExternalStore.call(void 0,
2335
- toastStore.subscribe,
2336
- toastStore.getSnapshot,
2337
- toastStore.getSnapshot
2338
- );
2339
- const visibleToasts = allToasts.length > stackLimit ? allToasts.slice(-stackLimit) : allToasts;
2340
- const addToast = _react.useCallback.call(void 0,
2341
- (t) => toastStore.add(t),
2342
- []
2343
- );
2344
- const removeToast = _react.useCallback.call(void 0, (id) => toastStore.dismiss(id), []);
2345
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2346
- ToastContext.Provider,
2347
- {
2348
- value: { toasts: visibleToasts, addToast, removeToast },
2349
- children: [
2350
- children,
2351
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2352
- "div",
2353
- {
2354
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2355
- "gap-element fixed z-50 flex flex-col",
2356
- positionStyles[position]
2357
- ),
2358
- role: "region",
2359
- "aria-label": "Notifications",
2360
- "data-opt-id": "M0KTS",
2361
- "data-opt-slug": "notification-toast.ToastProvider",
2362
- children: visibleToasts.map((t) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2363
- NotificationToast,
2364
- {
2365
- toast: t,
2366
- defaultDuration,
2367
- onDismiss: () => toastStore.dismiss(t.id)
2368
- },
2369
- t.id
2370
- ))
2371
- }
2372
- )
2373
- ]
2374
- }
2375
- );
2376
- }
2377
- function useToast() {
2378
- const context = _react.useContext.call(void 0, ToastContext);
2379
- if (!context) {
2380
- throw new Error("useToast must be used within a ToastProvider");
2381
- }
2382
- return context;
2383
- }
2384
- function NotificationToast({
2385
- toast: toast2,
2386
- onDismiss,
2387
- defaultDuration = 5e3
2388
- }) {
2389
- var _a;
2390
- const duration = (_a = toast2.duration) != null ? _a : defaultDuration;
2391
- const isUrgent = toast2.variant === "error" || toast2.variant === "warning";
2392
- const onDismissRef = _react.useRef.call(void 0, onDismiss);
2393
- const dismissedRef = _react.useRef.call(void 0, false);
2394
- const timerStartedAtRef = _react.useRef.call(void 0, null);
2395
- const remainingDurationRef = _react.useRef.call(void 0, duration);
2396
- const [paused, setPaused] = _react.useState.call(void 0, false);
2397
- _react.useEffect.call(void 0, () => {
2398
- onDismissRef.current = onDismiss;
2399
- }, [onDismiss]);
2400
- const dismissOnce = _react.useCallback.call(void 0, () => {
2401
- if (dismissedRef.current) return;
2402
- dismissedRef.current = true;
2403
- onDismissRef.current();
2404
- }, []);
2405
- _react.useEffect.call(void 0, () => {
2406
- dismissedRef.current = false;
2407
- remainingDurationRef.current = duration;
2408
- }, [toast2.id, duration]);
2409
- _react.useEffect.call(void 0, () => {
2410
- if (!duration || duration <= 0 || paused || dismissedRef.current) {
2411
- return;
2412
- }
2413
- timerStartedAtRef.current = Date.now();
2414
- const timer = setTimeout(() => {
2415
- dismissOnce();
2416
- }, remainingDurationRef.current);
2417
- return () => {
2418
- clearTimeout(timer);
2419
- if (timerStartedAtRef.current !== null) {
2420
- const elapsed = Date.now() - timerStartedAtRef.current;
2421
- remainingDurationRef.current = Math.max(
2422
- 0,
2423
- remainingDurationRef.current - elapsed
2424
- );
2425
- timerStartedAtRef.current = null;
2426
- }
2427
- };
2428
- }, [dismissOnce, duration, paused]);
2429
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2430
- "div",
2431
- {
2432
- className: "animate-in slide-in-from-right-full fade-in w-80 duration-200",
2433
- role: isUrgent ? "alert" : "status",
2434
- "aria-live": isUrgent ? "assertive" : "polite",
2435
- "aria-atomic": "true",
2436
- onMouseEnter: () => setPaused(true),
2437
- onMouseLeave: () => setPaused(false),
2438
- onFocus: () => setPaused(true),
2439
- onBlur: (event) => {
2440
- if (!event.currentTarget.contains(event.relatedTarget)) {
2441
- setPaused(false);
2442
- }
2443
- },
2444
- "data-opt-id": "26YVM",
2445
- "data-opt-slug": "notification-toast.NotificationToast",
2446
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2447
- _chunkAFF2HPE5cjs.Alert,
2448
- {
2449
- variant: toast2.variant,
2450
- title: toast2.title,
2451
- dismissible: true,
2452
- onDismiss: dismissOnce,
2453
- children: [
2454
- toast2.message,
2455
- toast2.actions && toast2.actions.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "gap-element mt-2 flex", children: toast2.actions.map((action) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2456
- "button",
2457
- {
2458
- type: "button",
2459
- onClick: action.onClick,
2460
- className: "text-xs font-medium underline hover:no-underline",
2461
- children: action.label
2462
- },
2463
- action.label
2464
- )) })
2465
- ]
2466
- }
2467
- )
2468
- }
2469
- );
2470
- }
2471
-
2472
- // src/shells/failure-list.tsx
2473
-
2474
- var defaultLabels13 = {
2475
- title: "\uCD5C\uADFC \uC2E4\uD328",
2476
- emptyMessage: "\uC2E4\uD328 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
2477
- moreItems: "{count}\uAC1C \uB354 \uBCF4\uAE30",
2478
- severityLabels: {
2479
- critical: "\uC2EC\uAC01",
2480
- error: "\uC624\uB958",
2481
- warning: "\uACBD\uACE0"
2482
- },
2483
- timeAgo: {
2484
- justNow: "\uBC29\uAE08 \uC804",
2485
- minutesAgo: "{minutes}\uBD84 \uC804",
2486
- hoursAgo: "{hours}\uC2DC\uAC04 \uC804",
2487
- daysAgo: "{days}\uC77C \uC804"
2488
- }
2489
- };
2490
- var severityVariant = {
2491
- critical: "error",
2492
- error: "error",
2493
- warning: "warning"
2494
- };
2495
- var severityBorder = {
2496
- critical: "border-l-2 border-l-danger",
2497
- error: "border-l-2 border-l-danger",
2498
- warning: "border-l-2 border-l-warning"
2499
- };
2500
- function formatRelativeTime(timestamp, timeLabels, locale) {
2501
- const now = /* @__PURE__ */ new Date();
2502
- const date = new Date(timestamp);
2503
- const diffMs = now.getTime() - date.getTime();
2504
- const diffMins = Math.floor(diffMs / 6e4);
2505
- const diffHours = Math.floor(diffMs / 36e5);
2506
- const diffDays = Math.floor(diffMs / 864e5);
2507
- if (diffMins < 1) return timeLabels.justNow;
2508
- if (diffMins < 60)
2509
- return timeLabels.minutesAgo.replace("{minutes}", String(diffMins));
2510
- if (diffHours < 24)
2511
- return timeLabels.hoursAgo.replace("{hours}", String(diffHours));
2512
- if (diffDays < 7)
2513
- return timeLabels.daysAgo.replace("{days}", String(diffDays));
2514
- return date.toLocaleDateString(locale);
2515
- }
2516
- function groupBy(items, key) {
2517
- const map = /* @__PURE__ */ new Map();
2518
- for (const item of items) {
2519
- const k = key(item);
2520
- const existing = map.get(k);
2521
- if (existing) {
2522
- existing.push(item);
2523
- } else {
2524
- map.set(k, [item]);
2525
- }
2526
- }
2527
- return map;
2528
- }
2529
- function FailureItemRow({
2530
- failure,
2531
- isLast,
2532
- onFailureClick,
2533
- renderActions,
2534
- mergedSeverityLabels,
2535
- mergedTimeAgo,
2536
- locale
2537
- }) {
2538
- const itemId = `failure-${failure.id}`;
2539
- const handleKeyDown = (event) => {
2540
- if (!onFailureClick) return;
2541
- if (event.key !== "Enter" && event.key !== " ") return;
2542
- event.preventDefault();
2543
- onFailureClick(failure);
2544
- };
2545
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2546
- _chunkAFF2HPE5cjs.CompositeItem,
2547
- {
2548
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "article", {}),
2549
- role: "article",
2550
- "aria-labelledby": itemId,
2551
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2552
- "group gap-group relative flex w-full items-start p-3",
2553
- _chunkAFF2HPE5cjs.OPT_FOCUS_VISIBLE,
2554
- "data-[active-item]:bg-accent-subtle",
2555
- onFailureClick && "cursor-pointer",
2556
- !isLast && "border-border-subtle border-b",
2557
- severityBorder[failure.severity]
2558
- ),
2559
- onClick: () => onFailureClick == null ? void 0 : onFailureClick(failure),
2560
- onKeyDown: handleKeyDown,
2561
- children: [
2562
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "min-w-0 flex-1", children: [
2563
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "gap-element flex items-center", children: [
2564
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.Badge, { variant: severityVariant[failure.severity], size: "sm", children: mergedSeverityLabels[failure.severity] }),
2565
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2566
- "span",
2567
- {
2568
- id: itemId,
2569
- className: `text-sm font-medium ${_chunkAFF2HPE5cjs.OPT_TEXT_PRIMARY} truncate`,
2570
- children: failure.title
2571
- }
2572
- )
2573
- ] }),
2574
- failure.message && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: `mt-1 text-xs ${_chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY} line-clamp-2`, children: failure.message }),
2575
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2576
- "time",
2577
- {
2578
- dateTime: failure.timestamp,
2579
- className: `mt-1 block text-xs ${_chunkAFF2HPE5cjs.OPT_TEXT_TERTIARY}`,
2580
- children: formatRelativeTime(failure.timestamp, mergedTimeAgo, locale)
2581
- }
2582
- )
2583
- ] }),
2584
- renderActions && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex shrink-0 items-center gap-1", children: renderActions(failure) })
2585
- ]
2586
- },
2587
- failure.id
2588
- );
2589
- }
2590
- function FailureList({
2591
- failures,
2592
- title,
2593
- maxItems,
2594
- grouped = false,
2595
- onFailureClick,
2596
- onShowMore,
2597
- labels: customLabels,
2598
- locale = "ko-KR",
2599
- loading = false,
2600
- renderActions,
2601
- className
2602
- }) {
2603
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
2604
- const mergedTimeAgo = {
2605
- justNow: (_b = (_a = customLabels == null ? void 0 : customLabels.timeAgo) == null ? void 0 : _a.justNow) != null ? _b : defaultLabels13.timeAgo.justNow,
2606
- minutesAgo: (_d = (_c = customLabels == null ? void 0 : customLabels.timeAgo) == null ? void 0 : _c.minutesAgo) != null ? _d : defaultLabels13.timeAgo.minutesAgo,
2607
- hoursAgo: (_f = (_e = customLabels == null ? void 0 : customLabels.timeAgo) == null ? void 0 : _e.hoursAgo) != null ? _f : defaultLabels13.timeAgo.hoursAgo,
2608
- daysAgo: (_h = (_g = customLabels == null ? void 0 : customLabels.timeAgo) == null ? void 0 : _g.daysAgo) != null ? _h : defaultLabels13.timeAgo.daysAgo
2609
- };
2610
- const mergedSeverityLabels = {
2611
- critical: (_j = (_i = customLabels == null ? void 0 : customLabels.severityLabels) == null ? void 0 : _i.critical) != null ? _j : defaultLabels13.severityLabels.critical,
2612
- error: (_l = (_k = customLabels == null ? void 0 : customLabels.severityLabels) == null ? void 0 : _k.error) != null ? _l : defaultLabels13.severityLabels.error,
2613
- warning: (_n = (_m = customLabels == null ? void 0 : customLabels.severityLabels) == null ? void 0 : _m.warning) != null ? _n : defaultLabels13.severityLabels.warning
2614
- };
2615
- const labels = {
2616
- title: (_o = customLabels == null ? void 0 : customLabels.title) != null ? _o : defaultLabels13.title,
2617
- emptyMessage: (_p = customLabels == null ? void 0 : customLabels.emptyMessage) != null ? _p : defaultLabels13.emptyMessage,
2618
- moreItems: (_q = customLabels == null ? void 0 : customLabels.moreItems) != null ? _q : defaultLabels13.moreItems
2619
- };
2620
- const displayTitle = title != null ? title : labels.title;
2621
- const allItems = maxItems ? failures.slice(0, maxItems) : failures;
2622
- const remainingCount = maxItems ? Math.max(0, failures.length - maxItems) : 0;
2623
- const rowProps = {
2624
- onFailureClick,
2625
- renderActions,
2626
- mergedSeverityLabels,
2627
- mergedTimeAgo,
2628
- locale
2629
- };
2630
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2631
- "div",
2632
- {
2633
- className,
2634
- "data-opt-id": "ZAM3R",
2635
- "data-opt-slug": "failure-list.FailureList",
2636
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "gap-group flex flex-col", children: [
2637
- displayTitle && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: `text-sm font-semibold ${_chunkAFF2HPE5cjs.OPT_TEXT_PRIMARY}`, children: displayTitle }),
2638
- failures.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2639
- "div",
2640
- {
2641
- role: "status",
2642
- className: `py-8 text-center text-sm ${_chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY}`,
2643
- children: labels.emptyMessage
2644
- }
2645
- ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAFF2HPE5cjs.CompositeProvider, { focusLoop: true, orientation: "vertical", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2646
- _chunkAFF2HPE5cjs.Composite,
2647
- {
2648
- role: "feed",
2649
- "aria-label": displayTitle,
2650
- "aria-busy": loading,
2651
- className: `rounded-lg ${_chunkAFF2HPE5cjs.OPT_BORDER} bg-surface`,
2652
- children: grouped ? renderGrouped(
2653
- allItems,
2654
- remainingCount,
2655
- rowProps,
2656
- labels,
2657
- onShowMore
2658
- ) : renderFlat(
2659
- allItems,
2660
- remainingCount,
2661
- rowProps,
2662
- labels,
2663
- onShowMore
2664
- )
2665
- }
2666
- ) })
2667
- ] })
2668
- }
2669
- );
2670
- }
2671
- function renderFlat(items, remainingCount, rowProps, labels, onShowMore) {
2672
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2673
- items.map((failure, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2674
- FailureItemRow,
2675
- _chunkONE3C5RVcjs.__spreadValues.call(void 0, {
2676
- failure,
2677
- isLast: index === items.length - 1 && remainingCount === 0
2678
- }, rowProps),
2679
- failure.id
2680
- )),
2681
- remainingCount > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2682
- _chunkAFF2HPE5cjs.CompositeItem,
2683
- {
2684
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button" }),
2685
- onClick: onShowMore,
2686
- className: `border-border-subtle w-full border-t p-3 text-center text-xs font-medium ${_chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY} ${_chunkAFF2HPE5cjs.OPT_FOCUS} hover:text-accent data-[active-item]:bg-accent-subtle transition-colors`,
2687
- "aria-label": `${remainingCount}\uAC1C\uC758 \uC2E4\uD328 \uB354 \uBCF4\uAE30`,
2688
- children: labels.moreItems.replace("{count}", String(remainingCount))
2689
- }
2690
- )
2691
- ] });
2692
- }
2693
- function renderGrouped(items, remainingCount, rowProps, labels, onShowMore) {
2694
- const groups = groupBy(items, (f) => {
2695
- var _a;
2696
- return (_a = f.group) != null ? _a : "";
2697
- });
2698
- const groupEntries = Array.from(groups.entries());
2699
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2700
- groupEntries.map(([groupName, groupItems], groupIndex) => {
2701
- const isLastGroup = groupIndex === groupEntries.length - 1 && remainingCount === 0;
2702
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
2703
- groupName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2704
- "div",
2705
- {
2706
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2707
- `px-3 py-2 text-xs font-semibold ${_chunkAFF2HPE5cjs.OPT_TEXT_TERTIARY} tracking-wider uppercase`,
2708
- groupIndex > 0 && "border-border-subtle border-t"
2709
- ),
2710
- children: groupName
2711
- }
2712
- ),
2713
- groupItems.map((failure, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2714
- FailureItemRow,
2715
- _chunkONE3C5RVcjs.__spreadValues.call(void 0, {
2716
- failure,
2717
- isLast: isLastGroup && index === groupItems.length - 1
2718
- }, rowProps),
2719
- failure.id
2720
- ))
2721
- ] }, groupName || "__ungrouped__");
2722
- }),
2723
- remainingCount > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2724
- _chunkAFF2HPE5cjs.CompositeItem,
2725
- {
2726
- render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button" }),
2727
- onClick: onShowMore,
2728
- className: `border-border-subtle w-full border-t p-3 text-center text-xs font-medium ${_chunkAFF2HPE5cjs.OPT_TEXT_SECONDARY} ${_chunkAFF2HPE5cjs.OPT_FOCUS} hover:text-accent data-[active-item]:bg-accent-subtle transition-colors`,
2729
- "aria-label": `${remainingCount}\uAC1C\uC758 \uC2E4\uD328 \uB354 \uBCF4\uAE30`,
2730
- children: labels.moreItems.replace("{count}", String(remainingCount))
2731
- }
2732
- )
2733
- ] });
2734
- }
2735
-
2736
- // src/shells/key-value-editor.tsx
2737
-
2738
-
2739
- var defaultLabels14 = {
2740
- keyPlaceholder: "\uD0A4",
2741
- valuePlaceholder: "\uAC12",
2742
- addButton: "\uCD94\uAC00",
2743
- removeAriaLabel: "\uD56D\uBAA9 \uC0AD\uC81C",
2744
- toggleSecretAriaLabel: "\uBE44\uBC00\uAC12 \uD1A0\uAE00",
2745
- emptyMessage: "\uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uCD94\uAC00 \uBC84\uD2BC\uC744 \uB20C\uB7EC\uC8FC\uC138\uC694."
2746
- };
2747
- var idCounter = 0;
2748
- function generateId() {
2749
- return `kv-${++idCounter}`;
2750
- }
2751
- function KeyValueEditor({
2752
- value: controlledValue,
2753
- defaultValue,
2754
- onChange,
2755
- showSecretToggle = false,
2756
- maxEntries,
2757
- readOnly = false,
2758
- labels: customLabels,
2759
- renderActions,
2760
- validateKey,
2761
- className
2762
- }) {
2763
- const labels = _chunkONE3C5RVcjs.__spreadValues.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, defaultLabels14), customLabels);
2764
- const [internalEntries, setInternalEntries] = _react.useState.call(void 0,
2765
- () => defaultValue != null ? defaultValue : []
2766
- );
2767
- const entries = controlledValue != null ? controlledValue : internalEntries;
2768
- const keyInputRef = _react.useRef.call(void 0, null);
2769
- const updateEntries = _react.useCallback.call(void 0,
2770
- (next) => {
2771
- if (!controlledValue) {
2772
- setInternalEntries(next);
2773
- }
2774
- onChange == null ? void 0 : onChange(next);
2775
- },
2776
- [controlledValue, onChange]
2777
- );
2778
- const addEntry = _react.useCallback.call(void 0, () => {
2779
- if (maxEntries && entries.length >= maxEntries) return;
2780
- const newEntry = {
2781
- id: generateId(),
2782
- key: "",
2783
- value: "",
2784
- isSecret: false
2785
- };
2786
- updateEntries([...entries, newEntry]);
2787
- requestAnimationFrame(() => {
2788
- var _a, _b, _c;
2789
- (_c = (_b = (_a = keyInputRef.current) == null ? void 0 : _a.closest("[data-kv-list]")) == null ? void 0 : _b.querySelector(
2790
- `[data-kv-id="${newEntry.id}"] [data-kv-key]`
2791
- )) == null ? void 0 : _c.focus();
2792
- });
2793
- }, [entries, maxEntries, updateEntries]);
2794
- const removeEntry = _react.useCallback.call(void 0,
2795
- (id) => {
2796
- updateEntries(entries.filter((e) => e.id !== id));
2797
- },
2798
- [entries, updateEntries]
2799
- );
2800
- const updateEntry = _react.useCallback.call(void 0,
2801
- (id, field, val) => {
2802
- updateEntries(
2803
- entries.map((e) => e.id === id ? _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, e), { [field]: val }) : e)
2804
- );
2805
- },
2806
- [entries, updateEntries]
2807
- );
2808
- const toggleSecret = _react.useCallback.call(void 0,
2809
- (id) => {
2810
- updateEntries(
2811
- entries.map((e) => e.id === id ? _chunkONE3C5RVcjs.__spreadProps.call(void 0, _chunkONE3C5RVcjs.__spreadValues.call(void 0, {}, e), { isSecret: !e.isSecret }) : e)
2812
- );
2813
- },
2814
- [entries, updateEntries]
2815
- );
2816
- const canAdd = !readOnly && (!maxEntries || entries.length < maxEntries);
2817
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2818
- "div",
2819
- {
2820
- className: _chunkAFF2HPE5cjs.cn.call(void 0, "gap-group flex flex-col", className),
2821
- "data-opt-id": "NCBWA",
2822
- "data-opt-slug": "key-value-editor.KeyValueEditor",
2823
- children: [
2824
- entries.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-text-tertiary py-4 text-center text-sm", children: labels.emptyMessage }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "gap-element flex flex-col", "data-kv-list": true, children: entries.map((entry, index) => {
2825
- const keyError = validateKey == null ? void 0 : validateKey(entry.key, entries);
2826
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2827
- "div",
2828
- {
2829
- "data-kv-id": entry.id,
2830
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2831
- "gap-element flex items-start",
2832
- "border-border rounded-lg border p-3",
2833
- "bg-surface"
2834
- ),
2835
- children: [
2836
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
2837
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2838
- "input",
2839
- {
2840
- "data-kv-key": true,
2841
- ref: index === entries.length - 1 ? keyInputRef : void 0,
2842
- type: "text",
2843
- value: entry.key,
2844
- onChange: (e) => updateEntry(entry.id, "key", e.target.value),
2845
- placeholder: labels.keyPlaceholder,
2846
- readOnly,
2847
- "aria-label": `${labels.keyPlaceholder} ${index + 1}`,
2848
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2849
- "border-border bg-bg-subtle text-text-primary placeholder:text-text-tertiary w-full rounded-md border px-3 py-1.5 font-mono text-sm",
2850
- "focus:border-accent focus-visible:ring-ring focus-visible:ring-offset-ring-offset focus-visible:ring-2 focus-visible:ring-offset-1",
2851
- readOnly && "cursor-default opacity-70",
2852
- keyError && "border-error"
2853
- )
2854
- }
2855
- ),
2856
- keyError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-error text-xs", children: keyError })
2857
- ] }),
2858
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-text-tertiary px-1 py-1.5", children: "=" }),
2859
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2860
- "input",
2861
- {
2862
- type: entry.isSecret ? "password" : "text",
2863
- value: entry.value,
2864
- onChange: (e) => updateEntry(entry.id, "value", e.target.value),
2865
- placeholder: labels.valuePlaceholder,
2866
- readOnly,
2867
- "aria-label": `${labels.valuePlaceholder} ${index + 1}`,
2868
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2869
- "border-border bg-bg-subtle text-text-primary placeholder:text-text-tertiary w-full rounded-md border px-3 py-1.5 font-mono text-sm",
2870
- "focus:border-accent focus-visible:ring-ring focus-visible:ring-offset-ring-offset focus-visible:ring-2 focus-visible:ring-offset-1",
2871
- readOnly && "cursor-default opacity-70"
2872
- )
2873
- }
2874
- ) }),
2875
- showSecretToggle && !readOnly && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2876
- "button",
2877
- {
2878
- type: "button",
2879
- onClick: () => toggleSecret(entry.id),
2880
- "aria-label": labels.toggleSecretAriaLabel,
2881
- "aria-pressed": entry.isSecret,
2882
- className: "text-text-tertiary hover:text-text-primary shrink-0 rounded p-1.5 transition-colors",
2883
- children: entry.isSecret ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2884
- "svg",
2885
- {
2886
- className: "size-4",
2887
- fill: "none",
2888
- viewBox: "0 0 24 24",
2889
- stroke: "currentColor",
2890
- strokeWidth: 2,
2891
- "aria-hidden": "true",
2892
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2893
- "path",
2894
- {
2895
- strokeLinecap: "round",
2896
- strokeLinejoin: "round",
2897
- d: "M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88"
2898
- }
2899
- )
2900
- }
2901
- ) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2902
- "svg",
2903
- {
2904
- className: "size-4",
2905
- fill: "none",
2906
- viewBox: "0 0 24 24",
2907
- stroke: "currentColor",
2908
- strokeWidth: 2,
2909
- "aria-hidden": "true",
2910
- children: [
2911
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2912
- "path",
2913
- {
2914
- strokeLinecap: "round",
2915
- strokeLinejoin: "round",
2916
- d: "M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"
2917
- }
2918
- ),
2919
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2920
- "path",
2921
- {
2922
- strokeLinecap: "round",
2923
- strokeLinejoin: "round",
2924
- d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z"
2925
- }
2926
- )
2927
- ]
2928
- }
2929
- )
2930
- }
2931
- ),
2932
- renderActions == null ? void 0 : renderActions(entry, index),
2933
- !readOnly && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2934
- "button",
2935
- {
2936
- type: "button",
2937
- onClick: () => removeEntry(entry.id),
2938
- "aria-label": labels.removeAriaLabel,
2939
- className: "text-text-tertiary hover:text-error shrink-0 rounded p-1.5 transition-colors",
2940
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2941
- "svg",
2942
- {
2943
- className: "size-4",
2944
- fill: "none",
2945
- viewBox: "0 0 24 24",
2946
- stroke: "currentColor",
2947
- strokeWidth: 2,
2948
- "aria-hidden": "true",
2949
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2950
- "path",
2951
- {
2952
- strokeLinecap: "round",
2953
- strokeLinejoin: "round",
2954
- d: "M6 18L18 6M6 6l12 12"
2955
- }
2956
- )
2957
- }
2958
- )
2959
- }
2960
- )
2961
- ]
2962
- },
2963
- entry.id
2964
- );
2965
- }) }),
2966
- canAdd && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2967
- "button",
2968
- {
2969
- type: "button",
2970
- onClick: addEntry,
2971
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
2972
- "border-border text-text-secondary rounded-lg border border-dashed px-4 py-2 text-sm transition-colors",
2973
- "hover:border-accent hover:text-accent"
2974
- ),
2975
- children: labels.addButton
2976
- }
2977
- )
2978
- ]
2979
- }
2980
- );
2981
- }
2982
-
2983
- // src/shells/workflow-canvas.tsx
2984
-
2985
-
2986
- var statusVariant = {
2987
- idle: "default",
2988
- running: "info",
2989
- success: "success",
2990
- error: "error"
2991
- };
2992
- function clamp(value, min, max) {
2993
- return Math.max(min, Math.min(max, value));
2994
- }
2995
- function WorkflowCanvas({
2996
- steps,
2997
- connections = [],
2998
- rows = 9,
2999
- cols = 9,
3000
- cellSize = 72,
3001
- gap = 12,
3002
- title = "Workflow Canvas",
3003
- emptyMessage = "No workflow steps",
3004
- selectedStepId,
3005
- onSelectStep,
3006
- onStepMove,
3007
- renderStep,
3008
- className
3009
- }) {
3010
- const stepMap = React.useMemo(
3011
- () => new Map(steps.map((step) => [step.id, step])),
3012
- [steps]
3013
- );
3014
- const width = cols * cellSize + (cols - 1) * gap;
3015
- const height = rows * cellSize + (rows - 1) * gap;
3016
- const renderDefaultStep = React.useCallback(
3017
- (step, selected) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3018
- "button",
3019
- {
3020
- type: "button",
3021
- onClick: () => onSelectStep == null ? void 0 : onSelectStep(step),
3022
- className: _chunkAFF2HPE5cjs.cn.call(void 0,
3023
- "group absolute flex h-full w-full flex-col justify-between rounded-lg border p-2 text-left transition-colors",
3024
- selected ? "border-accent bg-accent-subtle" : "border-border bg-surface hover:bg-bg-subtle"
3025
- ),
3026
- children: [
3027
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-text-primary truncate text-xs font-medium", children: step.title }),
3028
- step.status && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3029
- _chunkAFF2HPE5cjs.Badge,
3030
- {
3031
- variant: statusVariant[step.status],
3032
- size: "sm",
3033
- className: "w-fit",
3034
- children: step.status
3035
- }
3036
- )
3037
- ]
3038
- }
3039
- ),
3040
- [onSelectStep]
3041
- );
3042
- const handleStepKeyDown = React.useCallback(
3043
- (event, step) => {
3044
- if (!onStepMove) {
3045
- return;
3046
- }
3047
- let nextRow = step.row;
3048
- let nextCol = step.col;
3049
- switch (event.key) {
3050
- case "ArrowUp":
3051
- nextRow -= 1;
3052
- break;
3053
- case "ArrowDown":
3054
- nextRow += 1;
3055
- break;
3056
- case "ArrowLeft":
3057
- nextCol -= 1;
3058
- break;
3059
- case "ArrowRight":
3060
- nextCol += 1;
3061
- break;
3062
- default:
3063
- return;
3064
- }
3065
- event.preventDefault();
3066
- onStepMove(
3067
- step.id,
3068
- clamp(nextRow, 0, rows - 1),
3069
- clamp(nextCol, 0, cols - 1)
3070
- );
3071
- },
3072
- [onStepMove, rows, cols]
3073
- );
3074
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3075
- "div",
3076
- {
3077
- className: _chunkAFF2HPE5cjs.cn.call(void 0, "gap-group flex flex-col", className),
3078
- "data-opt-id": "4TX11",
3079
- "data-opt-slug": "workflow-canvas.WorkflowCanvas",
3080
- children: [
3081
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-text-primary text-sm font-semibold", children: title }),
3082
- steps.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-text-secondary border-border rounded-lg border border-dashed p-8 text-center text-sm", children: emptyMessage }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "border-border bg-bg-subtle relative overflow-auto rounded-lg border p-3", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3083
- "div",
3084
- {
3085
- role: "grid",
3086
- "aria-label": title,
3087
- className: "relative",
3088
- style: { width, height },
3089
- children: [
3090
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3091
- "div",
3092
- {
3093
- className: "grid",
3094
- style: {
3095
- gridTemplateColumns: `repeat(${cols}, ${cellSize}px)`,
3096
- gridTemplateRows: `repeat(${rows}, ${cellSize}px)`,
3097
- gap
3098
- },
3099
- children: Array.from({ length: rows * cols }, (_, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3100
- "div",
3101
- {
3102
- "aria-hidden": "true",
3103
- className: "border-border-subtle bg-surface/30 rounded-md border border-dashed"
3104
- },
3105
- i
3106
- ))
3107
- }
3108
- ),
3109
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3110
- "svg",
3111
- {
3112
- className: "pointer-events-none absolute inset-0",
3113
- width,
3114
- height,
3115
- "aria-hidden": "true",
3116
- children: connections.map((connection) => {
3117
- const from = stepMap.get(connection.from);
3118
- const to = stepMap.get(connection.to);
3119
- if (!from || !to) {
3120
- return null;
3121
- }
3122
- const x1 = from.col * (cellSize + gap) + cellSize / 2;
3123
- const y1 = from.row * (cellSize + gap) + cellSize / 2;
3124
- const x2 = to.col * (cellSize + gap) + cellSize / 2;
3125
- const y2 = to.row * (cellSize + gap) + cellSize / 2;
3126
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "g", { children: [
3127
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3128
- "line",
3129
- {
3130
- x1,
3131
- y1,
3132
- x2,
3133
- y2,
3134
- stroke: "currentColor",
3135
- strokeOpacity: "0.35",
3136
- strokeWidth: "2"
3137
- }
3138
- ),
3139
- connection.label && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3140
- "text",
3141
- {
3142
- x: (x1 + x2) / 2,
3143
- y: (y1 + y2) / 2 - 4,
3144
- textAnchor: "middle",
3145
- className: "fill-text-secondary text-[10px]",
3146
- children: connection.label
3147
- }
3148
- )
3149
- ] }, `${connection.from}-${connection.to}`);
3150
- })
3151
- }
3152
- ),
3153
- steps.map((step) => {
3154
- const selected = selectedStepId === step.id;
3155
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3156
- "div",
3157
- {
3158
- role: "gridcell",
3159
- tabIndex: 0,
3160
- "aria-selected": selected,
3161
- "aria-label": `${step.title} (${step.row + 1}, ${step.col + 1})`,
3162
- onKeyDown: (event) => handleStepKeyDown(event, step),
3163
- className: "focus-visible:ring-ring absolute focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-white focus-visible:outline-none",
3164
- style: {
3165
- width: cellSize,
3166
- height: cellSize,
3167
- left: step.col * (cellSize + gap),
3168
- top: step.row * (cellSize + gap)
3169
- },
3170
- children: renderStep ? renderStep(step, selected) : renderDefaultStep(step, selected)
3171
- },
3172
- step.id
3173
- );
3174
- })
3175
- ]
3176
- }
3177
- ) })
3178
- ]
3179
- }
3180
- );
3181
- }
3182
- WorkflowCanvas.displayName = "WorkflowCanvas";
3183
-
3184
-
3185
-
3186
-
3187
-
3188
-
3189
-
3190
-
3191
-
3192
-
3193
-
3194
-
3195
-
3196
-
3197
-
3198
-
3199
-
3200
-
3201
-
3202
-
3203
-
3204
-
3205
-
3206
-
3207
-
3208
-
3209
-
3210
-
3211
-
3212
-
3213
-
3214
-
3215
-
3216
-
3217
-
3218
- exports.Command = Command; exports.CommandDialog = CommandDialog; exports.CommandInput = CommandInput; exports.CommandList = CommandList; exports.CommandEmpty = CommandEmpty; exports.CommandGroup = CommandGroup; exports.CommandSeparator = CommandSeparator; exports.CommandItem = CommandItem; exports.CommandShortcut = CommandShortcut; exports.CommandPalette = CommandPalette; exports.CommandPaletteTrigger = CommandPaletteTrigger; exports.DashboardGrid = DashboardGrid; exports.SearchCombobox = SearchCombobox; exports.StatusSelect = StatusSelect; exports.AppMenubar = AppMenubar; exports.SidebarNav = SidebarNav; exports.EditorToolbar = EditorToolbar; exports.ContentTabs = ContentTabs; exports.FaqAccordion = FaqAccordion; exports.SettingsForm = SettingsForm; exports.DeploymentTimeline = DeploymentTimeline; exports.ProjectSwitcher = ProjectSwitcher; exports.EnvPanel = EnvPanel; exports.BranchSelect = BranchSelect; exports.DomainTable = DomainTable; exports.DataTable = DataTable; exports.toast = toast; exports.ToastProvider = ToastProvider; exports.useToast = useToast; exports.NotificationToast = NotificationToast; exports.FailureList = FailureList; exports.KeyValueEditor = KeyValueEditor; exports.WorkflowCanvas = WorkflowCanvas;