@reopt-ai/opt-ui 1.5.0 → 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 (87) hide show
  1. package/COMPONENT_CATALOG.md +83 -38
  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 -6
  6. package/dist/core/index.d.ts +3 -6
  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 +36 -28
  10. package/dist/docs/02-components/02-visuals.md +1 -1
  11. package/dist/docs/02-components/03-shells.md +40 -12
  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 +16 -12
  15. package/dist/docs/05-migration/01-breaking-changes.md +28 -0
  16. package/dist/id-registry.cjs +1899 -1872
  17. package/dist/id-registry.d.cts +13 -10
  18. package/dist/id-registry.d.cts.map +1 -0
  19. package/dist/id-registry.d.ts +13 -10
  20. package/dist/id-registry.d.ts.map +1 -0
  21. package/dist/id-registry.js +1897 -1871
  22. package/dist/id-registry.js.map +1 -0
  23. package/dist/id-registry.json +28 -28
  24. package/dist/index.cjs +8294 -9790
  25. package/dist/index.d.cts +1486 -1442
  26. package/dist/index.d.cts.map +1 -0
  27. package/dist/index.d.ts +1486 -1442
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +7933 -9777
  30. package/dist/index.js.map +1 -0
  31. package/dist/meta.cjs +7461 -6875
  32. package/dist/meta.d.cts.map +1 -0
  33. package/dist/meta.d.ts.map +1 -0
  34. package/dist/meta.js +7460 -6846
  35. package/dist/meta.js.map +1 -0
  36. package/dist/pagination-By7Ozv3U.js +3788 -0
  37. package/dist/pagination-By7Ozv3U.js.map +1 -0
  38. package/dist/pagination-Uv3CnGJz.cjs +4677 -0
  39. package/dist/shader-surface-BK1GMt5_.d.cts +1788 -0
  40. package/dist/shader-surface-BK1GMt5_.d.cts.map +1 -0
  41. package/dist/shader-surface-BWhO2xkk.js +3715 -0
  42. package/dist/shader-surface-BWhO2xkk.js.map +1 -0
  43. package/dist/shader-surface-DIVWtpFl.d.ts +1788 -0
  44. package/dist/shader-surface-DIVWtpFl.d.ts.map +1 -0
  45. package/dist/shader-surface-DxLLfrE6.cjs +4108 -0
  46. package/dist/shells/index.cjs +51 -65
  47. package/dist/shells/index.d.cts +4 -5
  48. package/dist/shells/index.d.ts +4 -5
  49. package/dist/shells/index.js +3 -64
  50. package/dist/tailwind.css +49 -0
  51. package/dist/theme/server.cjs +257 -228
  52. package/dist/theme/server.d.cts +48 -60
  53. package/dist/theme/server.d.cts.map +1 -0
  54. package/dist/theme/server.d.ts +48 -60
  55. package/dist/theme/server.d.ts.map +1 -0
  56. package/dist/theme/server.js +234 -189
  57. package/dist/theme/server.js.map +1 -0
  58. package/dist/types-D0FlcYnM.d.cts +301 -0
  59. package/dist/types-D0FlcYnM.d.cts.map +1 -0
  60. package/dist/types-D0FlcYnM.d.ts +301 -0
  61. package/dist/types-D0FlcYnM.d.ts.map +1 -0
  62. package/dist/visuals/index.cjs +10 -4
  63. package/dist/visuals/index.d.cts +2 -1
  64. package/dist/visuals/index.d.ts +2 -1
  65. package/dist/visuals/index.js +1 -2
  66. package/dist/workflow-canvas-3Jeevkgy.cjs +2599 -0
  67. package/dist/workflow-canvas-BGBAcjf-.js +2403 -0
  68. package/dist/workflow-canvas-BGBAcjf-.js.map +1 -0
  69. package/dist/workflow-canvas-Bar_O2SQ.d.ts +494 -0
  70. package/dist/workflow-canvas-Bar_O2SQ.d.ts.map +1 -0
  71. package/dist/workflow-canvas-DghDRtHn.d.cts +494 -0
  72. package/dist/workflow-canvas-DghDRtHn.d.cts.map +1 -0
  73. package/package.json +11 -6
  74. package/dist/chunk-3GWWZKX7.js +0 -38
  75. package/dist/chunk-3QFYBBL6.cjs +0 -4759
  76. package/dist/chunk-3XD4HIFL.js +0 -3241
  77. package/dist/chunk-AFF2HPE5.cjs +0 -5008
  78. package/dist/chunk-NXZJIHEZ.cjs +0 -3241
  79. package/dist/chunk-ONE3C5RV.cjs +0 -38
  80. package/dist/chunk-RBM2RNC2.js +0 -5008
  81. package/dist/chunk-VBGPEW45.js +0 -4759
  82. package/dist/index-BZ_lBlO1.d.ts +0 -474
  83. package/dist/index-BuvxoWHf.d.cts +0 -474
  84. package/dist/index-DWyqDIkH.d.cts +0 -1689
  85. package/dist/index-Uyijm14M.d.ts +0 -1689
  86. package/dist/types-D4-0lwaE.d.cts +0 -298
  87. package/dist/types-D4-0lwaE.d.ts +0 -298
@@ -0,0 +1,4108 @@
1
+ "use client";
2
+ const require_pagination = require("./pagination-Uv3CnGJz.cjs");
3
+ let react_jsx_runtime = require("react/jsx-runtime");
4
+ let react = require("react");
5
+ react = require_pagination.__toESM(react, 1);
6
+ let _reopt_ai_opt_ui_primitives = require("@reopt-ai/opt-ui-primitives");
7
+ let lucide_react = require("lucide-react");
8
+ let react_resizable_panels = require("react-resizable-panels");
9
+ let ogl = require("ogl");
10
+ let _reopt_ai_opt_palette = require("@reopt-ai/opt-palette");
11
+ //#region src/core/text.tsx
12
+ const _excluded$18 = [
13
+ "as",
14
+ "variant",
15
+ "tone",
16
+ "truncate",
17
+ "className",
18
+ "children"
19
+ ];
20
+ const toneStyles = {
21
+ primary: "text-text-primary",
22
+ secondary: "text-text-secondary",
23
+ tertiary: "text-text-tertiary",
24
+ inherit: "text-inherit"
25
+ };
26
+ /** Semantic body text whose visual role is controlled by foundation tokens. */
27
+ function Text(_ref) {
28
+ let { as, variant = "body", tone = "primary", truncate = false, className, children } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$18);
29
+ return (0, react.createElement)(as !== null && as !== void 0 ? as : "span", require_pagination._objectSpread2(require_pagination._objectSpread2({}, props), {}, {
30
+ className: require_pagination.cn(`opt-type-${variant}`, toneStyles[tone], truncate && "truncate", className),
31
+ "data-opt-component": "text",
32
+ "data-opt-part": "root",
33
+ "data-opt-id": "NFKP2",
34
+ "data-opt-slug": "text.Text",
35
+ "data-role": variant,
36
+ "data-tone": tone
37
+ }), children);
38
+ }
39
+ //#endregion
40
+ //#region src/core/heading.tsx
41
+ const _excluded$17 = [
42
+ "level",
43
+ "variant",
44
+ "className",
45
+ "children"
46
+ ];
47
+ /** Semantic heading with independently selectable visual hierarchy. */
48
+ function Heading(_ref) {
49
+ let { level = 2, variant = `heading-${level}`, className, children } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$17);
50
+ const Component = {
51
+ 1: "h1",
52
+ 2: "h2",
53
+ 3: "h3",
54
+ 4: "h4",
55
+ 5: "h5",
56
+ 6: "h6"
57
+ }[level];
58
+ return (0, react.createElement)(Component, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn(`opt-type-${variant}`, "text-text-primary", className) }, props), {}, {
59
+ "data-opt-component": "heading",
60
+ "data-opt-part": "root",
61
+ "data-opt-id": "NF0BT",
62
+ "data-opt-slug": "heading.Heading",
63
+ "data-level": level,
64
+ "data-role": variant
65
+ }), children);
66
+ }
67
+ //#endregion
68
+ //#region src/core/separator.tsx
69
+ /**
70
+ * Visual divider between content. Wraps the headless primitive with design
71
+ * tokens. With `children`, renders a centered label flanked by rules.
72
+ */
73
+ function Separator$1({ orientation = "horizontal", decorative = false, children, className }) {
74
+ if (orientation === "horizontal" && children != null) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
75
+ className: require_pagination.cn("gap-element flex items-center", className),
76
+ "data-opt-id": "7PWJS",
77
+ "data-opt-slug": "separator.Separator",
78
+ children: [
79
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.Separator, {
80
+ decorative: true,
81
+ orientation: "horizontal",
82
+ className: "bg-border h-px flex-1"
83
+ }),
84
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
85
+ className: "text-text-tertiary shrink-0 text-xs",
86
+ children
87
+ }),
88
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.Separator, {
89
+ decorative: true,
90
+ orientation: "horizontal",
91
+ className: "bg-border h-px flex-1"
92
+ })
93
+ ]
94
+ });
95
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.Separator, {
96
+ orientation,
97
+ decorative,
98
+ className: require_pagination.cn("bg-border shrink-0", orientation === "horizontal" ? "h-px w-full" : "h-full w-px self-stretch", className),
99
+ "data-opt-id": "7PWJS",
100
+ "data-opt-slug": "separator.Separator"
101
+ });
102
+ }
103
+ Separator$1.displayName = "Separator";
104
+ //#endregion
105
+ //#region src/core/otp-field.tsx
106
+ const PATTERNS = {
107
+ numeric: /[0-9]/,
108
+ alphanumeric: /[a-zA-Z0-9]/
109
+ };
110
+ /**
111
+ * One-time-code / PIN entry split into per-character cells, with paste
112
+ * distribution, auto-advancing focus, and arrow/backspace navigation.
113
+ */
114
+ function OtpField({ length = 6, value: controlledValue, defaultValue = "", onChange, onComplete, type = "numeric", mask = false, disabled = false, autoFocus = false, name, label, required, error, hint, className, id, "aria-label": ariaLabel }) {
115
+ const reactId = react.useId();
116
+ const fieldId = id !== null && id !== void 0 ? id : `otp-${reactId}`;
117
+ const hasError = Boolean(error);
118
+ const pattern = PATTERNS[type];
119
+ const inputsRef = react.useRef([]);
120
+ const labelId = label ? `${fieldId}-label` : void 0;
121
+ const groupLabelledBy = ariaLabel ? void 0 : labelId;
122
+ const groupAriaLabel = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : groupLabelledBy ? void 0 : "One-time code";
123
+ const [value, setRawValue] = require_pagination.useControlledState(defaultValue, controlledValue, onChange);
124
+ const completedRef = react.useRef(false);
125
+ const setValue = react.useCallback((next) => {
126
+ const clipped = next.slice(0, length);
127
+ setRawValue(clipped);
128
+ if (clipped.length === length) {
129
+ if (!completedRef.current) {
130
+ completedRef.current = true;
131
+ onComplete === null || onComplete === void 0 || onComplete(clipped);
132
+ }
133
+ } else completedRef.current = false;
134
+ }, [
135
+ length,
136
+ setRawValue,
137
+ onComplete
138
+ ]);
139
+ const focusCell = react.useCallback((index) => {
140
+ var _inputsRef$current$ta, _inputsRef$current$ta2;
141
+ const target = Math.max(0, Math.min(index, inputsRef.current.length - 1));
142
+ (_inputsRef$current$ta = inputsRef.current[target]) === null || _inputsRef$current$ta === void 0 || _inputsRef$current$ta.focus();
143
+ (_inputsRef$current$ta2 = inputsRef.current[target]) === null || _inputsRef$current$ta2 === void 0 || _inputsRef$current$ta2.select();
144
+ }, []);
145
+ const cells = react.useMemo(() => Array.from({ length }, (_, i) => {
146
+ var _value$i;
147
+ return (_value$i = value[i]) !== null && _value$i !== void 0 ? _value$i : "";
148
+ }), [length, value]);
149
+ const setCell = react.useCallback((index, char) => {
150
+ const arr = Array.from({ length }, (_, i) => {
151
+ var _value$i2;
152
+ return (_value$i2 = value[i]) !== null && _value$i2 !== void 0 ? _value$i2 : "";
153
+ });
154
+ arr[index] = char;
155
+ setValue(arr.join(""));
156
+ }, [
157
+ length,
158
+ value,
159
+ setValue
160
+ ]);
161
+ const handleChange = react.useCallback((index) => (e) => {
162
+ var _chars;
163
+ const raw = e.target.value;
164
+ const chars = raw.split("").filter((c) => pattern.test(c));
165
+ const char = (_chars = chars[chars.length - 1]) !== null && _chars !== void 0 ? _chars : "";
166
+ if (char === "" && raw !== "") return;
167
+ setCell(index, char);
168
+ if (char) focusCell(index + 1);
169
+ }, [
170
+ pattern,
171
+ setCell,
172
+ focusCell
173
+ ]);
174
+ const handleKeyDown = react.useCallback((index) => (e) => {
175
+ switch (e.key) {
176
+ case "Backspace":
177
+ e.preventDefault();
178
+ if (cells[index]) setCell(index, "");
179
+ else if (index > 0) {
180
+ setCell(index - 1, "");
181
+ focusCell(index - 1);
182
+ }
183
+ break;
184
+ case "ArrowLeft":
185
+ e.preventDefault();
186
+ focusCell(index - 1);
187
+ break;
188
+ case "ArrowRight":
189
+ e.preventDefault();
190
+ focusCell(index + 1);
191
+ break;
192
+ default: break;
193
+ }
194
+ }, [
195
+ cells,
196
+ setCell,
197
+ focusCell
198
+ ]);
199
+ const handlePaste = react.useCallback((index) => (e) => {
200
+ e.preventDefault();
201
+ const pasted = e.clipboardData.getData("text").split("").filter((c) => pattern.test(c)).join("");
202
+ if (!pasted) return;
203
+ const arr = Array.from({ length }, (_, i) => {
204
+ var _value$i3;
205
+ return (_value$i3 = value[i]) !== null && _value$i3 !== void 0 ? _value$i3 : "";
206
+ });
207
+ for (let i = 0; i < pasted.length && index + i < length; i++) arr[index + i] = pasted[i];
208
+ setValue(arr.join(""));
209
+ focusCell(index + pasted.length);
210
+ }, [
211
+ pattern,
212
+ length,
213
+ value,
214
+ setValue,
215
+ focusCell
216
+ ]);
217
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
218
+ className: require_pagination.cn("flex flex-col gap-1.5", className),
219
+ "data-opt-id": "0083Q",
220
+ "data-opt-slug": "otp-field.OtpField",
221
+ children: [
222
+ label && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
223
+ className: "text-sm font-medium text-text-primary",
224
+ id: labelId,
225
+ children: [label, required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.RequiredMark, {})]
226
+ }),
227
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
228
+ role: "group",
229
+ "aria-label": groupAriaLabel,
230
+ "aria-labelledby": groupLabelledBy,
231
+ "aria-describedby": require_pagination.getDescribedBy(fieldId, error, hint),
232
+ className: "gap-element flex items-center",
233
+ children: cells.map((cell, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
234
+ ref: (node) => {
235
+ inputsRef.current[i] = node;
236
+ },
237
+ type: mask ? "password" : "text",
238
+ inputMode: type === "numeric" ? "numeric" : "text",
239
+ autoComplete: i === 0 ? "one-time-code" : "off",
240
+ autoFocus: autoFocus && i === 0,
241
+ maxLength: 1,
242
+ disabled,
243
+ "aria-label": `${i + 1}번째 자리`,
244
+ "aria-invalid": hasError || void 0,
245
+ value: cell,
246
+ onChange: handleChange(i),
247
+ onKeyDown: handleKeyDown(i),
248
+ onPaste: handlePaste(i),
249
+ onFocus: (e) => e.target.select(),
250
+ className: require_pagination.cn(require_pagination.OPT_INPUT, "h-12 w-10 text-center text-lg font-medium", hasError && "border-danger focus-visible:outline-danger")
251
+ }, i))
252
+ }),
253
+ name && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
254
+ type: "hidden",
255
+ name,
256
+ value,
257
+ disabled
258
+ }),
259
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.FieldMessages, {
260
+ id: fieldId,
261
+ error,
262
+ hint
263
+ })
264
+ ]
265
+ });
266
+ }
267
+ OtpField.displayName = "OtpField";
268
+ //#endregion
269
+ //#region src/core/toggle.tsx
270
+ const _excluded$16 = [
271
+ "size",
272
+ "className",
273
+ "children"
274
+ ];
275
+ const _excluded2$8 = [
276
+ "className",
277
+ "children",
278
+ "orientation"
279
+ ];
280
+ const sizeStyles$5 = {
281
+ sm: "h-8 min-w-8 px-2 text-xs gap-1.5",
282
+ md: "h-10 min-w-10 px-3 text-sm gap-2"
283
+ };
284
+ const toggleBase = require_pagination.cn("inline-flex cursor-pointer items-center justify-center rounded-md border border-border bg-surface font-medium text-text-secondary", "hover:bg-bg-subtle hover:text-text-primary", "data-[pressed]:border-accent data-[pressed]:bg-accent-subtle data-[pressed]:text-accent", "disabled:pointer-events-none disabled:opacity-40", require_pagination.OPT_FOCUS_VISIBLE);
285
+ /** A two-state (pressed) button. Use standalone or inside `ToggleGroup`. */
286
+ function Toggle(_ref) {
287
+ let { size = "md", className, children } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$16);
288
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.Toggle, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn(toggleBase, sizeStyles$5[size], className) }, props), {}, {
289
+ "data-opt-id": "GFCMY",
290
+ "data-opt-slug": "toggle.Toggle",
291
+ children
292
+ }));
293
+ }
294
+ Toggle.displayName = "Toggle";
295
+ /** A set of related toggles with shared selection and keyboard navigation. */
296
+ function ToggleGroup(_ref2) {
297
+ let { className, children, orientation = "horizontal" } = _ref2, props = require_pagination._objectWithoutProperties(_ref2, _excluded2$8);
298
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.ToggleGroup, require_pagination._objectSpread2(require_pagination._objectSpread2({
299
+ orientation,
300
+ "aria-orientation": orientation,
301
+ className: require_pagination.cn("inline-flex gap-1", orientation === "vertical" ? "flex-col" : "flex-row", className)
302
+ }, props), {}, {
303
+ "data-opt-id": "47J37",
304
+ "data-opt-slug": "toggle.ToggleGroup",
305
+ children
306
+ }));
307
+ }
308
+ ToggleGroup.displayName = "ToggleGroup";
309
+ //#endregion
310
+ //#region src/core/accordion.tsx
311
+ const _excluded$15 = ["className"];
312
+ const _excluded2$7 = ["className"];
313
+ const _excluded3$4 = ["className", "children"];
314
+ const _excluded4$3 = ["className", "children"];
315
+ const triggerClass = `group/acc-trigger flex w-full cursor-pointer items-center justify-between gap-2 py-4 text-left text-sm font-medium text-text-primary transition-colors hover:text-text-secondary ${require_pagination.OPT_FOCUS} disabled:cursor-not-allowed disabled:opacity-50`;
316
+ const contentClass = `overflow-hidden text-sm text-text-secondary ${require_pagination.OPT_ANIMATE_ENTER_EXIT}`;
317
+ /** A vertically stacked set of expandable panels (single or multiple open). */
318
+ function AccordionRoot(_ref) {
319
+ let { className } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$15);
320
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
321
+ className: require_pagination.cn("border-border border-y", className),
322
+ "data-opt-id": "CSBA9",
323
+ "data-opt-slug": "accordion.AccordionRoot",
324
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.AccordionRoot, require_pagination._objectSpread2({}, props))
325
+ });
326
+ }
327
+ AccordionRoot.displayName = "AccordionRoot";
328
+ /** A single accordion entry, identified by its `value`. */
329
+ function AccordionItem(_ref2) {
330
+ let { className } = _ref2, props = require_pagination._objectWithoutProperties(_ref2, _excluded2$7);
331
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.AccordionItem, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("border-border border-b last:border-b-0", className) }, props), {}, {
332
+ "data-opt-id": "JTY9M",
333
+ "data-opt-slug": "accordion.AccordionItem"
334
+ }));
335
+ }
336
+ AccordionItem.displayName = "AccordionItem";
337
+ /** The clickable header that expands/collapses its panel. */
338
+ function AccordionTrigger(_ref3) {
339
+ let { className, children } = _ref3, props = require_pagination._objectWithoutProperties(_ref3, _excluded3$4);
340
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_reopt_ai_opt_ui_primitives.AccordionTrigger, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn(triggerClass, className) }, props), {}, {
341
+ "data-opt-id": "CWJZZ",
342
+ "data-opt-slug": "accordion.AccordionTrigger",
343
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
344
+ className: "flex-1",
345
+ children
346
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronDown, {
347
+ "aria-hidden": "true",
348
+ className: "text-text-tertiary h-4 w-4 shrink-0 transition-transform duration-200 group-data-[state=open]/acc-trigger:rotate-180"
349
+ })]
350
+ }));
351
+ }
352
+ AccordionTrigger.displayName = "AccordionTrigger";
353
+ /** The collapsible panel body associated with a trigger. */
354
+ function AccordionContent(_ref4) {
355
+ let { className, children } = _ref4, props = require_pagination._objectWithoutProperties(_ref4, _excluded4$3);
356
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.AccordionContent, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn(contentClass, className) }, props), {}, {
357
+ "data-opt-id": "J98AG",
358
+ "data-opt-slug": "accordion.AccordionContent",
359
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
360
+ className: "pb-4",
361
+ children
362
+ })
363
+ }));
364
+ }
365
+ AccordionContent.displayName = "AccordionContent";
366
+ //#endregion
367
+ //#region src/core/breadcrumb.tsx
368
+ function interpolate(template, values) {
369
+ return template.replace(/\{(\w+)\}/g, (_, key) => key in values ? String(values[key]) : `{${key}}`);
370
+ }
371
+ /** Renders the breadcrumb component. */
372
+ function Breadcrumb({ items, separator = "/", className, onNavigate, "aria-label": ariaLabel = "Breadcrumb" }) {
373
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
374
+ "aria-label": ariaLabel,
375
+ className: require_pagination.cn("flex items-center gap-1 px-1.5 text-sm", className),
376
+ "data-opt-id": "3FR0Y",
377
+ "data-opt-slug": "breadcrumb.Breadcrumb",
378
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ol", {
379
+ className: "flex items-center gap-1",
380
+ children: items.map((item, index) => {
381
+ const isLast = index === items.length - 1;
382
+ const linkClassName = require_pagination.cn(`flex items-center gap-1.5 rounded-sm ${require_pagination.OPT_FOCUS} transition-colors`, item.disabled ? `${require_pagination.OPT_TEXT_TERTIARY} cursor-not-allowed` : `${require_pagination.OPT_TEXT_SECONDARY} hover:text-text-primary cursor-pointer`);
383
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
384
+ className: "flex items-center gap-1",
385
+ children: isLast ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
386
+ "aria-current": "page",
387
+ className: `flex items-center gap-1.5 font-medium ${require_pagination.OPT_TEXT_PRIMARY}`,
388
+ children: [item.icon, item.label]
389
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [item.href ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
390
+ href: item.disabled ? void 0 : item.href,
391
+ "aria-disabled": item.disabled || void 0,
392
+ className: linkClassName,
393
+ onClick: () => !item.disabled && (onNavigate === null || onNavigate === void 0 ? void 0 : onNavigate(item)),
394
+ children: [item.icon, item.label]
395
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
396
+ type: "button",
397
+ disabled: item.disabled,
398
+ "aria-label": interpolate(require_pagination.koBreadcrumbLabels.navAriaLabel, { label: item.label }),
399
+ className: linkClassName,
400
+ onClick: () => !item.disabled && (onNavigate === null || onNavigate === void 0 ? void 0 : onNavigate(item)),
401
+ children: [item.icon, item.label]
402
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
403
+ "aria-hidden": "true",
404
+ className: require_pagination.OPT_TEXT_TERTIARY,
405
+ children: separator
406
+ })] })
407
+ }, item.id);
408
+ })
409
+ })
410
+ });
411
+ }
412
+ //#endregion
413
+ //#region src/core/card.tsx
414
+ const _excluded$14 = [
415
+ "variant",
416
+ "padding",
417
+ "shadow",
418
+ "selectable",
419
+ "selected",
420
+ "onSelectedChange",
421
+ "className",
422
+ "children",
423
+ "onClick",
424
+ "onKeyDown",
425
+ "role",
426
+ "tabIndex"
427
+ ];
428
+ const _excluded2$6 = [
429
+ "gap",
430
+ "className",
431
+ "children"
432
+ ];
433
+ const _excluded3$3 = [
434
+ "as",
435
+ "className",
436
+ "children"
437
+ ];
438
+ const _excluded4$2 = ["className", "children"];
439
+ const _excluded5 = [
440
+ "spacing",
441
+ "className",
442
+ "children"
443
+ ];
444
+ const _excluded6 = [
445
+ "divider",
446
+ "className",
447
+ "children"
448
+ ];
449
+ /** Renders the card component. */
450
+ function Card(_ref) {
451
+ let { variant = "default", padding = "md", shadow = true, selectable = false, selected = false, onSelectedChange, className, children, onClick, onKeyDown, role, tabIndex } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$14);
452
+ const isInteractive = selectable || !!onClick;
453
+ const handleClick = selectable ? (e) => {
454
+ onSelectedChange === null || onSelectedChange === void 0 || onSelectedChange(!selected);
455
+ onClick === null || onClick === void 0 || onClick(e);
456
+ } : onClick;
457
+ const handleKeyDown = selectable ? (e) => {
458
+ if (e.key === "Enter" || e.key === " ") {
459
+ e.preventDefault();
460
+ onSelectedChange === null || onSelectedChange === void 0 || onSelectedChange(!selected);
461
+ }
462
+ onKeyDown === null || onKeyDown === void 0 || onKeyDown(e);
463
+ } : isInteractive ? (e) => {
464
+ if (e.key === "Enter" || e.key === " ") {
465
+ e.preventDefault();
466
+ e.currentTarget.click();
467
+ }
468
+ onKeyDown === null || onKeyDown === void 0 || onKeyDown(e);
469
+ } : onKeyDown;
470
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", require_pagination._objectSpread2(require_pagination._objectSpread2(require_pagination._objectSpread2({}, props), {}, { className: require_pagination.cn("rounded-xl", variant === "default" && require_pagination.cn(`border border-border bg-surface`, shadow && "shadow-sm"), variant === "outline" && "border-border border-2 bg-transparent", variant === "ghost" && "bg-bg-subtle", padding === "none" && "p-0", padding === "sm" && "p-3", padding === "md" && "p-5", padding === "lg" && "p-8", selectable && "cursor-pointer transition-colors", selectable && selected && "ring-accent border-accent ring-2 ring-offset-1", selectable && !selected && "hover:border-accent/50", className) }, isInteractive ? {
471
+ role: selectable ? "option" : "button",
472
+ tabIndex: 0,
473
+ "aria-selected": selectable ? selected : void 0,
474
+ onClick: handleClick,
475
+ onKeyDown: handleKeyDown
476
+ } : {
477
+ role,
478
+ tabIndex,
479
+ "aria-selected": selectable ? selected : void 0,
480
+ onKeyDown
481
+ }), {}, {
482
+ "data-opt-id": "0A18R",
483
+ "data-opt-slug": "card.Card",
484
+ children
485
+ }));
486
+ }
487
+ const headerGapClasses = {
488
+ sm: "gap-1",
489
+ md: "gap-1.5",
490
+ lg: "gap-2"
491
+ };
492
+ /** Renders the card header component. */
493
+ function CardHeader(_ref2) {
494
+ let { gap = "sm", className, children } = _ref2, props = require_pagination._objectWithoutProperties(_ref2, _excluded2$6);
495
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("flex flex-col", headerGapClasses[gap], className) }, props), {}, {
496
+ "data-opt-id": "JST3J",
497
+ "data-opt-slug": "card.CardHeader",
498
+ children
499
+ }));
500
+ }
501
+ /** Renders the card title component. */
502
+ function CardTitle(_ref3) {
503
+ let { as: Tag = "h3", className, children } = _ref3, props = require_pagination._objectWithoutProperties(_ref3, _excluded3$3);
504
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn(`text-lg font-semibold ${require_pagination.OPT_TEXT_PRIMARY}`, className) }, props), {}, {
505
+ "data-opt-id": "V15TX",
506
+ "data-opt-slug": "card.CardTitle",
507
+ children
508
+ }));
509
+ }
510
+ /** Renders the card description component. */
511
+ function CardDescription(_ref4) {
512
+ let { className, children } = _ref4, props = require_pagination._objectWithoutProperties(_ref4, _excluded4$2);
513
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn(`text-sm ${require_pagination.OPT_TEXT_SECONDARY}`, className) }, props), {}, {
514
+ "data-opt-id": "YB1RN",
515
+ "data-opt-slug": "card.CardDescription",
516
+ children
517
+ }));
518
+ }
519
+ const contentSpacingClasses = {
520
+ none: "",
521
+ sm: "mt-2",
522
+ md: "mt-4",
523
+ lg: "mt-6"
524
+ };
525
+ /** Renders the card content component. */
526
+ function CardContent(_ref5) {
527
+ let { spacing = "md", className, children } = _ref5, props = require_pagination._objectWithoutProperties(_ref5, _excluded5);
528
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn(contentSpacingClasses[spacing], className) }, props), {}, {
529
+ "data-opt-id": "9Y68R",
530
+ "data-opt-slug": "card.CardContent",
531
+ children
532
+ }));
533
+ }
534
+ /** Renders the card footer component. */
535
+ function CardFooter(_ref6) {
536
+ let { divider = true, className, children } = _ref6, props = require_pagination._objectWithoutProperties(_ref6, _excluded6);
537
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("mt-4 flex items-center justify-end gap-2 pt-4", divider && `border-t border border-border`, className) }, props), {}, {
538
+ "data-opt-id": "GRNTR",
539
+ "data-opt-slug": "card.CardFooter",
540
+ children
541
+ }));
542
+ }
543
+ //#endregion
544
+ //#region src/core/input.tsx
545
+ const _excluded$13 = [
546
+ "label",
547
+ "error",
548
+ "hint",
549
+ "leftIcon",
550
+ "rightIcon",
551
+ "fullWidth",
552
+ "size",
553
+ "required",
554
+ "className",
555
+ "id"
556
+ ];
557
+ const inputSizeStyles = require_pagination.OPT_INPUT_SIZE;
558
+ const Input = (0, react.forwardRef)((_ref, ref) => {
559
+ var _useInputId;
560
+ let { label, error, hint, leftIcon, rightIcon, fullWidth = false, size = "md", required, className, id } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$13);
561
+ const fallbackId = (0, react.useId)().replace(/:/g, "");
562
+ const inputId = (_useInputId = require_pagination.useInputId(id, label, "input")) !== null && _useInputId !== void 0 ? _useInputId : `input-${fallbackId}`;
563
+ const hasError = Boolean(error);
564
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
565
+ className: require_pagination.cn("flex flex-col gap-1.5", fullWidth && "w-full"),
566
+ "data-opt-id": "7BY1Q",
567
+ "data-opt-slug": "input.Input",
568
+ children: [
569
+ label && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
570
+ htmlFor: inputId,
571
+ className: "text-text-primary text-sm font-medium",
572
+ children: [label, required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.RequiredMark, {})]
573
+ }),
574
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
575
+ className: "relative",
576
+ children: [
577
+ leftIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
578
+ className: "text-text-tertiary pointer-events-none absolute top-1/2 left-3 -translate-y-1/2",
579
+ children: leftIcon
580
+ }),
581
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", require_pagination._objectSpread2({
582
+ ref,
583
+ id: inputId,
584
+ className: require_pagination.cn(require_pagination.OPT_INPUT, inputSizeStyles[size], leftIcon && (size === "sm" ? "pl-8" : "pl-10"), rightIcon && (size === "sm" ? "pr-8" : "pr-10"), hasError && "border-danger focus-visible:outline-danger", !fullWidth && "w-auto", className),
585
+ "aria-invalid": hasError,
586
+ "aria-required": required,
587
+ "aria-describedby": require_pagination.getDescribedBy(inputId, error, hint),
588
+ required
589
+ }, props)),
590
+ rightIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
591
+ className: "text-text-tertiary pointer-events-none absolute top-1/2 right-3 -translate-y-1/2",
592
+ children: rightIcon
593
+ })
594
+ ]
595
+ }),
596
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.FieldMessages, {
597
+ id: inputId,
598
+ error,
599
+ hint
600
+ })
601
+ ]
602
+ });
603
+ });
604
+ Input.displayName = "Input";
605
+ //#endregion
606
+ //#region src/core/switch.tsx
607
+ const _excluded$12 = [
608
+ "label",
609
+ "required",
610
+ "error",
611
+ "hint",
612
+ "description",
613
+ "checked",
614
+ "defaultChecked",
615
+ "onChange",
616
+ "size",
617
+ "disabled",
618
+ "className",
619
+ "id",
620
+ "onClick",
621
+ "aria-label",
622
+ "aria-labelledby"
623
+ ];
624
+ const sizeStyles$4 = {
625
+ sm: {
626
+ track: "h-5 w-9",
627
+ thumb: "h-4 w-4",
628
+ translate: "translate-x-4"
629
+ },
630
+ md: {
631
+ track: "h-6 w-11",
632
+ thumb: "h-5 w-5",
633
+ translate: "translate-x-5"
634
+ },
635
+ lg: {
636
+ track: "h-7 w-14",
637
+ thumb: "h-6 w-6",
638
+ translate: "translate-x-7"
639
+ }
640
+ };
641
+ const Switch = (0, react.forwardRef)((_ref, ref) => {
642
+ var _useInputId;
643
+ let { label, required, error, hint, description, checked: controlledChecked, defaultChecked = false, onChange, size = "md", disabled, className, id, onClick, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$12);
644
+ const fallbackId = (0, react.useId)();
645
+ const switchId = (_useInputId = require_pagination.useInputId(id, label, "switch")) !== null && _useInputId !== void 0 ? _useInputId : `switch-${fallbackId}`;
646
+ const hintText = hint !== null && hint !== void 0 ? hint : description;
647
+ const hasError = Boolean(error);
648
+ const styles = sizeStyles$4[size];
649
+ const labelId = label ? `${switchId}-label` : void 0;
650
+ const switchLabelledBy = ariaLabelledBy !== null && ariaLabelledBy !== void 0 ? ariaLabelledBy : ariaLabel ? void 0 : labelId;
651
+ const switchAriaLabel = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : switchLabelledBy ? void 0 : "Switch";
652
+ const isControlled = controlledChecked !== void 0;
653
+ const [internalChecked, setInternalChecked] = (0, react.useState)(defaultChecked);
654
+ const checked = isControlled ? controlledChecked : internalChecked;
655
+ const handleClick = (0, react.useCallback)((e) => {
656
+ const next = !checked;
657
+ if (!isControlled) setInternalChecked(next);
658
+ onChange === null || onChange === void 0 || onChange(next);
659
+ onClick === null || onClick === void 0 || onClick(e);
660
+ }, [
661
+ checked,
662
+ isControlled,
663
+ onChange,
664
+ onClick
665
+ ]);
666
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
667
+ className: require_pagination.cn("flex flex-col gap-1.5", className),
668
+ "data-opt-id": "51Z9R",
669
+ "data-opt-slug": "switch.Switch",
670
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
671
+ className: "flex items-start gap-3",
672
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", require_pagination._objectSpread2(require_pagination._objectSpread2({
673
+ ref,
674
+ type: "button",
675
+ role: "switch",
676
+ id: switchId,
677
+ "aria-checked": checked,
678
+ "aria-label": switchAriaLabel,
679
+ "aria-labelledby": switchLabelledBy,
680
+ disabled,
681
+ className: require_pagination.cn("group relative inline-flex shrink-0 cursor-pointer rounded-full p-0.5 transition-colors", styles.track, "bg-bg-muted", "aria-[checked=true]:bg-accent", "disabled:cursor-not-allowed disabled:opacity-50", require_pagination.OPT_FOCUS_VISIBLE),
682
+ "aria-invalid": hasError,
683
+ "aria-required": required,
684
+ "aria-describedby": require_pagination.getDescribedBy(switchId, error, hintText),
685
+ onClick: handleClick
686
+ }, props), {}, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: require_pagination.cn("pointer-events-none inline-block transform rounded-full bg-white shadow-sm ring-0 transition-transform", styles.thumb, "translate-x-0", size === "sm" && "group-aria-[checked=true]:translate-x-4", size === "md" && "group-aria-[checked=true]:translate-x-5", size === "lg" && "group-aria-[checked=true]:translate-x-7") }) })), (label || hintText) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
687
+ className: "flex flex-col",
688
+ children: [label && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
689
+ id: labelId,
690
+ className: require_pagination.cn("text-text-primary text-sm font-medium", disabled && "opacity-50"),
691
+ children: [label, required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.RequiredMark, {})]
692
+ }), hintText && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
693
+ id: `${switchId}-hint`,
694
+ className: require_pagination.cn("text-text-tertiary text-sm", disabled && "opacity-50"),
695
+ children: hintText
696
+ })]
697
+ })]
698
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.FieldMessages, {
699
+ id: switchId,
700
+ error
701
+ })]
702
+ });
703
+ });
704
+ Switch.displayName = "Switch";
705
+ //#endregion
706
+ //#region src/core/skeleton.tsx
707
+ const _excluded$11 = [
708
+ "variant",
709
+ "width",
710
+ "height",
711
+ "lines",
712
+ "animated",
713
+ "className",
714
+ "style"
715
+ ];
716
+ const _excluded2$5 = ["lines", "className"];
717
+ const _excluded3$2 = ["size", "className"];
718
+ const _excluded4$1 = ["className"];
719
+ const variantStyles$2 = {
720
+ text: "rounded h-4",
721
+ circular: "rounded-full",
722
+ rectangular: "rounded-lg"
723
+ };
724
+ /** Renders the skeleton component. */
725
+ function Skeleton(_ref) {
726
+ let { variant = "text", width, height, lines = 1, animated = true, className, style } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$11);
727
+ const baseClass = require_pagination.cn("bg-bg-subtle", animated && "animate-pulse", variantStyles$2[variant], className);
728
+ const computedStyle = require_pagination._objectSpread2({
729
+ width: typeof width === "number" ? `${width}px` : width,
730
+ height: typeof height === "number" ? `${height}px` : height
731
+ }, style);
732
+ if (variant === "text" && lines > 1) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
733
+ className: "gap-element flex flex-col",
734
+ role: "status",
735
+ "aria-label": "Loading",
736
+ "data-opt-id": "EJT87",
737
+ "data-opt-slug": "skeleton.Skeleton",
738
+ children: [Array.from({ length: lines }).map((_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", require_pagination._objectSpread2({
739
+ className: require_pagination.cn(baseClass, i === lines - 1 && "w-4/5"),
740
+ style: i === lines - 1 ? void 0 : computedStyle
741
+ }, props), i)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
742
+ className: "sr-only",
743
+ children: "Loading..."
744
+ })]
745
+ });
746
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", require_pagination._objectSpread2(require_pagination._objectSpread2({
747
+ className: baseClass,
748
+ style: computedStyle,
749
+ role: "status",
750
+ "aria-label": "Loading"
751
+ }, props), {}, {
752
+ "data-opt-id": "EJT87",
753
+ "data-opt-slug": "skeleton.Skeleton",
754
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
755
+ className: "sr-only",
756
+ children: "Loading..."
757
+ })
758
+ }));
759
+ }
760
+ /** Renders the skeleton text component. */
761
+ function SkeletonText(_ref2) {
762
+ let { lines = 3, className } = _ref2, props = require_pagination._objectWithoutProperties(_ref2, _excluded2$5);
763
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, require_pagination._objectSpread2(require_pagination._objectSpread2({
764
+ variant: "text",
765
+ lines,
766
+ className
767
+ }, props), {}, {
768
+ "data-opt-id": "MX3D5",
769
+ "data-opt-slug": "skeleton.SkeletonText"
770
+ }));
771
+ }
772
+ /** Renders the skeleton avatar component. */
773
+ function SkeletonAvatar(_ref3) {
774
+ let { size = 40, className } = _ref3, props = require_pagination._objectWithoutProperties(_ref3, _excluded3$2);
775
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, require_pagination._objectSpread2(require_pagination._objectSpread2({
776
+ variant: "circular",
777
+ width: size,
778
+ height: size,
779
+ className
780
+ }, props), {}, {
781
+ "data-opt-id": "MP0HZ",
782
+ "data-opt-slug": "skeleton.SkeletonAvatar"
783
+ }));
784
+ }
785
+ /** Renders the skeleton card component. */
786
+ function SkeletonCard(_ref4) {
787
+ let { className } = _ref4, props = require_pagination._objectWithoutProperties(_ref4, _excluded4$1);
788
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("gap-group flex flex-col", className) }, props), {}, {
789
+ "data-opt-id": "34V5D",
790
+ "data-opt-slug": "skeleton.SkeletonCard",
791
+ children: [
792
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, {
793
+ variant: "rectangular",
794
+ height: 120
795
+ }),
796
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, {
797
+ variant: "text",
798
+ width: "60%"
799
+ }),
800
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, {
801
+ variant: "text",
802
+ lines: 2
803
+ })
804
+ ]
805
+ }));
806
+ }
807
+ /** Renders the skeleton table component. */
808
+ function SkeletonTable({ rows = 5, columns = 4, className }) {
809
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
810
+ className: require_pagination.cn("gap-element flex flex-col", className),
811
+ role: "status",
812
+ "aria-label": "Loading table",
813
+ "data-opt-id": "3KEDN",
814
+ "data-opt-slug": "skeleton.SkeletonTable",
815
+ children: [
816
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
817
+ className: "border-border-subtle gap-group flex border-b pb-2",
818
+ children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, {
819
+ variant: "text",
820
+ className: "flex-1",
821
+ height: 16
822
+ }, i))
823
+ }),
824
+ Array.from({ length: rows }).map((_, rowIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
825
+ className: "gap-group flex py-2",
826
+ children: Array.from({ length: columns }).map((_, colIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, {
827
+ variant: "text",
828
+ className: "flex-1",
829
+ height: 14
830
+ }, colIndex))
831
+ }, rowIndex)),
832
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
833
+ className: "sr-only",
834
+ children: "Loading..."
835
+ })
836
+ ]
837
+ });
838
+ }
839
+ //#endregion
840
+ //#region src/core/textarea.tsx
841
+ const _excluded$10 = [
842
+ "label",
843
+ "error",
844
+ "hint",
845
+ "fullWidth",
846
+ "required",
847
+ "resize",
848
+ "size",
849
+ "className",
850
+ "id",
851
+ "rows"
852
+ ];
853
+ const textareaSizeStyles = require_pagination.OPT_TEXTAREA_SIZE;
854
+ const resizeStyles = {
855
+ none: "resize-none",
856
+ vertical: "resize-y",
857
+ horizontal: "resize-x",
858
+ both: "resize"
859
+ };
860
+ const Textarea = (0, react.forwardRef)((_ref, ref) => {
861
+ var _useInputId;
862
+ let { label, error, hint, fullWidth = false, required, resize = "vertical", size = "md", className, id, rows = 4 } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$10);
863
+ const fallbackId = (0, react.useId)().replace(/:/g, "");
864
+ const textareaId = (_useInputId = require_pagination.useInputId(id, label, "textarea")) !== null && _useInputId !== void 0 ? _useInputId : `textarea-${fallbackId}`;
865
+ const hasError = Boolean(error);
866
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
867
+ className: require_pagination.cn("flex flex-col gap-1.5", fullWidth && "w-full"),
868
+ "data-opt-id": "6T58H",
869
+ "data-opt-slug": "textarea.Textarea",
870
+ children: [
871
+ label && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
872
+ htmlFor: textareaId,
873
+ className: "text-text-primary text-sm font-medium",
874
+ children: [label, required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.RequiredMark, {})]
875
+ }),
876
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", require_pagination._objectSpread2({
877
+ ref,
878
+ id: textareaId,
879
+ rows,
880
+ className: require_pagination.cn("border-border bg-surface text-text-primary placeholder:text-text-tertiary w-full rounded-lg border px-4 py-3 text-sm outline-transparent", require_pagination.OPT_FOCUS_VISIBLE, textareaSizeStyles[size], resizeStyles[resize], hasError && "border-danger focus-visible:outline-danger", !fullWidth && "w-auto", className),
881
+ "aria-invalid": hasError,
882
+ "aria-describedby": require_pagination.getDescribedBy(textareaId, error, hint)
883
+ }, props)),
884
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.FieldMessages, {
885
+ id: textareaId,
886
+ error,
887
+ hint
888
+ })
889
+ ]
890
+ });
891
+ });
892
+ Textarea.displayName = "Textarea";
893
+ //#endregion
894
+ //#region src/core/avatar.tsx
895
+ const _excluded$9 = [
896
+ "src",
897
+ "srcSet",
898
+ "sizes",
899
+ "crossOrigin",
900
+ "referrerPolicy",
901
+ "alt",
902
+ "name",
903
+ "size",
904
+ "fallback",
905
+ "status",
906
+ "className",
907
+ "onLoadingStatusChange"
908
+ ];
909
+ const _excluded2$4 = [
910
+ "max",
911
+ "size",
912
+ "children",
913
+ "className"
914
+ ];
915
+ const useIsoLayoutEffect = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
916
+ /**
917
+ * Tracks an image's loading status by preloading it off-DOM, so the avatar can
918
+ * show its fallback until the image is actually decoded (no broken-image flash)
919
+ * and recover from late `error`/`load` events. Supports responsive `srcSet`/`sizes`.
920
+ */
921
+ function useImageLoadingStatus(src, { srcSet, sizes, crossOrigin, referrerPolicy }) {
922
+ const [status, setStatus] = (0, react.useState)("idle");
923
+ useIsoLayoutEffect(() => {
924
+ if (!src && !srcSet) {
925
+ setStatus("error");
926
+ return;
927
+ }
928
+ let isMounted = true;
929
+ const image = new window.Image();
930
+ const update = (next) => () => {
931
+ if (isMounted) setStatus(next);
932
+ };
933
+ setStatus("loading");
934
+ image.onload = update("loaded");
935
+ image.onerror = update("error");
936
+ if (referrerPolicy) image.referrerPolicy = referrerPolicy;
937
+ image.crossOrigin = crossOrigin !== null && crossOrigin !== void 0 ? crossOrigin : null;
938
+ if (sizes) image.sizes = sizes;
939
+ if (srcSet) image.srcset = srcSet;
940
+ if (src) image.src = src;
941
+ if (image.complete) setStatus(image.naturalWidth > 0 ? "loaded" : "error");
942
+ return () => {
943
+ isMounted = false;
944
+ };
945
+ }, [
946
+ src,
947
+ srcSet,
948
+ sizes,
949
+ crossOrigin,
950
+ referrerPolicy
951
+ ]);
952
+ return status;
953
+ }
954
+ const sizeStyles$3 = {
955
+ xs: "h-6 w-6 text-[10px]",
956
+ sm: "h-8 w-8 text-xs",
957
+ md: "h-10 w-10 text-sm",
958
+ lg: "h-12 w-12 text-base",
959
+ xl: "h-16 w-16 text-lg"
960
+ };
961
+ const statusStyles = {
962
+ online: "bg-success",
963
+ offline: "bg-bg-muted",
964
+ busy: "bg-danger",
965
+ away: "bg-warning"
966
+ };
967
+ const statusSizeStyles = {
968
+ xs: "h-1.5 w-1.5 border",
969
+ sm: "h-2 w-2 border",
970
+ md: "h-2.5 w-2.5 border-2",
971
+ lg: "h-3 w-3 border-2",
972
+ xl: "h-4 w-4 border-2"
973
+ };
974
+ function getInitials(name) {
975
+ const parts = name.trim().split(/\s+/);
976
+ if (parts.length === 1) return parts[0].charAt(0).toUpperCase();
977
+ return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
978
+ }
979
+ const bgColors = [
980
+ "bg-blue-500",
981
+ "bg-emerald-500",
982
+ "bg-amber-500",
983
+ "bg-rose-500",
984
+ "bg-purple-500",
985
+ "bg-cyan-500",
986
+ "bg-orange-500",
987
+ "bg-indigo-500"
988
+ ];
989
+ function getColorFromName(name) {
990
+ let hash = 0;
991
+ for (let i = 0; i < name.length; i++) hash = name.charCodeAt(i) + ((hash << 5) - hash);
992
+ return bgColors[Math.abs(hash) % bgColors.length];
993
+ }
994
+ /** Renders the avatar component. */
995
+ function Avatar(_ref) {
996
+ var _ref2, _ref3;
997
+ let { src, srcSet, sizes, crossOrigin, referrerPolicy, alt, name, size = "md", fallback, status, className, onLoadingStatusChange } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$9);
998
+ const loadingStatus = useImageLoadingStatus(src, {
999
+ srcSet,
1000
+ sizes,
1001
+ crossOrigin,
1002
+ referrerPolicy
1003
+ });
1004
+ (0, react.useEffect)(() => {
1005
+ onLoadingStatusChange === null || onLoadingStatusChange === void 0 || onLoadingStatusChange(loadingStatus);
1006
+ }, [loadingStatus, onLoadingStatusChange]);
1007
+ const showImage = (Boolean(src) || Boolean(srcSet)) && loadingStatus === "loaded";
1008
+ const initials = name ? getInitials(name) : null;
1009
+ const bgColor = name ? getColorFromName(name) : "bg-bg-subtle";
1010
+ const avatarLabel = status ? `${(_ref2 = name !== null && name !== void 0 ? name : alt) !== null && _ref2 !== void 0 ? _ref2 : "Avatar"} (${status})` : (_ref3 = name !== null && name !== void 0 ? name : alt) !== null && _ref3 !== void 0 ? _ref3 : "Avatar";
1011
+ let avatarContent;
1012
+ if (showImage) {
1013
+ var _ref4;
1014
+ avatarContent = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1015
+ src,
1016
+ srcSet,
1017
+ sizes,
1018
+ crossOrigin,
1019
+ referrerPolicy,
1020
+ alt: (_ref4 = alt !== null && alt !== void 0 ? alt : name) !== null && _ref4 !== void 0 ? _ref4 : "Avatar",
1021
+ className: "h-full w-full object-cover"
1022
+ });
1023
+ } else if (fallback) avatarContent = fallback;
1024
+ else if (initials) avatarContent = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1025
+ className: "font-medium text-white",
1026
+ children: initials
1027
+ });
1028
+ else avatarContent = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1029
+ className: "text-text-tertiary h-3/5 w-3/5",
1030
+ fill: "currentColor",
1031
+ viewBox: "0 0 24 24",
1032
+ "aria-hidden": "true",
1033
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" })
1034
+ });
1035
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", require_pagination._objectSpread2(require_pagination._objectSpread2({
1036
+ role: "img",
1037
+ "aria-label": avatarLabel,
1038
+ className: require_pagination.cn("relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full", sizeStyles$3[size], !showImage && bgColor, className)
1039
+ }, props), {}, {
1040
+ "data-opt-id": "SCMM0",
1041
+ "data-opt-slug": "avatar.Avatar",
1042
+ children: [avatarContent, status && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1043
+ className: require_pagination.cn("border-surface absolute right-0 bottom-0 rounded-full", statusStyles[status], statusSizeStyles[size]),
1044
+ "aria-hidden": "true"
1045
+ })]
1046
+ }));
1047
+ }
1048
+ /** Renders the avatar group component. */
1049
+ function AvatarGroup(_ref5) {
1050
+ let { max = 4, size = "md", children, className } = _ref5, props = require_pagination._objectWithoutProperties(_ref5, _excluded2$4);
1051
+ const avatars = Array.isArray(children) ? children : [children];
1052
+ const visibleAvatars = avatars.slice(0, max);
1053
+ const remainingCount = avatars.length - max;
1054
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("flex", className) }, props), {}, {
1055
+ "data-opt-id": "MVB53",
1056
+ "data-opt-slug": "avatar.AvatarGroup",
1057
+ children: [visibleAvatars.map((child, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1058
+ className: "ring-surface relative -ml-2 inline-block rounded-full ring-2 first:ml-0",
1059
+ children: child
1060
+ }, index)), remainingCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1061
+ className: require_pagination.cn("bg-bg-subtle text-text-secondary ring-surface relative inline-flex items-center justify-center rounded-full font-medium ring-2", sizeStyles$3[size]),
1062
+ children: ["+", remainingCount]
1063
+ })]
1064
+ }));
1065
+ }
1066
+ //#endregion
1067
+ //#region src/core/progress.tsx
1068
+ const _excluded$8 = [
1069
+ "value",
1070
+ "max",
1071
+ "size",
1072
+ "variant",
1073
+ "showLabel",
1074
+ "label",
1075
+ "animated",
1076
+ "indeterminate",
1077
+ "className"
1078
+ ];
1079
+ const _excluded2$3 = [
1080
+ "value",
1081
+ "max",
1082
+ "size",
1083
+ "strokeWidth",
1084
+ "variant",
1085
+ "showLabel",
1086
+ "label",
1087
+ "indeterminate",
1088
+ "className"
1089
+ ];
1090
+ const sizeStyles$2 = {
1091
+ sm: "h-1",
1092
+ md: "h-2",
1093
+ lg: "h-3"
1094
+ };
1095
+ const variantStyles$1 = {
1096
+ default: "bg-accent",
1097
+ success: "bg-success",
1098
+ warning: "bg-warning",
1099
+ error: "bg-danger"
1100
+ };
1101
+ function getProgressValue(value, max) {
1102
+ const safeMax = Number.isFinite(max) ? Math.max(0, max) : 100;
1103
+ const clampedValue = safeMax > 0 ? Math.min(Math.max(Number.isFinite(value) ? value : 0, 0), safeMax) : 0;
1104
+ const percentage = safeMax > 0 ? clampedValue / safeMax * 100 : 0;
1105
+ return {
1106
+ clampedValue,
1107
+ max: safeMax,
1108
+ percentage,
1109
+ valueText: `${Math.round(percentage)}%`
1110
+ };
1111
+ }
1112
+ /** Renders the progress component. */
1113
+ function Progress(_ref) {
1114
+ let { value, max = 100, size = "md", variant = "default", showLabel = false, label, animated = true, indeterminate = false, className } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$8);
1115
+ const progress = indeterminate || value === void 0 ? null : getProgressValue(value, max);
1116
+ const shouldRenderHeader = Boolean(label) || showLabel && progress;
1117
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("w-full", className) }, props), {}, {
1118
+ "data-opt-id": "Y5N8R",
1119
+ "data-opt-slug": "progress.Progress",
1120
+ children: [shouldRenderHeader && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1121
+ className: "mb-1.5 flex items-center justify-between text-sm",
1122
+ children: [label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1123
+ className: "text-text-primary font-medium",
1124
+ children: label
1125
+ }), showLabel && progress && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1126
+ className: "text-text-tertiary",
1127
+ children: progress.valueText
1128
+ })]
1129
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1130
+ className: require_pagination.cn("bg-bg-subtle w-full overflow-hidden rounded-full", sizeStyles$2[size]),
1131
+ role: "progressbar",
1132
+ "aria-valuenow": progress === null || progress === void 0 ? void 0 : progress.clampedValue,
1133
+ "aria-valuemin": progress ? 0 : void 0,
1134
+ "aria-valuemax": progress === null || progress === void 0 ? void 0 : progress.max,
1135
+ "aria-valuetext": progress === null || progress === void 0 ? void 0 : progress.valueText,
1136
+ "aria-label": label !== null && label !== void 0 ? label : progress ? `${progress.valueText} complete` : "Loading",
1137
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1138
+ className: require_pagination.cn("h-full rounded-full", variantStyles$1[variant], !progress && "w-1/3 animate-pulse", animated && (progress ? "transition-all duration-300 ease-out" : "transition-opacity duration-700 ease-in-out")),
1139
+ style: progress ? { width: `${progress.percentage}%` } : void 0
1140
+ })
1141
+ })]
1142
+ }));
1143
+ }
1144
+ const circularVariantStyles = {
1145
+ default: "text-accent",
1146
+ success: "text-success",
1147
+ warning: "text-warning",
1148
+ error: "text-danger"
1149
+ };
1150
+ /** Renders the circular progress component. */
1151
+ function CircularProgress(_ref2) {
1152
+ var _progress$percentage;
1153
+ let { value, max = 100, size = 48, strokeWidth = 4, variant = "default", showLabel = false, label, indeterminate = false, className } = _ref2, props = require_pagination._objectWithoutProperties(_ref2, _excluded2$3);
1154
+ const labelId = (0, react.useId)();
1155
+ const isIndeterminate = indeterminate || value === void 0;
1156
+ const progress = isIndeterminate ? null : getProgressValue(value, max);
1157
+ const accessibleName = label !== null && label !== void 0 ? label : progress ? `${progress.valueText} complete` : "Loading";
1158
+ const radius = (size - strokeWidth) / 2;
1159
+ const circumference = radius * 2 * Math.PI;
1160
+ const strokeDashoffset = circumference - ((_progress$percentage = progress === null || progress === void 0 ? void 0 : progress.percentage) !== null && _progress$percentage !== void 0 ? _progress$percentage : 0) / 100 * circumference;
1161
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1162
+ className: "relative inline-flex items-center justify-center",
1163
+ "data-opt-id": "Q69KP",
1164
+ "data-opt-slug": "progress.CircularProgress",
1165
+ children: [
1166
+ label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1167
+ id: labelId,
1168
+ className: "sr-only",
1169
+ children: label
1170
+ }),
1171
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", require_pagination._objectSpread2(require_pagination._objectSpread2({
1172
+ width: size,
1173
+ height: size,
1174
+ className: require_pagination.cn(isIndeterminate ? "animate-spin" : "-rotate-90", className),
1175
+ role: isIndeterminate ? "progressbar" : "meter",
1176
+ "aria-labelledby": label ? labelId : void 0,
1177
+ "aria-valuenow": progress === null || progress === void 0 ? void 0 : progress.clampedValue,
1178
+ "aria-valuemin": progress ? 0 : void 0,
1179
+ "aria-valuemax": progress === null || progress === void 0 ? void 0 : progress.max,
1180
+ "aria-valuetext": progress === null || progress === void 0 ? void 0 : progress.valueText,
1181
+ "aria-label": label ? void 0 : accessibleName
1182
+ }, props), {}, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
1183
+ cx: size / 2,
1184
+ cy: size / 2,
1185
+ r: radius,
1186
+ fill: "none",
1187
+ strokeWidth,
1188
+ className: "stroke-border-subtle"
1189
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
1190
+ cx: size / 2,
1191
+ cy: size / 2,
1192
+ r: radius,
1193
+ fill: "none",
1194
+ strokeWidth,
1195
+ strokeLinecap: "round",
1196
+ className: require_pagination.cn("transition-all duration-300 ease-out", circularVariantStyles[variant]),
1197
+ style: {
1198
+ strokeDasharray: isIndeterminate ? `${circumference * .28} ${circumference}` : circumference,
1199
+ strokeDashoffset: isIndeterminate ? 0 : strokeDashoffset,
1200
+ stroke: "currentColor"
1201
+ }
1202
+ })] })),
1203
+ showLabel && progress && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1204
+ className: "text-text-primary absolute text-xs font-medium",
1205
+ children: progress.valueText
1206
+ })
1207
+ ]
1208
+ });
1209
+ }
1210
+ //#endregion
1211
+ //#region src/core/meter.tsx
1212
+ const _excluded$7 = [
1213
+ "value",
1214
+ "min",
1215
+ "max",
1216
+ "size",
1217
+ "variant",
1218
+ "showValue",
1219
+ "label",
1220
+ "getValueLabel",
1221
+ "className"
1222
+ ];
1223
+ const sizeStyles$1 = {
1224
+ sm: "h-1",
1225
+ md: "h-2",
1226
+ lg: "h-3"
1227
+ };
1228
+ const variantStyles = {
1229
+ default: "bg-accent",
1230
+ success: "bg-success",
1231
+ warning: "bg-warning",
1232
+ error: "bg-danger"
1233
+ };
1234
+ /**
1235
+ * A scalar measurement within a known range (disk usage, score, capacity) —
1236
+ * `role="meter"`, distinct from Progress (task completion). Built on the
1237
+ * opt-ui-primitives Meter primitive, which owns the role/aria/valuetext.
1238
+ */
1239
+ function Meter(_ref) {
1240
+ let { value, min = 0, max = 100, size = "md", variant = "default", showValue = false, label, getValueLabel, className } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$7);
1241
+ const clamped = Math.min(Math.max(value, min), max);
1242
+ const percentage = max === min ? 0 : (clamped - min) / (max - min) * 100;
1243
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("w-full", className) }, props), {}, {
1244
+ "data-opt-id": "G01TE",
1245
+ "data-opt-slug": "meter.Meter",
1246
+ children: [(showValue || label) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1247
+ className: "mb-1.5 flex items-center justify-between text-sm",
1248
+ children: [label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1249
+ className: "text-text-primary font-medium",
1250
+ children: label
1251
+ }), showValue && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1252
+ className: "text-text-tertiary",
1253
+ children: [Math.round(percentage), "%"]
1254
+ })]
1255
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.Meter, {
1256
+ value: clamped,
1257
+ min,
1258
+ max,
1259
+ getValueLabel,
1260
+ "aria-label": label !== null && label !== void 0 ? label : `${Math.round(percentage)}%`,
1261
+ className: require_pagination.cn("bg-bg-subtle w-full overflow-hidden rounded-full", sizeStyles$1[size]),
1262
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1263
+ className: require_pagination.cn("h-full rounded-full transition-all duration-300 ease-out", variantStyles[variant]),
1264
+ style: { width: `${percentage}%` }
1265
+ })
1266
+ })]
1267
+ }));
1268
+ }
1269
+ //#endregion
1270
+ //#region src/core/step-builder.tsx
1271
+ /** Renders the step builder component. */
1272
+ function StepBuilder({ steps, onChange, label, addLabel = "Add step", maxSteps, className, "aria-label": ariaLabel }) {
1273
+ var _ref;
1274
+ const [editingId, setEditingId] = (0, react.useState)(null);
1275
+ const nextStepIdRef = (0, react.useRef)(1);
1276
+ const createStepId = (0, react.useCallback)(() => {
1277
+ const existingIds = new Set(steps.map((step) => step.id));
1278
+ let id = "";
1279
+ do
1280
+ id = `step-${nextStepIdRef.current++}`;
1281
+ while (existingIds.has(id));
1282
+ return id;
1283
+ }, [steps]);
1284
+ const addStep = (0, react.useCallback)(() => {
1285
+ if (maxSteps && steps.length >= maxSteps) return;
1286
+ const newStep = {
1287
+ id: createStepId(),
1288
+ label: `Step ${steps.length + 1}`
1289
+ };
1290
+ onChange([...steps, newStep]);
1291
+ setEditingId(newStep.id);
1292
+ }, [
1293
+ steps,
1294
+ onChange,
1295
+ maxSteps,
1296
+ createStepId
1297
+ ]);
1298
+ const removeStep = (0, react.useCallback)((id) => {
1299
+ onChange(steps.filter((s) => s.id !== id));
1300
+ if (editingId === id) setEditingId(null);
1301
+ }, [
1302
+ steps,
1303
+ onChange,
1304
+ editingId
1305
+ ]);
1306
+ const updateStep = (0, react.useCallback)((id, updates) => {
1307
+ onChange(steps.map((s) => s.id === id ? require_pagination._objectSpread2(require_pagination._objectSpread2({}, s), updates) : s));
1308
+ }, [steps, onChange]);
1309
+ const moveStep = (0, react.useCallback)((index, direction) => {
1310
+ const target = index + direction;
1311
+ if (target < 0 || target >= steps.length) return;
1312
+ const newSteps = [...steps];
1313
+ [newSteps[index], newSteps[target]] = [newSteps[target], newSteps[index]];
1314
+ onChange(newSteps);
1315
+ }, [steps, onChange]);
1316
+ const atLimit = Boolean(maxSteps && steps.length >= maxSteps);
1317
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1318
+ className: require_pagination.cn("flex flex-col gap-3", className),
1319
+ role: "list",
1320
+ "aria-label": (_ref = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : label) !== null && _ref !== void 0 ? _ref : "Step builder",
1321
+ "data-opt-id": "7BQDT",
1322
+ "data-opt-slug": "step-builder.StepBuilder",
1323
+ children: [
1324
+ label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1325
+ className: "text-sm font-medium text-text-primary",
1326
+ children: label
1327
+ }),
1328
+ steps.map((step, index) => {
1329
+ var _step$description;
1330
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1331
+ className: require_pagination.cn(require_pagination.OPT_SURFACE, require_pagination.OPT_BORDER, "flex items-start gap-3 p-3"),
1332
+ role: "listitem",
1333
+ children: [
1334
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1335
+ className: "bg-accent text-accent-fg flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full text-xs font-bold",
1336
+ "aria-hidden": "true",
1337
+ children: index + 1
1338
+ }),
1339
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1340
+ className: "min-w-0 flex-1",
1341
+ children: editingId === step.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1342
+ className: "flex flex-col gap-2",
1343
+ children: [
1344
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1345
+ type: "text",
1346
+ value: step.label,
1347
+ onChange: (e) => updateStep(step.id, { label: e.target.value }),
1348
+ onKeyDown: (e) => {
1349
+ if (e.key === "Enter") setEditingId(null);
1350
+ },
1351
+ className: require_pagination.cn("border-border bg-surface focus-visible:ring-ring focus-visible:ring-offset-ring-offset w-full rounded-md border px-2 py-1 text-sm outline-none focus-visible:ring-2 focus-visible:ring-offset-1", require_pagination.OPT_TEXT_PRIMARY, require_pagination.OPT_FOCUS_VISIBLE),
1352
+ "aria-label": "Step label",
1353
+ autoFocus: true
1354
+ }),
1355
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1356
+ type: "text",
1357
+ value: (_step$description = step.description) !== null && _step$description !== void 0 ? _step$description : "",
1358
+ onChange: (e) => updateStep(step.id, { description: e.target.value }),
1359
+ placeholder: "Description (optional)",
1360
+ className: require_pagination.cn("border-border bg-surface focus-visible:ring-ring focus-visible:ring-offset-ring-offset w-full rounded-md border px-2 py-1 text-sm outline-none focus-visible:ring-2 focus-visible:ring-offset-1", require_pagination.OPT_TEXT_PRIMARY, "placeholder:text-text-tertiary", require_pagination.OPT_FOCUS_VISIBLE),
1361
+ "aria-label": "Step description"
1362
+ }),
1363
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.Button, {
1364
+ variant: "ghost",
1365
+ size: "sm",
1366
+ onClick: () => setEditingId(null),
1367
+ children: "Done"
1368
+ })
1369
+ ]
1370
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1371
+ type: "button",
1372
+ className: "w-full text-left",
1373
+ onClick: () => setEditingId(step.id),
1374
+ "aria-label": `Edit ${step.label}`,
1375
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1376
+ className: require_pagination.cn(require_pagination.OPT_TEXT_PRIMARY, "text-sm font-medium"),
1377
+ children: step.label
1378
+ }), step.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1379
+ className: require_pagination.cn("text-text-secondary", "mt-0.5 block text-xs"),
1380
+ children: step.description
1381
+ })]
1382
+ })
1383
+ }),
1384
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1385
+ className: "flex flex-shrink-0 items-center gap-1",
1386
+ children: [
1387
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1388
+ type: "button",
1389
+ onClick: () => moveStep(index, -1),
1390
+ disabled: index === 0,
1391
+ className: require_pagination.cn("rounded p-1 text-sm", require_pagination.OPT_TEXT_TERTIARY, "hover:bg-bg-subtle", "disabled:opacity-30", require_pagination.OPT_FOCUS_VISIBLE),
1392
+ "aria-label": "Move up",
1393
+ children: "▲"
1394
+ }),
1395
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1396
+ type: "button",
1397
+ onClick: () => moveStep(index, 1),
1398
+ disabled: index === steps.length - 1,
1399
+ className: require_pagination.cn("rounded p-1 text-sm", require_pagination.OPT_TEXT_TERTIARY, "hover:bg-bg-subtle", "disabled:opacity-30", require_pagination.OPT_FOCUS_VISIBLE),
1400
+ "aria-label": "Move down",
1401
+ children: "▼"
1402
+ }),
1403
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1404
+ type: "button",
1405
+ onClick: () => removeStep(step.id),
1406
+ className: require_pagination.cn("text-danger-fg hover:bg-danger-subtle rounded p-1 text-sm", require_pagination.OPT_FOCUS_VISIBLE),
1407
+ "aria-label": `Remove ${step.label}`,
1408
+ children: "✕"
1409
+ })
1410
+ ]
1411
+ })
1412
+ ]
1413
+ }, step.id);
1414
+ }),
1415
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_pagination.Button, {
1416
+ variant: "secondary",
1417
+ size: "sm",
1418
+ onClick: addStep,
1419
+ disabled: atLimit,
1420
+ className: "self-start",
1421
+ children: ["+ ", addLabel]
1422
+ })
1423
+ ]
1424
+ });
1425
+ }
1426
+ StepBuilder.displayName = "StepBuilder";
1427
+ //#endregion
1428
+ //#region src/lib/formatters.ts
1429
+ const OPT_UI_DEFAULT_LOCALE = "ko-KR";
1430
+ const KST_OFFSET_MS = 540 * 60 * 1e3;
1431
+ function getKstDateParts(input) {
1432
+ const date = input instanceof Date ? input : new Date(input);
1433
+ if (Number.isNaN(date.getTime())) return null;
1434
+ const kstDate = new Date(date.getTime() + KST_OFFSET_MS);
1435
+ return {
1436
+ year: kstDate.getUTCFullYear(),
1437
+ month: kstDate.getUTCMonth() + 1,
1438
+ day: kstDate.getUTCDate(),
1439
+ hour: kstDate.getUTCHours(),
1440
+ minute: kstDate.getUTCMinutes(),
1441
+ second: kstDate.getUTCSeconds()
1442
+ };
1443
+ }
1444
+ function pad2(value) {
1445
+ return String(value).padStart(2, "0");
1446
+ }
1447
+ function meridiem(hour) {
1448
+ return hour < 12 ? "오전" : "오후";
1449
+ }
1450
+ function hour12(hour) {
1451
+ const normalized = hour % 12;
1452
+ return normalized === 0 ? 12 : normalized;
1453
+ }
1454
+ /** Formats a date as Korean short date text in the opt-ui default timezone. */
1455
+ function formatOptShortDate(input) {
1456
+ const parts = getKstDateParts(input);
1457
+ if (!parts) return "-";
1458
+ return `${parts.month}월 ${parts.day}일`;
1459
+ }
1460
+ /** Formats a date as Korean clock time in the opt-ui default timezone. */
1461
+ function formatOptTime(input) {
1462
+ const parts = getKstDateParts(input);
1463
+ if (!parts) return "-";
1464
+ return `${meridiem(parts.hour)} ${pad2(hour12(parts.hour))}:${pad2(parts.minute)}`;
1465
+ }
1466
+ /** Formats a date as Korean date-time text in the opt-ui default timezone. */
1467
+ function formatOptDateTime(input) {
1468
+ const parts = getKstDateParts(input);
1469
+ if (!parts) return "-";
1470
+ return `${parts.year}. ${parts.month}. ${parts.day}. ${meridiem(parts.hour)} ${hour12(parts.hour)}:${pad2(parts.minute)}:${pad2(parts.second)}`;
1471
+ }
1472
+ /** Formats numbers without depending on the runtime default locale. */
1473
+ function formatOptNumber(value) {
1474
+ return new Intl.NumberFormat(OPT_UI_DEFAULT_LOCALE).format(value);
1475
+ }
1476
+ //#endregion
1477
+ //#region src/core/condition-builder.tsx
1478
+ const OPERATOR_LABELS = {
1479
+ equals: "equals",
1480
+ not_equals: "does not equal",
1481
+ contains: "contains",
1482
+ not_contains: "does not contain",
1483
+ gt: ">",
1484
+ lt: "<",
1485
+ gte: ">=",
1486
+ lte: "<=",
1487
+ is_set: "is set",
1488
+ is_not_set: "is not set"
1489
+ };
1490
+ const OPERATORS = /* @__PURE__ */ new Set([
1491
+ "equals",
1492
+ "not_equals",
1493
+ "contains",
1494
+ "not_contains",
1495
+ "gt",
1496
+ "lt",
1497
+ "gte",
1498
+ "lte",
1499
+ "is_set",
1500
+ "is_not_set"
1501
+ ]);
1502
+ function isConditionOperator(v) {
1503
+ return OPERATORS.has(v);
1504
+ }
1505
+ const NO_VALUE_OPS = ["is_set", "is_not_set"];
1506
+ const DEFAULT_PROPERTIES = [
1507
+ "event_name",
1508
+ "user_id",
1509
+ "email",
1510
+ "country",
1511
+ "browser",
1512
+ "os",
1513
+ "device",
1514
+ "page_url",
1515
+ "referrer",
1516
+ "amount"
1517
+ ];
1518
+ const ConditionBuilderIdScopeContext = react.createContext(null);
1519
+ function collectConditionBuilderIds(groups) {
1520
+ const groupIds = /* @__PURE__ */ new Set();
1521
+ const conditionIds = /* @__PURE__ */ new Set();
1522
+ const visit = (items) => {
1523
+ for (const group of items) {
1524
+ groupIds.add(group.id);
1525
+ for (const condition of group.conditions) conditionIds.add(condition.id);
1526
+ if (group.children) visit(group.children);
1527
+ }
1528
+ };
1529
+ visit(groups);
1530
+ return {
1531
+ groupIds,
1532
+ conditionIds
1533
+ };
1534
+ }
1535
+ /** Renders the condition builder component. */
1536
+ function ConditionBuilder({ groups, onChange, properties = DEFAULT_PROPERTIES, label, addConditionLabel = "Add condition", addGroupLabel = "Add group", addNestedGroupLabel = "Add nested group", nested = false, maxDepth = 3, conditionTypes, onPreview, previewCount, className, "aria-label": ariaLabel }) {
1537
+ var _ref;
1538
+ const inheritedIdScope = react.useContext(ConditionBuilderIdScopeContext);
1539
+ const nextGroupIdRef = react.useRef(1);
1540
+ const nextConditionIdRef = react.useRef(1);
1541
+ const getLocalReservedIds = (0, react.useCallback)(() => collectConditionBuilderIds(groups), [groups]);
1542
+ const localIdScope = react.useMemo(() => ({
1543
+ nextGroupIdRef,
1544
+ nextConditionIdRef,
1545
+ getReservedIds: getLocalReservedIds
1546
+ }), [getLocalReservedIds]);
1547
+ const idScope = inheritedIdScope !== null && inheritedIdScope !== void 0 ? inheritedIdScope : localIdScope;
1548
+ const createGroupId = (0, react.useCallback)((suffix = "") => {
1549
+ const { groupIds } = idScope.getReservedIds();
1550
+ let id = "";
1551
+ do
1552
+ id = `group-${idScope.nextGroupIdRef.current++}${suffix}`;
1553
+ while (groupIds.has(id));
1554
+ return id;
1555
+ }, [idScope]);
1556
+ const createConditionId = (0, react.useCallback)((suffix = "") => {
1557
+ const { conditionIds } = idScope.getReservedIds();
1558
+ let id = "";
1559
+ do
1560
+ id = `cond-${idScope.nextConditionIdRef.current++}${suffix}`;
1561
+ while (conditionIds.has(id));
1562
+ return id;
1563
+ }, [idScope]);
1564
+ (0, react.useEffect)(() => {
1565
+ onPreview === null || onPreview === void 0 || onPreview(groups);
1566
+ }, [groups, onPreview]);
1567
+ const addGroup = (0, react.useCallback)(() => {
1568
+ var _properties$;
1569
+ const newGroup = {
1570
+ id: createGroupId(),
1571
+ logic: "and",
1572
+ conditions: [{
1573
+ id: createConditionId(),
1574
+ property: (_properties$ = properties[0]) !== null && _properties$ !== void 0 ? _properties$ : "",
1575
+ operator: "equals",
1576
+ value: ""
1577
+ }]
1578
+ };
1579
+ onChange([...groups, newGroup]);
1580
+ }, [
1581
+ groups,
1582
+ onChange,
1583
+ properties,
1584
+ createGroupId,
1585
+ createConditionId
1586
+ ]);
1587
+ const removeGroup = (0, react.useCallback)((groupId) => {
1588
+ onChange(groups.filter((g) => g.id !== groupId));
1589
+ }, [groups, onChange]);
1590
+ const updateGroupLogic = (0, react.useCallback)((groupId, logic) => {
1591
+ onChange(groups.map((g) => g.id === groupId ? require_pagination._objectSpread2(require_pagination._objectSpread2({}, g), {}, { logic }) : g));
1592
+ }, [groups, onChange]);
1593
+ const addCondition = (0, react.useCallback)((groupId) => {
1594
+ onChange(groups.map((g) => {
1595
+ var _properties$2;
1596
+ return g.id === groupId ? require_pagination._objectSpread2(require_pagination._objectSpread2({}, g), {}, { conditions: [...g.conditions, {
1597
+ id: createConditionId(),
1598
+ property: (_properties$2 = properties[0]) !== null && _properties$2 !== void 0 ? _properties$2 : "",
1599
+ operator: "equals",
1600
+ value: ""
1601
+ }] }) : g;
1602
+ }));
1603
+ }, [
1604
+ groups,
1605
+ onChange,
1606
+ properties,
1607
+ createConditionId
1608
+ ]);
1609
+ const removeCondition = (0, react.useCallback)((groupId, condId) => {
1610
+ onChange(groups.map((g) => g.id === groupId ? require_pagination._objectSpread2(require_pagination._objectSpread2({}, g), {}, { conditions: g.conditions.filter((c) => c.id !== condId) }) : g));
1611
+ }, [groups, onChange]);
1612
+ const updateCondition = (0, react.useCallback)((groupId, condId, updates) => {
1613
+ onChange(groups.map((g) => g.id === groupId ? require_pagination._objectSpread2(require_pagination._objectSpread2({}, g), {}, { conditions: g.conditions.map((c) => c.id === condId ? require_pagination._objectSpread2(require_pagination._objectSpread2({}, c), updates) : c) }) : g));
1614
+ }, [groups, onChange]);
1615
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConditionBuilderIdScopeContext.Provider, {
1616
+ value: idScope,
1617
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1618
+ className: require_pagination.cn("flex flex-col gap-3", className),
1619
+ "aria-label": (_ref = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : label) !== null && _ref !== void 0 ? _ref : "Condition builder",
1620
+ "data-opt-id": "SXXKJ",
1621
+ "data-opt-slug": "condition-builder.ConditionBuilder",
1622
+ children: [
1623
+ label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1624
+ className: "text-sm font-medium text-text-primary",
1625
+ children: label
1626
+ }),
1627
+ groups.map((group, groupIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [groupIndex > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1628
+ className: "my-2 flex items-center gap-2",
1629
+ children: [
1630
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-border-subtle h-px flex-1" }),
1631
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1632
+ className: "text-warning-fg text-xs font-semibold uppercase",
1633
+ children: "OR"
1634
+ }),
1635
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-border-subtle h-px flex-1" })
1636
+ ]
1637
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1638
+ className: require_pagination.cn(require_pagination.OPT_SURFACE, require_pagination.OPT_BORDER, "p-3"),
1639
+ role: "group",
1640
+ "aria-label": `Condition group ${groupIndex + 1}`,
1641
+ children: [
1642
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1643
+ className: "mb-2 flex items-center justify-between",
1644
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1645
+ className: "flex items-center gap-2",
1646
+ children: [
1647
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1648
+ className: require_pagination.cn(require_pagination.OPT_TEXT_SECONDARY, "text-xs font-medium"),
1649
+ children: "Match"
1650
+ }),
1651
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
1652
+ value: group.logic,
1653
+ onChange: (e) => {
1654
+ const v = e.target.value;
1655
+ if (v === "and" || v === "or") updateGroupLogic(group.id, v);
1656
+ },
1657
+ className: require_pagination.cn("border-border bg-surface focus-visible:ring-ring focus-visible:ring-offset-ring-offset rounded border px-2 py-0.5 text-xs font-semibold outline-none focus-visible:ring-2 focus-visible:ring-offset-1", require_pagination.OPT_TEXT_PRIMARY, require_pagination.OPT_FOCUS_VISIBLE),
1658
+ "aria-label": "Group logic",
1659
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1660
+ value: "and",
1661
+ children: "ALL"
1662
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1663
+ value: "or",
1664
+ children: "ANY"
1665
+ })]
1666
+ }),
1667
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1668
+ className: require_pagination.cn(require_pagination.OPT_TEXT_SECONDARY, "text-xs"),
1669
+ children: "of the following"
1670
+ })
1671
+ ]
1672
+ }), groups.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1673
+ type: "button",
1674
+ onClick: () => removeGroup(group.id),
1675
+ className: require_pagination.cn("text-danger-fg hover:bg-danger-subtle rounded p-1 text-xs", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset"),
1676
+ "aria-label": "Remove group",
1677
+ children: "✕"
1678
+ })]
1679
+ }),
1680
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1681
+ className: "flex flex-col gap-2",
1682
+ children: group.conditions.map((cond, condIndex) => {
1683
+ const customRenderer = cond.type != null ? conditionTypes === null || conditionTypes === void 0 ? void 0 : conditionTypes[cond.type] : void 0;
1684
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1685
+ className: "flex items-center gap-2",
1686
+ children: [
1687
+ condIndex > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1688
+ className: require_pagination.cn("w-8 text-center text-[10px] font-semibold uppercase", group.logic === "and" ? "text-info-fg" : "text-warning-fg"),
1689
+ children: group.logic
1690
+ }),
1691
+ condIndex === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "w-8" }),
1692
+ customRenderer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1693
+ className: "min-w-[100px] flex-1",
1694
+ role: "group",
1695
+ "aria-label": customRenderer.label,
1696
+ children: customRenderer.render(cond, (updates) => updateCondition(group.id, cond.id, updates))
1697
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1698
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
1699
+ value: cond.property,
1700
+ onChange: (e) => updateCondition(group.id, cond.id, { property: e.target.value }),
1701
+ className: require_pagination.cn("border-border bg-surface focus-visible:ring-ring focus-visible:ring-offset-ring-offset min-w-[120px] rounded border px-2 py-1.5 text-sm outline-none focus-visible:ring-2 focus-visible:ring-offset-1", require_pagination.OPT_TEXT_PRIMARY, require_pagination.OPT_FOCUS_VISIBLE),
1702
+ "aria-label": "Property",
1703
+ children: properties.map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1704
+ value: p,
1705
+ children: p
1706
+ }, p))
1707
+ }),
1708
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
1709
+ value: cond.operator,
1710
+ onChange: (e) => {
1711
+ const v = e.target.value;
1712
+ if (isConditionOperator(v)) updateCondition(group.id, cond.id, { operator: v });
1713
+ },
1714
+ className: require_pagination.cn("border-border bg-surface focus-visible:ring-ring focus-visible:ring-offset-ring-offset min-w-[130px] rounded border px-2 py-1.5 text-sm outline-none focus-visible:ring-2 focus-visible:ring-offset-1", require_pagination.OPT_TEXT_PRIMARY, require_pagination.OPT_FOCUS_VISIBLE),
1715
+ "aria-label": "Operator",
1716
+ children: Object.entries(OPERATOR_LABELS).map(([key, lbl]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1717
+ value: key,
1718
+ children: lbl
1719
+ }, key))
1720
+ }),
1721
+ !NO_VALUE_OPS.includes(cond.operator) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1722
+ type: "text",
1723
+ value: cond.value,
1724
+ onChange: (e) => updateCondition(group.id, cond.id, { value: e.target.value }),
1725
+ placeholder: "Value",
1726
+ className: require_pagination.cn("border-border bg-surface focus-visible:ring-ring focus-visible:ring-offset-ring-offset min-w-[100px] flex-1 rounded border px-2 py-1.5 text-sm outline-none focus-visible:ring-2 focus-visible:ring-offset-1", "text-text-primary", "placeholder:text-text-tertiary", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset"),
1727
+ "aria-label": "Value"
1728
+ })
1729
+ ] }),
1730
+ group.conditions.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1731
+ type: "button",
1732
+ onClick: () => removeCondition(group.id, cond.id),
1733
+ className: require_pagination.cn("text-danger-fg hover:bg-danger-subtle rounded p-1 text-sm", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset"),
1734
+ "aria-label": "Remove condition",
1735
+ children: "✕"
1736
+ })
1737
+ ]
1738
+ }, cond.id);
1739
+ })
1740
+ }),
1741
+ nested && group.children && group.children.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1742
+ className: "border-accent/30 mt-2 ml-4 border-l-2 pl-3",
1743
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConditionBuilder, {
1744
+ groups: group.children,
1745
+ onChange: (newChildren) => {
1746
+ onChange(groups.map((g) => g.id === group.id ? require_pagination._objectSpread2(require_pagination._objectSpread2({}, g), {}, { children: newChildren }) : g));
1747
+ },
1748
+ properties,
1749
+ addConditionLabel,
1750
+ addGroupLabel,
1751
+ addNestedGroupLabel,
1752
+ nested,
1753
+ maxDepth: maxDepth - 1,
1754
+ conditionTypes
1755
+ })
1756
+ }),
1757
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1758
+ className: "mt-2 flex items-center gap-2",
1759
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_pagination.Button, {
1760
+ variant: "ghost",
1761
+ size: "sm",
1762
+ onClick: () => addCondition(group.id),
1763
+ children: ["+ ", addConditionLabel]
1764
+ }), nested && maxDepth > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_pagination.Button, {
1765
+ variant: "ghost",
1766
+ size: "sm",
1767
+ onClick: () => {
1768
+ var _properties$3;
1769
+ const nestedGroup = {
1770
+ id: createGroupId("-nested"),
1771
+ logic: group.logic === "and" ? "or" : "and",
1772
+ conditions: [{
1773
+ id: createConditionId("-nested"),
1774
+ property: (_properties$3 = properties[0]) !== null && _properties$3 !== void 0 ? _properties$3 : "",
1775
+ operator: "equals",
1776
+ value: ""
1777
+ }]
1778
+ };
1779
+ onChange(groups.map((g) => {
1780
+ var _g$children;
1781
+ return g.id === group.id ? require_pagination._objectSpread2(require_pagination._objectSpread2({}, g), {}, { children: [...(_g$children = g.children) !== null && _g$children !== void 0 ? _g$children : [], nestedGroup] }) : g;
1782
+ }));
1783
+ },
1784
+ children: ["+ ", addNestedGroupLabel]
1785
+ })]
1786
+ })
1787
+ ]
1788
+ })] }, group.id)),
1789
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1790
+ className: "flex items-center gap-3",
1791
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_pagination.Button, {
1792
+ variant: "secondary",
1793
+ size: "sm",
1794
+ onClick: addGroup,
1795
+ className: "self-start",
1796
+ children: ["+ ", addGroupLabel]
1797
+ }), previewCount != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1798
+ className: require_pagination.cn("text-text-secondary", "text-sm"),
1799
+ children: [formatOptNumber(previewCount), " matches"]
1800
+ })]
1801
+ })
1802
+ ]
1803
+ })
1804
+ });
1805
+ }
1806
+ ConditionBuilder.displayName = "ConditionBuilder";
1807
+ //#endregion
1808
+ //#region src/core/dropdown-menu.tsx
1809
+ const _excluded$6 = ["className"];
1810
+ const _excluded2$2 = ["className"];
1811
+ const _excluded3$1 = ["className", "variant"];
1812
+ const _excluded4 = ["className"];
1813
+ const DropdownMenu = require_pagination.MenuRoot;
1814
+ /** Renders the dropdown trigger component. */
1815
+ function DropdownTrigger(_ref) {
1816
+ let { className } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$6);
1817
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.MenuTrigger, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("cursor-pointer gap-2", className) }, props), {}, {
1818
+ "data-opt-id": "C4BSS",
1819
+ "data-opt-slug": "dropdown-menu.DropdownTrigger"
1820
+ }));
1821
+ }
1822
+ /** Renders the dropdown content component. */
1823
+ function DropdownContent(_ref2) {
1824
+ let { className } = _ref2, props = require_pagination._objectWithoutProperties(_ref2, _excluded2$2);
1825
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.MenuPopover, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn(className) }, props), {}, {
1826
+ "data-opt-id": "J6NF7",
1827
+ "data-opt-slug": "dropdown-menu.DropdownContent"
1828
+ }));
1829
+ }
1830
+ /** Renders the dropdown item component. */
1831
+ function DropdownItem(_ref3) {
1832
+ let { className, variant = "default" } = _ref3, props = require_pagination._objectWithoutProperties(_ref3, _excluded3$1);
1833
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.MenuItem, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("cursor-pointer data-[disabled]:cursor-not-allowed", variant === "destructive" && "text-danger-fg data-[active-item]:bg-danger-subtle data-[active-item]:text-danger-fg", className) }, props), {}, {
1834
+ "data-opt-id": "5M6GA",
1835
+ "data-opt-slug": "dropdown-menu.DropdownItem"
1836
+ }));
1837
+ }
1838
+ /** Renders the dropdown separator component. */
1839
+ function DropdownSeparator(_ref4) {
1840
+ let { className } = _ref4, props = require_pagination._objectWithoutProperties(_ref4, _excluded4);
1841
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.MenuSeparator, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn(className) }, props), {}, {
1842
+ "data-opt-id": "K9Y54",
1843
+ "data-opt-slug": "dropdown-menu.DropdownSeparator"
1844
+ }));
1845
+ }
1846
+ //#endregion
1847
+ //#region src/core/radio-group.tsx
1848
+ const _excluded$5 = [
1849
+ "label",
1850
+ "hint",
1851
+ "description",
1852
+ "value",
1853
+ "name",
1854
+ "size",
1855
+ "disabled",
1856
+ "className"
1857
+ ];
1858
+ const sizeStyles = {
1859
+ sm: {
1860
+ radio: "h-4 w-4",
1861
+ dot: "h-2 w-2",
1862
+ text: "text-sm"
1863
+ },
1864
+ md: {
1865
+ radio: "h-5 w-5",
1866
+ dot: "h-2.5 w-2.5",
1867
+ text: "text-sm"
1868
+ },
1869
+ lg: {
1870
+ radio: "h-6 w-6",
1871
+ dot: "h-3 w-3",
1872
+ text: "text-base"
1873
+ }
1874
+ };
1875
+ const RadioGroupContext = (0, react.createContext)({ size: "md" });
1876
+ /** Renders the radio group component. */
1877
+ function RadioGroup({ children, value, defaultValue = "", onChange, disabled, size = "md", error, required, className, orientation = "vertical", label, name }) {
1878
+ const ctxValue = (0, react.useMemo)(() => ({
1879
+ size,
1880
+ disabled
1881
+ }), [size, disabled]);
1882
+ const hasError = Boolean(error);
1883
+ const fallbackGroupId = (0, react.useId)().replace(/:/g, "");
1884
+ const groupId = label ? `radio-group-${label.replace(/\s+/g, "-").toLowerCase()}` : `radio-group-${fallbackGroupId}`;
1885
+ const labelId = label ? `${groupId}-label` : void 0;
1886
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RadioGroupContext.Provider, {
1887
+ value: ctxValue,
1888
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1889
+ className: require_pagination.cn("flex flex-col gap-1.5", className),
1890
+ "data-opt-id": "2F20H",
1891
+ "data-opt-slug": "radio-group.RadioGroup",
1892
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_reopt_ai_opt_ui_primitives.RadioGroupRoot, {
1893
+ value,
1894
+ defaultValue,
1895
+ onChange,
1896
+ disabled,
1897
+ orientation,
1898
+ name,
1899
+ id: groupId,
1900
+ "aria-label": label ? void 0 : "Radio group",
1901
+ "aria-labelledby": labelId,
1902
+ "aria-required": required,
1903
+ "aria-invalid": hasError,
1904
+ "aria-describedby": require_pagination.getDescribedBy(groupId, error, void 0),
1905
+ className: require_pagination.cn("flex", orientation === "vertical" ? "flex-col gap-3" : "flex-row gap-6"),
1906
+ children: [label && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1907
+ id: labelId,
1908
+ className: "text-text-secondary mb-1 text-sm font-medium",
1909
+ children: [label, required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.RequiredMark, {})]
1910
+ }), children]
1911
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.FieldMessages, {
1912
+ id: groupId,
1913
+ error
1914
+ })]
1915
+ })
1916
+ });
1917
+ }
1918
+ const Radio = (0, react.forwardRef)((_ref, ref) => {
1919
+ var _ref2;
1920
+ let { label, hint, description, value, name: _name, size: sizeProp, disabled: disabledProp, className } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$5);
1921
+ const groupContext = (0, react.useContext)(RadioGroupContext);
1922
+ const primContext = (0, _reopt_ai_opt_ui_primitives.useRadioGroupContext)();
1923
+ const size = sizeProp !== null && sizeProp !== void 0 ? sizeProp : groupContext.size;
1924
+ const disabled = (_ref2 = disabledProp !== null && disabledProp !== void 0 ? disabledProp : groupContext.disabled) !== null && _ref2 !== void 0 ? _ref2 : primContext === null || primContext === void 0 ? void 0 : primContext.disabled;
1925
+ const hintText = hint !== null && hint !== void 0 ? hint : description;
1926
+ const styles = sizeStyles[size];
1927
+ const isChecked = (primContext === null || primContext === void 0 ? void 0 : primContext.value) === value;
1928
+ const radioId = `radio-${(0, react.useId)().replace(/:/g, "")}`;
1929
+ const labelId = label ? `${radioId}-label` : void 0;
1930
+ const hintId = hintText ? `${radioId}-hint` : void 0;
1931
+ const handleChange = (0, react.useCallback)(() => {
1932
+ if (!disabled && value != null) primContext === null || primContext === void 0 || primContext.setValue(value);
1933
+ }, [
1934
+ disabled,
1935
+ value,
1936
+ primContext
1937
+ ]);
1938
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", require_pagination._objectSpread2(require_pagination._objectSpread2({
1939
+ ref,
1940
+ "aria-checked": isChecked,
1941
+ className: require_pagination.cn("group flex items-start gap-3", disabled && "cursor-not-allowed opacity-50", !disabled && "cursor-pointer", className)
1942
+ }, props), {}, {
1943
+ "data-opt-id": "HY7YG",
1944
+ "data-opt-slug": "radio-group.Radio",
1945
+ children: [
1946
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1947
+ id: radioId,
1948
+ type: "radio",
1949
+ name: primContext === null || primContext === void 0 ? void 0 : primContext.name,
1950
+ value,
1951
+ checked: isChecked,
1952
+ disabled,
1953
+ onChange: handleChange,
1954
+ "aria-label": label ? void 0 : value !== null && value !== void 0 ? value : "Radio option",
1955
+ "aria-labelledby": labelId,
1956
+ "aria-describedby": hintId,
1957
+ className: "sr-only"
1958
+ }),
1959
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1960
+ className: require_pagination.cn("relative mt-0.5 inline-flex shrink-0 items-center justify-center rounded-full", styles.radio, "border-border border-2", "bg-surface", "group-aria-checked:border-accent", "transition-colors", "group-has-[:focus-visible]:outline-ring outline-transparent group-has-[:focus-visible]:outline-2 group-has-[:focus-visible]:-outline-offset-1"),
1961
+ "aria-hidden": "true",
1962
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: require_pagination.cn(styles.dot, "bg-accent rounded-full", "scale-0 opacity-0 transition-all", "group-aria-checked:scale-100 group-aria-checked:opacity-100") })
1963
+ }),
1964
+ (label || hintText) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1965
+ className: "flex flex-col",
1966
+ children: [label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1967
+ id: labelId,
1968
+ className: require_pagination.cn("text-text-primary font-medium", styles.text),
1969
+ children: label
1970
+ }), hintText && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1971
+ id: hintId,
1972
+ className: "text-text-tertiary text-sm",
1973
+ children: hintText
1974
+ })]
1975
+ })
1976
+ ]
1977
+ }));
1978
+ });
1979
+ Radio.displayName = "Radio";
1980
+ //#endregion
1981
+ //#region src/core/loading-overlay.tsx
1982
+ const _excluded$4 = [
1983
+ "loading",
1984
+ "children",
1985
+ "label",
1986
+ "className"
1987
+ ];
1988
+ /** Renders the loading overlay component. */
1989
+ function LoadingOverlay(_ref) {
1990
+ let { loading, children, label = "Loading…", className } = _ref;
1991
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", require_pagination._objectSpread2(require_pagination._objectSpread2({
1992
+ "data-opt-id": "380ZR",
1993
+ "data-opt-slug": "loading-overlay.LoadingOverlay"
1994
+ }, require_pagination._objectWithoutProperties(_ref, _excluded$4)), {}, {
1995
+ className: require_pagination.cn("relative", className),
1996
+ children: [children, loading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1997
+ className: "bg-surface/60 absolute inset-0 z-10 flex items-center justify-center rounded-lg backdrop-blur-[1px]",
1998
+ role: "status",
1999
+ "aria-live": "polite",
2000
+ "aria-label": label,
2001
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2002
+ className: "flex flex-col items-center gap-2",
2003
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_pagination.Spinner, {
2004
+ size: "md",
2005
+ "aria-hidden": "true"
2006
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2007
+ className: "text-text-tertiary text-sm",
2008
+ children: label
2009
+ })]
2010
+ })
2011
+ })]
2012
+ }));
2013
+ }
2014
+ LoadingOverlay.displayName = "LoadingOverlay";
2015
+ //#endregion
2016
+ //#region src/core/block-layout.tsx
2017
+ const _excluded$3 = [
2018
+ "children",
2019
+ "className",
2020
+ "spacing",
2021
+ "inset",
2022
+ "loading",
2023
+ "loadingLabel"
2024
+ ];
2025
+ const spacingClass = {
2026
+ section: "gap-section",
2027
+ group: "gap-group",
2028
+ element: "gap-element",
2029
+ none: "gap-0"
2030
+ };
2031
+ const insetClass = {
2032
+ section: "p-section",
2033
+ group: "p-group",
2034
+ element: "p-element",
2035
+ none: "p-0"
2036
+ };
2037
+ /** Renders the block layout component. */
2038
+ function BlockLayout(_ref) {
2039
+ let { children, className, spacing = "section", inset, loading, loadingLabel } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$3);
2040
+ const layoutClassName = require_pagination.cn("flex flex-col", spacingClass[spacing], inset ? insetClass[inset] : void 0, className);
2041
+ if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoadingOverlay, require_pagination._objectSpread2(require_pagination._objectSpread2({
2042
+ "data-opt-id": "9D8QR",
2043
+ "data-opt-slug": "block-layout.BlockLayout"
2044
+ }, props), {}, {
2045
+ className: layoutClassName,
2046
+ loading,
2047
+ label: loadingLabel,
2048
+ children
2049
+ }));
2050
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", require_pagination._objectSpread2(require_pagination._objectSpread2({
2051
+ "data-opt-id": "9D8QR",
2052
+ "data-opt-slug": "block-layout.BlockLayout"
2053
+ }, props), {}, {
2054
+ className: layoutClassName,
2055
+ children
2056
+ }));
2057
+ }
2058
+ BlockLayout.displayName = "BlockLayout";
2059
+ //#endregion
2060
+ //#region src/core/create-block.tsx
2061
+ const _excluded$2 = ["loading", "className"];
2062
+ /**
2063
+ * Block 팩토리. BlockLayout 래핑을 구조적으로 강제합니다.
2064
+ *
2065
+ * @param name - displayName으로 사용할 컴포넌트 이름
2066
+ * @param render - 나머지 props를 받아 콘텐츠를 반환하는 렌더 함수
2067
+ * @param options - layoutClassName: BlockLayout에 전달할 추가 className
2068
+ */
2069
+ function createBlock(name, render, options) {
2070
+ const Component = (props) => {
2071
+ const { loading, className } = props, rest = require_pagination._objectWithoutProperties(props, _excluded$2);
2072
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockLayout, {
2073
+ loading,
2074
+ className: (options === null || options === void 0 ? void 0 : options.layoutClassName) ? `${options.layoutClassName}${className ? ` ${className}` : ""}` : className,
2075
+ children: render(rest)
2076
+ });
2077
+ };
2078
+ Component.displayName = name;
2079
+ return Component;
2080
+ }
2081
+ //#endregion
2082
+ //#region src/core/page-header.tsx
2083
+ /** Renders the page header component. */
2084
+ function PageHeader({ title, description, actions, className }) {
2085
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2086
+ className: require_pagination.cn("gap-group flex flex-col items-stretch sm:flex-row sm:items-center sm:justify-between", className),
2087
+ "data-opt-id": "7AK8Z",
2088
+ "data-opt-slug": "page-header.PageHeader",
2089
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2090
+ className: "gap-element flex min-w-0 flex-col",
2091
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
2092
+ className: "text-text-primary text-lg font-semibold",
2093
+ children: title
2094
+ }), description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2095
+ className: "text-text-tertiary text-sm",
2096
+ children: description
2097
+ })]
2098
+ }), actions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2099
+ className: "gap-element flex w-full shrink-0 items-center sm:w-auto",
2100
+ children: actions
2101
+ })]
2102
+ });
2103
+ }
2104
+ PageHeader.displayName = "PageHeader";
2105
+ //#endregion
2106
+ //#region src/core/scroll-area.tsx
2107
+ const overflowMap = {
2108
+ vertical: "overflow-y-auto overflow-x-hidden",
2109
+ horizontal: "overflow-x-auto overflow-y-hidden",
2110
+ both: "overflow-auto"
2111
+ };
2112
+ /** Renders the scroll area component. */
2113
+ function ScrollArea({ children, className, orientation = "vertical" }) {
2114
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2115
+ className: require_pagination.cn(overflowMap[orientation], "scrollbar-thin scrollbar-track-transparent scrollbar-thumb-border hover:scrollbar-thumb-border-hover", className),
2116
+ "data-opt-id": "A9X4K",
2117
+ "data-opt-slug": "scroll-area.ScrollArea",
2118
+ children
2119
+ });
2120
+ }
2121
+ ScrollArea.displayName = "ScrollArea";
2122
+ //#endregion
2123
+ //#region src/core/container.tsx
2124
+ const maxWidthMap = {
2125
+ sm: "max-w-screen-sm",
2126
+ md: "max-w-screen-md",
2127
+ lg: "max-w-screen-lg",
2128
+ xl: "max-w-screen-xl",
2129
+ "2xl": "max-w-screen-2xl",
2130
+ full: "max-w-full"
2131
+ };
2132
+ /** Renders the container component. */
2133
+ function Container({ children, maxWidth = "xl", center = true, className }) {
2134
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2135
+ className: require_pagination.cn(maxWidthMap[maxWidth], center && "mx-auto", "px-4", className),
2136
+ "data-opt-id": "H3G96",
2137
+ "data-opt-slug": "container.Container",
2138
+ children
2139
+ });
2140
+ }
2141
+ Container.displayName = "Container";
2142
+ //#endregion
2143
+ //#region src/core/section.tsx
2144
+ /** Renders the section component. */
2145
+ function Section({ children, title, description, className }) {
2146
+ const titleId = `${(0, react.useId)()}-title`;
2147
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2148
+ className: require_pagination.cn("gap-group flex flex-col", className),
2149
+ "aria-labelledby": title ? titleId : void 0,
2150
+ "data-opt-id": "M3QXW",
2151
+ "data-opt-slug": "section.Section",
2152
+ children: [(title || description) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2153
+ className: "gap-element flex flex-col",
2154
+ children: [title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
2155
+ id: titleId,
2156
+ className: "text-text-primary text-base font-semibold",
2157
+ children: title
2158
+ }), description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2159
+ className: "text-text-tertiary text-sm",
2160
+ children: description
2161
+ })]
2162
+ }), children]
2163
+ });
2164
+ }
2165
+ Section.displayName = "Section";
2166
+ //#endregion
2167
+ //#region src/core/resizable.tsx
2168
+ const _excluded$1 = [
2169
+ "direction",
2170
+ "children",
2171
+ "className",
2172
+ "id",
2173
+ "autoSaveId"
2174
+ ];
2175
+ const _excluded2$1 = [
2176
+ "collapsedSize",
2177
+ "defaultSize",
2178
+ "minSize",
2179
+ "maxSize",
2180
+ "children",
2181
+ "className"
2182
+ ];
2183
+ const _excluded3 = ["className", "withHandle"];
2184
+ function toPanelSize(size) {
2185
+ return typeof size === "number" ? `${size}%` : size;
2186
+ }
2187
+ /** Renders the resizable panel group component. */
2188
+ function ResizablePanelGroup(_ref) {
2189
+ let { direction, children, className, id, autoSaveId } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded$1);
2190
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_resizable_panels.Group, require_pagination._objectSpread2(require_pagination._objectSpread2({
2191
+ orientation: direction,
2192
+ id: id !== null && id !== void 0 ? id : autoSaveId,
2193
+ className: require_pagination.cn("flex h-full w-full", className)
2194
+ }, props), {}, {
2195
+ "data-opt-id": "BM5RR",
2196
+ "data-opt-slug": "resizable.ResizablePanelGroup",
2197
+ children
2198
+ }));
2199
+ }
2200
+ ResizablePanelGroup.displayName = "ResizablePanelGroup";
2201
+ /** Renders the resizable panel component. */
2202
+ function ResizablePanel(_ref2) {
2203
+ let { collapsedSize, defaultSize, minSize, maxSize, children, className } = _ref2, props = require_pagination._objectWithoutProperties(_ref2, _excluded2$1);
2204
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_resizable_panels.Panel, require_pagination._objectSpread2(require_pagination._objectSpread2({
2205
+ collapsedSize: toPanelSize(collapsedSize),
2206
+ defaultSize: toPanelSize(defaultSize),
2207
+ minSize: toPanelSize(minSize),
2208
+ maxSize: toPanelSize(maxSize),
2209
+ className: require_pagination.cn("overflow-auto", className)
2210
+ }, props), {}, {
2211
+ "data-opt-id": "88X4V",
2212
+ "data-opt-slug": "resizable.ResizablePanel",
2213
+ children
2214
+ }));
2215
+ }
2216
+ ResizablePanel.displayName = "ResizablePanel";
2217
+ /** Renders the resizable handle component. */
2218
+ function ResizableHandle(_ref3) {
2219
+ let { className, withHandle = false } = _ref3, props = require_pagination._objectWithoutProperties(_ref3, _excluded3);
2220
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_resizable_panels.Separator, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("bg-border relative flex items-center justify-center", "after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2", "data-[resize-handle-active]:bg-accent", "[&[data-orientation=vertical]]:h-px [&[data-orientation=vertical]]:w-full", "[&[data-orientation=horizontal]]:h-full [&[data-orientation=horizontal]]:w-px", className) }, props), {}, {
2221
+ "data-opt-id": "6Z22W",
2222
+ "data-opt-slug": "resizable.ResizableHandle",
2223
+ children: withHandle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2224
+ className: "border-border bg-surface z-10 flex h-4 w-3 items-center justify-center rounded-sm border",
2225
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.GripVertical, {
2226
+ "aria-hidden": "true",
2227
+ className: "text-text-tertiary h-3 w-3"
2228
+ })
2229
+ })
2230
+ }));
2231
+ }
2232
+ ResizableHandle.displayName = "ResizableHandle";
2233
+ //#endregion
2234
+ //#region src/core/logo.tsx
2235
+ const markSizeStyles = {
2236
+ sm: "h-6 w-6",
2237
+ md: "h-8 w-8",
2238
+ lg: "h-10 w-10"
2239
+ };
2240
+ const textSizeStyles = {
2241
+ sm: "text-sm",
2242
+ md: "text-base",
2243
+ lg: "text-lg"
2244
+ };
2245
+ /** Renders the logo component. */
2246
+ function Logo({ src, icon, text, alt = "Logo", size = "md", href, onClick, className }) {
2247
+ const [imageError, setImageError] = (0, react.useState)(false);
2248
+ const showImage = src && !imageError;
2249
+ const fallbackLetter = text ? text.charAt(0).toUpperCase() : null;
2250
+ let mark = null;
2251
+ if (showImage) mark = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
2252
+ src,
2253
+ alt,
2254
+ className: require_pagination.cn("object-contain", markSizeStyles[size]),
2255
+ onError: () => setImageError(true)
2256
+ });
2257
+ else if (icon) mark = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2258
+ className: require_pagination.cn("flex shrink-0 items-center justify-center", markSizeStyles[size]),
2259
+ "aria-hidden": "true",
2260
+ children: icon
2261
+ });
2262
+ else if (fallbackLetter) mark = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2263
+ className: require_pagination.cn("bg-accent text-on-accent flex shrink-0 items-center justify-center rounded-lg font-bold", markSizeStyles[size], textSizeStyles[size]),
2264
+ "aria-hidden": "true",
2265
+ children: fallbackLetter
2266
+ });
2267
+ const content = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [mark, text && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2268
+ className: require_pagination.cn("text-text-primary font-semibold", textSizeStyles[size]),
2269
+ children: text
2270
+ })] });
2271
+ const sharedClassName = require_pagination.cn("inline-flex items-center gap-element", className);
2272
+ if (href) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
2273
+ href,
2274
+ onClick,
2275
+ className: require_pagination.cn(sharedClassName, "no-underline"),
2276
+ "aria-label": text !== null && text !== void 0 ? text : alt,
2277
+ "data-opt-id": "R906A",
2278
+ "data-opt-slug": "logo.Logo",
2279
+ children: content
2280
+ });
2281
+ if (onClick) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2282
+ type: "button",
2283
+ onClick,
2284
+ className: sharedClassName,
2285
+ "aria-label": text !== null && text !== void 0 ? text : alt,
2286
+ "data-opt-id": "R906A",
2287
+ "data-opt-slug": "logo.Logo",
2288
+ children: content
2289
+ });
2290
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2291
+ className: sharedClassName,
2292
+ "data-opt-id": "R906A",
2293
+ "data-opt-slug": "logo.Logo",
2294
+ children: content
2295
+ });
2296
+ }
2297
+ //#endregion
2298
+ //#region src/core/drawer.tsx
2299
+ const _excluded = [
2300
+ "className",
2301
+ "side",
2302
+ "size",
2303
+ "swipeToDismiss",
2304
+ "swipeDismissThreshold",
2305
+ "style",
2306
+ "onPointerDown"
2307
+ ];
2308
+ const _excluded2 = ["className"];
2309
+ const sizeMap = {
2310
+ sm: "max-w-xs",
2311
+ md: "max-w-md",
2312
+ lg: "max-w-xl",
2313
+ full: "max-w-full"
2314
+ };
2315
+ const heightMap = {
2316
+ sm: "max-h-[320px]",
2317
+ md: "max-h-[480px]",
2318
+ lg: "max-h-[640px]",
2319
+ full: "max-h-full"
2320
+ };
2321
+ const positionClass = {
2322
+ right: "fixed inset-y-0 right-0",
2323
+ left: "fixed inset-y-0 left-0",
2324
+ bottom: "fixed inset-x-0 bottom-0"
2325
+ };
2326
+ /** Renders the drawer root component. */
2327
+ function DrawerRoot(props) {
2328
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.DialogRoot, require_pagination._objectSpread2(require_pagination._objectSpread2({ animated: true }, props), {}, {
2329
+ "data-opt-id": "YGJ0M",
2330
+ "data-opt-slug": "drawer.DrawerRoot"
2331
+ }));
2332
+ }
2333
+ /** Maps a drag delta to the dismiss offset for a given side (0 = no progress). */
2334
+ function dismissOffset(side, dx, dy) {
2335
+ switch (side) {
2336
+ case "right": return Math.max(0, dx);
2337
+ case "left": return Math.min(0, dx);
2338
+ case "bottom": return Math.max(0, dy);
2339
+ default: return 0;
2340
+ }
2341
+ }
2342
+ /** Renders the drawer panel component. */
2343
+ function DrawerPanel(_ref) {
2344
+ let { className, side = "right", size = "md", swipeToDismiss = true, swipeDismissThreshold = 80, style, onPointerDown } = _ref, props = require_pagination._objectWithoutProperties(_ref, _excluded);
2345
+ const isHorizontal = side === "left" || side === "right";
2346
+ const close = (0, _reopt_ai_opt_ui_primitives.useDialogClose)();
2347
+ const dragStart = (0, react.useRef)(null);
2348
+ const [offset, setOffset] = (0, react.useState)(0);
2349
+ const [dragging, setDragging] = (0, react.useState)(false);
2350
+ const axis = side === "bottom" ? "Y" : "X";
2351
+ const DRAG_ACTIVATE = 6;
2352
+ const handlePointerDown = (0, react.useCallback)((e) => {
2353
+ onPointerDown === null || onPointerDown === void 0 || onPointerDown(e);
2354
+ if (!swipeToDismiss || e.button !== 0) return;
2355
+ dragStart.current = {
2356
+ x: e.clientX,
2357
+ y: e.clientY
2358
+ };
2359
+ }, [swipeToDismiss, onPointerDown]);
2360
+ const handlePointerMove = (0, react.useCallback)((e) => {
2361
+ const start = dragStart.current;
2362
+ if (!start) return;
2363
+ const next = dismissOffset(side, e.clientX - start.x, e.clientY - start.y);
2364
+ if (!dragging) {
2365
+ if (Math.abs(next) < DRAG_ACTIVATE) return;
2366
+ setDragging(true);
2367
+ try {
2368
+ e.currentTarget.setPointerCapture(e.pointerId);
2369
+ } catch (_unused) {}
2370
+ }
2371
+ setOffset(next);
2372
+ }, [side, dragging]);
2373
+ const endDrag = (0, react.useCallback)((e) => {
2374
+ const wasDragging = dragging;
2375
+ dragStart.current = null;
2376
+ setDragging(false);
2377
+ try {
2378
+ e.currentTarget.releasePointerCapture(e.pointerId);
2379
+ } catch (_unused2) {}
2380
+ if (wasDragging && Math.abs(offset) >= swipeDismissThreshold) close();
2381
+ setOffset(0);
2382
+ }, [
2383
+ dragging,
2384
+ offset,
2385
+ swipeDismissThreshold,
2386
+ close
2387
+ ]);
2388
+ const [keyboardInset, setKeyboardInset] = (0, react.useState)(0);
2389
+ (0, react.useEffect)(() => {
2390
+ if (side !== "bottom" || typeof window === "undefined") return;
2391
+ const vv = window.visualViewport;
2392
+ if (!vv) return;
2393
+ const onResize = () => {
2394
+ const inset = Math.max(0, window.innerHeight - vv.height - vv.offsetTop);
2395
+ setKeyboardInset(inset);
2396
+ };
2397
+ onResize();
2398
+ vv.addEventListener("resize", onResize);
2399
+ vv.addEventListener("scroll", onResize);
2400
+ return () => {
2401
+ vv.removeEventListener("resize", onResize);
2402
+ vv.removeEventListener("scroll", onResize);
2403
+ };
2404
+ }, [side]);
2405
+ const dragStyle = offset !== 0 ? { transform: `translate${axis}(${offset}px)` } : void 0;
2406
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.DialogPanel, require_pagination._objectSpread2(require_pagination._objectSpread2({
2407
+ className: require_pagination.cn("border-border bg-surface z-50 m-0 flex flex-col border p-0 shadow-2xl", "data-[enter]:fade-in data-[leave]:fade-out", dragging ? "touch-none" : require_pagination.OPT_ANIMATE_DRAWER[side], positionClass[side], isHorizontal ? ["h-full w-full", sizeMap[size]] : ["w-full", heightMap[size]], className),
2408
+ style: require_pagination._objectSpread2(require_pagination._objectSpread2(require_pagination._objectSpread2(require_pagination._objectSpread2({}, style), dragStyle), keyboardInset > 0 ? { marginBottom: keyboardInset } : null), dragging ? { transition: "none" } : null),
2409
+ onPointerDown: handlePointerDown,
2410
+ onPointerMove: swipeToDismiss ? handlePointerMove : void 0,
2411
+ onPointerUp: swipeToDismiss ? endDrag : void 0,
2412
+ onPointerCancel: swipeToDismiss ? endDrag : void 0
2413
+ }, props), {}, {
2414
+ "data-opt-id": "RQERV",
2415
+ "data-opt-slug": "drawer.DrawerPanel"
2416
+ }));
2417
+ }
2418
+ /** Renders the drawer close component. */
2419
+ function DrawerClose(_ref2) {
2420
+ let { className } = _ref2, props = require_pagination._objectWithoutProperties(_ref2, _excluded2);
2421
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.DialogDismiss, require_pagination._objectSpread2(require_pagination._objectSpread2({ className: require_pagination.cn("hover:bg-bg-subtle rounded-md p-1.5 transition-colors", "cursor-pointer data-[disabled]:cursor-not-allowed", require_pagination.OPT_FOCUS, className) }, props), {}, {
2422
+ "data-opt-id": "M6D6D",
2423
+ "data-opt-slug": "drawer.DrawerClose"
2424
+ }));
2425
+ }
2426
+ //#endregion
2427
+ //#region src/core/virtual-list.tsx
2428
+ /** Renders the virtual list component. */
2429
+ function VirtualList({ items, renderItem, itemHeight, overscan = 3, className, style }) {
2430
+ const containerRef = (0, react.useRef)(null);
2431
+ const scrollTopRef = (0, react.useRef)(0);
2432
+ const containerHeightRef = (0, react.useRef)(0);
2433
+ const rafIdRef = (0, react.useRef)(0);
2434
+ const [visibleRange, setVisibleRange] = (0, react.useState)({
2435
+ start: 0,
2436
+ end: 0
2437
+ });
2438
+ const totalHeight = items.length * itemHeight;
2439
+ const computeRange = (0, react.useCallback)((scrollTop, height) => {
2440
+ const start = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan);
2441
+ const visibleCount = Math.ceil(height / itemHeight);
2442
+ return {
2443
+ start,
2444
+ end: Math.min(items.length - 1, start + visibleCount + overscan * 2)
2445
+ };
2446
+ }, [
2447
+ itemHeight,
2448
+ overscan,
2449
+ items.length
2450
+ ]);
2451
+ const scheduleUpdate = (0, react.useCallback)(() => {
2452
+ if (rafIdRef.current) return;
2453
+ rafIdRef.current = requestAnimationFrame(() => {
2454
+ rafIdRef.current = 0;
2455
+ const newRange = computeRange(scrollTopRef.current, containerHeightRef.current);
2456
+ setVisibleRange((prev) => prev.start === newRange.start && prev.end === newRange.end ? prev : newRange);
2457
+ });
2458
+ }, [computeRange]);
2459
+ const handleScroll = (0, react.useCallback)(() => {
2460
+ const el = containerRef.current;
2461
+ if (el) {
2462
+ scrollTopRef.current = el.scrollTop;
2463
+ if (el.clientHeight !== containerHeightRef.current) containerHeightRef.current = el.clientHeight;
2464
+ scheduleUpdate();
2465
+ }
2466
+ }, [scheduleUpdate]);
2467
+ const handleRef = (0, react.useCallback)((el) => {
2468
+ containerRef.current = el;
2469
+ if (el) {
2470
+ containerHeightRef.current = el.clientHeight;
2471
+ const range = computeRange(0, el.clientHeight);
2472
+ setVisibleRange(range);
2473
+ }
2474
+ }, [computeRange]);
2475
+ (0, react.useEffect)(() => {
2476
+ const el = containerRef.current;
2477
+ if (!el || typeof ResizeObserver === "undefined") return;
2478
+ const observer = new ResizeObserver(() => {
2479
+ const nextHeight = el.clientHeight;
2480
+ if (nextHeight !== containerHeightRef.current) {
2481
+ containerHeightRef.current = nextHeight;
2482
+ scheduleUpdate();
2483
+ }
2484
+ });
2485
+ observer.observe(el);
2486
+ return () => {
2487
+ observer.disconnect();
2488
+ };
2489
+ }, [scheduleUpdate]);
2490
+ (0, react.useEffect)(() => {
2491
+ scheduleUpdate();
2492
+ return () => {
2493
+ if (rafIdRef.current) {
2494
+ cancelAnimationFrame(rafIdRef.current);
2495
+ rafIdRef.current = 0;
2496
+ }
2497
+ };
2498
+ }, [
2499
+ scheduleUpdate,
2500
+ items.length,
2501
+ itemHeight,
2502
+ overscan
2503
+ ]);
2504
+ const visibleItems = (0, react.useMemo)(() => {
2505
+ const result = [];
2506
+ for (let i = visibleRange.start; i <= visibleRange.end && i < items.length; i++) result.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2507
+ role: "listitem",
2508
+ style: {
2509
+ position: "absolute",
2510
+ top: i * itemHeight,
2511
+ left: 0,
2512
+ right: 0,
2513
+ height: itemHeight
2514
+ },
2515
+ children: renderItem(items[i], i)
2516
+ }, i));
2517
+ return result;
2518
+ }, [
2519
+ visibleRange.start,
2520
+ visibleRange.end,
2521
+ items,
2522
+ itemHeight,
2523
+ renderItem
2524
+ ]);
2525
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2526
+ ref: handleRef,
2527
+ onScroll: handleScroll,
2528
+ className: require_pagination.cn("overflow-auto", className),
2529
+ style: require_pagination._objectSpread2({ position: "relative" }, style),
2530
+ role: "list",
2531
+ "data-opt-id": "VT2NP",
2532
+ "data-opt-slug": "virtual-list.VirtualList",
2533
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2534
+ style: {
2535
+ height: totalHeight,
2536
+ position: "relative"
2537
+ },
2538
+ children: visibleItems
2539
+ })
2540
+ });
2541
+ }
2542
+ //#endregion
2543
+ //#region src/core/shader-presets.ts
2544
+ /** 모든 프리셋이 공유하는 풀스크린 정점 셰이더. */
2545
+ const SHADER_VERTEX = `
2546
+ attribute vec2 position;
2547
+ attribute vec2 uv;
2548
+ varying vec2 vUv;
2549
+ void main() {
2550
+ vUv = uv;
2551
+ gl_Position = vec4(position, 0.0, 1.0);
2552
+ }
2553
+ `;
2554
+ /**
2555
+ * 모든 프래그먼트 본문 앞에 붙는 공유 프렐류드.
2556
+ * uniform 선언 + 공통 helper(rotate/value noise/fbm/grain/lux/coords).
2557
+ */
2558
+ const SHADER_PRELUDE = `
2559
+ precision highp float;
2560
+ varying vec2 vUv;
2561
+ uniform float u_time;
2562
+ uniform vec2 u_resolution;
2563
+ uniform float u_scale;
2564
+ uniform float u_speed;
2565
+ uniform float u_distortion;
2566
+ uniform float u_grain;
2567
+ uniform float u_contrast;
2568
+ uniform float u_angle;
2569
+ uniform float u_dim;
2570
+ uniform float u_vignette;
2571
+ uniform float u_scrim;
2572
+ uniform vec2 u_mouse;
2573
+ uniform float u_interactive;
2574
+ uniform float u_bars;
2575
+ uniform float u_blur;
2576
+ uniform float u_peak;
2577
+ uniform float u_valley;
2578
+ uniform vec3 u_color1;
2579
+ uniform vec3 u_color2;
2580
+ uniform vec3 u_color3;
2581
+
2582
+ const float PI = 3.14159265359;
2583
+
2584
+ mat2 rot(float a){ float c = cos(a), s = sin(a); return mat2(c, -s, s, c); }
2585
+
2586
+ float hash21(vec2 p){
2587
+ p = fract(p * vec2(123.34, 345.45));
2588
+ p += dot(p, p + 34.345);
2589
+ return fract(p.x * p.y);
2590
+ }
2591
+
2592
+ float vnoise(vec2 p){
2593
+ vec2 i = floor(p);
2594
+ vec2 f = fract(p);
2595
+ vec2 u = f * f * (3.0 - 2.0 * f);
2596
+ float a = hash21(i);
2597
+ float b = hash21(i + vec2(1.0, 0.0));
2598
+ float c = hash21(i + vec2(0.0, 1.0));
2599
+ float d = hash21(i + vec2(1.0, 1.0));
2600
+ return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
2601
+ }
2602
+
2603
+ float fbm(vec2 p){
2604
+ float v = 0.0;
2605
+ float amp = 0.5;
2606
+ for (int i = 0; i < 5; i++){
2607
+ v += amp * vnoise(p);
2608
+ p = rot(0.5) * p * 2.0;
2609
+ amp *= 0.5;
2610
+ }
2611
+ return v;
2612
+ }
2613
+
2614
+ // fine film grain — subtle, premium texture
2615
+ vec3 grain(vec3 col, vec2 uv){
2616
+ float g = hash21(uv * u_resolution.xy + fract(u_time));
2617
+ return col + (g - 0.5) * u_grain;
2618
+ }
2619
+
2620
+ // premium finish: gentle desaturation for an understated, refined look.
2621
+ vec3 lux(vec3 col){
2622
+ float l = dot(col, vec3(0.299, 0.587, 0.114));
2623
+ return clamp(mix(vec3(l), col, 0.82), 0.0, 1.0);
2624
+ }
2625
+
2626
+ // shared output finish: refine + legibility overlays (dim / vignette / bottom
2627
+ // scrim) + film grain. Every preset ends with finish(col, vUv).
2628
+ vec3 finish(vec3 col, vec2 uv){
2629
+ col = lux(col);
2630
+ col *= 1.0 - u_dim * 0.85;
2631
+ float edge = length(uv - 0.5);
2632
+ col *= 1.0 - u_vignette * smoothstep(0.35, 0.85, edge);
2633
+ col *= 1.0 - u_scrim * smoothstep(0.2, 1.0, uv.y);
2634
+ col = grain(col, uv);
2635
+ return col;
2636
+ }
2637
+
2638
+ // aspect-correct, angle-rotated, centered coords + pointer parallax
2639
+ vec2 coords(){
2640
+ vec2 uv = vUv - 0.5;
2641
+ uv.x *= u_resolution.x / max(u_resolution.y, 1.0);
2642
+ uv += (u_mouse - 0.5) * u_interactive * 0.3;
2643
+ uv = rot(radians(u_angle)) * uv;
2644
+ return uv;
2645
+ }
2646
+ `;
2647
+ const PARAM_RANGE = {
2648
+ scale: {
2649
+ min: .4,
2650
+ max: 3,
2651
+ step: .1,
2652
+ default: 1
2653
+ },
2654
+ speed: {
2655
+ min: 0,
2656
+ max: 3,
2657
+ step: .1,
2658
+ default: .5
2659
+ },
2660
+ distortion: {
2661
+ min: 0,
2662
+ max: 1,
2663
+ step: .01,
2664
+ default: .4
2665
+ },
2666
+ grain: {
2667
+ min: 0,
2668
+ max: .5,
2669
+ step: .01,
2670
+ default: .04
2671
+ },
2672
+ contrast: {
2673
+ min: 0,
2674
+ max: 1,
2675
+ step: .01,
2676
+ default: .4
2677
+ },
2678
+ angle: {
2679
+ min: 0,
2680
+ max: 360,
2681
+ step: 1,
2682
+ default: 0
2683
+ },
2684
+ dim: {
2685
+ min: 0,
2686
+ max: 1,
2687
+ step: .01,
2688
+ default: 0
2689
+ },
2690
+ vignette: {
2691
+ min: 0,
2692
+ max: 1,
2693
+ step: .01,
2694
+ default: 0
2695
+ },
2696
+ scrim: {
2697
+ min: 0,
2698
+ max: 1,
2699
+ step: .01,
2700
+ default: 0
2701
+ },
2702
+ interactive: {
2703
+ min: 0,
2704
+ max: 1,
2705
+ step: .01,
2706
+ default: 0
2707
+ },
2708
+ bars: {
2709
+ min: 2,
2710
+ max: 40,
2711
+ step: 1,
2712
+ default: 19
2713
+ },
2714
+ blur: {
2715
+ min: 0,
2716
+ max: 1,
2717
+ step: .01,
2718
+ default: .29
2719
+ },
2720
+ peak: {
2721
+ min: 0,
2722
+ max: 1,
2723
+ step: .01,
2724
+ default: .98
2725
+ },
2726
+ valley: {
2727
+ min: 0,
2728
+ max: 1,
2729
+ step: .01,
2730
+ default: .55
2731
+ }
2732
+ };
2733
+ /** 프리셋이 선언하지 않은 파라미터의 전역 기본값 (uniform 폴백). */
2734
+ const SHADER_PARAM_FALLBACK = {
2735
+ scale: PARAM_RANGE.scale.default,
2736
+ speed: PARAM_RANGE.speed.default,
2737
+ distortion: PARAM_RANGE.distortion.default,
2738
+ grain: PARAM_RANGE.grain.default,
2739
+ contrast: PARAM_RANGE.contrast.default,
2740
+ angle: PARAM_RANGE.angle.default,
2741
+ dim: PARAM_RANGE.dim.default,
2742
+ vignette: PARAM_RANGE.vignette.default,
2743
+ scrim: PARAM_RANGE.scrim.default,
2744
+ interactive: PARAM_RANGE.interactive.default,
2745
+ bars: PARAM_RANGE.bars.default,
2746
+ blur: PARAM_RANGE.blur.default,
2747
+ peak: PARAM_RANGE.peak.default,
2748
+ valley: PARAM_RANGE.valley.default
2749
+ };
2750
+ function param(key, defaultValue) {
2751
+ const range = PARAM_RANGE[key];
2752
+ return {
2753
+ key,
2754
+ min: range.min,
2755
+ max: range.max,
2756
+ step: range.step,
2757
+ default: defaultValue !== null && defaultValue !== void 0 ? defaultValue : range.default
2758
+ };
2759
+ }
2760
+ const SHADER_PRESETS = [
2761
+ {
2762
+ id: "felix-metallic",
2763
+ category: "luxury",
2764
+ colorSlots: 3,
2765
+ defaultColors: [
2766
+ "#0a1424",
2767
+ "#3a5a8c",
2768
+ "#c4d4e8"
2769
+ ],
2770
+ params: [
2771
+ param("scale"),
2772
+ param("speed", .4),
2773
+ param("distortion", .45),
2774
+ param("contrast", .4),
2775
+ param("grain", .04)
2776
+ ],
2777
+ body: `
2778
+ void main(){
2779
+ vec2 uv = coords() * u_scale;
2780
+ float t = u_time * u_speed * 0.3;
2781
+ vec2 q = vec2(fbm(uv + t), fbm(uv - t + 5.2));
2782
+ vec2 r = vec2(
2783
+ fbm(uv + q * 2.0 + vec2(1.7, 9.2) + t),
2784
+ fbm(uv + q * 2.0 + vec2(8.3, 2.8) - t)
2785
+ );
2786
+ float f = fbm(uv + r * (1.0 + u_distortion * 2.0));
2787
+ float band = sin((f + r.x * 0.5) * 6.2831 * 2.0);
2788
+ float spec = pow(abs(band), mix(2.0, 5.0, u_contrast));
2789
+ vec3 col = mix(u_color1, u_color2, smoothstep(0.0, 1.0, f + r.y * 0.4));
2790
+ col = mix(col, u_color3, spec * 0.5);
2791
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
2792
+ }
2793
+ `
2794
+ },
2795
+ {
2796
+ id: "liquid-silk",
2797
+ category: "luxury",
2798
+ colorSlots: 3,
2799
+ defaultColors: [
2800
+ "#1c1428",
2801
+ "#6a5a8c",
2802
+ "#d8cfe4"
2803
+ ],
2804
+ params: [
2805
+ param("scale"),
2806
+ param("speed", .4),
2807
+ param("distortion", .4),
2808
+ param("grain", .04),
2809
+ param("angle", 30)
2810
+ ],
2811
+ body: `
2812
+ void main(){
2813
+ vec2 uv = coords() * u_scale;
2814
+ float t = u_time * u_speed * 0.25;
2815
+ float warp = fbm(uv * 1.5 + t);
2816
+ float folds = sin((uv.x * 3.0 + uv.y * 1.5 + warp * (2.0 + u_distortion * 4.0)) * PI);
2817
+ float sheen = 0.5 + 0.5 * folds;
2818
+ vec3 col = mix(u_color1, u_color2, sheen);
2819
+ col = mix(col, u_color3, pow(sheen, 5.0) * 0.6);
2820
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
2821
+ }
2822
+ `
2823
+ },
2824
+ {
2825
+ id: "iridescent-pearl",
2826
+ category: "luxury",
2827
+ colorSlots: 3,
2828
+ defaultColors: [
2829
+ "#c9b8d6",
2830
+ "#a8c4d4",
2831
+ "#e4d4dc"
2832
+ ],
2833
+ params: [
2834
+ param("scale"),
2835
+ param("speed", .35),
2836
+ param("distortion", .4),
2837
+ param("grain", .04)
2838
+ ],
2839
+ body: `
2840
+ vec3 palette3(float t){
2841
+ t = fract(t);
2842
+ float s = t * 3.0;
2843
+ if (s < 1.0) return mix(u_color1, u_color2, smoothstep(0.0, 1.0, s));
2844
+ if (s < 2.0) return mix(u_color2, u_color3, smoothstep(0.0, 1.0, s - 1.0));
2845
+ return mix(u_color3, u_color1, smoothstep(0.0, 1.0, s - 2.0));
2846
+ }
2847
+ void main(){
2848
+ vec2 uv = coords() * u_scale;
2849
+ float t = u_time * u_speed * 0.2;
2850
+ float n = fbm(uv * 1.2 + vec2(t, -t));
2851
+ float thin = fbm(uv * 2.5 - n * (1.0 + u_distortion * 3.0) + t * 0.5);
2852
+ vec3 col = palette3(thin * 1.5 + n * 0.5 + t * 0.1);
2853
+ col += pow(thin, 3.0) * 0.12;
2854
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
2855
+ }
2856
+ `
2857
+ },
2858
+ {
2859
+ id: "molten-gold",
2860
+ category: "luxury",
2861
+ colorSlots: 3,
2862
+ defaultColors: [
2863
+ "#1c1208",
2864
+ "#b08848",
2865
+ "#e8d4a8"
2866
+ ],
2867
+ params: [
2868
+ param("scale"),
2869
+ param("speed", .4),
2870
+ param("contrast", .4),
2871
+ param("grain", .05)
2872
+ ],
2873
+ body: `
2874
+ void main(){
2875
+ vec2 uv = coords() * u_scale;
2876
+ float t = u_time * u_speed * 0.3;
2877
+ vec2 q = vec2(fbm(uv + t), fbm(uv * 1.3 - t));
2878
+ float f = fbm(uv * 1.5 + q * 2.5);
2879
+ float heat = smoothstep(0.25, 0.95, f);
2880
+ vec3 col = mix(u_color1, u_color2, heat);
2881
+ float hot = pow(smoothstep(0.6, 1.0, f + q.x * 0.3), mix(3.0, 6.0, u_contrast));
2882
+ col = mix(col, u_color3, hot * 0.7);
2883
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
2884
+ }
2885
+ `
2886
+ },
2887
+ {
2888
+ id: "liquid-glass",
2889
+ category: "luxury",
2890
+ colorSlots: 3,
2891
+ defaultColors: [
2892
+ "#0c1c2c",
2893
+ "#3a6a88",
2894
+ "#bcdce4"
2895
+ ],
2896
+ params: [
2897
+ param("scale"),
2898
+ param("speed", .4),
2899
+ param("distortion", .4),
2900
+ param("grain", .03)
2901
+ ],
2902
+ body: `
2903
+ void main(){
2904
+ vec2 uv = coords() * u_scale;
2905
+ float t = u_time * u_speed * 0.2;
2906
+ vec2 p = uv;
2907
+ for (int i = 1; i < 5; i++){
2908
+ float fi = float(i);
2909
+ p += (1.0 + u_distortion) * vec2(
2910
+ 0.3 / fi * sin(fi * p.y + t + 0.3 * fi),
2911
+ 0.3 / fi * cos(fi * p.x + t + 0.3 * fi)
2912
+ );
2913
+ }
2914
+ float caustic = 0.5 + 0.5 * sin(p.x * 3.0) * cos(p.y * 3.0);
2915
+ vec3 col = mix(u_color1, u_color2, caustic);
2916
+ col = mix(col, u_color3, pow(caustic, 6.0) * 0.6);
2917
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
2918
+ }
2919
+ `
2920
+ },
2921
+ {
2922
+ id: "aurora-veil",
2923
+ category: "luxury",
2924
+ colorSlots: 3,
2925
+ defaultColors: [
2926
+ "#050d18",
2927
+ "#2a8a8c",
2928
+ "#6a5a9c"
2929
+ ],
2930
+ params: [
2931
+ param("scale"),
2932
+ param("speed", .4),
2933
+ param("distortion", .45),
2934
+ param("grain", .03),
2935
+ param("angle", 0)
2936
+ ],
2937
+ body: `
2938
+ void main(){
2939
+ vec2 uv = coords() * u_scale;
2940
+ float t = u_time * u_speed * 0.3;
2941
+ vec3 col = u_color1;
2942
+ for (int i = 0; i < 3; i++){
2943
+ float fi = float(i);
2944
+ float band = uv.y * 1.5
2945
+ + sin(uv.x * 2.0 + t + fi * 1.7) * (0.3 + u_distortion * 0.5)
2946
+ + fbm(uv * 1.5 + t * 0.5 + fi) * 0.6;
2947
+ float glow = exp(-abs(band) * 3.0);
2948
+ vec3 rib = mix(u_color2, u_color3, fi * 0.5);
2949
+ col += rib * glow * 0.5;
2950
+ }
2951
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
2952
+ }
2953
+ `
2954
+ },
2955
+ {
2956
+ id: "holographic",
2957
+ category: "luxury",
2958
+ colorSlots: 3,
2959
+ defaultColors: [
2960
+ "#14101e",
2961
+ "#8a6a9c",
2962
+ "#7a9caa"
2963
+ ],
2964
+ params: [
2965
+ param("scale"),
2966
+ param("speed", .35),
2967
+ param("distortion", .4),
2968
+ param("grain", .03)
2969
+ ],
2970
+ body: `
2971
+ vec3 hsv2rgb(vec3 c){
2972
+ vec3 p = abs(fract(c.xxx + vec3(0.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - 3.0);
2973
+ return c.z * mix(vec3(1.0), clamp(p - 1.0, 0.0, 1.0), c.y);
2974
+ }
2975
+ void main(){
2976
+ vec2 uv = coords() * u_scale;
2977
+ float t = u_time * u_speed * 0.2;
2978
+ float n = fbm(uv * 1.5 + t);
2979
+ float ripple = fbm(uv * 3.0 - n * (1.0 + u_distortion * 2.0) + t);
2980
+ float hue = fract(ripple * 1.2 + n * 0.5 + length(uv) * 0.3 + t * 0.1);
2981
+ vec3 holo = hsv2rgb(vec3(hue, 0.3, 0.92));
2982
+ vec3 base = mix(u_color1, u_color2, n);
2983
+ vec3 col = mix(base, holo, 0.35);
2984
+ col = mix(col, u_color3, pow(ripple, 4.0) * 0.5);
2985
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
2986
+ }
2987
+ `
2988
+ },
2989
+ {
2990
+ id: "chrome-ripple",
2991
+ category: "luxury",
2992
+ colorSlots: 3,
2993
+ defaultColors: [
2994
+ "#0e1420",
2995
+ "#6a7a92",
2996
+ "#d4dce4"
2997
+ ],
2998
+ params: [
2999
+ param("scale"),
3000
+ param("speed", .4),
3001
+ param("contrast", .4),
3002
+ param("grain", .04)
3003
+ ],
3004
+ body: `
3005
+ void main(){
3006
+ vec2 uv = coords() * u_scale;
3007
+ float t = u_time * u_speed * 0.3;
3008
+ vec2 p = uv;
3009
+ for (int i = 1; i < 6; i++){
3010
+ float fi = float(i);
3011
+ p.x += (0.4 / fi) * sin(fi * 1.5 * p.y + t + fi);
3012
+ p.y += (0.4 / fi) * cos(fi * 1.5 * p.x + t + fi);
3013
+ }
3014
+ float sheen = 0.5 + 0.5 * sin(p.x * 3.0 + p.y * 2.0);
3015
+ float spec = pow(sheen, mix(3.0, 6.0, u_contrast));
3016
+ vec3 col = mix(u_color1, u_color2, sheen);
3017
+ col = mix(col, u_color3, spec * 0.5);
3018
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3019
+ }
3020
+ `
3021
+ },
3022
+ {
3023
+ id: "mesh-flow",
3024
+ category: "flow",
3025
+ colorSlots: 3,
3026
+ defaultColors: [
3027
+ "#3a4a6a",
3028
+ "#6a5a7c",
3029
+ "#4a7a82"
3030
+ ],
3031
+ params: [
3032
+ param("scale"),
3033
+ param("speed", .5),
3034
+ param("grain", .04)
3035
+ ],
3036
+ body: `
3037
+ void main(){
3038
+ vec2 uv = coords() * u_scale;
3039
+ float t = u_time * u_speed * 0.4;
3040
+ vec2 p1 = vec2(sin(t * 0.7), cos(t * 0.9)) * 0.5;
3041
+ vec2 p2 = vec2(cos(t * 0.8 + 1.0), sin(t * 0.6 + 2.0)) * 0.5;
3042
+ vec2 p3 = vec2(sin(t * 0.5 + 3.0), cos(t * 0.7 + 4.0)) * 0.5;
3043
+ float d1 = 1.0 / (0.15 + dot(uv - p1, uv - p1));
3044
+ float d2 = 1.0 / (0.15 + dot(uv - p2, uv - p2));
3045
+ float d3 = 1.0 / (0.15 + dot(uv - p3, uv - p3));
3046
+ float sum = d1 + d2 + d3;
3047
+ vec3 col = (u_color1 * d1 + u_color2 * d2 + u_color3 * d3) / sum;
3048
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3049
+ }
3050
+ `
3051
+ },
3052
+ {
3053
+ id: "plasma-wave",
3054
+ category: "flow",
3055
+ colorSlots: 3,
3056
+ defaultColors: [
3057
+ "#2a2440",
3058
+ "#4a5a7c",
3059
+ "#8a6a7c"
3060
+ ],
3061
+ params: [
3062
+ param("scale"),
3063
+ param("speed", .4),
3064
+ param("distortion", .4),
3065
+ param("grain", .03)
3066
+ ],
3067
+ body: `
3068
+ void main(){
3069
+ vec2 uv = coords() * u_scale * 3.0;
3070
+ float t = u_time * u_speed * 0.5;
3071
+ float v = sin(uv.x + t)
3072
+ + sin(uv.y + t * 1.3)
3073
+ + sin((uv.x + uv.y) * 0.7 + t)
3074
+ + sin(length(uv) * (1.0 + u_distortion * 2.0) - t * 1.5);
3075
+ v *= 0.25;
3076
+ float m = 0.5 + 0.5 * sin(v * PI);
3077
+ vec3 col = mix(u_color1, u_color2, m);
3078
+ col = mix(col, u_color3, (0.5 + 0.5 * sin(v * 6.2831)) * 0.5);
3079
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3080
+ }
3081
+ `
3082
+ },
3083
+ {
3084
+ id: "swirl-vortex",
3085
+ category: "flow",
3086
+ colorSlots: 3,
3087
+ defaultColors: [
3088
+ "#0a0e16",
3089
+ "#7c4a5c",
3090
+ "#3a7a72"
3091
+ ],
3092
+ params: [
3093
+ param("scale"),
3094
+ param("speed", .4),
3095
+ param("distortion", .45),
3096
+ param("grain", .03)
3097
+ ],
3098
+ body: `
3099
+ void main(){
3100
+ vec2 uv = coords() * u_scale;
3101
+ float t = u_time * u_speed * 0.3;
3102
+ float r = length(uv);
3103
+ float a = atan(uv.y, uv.x);
3104
+ a += (1.0 + u_distortion * 3.0) * (0.5 / (r + 0.2)) + t;
3105
+ vec2 p = vec2(cos(a), sin(a)) * r;
3106
+ float n = fbm(p * 2.0 + t);
3107
+ float bands = sin((a * 3.0 + r * 6.0 - t * 2.0) + n * 4.0);
3108
+ float m = 0.5 + 0.5 * bands;
3109
+ vec3 col = mix(u_color1, u_color2, m);
3110
+ col = mix(col, u_color3, pow(m, 3.0) * 0.6);
3111
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3112
+ }
3113
+ `
3114
+ },
3115
+ {
3116
+ id: "caustics",
3117
+ category: "flow",
3118
+ colorSlots: 3,
3119
+ defaultColors: [
3120
+ "#04161f",
3121
+ "#2a6a7c",
3122
+ "#a8d4d0"
3123
+ ],
3124
+ params: [
3125
+ param("scale"),
3126
+ param("speed", .4),
3127
+ param("distortion", .4),
3128
+ param("grain", .03)
3129
+ ],
3130
+ body: `
3131
+ void main(){
3132
+ vec2 uv = coords() * u_scale * 3.0;
3133
+ float t = u_time * u_speed * 0.4;
3134
+ vec2 p = uv;
3135
+ float c = 0.0;
3136
+ for (int i = 0; i < 4; i++){
3137
+ float fi = float(i);
3138
+ p += vec2(sin(p.y * 1.5 + t + fi), cos(p.x * 1.5 + t * 1.1 + fi))
3139
+ * (0.4 + u_distortion * 0.5);
3140
+ c += 1.0 / (length(fract(p) - 0.5) + 0.1);
3141
+ }
3142
+ c = pow(c * 0.06, 2.0);
3143
+ vec3 col = mix(u_color1, u_color2, clamp(c, 0.0, 1.0));
3144
+ col += u_color3 * pow(clamp(c - 0.6, 0.0, 1.0), 2.0) * 0.6;
3145
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3146
+ }
3147
+ `
3148
+ },
3149
+ {
3150
+ id: "nebula",
3151
+ category: "flow",
3152
+ colorSlots: 3,
3153
+ defaultColors: [
3154
+ "#06040e",
3155
+ "#4a3a6c",
3156
+ "#8a5a7c"
3157
+ ],
3158
+ params: [
3159
+ param("scale"),
3160
+ param("speed", .35),
3161
+ param("distortion", .5),
3162
+ param("grain", .03)
3163
+ ],
3164
+ body: `
3165
+ void main(){
3166
+ vec2 uv = coords() * u_scale;
3167
+ float t = u_time * u_speed * 0.15;
3168
+ vec2 q = vec2(fbm(uv + t), fbm(uv * 1.2 - t + 3.0));
3169
+ float density = fbm(uv * 1.5 + q * (2.0 + u_distortion * 2.0));
3170
+ density = pow(density, 2.0);
3171
+ vec3 col = mix(u_color1, u_color2, density);
3172
+ col = mix(col, u_color3, pow(density, 3.0) * 0.8);
3173
+ float stars = step(0.99, hash21(floor(vUv * u_resolution.xy / 2.5)));
3174
+ col += vec3(stars) * 0.35;
3175
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3176
+ }
3177
+ `
3178
+ },
3179
+ {
3180
+ id: "voronoi-crystal",
3181
+ category: "geometric",
3182
+ colorSlots: 3,
3183
+ defaultColors: [
3184
+ "#121a30",
3185
+ "#3a5a82",
3186
+ "#c4d0e0"
3187
+ ],
3188
+ params: [
3189
+ param("scale"),
3190
+ param("speed", .35),
3191
+ param("contrast", .4),
3192
+ param("grain", .03)
3193
+ ],
3194
+ body: `
3195
+ vec2 hash22(vec2 p){
3196
+ p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));
3197
+ return fract(sin(p) * 43758.5453);
3198
+ }
3199
+ void main(){
3200
+ vec2 uv = coords() * u_scale * 3.0;
3201
+ float t = u_time * u_speed * 0.3;
3202
+ vec2 ip = floor(uv);
3203
+ vec2 fp = fract(uv);
3204
+ float f1 = 8.0;
3205
+ float f2 = 8.0;
3206
+ vec2 cellId = vec2(0.0);
3207
+ for (int j = -1; j <= 1; j++){
3208
+ for (int i = -1; i <= 1; i++){
3209
+ vec2 n = vec2(float(i), float(j));
3210
+ vec2 pnt = n + 0.5 + 0.4 * sin(t + 6.2831 * hash22(ip + n));
3211
+ float d = length(pnt - fp);
3212
+ if (d < f1){ f2 = f1; f1 = d; cellId = ip + n; }
3213
+ else if (d < f2){ f2 = d; }
3214
+ }
3215
+ }
3216
+ float facet = f2 - f1;
3217
+ float cell = hash22(cellId).x;
3218
+ vec3 col = mix(u_color1, u_color2, cell);
3219
+ col = mix(col, u_color3, smoothstep(0.05, 0.0, facet) * mix(0.4, 0.7, u_contrast));
3220
+ col += pow(max(0.0, 1.0 - f1), 4.0) * 0.1;
3221
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3222
+ }
3223
+ `
3224
+ },
3225
+ {
3226
+ id: "kaleidoscope",
3227
+ category: "geometric",
3228
+ colorSlots: 3,
3229
+ defaultColors: [
3230
+ "#1a1428",
3231
+ "#7c5a6c",
3232
+ "#b09a6a"
3233
+ ],
3234
+ params: [
3235
+ param("scale"),
3236
+ param("speed", .35),
3237
+ param("distortion", .4),
3238
+ param("grain", .03)
3239
+ ],
3240
+ body: `
3241
+ void main(){
3242
+ vec2 uv = coords() * u_scale;
3243
+ float t = u_time * u_speed * 0.3;
3244
+ float r = length(uv);
3245
+ float a = atan(uv.y, uv.x);
3246
+ float seg = 6.0 + floor(u_distortion * 6.0);
3247
+ a = mod(a, 6.2831 / seg);
3248
+ a = abs(a - 3.14159 / seg);
3249
+ vec2 p = vec2(cos(a), sin(a)) * r;
3250
+ float pattern = fbm(p * 3.0 + t);
3251
+ float m = 0.5 + 0.5 * sin(pattern * 6.2831 + r * 4.0 - t);
3252
+ vec3 col = mix(u_color1, u_color2, m);
3253
+ col = mix(col, u_color3, pow(m, 3.0) * 0.6);
3254
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3255
+ }
3256
+ `
3257
+ },
3258
+ {
3259
+ id: "dither-gradient",
3260
+ category: "retro",
3261
+ colorSlots: 3,
3262
+ defaultColors: [
3263
+ "#14202e",
3264
+ "#7c4a54",
3265
+ "#d4d0c8"
3266
+ ],
3267
+ params: [
3268
+ param("scale"),
3269
+ param("speed", .35),
3270
+ param("distortion", .35)
3271
+ ],
3272
+ body: `
3273
+ float bayer2(vec2 a){ a = floor(a); return fract(dot(a, vec2(0.5, a.y * 0.75))); }
3274
+ float bayer4(vec2 a){ return bayer2(0.5 * a) * 0.25 + bayer2(a); }
3275
+ void main(){
3276
+ vec2 uv = coords() * u_scale;
3277
+ float t = u_time * u_speed * 0.2;
3278
+ float g = fbm(uv * 1.5 + vec2(t, -t) * (0.5 + u_distortion));
3279
+ float levels = 5.0;
3280
+ float d = bayer4(gl_FragCoord.xy);
3281
+ float q = floor(g * levels + d) / levels;
3282
+ vec3 col = mix(u_color1, u_color2, clamp(q, 0.0, 1.0));
3283
+ col = mix(col, u_color3, smoothstep(0.7, 1.0, q));
3284
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3285
+ }
3286
+ `
3287
+ },
3288
+ {
3289
+ id: "halftone",
3290
+ category: "retro",
3291
+ colorSlots: 3,
3292
+ defaultColors: [
3293
+ "#161616",
3294
+ "#8a5a3a",
3295
+ "#c4a06a"
3296
+ ],
3297
+ params: [
3298
+ param("scale"),
3299
+ param("speed", .35),
3300
+ param("distortion", .45)
3301
+ ],
3302
+ body: `
3303
+ void main(){
3304
+ vec2 uv = coords() * u_scale;
3305
+ float t = u_time * u_speed * 0.2;
3306
+ float g = fbm(uv * 1.5 + t);
3307
+ vec2 gp = gl_FragCoord.xy / mix(22.0, 9.0, clamp(u_distortion, 0.0, 1.0));
3308
+ vec2 cell = fract(gp) - 0.5;
3309
+ float radius = g * 0.7;
3310
+ float dot = smoothstep(radius, radius - 0.12, length(cell));
3311
+ vec3 col = mix(u_color1, u_color2, g);
3312
+ col = mix(col, u_color3, dot * 0.85);
3313
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3314
+ }
3315
+ `
3316
+ },
3317
+ {
3318
+ id: "dia-gradient",
3319
+ category: "gradient",
3320
+ colorSlots: 3,
3321
+ defaultColors: [
3322
+ "#FF9ECF",
3323
+ "#A9C9FF",
3324
+ "#FFF3A8"
3325
+ ],
3326
+ params: [
3327
+ param("bars"),
3328
+ param("blur"),
3329
+ param("peak"),
3330
+ param("valley"),
3331
+ param("speed", .3)
3332
+ ],
3333
+ body: `
3334
+ void main(){
3335
+ vec2 uv = vUv;
3336
+ float t = u_time * u_speed * 0.15;
3337
+ float cx = 0.5 + sin(t) * 0.04;
3338
+ float peakShape = clamp(1.0 - abs(uv.x - cx) * 2.0, 0.0, 1.0);
3339
+ peakShape = pow(peakShape, 0.85);
3340
+ float profile = mix(u_valley, u_peak, peakShape);
3341
+ float heightFromBottom = 1.0 - uv.y;
3342
+ float h = heightFromBottom / max(profile, 0.02);
3343
+ float bars = max(1.0, floor(u_bars));
3344
+ float hb = h * bars;
3345
+ float band = floor(hb);
3346
+ float frac = hb - band;
3347
+ float soft = mix(0.04, 0.5, clamp(u_blur, 0.0, 1.0));
3348
+ float sm = smoothstep(0.5 - soft, 0.5 + soft, frac);
3349
+ float hv = clamp((band + sm) / bars, 0.0, 1.0);
3350
+ vec3 col;
3351
+ if (hv < 0.33) col = mix(u_color1, u_color2, smoothstep(0.0, 0.33, hv));
3352
+ else if (hv < 0.66) col = mix(u_color2, u_color3, smoothstep(0.33, 0.66, hv));
3353
+ else col = mix(u_color3, vec3(1.0), smoothstep(0.66, 1.0, hv));
3354
+ float above = smoothstep(1.0, 1.0 + soft * 0.5, h);
3355
+ col = mix(col, vec3(1.0), above);
3356
+ gl_FragColor = vec4(finish(col, vUv), 1.0);
3357
+ }
3358
+ `
3359
+ }
3360
+ ];
3361
+ const SHADER_PRESET_IDS = SHADER_PRESETS.map((preset) => preset.id);
3362
+ const SHADER_PARAM_KEYS = [
3363
+ "scale",
3364
+ "speed",
3365
+ "distortion",
3366
+ "grain",
3367
+ "contrast",
3368
+ "angle",
3369
+ "dim",
3370
+ "vignette",
3371
+ "scrim",
3372
+ "interactive",
3373
+ "bars",
3374
+ "blur",
3375
+ "peak",
3376
+ "valley"
3377
+ ];
3378
+ /** 패턴과 무관하게 모든 프리셋에 공통 적용되는 마감(가독성) 파라미터 키. */
3379
+ const SHADER_OVERLAY_PARAM_KEYS = [
3380
+ "dim",
3381
+ "vignette",
3382
+ "scrim"
3383
+ ];
3384
+ const PRESET_BY_ID = new Map(SHADER_PRESETS.map((preset) => [preset.id, preset]));
3385
+ /** id로 프리셋 조회 (없으면 첫 프리셋 폴백). */
3386
+ function getShaderPreset(id) {
3387
+ var _PRESET_BY_ID$get;
3388
+ return (_PRESET_BY_ID$get = PRESET_BY_ID.get(id)) !== null && _PRESET_BY_ID$get !== void 0 ? _PRESET_BY_ID$get : SHADER_PRESETS[0];
3389
+ }
3390
+ /** 공유 프렐류드 + 프리셋 본문을 합친 완성 프래그먼트 셰이더 소스. */
3391
+ function getShaderFragment(preset) {
3392
+ return `${SHADER_PRELUDE}\n${preset.body}`;
3393
+ }
3394
+ //#endregion
3395
+ //#region src/core/shader-surface.tsx
3396
+ /** 정지(`paused`) 프레임에 사용하는 고정 시간 — t=0의 밋밋함 회피. */
3397
+ const STATIC_TIME = 8;
3398
+ /** hex → 0..1 RGB. 잘못된 hex는 검정으로 폴백. */
3399
+ function toRgbFloat(hex) {
3400
+ try {
3401
+ const [r, g, b] = (0, _reopt_ai_opt_palette.hexToSrgb)(hex);
3402
+ return [
3403
+ r / 255,
3404
+ g / 255,
3405
+ b / 255
3406
+ ];
3407
+ } catch (_unused) {
3408
+ return [
3409
+ 0,
3410
+ 0,
3411
+ 0
3412
+ ];
3413
+ }
3414
+ }
3415
+ function resolveColors(presetId, colors) {
3416
+ var _source$, _ref, _source$2, _ref2, _ref3, _source$3;
3417
+ const preset = getShaderPreset(presetId);
3418
+ const source = colors && colors.length > 0 ? colors : preset.defaultColors;
3419
+ return [
3420
+ (_source$ = source[0]) !== null && _source$ !== void 0 ? _source$ : preset.defaultColors[0],
3421
+ (_ref = (_source$2 = source[1]) !== null && _source$2 !== void 0 ? _source$2 : source[0]) !== null && _ref !== void 0 ? _ref : preset.defaultColors[1],
3422
+ (_ref2 = (_ref3 = (_source$3 = source[2]) !== null && _source$3 !== void 0 ? _source$3 : source[1]) !== null && _ref3 !== void 0 ? _ref3 : source[0]) !== null && _ref2 !== void 0 ? _ref2 : preset.defaultColors[2]
3423
+ ];
3424
+ }
3425
+ function resolveParam(presetId, key, override) {
3426
+ var _spec$default;
3427
+ if (typeof override === "number" && Number.isFinite(override)) return override;
3428
+ const spec = getShaderPreset(presetId).params.find((p) => p.key === key);
3429
+ return (_spec$default = spec === null || spec === void 0 ? void 0 : spec.default) !== null && _spec$default !== void 0 ? _spec$default : SHADER_PARAM_FALLBACK[key];
3430
+ }
3431
+ function prefersReducedMotion() {
3432
+ return typeof window !== "undefined" && window.matchMedia ? window.matchMedia("(prefers-reduced-motion: reduce)").matches : false;
3433
+ }
3434
+ const ShaderSurfaceComponent = (0, react.forwardRef)(function ShaderSurface({ preset, colors, scale, speed, distortion, grain, contrast, angle, dim, vignette, scrim, interactive, params, time, paused = false, dpr, className, style, "aria-hidden": ariaHidden = true }, ref) {
3435
+ const containerRef = (0, react.useRef)(null);
3436
+ const canvasRef = (0, react.useRef)(null);
3437
+ const stateRef = (0, react.useRef)({
3438
+ preset,
3439
+ colors,
3440
+ scale,
3441
+ speed,
3442
+ distortion,
3443
+ grain,
3444
+ contrast,
3445
+ angle,
3446
+ dim,
3447
+ vignette,
3448
+ scrim,
3449
+ interactive,
3450
+ params,
3451
+ time,
3452
+ paused
3453
+ });
3454
+ stateRef.current = {
3455
+ preset,
3456
+ colors,
3457
+ scale,
3458
+ speed,
3459
+ distortion,
3460
+ grain,
3461
+ contrast,
3462
+ angle,
3463
+ dim,
3464
+ vignette,
3465
+ scrim,
3466
+ interactive,
3467
+ params,
3468
+ time,
3469
+ paused
3470
+ };
3471
+ const rendererRef = (0, react.useRef)(null);
3472
+ const programRef = (0, react.useRef)(null);
3473
+ const renderAtRef = (0, react.useRef)(null);
3474
+ const loopRef = (0, react.useRef)(null);
3475
+ const mouseRef = (0, react.useRef)([.5, .5]);
3476
+ const fallbackBackground = (0, react.useMemo)(() => {
3477
+ const [c1, c2, c3] = resolveColors(preset, colors);
3478
+ return `linear-gradient(${resolveParam(preset, "angle", angle) + 120}deg, ${c1}, ${c2}, ${c3})`;
3479
+ }, [
3480
+ preset,
3481
+ colors,
3482
+ angle
3483
+ ]);
3484
+ (0, react.useImperativeHandle)(ref, () => ({ capture: () => {
3485
+ var _stateRef$current$tim;
3486
+ const canvas = canvasRef.current;
3487
+ if (!canvas || !renderAtRef.current || !programRef.current) return null;
3488
+ const now = stateRef.current.paused ? (_stateRef$current$tim = stateRef.current.time) !== null && _stateRef$current$tim !== void 0 ? _stateRef$current$tim : STATIC_TIME : performance.now() / 1e3;
3489
+ renderAtRef.current(now);
3490
+ try {
3491
+ return canvas.toDataURL("image/png");
3492
+ } catch (_unused2) {
3493
+ return null;
3494
+ }
3495
+ } }), []);
3496
+ (0, react.useEffect)(() => {
3497
+ const container = containerRef.current;
3498
+ const canvas = canvasRef.current;
3499
+ if (!container || !canvas) return;
3500
+ let renderer;
3501
+ try {
3502
+ renderer = new ogl.Renderer({
3503
+ canvas,
3504
+ dpr: dpr !== null && dpr !== void 0 ? dpr : typeof window !== "undefined" ? Math.min(window.devicePixelRatio || 1, 2) : 1,
3505
+ alpha: true,
3506
+ premultipliedAlpha: false
3507
+ });
3508
+ } catch (_unused3) {
3509
+ return;
3510
+ }
3511
+ const gl = renderer.gl;
3512
+ rendererRef.current = {
3513
+ renderer,
3514
+ gl
3515
+ };
3516
+ const resize = () => {
3517
+ const rect = container.getBoundingClientRect();
3518
+ renderer.setSize(Math.max(1, rect.width), Math.max(1, rect.height));
3519
+ };
3520
+ resize();
3521
+ const renderAt = (timeSeconds) => {
3522
+ const current = programRef.current;
3523
+ if (!current) return;
3524
+ const s = stateRef.current;
3525
+ const [c1, c2, c3] = resolveColors(s.preset, s.colors);
3526
+ const u = current.program.uniforms;
3527
+ const val = (key, override) => {
3528
+ var _s$params;
3529
+ return resolveParam(s.preset, key, override !== null && override !== void 0 ? override : (_s$params = s.params) === null || _s$params === void 0 ? void 0 : _s$params[key]);
3530
+ };
3531
+ u.u_time.value = timeSeconds;
3532
+ u.u_resolution.value = [gl.canvas.width, gl.canvas.height];
3533
+ u.u_scale.value = val("scale", s.scale);
3534
+ u.u_speed.value = val("speed", s.speed);
3535
+ u.u_distortion.value = val("distortion", s.distortion);
3536
+ u.u_grain.value = val("grain", s.grain);
3537
+ u.u_contrast.value = val("contrast", s.contrast);
3538
+ u.u_angle.value = val("angle", s.angle);
3539
+ u.u_dim.value = val("dim", s.dim);
3540
+ u.u_vignette.value = val("vignette", s.vignette);
3541
+ u.u_scrim.value = val("scrim", s.scrim);
3542
+ u.u_interactive.value = val("interactive", s.interactive);
3543
+ u.u_bars.value = val("bars", void 0);
3544
+ u.u_blur.value = val("blur", void 0);
3545
+ u.u_peak.value = val("peak", void 0);
3546
+ u.u_valley.value = val("valley", void 0);
3547
+ u.u_mouse.value = mouseRef.current;
3548
+ u.u_color1.value = toRgbFloat(c1);
3549
+ u.u_color2.value = toRgbFloat(c2);
3550
+ u.u_color3.value = toRgbFloat(c3);
3551
+ renderer.render({ scene: current.mesh });
3552
+ };
3553
+ renderAtRef.current = renderAt;
3554
+ const staticTime = () => {
3555
+ var _stateRef$current$tim2;
3556
+ return (_stateRef$current$tim2 = stateRef.current.time) !== null && _stateRef$current$tim2 !== void 0 ? _stateRef$current$tim2 : STATIC_TIME;
3557
+ };
3558
+ const reduced = prefersReducedMotion();
3559
+ let inView = true;
3560
+ const isAnimating = () => !stateRef.current.paused && !reduced && inView;
3561
+ let raf = 0;
3562
+ let startTime = performance.now();
3563
+ const loop = (nowMs) => {
3564
+ renderAt((nowMs - startTime) / 1e3);
3565
+ raf = requestAnimationFrame(loop);
3566
+ };
3567
+ const start = () => {
3568
+ if (raf) return;
3569
+ startTime = performance.now();
3570
+ raf = requestAnimationFrame(loop);
3571
+ };
3572
+ const stop = () => {
3573
+ if (raf) cancelAnimationFrame(raf);
3574
+ raf = 0;
3575
+ };
3576
+ loopRef.current = {
3577
+ start,
3578
+ stop,
3579
+ isAnimating
3580
+ };
3581
+ const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
3582
+ resize();
3583
+ if (!isAnimating()) renderAt(staticTime());
3584
+ }) : null;
3585
+ resizeObserver === null || resizeObserver === void 0 || resizeObserver.observe(container);
3586
+ const intersectionObserver = typeof IntersectionObserver !== "undefined" ? new IntersectionObserver((entries) => {
3587
+ var _entries$0$isIntersec, _entries$;
3588
+ inView = (_entries$0$isIntersec = (_entries$ = entries[0]) === null || _entries$ === void 0 ? void 0 : _entries$.isIntersecting) !== null && _entries$0$isIntersec !== void 0 ? _entries$0$isIntersec : true;
3589
+ if (inView && isAnimating()) start();
3590
+ else stop();
3591
+ }, { threshold: 0 }) : null;
3592
+ intersectionObserver === null || intersectionObserver === void 0 || intersectionObserver.observe(container);
3593
+ const handlePointer = (event) => {
3594
+ const rect = container.getBoundingClientRect();
3595
+ mouseRef.current = [(event.clientX - rect.left) / Math.max(1, rect.width), (event.clientY - rect.top) / Math.max(1, rect.height)];
3596
+ const s = stateRef.current;
3597
+ if (!isAnimating() && resolveParam(s.preset, "interactive", s.interactive) > 0) renderAt(staticTime());
3598
+ };
3599
+ container.addEventListener("pointermove", handlePointer);
3600
+ if (isAnimating()) start();
3601
+ return () => {
3602
+ stop();
3603
+ resizeObserver === null || resizeObserver === void 0 || resizeObserver.disconnect();
3604
+ intersectionObserver === null || intersectionObserver === void 0 || intersectionObserver.disconnect();
3605
+ container.removeEventListener("pointermove", handlePointer);
3606
+ loopRef.current = null;
3607
+ renderAtRef.current = null;
3608
+ rendererRef.current = null;
3609
+ };
3610
+ }, [dpr]);
3611
+ (0, react.useEffect)(() => {
3612
+ var _renderAtRef$current, _stateRef$current$tim3;
3613
+ const engine = rendererRef.current;
3614
+ if (!engine) return;
3615
+ const { gl } = engine;
3616
+ const presetDef = getShaderPreset(preset);
3617
+ const geometry = new ogl.Triangle(gl);
3618
+ const program = new ogl.Program(gl, {
3619
+ vertex: SHADER_VERTEX,
3620
+ fragment: getShaderFragment(presetDef),
3621
+ uniforms: {
3622
+ u_time: { value: 0 },
3623
+ u_resolution: { value: [1, 1] },
3624
+ u_scale: { value: 1 },
3625
+ u_speed: { value: 1 },
3626
+ u_distortion: { value: .5 },
3627
+ u_grain: { value: 0 },
3628
+ u_contrast: { value: .5 },
3629
+ u_angle: { value: 0 },
3630
+ u_dim: { value: 0 },
3631
+ u_vignette: { value: 0 },
3632
+ u_scrim: { value: 0 },
3633
+ u_mouse: { value: [.5, .5] },
3634
+ u_interactive: { value: 0 },
3635
+ u_bars: { value: 19 },
3636
+ u_blur: { value: .29 },
3637
+ u_peak: { value: .98 },
3638
+ u_valley: { value: .55 },
3639
+ u_color1: { value: [
3640
+ 0,
3641
+ 0,
3642
+ 0
3643
+ ] },
3644
+ u_color2: { value: [
3645
+ 0,
3646
+ 0,
3647
+ 0
3648
+ ] },
3649
+ u_color3: { value: [
3650
+ 0,
3651
+ 0,
3652
+ 0
3653
+ ] }
3654
+ }
3655
+ });
3656
+ const mesh = new ogl.Mesh(gl, {
3657
+ geometry,
3658
+ program
3659
+ });
3660
+ programRef.current = {
3661
+ program,
3662
+ mesh,
3663
+ geometry
3664
+ };
3665
+ const loop = loopRef.current;
3666
+ if (loop === null || loop === void 0 ? void 0 : loop.isAnimating()) loop.start();
3667
+ else (_renderAtRef$current = renderAtRef.current) === null || _renderAtRef$current === void 0 || _renderAtRef$current.call(renderAtRef, (_stateRef$current$tim3 = stateRef.current.time) !== null && _stateRef$current$tim3 !== void 0 ? _stateRef$current$tim3 : STATIC_TIME);
3668
+ return () => {
3669
+ programRef.current = null;
3670
+ program.remove();
3671
+ geometry.remove();
3672
+ };
3673
+ }, [preset]);
3674
+ (0, react.useEffect)(() => {
3675
+ const loop = loopRef.current;
3676
+ if (!loop) return;
3677
+ if (loop.isAnimating()) loop.start();
3678
+ else {
3679
+ var _renderAtRef$current2, _stateRef$current$tim4;
3680
+ loop.stop();
3681
+ (_renderAtRef$current2 = renderAtRef.current) === null || _renderAtRef$current2 === void 0 || _renderAtRef$current2.call(renderAtRef, (_stateRef$current$tim4 = stateRef.current.time) !== null && _stateRef$current$tim4 !== void 0 ? _stateRef$current$tim4 : STATIC_TIME);
3682
+ }
3683
+ }, [
3684
+ paused,
3685
+ colors,
3686
+ scale,
3687
+ speed,
3688
+ distortion,
3689
+ grain,
3690
+ contrast,
3691
+ angle,
3692
+ dim,
3693
+ vignette,
3694
+ scrim,
3695
+ interactive,
3696
+ params,
3697
+ time
3698
+ ]);
3699
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3700
+ ref: containerRef,
3701
+ "aria-hidden": ariaHidden,
3702
+ className: require_pagination.cn("relative overflow-hidden", className),
3703
+ style: require_pagination._objectSpread2({ background: fallbackBackground }, style),
3704
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
3705
+ ref: canvasRef,
3706
+ className: "absolute inset-0 block h-full w-full"
3707
+ })
3708
+ });
3709
+ });
3710
+ ShaderSurfaceComponent.displayName = "ShaderSurface";
3711
+ const ShaderSurface = ShaderSurfaceComponent;
3712
+ //#endregion
3713
+ Object.defineProperty(exports, "AccordionContent", {
3714
+ enumerable: true,
3715
+ get: function() {
3716
+ return AccordionContent;
3717
+ }
3718
+ });
3719
+ Object.defineProperty(exports, "AccordionItem", {
3720
+ enumerable: true,
3721
+ get: function() {
3722
+ return AccordionItem;
3723
+ }
3724
+ });
3725
+ Object.defineProperty(exports, "AccordionRoot", {
3726
+ enumerable: true,
3727
+ get: function() {
3728
+ return AccordionRoot;
3729
+ }
3730
+ });
3731
+ Object.defineProperty(exports, "AccordionTrigger", {
3732
+ enumerable: true,
3733
+ get: function() {
3734
+ return AccordionTrigger;
3735
+ }
3736
+ });
3737
+ Object.defineProperty(exports, "Avatar", {
3738
+ enumerable: true,
3739
+ get: function() {
3740
+ return Avatar;
3741
+ }
3742
+ });
3743
+ Object.defineProperty(exports, "AvatarGroup", {
3744
+ enumerable: true,
3745
+ get: function() {
3746
+ return AvatarGroup;
3747
+ }
3748
+ });
3749
+ Object.defineProperty(exports, "BlockLayout", {
3750
+ enumerable: true,
3751
+ get: function() {
3752
+ return BlockLayout;
3753
+ }
3754
+ });
3755
+ Object.defineProperty(exports, "Breadcrumb", {
3756
+ enumerable: true,
3757
+ get: function() {
3758
+ return Breadcrumb;
3759
+ }
3760
+ });
3761
+ Object.defineProperty(exports, "Card", {
3762
+ enumerable: true,
3763
+ get: function() {
3764
+ return Card;
3765
+ }
3766
+ });
3767
+ Object.defineProperty(exports, "CardContent", {
3768
+ enumerable: true,
3769
+ get: function() {
3770
+ return CardContent;
3771
+ }
3772
+ });
3773
+ Object.defineProperty(exports, "CardDescription", {
3774
+ enumerable: true,
3775
+ get: function() {
3776
+ return CardDescription;
3777
+ }
3778
+ });
3779
+ Object.defineProperty(exports, "CardFooter", {
3780
+ enumerable: true,
3781
+ get: function() {
3782
+ return CardFooter;
3783
+ }
3784
+ });
3785
+ Object.defineProperty(exports, "CardHeader", {
3786
+ enumerable: true,
3787
+ get: function() {
3788
+ return CardHeader;
3789
+ }
3790
+ });
3791
+ Object.defineProperty(exports, "CardTitle", {
3792
+ enumerable: true,
3793
+ get: function() {
3794
+ return CardTitle;
3795
+ }
3796
+ });
3797
+ Object.defineProperty(exports, "CircularProgress", {
3798
+ enumerable: true,
3799
+ get: function() {
3800
+ return CircularProgress;
3801
+ }
3802
+ });
3803
+ Object.defineProperty(exports, "ConditionBuilder", {
3804
+ enumerable: true,
3805
+ get: function() {
3806
+ return ConditionBuilder;
3807
+ }
3808
+ });
3809
+ Object.defineProperty(exports, "Container", {
3810
+ enumerable: true,
3811
+ get: function() {
3812
+ return Container;
3813
+ }
3814
+ });
3815
+ Object.defineProperty(exports, "DrawerClose", {
3816
+ enumerable: true,
3817
+ get: function() {
3818
+ return DrawerClose;
3819
+ }
3820
+ });
3821
+ Object.defineProperty(exports, "DrawerPanel", {
3822
+ enumerable: true,
3823
+ get: function() {
3824
+ return DrawerPanel;
3825
+ }
3826
+ });
3827
+ Object.defineProperty(exports, "DrawerRoot", {
3828
+ enumerable: true,
3829
+ get: function() {
3830
+ return DrawerRoot;
3831
+ }
3832
+ });
3833
+ Object.defineProperty(exports, "DropdownContent", {
3834
+ enumerable: true,
3835
+ get: function() {
3836
+ return DropdownContent;
3837
+ }
3838
+ });
3839
+ Object.defineProperty(exports, "DropdownItem", {
3840
+ enumerable: true,
3841
+ get: function() {
3842
+ return DropdownItem;
3843
+ }
3844
+ });
3845
+ Object.defineProperty(exports, "DropdownMenu", {
3846
+ enumerable: true,
3847
+ get: function() {
3848
+ return DropdownMenu;
3849
+ }
3850
+ });
3851
+ Object.defineProperty(exports, "DropdownSeparator", {
3852
+ enumerable: true,
3853
+ get: function() {
3854
+ return DropdownSeparator;
3855
+ }
3856
+ });
3857
+ Object.defineProperty(exports, "DropdownTrigger", {
3858
+ enumerable: true,
3859
+ get: function() {
3860
+ return DropdownTrigger;
3861
+ }
3862
+ });
3863
+ Object.defineProperty(exports, "Heading", {
3864
+ enumerable: true,
3865
+ get: function() {
3866
+ return Heading;
3867
+ }
3868
+ });
3869
+ Object.defineProperty(exports, "Input", {
3870
+ enumerable: true,
3871
+ get: function() {
3872
+ return Input;
3873
+ }
3874
+ });
3875
+ Object.defineProperty(exports, "LoadingOverlay", {
3876
+ enumerable: true,
3877
+ get: function() {
3878
+ return LoadingOverlay;
3879
+ }
3880
+ });
3881
+ Object.defineProperty(exports, "Logo", {
3882
+ enumerable: true,
3883
+ get: function() {
3884
+ return Logo;
3885
+ }
3886
+ });
3887
+ Object.defineProperty(exports, "Meter", {
3888
+ enumerable: true,
3889
+ get: function() {
3890
+ return Meter;
3891
+ }
3892
+ });
3893
+ Object.defineProperty(exports, "OtpField", {
3894
+ enumerable: true,
3895
+ get: function() {
3896
+ return OtpField;
3897
+ }
3898
+ });
3899
+ Object.defineProperty(exports, "PageHeader", {
3900
+ enumerable: true,
3901
+ get: function() {
3902
+ return PageHeader;
3903
+ }
3904
+ });
3905
+ Object.defineProperty(exports, "Progress", {
3906
+ enumerable: true,
3907
+ get: function() {
3908
+ return Progress;
3909
+ }
3910
+ });
3911
+ Object.defineProperty(exports, "Radio", {
3912
+ enumerable: true,
3913
+ get: function() {
3914
+ return Radio;
3915
+ }
3916
+ });
3917
+ Object.defineProperty(exports, "RadioGroup", {
3918
+ enumerable: true,
3919
+ get: function() {
3920
+ return RadioGroup;
3921
+ }
3922
+ });
3923
+ Object.defineProperty(exports, "ResizableHandle", {
3924
+ enumerable: true,
3925
+ get: function() {
3926
+ return ResizableHandle;
3927
+ }
3928
+ });
3929
+ Object.defineProperty(exports, "ResizablePanel", {
3930
+ enumerable: true,
3931
+ get: function() {
3932
+ return ResizablePanel;
3933
+ }
3934
+ });
3935
+ Object.defineProperty(exports, "ResizablePanelGroup", {
3936
+ enumerable: true,
3937
+ get: function() {
3938
+ return ResizablePanelGroup;
3939
+ }
3940
+ });
3941
+ Object.defineProperty(exports, "SHADER_OVERLAY_PARAM_KEYS", {
3942
+ enumerable: true,
3943
+ get: function() {
3944
+ return SHADER_OVERLAY_PARAM_KEYS;
3945
+ }
3946
+ });
3947
+ Object.defineProperty(exports, "SHADER_PARAM_FALLBACK", {
3948
+ enumerable: true,
3949
+ get: function() {
3950
+ return SHADER_PARAM_FALLBACK;
3951
+ }
3952
+ });
3953
+ Object.defineProperty(exports, "SHADER_PARAM_KEYS", {
3954
+ enumerable: true,
3955
+ get: function() {
3956
+ return SHADER_PARAM_KEYS;
3957
+ }
3958
+ });
3959
+ Object.defineProperty(exports, "SHADER_PRESETS", {
3960
+ enumerable: true,
3961
+ get: function() {
3962
+ return SHADER_PRESETS;
3963
+ }
3964
+ });
3965
+ Object.defineProperty(exports, "SHADER_PRESET_IDS", {
3966
+ enumerable: true,
3967
+ get: function() {
3968
+ return SHADER_PRESET_IDS;
3969
+ }
3970
+ });
3971
+ Object.defineProperty(exports, "ScrollArea", {
3972
+ enumerable: true,
3973
+ get: function() {
3974
+ return ScrollArea;
3975
+ }
3976
+ });
3977
+ Object.defineProperty(exports, "Section", {
3978
+ enumerable: true,
3979
+ get: function() {
3980
+ return Section;
3981
+ }
3982
+ });
3983
+ Object.defineProperty(exports, "Separator", {
3984
+ enumerable: true,
3985
+ get: function() {
3986
+ return Separator$1;
3987
+ }
3988
+ });
3989
+ Object.defineProperty(exports, "ShaderSurface", {
3990
+ enumerable: true,
3991
+ get: function() {
3992
+ return ShaderSurface;
3993
+ }
3994
+ });
3995
+ Object.defineProperty(exports, "Skeleton", {
3996
+ enumerable: true,
3997
+ get: function() {
3998
+ return Skeleton;
3999
+ }
4000
+ });
4001
+ Object.defineProperty(exports, "SkeletonAvatar", {
4002
+ enumerable: true,
4003
+ get: function() {
4004
+ return SkeletonAvatar;
4005
+ }
4006
+ });
4007
+ Object.defineProperty(exports, "SkeletonCard", {
4008
+ enumerable: true,
4009
+ get: function() {
4010
+ return SkeletonCard;
4011
+ }
4012
+ });
4013
+ Object.defineProperty(exports, "SkeletonTable", {
4014
+ enumerable: true,
4015
+ get: function() {
4016
+ return SkeletonTable;
4017
+ }
4018
+ });
4019
+ Object.defineProperty(exports, "SkeletonText", {
4020
+ enumerable: true,
4021
+ get: function() {
4022
+ return SkeletonText;
4023
+ }
4024
+ });
4025
+ Object.defineProperty(exports, "StepBuilder", {
4026
+ enumerable: true,
4027
+ get: function() {
4028
+ return StepBuilder;
4029
+ }
4030
+ });
4031
+ Object.defineProperty(exports, "Switch", {
4032
+ enumerable: true,
4033
+ get: function() {
4034
+ return Switch;
4035
+ }
4036
+ });
4037
+ Object.defineProperty(exports, "Text", {
4038
+ enumerable: true,
4039
+ get: function() {
4040
+ return Text;
4041
+ }
4042
+ });
4043
+ Object.defineProperty(exports, "Textarea", {
4044
+ enumerable: true,
4045
+ get: function() {
4046
+ return Textarea;
4047
+ }
4048
+ });
4049
+ Object.defineProperty(exports, "Toggle", {
4050
+ enumerable: true,
4051
+ get: function() {
4052
+ return Toggle;
4053
+ }
4054
+ });
4055
+ Object.defineProperty(exports, "ToggleGroup", {
4056
+ enumerable: true,
4057
+ get: function() {
4058
+ return ToggleGroup;
4059
+ }
4060
+ });
4061
+ Object.defineProperty(exports, "VirtualList", {
4062
+ enumerable: true,
4063
+ get: function() {
4064
+ return VirtualList;
4065
+ }
4066
+ });
4067
+ Object.defineProperty(exports, "createBlock", {
4068
+ enumerable: true,
4069
+ get: function() {
4070
+ return createBlock;
4071
+ }
4072
+ });
4073
+ Object.defineProperty(exports, "formatOptDateTime", {
4074
+ enumerable: true,
4075
+ get: function() {
4076
+ return formatOptDateTime;
4077
+ }
4078
+ });
4079
+ Object.defineProperty(exports, "formatOptNumber", {
4080
+ enumerable: true,
4081
+ get: function() {
4082
+ return formatOptNumber;
4083
+ }
4084
+ });
4085
+ Object.defineProperty(exports, "formatOptShortDate", {
4086
+ enumerable: true,
4087
+ get: function() {
4088
+ return formatOptShortDate;
4089
+ }
4090
+ });
4091
+ Object.defineProperty(exports, "formatOptTime", {
4092
+ enumerable: true,
4093
+ get: function() {
4094
+ return formatOptTime;
4095
+ }
4096
+ });
4097
+ Object.defineProperty(exports, "getShaderFragment", {
4098
+ enumerable: true,
4099
+ get: function() {
4100
+ return getShaderFragment;
4101
+ }
4102
+ });
4103
+ Object.defineProperty(exports, "getShaderPreset", {
4104
+ enumerable: true,
4105
+ get: function() {
4106
+ return getShaderPreset;
4107
+ }
4108
+ });