@reopt-ai/opt-ui 1.12.5 → 1.13.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 (39) hide show
  1. package/CHANGELOG.md +236 -0
  2. package/COMPONENT_CATALOG.md +290 -111
  3. package/dist/core/index.cjs +13 -13
  4. package/dist/core/index.d.cts +2 -2
  5. package/dist/core/index.d.ts +2 -2
  6. package/dist/core/index.js +2 -2
  7. package/dist/docs/02-components/01-core.md +49 -49
  8. package/dist/docs/02-components/02-visuals.md +1 -1
  9. package/dist/docs/02-components/03-shells.md +260 -63
  10. package/dist/docs/02-components/04-surfaces.md +1 -1
  11. package/dist/docs/02-components/index.md +4 -4
  12. package/dist/{field-sidebar-Ben7MQD4.js → field-sidebar-CRdToHRO.js} +3975 -235
  13. package/dist/{field-sidebar-DwtrYSSt.cjs → field-sidebar-CxxSK4JO.cjs} +4338 -244
  14. package/dist/{field-sidebar-Ct8c9L4V.d.cts → field-sidebar-D-rwuN_w.d.cts} +824 -2
  15. package/dist/{field-sidebar-YaWHfLLW.d.ts → field-sidebar-Dz7J4ett.d.ts} +824 -2
  16. package/dist/id-registry.cjs +72 -0
  17. package/dist/id-registry.js +72 -0
  18. package/dist/id-registry.json +153 -0
  19. package/dist/index.cjs +334 -1419
  20. package/dist/index.d.cts +51 -86
  21. package/dist/index.d.ts +51 -86
  22. package/dist/index.js +248 -1356
  23. package/dist/{key-pad-menu-BpQebDyw.cjs → key-pad-menu-0KWOnELe.cjs} +51 -481
  24. package/dist/{key-pad-menu-CwcY_Vps.d.cts → key-pad-menu-BOVu97bj.d.cts} +4 -55
  25. package/dist/{key-pad-menu-CYYtS_Tl.js → key-pad-menu-DMmbQ1jF.js} +52 -416
  26. package/dist/{key-pad-menu-WBJShCJn.d.ts → key-pad-menu-NlZ9zNF8.d.ts} +4 -55
  27. package/dist/meta.cjs +896 -7
  28. package/dist/meta.js +896 -7
  29. package/dist/shells/index.cjs +20 -1
  30. package/dist/shells/index.d.cts +2 -2
  31. package/dist/shells/index.d.ts +2 -2
  32. package/dist/shells/index.js +2 -2
  33. package/dist/{text-truncate-Dlm7JwDf.js → text-truncate-Bd-0WkSP.js} +461 -97
  34. package/dist/{text-truncate-CqdiQuj8.cjs → text-truncate-BeYW6XZu.cjs} +523 -99
  35. package/dist/{text-truncate-CQyfUZvq.d.cts → text-truncate-eMzvU_7k.d.cts} +52 -1
  36. package/dist/{text-truncate-CQyfUZvq.d.ts → text-truncate-eMzvU_7k.d.ts} +52 -1
  37. package/dist/theme/server.cjs +2 -2
  38. package/dist/theme/server.js +2 -2
  39. package/package.json +6 -2
package/dist/index.cjs CHANGED
@@ -1,114 +1,16 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_text_truncate = require("./text-truncate-CqdiQuj8.cjs");
4
- const require_key_pad_menu = require("./key-pad-menu-BpQebDyw.cjs");
5
- const require_field_sidebar = require("./field-sidebar-DwtrYSSt.cjs");
3
+ const require_text_truncate = require("./text-truncate-BeYW6XZu.cjs");
4
+ const require_key_pad_menu = require("./key-pad-menu-0KWOnELe.cjs");
5
+ const require_field_sidebar = require("./field-sidebar-CxxSK4JO.cjs");
6
6
  let react_jsx_runtime = require("react/jsx-runtime");
7
7
  let react = require("react");
8
8
  react = require_text_truncate.__toESM(react, 1);
9
- let _reopt_ai_opt_ui_primitives = require("@reopt-ai/opt-ui-primitives");
10
9
  let lucide_react = require("lucide-react");
11
- let _reopt_ai_opt_palette = require("@reopt-ai/opt-palette");
12
10
  let _reopt_ai_opt_charts = require("@reopt-ai/opt-charts");
13
11
  let match_sorter = require("match-sorter");
14
12
  let next_navigation = require("next/navigation");
15
- //#region src/core/callout.tsx
16
- const _excluded$2 = [
17
- "tone",
18
- "title",
19
- "icon",
20
- "action",
21
- "size",
22
- "className",
23
- "children"
24
- ];
25
- const toneStyles = {
26
- info: "border-info/40 bg-info-subtle",
27
- success: "border-success/40 bg-success-subtle",
28
- warning: "border-warning/40 bg-warning-subtle",
29
- danger: "border-danger/40 bg-danger-subtle",
30
- neutral: "border-border bg-bg-subtle"
31
- };
32
- const iconTone = {
33
- info: "text-info-fg",
34
- success: "text-success-fg",
35
- warning: "text-warning-fg",
36
- danger: "text-danger-fg",
37
- neutral: "text-text-tertiary"
38
- };
39
- const titleTone = {
40
- info: "text-info-fg",
41
- success: "text-success-fg",
42
- warning: "text-warning-fg",
43
- danger: "text-danger-fg",
44
- neutral: "text-text-primary"
45
- };
46
- const defaultIcons = {
47
- info: lucide_react.Info,
48
- success: lucide_react.CircleCheck,
49
- warning: lucide_react.TriangleAlert,
50
- danger: lucide_react.CircleAlert,
51
- neutral: null
52
- };
53
- const sizeStyles$3 = {
54
- sm: "gap-2 p-2.5 text-xs [&_svg]:size-3.5",
55
- md: "gap-3 p-3 text-sm [&_svg]:size-4"
56
- };
57
- /**
58
- * Callout — a notice that belongs to the page, not to the moment.
59
- *
60
- * `Alert` reports something that just happened and can be dismissed once read.
61
- * A callout is the opposite: it is part of the layout, it is true for as long
62
- * as the condition holds, and dismissing it would only hide a fact that is
63
- * still true. "12 new events to triage" above a list, or "these numbers come
64
- * from a 10,000-row sample" above a chart — both are read many times and
65
- * dismissed never.
66
- *
67
- * That is why there is no `onDismiss` here, and why `action` takes one control:
68
- * a notice earns its space by naming the single thing to do about it.
69
- *
70
- * @example
71
- * ```tsx
72
- * <Callout tone="info" title="정리할 신규 이벤트 12개"
73
- * action={<Button size="sm" onClick={showNew}>보기</Button>}>
74
- * 7일 안에 처음 관측된 이벤트입니다.
75
- * </Callout>
76
- * ```
77
- */
78
- function Callout(_ref) {
79
- let { tone = "info", title, icon, action, size = "md", className, children } = _ref, props = require_text_truncate._objectWithoutProperties(_ref, _excluded$2);
80
- const DefaultIcon = defaultIcons[tone];
81
- const glyph = icon === void 0 ? DefaultIcon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultIcon, { "aria-hidden": "true" }) : null : icon;
82
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({
83
- role: "status",
84
- className: require_text_truncate.cn("flex items-start rounded-lg border", toneStyles[tone], sizeStyles$3[size], className)
85
- }, props), {}, {
86
- "data-opt-id": "AT7TX",
87
- "data-opt-slug": "callout.Callout",
88
- "data-tone": tone,
89
- children: [
90
- glyph && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
91
- className: require_text_truncate.cn("mt-0.5 shrink-0", iconTone[tone]),
92
- children: glyph
93
- }),
94
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
95
- className: "min-w-0 flex-1",
96
- children: [title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
97
- className: require_text_truncate.cn("font-medium", titleTone[tone]),
98
- children: title
99
- }), children && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
100
- className: require_text_truncate.cn("text-text-secondary", title && "mt-1"),
101
- children
102
- })]
103
- }),
104
- action && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
105
- className: "shrink-0 self-center",
106
- children: action
107
- })
108
- ]
109
- }));
110
- }
111
- //#endregion
13
+ let _reopt_ai_opt_ui_primitives = require("@reopt-ai/opt-ui-primitives");
112
14
  //#region src/core/status-dot.tsx
113
15
  const _excluded$1 = [
114
16
  "tone",
@@ -133,7 +35,7 @@ const textTone = {
133
35
  warning: "text-text-secondary",
134
36
  danger: "text-text-secondary"
135
37
  };
136
- const sizeStyles$2 = {
38
+ const sizeStyles$1 = {
137
39
  sm: "gap-1.5 text-[11px]",
138
40
  md: "gap-2 text-xs"
139
41
  };
@@ -164,7 +66,7 @@ const dotSize = {
164
66
  function StatusDot(_ref) {
165
67
  let { tone = "neutral", size = "md", hint, className, children } = _ref, props = require_text_truncate._objectWithoutProperties(_ref, _excluded$1);
166
68
  const dot = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({
167
- className: require_text_truncate.cn("inline-flex items-center whitespace-nowrap", sizeStyles$2[size], textTone[tone], hint && "focus-visible:ring-ring rounded-sm outline-none focus-visible:ring-2", className),
69
+ className: require_text_truncate.cn("inline-flex items-center whitespace-nowrap", sizeStyles$1[size], textTone[tone], hint && "focus-visible:ring-ring rounded-sm outline-none focus-visible:ring-2", className),
168
70
  tabIndex: hint ? 0 : void 0
169
71
  }, props), {}, {
170
72
  "data-opt-id": "N51AT",
@@ -191,12 +93,12 @@ const _excluded = [
191
93
  "disabled",
192
94
  "onClick"
193
95
  ];
194
- const defaultLabels$35 = {
96
+ const defaultLabels$33 = {
195
97
  copy: "복사",
196
98
  copied: "복사됨",
197
99
  failed: "복사할 수 없습니다"
198
100
  };
199
- const sizeStyles$1 = {
101
+ const sizeStyles = {
200
102
  sm: "h-6 gap-1 text-[11px] [&>svg]:size-3",
201
103
  md: "h-7 gap-1.5 text-xs [&>svg]:size-3.5"
202
104
  };
@@ -238,7 +140,7 @@ const stateTone = {
238
140
  */
239
141
  function CopyButton(_ref) {
240
142
  let { value, variant = "icon", size = "md", feedbackDuration = 1500, onCopy, labels: customLabels, className, disabled, onClick } = _ref, props = require_text_truncate._objectWithoutProperties(_ref, _excluded);
241
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$35), customLabels);
143
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$33), customLabels);
242
144
  const [state, setState] = (0, react.useState)("idle");
243
145
  const timer = (0, react.useRef)(null);
244
146
  (0, react.useEffect)(() => () => {
@@ -271,7 +173,7 @@ function CopyButton(_ref) {
271
173
  onClick: handleClick,
272
174
  disabled,
273
175
  "aria-label": variant === "icon" ? label : void 0,
274
- className: require_text_truncate.cn("inline-flex shrink-0 items-center rounded transition-colors", "disabled:pointer-events-none disabled:opacity-50", require_text_truncate.OPT_FOCUS_VISIBLE, sizeStyles$1[size], paddingStyles[variant][size], stateTone[state], className)
176
+ className: require_text_truncate.cn("inline-flex shrink-0 items-center rounded transition-colors", "disabled:pointer-events-none disabled:opacity-50", require_text_truncate.OPT_FOCUS_VISIBLE, sizeStyles[size], paddingStyles[variant][size], stateTone[state], className)
275
177
  }, props), {}, {
276
178
  "data-opt-id": "E0C8T",
277
179
  "data-opt-slug": "copy-button.CopyButton",
@@ -289,76 +191,6 @@ function CopyButton(_ref) {
289
191
  }));
290
192
  }
291
193
  //#endregion
292
- //#region src/core/segmented-control.tsx
293
- const sizeStyles = {
294
- sm: "h-7 text-[11px] [&_svg]:size-3",
295
- md: "h-8 text-xs [&_svg]:size-3.5"
296
- };
297
- const segmentPadding = {
298
- sm: "gap-1 px-2",
299
- md: "gap-1.5 px-2.5"
300
- };
301
- /**
302
- * SegmentedControl — one of a few views, all of them visible.
303
- *
304
- * A `Select` hides the alternatives behind a click; a `ToggleGroup` presses
305
- * buttons that may be on together. Neither is what "이벤트 | 속성" is: exactly
306
- * one is true, the set is small enough to show, and the reader is choosing a
307
- * view rather than filtering anything.
308
- *
309
- * Built on the radio-group primitive rather than on buttons, so the arrow keys,
310
- * the group name and the checked state come from the platform. A control that
311
- * merely looks like a radiogroup is one a keyboard cannot drive.
312
- *
313
- * @example
314
- * ```tsx
315
- * <SegmentedControl
316
- * aria-label="카탈로그 탭"
317
- * options={[
318
- * { value: "events", label: "이벤트", badge: 128 },
319
- * { value: "properties", label: "속성", badge: 341 },
320
- * ]}
321
- * value={tab}
322
- * onChange={setTab}
323
- * />
324
- * ```
325
- */
326
- function SegmentedControl({ options, value, onChange, size = "md", fullWidth = false, disabled = false, "aria-label": ariaLabel, className }) {
327
- const name = (0, react.useId)();
328
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.RadioGroupRoot, {
329
- value,
330
- onValueChange: (next) => onChange(next),
331
- disabled,
332
- orientation: "horizontal",
333
- name,
334
- "aria-label": ariaLabel,
335
- className: require_text_truncate.cn("inline-flex items-center rounded-lg border border-border bg-bg-subtle p-0.5", fullWidth && "flex w-full", sizeStyles[size], className),
336
- "data-opt-id": "YKENE",
337
- "data-opt-slug": "segmented-control.SegmentedControl",
338
- children: options.map((option) => {
339
- const selected = option.value === value;
340
- const itemDisabled = disabled || option.disabled;
341
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
342
- className: require_text_truncate.cn("relative inline-flex h-full cursor-pointer items-center justify-center", "rounded-md font-medium whitespace-nowrap transition-colors", "has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-ring has-[:focus-visible]:ring-offset-1 has-[:focus-visible]:ring-offset-ring-offset", segmentPadding[size], fullWidth && "flex-1", selected ? "bg-surface text-text-primary shadow-sm" : "text-text-tertiary hover:text-text-secondary", itemDisabled && "pointer-events-none opacity-50"),
343
- "data-selected": selected || void 0,
344
- children: [
345
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.Radio, {
346
- value: option.value,
347
- disabled: itemDisabled,
348
- className: "absolute inset-0 m-0 h-full w-full cursor-pointer opacity-0"
349
- }),
350
- option.icon,
351
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: option.label }),
352
- option.badge != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
353
- className: require_text_truncate.cn("tabular-nums", selected ? "text-text-tertiary" : "text-text-tertiary/70"),
354
- children: option.badge
355
- })
356
- ]
357
- }, option.value);
358
- })
359
- });
360
- }
361
- //#endregion
362
194
  //#region src/lib/schema-validator.ts
363
195
  /** Handles schema validator. */
364
196
  function schemaValidator(schema) {
@@ -433,7 +265,7 @@ function PageAside({ header, children, footer, widthClassName = "w-60", label, h
433
265
  PageAside.displayName = "PageAside";
434
266
  //#endregion
435
267
  //#region src/shells/task-list.tsx
436
- const defaultLabels$34 = {
268
+ const defaultLabels$32 = {
437
269
  title: "작업 목록",
438
270
  emptyMessage: "작업이 없습니다",
439
271
  completedOf: "{completed}/{total} 완료",
@@ -453,9 +285,9 @@ const defaultLabels$34 = {
453
285
  };
454
286
  /** Renders the task list component. */
455
287
  function TaskList({ tasks, title, onTaskClick, onTaskStatusChange, emptyMessage, showSubtasks = false, maxItems, labels: customLabels, className }) {
456
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$34), customLabels), {}, {
457
- priority: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$34.priority), customLabels === null || customLabels === void 0 ? void 0 : customLabels.priority),
458
- status: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$34.status), customLabels === null || customLabels === void 0 ? void 0 : customLabels.status)
288
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$32), customLabels), {}, {
289
+ priority: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$32.priority), customLabels === null || customLabels === void 0 ? void 0 : customLabels.priority),
290
+ status: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$32.status), customLabels === null || customLabels === void 0 ? void 0 : customLabels.status)
459
291
  });
460
292
  const displayTitle = title !== null && title !== void 0 ? title : labels.title;
461
293
  const displayEmptyMessage = emptyMessage !== null && emptyMessage !== void 0 ? emptyMessage : labels.emptyMessage;
@@ -613,7 +445,7 @@ function TaskList({ tasks, title, onTaskClick, onTaskStatusChange, emptyMessage,
613
445
  }
614
446
  //#endregion
615
447
  //#region src/shells/activity-feed.tsx
616
- const defaultLabels$33 = {
448
+ const defaultLabels$31 = {
617
449
  title: "활동 피드",
618
450
  emptyMessage: "활동이 없습니다",
619
451
  moreItems: "{count}개 더 보기",
@@ -663,24 +495,24 @@ const variantBorder = {
663
495
  function ActivityFeed({ activities, title, maxItems, onActivityClick, onShowMore, emptyMessage, labels: customLabels, locale = "ko-KR", loading = false, layout = "list", renderActions, className }) {
664
496
  var _customLabels$timeAgo, _customLabels$timeAgo2, _customLabels$timeAgo3, _customLabels$timeAgo4, _customLabels$timeAgo5, _customLabels$timeAgo6, _customLabels$timeAgo7, _customLabels$timeAgo8, _customLabels$activit, _customLabels$activit2, _customLabels$activit3, _customLabels$activit4, _customLabels$activit5, _customLabels$activit6, _customLabels$activit7, _customLabels$activit8, _customLabels$activit9, _customLabels$activit10, _customLabels$activit11, _customLabels$activit12, _customLabels$activit13, _customLabels$activit14, _customLabels$title, _customLabels$emptyMe, _customLabels$moreIte;
665
497
  const mergedTimeAgo = {
666
- justNow: (_customLabels$timeAgo = customLabels === null || customLabels === void 0 || (_customLabels$timeAgo2 = customLabels.timeAgo) === null || _customLabels$timeAgo2 === void 0 ? void 0 : _customLabels$timeAgo2.justNow) !== null && _customLabels$timeAgo !== void 0 ? _customLabels$timeAgo : defaultLabels$33.timeAgo.justNow,
667
- minutesAgo: (_customLabels$timeAgo3 = customLabels === null || customLabels === void 0 || (_customLabels$timeAgo4 = customLabels.timeAgo) === null || _customLabels$timeAgo4 === void 0 ? void 0 : _customLabels$timeAgo4.minutesAgo) !== null && _customLabels$timeAgo3 !== void 0 ? _customLabels$timeAgo3 : defaultLabels$33.timeAgo.minutesAgo,
668
- hoursAgo: (_customLabels$timeAgo5 = customLabels === null || customLabels === void 0 || (_customLabels$timeAgo6 = customLabels.timeAgo) === null || _customLabels$timeAgo6 === void 0 ? void 0 : _customLabels$timeAgo6.hoursAgo) !== null && _customLabels$timeAgo5 !== void 0 ? _customLabels$timeAgo5 : defaultLabels$33.timeAgo.hoursAgo,
669
- daysAgo: (_customLabels$timeAgo7 = customLabels === null || customLabels === void 0 || (_customLabels$timeAgo8 = customLabels.timeAgo) === null || _customLabels$timeAgo8 === void 0 ? void 0 : _customLabels$timeAgo8.daysAgo) !== null && _customLabels$timeAgo7 !== void 0 ? _customLabels$timeAgo7 : defaultLabels$33.timeAgo.daysAgo
498
+ justNow: (_customLabels$timeAgo = customLabels === null || customLabels === void 0 || (_customLabels$timeAgo2 = customLabels.timeAgo) === null || _customLabels$timeAgo2 === void 0 ? void 0 : _customLabels$timeAgo2.justNow) !== null && _customLabels$timeAgo !== void 0 ? _customLabels$timeAgo : defaultLabels$31.timeAgo.justNow,
499
+ minutesAgo: (_customLabels$timeAgo3 = customLabels === null || customLabels === void 0 || (_customLabels$timeAgo4 = customLabels.timeAgo) === null || _customLabels$timeAgo4 === void 0 ? void 0 : _customLabels$timeAgo4.minutesAgo) !== null && _customLabels$timeAgo3 !== void 0 ? _customLabels$timeAgo3 : defaultLabels$31.timeAgo.minutesAgo,
500
+ hoursAgo: (_customLabels$timeAgo5 = customLabels === null || customLabels === void 0 || (_customLabels$timeAgo6 = customLabels.timeAgo) === null || _customLabels$timeAgo6 === void 0 ? void 0 : _customLabels$timeAgo6.hoursAgo) !== null && _customLabels$timeAgo5 !== void 0 ? _customLabels$timeAgo5 : defaultLabels$31.timeAgo.hoursAgo,
501
+ daysAgo: (_customLabels$timeAgo7 = customLabels === null || customLabels === void 0 || (_customLabels$timeAgo8 = customLabels.timeAgo) === null || _customLabels$timeAgo8 === void 0 ? void 0 : _customLabels$timeAgo8.daysAgo) !== null && _customLabels$timeAgo7 !== void 0 ? _customLabels$timeAgo7 : defaultLabels$31.timeAgo.daysAgo
670
502
  };
671
503
  const mergedActivityVerbs = {
672
- created: (_customLabels$activit = customLabels === null || customLabels === void 0 || (_customLabels$activit2 = customLabels.activityVerbs) === null || _customLabels$activit2 === void 0 ? void 0 : _customLabels$activit2.created) !== null && _customLabels$activit !== void 0 ? _customLabels$activit : defaultLabels$33.activityVerbs.created,
673
- updated: (_customLabels$activit3 = customLabels === null || customLabels === void 0 || (_customLabels$activit4 = customLabels.activityVerbs) === null || _customLabels$activit4 === void 0 ? void 0 : _customLabels$activit4.updated) !== null && _customLabels$activit3 !== void 0 ? _customLabels$activit3 : defaultLabels$33.activityVerbs.updated,
674
- completed: (_customLabels$activit5 = customLabels === null || customLabels === void 0 || (_customLabels$activit6 = customLabels.activityVerbs) === null || _customLabels$activit6 === void 0 ? void 0 : _customLabels$activit6.completed) !== null && _customLabels$activit5 !== void 0 ? _customLabels$activit5 : defaultLabels$33.activityVerbs.completed,
675
- commented: (_customLabels$activit7 = customLabels === null || customLabels === void 0 || (_customLabels$activit8 = customLabels.activityVerbs) === null || _customLabels$activit8 === void 0 ? void 0 : _customLabels$activit8.commented) !== null && _customLabels$activit7 !== void 0 ? _customLabels$activit7 : defaultLabels$33.activityVerbs.commented,
676
- assigned: (_customLabels$activit9 = customLabels === null || customLabels === void 0 || (_customLabels$activit10 = customLabels.activityVerbs) === null || _customLabels$activit10 === void 0 ? void 0 : _customLabels$activit10.assigned) !== null && _customLabels$activit9 !== void 0 ? _customLabels$activit9 : defaultLabels$33.activityVerbs.assigned,
677
- deployed: (_customLabels$activit11 = customLabels === null || customLabels === void 0 || (_customLabels$activit12 = customLabels.activityVerbs) === null || _customLabels$activit12 === void 0 ? void 0 : _customLabels$activit12.deployed) !== null && _customLabels$activit11 !== void 0 ? _customLabels$activit11 : defaultLabels$33.activityVerbs.deployed,
678
- merged: (_customLabels$activit13 = customLabels === null || customLabels === void 0 || (_customLabels$activit14 = customLabels.activityVerbs) === null || _customLabels$activit14 === void 0 ? void 0 : _customLabels$activit14.merged) !== null && _customLabels$activit13 !== void 0 ? _customLabels$activit13 : defaultLabels$33.activityVerbs.merged
504
+ created: (_customLabels$activit = customLabels === null || customLabels === void 0 || (_customLabels$activit2 = customLabels.activityVerbs) === null || _customLabels$activit2 === void 0 ? void 0 : _customLabels$activit2.created) !== null && _customLabels$activit !== void 0 ? _customLabels$activit : defaultLabels$31.activityVerbs.created,
505
+ updated: (_customLabels$activit3 = customLabels === null || customLabels === void 0 || (_customLabels$activit4 = customLabels.activityVerbs) === null || _customLabels$activit4 === void 0 ? void 0 : _customLabels$activit4.updated) !== null && _customLabels$activit3 !== void 0 ? _customLabels$activit3 : defaultLabels$31.activityVerbs.updated,
506
+ completed: (_customLabels$activit5 = customLabels === null || customLabels === void 0 || (_customLabels$activit6 = customLabels.activityVerbs) === null || _customLabels$activit6 === void 0 ? void 0 : _customLabels$activit6.completed) !== null && _customLabels$activit5 !== void 0 ? _customLabels$activit5 : defaultLabels$31.activityVerbs.completed,
507
+ commented: (_customLabels$activit7 = customLabels === null || customLabels === void 0 || (_customLabels$activit8 = customLabels.activityVerbs) === null || _customLabels$activit8 === void 0 ? void 0 : _customLabels$activit8.commented) !== null && _customLabels$activit7 !== void 0 ? _customLabels$activit7 : defaultLabels$31.activityVerbs.commented,
508
+ assigned: (_customLabels$activit9 = customLabels === null || customLabels === void 0 || (_customLabels$activit10 = customLabels.activityVerbs) === null || _customLabels$activit10 === void 0 ? void 0 : _customLabels$activit10.assigned) !== null && _customLabels$activit9 !== void 0 ? _customLabels$activit9 : defaultLabels$31.activityVerbs.assigned,
509
+ deployed: (_customLabels$activit11 = customLabels === null || customLabels === void 0 || (_customLabels$activit12 = customLabels.activityVerbs) === null || _customLabels$activit12 === void 0 ? void 0 : _customLabels$activit12.deployed) !== null && _customLabels$activit11 !== void 0 ? _customLabels$activit11 : defaultLabels$31.activityVerbs.deployed,
510
+ merged: (_customLabels$activit13 = customLabels === null || customLabels === void 0 || (_customLabels$activit14 = customLabels.activityVerbs) === null || _customLabels$activit14 === void 0 ? void 0 : _customLabels$activit14.merged) !== null && _customLabels$activit13 !== void 0 ? _customLabels$activit13 : defaultLabels$31.activityVerbs.merged
679
511
  };
680
512
  const labels = {
681
- title: (_customLabels$title = customLabels === null || customLabels === void 0 ? void 0 : customLabels.title) !== null && _customLabels$title !== void 0 ? _customLabels$title : defaultLabels$33.title,
682
- emptyMessage: (_customLabels$emptyMe = customLabels === null || customLabels === void 0 ? void 0 : customLabels.emptyMessage) !== null && _customLabels$emptyMe !== void 0 ? _customLabels$emptyMe : defaultLabels$33.emptyMessage,
683
- moreItems: (_customLabels$moreIte = customLabels === null || customLabels === void 0 ? void 0 : customLabels.moreItems) !== null && _customLabels$moreIte !== void 0 ? _customLabels$moreIte : defaultLabels$33.moreItems,
513
+ title: (_customLabels$title = customLabels === null || customLabels === void 0 ? void 0 : customLabels.title) !== null && _customLabels$title !== void 0 ? _customLabels$title : defaultLabels$31.title,
514
+ emptyMessage: (_customLabels$emptyMe = customLabels === null || customLabels === void 0 ? void 0 : customLabels.emptyMessage) !== null && _customLabels$emptyMe !== void 0 ? _customLabels$emptyMe : defaultLabels$31.emptyMessage,
515
+ moreItems: (_customLabels$moreIte = customLabels === null || customLabels === void 0 ? void 0 : customLabels.moreItems) !== null && _customLabels$moreIte !== void 0 ? _customLabels$moreIte : defaultLabels$31.moreItems,
684
516
  timeAgo: mergedTimeAgo,
685
517
  activityVerbs: mergedActivityVerbs
686
518
  };
@@ -808,13 +640,13 @@ function ActivityFeed({ activities, title, maxItems, onActivityClick, onShowMore
808
640
  ActivityFeed.displayName = "ActivityFeed";
809
641
  //#endregion
810
642
  //#region src/shells/filter-bar.tsx
811
- const defaultLabels$32 = {
643
+ const defaultLabels$30 = {
812
644
  clearAll: "필터 초기화",
813
645
  searchPlaceholder: "검색..."
814
646
  };
815
647
  /** Renders the filter bar component. */
816
648
  function FilterBar({ filters, onFilterChange, onDateRangeChange, onClearAll, labels: customLabels, presetActions, className }) {
817
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$32), customLabels);
649
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$30), customLabels);
818
650
  const [searchValues, setSearchValues] = (0, react.useState)({});
819
651
  const [tagInputValues, setTagInputValues] = (0, react.useState)({});
820
652
  const [multiSelectOpen, setMultiSelectOpen] = (0, react.useState)({});
@@ -1001,7 +833,7 @@ function FilterBar({ filters, onFilterChange, onDateRangeChange, onClearAll, lab
1001
833
  })]
1002
834
  }, filter.id);
1003
835
  }
1004
- if (filter.type === "toggle") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.Switch, {
836
+ if (filter.type === "toggle") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.Switch, {
1005
837
  label: filter.label,
1006
838
  size: "sm",
1007
839
  checked: filter.value === true,
@@ -1040,10 +872,10 @@ function matchesShortcut(event, shortcut) {
1040
872
  if (requiresMeta && !event.metaKey) return false;
1041
873
  return event.key.toLowerCase() === key;
1042
874
  }
1043
- const defaultLabels$31 = { title: "빠른 작업" };
875
+ const defaultLabels$29 = { title: "빠른 작업" };
1044
876
  /** Renders the quick actions component. */
1045
877
  function QuickActions({ actions, title, layout = "grid", columns = 3, showDescriptionInGrid = false, bindShortcuts = false, labels: customLabels, className }) {
1046
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$31), customLabels);
878
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$29), customLabels);
1047
879
  const displayTitle = title !== null && title !== void 0 ? title : labels.title;
1048
880
  const titleId = (0, react.useId)();
1049
881
  (0, react.useEffect)(() => {
@@ -1121,7 +953,7 @@ function QuickActions({ actions, title, layout = "grid", columns = 3, showDescri
1121
953
  QuickActions.displayName = "QuickActions";
1122
954
  //#endregion
1123
955
  //#region src/shells/team-member-list.tsx
1124
- const defaultLabels$30 = {
956
+ const defaultLabels$28 = {
1125
957
  title: "팀원",
1126
958
  emptyMessage: "팀원이 없습니다",
1127
959
  onlineCount: "{online}/{total} 온라인",
@@ -1142,7 +974,7 @@ const statusDot = {
1142
974
  };
1143
975
  /** Renders the team member list component. */
1144
976
  function TeamMemberList({ members, title, layout = "list", maxDisplay, onMemberClick, onShowMore, emptyMessage, labels: customLabels, className }) {
1145
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$30), customLabels), {}, { status: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$30.status), customLabels === null || customLabels === void 0 ? void 0 : customLabels.status) });
977
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$28), customLabels), {}, { status: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$28.status), customLabels === null || customLabels === void 0 ? void 0 : customLabels.status) });
1146
978
  const displayTitle = title !== null && title !== void 0 ? title : labels.title;
1147
979
  const displayEmptyMessage = emptyMessage !== null && emptyMessage !== void 0 ? emptyMessage : labels.emptyMessage;
1148
980
  const titleId = (0, react.useId)();
@@ -2042,7 +1874,7 @@ const COLOR_PRESETS = [
2042
1874
  "#f97316",
2043
1875
  "#14b8a6"
2044
1876
  ];
2045
- const defaultLabels$29 = {
1877
+ const defaultLabels$27 = {
2046
1878
  eventLabelPrefix: "Event",
2047
1879
  defaultAriaLabel: "Event icon"
2048
1880
  };
@@ -2073,7 +1905,7 @@ function getEventIconStyle(color) {
2073
1905
  /** Renders the event icon component. */
2074
1906
  function EventIcon({ icon, color, size = "md", className, labels: customLabels }) {
2075
1907
  var _iconEntry$label;
2076
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$29), customLabels);
1908
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$27), customLabels);
2077
1909
  const sizes = SIZE_MAP[size];
2078
1910
  const resolvedColor = (color === null || color === void 0 ? void 0 : color.trim()) ? color : void 0;
2079
1911
  const iconEntry = typeof icon === "string" ? require_text_truncate.getIconRegistryEntry(icon) : void 0;
@@ -2165,14 +1997,14 @@ function ConnectionIndicator({ status, tone, label, showLabel = true, pulse, cla
2165
1997
  ConnectionIndicator.displayName = "ConnectionIndicator";
2166
1998
  //#endregion
2167
1999
  //#region src/shells/floating-action-bar.tsx
2168
- const defaultLabels$28 = {
2000
+ const defaultLabels$26 = {
2169
2001
  toolbarAriaLabel: "Actions",
2170
2002
  selectedLabel: (count) => `${count} selected`,
2171
2003
  dismissAriaLabel: "Dismiss"
2172
2004
  };
2173
2005
  /** Renders the floating action bar component. */
2174
2006
  function FloatingActionBar({ actions, selectedCount, onAction, onDismiss, className, labels: customLabels }) {
2175
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$28), customLabels);
2007
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$26), customLabels);
2176
2008
  if (actions.length === 0) return null;
2177
2009
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2178
2010
  role: "toolbar",
@@ -2209,7 +2041,7 @@ function FloatingActionBar({ actions, selectedCount, onAction, onDismiss, classN
2209
2041
  FloatingActionBar.displayName = "FloatingActionBar";
2210
2042
  //#endregion
2211
2043
  //#region src/shells/template-picker.tsx
2212
- const defaultLabels$27 = {
2044
+ const defaultLabels$25 = {
2213
2045
  ariaLabel: "Templates",
2214
2046
  defaultCategory: "General",
2215
2047
  searchPlaceholder: "Search templates...",
@@ -2217,7 +2049,7 @@ const defaultLabels$27 = {
2217
2049
  };
2218
2050
  /** Renders the template picker component. */
2219
2051
  function TemplatePicker({ templates, selected, onSelect, labels: customLabels, showSearch = false, className }) {
2220
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$27), customLabels);
2052
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$25), customLabels);
2221
2053
  const [search, setSearch] = react.useState("");
2222
2054
  const filtered = react.useMemo(() => {
2223
2055
  if (!showSearch || !search) return templates;
@@ -2303,7 +2135,7 @@ function TemplatePicker({ templates, selected, onSelect, labels: customLabels, s
2303
2135
  TemplatePicker.displayName = "TemplatePicker";
2304
2136
  //#endregion
2305
2137
  //#region src/shells/code-snippet-viewer.tsx
2306
- const defaultLabels$26 = {
2138
+ const defaultLabels$24 = {
2307
2139
  copy: "Copy",
2308
2140
  copied: "Copied!",
2309
2141
  codeRegion: "Code snippet"
@@ -2341,7 +2173,7 @@ const syntaxThemeClasses = {
2341
2173
  /** Renders the code snippet viewer component. */
2342
2174
  function CodeSnippetViewer({ code, language = "text", title, showLineNumbers = true, showCopyButton = true, maxHeight = 400, syntaxTheme = "default", className, labels: customLabels }) {
2343
2175
  var _syntaxThemeClasses$s;
2344
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$26), customLabels);
2176
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$24), customLabels);
2345
2177
  const [copied, setCopied] = react.useState(false);
2346
2178
  const lines = code.split("\n");
2347
2179
  const theme = (_syntaxThemeClasses$s = syntaxThemeClasses[syntaxTheme]) !== null && _syntaxThemeClasses$s !== void 0 ? _syntaxThemeClasses$s : syntaxThemeClasses.default;
@@ -2393,7 +2225,7 @@ function CodeSnippetViewer({ code, language = "text", title, showLineNumbers = t
2393
2225
  CodeSnippetViewer.displayName = "CodeSnippetViewer";
2394
2226
  //#endregion
2395
2227
  //#region src/shells/property-explorer.tsx
2396
- const defaultLabels$25 = {
2228
+ const defaultLabels$23 = {
2397
2229
  searchPlaceholder: "Search properties...",
2398
2230
  noPropertiesFound: "No properties found",
2399
2231
  edit: (property) => `${property} 편집`,
@@ -2401,7 +2233,7 @@ const defaultLabels$25 = {
2401
2233
  };
2402
2234
  /** Renders the property explorer component. */
2403
2235
  function PropertyExplorer({ groups, onSelect, onEdit, className, labels: customLabels }) {
2404
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$25), customLabels);
2236
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$23), customLabels);
2405
2237
  const [search, setSearch] = react.useState("");
2406
2238
  const filtered = react.useMemo(() => {
2407
2239
  if (!search) return groups;
@@ -2485,99 +2317,209 @@ function PropertyExplorer({ groups, onSelect, onEdit, className, labels: customL
2485
2317
  }
2486
2318
  PropertyExplorer.displayName = "PropertyExplorer";
2487
2319
  //#endregion
2488
- //#region src/shells/query-results-table.tsx
2489
- const defaultLabels$24 = {
2490
- emptyMessage: "No results",
2491
- loadingMessage: "Running query...",
2492
- rowsSuffix: "row(s)"
2493
- };
2494
- /** Renders the query results table component. */
2495
- function QueryResultsTable({ columns, rows, maxHeight = 400, emptyMessage, loading = false, error, labels: customLabels, className }) {
2496
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$24), customLabels);
2497
- if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2498
- className: require_text_truncate.cn("border-danger bg-danger-subtle rounded-lg border p-4", className),
2499
- role: "alert",
2500
- "aria-live": "assertive",
2501
- "data-opt-id": "PNC1V",
2502
- "data-opt-slug": "query-results-table.QueryResultsTable",
2503
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2504
- className: "text-danger-fg font-mono text-sm",
2505
- children: error
2506
- })
2507
- });
2508
- if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2509
- className: require_text_truncate.cn("border-border rounded-lg border p-8 text-center", className),
2510
- role: "status",
2511
- "aria-live": "polite",
2512
- "aria-busy": "true",
2513
- "data-opt-id": "PNC1V",
2514
- "data-opt-slug": "query-results-table.QueryResultsTable",
2515
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2516
- className: "border-border border-t-accent inline-block h-5 w-5 animate-spin rounded-full border-2",
2517
- "aria-hidden": "true"
2518
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2519
- className: "text-text-tertiary mt-2 text-sm",
2520
- children: labels.loadingMessage
2521
- })]
2522
- });
2523
- if (rows.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2524
- className: require_text_truncate.cn("border-border rounded-lg border p-8 text-center", className),
2525
- "data-opt-id": "PNC1V",
2526
- "data-opt-slug": "query-results-table.QueryResultsTable",
2527
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2528
- className: "text-text-tertiary text-sm",
2529
- children: emptyMessage !== null && emptyMessage !== void 0 ? emptyMessage : labels.emptyMessage
2530
- })
2531
- });
2532
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2533
- className: require_text_truncate.cn("border-border overflow-hidden rounded-lg border", className),
2534
- "data-opt-id": "PNC1V",
2535
- "data-opt-slug": "query-results-table.QueryResultsTable",
2536
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2537
- className: "overflow-auto",
2538
- style: { maxHeight },
2539
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
2540
- className: "w-full text-sm",
2541
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", {
2542
- className: "bg-surface-inset sticky top-0",
2543
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
2544
- className: "text-text-tertiary w-10 px-3 py-2 text-left text-xs font-medium",
2545
- children: "#"
2546
- }), columns.map((col) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
2547
- className: "text-text-tertiary px-3 py-2 text-left text-xs font-medium whitespace-nowrap",
2548
- children: col
2549
- }, col))] })
2550
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: rows.map((row, ri) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
2551
- className: "border-border-subtle hover:bg-bg-subtle border-t",
2552
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
2553
- className: "text-text-tertiary px-3 py-1.5 font-mono text-xs",
2554
- children: ri + 1
2555
- }), columns.map((col) => {
2556
- var _row$col;
2557
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
2558
- className: "text-text-primary px-3 py-1.5 font-mono whitespace-nowrap",
2559
- children: String((_row$col = row[col]) !== null && _row$col !== void 0 ? _row$col : "")
2560
- }, col);
2561
- })]
2562
- }, ri)) })]
2563
- })
2564
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2565
- className: "border-border-subtle bg-surface-inset border-t px-3 py-1.5",
2566
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2567
- className: "text-text-tertiary text-xs",
2568
- children: [
2569
- rows.length,
2570
- " ",
2571
- labels.rowsSuffix
2572
- ]
2573
- })
2574
- })]
2575
- });
2320
+ //#region src/lib/sql/statements.ts
2321
+ /**
2322
+ * Split editor text into statements on top-level semicolons.
2323
+ *
2324
+ * Blank statements (two semicolons in a row, a trailing semicolon) are dropped.
2325
+ */
2326
+ function splitSqlStatements(text) {
2327
+ const out = [];
2328
+ let segmentStart = 0;
2329
+ let i = 0;
2330
+ const length = text.length;
2331
+ const push = (from, to) => {
2332
+ let start = from;
2333
+ let end = to;
2334
+ while (start < end && /\s/.test(text[start])) start++;
2335
+ while (end > start && /\s/.test(text[end - 1])) end--;
2336
+ if (end > start) out.push({
2337
+ text: text.slice(start, end),
2338
+ start,
2339
+ end
2340
+ });
2341
+ };
2342
+ while (i < length) {
2343
+ const ch = text[i];
2344
+ const next = text[i + 1];
2345
+ if (ch === "'" || ch === "\"" || ch === "`") {
2346
+ i = skipQuoted(text, i, ch);
2347
+ continue;
2348
+ }
2349
+ if (ch === "-" && next === "-") {
2350
+ i = skipLineComment(text, i + 2);
2351
+ continue;
2352
+ }
2353
+ if (ch === "/" && next === "*") {
2354
+ i = skipBlockComment(text, i + 2);
2355
+ continue;
2356
+ }
2357
+ if (ch === ";") {
2358
+ push(segmentStart, i);
2359
+ segmentStart = i + 1;
2360
+ }
2361
+ i++;
2362
+ }
2363
+ push(segmentStart, length);
2364
+ return out;
2365
+ }
2366
+ /**
2367
+ * The statement the cursor is in, or the nearest one when the cursor sits in
2368
+ * the whitespace between two. `null` only when there are no statements.
2369
+ *
2370
+ * "Nearest" prefers the statement before the cursor: a reader who just typed a
2371
+ * semicolon and pressed run means the thing they finished, not the empty line
2372
+ * after it.
2373
+ */
2374
+ function sqlStatementAtOffset(statements, offset) {
2375
+ var _before;
2376
+ if (statements.length === 0) return null;
2377
+ let before = null;
2378
+ for (const statement of statements) {
2379
+ if (offset >= statement.start && offset <= statement.end) return statement;
2380
+ if (statement.end < offset) before = statement;
2381
+ else break;
2382
+ }
2383
+ return (_before = before) !== null && _before !== void 0 ? _before : statements[0];
2384
+ }
2385
+ /**
2386
+ * Whether the SQL uses a `{name}` placeholder outside strings and comments.
2387
+ * Also matches `{name.` and `{name(` so a `{filters(...)}` binding counts.
2388
+ */
2389
+ function sqlUsesPlaceholder(sql, name) {
2390
+ const needle = `{${name}`;
2391
+ let i = 0;
2392
+ const length = sql.length;
2393
+ while (i < length) {
2394
+ const ch = sql[i];
2395
+ const next = sql[i + 1];
2396
+ if (ch === "'" || ch === "\"" || ch === "`") {
2397
+ i = skipQuoted(sql, i, ch);
2398
+ continue;
2399
+ }
2400
+ if (ch === "-" && next === "-") {
2401
+ i = skipLineComment(sql, i + 2);
2402
+ continue;
2403
+ }
2404
+ if (ch === "/" && next === "*") {
2405
+ i = skipBlockComment(sql, i + 2);
2406
+ continue;
2407
+ }
2408
+ if (sql.startsWith(needle, i)) {
2409
+ const after = sql[i + needle.length];
2410
+ if (after === "}" || after === "." || after === "(") return true;
2411
+ }
2412
+ i++;
2413
+ }
2414
+ return false;
2415
+ }
2416
+ /**
2417
+ * Replace every `{name}` placeholder outside strings and comments with the
2418
+ * given text. A `{name(...)}` binding is left alone — that form carries
2419
+ * arguments the caller must interpret, and a blind substitution would corrupt it.
2420
+ */
2421
+ function replaceSqlPlaceholder(sql, name, replacement) {
2422
+ const needle = `{${name}}`;
2423
+ let out = "";
2424
+ let i = 0;
2425
+ const length = sql.length;
2426
+ while (i < length) {
2427
+ const ch = sql[i];
2428
+ const next = sql[i + 1];
2429
+ let skipTo = -1;
2430
+ if (ch === "'" || ch === "\"" || ch === "`") skipTo = skipQuoted(sql, i, ch);
2431
+ else if (ch === "-" && next === "-") skipTo = skipLineComment(sql, i + 2);
2432
+ else if (ch === "/" && next === "*") skipTo = skipBlockComment(sql, i + 2);
2433
+ if (skipTo !== -1) {
2434
+ out += sql.slice(i, skipTo);
2435
+ i = skipTo;
2436
+ continue;
2437
+ }
2438
+ if (sql.startsWith(needle, i)) {
2439
+ out += replacement;
2440
+ i += needle.length;
2441
+ continue;
2442
+ }
2443
+ out += ch;
2444
+ i++;
2445
+ }
2446
+ return out;
2447
+ }
2448
+ /** Names of every `{name}` / `{name.x}` placeholder, in order of first use. */
2449
+ function sqlPlaceholderNames(sql) {
2450
+ const names = [];
2451
+ const seen = /* @__PURE__ */ new Set();
2452
+ let i = 0;
2453
+ const length = sql.length;
2454
+ while (i < length) {
2455
+ const ch = sql[i];
2456
+ const next = sql[i + 1];
2457
+ if (ch === "'" || ch === "\"" || ch === "`") {
2458
+ i = skipQuoted(sql, i, ch);
2459
+ continue;
2460
+ }
2461
+ if (ch === "-" && next === "-") {
2462
+ i = skipLineComment(sql, i + 2);
2463
+ continue;
2464
+ }
2465
+ if (ch === "/" && next === "*") {
2466
+ i = skipBlockComment(sql, i + 2);
2467
+ continue;
2468
+ }
2469
+ if (ch === "{") {
2470
+ const match = /^\{([A-Za-z_][A-Za-z0-9_]*)/.exec(sql.slice(i));
2471
+ if (match) {
2472
+ const name = match[1];
2473
+ if (!seen.has(name)) {
2474
+ seen.add(name);
2475
+ names.push(name);
2476
+ }
2477
+ i += match[0].length;
2478
+ continue;
2479
+ }
2480
+ }
2481
+ i++;
2482
+ }
2483
+ return names;
2484
+ }
2485
+ function skipQuoted(text, from, quote) {
2486
+ let i = from + 1;
2487
+ const length = text.length;
2488
+ while (i < length) {
2489
+ const ch = text[i];
2490
+ if (ch === "\\") {
2491
+ i += 2;
2492
+ continue;
2493
+ }
2494
+ if (ch === quote) {
2495
+ if (text[i + 1] === quote) {
2496
+ i += 2;
2497
+ continue;
2498
+ }
2499
+ return i + 1;
2500
+ }
2501
+ i++;
2502
+ }
2503
+ return length;
2504
+ }
2505
+ function skipLineComment(text, from) {
2506
+ let i = from;
2507
+ const length = text.length;
2508
+ while (i < length && text[i] !== "\n") i++;
2509
+ return i;
2510
+ }
2511
+ function skipBlockComment(text, from) {
2512
+ let i = from;
2513
+ const length = text.length;
2514
+ while (i < length) {
2515
+ if (text[i] === "*" && text[i + 1] === "/") return i + 2;
2516
+ i++;
2517
+ }
2518
+ return length;
2576
2519
  }
2577
- QueryResultsTable.displayName = "QueryResultsTable";
2578
2520
  //#endregion
2579
2521
  //#region src/shells/alert-builder.tsx
2580
- const defaultLabels$23 = {
2522
+ const defaultLabels$22 = {
2581
2523
  alertNameLabel: "Alert name",
2582
2524
  conditionsLabel: "Conditions",
2583
2525
  metricLabel: "Metric",
@@ -2648,7 +2590,7 @@ function AlertBuilder({ value, onChange, metrics = [
2648
2590
  ], labels: customLabels, className }) {
2649
2591
  const resolvedMetrics = eventOptions ? eventOptions.map((e) => e.id) : metrics;
2650
2592
  const metricLabelMap = eventOptions ? Object.fromEntries(eventOptions.map((e) => [e.id, e.name])) : null;
2651
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$23), customLabels);
2593
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$22), customLabels);
2652
2594
  const alertNameId = react.useId();
2653
2595
  const conditionsId = react.useId();
2654
2596
  const checkFrequencyId = react.useId();
@@ -2802,186 +2744,6 @@ function AlertBuilder({ value, onChange, metrics = [
2802
2744
  }
2803
2745
  AlertBuilder.displayName = "AlertBuilder";
2804
2746
  //#endregion
2805
- //#region src/shells/sql-editor.tsx
2806
- const defaultLabels$22 = {
2807
- placeholder: "SELECT * FROM events LIMIT 100",
2808
- runHint: "Ctrl+Enter to run",
2809
- runButton: "Run Query",
2810
- editor: "SQL 편집기"
2811
- };
2812
- /** Renders the sql editor component. */
2813
- function SqlEditor({ value, onChange, onRun, onRunAndAdvance, placeholder, readOnly = false, height = 200, schema, completionSources, keymap: customKeymap, extensions: customExtensions, ariaLabel, autoFocus = false, showFooter, labels: customLabels, className }) {
2814
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$22), customLabels);
2815
- const fill = height === "fill";
2816
- const footerVisible = showFooter !== null && showFooter !== void 0 ? showFooter : Boolean(onRun);
2817
- const editorRef = react.useRef(null);
2818
- const viewRef = react.useRef(null);
2819
- const completionCompartmentRef = react.useRef(null);
2820
- const editableCompartmentRef = react.useRef(null);
2821
- const buildCompletionRef = react.useRef(null);
2822
- const latestValueRef = react.useRef(value);
2823
- const onChangeRef = react.useRef(onChange);
2824
- const onRunRef = react.useRef(onRun);
2825
- const onRunAndAdvanceRef = react.useRef(onRunAndAdvance);
2826
- const customKeymapRef = react.useRef(customKeymap);
2827
- const schemaRef = react.useRef(schema);
2828
- const completionSourcesRef = react.useRef(completionSources);
2829
- const autoFocusRef = react.useRef(autoFocus);
2830
- latestValueRef.current = value;
2831
- onChangeRef.current = onChange;
2832
- onRunRef.current = onRun;
2833
- onRunAndAdvanceRef.current = onRunAndAdvance;
2834
- customKeymapRef.current = customKeymap;
2835
- schemaRef.current = schema;
2836
- completionSourcesRef.current = completionSources;
2837
- autoFocusRef.current = autoFocus;
2838
- const autocompleteEnabled = react.useRef(schema !== void 0 || completionSources !== void 0).current;
2839
- react.useEffect(() => {
2840
- let view = null;
2841
- let cancelled = false;
2842
- async function init() {
2843
- var _customKeymapRef$curr;
2844
- const parent = editorRef.current;
2845
- if (!parent) return;
2846
- const [{ EditorView, keymap: cmKeymap, placeholder: cmPlaceholder }, { Compartment, EditorState }, langSql, { oneDark }, autocomplete] = await Promise.all([
2847
- import("@codemirror/view"),
2848
- import("@codemirror/state"),
2849
- import("@codemirror/lang-sql"),
2850
- import("@codemirror/theme-one-dark"),
2851
- autocompleteEnabled ? import("@codemirror/autocomplete") : Promise.resolve(null)
2852
- ]);
2853
- if (cancelled || !parent.isConnected) return;
2854
- const completionCompartment = new Compartment();
2855
- const editableCompartment = new Compartment();
2856
- completionCompartmentRef.current = completionCompartment;
2857
- editableCompartmentRef.current = editableCompartment;
2858
- const buildCompletion = (nextSchema, nextSources) => {
2859
- if (!autocomplete) return [];
2860
- const dialect = langSql.PostgreSQL;
2861
- return [autocomplete.autocompletion({ override: [
2862
- langSql.schemaCompletionSource({
2863
- dialect,
2864
- schema: nextSchema !== null && nextSchema !== void 0 ? nextSchema : {}
2865
- }),
2866
- langSql.keywordCompletionSource(dialect),
2867
- ...nextSources !== null && nextSources !== void 0 ? nextSources : []
2868
- ] }), cmKeymap.of(autocomplete.completionKeymap)];
2869
- };
2870
- buildCompletionRef.current = buildCompletion;
2871
- const runKeymap = [{
2872
- key: "Shift-Enter",
2873
- run: (target) => {
2874
- const handler = onRunAndAdvanceRef.current;
2875
- if (!handler) return false;
2876
- handler(target.state.doc.toString());
2877
- return true;
2878
- }
2879
- }, {
2880
- key: "Mod-Enter",
2881
- run: (target) => {
2882
- const handler = onRunRef.current;
2883
- if (!handler) return false;
2884
- handler(target.state.doc.toString());
2885
- return true;
2886
- }
2887
- }];
2888
- const extensions = [
2889
- langSql.PostgreSQL.extension,
2890
- completionCompartment.of(buildCompletion(schemaRef.current, completionSourcesRef.current)),
2891
- oneDark,
2892
- cmKeymap.of([...(_customKeymapRef$curr = customKeymapRef.current) !== null && _customKeymapRef$curr !== void 0 ? _customKeymapRef$curr : [], ...runKeymap]),
2893
- EditorView.theme({
2894
- "&": { height: "100%" },
2895
- "&.cm-focused": {
2896
- outline: "2px solid var(--opt-ring)",
2897
- outlineOffset: "-2px"
2898
- },
2899
- ".cm-scroller": {
2900
- height: "100%",
2901
- overflow: "auto"
2902
- }
2903
- }),
2904
- cmPlaceholder(placeholder !== null && placeholder !== void 0 ? placeholder : labels.placeholder),
2905
- EditorView.lineWrapping,
2906
- EditorView.updateListener.of((update) => {
2907
- if (update.docChanged) onChangeRef.current(update.state.doc.toString());
2908
- }),
2909
- editableCompartment.of(EditorView.editable.of(!readOnly)),
2910
- EditorView.contentAttributes.of({ "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : labels.editor }),
2911
- ...customExtensions !== null && customExtensions !== void 0 ? customExtensions : []
2912
- ];
2913
- view = new EditorView({
2914
- state: EditorState.create({
2915
- doc: latestValueRef.current,
2916
- extensions
2917
- }),
2918
- parent
2919
- });
2920
- viewRef.current = view;
2921
- if (autoFocusRef.current) view.focus();
2922
- }
2923
- init();
2924
- return () => {
2925
- cancelled = true;
2926
- view === null || view === void 0 || view.destroy();
2927
- if (viewRef.current === view) viewRef.current = null;
2928
- completionCompartmentRef.current = null;
2929
- editableCompartmentRef.current = null;
2930
- buildCompletionRef.current = null;
2931
- };
2932
- }, []);
2933
- react.useEffect(() => {
2934
- const view = viewRef.current;
2935
- if (view && view.state.doc.toString() !== value) view.dispatch({ changes: {
2936
- from: 0,
2937
- to: view.state.doc.length,
2938
- insert: value
2939
- } });
2940
- }, [value]);
2941
- react.useEffect(() => {
2942
- const view = viewRef.current;
2943
- const compartment = completionCompartmentRef.current;
2944
- const build = buildCompletionRef.current;
2945
- if (!view || !compartment || !build) return;
2946
- view.dispatch({ effects: compartment.reconfigure(build(schema, completionSources)) });
2947
- }, [schema, completionSources]);
2948
- react.useEffect(() => {
2949
- const view = viewRef.current;
2950
- const compartment = editableCompartmentRef.current;
2951
- if (!view || !compartment) return;
2952
- let cancelled = false;
2953
- import("@codemirror/view").then(({ EditorView }) => {
2954
- if (cancelled || viewRef.current !== view) return;
2955
- view.dispatch({ effects: compartment.reconfigure(EditorView.editable.of(!readOnly)) });
2956
- });
2957
- return () => {
2958
- cancelled = true;
2959
- };
2960
- }, [readOnly]);
2961
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2962
- className: require_text_truncate.cn("gap-element flex flex-col", fill && "h-full min-h-0", className),
2963
- "data-opt-id": "RSGKV",
2964
- "data-opt-slug": "sql-editor.SqlEditor",
2965
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2966
- ref: editorRef,
2967
- className: require_text_truncate.cn("border-border overflow-hidden rounded-lg border", fill && "min-h-0 flex-1"),
2968
- style: fill ? void 0 : { height }
2969
- }), footerVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2970
- className: "flex flex-none items-center justify-between",
2971
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2972
- className: "text-text-tertiary text-xs",
2973
- children: labels.runHint
2974
- }), onRun && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.Button, {
2975
- variant: "primary",
2976
- size: "sm",
2977
- onClick: () => onRun(value),
2978
- children: labels.runButton
2979
- })]
2980
- })]
2981
- });
2982
- }
2983
- SqlEditor.displayName = "SqlEditor";
2984
- //#endregion
2985
2747
  //#region src/shells/event-meta-editor.tsx
2986
2748
  const defaultLabels$21 = {
2987
2749
  icon: "Icon",
@@ -4408,17 +4170,17 @@ function ExportButton({ data, columns, fileName = "export", formats = ["csv", "j
4408
4170
  })
4409
4171
  })]
4410
4172
  });
4411
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_key_pad_menu.DropdownMenu, {
4173
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.DropdownMenu, {
4412
4174
  "data-opt-id": "MGP2B",
4413
4175
  "data-opt-slug": "export-button.ExportButton",
4414
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_key_pad_menu.DropdownTrigger, {
4176
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.DropdownTrigger, {
4415
4177
  className: require_text_truncate.cn("inline-flex items-center justify-center rounded-lg font-medium transition-colors", "border-border bg-surface text-text-primary hover:bg-bg-subtle active:bg-bg-muted border", "h-8 gap-1.5 px-3 text-xs", className),
4416
4178
  "aria-label": labels.export,
4417
4179
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4418
4180
  "aria-hidden": "true",
4419
4181
  children: "⬇"
4420
4182
  }), labels.export]
4421
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.DropdownContent, { children: formats.map((fmt, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [i > 0 && fmt === "pdf" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.DropdownSeparator, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.DropdownItem, {
4183
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.DropdownContent, { children: formats.map((fmt, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [i > 0 && fmt === "pdf" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.DropdownSeparator, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.DropdownItem, {
4422
4184
  onClick: () => handleExport(fmt),
4423
4185
  children: formatLabels[fmt]
4424
4186
  })] }, fmt)) })]
@@ -4565,28 +4327,6 @@ function matchesQueryObject(query, row, options = {}) {
4565
4327
  return matchesQuery(query, read, searchable);
4566
4328
  }
4567
4329
  //#endregion
4568
- //#region src/lib/use-media-query.ts
4569
- /**
4570
- * Whether a media query matches, kept in sync with the browser.
4571
- *
4572
- * `useSyncExternalStore` rather than an effect: a layout that switches on width
4573
- * must not render the wrong shape for a frame first. The server snapshot is the
4574
- * caller's `serverFallback`, because the server does not know the viewport and
4575
- * guessing "narrow" collapses a wide layout on every first paint.
4576
- *
4577
- * Internal. Exported from `lib` for the components in this package, not from
4578
- * the package barrel — a hook that answers "is this viewport wide" invites
4579
- * layout decisions that belong in CSS.
4580
- */
4581
- function useMediaQuery(query, serverFallback = false) {
4582
- return (0, react.useSyncExternalStore)((onChange) => {
4583
- if (typeof window === "undefined") return () => {};
4584
- const list = window.matchMedia(query);
4585
- list.addEventListener("change", onChange);
4586
- return () => list.removeEventListener("change", onChange);
4587
- }, () => typeof window === "undefined" ? serverFallback : window.matchMedia(query).matches, () => serverFallback);
4588
- }
4589
- //#endregion
4590
4330
  //#region src/shells/inspector-layout.tsx
4591
4331
  /** Tailwind needs whole class names, so the queries and widths are literals. */
4592
4332
  const breakpointQuery = {
@@ -4635,7 +4375,7 @@ const flyoutSize = {
4635
4375
  * ```
4636
4376
  */
4637
4377
  function InspectorLayout({ children, inspector, open, onClose, title, description, actions, footer, breakpoint = "xl", width = "md", labels, className }) {
4638
- const canPush = useMediaQuery(breakpointQuery[breakpoint], true);
4378
+ const canPush = require_field_sidebar.useMediaQuery(breakpointQuery[breakpoint], true);
4639
4379
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4640
4380
  className: require_text_truncate.cn("flex min-w-0 items-stretch gap-group", className),
4641
4381
  "data-opt-id": "MN44T",
@@ -4859,13 +4599,13 @@ function CatalogRowActions({ item, actions, visibleCount = 2, labels }) {
4859
4599
  size: "sm",
4860
4600
  onClick: () => action.onSelect(item),
4861
4601
  children: [action.icon, action.label]
4862
- }, action.id)), overflow.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_key_pad_menu.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.DropdownTrigger, {
4602
+ }, action.id)), overflow.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.DropdownTrigger, {
4863
4603
  "aria-label": (_labels$moreActions = labels === null || labels === void 0 ? void 0 : labels.moreActions) !== null && _labels$moreActions !== void 0 ? _labels$moreActions : "더 보기",
4864
4604
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.MoreHorizontal, {
4865
4605
  "aria-hidden": "true",
4866
4606
  className: "size-4"
4867
4607
  })
4868
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.DropdownContent, { children: overflow.map((action) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.DropdownItem, {
4608
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.DropdownContent, { children: overflow.map((action) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.DropdownItem, {
4869
4609
  onClick: () => action.onSelect(item),
4870
4610
  children: action.label
4871
4611
  }, action.id)) })] })]
@@ -5122,853 +4862,6 @@ function ComparisonSelector({ segments, valueA, valueB, onChangeA, onChangeB, va
5122
4862
  });
5123
4863
  }
5124
4864
  ComparisonSelector.displayName = "ComparisonSelector";
5125
- const THEME_REGISTRY = {
5126
- default: {
5127
- id: "default",
5128
- label: "Default",
5129
- description: "Blue accent, balanced radius & shadow",
5130
- palette: {
5131
- seed: "#2563eb",
5132
- harmony: "split-complementary",
5133
- radiusScale: "medium",
5134
- shadowIntensity: "subtle",
5135
- neutralTemperature: "cool"
5136
- },
5137
- switcherSwatches: [
5138
- "hsl(221 83% 53%)",
5139
- "hsl(142 71% 45%)",
5140
- "hsl(38 92% 50%)"
5141
- ]
5142
- },
5143
- minimal: {
5144
- id: "minimal",
5145
- label: "Minimal",
5146
- description: "Monochrome, no shadow, sharp edges",
5147
- palette: {
5148
- seed: "#333333",
5149
- harmony: "analogous",
5150
- radiusScale: "sharp",
5151
- shadowIntensity: "none",
5152
- neutralTemperature: "cool"
5153
- },
5154
- switcherSwatches: [
5155
- "hsl(0 0% 20%)",
5156
- "hsl(0 0% 45%)",
5157
- "hsl(0 0% 70%)"
5158
- ]
5159
- },
5160
- natural: {
5161
- id: "natural",
5162
- label: "Natural",
5163
- description: "Always light — sage accent, warm cream",
5164
- forceLightOnly: true,
5165
- palette: {
5166
- seed: "#5a9376",
5167
- harmony: "complementary",
5168
- radiusScale: "medium",
5169
- shadowIntensity: "subtle",
5170
- neutralTemperature: "warm"
5171
- },
5172
- switcherSwatches: [
5173
- "hsl(155 38% 45%)",
5174
- "hsl(25 65% 55%)",
5175
- "hsl(45 75% 50%)"
5176
- ]
5177
- },
5178
- pro: {
5179
- id: "pro",
5180
- label: "Pro",
5181
- description: "Neon blue accent, mono headings, ultra-dense",
5182
- palette: {
5183
- seed: "#0080ff",
5184
- harmony: "tetradic",
5185
- radiusScale: "sharp",
5186
- shadowIntensity: "subtle",
5187
- neutralTemperature: "cool"
5188
- },
5189
- switcherSwatches: [
5190
- "hsl(210 100% 55%)",
5191
- "hsl(170 90% 48%)",
5192
- "hsl(290 85% 60%)"
5193
- ]
5194
- },
5195
- "mono-dark": {
5196
- id: "mono-dark",
5197
- label: "Mono Dark",
5198
- description: "OLED-friendly black, neon cyan accent, mono headings",
5199
- palette: {
5200
- seed: "#00d4ff",
5201
- harmony: "tetradic",
5202
- radiusScale: "sharp",
5203
- shadowIntensity: "subtle",
5204
- neutralTemperature: "cool"
5205
- },
5206
- switcherSwatches: [
5207
- "hsl(190 100% 50%)",
5208
- "hsl(0 0% 8%)",
5209
- "hsl(280 90% 65%)"
5210
- ]
5211
- }
5212
- };
5213
- /** All registered preset ids in declaration order. */
5214
- const THEME_PRESET_IDS = Object.keys(THEME_REGISTRY);
5215
- /** Look up a descriptor by id. Returns `undefined` for unknown ids. */
5216
- function getThemeDescriptor(id) {
5217
- return THEME_REGISTRY[id];
5218
- }
5219
- /** Type guard for a known preset id. */
5220
- function isThemePresetId(id) {
5221
- return id in THEME_REGISTRY;
5222
- }
5223
- /** Preset ids that suppress dark mode generation. */
5224
- const FORCE_LIGHT_PRESET_IDS = new Set(THEME_PRESET_IDS.filter((id) => THEME_REGISTRY[id].forceLightOnly));
5225
- /**
5226
- * Map from removed preset ids to the closest surviving preset. Boot script and
5227
- * `readStoredTheme` consult this so users with persisted `corporate`/`playful`
5228
- * values silently land on a working preset on next page load instead of
5229
- * showing the global default fallback for an unknown id.
5230
- *
5231
- * Keep this around indefinitely — localStorage values are forever and the
5232
- * cost of two extra entries is negligible.
5233
- */
5234
- const DEPRECATED_PRESET_MIGRATIONS = Object.freeze({
5235
- corporate: "default",
5236
- playful: "default"
5237
- });
5238
- /**
5239
- * Resolve a possibly-deprecated preset id to a registered one. Returns the
5240
- * input unchanged when it is already valid; returns the migration target when
5241
- * it is a known deprecated id; returns `null` when the id is unknown
5242
- * altogether (caller should fall back to its default).
5243
- */
5244
- function migrateDeprecatedPresetId(id) {
5245
- if (!id) return null;
5246
- if (isThemePresetId(id)) return id;
5247
- if (id in DEPRECATED_PRESET_MIGRATIONS) return DEPRECATED_PRESET_MIGRATIONS[id];
5248
- return null;
5249
- }
5250
- //#endregion
5251
- //#region src/lib/theme/theme-types.ts
5252
- /**
5253
- * Author canonical theme overrides with token-name autocomplete.
5254
- * ThemeOverrides remains broad for backward compatibility with older custom
5255
- * variables; new themes should use this helper as the governed entry point.
5256
- */
5257
- function defineThemeOverrides(overrides) {
5258
- return overrides;
5259
- }
5260
- /** Construct a `PresetThemeSpec` — convenience for the common case. */
5261
- function presetTheme(preset, overrides) {
5262
- return overrides ? {
5263
- kind: "preset",
5264
- preset,
5265
- overrides
5266
- } : {
5267
- kind: "preset",
5268
- preset
5269
- };
5270
- }
5271
- /** Construct a `GeneratedThemeSpec` from an inline `PaletteConfig`. */
5272
- function generatedTheme(palette, options) {
5273
- return require_text_truncate._objectSpread2({
5274
- kind: "generated",
5275
- palette
5276
- }, options);
5277
- }
5278
- /** True when `spec` references a registered preset id. */
5279
- function isPresetSpec(spec) {
5280
- return spec.kind === "preset";
5281
- }
5282
- /** True when `spec` carries an inline `PaletteConfig`. */
5283
- function isGeneratedSpec(spec) {
5284
- return spec.kind === "generated";
5285
- }
5286
- /** True when `spec` wraps a fully-formed `ThemeDescriptor`. */
5287
- function isDescriptorSpec(spec) {
5288
- return spec.kind === "descriptor";
5289
- }
5290
- //#endregion
5291
- //#region src/lib/theme/theme-serialize.ts
5292
- /**
5293
- * theme-serialize.ts
5294
- *
5295
- * Pure helpers that turn a `ThemeSpec` into the artifacts the runtime needs:
5296
- * resolved descriptor + mode, computed token maps for generated palettes, and
5297
- * `<style>` CSS strings ready to be injected into `<head>`.
5298
- *
5299
- * Kept side-effect free so the boot script and the provider can share the
5300
- * same logic without dragging React into the client bundle's critical path.
5301
- */
5302
- /** Element id used for the global generated theme style tag. */
5303
- const GLOBAL_THEME_STYLE_ID = "opt-global-theme";
5304
- /** localStorage key for the persisted ThemeSpec (generated mode). */
5305
- const THEME_SPEC_STORAGE_KEY = "opt-theme-spec";
5306
- /**
5307
- * localStorage key for the cached, pre-serialized token maps that match the
5308
- * spec under `THEME_SPEC_STORAGE_KEY`. The boot script reads this directly so
5309
- * it can inline tokens without invoking opt-palette at startup.
5310
- */
5311
- const THEME_TOKENS_STORAGE_KEY = "opt-theme-tokens";
5312
- /** Stable id used for unnamed generated themes. */
5313
- const GENERATED_THEME_ID_DEFAULT = "generated";
5314
- /** Cached token maps keyed by spec hash. Lazy-built per process. */
5315
- const generatedCache = /* @__PURE__ */ new Map();
5316
- /** Build a stable cache key for a `PaletteConfig`. */
5317
- function paletteCacheKey(config) {
5318
- return JSON.stringify(config);
5319
- }
5320
- /** Run opt-palette with caching. */
5321
- function generatePaletteCached(config) {
5322
- const key = paletteCacheKey(config);
5323
- let cached = generatedCache.get(key);
5324
- if (!cached) {
5325
- cached = (0, _reopt_ai_opt_palette.generatePalette)(config);
5326
- generatedCache.set(key, cached);
5327
- }
5328
- return cached;
5329
- }
5330
- /** Apply sparse override maps onto a base token record. */
5331
- function applyOverrides(base, overrides, mode) {
5332
- if (!overrides) return base;
5333
- const merged = require_text_truncate._objectSpread2({}, base);
5334
- if (overrides.shared) Object.assign(merged, overrides.shared);
5335
- const modeOverrides = mode === "light" ? overrides.light : overrides.dark;
5336
- if (modeOverrides) Object.assign(merged, modeOverrides);
5337
- return merged;
5338
- }
5339
- /**
5340
- * Stable id used in `<html data-theme>` and the `<style>` selector.
5341
- * - preset → the preset id (force-light) or `${id}` / `${id}-dark`
5342
- * - generated → `spec.id ?? "generated"` with `-dark` suffix when applicable
5343
- * - descriptor → `descriptor.id` with same suffix logic
5344
- */
5345
- function getCompoundIdForSpec(spec, resolvedMode, forceLightOnly) {
5346
- const baseId = baseIdFor(spec);
5347
- if (forceLightOnly) return baseId;
5348
- return resolvedMode === "dark" ? `${baseId}-dark` : baseId;
5349
- }
5350
- function baseIdFor(spec) {
5351
- var _spec$id;
5352
- if (isPresetSpec(spec)) return spec.preset;
5353
- if (isDescriptorSpec(spec)) return spec.descriptor.id;
5354
- return (_spec$id = spec.id) !== null && _spec$id !== void 0 ? _spec$id : GENERATED_THEME_ID_DEFAULT;
5355
- }
5356
- /** Whether the given spec emits dark variants at all. */
5357
- function isForceLightSpec(spec) {
5358
- if (isPresetSpec(spec)) {
5359
- const desc = THEME_REGISTRY[spec.preset];
5360
- return (desc === null || desc === void 0 ? void 0 : desc.forceLightOnly) === true;
5361
- }
5362
- if (isDescriptorSpec(spec)) return spec.descriptor.forceLightOnly === true;
5363
- return spec.forceLightOnly === true;
5364
- }
5365
- /**
5366
- * Compute the inline tokens for a `GeneratedThemeSpec` or
5367
- * `DescriptorThemeSpec` whose descriptor carries a `palette`. Returns `null`
5368
- * for preset specs (their tokens live in the static CSS files).
5369
- */
5370
- function computeGeneratedTokens(spec) {
5371
- if (isPresetSpec(spec)) return null;
5372
- let palette;
5373
- let overrides;
5374
- let id;
5375
- let forceLight;
5376
- if (isGeneratedSpec(spec)) {
5377
- var _spec$id2;
5378
- palette = spec.palette;
5379
- overrides = spec.overrides;
5380
- id = (_spec$id2 = spec.id) !== null && _spec$id2 !== void 0 ? _spec$id2 : GENERATED_THEME_ID_DEFAULT;
5381
- forceLight = spec.forceLightOnly === true;
5382
- } else {
5383
- palette = spec.descriptor.palette;
5384
- overrides = spec.overrides;
5385
- id = spec.descriptor.id;
5386
- forceLight = spec.descriptor.forceLightOnly === true;
5387
- }
5388
- if (!palette) return null;
5389
- const generated = generatePaletteCached(palette);
5390
- return {
5391
- id,
5392
- light: applyOverrides(generated.light, overrides, "light"),
5393
- dark: forceLight ? null : applyOverrides(generated.dark, overrides, "dark")
5394
- };
5395
- }
5396
- /**
5397
- * Serialize a token record into a CSS rule body — `--name:value;...` — without
5398
- * surrounding selector or braces. Values are not escaped; callers are
5399
- * responsible for trusted input. Boot script and provider both rely on this
5400
- * shape.
5401
- */
5402
- function serializeTokenBody(tokens) {
5403
- return Object.entries(tokens).map(([k, v]) => `${k}:${v}`).join(";");
5404
- }
5405
- /**
5406
- * Build a CSS rule scoped to `[data-theme="<id>"]`.
5407
- */
5408
- function serializeThemeRule(themeId, tokens) {
5409
- return `[data-theme="${themeId}"]{${serializeTokenBody(tokens)}}`;
5410
- }
5411
- /**
5412
- * Build the full CSS for a generated theme style tag — covers light + dark
5413
- * selectors based on the computed tokens. Caller chooses the id used in
5414
- * the selector (typically the spec base id).
5415
- */
5416
- function serializeGeneratedTheme(tokens) {
5417
- const { id, light, dark } = tokens;
5418
- let css = serializeThemeRule(id, light);
5419
- if (dark) css += serializeThemeRule(`${id}-dark`, dark);
5420
- return css;
5421
- }
5422
- /**
5423
- * Resolve a spec into its descriptor counterpart. Preset specs map to
5424
- * `THEME_REGISTRY[preset]`. Generated specs are wrapped into a synthetic
5425
- * descriptor so callers can treat them uniformly.
5426
- */
5427
- function resolveDescriptor(spec) {
5428
- if (isPresetSpec(spec)) {
5429
- const desc = THEME_REGISTRY[spec.preset];
5430
- if (!desc) throw new Error(`[opt-ui] Unknown theme preset id: "${spec.preset}". Registered ids: ${Object.keys(THEME_REGISTRY).join(", ")}`);
5431
- return desc;
5432
- }
5433
- if (isDescriptorSpec(spec)) return spec.descriptor;
5434
- return generatedSpecToDescriptor(spec);
5435
- }
5436
- function generatedSpecToDescriptor(spec) {
5437
- var _spec$id3, _spec$label;
5438
- return {
5439
- id: (_spec$id3 = spec.id) !== null && _spec$id3 !== void 0 ? _spec$id3 : GENERATED_THEME_ID_DEFAULT,
5440
- label: (_spec$label = spec.label) !== null && _spec$label !== void 0 ? _spec$label : "Custom",
5441
- description: "Generated theme",
5442
- palette: spec.palette,
5443
- forceLightOnly: spec.forceLightOnly
5444
- };
5445
- }
5446
- /**
5447
- * Validate a `ThemeSpec` parsed from localStorage. Returns the spec on
5448
- * success or `null` if any required field is missing or the preset id is
5449
- * unknown. Defensive parsing — never throws.
5450
- */
5451
- function safeParseStoredSpec(json) {
5452
- if (!json) return null;
5453
- try {
5454
- const parsed = JSON.parse(json);
5455
- if (!parsed || typeof parsed !== "object" || !("kind" in parsed)) return null;
5456
- if (parsed.kind === "preset") {
5457
- const preset = parsed.preset;
5458
- if (typeof preset !== "string" || !isThemePresetId(preset)) return null;
5459
- return {
5460
- kind: "preset",
5461
- preset
5462
- };
5463
- }
5464
- if (parsed.kind === "generated") {
5465
- const palette = parsed.palette;
5466
- if (!isPaletteConfig(palette)) return null;
5467
- return {
5468
- kind: "generated",
5469
- palette,
5470
- id: typeof parsed.id === "string" ? parsed.id : void 0,
5471
- label: typeof parsed.label === "string" ? parsed.label : void 0,
5472
- forceLightOnly: parsed.forceLightOnly === true,
5473
- overrides: isObjectMap(parsed.overrides) ? parsed.overrides : void 0
5474
- };
5475
- }
5476
- return null;
5477
- } catch (_unused) {
5478
- return null;
5479
- }
5480
- }
5481
- function isObjectMap(value) {
5482
- return value !== null && typeof value === "object" && !Array.isArray(value);
5483
- }
5484
- function isPaletteConfig(value) {
5485
- if (!isObjectMap(value)) return false;
5486
- const v = value;
5487
- return typeof v.seed === "string" && typeof v.harmony === "string" && typeof v.radiusScale === "string" && typeof v.shadowIntensity === "string" && typeof v.neutralTemperature === "string";
5488
- }
5489
- /**
5490
- * Parse the cached token payload from localStorage. Returns `null` on any
5491
- * shape mismatch — caller will recompute from the spec.
5492
- */
5493
- function safeParseStoredTokens(json) {
5494
- if (!json) return null;
5495
- try {
5496
- const parsed = JSON.parse(json);
5497
- if (!parsed || typeof parsed.id !== "string" || !isObjectMap(parsed.light)) return null;
5498
- return {
5499
- id: parsed.id,
5500
- light: parsed.light,
5501
- dark: isObjectMap(parsed.dark) ? parsed.dark : void 0
5502
- };
5503
- } catch (_unused2) {
5504
- return null;
5505
- }
5506
- }
5507
- /** Build the storage payload that pairs with `opt-theme-spec`. */
5508
- function buildTokenCache(tokens) {
5509
- var _tokens$dark;
5510
- return {
5511
- id: tokens.id,
5512
- light: tokens.light,
5513
- dark: (_tokens$dark = tokens.dark) !== null && _tokens$dark !== void 0 ? _tokens$dark : void 0
5514
- };
5515
- }
5516
- //#endregion
5517
- //#region src/lib/theme/theme-resolution.ts
5518
- /**
5519
- * Registered preset id list. Preferred for runtime iteration.
5520
- * @deprecated Prefer `THEME_PRESET_IDS` from `./presets`.
5521
- */
5522
- const THEME_PRESET_VALUES = THEME_PRESET_IDS;
5523
- const THEME_MODE_VALUES = [
5524
- "light",
5525
- "dark",
5526
- "system"
5527
- ];
5528
- const LEGACY_THEME_STORAGE_KEY = "opt-theme";
5529
- const THEME_PRESET_STORAGE_KEY = "opt-preset";
5530
- const THEME_MODE_STORAGE_KEY = "opt-mode";
5531
- const DARK_MQ = "(prefers-color-scheme: dark)";
5532
- /**
5533
- * Presets that force light mode regardless of system dark/light preference.
5534
- * Mirrors `FORCE_LIGHT_PRESET_IDS` from `./presets` — kept as alias for
5535
- * existing imports.
5536
- */
5537
- const FORCE_LIGHT_PRESETS = FORCE_LIGHT_PRESET_IDS;
5538
- /** All valid compound theme names. Useful for static enumeration. */
5539
- const ALL_COMPOUND_THEMES = THEME_PRESET_IDS.flatMap((id) => FORCE_LIGHT_PRESET_IDS.has(id) ? [id] : [id, `${id}-dark`]);
5540
- function hasStorageMutation(storage) {
5541
- return typeof storage.setItem === "function" && typeof storage.removeItem === "function";
5542
- }
5543
- /** Handles is theme mode. */
5544
- function isThemeMode(value) {
5545
- return typeof value === "string" && THEME_MODE_VALUES.includes(value);
5546
- }
5547
- /** Compute compound theme name from preset + resolved mode. */
5548
- function getCompoundTheme(preset, resolvedMode) {
5549
- if (FORCE_LIGHT_PRESETS.has(preset)) return preset;
5550
- return resolvedMode === "dark" ? `${preset}-dark` : preset;
5551
- }
5552
- /** Handles resolve theme mode. */
5553
- function resolveThemeMode(preset, mode, systemDark) {
5554
- if (FORCE_LIGHT_PRESETS.has(preset)) return "light";
5555
- if (mode === "system") return systemDark ? "dark" : "light";
5556
- return mode;
5557
- }
5558
- /** Handles read stored theme. */
5559
- function readStoredTheme(storage, defaultPreset, defaultMode, options = {}) {
5560
- const legacy = storage.getItem(LEGACY_THEME_STORAGE_KEY);
5561
- const storedPreset = storage.getItem(THEME_PRESET_STORAGE_KEY);
5562
- const storedMode = storage.getItem(THEME_MODE_STORAGE_KEY);
5563
- let preset = defaultPreset;
5564
- if (typeof legacy === "string") {
5565
- const migratedLegacy = migrateDeprecatedPresetId(legacy);
5566
- if (migratedLegacy) {
5567
- if (options.migrateLegacy && hasStorageMutation(storage)) {
5568
- storage.setItem(THEME_PRESET_STORAGE_KEY, migratedLegacy);
5569
- storage.removeItem(LEGACY_THEME_STORAGE_KEY);
5570
- }
5571
- preset = migratedLegacy;
5572
- }
5573
- } else if (typeof storedPreset === "string") {
5574
- const migrated = migrateDeprecatedPresetId(storedPreset);
5575
- if (migrated) {
5576
- preset = migrated;
5577
- if (hasStorageMutation(storage) && migrated !== storedPreset && storedPreset in DEPRECATED_PRESET_MIGRATIONS) storage.setItem(THEME_PRESET_STORAGE_KEY, migrated);
5578
- }
5579
- }
5580
- const mode = isThemeMode(storedMode) ? storedMode : defaultMode;
5581
- return {
5582
- preset,
5583
- mode
5584
- };
5585
- }
5586
- /** Normalize a mode against an optional allowed-mode list. */
5587
- function coerceThemeMode(mode, allowedModes, fallback = "system") {
5588
- var _allowedModes$;
5589
- if (!allowedModes || allowedModes.length === 0) return mode;
5590
- if (allowedModes.includes(mode)) return mode;
5591
- if (allowedModes.includes(fallback)) return fallback;
5592
- return (_allowedModes$ = allowedModes[0]) !== null && _allowedModes$ !== void 0 ? _allowedModes$ : fallback;
5593
- }
5594
- /**
5595
- * Build the inline `<head>` boot script that paints the correct theme before
5596
- * React mounts. Two paths:
5597
- *
5598
- * 1. **Generated** — when both `opt-theme-spec` (kind: "generated") and
5599
- * `opt-theme-tokens` are present and well-formed, a `<style id="…">` tag
5600
- * is inserted with the cached tokens and `<html data-theme>` is set to the
5601
- * generated id (with optional `-dark` suffix). This bypasses opt-palette
5602
- * at startup so first paint is instant.
5603
- * 2. **Preset (legacy)** — falls through to the existing preset selector,
5604
- * including legacy `opt-theme` → `opt-preset` migration.
5605
- *
5606
- * Returned as a single minified line; intended for `dangerouslySetInnerHTML`.
5607
- */
5608
- function createThemeBootScript(defaultPreset = "default", defaultMode = "system", options = {}) {
5609
- var _options$allowedModes, _allowedModes$2;
5610
- const presetValues = JSON.stringify(THEME_PRESET_VALUES);
5611
- const modeValues = JSON.stringify(THEME_MODE_VALUES);
5612
- const allowedModes = ((_options$allowedModes = options.allowedModes) === null || _options$allowedModes === void 0 ? void 0 : _options$allowedModes.length) ? options.allowedModes : THEME_MODE_VALUES;
5613
- const allowedModeValues = JSON.stringify(allowedModes);
5614
- const forceLightPresets = JSON.stringify(Array.from(FORCE_LIGHT_PRESETS));
5615
- const deprecatedMap = JSON.stringify(DEPRECATED_PRESET_MIGRATIONS);
5616
- const lockedPreset = options.lockedPreset;
5617
- const defaultPresetLiteral = JSON.stringify(lockedPreset !== null && lockedPreset !== void 0 ? lockedPreset : defaultPreset);
5618
- const defaultModeLiteral = JSON.stringify(coerceThemeMode(defaultMode, allowedModes, (_allowedModes$2 = allowedModes[0]) !== null && _allowedModes$2 !== void 0 ? _allowedModes$2 : "system"));
5619
- const lockedPresetLiteral = JSON.stringify(lockedPreset !== null && lockedPreset !== void 0 ? lockedPreset : null);
5620
- const styleId = JSON.stringify(GLOBAL_THEME_STYLE_ID);
5621
- const specKey = JSON.stringify(THEME_SPEC_STORAGE_KEY);
5622
- const tokensKey = JSON.stringify(THEME_TOKENS_STORAGE_KEY);
5623
- const presetKey = JSON.stringify(THEME_PRESET_STORAGE_KEY);
5624
- const modeKey = JSON.stringify(THEME_MODE_STORAGE_KEY);
5625
- const legacyKey = JSON.stringify(LEGACY_THEME_STORAGE_KEY);
5626
- const darkMq = JSON.stringify(DARK_MQ);
5627
- return `
5628
- try {
5629
- var pv=${presetValues},mv=${modeValues},am=${allowedModeValues},fp=${forceLightPresets},dm=${deprecatedMap},lk=${lockedPresetLiteral};
5630
- function mp(v){if(typeof v!=="string")return null;if(pv.indexOf(v)>=0)return v;return Object.prototype.hasOwnProperty.call(dm,v)?dm[v]:null;}
5631
- var p=${defaultPresetLiteral};
5632
- if(!lk){
5633
- var lp=localStorage.getItem(${legacyKey}),sp=localStorage.getItem(${presetKey});
5634
- var lpm=mp(lp),spm=mp(sp);
5635
- p=lpm||spm||${defaultPresetLiteral};
5636
- if(lpm){localStorage.setItem(${presetKey},lpm);localStorage.removeItem(${legacyKey});}
5637
- else if(sp&&spm&&sp!==spm){localStorage.setItem(${presetKey},spm);}
5638
- }
5639
- var sm=localStorage.getItem(${modeKey});
5640
- var m=(typeof sm==="string"&&mv.indexOf(sm)>=0&&am.indexOf(sm)>=0)?sm:${defaultModeLiteral};
5641
- var spec=null,tk=null;
5642
- if(!lk){try{var sj=localStorage.getItem(${specKey});if(sj)spec=JSON.parse(sj);}catch(e){}}
5643
- if(!lk){try{var tj=localStorage.getItem(${tokensKey});if(tj)tk=JSON.parse(tj);}catch(e){}}
5644
- if(!lk&&spec&&spec.kind==="generated"&&tk&&typeof tk.id==="string"&&tk.light&&typeof tk.light==="object"){
5645
- var fld=spec.forceLightOnly===true;
5646
- var dk=!fld&&(m==="dark"||(m==="system"&&matchMedia(${darkMq}).matches));
5647
- var tt=(dk&&tk.dark)?tk.dark:tk.light;
5648
- var cid=(dk&&tk.dark)?(tk.id+"-dark"):tk.id;
5649
- var css="";
5650
- for(var k in tt){if(Object.prototype.hasOwnProperty.call(tt,k))css+=k+":"+tt[k]+";"}
5651
- var st=document.getElementById(${styleId});
5652
- if(!st){st=document.createElement("style");st.id=${styleId};document.head.appendChild(st);}
5653
- st.textContent='[data-theme="'+cid+'"]{'+css+'}';
5654
- document.documentElement.setAttribute("data-theme",cid);
5655
- } else {
5656
- var d=fp.indexOf(p)<0&&(m==="dark"||(m==="system"&&matchMedia(${darkMq}).matches));
5657
- document.documentElement.setAttribute("data-theme",d?p+"-dark":p);
5658
- }
5659
- } catch(e){}`.replace(/\n\s*/g, "");
5660
- }
5661
- //#endregion
5662
- //#region src/lib/theme/theme-controller-context.tsx
5663
- const OptThemeControllerContext = (0, react.createContext)(null);
5664
- /**
5665
- * Reads the controller exposed by the nearest `OptThemeProvider`. Returns
5666
- * `null` when used outside a provider — callers should treat that as "no
5667
- * promotion available" and behave as if scope === "override".
5668
- */
5669
- function useOptThemeController() {
5670
- return (0, react.useContext)(OptThemeControllerContext);
5671
- }
5672
- //#endregion
5673
- //#region src/lib/theme/theme-provider.tsx
5674
- const THEME_STORAGE_KEYS = /* @__PURE__ */ new Set([
5675
- LEGACY_THEME_STORAGE_KEY,
5676
- THEME_PRESET_STORAGE_KEY,
5677
- THEME_MODE_STORAGE_KEY,
5678
- THEME_SPEC_STORAGE_KEY,
5679
- THEME_TOKENS_STORAGE_KEY
5680
- ]);
5681
- function getSystemDark() {
5682
- if (typeof window === "undefined") return false;
5683
- return window.matchMedia(DARK_MQ).matches;
5684
- }
5685
- function subscribeSystemDark(cb) {
5686
- if (typeof window === "undefined") return () => {};
5687
- const mql = window.matchMedia(DARK_MQ);
5688
- mql.addEventListener("change", cb);
5689
- return () => mql.removeEventListener("change", cb);
5690
- }
5691
- /**
5692
- * Read the persisted ThemeSpec, preferring a generated spec when present.
5693
- * Falls back to the legacy preset path otherwise. Does not touch localStorage
5694
- * apart from the legacy migration handled by `readStoredTheme`.
5695
- */
5696
- function readStoredSpec(defaultPreset, defaultMode, options = {}) {
5697
- const generated = safeParseStoredSpec(window.localStorage.getItem(THEME_SPEC_STORAGE_KEY));
5698
- const { preset, mode } = readStoredTheme(window.localStorage, defaultPreset, defaultMode, options);
5699
- if (generated && generated.kind === "generated") return {
5700
- spec: generated,
5701
- mode,
5702
- presetShadow: preset
5703
- };
5704
- return {
5705
- spec: presetTheme(preset),
5706
- mode,
5707
- presetShadow: preset
5708
- };
5709
- }
5710
- function persistSpec(spec) {
5711
- if (isPresetSpec(spec)) {
5712
- window.localStorage.setItem(THEME_PRESET_STORAGE_KEY, spec.preset);
5713
- window.localStorage.removeItem(THEME_SPEC_STORAGE_KEY);
5714
- window.localStorage.removeItem(THEME_TOKENS_STORAGE_KEY);
5715
- return;
5716
- }
5717
- if (isGeneratedSpec(spec)) {
5718
- const tokens = computeGeneratedTokens(spec);
5719
- window.localStorage.setItem(THEME_SPEC_STORAGE_KEY, JSON.stringify(spec));
5720
- if (tokens) window.localStorage.setItem(THEME_TOKENS_STORAGE_KEY, JSON.stringify(buildTokenCache(tokens)));
5721
- else window.localStorage.removeItem(THEME_TOKENS_STORAGE_KEY);
5722
- return;
5723
- }
5724
- const descriptor = spec.descriptor;
5725
- if (isThemePresetId(descriptor.id) && !descriptor.palette) {
5726
- window.localStorage.setItem(THEME_PRESET_STORAGE_KEY, descriptor.id);
5727
- window.localStorage.removeItem(THEME_SPEC_STORAGE_KEY);
5728
- window.localStorage.removeItem(THEME_TOKENS_STORAGE_KEY);
5729
- return;
5730
- }
5731
- if (descriptor.palette) persistSpec({
5732
- kind: "generated",
5733
- id: descriptor.id,
5734
- label: descriptor.label,
5735
- palette: descriptor.palette,
5736
- forceLightOnly: descriptor.forceLightOnly
5737
- });
5738
- }
5739
- function upsertGlobalStyle(css) {
5740
- if (typeof document === "undefined") return;
5741
- let node = document.getElementById(GLOBAL_THEME_STYLE_ID);
5742
- if (!node) {
5743
- node = document.createElement("style");
5744
- node.id = GLOBAL_THEME_STYLE_ID;
5745
- document.head.appendChild(node);
5746
- }
5747
- if (node.textContent !== css) node.textContent = css;
5748
- }
5749
- function removeGlobalStyle() {
5750
- var _document$getElementB;
5751
- if (typeof document === "undefined") return;
5752
- (_document$getElementB = document.getElementById("opt-global-theme")) === null || _document$getElementB === void 0 || _document$getElementB.remove();
5753
- }
5754
- const ThemeContext = (0, react.createContext)(void 0);
5755
- /** Renders the opt theme provider component. */
5756
- function OptThemeProvider({ children, defaultTheme, controlledTheme, defaultPreset = "default", defaultMode = "system", lockedPreset, allowedModes, allowThemePromotion = true }) {
5757
- var _allowedModes$, _ref, _effectiveStackTop$sp;
5758
- const normalizedDefaultMode = coerceThemeMode(defaultMode, allowedModes, (_allowedModes$ = allowedModes === null || allowedModes === void 0 ? void 0 : allowedModes[0]) !== null && _allowedModes$ !== void 0 ? _allowedModes$ : "system");
5759
- const initialSpec = (_ref = controlledTheme !== null && controlledTheme !== void 0 ? controlledTheme : lockedPreset ? presetTheme(lockedPreset) : defaultTheme) !== null && _ref !== void 0 ? _ref : presetTheme(defaultPreset);
5760
- const initialPresetShadow = isPresetSpec(initialSpec) ? initialSpec.preset : lockedPreset !== null && lockedPreset !== void 0 ? lockedPreset : defaultPreset;
5761
- const [theme, setThemeState] = (0, react.useState)(initialSpec);
5762
- const [presetShadow, setPresetShadow] = (0, react.useState)(initialPresetShadow);
5763
- const [mode, setModeState] = (0, react.useState)(normalizedDefaultMode);
5764
- /**
5765
- * Transient theme override stack — descendants (typically harnesses in
5766
- * promote-global mode) push specs that take priority over `controlledTheme`
5767
- * and persisted state. The stack is intentionally kept out of localStorage.
5768
- */
5769
- const [stack, setStack] = (0, react.useState)([]);
5770
- const isControlled = controlledTheme !== void 0;
5771
- const isLocked = !isControlled && lockedPreset !== void 0;
5772
- (0, react.useEffect)(() => {
5773
- if (!isControlled) return;
5774
- setThemeState(controlledTheme);
5775
- if (isPresetSpec(controlledTheme)) setPresetShadow(controlledTheme.preset);
5776
- }, [controlledTheme, isControlled]);
5777
- (0, react.useEffect)(() => {
5778
- if (isControlled) return;
5779
- if (isLocked) {
5780
- const locked = lockedPreset !== null && lockedPreset !== void 0 ? lockedPreset : defaultPreset;
5781
- const { mode: storedMode } = readStoredTheme(window.localStorage, locked, normalizedDefaultMode);
5782
- const nextMode = coerceThemeMode(storedMode, allowedModes, normalizedDefaultMode);
5783
- const nextSpec = presetTheme(locked);
5784
- setThemeState((prev) => themeEqual(prev, nextSpec) ? prev : nextSpec);
5785
- setPresetShadow((prev) => prev === locked ? prev : locked);
5786
- setModeState((prev) => prev === nextMode ? prev : nextMode);
5787
- return;
5788
- }
5789
- const next = readStoredSpec(defaultPreset, defaultMode, { migrateLegacy: true });
5790
- const nextMode = coerceThemeMode(next.mode, allowedModes, normalizedDefaultMode);
5791
- setThemeState((prev) => themeEqual(prev, next.spec) ? prev : next.spec);
5792
- setPresetShadow((prev) => prev === next.presetShadow ? prev : next.presetShadow);
5793
- setModeState((prev) => prev === nextMode ? prev : nextMode);
5794
- }, [
5795
- allowedModes,
5796
- isControlled,
5797
- isLocked,
5798
- lockedPreset,
5799
- normalizedDefaultMode
5800
- ]);
5801
- (0, react.useEffect)(() => {
5802
- if (isControlled) return;
5803
- function handleStorage(event) {
5804
- if (event.storageArea && event.storageArea !== window.localStorage) return;
5805
- if (event.key != null && !THEME_STORAGE_KEYS.has(event.key)) return;
5806
- if (isLocked) {
5807
- const locked = lockedPreset !== null && lockedPreset !== void 0 ? lockedPreset : defaultPreset;
5808
- const { mode: storedMode } = readStoredTheme(window.localStorage, locked, normalizedDefaultMode);
5809
- const nextMode = coerceThemeMode(storedMode, allowedModes, normalizedDefaultMode);
5810
- const nextSpec = presetTheme(locked);
5811
- setThemeState((prev) => themeEqual(prev, nextSpec) ? prev : nextSpec);
5812
- setPresetShadow((prev) => prev === locked ? prev : locked);
5813
- setModeState((prev) => prev === nextMode ? prev : nextMode);
5814
- return;
5815
- }
5816
- const next = readStoredSpec(defaultPreset, defaultMode, { migrateLegacy: event.key === LEGACY_THEME_STORAGE_KEY });
5817
- const nextMode = coerceThemeMode(next.mode, allowedModes, normalizedDefaultMode);
5818
- setThemeState((prev) => themeEqual(prev, next.spec) ? prev : next.spec);
5819
- setPresetShadow((prev) => prev === next.presetShadow ? prev : next.presetShadow);
5820
- setModeState((prev) => prev === nextMode ? prev : nextMode);
5821
- }
5822
- window.addEventListener("storage", handleStorage);
5823
- return () => window.removeEventListener("storage", handleStorage);
5824
- }, [
5825
- allowedModes,
5826
- isControlled,
5827
- isLocked,
5828
- defaultMode,
5829
- defaultPreset,
5830
- lockedPreset,
5831
- normalizedDefaultMode
5832
- ]);
5833
- const systemDark = (0, react.useSyncExternalStore)(subscribeSystemDark, getSystemDark, () => false);
5834
- const stackTop = stack.length > 0 ? stack[stack.length - 1] : null;
5835
- const effectiveStackTop = allowThemePromotion ? stackTop : null;
5836
- const isPromoted = effectiveStackTop !== null;
5837
- const effectiveSpec = (_effectiveStackTop$sp = effectiveStackTop === null || effectiveStackTop === void 0 ? void 0 : effectiveStackTop.spec) !== null && _effectiveStackTop$sp !== void 0 ? _effectiveStackTop$sp : theme;
5838
- const forceLight = isForceLightSpec(effectiveSpec);
5839
- const resolvedMode = computeResolvedMode(forceLight, mode, systemDark);
5840
- const compoundId = getCompoundIdForSpec(effectiveSpec, resolvedMode, forceLight);
5841
- const [hydrated, setHydrated] = (0, react.useState)(false);
5842
- (0, react.useEffect)(() => {
5843
- setHydrated(true);
5844
- }, []);
5845
- (0, react.useEffect)(() => {
5846
- if (!hydrated) return;
5847
- if (document.documentElement.getAttribute("data-theme") !== compoundId) document.documentElement.setAttribute("data-theme", compoundId);
5848
- }, [compoundId, hydrated]);
5849
- (0, react.useEffect)(() => {
5850
- if (isPresetSpec(effectiveSpec)) {
5851
- removeGlobalStyle();
5852
- return;
5853
- }
5854
- const tokens = computeGeneratedTokens(effectiveSpec);
5855
- if (!tokens) {
5856
- removeGlobalStyle();
5857
- return;
5858
- }
5859
- upsertGlobalStyle(serializeGeneratedTheme(tokens));
5860
- if (!isControlled && !isPromoted && effectiveSpec === theme) try {
5861
- window.localStorage.setItem(THEME_TOKENS_STORAGE_KEY, JSON.stringify(buildTokenCache(tokens)));
5862
- } catch (_unused) {}
5863
- }, [
5864
- effectiveSpec,
5865
- theme,
5866
- isControlled,
5867
- isPromoted
5868
- ]);
5869
- const setTheme = (0, react.useCallback)((next) => {
5870
- if (isLocked) {
5871
- if (process.env.NODE_ENV !== "production") console.warn("[OptThemeProvider] setTheme called while lockedPreset is set — ignoring.");
5872
- return;
5873
- }
5874
- if (isControlled) {
5875
- if (process.env.NODE_ENV !== "production") console.warn("[OptThemeProvider] setTheme called while controlledTheme is set — ignoring.");
5876
- return;
5877
- }
5878
- setThemeState(next);
5879
- if (isPresetSpec(next)) setPresetShadow(next.preset);
5880
- try {
5881
- persistSpec(next);
5882
- } catch (_unused2) {}
5883
- }, [isControlled, isLocked]);
5884
- const setPreset = (0, react.useCallback)((p) => {
5885
- setTheme(presetTheme(p));
5886
- }, [setTheme]);
5887
- const setMode = (0, react.useCallback)((m) => {
5888
- const nextMode = coerceThemeMode(m, allowedModes, normalizedDefaultMode);
5889
- setModeState(nextMode);
5890
- if (!isControlled) try {
5891
- window.localStorage.setItem(THEME_MODE_STORAGE_KEY, nextMode);
5892
- } catch (_unused3) {}
5893
- }, [
5894
- allowedModes,
5895
- isControlled,
5896
- normalizedDefaultMode
5897
- ]);
5898
- const controller = (0, react.useMemo)(() => ({
5899
- pushTheme(id, spec) {
5900
- if (!allowThemePromotion) return;
5901
- setStack((prev) => {
5902
- return [...prev.filter((entry) => entry.id !== id), {
5903
- id,
5904
- spec
5905
- }];
5906
- });
5907
- },
5908
- popTheme(id) {
5909
- if (!allowThemePromotion) return;
5910
- setStack((prev) => prev.filter((entry) => entry.id !== id));
5911
- }
5912
- }), [allowThemePromotion]);
5913
- const value = (0, react.useMemo)(() => ({
5914
- theme: effectiveSpec,
5915
- setTheme,
5916
- preset: presetShadow,
5917
- setPreset,
5918
- mode,
5919
- setMode,
5920
- resolvedMode,
5921
- isControlled,
5922
- isGenerated: !isPresetSpec(effectiveSpec),
5923
- isPromoted
5924
- }), [
5925
- effectiveSpec,
5926
- setTheme,
5927
- presetShadow,
5928
- setPreset,
5929
- mode,
5930
- setMode,
5931
- resolvedMode,
5932
- isControlled,
5933
- isPromoted
5934
- ]);
5935
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeContext.Provider, {
5936
- value,
5937
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OptThemeControllerContext.Provider, {
5938
- value: controller,
5939
- children
5940
- })
5941
- });
5942
- }
5943
- /** Provides opt theme. */
5944
- function useOptTheme() {
5945
- const ctx = (0, react.useContext)(ThemeContext);
5946
- if (!ctx) throw new Error("useOptTheme must be used within OptThemeProvider");
5947
- return ctx;
5948
- }
5949
- /** Reads opt theme context when present without requiring a provider. */
5950
- function useOptionalOptTheme() {
5951
- return (0, react.useContext)(ThemeContext);
5952
- }
5953
- function computeResolvedMode(forceLight, mode, systemDark) {
5954
- if (forceLight) return "light";
5955
- if (mode === "system") return systemDark ? "dark" : "light";
5956
- return mode;
5957
- }
5958
- function themeEqual(a, b) {
5959
- if (a === b) return true;
5960
- if (a.kind !== b.kind) return false;
5961
- if (a.kind === "preset" && b.kind === "preset") return a.preset === b.preset && overridesEqual(a.overrides, b.overrides);
5962
- if (a.kind === "generated" && b.kind === "generated") return a.id === b.id && a.label === b.label && a.forceLightOnly === b.forceLightOnly && JSON.stringify(a.palette) === JSON.stringify(b.palette) && overridesEqual(a.overrides, b.overrides);
5963
- if (a.kind === "descriptor" && b.kind === "descriptor") return a.descriptor === b.descriptor && overridesEqual(a.overrides, b.overrides);
5964
- return false;
5965
- }
5966
- function overridesEqual(a, b) {
5967
- if (a === b) return true;
5968
- if (!a && !b) return true;
5969
- if (!a || !b) return false;
5970
- return JSON.stringify(a) === JSON.stringify(b);
5971
- }
5972
4865
  //#endregion
5973
4866
  //#region src/shells/theme-switcher.tsx
5974
4867
  const FALLBACK_SWATCHES = [
@@ -5977,9 +4870,9 @@ const FALLBACK_SWATCHES = [
5977
4870
  "var(--opt-text)"
5978
4871
  ];
5979
4872
  function buildThemeOptions() {
5980
- return THEME_PRESET_IDS.map((id) => {
4873
+ return require_field_sidebar.THEME_PRESET_IDS.map((id) => {
5981
4874
  var _descriptor$switcherS;
5982
- const descriptor = THEME_REGISTRY[id];
4875
+ const descriptor = require_field_sidebar.THEME_REGISTRY[id];
5983
4876
  return {
5984
4877
  value: id,
5985
4878
  label: descriptor.label,
@@ -6060,7 +4953,7 @@ function resolveLabels(user) {
6060
4953
  /** Renders the theme switcher component. */
6061
4954
  function ThemeSwitcher({ className, labels: userLabels, variant = "default", customPresetEditor, preset: controlledPreset, onPresetChange, mode: controlledMode, onModeChange }) {
6062
4955
  var _ref;
6063
- const themeContext = useOptionalOptTheme();
4956
+ const themeContext = require_field_sidebar.useOptionalOptTheme();
6064
4957
  const preset = controlledPreset !== null && controlledPreset !== void 0 ? controlledPreset : themeContext === null || themeContext === void 0 ? void 0 : themeContext.preset;
6065
4958
  const mode = (_ref = controlledMode !== null && controlledMode !== void 0 ? controlledMode : themeContext === null || themeContext === void 0 ? void 0 : themeContext.mode) !== null && _ref !== void 0 ? _ref : "light";
6066
4959
  const setPreset = onPresetChange !== null && onPresetChange !== void 0 ? onPresetChange : themeContext === null || themeContext === void 0 ? void 0 : themeContext.setPreset;
@@ -6069,7 +4962,7 @@ function ThemeSwitcher({ className, labels: userLabels, variant = "default", cus
6069
4962
  const labels = resolveLabels(userLabels);
6070
4963
  const options = buildThemeOptions();
6071
4964
  const activePreset = preset;
6072
- const forcedMode = FORCE_LIGHT_PRESET_IDS.has(activePreset);
4965
+ const forcedMode = require_field_sidebar.FORCE_LIGHT_PRESET_IDS.has(activePreset);
6073
4966
  const showCustomBadge = controlledPreset === void 0 && ((themeContext === null || themeContext === void 0 ? void 0 : themeContext.isGenerated) === true || (themeContext === null || themeContext === void 0 ? void 0 : themeContext.isPromoted) === true);
6074
4967
  if (options.length === 0) return null;
6075
4968
  if (variant === "compact") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -6762,10 +5655,10 @@ function BulkActions({ selectedCount, actions, onAction, onClear, labels: custom
6762
5655
  labels.selected
6763
5656
  ]
6764
5657
  }),
6765
- hasActions ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_key_pad_menu.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.DropdownTrigger, {
5658
+ hasActions ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.DropdownTrigger, {
6766
5659
  className: "border-border bg-surface text-text-primary hover:bg-bg-subtle inline-flex h-8 items-center rounded-md border px-3 text-sm font-medium",
6767
5660
  children: labels.actions
6768
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.DropdownContent, { children: actions.map((action) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.DropdownItem, {
5661
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.DropdownContent, { children: actions.map((action) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.DropdownItem, {
6769
5662
  onClick: () => onAction(action.id),
6770
5663
  className: action.variant === "danger" ? "text-danger" : void 0,
6771
5664
  children: action.label
@@ -7800,7 +6693,7 @@ function FeatureFlagPanel({ flags, onToggle, onRolloutChange, environments, clas
7800
6693
  className: "text-text-tertiary text-xs",
7801
6694
  children: flag.description
7802
6695
  })]
7803
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_key_pad_menu.Switch, {
6696
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.Switch, {
7804
6697
  checked: flag.enabled,
7805
6698
  onChange: (checked) => onToggle(flag.id, checked),
7806
6699
  label: flag.enabled ? labels.enabled : labels.disabled
@@ -9284,7 +8177,7 @@ const enStarRatingLabels = {
9284
8177
  };
9285
8178
  const enBreadcrumbLabels = { navAriaLabel: "Go to {label}" };
9286
8179
  //#endregion
9287
- exports.ALL_COMPOUND_THEMES = ALL_COMPOUND_THEMES;
8180
+ exports.ALL_COMPOUND_THEMES = require_field_sidebar.ALL_COMPOUND_THEMES;
9288
8181
  exports.AccordionContent = require_key_pad_menu.AccordionContent;
9289
8182
  exports.AccordionItem = require_key_pad_menu.AccordionItem;
9290
8183
  exports.AccordionRoot = require_key_pad_menu.AccordionRoot;
@@ -9308,7 +8201,7 @@ exports.Breadcrumb = require_key_pad_menu.Breadcrumb;
9308
8201
  exports.BulkActions = BulkActions;
9309
8202
  exports.Button = require_text_truncate.Button;
9310
8203
  exports.COLOR_PRESETS = COLOR_PRESETS;
9311
- exports.Callout = Callout;
8204
+ exports.Callout = require_field_sidebar.Callout;
9312
8205
  exports.Card = require_key_pad_menu.Card;
9313
8206
  exports.CardContent = require_key_pad_menu.CardContent;
9314
8207
  exports.CardDescription = require_key_pad_menu.CardDescription;
@@ -9367,7 +8260,7 @@ exports.DataImportWizard = DataImportWizard;
9367
8260
  exports.DataTable = require_field_sidebar.DataTable;
9368
8261
  exports.DateRangePicker = require_text_truncate.DateRangePicker;
9369
8262
  exports.DeploymentTimeline = require_field_sidebar.DeploymentTimeline;
9370
- exports.DescriptionList = require_key_pad_menu.DescriptionList;
8263
+ exports.DescriptionList = require_text_truncate.DescriptionList;
9371
8264
  exports.DesignGuidePanel = DesignGuidePanel;
9372
8265
  exports.DialogBody = require_text_truncate.DialogBody;
9373
8266
  exports.DialogDescription = require_text_truncate.DialogDescription;
@@ -9385,13 +8278,14 @@ exports.DomainTable = require_field_sidebar.DomainTable;
9385
8278
  exports.DrawerClose = require_key_pad_menu.DrawerClose;
9386
8279
  exports.DrawerPanel = require_key_pad_menu.DrawerPanel;
9387
8280
  exports.DrawerRoot = require_key_pad_menu.DrawerRoot;
9388
- exports.DropdownContent = require_key_pad_menu.DropdownContent;
9389
- exports.DropdownItem = require_key_pad_menu.DropdownItem;
9390
- exports.DropdownMenu = require_key_pad_menu.DropdownMenu;
9391
- exports.DropdownSeparator = require_key_pad_menu.DropdownSeparator;
9392
- exports.DropdownTrigger = require_key_pad_menu.DropdownTrigger;
8281
+ exports.DropdownContent = require_text_truncate.DropdownContent;
8282
+ exports.DropdownItem = require_text_truncate.DropdownItem;
8283
+ exports.DropdownMenu = require_text_truncate.DropdownMenu;
8284
+ exports.DropdownSeparator = require_text_truncate.DropdownSeparator;
8285
+ exports.DropdownTrigger = require_text_truncate.DropdownTrigger;
9393
8286
  exports.DynamicFieldForm = DynamicFieldForm;
9394
8287
  exports.EMPTY_QUERY = require_field_sidebar.EMPTY_QUERY;
8288
+ exports.EMPTY_QUERY_FILTERS = require_field_sidebar.EMPTY_QUERY_FILTERS;
9395
8289
  exports.EditorToolbar = require_field_sidebar.EditorToolbar;
9396
8290
  exports.EmptyState = require_text_truncate.EmptyState;
9397
8291
  exports.EnvPanel = require_field_sidebar.EnvPanel;
@@ -9409,8 +8303,8 @@ exports.ExportButton = ExportButton;
9409
8303
  exports.Expression = require_key_pad_menu.Expression;
9410
8304
  exports.ExpressionGroup = require_key_pad_menu.ExpressionGroup;
9411
8305
  exports.FIELD_TYPE_TOKENS = require_text_truncate.FIELD_TYPE_TOKENS;
9412
- exports.FORCE_LIGHT_PRESETS = FORCE_LIGHT_PRESETS;
9413
- exports.FORCE_LIGHT_PRESET_IDS = FORCE_LIGHT_PRESET_IDS;
8306
+ exports.FORCE_LIGHT_PRESETS = require_field_sidebar.FORCE_LIGHT_PRESETS;
8307
+ exports.FORCE_LIGHT_PRESET_IDS = require_field_sidebar.FORCE_LIGHT_PRESET_IDS;
9414
8308
  exports.Facet = require_key_pad_menu.Facet;
9415
8309
  exports.FacetGroup = require_key_pad_menu.FacetGroup;
9416
8310
  exports.FailureList = require_field_sidebar.FailureList;
@@ -9452,8 +8346,8 @@ exports.FormSubmit = require_text_truncate.FormSubmit;
9452
8346
  exports.FormSwitch = require_text_truncate.FormSwitch;
9453
8347
  exports.FormTagInput = require_text_truncate.FormTagInput;
9454
8348
  exports.FormTextarea = require_text_truncate.FormTextarea;
9455
- exports.GENERATED_THEME_ID_DEFAULT = GENERATED_THEME_ID_DEFAULT;
9456
- exports.GLOBAL_THEME_STYLE_ID = GLOBAL_THEME_STYLE_ID;
8349
+ exports.GENERATED_THEME_ID_DEFAULT = require_field_sidebar.GENERATED_THEME_ID_DEFAULT;
8350
+ exports.GLOBAL_THEME_STYLE_ID = require_field_sidebar.GLOBAL_THEME_STYLE_ID;
9457
8351
  exports.Heading = require_key_pad_menu.Heading;
9458
8352
  exports.Highlight = require_text_truncate.Highlight;
9459
8353
  exports.IconPicker = require_text_truncate.IconPicker;
@@ -9494,8 +8388,8 @@ exports.NotificationToast = require_field_sidebar.NotificationToast;
9494
8388
  exports.NumberInput = require_text_truncate.NumberInput;
9495
8389
  exports.OPT_TEXT_PRIMARY = require_text_truncate.OPT_TEXT_PRIMARY;
9496
8390
  exports.OPT_TEXT_SECONDARY = require_text_truncate.OPT_TEXT_SECONDARY;
9497
- exports.OptThemeControllerContext = OptThemeControllerContext;
9498
- exports.OptThemeProvider = OptThemeProvider;
8391
+ exports.OptThemeControllerContext = require_field_sidebar.OptThemeControllerContext;
8392
+ exports.OptThemeProvider = require_field_sidebar.OptThemeProvider;
9499
8393
  exports.OtpField = require_key_pad_menu.OtpField;
9500
8394
  exports.POPULAR_ICONS = POPULAR_ICONS;
9501
8395
  exports.PageAside = PageAside;
@@ -9511,7 +8405,14 @@ exports.PromptTemplate = PromptTemplate;
9511
8405
  exports.PropertyExplorer = PropertyExplorer;
9512
8406
  exports.QueryBar = require_field_sidebar.QueryBar;
9513
8407
  exports.QueryFilterBar = QueryFilterBar;
9514
- exports.QueryResultsTable = QueryResultsTable;
8408
+ exports.QueryFiltersMenu = require_field_sidebar.QueryFiltersMenu;
8409
+ exports.QueryHistoryList = require_field_sidebar.QueryHistoryList;
8410
+ exports.QueryOutputPane = require_field_sidebar.QueryOutputPane;
8411
+ exports.QueryResultChart = require_field_sidebar.QueryResultChart;
8412
+ exports.QueryResultsTable = require_field_sidebar.QueryResultsTable;
8413
+ exports.QueryToolbar = require_field_sidebar.QueryToolbar;
8414
+ exports.QueryVariablesMenu = require_field_sidebar.QueryVariablesMenu;
8415
+ exports.QueryWorkspace = require_field_sidebar.QueryWorkspace;
9515
8416
  exports.QuickActions = QuickActions;
9516
8417
  exports.Radio = require_key_pad_menu.Radio;
9517
8418
  exports.RadioGroup = require_key_pad_menu.RadioGroup;
@@ -9522,9 +8423,9 @@ Object.defineProperty(exports, "ReportWidget", {
9522
8423
  return _reopt_ai_opt_charts.ReportWidget;
9523
8424
  }
9524
8425
  });
9525
- exports.ResizableHandle = require_key_pad_menu.ResizableHandle;
9526
- exports.ResizablePanel = require_key_pad_menu.ResizablePanel;
9527
- exports.ResizablePanelGroup = require_key_pad_menu.ResizablePanelGroup;
8426
+ exports.ResizableHandle = require_text_truncate.ResizableHandle;
8427
+ exports.ResizablePanel = require_text_truncate.ResizablePanel;
8428
+ exports.ResizablePanelGroup = require_text_truncate.ResizablePanelGroup;
9528
8429
  exports.RichTextEditor = RichTextEditor;
9529
8430
  exports.RouteFocusManager = RouteFocusManager;
9530
8431
  exports.SHADER_OVERLAY_PARAM_KEYS = require_key_pad_menu.SHADER_OVERLAY_PARAM_KEYS;
@@ -9532,13 +8433,15 @@ exports.SHADER_PARAM_FALLBACK = require_key_pad_menu.SHADER_PARAM_FALLBACK;
9532
8433
  exports.SHADER_PARAM_KEYS = require_key_pad_menu.SHADER_PARAM_KEYS;
9533
8434
  exports.SHADER_PRESETS = require_key_pad_menu.SHADER_PRESETS;
9534
8435
  exports.SHADER_PRESET_IDS = require_key_pad_menu.SHADER_PRESET_IDS;
8436
+ exports.SaveQueryDialog = require_field_sidebar.SaveQueryDialog;
9535
8437
  exports.SavedFilters = SavedFilters;
8438
+ exports.SchemaTree = require_field_sidebar.SchemaTree;
9536
8439
  exports.ScoreBreakdown = require_field_sidebar.ScoreBreakdown;
9537
8440
  exports.ScrollArea = require_key_pad_menu.ScrollArea;
9538
8441
  exports.SearchCombobox = require_field_sidebar.SearchCombobox;
9539
8442
  exports.Section = require_key_pad_menu.Section;
9540
8443
  exports.SegmentBuilder = SegmentBuilder;
9541
- exports.SegmentedControl = SegmentedControl;
8444
+ exports.SegmentedControl = require_field_sidebar.SegmentedControl;
9542
8445
  exports.SelectItem = require_text_truncate.SelectItem;
9543
8446
  exports.SelectLabel = require_text_truncate.SelectLabel;
9544
8447
  exports.SelectPopover = require_text_truncate.SelectPopover;
@@ -9557,7 +8460,7 @@ exports.SkeletonText = require_text_truncate.SkeletonText;
9557
8460
  exports.Slider = require_text_truncate.Slider;
9558
8461
  exports.SpatialNavProvider = SpatialNavProvider;
9559
8462
  exports.Spinner = require_text_truncate.Spinner;
9560
- exports.SqlEditor = SqlEditor;
8463
+ exports.SqlEditor = require_field_sidebar.SqlEditor;
9561
8464
  exports.StarRating = require_text_truncate.StarRating;
9562
8465
  exports.StatCard = require_text_truncate.StatCard;
9563
8466
  exports.StatusDot = StatusDot;
@@ -9565,12 +8468,12 @@ exports.StatusSelect = require_field_sidebar.StatusSelect;
9565
8468
  exports.StepBuilder = require_key_pad_menu.StepBuilder;
9566
8469
  exports.SummaryRow = SummaryRow;
9567
8470
  exports.SurfaceLayout = require_key_pad_menu.BlockLayout;
9568
- exports.Switch = require_key_pad_menu.Switch;
8471
+ exports.Switch = require_text_truncate.Switch;
9569
8472
  exports.THEME_PALETTES = require_key_pad_menu.THEME_PALETTES;
9570
- exports.THEME_PRESET_IDS = THEME_PRESET_IDS;
9571
- exports.THEME_REGISTRY = THEME_REGISTRY;
9572
- exports.THEME_SPEC_STORAGE_KEY = THEME_SPEC_STORAGE_KEY;
9573
- exports.THEME_TOKENS_STORAGE_KEY = THEME_TOKENS_STORAGE_KEY;
8473
+ exports.THEME_PRESET_IDS = require_field_sidebar.THEME_PRESET_IDS;
8474
+ exports.THEME_REGISTRY = require_field_sidebar.THEME_REGISTRY;
8475
+ exports.THEME_SPEC_STORAGE_KEY = require_field_sidebar.THEME_SPEC_STORAGE_KEY;
8476
+ exports.THEME_TOKENS_STORAGE_KEY = require_field_sidebar.THEME_TOKENS_STORAGE_KEY;
9574
8477
  exports.Tab = require_text_truncate.Tab;
9575
8478
  exports.TabList = require_text_truncate.TabList;
9576
8479
  exports.TabPanel = require_text_truncate.TabPanel;
@@ -9581,7 +8484,7 @@ exports.TeamMemberList = TeamMemberList;
9581
8484
  exports.TemplatePicker = TemplatePicker;
9582
8485
  exports.Text = require_key_pad_menu.Text;
9583
8486
  exports.TextTruncate = require_text_truncate.TextTruncate;
9584
- exports.Textarea = require_key_pad_menu.Textarea;
8487
+ exports.Textarea = require_text_truncate.Textarea;
9585
8488
  exports.ThemeSwitcher = ThemeSwitcher;
9586
8489
  exports.TimeRangeControl = require_field_sidebar.TimeRangeControl;
9587
8490
  exports.TimeRangeSelector = TimeRangeSelector;
@@ -9603,6 +8506,7 @@ Object.defineProperty(exports, "TrendChart", {
9603
8506
  return _reopt_ai_opt_charts.TrendChart;
9604
8507
  }
9605
8508
  });
8509
+ exports.VALUELESS_OPERATORS = require_field_sidebar.VALUELESS_OPERATORS;
9606
8510
  exports.VerticalTabs = VerticalTabs;
9607
8511
  exports.VirtualList = require_key_pad_menu.VirtualList;
9608
8512
  exports.WebhookConfig = WebhookConfig;
@@ -9611,15 +8515,17 @@ exports.WizardForm = WizardForm;
9611
8515
  exports.WorkflowCanvas = require_field_sidebar.WorkflowCanvas;
9612
8516
  exports.addClause = require_field_sidebar.addClause;
9613
8517
  exports.applyCellAction = require_field_sidebar.applyCellAction;
9614
- exports.buildTokenCache = buildTokenCache;
8518
+ exports.buildTokenCache = require_field_sidebar.buildTokenCache;
9615
8519
  exports.cn = require_text_truncate.cn;
9616
- exports.coerceThemeMode = coerceThemeMode;
9617
- exports.computeGeneratedTokens = computeGeneratedTokens;
8520
+ exports.coerceThemeMode = require_field_sidebar.coerceThemeMode;
8521
+ exports.computeGeneratedTokens = require_field_sidebar.computeGeneratedTokens;
9618
8522
  exports.computeSpatialTargets = computeSpatialTargets;
8523
+ exports.countActiveQueryFilters = require_field_sidebar.countActiveQueryFilters;
9619
8524
  exports.createBlock = require_key_pad_menu.createBlock;
9620
8525
  exports.createSurface = require_key_pad_menu.createBlock;
9621
- exports.createThemeBootScript = createThemeBootScript;
9622
- exports.defineThemeOverrides = defineThemeOverrides;
8526
+ exports.createThemeBootScript = require_field_sidebar.createThemeBootScript;
8527
+ exports.defaultQueryChartConfig = require_field_sidebar.defaultQueryChartConfig;
8528
+ exports.defineThemeOverrides = require_field_sidebar.defineThemeOverrides;
9623
8529
  exports.describeClause = require_field_sidebar.describeClause;
9624
8530
  exports.enBreadcrumbLabels = enBreadcrumbLabels;
9625
8531
  exports.enComboboxLabels = enComboboxLabels;
@@ -9631,42 +8537,51 @@ exports.formatOptNumber = require_text_truncate.formatOptNumber;
9631
8537
  exports.formatOptShortDate = require_text_truncate.formatOptShortDate;
9632
8538
  exports.formatOptTime = require_text_truncate.formatOptTime;
9633
8539
  exports.formatQuery = require_field_sidebar.formatQuery;
9634
- exports.generatedTheme = generatedTheme;
9635
- exports.getCompoundIdForSpec = getCompoundIdForSpec;
9636
- exports.getCompoundTheme = getCompoundTheme;
8540
+ exports.formatQueryCell = require_field_sidebar.formatQueryCell;
8541
+ exports.generatedTheme = require_field_sidebar.generatedTheme;
8542
+ exports.getCompoundIdForSpec = require_field_sidebar.getCompoundIdForSpec;
8543
+ exports.getCompoundTheme = require_field_sidebar.getCompoundTheme;
9637
8544
  exports.getShaderFragment = require_key_pad_menu.getShaderFragment;
9638
8545
  exports.getShaderPreset = require_key_pad_menu.getShaderPreset;
9639
- exports.getThemeDescriptor = getThemeDescriptor;
8546
+ exports.getThemeDescriptor = require_field_sidebar.getThemeDescriptor;
9640
8547
  exports.getTrappedContextRole = getTrappedContextRole;
9641
8548
  exports.hasActiveQuery = hasActiveQuery;
9642
- exports.isDescriptorSpec = isDescriptorSpec;
8549
+ exports.hasActiveQueryFilters = require_field_sidebar.hasActiveQueryFilters;
8550
+ exports.isDescriptorSpec = require_field_sidebar.isDescriptorSpec;
9643
8551
  exports.isEmptyQuery = require_field_sidebar.isEmptyQuery;
9644
- exports.isForceLightSpec = isForceLightSpec;
9645
- exports.isGeneratedSpec = isGeneratedSpec;
9646
- exports.isPresetSpec = isPresetSpec;
9647
- exports.isThemePresetId = isThemePresetId;
8552
+ exports.isForceLightSpec = require_field_sidebar.isForceLightSpec;
8553
+ exports.isGeneratedSpec = require_field_sidebar.isGeneratedSpec;
8554
+ exports.isPresetSpec = require_field_sidebar.isPresetSpec;
8555
+ exports.isThemePresetId = require_field_sidebar.isThemePresetId;
8556
+ exports.isValidQueryVariableName = require_field_sidebar.isValidQueryVariableName;
9648
8557
  exports.koBreadcrumbLabels = require_text_truncate.koBreadcrumbLabels;
9649
8558
  exports.koComboboxLabels = require_text_truncate.koComboboxLabels;
9650
8559
  exports.koStarRatingLabels = require_text_truncate.koStarRatingLabels;
9651
8560
  exports.matchesQuery = matchesQuery;
9652
8561
  exports.matchesQueryObject = matchesQueryObject;
8562
+ exports.numericResultColumns = require_field_sidebar.numericResultColumns;
9653
8563
  exports.parseQuery = require_field_sidebar.parseQuery;
9654
8564
  exports.parseQueryWithDiagnostics = require_field_sidebar.parseQueryWithDiagnostics;
9655
- exports.presetTheme = presetTheme;
8565
+ exports.presetTheme = require_field_sidebar.presetTheme;
9656
8566
  exports.queryFields = require_field_sidebar.queryFields;
9657
8567
  exports.quoteValue = require_field_sidebar.quoteValue;
9658
- exports.readStoredTheme = readStoredTheme;
8568
+ exports.readStoredTheme = require_field_sidebar.readStoredTheme;
9659
8569
  exports.removeClause = require_field_sidebar.removeClause;
9660
- exports.resolveDescriptor = resolveDescriptor;
8570
+ exports.replaceSqlPlaceholder = replaceSqlPlaceholder;
8571
+ exports.resolveDescriptor = require_field_sidebar.resolveDescriptor;
9661
8572
  exports.resolveFieldType = require_text_truncate.resolveFieldType;
9662
- exports.resolveThemeMode = resolveThemeMode;
9663
- exports.safeParseStoredSpec = safeParseStoredSpec;
9664
- exports.safeParseStoredTokens = safeParseStoredTokens;
8573
+ exports.resolveThemeMode = require_field_sidebar.resolveThemeMode;
8574
+ exports.safeParseStoredSpec = require_field_sidebar.safeParseStoredSpec;
8575
+ exports.safeParseStoredTokens = require_field_sidebar.safeParseStoredTokens;
9665
8576
  exports.schemaValidator = schemaValidator;
9666
- exports.serializeGeneratedTheme = serializeGeneratedTheme;
9667
- exports.serializeThemeRule = serializeThemeRule;
9668
- exports.serializeTokenBody = serializeTokenBody;
8577
+ exports.serializeGeneratedTheme = require_field_sidebar.serializeGeneratedTheme;
8578
+ exports.serializeThemeRule = require_field_sidebar.serializeThemeRule;
8579
+ exports.serializeTokenBody = require_field_sidebar.serializeTokenBody;
9669
8580
  exports.shouldSkipArrow = shouldSkipArrow;
8581
+ exports.splitSqlStatements = splitSqlStatements;
8582
+ exports.sqlPlaceholderNames = sqlPlaceholderNames;
8583
+ exports.sqlStatementAtOffset = sqlStatementAtOffset;
8584
+ exports.sqlUsesPlaceholder = sqlUsesPlaceholder;
9670
8585
  exports.toast = require_field_sidebar.toast;
9671
8586
  exports.useAutoRefresh = require_field_sidebar.useAutoRefresh;
9672
8587
  exports.useControlledState = require_text_truncate.useControlledState;
@@ -9674,9 +8589,9 @@ exports.useFieldValue = _reopt_ai_opt_ui_primitives.useFieldValue;
9674
8589
  exports.useFormContext = _reopt_ai_opt_ui_primitives.useFormContext;
9675
8590
  exports.useFormStore = _reopt_ai_opt_ui_primitives.useFormStore;
9676
8591
  exports.useInputId = require_text_truncate.useInputId;
9677
- exports.useOptTheme = useOptTheme;
9678
- exports.useOptThemeController = useOptThemeController;
9679
- exports.useOptionalOptTheme = useOptionalOptTheme;
8592
+ exports.useOptTheme = require_field_sidebar.useOptTheme;
8593
+ exports.useOptThemeController = require_field_sidebar.useOptThemeController;
8594
+ exports.useOptionalOptTheme = require_field_sidebar.useOptionalOptTheme;
9680
8595
  exports.useSidebar = useSidebar;
9681
8596
  exports.useToast = require_field_sidebar.useToast;
9682
8597
  exports.withFieldValue = require_field_sidebar.withFieldValue;