@open-mercato/ui 0.6.1-develop.3246.1.dbef9d7392 → 0.6.1-develop.3260.1.dc719cac84
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/.turbo/turbo-build.log +1 -1
- package/__integration__/TC-AI-UI-003-aichat-registry.spec.tsx +13 -0
- package/dist/ai/AiAssistantLauncher.js +8 -0
- package/dist/ai/AiAssistantLauncher.js.map +2 -2
- package/dist/ai/AiChat.js +226 -58
- package/dist/ai/AiChat.js.map +2 -2
- package/dist/ai/AiDock.js +3 -2
- package/dist/ai/AiDock.js.map +2 -2
- package/dist/ai/ModelPicker.js +186 -0
- package/dist/ai/ModelPicker.js.map +7 -0
- package/dist/ai/index.js +3 -1
- package/dist/ai/index.js.map +2 -2
- package/dist/ai/useAiChat.js +12 -16
- package/dist/ai/useAiChat.js.map +2 -2
- package/dist/backend/CrudForm.js +46 -129
- package/dist/backend/CrudForm.js.map +3 -3
- package/dist/backend/DataTable.js +10 -3
- package/dist/backend/DataTable.js.map +2 -2
- package/dist/backend/EmptyState.js +1 -47
- package/dist/backend/EmptyState.js.map +2 -2
- package/dist/backend/FilterOverlay.js +31 -26
- package/dist/backend/FilterOverlay.js.map +2 -2
- package/dist/backend/FlashMessages.js +23 -25
- package/dist/backend/FlashMessages.js.map +2 -2
- package/dist/backend/JsonBuilder.js +4 -2
- package/dist/backend/JsonBuilder.js.map +2 -2
- package/dist/backend/LogList.js +49 -0
- package/dist/backend/LogList.js.map +7 -0
- package/dist/backend/crud/CollapsibleGroup.js +13 -3
- package/dist/backend/crud/CollapsibleGroup.js.map +2 -2
- package/dist/backend/detail/InlineEditors.js +80 -32
- package/dist/backend/detail/InlineEditors.js.map +2 -2
- package/dist/backend/inputs/ComboboxInput.js +60 -6
- package/dist/backend/inputs/ComboboxInput.js.map +2 -2
- package/dist/backend/inputs/DatePicker.js +6 -142
- package/dist/backend/inputs/DatePicker.js.map +2 -2
- package/dist/backend/inputs/DateTimePicker.js +6 -182
- package/dist/backend/inputs/DateTimePicker.js.map +2 -2
- package/dist/backend/inputs/TagsInput.js +16 -19
- package/dist/backend/inputs/TagsInput.js.map +2 -2
- package/dist/backend/inputs/TimeInput.js +1 -1
- package/dist/backend/inputs/TimeInput.js.map +2 -2
- package/dist/backend/inputs/TimePicker.js +83 -72
- package/dist/backend/inputs/TimePicker.js.map +2 -2
- package/dist/backend/utils/customFieldForms.js +2 -2
- package/dist/backend/utils/customFieldForms.js.map +1 -1
- package/dist/portal/components/PortalEmptyState.js +13 -9
- package/dist/portal/components/PortalEmptyState.js.map +2 -2
- package/dist/primitives/accordion.js +137 -0
- package/dist/primitives/accordion.js.map +7 -0
- package/dist/primitives/alert.js +180 -12
- package/dist/primitives/alert.js.map +2 -2
- package/dist/primitives/calendar.js +122 -32
- package/dist/primitives/calendar.js.map +2 -2
- package/dist/primitives/compact-select.js +47 -0
- package/dist/primitives/compact-select.js.map +7 -0
- package/dist/primitives/counter-input.js +174 -0
- package/dist/primitives/counter-input.js.map +7 -0
- package/dist/primitives/date-picker-helpers.js +79 -0
- package/dist/primitives/date-picker-helpers.js.map +7 -0
- package/dist/primitives/date-picker.js +216 -0
- package/dist/primitives/date-picker.js.map +7 -0
- package/dist/primitives/date-range-picker.js +239 -0
- package/dist/primitives/date-range-picker.js.map +7 -0
- package/dist/primitives/digit-input.js +157 -0
- package/dist/primitives/digit-input.js.map +7 -0
- package/dist/primitives/empty-state.js +93 -0
- package/dist/primitives/empty-state.js.map +7 -0
- package/dist/primitives/inline-input.js +29 -0
- package/dist/primitives/inline-input.js.map +7 -0
- package/dist/primitives/inline-select.js +41 -0
- package/dist/primitives/inline-select.js.map +7 -0
- package/dist/primitives/notification-stack.js +116 -0
- package/dist/primitives/notification-stack.js.map +7 -0
- package/dist/primitives/notification.js +62 -0
- package/dist/primitives/notification.js.map +7 -0
- package/dist/primitives/rich-editor.js +1230 -0
- package/dist/primitives/rich-editor.js.map +7 -0
- package/dist/primitives/select.js +1 -0
- package/dist/primitives/select.js.map +2 -2
- package/dist/primitives/skeleton.js +55 -0
- package/dist/primitives/skeleton.js.map +7 -0
- package/dist/primitives/tag-input.js +186 -0
- package/dist/primitives/tag-input.js.map +7 -0
- package/dist/primitives/tag.js +66 -13
- package/dist/primitives/tag.js.map +2 -2
- package/dist/primitives/time-picker.js +793 -0
- package/dist/primitives/time-picker.js.map +7 -0
- package/package.json +4 -3
- package/src/ai/AiAssistantLauncher.tsx +8 -0
- package/src/ai/AiChat.tsx +229 -11
- package/src/ai/AiDock.tsx +3 -2
- package/src/ai/ModelPicker.tsx +248 -0
- package/src/ai/__tests__/AiAssistantLauncher.test.tsx +58 -0
- package/src/ai/__tests__/AiChat.conversation.test.tsx +16 -0
- package/src/ai/__tests__/AiChat.debug.test.tsx +16 -0
- package/src/ai/__tests__/AiChat.registry.test.tsx +16 -0
- package/src/ai/__tests__/AiChat.test.tsx +180 -0
- package/src/ai/__tests__/AiChat.thinking-unmount.test.tsx +16 -0
- package/src/ai/__tests__/AiDock.test.tsx +12 -1
- package/src/ai/__tests__/ModelPicker.test.tsx +252 -0
- package/src/ai/index.ts +1 -0
- package/src/ai/useAiChat.ts +29 -16
- package/src/backend/CrudForm.tsx +61 -113
- package/src/backend/DataTable.tsx +17 -5
- package/src/backend/EmptyState.tsx +13 -63
- package/src/backend/FilterOverlay.tsx +38 -22
- package/src/backend/FlashMessages.tsx +23 -24
- package/src/backend/JsonBuilder.tsx +4 -2
- package/src/backend/LogList.tsx +109 -0
- package/src/backend/__tests__/CrudForm.datetime.test.tsx +12 -7
- package/src/backend/__tests__/FilterOverlay.dateRange.test.tsx +89 -0
- package/src/backend/__tests__/LogList.test.tsx +163 -0
- package/src/backend/crud/CollapsibleGroup.tsx +17 -3
- package/src/backend/detail/InlineEditors.tsx +78 -25
- package/src/backend/detail/__tests__/InlineEditors.test.tsx +81 -1
- package/src/backend/inputs/ComboboxInput.tsx +81 -9
- package/src/backend/inputs/DatePicker.tsx +28 -155
- package/src/backend/inputs/DateTimePicker.tsx +25 -193
- package/src/backend/inputs/TagsInput.tsx +10 -13
- package/src/backend/inputs/TimeInput.tsx +2 -1
- package/src/backend/inputs/TimePicker.tsx +99 -70
- package/src/backend/inputs/__tests__/ComboboxInput.test.tsx +133 -0
- package/src/backend/inputs/__tests__/TimePicker.test.tsx +2 -2
- package/src/backend/utils/__tests__/richTextSanitizer.test.ts +5 -2
- package/src/backend/utils/customFieldForms.ts +2 -2
- package/src/portal/components/PortalEmptyState.tsx +27 -22
- package/src/primitives/__tests__/accordion.test.tsx +197 -0
- package/src/primitives/__tests__/alert.test.tsx +204 -0
- package/src/primitives/__tests__/compact-select.test.tsx +98 -0
- package/src/primitives/__tests__/counter-input.test.tsx +165 -0
- package/src/primitives/__tests__/date-picker.test.tsx +221 -0
- package/src/primitives/__tests__/date-range-picker.test.tsx +173 -0
- package/src/primitives/__tests__/digit-input.test.tsx +168 -0
- package/src/primitives/__tests__/empty-state.test.tsx +154 -0
- package/src/primitives/__tests__/inline-input.test.tsx +100 -0
- package/src/primitives/__tests__/inline-select.test.tsx +103 -0
- package/src/primitives/__tests__/notification-stack.test.tsx +174 -0
- package/src/primitives/__tests__/notification.test.tsx +119 -0
- package/src/primitives/__tests__/rich-editor.test.tsx +411 -0
- package/src/primitives/__tests__/skeleton.test.tsx +76 -0
- package/src/primitives/__tests__/tag-input.test.tsx +198 -0
- package/src/primitives/__tests__/tag.test.tsx +123 -0
- package/src/primitives/__tests__/time-picker.test.tsx +392 -0
- package/src/primitives/accordion.tsx +225 -0
- package/src/primitives/alert.tsx +234 -24
- package/src/primitives/calendar.tsx +146 -38
- package/src/primitives/compact-select.tsx +59 -0
- package/src/primitives/counter-input.tsx +211 -0
- package/src/primitives/date-picker-helpers.ts +96 -0
- package/src/primitives/date-picker.tsx +290 -0
- package/src/primitives/date-range-picker.tsx +281 -0
- package/src/primitives/digit-input.tsx +208 -0
- package/src/primitives/empty-state.tsx +140 -0
- package/src/primitives/inline-input.tsx +55 -0
- package/src/primitives/inline-select.tsx +74 -0
- package/src/primitives/notification-stack.tsx +185 -0
- package/src/primitives/notification.tsx +136 -0
- package/src/primitives/rich-editor.tsx +1578 -0
- package/src/primitives/select.tsx +1 -0
- package/src/primitives/skeleton.tsx +70 -0
- package/src/primitives/tag-input.tsx +223 -0
- package/src/primitives/tag.tsx +69 -10
- package/src/primitives/time-picker.tsx +1059 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
4
|
+
import {
|
|
5
|
+
Accordion,
|
|
6
|
+
AccordionContent,
|
|
7
|
+
AccordionItem,
|
|
8
|
+
AccordionTrigger
|
|
9
|
+
} from "@open-mercato/ui/primitives/accordion";
|
|
10
|
+
import { Badge } from "@open-mercato/ui/primitives/badge";
|
|
11
|
+
const LOG_LEVEL_BADGE_VARIANT = {
|
|
12
|
+
info: "info",
|
|
13
|
+
warn: "warning",
|
|
14
|
+
warning: "warning",
|
|
15
|
+
error: "error",
|
|
16
|
+
debug: "neutral"
|
|
17
|
+
};
|
|
18
|
+
function LogLevelBadge({ level, label, className }) {
|
|
19
|
+
const key = typeof level === "string" ? level.toLowerCase() : "";
|
|
20
|
+
const variant = LOG_LEVEL_BADGE_VARIANT[key] ?? "secondary";
|
|
21
|
+
return /* @__PURE__ */ jsx(Badge, { variant, className, "data-log-level": key || void 0, children: label ?? level });
|
|
22
|
+
}
|
|
23
|
+
function LogList({ entries, emptyMessage, className }) {
|
|
24
|
+
if (entries.length === 0) {
|
|
25
|
+
return emptyMessage ? /* @__PURE__ */ jsx("p", { className: cn("py-4 text-sm text-muted-foreground", className), "data-slot": "log-list-empty", children: emptyMessage }) : null;
|
|
26
|
+
}
|
|
27
|
+
return /* @__PURE__ */ jsx(
|
|
28
|
+
Accordion,
|
|
29
|
+
{
|
|
30
|
+
type: "single",
|
|
31
|
+
collapsible: true,
|
|
32
|
+
className: cn("space-y-2", className),
|
|
33
|
+
"data-slot": "log-list",
|
|
34
|
+
children: entries.map((entry) => /* @__PURE__ */ jsxs(AccordionItem, { value: entry.id, "data-log-entry-id": entry.id, children: [
|
|
35
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { triggerIcon: "chevron", children: /* @__PURE__ */ jsxs("span", { className: "grid w-full items-center gap-3 sm:grid-cols-[10rem_5rem_minmax(0,1fr)]", children: [
|
|
36
|
+
/* @__PURE__ */ jsx("span", { className: "truncate whitespace-nowrap text-xs text-muted-foreground sm:text-sm", children: entry.time }),
|
|
37
|
+
/* @__PURE__ */ jsx("span", { className: "justify-self-start", children: /* @__PURE__ */ jsx(LogLevelBadge, { level: entry.level, label: entry.levelLabel }) }),
|
|
38
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-left text-sm font-normal", children: entry.message })
|
|
39
|
+
] }) }),
|
|
40
|
+
/* @__PURE__ */ jsx(AccordionContent, { children: entry.body })
|
|
41
|
+
] }, entry.id))
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
LogLevelBadge,
|
|
47
|
+
LogList
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=LogList.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/backend/LogList.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from '@open-mercato/ui/primitives/accordion'\nimport { Badge, type BadgeProps } from '@open-mercato/ui/primitives/badge'\n\nexport type LogListLevel = 'info' | 'warn' | 'warning' | 'error' | 'debug' | string\n\nexport type LogListEntry = {\n id: string\n /** Pre-formatted timestamp (consumer formats with `formatDateTime()` / locale). */\n time: React.ReactNode\n /** Raw level value \u2014 drives the badge color via the built-in map. */\n level: LogListLevel\n /** Optional translated label override; falls back to `level` verbatim. */\n levelLabel?: React.ReactNode\n /** Trigger message (one-liner \u2014 truncates in the trigger row, full text available inside `body`). */\n message: React.ReactNode\n /** Body content rendered inside `AccordionContent` when expanded \u2014 typically a metadata grid + JSON payload. */\n body: React.ReactNode\n}\n\ntype LogLevelBadgeVariant = NonNullable<BadgeProps['variant']>\n\nconst LOG_LEVEL_BADGE_VARIANT: Record<string, LogLevelBadgeVariant> = {\n info: 'info',\n warn: 'warning',\n warning: 'warning',\n error: 'error',\n debug: 'neutral',\n}\n\nexport type LogLevelBadgeProps = {\n level: LogListLevel\n label?: React.ReactNode\n className?: string\n}\n\nexport function LogLevelBadge({ level, label, className }: LogLevelBadgeProps) {\n const key = typeof level === 'string' ? level.toLowerCase() : ''\n const variant = LOG_LEVEL_BADGE_VARIANT[key] ?? 'secondary'\n return (\n <Badge variant={variant} className={className} data-log-level={key || undefined}>\n {label ?? level}\n </Badge>\n )\n}\n\nexport type LogListProps = {\n entries: LogListEntry[]\n /** Optional message rendered when the list is empty. Pass through `useT()` for i18n. */\n emptyMessage?: React.ReactNode\n className?: string\n}\n\n/**\n * Unified `Accordion`-driven log list for admin \"logs\" tabs (integrations,\n * data sync runs, payment gateway transactions, \u2026). Replaces the per-module\n * `<table>` + `expandedLogId` row-expand pattern with a Figma-aligned card\n * list that uses the DS `Accordion` primitive under the hood. Each row\n * shows time + level badge + message in the trigger; the consumer controls\n * the expanded body content (metadata grid, JSON payload, etc.).\n *\n * `type='single' collapsible` matches the previous \"one expanded row at a\n * time\" behaviour. Switch to `Accordion` directly if you need multi-open.\n */\nexport function LogList({ entries, emptyMessage, className }: LogListProps) {\n if (entries.length === 0) {\n return emptyMessage ? (\n <p className={cn('py-4 text-sm text-muted-foreground', className)} data-slot=\"log-list-empty\">\n {emptyMessage}\n </p>\n ) : null\n }\n\n return (\n <Accordion\n type=\"single\"\n collapsible\n className={cn('space-y-2', className)}\n data-slot=\"log-list\"\n >\n {entries.map((entry) => (\n <AccordionItem key={entry.id} value={entry.id} data-log-entry-id={entry.id}>\n <AccordionTrigger triggerIcon=\"chevron\">\n <span className=\"grid w-full items-center gap-3 sm:grid-cols-[10rem_5rem_minmax(0,1fr)]\">\n <span className=\"truncate whitespace-nowrap text-xs text-muted-foreground sm:text-sm\">\n {entry.time}\n </span>\n <span className=\"justify-self-start\">\n <LogLevelBadge level={entry.level} label={entry.levelLabel} />\n </span>\n <span className=\"min-w-0 truncate text-left text-sm font-normal\">\n {entry.message}\n </span>\n </span>\n </AccordionTrigger>\n <AccordionContent>{entry.body}</AccordionContent>\n </AccordionItem>\n ))}\n </Accordion>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAgDI,cA2CQ,YA3CR;AA7CJ,SAAS,UAAU;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,aAA8B;AAoBvC,MAAM,0BAAgE;AAAA,EACpE,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AACT;AAQO,SAAS,cAAc,EAAE,OAAO,OAAO,UAAU,GAAuB;AAC7E,QAAM,MAAM,OAAO,UAAU,WAAW,MAAM,YAAY,IAAI;AAC9D,QAAM,UAAU,wBAAwB,GAAG,KAAK;AAChD,SACE,oBAAC,SAAM,SAAkB,WAAsB,kBAAgB,OAAO,QACnE,mBAAS,OACZ;AAEJ;AAoBO,SAAS,QAAQ,EAAE,SAAS,cAAc,UAAU,GAAiB;AAC1E,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,eACL,oBAAC,OAAE,WAAW,GAAG,sCAAsC,SAAS,GAAG,aAAU,kBAC1E,wBACH,IACE;AAAA,EACN;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,aAAW;AAAA,MACX,WAAW,GAAG,aAAa,SAAS;AAAA,MACpC,aAAU;AAAA,MAET,kBAAQ,IAAI,CAAC,UACZ,qBAAC,iBAA6B,OAAO,MAAM,IAAI,qBAAmB,MAAM,IACtE;AAAA,4BAAC,oBAAiB,aAAY,WAC5B,+BAAC,UAAK,WAAU,0EACd;AAAA,8BAAC,UAAK,WAAU,uEACb,gBAAM,MACT;AAAA,UACA,oBAAC,UAAK,WAAU,sBACd,8BAAC,iBAAc,OAAO,MAAM,OAAO,OAAO,MAAM,YAAY,GAC9D;AAAA,UACA,oBAAC,UAAK,WAAU,kDACb,gBAAM,SACT;AAAA,WACF,GACF;AAAA,QACA,oBAAC,oBAAkB,gBAAM,MAAK;AAAA,WAdZ,MAAM,EAe1B,CACD;AAAA;AAAA,EACH;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -48,11 +48,17 @@ const CollapsibleGroup = React.forwardRef(
|
|
|
48
48
|
{
|
|
49
49
|
id: `collapsible-group-wrapper-${groupId}`,
|
|
50
50
|
className: cn(
|
|
51
|
-
|
|
51
|
+
// Aligned with Figma Accordion `210:4022`: rounded-10, three visual
|
|
52
|
+
// states (closed = white card + soft border + x-small shadow,
|
|
53
|
+
// hover-while-closed = bg-muted + no border + no shadow,
|
|
54
|
+
// open = bg-muted + no border + no shadow). Destructive border
|
|
55
|
+
// wins over the Figma states when the group has validation errors.
|
|
56
|
+
"rounded-[10px] border bg-card transition-colors",
|
|
52
57
|
!isHydrated && "invisible",
|
|
53
|
-
errorCount > 0
|
|
58
|
+
errorCount > 0 ? "border-destructive" : expanded ? "border-transparent bg-muted shadow-none" : "border-border shadow-xs hover:border-transparent hover:bg-muted hover:shadow-none"
|
|
54
59
|
),
|
|
55
60
|
"data-collapsible-group-id": groupId,
|
|
61
|
+
"data-state": expanded ? "open" : "closed",
|
|
56
62
|
"data-persistence-hydrated": isHydrated ? "true" : "false",
|
|
57
63
|
"aria-hidden": isHydrated ? void 0 : true,
|
|
58
64
|
children: [
|
|
@@ -72,7 +78,11 @@ const CollapsibleGroup = React.forwardRef(
|
|
|
72
78
|
variant: "muted",
|
|
73
79
|
onClick: toggle,
|
|
74
80
|
className: cn(
|
|
75
|
-
|
|
81
|
+
// Defer hover styling to the surrounding wrapper so the whole
|
|
82
|
+
// row toggles to `bg-muted` together (Figma Accordion behaviour)
|
|
83
|
+
// instead of stacking a second hover layer over the trigger
|
|
84
|
+
// button.
|
|
85
|
+
"flex-1 rounded-md px-2 py-1 text-sm font-medium hover:bg-transparent dark:hover:bg-transparent",
|
|
76
86
|
chevronPosition === "left" ? "justify-start gap-2" : "justify-between"
|
|
77
87
|
),
|
|
78
88
|
"aria-expanded": expanded,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/crud/CollapsibleGroup.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\nimport * as React from 'react'\nimport { ChevronDown } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '../../primitives/button'\nimport { useGroupCollapse } from './useGroupCollapse'\nimport { SortableGroupHandle, useSortableGroupHandle } from './SortableGroupHandle'\n\nexport interface CollapsibleGroupProps {\n groupId: string\n title?: string\n pageType: string\n defaultExpanded?: boolean\n errorCount?: number\n fieldCount?: number\n chevronPosition?: 'left' | 'right'\n icon?: React.ReactNode\n children: React.ReactNode\n}\n\nexport interface CollapsibleGroupHandle {\n expand: () => void\n}\n\nexport const CollapsibleGroup = React.forwardRef<CollapsibleGroupHandle, CollapsibleGroupProps>(\n function CollapsibleGroup({ groupId, title, pageType, defaultExpanded = true, errorCount = 0, fieldCount, chevronPosition = 'right', icon, children }, ref) {\n const t = useT()\n const { expanded, toggle, setExpanded, isHydrated } = useGroupCollapse(pageType, groupId, defaultExpanded)\n const contentId = `collapsible-group-${groupId}`\n const sortableHandle = useSortableGroupHandle()\n const showDragHandle = sortableHandle !== null\n\n React.useImperativeHandle(ref, () => ({\n expand: () => setExpanded(true),\n }), [setExpanded])\n\n const chevronIcon = (\n <ChevronDown\n className={cn(\n 'size-4 shrink-0 motion-safe:transition-transform motion-safe:duration-200',\n expanded && 'rotate-180'\n )}\n />\n )\n\n const fieldCountLabel = typeof fieldCount === 'number' && fieldCount > 0 ? (\n <span className=\"text-xs font-normal text-muted-foreground\">\n \u00B7 {fieldCount} {fieldCount === 1\n ? t('ui.collapsible.fieldSingular', 'field')\n : t('ui.collapsible.fieldPlural', 'fields')}\n </span>\n ) : null\n\n const errorBadge = errorCount > 0 ? (\n <span className=\"inline-flex items-center rounded-full bg-destructive/10 px-2 py-0.5 text-xs font-medium text-destructive\">\n {errorCount === 1\n ? t('ui.collapsible.errorSingular', '{{count}} error', { count: errorCount })\n : t('ui.collapsible.errorPlural', '{{count}} errors', { count: errorCount })}\n </span>\n ) : null\n\n const dragHandle = showDragHandle ? (\n <span\n className=\"inline-flex shrink-0 items-center\"\n onClick={(event) => event.stopPropagation()}\n onPointerDown={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n <SortableGroupHandle ariaLabel={t('ui.crud.dragHandle.aria', 'Drag to reorder')} />\n </span>\n ) : null\n\n return (\n <div\n id={`collapsible-group-wrapper-${groupId}`}\n className={cn(\n 'rounded-
|
|
5
|
-
"mappings": ";AAsCM,
|
|
4
|
+
"sourcesContent": ["'use client'\nimport * as React from 'react'\nimport { ChevronDown } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '../../primitives/button'\nimport { useGroupCollapse } from './useGroupCollapse'\nimport { SortableGroupHandle, useSortableGroupHandle } from './SortableGroupHandle'\n\nexport interface CollapsibleGroupProps {\n groupId: string\n title?: string\n pageType: string\n defaultExpanded?: boolean\n errorCount?: number\n fieldCount?: number\n chevronPosition?: 'left' | 'right'\n icon?: React.ReactNode\n children: React.ReactNode\n}\n\nexport interface CollapsibleGroupHandle {\n expand: () => void\n}\n\nexport const CollapsibleGroup = React.forwardRef<CollapsibleGroupHandle, CollapsibleGroupProps>(\n function CollapsibleGroup({ groupId, title, pageType, defaultExpanded = true, errorCount = 0, fieldCount, chevronPosition = 'right', icon, children }, ref) {\n const t = useT()\n const { expanded, toggle, setExpanded, isHydrated } = useGroupCollapse(pageType, groupId, defaultExpanded)\n const contentId = `collapsible-group-${groupId}`\n const sortableHandle = useSortableGroupHandle()\n const showDragHandle = sortableHandle !== null\n\n React.useImperativeHandle(ref, () => ({\n expand: () => setExpanded(true),\n }), [setExpanded])\n\n const chevronIcon = (\n <ChevronDown\n className={cn(\n 'size-4 shrink-0 motion-safe:transition-transform motion-safe:duration-200',\n expanded && 'rotate-180'\n )}\n />\n )\n\n const fieldCountLabel = typeof fieldCount === 'number' && fieldCount > 0 ? (\n <span className=\"text-xs font-normal text-muted-foreground\">\n \u00B7 {fieldCount} {fieldCount === 1\n ? t('ui.collapsible.fieldSingular', 'field')\n : t('ui.collapsible.fieldPlural', 'fields')}\n </span>\n ) : null\n\n const errorBadge = errorCount > 0 ? (\n <span className=\"inline-flex items-center rounded-full bg-destructive/10 px-2 py-0.5 text-xs font-medium text-destructive\">\n {errorCount === 1\n ? t('ui.collapsible.errorSingular', '{{count}} error', { count: errorCount })\n : t('ui.collapsible.errorPlural', '{{count}} errors', { count: errorCount })}\n </span>\n ) : null\n\n const dragHandle = showDragHandle ? (\n <span\n className=\"inline-flex shrink-0 items-center\"\n onClick={(event) => event.stopPropagation()}\n onPointerDown={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n <SortableGroupHandle ariaLabel={t('ui.crud.dragHandle.aria', 'Drag to reorder')} />\n </span>\n ) : null\n\n return (\n <div\n id={`collapsible-group-wrapper-${groupId}`}\n className={cn(\n // Aligned with Figma Accordion `210:4022`: rounded-10, three visual\n // states (closed = white card + soft border + x-small shadow,\n // hover-while-closed = bg-muted + no border + no shadow,\n // open = bg-muted + no border + no shadow). Destructive border\n // wins over the Figma states when the group has validation errors.\n 'rounded-[10px] border bg-card transition-colors',\n !isHydrated && 'invisible',\n errorCount > 0\n ? 'border-destructive'\n : expanded\n ? 'border-transparent bg-muted shadow-none'\n : 'border-border shadow-xs hover:border-transparent hover:bg-muted hover:shadow-none',\n )}\n data-collapsible-group-id={groupId}\n data-state={expanded ? 'open' : 'closed'}\n data-persistence-hydrated={isHydrated ? 'true' : 'false'}\n aria-hidden={isHydrated ? undefined : true}\n >\n {title && (\n <div\n className={cn(\n 'flex items-center gap-2 px-2 py-2',\n chevronPosition === 'left' ? 'flex-row' : 'flex-row',\n )}\n >\n {dragHandle}\n <Button\n type=\"button\"\n variant=\"muted\"\n onClick={toggle}\n className={cn(\n // Defer hover styling to the surrounding wrapper so the whole\n // row toggles to `bg-muted` together (Figma Accordion behaviour)\n // instead of stacking a second hover layer over the trigger\n // button.\n 'flex-1 rounded-md px-2 py-1 text-sm font-medium hover:bg-transparent dark:hover:bg-transparent',\n chevronPosition === 'left' ? 'justify-start gap-2' : 'justify-between',\n )}\n aria-expanded={expanded}\n aria-controls={contentId}\n >\n {chevronPosition === 'left' ? (\n <>\n {chevronIcon}\n <span className=\"flex items-center gap-2\">\n {icon && <span className=\"relative shrink-0 text-muted-foreground\">{icon}{!expanded && errorCount > 0 && <span className=\"absolute -right-0.5 -top-0.5 size-2 rounded-full bg-destructive\" />}</span>}\n <span>{title}</span>\n {fieldCountLabel}\n {errorBadge}\n </span>\n </>\n ) : (\n <>\n <span className=\"flex items-center gap-2\">\n {icon && <span className=\"relative shrink-0 text-muted-foreground\">{icon}{!expanded && errorCount > 0 && <span className=\"absolute -right-0.5 -top-0.5 size-2 rounded-full bg-destructive\" />}</span>}\n <span>{title}</span>\n {fieldCountLabel}\n {errorBadge}\n </span>\n {chevronIcon}\n </>\n )}\n </Button>\n </div>\n )}\n <div\n id={contentId}\n className={cn(\n 'motion-safe:transition-all motion-safe:duration-200 overflow-hidden',\n expanded ? 'max-h-[5000px] opacity-100' : 'max-h-0 opacity-0'\n )}\n >\n <div className=\"px-4 py-3\">\n {children}\n </div>\n </div>\n </div>\n )\n }\n)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["CollapsibleGroup"]
|
|
7
7
|
}
|
|
@@ -13,8 +13,10 @@ import {
|
|
|
13
13
|
SelectValue
|
|
14
14
|
} from "@open-mercato/ui/primitives/select";
|
|
15
15
|
import { Textarea } from "@open-mercato/ui/primitives/textarea";
|
|
16
|
+
import { DatePicker } from "@open-mercato/ui/primitives/date-picker";
|
|
16
17
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
17
18
|
import { cn } from "@open-mercato/shared/lib/utils";
|
|
19
|
+
import { format } from "date-fns";
|
|
18
20
|
import { LoadingMessage } from "./LoadingMessage.js";
|
|
19
21
|
import { mapCrudServerErrorToFormErrors } from "../utils/serverErrors.js";
|
|
20
22
|
import { MarkdownPreview } from "../markdown/index.js";
|
|
@@ -236,42 +238,88 @@ function InlineTextEditor({
|
|
|
236
238
|
}
|
|
237
239
|
},
|
|
238
240
|
children: [
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
241
|
+
(() => {
|
|
242
|
+
const lowerType = (inputType ?? resolvedType ?? "").toLowerCase();
|
|
243
|
+
const isDate = lowerType === "date";
|
|
244
|
+
const isDateTime = lowerType === "datetime-local" || lowerType === "datetime";
|
|
245
|
+
if (resolvedType === "tel") {
|
|
246
|
+
return /* @__PURE__ */ jsx(
|
|
247
|
+
PhoneNumberField,
|
|
248
|
+
{
|
|
249
|
+
value: draft.length ? draft : void 0,
|
|
250
|
+
onValueChange: (next) => {
|
|
251
|
+
if (error) setError(null);
|
|
252
|
+
setDraft(next ?? "");
|
|
253
|
+
},
|
|
254
|
+
placeholder,
|
|
255
|
+
autoFocus: true,
|
|
256
|
+
disabled: saving,
|
|
257
|
+
minDigits: 7
|
|
258
|
+
}
|
|
259
|
+
);
|
|
251
260
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
261
|
+
if (isDate || isDateTime) {
|
|
262
|
+
let parsed = null;
|
|
263
|
+
if (draft && draft.length) {
|
|
264
|
+
const candidate = new Date(draft);
|
|
265
|
+
if (!Number.isNaN(candidate.getTime())) parsed = candidate;
|
|
266
|
+
}
|
|
267
|
+
return /* @__PURE__ */ jsx(
|
|
268
|
+
DatePicker,
|
|
269
|
+
{
|
|
270
|
+
value: parsed,
|
|
271
|
+
onChange: (date) => {
|
|
272
|
+
if (error) setError(null);
|
|
273
|
+
const formatted = !date ? "" : isDateTime ? format(date, "yyyy-MM-dd'T'HH:mm") : format(date, "yyyy-MM-dd");
|
|
274
|
+
setDraft(formatted);
|
|
275
|
+
setSaving(true);
|
|
276
|
+
(async () => {
|
|
277
|
+
try {
|
|
278
|
+
await onSave(formatted.length ? formatted : null);
|
|
279
|
+
setEditingSafe(false);
|
|
280
|
+
} catch (err) {
|
|
281
|
+
setError(resolveInlineErrorMessage(err, fallbackError));
|
|
282
|
+
} finally {
|
|
283
|
+
setSaving(false);
|
|
284
|
+
}
|
|
285
|
+
})();
|
|
286
|
+
},
|
|
287
|
+
withTime: isDateTime,
|
|
288
|
+
footer: "apply-cancel",
|
|
289
|
+
placeholder,
|
|
290
|
+
disabled: saving
|
|
291
|
+
}
|
|
292
|
+
);
|
|
264
293
|
}
|
|
265
|
-
|
|
294
|
+
return /* @__PURE__ */ jsx(
|
|
295
|
+
"input",
|
|
296
|
+
{
|
|
297
|
+
className: "w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
298
|
+
value: draft,
|
|
299
|
+
onChange: (event) => {
|
|
300
|
+
if (error) setError(null);
|
|
301
|
+
setDraft(event.target.value);
|
|
302
|
+
},
|
|
303
|
+
placeholder,
|
|
304
|
+
type: inputType ?? resolvedType,
|
|
305
|
+
autoFocus: true
|
|
306
|
+
}
|
|
307
|
+
);
|
|
308
|
+
})(),
|
|
266
309
|
error ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: error }) : null,
|
|
267
310
|
renderBelowInput ? renderBelowInput({ draft, resolvedType, error, saving }) : null,
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
311
|
+
(() => {
|
|
312
|
+
const lowerType = (inputType ?? resolvedType ?? "").toLowerCase();
|
|
313
|
+
const isDateLike = lowerType === "date" || lowerType === "datetime-local" || lowerType === "datetime";
|
|
314
|
+
if (isDateLike) return null;
|
|
315
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
316
|
+
/* @__PURE__ */ jsxs(Button, { type: "submit", size: "sm", disabled: saving, children: [
|
|
317
|
+
saving ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-3.5 w-3.5 animate-spin" }) : null,
|
|
318
|
+
computedSaveLabel
|
|
319
|
+
] }),
|
|
320
|
+
/* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => setEditingSafe(false), disabled: saving, children: t("ui.detail.inline.cancel", "Cancel") })
|
|
321
|
+
] });
|
|
322
|
+
})()
|
|
275
323
|
]
|
|
276
324
|
}
|
|
277
325
|
) : /* @__PURE__ */ jsx("div", { className: variant === "plain" ? "" : "mt-1", children: displayContent })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/detail/InlineEditors.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport dynamic from 'next/dynamic'\nimport { FileCode, Loader2, Mail, Pencil, Phone, X } from 'lucide-react'\nimport type { PluggableList } from 'unified'\nimport { PhoneNumberField } from '@open-mercato/ui/backend/inputs/PhoneNumberField'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Textarea } from '@open-mercato/ui/primitives/textarea'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { LoadingMessage } from './LoadingMessage'\nimport { mapCrudServerErrorToFormErrors } from '../utils/serverErrors'\nimport { MarkdownPreview } from '../markdown'\n\nfunction resolveInlineErrorMessage(err: unknown, fallbackMessage: string): string {\n const { message, fieldErrors } = mapCrudServerErrorToFormErrors(err)\n const firstFieldError = fieldErrors\n ? Object.values(fieldErrors).find((text) => typeof text === 'string' && text.trim().length)\n : null\n if (typeof firstFieldError === 'string' && firstFieldError.trim().length) {\n return firstFieldError.trim()\n }\n if (typeof message === 'string' && message.trim().length) {\n return message.trim()\n }\n if (err instanceof Error && typeof err.message === 'string' && err.message.trim().length) {\n return err.message.trim()\n }\n if (typeof err === 'string' && err.trim().length) {\n return err.trim()\n }\n return fallbackMessage\n}\n\ntype EditorVariant = 'default' | 'muted' | 'plain'\n\nexport type InlineFieldType = 'text' | 'email' | 'tel' | 'url'\n\nconst ALLOWED_INLINE_URL_PROTOCOLS = new Set(['http:', 'https:', 'mailto:', 'tel:'])\n\nexport function resolveSafeInlineUrlHref(value: string): string | null {\n const trimmed = value.trim()\n if (!trimmed.length) return null\n try {\n const parsed = new URL(trimmed)\n return ALLOWED_INLINE_URL_PROTOCOLS.has(parsed.protocol) ? trimmed : null\n } catch {\n return null\n }\n}\n\nexport type InlineTextEditorProps = {\n label: string\n value: string | null | undefined\n placeholder?: string\n emptyLabel: string\n onSave: (value: string | null) => Promise<void>\n type?: InlineFieldType\n inputType?: React.HTMLInputTypeAttribute\n validator?: (value: string) => string | null\n variant?: EditorVariant\n activateOnClick?: boolean\n containerClassName?: string\n triggerClassName?: string\n hideLabel?: boolean\n renderDisplay?: (params: { value: string | null | undefined; emptyLabel: string; type: InlineFieldType }) => React.ReactNode\n onEditingChange?: (editing: boolean) => void\n renderActions?: React.ReactNode\n saveLabel?: string\n recordId?: string\n onDraftChange?: (draft: string) => void\n renderBelowInput?: (params: {\n draft: string\n resolvedType: InlineFieldType\n error: string | null\n saving: boolean\n }) => React.ReactNode\n}\n\nexport function InlineTextEditor({\n label,\n value,\n placeholder,\n emptyLabel,\n onSave,\n type = 'text',\n inputType,\n validator,\n variant = 'default',\n activateOnClick = false,\n containerClassName,\n triggerClassName,\n hideLabel = false,\n renderDisplay,\n onEditingChange,\n renderActions,\n saveLabel,\n onDraftChange,\n renderBelowInput,\n}: InlineTextEditorProps) {\n const t = useT()\n const [editing, setEditing] = React.useState(false)\n const [draft, setDraft] = React.useState(value ?? '')\n const [error, setError] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n const computedSaveLabel = saveLabel ?? t('ui.detail.inline.saveShortcut', 'Save \u2318\u23CE / Ctrl+Enter')\n const fallbackError = React.useMemo(\n () => t('ui.detail.inline.error', 'Failed to save value.'),\n [t],\n )\n const resolvedType = React.useMemo<InlineFieldType>(() => {\n if (type && typeof type === 'string') return type\n if (inputType && typeof inputType === 'string') {\n const normalized = inputType.toLowerCase()\n if (normalized === 'email' || normalized === 'tel' || normalized === 'url') {\n return normalized as InlineFieldType\n }\n }\n return 'text'\n }, [inputType, type])\n\n React.useEffect(() => {\n if (!editing) setDraft(value ?? '')\n }, [editing, value])\n\n React.useEffect(() => {\n if (onDraftChange) onDraftChange(draft)\n }, [draft, onDraftChange])\n\n const containerClasses = cn(\n 'group overflow-hidden',\n variant === 'muted'\n ? 'relative rounded border bg-muted/30 p-3'\n : variant === 'plain'\n ? 'relative flex items-center gap-3 rounded-none border-0 p-0'\n : 'rounded-lg border p-4',\n activateOnClick && !editing ? 'cursor-pointer' : null,\n containerClassName ?? null,\n )\n const readOnlyWrapperClasses = cn(\n 'flex-1 min-w-0',\n activateOnClick && !editing ? 'cursor-pointer' : null,\n variant === 'plain' ? 'flex items-center gap-2' : null,\n )\n const triggerClasses = cn(\n 'shrink-0 transition-opacity duration-150',\n editing\n ? 'opacity-100'\n : 'opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100',\n variant === 'muted' ? 'h-8 w-8' : null,\n triggerClassName ?? null,\n )\n const triggerSize = variant === 'plain' ? 'icon' : 'sm'\n\n const setEditingSafe = React.useCallback(\n (next: boolean) => {\n setEditing(next)\n if (onEditingChange) onEditingChange(next)\n },\n [onEditingChange],\n )\n\n const handleActivate = React.useCallback(() => {\n if (!editing) setEditingSafe(true)\n }, [editing, setEditingSafe])\n\n const handleInteractiveClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n const target = event.target as HTMLElement\n const interactiveElement = target.closest('button, input, select, textarea, a, [role=\"link\"]')\n if (interactiveElement) {\n if (interactiveElement.tagName.toLowerCase() === 'a') {\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return\n }\n event.preventDefault()\n // let the link click toggle edit mode instead of navigating away\n } else {\n return\n }\n }\n handleActivate()\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const handleContainerKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n handleActivate()\n }\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const handleSave = React.useCallback(async () => {\n const trimmed = draft.trim()\n if (validator) {\n const validationError = validator(trimmed)\n if (validationError) {\n setError(validationError)\n return\n }\n }\n setError(null)\n setSaving(true)\n try {\n await onSave(trimmed.length ? trimmed : null)\n setEditingSafe(false)\n } catch (err) {\n setError(resolveInlineErrorMessage(err, fallbackError))\n } finally {\n setSaving(false)\n }\n }, [draft, fallbackError, onSave, setEditingSafe, validator])\n\n const interactiveProps: React.HTMLAttributes<HTMLDivElement> =\n activateOnClick && !editing\n ? {\n role: 'button' as const,\n tabIndex: 0,\n onKeyDown: handleContainerKeyDown,\n }\n : {}\n\n const displayContent = React.useMemo(() => {\n if (renderDisplay) {\n return renderDisplay({ value, emptyLabel, type: resolvedType })\n }\n const baseValue = value && typeof value === 'string' ? value : ''\n const anchorClass =\n variant === 'plain'\n ? 'inline-flex max-w-full min-w-0 items-center gap-2 text-xl font-semibold leading-tight text-primary hover:text-primary/90 hover:underline'\n : 'flex max-w-full min-w-0 items-center gap-2 text-sm text-primary hover:text-primary/90 hover:underline'\n const textClass = variant === 'plain' ? 'text-2xl font-semibold leading-tight' : 'text-sm break-words'\n if (resolvedType === 'email') {\n if (!baseValue.length) {\n return (\n <p className={variant === 'plain' ? 'text-base text-muted-foreground' : 'text-sm text-muted-foreground'}>\n {emptyLabel}\n </p>\n )\n }\n return (\n <a className={anchorClass} href={`mailto:${baseValue}`}>\n <Mail aria-hidden className={variant === 'plain' ? 'h-5 w-5' : 'h-4 w-4'} />\n <span className=\"truncate min-w-0\">{baseValue}</span>\n </a>\n )\n }\n if (!baseValue.length) {\n return (\n <p className={variant === 'plain' ? 'text-base text-muted-foreground' : 'text-sm text-muted-foreground'}>\n {emptyLabel}\n </p>\n )\n }\n if (resolvedType === 'tel') {\n const sanitizedValue = baseValue.replace(/[^+\\d]/g, '')\n const hrefValue = sanitizedValue.length ? sanitizedValue : baseValue\n return (\n <a className={anchorClass} href={`tel:${hrefValue}`}>\n <Phone aria-hidden className={variant === 'plain' ? 'h-5 w-5' : 'h-4 w-4'} />\n <span className=\"truncate\">{baseValue}</span>\n </a>\n )\n }\n if (resolvedType === 'url') {\n const safeHref = resolveSafeInlineUrlHref(baseValue)\n if (!safeHref) {\n return <p className={textClass}>{baseValue}</p>\n }\n return (\n <a className={textClass} href={safeHref} target=\"_blank\" rel=\"noopener noreferrer\">\n {baseValue}\n </a>\n )\n }\n return <p className={textClass}>{baseValue}</p>\n }, [emptyLabel, renderDisplay, resolvedType, value, variant])\n\n const editingContainerClass = variant === 'plain' ? 'mt-0 w-full max-w-sm space-y-3' : 'mt-2 space-y-3'\n\n return (\n <div className={containerClasses} onClick={handleInteractiveClick}>\n <div className=\"flex items-start justify-between gap-2 min-w-0\">\n <div className={readOnlyWrapperClasses} {...interactiveProps}>\n {hideLabel ? null : <p className=\"text-xs uppercase tracking-wide text-muted-foreground\">{label}</p>}\n {editing ? (\n <form\n className={editingContainerClass}\n onSubmit={(event) => {\n event.preventDefault()\n if (!saving) void handleSave()\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n setEditingSafe(false)\n setError(null)\n return\n }\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n if (!saving) void handleSave()\n }\n }}\n >\n {resolvedType === 'tel' ? (\n <PhoneNumberField\n value={draft.length ? draft : undefined}\n onValueChange={(next) => {\n if (error) setError(null)\n setDraft(next ?? '')\n }}\n placeholder={placeholder}\n autoFocus\n disabled={saving}\n minDigits={7}\n />\n ) : (\n <input\n className=\"w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n value={draft}\n onChange={(event) => {\n if (error) setError(null)\n setDraft(event.target.value)\n }}\n placeholder={placeholder}\n type={inputType ?? resolvedType}\n autoFocus\n />\n )}\n {error ? <p className=\"text-xs text-destructive\">{error}</p> : null}\n {renderBelowInput ? renderBelowInput({ draft, resolvedType, error, saving }) : null}\n <div className=\"flex items-center gap-2\">\n <Button type=\"submit\" size=\"sm\" disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 h-3.5 w-3.5 animate-spin\" /> : null}\n {computedSaveLabel}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setEditingSafe(false)} disabled={saving}>\n {t('ui.detail.inline.cancel', 'Cancel')}\n </Button>\n </div>\n </form>\n ) : (\n <div className={variant === 'plain' ? '' : 'mt-1'}>{displayContent}</div>\n )}\n </div>\n {renderActions ? <div className=\"flex items-center gap-2\">{renderActions}</div> : null}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size={triggerSize}\n className={triggerClasses}\n onClick={(event) => {\n event.stopPropagation()\n const next = !editing\n setEditingSafe(next)\n }}\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n </Button>\n </div>\n </div>\n )\n}\n\nexport type InlineMultilineEditorProps = {\n label: string\n value: string | null | undefined\n placeholder?: string\n emptyLabel: string\n onSave: (value: string | null) => Promise<void>\n validator?: (value: string) => string | null\n variant?: EditorVariant\n activateOnClick?: boolean\n containerClassName?: string\n triggerClassName?: string\n renderDisplay?: (params: { value: string | null | undefined; emptyLabel: string }) => React.ReactNode\n}\n\ntype UiMarkdownEditorProps = {\n value?: string\n height?: number\n onChange?: (value?: string) => void\n previewOptions?: { remarkPlugins?: unknown[] }\n}\n\nconst isTestEnv =\n typeof process !== 'undefined' &&\n (process.env.NODE_ENV === 'test' || typeof process.env.JEST_WORKER_ID !== 'undefined')\n\nfunction MarkdownEditorFallback() {\n const t = useT()\n return (\n <LoadingMessage label={t('ui.detail.inline.editorLoading', 'Loading editor\u2026')} className=\"min-h-[200px] justify-center\" />\n )\n}\n\nconst MarkdownEditorTestStub: React.ComponentType<UiMarkdownEditorProps> = ({ value, onChange }) => (\n <Textarea\n data-testid=\"markdown-editor\"\n rows={8}\n value={value ?? ''}\n onChange={(event) => onChange?.(event.target.value)}\n />\n)\n\nconst MarkdownEditorComponent: React.ComponentType<UiMarkdownEditorProps> = isTestEnv\n ? MarkdownEditorTestStub\n : (dynamic(() => import('@uiw/react-md-editor'), {\n ssr: false,\n loading: () => <MarkdownEditorFallback />,\n }) as unknown as React.ComponentType<UiMarkdownEditorProps>)\n\nlet markdownPluginsPromise: Promise<PluggableList> | null = null\n\nasync function loadMarkdownPlugins(): Promise<PluggableList> {\n if (isTestEnv) return []\n if (!markdownPluginsPromise) {\n markdownPluginsPromise = import('remark-gfm')\n .then((mod) => [mod.default ?? mod] as PluggableList)\n .catch(() => [])\n }\n return markdownPluginsPromise\n}\n\nexport function InlineMultilineEditor({\n label,\n value,\n placeholder,\n emptyLabel,\n onSave,\n validator,\n variant = 'default',\n activateOnClick = true,\n containerClassName,\n triggerClassName,\n renderDisplay,\n}: InlineMultilineEditorProps) {\n const t = useT()\n const [editing, setEditing] = React.useState(false)\n const [draft, setDraft] = React.useState(value ?? '')\n const [error, setError] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n const [isMarkdownEnabled, setIsMarkdownEnabled] = React.useState(true)\n const textareaRef = React.useRef<HTMLTextAreaElement | null>(null)\n const markdownEditorRef = React.useRef<HTMLDivElement | null>(null)\n const [markdownPlugins, setMarkdownPlugins] = React.useState<PluggableList>([])\n const fallbackError = React.useMemo(\n () => t('ui.detail.inline.error', 'Failed to save value.'),\n [t],\n )\n React.useEffect(() => {\n if (isTestEnv) return\n let mounted = true\n void loadMarkdownPlugins().then((plugins) => {\n if (!mounted) return\n setMarkdownPlugins(plugins)\n })\n return () => {\n mounted = false\n }\n }, [])\n\n const adjustTextareaSize = React.useCallback((element: HTMLTextAreaElement | null) => {\n if (!element) return\n element.style.height = 'auto'\n element.style.height = `${element.scrollHeight}px`\n }, [])\n\n React.useEffect(() => {\n adjustTextareaSize(textareaRef.current)\n }, [adjustTextareaSize, draft, isMarkdownEnabled])\n\n React.useEffect(() => {\n if (!editing) return\n if (isMarkdownEnabled) {\n const element = markdownEditorRef.current?.querySelector('textarea')\n if (!element) return\n window.requestAnimationFrame(() => {\n element.focus()\n })\n return\n }\n const element = textareaRef.current\n if (!element) return\n window.requestAnimationFrame(() => {\n adjustTextareaSize(element)\n element.focus()\n })\n }, [adjustTextareaSize, editing, isMarkdownEnabled])\n\n const handleMarkdownToggle = React.useCallback(() => {\n setIsMarkdownEnabled((prev) => !prev)\n }, [])\n\n React.useEffect(() => {\n if (!editing) {\n setDraft(value ?? '')\n setError(null)\n }\n }, [editing, value])\n\n const handleActivate = React.useCallback(() => {\n if (!editing) setEditing(true)\n }, [editing])\n\n const handleInteractiveClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n const target = event.target as HTMLElement\n const interactiveElement = target.closest('button, input, select, textarea, a, [role=\"link\"]')\n if (interactiveElement) {\n if (interactiveElement.tagName.toLowerCase() === 'a') {\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return\n }\n event.preventDefault()\n // Links should not block activation; let the click toggle edit mode\n } else {\n return\n }\n }\n handleActivate()\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const handleContainerKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n handleActivate()\n }\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const adjustError = React.useCallback(\n (nextValue: string) => {\n if (!validator) return null\n const trimmed = nextValue.trim()\n return validator(trimmed)\n },\n [validator],\n )\n\n const containerClasses = cn(\n 'group rounded-lg border p-4',\n variant === 'muted' ? 'bg-muted/30' : null,\n activateOnClick && !editing ? 'cursor-pointer' : null,\n containerClassName ?? null,\n )\n const triggerClasses = cn(\n 'transition-opacity duration-150',\n editing\n ? 'opacity-100'\n : 'opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100',\n triggerClassName ?? null,\n )\n\n const handleSave = React.useCallback(async () => {\n const trimmed = draft.trim()\n const validationError = adjustError(draft)\n if (validationError) {\n setError(validationError)\n return\n }\n setSaving(true)\n try {\n await onSave(trimmed.length ? trimmed : null)\n setEditing(false)\n } catch (err) {\n setError(resolveInlineErrorMessage(err, fallbackError))\n } finally {\n setSaving(false)\n }\n }, [adjustError, draft, fallbackError, onSave])\n\n return (\n <div className={containerClasses} onClick={handleInteractiveClick}>\n <div className=\"flex items-start justify-between gap-2\">\n <div\n className={cn('flex-1 min-w-0', activateOnClick && !editing ? 'cursor-pointer' : null)}\n {...(activateOnClick && !editing\n ? { role: 'button' as const, tabIndex: 0, onKeyDown: handleContainerKeyDown }\n : {})}\n >\n <p className=\"text-xs uppercase tracking-wide text-muted-foreground\">{label}</p>\n {editing ? (\n <form\n className=\"mt-2 space-y-3\"\n onSubmit={(event) => {\n event.preventDefault()\n if (!saving) void handleSave()\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n setEditing(false)\n setError(null)\n return\n }\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n if (!saving) void handleSave()\n }\n }}\n >\n {isMarkdownEnabled ? (\n <div\n ref={markdownEditorRef}\n className={cn(\n 'w-full rounded-md border border-muted-foreground/30 bg-background p-2',\n saving ? 'pointer-events-none opacity-75' : null,\n )}\n >\n <div data-color-mode=\"light\" className=\"w-full\">\n <MarkdownEditorComponent\n value={draft}\n height={220}\n onChange={(nextValue) => {\n if (error) setError(null)\n setDraft(typeof nextValue === 'string' ? nextValue : '')\n }}\n previewOptions={{ remarkPlugins: markdownPlugins }}\n />\n </div>\n </div>\n ) : (\n <Textarea\n ref={textareaRef}\n rows={3}\n className=\"w-full resize-none overflow-hidden rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n placeholder={placeholder}\n value={draft}\n onChange={(event) => {\n if (error) setError(null)\n setDraft(event.target.value)\n }}\n onInput={(event) => adjustTextareaSize(event.currentTarget)}\n autoFocus\n disabled={saving}\n />\n )}\n {error ? <p className=\"text-xs text-destructive\">{error}</p> : null}\n <div className=\"flex items-center gap-2\">\n <Button type=\"submit\" size=\"sm\" disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 h-3.5 w-3.5 animate-spin\" /> : null}\n {t('ui.detail.inline.saveShortcut', 'Save \u2318\u23CE / Ctrl+Enter')}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setEditing(false)} disabled={saving}>\n {t('ui.detail.inline.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={handleMarkdownToggle}\n aria-pressed={isMarkdownEnabled}\n title={\n isMarkdownEnabled\n ? t('ui.detail.inline.markdownDisable', 'Disable Markdown')\n : t('ui.detail.inline.markdownEnable', 'Enable Markdown')\n }\n aria-label={\n isMarkdownEnabled\n ? t('ui.detail.inline.markdownDisable', 'Disable Markdown')\n : t('ui.detail.inline.markdownEnable', 'Enable Markdown')\n }\n className={cn('h-8 w-8', isMarkdownEnabled ? 'text-primary' : undefined)}\n disabled={saving}\n >\n <FileCode className=\"h-4 w-4\" aria-hidden />\n <span className=\"sr-only\">\n {isMarkdownEnabled\n ? t('ui.detail.inline.markdownDisable', 'Disable Markdown')\n : t('ui.detail.inline.markdownEnable', 'Enable Markdown')}\n </span>\n </Button>\n </div>\n </form>\n ) : (\n <div\n className={cn(\n 'mt-1 text-sm break-words',\n renderDisplay ? null : 'whitespace-pre-wrap',\n activateOnClick && !editing ? 'cursor-pointer' : null,\n )}\n >\n {renderDisplay ? (\n renderDisplay({ value, emptyLabel })\n ) : value && value.length ? (\n <MarkdownPreview\n remarkPlugins={markdownPlugins}\n className=\"prose prose-sm max-w-none text-foreground [&>*]:my-2 [&>*:last-child]:mb-0 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5\"\n >\n {value}\n </MarkdownPreview>\n ) : (\n <span className=\"text-muted-foreground\">{emptyLabel}</span>\n )}\n </div>\n )}\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className={triggerClasses}\n onClick={(event) => {\n event.stopPropagation()\n setEditing((state) => !state)\n }}\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n </Button>\n </div>\n </div>\n )\n}\n\nexport type InlineSelectOption = { value: string; label: string; description?: string }\n\nexport type InlineSelectEditorProps = {\n label: string\n value: string | null | undefined\n emptyLabel: string\n options: InlineSelectOption[]\n onSave: (value: string | null) => Promise<void>\n variant?: EditorVariant\n activateOnClick?: boolean\n containerClassName?: string\n triggerClassName?: string\n hideLabel?: boolean\n renderEditor?: (params: { value: string; onChange: (next: string) => void }) => React.ReactNode\n renderDisplay?: (params: { value: string | null | undefined; emptyLabel: string }) => React.ReactNode\n}\n\nexport function InlineSelectEditor({\n label,\n value,\n emptyLabel,\n options,\n onSave,\n variant = 'default',\n activateOnClick = false,\n containerClassName,\n triggerClassName,\n hideLabel = false,\n renderEditor,\n renderDisplay,\n}: InlineSelectEditorProps) {\n const t = useT()\n const [editing, setEditing] = React.useState(false)\n const [draft, setDraft] = React.useState<string>(value ?? '')\n const [saving, setSaving] = React.useState(false)\n\n React.useEffect(() => {\n if (!editing) setDraft(value ?? '')\n }, [editing, value])\n\n const containerClasses = cn(\n 'group',\n variant === 'muted'\n ? 'relative rounded border bg-muted/30 p-3'\n : variant === 'plain'\n ? 'relative flex flex-col gap-1 rounded-none border-0 p-0'\n : 'rounded-lg border bg-card p-4',\n activateOnClick && !editing ? 'cursor-pointer' : null,\n containerClassName ?? null,\n )\n const triggerClasses = cn(\n 'shrink-0 transition-opacity duration-150',\n editing\n ? 'opacity-100'\n : 'opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100',\n variant === 'muted' ? 'h-8 w-8' : null,\n triggerClassName ?? null,\n )\n\n const handleSave = React.useCallback(async () => {\n setSaving(true)\n try {\n await onSave(draft.length ? draft : null)\n setEditing(false)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('ui.detail.inline.error', 'Failed to save value.')\n console.error(message, err)\n } finally {\n setSaving(false)\n }\n }, [draft, onSave, t])\n\n const selected = options.find((option) => option.value === value)\n\n const interactiveProps: React.HTMLAttributes<HTMLDivElement> =\n activateOnClick && !editing\n ? {\n role: 'button' as const,\n tabIndex: 0,\n onClick: () => setEditing(true),\n onKeyDown: (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n setEditing(true)\n }\n },\n }\n : {}\n\n return (\n <div className={containerClasses}>\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\" {...interactiveProps}>\n {hideLabel ? null : <p className=\"text-xs uppercase tracking-wide text-muted-foreground\">{label}</p>}\n {editing ? (\n <div className={variant === 'plain' ? 'space-y-2 pt-1' : 'mt-2 space-y-2'}>\n {renderEditor ? (\n renderEditor({ value: draft, onChange: setDraft })\n ) : (\n <Select\n value={draft || undefined}\n onValueChange={(next) => setDraft(next ?? '')}\n >\n <SelectTrigger>\n <SelectValue placeholder={t('ui.detail.inline.select.placeholder', 'Not set')} />\n </SelectTrigger>\n <SelectContent>\n {options.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" size=\"sm\" onClick={() => void handleSave()} disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 h-3.5 w-3.5 animate-spin\" /> : null}\n {t('ui.detail.inline.saveShortcut', 'Save \u2318\u23CE / Ctrl+Enter')}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setEditing(false)} disabled={saving}>\n {t('ui.detail.inline.cancel', 'Cancel')}\n </Button>\n </div>\n </div>\n ) : (\n <div className={variant === 'plain' ? 'flex items-center gap-2' : 'mt-1 text-sm'}>\n {renderDisplay ? (\n renderDisplay({ value, emptyLabel })\n ) : selected ? (\n <div className=\"space-y-0.5\">\n <p className=\"font-medium leading-tight\">{selected.label}</p>\n {selected.description ? (\n <p className=\"text-xs text-muted-foreground\">{selected.description}</p>\n ) : null}\n </div>\n ) : (\n <span className=\"text-muted-foreground\">{emptyLabel}</span>\n )}\n </div>\n )}\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size={variant === 'plain' ? 'icon' : 'sm'}\n className={triggerClasses}\n onClick={(event) => {\n event.stopPropagation()\n setEditing((state) => !state)\n }}\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n </Button>\n </div>\n </div>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport dynamic from 'next/dynamic'\nimport { FileCode, Loader2, Mail, Pencil, Phone, X } from 'lucide-react'\nimport type { PluggableList } from 'unified'\nimport { PhoneNumberField } from '@open-mercato/ui/backend/inputs/PhoneNumberField'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Textarea } from '@open-mercato/ui/primitives/textarea'\nimport { DatePicker } from '@open-mercato/ui/primitives/date-picker'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { format } from 'date-fns'\nimport { LoadingMessage } from './LoadingMessage'\nimport { mapCrudServerErrorToFormErrors } from '../utils/serverErrors'\nimport { MarkdownPreview } from '../markdown'\n\nfunction resolveInlineErrorMessage(err: unknown, fallbackMessage: string): string {\n const { message, fieldErrors } = mapCrudServerErrorToFormErrors(err)\n const firstFieldError = fieldErrors\n ? Object.values(fieldErrors).find((text) => typeof text === 'string' && text.trim().length)\n : null\n if (typeof firstFieldError === 'string' && firstFieldError.trim().length) {\n return firstFieldError.trim()\n }\n if (typeof message === 'string' && message.trim().length) {\n return message.trim()\n }\n if (err instanceof Error && typeof err.message === 'string' && err.message.trim().length) {\n return err.message.trim()\n }\n if (typeof err === 'string' && err.trim().length) {\n return err.trim()\n }\n return fallbackMessage\n}\n\ntype EditorVariant = 'default' | 'muted' | 'plain'\n\nexport type InlineFieldType = 'text' | 'email' | 'tel' | 'url'\n\nconst ALLOWED_INLINE_URL_PROTOCOLS = new Set(['http:', 'https:', 'mailto:', 'tel:'])\n\nexport function resolveSafeInlineUrlHref(value: string): string | null {\n const trimmed = value.trim()\n if (!trimmed.length) return null\n try {\n const parsed = new URL(trimmed)\n return ALLOWED_INLINE_URL_PROTOCOLS.has(parsed.protocol) ? trimmed : null\n } catch {\n return null\n }\n}\n\nexport type InlineTextEditorProps = {\n label: string\n value: string | null | undefined\n placeholder?: string\n emptyLabel: string\n onSave: (value: string | null) => Promise<void>\n type?: InlineFieldType\n inputType?: React.HTMLInputTypeAttribute\n validator?: (value: string) => string | null\n variant?: EditorVariant\n activateOnClick?: boolean\n containerClassName?: string\n triggerClassName?: string\n hideLabel?: boolean\n renderDisplay?: (params: { value: string | null | undefined; emptyLabel: string; type: InlineFieldType }) => React.ReactNode\n onEditingChange?: (editing: boolean) => void\n renderActions?: React.ReactNode\n saveLabel?: string\n recordId?: string\n onDraftChange?: (draft: string) => void\n renderBelowInput?: (params: {\n draft: string\n resolvedType: InlineFieldType\n error: string | null\n saving: boolean\n }) => React.ReactNode\n}\n\nexport function InlineTextEditor({\n label,\n value,\n placeholder,\n emptyLabel,\n onSave,\n type = 'text',\n inputType,\n validator,\n variant = 'default',\n activateOnClick = false,\n containerClassName,\n triggerClassName,\n hideLabel = false,\n renderDisplay,\n onEditingChange,\n renderActions,\n saveLabel,\n onDraftChange,\n renderBelowInput,\n}: InlineTextEditorProps) {\n const t = useT()\n const [editing, setEditing] = React.useState(false)\n const [draft, setDraft] = React.useState(value ?? '')\n const [error, setError] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n const computedSaveLabel = saveLabel ?? t('ui.detail.inline.saveShortcut', 'Save \u2318\u23CE / Ctrl+Enter')\n const fallbackError = React.useMemo(\n () => t('ui.detail.inline.error', 'Failed to save value.'),\n [t],\n )\n const resolvedType = React.useMemo<InlineFieldType>(() => {\n if (type && typeof type === 'string') return type\n if (inputType && typeof inputType === 'string') {\n const normalized = inputType.toLowerCase()\n if (normalized === 'email' || normalized === 'tel' || normalized === 'url') {\n return normalized as InlineFieldType\n }\n }\n return 'text'\n }, [inputType, type])\n\n React.useEffect(() => {\n if (!editing) setDraft(value ?? '')\n }, [editing, value])\n\n React.useEffect(() => {\n if (onDraftChange) onDraftChange(draft)\n }, [draft, onDraftChange])\n\n const containerClasses = cn(\n 'group overflow-hidden',\n variant === 'muted'\n ? 'relative rounded border bg-muted/30 p-3'\n : variant === 'plain'\n ? 'relative flex items-center gap-3 rounded-none border-0 p-0'\n : 'rounded-lg border p-4',\n activateOnClick && !editing ? 'cursor-pointer' : null,\n containerClassName ?? null,\n )\n const readOnlyWrapperClasses = cn(\n 'flex-1 min-w-0',\n activateOnClick && !editing ? 'cursor-pointer' : null,\n variant === 'plain' ? 'flex items-center gap-2' : null,\n )\n const triggerClasses = cn(\n 'shrink-0 transition-opacity duration-150',\n editing\n ? 'opacity-100'\n : 'opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100',\n variant === 'muted' ? 'h-8 w-8' : null,\n triggerClassName ?? null,\n )\n const triggerSize = variant === 'plain' ? 'icon' : 'sm'\n\n const setEditingSafe = React.useCallback(\n (next: boolean) => {\n setEditing(next)\n if (onEditingChange) onEditingChange(next)\n },\n [onEditingChange],\n )\n\n const handleActivate = React.useCallback(() => {\n if (!editing) setEditingSafe(true)\n }, [editing, setEditingSafe])\n\n const handleInteractiveClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n const target = event.target as HTMLElement\n const interactiveElement = target.closest('button, input, select, textarea, a, [role=\"link\"]')\n if (interactiveElement) {\n if (interactiveElement.tagName.toLowerCase() === 'a') {\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return\n }\n event.preventDefault()\n // let the link click toggle edit mode instead of navigating away\n } else {\n return\n }\n }\n handleActivate()\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const handleContainerKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n handleActivate()\n }\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const handleSave = React.useCallback(async () => {\n const trimmed = draft.trim()\n if (validator) {\n const validationError = validator(trimmed)\n if (validationError) {\n setError(validationError)\n return\n }\n }\n setError(null)\n setSaving(true)\n try {\n await onSave(trimmed.length ? trimmed : null)\n setEditingSafe(false)\n } catch (err) {\n setError(resolveInlineErrorMessage(err, fallbackError))\n } finally {\n setSaving(false)\n }\n }, [draft, fallbackError, onSave, setEditingSafe, validator])\n\n const interactiveProps: React.HTMLAttributes<HTMLDivElement> =\n activateOnClick && !editing\n ? {\n role: 'button' as const,\n tabIndex: 0,\n onKeyDown: handleContainerKeyDown,\n }\n : {}\n\n const displayContent = React.useMemo(() => {\n if (renderDisplay) {\n return renderDisplay({ value, emptyLabel, type: resolvedType })\n }\n const baseValue = value && typeof value === 'string' ? value : ''\n const anchorClass =\n variant === 'plain'\n ? 'inline-flex max-w-full min-w-0 items-center gap-2 text-xl font-semibold leading-tight text-primary hover:text-primary/90 hover:underline'\n : 'flex max-w-full min-w-0 items-center gap-2 text-sm text-primary hover:text-primary/90 hover:underline'\n const textClass = variant === 'plain' ? 'text-2xl font-semibold leading-tight' : 'text-sm break-words'\n if (resolvedType === 'email') {\n if (!baseValue.length) {\n return (\n <p className={variant === 'plain' ? 'text-base text-muted-foreground' : 'text-sm text-muted-foreground'}>\n {emptyLabel}\n </p>\n )\n }\n return (\n <a className={anchorClass} href={`mailto:${baseValue}`}>\n <Mail aria-hidden className={variant === 'plain' ? 'h-5 w-5' : 'h-4 w-4'} />\n <span className=\"truncate min-w-0\">{baseValue}</span>\n </a>\n )\n }\n if (!baseValue.length) {\n return (\n <p className={variant === 'plain' ? 'text-base text-muted-foreground' : 'text-sm text-muted-foreground'}>\n {emptyLabel}\n </p>\n )\n }\n if (resolvedType === 'tel') {\n const sanitizedValue = baseValue.replace(/[^+\\d]/g, '')\n const hrefValue = sanitizedValue.length ? sanitizedValue : baseValue\n return (\n <a className={anchorClass} href={`tel:${hrefValue}`}>\n <Phone aria-hidden className={variant === 'plain' ? 'h-5 w-5' : 'h-4 w-4'} />\n <span className=\"truncate\">{baseValue}</span>\n </a>\n )\n }\n if (resolvedType === 'url') {\n const safeHref = resolveSafeInlineUrlHref(baseValue)\n if (!safeHref) {\n return <p className={textClass}>{baseValue}</p>\n }\n return (\n <a className={textClass} href={safeHref} target=\"_blank\" rel=\"noopener noreferrer\">\n {baseValue}\n </a>\n )\n }\n return <p className={textClass}>{baseValue}</p>\n }, [emptyLabel, renderDisplay, resolvedType, value, variant])\n\n const editingContainerClass = variant === 'plain' ? 'mt-0 w-full max-w-sm space-y-3' : 'mt-2 space-y-3'\n\n return (\n <div className={containerClasses} onClick={handleInteractiveClick}>\n <div className=\"flex items-start justify-between gap-2 min-w-0\">\n <div className={readOnlyWrapperClasses} {...interactiveProps}>\n {hideLabel ? null : <p className=\"text-xs uppercase tracking-wide text-muted-foreground\">{label}</p>}\n {editing ? (\n <form\n className={editingContainerClass}\n onSubmit={(event) => {\n event.preventDefault()\n if (!saving) void handleSave()\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n setEditingSafe(false)\n setError(null)\n return\n }\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n if (!saving) void handleSave()\n }\n }}\n >\n {(() => {\n const lowerType = (inputType ?? resolvedType ?? '').toLowerCase()\n const isDate = lowerType === 'date'\n const isDateTime = lowerType === 'datetime-local' || lowerType === 'datetime'\n if (resolvedType === 'tel') {\n return (\n <PhoneNumberField\n value={draft.length ? draft : undefined}\n onValueChange={(next) => {\n if (error) setError(null)\n setDraft(next ?? '')\n }}\n placeholder={placeholder}\n autoFocus\n disabled={saving}\n minDigits={7}\n />\n )\n }\n if (isDate || isDateTime) {\n let parsed: Date | null = null\n if (draft && draft.length) {\n const candidate = new Date(draft)\n if (!Number.isNaN(candidate.getTime())) parsed = candidate\n }\n return (\n <DatePicker\n value={parsed}\n onChange={(date) => {\n if (error) setError(null)\n const formatted = !date\n ? ''\n : isDateTime\n ? format(date, \"yyyy-MM-dd'T'HH:mm\")\n : format(date, 'yyyy-MM-dd')\n setDraft(formatted)\n setSaving(true)\n ;(async () => {\n try {\n await onSave(formatted.length ? formatted : null)\n setEditingSafe(false)\n } catch (err) {\n setError(resolveInlineErrorMessage(err, fallbackError))\n } finally {\n setSaving(false)\n }\n })()\n }}\n withTime={isDateTime}\n footer=\"apply-cancel\"\n placeholder={placeholder}\n disabled={saving}\n />\n )\n }\n return (\n <input\n className=\"w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n value={draft}\n onChange={(event) => {\n if (error) setError(null)\n setDraft(event.target.value)\n }}\n placeholder={placeholder}\n type={inputType ?? resolvedType}\n autoFocus\n />\n )\n })()}\n {error ? <p className=\"text-xs text-destructive\">{error}</p> : null}\n {renderBelowInput ? renderBelowInput({ draft, resolvedType, error, saving }) : null}\n {(() => {\n const lowerType = (inputType ?? resolvedType ?? '').toLowerCase()\n const isDateLike = lowerType === 'date' || lowerType === 'datetime-local' || lowerType === 'datetime'\n if (isDateLike) return null\n return (\n <div className=\"flex items-center gap-2\">\n <Button type=\"submit\" size=\"sm\" disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 h-3.5 w-3.5 animate-spin\" /> : null}\n {computedSaveLabel}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setEditingSafe(false)} disabled={saving}>\n {t('ui.detail.inline.cancel', 'Cancel')}\n </Button>\n </div>\n )\n })()}\n </form>\n ) : (\n <div className={variant === 'plain' ? '' : 'mt-1'}>{displayContent}</div>\n )}\n </div>\n {renderActions ? <div className=\"flex items-center gap-2\">{renderActions}</div> : null}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size={triggerSize}\n className={triggerClasses}\n onClick={(event) => {\n event.stopPropagation()\n const next = !editing\n setEditingSafe(next)\n }}\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n </Button>\n </div>\n </div>\n )\n}\n\nexport type InlineMultilineEditorProps = {\n label: string\n value: string | null | undefined\n placeholder?: string\n emptyLabel: string\n onSave: (value: string | null) => Promise<void>\n validator?: (value: string) => string | null\n variant?: EditorVariant\n activateOnClick?: boolean\n containerClassName?: string\n triggerClassName?: string\n renderDisplay?: (params: { value: string | null | undefined; emptyLabel: string }) => React.ReactNode\n}\n\ntype UiMarkdownEditorProps = {\n value?: string\n height?: number\n onChange?: (value?: string) => void\n previewOptions?: { remarkPlugins?: unknown[] }\n}\n\nconst isTestEnv =\n typeof process !== 'undefined' &&\n (process.env.NODE_ENV === 'test' || typeof process.env.JEST_WORKER_ID !== 'undefined')\n\nfunction MarkdownEditorFallback() {\n const t = useT()\n return (\n <LoadingMessage label={t('ui.detail.inline.editorLoading', 'Loading editor\u2026')} className=\"min-h-[200px] justify-center\" />\n )\n}\n\nconst MarkdownEditorTestStub: React.ComponentType<UiMarkdownEditorProps> = ({ value, onChange }) => (\n <Textarea\n data-testid=\"markdown-editor\"\n rows={8}\n value={value ?? ''}\n onChange={(event) => onChange?.(event.target.value)}\n />\n)\n\nconst MarkdownEditorComponent: React.ComponentType<UiMarkdownEditorProps> = isTestEnv\n ? MarkdownEditorTestStub\n : (dynamic(() => import('@uiw/react-md-editor'), {\n ssr: false,\n loading: () => <MarkdownEditorFallback />,\n }) as unknown as React.ComponentType<UiMarkdownEditorProps>)\n\nlet markdownPluginsPromise: Promise<PluggableList> | null = null\n\nasync function loadMarkdownPlugins(): Promise<PluggableList> {\n if (isTestEnv) return []\n if (!markdownPluginsPromise) {\n markdownPluginsPromise = import('remark-gfm')\n .then((mod) => [mod.default ?? mod] as PluggableList)\n .catch(() => [])\n }\n return markdownPluginsPromise\n}\n\nexport function InlineMultilineEditor({\n label,\n value,\n placeholder,\n emptyLabel,\n onSave,\n validator,\n variant = 'default',\n activateOnClick = true,\n containerClassName,\n triggerClassName,\n renderDisplay,\n}: InlineMultilineEditorProps) {\n const t = useT()\n const [editing, setEditing] = React.useState(false)\n const [draft, setDraft] = React.useState(value ?? '')\n const [error, setError] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n const [isMarkdownEnabled, setIsMarkdownEnabled] = React.useState(true)\n const textareaRef = React.useRef<HTMLTextAreaElement | null>(null)\n const markdownEditorRef = React.useRef<HTMLDivElement | null>(null)\n const [markdownPlugins, setMarkdownPlugins] = React.useState<PluggableList>([])\n const fallbackError = React.useMemo(\n () => t('ui.detail.inline.error', 'Failed to save value.'),\n [t],\n )\n React.useEffect(() => {\n if (isTestEnv) return\n let mounted = true\n void loadMarkdownPlugins().then((plugins) => {\n if (!mounted) return\n setMarkdownPlugins(plugins)\n })\n return () => {\n mounted = false\n }\n }, [])\n\n const adjustTextareaSize = React.useCallback((element: HTMLTextAreaElement | null) => {\n if (!element) return\n element.style.height = 'auto'\n element.style.height = `${element.scrollHeight}px`\n }, [])\n\n React.useEffect(() => {\n adjustTextareaSize(textareaRef.current)\n }, [adjustTextareaSize, draft, isMarkdownEnabled])\n\n React.useEffect(() => {\n if (!editing) return\n if (isMarkdownEnabled) {\n const element = markdownEditorRef.current?.querySelector('textarea')\n if (!element) return\n window.requestAnimationFrame(() => {\n element.focus()\n })\n return\n }\n const element = textareaRef.current\n if (!element) return\n window.requestAnimationFrame(() => {\n adjustTextareaSize(element)\n element.focus()\n })\n }, [adjustTextareaSize, editing, isMarkdownEnabled])\n\n const handleMarkdownToggle = React.useCallback(() => {\n setIsMarkdownEnabled((prev) => !prev)\n }, [])\n\n React.useEffect(() => {\n if (!editing) {\n setDraft(value ?? '')\n setError(null)\n }\n }, [editing, value])\n\n const handleActivate = React.useCallback(() => {\n if (!editing) setEditing(true)\n }, [editing])\n\n const handleInteractiveClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n const target = event.target as HTMLElement\n const interactiveElement = target.closest('button, input, select, textarea, a, [role=\"link\"]')\n if (interactiveElement) {\n if (interactiveElement.tagName.toLowerCase() === 'a') {\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return\n }\n event.preventDefault()\n // Links should not block activation; let the click toggle edit mode\n } else {\n return\n }\n }\n handleActivate()\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const handleContainerKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!activateOnClick || editing) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n handleActivate()\n }\n },\n [activateOnClick, editing, handleActivate],\n )\n\n const adjustError = React.useCallback(\n (nextValue: string) => {\n if (!validator) return null\n const trimmed = nextValue.trim()\n return validator(trimmed)\n },\n [validator],\n )\n\n const containerClasses = cn(\n 'group rounded-lg border p-4',\n variant === 'muted' ? 'bg-muted/30' : null,\n activateOnClick && !editing ? 'cursor-pointer' : null,\n containerClassName ?? null,\n )\n const triggerClasses = cn(\n 'transition-opacity duration-150',\n editing\n ? 'opacity-100'\n : 'opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100',\n triggerClassName ?? null,\n )\n\n const handleSave = React.useCallback(async () => {\n const trimmed = draft.trim()\n const validationError = adjustError(draft)\n if (validationError) {\n setError(validationError)\n return\n }\n setSaving(true)\n try {\n await onSave(trimmed.length ? trimmed : null)\n setEditing(false)\n } catch (err) {\n setError(resolveInlineErrorMessage(err, fallbackError))\n } finally {\n setSaving(false)\n }\n }, [adjustError, draft, fallbackError, onSave])\n\n return (\n <div className={containerClasses} onClick={handleInteractiveClick}>\n <div className=\"flex items-start justify-between gap-2\">\n <div\n className={cn('flex-1 min-w-0', activateOnClick && !editing ? 'cursor-pointer' : null)}\n {...(activateOnClick && !editing\n ? { role: 'button' as const, tabIndex: 0, onKeyDown: handleContainerKeyDown }\n : {})}\n >\n <p className=\"text-xs uppercase tracking-wide text-muted-foreground\">{label}</p>\n {editing ? (\n <form\n className=\"mt-2 space-y-3\"\n onSubmit={(event) => {\n event.preventDefault()\n if (!saving) void handleSave()\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n setEditing(false)\n setError(null)\n return\n }\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n if (!saving) void handleSave()\n }\n }}\n >\n {isMarkdownEnabled ? (\n <div\n ref={markdownEditorRef}\n className={cn(\n 'w-full rounded-md border border-muted-foreground/30 bg-background p-2',\n saving ? 'pointer-events-none opacity-75' : null,\n )}\n >\n <div data-color-mode=\"light\" className=\"w-full\">\n <MarkdownEditorComponent\n value={draft}\n height={220}\n onChange={(nextValue) => {\n if (error) setError(null)\n setDraft(typeof nextValue === 'string' ? nextValue : '')\n }}\n previewOptions={{ remarkPlugins: markdownPlugins }}\n />\n </div>\n </div>\n ) : (\n <Textarea\n ref={textareaRef}\n rows={3}\n className=\"w-full resize-none overflow-hidden rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n placeholder={placeholder}\n value={draft}\n onChange={(event) => {\n if (error) setError(null)\n setDraft(event.target.value)\n }}\n onInput={(event) => adjustTextareaSize(event.currentTarget)}\n autoFocus\n disabled={saving}\n />\n )}\n {error ? <p className=\"text-xs text-destructive\">{error}</p> : null}\n <div className=\"flex items-center gap-2\">\n <Button type=\"submit\" size=\"sm\" disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 h-3.5 w-3.5 animate-spin\" /> : null}\n {t('ui.detail.inline.saveShortcut', 'Save \u2318\u23CE / Ctrl+Enter')}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setEditing(false)} disabled={saving}>\n {t('ui.detail.inline.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={handleMarkdownToggle}\n aria-pressed={isMarkdownEnabled}\n title={\n isMarkdownEnabled\n ? t('ui.detail.inline.markdownDisable', 'Disable Markdown')\n : t('ui.detail.inline.markdownEnable', 'Enable Markdown')\n }\n aria-label={\n isMarkdownEnabled\n ? t('ui.detail.inline.markdownDisable', 'Disable Markdown')\n : t('ui.detail.inline.markdownEnable', 'Enable Markdown')\n }\n className={cn('h-8 w-8', isMarkdownEnabled ? 'text-primary' : undefined)}\n disabled={saving}\n >\n <FileCode className=\"h-4 w-4\" aria-hidden />\n <span className=\"sr-only\">\n {isMarkdownEnabled\n ? t('ui.detail.inline.markdownDisable', 'Disable Markdown')\n : t('ui.detail.inline.markdownEnable', 'Enable Markdown')}\n </span>\n </Button>\n </div>\n </form>\n ) : (\n <div\n className={cn(\n 'mt-1 text-sm break-words',\n renderDisplay ? null : 'whitespace-pre-wrap',\n activateOnClick && !editing ? 'cursor-pointer' : null,\n )}\n >\n {renderDisplay ? (\n renderDisplay({ value, emptyLabel })\n ) : value && value.length ? (\n <MarkdownPreview\n remarkPlugins={markdownPlugins}\n className=\"prose prose-sm max-w-none text-foreground [&>*]:my-2 [&>*:last-child]:mb-0 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5\"\n >\n {value}\n </MarkdownPreview>\n ) : (\n <span className=\"text-muted-foreground\">{emptyLabel}</span>\n )}\n </div>\n )}\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className={triggerClasses}\n onClick={(event) => {\n event.stopPropagation()\n setEditing((state) => !state)\n }}\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n </Button>\n </div>\n </div>\n )\n}\n\nexport type InlineSelectOption = { value: string; label: string; description?: string }\n\nexport type InlineSelectEditorProps = {\n label: string\n value: string | null | undefined\n emptyLabel: string\n options: InlineSelectOption[]\n onSave: (value: string | null) => Promise<void>\n variant?: EditorVariant\n activateOnClick?: boolean\n containerClassName?: string\n triggerClassName?: string\n hideLabel?: boolean\n renderEditor?: (params: { value: string; onChange: (next: string) => void }) => React.ReactNode\n renderDisplay?: (params: { value: string | null | undefined; emptyLabel: string }) => React.ReactNode\n}\n\nexport function InlineSelectEditor({\n label,\n value,\n emptyLabel,\n options,\n onSave,\n variant = 'default',\n activateOnClick = false,\n containerClassName,\n triggerClassName,\n hideLabel = false,\n renderEditor,\n renderDisplay,\n}: InlineSelectEditorProps) {\n const t = useT()\n const [editing, setEditing] = React.useState(false)\n const [draft, setDraft] = React.useState<string>(value ?? '')\n const [saving, setSaving] = React.useState(false)\n\n React.useEffect(() => {\n if (!editing) setDraft(value ?? '')\n }, [editing, value])\n\n const containerClasses = cn(\n 'group',\n variant === 'muted'\n ? 'relative rounded border bg-muted/30 p-3'\n : variant === 'plain'\n ? 'relative flex flex-col gap-1 rounded-none border-0 p-0'\n : 'rounded-lg border bg-card p-4',\n activateOnClick && !editing ? 'cursor-pointer' : null,\n containerClassName ?? null,\n )\n const triggerClasses = cn(\n 'shrink-0 transition-opacity duration-150',\n editing\n ? 'opacity-100'\n : 'opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100',\n variant === 'muted' ? 'h-8 w-8' : null,\n triggerClassName ?? null,\n )\n\n const handleSave = React.useCallback(async () => {\n setSaving(true)\n try {\n await onSave(draft.length ? draft : null)\n setEditing(false)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('ui.detail.inline.error', 'Failed to save value.')\n console.error(message, err)\n } finally {\n setSaving(false)\n }\n }, [draft, onSave, t])\n\n const selected = options.find((option) => option.value === value)\n\n const interactiveProps: React.HTMLAttributes<HTMLDivElement> =\n activateOnClick && !editing\n ? {\n role: 'button' as const,\n tabIndex: 0,\n onClick: () => setEditing(true),\n onKeyDown: (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n setEditing(true)\n }\n },\n }\n : {}\n\n return (\n <div className={containerClasses}>\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\" {...interactiveProps}>\n {hideLabel ? null : <p className=\"text-xs uppercase tracking-wide text-muted-foreground\">{label}</p>}\n {editing ? (\n <div className={variant === 'plain' ? 'space-y-2 pt-1' : 'mt-2 space-y-2'}>\n {renderEditor ? (\n renderEditor({ value: draft, onChange: setDraft })\n ) : (\n <Select\n value={draft || undefined}\n onValueChange={(next) => setDraft(next ?? '')}\n >\n <SelectTrigger>\n <SelectValue placeholder={t('ui.detail.inline.select.placeholder', 'Not set')} />\n </SelectTrigger>\n <SelectContent>\n {options.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" size=\"sm\" onClick={() => void handleSave()} disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 h-3.5 w-3.5 animate-spin\" /> : null}\n {t('ui.detail.inline.saveShortcut', 'Save \u2318\u23CE / Ctrl+Enter')}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setEditing(false)} disabled={saving}>\n {t('ui.detail.inline.cancel', 'Cancel')}\n </Button>\n </div>\n </div>\n ) : (\n <div className={variant === 'plain' ? 'flex items-center gap-2' : 'mt-1 text-sm'}>\n {renderDisplay ? (\n renderDisplay({ value, emptyLabel })\n ) : selected ? (\n <div className=\"space-y-0.5\">\n <p className=\"font-medium leading-tight\">{selected.label}</p>\n {selected.description ? (\n <p className=\"text-xs text-muted-foreground\">{selected.description}</p>\n ) : null}\n </div>\n ) : (\n <span className=\"text-muted-foreground\">{emptyLabel}</span>\n )}\n </div>\n )}\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size={variant === 'plain' ? 'icon' : 'sm'}\n className={triggerClasses}\n onClick={(event) => {\n event.stopPropagation()\n setEditing((state) => !state)\n }}\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n </Button>\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["element"]
|
|
7
7
|
}
|