@reopt-ai/opt-ui 1.11.0 → 1.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/COMPONENT_CATALOG.md +495 -230
  2. package/README.md +43 -5
  3. package/dist/core/index.cjs +2 -2
  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 +154 -85
  8. package/dist/docs/02-components/02-visuals.md +1 -1
  9. package/dist/docs/02-components/03-shells.md +349 -149
  10. package/dist/docs/02-components/04-surfaces.md +1 -1
  11. package/dist/docs/02-components/index.md +5 -5
  12. package/dist/docs/03-recipes/02-dashboards.md +126 -10
  13. package/dist/{field-sidebar-B5SQC35J.d.cts → field-sidebar-CrYlRZew.d.ts} +164 -154
  14. package/dist/{field-sidebar-DAuN4jPV.cjs → field-sidebar-oa6zOmcd.cjs} +1540 -1537
  15. package/dist/{field-sidebar-CBeWE8xX.d.ts → field-sidebar-uXmoyvd7.d.cts} +164 -154
  16. package/dist/{field-sidebar-BXl5RJ3q.js → field-sidebar-zkkqC7__.js} +1541 -1540
  17. package/dist/id-registry.cjs +78 -6
  18. package/dist/id-registry.d.cts +1 -2
  19. package/dist/id-registry.d.ts +1 -2
  20. package/dist/id-registry.js +78 -8
  21. package/dist/id-registry.json +168 -19
  22. package/dist/index.cjs +1127 -224
  23. package/dist/index.d.cts +567 -58
  24. package/dist/index.d.ts +567 -58
  25. package/dist/index.js +1118 -227
  26. package/dist/{key-pad-menu-BxTy_u0Q.d.cts → key-pad-menu-CwcY_Vps.d.cts} +2 -3
  27. package/dist/{key-pad-menu-wXkWn1I1.js → key-pad-menu-Di2aRGbM.js} +4 -6
  28. package/dist/{key-pad-menu-Cg6rZBie.cjs → key-pad-menu-SItoHPLu.cjs} +1 -1
  29. package/dist/{key-pad-menu-u5GTJl9B.d.ts → key-pad-menu-WBJShCJn.d.ts} +3 -4
  30. package/dist/meta.cjs +894 -28
  31. package/dist/meta.d.cts +12 -36
  32. package/dist/meta.d.ts +12 -36
  33. package/dist/meta.js +894 -30
  34. package/dist/query.d.cts +1 -2
  35. package/dist/query.d.ts +1 -2
  36. package/dist/query.js +0 -2
  37. package/dist/shells/index.cjs +1 -1
  38. package/dist/shells/index.d.cts +1 -1
  39. package/dist/shells/index.d.ts +1 -1
  40. package/dist/shells/index.js +1 -1
  41. package/dist/tailwind.css +7 -0
  42. package/dist/{text-truncate-DW78lg4S.d.cts → text-truncate-CQyfUZvq.d.cts} +31 -3
  43. package/dist/{text-truncate-DW78lg4S.d.ts → text-truncate-CQyfUZvq.d.ts} +31 -3
  44. package/dist/{text-truncate-C17HHCR-.js → text-truncate-DSuZECy0.js} +43 -10
  45. package/dist/{text-truncate-BZdL1k5Z.cjs → text-truncate-I1XLWmRa.cjs} +48 -7
  46. package/dist/theme/server.d.cts +1 -2
  47. package/dist/theme/server.d.ts +1 -2
  48. package/dist/theme/server.js +0 -2
  49. package/dist/visuals/index.js +0 -1
  50. package/package.json +4 -3
  51. package/dist/field-sidebar-B5SQC35J.d.cts.map +0 -1
  52. package/dist/field-sidebar-BXl5RJ3q.js.map +0 -1
  53. package/dist/field-sidebar-CBeWE8xX.d.ts.map +0 -1
  54. package/dist/id-registry.d.cts.map +0 -1
  55. package/dist/id-registry.d.ts.map +0 -1
  56. package/dist/id-registry.js.map +0 -1
  57. package/dist/index.d.cts.map +0 -1
  58. package/dist/index.d.ts.map +0 -1
  59. package/dist/index.js.map +0 -1
  60. package/dist/key-pad-menu-BxTy_u0Q.d.cts.map +0 -1
  61. package/dist/key-pad-menu-u5GTJl9B.d.ts.map +0 -1
  62. package/dist/key-pad-menu-wXkWn1I1.js.map +0 -1
  63. package/dist/meta.d.cts.map +0 -1
  64. package/dist/meta.d.ts.map +0 -1
  65. package/dist/meta.js.map +0 -1
  66. package/dist/query.d.cts.map +0 -1
  67. package/dist/query.d.ts.map +0 -1
  68. package/dist/query.js.map +0 -1
  69. package/dist/text-truncate-C17HHCR-.js.map +0 -1
  70. package/dist/text-truncate-DW78lg4S.d.cts.map +0 -1
  71. package/dist/text-truncate-DW78lg4S.d.ts.map +0 -1
  72. package/dist/theme/server.d.cts.map +0 -1
  73. package/dist/theme/server.d.ts.map +0 -1
  74. package/dist/theme/server.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,17 +1,355 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_text_truncate = require("./text-truncate-BZdL1k5Z.cjs");
4
- const require_key_pad_menu = require("./key-pad-menu-Cg6rZBie.cjs");
5
- const require_field_sidebar = require("./field-sidebar-DAuN4jPV.cjs");
3
+ const require_text_truncate = require("./text-truncate-I1XLWmRa.cjs");
4
+ const require_key_pad_menu = require("./key-pad-menu-SItoHPLu.cjs");
5
+ const require_field_sidebar = require("./field-sidebar-oa6zOmcd.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");
9
10
  let lucide_react = require("lucide-react");
10
11
  let _reopt_ai_opt_palette = require("@reopt-ai/opt-palette");
11
12
  let _reopt_ai_opt_charts = require("@reopt-ai/opt-charts");
12
13
  let match_sorter = require("match-sorter");
13
14
  let next_navigation = require("next/navigation");
14
- let _reopt_ai_opt_ui_primitives = require("@reopt-ai/opt-ui-primitives");
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({ className: require_text_truncate.cn("flex items-start rounded-lg border", toneStyles[tone], sizeStyles$3[size], className) }, props), {}, {
83
+ "data-opt-id": "AT7TX",
84
+ "data-opt-slug": "callout.Callout",
85
+ "data-tone": tone,
86
+ children: [
87
+ glyph && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
88
+ className: require_text_truncate.cn("mt-0.5 shrink-0", iconTone[tone]),
89
+ children: glyph
90
+ }),
91
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
92
+ className: "min-w-0 flex-1",
93
+ children: [title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
94
+ className: require_text_truncate.cn("font-medium", titleTone[tone]),
95
+ children: title
96
+ }), children && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
97
+ className: require_text_truncate.cn("text-text-secondary", title && "mt-1"),
98
+ children
99
+ })]
100
+ }),
101
+ action && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
102
+ className: "shrink-0 self-center",
103
+ children: action
104
+ })
105
+ ]
106
+ }));
107
+ }
108
+ //#endregion
109
+ //#region src/core/status-dot.tsx
110
+ const _excluded$1 = [
111
+ "tone",
112
+ "size",
113
+ "hint",
114
+ "className",
115
+ "children"
116
+ ];
117
+ const dotTone = {
118
+ neutral: "bg-text-tertiary",
119
+ muted: "bg-border-hover",
120
+ info: "bg-info",
121
+ success: "bg-success",
122
+ warning: "bg-warning",
123
+ danger: "bg-danger"
124
+ };
125
+ const textTone = {
126
+ neutral: "text-text-secondary",
127
+ muted: "text-text-tertiary",
128
+ info: "text-text-secondary",
129
+ success: "text-text-secondary",
130
+ warning: "text-text-secondary",
131
+ danger: "text-text-secondary"
132
+ };
133
+ const sizeStyles$2 = {
134
+ sm: "gap-1.5 text-[11px]",
135
+ md: "gap-2 text-xs"
136
+ };
137
+ const dotSize = {
138
+ sm: "size-1.5",
139
+ md: "size-2"
140
+ };
141
+ /**
142
+ * StatusDot — a state, said in a dot and a word.
143
+ *
144
+ * `Badge` is a chip: a filled pill that reads as a label somebody attached.
145
+ * A status is not attached, it is observed, and a column of seven filled pills
146
+ * is a column nobody scans. This is the other shape — a dot, the word, no
147
+ * chrome — which is what a dense table can afford to repeat on every row.
148
+ *
149
+ * The dot is decorative on purpose. It never carries meaning the text does not
150
+ * also carry, so the component cannot be used to say something in colour alone.
151
+ *
152
+ * @example
153
+ * ```tsx
154
+ * <StatusDot tone="warning" hint="7일 이상 수신되지 않음">비활성</StatusDot>
155
+ * ```
156
+ */
157
+ function StatusDot(_ref) {
158
+ let { tone = "neutral", size = "md", hint, className, children } = _ref, props = require_text_truncate._objectWithoutProperties(_ref, _excluded$1);
159
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({
160
+ className: require_text_truncate.cn("inline-flex items-center whitespace-nowrap", sizeStyles$2[size], textTone[tone], className),
161
+ title: hint
162
+ }, props), {}, {
163
+ "data-opt-id": "N51AT",
164
+ "data-opt-slug": "status-dot.StatusDot",
165
+ "data-tone": tone,
166
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
167
+ className: require_text_truncate.cn("shrink-0 rounded-full", dotSize[size], dotTone[tone]),
168
+ "aria-hidden": "true"
169
+ }), children]
170
+ }));
171
+ }
172
+ //#endregion
173
+ //#region src/core/copy-button.tsx
174
+ const _excluded = [
175
+ "value",
176
+ "variant",
177
+ "size",
178
+ "feedbackDuration",
179
+ "onCopy",
180
+ "labels",
181
+ "className",
182
+ "disabled",
183
+ "onClick"
184
+ ];
185
+ const defaultLabels$35 = {
186
+ copy: "복사",
187
+ copied: "복사됨",
188
+ failed: "복사할 수 없습니다"
189
+ };
190
+ const sizeStyles$1 = {
191
+ sm: "h-6 gap-1 text-[11px] [&>svg]:size-3",
192
+ md: "h-7 gap-1.5 text-xs [&>svg]:size-3.5"
193
+ };
194
+ const paddingStyles = {
195
+ icon: {
196
+ sm: "w-6 justify-center",
197
+ md: "w-7 justify-center"
198
+ },
199
+ text: {
200
+ sm: "px-1.5",
201
+ md: "px-2"
202
+ }
203
+ };
204
+ const stateIcon = {
205
+ idle: lucide_react.Copy,
206
+ copied: lucide_react.Check,
207
+ failed: lucide_react.X
208
+ };
209
+ const stateTone = {
210
+ idle: "text-text-tertiary hover:text-text-primary",
211
+ copied: "text-success-fg",
212
+ failed: "text-danger-fg"
213
+ };
214
+ /**
215
+ * CopyButton — put a value on the clipboard, and say whether it went.
216
+ *
217
+ * Copying an identifier is the most common thing a reader does with one: an
218
+ * event key, a property name, a request id. Every surface that shows one was
219
+ * writing this button again, and each copy re-decided what happens when the
220
+ * clipboard refuses — mostly by pretending it did not.
221
+ *
222
+ * The confirmed state is announced, not just drawn, so the answer reaches a
223
+ * reader who is not looking at the glyph.
224
+ *
225
+ * @example
226
+ * ```tsx
227
+ * <CopyButton value={event.name} labels={{ copy: "이벤트 키 복사" }} />
228
+ * ```
229
+ */
230
+ function CopyButton(_ref) {
231
+ let { value, variant = "icon", size = "md", feedbackDuration = 1500, onCopy, labels: customLabels, className, disabled, onClick } = _ref, props = require_text_truncate._objectWithoutProperties(_ref, _excluded);
232
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$35), customLabels);
233
+ const [state, setState] = (0, react.useState)("idle");
234
+ const timer = (0, react.useRef)(null);
235
+ (0, react.useEffect)(() => () => {
236
+ if (timer.current) clearTimeout(timer.current);
237
+ }, []);
238
+ const handleClick = (0, react.useCallback)(async (event) => {
239
+ onClick === null || onClick === void 0 || onClick(event);
240
+ if (event.defaultPrevented) return;
241
+ let ok = false;
242
+ try {
243
+ await navigator.clipboard.writeText(value);
244
+ ok = true;
245
+ } catch (_unused) {
246
+ ok = false;
247
+ }
248
+ setState(ok ? "copied" : "failed");
249
+ onCopy === null || onCopy === void 0 || onCopy(ok);
250
+ if (timer.current) clearTimeout(timer.current);
251
+ timer.current = setTimeout(() => setState("idle"), feedbackDuration);
252
+ }, [
253
+ feedbackDuration,
254
+ onClick,
255
+ onCopy,
256
+ value
257
+ ]);
258
+ const Icon = stateIcon[state];
259
+ const label = state === "copied" ? labels.copied : state === "failed" ? labels.failed : labels.copy;
260
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({
261
+ type: "button",
262
+ onClick: handleClick,
263
+ disabled,
264
+ "aria-label": variant === "icon" ? label : void 0,
265
+ 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)
266
+ }, props), {}, {
267
+ "data-opt-id": "E0C8T",
268
+ "data-opt-slug": "copy-button.CopyButton",
269
+ "data-copy-state": state,
270
+ children: [
271
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { "aria-hidden": "true" }),
272
+ variant === "text" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label }),
273
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
274
+ role: "status",
275
+ "aria-live": "polite",
276
+ className: "sr-only",
277
+ children: state === "idle" ? "" : label
278
+ })
279
+ ]
280
+ }));
281
+ }
282
+ //#endregion
283
+ //#region src/core/segmented-control.tsx
284
+ const sizeStyles = {
285
+ sm: "h-7 text-[11px] [&_svg]:size-3",
286
+ md: "h-8 text-xs [&_svg]:size-3.5"
287
+ };
288
+ const segmentPadding = {
289
+ sm: "gap-1 px-2",
290
+ md: "gap-1.5 px-2.5"
291
+ };
292
+ /**
293
+ * SegmentedControl — one of a few views, all of them visible.
294
+ *
295
+ * A `Select` hides the alternatives behind a click; a `ToggleGroup` presses
296
+ * buttons that may be on together. Neither is what "이벤트 | 속성" is: exactly
297
+ * one is true, the set is small enough to show, and the reader is choosing a
298
+ * view rather than filtering anything.
299
+ *
300
+ * Built on the radio-group primitive rather than on buttons, so the arrow keys,
301
+ * the group name and the checked state come from the platform. A control that
302
+ * merely looks like a radiogroup is one a keyboard cannot drive.
303
+ *
304
+ * @example
305
+ * ```tsx
306
+ * <SegmentedControl
307
+ * aria-label="카탈로그 탭"
308
+ * options={[
309
+ * { value: "events", label: "이벤트", badge: 128 },
310
+ * { value: "properties", label: "속성", badge: 341 },
311
+ * ]}
312
+ * value={tab}
313
+ * onChange={setTab}
314
+ * />
315
+ * ```
316
+ */
317
+ function SegmentedControl({ options, value, onChange, size = "md", fullWidth = false, disabled = false, "aria-label": ariaLabel, className }) {
318
+ const name = (0, react.useId)();
319
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.RadioGroupRoot, {
320
+ value,
321
+ onValueChange: (next) => onChange(next),
322
+ disabled,
323
+ orientation: "horizontal",
324
+ name,
325
+ "aria-label": ariaLabel,
326
+ 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),
327
+ "data-opt-id": "YKENE",
328
+ "data-opt-slug": "segmented-control.SegmentedControl",
329
+ children: options.map((option) => {
330
+ const selected = option.value === value;
331
+ const itemDisabled = disabled || option.disabled;
332
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
333
+ 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"),
334
+ "data-selected": selected || void 0,
335
+ children: [
336
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.Radio, {
337
+ value: option.value,
338
+ disabled: itemDisabled,
339
+ className: "sr-only"
340
+ }),
341
+ option.icon,
342
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: option.label }),
343
+ option.badge != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
344
+ className: require_text_truncate.cn("tabular-nums", selected ? "text-text-tertiary" : "text-text-tertiary/70"),
345
+ children: option.badge
346
+ })
347
+ ]
348
+ }, option.value);
349
+ })
350
+ });
351
+ }
352
+ //#endregion
15
353
  //#region src/lib/schema-validator.ts
16
354
  /** Handles schema validator. */
17
355
  function schemaValidator(schema) {
@@ -86,7 +424,7 @@ function PageAside({ header, children, footer, widthClassName = "w-60", label, h
86
424
  PageAside.displayName = "PageAside";
87
425
  //#endregion
88
426
  //#region src/shells/task-list.tsx
89
- const defaultLabels$31 = {
427
+ const defaultLabels$34 = {
90
428
  title: "작업 목록",
91
429
  emptyMessage: "작업이 없습니다",
92
430
  completedOf: "{completed}/{total} 완료",
@@ -106,9 +444,9 @@ const defaultLabels$31 = {
106
444
  };
107
445
  /** Renders the task list component. */
108
446
  function TaskList({ tasks, title, onTaskClick, onTaskStatusChange, emptyMessage, showSubtasks = false, maxItems, labels: customLabels, className }) {
109
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$31), customLabels), {}, {
110
- priority: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$31.priority), customLabels === null || customLabels === void 0 ? void 0 : customLabels.priority),
111
- status: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$31.status), customLabels === null || customLabels === void 0 ? void 0 : customLabels.status)
447
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$34), customLabels), {}, {
448
+ priority: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$34.priority), customLabels === null || customLabels === void 0 ? void 0 : customLabels.priority),
449
+ status: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$34.status), customLabels === null || customLabels === void 0 ? void 0 : customLabels.status)
112
450
  });
113
451
  const displayTitle = title !== null && title !== void 0 ? title : labels.title;
114
452
  const displayEmptyMessage = emptyMessage !== null && emptyMessage !== void 0 ? emptyMessage : labels.emptyMessage;
@@ -266,7 +604,7 @@ function TaskList({ tasks, title, onTaskClick, onTaskStatusChange, emptyMessage,
266
604
  }
267
605
  //#endregion
268
606
  //#region src/shells/activity-feed.tsx
269
- const defaultLabels$30 = {
607
+ const defaultLabels$33 = {
270
608
  title: "활동 피드",
271
609
  emptyMessage: "활동이 없습니다",
272
610
  moreItems: "{count}개 더 보기",
@@ -316,24 +654,24 @@ const variantBorder = {
316
654
  function ActivityFeed({ activities, title, maxItems, onActivityClick, onShowMore, emptyMessage, labels: customLabels, locale = "ko-KR", loading = false, layout = "list", renderActions, className }) {
317
655
  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;
318
656
  const mergedTimeAgo = {
319
- 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$30.timeAgo.justNow,
320
- 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$30.timeAgo.minutesAgo,
321
- 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$30.timeAgo.hoursAgo,
322
- 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$30.timeAgo.daysAgo
657
+ 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,
658
+ 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,
659
+ 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,
660
+ 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
323
661
  };
324
662
  const mergedActivityVerbs = {
325
- 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$30.activityVerbs.created,
326
- 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$30.activityVerbs.updated,
327
- 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$30.activityVerbs.completed,
328
- 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$30.activityVerbs.commented,
329
- 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$30.activityVerbs.assigned,
330
- 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$30.activityVerbs.deployed,
331
- 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$30.activityVerbs.merged
663
+ 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,
664
+ 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,
665
+ 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,
666
+ 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,
667
+ 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,
668
+ 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,
669
+ 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
332
670
  };
333
671
  const labels = {
334
- title: (_customLabels$title = customLabels === null || customLabels === void 0 ? void 0 : customLabels.title) !== null && _customLabels$title !== void 0 ? _customLabels$title : defaultLabels$30.title,
335
- emptyMessage: (_customLabels$emptyMe = customLabels === null || customLabels === void 0 ? void 0 : customLabels.emptyMessage) !== null && _customLabels$emptyMe !== void 0 ? _customLabels$emptyMe : defaultLabels$30.emptyMessage,
336
- moreItems: (_customLabels$moreIte = customLabels === null || customLabels === void 0 ? void 0 : customLabels.moreItems) !== null && _customLabels$moreIte !== void 0 ? _customLabels$moreIte : defaultLabels$30.moreItems,
672
+ title: (_customLabels$title = customLabels === null || customLabels === void 0 ? void 0 : customLabels.title) !== null && _customLabels$title !== void 0 ? _customLabels$title : defaultLabels$33.title,
673
+ emptyMessage: (_customLabels$emptyMe = customLabels === null || customLabels === void 0 ? void 0 : customLabels.emptyMessage) !== null && _customLabels$emptyMe !== void 0 ? _customLabels$emptyMe : defaultLabels$33.emptyMessage,
674
+ moreItems: (_customLabels$moreIte = customLabels === null || customLabels === void 0 ? void 0 : customLabels.moreItems) !== null && _customLabels$moreIte !== void 0 ? _customLabels$moreIte : defaultLabels$33.moreItems,
337
675
  timeAgo: mergedTimeAgo,
338
676
  activityVerbs: mergedActivityVerbs
339
677
  };
@@ -461,13 +799,13 @@ function ActivityFeed({ activities, title, maxItems, onActivityClick, onShowMore
461
799
  ActivityFeed.displayName = "ActivityFeed";
462
800
  //#endregion
463
801
  //#region src/shells/filter-bar.tsx
464
- const defaultLabels$29 = {
802
+ const defaultLabels$32 = {
465
803
  clearAll: "필터 초기화",
466
804
  searchPlaceholder: "검색..."
467
805
  };
468
806
  /** Renders the filter bar component. */
469
807
  function FilterBar({ filters, onFilterChange, onDateRangeChange, onClearAll, labels: customLabels, presetActions, className }) {
470
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$29), customLabels);
808
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$32), customLabels);
471
809
  const [searchValues, setSearchValues] = (0, react.useState)({});
472
810
  const [tagInputValues, setTagInputValues] = (0, react.useState)({});
473
811
  const [multiSelectOpen, setMultiSelectOpen] = (0, react.useState)({});
@@ -693,10 +1031,10 @@ function matchesShortcut(event, shortcut) {
693
1031
  if (requiresMeta && !event.metaKey) return false;
694
1032
  return event.key.toLowerCase() === key;
695
1033
  }
696
- const defaultLabels$28 = { title: "빠른 작업" };
1034
+ const defaultLabels$31 = { title: "빠른 작업" };
697
1035
  /** Renders the quick actions component. */
698
1036
  function QuickActions({ actions, title, layout = "grid", columns = 3, showDescriptionInGrid = false, bindShortcuts = false, labels: customLabels, className }) {
699
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$28), customLabels);
1037
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$31), customLabels);
700
1038
  const displayTitle = title !== null && title !== void 0 ? title : labels.title;
701
1039
  const titleId = (0, react.useId)();
702
1040
  (0, react.useEffect)(() => {
@@ -774,7 +1112,7 @@ function QuickActions({ actions, title, layout = "grid", columns = 3, showDescri
774
1112
  QuickActions.displayName = "QuickActions";
775
1113
  //#endregion
776
1114
  //#region src/shells/team-member-list.tsx
777
- const defaultLabels$27 = {
1115
+ const defaultLabels$30 = {
778
1116
  title: "팀원",
779
1117
  emptyMessage: "팀원이 없습니다",
780
1118
  onlineCount: "{online}/{total} 온라인",
@@ -795,7 +1133,7 @@ const statusDot = {
795
1133
  };
796
1134
  /** Renders the team member list component. */
797
1135
  function TeamMemberList({ members, title, layout = "list", maxDisplay, onMemberClick, onShowMore, emptyMessage, labels: customLabels, className }) {
798
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$27), customLabels), {}, { status: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$27.status), customLabels === null || customLabels === void 0 ? void 0 : customLabels.status) });
1136
+ 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) });
799
1137
  const displayTitle = title !== null && title !== void 0 ? title : labels.title;
800
1138
  const displayEmptyMessage = emptyMessage !== null && emptyMessage !== void 0 ? emptyMessage : labels.emptyMessage;
801
1139
  const titleId = (0, react.useId)();
@@ -1695,7 +2033,7 @@ const COLOR_PRESETS = [
1695
2033
  "#f97316",
1696
2034
  "#14b8a6"
1697
2035
  ];
1698
- const defaultLabels$26 = {
2036
+ const defaultLabels$29 = {
1699
2037
  eventLabelPrefix: "Event",
1700
2038
  defaultAriaLabel: "Event icon"
1701
2039
  };
@@ -1726,7 +2064,7 @@ function getEventIconStyle(color) {
1726
2064
  /** Renders the event icon component. */
1727
2065
  function EventIcon({ icon, color, size = "md", className, labels: customLabels }) {
1728
2066
  var _iconEntry$label;
1729
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$26), customLabels);
2067
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$29), customLabels);
1730
2068
  const sizes = SIZE_MAP[size];
1731
2069
  const resolvedColor = (color === null || color === void 0 ? void 0 : color.trim()) ? color : void 0;
1732
2070
  const iconEntry = typeof icon === "string" ? require_text_truncate.getIconRegistryEntry(icon) : void 0;
@@ -1818,14 +2156,14 @@ function ConnectionIndicator({ status, tone, label, showLabel = true, pulse, cla
1818
2156
  ConnectionIndicator.displayName = "ConnectionIndicator";
1819
2157
  //#endregion
1820
2158
  //#region src/shells/floating-action-bar.tsx
1821
- const defaultLabels$25 = {
2159
+ const defaultLabels$28 = {
1822
2160
  toolbarAriaLabel: "Actions",
1823
2161
  selectedLabel: (count) => `${count} selected`,
1824
2162
  dismissAriaLabel: "Dismiss"
1825
2163
  };
1826
2164
  /** Renders the floating action bar component. */
1827
2165
  function FloatingActionBar({ actions, selectedCount, onAction, onDismiss, className, labels: customLabels }) {
1828
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$25), customLabels);
2166
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$28), customLabels);
1829
2167
  if (actions.length === 0) return null;
1830
2168
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1831
2169
  role: "toolbar",
@@ -1862,7 +2200,7 @@ function FloatingActionBar({ actions, selectedCount, onAction, onDismiss, classN
1862
2200
  FloatingActionBar.displayName = "FloatingActionBar";
1863
2201
  //#endregion
1864
2202
  //#region src/shells/template-picker.tsx
1865
- const defaultLabels$24 = {
2203
+ const defaultLabels$27 = {
1866
2204
  ariaLabel: "Templates",
1867
2205
  defaultCategory: "General",
1868
2206
  searchPlaceholder: "Search templates...",
@@ -1870,7 +2208,7 @@ const defaultLabels$24 = {
1870
2208
  };
1871
2209
  /** Renders the template picker component. */
1872
2210
  function TemplatePicker({ templates, selected, onSelect, labels: customLabels, showSearch = false, className }) {
1873
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$24), customLabels);
2211
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$27), customLabels);
1874
2212
  const [search, setSearch] = react.useState("");
1875
2213
  const filtered = react.useMemo(() => {
1876
2214
  if (!showSearch || !search) return templates;
@@ -1956,7 +2294,7 @@ function TemplatePicker({ templates, selected, onSelect, labels: customLabels, s
1956
2294
  TemplatePicker.displayName = "TemplatePicker";
1957
2295
  //#endregion
1958
2296
  //#region src/shells/code-snippet-viewer.tsx
1959
- const defaultLabels$23 = {
2297
+ const defaultLabels$26 = {
1960
2298
  copy: "Copy",
1961
2299
  copied: "Copied!",
1962
2300
  codeRegion: "Code snippet"
@@ -1994,7 +2332,7 @@ const syntaxThemeClasses = {
1994
2332
  /** Renders the code snippet viewer component. */
1995
2333
  function CodeSnippetViewer({ code, language = "text", title, showLineNumbers = true, showCopyButton = true, maxHeight = 400, syntaxTheme = "default", className, labels: customLabels }) {
1996
2334
  var _syntaxThemeClasses$s;
1997
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$23), customLabels);
2335
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$26), customLabels);
1998
2336
  const [copied, setCopied] = react.useState(false);
1999
2337
  const lines = code.split("\n");
2000
2338
  const theme = (_syntaxThemeClasses$s = syntaxThemeClasses[syntaxTheme]) !== null && _syntaxThemeClasses$s !== void 0 ? _syntaxThemeClasses$s : syntaxThemeClasses.default;
@@ -2046,13 +2384,15 @@ function CodeSnippetViewer({ code, language = "text", title, showLineNumbers = t
2046
2384
  CodeSnippetViewer.displayName = "CodeSnippetViewer";
2047
2385
  //#endregion
2048
2386
  //#region src/shells/property-explorer.tsx
2049
- const defaultLabels$22 = {
2387
+ const defaultLabels$25 = {
2050
2388
  searchPlaceholder: "Search properties...",
2051
- noPropertiesFound: "No properties found"
2389
+ noPropertiesFound: "No properties found",
2390
+ edit: (property) => `${property} 편집`,
2391
+ hidden: "숨김"
2052
2392
  };
2053
2393
  /** Renders the property explorer component. */
2054
- function PropertyExplorer({ groups, onSelect, className, labels: customLabels }) {
2055
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$22), customLabels);
2394
+ function PropertyExplorer({ groups, onSelect, onEdit, className, labels: customLabels }) {
2395
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$25), customLabels);
2056
2396
  const [search, setSearch] = react.useState("");
2057
2397
  const filtered = react.useMemo(() => {
2058
2398
  if (!search) return groups;
@@ -2078,36 +2418,55 @@ function PropertyExplorer({ groups, onSelect, className, labels: customLabels })
2078
2418
  children: group.name
2079
2419
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2080
2420
  className: "gap-element flex flex-col",
2081
- children: group.properties.map((prop) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
2082
- onClick: () => onSelect === null || onSelect === void 0 ? void 0 : onSelect(prop),
2083
- className: require_text_truncate.cn("flex w-full items-center justify-between rounded-md px-2.5 py-1.5 text-left", "hover:bg-bg-subtle transition-colors"),
2084
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2085
- className: "min-w-0",
2086
- children: [
2087
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.FieldToken, {
2088
- type: require_text_truncate.resolveFieldType(prop.type),
2089
- size: "xs",
2090
- title: prop.type,
2091
- className: "mr-2 align-[-2px]"
2092
- }),
2093
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2094
- className: "text-text-primary text-sm font-medium",
2095
- children: prop.name
2096
- }),
2097
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2098
- className: "text-text-tertiary ml-2 font-mono text-xs",
2099
- children: prop.type
2100
- }),
2101
- prop.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2102
- className: "text-text-tertiary truncate text-xs",
2103
- children: prop.description
2421
+ children: group.properties.map((prop) => {
2422
+ var _prop$dataType;
2423
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2424
+ className: require_text_truncate.cn("hover:bg-bg-subtle flex items-center rounded-md transition-colors", prop.hidden && "opacity-60"),
2425
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
2426
+ onClick: () => onSelect === null || onSelect === void 0 ? void 0 : onSelect(prop),
2427
+ className: "flex min-w-0 flex-1 items-center justify-between px-2.5 py-1.5 text-left",
2428
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2429
+ className: "min-w-0",
2430
+ children: [
2431
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.FieldToken, {
2432
+ type: (_prop$dataType = prop.dataType) !== null && _prop$dataType !== void 0 ? _prop$dataType : require_text_truncate.resolveFieldType(prop.type),
2433
+ size: "xs",
2434
+ title: prop.type,
2435
+ className: "mr-2 align-[-2px]"
2436
+ }),
2437
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2438
+ className: "text-text-primary text-sm font-medium",
2439
+ children: prop.name
2440
+ }),
2441
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2442
+ className: "text-text-tertiary ml-2 font-mono text-xs",
2443
+ children: prop.type
2444
+ }),
2445
+ prop.hidden && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2446
+ className: "text-text-tertiary ml-2 text-xs",
2447
+ children: labels.hidden
2448
+ }),
2449
+ prop.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2450
+ className: "text-text-tertiary truncate text-xs",
2451
+ children: prop.description
2452
+ })
2453
+ ]
2454
+ }), prop.eventCount !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2455
+ className: "text-text-tertiary ml-2 shrink-0 text-xs",
2456
+ children: require_text_truncate.formatOptNumber(prop.eventCount)
2457
+ })]
2458
+ }), onEdit && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2459
+ type: "button",
2460
+ onClick: () => onEdit(prop),
2461
+ "aria-label": labels.edit(prop.name),
2462
+ className: "text-text-tertiary hover:text-text-primary mr-1.5 shrink-0 rounded p-1",
2463
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Pencil, {
2464
+ "aria-hidden": "true",
2465
+ className: "size-3.5"
2104
2466
  })
2105
- ]
2106
- }), prop.eventCount !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2107
- className: "text-text-tertiary ml-2 shrink-0 text-xs",
2108
- children: require_text_truncate.formatOptNumber(prop.eventCount)
2109
- })]
2110
- }, prop.name))
2467
+ })]
2468
+ }, prop.name);
2469
+ })
2111
2470
  })] }, group.name)), filtered.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2112
2471
  className: "text-text-tertiary py-4 text-center text-sm",
2113
2472
  children: labels.noPropertiesFound
@@ -2118,14 +2477,14 @@ function PropertyExplorer({ groups, onSelect, className, labels: customLabels })
2118
2477
  PropertyExplorer.displayName = "PropertyExplorer";
2119
2478
  //#endregion
2120
2479
  //#region src/shells/query-results-table.tsx
2121
- const defaultLabels$21 = {
2480
+ const defaultLabels$24 = {
2122
2481
  emptyMessage: "No results",
2123
2482
  loadingMessage: "Running query...",
2124
2483
  rowsSuffix: "row(s)"
2125
2484
  };
2126
2485
  /** Renders the query results table component. */
2127
2486
  function QueryResultsTable({ columns, rows, maxHeight = 400, emptyMessage, loading = false, error, labels: customLabels, className }) {
2128
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$21), customLabels);
2487
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$24), customLabels);
2129
2488
  if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2130
2489
  className: require_text_truncate.cn("border-danger bg-danger-subtle rounded-lg border p-4", className),
2131
2490
  role: "alert",
@@ -2209,7 +2568,7 @@ function QueryResultsTable({ columns, rows, maxHeight = 400, emptyMessage, loadi
2209
2568
  QueryResultsTable.displayName = "QueryResultsTable";
2210
2569
  //#endregion
2211
2570
  //#region src/shells/alert-builder.tsx
2212
- const defaultLabels$20 = {
2571
+ const defaultLabels$23 = {
2213
2572
  alertNameLabel: "Alert name",
2214
2573
  conditionsLabel: "Conditions",
2215
2574
  metricLabel: "Metric",
@@ -2280,7 +2639,7 @@ function AlertBuilder({ value, onChange, metrics = [
2280
2639
  ], labels: customLabels, className }) {
2281
2640
  const resolvedMetrics = eventOptions ? eventOptions.map((e) => e.id) : metrics;
2282
2641
  const metricLabelMap = eventOptions ? Object.fromEntries(eventOptions.map((e) => [e.id, e.name])) : null;
2283
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$20), customLabels);
2642
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$23), customLabels);
2284
2643
  const alertNameId = react.useId();
2285
2644
  const conditionsId = react.useId();
2286
2645
  const checkFrequencyId = react.useId();
@@ -2435,7 +2794,7 @@ function AlertBuilder({ value, onChange, metrics = [
2435
2794
  AlertBuilder.displayName = "AlertBuilder";
2436
2795
  //#endregion
2437
2796
  //#region src/shells/sql-editor.tsx
2438
- const defaultLabels$19 = {
2797
+ const defaultLabels$22 = {
2439
2798
  placeholder: "SELECT * FROM events LIMIT 100",
2440
2799
  runHint: "Ctrl+Enter to run",
2441
2800
  runButton: "Run Query",
@@ -2443,7 +2802,7 @@ const defaultLabels$19 = {
2443
2802
  };
2444
2803
  /** Renders the sql editor component. */
2445
2804
  function SqlEditor({ value, onChange, onRun, onRunAndAdvance, placeholder, readOnly = false, height = 200, schema, completionSources, keymap: customKeymap, extensions: customExtensions, ariaLabel, autoFocus = false, showFooter, labels: customLabels, className }) {
2446
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$19), customLabels);
2805
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$22), customLabels);
2447
2806
  const fill = height === "fill";
2448
2807
  const footerVisible = showFooter !== null && showFooter !== void 0 ? showFooter : Boolean(onRun);
2449
2808
  const editorRef = react.useRef(null);
@@ -2615,7 +2974,7 @@ function SqlEditor({ value, onChange, onRun, onRunAndAdvance, placeholder, readO
2615
2974
  SqlEditor.displayName = "SqlEditor";
2616
2975
  //#endregion
2617
2976
  //#region src/shells/event-meta-editor.tsx
2618
- const defaultLabels$18 = {
2977
+ const defaultLabels$21 = {
2619
2978
  icon: "Icon",
2620
2979
  color: "Color",
2621
2980
  name: "Event name",
@@ -2629,8 +2988,8 @@ const defaultLabels$18 = {
2629
2988
  emptyTagsMessage: "No tags added yet."
2630
2989
  };
2631
2990
  /** Renders the event meta editor component. */
2632
- function EventMetaEditor({ value, onChange, icons, className, labels: customLabels }) {
2633
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$18), customLabels);
2991
+ function EventMetaEditor({ value, onChange, icons, sections, footer, className, labels: customLabels }) {
2992
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$21), customLabels);
2634
2993
  const hasTags = value.tags.length > 0;
2635
2994
  const nameId = react.useId();
2636
2995
  const displayNameId = react.useId();
@@ -2723,17 +3082,32 @@ function EventMetaEditor({ value, onChange, icons, className, labels: customLabe
2723
3082
  className: "text-text-tertiary mt-1 block text-xs",
2724
3083
  children: labels.emptyTagsMessage
2725
3084
  })
2726
- ] })
3085
+ ] }),
3086
+ sections === null || sections === void 0 ? void 0 : sections.map((section) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3087
+ className: "gap-element flex flex-col",
3088
+ children: [
3089
+ section.title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3090
+ className: "text-text-tertiary block text-xs font-medium",
3091
+ children: section.title
3092
+ }),
3093
+ section.children,
3094
+ section.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3095
+ className: "text-text-tertiary block text-xs",
3096
+ children: section.description
3097
+ })
3098
+ ]
3099
+ }, section.id)),
3100
+ footer
2727
3101
  ]
2728
3102
  });
2729
3103
  }
2730
3104
  EventMetaEditor.displayName = "EventMetaEditor";
2731
3105
  //#endregion
2732
3106
  //#region src/shells/widget-grid.tsx
2733
- const defaultLabels$17 = { emptyMessage: "No widgets to display" };
3107
+ const defaultLabels$20 = { emptyMessage: "No widgets to display" };
2734
3108
  /** Renders the widget grid component. */
2735
3109
  function WidgetGrid({ widgets, cols = 12, rowHeight = 80, gap = 16, editable = false, onReorder, labels: customLabels, className }) {
2736
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$17), customLabels);
3110
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$20), customLabels);
2737
3111
  const [dragIdx, setDragIdx] = react.useState(null);
2738
3112
  const [overIdx, setOverIdx] = react.useState(null);
2739
3113
  if (widgets.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -2778,7 +3152,7 @@ function WidgetGrid({ widgets, cols = 12, rowHeight = 80, gap = 16, editable = f
2778
3152
  WidgetGrid.displayName = "WidgetGrid";
2779
3153
  //#endregion
2780
3154
  //#region src/shells/report-builder.tsx
2781
- const defaultLabels$16 = {
3155
+ const defaultLabels$19 = {
2782
3156
  stepsLabel: "Report steps",
2783
3157
  stepType: "Chart Type",
2784
3158
  stepConfig: "Data Config",
@@ -2854,7 +3228,7 @@ const STEPS = [
2854
3228
  ];
2855
3229
  /** Renders the report builder component. */
2856
3230
  function ReportBuilder({ chartTypes = DEFAULT_CHART_TYPES, dataSources = [], onSave, onCancel, configForm, styleForm, preview, onChartTypeChange, onDataSourceChange, onStepChange, selectedChartType: controlledChartType, selectedDataSource: controlledDataSource, labels: customLabels, className }) {
2857
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$16), customLabels);
3231
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$19), customLabels);
2858
3232
  const [stepIndex, setStepIndex] = react.useState(0);
2859
3233
  const [internalChartType, setInternalChartType] = react.useState(null);
2860
3234
  const [internalDataSource, setInternalDataSource] = react.useState("");
@@ -3074,7 +3448,7 @@ function ReportBuilder({ chartTypes = DEFAULT_CHART_TYPES, dataSources = [], onS
3074
3448
  ReportBuilder.displayName = "ReportBuilder";
3075
3449
  //#endregion
3076
3450
  //#region src/shells/audit-timeline.tsx
3077
- const defaultLabels$15 = {
3451
+ const defaultLabels$18 = {
3078
3452
  title: "변경 이력",
3079
3453
  empty: "변경 이력이 없습니다",
3080
3454
  expand: "상세 보기",
@@ -3153,7 +3527,7 @@ function DiffTable({ changes, labels }) {
3153
3527
  }
3154
3528
  /** Renders the audit timeline component. */
3155
3529
  function AuditTimeline({ entries, labels: customLabels, className, onEntryClick }) {
3156
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$15), customLabels);
3530
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$18), customLabels);
3157
3531
  const [expandedIds, setExpandedIds] = react.useState(/* @__PURE__ */ new Set());
3158
3532
  const toggleExpanded = react.useCallback((id) => {
3159
3533
  setExpandedIds((prev) => {
@@ -3276,7 +3650,7 @@ function AuditTimeline({ entries, labels: customLabels, className, onEntryClick
3276
3650
  AuditTimeline.displayName = "AuditTimeline";
3277
3651
  //#endregion
3278
3652
  //#region src/shells/segment-builder.tsx
3279
- const defaultLabels$14 = {
3653
+ const defaultLabels$17 = {
3280
3654
  match: "Match",
3281
3655
  ofTheFollowing: "of the following",
3282
3656
  groupLabel: "Segment group",
@@ -3397,7 +3771,7 @@ function SegmentBuilder({ groups, onChange, eventOptions = [
3397
3771
  "New Users",
3398
3772
  "Power Users"
3399
3773
  ], className, labels: customLabels }) {
3400
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$14), customLabels);
3774
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$17), customLabels);
3401
3775
  const builderId = react.useId().replace(/:/g, "");
3402
3776
  const nextIdRef = react.useRef(1);
3403
3777
  const createId = react.useCallback(() => {
@@ -3610,7 +3984,7 @@ function SegmentBuilder({ groups, onChange, eventOptions = [
3610
3984
  SegmentBuilder.displayName = "SegmentBuilder";
3611
3985
  //#endregion
3612
3986
  //#region src/shells/insights-panel.tsx
3613
- const defaultLabels$13 = {
3987
+ const defaultLabels$16 = {
3614
3988
  title: "Insights",
3615
3989
  dismiss: "Dismiss",
3616
3990
  showDismissed: "Show dismissed",
@@ -3641,7 +4015,7 @@ const severityConfig = {
3641
4015
  /** Renders the insights panel component. */
3642
4016
  function InsightsPanel({ insights, stats, detectionTypes, onDetectionTypeToggle, detectionConfig, onDetectionConfigChange, onDismiss, onInsightClick, onStatClick, header, actions, labels: customLabels, className }) {
3643
4017
  var _detectionConfig$days, _detectionConfig$zSco;
3644
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$13), customLabels);
4018
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$16), customLabels);
3645
4019
  const [showDismissed, setShowDismissed] = react.useState(false);
3646
4020
  const visibleInsights = showDismissed ? insights : insights.filter((i) => !i.dismissed);
3647
4021
  const hasStats = stats && stats.length > 0;
@@ -4033,7 +4407,7 @@ function ExportButton({ data, columns, fileName = "export", formats = ["csv", "j
4033
4407
  ExportButton.displayName = "ExportButton";
4034
4408
  //#endregion
4035
4409
  //#region src/shells/summary-row.tsx
4036
- const defaultLabels$12 = {
4410
+ const defaultLabels$15 = {
4037
4411
  emptyTitle: "No summary stats",
4038
4412
  emptyDescription: "Provide at least one stat to render the summary row."
4039
4413
  };
@@ -4057,7 +4431,7 @@ const colsClass = {
4057
4431
  };
4058
4432
  /** Renders the summary row component. */
4059
4433
  function SummaryRow({ stats, columns = 4, onStatClick, selectedStatId, size = "md", formatValue, durationFractionDigits = 1, percentageFractionDigits = 1, loading = false, labels: customLabels, className }) {
4060
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$12), customLabels);
4434
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$15), customLabels);
4061
4435
  if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4062
4436
  className: require_text_truncate.cn("gap-group grid", colsClass[columns], className),
4063
4437
  "data-opt-id": "FGFP3",
@@ -4097,6 +4471,505 @@ function SummaryRow({ stats, columns = 4, onStatClick, selectedStatId, size = "m
4097
4471
  }
4098
4472
  SummaryRow.displayName = "SummaryRow";
4099
4473
  //#endregion
4474
+ //#region src/lib/query/query-match.ts
4475
+ function toText(value) {
4476
+ if (value === null || value === void 0) return "";
4477
+ if (typeof value === "string") return value;
4478
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
4479
+ return JSON.stringify(value);
4480
+ }
4481
+ function compare(left, right) {
4482
+ const leftNumber = typeof left === "number" ? left : Number(toText(left));
4483
+ const rightNumber = Number(right);
4484
+ if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) return leftNumber - rightNumber;
4485
+ return toText(left).localeCompare(right);
4486
+ }
4487
+ function matchesClause(clause, read, searchable) {
4488
+ if (clause.type === "term") return searchable().toLowerCase().includes(clause.value.toLowerCase());
4489
+ const value = read(clause.field);
4490
+ switch (clause.operator) {
4491
+ case "exists": return value !== void 0 && value !== null && value !== "";
4492
+ case "eq": return clause.values.some((candidate) => toText(value).toLowerCase() === candidate.toLowerCase());
4493
+ case "contains": return clause.values.some((candidate) => toText(value).toLowerCase().includes(candidate.toLowerCase()));
4494
+ case "gt":
4495
+ var _clause$values$;
4496
+ return compare(value, (_clause$values$ = clause.values[0]) !== null && _clause$values$ !== void 0 ? _clause$values$ : "") > 0;
4497
+ case "gte":
4498
+ var _clause$values$2;
4499
+ return compare(value, (_clause$values$2 = clause.values[0]) !== null && _clause$values$2 !== void 0 ? _clause$values$2 : "") >= 0;
4500
+ case "lt":
4501
+ var _clause$values$3;
4502
+ return compare(value, (_clause$values$3 = clause.values[0]) !== null && _clause$values$3 !== void 0 ? _clause$values$3 : "") < 0;
4503
+ case "lte":
4504
+ var _clause$values$4;
4505
+ return compare(value, (_clause$values$4 = clause.values[0]) !== null && _clause$values$4 !== void 0 ? _clause$values$4 : "") <= 0;
4506
+ default: return true;
4507
+ }
4508
+ }
4509
+ /**
4510
+ * Whether one row satisfies every clause.
4511
+ *
4512
+ * `searchable` is lazy because most queries are field constraints, and
4513
+ * flattening a row to text for a term match nobody asked for is the expensive
4514
+ * part of filtering a live tail.
4515
+ */
4516
+ function matchesQuery(query, read, searchable) {
4517
+ return query.clauses.every((clause) => {
4518
+ const matched = matchesClause(clause, read, searchable);
4519
+ return clause.negated ? !matched : matched;
4520
+ });
4521
+ }
4522
+ /** Convenience for plain objects, including one level of nested properties. */
4523
+ function matchesQueryObject(query, row, options = {}) {
4524
+ const nested = options.nested ? row[options.nested] : void 0;
4525
+ const read = (field) => field in row ? row[field] : nested === null || nested === void 0 ? void 0 : nested[field];
4526
+ let cached = null;
4527
+ const searchable = () => {
4528
+ var _cached;
4529
+ (_cached = cached) !== null && _cached !== void 0 || (cached = [...Object.values(row).filter((value) => typeof value !== "object"), ...Object.values(nested !== null && nested !== void 0 ? nested : {})].map(toText).join(" "));
4530
+ return cached;
4531
+ };
4532
+ return matchesQuery(query, read, searchable);
4533
+ }
4534
+ //#endregion
4535
+ //#region src/lib/use-media-query.ts
4536
+ /**
4537
+ * Whether a media query matches, kept in sync with the browser.
4538
+ *
4539
+ * `useSyncExternalStore` rather than an effect: a layout that switches on width
4540
+ * must not render the wrong shape for a frame first. The server snapshot is the
4541
+ * caller's `serverFallback`, because the server does not know the viewport and
4542
+ * guessing "narrow" collapses a wide layout on every first paint.
4543
+ *
4544
+ * Internal. Exported from `lib` for the components in this package, not from
4545
+ * the package barrel — a hook that answers "is this viewport wide" invites
4546
+ * layout decisions that belong in CSS.
4547
+ */
4548
+ function useMediaQuery(query, serverFallback = false) {
4549
+ return (0, react.useSyncExternalStore)((onChange) => {
4550
+ if (typeof window === "undefined") return () => {};
4551
+ const list = window.matchMedia(query);
4552
+ list.addEventListener("change", onChange);
4553
+ return () => list.removeEventListener("change", onChange);
4554
+ }, () => typeof window === "undefined" ? serverFallback : window.matchMedia(query).matches, () => serverFallback);
4555
+ }
4556
+ //#endregion
4557
+ //#region src/shells/inspector-layout.tsx
4558
+ /** Tailwind needs whole class names, so the queries and widths are literals. */
4559
+ const breakpointQuery = {
4560
+ lg: "(min-width: 64rem)",
4561
+ xl: "(min-width: 80rem)",
4562
+ "2xl": "(min-width: 96rem)"
4563
+ };
4564
+ const pushWidth = {
4565
+ sm: "w-[22rem]",
4566
+ md: "w-[30rem]",
4567
+ lg: "w-[42rem]"
4568
+ };
4569
+ const flyoutSize = {
4570
+ sm: "sm",
4571
+ md: "md",
4572
+ lg: "lg"
4573
+ };
4574
+ /**
4575
+ * InspectorLayout — a list and the record it is showing, side by side.
4576
+ *
4577
+ * Reading a catalogue is a loop: look at the list, open one, decide, come back.
4578
+ * A dialog breaks that loop — it takes the list away, and coming back costs the
4579
+ * reader their scroll position and their place in the scan. This keeps both on
4580
+ * screen where there is room, and falls back to an overlay where there is not.
4581
+ *
4582
+ * Every surface that wanted this was writing `w-80 border-l` by hand and
4583
+ * re-deciding the two things that are easy to get wrong: which width switches
4584
+ * the layout, and whether the list stays mounted.
4585
+ *
4586
+ * Focus is deliberately **not** one of them. `Flyout` already remembers who
4587
+ * opened it and hands focus back on close, and its effect runs before this
4588
+ * one — a parent that also tried to capture `document.activeElement` would
4589
+ * read the panel the child had just focused and "restore" to a node that is
4590
+ * about to be removed. One owner, and it is the one closest to the panel.
4591
+ *
4592
+ * @example
4593
+ * ```tsx
4594
+ * <InspectorLayout
4595
+ * open={selected !== null}
4596
+ * onClose={() => setSelected(null)}
4597
+ * title={selected?.name}
4598
+ * inspector={<EventInspector name={selected?.name} />}
4599
+ * >
4600
+ * <DataTable … />
4601
+ * </InspectorLayout>
4602
+ * ```
4603
+ */
4604
+ function InspectorLayout({ children, inspector, open, onClose, title, description, actions, footer, breakpoint = "xl", width = "md", labels, className }) {
4605
+ const canPush = useMediaQuery(breakpointQuery[breakpoint], true);
4606
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4607
+ className: require_text_truncate.cn("flex min-w-0 items-stretch gap-group", className),
4608
+ "data-opt-id": "MN44T",
4609
+ "data-opt-slug": "inspector-layout.InspectorLayout",
4610
+ "data-inspector-mode": canPush ? "push" : "overlay",
4611
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4612
+ className: "min-w-0 flex-1",
4613
+ children
4614
+ }), canPush ? open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", {
4615
+ className: require_text_truncate.cn("shrink-0", pushWidth[width]),
4616
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_field_sidebar.Flyout, {
4617
+ open,
4618
+ onClose,
4619
+ type: "inline",
4620
+ title,
4621
+ description,
4622
+ actions,
4623
+ footer,
4624
+ labels,
4625
+ className: "h-full",
4626
+ children: inspector
4627
+ })
4628
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_field_sidebar.Flyout, {
4629
+ open,
4630
+ onClose,
4631
+ type: "overlay",
4632
+ scrim: true,
4633
+ size: flyoutSize[width],
4634
+ title,
4635
+ description,
4636
+ actions,
4637
+ footer,
4638
+ labels,
4639
+ children: inspector
4640
+ })]
4641
+ });
4642
+ }
4643
+ //#endregion
4644
+ //#region src/shells/query-filter-bar.tsx
4645
+ const defaultLabels$14 = {
4646
+ placeholder: "검색하거나 필터를 입력하세요",
4647
+ ariaLabel: "검색",
4648
+ filtersAriaLabel: "필터",
4649
+ clearAll: "필터 지우기",
4650
+ activeCount: (count) => `${count}개 적용됨`
4651
+ };
4652
+ function toggleValue(query, field, value, active, multiSelect) {
4653
+ if (active) {
4654
+ const remaining = require_field_sidebar.fieldValues(query, field).filter((it) => it !== value);
4655
+ const cleared = require_field_sidebar.withoutField(query, field);
4656
+ return remaining.reduce((next, keep) => require_field_sidebar.withFieldValue(next, field, keep), cleared);
4657
+ }
4658
+ return multiSelect ? require_field_sidebar.withFieldValue(query, field, value) : require_field_sidebar.withFieldValue(require_field_sidebar.withoutField(query, field), field, value);
4659
+ }
4660
+ /**
4661
+ * QueryFilterBar — filter buttons and a query string that are the same thing.
4662
+ *
4663
+ * The failure this exists to prevent is two sources of truth. A search box
4664
+ * beside a row of filter buttons will drift: the buttons keep their own state,
4665
+ * the box keeps the text, and a link to the page carries one of them. Readers
4666
+ * find the two disagreeing and stop trusting either.
4667
+ *
4668
+ * So the buttons hold no state at all. Each one reads the query to decide
4669
+ * whether it is active and writes the query when clicked, which makes the
4670
+ * behaviour fall out for free: typing `status:archived` lights up the status
4671
+ * filter, clicking the filter puts `status:archived` in the box, and the URL
4672
+ * that carries the query carries the whole filter state with it.
4673
+ *
4674
+ * @example
4675
+ * ```tsx
4676
+ * <QueryFilterBar
4677
+ * value={query}
4678
+ * onChange={setQuery}
4679
+ * filters={[
4680
+ * { id: "conversion", label: "전환", kind: "is", field: "is", value: "conversion" },
4681
+ * { id: "status", label: "상태", kind: "field_value_selection", field: "status",
4682
+ * options: [{ value: "archived", label: "보관", count: 12 }] },
4683
+ * ]}
4684
+ * />
4685
+ * ```
4686
+ */
4687
+ function QueryFilterBar({ value, onChange, filters, fields, actions, showClauses = true, live = false, disabled = false, labels: customLabels, queryBarLabels, className }) {
4688
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$14), customLabels);
4689
+ const activeCount = (0, react.useMemo)(() => filters.reduce((count, filter) => {
4690
+ const values = require_field_sidebar.fieldValues(value, filter.field);
4691
+ if (filter.kind === "field_value_selection") return count + values.length;
4692
+ return count + (filter.value && values.includes(filter.value) ? 1 : 0);
4693
+ }, 0), [filters, value]);
4694
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4695
+ className: require_text_truncate.cn("flex flex-col gap-element", className),
4696
+ "data-opt-id": "SK31N",
4697
+ "data-opt-slug": "query-filter-bar.QueryFilterBar",
4698
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_field_sidebar.QueryBar, {
4699
+ value,
4700
+ onChange,
4701
+ fields,
4702
+ showClauses,
4703
+ live,
4704
+ disabled,
4705
+ labels: require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, queryBarLabels), {}, {
4706
+ placeholder: labels.placeholder,
4707
+ ariaLabel: labels.ariaLabel
4708
+ })
4709
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4710
+ className: "gap-element flex flex-wrap items-center",
4711
+ role: "group",
4712
+ "aria-label": labels.filtersAriaLabel,
4713
+ children: [
4714
+ filters.map((filter) => {
4715
+ var _filter$multiSelect, _filter$value;
4716
+ const values = require_field_sidebar.fieldValues(value, filter.field);
4717
+ const multiSelect = (_filter$multiSelect = filter.multiSelect) !== null && _filter$multiSelect !== void 0 ? _filter$multiSelect : true;
4718
+ if (filter.kind === "field_value_selection") {
4719
+ var _filter$options, _filter$options2;
4720
+ const selected = (_filter$options = filter.options) === null || _filter$options === void 0 ? void 0 : _filter$options.filter((option) => values.includes(option.value));
4721
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.PopoverRoot, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.PopoverTrigger, {
4722
+ disabled,
4723
+ className: require_text_truncate.cn("inline-flex h-7 items-center gap-1 rounded-md border px-2 text-xs transition-colors", require_text_truncate.OPT_FOCUS_VISIBLE, (selected === null || selected === void 0 ? void 0 : selected.length) ? "border-accent bg-accent-subtle text-text-primary" : "border-border text-text-secondary hover:text-text-primary", disabled && "pointer-events-none opacity-50"),
4724
+ children: [
4725
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: filter.label }),
4726
+ (selected === null || selected === void 0 ? void 0 : selected.length) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.Badge, {
4727
+ variant: "info",
4728
+ size: "sm",
4729
+ children: selected.length
4730
+ }) : null,
4731
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronDown, {
4732
+ "aria-hidden": "true",
4733
+ className: "size-3"
4734
+ })
4735
+ ]
4736
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.PopoverContent, {
4737
+ className: "min-w-48 p-1",
4738
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4739
+ role: "group",
4740
+ "aria-label": filter.label,
4741
+ children: (_filter$options2 = filter.options) === null || _filter$options2 === void 0 ? void 0 : _filter$options2.map((option) => {
4742
+ const active = values.includes(option.value);
4743
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
4744
+ type: "button",
4745
+ disabled,
4746
+ "aria-pressed": active,
4747
+ onClick: () => onChange(toggleValue(value, filter.field, option.value, active, multiSelect)),
4748
+ className: require_text_truncate.cn("flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs", "hover:bg-bg-subtle", "disabled:pointer-events-none disabled:opacity-50", require_text_truncate.OPT_FOCUS_VISIBLE),
4749
+ children: [
4750
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, {
4751
+ "aria-hidden": "true",
4752
+ className: require_text_truncate.cn("size-3 shrink-0", active ? "opacity-100" : "opacity-0")
4753
+ }),
4754
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4755
+ className: "flex-1 truncate",
4756
+ children: option.label
4757
+ }),
4758
+ option.count != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4759
+ className: "text-text-tertiary tabular-nums",
4760
+ children: option.count
4761
+ })
4762
+ ]
4763
+ }, option.value);
4764
+ })
4765
+ })
4766
+ })] }, filter.id);
4767
+ }
4768
+ const filterValue = (_filter$value = filter.value) !== null && _filter$value !== void 0 ? _filter$value : filter.id;
4769
+ const active = values.includes(filterValue);
4770
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4771
+ type: "button",
4772
+ disabled,
4773
+ "aria-pressed": active,
4774
+ onClick: () => onChange(toggleValue(value, filter.field, filterValue, active, multiSelect)),
4775
+ className: require_text_truncate.cn("inline-flex h-7 items-center rounded-md border px-2 text-xs transition-colors", require_text_truncate.OPT_FOCUS_VISIBLE, active ? "border-accent bg-accent-subtle text-text-primary" : "border-border text-text-secondary hover:text-text-primary", "disabled:pointer-events-none disabled:opacity-50"),
4776
+ children: filter.label
4777
+ }, filter.id);
4778
+ }),
4779
+ activeCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4780
+ className: "text-text-tertiary text-xs",
4781
+ children: labels.activeCount(activeCount)
4782
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.Button, {
4783
+ variant: "ghost",
4784
+ size: "sm",
4785
+ disabled,
4786
+ onClick: () => onChange({ clauses: [] }),
4787
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, {
4788
+ "aria-hidden": "true",
4789
+ className: "size-3"
4790
+ }), labels.clearAll]
4791
+ })] }),
4792
+ actions
4793
+ ]
4794
+ })]
4795
+ });
4796
+ }
4797
+ /** Whether the bar is filtering anything — for an empty state's wording. */
4798
+ function hasActiveQuery(query) {
4799
+ return !require_field_sidebar.isEmptyQuery(query);
4800
+ }
4801
+ //#endregion
4802
+ //#region src/shells/catalog-frame.tsx
4803
+ /**
4804
+ * CatalogRowActions — a row's actions, two of them visible.
4805
+ *
4806
+ * Beyond two, a row's action column starts competing with the row's content
4807
+ * for the reader's eye, so the rest go behind one menu. The click never
4808
+ * reaches the row: acting on a row and selecting it are different intentions,
4809
+ * and a table that does both at once is one a reader stops trusting.
4810
+ */
4811
+ function CatalogRowActions({ item, actions, visibleCount = 2, labels }) {
4812
+ var _labels$rowActions, _labels$moreActions;
4813
+ const applicable = actions.filter((action) => {
4814
+ var _action$available, _action$available2;
4815
+ return (_action$available = (_action$available2 = action.available) === null || _action$available2 === void 0 ? void 0 : _action$available2.call(action, item)) !== null && _action$available !== void 0 ? _action$available : true;
4816
+ });
4817
+ const visible = applicable.slice(0, visibleCount);
4818
+ const overflow = applicable.slice(visibleCount);
4819
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4820
+ className: "flex items-center justify-end gap-1",
4821
+ role: "group",
4822
+ "aria-label": (_labels$rowActions = labels === null || labels === void 0 ? void 0 : labels.rowActions) !== null && _labels$rowActions !== void 0 ? _labels$rowActions : "행 액션",
4823
+ onClick: (event) => event.stopPropagation(),
4824
+ children: [visible.map((action) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.Button, {
4825
+ variant: "ghost",
4826
+ size: "sm",
4827
+ onClick: () => action.onSelect(item),
4828
+ children: [action.icon, action.label]
4829
+ }, 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, {
4830
+ "aria-label": (_labels$moreActions = labels === null || labels === void 0 ? void 0 : labels.moreActions) !== null && _labels$moreActions !== void 0 ? _labels$moreActions : "더 보기",
4831
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.MoreHorizontal, {
4832
+ "aria-hidden": "true",
4833
+ className: "size-4"
4834
+ })
4835
+ }), /* @__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, {
4836
+ onClick: () => action.onSelect(item),
4837
+ children: action.label
4838
+ }, action.id)) })] })]
4839
+ });
4840
+ }
4841
+ /**
4842
+ * Keeps a cell's own controls from also selecting the row.
4843
+ *
4844
+ * A click on a switch or a copy button reaches the row handler on its way up,
4845
+ * so toggling a flag would open the inspector at the same time.
4846
+ */
4847
+ function CatalogCellControls({ children }) {
4848
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4849
+ className: "contents",
4850
+ onClick: (event) => event.stopPropagation(),
4851
+ children
4852
+ });
4853
+ }
4854
+ const defaultLabels$13 = {
4855
+ emptyTitle: "아직 아무것도 없습니다",
4856
+ emptyDescription: "데이터가 도착하면 여기에 나타납니다.",
4857
+ filteredEmptyTitle: "조건에 맞는 항목이 없습니다",
4858
+ filteredEmptyDescription: "필터를 지우면 전체 목록이 보입니다.",
4859
+ clearFilters: "필터 지우기",
4860
+ errorTitle: "목록을 불러오지 못했습니다",
4861
+ retry: "다시 시도"
4862
+ };
4863
+ /**
4864
+ * CatalogFrame — the shape every catalogue list has.
4865
+ *
4866
+ * Two catalogues (events, properties) differ only in their columns and their
4867
+ * words; everything around the table is the same, and writing it twice meant
4868
+ * two copies of the decisions that are easy to get wrong — that a failed read
4869
+ * must not look like an empty list, that an empty list reads differently when a
4870
+ * filter is on, and that a selection must not survive a filter change.
4871
+ *
4872
+ * The last one is enforced here rather than left to the caller. A bulk action
4873
+ * applied to rows the reader can no longer see is the kind of mistake that is
4874
+ * only noticed afterwards.
4875
+ */
4876
+ function CatalogFrame({ children, isEmpty, query, onQueryChange, filters, stats, onStatClick, notice, emptyActions, header, actions, toolbar, inspector, inspectorOpen, onInspectorClose, inspectorTitle, inspectorDescription, inspectorActions, inspectorFooter, inspectorWidth, page = 1, pageSize = 50, totalCount, onPageChange, selectedKeys, onSelectionChange, bulkActions, onBulkAction, error, onRetry, labels: customLabels, className }) {
4877
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$13), customLabels);
4878
+ const lastScope = (0, react.useRef)({
4879
+ query,
4880
+ page
4881
+ });
4882
+ (0, react.useEffect)(() => {
4883
+ const changed = lastScope.current.query !== query || lastScope.current.page !== page;
4884
+ lastScope.current = {
4885
+ query,
4886
+ page
4887
+ };
4888
+ if (changed && selectedKeys && selectedKeys.length > 0) onSelectionChange === null || onSelectionChange === void 0 || onSelectionChange([]);
4889
+ }, [
4890
+ query,
4891
+ page,
4892
+ selectedKeys,
4893
+ onSelectionChange
4894
+ ]);
4895
+ const filtering = !require_field_sidebar.isEmptyQuery(query);
4896
+ const body = error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.EmptyState, {
4897
+ tone: "error",
4898
+ hasBorder: true,
4899
+ title: labels.errorTitle,
4900
+ body: error,
4901
+ actions: onRetry ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.Button, {
4902
+ variant: "secondary",
4903
+ onClick: onRetry,
4904
+ children: labels.retry
4905
+ }) : void 0
4906
+ }) : isEmpty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.EmptyState, {
4907
+ tone: "subdued",
4908
+ hasBorder: true,
4909
+ title: filtering ? labels.filteredEmptyTitle : labels.emptyTitle,
4910
+ description: filtering ? labels.filteredEmptyDescription : labels.emptyDescription,
4911
+ actions: filtering ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.Button, {
4912
+ variant: "secondary",
4913
+ onClick: () => onQueryChange({ clauses: [] }),
4914
+ children: labels.clearFilters
4915
+ }) : emptyActions
4916
+ }) : children;
4917
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4918
+ className: require_text_truncate.cn("flex flex-col gap-section", className),
4919
+ children: [
4920
+ (header || actions) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4921
+ className: "gap-group flex min-w-0 flex-col lg:flex-row lg:items-start lg:justify-between",
4922
+ children: [header && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4923
+ className: "min-w-0 flex-1",
4924
+ children: header
4925
+ }), actions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4926
+ className: "gap-element flex flex-wrap items-center",
4927
+ children: actions
4928
+ })]
4929
+ }),
4930
+ stats && stats.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SummaryRow, {
4931
+ stats,
4932
+ onStatClick
4933
+ }),
4934
+ notice,
4935
+ toolbar && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4936
+ className: "gap-group flex flex-wrap items-center",
4937
+ children: toolbar
4938
+ }),
4939
+ filters && filters.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QueryFilterBar, {
4940
+ value: query,
4941
+ onChange: onQueryChange,
4942
+ filters,
4943
+ disabled: Boolean(error)
4944
+ }),
4945
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InspectorLayout, {
4946
+ open: inspectorOpen && Boolean(inspector),
4947
+ onClose: onInspectorClose,
4948
+ inspector,
4949
+ title: inspectorTitle,
4950
+ description: inspectorDescription,
4951
+ actions: inspectorActions,
4952
+ footer: inspectorFooter,
4953
+ width: inspectorWidth,
4954
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4955
+ className: "gap-group flex flex-col",
4956
+ children: [body, onPageChange && totalCount != null && totalCount > pageSize && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.Pagination, {
4957
+ currentPage: page,
4958
+ totalPages: Math.ceil(totalCount / pageSize),
4959
+ onPageChange
4960
+ })]
4961
+ })
4962
+ }),
4963
+ bulkActions && bulkActions.length > 0 && onBulkAction && selectedKeys && selectedKeys.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FloatingActionBar, {
4964
+ actions: bulkActions,
4965
+ selectedCount: selectedKeys.length,
4966
+ onAction: onBulkAction,
4967
+ onDismiss: () => onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange([])
4968
+ })
4969
+ ]
4970
+ });
4971
+ }
4972
+ //#endregion
4100
4973
  //#region src/shells/comparison-selector.tsx
4101
4974
  /** Renders the comparison selector component. */
4102
4975
  function ComparisonSelector({ segments, valueA, valueB, onChangeA, onChangeB, values, onValuesChange, maxItems = 5, labels: customLabels, className }) {
@@ -5251,7 +6124,7 @@ function ThemeSwitcher({ className, labels: userLabels, variant = "default", cus
5251
6124
  ThemeSwitcher.displayName = "ThemeSwitcher";
5252
6125
  //#endregion
5253
6126
  //#region src/shells/prompt-template.tsx
5254
- const defaultLabels$11 = {
6127
+ const defaultLabels$12 = {
5255
6128
  copy: "Copy",
5256
6129
  copied: "Copied!",
5257
6130
  copyFailed: "Copy failed"
@@ -5261,7 +6134,7 @@ function renderPrompt(template, values) {
5261
6134
  }
5262
6135
  /** Renders the prompt template component. */
5263
6136
  function PromptTemplate({ title, description, template, variables = [], className, labels: customLabels }) {
5264
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$11), customLabels);
6137
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$12), customLabels);
5265
6138
  const [values, setValues] = react.useState(() => {
5266
6139
  const initial = {};
5267
6140
  for (const v of variables) if (v.defaultValue) initial[v.name] = v.defaultValue;
@@ -5750,14 +6623,14 @@ function AsyncCombobox({ onSearch, debounceMs = 300, loadingText, minChars = 1,
5750
6623
  }
5751
6624
  //#endregion
5752
6625
  //#region src/shells/vertical-tabs.tsx
5753
- const defaultLabels$10 = {
6626
+ const defaultLabels$11 = {
5754
6627
  ariaLabel: "Vertical tabs",
5755
6628
  emptyMessage: "No tabs available"
5756
6629
  };
5757
6630
  /** Renders the vertical tabs component. */
5758
6631
  function VerticalTabs({ tabs, defaultTabId, labels: customLabels, className }) {
5759
6632
  var _tabs$;
5760
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$10), customLabels);
6633
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$11), customLabels);
5761
6634
  if (tabs.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5762
6635
  className: require_text_truncate.cn("text-text-secondary text-sm", className),
5763
6636
  "data-opt-id": "J81G4",
@@ -5766,6 +6639,7 @@ function VerticalTabs({ tabs, defaultTabId, labels: customLabels, className }) {
5766
6639
  });
5767
6640
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.TabsRoot, {
5768
6641
  defaultSelectedId: defaultTabId !== null && defaultTabId !== void 0 ? defaultTabId : (_tabs$ = tabs[0]) === null || _tabs$ === void 0 ? void 0 : _tabs$.id,
6642
+ orientation: "vertical",
5769
6643
  "data-opt-id": "J81G4",
5770
6644
  "data-opt-slug": "vertical-tabs.VerticalTabs",
5771
6645
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -5790,13 +6664,13 @@ function VerticalTabs({ tabs, defaultTabId, labels: customLabels, className }) {
5790
6664
  }
5791
6665
  //#endregion
5792
6666
  //#region src/shells/column-toggler.tsx
5793
- const defaultLabels$9 = {
6667
+ const defaultLabels$10 = {
5794
6668
  triggerLabel: (count) => `Columns (${count})`,
5795
6669
  emptyMessage: "No columns available"
5796
6670
  };
5797
6671
  /** Renders the column toggler component. */
5798
6672
  function ColumnToggler({ columns, visibleColumns, onChange, className, labels: customLabels }) {
5799
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$9), customLabels);
6673
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$10), customLabels);
5800
6674
  const visibleCount = visibleColumns.length;
5801
6675
  const hasColumns = columns.length > 0;
5802
6676
  const toggle = (id) => {
@@ -5875,7 +6749,7 @@ function BulkActions({ selectedCount, actions, onAction, onClear, labels: custom
5875
6749
  }
5876
6750
  //#endregion
5877
6751
  //#region src/shells/saved-filters.tsx
5878
- const defaultLabels$8 = {
6752
+ const defaultLabels$9 = {
5879
6753
  triggerLabel: (count) => `Saved Filters (${count})`,
5880
6754
  emptyMessage: "No saved filters",
5881
6755
  deleteLabel: (name) => `Delete ${name}`,
@@ -5886,7 +6760,7 @@ const defaultLabels$8 = {
5886
6760
  };
5887
6761
  /** Renders the saved filters component. */
5888
6762
  function SavedFilters({ currentFilters, presets, onSavePreset, onLoadPreset, onDeletePreset, className, labels: customLabels }) {
5889
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$8), customLabels);
6763
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$9), customLabels);
5890
6764
  const [newName, setNewName] = react.useState("");
5891
6765
  const [pendingDeleteId, setPendingDeleteId] = react.useState(null);
5892
6766
  const triggerId = react.useId();
@@ -6038,7 +6912,7 @@ function SavedFilters({ currentFilters, presets, onSavePreset, onLoadPreset, onD
6038
6912
  }
6039
6913
  //#endregion
6040
6914
  //#region src/shells/notification-center.tsx
6041
- const defaultLabels$7 = {
6915
+ const defaultLabels$8 = {
6042
6916
  triggerLabel: "Notifications",
6043
6917
  unreadSuffix: (count) => `(${count} unread)`,
6044
6918
  title: "Notifications",
@@ -6047,7 +6921,7 @@ const defaultLabels$7 = {
6047
6921
  };
6048
6922
  /** Renders the notification center component. */
6049
6923
  function NotificationCenter({ notifications, onMarkRead, onMarkAllRead, onAction, className, labels: customLabels }) {
6050
- const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$7), customLabels);
6924
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$8), customLabels);
6051
6925
  const unreadCount = notifications.filter((n) => !n.read).length;
6052
6926
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.PopoverRoot, {
6053
6927
  "data-opt-id": "7A0XY",
@@ -6251,9 +7125,29 @@ function AuditLog({ entries, onLoadMore, loading, labels: customLabels, classNam
6251
7125
  AuditLog.displayName = "AuditLog";
6252
7126
  //#endregion
6253
7127
  //#region src/shells/tree-table.tsx
7128
+ const defaultLabels$7 = {
7129
+ ariaLabel: "Tree table",
7130
+ expand: (rowLabel) => `Expand ${rowLabel}`,
7131
+ collapse: (rowLabel) => `Collapse ${rowLabel}`,
7132
+ level: (depth) => `Level ${depth}`
7133
+ };
7134
+ function flattenTree(nodes, expanded, depth = 0, ancestorsVisible = true) {
7135
+ return nodes.flatMap((node) => {
7136
+ var _node$children;
7137
+ const visible = ancestorsVisible;
7138
+ return [{
7139
+ node,
7140
+ depth,
7141
+ visible
7142
+ }, ...flattenTree((_node$children = node.children) !== null && _node$children !== void 0 ? _node$children : [], expanded, depth + 1, visible && expanded.has(node.id))];
7143
+ });
7144
+ }
6254
7145
  /** Renders the tree table component. */
6255
- function TreeTable({ data, columns, defaultExpanded = [], indentSize = 24, className }) {
7146
+ function TreeTable({ data, columns, defaultExpanded = [], indentSize = 24, getRowLabel, labels: customLabels, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }) {
6256
7147
  const [expanded, setExpanded] = react.useState(() => new Set(defaultExpanded));
7148
+ const baseId = react.useId();
7149
+ const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$7), customLabels);
7150
+ const rows = flattenTree(data, expanded);
6257
7151
  const toggle = (id) => {
6258
7152
  setExpanded((prev) => {
6259
7153
  const next = new Set(prev);
@@ -6267,46 +7161,82 @@ function TreeTable({ data, columns, defaultExpanded = [], indentSize = 24, class
6267
7161
  if (typeof col.accessor === "function") return col.accessor(row);
6268
7162
  return String((_row$col$accessor = row[col.accessor]) !== null && _row$col$accessor !== void 0 ? _row$col$accessor : "");
6269
7163
  };
6270
- const renderRows = (nodes, depth) => nodes.flatMap((node) => {
6271
- const hasChildren = node.children && node.children.length > 0;
6272
- const isExpanded = expanded.has(node.id);
6273
- return [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
6274
- className: "border-border border-b",
6275
- children: columns.map((col, ci) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
6276
- className: require_text_truncate.cn(require_text_truncate.OPT_TD),
6277
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6278
- className: "flex items-center",
6279
- style: ci === 0 ? { paddingLeft: depth * indentSize } : void 0,
6280
- children: [
6281
- ci === 0 && hasChildren && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6282
- type: "button",
6283
- onClick: () => toggle(node.id),
6284
- className: require_text_truncate.cn("mr-1 flex h-5 w-5 items-center justify-center rounded text-xs", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset"),
6285
- "aria-expanded": isExpanded,
6286
- "aria-label": isExpanded ? "Collapse" : "Expand",
6287
- children: isExpanded ? "▼" : "▶"
6288
- }),
6289
- ci === 0 && !hasChildren && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "mr-1 inline-block w-5" }),
6290
- getCellValue(node.data, col)
6291
- ]
6292
- })
6293
- }, col.id))
6294
- }, node.id), ...isExpanded && hasChildren ? renderRows(node.children, depth + 1) : []];
6295
- });
7164
+ const rowId = (id) => `${baseId}-row-${encodeURIComponent(id)}`;
7165
+ const resolveRowLabel = (node) => {
7166
+ if (getRowLabel) return getRowLabel(node);
7167
+ const firstColumn = columns[0];
7168
+ if (firstColumn) {
7169
+ const value = getCellValue(node.data, firstColumn);
7170
+ if (typeof value === "string" || typeof value === "number") return String(value);
7171
+ }
7172
+ return node.id;
7173
+ };
6296
7174
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6297
7175
  className: require_text_truncate.cn("overflow-auto", className),
6298
- "data-opt-id": "EJRTW",
7176
+ "data-opt-id": "PP194",
6299
7177
  "data-opt-slug": "tree-table.TreeTable",
6300
7178
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
6301
7179
  className: require_text_truncate.cn("w-full border-collapse", require_text_truncate.OPT_BORDER),
7180
+ "aria-label": ariaLabelledBy == null ? ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : labels.ariaLabel : void 0,
7181
+ "aria-labelledby": ariaLabelledBy,
6302
7182
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
6303
7183
  className: "border-border border-b",
6304
7184
  children: columns.map((col) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
7185
+ scope: "col",
6305
7186
  className: require_text_truncate.cn(require_text_truncate.OPT_TH),
6306
7187
  style: { width: col.width },
6307
7188
  children: col.header
6308
7189
  }, col.id))
6309
- }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: renderRows(data, 0) })]
7190
+ }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: rows.map(({ node, depth, visible }) => {
7191
+ var _node$children$length, _node$children2, _node$children3;
7192
+ const hasChildren = ((_node$children$length = (_node$children2 = node.children) === null || _node$children2 === void 0 ? void 0 : _node$children2.length) !== null && _node$children$length !== void 0 ? _node$children$length : 0) > 0;
7193
+ const isExpanded = expanded.has(node.id);
7194
+ const resolvedRowLabel = resolveRowLabel(node);
7195
+ const controlledRows = ((_node$children3 = node.children) !== null && _node$children3 !== void 0 ? _node$children3 : []).map((child) => rowId(child.id)).join(" ");
7196
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
7197
+ id: rowId(node.id),
7198
+ hidden: !visible,
7199
+ className: "border-border border-b",
7200
+ children: columns.map((col, columnIndex) => {
7201
+ const content = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7202
+ className: "flex items-center",
7203
+ style: columnIndex === 0 ? { paddingLeft: depth * indentSize } : void 0,
7204
+ children: [
7205
+ columnIndex === 0 && hasChildren && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7206
+ type: "button",
7207
+ onClick: () => toggle(node.id),
7208
+ className: require_text_truncate.cn("mr-1 flex h-5 w-5 items-center justify-center rounded text-xs", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset"),
7209
+ "aria-expanded": isExpanded,
7210
+ "aria-controls": controlledRows || void 0,
7211
+ "aria-label": isExpanded ? labels.collapse(resolvedRowLabel) : labels.expand(resolvedRowLabel),
7212
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7213
+ "aria-hidden": "true",
7214
+ children: isExpanded ? "▼" : "▶"
7215
+ })
7216
+ }),
7217
+ columnIndex === 0 && !hasChildren && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "mr-1 inline-block w-5" }),
7218
+ columnIndex === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7219
+ className: "sr-only",
7220
+ children: [
7221
+ labels.level(depth + 1),
7222
+ ".",
7223
+ " "
7224
+ ]
7225
+ }),
7226
+ getCellValue(node.data, col)
7227
+ ]
7228
+ });
7229
+ return columnIndex === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
7230
+ scope: "row",
7231
+ className: require_text_truncate.cn(require_text_truncate.OPT_TD),
7232
+ children: content
7233
+ }, col.id) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
7234
+ className: require_text_truncate.cn(require_text_truncate.OPT_TD),
7235
+ children: content
7236
+ }, col.id);
7237
+ })
7238
+ }, node.id);
7239
+ }) })]
6310
7240
  })
6311
7241
  });
6312
7242
  }
@@ -7048,17 +7978,37 @@ function DataImportWizard({ fields, onImport, acceptedFormats = ".csv", labels:
7048
7978
  //#endregion
7049
7979
  //#region src/shells/mega-menu.tsx
7050
7980
  const defaultLabels$3 = { trigger: "Menu" };
7981
+ function MegaMenuItemContent({ item }) {
7982
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [item.icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7983
+ "aria-hidden": "true",
7984
+ className: "text-text-secondary mt-0.5 flex-shrink-0",
7985
+ children: item.icon
7986
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7987
+ className: "flex flex-col text-left",
7988
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7989
+ className: "text-text-primary text-sm font-medium",
7990
+ children: item.label
7991
+ }), item.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7992
+ className: "text-text-tertiary text-xs",
7993
+ children: item.description
7994
+ })]
7995
+ })] });
7996
+ }
7051
7997
  /** Renders the mega menu component. */
7052
- function MegaMenu({ menus, columns = 3, footer, triggerLabel, labels: customLabels, className }) {
7998
+ function MegaMenu({ menus, columns = 3, footer, triggerLabel, labels: customLabels, className, "aria-label": ariaLabel }) {
7999
+ var _ref;
7053
8000
  const labels = require_text_truncate._objectSpread2(require_text_truncate._objectSpread2({}, defaultLabels$3), customLabels);
7054
8001
  const resolvedTriggerLabel = triggerLabel !== null && triggerLabel !== void 0 ? triggerLabel : labels.trigger;
8002
+ const navigationLabel = (_ref = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : labels.navigation) !== null && _ref !== void 0 ? _ref : `${resolvedTriggerLabel} navigation`;
8003
+ const itemClassName = "hover:bg-bg-subtle gap-element flex w-full items-start rounded-md p-2 transition-colors";
7055
8004
  if (menus.length === 0) return null;
7056
8005
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.PopoverRoot, {
7057
- "data-opt-id": "42177",
8006
+ "data-opt-id": "AHTK9",
7058
8007
  "data-opt-slug": "mega-menu.MegaMenu",
7059
8008
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.PopoverTrigger, {
7060
8009
  className: require_text_truncate.cn("border-border bg-surface text-text-primary hover:bg-bg-subtle inline-flex h-9 items-center gap-1.5 rounded-lg border px-3 text-sm font-medium", className),
7061
8010
  children: [resolvedTriggerLabel, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
8011
+ "aria-hidden": "true",
7062
8012
  width: "12",
7063
8013
  height: "12",
7064
8014
  viewBox: "0 0 12 12",
@@ -7067,38 +8017,41 @@ function MegaMenu({ menus, columns = 3, footer, triggerLabel, labels: customLabe
7067
8017
  strokeWidth: "1.5",
7068
8018
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M3 5l3 3 3-3" })
7069
8019
  })]
7070
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.PopoverContent, {
8020
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.PopoverContent, {
7071
8021
  className: "w-auto max-w-2xl p-0",
7072
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7073
- className: "gap-group grid p-4",
7074
- style: { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` },
7075
- children: menus.map((section) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7076
- className: "gap-element flex flex-col",
7077
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
7078
- className: "text-text-tertiary text-xs font-semibold tracking-wider uppercase",
7079
- children: section.title
7080
- }), section.items.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
7081
- href: item.href || "#",
7082
- className: "hover:bg-bg-subtle gap-element flex items-start rounded-md p-2 transition-colors",
7083
- children: [item.icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7084
- className: "text-text-secondary mt-0.5 flex-shrink-0",
7085
- children: item.icon
7086
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7087
- className: "flex flex-col",
7088
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7089
- className: "text-text-primary text-sm font-medium",
7090
- children: item.label
7091
- }), item.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7092
- className: "text-text-tertiary text-xs",
7093
- children: item.description
7094
- })]
8022
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
8023
+ "aria-label": navigationLabel,
8024
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8025
+ className: "gap-group grid p-4",
8026
+ style: { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` },
8027
+ children: menus.map((section) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8028
+ className: "gap-element flex flex-col",
8029
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
8030
+ className: "text-text-tertiary text-xs font-semibold tracking-wider uppercase",
8031
+ children: section.title
8032
+ }), section.items.map((item) => {
8033
+ if (item.href != null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
8034
+ href: item.href,
8035
+ className: itemClassName,
8036
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MegaMenuItemContent, { item })
8037
+ }, item.label);
8038
+ if (item.onSelect) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_text_truncate.PopoverClose, {
8039
+ onClick: item.onSelect,
8040
+ className: itemClassName,
8041
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MegaMenuItemContent, { item })
8042
+ }, item.label);
8043
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8044
+ "aria-disabled": "true",
8045
+ className: require_text_truncate.cn(itemClassName, "cursor-not-allowed opacity-60"),
8046
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MegaMenuItemContent, { item })
8047
+ }, item.label);
7095
8048
  })]
7096
- }, item.label))]
7097
- }, section.title))
7098
- }), footer && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7099
- className: "border-border bg-bg-subtle border-t px-4 py-3",
7100
- children: footer
7101
- })]
8049
+ }, section.title))
8050
+ }), footer && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8051
+ className: "border-border bg-bg-subtle border-t px-4 py-3",
8052
+ children: footer
8053
+ })]
8054
+ })
7102
8055
  })]
7103
8056
  });
7104
8057
  }
@@ -8296,67 +9249,6 @@ const enStarRatingLabels = {
8296
9249
  };
8297
9250
  const enBreadcrumbLabels = { navAriaLabel: "Go to {label}" };
8298
9251
  //#endregion
8299
- //#region src/lib/query/query-match.ts
8300
- function toText(value) {
8301
- if (value === null || value === void 0) return "";
8302
- if (typeof value === "string") return value;
8303
- if (typeof value === "number" || typeof value === "boolean") return String(value);
8304
- return JSON.stringify(value);
8305
- }
8306
- function compare(left, right) {
8307
- const leftNumber = typeof left === "number" ? left : Number(toText(left));
8308
- const rightNumber = Number(right);
8309
- if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) return leftNumber - rightNumber;
8310
- return toText(left).localeCompare(right);
8311
- }
8312
- function matchesClause(clause, read, searchable) {
8313
- if (clause.type === "term") return searchable().toLowerCase().includes(clause.value.toLowerCase());
8314
- const value = read(clause.field);
8315
- switch (clause.operator) {
8316
- case "exists": return value !== void 0 && value !== null && value !== "";
8317
- case "eq": return clause.values.some((candidate) => toText(value).toLowerCase() === candidate.toLowerCase());
8318
- case "contains": return clause.values.some((candidate) => toText(value).toLowerCase().includes(candidate.toLowerCase()));
8319
- case "gt":
8320
- var _clause$values$;
8321
- return compare(value, (_clause$values$ = clause.values[0]) !== null && _clause$values$ !== void 0 ? _clause$values$ : "") > 0;
8322
- case "gte":
8323
- var _clause$values$2;
8324
- return compare(value, (_clause$values$2 = clause.values[0]) !== null && _clause$values$2 !== void 0 ? _clause$values$2 : "") >= 0;
8325
- case "lt":
8326
- var _clause$values$3;
8327
- return compare(value, (_clause$values$3 = clause.values[0]) !== null && _clause$values$3 !== void 0 ? _clause$values$3 : "") < 0;
8328
- case "lte":
8329
- var _clause$values$4;
8330
- return compare(value, (_clause$values$4 = clause.values[0]) !== null && _clause$values$4 !== void 0 ? _clause$values$4 : "") <= 0;
8331
- default: return true;
8332
- }
8333
- }
8334
- /**
8335
- * Whether one row satisfies every clause.
8336
- *
8337
- * `searchable` is lazy because most queries are field constraints, and
8338
- * flattening a row to text for a term match nobody asked for is the expensive
8339
- * part of filtering a live tail.
8340
- */
8341
- function matchesQuery(query, read, searchable) {
8342
- return query.clauses.every((clause) => {
8343
- const matched = matchesClause(clause, read, searchable);
8344
- return clause.negated ? !matched : matched;
8345
- });
8346
- }
8347
- /** Convenience for plain objects, including one level of nested properties. */
8348
- function matchesQueryObject(query, row, options = {}) {
8349
- const nested = options.nested ? row[options.nested] : void 0;
8350
- const read = (field) => field in row ? row[field] : nested === null || nested === void 0 ? void 0 : nested[field];
8351
- let cached = null;
8352
- const searchable = () => {
8353
- var _cached;
8354
- (_cached = cached) !== null && _cached !== void 0 || (cached = [...Object.values(row).filter((value) => typeof value !== "object"), ...Object.values(nested !== null && nested !== void 0 ? nested : {})].map(toText).join(" "));
8355
- return cached;
8356
- };
8357
- return matchesQuery(query, read, searchable);
8358
- }
8359
- //#endregion
8360
9252
  exports.ALL_COMPOUND_THEMES = ALL_COMPOUND_THEMES;
8361
9253
  exports.AccordionContent = require_key_pad_menu.AccordionContent;
8362
9254
  exports.AccordionItem = require_key_pad_menu.AccordionItem;
@@ -8381,12 +9273,16 @@ exports.Breadcrumb = require_key_pad_menu.Breadcrumb;
8381
9273
  exports.BulkActions = BulkActions;
8382
9274
  exports.Button = require_text_truncate.Button;
8383
9275
  exports.COLOR_PRESETS = COLOR_PRESETS;
9276
+ exports.Callout = Callout;
8384
9277
  exports.Card = require_key_pad_menu.Card;
8385
9278
  exports.CardContent = require_key_pad_menu.CardContent;
8386
9279
  exports.CardDescription = require_key_pad_menu.CardDescription;
8387
9280
  exports.CardFooter = require_key_pad_menu.CardFooter;
8388
9281
  exports.CardHeader = require_key_pad_menu.CardHeader;
8389
9282
  exports.CardTitle = require_key_pad_menu.CardTitle;
9283
+ exports.CatalogCellControls = CatalogCellControls;
9284
+ exports.CatalogFrame = CatalogFrame;
9285
+ exports.CatalogRowActions = CatalogRowActions;
8390
9286
  exports.ChatInput = ChatInput;
8391
9287
  exports.ChatMessageList = ChatMessageList;
8392
9288
  exports.ChatSidebar = ChatSidebar;
@@ -8428,6 +9324,7 @@ exports.ConfirmDialog = ConfirmDialog;
8428
9324
  exports.ConnectionIndicator = ConnectionIndicator;
8429
9325
  exports.Container = require_key_pad_menu.Container;
8430
9326
  exports.ContentTabs = require_field_sidebar.ContentTabs;
9327
+ exports.CopyButton = CopyButton;
8431
9328
  exports.DEFAULT_PRESETS = require_text_truncate.DEFAULT_PRESETS;
8432
9329
  exports.DEFAULT_TIME_PRESETS = require_field_sidebar.DEFAULT_TIME_PRESETS;
8433
9330
  exports.DashboardGrid = require_field_sidebar.DashboardGrid;
@@ -8486,6 +9383,7 @@ exports.FaqAccordion = require_field_sidebar.FaqAccordion;
8486
9383
  exports.FeatureFlagPanel = FeatureFlagPanel;
8487
9384
  exports.FieldSidebar = require_field_sidebar.FieldSidebar;
8488
9385
  exports.FieldToken = require_text_truncate.FieldToken;
9386
+ exports.FieldTokenLegend = require_text_truncate.FieldTokenLegend;
8489
9387
  exports.FileUploadForm = FileUploadForm;
8490
9388
  exports.FilterBar = FilterBar;
8491
9389
  exports.FloatingActionBar = FloatingActionBar;
@@ -8529,6 +9427,7 @@ exports.InlineEdit = require_key_pad_menu.InlineEdit;
8529
9427
  exports.InlineEditTable = InlineEditTable;
8530
9428
  exports.Input = require_text_truncate.Input;
8531
9429
  exports.InsightsPanel = InsightsPanel;
9430
+ exports.InspectorLayout = InspectorLayout;
8532
9431
  exports.KanbanBoard = KanbanBoard;
8533
9432
  exports.Kbd = require_text_truncate.Kbd;
8534
9433
  exports.KeyPadMenu = require_key_pad_menu.KeyPadMenu;
@@ -8576,6 +9475,7 @@ exports.ProjectSwitcher = require_field_sidebar.ProjectSwitcher;
8576
9475
  exports.PromptTemplate = PromptTemplate;
8577
9476
  exports.PropertyExplorer = PropertyExplorer;
8578
9477
  exports.QueryBar = require_field_sidebar.QueryBar;
9478
+ exports.QueryFilterBar = QueryFilterBar;
8579
9479
  exports.QueryResultsTable = QueryResultsTable;
8580
9480
  exports.QuickActions = QuickActions;
8581
9481
  exports.Radio = require_key_pad_menu.Radio;
@@ -8603,6 +9503,7 @@ exports.ScrollArea = require_key_pad_menu.ScrollArea;
8603
9503
  exports.SearchCombobox = require_field_sidebar.SearchCombobox;
8604
9504
  exports.Section = require_key_pad_menu.Section;
8605
9505
  exports.SegmentBuilder = SegmentBuilder;
9506
+ exports.SegmentedControl = SegmentedControl;
8606
9507
  exports.SelectItem = require_text_truncate.SelectItem;
8607
9508
  exports.SelectLabel = require_text_truncate.SelectLabel;
8608
9509
  exports.SelectPopover = require_text_truncate.SelectPopover;
@@ -8624,6 +9525,7 @@ exports.Spinner = require_text_truncate.Spinner;
8624
9525
  exports.SqlEditor = SqlEditor;
8625
9526
  exports.StarRating = require_text_truncate.StarRating;
8626
9527
  exports.StatCard = require_text_truncate.StatCard;
9528
+ exports.StatusDot = StatusDot;
8627
9529
  exports.StatusSelect = require_field_sidebar.StatusSelect;
8628
9530
  exports.StepBuilder = require_key_pad_menu.StepBuilder;
8629
9531
  exports.SummaryRow = SummaryRow;
@@ -8701,6 +9603,7 @@ exports.getShaderFragment = require_key_pad_menu.getShaderFragment;
8701
9603
  exports.getShaderPreset = require_key_pad_menu.getShaderPreset;
8702
9604
  exports.getThemeDescriptor = getThemeDescriptor;
8703
9605
  exports.getTrappedContextRole = getTrappedContextRole;
9606
+ exports.hasActiveQuery = hasActiveQuery;
8704
9607
  exports.isDescriptorSpec = isDescriptorSpec;
8705
9608
  exports.isEmptyQuery = require_field_sidebar.isEmptyQuery;
8706
9609
  exports.isForceLightSpec = isForceLightSpec;