@reopt-ai/opt-ui 1.10.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPONENT_CATALOG.md +177 -66
- package/README.md +21 -5
- package/dist/core/index.cjs +10 -8
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +3 -3
- package/dist/docs/02-components/01-core.md +92 -41
- package/dist/docs/02-components/02-visuals.md +1 -1
- package/dist/docs/02-components/03-shells.md +96 -26
- package/dist/docs/02-components/04-surfaces.md +1 -1
- package/dist/docs/02-components/index.md +5 -5
- package/dist/{field-sidebar-DWfJAJlx.d.ts → field-sidebar-B5SQC35J.d.cts} +214 -3
- package/dist/field-sidebar-B5SQC35J.d.cts.map +1 -0
- package/dist/{field-sidebar-BXjvV7Cz.js → field-sidebar-BXl5RJ3q.js} +589 -40
- package/dist/field-sidebar-BXl5RJ3q.js.map +1 -0
- package/dist/{field-sidebar-nwcE9LC4.d.cts → field-sidebar-CBeWE8xX.d.ts} +214 -3
- package/dist/field-sidebar-CBeWE8xX.d.ts.map +1 -0
- package/dist/{field-sidebar-B6Ndr8HE.cjs → field-sidebar-DAuN4jPV.cjs} +605 -38
- package/dist/id-registry.cjs +46 -6
- package/dist/id-registry.d.cts.map +1 -1
- package/dist/id-registry.d.ts.map +1 -1
- package/dist/id-registry.js +46 -6
- package/dist/id-registry.js.map +1 -1
- package/dist/id-registry.json +97 -12
- package/dist/index.cjs +39 -33
- package/dist/index.d.cts +10 -6
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +10 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -19
- package/dist/index.js.map +1 -1
- package/dist/{key-pad-menu-DfZbeXhG.d.cts → key-pad-menu-BxTy_u0Q.d.cts} +152 -7
- package/dist/key-pad-menu-BxTy_u0Q.d.cts.map +1 -0
- package/dist/{key-pad-menu-D5mQcS5v.cjs → key-pad-menu-Cg6rZBie.cjs} +490 -609
- package/dist/{key-pad-menu-BsgJMjD4.d.ts → key-pad-menu-u5GTJl9B.d.ts} +152 -7
- package/dist/key-pad-menu-u5GTJl9B.d.ts.map +1 -0
- package/dist/{key-pad-menu-BQunU20e.js → key-pad-menu-wXkWn1I1.js} +387 -458
- package/dist/key-pad-menu-wXkWn1I1.js.map +1 -0
- package/dist/meta.cjs +486 -9
- package/dist/meta.d.cts.map +1 -1
- package/dist/meta.d.ts.map +1 -1
- package/dist/meta.js +486 -9
- package/dist/meta.js.map +1 -1
- package/dist/shells/index.cjs +4 -1
- package/dist/shells/index.d.cts +2 -2
- package/dist/shells/index.d.ts +2 -2
- package/dist/shells/index.js +2 -2
- package/dist/{text-truncate-CxdzAnhS.cjs → text-truncate-BZdL1k5Z.cjs} +474 -83
- package/dist/{text-truncate-j6X3z7Pv.js → text-truncate-C17HHCR-.js} +405 -86
- package/dist/text-truncate-C17HHCR-.js.map +1 -0
- package/dist/{text-truncate-BGr7bB_8.d.ts → text-truncate-DW78lg4S.d.cts} +18 -3
- package/dist/text-truncate-DW78lg4S.d.cts.map +1 -0
- package/dist/{text-truncate-BGr7bB_8.d.cts → text-truncate-DW78lg4S.d.ts} +18 -3
- package/dist/text-truncate-DW78lg4S.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/field-sidebar-BXjvV7Cz.js.map +0 -1
- package/dist/field-sidebar-DWfJAJlx.d.ts.map +0 -1
- package/dist/field-sidebar-nwcE9LC4.d.cts.map +0 -1
- package/dist/key-pad-menu-BQunU20e.js.map +0 -1
- package/dist/key-pad-menu-BsgJMjD4.d.ts.map +0 -1
- package/dist/key-pad-menu-DfZbeXhG.d.cts.map +0 -1
- package/dist/text-truncate-BGr7bB_8.d.cts.map +0 -1
- package/dist/text-truncate-BGr7bB_8.d.ts.map +0 -1
- package/dist/text-truncate-j6X3z7Pv.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as PopoverContent$1, $n as OPT_TEXT_PRIMARY, $t as CompositeRow, A as FormRadioGroup$1, An as OPT_BADGE_YELLOW, At as DialogDescription$1, B as FormSwitch$1, Bn as OPT_FOCUS_VISIBLE, Bt as SelectPopover$1, Cn as OPT_ACTIVE_ITEM, Dn as OPT_BADGE_GREEN, Dt as ComboboxRoot$1, En as OPT_BADGE_BLUE, Et as ComboboxPopover$1, F as FormSelectItem, Ft as DialogHeading$1, G as useFormStore, Gn as OPT_SURFACE, Gt as TabPanel$1, H as FormTextarea, Hn as OPT_INPUT, Ht as SelectTrigger$1, I as FormSelectPopover, In as OPT_DOT_GREEN, It as DialogPanel$1, J as TagInput, Jn as OPT_TABLE_ROW_ACTIVE, Jt as DisclosureRoot$1, Kn as OPT_SURFACE_POPOVER, Kt as TabsRoot$1, Ln as OPT_DOT_RED, Lt as DialogRoot$1, Mn as OPT_DISCLOSURE_CONTENT, N as FormRoot$1, Nn as OPT_DISCLOSURE_TRIGGER, On as OPT_BADGE_NEUTRAL, P as FormSelect, Pn as OPT_DIVIDER, Qn as OPT_TEXT_LABEL, Qt as CompositeProvider, Rn as OPT_DOT_YELLOW, Rt as SelectItem$1, T as FormLabel$1, Tn as OPT_ANIMATE_ENTER_EXIT, Tt as ComboboxItem$1, Ut as Tab$1, Vt as SelectRoot$1, Wn as OPT_ITEM_BASE, Wt as TabList$1, Xn as OPT_TD_MUTED, Xt as Composite, Yn as OPT_TD, Yt as DisclosureTrigger$1, Zt as CompositeItem, _t as MenuSeparator$1, an as Alert, ar as Kbd, at as ToolbarContainer$1, bt as MenubarRoot$1, cn as EmptyState, ct as Tooltip$1, dt as MenuButtonArrow$1, er as OPT_TEXT_SECONDARY, et as PopoverRoot$1, ft as MenuItem$1, gt as MenuRoot$1, ht as MenuPopover$1, i as FieldToken, ir as _objectWithoutProperties, it as ToolbarButton$1, jn as OPT_BORDER, k as FormRadio$1, kn as OPT_BADGE_RED, l as OPT_UI_DEFAULT_LOCALE, ln as Button, lt as TooltipAnchor$1, m as FormCheckbox$1, mn as Skeleton, mt as MenuItemRadio$1, n as Highlight, nr as OPT_TH, o as Pagination, on as Spinner, or as cn, ot as ToolbarRoot$1, p as formatOptTime, pn as StatCard, pt as MenuItemCheckbox$1, qt as DisclosureContent$1, rn as Input, rr as _objectSpread2, s as Checkbox, sn as Badge, st as ToolbarSeparator$1, t as TextTruncate, tn as Meter$1, tr as OPT_TEXT_TERTIARY, tt as PopoverTrigger$1, ut as TooltipProvider$1, vt as MenuTrigger$1, w as FormInput$1, wt as ComboboxInput$1, xt as ComboboxEmpty, y as FormError$1, yt as MenubarContainer$1, z as FormSubmit$1, zn as OPT_FOCUS, zt as SelectLabel$1 } from "./text-truncate-C17HHCR-.js";
|
|
3
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { Fragment as Fragment$1, createContext, forwardRef, memo, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
@@ -253,7 +253,7 @@ function CommandPaletteTrigger({ commands, onSelect, labels }) {
|
|
|
253
253
|
}
|
|
254
254
|
//#endregion
|
|
255
255
|
//#region src/shells/dashboard-grid.tsx
|
|
256
|
-
const defaultLabels$
|
|
256
|
+
const defaultLabels$21 = { ariaLabel: "대시보드 통계" };
|
|
257
257
|
const MIN_DASHBOARD_COLUMNS = 1;
|
|
258
258
|
const MAX_DASHBOARD_COLUMNS = 12;
|
|
259
259
|
function normalizeDashboardColumns(columns) {
|
|
@@ -262,7 +262,7 @@ function normalizeDashboardColumns(columns) {
|
|
|
262
262
|
}
|
|
263
263
|
/** Renders the dashboard grid component. */
|
|
264
264
|
function DashboardGrid({ stats, columns = 3, labels: customLabels }) {
|
|
265
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
265
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$21), customLabels);
|
|
266
266
|
const columnCount = normalizeDashboardColumns(columns);
|
|
267
267
|
const rowStyle = { "--opt-dashboard-grid-columns": `repeat(${columnCount}, minmax(0, 1fr))` };
|
|
268
268
|
const rows = [];
|
|
@@ -290,13 +290,13 @@ function DashboardGrid({ stats, columns = 3, labels: customLabels }) {
|
|
|
290
290
|
}
|
|
291
291
|
//#endregion
|
|
292
292
|
//#region src/shells/search-combobox.tsx
|
|
293
|
-
const defaultLabels$
|
|
293
|
+
const defaultLabels$20 = {
|
|
294
294
|
noResults: "결과가 없습니다.",
|
|
295
295
|
loading: "Loading…"
|
|
296
296
|
};
|
|
297
297
|
/** Renders the search combobox component. */
|
|
298
298
|
function SearchCombobox({ items, placeholder = "검색...", label = "검색", onSelect, labels: customLabels, async: isAsync = false, onSearch, debounceMs = 300 }) {
|
|
299
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
299
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$20), customLabels);
|
|
300
300
|
const inputId = useId();
|
|
301
301
|
const [query, setQuery] = useState("");
|
|
302
302
|
const [asyncResults, setAsyncResults] = useState([]);
|
|
@@ -394,14 +394,14 @@ function SearchCombobox({ items, placeholder = "검색...", label = "검색", on
|
|
|
394
394
|
}
|
|
395
395
|
//#endregion
|
|
396
396
|
//#region src/shells/status-select.tsx
|
|
397
|
-
const defaultLabels$
|
|
397
|
+
const defaultLabels$19 = {
|
|
398
398
|
selectLabel: "상태",
|
|
399
399
|
emptyMessage: "사용 가능한 상태 옵션이 없습니다."
|
|
400
400
|
};
|
|
401
401
|
/** Renders the status select component. */
|
|
402
402
|
function StatusSelect({ options, value: controlledValue, onChange, label, labels: customLabels }) {
|
|
403
403
|
var _options$0$value, _options$;
|
|
404
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
404
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$19), customLabels);
|
|
405
405
|
const resolvedLabel = label !== null && label !== void 0 ? label : labels.selectLabel;
|
|
406
406
|
const [internalValue, setInternalValue] = useState((_options$0$value = (_options$ = options[0]) === null || _options$ === void 0 ? void 0 : _options$.value) !== null && _options$0$value !== void 0 ? _options$0$value : "");
|
|
407
407
|
const value = controlledValue !== null && controlledValue !== void 0 ? controlledValue : internalValue;
|
|
@@ -468,7 +468,7 @@ function StatusSelect({ options, value: controlledValue, onChange, label, labels
|
|
|
468
468
|
}
|
|
469
469
|
//#endregion
|
|
470
470
|
//#region src/shells/app-menubar.tsx
|
|
471
|
-
const defaultLabels$
|
|
471
|
+
const defaultLabels$18 = { ariaLabel: "Application menu" };
|
|
472
472
|
function MenuSection({ menu }) {
|
|
473
473
|
return /* @__PURE__ */ jsxs(MenuRoot$1, { children: [/* @__PURE__ */ jsxs(MenuTrigger$1, { children: [menu.label, /* @__PURE__ */ jsx(MenuButtonArrow$1, {})] }), /* @__PURE__ */ jsx(MenuPopover$1, { children: menu.items.map((item, i) => {
|
|
474
474
|
if (item.type === "separator") return /* @__PURE__ */ jsx(MenuSeparator$1, {}, `sep-${i}`);
|
|
@@ -512,7 +512,7 @@ function MenuSection({ menu }) {
|
|
|
512
512
|
}
|
|
513
513
|
/** Renders the app menubar component. */
|
|
514
514
|
function AppMenubar({ menus, labels: customLabels }) {
|
|
515
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
515
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$18), customLabels);
|
|
516
516
|
if (menus.length === 0) return null;
|
|
517
517
|
return /* @__PURE__ */ jsx(MenubarRoot$1, {
|
|
518
518
|
"data-opt-id": "BGKHW",
|
|
@@ -551,10 +551,10 @@ const sectionStyles = {
|
|
|
551
551
|
Templates: "text-text-tertiary"
|
|
552
552
|
};
|
|
553
553
|
const defaultSectionStyle = "text-text-secondary";
|
|
554
|
-
const defaultLabels$
|
|
554
|
+
const defaultLabels$17 = { ariaLabel: "문서 네비게이션" };
|
|
555
555
|
/** Renders the sidebar nav component. */
|
|
556
556
|
function SidebarNav({ items, labels: customLabels }) {
|
|
557
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
557
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$17), customLabels);
|
|
558
558
|
const pathname = usePathname();
|
|
559
559
|
const activeItem = items.find((item) => item.href === pathname);
|
|
560
560
|
const [activeId, setActiveId] = useState(activeItem ? domId(activeItem.id) : void 0);
|
|
@@ -602,7 +602,7 @@ function SidebarNav({ items, labels: customLabels }) {
|
|
|
602
602
|
}
|
|
603
603
|
//#endregion
|
|
604
604
|
//#region src/shells/editor-toolbar.tsx
|
|
605
|
-
const defaultLabels$
|
|
605
|
+
const defaultLabels$16 = { ariaLabel: "텍스트 편집기 툴바" };
|
|
606
606
|
function ToolbarButtonWithTooltip({ button, active, onAction }) {
|
|
607
607
|
return /* @__PURE__ */ jsxs(TooltipProvider$1, { children: [/* @__PURE__ */ jsx(TooltipAnchor$1, { children: /* @__PURE__ */ jsx(ToolbarButton$1, {
|
|
608
608
|
className: `text-text-primary data-[active-item]:bg-bg-subtle data-[focus-visible]:ring-ring rounded-md p-2 transition-colors outline-none data-[focus-visible]:ring-2 ${active ? "bg-bg-muted" : "hover:bg-bg-subtle"}`,
|
|
@@ -612,7 +612,7 @@ function ToolbarButtonWithTooltip({ button, active, onAction }) {
|
|
|
612
612
|
}
|
|
613
613
|
/** Renders the editor toolbar component. */
|
|
614
614
|
function EditorToolbar({ buttons, onAction, activeButtons = [], labels: customLabels }) {
|
|
615
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
615
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$16), customLabels);
|
|
616
616
|
const groups = [];
|
|
617
617
|
let current = [];
|
|
618
618
|
for (const btn of buttons) {
|
|
@@ -645,14 +645,14 @@ function EditorToolbar({ buttons, onAction, activeButtons = [], labels: customLa
|
|
|
645
645
|
}
|
|
646
646
|
//#endregion
|
|
647
647
|
//#region src/shells/content-tabs.tsx
|
|
648
|
-
const defaultLabels$
|
|
648
|
+
const defaultLabels$15 = {
|
|
649
649
|
ariaLabel: "콘텐츠 탭",
|
|
650
650
|
emptyMessage: "표시할 탭이 없습니다."
|
|
651
651
|
};
|
|
652
652
|
/** Renders the content tabs component. */
|
|
653
653
|
function ContentTabs({ tabs, defaultTabId, labels: customLabels }) {
|
|
654
654
|
var _tabs$, _tabs$find;
|
|
655
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
655
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$15), customLabels);
|
|
656
656
|
const [selectedTabId, setSelectedTabId] = useState(defaultTabId !== null && defaultTabId !== void 0 ? defaultTabId : (_tabs$ = tabs[0]) === null || _tabs$ === void 0 ? void 0 : _tabs$.id);
|
|
657
657
|
if (tabs.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
658
658
|
className: "text-text-secondary text-sm",
|
|
@@ -684,13 +684,13 @@ function ContentTabs({ tabs, defaultTabId, labels: customLabels }) {
|
|
|
684
684
|
}
|
|
685
685
|
//#endregion
|
|
686
686
|
//#region src/shells/faq-accordion.tsx
|
|
687
|
-
const defaultLabels$
|
|
687
|
+
const defaultLabels$14 = {
|
|
688
688
|
ariaLabel: "자주 묻는 질문",
|
|
689
689
|
emptyMessage: "등록된 FAQ가 없습니다."
|
|
690
690
|
};
|
|
691
691
|
/** Renders the faq accordion component. */
|
|
692
692
|
function FaqAccordion({ items, labels: customLabels }) {
|
|
693
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
693
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$14), customLabels);
|
|
694
694
|
if (items.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
695
695
|
className: "text-text-secondary text-sm",
|
|
696
696
|
"data-opt-id": "QRBHV",
|
|
@@ -730,14 +730,14 @@ function FaqAccordion({ items, labels: customLabels }) {
|
|
|
730
730
|
}
|
|
731
731
|
//#endregion
|
|
732
732
|
//#region src/shells/settings-form.tsx
|
|
733
|
-
const defaultLabels$
|
|
733
|
+
const defaultLabels$13 = {
|
|
734
734
|
formAriaLabel: "설정 폼",
|
|
735
735
|
submitButton: "저장",
|
|
736
736
|
successMessage: "설정이 저장되었습니다."
|
|
737
737
|
};
|
|
738
738
|
/** Renders the settings form component. */
|
|
739
739
|
function SettingsForm({ fields, onSubmit, labels: customLabels }) {
|
|
740
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
740
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$13), customLabels);
|
|
741
741
|
const [submitted, setSubmitted] = useState(false);
|
|
742
742
|
const defaultValues = {};
|
|
743
743
|
for (const field of fields) {
|
|
@@ -1063,7 +1063,7 @@ function ProjectSwitcher({ projects, value, onChange, placeholder = "프로젝
|
|
|
1063
1063
|
ProjectSwitcher.displayName = "ProjectSwitcher";
|
|
1064
1064
|
//#endregion
|
|
1065
1065
|
//#region src/shells/env-panel.tsx
|
|
1066
|
-
const defaultLabels$
|
|
1066
|
+
const defaultLabels$12 = {
|
|
1067
1067
|
varCount: (count) => `${count}개 변수`,
|
|
1068
1068
|
envVarsLabel: (env) => `${env} 환경 변수`,
|
|
1069
1069
|
secretBadge: "secret"
|
|
@@ -1075,7 +1075,7 @@ const envDot = {
|
|
|
1075
1075
|
};
|
|
1076
1076
|
/** Renders the env panel component. */
|
|
1077
1077
|
function EnvPanel({ groups, labels: customLabels }) {
|
|
1078
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
1078
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$12), customLabels);
|
|
1079
1079
|
return /* @__PURE__ */ jsx("div", {
|
|
1080
1080
|
className: `rounded-lg ${OPT_BORDER} divide-y ${OPT_DIVIDER} bg-surface`,
|
|
1081
1081
|
"data-opt-id": "ZBDWK",
|
|
@@ -1148,7 +1148,7 @@ function EnvPanel({ groups, labels: customLabels }) {
|
|
|
1148
1148
|
}
|
|
1149
1149
|
//#endregion
|
|
1150
1150
|
//#region src/shells/branch-select.tsx
|
|
1151
|
-
const defaultLabels$
|
|
1151
|
+
const defaultLabels$11 = {
|
|
1152
1152
|
selectLabel: "브랜치",
|
|
1153
1153
|
emptySelectionLabel: "선택...",
|
|
1154
1154
|
emptyMessage: "사용 가능한 브랜치가 없습니다.",
|
|
@@ -1157,7 +1157,7 @@ const defaultLabels$8 = {
|
|
|
1157
1157
|
/** Renders the branch select component. */
|
|
1158
1158
|
function BranchSelect({ branches, value: controlledValue, onChange, label, labels: customLabels }) {
|
|
1159
1159
|
var _ref, _defaultBranch$name, _branches$, _selected$name;
|
|
1160
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
1160
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$11), customLabels);
|
|
1161
1161
|
const resolvedLabel = label !== null && label !== void 0 ? label : labels.selectLabel;
|
|
1162
1162
|
const defaultBranch = branches.find((b) => b.isDefault);
|
|
1163
1163
|
const [internalValue, setInternalValue] = useState((_ref = (_defaultBranch$name = defaultBranch === null || defaultBranch === void 0 ? void 0 : defaultBranch.name) !== null && _defaultBranch$name !== void 0 ? _defaultBranch$name : (_branches$ = branches[0]) === null || _branches$ === void 0 ? void 0 : _branches$.name) !== null && _ref !== void 0 ? _ref : "");
|
|
@@ -1266,7 +1266,7 @@ function BranchSelect({ branches, value: controlledValue, onChange, label, label
|
|
|
1266
1266
|
BranchSelect.displayName = "BranchSelect";
|
|
1267
1267
|
//#endregion
|
|
1268
1268
|
//#region src/shells/domain-table.tsx
|
|
1269
|
-
const defaultLabels$
|
|
1269
|
+
const defaultLabels$10 = {
|
|
1270
1270
|
domain: "Domain",
|
|
1271
1271
|
status: "Status",
|
|
1272
1272
|
ssl: "SSL",
|
|
@@ -1296,7 +1296,7 @@ const sslLabel = {
|
|
|
1296
1296
|
};
|
|
1297
1297
|
/** Renders the domain table component. */
|
|
1298
1298
|
function DomainTable({ domains, title = "도메인", labels: customLabels }) {
|
|
1299
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
1299
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$10), customLabels);
|
|
1300
1300
|
if (domains.length === 0) return /* @__PURE__ */ jsxs("div", {
|
|
1301
1301
|
className: "gap-group flex flex-col",
|
|
1302
1302
|
"data-opt-id": "A7SRM",
|
|
@@ -1902,7 +1902,7 @@ function NotificationToast({ toast, onDismiss, defaultDuration = 5e3 }) {
|
|
|
1902
1902
|
}
|
|
1903
1903
|
//#endregion
|
|
1904
1904
|
//#region src/shells/failure-list.tsx
|
|
1905
|
-
const defaultLabels$
|
|
1905
|
+
const defaultLabels$9 = {
|
|
1906
1906
|
title: "최근 실패",
|
|
1907
1907
|
emptyMessage: "실패 항목이 없습니다",
|
|
1908
1908
|
moreItems: "{count}개 더 보기",
|
|
@@ -2001,20 +2001,20 @@ function FailureItemRow({ failure, isLast, onFailureClick, renderActions, merged
|
|
|
2001
2001
|
function FailureList({ failures, title, maxItems, grouped = false, onFailureClick, onShowMore, labels: customLabels, locale = "ko-KR", loading = false, renderActions, className }) {
|
|
2002
2002
|
var _customLabels$timeAgo, _customLabels$timeAgo2, _customLabels$timeAgo3, _customLabels$timeAgo4, _customLabels$timeAgo5, _customLabels$timeAgo6, _customLabels$timeAgo7, _customLabels$timeAgo8, _customLabels$severit, _customLabels$severit2, _customLabels$severit3, _customLabels$severit4, _customLabels$severit5, _customLabels$severit6, _customLabels$title, _customLabels$emptyMe, _customLabels$moreIte;
|
|
2003
2003
|
const mergedTimeAgo = {
|
|
2004
|
-
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$
|
|
2005
|
-
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$
|
|
2006
|
-
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$
|
|
2007
|
-
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$
|
|
2004
|
+
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$9.timeAgo.justNow,
|
|
2005
|
+
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$9.timeAgo.minutesAgo,
|
|
2006
|
+
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$9.timeAgo.hoursAgo,
|
|
2007
|
+
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$9.timeAgo.daysAgo
|
|
2008
2008
|
};
|
|
2009
2009
|
const mergedSeverityLabels = {
|
|
2010
|
-
critical: (_customLabels$severit = customLabels === null || customLabels === void 0 || (_customLabels$severit2 = customLabels.severityLabels) === null || _customLabels$severit2 === void 0 ? void 0 : _customLabels$severit2.critical) !== null && _customLabels$severit !== void 0 ? _customLabels$severit : defaultLabels$
|
|
2011
|
-
error: (_customLabels$severit3 = customLabels === null || customLabels === void 0 || (_customLabels$severit4 = customLabels.severityLabels) === null || _customLabels$severit4 === void 0 ? void 0 : _customLabels$severit4.error) !== null && _customLabels$severit3 !== void 0 ? _customLabels$severit3 : defaultLabels$
|
|
2012
|
-
warning: (_customLabels$severit5 = customLabels === null || customLabels === void 0 || (_customLabels$severit6 = customLabels.severityLabels) === null || _customLabels$severit6 === void 0 ? void 0 : _customLabels$severit6.warning) !== null && _customLabels$severit5 !== void 0 ? _customLabels$severit5 : defaultLabels$
|
|
2010
|
+
critical: (_customLabels$severit = customLabels === null || customLabels === void 0 || (_customLabels$severit2 = customLabels.severityLabels) === null || _customLabels$severit2 === void 0 ? void 0 : _customLabels$severit2.critical) !== null && _customLabels$severit !== void 0 ? _customLabels$severit : defaultLabels$9.severityLabels.critical,
|
|
2011
|
+
error: (_customLabels$severit3 = customLabels === null || customLabels === void 0 || (_customLabels$severit4 = customLabels.severityLabels) === null || _customLabels$severit4 === void 0 ? void 0 : _customLabels$severit4.error) !== null && _customLabels$severit3 !== void 0 ? _customLabels$severit3 : defaultLabels$9.severityLabels.error,
|
|
2012
|
+
warning: (_customLabels$severit5 = customLabels === null || customLabels === void 0 || (_customLabels$severit6 = customLabels.severityLabels) === null || _customLabels$severit6 === void 0 ? void 0 : _customLabels$severit6.warning) !== null && _customLabels$severit5 !== void 0 ? _customLabels$severit5 : defaultLabels$9.severityLabels.warning
|
|
2013
2013
|
};
|
|
2014
2014
|
const labels = {
|
|
2015
|
-
title: (_customLabels$title = customLabels === null || customLabels === void 0 ? void 0 : customLabels.title) !== null && _customLabels$title !== void 0 ? _customLabels$title : defaultLabels$
|
|
2016
|
-
emptyMessage: (_customLabels$emptyMe = customLabels === null || customLabels === void 0 ? void 0 : customLabels.emptyMessage) !== null && _customLabels$emptyMe !== void 0 ? _customLabels$emptyMe : defaultLabels$
|
|
2017
|
-
moreItems: (_customLabels$moreIte = customLabels === null || customLabels === void 0 ? void 0 : customLabels.moreItems) !== null && _customLabels$moreIte !== void 0 ? _customLabels$moreIte : defaultLabels$
|
|
2015
|
+
title: (_customLabels$title = customLabels === null || customLabels === void 0 ? void 0 : customLabels.title) !== null && _customLabels$title !== void 0 ? _customLabels$title : defaultLabels$9.title,
|
|
2016
|
+
emptyMessage: (_customLabels$emptyMe = customLabels === null || customLabels === void 0 ? void 0 : customLabels.emptyMessage) !== null && _customLabels$emptyMe !== void 0 ? _customLabels$emptyMe : defaultLabels$9.emptyMessage,
|
|
2017
|
+
moreItems: (_customLabels$moreIte = customLabels === null || customLabels === void 0 ? void 0 : customLabels.moreItems) !== null && _customLabels$moreIte !== void 0 ? _customLabels$moreIte : defaultLabels$9.moreItems
|
|
2018
2018
|
};
|
|
2019
2019
|
const displayTitle = title !== null && title !== void 0 ? title : labels.title;
|
|
2020
2020
|
const allItems = maxItems ? failures.slice(0, maxItems) : failures;
|
|
@@ -2090,7 +2090,7 @@ function renderGrouped(items, remainingCount, rowProps, labels, onShowMore) {
|
|
|
2090
2090
|
}
|
|
2091
2091
|
//#endregion
|
|
2092
2092
|
//#region src/shells/key-value-editor.tsx
|
|
2093
|
-
const defaultLabels$
|
|
2093
|
+
const defaultLabels$8 = {
|
|
2094
2094
|
keyPlaceholder: "키",
|
|
2095
2095
|
valuePlaceholder: "값",
|
|
2096
2096
|
addButton: "추가",
|
|
@@ -2104,7 +2104,7 @@ function generateId() {
|
|
|
2104
2104
|
}
|
|
2105
2105
|
/** Renders the key value editor component. */
|
|
2106
2106
|
function KeyValueEditor({ value: controlledValue, defaultValue, onChange, showSecretToggle = false, maxEntries, readOnly = false, labels: customLabels, renderActions, validateKey, className }) {
|
|
2107
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
2107
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$8), customLabels);
|
|
2108
2108
|
const [internalEntries, setInternalEntries] = useState(() => defaultValue !== null && defaultValue !== void 0 ? defaultValue : []);
|
|
2109
2109
|
const entries = controlledValue !== null && controlledValue !== void 0 ? controlledValue : internalEntries;
|
|
2110
2110
|
const keyInputRef = useRef(null);
|
|
@@ -2400,6 +2400,555 @@ function WorkflowCanvas({ steps, connections = [], rows = 9, cols = 9, cellSize
|
|
|
2400
2400
|
}
|
|
2401
2401
|
WorkflowCanvas.displayName = "WorkflowCanvas";
|
|
2402
2402
|
//#endregion
|
|
2403
|
+
//#region src/shells/event-timeline.tsx
|
|
2404
|
+
const defaultLabels$7 = {
|
|
2405
|
+
emptyTitle: "No events yet",
|
|
2406
|
+
emptyDescription: "Events appear here as soon as they arrive.",
|
|
2407
|
+
expand: "Show properties",
|
|
2408
|
+
collapse: "Hide properties",
|
|
2409
|
+
loadMore: "Load more",
|
|
2410
|
+
gap: (duration) => `+${duration}`,
|
|
2411
|
+
properties: "Event properties",
|
|
2412
|
+
openGroup: (title) => `Open ${title}`
|
|
2413
|
+
};
|
|
2414
|
+
/**
|
|
2415
|
+
* A line of text and the time it happened have to read as one row. Past about
|
|
2416
|
+
* this width the eye stops connecting them, so the rail is capped rather than
|
|
2417
|
+
* stretched to whatever the page allows. Override with `className` where a
|
|
2418
|
+
* layout genuinely needs the full width.
|
|
2419
|
+
*/
|
|
2420
|
+
const TIMELINE_WIDTH = "max-w-5xl";
|
|
2421
|
+
const toneDot = {
|
|
2422
|
+
default: "bg-text-tertiary",
|
|
2423
|
+
accent: "bg-accent",
|
|
2424
|
+
success: "bg-success",
|
|
2425
|
+
warning: "bg-warning",
|
|
2426
|
+
danger: "bg-danger"
|
|
2427
|
+
};
|
|
2428
|
+
function toMillis(timestamp) {
|
|
2429
|
+
const parsed = Date.parse(timestamp);
|
|
2430
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
2431
|
+
}
|
|
2432
|
+
function stringifyValue(value) {
|
|
2433
|
+
if (value === null || value === void 0) return "—";
|
|
2434
|
+
if (typeof value === "string") return value;
|
|
2435
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
2436
|
+
return JSON.stringify(value);
|
|
2437
|
+
}
|
|
2438
|
+
function PropertyTable({ properties, ariaLabel }) {
|
|
2439
|
+
const entries = Object.entries(properties);
|
|
2440
|
+
if (entries.length === 0) return null;
|
|
2441
|
+
return /* @__PURE__ */ jsx("dl", {
|
|
2442
|
+
className: cn(OPT_BORDER, "gap-element bg-bg-subtle mt-2 grid grid-cols-1 rounded-lg p-2.5 sm:grid-cols-2"),
|
|
2443
|
+
"aria-label": ariaLabel,
|
|
2444
|
+
children: entries.map(([key, value]) => /* @__PURE__ */ jsxs("div", {
|
|
2445
|
+
className: "flex min-w-0 flex-col",
|
|
2446
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
2447
|
+
className: cn(OPT_TEXT_TERTIARY, "truncate text-xs"),
|
|
2448
|
+
children: key
|
|
2449
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
2450
|
+
className: cn(OPT_TEXT_PRIMARY, "truncate text-xs"),
|
|
2451
|
+
children: stringifyValue(value)
|
|
2452
|
+
})]
|
|
2453
|
+
}, key))
|
|
2454
|
+
});
|
|
2455
|
+
}
|
|
2456
|
+
function TimelineRow({ item, gapLabel, labels, onItemSelect, isLast }) {
|
|
2457
|
+
var _item$tone, _item$content, _item$properties;
|
|
2458
|
+
const [open, setOpen] = useState(false);
|
|
2459
|
+
const expandable = Boolean(item.content || item.properties);
|
|
2460
|
+
const toggle = useCallback(() => setOpen((value) => !value), []);
|
|
2461
|
+
const headline = /* @__PURE__ */ jsx("span", {
|
|
2462
|
+
className: cn(OPT_TEXT_PRIMARY, "truncate text-sm font-medium"),
|
|
2463
|
+
children: item.name
|
|
2464
|
+
});
|
|
2465
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
2466
|
+
className: "relative flex gap-3 pb-4 last:pb-0",
|
|
2467
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
2468
|
+
className: "flex shrink-0 flex-col items-center",
|
|
2469
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2470
|
+
className: cn("mt-1.5 size-2 shrink-0 rounded-full", toneDot[(_item$tone = item.tone) !== null && _item$tone !== void 0 ? _item$tone : "default"]),
|
|
2471
|
+
"aria-hidden": "true"
|
|
2472
|
+
}), !isLast && /* @__PURE__ */ jsx("span", {
|
|
2473
|
+
className: "bg-border mt-1 w-px grow",
|
|
2474
|
+
"aria-hidden": "true"
|
|
2475
|
+
})]
|
|
2476
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
2477
|
+
className: "flex min-w-0 grow flex-col",
|
|
2478
|
+
children: [
|
|
2479
|
+
gapLabel && /* @__PURE__ */ jsx("span", {
|
|
2480
|
+
className: cn("text-text-tertiary", "mb-1 text-xs tabular-nums"),
|
|
2481
|
+
children: labels.gap(gapLabel)
|
|
2482
|
+
}),
|
|
2483
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2484
|
+
className: "flex min-w-0 items-baseline gap-2",
|
|
2485
|
+
children: [
|
|
2486
|
+
item.icon && /* @__PURE__ */ jsx("span", {
|
|
2487
|
+
className: "text-text-tertiary",
|
|
2488
|
+
"aria-hidden": "true",
|
|
2489
|
+
children: item.icon
|
|
2490
|
+
}),
|
|
2491
|
+
onItemSelect ? /* @__PURE__ */ jsx("button", {
|
|
2492
|
+
type: "button",
|
|
2493
|
+
onClick: () => onItemSelect(item),
|
|
2494
|
+
className: cn(OPT_FOCUS_VISIBLE, "hover:text-accent min-w-0 truncate rounded text-left"),
|
|
2495
|
+
children: headline
|
|
2496
|
+
}) : headline,
|
|
2497
|
+
/* @__PURE__ */ jsx("time", {
|
|
2498
|
+
dateTime: item.timestamp,
|
|
2499
|
+
className: cn(OPT_TEXT_TERTIARY, "ml-auto shrink-0 text-xs tabular-nums"),
|
|
2500
|
+
children: formatOptTime(item.timestamp)
|
|
2501
|
+
})
|
|
2502
|
+
]
|
|
2503
|
+
}),
|
|
2504
|
+
item.detail && /* @__PURE__ */ jsx("span", {
|
|
2505
|
+
className: cn("text-text-secondary", "truncate text-xs"),
|
|
2506
|
+
children: item.detail
|
|
2507
|
+
}),
|
|
2508
|
+
expandable && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("button", {
|
|
2509
|
+
type: "button",
|
|
2510
|
+
onClick: toggle,
|
|
2511
|
+
"aria-expanded": open,
|
|
2512
|
+
className: cn("outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset", "text-text-tertiary", "hover:text-text-primary mt-1 flex w-fit items-center gap-1 rounded text-xs"),
|
|
2513
|
+
children: [open ? /* @__PURE__ */ jsx(ChevronDown, {
|
|
2514
|
+
className: "size-3",
|
|
2515
|
+
"aria-hidden": "true"
|
|
2516
|
+
}) : /* @__PURE__ */ jsx(ChevronRight, {
|
|
2517
|
+
className: "size-3",
|
|
2518
|
+
"aria-hidden": "true"
|
|
2519
|
+
}), open ? labels.collapse : labels.expand]
|
|
2520
|
+
}), open && ((_item$content = item.content) !== null && _item$content !== void 0 ? _item$content : /* @__PURE__ */ jsx(PropertyTable, {
|
|
2521
|
+
properties: (_item$properties = item.properties) !== null && _item$properties !== void 0 ? _item$properties : {},
|
|
2522
|
+
ariaLabel: labels.properties
|
|
2523
|
+
}))] })
|
|
2524
|
+
]
|
|
2525
|
+
})]
|
|
2526
|
+
});
|
|
2527
|
+
}
|
|
2528
|
+
/** Builds the gap label for each row, given the reading order. */
|
|
2529
|
+
function useGapLabels(items, showGaps, order, minGapMs, locale) {
|
|
2530
|
+
return useMemo(() => {
|
|
2531
|
+
if (!showGaps) return items.map(() => null);
|
|
2532
|
+
return items.map((item, index) => {
|
|
2533
|
+
const neighbour = order === "desc" ? items[index + 1] : items[index - 1];
|
|
2534
|
+
if (!neighbour) return null;
|
|
2535
|
+
const delta = Math.abs(toMillis(item.timestamp) - toMillis(neighbour.timestamp));
|
|
2536
|
+
if (delta < minGapMs) return null;
|
|
2537
|
+
return formatDuration(delta, locale);
|
|
2538
|
+
});
|
|
2539
|
+
}, [
|
|
2540
|
+
items,
|
|
2541
|
+
showGaps,
|
|
2542
|
+
order,
|
|
2543
|
+
minGapMs,
|
|
2544
|
+
locale
|
|
2545
|
+
]);
|
|
2546
|
+
}
|
|
2547
|
+
function TimelineList({ items, showGaps, order, minGapMs, locale, labels, onItemSelect }) {
|
|
2548
|
+
const gaps = useGapLabels(items, showGaps, order, minGapMs, locale);
|
|
2549
|
+
return /* @__PURE__ */ jsx("ol", {
|
|
2550
|
+
className: "flex flex-col",
|
|
2551
|
+
children: items.map((item, index) => {
|
|
2552
|
+
var _gaps$index;
|
|
2553
|
+
return /* @__PURE__ */ jsx(TimelineRow, {
|
|
2554
|
+
item,
|
|
2555
|
+
gapLabel: (_gaps$index = gaps[index]) !== null && _gaps$index !== void 0 ? _gaps$index : null,
|
|
2556
|
+
labels,
|
|
2557
|
+
onItemSelect,
|
|
2558
|
+
isLast: index === items.length - 1
|
|
2559
|
+
}, item.id);
|
|
2560
|
+
})
|
|
2561
|
+
});
|
|
2562
|
+
}
|
|
2563
|
+
function GroupBlock({ group, showGaps, order, minGapMs, locale, labels, onItemSelect }) {
|
|
2564
|
+
var _group$defaultOpen;
|
|
2565
|
+
const [open, setOpen] = useState((_group$defaultOpen = group.defaultOpen) !== null && _group$defaultOpen !== void 0 ? _group$defaultOpen : true);
|
|
2566
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
2567
|
+
className: cn(OPT_BORDER, "rounded-xl"),
|
|
2568
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
2569
|
+
className: "flex items-center gap-2 px-3 py-2",
|
|
2570
|
+
children: [
|
|
2571
|
+
/* @__PURE__ */ jsxs("button", {
|
|
2572
|
+
type: "button",
|
|
2573
|
+
onClick: () => setOpen((value) => !value),
|
|
2574
|
+
"aria-expanded": open,
|
|
2575
|
+
className: cn(OPT_FOCUS_VISIBLE, "flex min-w-0 grow items-center gap-2 rounded text-left"),
|
|
2576
|
+
children: [
|
|
2577
|
+
open ? /* @__PURE__ */ jsx(ChevronDown, {
|
|
2578
|
+
className: cn(OPT_TEXT_TERTIARY, "size-4 shrink-0"),
|
|
2579
|
+
"aria-hidden": "true"
|
|
2580
|
+
}) : /* @__PURE__ */ jsx(ChevronRight, {
|
|
2581
|
+
className: cn(OPT_TEXT_TERTIARY, "size-4 shrink-0"),
|
|
2582
|
+
"aria-hidden": "true"
|
|
2583
|
+
}),
|
|
2584
|
+
/* @__PURE__ */ jsx("span", {
|
|
2585
|
+
className: cn(OPT_TEXT_PRIMARY, "truncate text-sm font-medium"),
|
|
2586
|
+
children: group.title
|
|
2587
|
+
}),
|
|
2588
|
+
/* @__PURE__ */ jsx(Badge, {
|
|
2589
|
+
size: "sm",
|
|
2590
|
+
variant: "default",
|
|
2591
|
+
className: "shrink-0",
|
|
2592
|
+
children: group.items.length
|
|
2593
|
+
})
|
|
2594
|
+
]
|
|
2595
|
+
}),
|
|
2596
|
+
group.meta && /* @__PURE__ */ jsx("span", {
|
|
2597
|
+
className: cn("text-text-tertiary", "shrink-0 text-xs"),
|
|
2598
|
+
children: group.meta
|
|
2599
|
+
}),
|
|
2600
|
+
group.href && /* @__PURE__ */ jsx("a", {
|
|
2601
|
+
href: group.href,
|
|
2602
|
+
className: cn("outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset", "text-accent shrink-0 rounded text-xs"),
|
|
2603
|
+
children: labels.openGroup(typeof group.title === "string" ? group.title : group.id)
|
|
2604
|
+
})
|
|
2605
|
+
]
|
|
2606
|
+
}), open && /* @__PURE__ */ jsx("div", {
|
|
2607
|
+
className: "border-border-subtle border-t px-3 py-3",
|
|
2608
|
+
children: /* @__PURE__ */ jsx(TimelineList, {
|
|
2609
|
+
items: group.items,
|
|
2610
|
+
showGaps,
|
|
2611
|
+
order,
|
|
2612
|
+
minGapMs,
|
|
2613
|
+
locale,
|
|
2614
|
+
labels,
|
|
2615
|
+
onItemSelect
|
|
2616
|
+
})
|
|
2617
|
+
})]
|
|
2618
|
+
});
|
|
2619
|
+
}
|
|
2620
|
+
/**
|
|
2621
|
+
* EventTimeline — a sequence of events, read as a sequence.
|
|
2622
|
+
*
|
|
2623
|
+
* A table of events answers "what happened" and hides "how it went": the rows
|
|
2624
|
+
* are evenly spaced no matter whether they were two seconds or two hours
|
|
2625
|
+
* apart, and the payload that would explain a row lives in a column nobody
|
|
2626
|
+
* widened. This renders the same data as an ordered rail, labels the elapsed
|
|
2627
|
+
* time between adjacent events, and opens each payload in place. Grouping by
|
|
2628
|
+
* session restores the boundary that makes a history legible.
|
|
2629
|
+
*
|
|
2630
|
+
* @example
|
|
2631
|
+
* ```tsx
|
|
2632
|
+
* <EventTimeline
|
|
2633
|
+
* groups={sessions.map((session) => ({
|
|
2634
|
+
* id: session.id,
|
|
2635
|
+
* title: session.entryPath,
|
|
2636
|
+
* meta: `${session.duration} · ${session.events} events`,
|
|
2637
|
+
* items: session.events,
|
|
2638
|
+
* }))}
|
|
2639
|
+
* showGaps
|
|
2640
|
+
* />
|
|
2641
|
+
* ```
|
|
2642
|
+
*/
|
|
2643
|
+
function EventTimeline({ items, groups, showGaps = true, order = "desc", minGapMs = 1e3, loading = false, hasMore = false, onLoadMore, onItemSelect, locale = OPT_UI_DEFAULT_LOCALE, labels: customLabels, className }) {
|
|
2644
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$7), customLabels);
|
|
2645
|
+
const flatItems = items !== null && items !== void 0 ? items : [];
|
|
2646
|
+
const hasContent = groups ? groups.length > 0 : flatItems.length > 0;
|
|
2647
|
+
if (loading) return /* @__PURE__ */ jsx("div", {
|
|
2648
|
+
className: cn(TIMELINE_WIDTH, "flex flex-col gap-3", className),
|
|
2649
|
+
"data-opt-id": "H6S6T",
|
|
2650
|
+
"data-opt-slug": "event-timeline.EventTimeline",
|
|
2651
|
+
children: Array.from({ length: 5 }).map((_, index) => /* @__PURE__ */ jsxs("div", {
|
|
2652
|
+
className: "flex gap-3",
|
|
2653
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "mt-1.5 size-2 rounded-full" }), /* @__PURE__ */ jsxs("div", {
|
|
2654
|
+
className: "flex grow flex-col gap-1.5",
|
|
2655
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-40" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-64" })]
|
|
2656
|
+
})]
|
|
2657
|
+
}, index))
|
|
2658
|
+
});
|
|
2659
|
+
if (!hasContent) return /* @__PURE__ */ jsx("div", {
|
|
2660
|
+
className: cn(TIMELINE_WIDTH, className),
|
|
2661
|
+
"data-opt-id": "H6S6T",
|
|
2662
|
+
"data-opt-slug": "event-timeline.EventTimeline",
|
|
2663
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
2664
|
+
title: labels.emptyTitle,
|
|
2665
|
+
description: labels.emptyDescription,
|
|
2666
|
+
tone: "subdued",
|
|
2667
|
+
hasBorder: true
|
|
2668
|
+
})
|
|
2669
|
+
});
|
|
2670
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2671
|
+
className: cn(TIMELINE_WIDTH, "flex flex-col gap-3", className),
|
|
2672
|
+
"data-opt-id": "H6S6T",
|
|
2673
|
+
"data-opt-slug": "event-timeline.EventTimeline",
|
|
2674
|
+
children: [groups ? groups.map((group) => /* @__PURE__ */ jsx(GroupBlock, {
|
|
2675
|
+
group,
|
|
2676
|
+
showGaps,
|
|
2677
|
+
order,
|
|
2678
|
+
minGapMs,
|
|
2679
|
+
locale,
|
|
2680
|
+
labels,
|
|
2681
|
+
onItemSelect
|
|
2682
|
+
}, group.id)) : /* @__PURE__ */ jsx(TimelineList, {
|
|
2683
|
+
items: flatItems,
|
|
2684
|
+
showGaps,
|
|
2685
|
+
order,
|
|
2686
|
+
minGapMs,
|
|
2687
|
+
locale,
|
|
2688
|
+
labels,
|
|
2689
|
+
onItemSelect
|
|
2690
|
+
}), hasMore && onLoadMore && /* @__PURE__ */ jsx("div", {
|
|
2691
|
+
className: "flex justify-center pt-1",
|
|
2692
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
2693
|
+
variant: "secondary",
|
|
2694
|
+
size: "sm",
|
|
2695
|
+
onClick: onLoadMore,
|
|
2696
|
+
children: labels.loadMore
|
|
2697
|
+
})
|
|
2698
|
+
})]
|
|
2699
|
+
});
|
|
2700
|
+
}
|
|
2701
|
+
EventTimeline.displayName = "EventTimeline";
|
|
2702
|
+
//#endregion
|
|
2703
|
+
//#region src/shells/score-breakdown.tsx
|
|
2704
|
+
const defaultLabels$6 = {
|
|
2705
|
+
title: "Score",
|
|
2706
|
+
outOf: (max) => `out of ${max}`,
|
|
2707
|
+
weight: (percent) => `${percent} of total`,
|
|
2708
|
+
empty: "Not enough activity to score."
|
|
2709
|
+
};
|
|
2710
|
+
const toneText = {
|
|
2711
|
+
default: "text-text-primary",
|
|
2712
|
+
success: "text-success-fg",
|
|
2713
|
+
warning: "text-warning-fg",
|
|
2714
|
+
error: "text-danger-fg"
|
|
2715
|
+
};
|
|
2716
|
+
const toneMeter = {
|
|
2717
|
+
default: "default",
|
|
2718
|
+
success: "success",
|
|
2719
|
+
warning: "warning",
|
|
2720
|
+
error: "error"
|
|
2721
|
+
};
|
|
2722
|
+
/** Picks the band a score falls into — the highest `min` at or below it. */
|
|
2723
|
+
function resolveBand(score, bands) {
|
|
2724
|
+
return bands.filter((band) => score >= band.min).sort((left, right) => right.min - left.min)[0];
|
|
2725
|
+
}
|
|
2726
|
+
/**
|
|
2727
|
+
* ScoreBreakdown — a composite score you can argue with.
|
|
2728
|
+
*
|
|
2729
|
+
* Engagement, health and risk scores all collapse several signals into one
|
|
2730
|
+
* number, and the number alone tells nobody what to do about it. Showing the
|
|
2731
|
+
* axes and their weights beside the headline turns "43" into "recent, but
|
|
2732
|
+
* shallow", which is a finding rather than a verdict.
|
|
2733
|
+
*/
|
|
2734
|
+
function ScoreBreakdown({ score, max = 100, axes, bands = [], formula, loading = false, labels: customLabels, className }) {
|
|
2735
|
+
var _band$tone;
|
|
2736
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$6), customLabels);
|
|
2737
|
+
const band = resolveBand(score, bands);
|
|
2738
|
+
const tone = (_band$tone = band === null || band === void 0 ? void 0 : band.tone) !== null && _band$tone !== void 0 ? _band$tone : "default";
|
|
2739
|
+
if (loading) return /* @__PURE__ */ jsxs("section", {
|
|
2740
|
+
className: cn(OPT_BORDER, "flex flex-col gap-3 rounded-xl p-4", className),
|
|
2741
|
+
"data-opt-id": "DYZSG",
|
|
2742
|
+
"data-opt-slug": "score-breakdown.ScoreBreakdown",
|
|
2743
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-9 w-24" }), Array.from({ length: 4 }).map((_, index) => /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-full" }, index))]
|
|
2744
|
+
});
|
|
2745
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
2746
|
+
className: cn(OPT_BORDER, "flex flex-col gap-4 rounded-xl p-4", className),
|
|
2747
|
+
"data-opt-id": "DYZSG",
|
|
2748
|
+
"data-opt-slug": "score-breakdown.ScoreBreakdown",
|
|
2749
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
2750
|
+
className: "flex flex-col gap-1",
|
|
2751
|
+
children: [
|
|
2752
|
+
/* @__PURE__ */ jsx("span", {
|
|
2753
|
+
className: cn(OPT_TEXT_SECONDARY, "text-sm"),
|
|
2754
|
+
children: labels.title
|
|
2755
|
+
}),
|
|
2756
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2757
|
+
className: "flex items-baseline gap-2",
|
|
2758
|
+
children: [
|
|
2759
|
+
/* @__PURE__ */ jsx("span", {
|
|
2760
|
+
className: cn("text-3xl font-bold tabular-nums", toneText[tone]),
|
|
2761
|
+
children: score
|
|
2762
|
+
}),
|
|
2763
|
+
/* @__PURE__ */ jsx("span", {
|
|
2764
|
+
className: cn(OPT_TEXT_TERTIARY, "text-xs"),
|
|
2765
|
+
children: labels.outOf(max)
|
|
2766
|
+
}),
|
|
2767
|
+
band && /* @__PURE__ */ jsx("span", {
|
|
2768
|
+
className: cn("ml-1 text-sm font-medium", toneText[tone]),
|
|
2769
|
+
children: band.label
|
|
2770
|
+
})
|
|
2771
|
+
]
|
|
2772
|
+
}),
|
|
2773
|
+
formula && /* @__PURE__ */ jsx("p", {
|
|
2774
|
+
className: cn("text-text-tertiary", "text-xs"),
|
|
2775
|
+
children: formula
|
|
2776
|
+
})
|
|
2777
|
+
]
|
|
2778
|
+
}), axes.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
2779
|
+
className: cn(OPT_TEXT_SECONDARY, "text-sm"),
|
|
2780
|
+
children: labels.empty
|
|
2781
|
+
}) : /* @__PURE__ */ jsx("dl", {
|
|
2782
|
+
className: "flex flex-col gap-3",
|
|
2783
|
+
children: axes.map((axis) => /* @__PURE__ */ jsxs("div", {
|
|
2784
|
+
className: "flex flex-col gap-1",
|
|
2785
|
+
children: [
|
|
2786
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2787
|
+
className: "flex items-baseline justify-between gap-2",
|
|
2788
|
+
children: [/* @__PURE__ */ jsxs("dt", {
|
|
2789
|
+
className: cn(OPT_TEXT_PRIMARY, "text-sm"),
|
|
2790
|
+
title: axis.hint,
|
|
2791
|
+
children: [axis.label, axis.weight !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
2792
|
+
className: cn("text-text-tertiary", "ml-1.5 text-xs"),
|
|
2793
|
+
children: labels.weight(`${Math.round(axis.weight * 100)}%`)
|
|
2794
|
+
})]
|
|
2795
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
2796
|
+
className: cn(OPT_TEXT_SECONDARY, "text-sm font-medium tabular-nums"),
|
|
2797
|
+
children: Math.round(axis.value)
|
|
2798
|
+
})]
|
|
2799
|
+
}),
|
|
2800
|
+
/* @__PURE__ */ jsx(Meter$1, {
|
|
2801
|
+
value: axis.value,
|
|
2802
|
+
max,
|
|
2803
|
+
size: "sm",
|
|
2804
|
+
variant: toneMeter[tone],
|
|
2805
|
+
"aria-label": axis.label
|
|
2806
|
+
}),
|
|
2807
|
+
axis.hint && /* @__PURE__ */ jsx("p", {
|
|
2808
|
+
className: cn("text-text-tertiary", "text-xs"),
|
|
2809
|
+
children: axis.hint
|
|
2810
|
+
})
|
|
2811
|
+
]
|
|
2812
|
+
}, axis.id))
|
|
2813
|
+
})]
|
|
2814
|
+
});
|
|
2815
|
+
}
|
|
2816
|
+
ScoreBreakdown.displayName = "ScoreBreakdown";
|
|
2817
|
+
//#endregion
|
|
2818
|
+
//#region src/shells/flyout.tsx
|
|
2819
|
+
const defaultLabels$5 = { close: "Close panel" };
|
|
2820
|
+
const sizeClass = {
|
|
2821
|
+
sm: "sm:w-[22rem]",
|
|
2822
|
+
md: "sm:w-[30rem]",
|
|
2823
|
+
lg: "sm:w-[42rem]"
|
|
2824
|
+
};
|
|
2825
|
+
/**
|
|
2826
|
+
* Flyout — a detail panel that does not take the page away.
|
|
2827
|
+
*
|
|
2828
|
+
* Navigating from a list to a record and back costs the reader their scroll
|
|
2829
|
+
* position, their filters and their place in the scan. A flyout keeps the list
|
|
2830
|
+
* on screen and shows the record beside it, so comparing three rows is three
|
|
2831
|
+
* clicks rather than six navigations.
|
|
2832
|
+
*
|
|
2833
|
+
* Deliberately **not** a modal: no focus trap, no `aria-modal`, no inert page.
|
|
2834
|
+
* The list behind it is still the point, and a reader who tabs out of the panel
|
|
2835
|
+
* to change a filter is doing the expected thing. Escape closes; focus returns
|
|
2836
|
+
* to whatever opened it.
|
|
2837
|
+
*
|
|
2838
|
+
* @example
|
|
2839
|
+
* ```tsx
|
|
2840
|
+
* <Flyout open={Boolean(selected)} onClose={clear} title={selected?.name}>
|
|
2841
|
+
* <DescriptionList items={fields} />
|
|
2842
|
+
* </Flyout>
|
|
2843
|
+
* ```
|
|
2844
|
+
*/
|
|
2845
|
+
function Flyout({ open, onClose, title, description, type = "overlay", side = "right", size = "md", actions, footer, scrim = false, closeOnOutsideClick = true, hideCloseButton = false, labels: customLabels, className, children }) {
|
|
2846
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$5), customLabels);
|
|
2847
|
+
const panelRef = useRef(null);
|
|
2848
|
+
const openerRef = useRef(null);
|
|
2849
|
+
useEffect(() => {
|
|
2850
|
+
var _panelRef$current;
|
|
2851
|
+
if (!open) return;
|
|
2852
|
+
openerRef.current = document.activeElement;
|
|
2853
|
+
(_panelRef$current = panelRef.current) === null || _panelRef$current === void 0 || _panelRef$current.focus({ preventScroll: true });
|
|
2854
|
+
return () => {
|
|
2855
|
+
var _openerRef$current, _openerRef$current$fo;
|
|
2856
|
+
(_openerRef$current = openerRef.current) === null || _openerRef$current === void 0 || (_openerRef$current$fo = _openerRef$current.focus) === null || _openerRef$current$fo === void 0 || _openerRef$current$fo.call(_openerRef$current, { preventScroll: true });
|
|
2857
|
+
};
|
|
2858
|
+
}, [open]);
|
|
2859
|
+
useEffect(() => {
|
|
2860
|
+
if (!open) return;
|
|
2861
|
+
const handleKeyDown = (event) => {
|
|
2862
|
+
if (event.key === "Escape") {
|
|
2863
|
+
event.stopPropagation();
|
|
2864
|
+
onClose();
|
|
2865
|
+
}
|
|
2866
|
+
};
|
|
2867
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
2868
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
2869
|
+
}, [open, onClose]);
|
|
2870
|
+
useEffect(() => {
|
|
2871
|
+
if (!open || !closeOnOutsideClick || type !== "overlay") return;
|
|
2872
|
+
const handlePointerDown = (event) => {
|
|
2873
|
+
const panel = panelRef.current;
|
|
2874
|
+
if (panel && !panel.contains(event.target)) onClose();
|
|
2875
|
+
};
|
|
2876
|
+
const timer = window.setTimeout(() => {
|
|
2877
|
+
document.addEventListener("pointerdown", handlePointerDown);
|
|
2878
|
+
}, 0);
|
|
2879
|
+
return () => {
|
|
2880
|
+
window.clearTimeout(timer);
|
|
2881
|
+
document.removeEventListener("pointerdown", handlePointerDown);
|
|
2882
|
+
};
|
|
2883
|
+
}, [
|
|
2884
|
+
open,
|
|
2885
|
+
closeOnOutsideClick,
|
|
2886
|
+
type,
|
|
2887
|
+
onClose
|
|
2888
|
+
]);
|
|
2889
|
+
const handleClose = useCallback(() => onClose(), [onClose]);
|
|
2890
|
+
if (!open) return null;
|
|
2891
|
+
const header = (title || actions || !hideCloseButton) && /* @__PURE__ */ jsxs("header", {
|
|
2892
|
+
className: cn("border-border-subtle flex items-start gap-2 border-b px-4 py-3"),
|
|
2893
|
+
children: [
|
|
2894
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2895
|
+
className: "flex min-w-0 grow flex-col gap-0.5",
|
|
2896
|
+
children: [title && /* @__PURE__ */ jsx("h2", {
|
|
2897
|
+
className: cn("text-text-primary", "truncate text-base font-semibold"),
|
|
2898
|
+
children: title
|
|
2899
|
+
}), description && /* @__PURE__ */ jsx("p", {
|
|
2900
|
+
className: cn("text-text-secondary", "truncate text-xs"),
|
|
2901
|
+
children: description
|
|
2902
|
+
})]
|
|
2903
|
+
}),
|
|
2904
|
+
actions,
|
|
2905
|
+
!hideCloseButton && /* @__PURE__ */ jsx("button", {
|
|
2906
|
+
type: "button",
|
|
2907
|
+
onClick: handleClose,
|
|
2908
|
+
"aria-label": labels.close,
|
|
2909
|
+
className: cn("outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset", "text-text-tertiary", "hover:text-text-primary shrink-0 rounded p-1 transition-colors"),
|
|
2910
|
+
children: /* @__PURE__ */ jsx(X, {
|
|
2911
|
+
className: "size-4",
|
|
2912
|
+
"aria-hidden": "true"
|
|
2913
|
+
})
|
|
2914
|
+
})
|
|
2915
|
+
]
|
|
2916
|
+
});
|
|
2917
|
+
const panel = /* @__PURE__ */ jsxs("aside", {
|
|
2918
|
+
ref: panelRef,
|
|
2919
|
+
role: "dialog",
|
|
2920
|
+
"aria-modal": false,
|
|
2921
|
+
"aria-label": typeof title === "string" ? title : void 0,
|
|
2922
|
+
tabIndex: -1,
|
|
2923
|
+
className: cn(OPT_FOCUS_VISIBLE, "flex min-h-0 flex-col", type === "overlay" && [
|
|
2924
|
+
"rounded-xl bg-surface-raised shadow-md",
|
|
2925
|
+
"fixed inset-y-0 z-40 w-full",
|
|
2926
|
+
sizeClass[size],
|
|
2927
|
+
side === "right" ? "right-0 border-l" : "left-0 border-r",
|
|
2928
|
+
"border-border"
|
|
2929
|
+
], type === "inline" && ["border border-border", "rounded-xl bg-surface"], className),
|
|
2930
|
+
"data-opt-id": "85XVE",
|
|
2931
|
+
"data-opt-slug": "flyout.Flyout",
|
|
2932
|
+
children: [
|
|
2933
|
+
header,
|
|
2934
|
+
/* @__PURE__ */ jsx("div", {
|
|
2935
|
+
className: "min-h-0 grow overflow-y-auto px-4 py-4",
|
|
2936
|
+
children
|
|
2937
|
+
}),
|
|
2938
|
+
footer && /* @__PURE__ */ jsx("footer", {
|
|
2939
|
+
className: "border-border-subtle border-t px-4 py-3",
|
|
2940
|
+
children: footer
|
|
2941
|
+
})
|
|
2942
|
+
]
|
|
2943
|
+
});
|
|
2944
|
+
if (type === "inline") return panel;
|
|
2945
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [scrim && /* @__PURE__ */ jsx("div", {
|
|
2946
|
+
className: "bg-overlay fixed inset-0 z-30",
|
|
2947
|
+
"aria-hidden": "true"
|
|
2948
|
+
}), panel] });
|
|
2949
|
+
}
|
|
2950
|
+
Flyout.displayName = "Flyout";
|
|
2951
|
+
//#endregion
|
|
2403
2952
|
//#region src/lib/use-auto-refresh.ts
|
|
2404
2953
|
/**
|
|
2405
2954
|
* A refresh timer that waits for its own work.
|
|
@@ -4270,6 +4819,6 @@ function FieldValues({ values, loading, total, sampledRows, onFilter, labels })
|
|
|
4270
4819
|
});
|
|
4271
4820
|
}
|
|
4272
4821
|
//#endregion
|
|
4273
|
-
export {
|
|
4822
|
+
export { CommandGroup$1 as $, ToastProvider as A, FaqAccordion as B, Flyout as C, KeyValueEditor as D, WorkflowCanvas as E, BranchSelect as F, StatusSelect as G, EditorToolbar as H, EnvPanel as I, CommandPaletteTrigger as J, SearchCombobox as K, ProjectSwitcher as L, useToast as M, DataTable as N, FailureList as O, DomainTable as P, CommandEmpty$1 as Q, DeploymentTimeline as R, useAutoRefresh as S, EventTimeline as T, SidebarNav as U, ContentTabs as V, AppMenubar as W, Command as X, CommandPalette as Y, CommandDialog as Z, withoutField as _, formatQuery as a, DEFAULT_TIME_PRESETS as b, parseQueryWithDiagnostics as c, applyCellAction as d, CommandInput$1 as et, fieldValues as f, withFieldValue as g, removeClause as h, formatClause as i, CommandShortcut as it, toast as j, NotificationToast as k, EMPTY_QUERY as l, queryFields as m, QueryBar as n, CommandList$1 as nt, quoteValue as o, isEmptyQuery as p, DashboardGrid as q, describeClause as r, CommandSeparator$1 as rt, parseQuery as s, FieldSidebar as t, CommandItem$1 as tt, addClause as u, LogTable as v, ScoreBreakdown as w, TimeRangeControl as x, TimeSeriesPanel as y, SettingsForm as z };
|
|
4274
4823
|
|
|
4275
|
-
//# sourceMappingURL=field-sidebar-
|
|
4824
|
+
//# sourceMappingURL=field-sidebar-BXl5RJ3q.js.map
|