@almadar/ui 5.159.0 → 5.161.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/dist/avl/index.cjs +958 -912
- package/dist/avl/index.js +947 -901
- package/dist/components/index.cjs +978 -955
- package/dist/components/index.d.cts +156 -31
- package/dist/components/index.d.ts +156 -31
- package/dist/components/index.js +964 -944
- package/dist/hooks/index.cjs +25 -49
- package/dist/hooks/index.js +25 -49
- package/dist/locales/index.cjs +75 -147
- package/dist/locales/index.js +75 -147
- package/dist/providers/index.cjs +934 -892
- package/dist/providers/index.js +934 -892
- package/dist/runtime/index.cjs +953 -907
- package/dist/runtime/index.js +943 -897
- package/locales/ar.json +25 -49
- package/locales/en.json +25 -49
- package/locales/sl.json +25 -49
- package/package.json +5 -5
package/dist/avl/index.cjs
CHANGED
|
@@ -28612,8 +28612,9 @@ function DataGrid({
|
|
|
28612
28612
|
const titleField = fieldDefs.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fieldDefs[0];
|
|
28613
28613
|
const badgeFields = fieldDefs.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
28614
28614
|
const bodyFields = fieldDefs.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
|
|
28615
|
-
const
|
|
28616
|
-
const
|
|
28615
|
+
const inlineCap = Math.min(maxInlineActions ?? 1, 1);
|
|
28616
|
+
const inlineCardActions = actionDefs.filter((a) => a.variant === "primary").slice(0, inlineCap);
|
|
28617
|
+
const menuCardActions = actionDefs.filter((a) => !inlineCardActions.includes(a));
|
|
28617
28618
|
const fireAction = (action, itemData) => {
|
|
28618
28619
|
if (action.navigatesTo) {
|
|
28619
28620
|
const url = action.navigatesTo.replace(
|
|
@@ -28633,6 +28634,9 @@ function DataGrid({
|
|
|
28633
28634
|
e.stopPropagation();
|
|
28634
28635
|
fireAction(action, itemData);
|
|
28635
28636
|
};
|
|
28637
|
+
const cardClickAction = actionDefs.find((a) => a.variant !== "danger");
|
|
28638
|
+
const handleCardClick = cardClickAction ? (itemData) => () => fireAction(cardClickAction, itemData) : void 0;
|
|
28639
|
+
const stopCardClick = handleCardClick ? (e) => e.stopPropagation() : void 0;
|
|
28636
28640
|
const hasRenderProp = typeof children === "function";
|
|
28637
28641
|
React94.useEffect(() => {
|
|
28638
28642
|
if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
|
|
@@ -28704,55 +28708,40 @@ function DataGrid({
|
|
|
28704
28708
|
{
|
|
28705
28709
|
"data-entity-row": true,
|
|
28706
28710
|
"data-entity-id": id,
|
|
28707
|
-
|
|
28711
|
+
onClick: handleCardClick?.(itemData),
|
|
28712
|
+
className: cn("relative group/rowactions", handleCardClick && "cursor-pointer", isSelected && "ring-2 ring-primary rounded-lg"),
|
|
28708
28713
|
children: [
|
|
28709
28714
|
children(itemData, index),
|
|
28710
|
-
actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.
|
|
28711
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
28712
|
-
|
|
28713
|
-
|
|
28714
|
-
|
|
28715
|
-
|
|
28716
|
-
|
|
28717
|
-
|
|
28718
|
-
|
|
28719
|
-
|
|
28720
|
-
|
|
28721
|
-
|
|
28722
|
-
|
|
28723
|
-
|
|
28724
|
-
|
|
28725
|
-
|
|
28726
|
-
|
|
28727
|
-
)),
|
|
28728
|
-
maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
|
|
28729
|
-
Menu,
|
|
28730
|
-
{
|
|
28731
|
-
position: "bottom-end",
|
|
28732
|
-
trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
28733
|
-
items: actionDefs.slice(maxInlineActions).map((action) => ({
|
|
28734
|
-
label: action.label,
|
|
28735
|
-
icon: action.icon,
|
|
28736
|
-
event: action.event,
|
|
28737
|
-
onClick: () => fireAction(action, itemData)
|
|
28738
|
-
}))
|
|
28739
|
-
}
|
|
28740
|
-
)
|
|
28741
|
-
] }),
|
|
28742
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "hidden [@media(pointer:coarse)]:block rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
28715
|
+
actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { onClick: stopCardClick, className: "absolute top-2 right-2 z-10 opacity-0 group-hover/rowactions:opacity-100 focus-within:opacity-100 [@media(pointer:coarse)]:opacity-100 transition-opacity duration-fast", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5", children: [
|
|
28716
|
+
inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28717
|
+
Button,
|
|
28718
|
+
{
|
|
28719
|
+
variant: "primary",
|
|
28720
|
+
size: "sm",
|
|
28721
|
+
onClick: handleActionClick(action, itemData),
|
|
28722
|
+
"data-testid": `action-${action.event}`,
|
|
28723
|
+
"data-row-id": String(itemData.id),
|
|
28724
|
+
children: [
|
|
28725
|
+
action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
|
|
28726
|
+
action.label
|
|
28727
|
+
]
|
|
28728
|
+
},
|
|
28729
|
+
idx
|
|
28730
|
+
)),
|
|
28731
|
+
menuCardActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
28743
28732
|
Menu,
|
|
28744
28733
|
{
|
|
28745
28734
|
position: "bottom-end",
|
|
28746
28735
|
trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
28747
|
-
items:
|
|
28736
|
+
items: menuCardActions.map((action) => ({
|
|
28748
28737
|
label: action.label,
|
|
28749
28738
|
icon: action.icon,
|
|
28750
|
-
|
|
28739
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
28751
28740
|
onClick: () => fireAction(action, itemData)
|
|
28752
28741
|
}))
|
|
28753
28742
|
}
|
|
28754
|
-
)
|
|
28755
|
-
] })
|
|
28743
|
+
)
|
|
28744
|
+
] }) })
|
|
28756
28745
|
]
|
|
28757
28746
|
},
|
|
28758
28747
|
id
|
|
@@ -28766,12 +28755,14 @@ function DataGrid({
|
|
|
28766
28755
|
{
|
|
28767
28756
|
"data-entity-row": true,
|
|
28768
28757
|
"data-entity-id": id,
|
|
28758
|
+
onClick: handleCardClick?.(itemData),
|
|
28769
28759
|
className: cn(
|
|
28770
28760
|
"bg-card rounded-lg",
|
|
28771
28761
|
"border border-border",
|
|
28772
28762
|
"shadow-elevation-card hover:shadow-elevation-dialog",
|
|
28773
28763
|
"hover:border-primary transition-all",
|
|
28774
28764
|
"flex flex-col",
|
|
28765
|
+
handleCardClick && "cursor-pointer",
|
|
28775
28766
|
isSelected && "ring-2 ring-primary border-primary"
|
|
28776
28767
|
),
|
|
28777
28768
|
children: [
|
|
@@ -28821,53 +28812,35 @@ function DataGrid({
|
|
|
28821
28812
|
] }, field.name);
|
|
28822
28813
|
}) })
|
|
28823
28814
|
] }),
|
|
28824
|
-
|
|
28825
|
-
|
|
28815
|
+
actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", onClick: stopCardClick, className: "flex-shrink-0", children: [
|
|
28816
|
+
inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
28826
28817
|
Button,
|
|
28827
28818
|
{
|
|
28828
|
-
variant:
|
|
28819
|
+
variant: "primary",
|
|
28829
28820
|
size: "sm",
|
|
28830
28821
|
onClick: handleActionClick(action, itemData),
|
|
28831
28822
|
"data-testid": `action-${action.event}`,
|
|
28832
28823
|
"data-row-id": String(itemData.id),
|
|
28833
28824
|
"aria-label": action.label,
|
|
28834
28825
|
title: action.label,
|
|
28835
|
-
className: cn(
|
|
28836
|
-
action.variant === "primary" ? void 0 : "text-muted-foreground hover:text-foreground",
|
|
28837
|
-
action.icon && "px-2"
|
|
28838
|
-
),
|
|
28826
|
+
className: cn(action.icon && "px-2"),
|
|
28839
28827
|
children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
|
|
28840
28828
|
},
|
|
28841
28829
|
idx
|
|
28842
28830
|
)),
|
|
28843
|
-
|
|
28831
|
+
menuCardActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
28844
28832
|
Menu,
|
|
28845
28833
|
{
|
|
28846
28834
|
position: "bottom-end",
|
|
28847
28835
|
trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
28848
|
-
items:
|
|
28836
|
+
items: menuCardActions.map((action) => ({
|
|
28849
28837
|
label: action.label,
|
|
28850
28838
|
icon: action.icon,
|
|
28851
|
-
|
|
28839
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
28852
28840
|
onClick: () => fireAction(action, itemData)
|
|
28853
28841
|
}))
|
|
28854
28842
|
}
|
|
28855
|
-
)
|
|
28856
|
-
dangerActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
28857
|
-
Button,
|
|
28858
|
-
{
|
|
28859
|
-
variant: "ghost",
|
|
28860
|
-
size: "sm",
|
|
28861
|
-
onClick: handleActionClick(action, itemData),
|
|
28862
|
-
"data-testid": `action-${action.event}`,
|
|
28863
|
-
"data-row-id": String(itemData.id),
|
|
28864
|
-
"aria-label": action.label,
|
|
28865
|
-
title: action.label,
|
|
28866
|
-
className: "text-error hover:text-error hover:bg-error/10 px-2",
|
|
28867
|
-
children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
|
|
28868
|
-
},
|
|
28869
|
-
`danger-${idx}`
|
|
28870
|
-
))
|
|
28843
|
+
)
|
|
28871
28844
|
] })
|
|
28872
28845
|
] }) }),
|
|
28873
28846
|
bodyFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-4 pt-2 pb-4 flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
@@ -28888,8 +28861,8 @@ function DataGrid({
|
|
|
28888
28861
|
}
|
|
28889
28862
|
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
28890
28863
|
field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
28891
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
28892
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", children: formatValue(value, field.format) })
|
|
28864
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", className: "sr-only", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
28865
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: formatValue(value, field.format) })
|
|
28893
28866
|
] }, field.name);
|
|
28894
28867
|
}) })
|
|
28895
28868
|
] }) })
|
|
@@ -29109,54 +29082,59 @@ function DataList({
|
|
|
29109
29082
|
if (!itemActions || itemActions.length === 0) return null;
|
|
29110
29083
|
const inline = maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions;
|
|
29111
29084
|
const overflow = maxInlineActions != null ? itemActions.slice(maxInlineActions) : [];
|
|
29112
|
-
return
|
|
29113
|
-
|
|
29114
|
-
|
|
29115
|
-
|
|
29116
|
-
|
|
29117
|
-
|
|
29118
|
-
|
|
29119
|
-
|
|
29120
|
-
|
|
29121
|
-
|
|
29122
|
-
action
|
|
29123
|
-
|
|
29124
|
-
|
|
29125
|
-
|
|
29126
|
-
|
|
29127
|
-
|
|
29128
|
-
|
|
29129
|
-
|
|
29130
|
-
|
|
29131
|
-
|
|
29132
|
-
|
|
29133
|
-
|
|
29134
|
-
|
|
29135
|
-
|
|
29136
|
-
|
|
29137
|
-
|
|
29138
|
-
|
|
29139
|
-
|
|
29140
|
-
|
|
29141
|
-
|
|
29142
|
-
|
|
29143
|
-
|
|
29144
|
-
|
|
29145
|
-
|
|
29146
|
-
|
|
29147
|
-
|
|
29148
|
-
|
|
29149
|
-
|
|
29150
|
-
|
|
29151
|
-
|
|
29085
|
+
return (
|
|
29086
|
+
// stopPropagation at the cluster: the "⋯" trigger opens the overflow
|
|
29087
|
+
// menu without also firing the row's default click (inline buttons
|
|
29088
|
+
// already stop it in handleActionClick; the Menu panel is portaled).
|
|
29089
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", onClick: rowClickEvent ? (e) => e.stopPropagation() : void 0, className: "flex-shrink-0", children: [
|
|
29090
|
+
inline.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29091
|
+
Button,
|
|
29092
|
+
{
|
|
29093
|
+
variant: action.variant ?? "ghost",
|
|
29094
|
+
size: "sm",
|
|
29095
|
+
onClick: handleActionClick(action, itemData),
|
|
29096
|
+
"data-testid": `action-${action.event}`,
|
|
29097
|
+
"data-row-id": String(itemData.id),
|
|
29098
|
+
className: cn(
|
|
29099
|
+
action.variant === "danger" && "text-error hover:bg-error/10",
|
|
29100
|
+
// Must sit on the Button itself: the variant's own text colour
|
|
29101
|
+
// beats an inherited one from the row wrapper.
|
|
29102
|
+
onPrimary && "!text-primary-foreground hover:bg-primary-foreground/15"
|
|
29103
|
+
),
|
|
29104
|
+
children: [
|
|
29105
|
+
action.icon && renderIconInput2(action.icon, { size: "xs", className: "mr-1" }),
|
|
29106
|
+
action.label
|
|
29107
|
+
]
|
|
29108
|
+
},
|
|
29109
|
+
idx
|
|
29110
|
+
)),
|
|
29111
|
+
overflow.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29112
|
+
Menu,
|
|
29113
|
+
{
|
|
29114
|
+
position: "bottom-end",
|
|
29115
|
+
trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
29116
|
+
items: overflow.map((action) => ({
|
|
29117
|
+
label: action.label,
|
|
29118
|
+
icon: action.icon,
|
|
29119
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
29120
|
+
onClick: () => eventBus.emit(`UI:${action.event}`, {
|
|
29121
|
+
id: itemData.id,
|
|
29122
|
+
row: itemData
|
|
29123
|
+
})
|
|
29124
|
+
}))
|
|
29125
|
+
}
|
|
29126
|
+
)
|
|
29127
|
+
] })
|
|
29128
|
+
);
|
|
29152
29129
|
};
|
|
29130
|
+
const rowClickEvent = itemClickEvent || itemActions?.find((a) => a.variant !== "danger")?.event;
|
|
29153
29131
|
const handleRowClick = (itemData) => () => {
|
|
29154
|
-
if (!
|
|
29132
|
+
if (!rowClickEvent) return;
|
|
29155
29133
|
const payload = {
|
|
29156
29134
|
id: itemData.id,
|
|
29157
29135
|
row: itemData
|
|
29158
29136
|
};
|
|
29159
|
-
eventBus.emit(`UI:${
|
|
29137
|
+
eventBus.emit(`UI:${rowClickEvent}`, payload);
|
|
29160
29138
|
};
|
|
29161
29139
|
if (isLoading) {
|
|
29162
29140
|
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") }) });
|
|
@@ -29204,10 +29182,10 @@ function DataList({
|
|
|
29204
29182
|
{
|
|
29205
29183
|
"data-entity-row": true,
|
|
29206
29184
|
"data-entity-id": id,
|
|
29207
|
-
onClick:
|
|
29185
|
+
onClick: rowClickEvent ? handleRowClick(itemData) : void 0,
|
|
29208
29186
|
className: cn(
|
|
29209
29187
|
"flex px-4 group/rowactions",
|
|
29210
|
-
|
|
29188
|
+
rowClickEvent && "cursor-pointer",
|
|
29211
29189
|
isSent ? "justify-end" : "justify-start"
|
|
29212
29190
|
),
|
|
29213
29191
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -29283,7 +29261,7 @@ function DataList({
|
|
|
29283
29261
|
const id2 = itemData.id || String(index);
|
|
29284
29262
|
const actions = renderItemActions(itemData);
|
|
29285
29263
|
return wrapDnd(
|
|
29286
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick:
|
|
29264
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick: rowClickEvent ? handleRowClick(itemData) : void 0, className: cn("relative group/rowactions", rowClickEvent && "cursor-pointer"), children: [
|
|
29287
29265
|
children(itemData, index),
|
|
29288
29266
|
actions && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "absolute top-2 right-2 z-10 opacity-0 group-hover/rowactions:opacity-100 focus-within:opacity-100 [@media(pointer:coarse)]:opacity-100 transition-opacity duration-fast", children: [
|
|
29289
29267
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5 [@media(pointer:coarse)]:hidden", children: actions }),
|
|
@@ -29295,7 +29273,6 @@ function DataList({
|
|
|
29295
29273
|
items: (itemActions ?? []).map((action) => ({
|
|
29296
29274
|
label: action.label,
|
|
29297
29275
|
icon: action.icon,
|
|
29298
|
-
event: action.event,
|
|
29299
29276
|
variant: action.variant === "danger" ? "danger" : "default",
|
|
29300
29277
|
onClick: () => eventBus.emit(`UI:${action.event}`, {
|
|
29301
29278
|
id: itemData.id,
|
|
@@ -29312,12 +29289,16 @@ function DataList({
|
|
|
29312
29289
|
const id = itemData.id || String(index);
|
|
29313
29290
|
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
29314
29291
|
return wrapDnd(
|
|
29315
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id, onClick:
|
|
29292
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id, onClick: rowClickEvent ? handleRowClick(itemData) : void 0, className: cn(rowClickEvent && "cursor-pointer"), children: [
|
|
29316
29293
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29317
29294
|
Box,
|
|
29318
29295
|
{
|
|
29319
29296
|
className: cn(
|
|
29320
|
-
|
|
29297
|
+
// items-start, not items-center: a multi-line row (title + meta +
|
|
29298
|
+
// progress) centred its action cluster in the vertical middle, so
|
|
29299
|
+
// the buttons floated between the meta fields instead of anchoring
|
|
29300
|
+
// to the title they act on (U-DATALIST-ACTIONS-FLOAT-MID-ROW).
|
|
29301
|
+
"group flex items-start gap-4 transition-all duration-fast",
|
|
29321
29302
|
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
29322
29303
|
"hover:bg-muted/80",
|
|
29323
29304
|
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
@@ -29348,11 +29329,19 @@ function DataList({
|
|
|
29348
29329
|
if (value === void 0 || value === null || value === "") return null;
|
|
29349
29330
|
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
29350
29331
|
field.icon && renderIconInput2(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
29351
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29352
|
-
|
|
29353
|
-
|
|
29354
|
-
|
|
29355
|
-
|
|
29332
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29333
|
+
Typography,
|
|
29334
|
+
{
|
|
29335
|
+
variant: "caption",
|
|
29336
|
+
color: "secondary",
|
|
29337
|
+
className: cn(field.format !== "boolean" && "sr-only"),
|
|
29338
|
+
children: [
|
|
29339
|
+
field.label ?? fieldLabel3(field.name),
|
|
29340
|
+
":"
|
|
29341
|
+
]
|
|
29342
|
+
}
|
|
29343
|
+
),
|
|
29344
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: formatValue2(value, field.format, { yes: t("common.yes"), no: t("common.no") }) })
|
|
29356
29345
|
] }, field.name);
|
|
29357
29346
|
}) }),
|
|
29358
29347
|
progressFields.map((field) => {
|
|
@@ -29371,7 +29360,7 @@ function DataList({
|
|
|
29371
29360
|
]
|
|
29372
29361
|
}
|
|
29373
29362
|
),
|
|
29374
|
-
isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "
|
|
29363
|
+
(isCard || isCompact) && !isLast && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("border-b border-border/40", isCompact ? "mx-4" : "mx-6") })
|
|
29375
29364
|
] }, id)
|
|
29376
29365
|
);
|
|
29377
29366
|
};
|
|
@@ -29381,7 +29370,13 @@ function DataList({
|
|
|
29381
29370
|
{
|
|
29382
29371
|
className: cn(
|
|
29383
29372
|
isCard && "bg-card rounded-xl border border-border shadow-elevation-dialog overflow-hidden",
|
|
29384
|
-
|
|
29373
|
+
// `gap-*` is inert on a block container, and Box only emits a display
|
|
29374
|
+
// class when its `display` prop is set — so every non-card list had
|
|
29375
|
+
// been asking for a gap that CSS silently dropped. flex-col makes it
|
|
29376
|
+
// real. `compact` keeps gap-0 on purpose: it separates with the row
|
|
29377
|
+
// divider above instead, never both (Almadar_UI_Beauty.md 6).
|
|
29378
|
+
!isCard && "flex flex-col",
|
|
29379
|
+
!isCard && !isCompact && gapClass,
|
|
29385
29380
|
listLookStyles[look],
|
|
29386
29381
|
className
|
|
29387
29382
|
),
|
|
@@ -34570,7 +34565,7 @@ var init_MapView = __esm({
|
|
|
34570
34565
|
shadowSize: [41, 41]
|
|
34571
34566
|
});
|
|
34572
34567
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
34573
|
-
const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback96, useState:
|
|
34568
|
+
const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback96, useState: useState102 } = React94__namespace.default;
|
|
34574
34569
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
34575
34570
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
34576
34571
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -34615,7 +34610,7 @@ var init_MapView = __esm({
|
|
|
34615
34610
|
showAttribution = true
|
|
34616
34611
|
}) {
|
|
34617
34612
|
const eventBus = useEventBus2();
|
|
34618
|
-
const [clickedPosition, setClickedPosition] =
|
|
34613
|
+
const [clickedPosition, setClickedPosition] = useState102(null);
|
|
34619
34614
|
const handleMapClick = useCallback96((lat, lng) => {
|
|
34620
34615
|
if (showClickedPin) {
|
|
34621
34616
|
setClickedPosition({ lat, lng });
|
|
@@ -38977,741 +38972,775 @@ var init_PositionedCanvas = __esm({
|
|
|
38977
38972
|
PositionedCanvas.displayName = "PositionedCanvas";
|
|
38978
38973
|
}
|
|
38979
38974
|
});
|
|
38980
|
-
function
|
|
38981
|
-
|
|
38982
|
-
|
|
38983
|
-
|
|
38975
|
+
function safeUrl(raw, kinds) {
|
|
38976
|
+
const url = raw.trim();
|
|
38977
|
+
if (url.startsWith("#") || url.startsWith("/")) return url;
|
|
38978
|
+
const lower = url.toLowerCase();
|
|
38979
|
+
for (const kind of kinds) {
|
|
38980
|
+
if (lower.startsWith(kind)) return url;
|
|
38981
|
+
}
|
|
38982
|
+
return null;
|
|
38984
38983
|
}
|
|
38985
|
-
function
|
|
38986
|
-
|
|
38987
|
-
|
|
38988
|
-
const
|
|
38989
|
-
|
|
38990
|
-
|
|
38991
|
-
|
|
38992
|
-
|
|
38993
|
-
|
|
38984
|
+
function sanitizeNode(el) {
|
|
38985
|
+
const children = Array.from(el.children);
|
|
38986
|
+
for (const child of children) {
|
|
38987
|
+
const tag = child.tagName.toLowerCase();
|
|
38988
|
+
if (DROP_TAGS.has(tag)) {
|
|
38989
|
+
child.remove();
|
|
38990
|
+
continue;
|
|
38991
|
+
}
|
|
38992
|
+
const allowed = ALLOWED_ATTRS[tag];
|
|
38993
|
+
if (!allowed) {
|
|
38994
|
+
sanitizeNode(child);
|
|
38995
|
+
child.replaceWith(...Array.from(child.childNodes));
|
|
38996
|
+
continue;
|
|
38997
|
+
}
|
|
38998
|
+
for (const attr of Array.from(child.attributes)) {
|
|
38999
|
+
const name = attr.name.toLowerCase();
|
|
39000
|
+
if (!allowed.includes(name)) {
|
|
39001
|
+
child.removeAttribute(attr.name);
|
|
39002
|
+
continue;
|
|
39003
|
+
}
|
|
39004
|
+
if (name === "href") {
|
|
39005
|
+
const url = safeUrl(attr.value, ["http://", "https://", "mailto:"]);
|
|
39006
|
+
if (url === null) child.removeAttribute(attr.name);
|
|
39007
|
+
else child.setAttribute("href", url);
|
|
39008
|
+
}
|
|
39009
|
+
if (name === "src") {
|
|
39010
|
+
const url = safeUrl(attr.value, ["http://", "https://", "data:image/"]);
|
|
39011
|
+
if (url === null) child.remove();
|
|
39012
|
+
else child.setAttribute("src", url);
|
|
39013
|
+
}
|
|
39014
|
+
}
|
|
39015
|
+
sanitizeNode(child);
|
|
39016
|
+
}
|
|
38994
39017
|
}
|
|
38995
|
-
function
|
|
38996
|
-
|
|
38997
|
-
|
|
38998
|
-
|
|
38999
|
-
|
|
39000
|
-
|
|
39001
|
-
|
|
39002
|
-
children: [
|
|
39003
|
-
{ id: nextBlockId("li"), type: "paragraph", content: "" }
|
|
39004
|
-
]
|
|
39005
|
-
};
|
|
39006
|
-
case "image":
|
|
39007
|
-
return {
|
|
39008
|
-
id: nextBlockId(type),
|
|
39009
|
-
type,
|
|
39010
|
-
content: "",
|
|
39011
|
-
metadata: { url: "", caption: "" }
|
|
39012
|
-
};
|
|
39013
|
-
case "code":
|
|
39014
|
-
return {
|
|
39015
|
-
id: nextBlockId(type),
|
|
39016
|
-
type,
|
|
39017
|
-
content: "",
|
|
39018
|
-
metadata: { language: "plaintext" }
|
|
39019
|
-
};
|
|
39020
|
-
case "divider":
|
|
39021
|
-
return { id: nextBlockId(type), type };
|
|
39022
|
-
default:
|
|
39023
|
-
return { id: nextBlockId(type), type, content: "" };
|
|
39018
|
+
function sanitizeRichHtml(html) {
|
|
39019
|
+
if (!html || typeof html !== "string") return "";
|
|
39020
|
+
if (typeof window === "undefined" || typeof DOMParser === "undefined") return "";
|
|
39021
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
39022
|
+
sanitizeNode(doc.body);
|
|
39023
|
+
if (!doc.body.querySelector("img, hr") && (doc.body.textContent ?? "").trim().length === 0) {
|
|
39024
|
+
return "";
|
|
39024
39025
|
}
|
|
39026
|
+
return doc.body.innerHTML.replace(//g, "");
|
|
39025
39027
|
}
|
|
39026
|
-
function
|
|
39027
|
-
|
|
39028
|
+
function htmlIsEmpty(el) {
|
|
39029
|
+
if (el.querySelector("img, hr")) return false;
|
|
39030
|
+
return (el.textContent ?? "").trim().length === 0;
|
|
39028
39031
|
}
|
|
39029
|
-
function
|
|
39030
|
-
|
|
39032
|
+
function closestBlock(node, root) {
|
|
39033
|
+
let cur = node;
|
|
39034
|
+
while (cur && cur !== root) {
|
|
39035
|
+
if (cur instanceof Element && BLOCK_TAGS.has(cur.tagName)) return cur;
|
|
39036
|
+
cur = cur.parentNode;
|
|
39037
|
+
}
|
|
39038
|
+
return null;
|
|
39031
39039
|
}
|
|
39032
|
-
function
|
|
39040
|
+
function RichTextStyles() {
|
|
39041
|
+
return /* @__PURE__ */ jsxRuntime.jsx("style", { children: RICH_TEXT_CSS });
|
|
39042
|
+
}
|
|
39043
|
+
function readToolbarState(root) {
|
|
39044
|
+
const sel = window.getSelection();
|
|
39045
|
+
if (!sel || sel.rangeCount === 0) return IDLE_TOOLBAR;
|
|
39046
|
+
const anchor = sel.anchorNode;
|
|
39047
|
+
if (!anchor || !root.contains(anchor)) return IDLE_TOOLBAR;
|
|
39048
|
+
let block = null;
|
|
39049
|
+
let link = false;
|
|
39050
|
+
let node = anchor;
|
|
39051
|
+
while (node && node !== root) {
|
|
39052
|
+
if (node instanceof Element) {
|
|
39053
|
+
const tag = node.tagName.toLowerCase();
|
|
39054
|
+
if (!block && (tag === "h1" || tag === "h2" || tag === "h3" || tag === "blockquote" || tag === "pre")) {
|
|
39055
|
+
block = tag;
|
|
39056
|
+
}
|
|
39057
|
+
if (tag === "a") link = true;
|
|
39058
|
+
}
|
|
39059
|
+
node = node.parentNode;
|
|
39060
|
+
}
|
|
39033
39061
|
return {
|
|
39034
|
-
|
|
39035
|
-
|
|
39036
|
-
|
|
39037
|
-
|
|
39038
|
-
|
|
39039
|
-
|
|
39040
|
-
|
|
39062
|
+
bold: document.queryCommandState("bold"),
|
|
39063
|
+
italic: document.queryCommandState("italic"),
|
|
39064
|
+
underline: document.queryCommandState("underline"),
|
|
39065
|
+
strikeThrough: document.queryCommandState("strikeThrough"),
|
|
39066
|
+
block,
|
|
39067
|
+
bullets: document.queryCommandState("insertUnorderedList"),
|
|
39068
|
+
numbers: document.queryCommandState("insertOrderedList"),
|
|
39069
|
+
link
|
|
39041
39070
|
};
|
|
39042
39071
|
}
|
|
39043
|
-
function
|
|
39044
|
-
|
|
39045
|
-
|
|
39046
|
-
|
|
39047
|
-
|
|
39048
|
-
|
|
39049
|
-
|
|
39050
|
-
|
|
39051
|
-
|
|
39052
|
-
|
|
39053
|
-
|
|
39054
|
-
|
|
39072
|
+
function ToolbarButton({ icon: IconCmp, label, active, onExec }) {
|
|
39073
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39074
|
+
Button,
|
|
39075
|
+
{
|
|
39076
|
+
type: "button",
|
|
39077
|
+
variant: "ghost",
|
|
39078
|
+
size: "sm",
|
|
39079
|
+
"aria-label": label,
|
|
39080
|
+
"aria-pressed": active,
|
|
39081
|
+
title: label,
|
|
39082
|
+
className: cn(
|
|
39083
|
+
"h-8 w-8 p-0 gap-0 justify-center",
|
|
39084
|
+
active && "bg-muted text-foreground"
|
|
39085
|
+
),
|
|
39086
|
+
onMouseDown: (e) => {
|
|
39087
|
+
e.preventDefault();
|
|
39088
|
+
onExec();
|
|
39089
|
+
},
|
|
39090
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(IconCmp, { size: 15 })
|
|
39055
39091
|
}
|
|
39056
|
-
|
|
39057
|
-
|
|
39058
|
-
|
|
39059
|
-
|
|
39060
|
-
|
|
39061
|
-
|
|
39062
|
-
|
|
39063
|
-
|
|
39064
|
-
|
|
39065
|
-
|
|
39066
|
-
|
|
39067
|
-
|
|
39068
|
-
|
|
39069
|
-
|
|
39070
|
-
|
|
39071
|
-
|
|
39072
|
-
|
|
39073
|
-
|
|
39074
|
-
|
|
39075
|
-
|
|
39076
|
-
|
|
39077
|
-
|
|
39078
|
-
|
|
39079
|
-
|
|
39080
|
-
|
|
39081
|
-
|
|
39092
|
+
);
|
|
39093
|
+
}
|
|
39094
|
+
var CHANGE_DEBOUNCE_MS, ALLOWED_ATTRS, DROP_TAGS, MD_BLOCK_PREFIXES, BLOCK_TAGS, MD_INLINE_RULES, RICH_TEXT_CSS, IDLE_TOOLBAR, RichTextEditor;
|
|
39095
|
+
var init_RichTextEditor = __esm({
|
|
39096
|
+
"components/core/molecules/RichTextEditor.tsx"() {
|
|
39097
|
+
"use client";
|
|
39098
|
+
init_cn();
|
|
39099
|
+
init_Box();
|
|
39100
|
+
init_Button();
|
|
39101
|
+
init_useEventBus();
|
|
39102
|
+
CHANGE_DEBOUNCE_MS = 400;
|
|
39103
|
+
ALLOWED_ATTRS = {
|
|
39104
|
+
p: [],
|
|
39105
|
+
h1: [],
|
|
39106
|
+
h2: [],
|
|
39107
|
+
h3: [],
|
|
39108
|
+
h4: [],
|
|
39109
|
+
ul: [],
|
|
39110
|
+
ol: [],
|
|
39111
|
+
li: [],
|
|
39112
|
+
blockquote: [],
|
|
39113
|
+
pre: [],
|
|
39114
|
+
code: [],
|
|
39115
|
+
b: [],
|
|
39116
|
+
strong: [],
|
|
39117
|
+
i: [],
|
|
39118
|
+
em: [],
|
|
39119
|
+
u: [],
|
|
39120
|
+
s: [],
|
|
39121
|
+
strike: [],
|
|
39122
|
+
br: [],
|
|
39123
|
+
hr: [],
|
|
39124
|
+
div: [],
|
|
39125
|
+
span: [],
|
|
39126
|
+
a: ["href"],
|
|
39127
|
+
img: ["src", "alt"]
|
|
39128
|
+
};
|
|
39129
|
+
DROP_TAGS = /* @__PURE__ */ new Set(["script", "style", "iframe", "object", "embed", "link", "meta", "form", "input", "button", "textarea", "select"]);
|
|
39130
|
+
MD_BLOCK_PREFIXES = {
|
|
39131
|
+
"#": { kind: "block", tag: "h1" },
|
|
39132
|
+
"##": { kind: "block", tag: "h2" },
|
|
39133
|
+
"###": { kind: "block", tag: "h3" },
|
|
39134
|
+
">": { kind: "block", tag: "blockquote" },
|
|
39135
|
+
"```": { kind: "block", tag: "pre" },
|
|
39136
|
+
"-": { kind: "list", command: "insertUnorderedList" },
|
|
39137
|
+
"*": { kind: "list", command: "insertUnorderedList" },
|
|
39138
|
+
"1.": { kind: "list", command: "insertOrderedList" }
|
|
39139
|
+
};
|
|
39140
|
+
BLOCK_TAGS = /* @__PURE__ */ new Set(["P", "DIV", "LI", "H1", "H2", "H3", "H4", "BLOCKQUOTE", "PRE"]);
|
|
39141
|
+
MD_INLINE_RULES = [
|
|
39142
|
+
{ pattern: /\*\*([^*\n]+)\*\*$/, wrap: "strong" },
|
|
39143
|
+
{ pattern: /(^|[^*])\*([^*\n]+)\*$/, wrap: "em" },
|
|
39144
|
+
{ pattern: /`([^`\n]+)`$/, wrap: "code" }
|
|
39145
|
+
];
|
|
39146
|
+
RICH_TEXT_CSS = `
|
|
39147
|
+
.almadar-rich-text { line-height: 1.7; color: var(--color-foreground); }
|
|
39148
|
+
.almadar-rich-text h1 { font-size: 1.875rem; font-weight: 700; line-height: 1.25; margin: 1.25em 0 0.4em; }
|
|
39149
|
+
.almadar-rich-text h2 { font-size: 1.5rem; font-weight: 650; line-height: 1.3; margin: 1.1em 0 0.4em; }
|
|
39150
|
+
.almadar-rich-text h3 { font-size: 1.25rem; font-weight: 600; line-height: 1.35; margin: 1em 0 0.35em; }
|
|
39151
|
+
.almadar-rich-text h1:first-child, .almadar-rich-text h2:first-child, .almadar-rich-text h3:first-child { margin-top: 0; }
|
|
39152
|
+
.almadar-rich-text p { margin: 0.5em 0; }
|
|
39153
|
+
.almadar-rich-text ul { list-style: disc; padding-inline-start: 1.5rem; margin: 0.5em 0; }
|
|
39154
|
+
.almadar-rich-text ol { list-style: decimal; padding-inline-start: 1.5rem; margin: 0.5em 0; }
|
|
39155
|
+
.almadar-rich-text li { margin: 0.25em 0; }
|
|
39156
|
+
.almadar-rich-text blockquote { border-inline-start: 3px solid var(--color-primary); padding-inline-start: 1rem; font-style: italic; color: var(--color-muted-foreground); margin: 0.75em 0; }
|
|
39157
|
+
.almadar-rich-text pre { background: var(--color-muted); border: 1px solid var(--color-border); border-radius: 0.375rem; padding: 0.75rem 1rem; font-family: ui-monospace, monospace; font-size: 0.875em; white-space: pre-wrap; margin: 0.75em 0; }
|
|
39158
|
+
.almadar-rich-text code { font-family: ui-monospace, monospace; font-size: 0.875em; background: var(--color-muted); border-radius: 0.25rem; padding: 0.1em 0.35em; }
|
|
39159
|
+
.almadar-rich-text pre code { background: transparent; padding: 0; }
|
|
39160
|
+
.almadar-rich-text a { color: var(--color-primary); text-decoration: underline; }
|
|
39161
|
+
.almadar-rich-text hr { border: none; border-top: 1px solid var(--color-border); margin: 1.25em 0; }
|
|
39162
|
+
.almadar-rich-text img { max-width: 100%; border-radius: 0.375rem; }
|
|
39163
|
+
`;
|
|
39164
|
+
IDLE_TOOLBAR = {
|
|
39165
|
+
bold: false,
|
|
39166
|
+
italic: false,
|
|
39167
|
+
underline: false,
|
|
39168
|
+
strikeThrough: false,
|
|
39169
|
+
block: null,
|
|
39170
|
+
bullets: false,
|
|
39171
|
+
numbers: false,
|
|
39172
|
+
link: false
|
|
39173
|
+
};
|
|
39174
|
+
RichTextEditor = ({
|
|
39175
|
+
value,
|
|
39176
|
+
onChange,
|
|
39177
|
+
changeEvent,
|
|
39178
|
+
readOnly = false,
|
|
39179
|
+
placeholder,
|
|
39180
|
+
showToolbar = true,
|
|
39181
|
+
className
|
|
39182
|
+
}) => {
|
|
39183
|
+
const { t } = hooks.useTranslate();
|
|
39184
|
+
const ref = React94.useRef(null);
|
|
39185
|
+
const [toolbar, setToolbar] = React94.useState(IDLE_TOOLBAR);
|
|
39186
|
+
const [empty, setEmpty] = React94.useState(() => !value || !sanitizeRichHtml(value).trim());
|
|
39187
|
+
const eventBus = useEventBus();
|
|
39188
|
+
const onChangeRef = React94.useRef(onChange);
|
|
39189
|
+
const changeEventRef = React94.useRef(changeEvent);
|
|
39190
|
+
React94.useEffect(() => {
|
|
39191
|
+
onChangeRef.current = onChange;
|
|
39192
|
+
changeEventRef.current = changeEvent;
|
|
39193
|
+
}, [onChange, changeEvent]);
|
|
39194
|
+
const emitTimerRef = React94.useRef(null);
|
|
39195
|
+
const emitNow = React94.useCallback(() => {
|
|
39196
|
+
const el = ref.current;
|
|
39197
|
+
if (!el) return;
|
|
39198
|
+
const html = sanitizeRichHtml(el.innerHTML);
|
|
39199
|
+
onChangeRef.current?.(html);
|
|
39200
|
+
const evt = changeEventRef.current;
|
|
39201
|
+
if (evt) eventBus.emit(`UI:${evt}`, { value: html });
|
|
39202
|
+
}, [eventBus]);
|
|
39203
|
+
const scheduleEmit = React94.useCallback(() => {
|
|
39204
|
+
if (emitTimerRef.current) clearTimeout(emitTimerRef.current);
|
|
39205
|
+
emitTimerRef.current = setTimeout(() => {
|
|
39206
|
+
emitTimerRef.current = null;
|
|
39207
|
+
emitNow();
|
|
39208
|
+
}, CHANGE_DEBOUNCE_MS);
|
|
39209
|
+
}, [emitNow]);
|
|
39210
|
+
const flushEmit = React94.useCallback(() => {
|
|
39211
|
+
if (!emitTimerRef.current) return;
|
|
39212
|
+
clearTimeout(emitTimerRef.current);
|
|
39213
|
+
emitTimerRef.current = null;
|
|
39214
|
+
emitNow();
|
|
39215
|
+
}, [emitNow]);
|
|
39216
|
+
React94.useEffect(() => () => {
|
|
39217
|
+
if (emitTimerRef.current) {
|
|
39218
|
+
clearTimeout(emitTimerRef.current);
|
|
39219
|
+
emitTimerRef.current = null;
|
|
39220
|
+
emitNow();
|
|
39221
|
+
}
|
|
39222
|
+
}, [emitNow]);
|
|
39223
|
+
React94.useEffect(() => {
|
|
39224
|
+
if (readOnly) return;
|
|
39225
|
+
const el = ref.current;
|
|
39226
|
+
if (!el) return;
|
|
39227
|
+
if (document.activeElement === el) return;
|
|
39228
|
+
const next = sanitizeRichHtml(value ?? "") || "<p><br></p>";
|
|
39229
|
+
if (el.innerHTML !== next) {
|
|
39230
|
+
el.innerHTML = next;
|
|
39231
|
+
setEmpty(htmlIsEmpty(el));
|
|
39232
|
+
}
|
|
39233
|
+
}, [readOnly, value]);
|
|
39234
|
+
React94.useEffect(() => {
|
|
39235
|
+
if (readOnly) return;
|
|
39236
|
+
document.execCommand("defaultParagraphSeparator", false, "p");
|
|
39237
|
+
}, [readOnly]);
|
|
39238
|
+
React94.useEffect(() => {
|
|
39239
|
+
if (readOnly || !showToolbar) return;
|
|
39240
|
+
const onSelectionChange = () => {
|
|
39241
|
+
const el = ref.current;
|
|
39242
|
+
if (!el) return;
|
|
39243
|
+
setToolbar(readToolbarState(el));
|
|
39244
|
+
};
|
|
39245
|
+
document.addEventListener("selectionchange", onSelectionChange);
|
|
39246
|
+
return () => document.removeEventListener("selectionchange", onSelectionChange);
|
|
39247
|
+
}, [readOnly, showToolbar]);
|
|
39248
|
+
const tryInlineMarkdown = React94.useCallback(() => {
|
|
39249
|
+
const root = ref.current;
|
|
39250
|
+
if (!root) return false;
|
|
39251
|
+
const sel = window.getSelection();
|
|
39252
|
+
if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return false;
|
|
39253
|
+
const node = sel.anchorNode;
|
|
39254
|
+
if (!node || node.nodeType !== Node.TEXT_NODE || !root.contains(node)) return false;
|
|
39255
|
+
if (node.parentElement?.closest("code, pre")) return false;
|
|
39256
|
+
const text = (node.textContent ?? "").slice(0, sel.anchorOffset);
|
|
39257
|
+
for (const rule of MD_INLINE_RULES) {
|
|
39258
|
+
const m = rule.pattern.exec(text);
|
|
39259
|
+
if (!m) continue;
|
|
39260
|
+
const inner = rule.wrap === "em" ? m[2] : m[1];
|
|
39261
|
+
if (!inner || !inner.trim()) continue;
|
|
39262
|
+
const lead = rule.wrap === "em" ? m[1]?.length ?? 0 : 0;
|
|
39263
|
+
const range = document.createRange();
|
|
39264
|
+
range.setStart(node, m.index + lead);
|
|
39265
|
+
range.setEnd(node, sel.anchorOffset);
|
|
39266
|
+
const el = document.createElement(rule.wrap);
|
|
39267
|
+
el.textContent = inner;
|
|
39268
|
+
range.deleteContents();
|
|
39269
|
+
range.insertNode(el);
|
|
39270
|
+
const after = document.createTextNode("\u200B");
|
|
39271
|
+
el.parentNode?.insertBefore(after, el.nextSibling);
|
|
39272
|
+
const caret = document.createRange();
|
|
39273
|
+
caret.setStart(after, 1);
|
|
39274
|
+
caret.collapse(true);
|
|
39275
|
+
sel.removeAllRanges();
|
|
39276
|
+
sel.addRange(caret);
|
|
39277
|
+
return true;
|
|
39278
|
+
}
|
|
39279
|
+
return false;
|
|
39280
|
+
}, []);
|
|
39281
|
+
const tryBlockMarkdown = React94.useCallback(() => {
|
|
39282
|
+
const root = ref.current;
|
|
39283
|
+
if (!root) return false;
|
|
39284
|
+
const sel = window.getSelection();
|
|
39285
|
+
if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return false;
|
|
39286
|
+
const node = sel.anchorNode;
|
|
39287
|
+
if (!node || node.nodeType !== Node.TEXT_NODE || !root.contains(node)) return false;
|
|
39288
|
+
const block = closestBlock(node, root);
|
|
39289
|
+
if (block ? block.firstChild !== node : root.firstChild !== node) return false;
|
|
39290
|
+
const prefix = (node.textContent ?? "").slice(0, sel.anchorOffset);
|
|
39291
|
+
const rule = MD_BLOCK_PREFIXES[prefix];
|
|
39292
|
+
if (!rule) return false;
|
|
39293
|
+
if (node.parentElement?.closest("pre, code")) return false;
|
|
39294
|
+
if (rule.kind === "list" && node.parentElement?.closest("li")) return false;
|
|
39295
|
+
node.deleteData(0, prefix.length);
|
|
39296
|
+
const caret = document.createRange();
|
|
39297
|
+
caret.setStart(node, 0);
|
|
39298
|
+
caret.collapse(true);
|
|
39299
|
+
sel.removeAllRanges();
|
|
39300
|
+
sel.addRange(caret);
|
|
39301
|
+
if (rule.kind === "list") {
|
|
39302
|
+
const container = block ?? node.parentElement;
|
|
39303
|
+
const list = document.createElement(rule.command === "insertOrderedList" ? "ol" : "ul");
|
|
39304
|
+
const li = document.createElement("li");
|
|
39305
|
+
if (block) {
|
|
39306
|
+
while (block.firstChild) li.appendChild(block.firstChild);
|
|
39307
|
+
list.appendChild(li);
|
|
39308
|
+
block.replaceWith(list);
|
|
39309
|
+
} else if (container) {
|
|
39310
|
+
li.appendChild(node);
|
|
39311
|
+
list.appendChild(li);
|
|
39312
|
+
container.appendChild(list);
|
|
39313
|
+
}
|
|
39314
|
+
if (!li.firstChild) li.appendChild(document.createElement("br"));
|
|
39315
|
+
const liCaret = document.createRange();
|
|
39316
|
+
liCaret.selectNodeContents(li);
|
|
39317
|
+
liCaret.collapse(true);
|
|
39318
|
+
sel.removeAllRanges();
|
|
39319
|
+
sel.addRange(liCaret);
|
|
39320
|
+
} else {
|
|
39321
|
+
document.execCommand("formatBlock", false, rule.tag);
|
|
39322
|
+
}
|
|
39323
|
+
return true;
|
|
39324
|
+
}, []);
|
|
39325
|
+
const afterEdit = React94.useCallback(() => {
|
|
39326
|
+
const el = ref.current;
|
|
39327
|
+
if (!el) return;
|
|
39328
|
+
tryInlineMarkdown();
|
|
39329
|
+
setEmpty(htmlIsEmpty(el));
|
|
39330
|
+
setToolbar(readToolbarState(el));
|
|
39331
|
+
scheduleEmit();
|
|
39332
|
+
}, [scheduleEmit, tryInlineMarkdown]);
|
|
39333
|
+
const handleKeyDown = React94.useCallback((e) => {
|
|
39334
|
+
if (e.key === " " && tryBlockMarkdown()) {
|
|
39335
|
+
e.preventDefault();
|
|
39336
|
+
afterEdit();
|
|
39337
|
+
}
|
|
39338
|
+
}, [afterEdit, tryBlockMarkdown]);
|
|
39339
|
+
const execInline = React94.useCallback((command) => {
|
|
39340
|
+
document.execCommand(command, false);
|
|
39341
|
+
afterEdit();
|
|
39342
|
+
}, [afterEdit]);
|
|
39343
|
+
const execBlock = React94.useCallback((tag) => {
|
|
39344
|
+
const next = toolbar.block === tag ? "p" : tag;
|
|
39345
|
+
document.execCommand("formatBlock", false, next);
|
|
39346
|
+
afterEdit();
|
|
39347
|
+
}, [afterEdit, toolbar.block]);
|
|
39348
|
+
const execList = React94.useCallback((command) => {
|
|
39349
|
+
document.execCommand(command, false);
|
|
39350
|
+
afterEdit();
|
|
39351
|
+
}, [afterEdit]);
|
|
39352
|
+
const execLink = React94.useCallback(() => {
|
|
39353
|
+
if (toolbar.link) {
|
|
39354
|
+
document.execCommand("unlink", false);
|
|
39355
|
+
afterEdit();
|
|
39356
|
+
return;
|
|
39357
|
+
}
|
|
39358
|
+
const url = window.prompt(t("richTextEditor.linkPrompt"));
|
|
39359
|
+
if (!url) return;
|
|
39360
|
+
const safe = safeUrl(url, ["http://", "https://", "mailto:"]) ?? `https://${url}`;
|
|
39361
|
+
document.execCommand("createLink", false, safe);
|
|
39362
|
+
afterEdit();
|
|
39363
|
+
}, [afterEdit, t, toolbar.link]);
|
|
39364
|
+
const execRule = React94.useCallback(() => {
|
|
39365
|
+
document.execCommand("insertHorizontalRule", false);
|
|
39366
|
+
afterEdit();
|
|
39367
|
+
}, [afterEdit]);
|
|
39368
|
+
if (readOnly) {
|
|
39369
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("almadar-rich-text max-w-none", className), children: [
|
|
39370
|
+
/* @__PURE__ */ jsxRuntime.jsx(RichTextStyles, {}),
|
|
39371
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { dangerouslySetInnerHTML: { __html: sanitizeRichHtml(value ?? "") } })
|
|
39372
|
+
] });
|
|
39373
|
+
}
|
|
39374
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex flex-col gap-2", className), children: [
|
|
39375
|
+
/* @__PURE__ */ jsxRuntime.jsx(RichTextStyles, {}),
|
|
39376
|
+
showToolbar && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
39377
|
+
Box,
|
|
39378
|
+
{
|
|
39379
|
+
role: "toolbar",
|
|
39380
|
+
"aria-label": t("richTextEditor.editorToolbar"),
|
|
39381
|
+
className: cn(
|
|
39382
|
+
"sticky top-0 z-10 flex flex-wrap items-center gap-0.5 self-start",
|
|
39383
|
+
"rounded-md border border-border bg-background/95 px-1 py-0.5 shadow-sm"
|
|
39384
|
+
),
|
|
39385
|
+
children: [
|
|
39386
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Bold, label: t("richTextEditor.bold"), active: toolbar.bold, onExec: () => execInline("bold") }),
|
|
39387
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Italic, label: t("richTextEditor.italic"), active: toolbar.italic, onExec: () => execInline("italic") }),
|
|
39388
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Underline, label: t("richTextEditor.underline"), active: toolbar.underline, onExec: () => execInline("underline") }),
|
|
39389
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Strikethrough, label: t("richTextEditor.strikethrough"), active: toolbar.strikeThrough, onExec: () => execInline("strikeThrough") }),
|
|
39390
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
39391
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Heading1, label: t("richTextEditor.heading1"), active: toolbar.block === "h1", onExec: () => execBlock("h1") }),
|
|
39392
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Heading2, label: t("richTextEditor.heading2"), active: toolbar.block === "h2", onExec: () => execBlock("h2") }),
|
|
39393
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Heading3, label: t("richTextEditor.heading3"), active: toolbar.block === "h3", onExec: () => execBlock("h3") }),
|
|
39394
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
39395
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.List, label: t("richTextEditor.bulletList"), active: toolbar.bullets, onExec: () => execList("insertUnorderedList") }),
|
|
39396
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.ListOrdered, label: t("richTextEditor.numberedList"), active: toolbar.numbers, onExec: () => execList("insertOrderedList") }),
|
|
39397
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
39398
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Quote, label: t("richTextEditor.quote"), active: toolbar.block === "blockquote", onExec: () => execBlock("blockquote") }),
|
|
39399
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Code, label: t("richTextEditor.code"), active: toolbar.block === "pre", onExec: () => execBlock("pre") }),
|
|
39400
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Link, label: toolbar.link ? t("richTextEditor.removeLink") : t("richTextEditor.link"), active: toolbar.link, onExec: execLink }),
|
|
39401
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Minus, label: t("richTextEditor.divider"), onExec: execRule })
|
|
39402
|
+
]
|
|
39403
|
+
}
|
|
39404
|
+
),
|
|
39405
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
39406
|
+
Box,
|
|
39407
|
+
{
|
|
39408
|
+
ref,
|
|
39409
|
+
contentEditable: true,
|
|
39410
|
+
suppressContentEditableWarning: true,
|
|
39411
|
+
role: "textbox",
|
|
39412
|
+
"aria-multiline": "true",
|
|
39413
|
+
"aria-label": t("richTextEditor.editorSurface"),
|
|
39414
|
+
"data-placeholder": placeholder ?? t("richTextEditor.placeholder"),
|
|
39415
|
+
"data-empty": empty ? "true" : "false",
|
|
39416
|
+
className: cn(
|
|
39417
|
+
"almadar-rich-text max-w-none min-h-[8rem] outline-none",
|
|
39418
|
+
"data-[empty=true]:before:content-[attr(data-placeholder)]",
|
|
39419
|
+
"data-[empty=true]:before:text-muted-foreground/60",
|
|
39420
|
+
"data-[empty=true]:before:pointer-events-none",
|
|
39421
|
+
"data-[empty=true]:before:absolute",
|
|
39422
|
+
"relative cursor-text"
|
|
39423
|
+
),
|
|
39424
|
+
onInput: afterEdit,
|
|
39425
|
+
onKeyDown: handleKeyDown,
|
|
39426
|
+
onBlur: flushEmit
|
|
39427
|
+
}
|
|
39428
|
+
)
|
|
39429
|
+
] });
|
|
39082
39430
|
};
|
|
39431
|
+
RichTextEditor.displayName = "RichTextEditor";
|
|
39083
39432
|
}
|
|
39084
|
-
|
|
39085
|
-
|
|
39433
|
+
});
|
|
39434
|
+
function renderIconInput4(icon, props) {
|
|
39435
|
+
return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, ...props });
|
|
39086
39436
|
}
|
|
39087
|
-
function
|
|
39437
|
+
function DocumentPanel({
|
|
39438
|
+
entity,
|
|
39439
|
+
title,
|
|
39440
|
+
subtitle,
|
|
39441
|
+
value,
|
|
39442
|
+
actions,
|
|
39443
|
+
maxInlineActions,
|
|
39444
|
+
editing = false,
|
|
39445
|
+
titleCommitEvent,
|
|
39446
|
+
contentChangeEvent,
|
|
39447
|
+
editEvent,
|
|
39448
|
+
doneEvent,
|
|
39449
|
+
editLabel,
|
|
39450
|
+
doneLabel,
|
|
39451
|
+
autosaveHint,
|
|
39452
|
+
placeholder,
|
|
39453
|
+
className
|
|
39454
|
+
}) {
|
|
39455
|
+
const eventBus = useEventBus();
|
|
39088
39456
|
const { t } = hooks.useTranslate();
|
|
39089
|
-
const [
|
|
39090
|
-
const
|
|
39091
|
-
|
|
39092
|
-
|
|
39093
|
-
|
|
39094
|
-
|
|
39095
|
-
|
|
39096
|
-
|
|
39457
|
+
const [titleDraft, setTitleDraft] = React94.useState(null);
|
|
39458
|
+
const recordId = entity?.id !== void 0 && entity?.id !== null ? String(entity.id) : "";
|
|
39459
|
+
const actionDefs = actions ?? [];
|
|
39460
|
+
const inlineCap = Math.min(maxInlineActions ?? 1, 1);
|
|
39461
|
+
const inlineActions = actionDefs.filter((a) => a.variant === "primary").slice(0, inlineCap);
|
|
39462
|
+
const menuActions = actionDefs.filter((a) => !inlineActions.includes(a));
|
|
39463
|
+
const fireAction = (action) => {
|
|
39464
|
+
if (!action.event) return;
|
|
39465
|
+
eventBus.emit(`UI:${action.event}`, { id: recordId, row: entity });
|
|
39466
|
+
};
|
|
39467
|
+
const commitTitle = () => {
|
|
39468
|
+
if (!titleCommitEvent) return;
|
|
39469
|
+
const next = (titleDraft ?? "").trim();
|
|
39470
|
+
setTitleDraft(null);
|
|
39471
|
+
if (!next || next === title) return;
|
|
39472
|
+
eventBus.emit(`UI:${titleCommitEvent}`, { title: next, id: recordId });
|
|
39473
|
+
};
|
|
39474
|
+
const untitled = t("documentPanel.untitled") || "Untitled";
|
|
39475
|
+
const titleNode = titleCommitEvent && titleDraft !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
39476
|
+
Input,
|
|
39477
|
+
{
|
|
39478
|
+
value: titleDraft,
|
|
39479
|
+
autoFocus: true,
|
|
39480
|
+
"aria-label": t("common.title"),
|
|
39481
|
+
className: "h-auto py-1 text-3xl font-bold tracking-tight",
|
|
39482
|
+
onFocus: (e) => e.currentTarget.select(),
|
|
39483
|
+
onChange: (e) => setTitleDraft(e.target.value),
|
|
39484
|
+
onBlur: commitTitle,
|
|
39485
|
+
onKeyDown: (e) => {
|
|
39486
|
+
if (e.key === "Enter") {
|
|
39487
|
+
e.preventDefault();
|
|
39488
|
+
commitTitle();
|
|
39489
|
+
} else if (e.key === "Escape") {
|
|
39490
|
+
e.preventDefault();
|
|
39491
|
+
setTitleDraft(null);
|
|
39492
|
+
}
|
|
39493
|
+
},
|
|
39494
|
+
"data-testid": "document-title-input"
|
|
39097
39495
|
}
|
|
39098
|
-
|
|
39099
|
-
|
|
39100
|
-
|
|
39101
|
-
|
|
39102
|
-
|
|
39103
|
-
|
|
39104
|
-
|
|
39496
|
+
) : titleCommitEvent ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
39497
|
+
Box,
|
|
39498
|
+
{
|
|
39499
|
+
role: "button",
|
|
39500
|
+
tabIndex: 0,
|
|
39501
|
+
className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
39502
|
+
onClick: () => setTitleDraft(title ?? ""),
|
|
39503
|
+
onKeyDown: (e) => {
|
|
39504
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
39505
|
+
e.preventDefault();
|
|
39506
|
+
setTitleDraft(title ?? "");
|
|
39507
|
+
}
|
|
39508
|
+
},
|
|
39509
|
+
"data-testid": "document-title-editable",
|
|
39510
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", className: cn(!title && "text-muted-foreground"), children: title || untitled })
|
|
39511
|
+
}
|
|
39512
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || untitled });
|
|
39513
|
+
const emitWithId = (event) => () => {
|
|
39514
|
+
if (event) eventBus.emit(`UI:${event}`, { id: recordId });
|
|
39515
|
+
};
|
|
39516
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { variant: "elevated", className: cn("w-full", className), children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", className: "p-6 sm:p-8", children: [
|
|
39517
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
39518
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
39519
|
+
titleNode,
|
|
39520
|
+
subtitle ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
39521
|
+
] }),
|
|
39522
|
+
/* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
39523
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
39524
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
39525
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
39526
|
+
editEvent && /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
39527
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
39528
|
+
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
39529
|
+
] }),
|
|
39530
|
+
inlineActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
39531
|
+
Button,
|
|
39532
|
+
{
|
|
39533
|
+
variant: "primary",
|
|
39534
|
+
size: "sm",
|
|
39535
|
+
onClick: () => fireAction(action),
|
|
39536
|
+
"data-testid": `action-${action.event}`,
|
|
39537
|
+
children: [
|
|
39538
|
+
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
39539
|
+
action.label
|
|
39540
|
+
]
|
|
39541
|
+
},
|
|
39542
|
+
idx
|
|
39543
|
+
)),
|
|
39544
|
+
menuActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
39545
|
+
Menu,
|
|
39546
|
+
{
|
|
39547
|
+
position: "bottom-end",
|
|
39548
|
+
trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
39549
|
+
items: menuActions.map((action) => ({
|
|
39550
|
+
label: action.label,
|
|
39551
|
+
icon: action.icon,
|
|
39552
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
39553
|
+
onClick: () => fireAction(action)
|
|
39554
|
+
}))
|
|
39555
|
+
}
|
|
39556
|
+
)
|
|
39557
|
+
] }) })
|
|
39558
|
+
] }),
|
|
39559
|
+
editing ? /* @__PURE__ */ jsxRuntime.jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
39560
|
+
Box,
|
|
39105
39561
|
{
|
|
39106
|
-
|
|
39107
|
-
variant: "ghost",
|
|
39108
|
-
"aria-label": t("richBlockEditor.blockActions"),
|
|
39562
|
+
onClick: emitWithId(editEvent),
|
|
39109
39563
|
className: cn(
|
|
39110
|
-
"
|
|
39111
|
-
|
|
39112
|
-
"text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
39113
|
-
"opacity-0 group-hover:opacity-100 focus-visible:opacity-100",
|
|
39114
|
-
"transition-opacity"
|
|
39564
|
+
"rounded-md px-1 -mx-1 min-h-[16rem]",
|
|
39565
|
+
editEvent && "cursor-text transition-colors hover:bg-muted/30"
|
|
39115
39566
|
),
|
|
39116
|
-
|
|
39117
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
39118
|
-
}
|
|
39119
|
-
),
|
|
39120
|
-
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
39121
|
-
Box,
|
|
39122
|
-
{
|
|
39123
|
-
role: "menu",
|
|
39124
|
-
className: cn(
|
|
39125
|
-
"absolute right-0 z-10 mt-1 w-44",
|
|
39126
|
-
"rounded-container border border-border bg-popover shadow-elevation-popover",
|
|
39127
|
-
"py-1 text-sm"
|
|
39128
|
-
),
|
|
39129
|
-
children: [
|
|
39130
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-2 py-1 text-xs uppercase tracking-wide text-muted-foreground", children: t(BLOCK_TYPE_LABEL_KEY[block.type]) }),
|
|
39131
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
39132
|
-
Button,
|
|
39133
|
-
{
|
|
39134
|
-
type: "button",
|
|
39135
|
-
variant: "ghost",
|
|
39136
|
-
role: "menuitem",
|
|
39137
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left justify-start rounded-none",
|
|
39138
|
-
onClick: () => {
|
|
39139
|
-
onDuplicate();
|
|
39140
|
-
setOpen(false);
|
|
39141
|
-
},
|
|
39142
|
-
children: [
|
|
39143
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "plus", className: "w-3.5 h-3.5" }),
|
|
39144
|
-
" ",
|
|
39145
|
-
t("richBlockEditor.duplicate")
|
|
39146
|
-
]
|
|
39147
|
-
}
|
|
39148
|
-
),
|
|
39149
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
39150
|
-
Button,
|
|
39151
|
-
{
|
|
39152
|
-
type: "button",
|
|
39153
|
-
variant: "ghost",
|
|
39154
|
-
role: "menuitem",
|
|
39155
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left text-destructive hover:bg-muted justify-start rounded-none",
|
|
39156
|
-
onClick: () => {
|
|
39157
|
-
onDelete();
|
|
39158
|
-
setOpen(false);
|
|
39159
|
-
},
|
|
39160
|
-
children: [
|
|
39161
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "trash", className: "w-3.5 h-3.5" }),
|
|
39162
|
-
" ",
|
|
39163
|
-
t("common.delete")
|
|
39164
|
-
]
|
|
39165
|
-
}
|
|
39166
|
-
),
|
|
39167
|
-
CHANGEABLE_TYPES.includes(block.type) && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
39168
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "my-1 border-t border-border" }),
|
|
39169
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-2 py-1 text-xs uppercase tracking-wide text-muted-foreground", children: t("richBlockEditor.turnInto") }),
|
|
39170
|
-
CHANGEABLE_TYPES.filter((bt) => bt !== block.type).map((bt) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
39171
|
-
Button,
|
|
39172
|
-
{
|
|
39173
|
-
type: "button",
|
|
39174
|
-
variant: "ghost",
|
|
39175
|
-
role: "menuitem",
|
|
39176
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left justify-start rounded-none",
|
|
39177
|
-
onClick: () => {
|
|
39178
|
-
onChangeType(bt);
|
|
39179
|
-
setOpen(false);
|
|
39180
|
-
},
|
|
39181
|
-
children: t(BLOCK_TYPE_LABEL_KEY[bt])
|
|
39182
|
-
},
|
|
39183
|
-
bt
|
|
39184
|
-
))
|
|
39185
|
-
] })
|
|
39186
|
-
]
|
|
39567
|
+
"data-testid": "document-body",
|
|
39568
|
+
children: value && value !== "" ? /* @__PURE__ */ jsxRuntime.jsx(RichTextEditor, { value, readOnly: true }) : /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "muted", children: placeholder ?? (t("documentPanel.placeholder") || "") })
|
|
39187
39569
|
}
|
|
39188
39570
|
)
|
|
39189
|
-
] });
|
|
39571
|
+
] }) });
|
|
39190
39572
|
}
|
|
39191
|
-
|
|
39192
|
-
|
|
39193
|
-
|
|
39194
|
-
|
|
39195
|
-
|
|
39196
|
-
|
|
39197
|
-
|
|
39198
|
-
|
|
39199
|
-
|
|
39200
|
-
|
|
39201
|
-
|
|
39202
|
-
|
|
39203
|
-
|
|
39204
|
-
|
|
39205
|
-
|
|
39206
|
-
|
|
39207
|
-
|
|
39208
|
-
},
|
|
39209
|
-
const handleInput = React94.useCallback(
|
|
39210
|
-
(e) => {
|
|
39211
|
-
onValueChange(e.currentTarget.textContent ?? "");
|
|
39212
|
-
},
|
|
39213
|
-
[onValueChange]
|
|
39214
|
-
);
|
|
39215
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39216
|
-
Box,
|
|
39217
|
-
{
|
|
39218
|
-
as: tag,
|
|
39219
|
-
ref,
|
|
39220
|
-
contentEditable: !readOnly,
|
|
39221
|
-
suppressContentEditableWarning: true,
|
|
39222
|
-
role: readOnly ? void 0 : "textbox",
|
|
39223
|
-
"aria-label": ariaLabel,
|
|
39224
|
-
"aria-multiline": "true",
|
|
39225
|
-
"data-placeholder": placeholder,
|
|
39226
|
-
className: cn(
|
|
39227
|
-
"outline-none focus-visible:ring-1 focus-visible:ring-ring rounded-sm",
|
|
39228
|
-
"empty:before:content-[attr(data-placeholder)] empty:before:text-muted-foreground/60",
|
|
39229
|
-
className
|
|
39230
|
-
),
|
|
39231
|
-
onInput: handleInput
|
|
39232
|
-
}
|
|
39233
|
-
);
|
|
39573
|
+
var init_DocumentPanel = __esm({
|
|
39574
|
+
"components/core/molecules/DocumentPanel.tsx"() {
|
|
39575
|
+
"use client";
|
|
39576
|
+
init_cn();
|
|
39577
|
+
init_useEventBus();
|
|
39578
|
+
init_Box();
|
|
39579
|
+
init_Stack();
|
|
39580
|
+
init_Typography();
|
|
39581
|
+
init_Button();
|
|
39582
|
+
init_Card();
|
|
39583
|
+
init_Icon();
|
|
39584
|
+
init_Input();
|
|
39585
|
+
init_Menu();
|
|
39586
|
+
init_RichTextEditor();
|
|
39587
|
+
}
|
|
39588
|
+
});
|
|
39589
|
+
function renderIconInput5(icon, props) {
|
|
39590
|
+
return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, ...props });
|
|
39234
39591
|
}
|
|
39235
|
-
function
|
|
39236
|
-
|
|
39237
|
-
|
|
39238
|
-
|
|
39239
|
-
|
|
39240
|
-
|
|
39241
|
-
|
|
39242
|
-
|
|
39243
|
-
|
|
39592
|
+
function fieldName(field) {
|
|
39593
|
+
return field.name ?? field.key ?? "";
|
|
39594
|
+
}
|
|
39595
|
+
function relationLabel(value) {
|
|
39596
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date) return null;
|
|
39597
|
+
for (const key of ["name", "title", "label"]) {
|
|
39598
|
+
const candidate = value[key];
|
|
39599
|
+
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
39600
|
+
}
|
|
39601
|
+
const id = value.id;
|
|
39602
|
+
return id !== void 0 && id !== null ? String(id) : null;
|
|
39603
|
+
}
|
|
39604
|
+
function fieldKind(field, value) {
|
|
39605
|
+
if (field.kind) return field.kind;
|
|
39606
|
+
if (field.options && field.options.length > 0) return "select";
|
|
39607
|
+
if (typeof value === "boolean" || field.format === "boolean") return "boolean";
|
|
39608
|
+
if (Array.isArray(value) || relationLabel(value ?? null) !== null) return "readonly";
|
|
39609
|
+
return "text";
|
|
39610
|
+
}
|
|
39611
|
+
function DocumentDetails({
|
|
39612
|
+
entity,
|
|
39613
|
+
fields,
|
|
39614
|
+
metaCommitEvent,
|
|
39615
|
+
title,
|
|
39616
|
+
className
|
|
39244
39617
|
}) {
|
|
39618
|
+
const eventBus = useEventBus();
|
|
39245
39619
|
const { t } = hooks.useTranslate();
|
|
39246
|
-
const
|
|
39247
|
-
|
|
39248
|
-
|
|
39249
|
-
);
|
|
39250
|
-
const
|
|
39251
|
-
(
|
|
39252
|
-
|
|
39253
|
-
|
|
39254
|
-
|
|
39255
|
-
|
|
39256
|
-
|
|
39257
|
-
|
|
39258
|
-
|
|
39259
|
-
|
|
39260
|
-
|
|
39261
|
-
|
|
39262
|
-
|
|
39263
|
-
|
|
39264
|
-
|
|
39265
|
-
|
|
39266
|
-
|
|
39267
|
-
|
|
39268
|
-
|
|
39269
|
-
|
|
39270
|
-
|
|
39271
|
-
|
|
39272
|
-
|
|
39273
|
-
|
|
39274
|
-
|
|
39275
|
-
|
|
39276
|
-
|
|
39277
|
-
|
|
39278
|
-
|
|
39279
|
-
|
|
39280
|
-
|
|
39281
|
-
|
|
39282
|
-
|
|
39283
|
-
}
|
|
39284
|
-
|
|
39285
|
-
|
|
39286
|
-
|
|
39287
|
-
|
|
39288
|
-
|
|
39289
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39290
|
-
Editable,
|
|
39291
|
-
{
|
|
39292
|
-
tag: "h1",
|
|
39293
|
-
value: block.content ?? "",
|
|
39294
|
-
readOnly,
|
|
39295
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.heading1"),
|
|
39296
|
-
ariaLabel: t("richBlockEditor.aria.heading1Block"),
|
|
39297
|
-
className: "text-3xl font-bold leading-tight",
|
|
39298
|
-
onValueChange: setContent
|
|
39299
|
-
}
|
|
39300
|
-
);
|
|
39301
|
-
case "heading-2":
|
|
39302
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39303
|
-
Editable,
|
|
39304
|
-
{
|
|
39305
|
-
tag: "h2",
|
|
39306
|
-
value: block.content ?? "",
|
|
39307
|
-
readOnly,
|
|
39308
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.heading2"),
|
|
39309
|
-
ariaLabel: t("richBlockEditor.aria.heading2Block"),
|
|
39310
|
-
className: "text-2xl font-semibold leading-tight",
|
|
39311
|
-
onValueChange: setContent
|
|
39312
|
-
}
|
|
39313
|
-
);
|
|
39314
|
-
case "heading-3":
|
|
39315
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39316
|
-
Editable,
|
|
39317
|
-
{
|
|
39318
|
-
tag: "h3",
|
|
39319
|
-
value: block.content ?? "",
|
|
39320
|
-
readOnly,
|
|
39321
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.heading3"),
|
|
39322
|
-
ariaLabel: t("richBlockEditor.aria.heading3Block"),
|
|
39323
|
-
className: "text-xl font-semibold leading-tight",
|
|
39324
|
-
onValueChange: setContent
|
|
39325
|
-
}
|
|
39326
|
-
);
|
|
39327
|
-
case "quote":
|
|
39328
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39329
|
-
Editable,
|
|
39330
|
-
{
|
|
39331
|
-
tag: "blockquote",
|
|
39332
|
-
value: block.content ?? "",
|
|
39333
|
-
readOnly,
|
|
39334
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.quote"),
|
|
39335
|
-
ariaLabel: t("richBlockEditor.aria.quoteBlock"),
|
|
39336
|
-
className: "border-l-4 border-primary/60 pl-4 italic text-muted-foreground",
|
|
39337
|
-
onValueChange: setContent
|
|
39338
|
-
}
|
|
39339
|
-
);
|
|
39340
|
-
case "code":
|
|
39341
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "rounded-md border border-border bg-muted/40", children: [
|
|
39342
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center justify-between border-b border-border px-3 py-1 text-xs text-muted-foreground", children: [
|
|
39343
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", variant: "caption", className: "uppercase tracking-wide", children: t("richBlockEditor.blockType.code") }),
|
|
39344
|
-
!readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
39345
|
-
Input,
|
|
39346
|
-
{
|
|
39347
|
-
inputType: "text",
|
|
39348
|
-
value: String(block.metadata?.language ?? "plaintext"),
|
|
39349
|
-
"aria-label": t("richBlockEditor.aria.codeLanguage"),
|
|
39350
|
-
className: cn(
|
|
39351
|
-
"h-6 w-32 rounded-sm border border-border bg-background",
|
|
39352
|
-
"px-2 text-xs outline-none focus:ring-1 focus:ring-ring"
|
|
39353
|
-
),
|
|
39354
|
-
onChange: (e) => setMetadata("language", e.target.value)
|
|
39355
|
-
}
|
|
39356
|
-
),
|
|
39357
|
-
readOnly && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", variant: "caption", className: "text-xs", children: String(block.metadata?.language ?? "plaintext") })
|
|
39358
|
-
] }),
|
|
39359
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
39360
|
-
Editable,
|
|
39361
|
-
{
|
|
39362
|
-
tag: "pre",
|
|
39363
|
-
value: block.content ?? "",
|
|
39364
|
-
readOnly,
|
|
39365
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.code"),
|
|
39366
|
-
ariaLabel: t("richBlockEditor.aria.codeBlock"),
|
|
39367
|
-
className: "block whitespace-pre-wrap p-3 font-mono text-sm leading-relaxed",
|
|
39368
|
-
onValueChange: setContent
|
|
39369
|
-
}
|
|
39370
|
-
)
|
|
39371
|
-
] });
|
|
39372
|
-
case "divider":
|
|
39373
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Divider, { className: "my-2" });
|
|
39374
|
-
case "image": {
|
|
39375
|
-
const url = String(block.metadata?.url ?? "");
|
|
39376
|
-
const caption = String(block.metadata?.caption ?? "");
|
|
39377
|
-
const imgProps = {
|
|
39378
|
-
src: url,
|
|
39379
|
-
alt: caption || t("richBlockEditor.embeddedImage"),
|
|
39380
|
-
className: "max-h-96 w-full rounded-md border border-border object-contain"
|
|
39381
|
-
};
|
|
39382
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "space-y-2", children: [
|
|
39383
|
-
url ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "img", ...imgProps }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
39384
|
-
Box,
|
|
39385
|
-
{
|
|
39386
|
-
className: cn(
|
|
39387
|
-
"flex h-32 items-center justify-center",
|
|
39388
|
-
"rounded-md border border-dashed border-border",
|
|
39389
|
-
"text-sm text-muted-foreground"
|
|
39390
|
-
),
|
|
39391
|
-
children: [
|
|
39392
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "image", className: "mr-2 w-4 h-4" }),
|
|
39393
|
-
" ",
|
|
39394
|
-
t("richBlockEditor.noImageUrl")
|
|
39395
|
-
]
|
|
39396
|
-
}
|
|
39397
|
-
),
|
|
39398
|
-
!readOnly && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col gap-2 sm:flex-row", children: [
|
|
39399
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
39400
|
-
Input,
|
|
39401
|
-
{
|
|
39402
|
-
inputType: "url",
|
|
39403
|
-
value: url,
|
|
39404
|
-
placeholder: "https://example.com/image.png",
|
|
39405
|
-
"aria-label": t("richBlockEditor.aria.imageUrl"),
|
|
39406
|
-
className: cn(
|
|
39407
|
-
"h-8 flex-1 rounded-sm border border-border bg-background",
|
|
39408
|
-
"px-2 text-sm outline-none focus:ring-1 focus:ring-ring"
|
|
39409
|
-
),
|
|
39410
|
-
onChange: (e) => setMetadata("url", e.target.value)
|
|
39411
|
-
}
|
|
39412
|
-
),
|
|
39413
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
39414
|
-
Input,
|
|
39415
|
-
{
|
|
39416
|
-
inputType: "text",
|
|
39417
|
-
value: caption,
|
|
39418
|
-
placeholder: t("richBlockEditor.placeholder.caption"),
|
|
39419
|
-
"aria-label": t("richBlockEditor.aria.imageCaption"),
|
|
39420
|
-
className: cn(
|
|
39421
|
-
"h-8 flex-1 rounded-sm border border-border bg-background",
|
|
39422
|
-
"px-2 text-sm outline-none focus:ring-1 focus:ring-ring"
|
|
39423
|
-
),
|
|
39424
|
-
onChange: (e) => setMetadata("caption", e.target.value)
|
|
39425
|
-
}
|
|
39426
|
-
)
|
|
39427
|
-
] }),
|
|
39428
|
-
readOnly && caption && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-center text-muted-foreground", children: caption })
|
|
39429
|
-
] });
|
|
39620
|
+
const [fieldDraft, setFieldDraft] = React94.useState(null);
|
|
39621
|
+
const recordId = entity?.id !== void 0 && entity?.id !== null ? String(entity.id) : "";
|
|
39622
|
+
const fieldDefs = (fields ?? []).filter((f3) => fieldName(f3) !== "");
|
|
39623
|
+
if (fieldDefs.length === 0) return null;
|
|
39624
|
+
const commitField = (name, next, current) => {
|
|
39625
|
+
setFieldDraft(null);
|
|
39626
|
+
if (!metaCommitEvent || next === current) return;
|
|
39627
|
+
eventBus.emit(`UI:${metaCommitEvent}`, { id: recordId, patch: { id: recordId, [name]: next } });
|
|
39628
|
+
};
|
|
39629
|
+
const renderValue = (field) => {
|
|
39630
|
+
const name = fieldName(field);
|
|
39631
|
+
const raw = getNestedValue(entity ?? {}, name);
|
|
39632
|
+
const kind = fieldKind(field, raw);
|
|
39633
|
+
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
39634
|
+
if (kind === "boolean") {
|
|
39635
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39636
|
+
Switch,
|
|
39637
|
+
{
|
|
39638
|
+
checked: Boolean(raw),
|
|
39639
|
+
disabled: !metaCommitEvent,
|
|
39640
|
+
"aria-label": label,
|
|
39641
|
+
onChange: (checked) => commitField(name, checked, Boolean(raw))
|
|
39642
|
+
}
|
|
39643
|
+
);
|
|
39644
|
+
}
|
|
39645
|
+
if (kind === "select") {
|
|
39646
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39647
|
+
Select,
|
|
39648
|
+
{
|
|
39649
|
+
value: raw !== void 0 && raw !== null ? String(raw) : "",
|
|
39650
|
+
disabled: !metaCommitEvent,
|
|
39651
|
+
"aria-label": label,
|
|
39652
|
+
className: "h-8 w-full",
|
|
39653
|
+
options: (field.options ?? []).map((opt) => ({ value: opt, label: humanizeEnumValue(opt) })),
|
|
39654
|
+
onChange: (e) => commitField(name, e.target.value, raw)
|
|
39655
|
+
}
|
|
39656
|
+
);
|
|
39657
|
+
}
|
|
39658
|
+
if (kind === "readonly" || !metaCommitEvent) {
|
|
39659
|
+
if (Array.isArray(raw)) {
|
|
39660
|
+
if (raw.length === 0) {
|
|
39661
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
39662
|
+
}
|
|
39663
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", children: relationLabel(item) ?? humanizeEnumValue(String(item)) }, i)) });
|
|
39430
39664
|
}
|
|
39431
|
-
|
|
39432
|
-
|
|
39433
|
-
|
|
39434
|
-
|
|
39435
|
-
|
|
39436
|
-
|
|
39437
|
-
|
|
39438
|
-
|
|
39439
|
-
|
|
39440
|
-
|
|
39441
|
-
|
|
39442
|
-
|
|
39443
|
-
|
|
39444
|
-
|
|
39445
|
-
|
|
39446
|
-
|
|
39447
|
-
|
|
39448
|
-
|
|
39449
|
-
|
|
39450
|
-
|
|
39451
|
-
|
|
39452
|
-
|
|
39453
|
-
|
|
39454
|
-
|
|
39455
|
-
|
|
39456
|
-
|
|
39457
|
-
|
|
39458
|
-
|
|
39459
|
-
|
|
39460
|
-
|
|
39461
|
-
|
|
39462
|
-
|
|
39463
|
-
|
|
39464
|
-
|
|
39465
|
-
|
|
39466
|
-
|
|
39467
|
-
|
|
39468
|
-
|
|
39469
|
-
|
|
39470
|
-
|
|
39471
|
-
|
|
39472
|
-
Button,
|
|
39473
|
-
{
|
|
39474
|
-
type: "button",
|
|
39475
|
-
variant: "ghost",
|
|
39476
|
-
className: cn(
|
|
39477
|
-
"inline-flex items-center gap-1 text-xs text-muted-foreground",
|
|
39478
|
-
"hover:text-foreground p-0 h-auto"
|
|
39479
|
-
),
|
|
39480
|
-
onClick: addListItem,
|
|
39481
|
-
children: [
|
|
39482
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "plus", className: "w-3 h-3" }),
|
|
39483
|
-
" ",
|
|
39484
|
-
t("richBlockEditor.addItem")
|
|
39485
|
-
]
|
|
39486
|
-
}
|
|
39487
|
-
) })
|
|
39488
|
-
]
|
|
39665
|
+
const shown2 = raw === void 0 || raw === null || raw === "" ? "\u2014" : relationLabel(raw) ?? formatValue(raw, field.format);
|
|
39666
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "break-words", children: shown2 });
|
|
39667
|
+
}
|
|
39668
|
+
if (fieldDraft?.name === name) {
|
|
39669
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39670
|
+
Input,
|
|
39671
|
+
{
|
|
39672
|
+
value: fieldDraft.value,
|
|
39673
|
+
autoFocus: true,
|
|
39674
|
+
"aria-label": label,
|
|
39675
|
+
className: "h-8 w-full",
|
|
39676
|
+
onChange: (e) => setFieldDraft({ name, value: e.target.value }),
|
|
39677
|
+
onBlur: () => commitField(name, fieldDraft.value.trim(), raw),
|
|
39678
|
+
onKeyDown: (e) => {
|
|
39679
|
+
if (e.key === "Enter") {
|
|
39680
|
+
e.preventDefault();
|
|
39681
|
+
commitField(name, fieldDraft.value.trim(), raw);
|
|
39682
|
+
} else if (e.key === "Escape") {
|
|
39683
|
+
e.preventDefault();
|
|
39684
|
+
setFieldDraft(null);
|
|
39685
|
+
}
|
|
39686
|
+
},
|
|
39687
|
+
"data-testid": `document-property-input-${name}`
|
|
39688
|
+
}
|
|
39689
|
+
);
|
|
39690
|
+
}
|
|
39691
|
+
const shown = raw === void 0 || raw === null || raw === "" ? "\u2014" : relationLabel(raw) ?? formatValue(raw, field.format);
|
|
39692
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39693
|
+
Box,
|
|
39694
|
+
{
|
|
39695
|
+
role: "button",
|
|
39696
|
+
tabIndex: 0,
|
|
39697
|
+
className: cn(
|
|
39698
|
+
"cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
39699
|
+
(raw === void 0 || raw === null || raw === "") && "text-muted-foreground"
|
|
39700
|
+
),
|
|
39701
|
+
onClick: () => setFieldDraft({ name, value: raw !== void 0 && raw !== null ? String(raw) : "" }),
|
|
39702
|
+
onKeyDown: (e) => {
|
|
39703
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
39704
|
+
e.preventDefault();
|
|
39705
|
+
setFieldDraft({ name, value: raw !== void 0 && raw !== null ? String(raw) : "" });
|
|
39489
39706
|
}
|
|
39490
|
-
|
|
39707
|
+
},
|
|
39708
|
+
"data-testid": `document-property-${name}`,
|
|
39709
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "break-words", children: shown })
|
|
39491
39710
|
}
|
|
39492
|
-
|
|
39493
|
-
default:
|
|
39494
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39495
|
-
Editable,
|
|
39496
|
-
{
|
|
39497
|
-
tag: "p",
|
|
39498
|
-
value: block.content ?? "",
|
|
39499
|
-
readOnly,
|
|
39500
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.paragraph"),
|
|
39501
|
-
ariaLabel: t("richBlockEditor.aria.paragraphBlock"),
|
|
39502
|
-
className: "leading-7",
|
|
39503
|
-
onValueChange: setContent
|
|
39504
|
-
}
|
|
39505
|
-
);
|
|
39506
|
-
}
|
|
39711
|
+
);
|
|
39507
39712
|
};
|
|
39508
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
39509
|
-
|
|
39510
|
-
{
|
|
39511
|
-
|
|
39512
|
-
|
|
39513
|
-
|
|
39514
|
-
|
|
39515
|
-
|
|
39516
|
-
|
|
39517
|
-
|
|
39518
|
-
|
|
39519
|
-
|
|
39520
|
-
|
|
39521
|
-
|
|
39522
|
-
readOnly,
|
|
39523
|
-
onDelete,
|
|
39524
|
-
onDuplicate,
|
|
39525
|
-
onChangeType
|
|
39526
|
-
}
|
|
39527
|
-
) }),
|
|
39528
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "min-w-0 flex-1", children: renderBody() })
|
|
39529
|
-
]
|
|
39530
|
-
}
|
|
39531
|
-
);
|
|
39713
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { variant: "bordered", className: cn("w-full", className), children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", className: "p-4", children: [
|
|
39714
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", weight: "medium", className: "uppercase tracking-wide", children: title ?? (t("documentDetails.title") || "Details") }),
|
|
39715
|
+
/* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "sm", children: fieldDefs.map((field) => {
|
|
39716
|
+
const name = fieldName(field);
|
|
39717
|
+
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
39718
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
39719
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
39720
|
+
field.icon && renderIconInput5(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
39721
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "muted", children: label })
|
|
39722
|
+
] }),
|
|
39723
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "min-w-0", children: renderValue(field) })
|
|
39724
|
+
] }, name);
|
|
39725
|
+
}) })
|
|
39726
|
+
] }) });
|
|
39532
39727
|
}
|
|
39533
|
-
var
|
|
39534
|
-
|
|
39535
|
-
"components/core/molecules/RichBlockEditor.tsx"() {
|
|
39728
|
+
var init_DocumentDetails = __esm({
|
|
39729
|
+
"components/core/molecules/DocumentDetails.tsx"() {
|
|
39536
39730
|
"use client";
|
|
39537
39731
|
init_cn();
|
|
39538
|
-
|
|
39539
|
-
|
|
39540
|
-
|
|
39732
|
+
init_format();
|
|
39733
|
+
init_getNestedValue();
|
|
39734
|
+
init_useEventBus();
|
|
39541
39735
|
init_Box();
|
|
39542
|
-
|
|
39543
|
-
|
|
39736
|
+
init_Stack();
|
|
39737
|
+
init_Typography();
|
|
39738
|
+
init_Badge();
|
|
39739
|
+
init_Card();
|
|
39544
39740
|
init_Icon();
|
|
39545
|
-
|
|
39546
|
-
|
|
39547
|
-
|
|
39548
|
-
{ type: "heading-1", labelKey: "richBlockEditor.toolbar.h1", icon: LucideIcons2.Heading1 },
|
|
39549
|
-
{ type: "heading-2", labelKey: "richBlockEditor.toolbar.h2", icon: LucideIcons2.Heading2 },
|
|
39550
|
-
{ type: "heading-3", labelKey: "richBlockEditor.toolbar.h3", icon: LucideIcons2.Heading3 },
|
|
39551
|
-
{ type: "bullet-list", labelKey: "richBlockEditor.toolbar.bulletList", icon: LucideIcons2.List },
|
|
39552
|
-
{ type: "numbered-list", labelKey: "richBlockEditor.toolbar.numbered", icon: LucideIcons2.ListOrdered },
|
|
39553
|
-
{ type: "quote", labelKey: "richBlockEditor.toolbar.quote", icon: LucideIcons2.Quote },
|
|
39554
|
-
{ type: "code", labelKey: "richBlockEditor.toolbar.code", icon: LucideIcons2.Code },
|
|
39555
|
-
{ type: "divider", labelKey: "richBlockEditor.toolbar.divider", icon: LucideIcons2.Minus },
|
|
39556
|
-
{ type: "image", labelKey: "richBlockEditor.toolbar.image", icon: LucideIcons2.Image }
|
|
39557
|
-
];
|
|
39558
|
-
BLOCK_TYPE_LABEL_KEY = {
|
|
39559
|
-
paragraph: "richBlockEditor.blockType.paragraph",
|
|
39560
|
-
"heading-1": "richBlockEditor.blockType.heading1",
|
|
39561
|
-
"heading-2": "richBlockEditor.blockType.heading2",
|
|
39562
|
-
"heading-3": "richBlockEditor.blockType.heading3",
|
|
39563
|
-
"bullet-list": "richBlockEditor.blockType.bulletList",
|
|
39564
|
-
"numbered-list": "richBlockEditor.blockType.numberedList",
|
|
39565
|
-
quote: "richBlockEditor.blockType.quote",
|
|
39566
|
-
code: "richBlockEditor.blockType.code",
|
|
39567
|
-
divider: "richBlockEditor.blockType.divider",
|
|
39568
|
-
image: "richBlockEditor.blockType.image"
|
|
39569
|
-
};
|
|
39570
|
-
CHANGEABLE_TYPES = [
|
|
39571
|
-
"paragraph",
|
|
39572
|
-
"heading-1",
|
|
39573
|
-
"heading-2",
|
|
39574
|
-
"heading-3",
|
|
39575
|
-
"bullet-list",
|
|
39576
|
-
"numbered-list",
|
|
39577
|
-
"quote",
|
|
39578
|
-
"code"
|
|
39579
|
-
];
|
|
39580
|
-
_idSeq = 0;
|
|
39581
|
-
BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
39582
|
-
"paragraph",
|
|
39583
|
-
"heading-1",
|
|
39584
|
-
"heading-2",
|
|
39585
|
-
"heading-3",
|
|
39586
|
-
"bullet-list",
|
|
39587
|
-
"numbered-list",
|
|
39588
|
-
"quote",
|
|
39589
|
-
"code",
|
|
39590
|
-
"divider",
|
|
39591
|
-
"image"
|
|
39592
|
-
]);
|
|
39593
|
-
RichBlockEditor = ({
|
|
39594
|
-
initialBlocks,
|
|
39595
|
-
onChange,
|
|
39596
|
-
changeEvent,
|
|
39597
|
-
readOnly = false,
|
|
39598
|
-
placeholder,
|
|
39599
|
-
enableBlocks = true,
|
|
39600
|
-
showToolbar = true,
|
|
39601
|
-
className
|
|
39602
|
-
}) => {
|
|
39603
|
-
const { t } = hooks.useTranslate();
|
|
39604
|
-
const [blocks, setBlocks] = React94.useState(
|
|
39605
|
-
() => normalizeBlocks(initialBlocks)
|
|
39606
|
-
);
|
|
39607
|
-
const onChangeRef = React94.useRef(onChange);
|
|
39608
|
-
React94.useEffect(() => {
|
|
39609
|
-
onChangeRef.current = onChange;
|
|
39610
|
-
}, [onChange]);
|
|
39611
|
-
const eventBus = useEventBus();
|
|
39612
|
-
const changeEventRef = React94.useRef(changeEvent);
|
|
39613
|
-
React94.useEffect(() => {
|
|
39614
|
-
changeEventRef.current = changeEvent;
|
|
39615
|
-
}, [changeEvent]);
|
|
39616
|
-
const commit = React94.useCallback((next) => {
|
|
39617
|
-
setBlocks(next);
|
|
39618
|
-
onChangeRef.current?.(next);
|
|
39619
|
-
const evt = changeEventRef.current;
|
|
39620
|
-
if (evt) eventBus.emit(`UI:${evt}`, { blocks: next });
|
|
39621
|
-
}, [eventBus]);
|
|
39622
|
-
const handleAppend = React94.useCallback(
|
|
39623
|
-
(type) => {
|
|
39624
|
-
if (readOnly) return;
|
|
39625
|
-
commit([...blocks, createBlock(type)]);
|
|
39626
|
-
},
|
|
39627
|
-
[blocks, commit, readOnly]
|
|
39628
|
-
);
|
|
39629
|
-
const handleUpdate = React94.useCallback(
|
|
39630
|
-
(id, updater) => {
|
|
39631
|
-
commit(replaceBlock(blocks, id, updater));
|
|
39632
|
-
},
|
|
39633
|
-
[blocks, commit]
|
|
39634
|
-
);
|
|
39635
|
-
const handleDelete = React94.useCallback(
|
|
39636
|
-
(id) => {
|
|
39637
|
-
const next = removeBlock(blocks, id);
|
|
39638
|
-
commit(next.length > 0 ? next : [createBlock("paragraph")]);
|
|
39639
|
-
},
|
|
39640
|
-
[blocks, commit]
|
|
39641
|
-
);
|
|
39642
|
-
const handleDuplicate = React94.useCallback(
|
|
39643
|
-
(id) => {
|
|
39644
|
-
const target = blocks.find((b) => b.id === id);
|
|
39645
|
-
if (!target) return;
|
|
39646
|
-
commit(insertAfter(blocks, id, duplicateBlock(target)));
|
|
39647
|
-
},
|
|
39648
|
-
[blocks, commit]
|
|
39649
|
-
);
|
|
39650
|
-
const handleChangeType = React94.useCallback(
|
|
39651
|
-
(id, type) => {
|
|
39652
|
-
commit(
|
|
39653
|
-
replaceBlock(blocks, id, (b) => changeBlockType(b, type))
|
|
39654
|
-
);
|
|
39655
|
-
},
|
|
39656
|
-
[blocks, commit]
|
|
39657
|
-
);
|
|
39658
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
39659
|
-
Card,
|
|
39660
|
-
{
|
|
39661
|
-
variant: "bordered",
|
|
39662
|
-
padding: "none",
|
|
39663
|
-
className: cn("flex flex-col text-card-foreground", className),
|
|
39664
|
-
children: [
|
|
39665
|
-
enableBlocks && showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
39666
|
-
Box,
|
|
39667
|
-
{
|
|
39668
|
-
role: "toolbar",
|
|
39669
|
-
"aria-label": t("richBlockEditor.editorToolbar"),
|
|
39670
|
-
className: cn(
|
|
39671
|
-
"flex flex-wrap items-center gap-1",
|
|
39672
|
-
"border-b border-border bg-muted/30 px-2 py-2"
|
|
39673
|
-
),
|
|
39674
|
-
children: TOOLBAR_ENTRIES.map((entry) => {
|
|
39675
|
-
const Icon2 = entry.icon;
|
|
39676
|
-
const entryLabel = t(entry.labelKey);
|
|
39677
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
39678
|
-
Button,
|
|
39679
|
-
{
|
|
39680
|
-
type: "button",
|
|
39681
|
-
variant: "ghost",
|
|
39682
|
-
size: "sm",
|
|
39683
|
-
"aria-label": t("richBlockEditor.insertEntry", { label: entryLabel }),
|
|
39684
|
-
title: entryLabel,
|
|
39685
|
-
onClick: () => handleAppend(entry.type),
|
|
39686
|
-
children: [
|
|
39687
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon2, { size: 14 }),
|
|
39688
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", variant: "caption", className: "ml-1 hidden text-xs sm:inline", children: entryLabel })
|
|
39689
|
-
]
|
|
39690
|
-
},
|
|
39691
|
-
entry.type
|
|
39692
|
-
);
|
|
39693
|
-
})
|
|
39694
|
-
}
|
|
39695
|
-
),
|
|
39696
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-1 px-3 py-3", children: blocks.map((block) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
39697
|
-
BlockRow,
|
|
39698
|
-
{
|
|
39699
|
-
block,
|
|
39700
|
-
readOnly,
|
|
39701
|
-
showAffordances: enableBlocks,
|
|
39702
|
-
placeholder,
|
|
39703
|
-
onUpdate: (updater) => handleUpdate(block.id, updater),
|
|
39704
|
-
onDelete: () => handleDelete(block.id),
|
|
39705
|
-
onDuplicate: () => handleDuplicate(block.id),
|
|
39706
|
-
onChangeType: (type) => handleChangeType(block.id, type)
|
|
39707
|
-
},
|
|
39708
|
-
block.id
|
|
39709
|
-
)) })
|
|
39710
|
-
]
|
|
39711
|
-
}
|
|
39712
|
-
);
|
|
39713
|
-
};
|
|
39714
|
-
RichBlockEditor.displayName = "RichBlockEditor";
|
|
39741
|
+
init_Input();
|
|
39742
|
+
init_Select();
|
|
39743
|
+
init_Switch();
|
|
39715
39744
|
}
|
|
39716
39745
|
});
|
|
39717
39746
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
@@ -44251,8 +44280,8 @@ var init_DataTable = __esm({
|
|
|
44251
44280
|
DataTable.displayName = "DataTable";
|
|
44252
44281
|
}
|
|
44253
44282
|
});
|
|
44254
|
-
function getBadgeVariant(
|
|
44255
|
-
const name =
|
|
44283
|
+
function getBadgeVariant(fieldName2, value) {
|
|
44284
|
+
const name = fieldName2.toLowerCase();
|
|
44256
44285
|
const val = String(value).toLowerCase();
|
|
44257
44286
|
if (name.includes("status")) {
|
|
44258
44287
|
if (val.includes("complete") || val.includes("done") || val.includes("active"))
|
|
@@ -44268,12 +44297,12 @@ function getBadgeVariant(fieldName, value) {
|
|
|
44268
44297
|
}
|
|
44269
44298
|
return "default";
|
|
44270
44299
|
}
|
|
44271
|
-
function formatFieldValue2(value,
|
|
44300
|
+
function formatFieldValue2(value, fieldName2) {
|
|
44272
44301
|
if (typeof value === "number") {
|
|
44273
|
-
if (
|
|
44302
|
+
if (fieldName2.toLowerCase().includes("progress") || fieldName2.toLowerCase().includes("percent")) {
|
|
44274
44303
|
return `${value}%`;
|
|
44275
44304
|
}
|
|
44276
|
-
if (
|
|
44305
|
+
if (fieldName2.toLowerCase().includes("budget") || fieldName2.toLowerCase().includes("cost")) {
|
|
44277
44306
|
return `$${value.toLocaleString()}`;
|
|
44278
44307
|
}
|
|
44279
44308
|
return value.toLocaleString();
|
|
@@ -44283,7 +44312,7 @@ function formatFieldValue2(value, fieldName) {
|
|
|
44283
44312
|
}
|
|
44284
44313
|
return String(value);
|
|
44285
44314
|
}
|
|
44286
|
-
function renderRichFieldValue(value,
|
|
44315
|
+
function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
44287
44316
|
if (value === void 0 || value === null) return "\u2014";
|
|
44288
44317
|
const str = String(value);
|
|
44289
44318
|
switch (fieldType) {
|
|
@@ -44294,7 +44323,7 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
|
|
|
44294
44323
|
"img",
|
|
44295
44324
|
{
|
|
44296
44325
|
src: str,
|
|
44297
|
-
alt: formatFieldLabel(
|
|
44326
|
+
alt: formatFieldLabel(fieldName2),
|
|
44298
44327
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
44299
44328
|
loading: "lazy"
|
|
44300
44329
|
}
|
|
@@ -44429,9 +44458,9 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
|
|
|
44429
44458
|
return /* @__PURE__ */ jsxRuntime.jsx("a", { href: `tel:${str}`, className: "text-primary hover:underline", children: str });
|
|
44430
44459
|
default:
|
|
44431
44460
|
if (meta?.values && meta.values.length > 0 && meta.values.includes(str)) {
|
|
44432
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: getBadgeVariant(
|
|
44461
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: getBadgeVariant(fieldName2, str), children: humanizeEnumValue(str) });
|
|
44433
44462
|
}
|
|
44434
|
-
return formatFieldValue2(value,
|
|
44463
|
+
return formatFieldValue2(value, fieldName2);
|
|
44435
44464
|
}
|
|
44436
44465
|
}
|
|
44437
44466
|
function normalizeFieldDefs(fields) {
|
|
@@ -44901,16 +44930,11 @@ var init_DetailPanel = __esm({
|
|
|
44901
44930
|
footer
|
|
44902
44931
|
] })
|
|
44903
44932
|
] }) });
|
|
44904
|
-
|
|
44905
|
-
Box,
|
|
44906
|
-
|
|
44907
|
-
|
|
44908
|
-
|
|
44909
|
-
className
|
|
44910
|
-
),
|
|
44911
|
-
children: content
|
|
44912
|
-
}
|
|
44913
|
-
);
|
|
44933
|
+
if (!slideOver) {
|
|
44934
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className, children: content });
|
|
44935
|
+
}
|
|
44936
|
+
const panel = /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("fixed inset-y-0 right-0 w-full max-w-2xl bg-card shadow-lg z-50 overflow-y-auto p-6", className), children: content });
|
|
44937
|
+
return typeof document === "undefined" ? panel : reactDom.createPortal(panel, document.body);
|
|
44914
44938
|
};
|
|
44915
44939
|
DetailPanel.displayName = "DetailPanel";
|
|
44916
44940
|
}
|
|
@@ -45279,7 +45303,21 @@ var init_Form = __esm({
|
|
|
45279
45303
|
const normalizedInitialData = React94__namespace.default.useMemo(() => {
|
|
45280
45304
|
const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
|
|
45281
45305
|
const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
|
|
45282
|
-
|
|
45306
|
+
const merged = entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
|
|
45307
|
+
const toId = (value) => {
|
|
45308
|
+
if (value === null || value === void 0 || typeof value !== "object" || value instanceof Date) return value;
|
|
45309
|
+
if (Array.isArray(value)) {
|
|
45310
|
+
return value.map(
|
|
45311
|
+
(item) => item !== null && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && item.id !== void 0 && item.id !== null ? String(item.id) : item
|
|
45312
|
+
);
|
|
45313
|
+
}
|
|
45314
|
+
return value.id !== void 0 && value.id !== null ? String(value.id) : value;
|
|
45315
|
+
};
|
|
45316
|
+
const normalized = {};
|
|
45317
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
45318
|
+
normalized[key] = key === "id" ? value : toId(value);
|
|
45319
|
+
}
|
|
45320
|
+
return normalized;
|
|
45283
45321
|
}, [entity, initialData]);
|
|
45284
45322
|
const entityDerivedFields = React94__namespace.default.useMemo(() => {
|
|
45285
45323
|
if (fields && fields.length > 0) return void 0;
|
|
@@ -45408,8 +45446,8 @@ var init_Form = __esm({
|
|
|
45408
45446
|
checkViolations(name, newFormData);
|
|
45409
45447
|
};
|
|
45410
45448
|
const isFieldVisible = React94__namespace.default.useCallback(
|
|
45411
|
-
(
|
|
45412
|
-
const condition = conditionalFields[
|
|
45449
|
+
(fieldName2) => {
|
|
45450
|
+
const condition = conditionalFields[fieldName2];
|
|
45413
45451
|
if (!condition) return true;
|
|
45414
45452
|
return Boolean(evaluateFormExpression(condition, evalContext));
|
|
45415
45453
|
},
|
|
@@ -45455,9 +45493,9 @@ var init_Form = __esm({
|
|
|
45455
45493
|
};
|
|
45456
45494
|
const handleInvalid = (e) => {
|
|
45457
45495
|
const target = e.target;
|
|
45458
|
-
const
|
|
45496
|
+
const fieldName2 = target.getAttribute("data-field-name") ?? target.name ?? "";
|
|
45459
45497
|
const fieldMessage = target.validationMessage || "Invalid value";
|
|
45460
|
-
debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
|
|
45498
|
+
debug("forms", "invalid", { mode: formMode, fieldName: fieldName2, fieldMessage });
|
|
45461
45499
|
queueMicrotask(() => {
|
|
45462
45500
|
const form = formRef.current;
|
|
45463
45501
|
if (!form) return;
|
|
@@ -45493,22 +45531,22 @@ var init_Form = __esm({
|
|
|
45493
45531
|
};
|
|
45494
45532
|
const renderField = React94__namespace.default.useCallback(
|
|
45495
45533
|
(field) => {
|
|
45496
|
-
const
|
|
45497
|
-
if (!
|
|
45498
|
-
if (!isFieldVisible(
|
|
45534
|
+
const fieldName2 = field.name || field.field;
|
|
45535
|
+
if (!fieldName2) return null;
|
|
45536
|
+
if (!isFieldVisible(fieldName2)) {
|
|
45499
45537
|
return null;
|
|
45500
45538
|
}
|
|
45501
45539
|
const inputType = determineInputType(field);
|
|
45502
|
-
const label = field.label ||
|
|
45503
|
-
const currentValue = formData[
|
|
45504
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", "data-field":
|
|
45540
|
+
const label = field.label || fieldName2.charAt(0).toUpperCase() + fieldName2.slice(1).replace(/([A-Z])/g, " $1");
|
|
45541
|
+
const currentValue = formData[fieldName2] ?? field.defaultValue ?? "";
|
|
45542
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", "data-field": fieldName2, children: [
|
|
45505
45543
|
inputType !== "checkbox" && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "label", variant: "label", weight: "bold", children: [
|
|
45506
45544
|
label,
|
|
45507
45545
|
field.required && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", color: "error", className: "ml-1", children: "*" })
|
|
45508
45546
|
] }),
|
|
45509
|
-
renderFieldInput(field,
|
|
45547
|
+
renderFieldInput(field, fieldName2, inputType, currentValue, label),
|
|
45510
45548
|
field.hint && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "muted", children: field.hint })
|
|
45511
|
-
] },
|
|
45549
|
+
] }, fieldName2);
|
|
45512
45550
|
},
|
|
45513
45551
|
[formData, isFieldVisible, relationsData, relationsLoading, isLoading]
|
|
45514
45552
|
);
|
|
@@ -45537,8 +45575,8 @@ var init_Form = __esm({
|
|
|
45537
45575
|
}
|
|
45538
45576
|
return field;
|
|
45539
45577
|
}).map((field) => {
|
|
45540
|
-
const
|
|
45541
|
-
const override = fieldOverrides?.find((o) => o.name ===
|
|
45578
|
+
const fieldName2 = field.name || field.field;
|
|
45579
|
+
const override = fieldOverrides?.find((o) => o.name === fieldName2);
|
|
45542
45580
|
if (!override) return field;
|
|
45543
45581
|
return {
|
|
45544
45582
|
...field,
|
|
@@ -45594,11 +45632,11 @@ var init_Form = __esm({
|
|
|
45594
45632
|
] }, section.id);
|
|
45595
45633
|
}).filter(Boolean);
|
|
45596
45634
|
}, [sections, isSectionVisible, collapsedSections, renderField, gap]);
|
|
45597
|
-
function renderFieldInput(field,
|
|
45635
|
+
function renderFieldInput(field, fieldName2, inputType, currentValue, label) {
|
|
45598
45636
|
const commonProps = {
|
|
45599
|
-
id:
|
|
45600
|
-
name:
|
|
45601
|
-
"data-field-name":
|
|
45637
|
+
id: fieldName2,
|
|
45638
|
+
name: fieldName2,
|
|
45639
|
+
"data-field-name": fieldName2,
|
|
45602
45640
|
required: field.required,
|
|
45603
45641
|
disabled: isLoading,
|
|
45604
45642
|
placeholder: field.placeholder,
|
|
@@ -45612,7 +45650,7 @@ var init_Form = __esm({
|
|
|
45612
45650
|
...commonProps,
|
|
45613
45651
|
label: label + (field.required ? " *" : ""),
|
|
45614
45652
|
checked: Boolean(currentValue),
|
|
45615
|
-
onChange: (e) => handleChange(
|
|
45653
|
+
onChange: (e) => handleChange(fieldName2, e.target.checked)
|
|
45616
45654
|
}
|
|
45617
45655
|
);
|
|
45618
45656
|
case "textarea":
|
|
@@ -45621,7 +45659,7 @@ var init_Form = __esm({
|
|
|
45621
45659
|
{
|
|
45622
45660
|
...commonProps,
|
|
45623
45661
|
value: String(currentValue),
|
|
45624
|
-
onChange: (e) => handleChange(
|
|
45662
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
45625
45663
|
minLength: field.min,
|
|
45626
45664
|
maxLength: field.max
|
|
45627
45665
|
}
|
|
@@ -45634,14 +45672,14 @@ var init_Form = __esm({
|
|
|
45634
45672
|
...commonProps,
|
|
45635
45673
|
options,
|
|
45636
45674
|
value: String(currentValue),
|
|
45637
|
-
onValueChange: (v) => handleChange(
|
|
45675
|
+
onValueChange: (v) => handleChange(fieldName2, v),
|
|
45638
45676
|
placeholder: field.placeholder || `Select ${label}...`
|
|
45639
45677
|
}
|
|
45640
45678
|
);
|
|
45641
45679
|
}
|
|
45642
45680
|
case "relation": {
|
|
45643
|
-
const relationOptions = relationsData[
|
|
45644
|
-
const relationLoading = relationsLoading[
|
|
45681
|
+
const relationOptions = relationsData[fieldName2] || [];
|
|
45682
|
+
const relationLoading = relationsLoading[fieldName2] || false;
|
|
45645
45683
|
if (field.relation?.cardinality !== void 0 && MANY_CARDINALITIES.includes(field.relation.cardinality)) {
|
|
45646
45684
|
const selectedValues = Array.isArray(currentValue) ? currentValue.map((v) => String(v)) : [];
|
|
45647
45685
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -45653,7 +45691,7 @@ var init_Form = __esm({
|
|
|
45653
45691
|
clearable: true,
|
|
45654
45692
|
options: [...relationOptions],
|
|
45655
45693
|
value: selectedValues,
|
|
45656
|
-
onValueChange: (value) => handleChange(
|
|
45694
|
+
onValueChange: (value) => handleChange(fieldName2, Array.isArray(value) ? value : [value]),
|
|
45657
45695
|
placeholder: field.placeholder || `Select ${label}...`
|
|
45658
45696
|
}
|
|
45659
45697
|
);
|
|
@@ -45663,7 +45701,7 @@ var init_Form = __esm({
|
|
|
45663
45701
|
{
|
|
45664
45702
|
...commonProps,
|
|
45665
45703
|
value: currentValue ? String(currentValue) : void 0,
|
|
45666
|
-
onChange: (value) => handleChange(
|
|
45704
|
+
onChange: (value) => handleChange(fieldName2, value),
|
|
45667
45705
|
options: relationOptions,
|
|
45668
45706
|
isLoading: relationLoading,
|
|
45669
45707
|
placeholder: field.placeholder || `Select ${label}...`,
|
|
@@ -45680,7 +45718,7 @@ var init_Form = __esm({
|
|
|
45680
45718
|
placeholder: field.placeholder,
|
|
45681
45719
|
disabled: isLoading,
|
|
45682
45720
|
value: arrayValue,
|
|
45683
|
-
onChange: (next) => handleChange(
|
|
45721
|
+
onChange: (next) => handleChange(fieldName2, [...next])
|
|
45684
45722
|
}
|
|
45685
45723
|
);
|
|
45686
45724
|
}
|
|
@@ -45692,7 +45730,7 @@ var init_Form = __esm({
|
|
|
45692
45730
|
type: "number",
|
|
45693
45731
|
value: currentValue !== void 0 && currentValue !== "" ? String(currentValue) : "",
|
|
45694
45732
|
onChange: (e) => handleChange(
|
|
45695
|
-
|
|
45733
|
+
fieldName2,
|
|
45696
45734
|
e.target.value ? Number(e.target.value) : void 0
|
|
45697
45735
|
),
|
|
45698
45736
|
min: field.min,
|
|
@@ -45709,7 +45747,7 @@ var init_Form = __esm({
|
|
|
45709
45747
|
icon: LucideIcons2.DollarSign,
|
|
45710
45748
|
value: currentValue !== void 0 && currentValue !== "" ? String(currentValue) : "",
|
|
45711
45749
|
onChange: (e) => handleChange(
|
|
45712
|
-
|
|
45750
|
+
fieldName2,
|
|
45713
45751
|
e.target.value ? Number(e.target.value) : void 0
|
|
45714
45752
|
),
|
|
45715
45753
|
min: field.min,
|
|
@@ -45727,7 +45765,7 @@ var init_Form = __esm({
|
|
|
45727
45765
|
const f3 = files[0];
|
|
45728
45766
|
if (!f3) return;
|
|
45729
45767
|
const reader = new FileReader();
|
|
45730
|
-
reader.onload = () => handleChange(
|
|
45768
|
+
reader.onload = () => handleChange(fieldName2, {
|
|
45731
45769
|
name: f3.name,
|
|
45732
45770
|
mimeType: f3.type,
|
|
45733
45771
|
sizeBytes: f3.size,
|
|
@@ -45744,7 +45782,7 @@ var init_Form = __esm({
|
|
|
45744
45782
|
...commonProps,
|
|
45745
45783
|
type: "date",
|
|
45746
45784
|
value: formatDateValue(currentValue),
|
|
45747
|
-
onChange: (e) => handleChange(
|
|
45785
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
45748
45786
|
}
|
|
45749
45787
|
);
|
|
45750
45788
|
case "datetime-local":
|
|
@@ -45754,7 +45792,7 @@ var init_Form = __esm({
|
|
|
45754
45792
|
...commonProps,
|
|
45755
45793
|
type: "datetime-local",
|
|
45756
45794
|
value: formatDateTimeValue(currentValue),
|
|
45757
|
-
onChange: (e) => handleChange(
|
|
45795
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
45758
45796
|
}
|
|
45759
45797
|
);
|
|
45760
45798
|
case "email":
|
|
@@ -45764,7 +45802,7 @@ var init_Form = __esm({
|
|
|
45764
45802
|
...commonProps,
|
|
45765
45803
|
type: "email",
|
|
45766
45804
|
value: String(currentValue),
|
|
45767
|
-
onChange: (e) => handleChange(
|
|
45805
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
45768
45806
|
minLength: field.min,
|
|
45769
45807
|
maxLength: field.max
|
|
45770
45808
|
}
|
|
@@ -45776,7 +45814,7 @@ var init_Form = __esm({
|
|
|
45776
45814
|
...commonProps,
|
|
45777
45815
|
type: "url",
|
|
45778
45816
|
value: String(currentValue),
|
|
45779
|
-
onChange: (e) => handleChange(
|
|
45817
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
45780
45818
|
minLength: field.min,
|
|
45781
45819
|
maxLength: field.max
|
|
45782
45820
|
}
|
|
@@ -45788,7 +45826,7 @@ var init_Form = __esm({
|
|
|
45788
45826
|
...commonProps,
|
|
45789
45827
|
type: "password",
|
|
45790
45828
|
value: String(currentValue),
|
|
45791
|
-
onChange: (e) => handleChange(
|
|
45829
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
45792
45830
|
minLength: field.min,
|
|
45793
45831
|
maxLength: field.max
|
|
45794
45832
|
}
|
|
@@ -45801,7 +45839,7 @@ var init_Form = __esm({
|
|
|
45801
45839
|
...commonProps,
|
|
45802
45840
|
type: "text",
|
|
45803
45841
|
value: String(currentValue),
|
|
45804
|
-
onChange: (e) => handleChange(
|
|
45842
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
45805
45843
|
minLength: field.min,
|
|
45806
45844
|
maxLength: field.max
|
|
45807
45845
|
}
|
|
@@ -46158,7 +46196,7 @@ function entityFieldsFromListItem(item) {
|
|
|
46158
46196
|
}
|
|
46159
46197
|
return result;
|
|
46160
46198
|
}
|
|
46161
|
-
function getStatusStyle(
|
|
46199
|
+
function getStatusStyle(fieldName2, value) {
|
|
46162
46200
|
const val = String(value).toLowerCase();
|
|
46163
46201
|
if (val.includes("complete") || val.includes("done"))
|
|
46164
46202
|
return STATUS_STYLES.complete;
|
|
@@ -46174,12 +46212,12 @@ function getStatusStyle(fieldName, value) {
|
|
|
46174
46212
|
if (val.includes("low")) return STATUS_STYLES.low;
|
|
46175
46213
|
return STATUS_STYLES.default;
|
|
46176
46214
|
}
|
|
46177
|
-
function formatValue3(value,
|
|
46215
|
+
function formatValue3(value, fieldName2) {
|
|
46178
46216
|
if (typeof value === "number") {
|
|
46179
|
-
if (
|
|
46217
|
+
if (fieldName2.toLowerCase().includes("progress") || fieldName2.toLowerCase().includes("percent")) {
|
|
46180
46218
|
return `${value}%`;
|
|
46181
46219
|
}
|
|
46182
|
-
if (
|
|
46220
|
+
if (fieldName2.toLowerCase().includes("budget") || fieldName2.toLowerCase().includes("cost")) {
|
|
46183
46221
|
return new Intl.NumberFormat("en-US", {
|
|
46184
46222
|
style: "currency",
|
|
46185
46223
|
currency: "USD",
|
|
@@ -46202,8 +46240,8 @@ function formatValue3(value, fieldName) {
|
|
|
46202
46240
|
}
|
|
46203
46241
|
return String(value);
|
|
46204
46242
|
}
|
|
46205
|
-
function formatFieldLabel2(
|
|
46206
|
-
return humanizeFieldName(
|
|
46243
|
+
function formatFieldLabel2(fieldName2) {
|
|
46244
|
+
return humanizeFieldName(fieldName2).replace(/\sId$/, "").trim();
|
|
46207
46245
|
}
|
|
46208
46246
|
var STATUS_STYLES, StatusBadge, ProgressIndicator, List3;
|
|
46209
46247
|
var init_List = __esm({
|
|
@@ -46271,9 +46309,9 @@ var init_List = __esm({
|
|
|
46271
46309
|
};
|
|
46272
46310
|
StatusBadge = ({
|
|
46273
46311
|
value,
|
|
46274
|
-
fieldName
|
|
46312
|
+
fieldName: fieldName2
|
|
46275
46313
|
}) => {
|
|
46276
|
-
const style = getStatusStyle(
|
|
46314
|
+
const style = getStatusStyle(fieldName2, value);
|
|
46277
46315
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
46278
46316
|
Typography,
|
|
46279
46317
|
{
|
|
@@ -49205,8 +49243,8 @@ var init_StatCard = __esm({
|
|
|
49205
49243
|
return items.length;
|
|
49206
49244
|
}
|
|
49207
49245
|
if (field.includes(":")) {
|
|
49208
|
-
const [
|
|
49209
|
-
return items.filter((item) => item[
|
|
49246
|
+
const [fieldName2, fieldValue] = field.split(":");
|
|
49247
|
+
return items.filter((item) => item[fieldName2] === fieldValue).length;
|
|
49210
49248
|
}
|
|
49211
49249
|
const fieldExistsOnItems = items.some((item) => field in item);
|
|
49212
49250
|
if (fieldExistsOnItems) {
|
|
@@ -50726,6 +50764,8 @@ var init_component_registry_generated = __esm({
|
|
|
50726
50764
|
init_DocSearch();
|
|
50727
50765
|
init_DocSidebar();
|
|
50728
50766
|
init_DocTOC();
|
|
50767
|
+
init_DocumentDetails();
|
|
50768
|
+
init_DocumentPanel();
|
|
50729
50769
|
init_DocumentViewer();
|
|
50730
50770
|
init_DrawFxLayer();
|
|
50731
50771
|
init_DrawGroup();
|
|
@@ -50835,7 +50875,7 @@ var init_component_registry_generated = __esm({
|
|
|
50835
50875
|
init_RelationSelect();
|
|
50836
50876
|
init_RepeatableFormSection();
|
|
50837
50877
|
init_ReplyTree();
|
|
50838
|
-
|
|
50878
|
+
init_RichTextEditor();
|
|
50839
50879
|
init_RuntimeDebugger2();
|
|
50840
50880
|
init_ScaledDiagram();
|
|
50841
50881
|
init_ScoreDisplay();
|
|
@@ -50998,6 +51038,8 @@ var init_component_registry_generated = __esm({
|
|
|
50998
51038
|
"DocSearch": DocSearch,
|
|
50999
51039
|
"DocSidebar": DocSidebar,
|
|
51000
51040
|
"DocTOC": DocTOC,
|
|
51041
|
+
"DocumentDetails": DocumentDetails,
|
|
51042
|
+
"DocumentPanel": DocumentPanel,
|
|
51001
51043
|
"DocumentViewer": DocumentViewer,
|
|
51002
51044
|
"DrawFxLayer": DrawFxLayer,
|
|
51003
51045
|
"DrawGroup": DrawGroup,
|
|
@@ -51109,7 +51151,7 @@ var init_component_registry_generated = __esm({
|
|
|
51109
51151
|
"RelationSelect": RelationSelect,
|
|
51110
51152
|
"RepeatableFormSection": RepeatableFormSection,
|
|
51111
51153
|
"ReplyTree": ReplyTree,
|
|
51112
|
-
"
|
|
51154
|
+
"RichTextEditor": RichTextEditor,
|
|
51113
51155
|
"RuntimeDebugger": RuntimeDebugger,
|
|
51114
51156
|
"ScaledDiagram": ScaledDiagram,
|
|
51115
51157
|
"ScoreDisplay": ScoreDisplay,
|
|
@@ -51263,10 +51305,10 @@ function enrichFormFields(fields, entityDef) {
|
|
|
51263
51305
|
}
|
|
51264
51306
|
if (field && typeof field === "object" && !Array.isArray(field) && !React94__namespace.default.isValidElement(field) && !(field instanceof Date)) {
|
|
51265
51307
|
const obj = field;
|
|
51266
|
-
const
|
|
51267
|
-
if (!
|
|
51308
|
+
const fieldName2 = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
|
|
51309
|
+
if (!fieldName2) return field;
|
|
51268
51310
|
if (obj.type || obj.inputType) return field;
|
|
51269
|
-
const entityField = fieldMap.get(
|
|
51311
|
+
const entityField = fieldMap.get(fieldName2);
|
|
51270
51312
|
if (!entityField) return field;
|
|
51271
51313
|
const enriched = { ...obj, type: entityField.type };
|
|
51272
51314
|
if (entityField.required && !("required" in obj)) {
|
|
@@ -51316,9 +51358,9 @@ function enrichDetailFields(fields, entityDef) {
|
|
|
51316
51358
|
}
|
|
51317
51359
|
if (field && typeof field === "object" && !Array.isArray(field) && !React94__namespace.default.isValidElement(field) && !(field instanceof Date)) {
|
|
51318
51360
|
const obj = field;
|
|
51319
|
-
const
|
|
51320
|
-
if (!
|
|
51321
|
-
const meta = metaFor(
|
|
51361
|
+
const fieldName2 = typeof obj.key === "string" ? obj.key : typeof obj.name === "string" ? obj.name : void 0;
|
|
51362
|
+
if (!fieldName2 || obj.type) return field;
|
|
51363
|
+
const meta = metaFor(fieldName2);
|
|
51322
51364
|
return meta ? { ...obj, ...meta } : field;
|
|
51323
51365
|
}
|
|
51324
51366
|
return field;
|
|
@@ -52157,9 +52199,9 @@ function UISlotRenderer({
|
|
|
52157
52199
|
"ui-slot-renderer relative min-h-full",
|
|
52158
52200
|
className
|
|
52159
52201
|
), children: [
|
|
52160
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex min-h-full", children: [
|
|
52161
|
-
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "sidebar", className: "ui-slot-sidebar min-w-0 shrink-0" }),
|
|
52162
|
-
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "main", className: "ui-slot-main flex-1 min-h-[200px]" })
|
|
52202
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex min-h-full flex-col lg:flex-row", children: [
|
|
52203
|
+
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "sidebar", className: "ui-slot-sidebar min-w-0 lg:shrink-0" }),
|
|
52204
|
+
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "main", className: "ui-slot-main flex-1 min-w-0 min-h-[200px]" })
|
|
52163
52205
|
] }),
|
|
52164
52206
|
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "modal", portal: true }),
|
|
52165
52207
|
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "drawer", portal: true }),
|
|
@@ -56056,7 +56098,7 @@ function buildTraitRenderConfig(binding, traitConfigsByName, payload) {
|
|
|
56056
56098
|
}
|
|
56057
56099
|
return void 0;
|
|
56058
56100
|
}
|
|
56059
|
-
function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
|
|
56101
|
+
function createSharedEntityWriter(binding, tick, traitStatesRef, emit, traitConfigsByName) {
|
|
56060
56102
|
return (scratch) => {
|
|
56061
56103
|
const traitName = binding.trait.name;
|
|
56062
56104
|
const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
|
|
@@ -56065,9 +56107,13 @@ function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
|
|
|
56065
56107
|
const writes = [];
|
|
56066
56108
|
const ctx = evaluator.createMinimalContext(scratchEntity, {}, currentState);
|
|
56067
56109
|
const declaredDefaults = runtime.collectDeclaredConfigDefaults(binding.trait);
|
|
56068
|
-
const
|
|
56069
|
-
|
|
56070
|
-
|
|
56110
|
+
const resolvedByName = traitConfigsByName?.[traitName];
|
|
56111
|
+
const callSiteRaw = getBindingConfig(binding);
|
|
56112
|
+
const callSiteConfig = callSiteRaw ? Object.fromEntries(
|
|
56113
|
+
Object.entries(callSiteRaw).filter(([, v]) => !containsConfigForward(v))
|
|
56114
|
+
) : void 0;
|
|
56115
|
+
if (declaredDefaults || resolvedByName || callSiteConfig) {
|
|
56116
|
+
ctx.config = { ...declaredDefaults ?? {}, ...resolvedByName ?? {}, ...callSiteConfig ?? {} };
|
|
56071
56117
|
}
|
|
56072
56118
|
ctx.mutateEntity = (changes) => {
|
|
56073
56119
|
for (const [field, value] of Object.entries(changes)) {
|
|
@@ -56670,7 +56716,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56670
56716
|
const interval = entries[0].tick.interval;
|
|
56671
56717
|
const onDue = timedTick(`tick:shared:${group.storeKey}@${String(interval)}`, () => {
|
|
56672
56718
|
const writers = entries.map(
|
|
56673
|
-
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
|
|
56719
|
+
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter, traitConfigsByName)
|
|
56674
56720
|
);
|
|
56675
56721
|
runTickFrame(group.storeKey, writers, sharedEntityStore);
|
|
56676
56722
|
});
|
|
@@ -59183,11 +59229,11 @@ function OrbInspector({ node, schema, editable = false, userType = "builder", th
|
|
|
59183
59229
|
const handleAddField = React94.useCallback(() => {
|
|
59184
59230
|
eventBus.emit("UI:ADD_FIELD", {});
|
|
59185
59231
|
}, [eventBus]);
|
|
59186
|
-
const handleUpdateField = React94.useCallback((
|
|
59187
|
-
eventBus.emit("UI:UPDATE_FIELD", { fieldName, updates });
|
|
59232
|
+
const handleUpdateField = React94.useCallback((fieldName2, updates) => {
|
|
59233
|
+
eventBus.emit("UI:UPDATE_FIELD", { fieldName: fieldName2, updates });
|
|
59188
59234
|
}, [eventBus]);
|
|
59189
|
-
const handleRemoveField = React94.useCallback((
|
|
59190
|
-
eventBus.emit("UI:REMOVE_FIELD", { fieldName });
|
|
59235
|
+
const handleRemoveField = React94.useCallback((fieldName2) => {
|
|
59236
|
+
eventBus.emit("UI:REMOVE_FIELD", { fieldName: fieldName2 });
|
|
59191
59237
|
}, [eventBus]);
|
|
59192
59238
|
const handleGuardChange = React94.useCallback((guardExpr) => {
|
|
59193
59239
|
if (!editable) return;
|