@reopt-ai/opt-ui 1.13.0 → 1.15.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/CHANGELOG.md +45 -0
- package/COMPONENT_CATALOG.md +644 -123
- package/README.md +35 -7
- package/dist/core/index.cjs +4 -4
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +2 -2
- package/dist/docs/02-components/01-core.md +261 -58
- package/dist/docs/02-components/02-visuals.md +1 -1
- package/dist/docs/02-components/03-shells.md +391 -65
- package/dist/docs/02-components/04-surfaces.md +1 -1
- package/dist/docs/02-components/index.md +4 -4
- package/dist/id-registry.cjs +32 -0
- package/dist/id-registry.js +32 -0
- package/dist/id-registry.json +68 -0
- package/dist/index.cjs +1196 -427
- package/dist/index.d.cts +208 -19
- package/dist/index.d.ts +208 -19
- package/dist/index.js +1050 -295
- package/dist/{key-pad-menu-DMmbQ1jF.js → key-pad-menu-BCOeYvsH.js} +59 -67
- package/dist/{key-pad-menu-BOVu97bj.d.cts → key-pad-menu-CaIsTHB2.d.cts} +22 -9
- package/dist/{key-pad-menu-0KWOnELe.cjs → key-pad-menu-Jaqxhx9P.cjs} +57 -77
- package/dist/{key-pad-menu-NlZ9zNF8.d.ts → key-pad-menu-odAEycIX.d.ts} +22 -9
- package/dist/meta.cjs +877 -26
- package/dist/meta.js +877 -26
- package/dist/{field-sidebar-CRdToHRO.js → replay-player-layout-BVUNsUS1.js} +904 -203
- package/dist/{field-sidebar-CxxSK4JO.cjs → replay-player-layout-Cmzptq89.cjs} +944 -201
- package/dist/{field-sidebar-D-rwuN_w.d.cts → replay-player-layout-DpqdfdQ6.d.ts} +246 -3
- package/dist/{field-sidebar-Dz7J4ett.d.ts → replay-player-layout-DuZW-gFF.d.cts} +246 -3
- package/dist/shells/index.cjs +58 -52
- 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-Bd-0WkSP.js → text-truncate-B-8nJgnu.js} +200 -101
- package/dist/{text-truncate-eMzvU_7k.d.cts → text-truncate-DOxUijpB.d.cts} +3 -30
- package/dist/{text-truncate-eMzvU_7k.d.ts → text-truncate-DOxUijpB.d.ts} +3 -30
- package/dist/{text-truncate-BeYW6XZu.cjs → text-truncate-gQhpMy-Z.cjs} +214 -97
- package/dist/theme/server.d.cts +2 -2
- package/dist/theme/server.d.ts +2 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { $ as useFormContext, $n as
|
|
3
|
-
import { $ as
|
|
4
|
-
import { $ as
|
|
2
|
+
import { $ as useFormContext, $n as OPT_DOT_YELLOW, $t as Composite, A as FormGroup, An as SkeletonTable, At as ComboboxRoot, B as FormRemove, Bt as DialogRoot, C as FormCheckbox, Cn as koBreadcrumbLabels, Ct as MenubarRoot, D as FormDescription, Dn as Skeleton, Dt as ComboboxInput, E as FormDateRangePicker, En as StatCard, Et as ComboboxGroupLabel, F as FormNumberInput, Ft as DialogDismiss, G as FormSelectPopover, Gn as OPT_BADGE_YELLOW, Gt as SelectTrigger, H as FormRoot, Hn as OPT_BADGE_GREEN, Ht as SelectLabel, I as FormProvider, It as DialogFooter, J as FormSubmit, Jt as TabPanel, K as FormSlider, Kn as OPT_BORDER, Kt as Tab, L as FormPush, Lt as DialogHeader, M as FormIconPicker, Mn as Toggle, Mt as DialogBody, N as FormInput, Nn as ToggleGroup, Nt as DialogDescription, O as FormError, On as SkeletonAvatar, Ot as ComboboxItem, P as FormLabel, Pn as useControlledState, Pt as DialogDisclosure, Q as useFieldValue, Qn as OPT_DOT_RED, Qt as DisclosureTrigger, R as FormRadio, Rt as DialogHeading, S as formatOptTime, Sn as Button, St as MenubarContainer, T as FormControl, Tn as koStarRatingLabels, Tt as ComboboxGroup, U as FormSelect, Un as OPT_BADGE_NEUTRAL, Ut as SelectPopover, V as FormReset, Vn as OPT_BADGE_BLUE, Vt as SelectItem, W as FormSelectItem, Wn as OPT_BADGE_RED, Wt as SelectRoot, X as FormTagInput, Xn as OPT_DOT_GRAY, Xt as DisclosureContent, Y as FormSwitch, Yt as TabsRoot, Z as FormTextarea, Zn as OPT_DOT_GREEN, Zt as DisclosureRoot, _ as DropdownTrigger, _n as Alert, _r as _objectSpread2, _t as MenuItemRadio, a as FieldTokenLegend, an as Textarea, at as IconPicker, b as formatOptNumber, bn as DescriptionList, br as cn, bt as MenuSeparator, c as ResizableHandle, cn as Input, ct as PopoverClose, d as Checkbox, dn as ToolbarContainer, dt as PopoverTrigger, en as CompositeItem, er as OPT_FOCUS, et as useFormStore, f as CheckboxGroup, fn as ToolbarRoot, ft as Slider, g as DropdownSeparator, gn as TooltipProvider, gr as OPT_TH, gt as MenuItemCheckbox, h as DropdownMenu, hn as TooltipAnchor, hr as OPT_TEXT_TERTIARY, ht as MenuItem, i as FieldToken, in as Meter, j as FormGroupLabel, jn as SkeletonText, jt as AlertDialogPanel, k as FormField, kn as SkeletonCard, kt as ComboboxPopover, l as ResizablePanel, ln as useInputId, lt as PopoverContent, m as DropdownItem, mn as Tooltip, mr as OPT_TEXT_SECONDARY, mt as MenuButtonArrow, n as Highlight, nn as CompositeRow, nr as OPT_HOVER_ITEM, nt as DateRangePicker, o as resolveFieldType, on as StarRating, ot as getIconRegistryEntry, p as DropdownContent, pn as ToolbarSeparator, pr as OPT_TEXT_PRIMARY, pt as NumberInput, q as FormStarRating, qt as TabList, r as FIELD_TYPE_TOKENS, rn as CompositeZone, rr as OPT_INPUT, rt as TagInput, s as Pagination, sn as Switch, st as ColorPicker, t as TextTruncate, tn as CompositeProvider, tr as OPT_FOCUS_VISIBLE, tt as DEFAULT_PRESETS, u as ResizablePanelGroup, un as ToolbarButton, ur as OPT_TD, ut as PopoverRoot, vn as Spinner, vr as _objectWithoutProperties, vt as MenuPopover, w as FormColorPicker, wn as koComboboxLabels, wt as ComboboxEmpty, x as formatOptShortDate, xn as EmptyState, xt as MenuTrigger, y as formatOptDateTime, yn as Badge, yr as Kbd, yt as MenuRoot, z as FormRadioGroup, zt as DialogPanel } from "./text-truncate-B-8nJgnu.js";
|
|
3
|
+
import { $ as Heading, A as LoadingOverlay, B as CardFooter, C as Logo, D as PageHeader, E as ScrollArea, F as CircularProgress, G as AvatarGroup, H as CardTitle, I as Progress, J as AccordionItem, K as Breadcrumb, L as Card, M as RadioGroup, N as ConditionBuilder, O as createBlock, P as StepBuilder, Q as Separator, R as CardContent, S as DrawerRoot, T as Container, U as Identity, V as CardHeader, W as Avatar, X as AccordionTrigger, Y as AccordionRoot, Z as OtpField, _ as getShaderFragment, a as THEME_PALETTES, b as DrawerClose, c as ExpressionGroup, d as ShaderSurface, et as Text, f as SHADER_OVERLAY_PARAM_KEYS, g as SHADER_PRESET_IDS, h as SHADER_PRESETS, i as ColorPalettePicker, j as Radio, k as BlockLayout, l as Facet, m as SHADER_PARAM_KEYS, n as InlineEdit, o as LiveRegion, p as SHADER_PARAM_FALLBACK, q as AccordionContent, r as ColorPaletteDisplay, s as Expression, t as KeyPadMenu, u as FacetGroup, v as getShaderPreset, w as Section, x as DrawerPanel, y as VirtualList, z as CardDescription } from "./key-pad-menu-BCOeYvsH.js";
|
|
4
|
+
import { $ as safeParseStoredSpec, $t as AppMenubar, A as EventTimeline, At as QueryToolbar, B as createThemeBootScript, Bt as toast, C as fieldValues, Ct as VALUELESS_OPERATORS, D as withFieldValue, Dt as defaultQueryChartConfig, E as removeClause, Et as QueryResultChart, F as OptThemeControllerContext, Ft as WorkflowCanvas, G as GLOBAL_THEME_STYLE_ID, Gt as EnvPanel, H as readStoredTheme, Ht as DataTable, I as useOptThemeController, It as KeyValueEditor, J as buildTokenCache, Jt as SettingsForm, K as THEME_SPEC_STORAGE_KEY, Kt as ProjectSwitcher, L as ALL_COMPOUND_THEMES, Lt as FailureList, M as OptThemeProvider, Mt as QueryResultsTable, N as useOptTheme, Nt as formatQueryCell, O as withoutField, Ot as numericResultColumns, P as useOptionalOptTheme, Pt as Flyout, Q as resolveDescriptor, Qt as SidebarNav, R as FORCE_LIGHT_PRESETS, Rt as NotificationToast, S as applyCellAction, St as QueryFiltersMenu, T as queryFields, Tt as hasActiveQueryFilters, U as resolveThemeMode, Ut as DomainTable, V as getCompoundTheme, Vt as useToast, W as GENERATED_THEME_ID_DEFAULT, Wt as BranchSelect, X as getCompoundIdForSpec, Xt as ContentTabs, Y as computeGeneratedTokens, Yt as FaqAccordion, Z as isForceLightSpec, Zt as EditorToolbar, _ as quoteValue, _t as SaveQueryDialog, a as ReplayScrubber, an as CommandPalette, at as generatedTheme, b as EMPTY_QUERY, bt as isValidQueryVariableName, c as LogTable, cn as CommandEmpty, ct as isPresetSpec, d as TimeRangeControl, dn as CommandItem, dt as THEME_PRESET_IDS, en as StatusSelect, et as safeParseStoredTokens, f as useAutoRefresh, fn as CommandList, ft as THEME_REGISTRY, g as formatQuery, gn as Callout, gt as useMediaQuery, h as formatClause, hn as SegmentedControl, ht as QueryWorkspace, i as formatReplayElapsed, in as CommandPaletteTrigger, it as defineThemeOverrides, j as SqlEditor, jt as SchemaTree, k as ScoreBreakdown, kt as QueryOutputPane, l as TimeSeriesPanel, ln as CommandGroup, lt as presetTheme, m as describeClause, mn as CommandShortcut, mt as isThemePresetId, n as replayShortcutKey, nn as useAsyncSearch, nt as serializeThemeRule, o as groupReplayMarkers, on as Command, ot as isDescriptorSpec, p as QueryBar, pn as CommandSeparator, pt as getThemeDescriptor, q as THEME_TOKENS_STORAGE_KEY, qt as DeploymentTimeline, r as ReplayTransport, rn as DashboardGrid, rt as serializeTokenBody, s as FieldSidebar, sn as CommandDialog, st as isGeneratedSpec, t as ReplayPlayerLayout, tn as SearchCombobox, tt as serializeGeneratedTheme, u as DEFAULT_TIME_PRESETS, un as CommandInput, ut as FORCE_LIGHT_PRESET_IDS, v as parseQuery, vt as QueryHistoryList, w as isEmptyQuery, wt as countActiveQueryFilters, x as addClause, xt as EMPTY_QUERY_FILTERS, y as parseQueryWithDiagnostics, yt as QueryVariablesMenu, z as coerceThemeMode, zt as ToastProvider } from "./replay-player-layout-BVUNsUS1.js";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import * as React from "react";
|
|
7
7
|
import { Component, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
8
|
-
import { Check, ChevronDown, CircleCheck, Copy, FilePen, GitMerge, MessageSquare, MoreHorizontal, Pencil, Rocket, Search, Sparkles, Trash2, User, X } from "lucide-react";
|
|
8
|
+
import { ArrowDown, ArrowUp, Check, ChevronDown, CircleCheck, Copy, FilePen, GitMerge, MessageSquare, MoreHorizontal, Pencil, Plus, Rocket, Search, Sparkles, Trash2, TriangleAlert, User, X } from "lucide-react";
|
|
9
9
|
import { EventSparkline, MetricsCard, ReportWidget, TrendChart } from "@reopt-ai/opt-charts";
|
|
10
10
|
import { matchSorter } from "match-sorter";
|
|
11
11
|
import { usePathname } from "next/navigation";
|
|
@@ -92,7 +92,7 @@ const _excluded = [
|
|
|
92
92
|
"disabled",
|
|
93
93
|
"onClick"
|
|
94
94
|
];
|
|
95
|
-
const defaultLabels$
|
|
95
|
+
const defaultLabels$34 = {
|
|
96
96
|
copy: "복사",
|
|
97
97
|
copied: "복사됨",
|
|
98
98
|
failed: "복사할 수 없습니다"
|
|
@@ -139,7 +139,7 @@ const stateTone = {
|
|
|
139
139
|
*/
|
|
140
140
|
function CopyButton(_ref) {
|
|
141
141
|
let { value, variant = "icon", size = "md", feedbackDuration = 1500, onCopy, labels: customLabels, className, disabled, onClick } = _ref, props = _objectWithoutProperties(_ref, _excluded);
|
|
142
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
142
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$34), customLabels);
|
|
143
143
|
const [state, setState] = useState("idle");
|
|
144
144
|
const timer = useRef(null);
|
|
145
145
|
useEffect(() => () => {
|
|
@@ -264,7 +264,7 @@ function PageAside({ header, children, footer, widthClassName = "w-60", label, h
|
|
|
264
264
|
PageAside.displayName = "PageAside";
|
|
265
265
|
//#endregion
|
|
266
266
|
//#region src/shells/task-list.tsx
|
|
267
|
-
const defaultLabels$
|
|
267
|
+
const defaultLabels$33 = {
|
|
268
268
|
title: "작업 목록",
|
|
269
269
|
emptyMessage: "작업이 없습니다",
|
|
270
270
|
completedOf: "{completed}/{total} 완료",
|
|
@@ -284,9 +284,9 @@ const defaultLabels$32 = {
|
|
|
284
284
|
};
|
|
285
285
|
/** Renders the task list component. */
|
|
286
286
|
function TaskList({ tasks, title, onTaskClick, onTaskStatusChange, emptyMessage, showSubtasks = false, maxItems, labels: customLabels, className }) {
|
|
287
|
-
const labels = _objectSpread2(_objectSpread2(_objectSpread2({}, defaultLabels$
|
|
288
|
-
priority: _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
289
|
-
status: _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
287
|
+
const labels = _objectSpread2(_objectSpread2(_objectSpread2({}, defaultLabels$33), customLabels), {}, {
|
|
288
|
+
priority: _objectSpread2(_objectSpread2({}, defaultLabels$33.priority), customLabels === null || customLabels === void 0 ? void 0 : customLabels.priority),
|
|
289
|
+
status: _objectSpread2(_objectSpread2({}, defaultLabels$33.status), customLabels === null || customLabels === void 0 ? void 0 : customLabels.status)
|
|
290
290
|
});
|
|
291
291
|
const displayTitle = title !== null && title !== void 0 ? title : labels.title;
|
|
292
292
|
const displayEmptyMessage = emptyMessage !== null && emptyMessage !== void 0 ? emptyMessage : labels.emptyMessage;
|
|
@@ -444,7 +444,7 @@ function TaskList({ tasks, title, onTaskClick, onTaskStatusChange, emptyMessage,
|
|
|
444
444
|
}
|
|
445
445
|
//#endregion
|
|
446
446
|
//#region src/shells/activity-feed.tsx
|
|
447
|
-
const defaultLabels$
|
|
447
|
+
const defaultLabels$32 = {
|
|
448
448
|
title: "활동 피드",
|
|
449
449
|
emptyMessage: "활동이 없습니다",
|
|
450
450
|
moreItems: "{count}개 더 보기",
|
|
@@ -494,24 +494,24 @@ const variantBorder = {
|
|
|
494
494
|
function ActivityFeed({ activities, title, maxItems, onActivityClick, onShowMore, emptyMessage, labels: customLabels, locale = "ko-KR", loading = false, layout = "list", renderActions, className }) {
|
|
495
495
|
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;
|
|
496
496
|
const mergedTimeAgo = {
|
|
497
|
-
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$
|
|
498
|
-
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$
|
|
499
|
-
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$
|
|
500
|
-
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$
|
|
497
|
+
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$32.timeAgo.justNow,
|
|
498
|
+
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$32.timeAgo.minutesAgo,
|
|
499
|
+
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$32.timeAgo.hoursAgo,
|
|
500
|
+
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$32.timeAgo.daysAgo
|
|
501
501
|
};
|
|
502
502
|
const mergedActivityVerbs = {
|
|
503
|
-
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$
|
|
504
|
-
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$
|
|
505
|
-
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$
|
|
506
|
-
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$
|
|
507
|
-
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$
|
|
508
|
-
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$
|
|
509
|
-
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$
|
|
503
|
+
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$32.activityVerbs.created,
|
|
504
|
+
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$32.activityVerbs.updated,
|
|
505
|
+
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$32.activityVerbs.completed,
|
|
506
|
+
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$32.activityVerbs.commented,
|
|
507
|
+
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$32.activityVerbs.assigned,
|
|
508
|
+
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$32.activityVerbs.deployed,
|
|
509
|
+
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$32.activityVerbs.merged
|
|
510
510
|
};
|
|
511
511
|
const labels = {
|
|
512
|
-
title: (_customLabels$title = customLabels === null || customLabels === void 0 ? void 0 : customLabels.title) !== null && _customLabels$title !== void 0 ? _customLabels$title : defaultLabels$
|
|
513
|
-
emptyMessage: (_customLabels$emptyMe = customLabels === null || customLabels === void 0 ? void 0 : customLabels.emptyMessage) !== null && _customLabels$emptyMe !== void 0 ? _customLabels$emptyMe : defaultLabels$
|
|
514
|
-
moreItems: (_customLabels$moreIte = customLabels === null || customLabels === void 0 ? void 0 : customLabels.moreItems) !== null && _customLabels$moreIte !== void 0 ? _customLabels$moreIte : defaultLabels$
|
|
512
|
+
title: (_customLabels$title = customLabels === null || customLabels === void 0 ? void 0 : customLabels.title) !== null && _customLabels$title !== void 0 ? _customLabels$title : defaultLabels$32.title,
|
|
513
|
+
emptyMessage: (_customLabels$emptyMe = customLabels === null || customLabels === void 0 ? void 0 : customLabels.emptyMessage) !== null && _customLabels$emptyMe !== void 0 ? _customLabels$emptyMe : defaultLabels$32.emptyMessage,
|
|
514
|
+
moreItems: (_customLabels$moreIte = customLabels === null || customLabels === void 0 ? void 0 : customLabels.moreItems) !== null && _customLabels$moreIte !== void 0 ? _customLabels$moreIte : defaultLabels$32.moreItems,
|
|
515
515
|
timeAgo: mergedTimeAgo,
|
|
516
516
|
activityVerbs: mergedActivityVerbs
|
|
517
517
|
};
|
|
@@ -639,13 +639,13 @@ function ActivityFeed({ activities, title, maxItems, onActivityClick, onShowMore
|
|
|
639
639
|
ActivityFeed.displayName = "ActivityFeed";
|
|
640
640
|
//#endregion
|
|
641
641
|
//#region src/shells/filter-bar.tsx
|
|
642
|
-
const defaultLabels$
|
|
642
|
+
const defaultLabels$31 = {
|
|
643
643
|
clearAll: "필터 초기화",
|
|
644
644
|
searchPlaceholder: "검색..."
|
|
645
645
|
};
|
|
646
646
|
/** Renders the filter bar component. */
|
|
647
647
|
function FilterBar({ filters, onFilterChange, onDateRangeChange, onClearAll, labels: customLabels, presetActions, className }) {
|
|
648
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
648
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$31), customLabels);
|
|
649
649
|
const [searchValues, setSearchValues] = useState({});
|
|
650
650
|
const [tagInputValues, setTagInputValues] = useState({});
|
|
651
651
|
const [multiSelectOpen, setMultiSelectOpen] = useState({});
|
|
@@ -871,10 +871,10 @@ function matchesShortcut(event, shortcut) {
|
|
|
871
871
|
if (requiresMeta && !event.metaKey) return false;
|
|
872
872
|
return event.key.toLowerCase() === key;
|
|
873
873
|
}
|
|
874
|
-
const defaultLabels$
|
|
874
|
+
const defaultLabels$30 = { title: "빠른 작업" };
|
|
875
875
|
/** Renders the quick actions component. */
|
|
876
876
|
function QuickActions({ actions, title, layout = "grid", columns = 3, showDescriptionInGrid = false, bindShortcuts = false, labels: customLabels, className }) {
|
|
877
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
877
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$30), customLabels);
|
|
878
878
|
const displayTitle = title !== null && title !== void 0 ? title : labels.title;
|
|
879
879
|
const titleId = useId();
|
|
880
880
|
useEffect(() => {
|
|
@@ -952,7 +952,7 @@ function QuickActions({ actions, title, layout = "grid", columns = 3, showDescri
|
|
|
952
952
|
QuickActions.displayName = "QuickActions";
|
|
953
953
|
//#endregion
|
|
954
954
|
//#region src/shells/team-member-list.tsx
|
|
955
|
-
const defaultLabels$
|
|
955
|
+
const defaultLabels$29 = {
|
|
956
956
|
title: "팀원",
|
|
957
957
|
emptyMessage: "팀원이 없습니다",
|
|
958
958
|
onlineCount: "{online}/{total} 온라인",
|
|
@@ -973,7 +973,7 @@ const statusDot = {
|
|
|
973
973
|
};
|
|
974
974
|
/** Renders the team member list component. */
|
|
975
975
|
function TeamMemberList({ members, title, layout = "list", maxDisplay, onMemberClick, onShowMore, emptyMessage, labels: customLabels, className }) {
|
|
976
|
-
const labels = _objectSpread2(_objectSpread2(_objectSpread2({}, defaultLabels$
|
|
976
|
+
const labels = _objectSpread2(_objectSpread2(_objectSpread2({}, defaultLabels$29), customLabels), {}, { status: _objectSpread2(_objectSpread2({}, defaultLabels$29.status), customLabels === null || customLabels === void 0 ? void 0 : customLabels.status) });
|
|
977
977
|
const displayTitle = title !== null && title !== void 0 ? title : labels.title;
|
|
978
978
|
const displayEmptyMessage = emptyMessage !== null && emptyMessage !== void 0 ? emptyMessage : labels.emptyMessage;
|
|
979
979
|
const titleId = useId();
|
|
@@ -1126,9 +1126,14 @@ function TeamMemberList({ members, title, layout = "list", maxDisplay, onMemberC
|
|
|
1126
1126
|
//#region src/shells/auth-form.tsx
|
|
1127
1127
|
/** Renders the auth form component. */
|
|
1128
1128
|
function AuthForm({ defaultMode = "login", mode: controlledMode, onModeChange, showRememberMe = true, minPasswordLength = 8, onSubmit, renderExtraFields, labels = {}, ariaLabel }) {
|
|
1129
|
-
var _labels$loginTitle, _labels$signupTitle, _labels$emailLabel, _labels$passwordLabel, _labels$confirmPasswo, _labels$rememberMeLab, _labels$loginButton, _labels$signupButton;
|
|
1129
|
+
var _labels$loginTitle, _labels$signupTitle, _labels$emailLabel, _labels$passwordLabel, _labels$confirmPasswo, _labels$rememberMeLab, _labels$loginButton, _labels$signupButton, _labels$submitError;
|
|
1130
1130
|
const [uncontrolledMode, setUncontrolledMode] = useState(defaultMode);
|
|
1131
1131
|
const [submitted, setSubmitted] = useState(false);
|
|
1132
|
+
useEffect(() => {
|
|
1133
|
+
if (!submitted) return;
|
|
1134
|
+
const timer = setTimeout(() => setSubmitted(false), 3e3);
|
|
1135
|
+
return () => clearTimeout(timer);
|
|
1136
|
+
}, [submitted]);
|
|
1132
1137
|
const mode = controlledMode !== null && controlledMode !== void 0 ? controlledMode : uncontrolledMode;
|
|
1133
1138
|
const handleModeChange = (newMode) => {
|
|
1134
1139
|
if (controlledMode === void 0) setUncontrolledMode(newMode);
|
|
@@ -1167,13 +1172,13 @@ function AuthForm({ defaultMode = "login", mode: controlledMode, onModeChange, s
|
|
|
1167
1172
|
}
|
|
1168
1173
|
return errors;
|
|
1169
1174
|
},
|
|
1170
|
-
onSubmit: (values) => {
|
|
1171
|
-
setSubmitted(
|
|
1172
|
-
|
|
1173
|
-
if (onSubmit) onSubmit(_objectSpread2(_objectSpread2(_objectSpread2({
|
|
1175
|
+
onSubmit: async (values) => {
|
|
1176
|
+
setSubmitted(false);
|
|
1177
|
+
if (onSubmit) await onSubmit(_objectSpread2(_objectSpread2(_objectSpread2({
|
|
1174
1178
|
email: values.email,
|
|
1175
1179
|
password: values.password
|
|
1176
1180
|
}, mode === "signup" ? { confirmPassword: values.confirmPassword } : {}), mode === "login" ? { rememberMe: values.rememberMe } : {}), {}, { mode }));
|
|
1181
|
+
setSubmitted(true);
|
|
1177
1182
|
}
|
|
1178
1183
|
});
|
|
1179
1184
|
const loginTitle = (_labels$loginTitle = labels.loginTitle) !== null && _labels$loginTitle !== void 0 ? _labels$loginTitle : "로그인";
|
|
@@ -1188,11 +1193,13 @@ function AuthForm({ defaultMode = "login", mode: controlledMode, onModeChange, s
|
|
|
1188
1193
|
children: [/* @__PURE__ */ jsx("button", {
|
|
1189
1194
|
type: "button",
|
|
1190
1195
|
className: `flex-1 rounded-l-lg px-4 py-2 text-sm font-medium transition-colors ${mode === "login" ? "bg-accent text-accent-fg" : "text-text-secondary hover:bg-bg-subtle"}`,
|
|
1196
|
+
disabled: form.isSubmitting(),
|
|
1191
1197
|
onClick: () => handleModeChange("login"),
|
|
1192
1198
|
children: loginTitle
|
|
1193
1199
|
}), /* @__PURE__ */ jsx("button", {
|
|
1194
1200
|
type: "button",
|
|
1195
1201
|
className: `flex-1 rounded-r-lg px-4 py-2 text-sm font-medium transition-colors ${mode === "signup" ? "bg-accent text-accent-fg" : "text-text-secondary hover:bg-bg-subtle"}`,
|
|
1202
|
+
disabled: form.isSubmitting(),
|
|
1196
1203
|
onClick: () => handleModeChange("signup"),
|
|
1197
1204
|
children: signupTitle
|
|
1198
1205
|
})]
|
|
@@ -1201,8 +1208,8 @@ function AuthForm({ defaultMode = "login", mode: controlledMode, onModeChange, s
|
|
|
1201
1208
|
store: form,
|
|
1202
1209
|
"aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : mode === "login" ? "로그인 폼" : "회원가입 폼",
|
|
1203
1210
|
children: [
|
|
1204
|
-
/* @__PURE__ */ jsxs(
|
|
1205
|
-
|
|
1211
|
+
/* @__PURE__ */ jsxs(FormField, {
|
|
1212
|
+
name: "email",
|
|
1206
1213
|
children: [
|
|
1207
1214
|
/* @__PURE__ */ jsx(FormLabel, {
|
|
1208
1215
|
name: "email",
|
|
@@ -1217,8 +1224,8 @@ function AuthForm({ defaultMode = "login", mode: controlledMode, onModeChange, s
|
|
|
1217
1224
|
]
|
|
1218
1225
|
}),
|
|
1219
1226
|
renderExtraFields === null || renderExtraFields === void 0 ? void 0 : renderExtraFields(mode),
|
|
1220
|
-
/* @__PURE__ */ jsxs(
|
|
1221
|
-
|
|
1227
|
+
/* @__PURE__ */ jsxs(FormField, {
|
|
1228
|
+
name: "password",
|
|
1222
1229
|
children: [
|
|
1223
1230
|
/* @__PURE__ */ jsx(FormLabel, {
|
|
1224
1231
|
name: "password",
|
|
@@ -1232,8 +1239,8 @@ function AuthForm({ defaultMode = "login", mode: controlledMode, onModeChange, s
|
|
|
1232
1239
|
/* @__PURE__ */ jsx(FormError, { name: "password" })
|
|
1233
1240
|
]
|
|
1234
1241
|
}),
|
|
1235
|
-
mode === "signup" && /* @__PURE__ */ jsxs(
|
|
1236
|
-
|
|
1242
|
+
mode === "signup" && /* @__PURE__ */ jsxs(FormField, {
|
|
1243
|
+
name: "confirmPassword",
|
|
1237
1244
|
children: [
|
|
1238
1245
|
/* @__PURE__ */ jsx(FormLabel, {
|
|
1239
1246
|
name: "confirmPassword",
|
|
@@ -1263,7 +1270,13 @@ function AuthForm({ defaultMode = "login", mode: controlledMode, onModeChange, s
|
|
|
1263
1270
|
})
|
|
1264
1271
|
]
|
|
1265
1272
|
}),
|
|
1273
|
+
form.getSubmitError() !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
1274
|
+
role: "alert",
|
|
1275
|
+
className: "border-danger bg-danger-subtle text-danger-fg rounded-lg border p-3 text-sm",
|
|
1276
|
+
children: (_labels$submitError = labels.submitError) !== null && _labels$submitError !== void 0 ? _labels$submitError : "처리에 실패했습니다. 다시 시도해주세요."
|
|
1277
|
+
}),
|
|
1266
1278
|
submitted && /* @__PURE__ */ jsx("div", {
|
|
1279
|
+
role: "status",
|
|
1267
1280
|
className: "border-success bg-success-subtle text-success-fg rounded-lg border p-3 text-sm",
|
|
1268
1281
|
children: mode === "login" ? "로그인 성공!" : "회원가입 완료!"
|
|
1269
1282
|
})
|
|
@@ -1274,11 +1287,16 @@ function AuthForm({ defaultMode = "login", mode: controlledMode, onModeChange, s
|
|
|
1274
1287
|
//#region src/shells/dynamic-field-form.tsx
|
|
1275
1288
|
/** Renders the dynamic field form component. */
|
|
1276
1289
|
function DynamicFieldForm({ initialCount = 1, minFields = 1, maxFields, fieldType = "text", validateField, onSubmit, onFieldsChange, labels = {}, ariaLabel }) {
|
|
1277
|
-
var _labels$itemLabel, _labels$itemPlacehold, _labels$removeAriaLab, _labels$addButton, _labels$submitButton;
|
|
1290
|
+
var _labels$itemLabel, _labels$itemPlacehold, _labels$removeAriaLab, _labels$addButton, _labels$submitButton, _labels$submitError;
|
|
1278
1291
|
const initialFields = Array.from({ length: initialCount }, (_, i) => ({ id: i + 1 }));
|
|
1279
1292
|
const [fields, setFields] = useState(initialFields);
|
|
1280
1293
|
const [nextId, setNextId] = useState(initialCount + 1);
|
|
1281
1294
|
const [submitted, setSubmitted] = useState(false);
|
|
1295
|
+
useEffect(() => {
|
|
1296
|
+
if (!submitted) return;
|
|
1297
|
+
const timer = setTimeout(() => setSubmitted(false), 3e3);
|
|
1298
|
+
return () => clearTimeout(timer);
|
|
1299
|
+
}, [submitted]);
|
|
1282
1300
|
const [submittedValues, setSubmittedValues] = useState([]);
|
|
1283
1301
|
const form = useFormStore({
|
|
1284
1302
|
defaultValues: { items: Array.from({ length: initialCount }, () => "") },
|
|
@@ -1302,12 +1320,12 @@ function DynamicFieldForm({ initialCount = 1, minFields = 1, maxFields, fieldTyp
|
|
|
1302
1320
|
}
|
|
1303
1321
|
return errors;
|
|
1304
1322
|
},
|
|
1305
|
-
onSubmit: (values) => {
|
|
1323
|
+
onSubmit: async (values) => {
|
|
1324
|
+
setSubmitted(false);
|
|
1306
1325
|
const items = [...values.items];
|
|
1326
|
+
await (onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit(items));
|
|
1307
1327
|
setSubmittedValues(items);
|
|
1308
1328
|
setSubmitted(true);
|
|
1309
|
-
setTimeout(() => setSubmitted(false), 3e3);
|
|
1310
|
-
onSubmit === null || onSubmit === void 0 || onSubmit(items);
|
|
1311
1329
|
}
|
|
1312
1330
|
});
|
|
1313
1331
|
const addField = () => {
|
|
@@ -1338,70 +1356,79 @@ function DynamicFieldForm({ initialCount = 1, minFields = 1, maxFields, fieldTyp
|
|
|
1338
1356
|
className: "gap-group flex flex-col",
|
|
1339
1357
|
"data-opt-id": "8RYG7",
|
|
1340
1358
|
"data-opt-slug": "form-dynamic.DynamicFieldForm",
|
|
1341
|
-
children: [
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1359
|
+
children: [
|
|
1360
|
+
/* @__PURE__ */ jsxs(FormRoot, {
|
|
1361
|
+
store: form,
|
|
1362
|
+
"aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : "동적 필드 폼",
|
|
1363
|
+
children: [
|
|
1364
|
+
/* @__PURE__ */ jsx("div", {
|
|
1365
|
+
className: "gap-group flex flex-col",
|
|
1366
|
+
children: fields.map((field, displayIndex) => {
|
|
1367
|
+
const fieldName = `items.${displayIndex}`;
|
|
1368
|
+
return /* @__PURE__ */ jsxs(FormField, {
|
|
1369
|
+
name: fieldName,
|
|
1370
|
+
children: [
|
|
1371
|
+
/* @__PURE__ */ jsx(FormLabel, {
|
|
1372
|
+
name: fieldName,
|
|
1373
|
+
children: formatTemplate(itemLabel, displayIndex + 1)
|
|
1374
|
+
}),
|
|
1375
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1376
|
+
className: "gap-element flex",
|
|
1377
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1378
|
+
className: "flex-1",
|
|
1379
|
+
children: /* @__PURE__ */ jsx(FormInput, {
|
|
1380
|
+
name: fieldName,
|
|
1381
|
+
type: fieldType,
|
|
1382
|
+
placeholder: formatTemplate(itemPlaceholder, displayIndex + 1)
|
|
1383
|
+
})
|
|
1384
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
1385
|
+
type: "button",
|
|
1386
|
+
onClick: () => removeField(field.id),
|
|
1387
|
+
disabled: form.isSubmitting() || fields.length <= minFields,
|
|
1388
|
+
className: "border-border text-text-tertiary hover:border-danger hover:bg-danger-subtle hover:text-danger-fg inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-lg border transition-colors disabled:cursor-not-allowed disabled:opacity-30",
|
|
1389
|
+
"aria-label": formatTemplate(removeAriaLabel, displayIndex + 1),
|
|
1390
|
+
children: "✕"
|
|
1391
|
+
})]
|
|
1392
|
+
}),
|
|
1393
|
+
/* @__PURE__ */ jsx(FormError, { name: fieldName })
|
|
1394
|
+
]
|
|
1395
|
+
}, field.id);
|
|
1396
|
+
})
|
|
1397
|
+
}),
|
|
1398
|
+
/* @__PURE__ */ jsx("button", {
|
|
1399
|
+
type: "button",
|
|
1400
|
+
onClick: addField,
|
|
1401
|
+
disabled: form.isSubmitting() || maxFields !== void 0 && fields.length >= maxFields,
|
|
1402
|
+
className: "border-border text-text-secondary hover:border-accent hover:bg-accent-subtle hover:text-accent w-full rounded-lg border border-dashed px-4 py-2.5 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-30",
|
|
1403
|
+
children: (_labels$addButton = labels.addButton) !== null && _labels$addButton !== void 0 ? _labels$addButton : "+ 항목 추가"
|
|
1404
|
+
}),
|
|
1405
|
+
/* @__PURE__ */ jsx(FormSubmit, {
|
|
1406
|
+
disabled: form.isSubmitting(),
|
|
1407
|
+
children: (_labels$submitButton = labels.submitButton) !== null && _labels$submitButton !== void 0 ? _labels$submitButton : "제출"
|
|
1377
1408
|
})
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
/* @__PURE__ */ jsx("strong", { children: val })
|
|
1402
|
-
] }, i))
|
|
1403
|
-
})]
|
|
1404
|
-
})]
|
|
1409
|
+
]
|
|
1410
|
+
}),
|
|
1411
|
+
form.getSubmitError() !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
1412
|
+
role: "alert",
|
|
1413
|
+
className: "border-danger bg-danger-subtle text-danger-fg rounded-lg border p-3 text-sm",
|
|
1414
|
+
children: (_labels$submitError = labels.submitError) !== null && _labels$submitError !== void 0 ? _labels$submitError : "처리에 실패했습니다. 다시 시도해주세요."
|
|
1415
|
+
}),
|
|
1416
|
+
submitted && submittedValues.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
1417
|
+
role: "status",
|
|
1418
|
+
className: "border-success bg-success-subtle rounded-lg border p-3",
|
|
1419
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
1420
|
+
className: "text-success-fg mb-2 text-sm font-medium",
|
|
1421
|
+
children: "제출된 값:"
|
|
1422
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
1423
|
+
className: "text-success-fg gap-element flex flex-col text-sm",
|
|
1424
|
+
children: submittedValues.map((val, i) => /* @__PURE__ */ jsxs("li", { children: [
|
|
1425
|
+
formatTemplate(itemLabel, i + 1),
|
|
1426
|
+
": ",
|
|
1427
|
+
/* @__PURE__ */ jsx("strong", { children: val })
|
|
1428
|
+
] }, i))
|
|
1429
|
+
})]
|
|
1430
|
+
})
|
|
1431
|
+
]
|
|
1405
1432
|
});
|
|
1406
1433
|
}
|
|
1407
1434
|
//#endregion
|
|
@@ -1413,10 +1440,16 @@ function formatFileSize(bytes) {
|
|
|
1413
1440
|
}
|
|
1414
1441
|
/** Renders the file upload form component. */
|
|
1415
1442
|
function FileUploadForm({ accept = "image/*,.pdf,.doc,.docx", showPreview = true, showFileInfo = true, showDescription = true, descriptionRows = 3, titleRequired = true, maxFileSize, onSubmit, onFileChange, onPreview, columnMapping, labels = {}, ariaLabel }) {
|
|
1416
|
-
var _labels$titleLabel, _labels$titlePlacehol, _labels$descriptionLa, _labels$descriptionPl, _labels$fileLabel, _labels$columnMapping, _labels$submitButton, _labels$successMessag;
|
|
1443
|
+
var _labels$titleLabel, _labels$titlePlacehol, _labels$descriptionLa, _labels$descriptionPl, _labels$fileLabel, _labels$columnMapping, _labels$submitButton, _labels$submitError, _labels$successMessag;
|
|
1444
|
+
const fileId = useId();
|
|
1417
1445
|
const [selectedFile, setSelectedFile] = useState(null);
|
|
1418
1446
|
const [preview, setPreview] = useState(null);
|
|
1419
1447
|
const [submitted, setSubmitted] = useState(false);
|
|
1448
|
+
useEffect(() => {
|
|
1449
|
+
if (!submitted) return;
|
|
1450
|
+
const timer = setTimeout(() => setSubmitted(false), 3e3);
|
|
1451
|
+
return () => clearTimeout(timer);
|
|
1452
|
+
}, [submitted]);
|
|
1420
1453
|
const [fileSizeError, setFileSizeError] = useState(null);
|
|
1421
1454
|
const form = useFormStore({
|
|
1422
1455
|
defaultValues: {
|
|
@@ -1434,14 +1467,14 @@ function FileUploadForm({ accept = "image/*,.pdf,.doc,.docx", showPreview = true
|
|
|
1434
1467
|
}
|
|
1435
1468
|
return errors;
|
|
1436
1469
|
},
|
|
1437
|
-
onSubmit: (values) => {
|
|
1438
|
-
setSubmitted(
|
|
1439
|
-
|
|
1440
|
-
if (onSubmit) onSubmit({
|
|
1470
|
+
onSubmit: async (values) => {
|
|
1471
|
+
setSubmitted(false);
|
|
1472
|
+
if (onSubmit) await onSubmit({
|
|
1441
1473
|
title: values.title,
|
|
1442
1474
|
description: values.description,
|
|
1443
1475
|
file: selectedFile
|
|
1444
1476
|
});
|
|
1477
|
+
setSubmitted(true);
|
|
1445
1478
|
}
|
|
1446
1479
|
});
|
|
1447
1480
|
const handleFileChange = (e) => {
|
|
@@ -1473,111 +1506,128 @@ function FileUploadForm({ accept = "image/*,.pdf,.doc,.docx", showPreview = true
|
|
|
1473
1506
|
className: "gap-group flex flex-col",
|
|
1474
1507
|
"data-opt-id": "4E3MD",
|
|
1475
1508
|
"data-opt-slug": "form-upload.FileUploadForm",
|
|
1476
|
-
children: [
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
/* @__PURE__ */ jsx(FormLabel, {
|
|
1484
|
-
name: "title",
|
|
1485
|
-
children: (_labels$titleLabel = labels.titleLabel) !== null && _labels$titleLabel !== void 0 ? _labels$titleLabel : "제목"
|
|
1486
|
-
}),
|
|
1487
|
-
/* @__PURE__ */ jsx(FormInput, {
|
|
1488
|
-
name: "title",
|
|
1489
|
-
placeholder: (_labels$titlePlacehol = labels.titlePlaceholder) !== null && _labels$titlePlacehol !== void 0 ? _labels$titlePlacehol : "파일 제목을 입력하세요"
|
|
1490
|
-
}),
|
|
1491
|
-
/* @__PURE__ */ jsx(FormError, { name: "title" })
|
|
1492
|
-
]
|
|
1493
|
-
}),
|
|
1494
|
-
showDescription && /* @__PURE__ */ jsxs("div", {
|
|
1495
|
-
className: "gap-element flex flex-col",
|
|
1496
|
-
children: [/* @__PURE__ */ jsx(FormLabel, {
|
|
1497
|
-
name: "description",
|
|
1498
|
-
children: (_labels$descriptionLa = labels.descriptionLabel) !== null && _labels$descriptionLa !== void 0 ? _labels$descriptionLa : "설명"
|
|
1499
|
-
}), /* @__PURE__ */ jsx(FormTextarea, {
|
|
1500
|
-
name: "description",
|
|
1501
|
-
placeholder: (_labels$descriptionPl = labels.descriptionPlaceholder) !== null && _labels$descriptionPl !== void 0 ? _labels$descriptionPl : "파일에 대한 설명을 입력하세요",
|
|
1502
|
-
rows: descriptionRows,
|
|
1503
|
-
resize: "none"
|
|
1504
|
-
})]
|
|
1505
|
-
}),
|
|
1506
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1507
|
-
className: "gap-element flex flex-col",
|
|
1508
|
-
children: [
|
|
1509
|
-
/* @__PURE__ */ jsx("label", {
|
|
1510
|
-
className: "text-text-primary text-sm font-medium",
|
|
1511
|
-
children: (_labels$fileLabel = labels.fileLabel) !== null && _labels$fileLabel !== void 0 ? _labels$fileLabel : "파일 선택"
|
|
1512
|
-
}),
|
|
1513
|
-
/* @__PURE__ */ jsx("div", {
|
|
1514
|
-
className: "relative",
|
|
1515
|
-
children: /* @__PURE__ */ jsx("input", {
|
|
1516
|
-
type: "file",
|
|
1517
|
-
onChange: handleFileChange,
|
|
1518
|
-
accept,
|
|
1519
|
-
className: "border-border bg-surface text-text-primary file:bg-accent-subtle file:text-accent hover:file:bg-accent-subtle block w-full cursor-pointer rounded-lg border px-4 py-2.5 text-sm file:mr-4 file:cursor-pointer file:rounded-md file:border-0 file:px-3 file:py-1 file:text-sm file:font-medium"
|
|
1520
|
-
})
|
|
1521
|
-
}),
|
|
1522
|
-
fileSizeError && /* @__PURE__ */ jsx("p", {
|
|
1523
|
-
className: "text-danger-fg text-xs",
|
|
1524
|
-
children: fileSizeError
|
|
1525
|
-
})
|
|
1526
|
-
]
|
|
1527
|
-
}),
|
|
1528
|
-
selectedFile && showFileInfo && /* @__PURE__ */ jsx("div", {
|
|
1529
|
-
className: "border-border-subtle rounded-lg border p-4",
|
|
1530
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
1531
|
-
className: "gap-element flex flex-col",
|
|
1509
|
+
children: [
|
|
1510
|
+
/* @__PURE__ */ jsxs(FormRoot, {
|
|
1511
|
+
store: form,
|
|
1512
|
+
"aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : "파일 업로드 폼",
|
|
1513
|
+
children: [
|
|
1514
|
+
/* @__PURE__ */ jsxs(FormField, {
|
|
1515
|
+
name: "title",
|
|
1532
1516
|
children: [
|
|
1533
|
-
/* @__PURE__ */
|
|
1534
|
-
|
|
1535
|
-
children:
|
|
1536
|
-
className: "text-text-primary font-medium",
|
|
1537
|
-
children: selectedFile.name
|
|
1538
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
1539
|
-
className: "text-text-tertiary",
|
|
1540
|
-
children: formatFileSize(selectedFile.size)
|
|
1541
|
-
})]
|
|
1517
|
+
/* @__PURE__ */ jsx(FormLabel, {
|
|
1518
|
+
name: "title",
|
|
1519
|
+
children: (_labels$titleLabel = labels.titleLabel) !== null && _labels$titleLabel !== void 0 ? _labels$titleLabel : "제목"
|
|
1542
1520
|
}),
|
|
1543
|
-
/* @__PURE__ */
|
|
1544
|
-
|
|
1545
|
-
|
|
1521
|
+
/* @__PURE__ */ jsx(FormInput, {
|
|
1522
|
+
name: "title",
|
|
1523
|
+
placeholder: (_labels$titlePlacehol = labels.titlePlaceholder) !== null && _labels$titlePlacehol !== void 0 ? _labels$titlePlacehol : "파일 제목을 입력하세요"
|
|
1524
|
+
}),
|
|
1525
|
+
/* @__PURE__ */ jsx(FormError, { name: "title" })
|
|
1526
|
+
]
|
|
1527
|
+
}),
|
|
1528
|
+
showDescription && /* @__PURE__ */ jsxs(FormField, {
|
|
1529
|
+
name: "description",
|
|
1530
|
+
children: [/* @__PURE__ */ jsx(FormLabel, {
|
|
1531
|
+
name: "description",
|
|
1532
|
+
children: (_labels$descriptionLa = labels.descriptionLabel) !== null && _labels$descriptionLa !== void 0 ? _labels$descriptionLa : "설명"
|
|
1533
|
+
}), /* @__PURE__ */ jsx(FormTextarea, {
|
|
1534
|
+
name: "description",
|
|
1535
|
+
placeholder: (_labels$descriptionPl = labels.descriptionPlaceholder) !== null && _labels$descriptionPl !== void 0 ? _labels$descriptionPl : "파일에 대한 설명을 입력하세요",
|
|
1536
|
+
rows: descriptionRows,
|
|
1537
|
+
resize: "none"
|
|
1538
|
+
})]
|
|
1539
|
+
}),
|
|
1540
|
+
/* @__PURE__ */ jsxs(FormField, {
|
|
1541
|
+
name: "file",
|
|
1542
|
+
children: [
|
|
1543
|
+
/* @__PURE__ */ jsx("label", {
|
|
1544
|
+
htmlFor: fileId,
|
|
1545
|
+
className: "text-text-primary text-sm font-medium",
|
|
1546
|
+
children: (_labels$fileLabel = labels.fileLabel) !== null && _labels$fileLabel !== void 0 ? _labels$fileLabel : "파일 선택"
|
|
1546
1547
|
}),
|
|
1547
|
-
|
|
1548
|
-
className: "
|
|
1549
|
-
children: /* @__PURE__ */ jsx("
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1548
|
+
/* @__PURE__ */ jsx("div", {
|
|
1549
|
+
className: "relative",
|
|
1550
|
+
children: /* @__PURE__ */ jsx("input", {
|
|
1551
|
+
id: fileId,
|
|
1552
|
+
type: "file",
|
|
1553
|
+
disabled: form.isSubmitting(),
|
|
1554
|
+
"aria-invalid": Boolean(fileSizeError),
|
|
1555
|
+
"aria-describedby": fileSizeError ? `${fileId}-error` : void 0,
|
|
1556
|
+
onChange: handleFileChange,
|
|
1557
|
+
accept,
|
|
1558
|
+
className: "border-border bg-surface text-text-primary file:bg-accent-subtle file:text-accent hover:file:bg-accent-subtle block w-full cursor-pointer rounded-lg border px-4 py-2.5 text-sm file:mr-4 file:cursor-pointer file:rounded-md file:border-0 file:px-3 file:py-1 file:text-sm file:font-medium"
|
|
1553
1559
|
})
|
|
1560
|
+
}),
|
|
1561
|
+
fileSizeError && /* @__PURE__ */ jsx("p", {
|
|
1562
|
+
id: `${fileId}-error`,
|
|
1563
|
+
role: "alert",
|
|
1564
|
+
className: "text-danger-fg text-xs",
|
|
1565
|
+
children: fileSizeError
|
|
1554
1566
|
})
|
|
1555
1567
|
]
|
|
1568
|
+
}),
|
|
1569
|
+
selectedFile && showFileInfo && /* @__PURE__ */ jsx("div", {
|
|
1570
|
+
className: "border-border-subtle rounded-lg border p-4",
|
|
1571
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1572
|
+
className: "gap-element flex flex-col",
|
|
1573
|
+
children: [
|
|
1574
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1575
|
+
className: "flex items-center justify-between text-sm",
|
|
1576
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1577
|
+
className: "text-text-primary font-medium",
|
|
1578
|
+
children: selectedFile.name
|
|
1579
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1580
|
+
className: "text-text-tertiary",
|
|
1581
|
+
children: formatFileSize(selectedFile.size)
|
|
1582
|
+
})]
|
|
1583
|
+
}),
|
|
1584
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1585
|
+
className: "text-text-tertiary text-xs",
|
|
1586
|
+
children: ["타입: ", selectedFile.type || "알 수 없음"]
|
|
1587
|
+
}),
|
|
1588
|
+
showPreview && preview && /* @__PURE__ */ jsx("div", {
|
|
1589
|
+
className: "border-border-subtle overflow-hidden rounded-lg border",
|
|
1590
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
1591
|
+
src: preview,
|
|
1592
|
+
alt: "미리보기",
|
|
1593
|
+
className: "max-h-48 w-full object-contain"
|
|
1594
|
+
})
|
|
1595
|
+
})
|
|
1596
|
+
]
|
|
1597
|
+
})
|
|
1598
|
+
}),
|
|
1599
|
+
columnMapping && selectedFile && /* @__PURE__ */ jsx("div", {
|
|
1600
|
+
className: "gap-element flex flex-col",
|
|
1601
|
+
"aria-label": (_labels$columnMapping = labels.columnMappingLabel) !== null && _labels$columnMapping !== void 0 ? _labels$columnMapping : "Column mapping",
|
|
1602
|
+
children: columnMapping
|
|
1603
|
+
}),
|
|
1604
|
+
/* @__PURE__ */ jsx(FormSubmit, {
|
|
1605
|
+
disabled: form.isSubmitting(),
|
|
1606
|
+
children: (_labels$submitButton = labels.submitButton) !== null && _labels$submitButton !== void 0 ? _labels$submitButton : "업로드"
|
|
1556
1607
|
})
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
children: (_labels$successMessag = labels.successMessage) !== null && _labels$successMessag !== void 0 ? _labels$successMessag : "업로드가 완료되었습니다!"
|
|
1571
|
-
})]
|
|
1608
|
+
]
|
|
1609
|
+
}),
|
|
1610
|
+
form.getSubmitError() !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
1611
|
+
role: "alert",
|
|
1612
|
+
className: "border-danger bg-danger-subtle text-danger-fg rounded-lg border p-3 text-sm",
|
|
1613
|
+
children: (_labels$submitError = labels.submitError) !== null && _labels$submitError !== void 0 ? _labels$submitError : "처리에 실패했습니다. 다시 시도해주세요."
|
|
1614
|
+
}),
|
|
1615
|
+
submitted && /* @__PURE__ */ jsx("div", {
|
|
1616
|
+
role: "status",
|
|
1617
|
+
className: "border-success bg-success-subtle text-success-fg rounded-lg border p-3 text-sm",
|
|
1618
|
+
children: (_labels$successMessag = labels.successMessage) !== null && _labels$successMessag !== void 0 ? _labels$successMessag : "업로드가 완료되었습니다!"
|
|
1619
|
+
})
|
|
1620
|
+
]
|
|
1572
1621
|
});
|
|
1573
1622
|
}
|
|
1574
1623
|
//#endregion
|
|
1575
1624
|
//#region src/shells/wizard-form.tsx
|
|
1576
1625
|
/** Renders the wizard form component. */
|
|
1577
1626
|
function WizardForm({ fields, steps, showReview = true, onSubmit, onStepChange, resetOnSuccess = false, labels = {}, ariaLabel }) {
|
|
1578
|
-
var _labels$reviewTitle, _labels$stepsLabel, _labels$reviewTitle2, _labels$backButton, _labels$submitButton, _labels$nextButton, _labels$successMessag, _labels$resetLink;
|
|
1627
|
+
var _labels$reviewTitle, _labels$stepsLabel, _labels$reviewTitle2, _labels$backButton, _labels$submitButton, _labels$nextButton, _labels$submitError, _labels$successMessag, _labels$resetLink;
|
|
1579
1628
|
const [currentStep, setCurrentStep] = useState(0);
|
|
1580
1629
|
const [submitted, setSubmitted] = useState(false);
|
|
1630
|
+
const formId = useId();
|
|
1581
1631
|
const totalSteps = showReview ? steps.length + 1 : steps.length;
|
|
1582
1632
|
const isReviewStep = showReview && currentStep === steps.length;
|
|
1583
1633
|
const isLastStep = currentStep === totalSteps - 1;
|
|
@@ -1611,22 +1661,31 @@ function WizardForm({ fields, steps, showReview = true, onSubmit, onStepChange,
|
|
|
1611
1661
|
}
|
|
1612
1662
|
return errors;
|
|
1613
1663
|
},
|
|
1614
|
-
onSubmit: (values) => {
|
|
1664
|
+
onSubmit: async (values) => {
|
|
1615
1665
|
if (!isLastStep) {
|
|
1616
1666
|
const next = currentStep + 1;
|
|
1617
1667
|
setCurrentStep(next);
|
|
1618
1668
|
onStepChange === null || onStepChange === void 0 || onStepChange(next);
|
|
1619
1669
|
} else {
|
|
1670
|
+
setSubmitted(false);
|
|
1671
|
+
await (onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit(values));
|
|
1620
1672
|
setSubmitted(true);
|
|
1621
|
-
onSubmit === null || onSubmit === void 0 || onSubmit(values);
|
|
1622
|
-
if (resetOnSuccess) setTimeout(() => {
|
|
1623
|
-
setCurrentStep(0);
|
|
1624
|
-
setSubmitted(false);
|
|
1625
|
-
form.reset();
|
|
1626
|
-
}, 3e3);
|
|
1627
1673
|
}
|
|
1628
1674
|
}
|
|
1629
1675
|
});
|
|
1676
|
+
useEffect(() => {
|
|
1677
|
+
if (!submitted || !resetOnSuccess) return;
|
|
1678
|
+
const timer = setTimeout(() => {
|
|
1679
|
+
setCurrentStep(0);
|
|
1680
|
+
setSubmitted(false);
|
|
1681
|
+
form.reset();
|
|
1682
|
+
}, 3e3);
|
|
1683
|
+
return () => clearTimeout(timer);
|
|
1684
|
+
}, [
|
|
1685
|
+
submitted,
|
|
1686
|
+
resetOnSuccess,
|
|
1687
|
+
form
|
|
1688
|
+
]);
|
|
1630
1689
|
const handleBack = () => {
|
|
1631
1690
|
if (currentStep > 0) {
|
|
1632
1691
|
const prev = currentStep - 1;
|
|
@@ -1664,8 +1723,8 @@ function WizardForm({ fields, steps, showReview = true, onSubmit, onStepChange,
|
|
|
1664
1723
|
]
|
|
1665
1724
|
}, field.name);
|
|
1666
1725
|
}
|
|
1667
|
-
if (field.type === "checkbox") return /* @__PURE__ */ jsxs(
|
|
1668
|
-
|
|
1726
|
+
if (field.type === "checkbox") return /* @__PURE__ */ jsxs(FormField, {
|
|
1727
|
+
name: field.name,
|
|
1669
1728
|
children: [/* @__PURE__ */ jsxs("label", {
|
|
1670
1729
|
className: "text-text-primary gap-element flex items-center text-sm",
|
|
1671
1730
|
children: [/* @__PURE__ */ jsx(FormCheckbox, { name: field.name }), /* @__PURE__ */ jsx("span", { children: field.label })]
|
|
@@ -1673,13 +1732,10 @@ function WizardForm({ fields, steps, showReview = true, onSubmit, onStepChange,
|
|
|
1673
1732
|
}, field.name);
|
|
1674
1733
|
if (field.type === "textarea") {
|
|
1675
1734
|
var _field$rows, _field$resize;
|
|
1676
|
-
return /* @__PURE__ */ jsxs(
|
|
1677
|
-
|
|
1735
|
+
return /* @__PURE__ */ jsxs(FormField, {
|
|
1736
|
+
name: field.name,
|
|
1678
1737
|
children: [
|
|
1679
|
-
/* @__PURE__ */ jsx(FormLabel, {
|
|
1680
|
-
name: field.name,
|
|
1681
|
-
children: field.label
|
|
1682
|
-
}),
|
|
1738
|
+
/* @__PURE__ */ jsx(FormLabel, { children: field.label }),
|
|
1683
1739
|
/* @__PURE__ */ jsx(FormTextarea, {
|
|
1684
1740
|
name: field.name,
|
|
1685
1741
|
placeholder: field.placeholder,
|
|
@@ -1692,22 +1748,28 @@ function WizardForm({ fields, steps, showReview = true, onSubmit, onStepChange,
|
|
|
1692
1748
|
}
|
|
1693
1749
|
if (field.type === "select") {
|
|
1694
1750
|
var _field$options2;
|
|
1695
|
-
return /* @__PURE__ */ jsxs(
|
|
1696
|
-
|
|
1751
|
+
return /* @__PURE__ */ jsxs(FormField, {
|
|
1752
|
+
name: field.name,
|
|
1697
1753
|
children: [
|
|
1698
1754
|
/* @__PURE__ */ jsx(FormLabel, {
|
|
1699
|
-
|
|
1755
|
+
htmlFor: `${formId}-${field.name}`,
|
|
1700
1756
|
children: field.label
|
|
1701
1757
|
}),
|
|
1702
1758
|
/* @__PURE__ */ jsx(FormSelect, {
|
|
1703
1759
|
name: field.name,
|
|
1760
|
+
id: `${formId}-${field.name}`,
|
|
1761
|
+
"aria-label": field.label,
|
|
1762
|
+
"aria-describedby": form.getError(field.name) && form.getFieldTouched(field.name) ? `${formId}-${field.name}-error` : void 0,
|
|
1704
1763
|
placeholder: field.placeholder,
|
|
1705
1764
|
children: /* @__PURE__ */ jsx(FormSelectPopover, { children: (_field$options2 = field.options) === null || _field$options2 === void 0 ? void 0 : _field$options2.map((option) => /* @__PURE__ */ jsx(FormSelectItem, {
|
|
1706
1765
|
value: option.value,
|
|
1707
1766
|
children: option.label
|
|
1708
1767
|
}, option.value)) })
|
|
1709
1768
|
}),
|
|
1710
|
-
/* @__PURE__ */ jsx(FormError, {
|
|
1769
|
+
/* @__PURE__ */ jsx(FormError, {
|
|
1770
|
+
name: field.name,
|
|
1771
|
+
id: `${formId}-${field.name}-error`
|
|
1772
|
+
})
|
|
1711
1773
|
]
|
|
1712
1774
|
}, field.name);
|
|
1713
1775
|
}
|
|
@@ -1724,13 +1786,10 @@ function WizardForm({ fields, steps, showReview = true, onSubmit, onStepChange,
|
|
|
1724
1786
|
})]
|
|
1725
1787
|
})]
|
|
1726
1788
|
}, field.name);
|
|
1727
|
-
return /* @__PURE__ */ jsxs(
|
|
1728
|
-
|
|
1789
|
+
return /* @__PURE__ */ jsxs(FormField, {
|
|
1790
|
+
name: field.name,
|
|
1729
1791
|
children: [
|
|
1730
|
-
/* @__PURE__ */ jsx(FormLabel, {
|
|
1731
|
-
name: field.name,
|
|
1732
|
-
children: field.label
|
|
1733
|
-
}),
|
|
1792
|
+
/* @__PURE__ */ jsx(FormLabel, { children: field.label }),
|
|
1734
1793
|
/* @__PURE__ */ jsx(FormInput, {
|
|
1735
1794
|
name: field.name,
|
|
1736
1795
|
type: (_field$type = field.type) !== null && _field$type !== void 0 ? _field$type : "text",
|
|
@@ -1814,13 +1873,20 @@ function WizardForm({ fields, steps, showReview = true, onSubmit, onStepChange,
|
|
|
1814
1873
|
children: [currentStep > 0 ? /* @__PURE__ */ jsx("button", {
|
|
1815
1874
|
type: "button",
|
|
1816
1875
|
onClick: handleBack,
|
|
1876
|
+
disabled: form.isSubmitting(),
|
|
1817
1877
|
className: "border-border text-text-primary hover:bg-bg-subtle rounded-lg border px-4 py-2 text-sm font-medium",
|
|
1818
1878
|
children: (_labels$backButton = labels.backButton) !== null && _labels$backButton !== void 0 ? _labels$backButton : "이전"
|
|
1819
1879
|
}) : /* @__PURE__ */ jsx("div", {}), /* @__PURE__ */ jsx(FormSubmit, { children: isLastStep ? (_labels$submitButton = labels.submitButton) !== null && _labels$submitButton !== void 0 ? _labels$submitButton : "제출" : (_labels$nextButton = labels.nextButton) !== null && _labels$nextButton !== void 0 ? _labels$nextButton : "다음" })]
|
|
1820
1880
|
})
|
|
1821
1881
|
]
|
|
1822
1882
|
}),
|
|
1883
|
+
form.getSubmitError() !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
1884
|
+
role: "alert",
|
|
1885
|
+
className: "border-danger bg-danger-subtle text-danger-fg rounded-lg border p-3 text-sm",
|
|
1886
|
+
children: (_labels$submitError = labels.submitError) !== null && _labels$submitError !== void 0 ? _labels$submitError : "처리에 실패했습니다. 다시 시도해주세요."
|
|
1887
|
+
}),
|
|
1823
1888
|
submitted && /* @__PURE__ */ jsxs("div", {
|
|
1889
|
+
role: "status",
|
|
1824
1890
|
className: "border-success bg-success-subtle rounded-lg border p-4 text-center",
|
|
1825
1891
|
children: [/* @__PURE__ */ jsx("p", {
|
|
1826
1892
|
className: "text-success-fg text-sm font-medium",
|
|
@@ -1873,7 +1939,7 @@ const COLOR_PRESETS = [
|
|
|
1873
1939
|
"#f97316",
|
|
1874
1940
|
"#14b8a6"
|
|
1875
1941
|
];
|
|
1876
|
-
const defaultLabels$
|
|
1942
|
+
const defaultLabels$28 = {
|
|
1877
1943
|
eventLabelPrefix: "Event",
|
|
1878
1944
|
defaultAriaLabel: "Event icon"
|
|
1879
1945
|
};
|
|
@@ -1904,7 +1970,7 @@ function getEventIconStyle(color) {
|
|
|
1904
1970
|
/** Renders the event icon component. */
|
|
1905
1971
|
function EventIcon({ icon, color, size = "md", className, labels: customLabels }) {
|
|
1906
1972
|
var _iconEntry$label;
|
|
1907
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
1973
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$28), customLabels);
|
|
1908
1974
|
const sizes = SIZE_MAP[size];
|
|
1909
1975
|
const resolvedColor = (color === null || color === void 0 ? void 0 : color.trim()) ? color : void 0;
|
|
1910
1976
|
const iconEntry = typeof icon === "string" ? getIconRegistryEntry(icon) : void 0;
|
|
@@ -1996,14 +2062,14 @@ function ConnectionIndicator({ status, tone, label, showLabel = true, pulse, cla
|
|
|
1996
2062
|
ConnectionIndicator.displayName = "ConnectionIndicator";
|
|
1997
2063
|
//#endregion
|
|
1998
2064
|
//#region src/shells/floating-action-bar.tsx
|
|
1999
|
-
const defaultLabels$
|
|
2065
|
+
const defaultLabels$27 = {
|
|
2000
2066
|
toolbarAriaLabel: "Actions",
|
|
2001
2067
|
selectedLabel: (count) => `${count} selected`,
|
|
2002
2068
|
dismissAriaLabel: "Dismiss"
|
|
2003
2069
|
};
|
|
2004
2070
|
/** Renders the floating action bar component. */
|
|
2005
2071
|
function FloatingActionBar({ actions, selectedCount, onAction, onDismiss, className, labels: customLabels }) {
|
|
2006
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
2072
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$27), customLabels);
|
|
2007
2073
|
if (actions.length === 0) return null;
|
|
2008
2074
|
return /* @__PURE__ */ jsxs("div", {
|
|
2009
2075
|
role: "toolbar",
|
|
@@ -2040,7 +2106,7 @@ function FloatingActionBar({ actions, selectedCount, onAction, onDismiss, classN
|
|
|
2040
2106
|
FloatingActionBar.displayName = "FloatingActionBar";
|
|
2041
2107
|
//#endregion
|
|
2042
2108
|
//#region src/shells/template-picker.tsx
|
|
2043
|
-
const defaultLabels$
|
|
2109
|
+
const defaultLabels$26 = {
|
|
2044
2110
|
ariaLabel: "Templates",
|
|
2045
2111
|
defaultCategory: "General",
|
|
2046
2112
|
searchPlaceholder: "Search templates...",
|
|
@@ -2048,7 +2114,7 @@ const defaultLabels$25 = {
|
|
|
2048
2114
|
};
|
|
2049
2115
|
/** Renders the template picker component. */
|
|
2050
2116
|
function TemplatePicker({ templates, selected, onSelect, labels: customLabels, showSearch = false, className }) {
|
|
2051
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
2117
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$26), customLabels);
|
|
2052
2118
|
const [search, setSearch] = React.useState("");
|
|
2053
2119
|
const filtered = React.useMemo(() => {
|
|
2054
2120
|
if (!showSearch || !search) return templates;
|
|
@@ -2134,7 +2200,7 @@ function TemplatePicker({ templates, selected, onSelect, labels: customLabels, s
|
|
|
2134
2200
|
TemplatePicker.displayName = "TemplatePicker";
|
|
2135
2201
|
//#endregion
|
|
2136
2202
|
//#region src/shells/code-snippet-viewer.tsx
|
|
2137
|
-
const defaultLabels$
|
|
2203
|
+
const defaultLabels$25 = {
|
|
2138
2204
|
copy: "Copy",
|
|
2139
2205
|
copied: "Copied!",
|
|
2140
2206
|
codeRegion: "Code snippet"
|
|
@@ -2172,7 +2238,7 @@ const syntaxThemeClasses = {
|
|
|
2172
2238
|
/** Renders the code snippet viewer component. */
|
|
2173
2239
|
function CodeSnippetViewer({ code, language = "text", title, showLineNumbers = true, showCopyButton = true, maxHeight = 400, syntaxTheme = "default", className, labels: customLabels }) {
|
|
2174
2240
|
var _syntaxThemeClasses$s;
|
|
2175
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
2241
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$25), customLabels);
|
|
2176
2242
|
const [copied, setCopied] = React.useState(false);
|
|
2177
2243
|
const lines = code.split("\n");
|
|
2178
2244
|
const theme = (_syntaxThemeClasses$s = syntaxThemeClasses[syntaxTheme]) !== null && _syntaxThemeClasses$s !== void 0 ? _syntaxThemeClasses$s : syntaxThemeClasses.default;
|
|
@@ -2224,7 +2290,7 @@ function CodeSnippetViewer({ code, language = "text", title, showLineNumbers = t
|
|
|
2224
2290
|
CodeSnippetViewer.displayName = "CodeSnippetViewer";
|
|
2225
2291
|
//#endregion
|
|
2226
2292
|
//#region src/shells/property-explorer.tsx
|
|
2227
|
-
const defaultLabels$
|
|
2293
|
+
const defaultLabels$24 = {
|
|
2228
2294
|
searchPlaceholder: "Search properties...",
|
|
2229
2295
|
noPropertiesFound: "No properties found",
|
|
2230
2296
|
edit: (property) => `${property} 편집`,
|
|
@@ -2232,7 +2298,7 @@ const defaultLabels$23 = {
|
|
|
2232
2298
|
};
|
|
2233
2299
|
/** Renders the property explorer component. */
|
|
2234
2300
|
function PropertyExplorer({ groups, onSelect, onEdit, className, labels: customLabels }) {
|
|
2235
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
2301
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$24), customLabels);
|
|
2236
2302
|
const [search, setSearch] = React.useState("");
|
|
2237
2303
|
const filtered = React.useMemo(() => {
|
|
2238
2304
|
if (!search) return groups;
|
|
@@ -2518,7 +2584,7 @@ function skipBlockComment(text, from) {
|
|
|
2518
2584
|
}
|
|
2519
2585
|
//#endregion
|
|
2520
2586
|
//#region src/shells/alert-builder.tsx
|
|
2521
|
-
const defaultLabels$
|
|
2587
|
+
const defaultLabels$23 = {
|
|
2522
2588
|
alertNameLabel: "Alert name",
|
|
2523
2589
|
conditionsLabel: "Conditions",
|
|
2524
2590
|
metricLabel: "Metric",
|
|
@@ -2589,7 +2655,7 @@ function AlertBuilder({ value, onChange, metrics = [
|
|
|
2589
2655
|
], labels: customLabels, className }) {
|
|
2590
2656
|
const resolvedMetrics = eventOptions ? eventOptions.map((e) => e.id) : metrics;
|
|
2591
2657
|
const metricLabelMap = eventOptions ? Object.fromEntries(eventOptions.map((e) => [e.id, e.name])) : null;
|
|
2592
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
2658
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$23), customLabels);
|
|
2593
2659
|
const alertNameId = React.useId();
|
|
2594
2660
|
const conditionsId = React.useId();
|
|
2595
2661
|
const checkFrequencyId = React.useId();
|
|
@@ -2744,7 +2810,7 @@ function AlertBuilder({ value, onChange, metrics = [
|
|
|
2744
2810
|
AlertBuilder.displayName = "AlertBuilder";
|
|
2745
2811
|
//#endregion
|
|
2746
2812
|
//#region src/shells/event-meta-editor.tsx
|
|
2747
|
-
const defaultLabels$
|
|
2813
|
+
const defaultLabels$22 = {
|
|
2748
2814
|
icon: "Icon",
|
|
2749
2815
|
color: "Color",
|
|
2750
2816
|
name: "Event name",
|
|
@@ -2762,7 +2828,7 @@ const defaultLabels$21 = {
|
|
|
2762
2828
|
};
|
|
2763
2829
|
/** Renders the event meta editor component. */
|
|
2764
2830
|
function EventMetaEditor({ value, onChange, icons, sections, footer, className, labels: customLabels }) {
|
|
2765
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
2831
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$22), customLabels);
|
|
2766
2832
|
const hasTags = value.tags.length > 0;
|
|
2767
2833
|
const nameId = React.useId();
|
|
2768
2834
|
const displayNameId = React.useId();
|
|
@@ -2885,10 +2951,10 @@ function EventMetaEditor({ value, onChange, icons, sections, footer, className,
|
|
|
2885
2951
|
EventMetaEditor.displayName = "EventMetaEditor";
|
|
2886
2952
|
//#endregion
|
|
2887
2953
|
//#region src/shells/widget-grid.tsx
|
|
2888
|
-
const defaultLabels$
|
|
2954
|
+
const defaultLabels$21 = { emptyMessage: "No widgets to display" };
|
|
2889
2955
|
/** Renders the widget grid component. */
|
|
2890
2956
|
function WidgetGrid({ widgets, cols = 12, rowHeight = 80, gap = 16, editable = false, onReorder, labels: customLabels, className }) {
|
|
2891
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
2957
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$21), customLabels);
|
|
2892
2958
|
const [dragIdx, setDragIdx] = React.useState(null);
|
|
2893
2959
|
const [overIdx, setOverIdx] = React.useState(null);
|
|
2894
2960
|
if (widgets.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
@@ -2933,7 +2999,7 @@ function WidgetGrid({ widgets, cols = 12, rowHeight = 80, gap = 16, editable = f
|
|
|
2933
2999
|
WidgetGrid.displayName = "WidgetGrid";
|
|
2934
3000
|
//#endregion
|
|
2935
3001
|
//#region src/shells/report-builder.tsx
|
|
2936
|
-
const defaultLabels$
|
|
3002
|
+
const defaultLabels$20 = {
|
|
2937
3003
|
stepsLabel: "Report steps",
|
|
2938
3004
|
stepType: "Chart Type",
|
|
2939
3005
|
stepConfig: "Data Config",
|
|
@@ -3009,7 +3075,7 @@ const STEPS = [
|
|
|
3009
3075
|
];
|
|
3010
3076
|
/** Renders the report builder component. */
|
|
3011
3077
|
function ReportBuilder({ chartTypes = DEFAULT_CHART_TYPES, dataSources = [], onSave, onCancel, configForm, styleForm, preview, onChartTypeChange, onDataSourceChange, onStepChange, selectedChartType: controlledChartType, selectedDataSource: controlledDataSource, labels: customLabels, className }) {
|
|
3012
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
3078
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$20), customLabels);
|
|
3013
3079
|
const [stepIndex, setStepIndex] = React.useState(0);
|
|
3014
3080
|
const [internalChartType, setInternalChartType] = React.useState(null);
|
|
3015
3081
|
const [internalDataSource, setInternalDataSource] = React.useState("");
|
|
@@ -3229,7 +3295,7 @@ function ReportBuilder({ chartTypes = DEFAULT_CHART_TYPES, dataSources = [], onS
|
|
|
3229
3295
|
ReportBuilder.displayName = "ReportBuilder";
|
|
3230
3296
|
//#endregion
|
|
3231
3297
|
//#region src/shells/audit-timeline.tsx
|
|
3232
|
-
const defaultLabels$
|
|
3298
|
+
const defaultLabels$19 = {
|
|
3233
3299
|
title: "변경 이력",
|
|
3234
3300
|
empty: "변경 이력이 없습니다",
|
|
3235
3301
|
expand: "상세 보기",
|
|
@@ -3308,7 +3374,7 @@ function DiffTable({ changes, labels }) {
|
|
|
3308
3374
|
}
|
|
3309
3375
|
/** Renders the audit timeline component. */
|
|
3310
3376
|
function AuditTimeline({ entries, labels: customLabels, className, onEntryClick }) {
|
|
3311
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
3377
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$19), customLabels);
|
|
3312
3378
|
const [expandedIds, setExpandedIds] = React.useState(/* @__PURE__ */ new Set());
|
|
3313
3379
|
const toggleExpanded = React.useCallback((id) => {
|
|
3314
3380
|
setExpandedIds((prev) => {
|
|
@@ -3431,7 +3497,7 @@ function AuditTimeline({ entries, labels: customLabels, className, onEntryClick
|
|
|
3431
3497
|
AuditTimeline.displayName = "AuditTimeline";
|
|
3432
3498
|
//#endregion
|
|
3433
3499
|
//#region src/shells/segment-builder.tsx
|
|
3434
|
-
const defaultLabels$
|
|
3500
|
+
const defaultLabels$18 = {
|
|
3435
3501
|
match: "Match",
|
|
3436
3502
|
ofTheFollowing: "of the following",
|
|
3437
3503
|
groupLabel: "Segment group",
|
|
@@ -3552,7 +3618,7 @@ function SegmentBuilder({ groups, onChange, eventOptions = [
|
|
|
3552
3618
|
"New Users",
|
|
3553
3619
|
"Power Users"
|
|
3554
3620
|
], className, labels: customLabels }) {
|
|
3555
|
-
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$
|
|
3621
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$18), customLabels);
|
|
3556
3622
|
const builderId = React.useId().replace(/:/g, "");
|
|
3557
3623
|
const nextIdRef = React.useRef(1);
|
|
3558
3624
|
const createId = React.useCallback(() => {
|
|
@@ -3764,6 +3830,703 @@ function SegmentBuilder({ groups, onChange, eventOptions = [
|
|
|
3764
3830
|
}
|
|
3765
3831
|
SegmentBuilder.displayName = "SegmentBuilder";
|
|
3766
3832
|
//#endregion
|
|
3833
|
+
//#region src/shells/criteria-builder.tsx
|
|
3834
|
+
const defaultLabels$17 = {
|
|
3835
|
+
builder: "조건 빌더",
|
|
3836
|
+
rootLogicLegend: "그룹 결합 방식",
|
|
3837
|
+
matchAllGroups: "모든 그룹 일치",
|
|
3838
|
+
matchAnyGroup: "하나 이상 일치",
|
|
3839
|
+
groupLogicLegend: (letter) => `그룹 ${letter} 조건 결합 방식`,
|
|
3840
|
+
matchAllCriteria: "모두 충족",
|
|
3841
|
+
matchAnyCriteria: "하나 이상 충족",
|
|
3842
|
+
and: "그리고",
|
|
3843
|
+
or: "또는",
|
|
3844
|
+
groupLabel: (letter) => `그룹 ${letter}`,
|
|
3845
|
+
criterionLabel: (letter, index) => `조건 ${letter}.${index}`,
|
|
3846
|
+
actionLabel: (action, target) => `${action}: ${target}`,
|
|
3847
|
+
addCriterion: "조건 추가",
|
|
3848
|
+
addGroup: "그룹 추가",
|
|
3849
|
+
kindMenuTitle: "조건 유형",
|
|
3850
|
+
duplicateCriterion: "조건 복제",
|
|
3851
|
+
removeCriterion: "조건 제거",
|
|
3852
|
+
moveUp: "위로 이동",
|
|
3853
|
+
moveDown: "아래로 이동",
|
|
3854
|
+
negate: "제외",
|
|
3855
|
+
duplicateGroup: "그룹 복제",
|
|
3856
|
+
removeGroup: "그룹 제거",
|
|
3857
|
+
emptyGroup: "이 그룹에는 아직 조건이 없습니다.",
|
|
3858
|
+
unknownKind: (kind) => `알 수 없는 조건 유형 "${kind}"`,
|
|
3859
|
+
unknownKindDescription: "이 조건은 표시할 수 없습니다. 유형을 바꾸거나 제거하세요.",
|
|
3860
|
+
replaceKind: "유형 바꾸기",
|
|
3861
|
+
emptyTitle: "조건이 없습니다",
|
|
3862
|
+
emptyDescription: "첫 그룹을 추가해 누가 포함되는지 정의하세요.",
|
|
3863
|
+
emptyAction: "첫 조건 추가",
|
|
3864
|
+
keyboardHint: "조건 추가 · 그룹 추가",
|
|
3865
|
+
maxGroupsReached: (max) => `그룹은 최대 ${max}개까지 추가할 수 있습니다.`,
|
|
3866
|
+
maxCriteriaReached: (max) => `한 그룹에는 조건을 최대 ${max}개까지 추가할 수 있습니다.`
|
|
3867
|
+
};
|
|
3868
|
+
/** `A`, `B`, … `Z`, `AA`, `AB` — the badge a group wears. */
|
|
3869
|
+
function criteriaGroupLetter(index) {
|
|
3870
|
+
let n = Math.max(0, Math.floor(index));
|
|
3871
|
+
let out = "";
|
|
3872
|
+
do {
|
|
3873
|
+
out = String.fromCharCode(65 + n % 26) + out;
|
|
3874
|
+
n = Math.floor(n / 26) - 1;
|
|
3875
|
+
} while (n >= 0);
|
|
3876
|
+
return out;
|
|
3877
|
+
}
|
|
3878
|
+
function collectIds(value) {
|
|
3879
|
+
const ids = /* @__PURE__ */ new Set();
|
|
3880
|
+
for (const group of value.groups) {
|
|
3881
|
+
ids.add(group.id);
|
|
3882
|
+
for (const criterion of group.criteria) ids.add(criterion.id);
|
|
3883
|
+
}
|
|
3884
|
+
return ids;
|
|
3885
|
+
}
|
|
3886
|
+
function uniqueId(base, taken) {
|
|
3887
|
+
if (!taken.has(base)) return base;
|
|
3888
|
+
let n = 2;
|
|
3889
|
+
while (taken.has(`${base}-${n}`)) n += 1;
|
|
3890
|
+
return `${base}-${n}`;
|
|
3891
|
+
}
|
|
3892
|
+
function replaceGroup(value, groupIndex, next) {
|
|
3893
|
+
return _objectSpread2(_objectSpread2({}, value), {}, { groups: value.groups.map((group, i) => i === groupIndex ? next : group) });
|
|
3894
|
+
}
|
|
3895
|
+
/**
|
|
3896
|
+
* Moves one criterion a step up or down inside its group. Returns the same
|
|
3897
|
+
* value when the move is impossible, so a caller can `===` to know nothing
|
|
3898
|
+
* changed.
|
|
3899
|
+
*/
|
|
3900
|
+
function criteriaBuilderMove(value, groupIndex, index, direction) {
|
|
3901
|
+
const group = value.groups[groupIndex];
|
|
3902
|
+
if (!group) return value;
|
|
3903
|
+
const target = direction === "up" ? index - 1 : index + 1;
|
|
3904
|
+
if (index < 0 || target < 0 || target >= group.criteria.length) return value;
|
|
3905
|
+
const criteria = [...group.criteria];
|
|
3906
|
+
const [moved] = criteria.splice(index, 1);
|
|
3907
|
+
criteria.splice(target, 0, moved);
|
|
3908
|
+
return replaceGroup(value, groupIndex, _objectSpread2(_objectSpread2({}, group), {}, { criteria }));
|
|
3909
|
+
}
|
|
3910
|
+
/**
|
|
3911
|
+
* Inserts a copy of one criterion *before* the original, so the copy takes the
|
|
3912
|
+
* original's place in the reading order and the original follows as the thing
|
|
3913
|
+
* to edit.
|
|
3914
|
+
*/
|
|
3915
|
+
function criteriaBuilderDuplicate(value, groupIndex, index, clone) {
|
|
3916
|
+
const group = value.groups[groupIndex];
|
|
3917
|
+
const original = group === null || group === void 0 ? void 0 : group.criteria[index];
|
|
3918
|
+
if (!group || !original) return value;
|
|
3919
|
+
const criteria = [...group.criteria];
|
|
3920
|
+
criteria.splice(index, 0, clone(original));
|
|
3921
|
+
return replaceGroup(value, groupIndex, _objectSpread2(_objectSpread2({}, group), {}, { criteria }));
|
|
3922
|
+
}
|
|
3923
|
+
/** Removes one criterion. The group stays, even when it empties. */
|
|
3924
|
+
function criteriaBuilderRemove(value, groupIndex, index) {
|
|
3925
|
+
const group = value.groups[groupIndex];
|
|
3926
|
+
if (!group || index < 0 || index >= group.criteria.length) return value;
|
|
3927
|
+
return replaceGroup(value, groupIndex, _objectSpread2(_objectSpread2({}, group), {}, { criteria: group.criteria.filter((_, i) => i !== index) }));
|
|
3928
|
+
}
|
|
3929
|
+
/** Appends a criterion to a group, or inserts it at `at`. */
|
|
3930
|
+
function criteriaBuilderInsert(value, groupIndex, criterion, at) {
|
|
3931
|
+
const group = value.groups[groupIndex];
|
|
3932
|
+
if (!group) return value;
|
|
3933
|
+
const criteria = [...group.criteria];
|
|
3934
|
+
const position = at === void 0 ? criteria.length : Math.max(0, Math.min(at, criteria.length));
|
|
3935
|
+
criteria.splice(position, 0, criterion);
|
|
3936
|
+
return replaceGroup(value, groupIndex, _objectSpread2(_objectSpread2({}, group), {}, { criteria }));
|
|
3937
|
+
}
|
|
3938
|
+
/** Removes one group. */
|
|
3939
|
+
function criteriaBuilderRemoveGroup(value, groupIndex) {
|
|
3940
|
+
if (groupIndex < 0 || groupIndex >= value.groups.length) return value;
|
|
3941
|
+
return _objectSpread2(_objectSpread2({}, value), {}, { groups: value.groups.filter((_, i) => i !== groupIndex) });
|
|
3942
|
+
}
|
|
3943
|
+
/** Inserts a copy of one group — every criterion cloned — before the original. */
|
|
3944
|
+
function criteriaBuilderDuplicateGroup(value, groupIndex, groupId, clone) {
|
|
3945
|
+
const group = value.groups[groupIndex];
|
|
3946
|
+
if (!group) return value;
|
|
3947
|
+
const copy = {
|
|
3948
|
+
id: groupId,
|
|
3949
|
+
logic: group.logic,
|
|
3950
|
+
criteria: group.criteria.map(clone)
|
|
3951
|
+
};
|
|
3952
|
+
const groups = [...value.groups];
|
|
3953
|
+
groups.splice(groupIndex, 0, copy);
|
|
3954
|
+
return _objectSpread2(_objectSpread2({}, value), {}, { groups });
|
|
3955
|
+
}
|
|
3956
|
+
const EDITABLE_TARGET = "input, textarea, select, [contenteditable=\"\"], [contenteditable=\"true\"], [role=\"combobox\"], [role=\"textbox\"], [role=\"menu\"], [role=\"menuitem\"], [role=\"listbox\"], [role=\"option\"]";
|
|
3957
|
+
function isEditableTarget(target) {
|
|
3958
|
+
return target instanceof Element && target.closest(EDITABLE_TARGET) !== null;
|
|
3959
|
+
}
|
|
3960
|
+
function sectionKinds(kinds) {
|
|
3961
|
+
const sections = [];
|
|
3962
|
+
const byHeading = /* @__PURE__ */ new Map();
|
|
3963
|
+
for (const option of kinds) {
|
|
3964
|
+
let section = byHeading.get(option.group);
|
|
3965
|
+
if (!section) {
|
|
3966
|
+
section = {
|
|
3967
|
+
heading: option.group,
|
|
3968
|
+
entries: []
|
|
3969
|
+
};
|
|
3970
|
+
byHeading.set(option.group, section);
|
|
3971
|
+
sections.push(section);
|
|
3972
|
+
}
|
|
3973
|
+
section.entries.push({
|
|
3974
|
+
key: option.kind,
|
|
3975
|
+
kind: option.kind,
|
|
3976
|
+
negate: false,
|
|
3977
|
+
option
|
|
3978
|
+
});
|
|
3979
|
+
if (option.negatedLabel) section.entries.push({
|
|
3980
|
+
key: `${option.kind}:not`,
|
|
3981
|
+
kind: option.kind,
|
|
3982
|
+
negate: true,
|
|
3983
|
+
option
|
|
3984
|
+
});
|
|
3985
|
+
}
|
|
3986
|
+
return [...sections.filter((s) => s.heading === void 0), ...sections.filter((s) => s.heading !== void 0)];
|
|
3987
|
+
}
|
|
3988
|
+
function KindMenu({ kinds, menuLabel, triggerLabel, triggerAriaLabel, triggerIcon, disabled = false, disabledReason, variant = "ghost", onPick, addTarget }) {
|
|
3989
|
+
const sections = React.useMemo(() => sectionKinds(kinds), [kinds]);
|
|
3990
|
+
const trigger = /* @__PURE__ */ jsxs(DropdownTrigger, {
|
|
3991
|
+
disabled,
|
|
3992
|
+
"aria-label": triggerAriaLabel,
|
|
3993
|
+
title: disabled ? disabledReason : void 0,
|
|
3994
|
+
"data-criteria-add": addTarget,
|
|
3995
|
+
className: cn("inline-flex cursor-pointer items-center justify-center rounded-lg font-medium transition-colors", "h-[var(--opt-control-sm)] gap-[var(--opt-space-1-5)] px-[var(--opt-control-padding-sm)] text-xs", variant === "secondary" ? "border-border bg-surface text-text-primary hover:bg-bg-subtle active:bg-bg-muted border" : "text-text-secondary hover:bg-bg-subtle active:bg-bg-muted", "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50", "[&_svg]:size-3.5", OPT_FOCUS_VISIBLE),
|
|
3996
|
+
children: [triggerIcon, triggerLabel]
|
|
3997
|
+
});
|
|
3998
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, {
|
|
3999
|
+
animated: false,
|
|
4000
|
+
children: [trigger, /* @__PURE__ */ jsx(DropdownContent, {
|
|
4001
|
+
"aria-label": menuLabel,
|
|
4002
|
+
"aria-labelledby": void 0,
|
|
4003
|
+
className: "min-w-56",
|
|
4004
|
+
children: sections.map((section, si) => {
|
|
4005
|
+
var _section$heading;
|
|
4006
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
4007
|
+
si > 0 && /* @__PURE__ */ jsx(DropdownSeparator, {}),
|
|
4008
|
+
section.heading !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
4009
|
+
role: "presentation",
|
|
4010
|
+
className: "text-text-tertiary px-2 pt-1.5 pb-1 text-[11px] font-semibold tracking-wide uppercase",
|
|
4011
|
+
children: section.heading
|
|
4012
|
+
}),
|
|
4013
|
+
section.entries.map((entry) => /* @__PURE__ */ jsxs(DropdownItem, {
|
|
4014
|
+
onClick: () => onPick(entry.kind, entry.negate),
|
|
4015
|
+
className: "flex items-start gap-2",
|
|
4016
|
+
children: [entry.option.icon && /* @__PURE__ */ jsx("span", {
|
|
4017
|
+
className: "text-text-tertiary mt-0.5 shrink-0 [&_svg]:size-3.5",
|
|
4018
|
+
children: entry.option.icon
|
|
4019
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
4020
|
+
className: "flex min-w-0 flex-col",
|
|
4021
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4022
|
+
className: cn("text-sm", entry.negate && "text-danger-fg"),
|
|
4023
|
+
children: entry.negate ? entry.option.negatedLabel : entry.option.label
|
|
4024
|
+
}), !entry.negate && entry.option.description && /* @__PURE__ */ jsx("span", {
|
|
4025
|
+
className: "text-text-tertiary text-xs",
|
|
4026
|
+
children: entry.option.description
|
|
4027
|
+
})]
|
|
4028
|
+
})]
|
|
4029
|
+
}, entry.key))
|
|
4030
|
+
] }, (_section$heading = section.heading) !== null && _section$heading !== void 0 ? _section$heading : "__none");
|
|
4031
|
+
})
|
|
4032
|
+
})]
|
|
4033
|
+
});
|
|
4034
|
+
}
|
|
4035
|
+
function IconAction({ icon, label, onClick, disabled = false, danger = false }) {
|
|
4036
|
+
return /* @__PURE__ */ jsx("button", {
|
|
4037
|
+
type: "button",
|
|
4038
|
+
onClick,
|
|
4039
|
+
disabled,
|
|
4040
|
+
"aria-label": label,
|
|
4041
|
+
title: label,
|
|
4042
|
+
className: cn("inline-flex size-7 shrink-0 items-center justify-center rounded-md transition-colors [&_svg]:size-3.5", danger ? "text-text-tertiary hover:bg-danger-subtle hover:text-danger-fg" : "text-text-tertiary hover:bg-bg-muted hover:text-text-primary", "disabled:pointer-events-none disabled:opacity-40", OPT_FOCUS_VISIBLE),
|
|
4043
|
+
children: icon
|
|
4044
|
+
});
|
|
4045
|
+
}
|
|
4046
|
+
function LogicDivider({ label, emphasis }) {
|
|
4047
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4048
|
+
role: "separator",
|
|
4049
|
+
"aria-label": label,
|
|
4050
|
+
className: cn("flex items-center", emphasis === "root" ? "gap-group" : "gap-element"),
|
|
4051
|
+
children: [
|
|
4052
|
+
/* @__PURE__ */ jsx("span", { className: cn("h-px flex-1", emphasis === "root" ? "bg-border" : "bg-border-subtle") }),
|
|
4053
|
+
/* @__PURE__ */ jsx("span", {
|
|
4054
|
+
className: cn("text-[11px] font-semibold tracking-wide uppercase", emphasis === "root" ? "bg-bg-subtle text-text-secondary border-border rounded-full border px-2 py-0.5" : "text-text-tertiary"),
|
|
4055
|
+
children: label
|
|
4056
|
+
}),
|
|
4057
|
+
/* @__PURE__ */ jsx("span", { className: cn("h-px flex-1", emphasis === "root" ? "bg-border" : "bg-border-subtle") })
|
|
4058
|
+
]
|
|
4059
|
+
});
|
|
4060
|
+
}
|
|
4061
|
+
function Lettermark({ letter }) {
|
|
4062
|
+
return /* @__PURE__ */ jsx("span", {
|
|
4063
|
+
"aria-hidden": "true",
|
|
4064
|
+
className: "bg-accent-subtle text-accent inline-flex size-6 shrink-0 items-center justify-center rounded-md text-xs font-semibold tabular-nums",
|
|
4065
|
+
children: letter
|
|
4066
|
+
});
|
|
4067
|
+
}
|
|
4068
|
+
/**
|
|
4069
|
+
* CriteriaBuilder — a two-level tree of criteria, edited as sentences.
|
|
4070
|
+
*
|
|
4071
|
+
* The builder owns what every criteria editor needs and nothing a particular
|
|
4072
|
+
* product does: groups and their AND/OR, the order of criteria, negation,
|
|
4073
|
+
* inline errors, the "add" menu, and the keyboard. The consumer owns the
|
|
4074
|
+
* criterion type and renders each one — usually as `Expression` chips whose
|
|
4075
|
+
* values open an editor — so the same shell serves a cohort of users, an
|
|
4076
|
+
* alert condition, or a feature-flag rollout without knowing which.
|
|
4077
|
+
*
|
|
4078
|
+
* Kinds the builder does not know render as an invalid row with a warning and
|
|
4079
|
+
* a replace/remove pair, never as some other kind's fields: a criterion saved
|
|
4080
|
+
* by a newer client should look broken, not silently different.
|
|
4081
|
+
*
|
|
4082
|
+
* @example
|
|
4083
|
+
* ```tsx
|
|
4084
|
+
* <CriteriaBuilder
|
|
4085
|
+
* value={value}
|
|
4086
|
+
* onChange={setValue}
|
|
4087
|
+
* kinds={[
|
|
4088
|
+
* { kind: "performed", label: "이벤트를 수행함", negatedLabel: "이벤트를 수행하지 않음" },
|
|
4089
|
+
* { kind: "property", label: "속성이 일치함" },
|
|
4090
|
+
* ]}
|
|
4091
|
+
* createCriterion={(kind, negate) => ({ id: nextId(), kind, negate, event: "" })}
|
|
4092
|
+
* renderCriterion={(c, api) => (
|
|
4093
|
+
* <ExpressionGroup>
|
|
4094
|
+
* <Expression description="이벤트" value={c.event} onClick={() => open(c.id)} />
|
|
4095
|
+
* </ExpressionGroup>
|
|
4096
|
+
* )}
|
|
4097
|
+
* />
|
|
4098
|
+
* ```
|
|
4099
|
+
*/
|
|
4100
|
+
function CriteriaBuilder({ value, onChange, kinds, createCriterion, renderCriterion, cloneCriterion, createGroupId, errors, maxGroups = 10, maxCriteriaPerGroup = 20, allowNegation = true, disabled = false, aside, labels: customLabels, className, "aria-label": ariaLabel }) {
|
|
4101
|
+
const labels = React.useMemo(() => _objectSpread2(_objectSpread2({}, defaultLabels$17), customLabels), [customLabels]);
|
|
4102
|
+
const baseId = React.useId().replace(/:/g, "");
|
|
4103
|
+
const nextGroupRef = React.useRef(1);
|
|
4104
|
+
const rootRef = React.useRef(null);
|
|
4105
|
+
const [pendingOpen, setPendingOpen] = React.useState(null);
|
|
4106
|
+
const knownKinds = React.useMemo(() => new Set(kinds.map((k) => k.kind)), [kinds]);
|
|
4107
|
+
const groupsFull = value.groups.length >= maxGroups;
|
|
4108
|
+
const newGroupId = React.useCallback(() => {
|
|
4109
|
+
const taken = collectIds(value);
|
|
4110
|
+
if (createGroupId) return uniqueId(createGroupId(), taken);
|
|
4111
|
+
let id = "";
|
|
4112
|
+
do
|
|
4113
|
+
id = `group-${nextGroupRef.current++}`;
|
|
4114
|
+
while (taken.has(id));
|
|
4115
|
+
return id;
|
|
4116
|
+
}, [createGroupId, value]);
|
|
4117
|
+
const clone = React.useCallback((criterion, taken) => {
|
|
4118
|
+
if (cloneCriterion) return cloneCriterion(criterion);
|
|
4119
|
+
const id = uniqueId(`${criterion.id}-copy`, taken);
|
|
4120
|
+
taken.add(id);
|
|
4121
|
+
return _objectSpread2(_objectSpread2({}, criterion), {}, { id });
|
|
4122
|
+
}, [cloneCriterion]);
|
|
4123
|
+
const addGroup = React.useCallback(() => {
|
|
4124
|
+
if (disabled || groupsFull) return null;
|
|
4125
|
+
const id = newGroupId();
|
|
4126
|
+
onChange(_objectSpread2(_objectSpread2({}, value), {}, { groups: [...value.groups, {
|
|
4127
|
+
id,
|
|
4128
|
+
logic: "and",
|
|
4129
|
+
criteria: []
|
|
4130
|
+
}] }));
|
|
4131
|
+
return id;
|
|
4132
|
+
}, [
|
|
4133
|
+
disabled,
|
|
4134
|
+
groupsFull,
|
|
4135
|
+
newGroupId,
|
|
4136
|
+
onChange,
|
|
4137
|
+
value
|
|
4138
|
+
]);
|
|
4139
|
+
const addCriterion = React.useCallback((groupIndex, kind, negate) => {
|
|
4140
|
+
const group = value.groups[groupIndex];
|
|
4141
|
+
if (!group || group.criteria.length >= maxCriteriaPerGroup) return;
|
|
4142
|
+
onChange(criteriaBuilderInsert(value, groupIndex, createCriterion(kind, negate)));
|
|
4143
|
+
}, [
|
|
4144
|
+
createCriterion,
|
|
4145
|
+
maxCriteriaPerGroup,
|
|
4146
|
+
onChange,
|
|
4147
|
+
value
|
|
4148
|
+
]);
|
|
4149
|
+
const addFirst = React.useCallback((kind, negate) => {
|
|
4150
|
+
if (disabled) return;
|
|
4151
|
+
onChange(_objectSpread2(_objectSpread2({}, value), {}, { groups: [{
|
|
4152
|
+
id: newGroupId(),
|
|
4153
|
+
logic: "and",
|
|
4154
|
+
criteria: [createCriterion(kind, negate)]
|
|
4155
|
+
}] }));
|
|
4156
|
+
}, [
|
|
4157
|
+
createCriterion,
|
|
4158
|
+
disabled,
|
|
4159
|
+
newGroupId,
|
|
4160
|
+
onChange,
|
|
4161
|
+
value
|
|
4162
|
+
]);
|
|
4163
|
+
const replaceCriterion = React.useCallback((groupIndex, index, kind, negate) => {
|
|
4164
|
+
const group = value.groups[groupIndex];
|
|
4165
|
+
const current = group === null || group === void 0 ? void 0 : group.criteria[index];
|
|
4166
|
+
if (!group || !current) return;
|
|
4167
|
+
const replacement = _objectSpread2(_objectSpread2({}, createCriterion(kind, negate)), {}, { id: current.id });
|
|
4168
|
+
onChange(replaceGroup(value, groupIndex, _objectSpread2(_objectSpread2({}, group), {}, { criteria: group.criteria.map((c, i) => i === index ? replacement : c) })));
|
|
4169
|
+
}, [
|
|
4170
|
+
createCriterion,
|
|
4171
|
+
onChange,
|
|
4172
|
+
value
|
|
4173
|
+
]);
|
|
4174
|
+
const updateCriterion = React.useCallback((groupIndex, index, patch) => {
|
|
4175
|
+
const group = value.groups[groupIndex];
|
|
4176
|
+
if (!group) return;
|
|
4177
|
+
onChange(replaceGroup(value, groupIndex, _objectSpread2(_objectSpread2({}, group), {}, { criteria: group.criteria.map((c, i) => i === index ? _objectSpread2(_objectSpread2({}, c), patch) : c) })));
|
|
4178
|
+
}, [onChange, value]);
|
|
4179
|
+
const findAddTrigger = React.useCallback((groupId) => {
|
|
4180
|
+
var _rootRef$current$quer, _rootRef$current;
|
|
4181
|
+
return (_rootRef$current$quer = (_rootRef$current = rootRef.current) === null || _rootRef$current === void 0 ? void 0 : _rootRef$current.querySelector(`[data-criteria-add="${groupId.replace(/["\\]/g, "\\$&")}"]`)) !== null && _rootRef$current$quer !== void 0 ? _rootRef$current$quer : null;
|
|
4182
|
+
}, []);
|
|
4183
|
+
React.useEffect(() => {
|
|
4184
|
+
if (!pendingOpen) return;
|
|
4185
|
+
const trigger = findAddTrigger(pendingOpen);
|
|
4186
|
+
if (!trigger) return;
|
|
4187
|
+
setPendingOpen(null);
|
|
4188
|
+
trigger.focus();
|
|
4189
|
+
trigger.click();
|
|
4190
|
+
}, [
|
|
4191
|
+
findAddTrigger,
|
|
4192
|
+
pendingOpen,
|
|
4193
|
+
value
|
|
4194
|
+
]);
|
|
4195
|
+
const handleKeyDown = React.useCallback((event) => {
|
|
4196
|
+
if (disabled || event.defaultPrevented) return;
|
|
4197
|
+
if (event.altKey || event.ctrlKey || event.metaKey) return;
|
|
4198
|
+
if (isEditableTarget(event.target)) return;
|
|
4199
|
+
const key = event.key.toLowerCase();
|
|
4200
|
+
if (key === "g") {
|
|
4201
|
+
const id = addGroup();
|
|
4202
|
+
if (id) {
|
|
4203
|
+
event.preventDefault();
|
|
4204
|
+
setPendingOpen(id);
|
|
4205
|
+
}
|
|
4206
|
+
return;
|
|
4207
|
+
}
|
|
4208
|
+
if (key === "a") {
|
|
4209
|
+
const host = event.target instanceof Element ? event.target.closest("[data-criteria-group]") : null;
|
|
4210
|
+
const groupId = host === null || host === void 0 ? void 0 : host.dataset.criteriaGroup;
|
|
4211
|
+
const trigger = groupId ? findAddTrigger(groupId) : null;
|
|
4212
|
+
if (trigger && !trigger.disabled) {
|
|
4213
|
+
event.preventDefault();
|
|
4214
|
+
trigger.focus();
|
|
4215
|
+
trigger.click();
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
}, [
|
|
4219
|
+
addGroup,
|
|
4220
|
+
disabled,
|
|
4221
|
+
findAddTrigger
|
|
4222
|
+
]);
|
|
4223
|
+
const rootLogicOptions = React.useMemo(() => [{
|
|
4224
|
+
value: "and",
|
|
4225
|
+
label: labels.matchAllGroups
|
|
4226
|
+
}, {
|
|
4227
|
+
value: "or",
|
|
4228
|
+
label: labels.matchAnyGroup
|
|
4229
|
+
}], [labels]);
|
|
4230
|
+
const groupLogicOptions = React.useMemo(() => [{
|
|
4231
|
+
value: "and",
|
|
4232
|
+
label: labels.matchAllCriteria
|
|
4233
|
+
}, {
|
|
4234
|
+
value: "or",
|
|
4235
|
+
label: labels.matchAnyCriteria
|
|
4236
|
+
}], [labels]);
|
|
4237
|
+
const isEmpty = value.groups.length === 0;
|
|
4238
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4239
|
+
ref: rootRef,
|
|
4240
|
+
role: "group",
|
|
4241
|
+
"aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : labels.builder,
|
|
4242
|
+
className: cn("gap-section flex flex-col lg:flex-row", className),
|
|
4243
|
+
onKeyDown: handleKeyDown,
|
|
4244
|
+
"data-opt-id": "6F4JG",
|
|
4245
|
+
"data-opt-slug": "criteria-builder.CriteriaBuilder",
|
|
4246
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
4247
|
+
className: "gap-group flex min-w-0 flex-1 flex-col",
|
|
4248
|
+
children: isEmpty ? /* @__PURE__ */ jsx(EmptyState, {
|
|
4249
|
+
title: labels.emptyTitle,
|
|
4250
|
+
description: labels.emptyDescription,
|
|
4251
|
+
hasBorder: true,
|
|
4252
|
+
tone: "subdued",
|
|
4253
|
+
actions: /* @__PURE__ */ jsx(KindMenu, {
|
|
4254
|
+
kinds,
|
|
4255
|
+
menuLabel: labels.kindMenuTitle,
|
|
4256
|
+
triggerLabel: labels.emptyAction,
|
|
4257
|
+
triggerAriaLabel: labels.emptyAction,
|
|
4258
|
+
triggerIcon: /* @__PURE__ */ jsx(Plus, { "aria-hidden": "true" }),
|
|
4259
|
+
variant: "secondary",
|
|
4260
|
+
disabled,
|
|
4261
|
+
onPick: addFirst
|
|
4262
|
+
}),
|
|
4263
|
+
footer: /* @__PURE__ */ jsxs("span", {
|
|
4264
|
+
className: "gap-element inline-flex items-center",
|
|
4265
|
+
children: [
|
|
4266
|
+
/* @__PURE__ */ jsx(Kbd, {
|
|
4267
|
+
hint: true,
|
|
4268
|
+
children: "A"
|
|
4269
|
+
}),
|
|
4270
|
+
/* @__PURE__ */ jsx(Kbd, {
|
|
4271
|
+
hint: true,
|
|
4272
|
+
children: "G"
|
|
4273
|
+
}),
|
|
4274
|
+
/* @__PURE__ */ jsx("span", { children: labels.keyboardHint })
|
|
4275
|
+
]
|
|
4276
|
+
})
|
|
4277
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4278
|
+
/* @__PURE__ */ jsxs("fieldset", {
|
|
4279
|
+
className: "gap-group m-0 flex min-w-0 flex-wrap items-center border-0 p-0",
|
|
4280
|
+
children: [
|
|
4281
|
+
/* @__PURE__ */ jsx("legend", {
|
|
4282
|
+
className: "sr-only",
|
|
4283
|
+
children: labels.rootLogicLegend
|
|
4284
|
+
}),
|
|
4285
|
+
/* @__PURE__ */ jsx(SegmentedControl, {
|
|
4286
|
+
"aria-label": labels.rootLogicLegend,
|
|
4287
|
+
size: "sm",
|
|
4288
|
+
options: rootLogicOptions,
|
|
4289
|
+
value: value.logic,
|
|
4290
|
+
onChange: (logic) => onChange(_objectSpread2(_objectSpread2({}, value), {}, { logic })),
|
|
4291
|
+
disabled
|
|
4292
|
+
}),
|
|
4293
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4294
|
+
className: "text-text-tertiary gap-element hidden items-center text-xs sm:inline-flex",
|
|
4295
|
+
children: [
|
|
4296
|
+
/* @__PURE__ */ jsx(Kbd, {
|
|
4297
|
+
hint: true,
|
|
4298
|
+
children: "A"
|
|
4299
|
+
}),
|
|
4300
|
+
/* @__PURE__ */ jsx(Kbd, {
|
|
4301
|
+
hint: true,
|
|
4302
|
+
children: "G"
|
|
4303
|
+
}),
|
|
4304
|
+
labels.keyboardHint
|
|
4305
|
+
]
|
|
4306
|
+
})
|
|
4307
|
+
]
|
|
4308
|
+
}),
|
|
4309
|
+
value.groups.map((group, groupIndex) => {
|
|
4310
|
+
const letter = criteriaGroupLetter(groupIndex);
|
|
4311
|
+
const groupName = labels.groupLabel(letter);
|
|
4312
|
+
const groupLabelId = `${baseId}-${group.id}-label`;
|
|
4313
|
+
const groupError = errors === null || errors === void 0 ? void 0 : errors[group.id];
|
|
4314
|
+
const groupErrorId = `${baseId}-${group.id}-error`;
|
|
4315
|
+
const criteriaFull = group.criteria.length >= maxCriteriaPerGroup;
|
|
4316
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [groupIndex > 0 && /* @__PURE__ */ jsx(LogicDivider, {
|
|
4317
|
+
emphasis: "root",
|
|
4318
|
+
label: value.logic === "and" ? labels.and : labels.or
|
|
4319
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
4320
|
+
role: "group",
|
|
4321
|
+
"aria-labelledby": groupLabelId,
|
|
4322
|
+
"aria-describedby": groupError ? groupErrorId : void 0,
|
|
4323
|
+
"data-criteria-group": group.id,
|
|
4324
|
+
"data-invalid": groupError ? true : void 0,
|
|
4325
|
+
className: cn("bg-bg-subtle gap-element flex flex-col rounded-lg border p-3", groupError ? "border-danger/40" : "border-border"),
|
|
4326
|
+
children: [
|
|
4327
|
+
/* @__PURE__ */ jsx("span", {
|
|
4328
|
+
id: groupLabelId,
|
|
4329
|
+
className: "sr-only",
|
|
4330
|
+
children: groupName
|
|
4331
|
+
}),
|
|
4332
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4333
|
+
className: "gap-element flex flex-wrap items-center justify-between",
|
|
4334
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
4335
|
+
className: "gap-element flex items-center",
|
|
4336
|
+
children: [/* @__PURE__ */ jsx(Lettermark, { letter }), /* @__PURE__ */ jsxs("fieldset", {
|
|
4337
|
+
className: "m-0 border-0 p-0",
|
|
4338
|
+
children: [/* @__PURE__ */ jsx("legend", {
|
|
4339
|
+
className: "sr-only",
|
|
4340
|
+
children: labels.groupLogicLegend(letter)
|
|
4341
|
+
}), /* @__PURE__ */ jsx(SegmentedControl, {
|
|
4342
|
+
"aria-label": labels.groupLogicLegend(letter),
|
|
4343
|
+
size: "sm",
|
|
4344
|
+
options: groupLogicOptions,
|
|
4345
|
+
value: group.logic,
|
|
4346
|
+
onChange: (logic) => onChange(replaceGroup(value, groupIndex, _objectSpread2(_objectSpread2({}, group), {}, { logic }))),
|
|
4347
|
+
disabled
|
|
4348
|
+
})]
|
|
4349
|
+
})]
|
|
4350
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
4351
|
+
className: "flex items-center gap-0.5",
|
|
4352
|
+
children: [/* @__PURE__ */ jsx(IconAction, {
|
|
4353
|
+
icon: /* @__PURE__ */ jsx(Copy, { "aria-hidden": "true" }),
|
|
4354
|
+
label: labels.actionLabel(labels.duplicateGroup, groupName),
|
|
4355
|
+
disabled: disabled || groupsFull,
|
|
4356
|
+
onClick: () => {
|
|
4357
|
+
const taken = collectIds(value);
|
|
4358
|
+
const id = newGroupId();
|
|
4359
|
+
taken.add(id);
|
|
4360
|
+
onChange(criteriaBuilderDuplicateGroup(value, groupIndex, id, (c) => clone(c, taken)));
|
|
4361
|
+
}
|
|
4362
|
+
}), /* @__PURE__ */ jsx(IconAction, {
|
|
4363
|
+
icon: /* @__PURE__ */ jsx(Trash2, { "aria-hidden": "true" }),
|
|
4364
|
+
label: labels.actionLabel(labels.removeGroup, groupName),
|
|
4365
|
+
disabled,
|
|
4366
|
+
danger: true,
|
|
4367
|
+
onClick: () => onChange(criteriaBuilderRemoveGroup(value, groupIndex))
|
|
4368
|
+
})]
|
|
4369
|
+
})]
|
|
4370
|
+
}),
|
|
4371
|
+
group.criteria.length === 0 && /* @__PURE__ */ jsx("p", {
|
|
4372
|
+
className: "text-text-tertiary text-xs",
|
|
4373
|
+
children: labels.emptyGroup
|
|
4374
|
+
}),
|
|
4375
|
+
group.criteria.map((criterion, index) => {
|
|
4376
|
+
const criterionName = labels.criterionLabel(letter, index + 1);
|
|
4377
|
+
const rowLabelId = `${baseId}-${criterion.id}-label`;
|
|
4378
|
+
const error = errors === null || errors === void 0 ? void 0 : errors[criterion.id];
|
|
4379
|
+
const errorId = `${baseId}-${criterion.id}-error`;
|
|
4380
|
+
const known = knownKinds.has(criterion.kind);
|
|
4381
|
+
const negated = criterion.negate === true;
|
|
4382
|
+
const api = {
|
|
4383
|
+
update: (patch) => updateCriterion(groupIndex, index, patch),
|
|
4384
|
+
invalid: Boolean(error) || !known,
|
|
4385
|
+
error,
|
|
4386
|
+
disabled,
|
|
4387
|
+
groupIndex,
|
|
4388
|
+
index
|
|
4389
|
+
};
|
|
4390
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [index > 0 && /* @__PURE__ */ jsx(LogicDivider, {
|
|
4391
|
+
emphasis: "group",
|
|
4392
|
+
label: group.logic === "and" ? labels.and : labels.or
|
|
4393
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
4394
|
+
role: "group",
|
|
4395
|
+
"aria-labelledby": rowLabelId,
|
|
4396
|
+
"aria-describedby": error ? errorId : void 0,
|
|
4397
|
+
"data-criterion-kind": criterion.kind,
|
|
4398
|
+
"data-negated": negated || void 0,
|
|
4399
|
+
"data-invalid": error || !known ? true : void 0,
|
|
4400
|
+
className: cn("bg-surface gap-element flex flex-col rounded-md border p-2", error || !known ? "border-danger/40" : "border-border-subtle"),
|
|
4401
|
+
children: [
|
|
4402
|
+
/* @__PURE__ */ jsx("span", {
|
|
4403
|
+
id: rowLabelId,
|
|
4404
|
+
className: "sr-only",
|
|
4405
|
+
children: criterionName
|
|
4406
|
+
}),
|
|
4407
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4408
|
+
className: "gap-element flex flex-wrap items-start",
|
|
4409
|
+
children: [
|
|
4410
|
+
allowNegation && known && /* @__PURE__ */ jsx("button", {
|
|
4411
|
+
type: "button",
|
|
4412
|
+
"aria-pressed": negated,
|
|
4413
|
+
"aria-label": labels.actionLabel(labels.negate, criterionName),
|
|
4414
|
+
disabled,
|
|
4415
|
+
onClick: () => updateCriterion(groupIndex, index, { negate: !negated }),
|
|
4416
|
+
className: cn("inline-flex h-7 shrink-0 items-center rounded-md border px-2 text-[11px] font-semibold tracking-wide uppercase transition-colors", negated ? "border-danger/40 bg-danger-subtle text-danger-fg" : "border-border bg-bg-subtle text-text-tertiary hover:text-text-secondary", "disabled:pointer-events-none disabled:opacity-50", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset"),
|
|
4417
|
+
children: labels.negate
|
|
4418
|
+
}),
|
|
4419
|
+
/* @__PURE__ */ jsx("div", {
|
|
4420
|
+
className: "min-w-0 flex-1",
|
|
4421
|
+
children: known ? renderCriterion(criterion, api) : /* @__PURE__ */ jsx(Callout, {
|
|
4422
|
+
tone: "warning",
|
|
4423
|
+
size: "sm",
|
|
4424
|
+
title: labels.unknownKind(criterion.kind),
|
|
4425
|
+
icon: /* @__PURE__ */ jsx(TriangleAlert, { "aria-hidden": "true" }),
|
|
4426
|
+
action: /* @__PURE__ */ jsx(KindMenu, {
|
|
4427
|
+
kinds,
|
|
4428
|
+
menuLabel: labels.kindMenuTitle,
|
|
4429
|
+
triggerLabel: labels.replaceKind,
|
|
4430
|
+
triggerAriaLabel: labels.actionLabel(labels.replaceKind, criterionName),
|
|
4431
|
+
variant: "secondary",
|
|
4432
|
+
disabled,
|
|
4433
|
+
onPick: (kind, negate) => replaceCriterion(groupIndex, index, kind, negate)
|
|
4434
|
+
}),
|
|
4435
|
+
children: labels.unknownKindDescription
|
|
4436
|
+
})
|
|
4437
|
+
}),
|
|
4438
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4439
|
+
className: "flex items-center gap-0.5",
|
|
4440
|
+
children: [
|
|
4441
|
+
/* @__PURE__ */ jsx(IconAction, {
|
|
4442
|
+
icon: /* @__PURE__ */ jsx(ArrowUp, { "aria-hidden": "true" }),
|
|
4443
|
+
label: labels.actionLabel(labels.moveUp, criterionName),
|
|
4444
|
+
disabled: disabled || index === 0,
|
|
4445
|
+
onClick: () => onChange(criteriaBuilderMove(value, groupIndex, index, "up"))
|
|
4446
|
+
}),
|
|
4447
|
+
/* @__PURE__ */ jsx(IconAction, {
|
|
4448
|
+
icon: /* @__PURE__ */ jsx(ArrowDown, { "aria-hidden": "true" }),
|
|
4449
|
+
label: labels.actionLabel(labels.moveDown, criterionName),
|
|
4450
|
+
disabled: disabled || index === group.criteria.length - 1,
|
|
4451
|
+
onClick: () => onChange(criteriaBuilderMove(value, groupIndex, index, "down"))
|
|
4452
|
+
}),
|
|
4453
|
+
/* @__PURE__ */ jsx(IconAction, {
|
|
4454
|
+
icon: /* @__PURE__ */ jsx(Copy, { "aria-hidden": "true" }),
|
|
4455
|
+
label: labels.actionLabel(labels.duplicateCriterion, criterionName),
|
|
4456
|
+
disabled: disabled || criteriaFull,
|
|
4457
|
+
onClick: () => onChange(criteriaBuilderDuplicate(value, groupIndex, index, (c) => clone(c, collectIds(value))))
|
|
4458
|
+
}),
|
|
4459
|
+
/* @__PURE__ */ jsx(IconAction, {
|
|
4460
|
+
icon: /* @__PURE__ */ jsx(Trash2, { "aria-hidden": "true" }),
|
|
4461
|
+
label: labels.actionLabel(labels.removeCriterion, criterionName),
|
|
4462
|
+
disabled,
|
|
4463
|
+
danger: true,
|
|
4464
|
+
onClick: () => onChange(criteriaBuilderRemove(value, groupIndex, index))
|
|
4465
|
+
})
|
|
4466
|
+
]
|
|
4467
|
+
})
|
|
4468
|
+
]
|
|
4469
|
+
}),
|
|
4470
|
+
error && /* @__PURE__ */ jsx("p", {
|
|
4471
|
+
id: errorId,
|
|
4472
|
+
className: "text-danger-fg text-xs",
|
|
4473
|
+
children: error
|
|
4474
|
+
})
|
|
4475
|
+
]
|
|
4476
|
+
})] }, criterion.id);
|
|
4477
|
+
}),
|
|
4478
|
+
groupError && /* @__PURE__ */ jsx("p", {
|
|
4479
|
+
id: groupErrorId,
|
|
4480
|
+
className: "text-danger-fg text-xs",
|
|
4481
|
+
children: groupError
|
|
4482
|
+
}),
|
|
4483
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4484
|
+
className: "gap-element flex flex-wrap items-center",
|
|
4485
|
+
children: [/* @__PURE__ */ jsx(KindMenu, {
|
|
4486
|
+
kinds,
|
|
4487
|
+
menuLabel: labels.kindMenuTitle,
|
|
4488
|
+
triggerLabel: labels.addCriterion,
|
|
4489
|
+
triggerAriaLabel: labels.actionLabel(labels.addCriterion, groupName),
|
|
4490
|
+
triggerIcon: /* @__PURE__ */ jsx(Plus, { "aria-hidden": "true" }),
|
|
4491
|
+
disabled: disabled || criteriaFull,
|
|
4492
|
+
disabledReason: labels.maxCriteriaReached(maxCriteriaPerGroup),
|
|
4493
|
+
onPick: (kind, negate) => addCriterion(groupIndex, kind, negate),
|
|
4494
|
+
addTarget: group.id
|
|
4495
|
+
}), criteriaFull && /* @__PURE__ */ jsx("span", {
|
|
4496
|
+
className: "text-text-tertiary text-xs",
|
|
4497
|
+
children: labels.maxCriteriaReached(maxCriteriaPerGroup)
|
|
4498
|
+
})]
|
|
4499
|
+
})
|
|
4500
|
+
]
|
|
4501
|
+
})] }, group.id);
|
|
4502
|
+
}),
|
|
4503
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4504
|
+
className: "gap-element flex flex-wrap items-center",
|
|
4505
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
4506
|
+
variant: "secondary",
|
|
4507
|
+
size: "sm",
|
|
4508
|
+
leftIcon: /* @__PURE__ */ jsx(Plus, { "aria-hidden": "true" }),
|
|
4509
|
+
disabled: disabled || groupsFull,
|
|
4510
|
+
title: groupsFull ? labels.maxGroupsReached(maxGroups) : void 0,
|
|
4511
|
+
onClick: () => {
|
|
4512
|
+
const id = addGroup();
|
|
4513
|
+
if (id) setPendingOpen(id);
|
|
4514
|
+
},
|
|
4515
|
+
children: labels.addGroup
|
|
4516
|
+
}), groupsFull && /* @__PURE__ */ jsx("span", {
|
|
4517
|
+
className: "text-text-tertiary text-xs",
|
|
4518
|
+
children: labels.maxGroupsReached(maxGroups)
|
|
4519
|
+
})]
|
|
4520
|
+
})
|
|
4521
|
+
] })
|
|
4522
|
+
}), aside !== void 0 && aside !== null && /* @__PURE__ */ jsx("aside", {
|
|
4523
|
+
className: "min-w-0 lg:w-72 lg:shrink-0",
|
|
4524
|
+
children: aside
|
|
4525
|
+
})]
|
|
4526
|
+
});
|
|
4527
|
+
}
|
|
4528
|
+
CriteriaBuilder.displayName = "CriteriaBuilder";
|
|
4529
|
+
//#endregion
|
|
3767
4530
|
//#region src/shells/insights-panel.tsx
|
|
3768
4531
|
const defaultLabels$16 = {
|
|
3769
4532
|
title: "Insights",
|
|
@@ -5476,64 +6239,56 @@ ConfirmDialog.displayName = "ConfirmDialog";
|
|
|
5476
6239
|
function AsyncCombobox({ onSearch, debounceMs = 300, loadingText, minChars = 1, placeholder, onSelect, labels: customLabels, className }) {
|
|
5477
6240
|
const labels = _objectSpread2({
|
|
5478
6241
|
input: placeholder !== null && placeholder !== void 0 ? placeholder : "Search",
|
|
6242
|
+
error: "Search failed. Please try again.",
|
|
6243
|
+
retry: "Retry",
|
|
5479
6244
|
loading: loadingText !== null && loadingText !== void 0 ? loadingText : "Loading…",
|
|
5480
6245
|
noResults: "No results",
|
|
5481
6246
|
placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : "Search…"
|
|
5482
6247
|
}, customLabels);
|
|
5483
6248
|
const [query, setQuery] = React.useState("");
|
|
5484
|
-
const
|
|
5485
|
-
const
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
6249
|
+
const inputRef = React.useRef(null);
|
|
6250
|
+
const { results, loading, failed, retry, invalidate } = useAsyncSearch({
|
|
6251
|
+
query,
|
|
6252
|
+
search: onSearch,
|
|
6253
|
+
enabled: query.length >= minChars,
|
|
6254
|
+
debounceMs
|
|
6255
|
+
});
|
|
6256
|
+
const handleInput = (event) => {
|
|
6257
|
+
inputRef.current = event.currentTarget;
|
|
6258
|
+
invalidate();
|
|
5490
6259
|
setQuery(event.currentTarget.value);
|
|
5491
|
-
}
|
|
5492
|
-
const handleValueChange =
|
|
5493
|
-
|
|
5494
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
5495
|
-
setLoading(false);
|
|
5496
|
-
setResults([]);
|
|
6260
|
+
};
|
|
6261
|
+
const handleValueChange = (value) => {
|
|
6262
|
+
invalidate();
|
|
5497
6263
|
onSelect === null || onSelect === void 0 || onSelect(value);
|
|
5498
|
-
}
|
|
5499
|
-
React.useEffect(() => {
|
|
5500
|
-
const generation = ++searchGenerationRef.current;
|
|
5501
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
5502
|
-
if (query.length < minChars) {
|
|
5503
|
-
setResults([]);
|
|
5504
|
-
setLoading(false);
|
|
5505
|
-
return;
|
|
5506
|
-
}
|
|
5507
|
-
setLoading(true);
|
|
5508
|
-
timerRef.current = setTimeout(async () => {
|
|
5509
|
-
try {
|
|
5510
|
-
const items = await onSearch(query);
|
|
5511
|
-
if (searchGenerationRef.current !== generation) return;
|
|
5512
|
-
setResults(items);
|
|
5513
|
-
} finally {
|
|
5514
|
-
if (searchGenerationRef.current === generation) setLoading(false);
|
|
5515
|
-
}
|
|
5516
|
-
}, debounceMs);
|
|
5517
|
-
return () => {
|
|
5518
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
5519
|
-
};
|
|
5520
|
-
}, [
|
|
5521
|
-
query,
|
|
5522
|
-
minChars,
|
|
5523
|
-
debounceMs,
|
|
5524
|
-
onSearch
|
|
5525
|
-
]);
|
|
6264
|
+
};
|
|
5526
6265
|
return /* @__PURE__ */ jsxs(ComboboxRoot, {
|
|
5527
6266
|
onValueChange: handleValueChange,
|
|
5528
6267
|
"data-opt-id": "KAKTV",
|
|
5529
6268
|
"data-opt-slug": "async-combobox.AsyncCombobox",
|
|
5530
|
-
children: [/* @__PURE__ */ jsx(ComboboxInput, {
|
|
6269
|
+
children: [/* @__PURE__ */ jsx(ComboboxInput, _objectSpread2({
|
|
5531
6270
|
className: cn(className),
|
|
5532
6271
|
"aria-label": labels.input,
|
|
5533
6272
|
"aria-busy": loading || void 0,
|
|
5534
6273
|
placeholder: labels.placeholder,
|
|
5535
6274
|
onInput: handleInput
|
|
5536
|
-
}
|
|
6275
|
+
}, failed ? {
|
|
6276
|
+
"aria-expanded": false,
|
|
6277
|
+
"aria-controls": void 0
|
|
6278
|
+
} : {})), /* @__PURE__ */ jsx(ComboboxPopover, _objectSpread2(_objectSpread2({}, failed ? { role: "presentation" } : {}), {}, { children: failed ? /* @__PURE__ */ jsxs("div", {
|
|
6279
|
+
role: "alert",
|
|
6280
|
+
className: "gap-element flex flex-col px-3 py-2 text-sm",
|
|
6281
|
+
children: [/* @__PURE__ */ jsx("span", { children: labels.error }), /* @__PURE__ */ jsx(Button, {
|
|
6282
|
+
variant: "secondary",
|
|
6283
|
+
size: "sm",
|
|
6284
|
+
onClick: () => {
|
|
6285
|
+
var _inputRef$current;
|
|
6286
|
+
retry();
|
|
6287
|
+
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
|
|
6288
|
+
},
|
|
6289
|
+
children: labels.retry
|
|
6290
|
+
})]
|
|
6291
|
+
}) : loading ? /* @__PURE__ */ jsxs("div", {
|
|
5537
6292
|
className: "text-text-secondary gap-element flex items-center px-3 py-2 text-sm",
|
|
5538
6293
|
role: "status",
|
|
5539
6294
|
"aria-live": "polite",
|
|
@@ -5545,7 +6300,7 @@ function AsyncCombobox({ onSearch, debounceMs = 300, loadingText, minChars = 1,
|
|
|
5545
6300
|
}) : results.length === 0 ? /* @__PURE__ */ jsx(ComboboxEmpty, { children: labels.noResults }) : results.map((item) => /* @__PURE__ */ jsx(ComboboxItem, {
|
|
5546
6301
|
value: item,
|
|
5547
6302
|
children: item
|
|
5548
|
-
}, item)) })]
|
|
6303
|
+
}, item)) }))]
|
|
5549
6304
|
});
|
|
5550
6305
|
}
|
|
5551
6306
|
//#endregion
|
|
@@ -8176,4 +8931,4 @@ const enStarRatingLabels = {
|
|
|
8176
8931
|
};
|
|
8177
8932
|
const enBreadcrumbLabels = { navAriaLabel: "Go to {label}" };
|
|
8178
8933
|
//#endregion
|
|
8179
|
-
export { ALL_COMPOUND_THEMES, AccordionContent, AccordionItem, AccordionRoot, AccordionTrigger, ActivityFeed, Alert, AlertBuilder, AlertDialogPanel, AppMenubar, AppShell, AsyncCombobox, AuditLog, AuditTimeline, AuthForm, Avatar, AvatarGroup, Badge, BlockLayout, BlockLayout as SurfaceLayout, BranchSelect, Breadcrumb, BulkActions, Button, COLOR_PRESETS, Callout, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CatalogCellControls, CatalogFrame, CatalogRowActions, ChatInput, ChatMessageList, ChatSidebar, Checkbox, CheckboxGroup, CircularProgress, CodeDiffViewer, CodeSnippetViewer, ColorPaletteDisplay, ColorPalettePicker, ColorPicker, ColumnToggler, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxPopover, ComboboxRoot, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandPalette, CommandPaletteTrigger, CommandSeparator, CommandShortcut, ComparisonSelector, Composite, CompositeItem, CompositeProvider, CompositeRow, CompositeZone, ConditionBuilder, ConfirmDialog, ConnectionIndicator, Container, ContentTabs, CopyButton, DEFAULT_PRESETS, DEFAULT_TIME_PRESETS, DashboardGrid, DataImportWizard, DataTable, DateRangePicker, DeploymentTimeline, DescriptionList, DesignGuidePanel, DialogBody, DialogDescription, DialogDisclosure, DialogDismiss, DialogFooter, DialogHeader, DialogHeading, DialogPanel, DialogRoot, DisclosureContent, DisclosureRoot, DisclosureTrigger, DomainTable, DrawerClose, DrawerPanel, DrawerRoot, DropdownContent, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, DynamicFieldForm, EMPTY_QUERY, EMPTY_QUERY_FILTERS, EditorToolbar, EmptyState, EnvPanel, ErrorBoundary, EventIcon, EventMetaEditor, EventSparkline, EventTimeline, ExportButton, Expression, ExpressionGroup, FIELD_TYPE_TOKENS, FORCE_LIGHT_PRESETS, FORCE_LIGHT_PRESET_IDS, Facet, FacetGroup, FailureList, FaqAccordion, FeatureFlagPanel, FieldSidebar, FieldToken, FieldTokenLegend, FileUploadForm, FilterBar, FloatingActionBar, Flyout, FormCheckbox, FormColorPicker, FormControl, FormDateRangePicker, FormDescription, FormError, FormField, FormGroup, FormGroupLabel, FormIconPicker, FormInput, FormLabel, FormNumberInput, FormProvider, FormPush, FormRadio, FormRadioGroup, FormRemove, FormReset, FormRoot, FormSelect, FormSelectItem, FormSelectPopover, FormSlider, FormStarRating, FormSubmit, FormSwitch, FormTagInput, FormTextarea, GENERATED_THEME_ID_DEFAULT, GLOBAL_THEME_STYLE_ID, Heading, Highlight, IconPicker, Identity, InlineEdit, InlineEditTable, Input, InsightsPanel, InspectorLayout, KanbanBoard, Kbd, KeyPadMenu, KeyValueEditor, LiveRegion, LoadingOverlay, LogTable, Logo, MegaMenu, MenuButtonArrow, MenuItem, MenuItemCheckbox, MenuItemRadio, MenuPopover, MenuRoot, MenuSeparator, MenuTrigger, MenubarContainer, MenubarRoot, Meter, MetricsCard, NotificationCenter, NotificationToast, NumberInput, OPT_TEXT_PRIMARY, OPT_TEXT_SECONDARY, OptThemeControllerContext, OptThemeProvider, OtpField, POPULAR_ICONS, PageAside, PageHeader, Pagination, PopoverClose, PopoverContent, PopoverRoot, PopoverTrigger, Progress, ProjectSwitcher, PromptTemplate, PropertyExplorer, QueryBar, QueryFilterBar, QueryFiltersMenu, QueryHistoryList, QueryOutputPane, QueryResultChart, QueryResultsTable, QueryToolbar, QueryVariablesMenu, QueryWorkspace, QuickActions, Radio, RadioGroup, ReportBuilder, ReportWidget, ResizableHandle, ResizablePanel, ResizablePanelGroup, RichTextEditor, RouteFocusManager, SHADER_OVERLAY_PARAM_KEYS, SHADER_PARAM_FALLBACK, SHADER_PARAM_KEYS, SHADER_PRESETS, SHADER_PRESET_IDS, SaveQueryDialog, SavedFilters, SchemaTree, ScoreBreakdown, ScrollArea, SearchCombobox, Section, SegmentBuilder, SegmentedControl, SelectItem, SelectLabel, SelectPopover, SelectRoot, SelectTrigger, Separator, SettingsForm, ShaderSurface, Sidebar, SidebarNav, Skeleton, SkeletonAvatar, SkeletonCard, SkeletonTable, SkeletonText, Slider, SpatialNavProvider, Spinner, SqlEditor, StarRating, StatCard, StatusDot, StatusSelect, StepBuilder, SummaryRow, Switch, THEME_PALETTES, THEME_PRESET_IDS, THEME_REGISTRY, THEME_SPEC_STORAGE_KEY, THEME_TOKENS_STORAGE_KEY, Tab, TabList, TabPanel, TabsRoot, TagInput, TaskList, TeamMemberList, TemplatePicker, Text, TextTruncate, Textarea, ThemeSwitcher, TimeRangeControl, TimeRangeSelector, TimeSeriesPanel, ToastProvider, Toggle, ToggleGroup, ToolbarButton, ToolbarContainer, ToolbarRoot, ToolbarSeparator, Tooltip, TooltipAnchor, TooltipProvider, TreeTable, TrendChart, VALUELESS_OPERATORS, VerticalTabs, VirtualList, WebhookConfig, WidgetGrid, WizardForm, WorkflowCanvas, addClause, applyCellAction, buildTokenCache, cn, coerceThemeMode, computeGeneratedTokens, computeSpatialTargets, countActiveQueryFilters, createBlock, createBlock as createSurface, createThemeBootScript, defaultQueryChartConfig, defineThemeOverrides, describeClause, enBreadcrumbLabels, enComboboxLabels, enStarRatingLabels, fieldValues, formatClause, formatOptDateTime, formatOptNumber, formatOptShortDate, formatOptTime, formatQuery, formatQueryCell, generatedTheme, getCompoundIdForSpec, getCompoundTheme, getShaderFragment, getShaderPreset, getThemeDescriptor, getTrappedContextRole, hasActiveQuery, hasActiveQueryFilters, isDescriptorSpec, isEmptyQuery, isForceLightSpec, isGeneratedSpec, isPresetSpec, isThemePresetId, isValidQueryVariableName, koBreadcrumbLabels, koComboboxLabels, koStarRatingLabels, matchesQuery, matchesQueryObject, numericResultColumns, parseQuery, parseQueryWithDiagnostics, presetTheme, queryFields, quoteValue, readStoredTheme, removeClause, replaceSqlPlaceholder, resolveDescriptor, resolveFieldType, resolveThemeMode, safeParseStoredSpec, safeParseStoredTokens, schemaValidator, serializeGeneratedTheme, serializeThemeRule, serializeTokenBody, shouldSkipArrow, splitSqlStatements, sqlPlaceholderNames, sqlStatementAtOffset, sqlUsesPlaceholder, toast, useAutoRefresh, useControlledState, useFieldValue, useFormContext, useFormStore, useInputId, useOptTheme, useOptThemeController, useOptionalOptTheme, useSidebar, useToast, withFieldValue, withoutField };
|
|
8934
|
+
export { ALL_COMPOUND_THEMES, AccordionContent, AccordionItem, AccordionRoot, AccordionTrigger, ActivityFeed, Alert, AlertBuilder, AlertDialogPanel, AppMenubar, AppShell, AsyncCombobox, AuditLog, AuditTimeline, AuthForm, Avatar, AvatarGroup, Badge, BlockLayout, BlockLayout as SurfaceLayout, BranchSelect, Breadcrumb, BulkActions, Button, COLOR_PRESETS, Callout, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CatalogCellControls, CatalogFrame, CatalogRowActions, ChatInput, ChatMessageList, ChatSidebar, Checkbox, CheckboxGroup, CircularProgress, CodeDiffViewer, CodeSnippetViewer, ColorPaletteDisplay, ColorPalettePicker, ColorPicker, ColumnToggler, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxPopover, ComboboxRoot, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandPalette, CommandPaletteTrigger, CommandSeparator, CommandShortcut, ComparisonSelector, Composite, CompositeItem, CompositeProvider, CompositeRow, CompositeZone, ConditionBuilder, ConfirmDialog, ConnectionIndicator, Container, ContentTabs, CopyButton, CriteriaBuilder, DEFAULT_PRESETS, DEFAULT_TIME_PRESETS, DashboardGrid, DataImportWizard, DataTable, DateRangePicker, DeploymentTimeline, DescriptionList, DesignGuidePanel, DialogBody, DialogDescription, DialogDisclosure, DialogDismiss, DialogFooter, DialogHeader, DialogHeading, DialogPanel, DialogRoot, DisclosureContent, DisclosureRoot, DisclosureTrigger, DomainTable, DrawerClose, DrawerPanel, DrawerRoot, DropdownContent, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, DynamicFieldForm, EMPTY_QUERY, EMPTY_QUERY_FILTERS, EditorToolbar, EmptyState, EnvPanel, ErrorBoundary, EventIcon, EventMetaEditor, EventSparkline, EventTimeline, ExportButton, Expression, ExpressionGroup, FIELD_TYPE_TOKENS, FORCE_LIGHT_PRESETS, FORCE_LIGHT_PRESET_IDS, Facet, FacetGroup, FailureList, FaqAccordion, FeatureFlagPanel, FieldSidebar, FieldToken, FieldTokenLegend, FileUploadForm, FilterBar, FloatingActionBar, Flyout, FormCheckbox, FormColorPicker, FormControl, FormDateRangePicker, FormDescription, FormError, FormField, FormGroup, FormGroupLabel, FormIconPicker, FormInput, FormLabel, FormNumberInput, FormProvider, FormPush, FormRadio, FormRadioGroup, FormRemove, FormReset, FormRoot, FormSelect, FormSelectItem, FormSelectPopover, FormSlider, FormStarRating, FormSubmit, FormSwitch, FormTagInput, FormTextarea, GENERATED_THEME_ID_DEFAULT, GLOBAL_THEME_STYLE_ID, Heading, Highlight, IconPicker, Identity, InlineEdit, InlineEditTable, Input, InsightsPanel, InspectorLayout, KanbanBoard, Kbd, KeyPadMenu, KeyValueEditor, LiveRegion, LoadingOverlay, LogTable, Logo, MegaMenu, MenuButtonArrow, MenuItem, MenuItemCheckbox, MenuItemRadio, MenuPopover, MenuRoot, MenuSeparator, MenuTrigger, MenubarContainer, MenubarRoot, Meter, MetricsCard, NotificationCenter, NotificationToast, NumberInput, OPT_TEXT_PRIMARY, OPT_TEXT_SECONDARY, OptThemeControllerContext, OptThemeProvider, OtpField, POPULAR_ICONS, PageAside, PageHeader, Pagination, PopoverClose, PopoverContent, PopoverRoot, PopoverTrigger, Progress, ProjectSwitcher, PromptTemplate, PropertyExplorer, QueryBar, QueryFilterBar, QueryFiltersMenu, QueryHistoryList, QueryOutputPane, QueryResultChart, QueryResultsTable, QueryToolbar, QueryVariablesMenu, QueryWorkspace, QuickActions, Radio, RadioGroup, ReplayPlayerLayout, ReplayScrubber, ReplayTransport, ReportBuilder, ReportWidget, ResizableHandle, ResizablePanel, ResizablePanelGroup, RichTextEditor, RouteFocusManager, SHADER_OVERLAY_PARAM_KEYS, SHADER_PARAM_FALLBACK, SHADER_PARAM_KEYS, SHADER_PRESETS, SHADER_PRESET_IDS, SaveQueryDialog, SavedFilters, SchemaTree, ScoreBreakdown, ScrollArea, SearchCombobox, Section, SegmentBuilder, SegmentedControl, SelectItem, SelectLabel, SelectPopover, SelectRoot, SelectTrigger, Separator, SettingsForm, ShaderSurface, Sidebar, SidebarNav, Skeleton, SkeletonAvatar, SkeletonCard, SkeletonTable, SkeletonText, Slider, SpatialNavProvider, Spinner, SqlEditor, StarRating, StatCard, StatusDot, StatusSelect, StepBuilder, SummaryRow, Switch, THEME_PALETTES, THEME_PRESET_IDS, THEME_REGISTRY, THEME_SPEC_STORAGE_KEY, THEME_TOKENS_STORAGE_KEY, Tab, TabList, TabPanel, TabsRoot, TagInput, TaskList, TeamMemberList, TemplatePicker, Text, TextTruncate, Textarea, ThemeSwitcher, TimeRangeControl, TimeRangeSelector, TimeSeriesPanel, ToastProvider, Toggle, ToggleGroup, ToolbarButton, ToolbarContainer, ToolbarRoot, ToolbarSeparator, Tooltip, TooltipAnchor, TooltipProvider, TreeTable, TrendChart, VALUELESS_OPERATORS, VerticalTabs, VirtualList, WebhookConfig, WidgetGrid, WizardForm, WorkflowCanvas, addClause, applyCellAction, buildTokenCache, cn, coerceThemeMode, computeGeneratedTokens, computeSpatialTargets, countActiveQueryFilters, createBlock, createBlock as createSurface, createThemeBootScript, criteriaBuilderDuplicate, criteriaBuilderDuplicateGroup, criteriaBuilderInsert, criteriaBuilderMove, criteriaBuilderRemove, criteriaBuilderRemoveGroup, criteriaGroupLetter, defaultQueryChartConfig, defineThemeOverrides, describeClause, enBreadcrumbLabels, enComboboxLabels, enStarRatingLabels, fieldValues, formatClause, formatOptDateTime, formatOptNumber, formatOptShortDate, formatOptTime, formatQuery, formatQueryCell, formatReplayElapsed, generatedTheme, getCompoundIdForSpec, getCompoundTheme, getShaderFragment, getShaderPreset, getThemeDescriptor, getTrappedContextRole, groupReplayMarkers, hasActiveQuery, hasActiveQueryFilters, isDescriptorSpec, isEmptyQuery, isForceLightSpec, isGeneratedSpec, isPresetSpec, isThemePresetId, isValidQueryVariableName, koBreadcrumbLabels, koComboboxLabels, koStarRatingLabels, matchesQuery, matchesQueryObject, numericResultColumns, parseQuery, parseQueryWithDiagnostics, presetTheme, queryFields, quoteValue, readStoredTheme, removeClause, replaceSqlPlaceholder, replayShortcutKey, resolveDescriptor, resolveFieldType, resolveThemeMode, safeParseStoredSpec, safeParseStoredTokens, schemaValidator, serializeGeneratedTheme, serializeThemeRule, serializeTokenBody, shouldSkipArrow, splitSqlStatements, sqlPlaceholderNames, sqlStatementAtOffset, sqlUsesPlaceholder, toast, useAutoRefresh, useControlledState, useFieldValue, useFormContext, useFormStore, useInputId, useOptTheme, useOptThemeController, useOptionalOptTheme, useSidebar, useToast, withFieldValue, withoutField };
|