@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/runtime/index.cjs
CHANGED
|
@@ -25903,8 +25903,9 @@ function DataGrid({
|
|
|
25903
25903
|
const titleField = fieldDefs.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fieldDefs[0];
|
|
25904
25904
|
const badgeFields = fieldDefs.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
25905
25905
|
const bodyFields = fieldDefs.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
|
|
25906
|
-
const
|
|
25907
|
-
const
|
|
25906
|
+
const inlineCap = Math.min(maxInlineActions ?? 1, 1);
|
|
25907
|
+
const inlineCardActions = actionDefs.filter((a) => a.variant === "primary").slice(0, inlineCap);
|
|
25908
|
+
const menuCardActions = actionDefs.filter((a) => !inlineCardActions.includes(a));
|
|
25908
25909
|
const fireAction = (action, itemData) => {
|
|
25909
25910
|
if (action.navigatesTo) {
|
|
25910
25911
|
const url = action.navigatesTo.replace(
|
|
@@ -25924,6 +25925,9 @@ function DataGrid({
|
|
|
25924
25925
|
e.stopPropagation();
|
|
25925
25926
|
fireAction(action, itemData);
|
|
25926
25927
|
};
|
|
25928
|
+
const cardClickAction = actionDefs.find((a) => a.variant !== "danger");
|
|
25929
|
+
const handleCardClick = cardClickAction ? (itemData) => () => fireAction(cardClickAction, itemData) : void 0;
|
|
25930
|
+
const stopCardClick = handleCardClick ? (e) => e.stopPropagation() : void 0;
|
|
25927
25931
|
const hasRenderProp = typeof children === "function";
|
|
25928
25932
|
React85.useEffect(() => {
|
|
25929
25933
|
if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
|
|
@@ -25995,55 +25999,40 @@ function DataGrid({
|
|
|
25995
25999
|
{
|
|
25996
26000
|
"data-entity-row": true,
|
|
25997
26001
|
"data-entity-id": id,
|
|
25998
|
-
|
|
26002
|
+
onClick: handleCardClick?.(itemData),
|
|
26003
|
+
className: cn("relative group/rowactions", handleCardClick && "cursor-pointer", isSelected && "ring-2 ring-primary rounded-lg"),
|
|
25999
26004
|
children: [
|
|
26000
26005
|
children(itemData, index),
|
|
26001
|
-
actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.
|
|
26002
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
26003
|
-
|
|
26004
|
-
|
|
26005
|
-
|
|
26006
|
-
|
|
26007
|
-
|
|
26008
|
-
|
|
26009
|
-
|
|
26010
|
-
|
|
26011
|
-
|
|
26012
|
-
|
|
26013
|
-
|
|
26014
|
-
|
|
26015
|
-
|
|
26016
|
-
|
|
26017
|
-
|
|
26018
|
-
)),
|
|
26019
|
-
maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
|
|
26020
|
-
Menu,
|
|
26021
|
-
{
|
|
26022
|
-
position: "bottom-end",
|
|
26023
|
-
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" }) }),
|
|
26024
|
-
items: actionDefs.slice(maxInlineActions).map((action) => ({
|
|
26025
|
-
label: action.label,
|
|
26026
|
-
icon: action.icon,
|
|
26027
|
-
event: action.event,
|
|
26028
|
-
onClick: () => fireAction(action, itemData)
|
|
26029
|
-
}))
|
|
26030
|
-
}
|
|
26031
|
-
)
|
|
26032
|
-
] }),
|
|
26033
|
-
/* @__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(
|
|
26006
|
+
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: [
|
|
26007
|
+
inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
26008
|
+
Button,
|
|
26009
|
+
{
|
|
26010
|
+
variant: "primary",
|
|
26011
|
+
size: "sm",
|
|
26012
|
+
onClick: handleActionClick(action, itemData),
|
|
26013
|
+
"data-testid": `action-${action.event}`,
|
|
26014
|
+
"data-row-id": String(itemData.id),
|
|
26015
|
+
children: [
|
|
26016
|
+
action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
|
|
26017
|
+
action.label
|
|
26018
|
+
]
|
|
26019
|
+
},
|
|
26020
|
+
idx
|
|
26021
|
+
)),
|
|
26022
|
+
menuCardActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
26034
26023
|
Menu,
|
|
26035
26024
|
{
|
|
26036
26025
|
position: "bottom-end",
|
|
26037
26026
|
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" }) }),
|
|
26038
|
-
items:
|
|
26027
|
+
items: menuCardActions.map((action) => ({
|
|
26039
26028
|
label: action.label,
|
|
26040
26029
|
icon: action.icon,
|
|
26041
|
-
|
|
26030
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
26042
26031
|
onClick: () => fireAction(action, itemData)
|
|
26043
26032
|
}))
|
|
26044
26033
|
}
|
|
26045
|
-
)
|
|
26046
|
-
] })
|
|
26034
|
+
)
|
|
26035
|
+
] }) })
|
|
26047
26036
|
]
|
|
26048
26037
|
},
|
|
26049
26038
|
id
|
|
@@ -26057,12 +26046,14 @@ function DataGrid({
|
|
|
26057
26046
|
{
|
|
26058
26047
|
"data-entity-row": true,
|
|
26059
26048
|
"data-entity-id": id,
|
|
26049
|
+
onClick: handleCardClick?.(itemData),
|
|
26060
26050
|
className: cn(
|
|
26061
26051
|
"bg-card rounded-lg",
|
|
26062
26052
|
"border border-border",
|
|
26063
26053
|
"shadow-elevation-card hover:shadow-elevation-dialog",
|
|
26064
26054
|
"hover:border-primary transition-all",
|
|
26065
26055
|
"flex flex-col",
|
|
26056
|
+
handleCardClick && "cursor-pointer",
|
|
26066
26057
|
isSelected && "ring-2 ring-primary border-primary"
|
|
26067
26058
|
),
|
|
26068
26059
|
children: [
|
|
@@ -26112,53 +26103,35 @@ function DataGrid({
|
|
|
26112
26103
|
] }, field.name);
|
|
26113
26104
|
}) })
|
|
26114
26105
|
] }),
|
|
26115
|
-
|
|
26116
|
-
|
|
26106
|
+
actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", onClick: stopCardClick, className: "flex-shrink-0", children: [
|
|
26107
|
+
inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
26117
26108
|
Button,
|
|
26118
26109
|
{
|
|
26119
|
-
variant:
|
|
26110
|
+
variant: "primary",
|
|
26120
26111
|
size: "sm",
|
|
26121
26112
|
onClick: handleActionClick(action, itemData),
|
|
26122
26113
|
"data-testid": `action-${action.event}`,
|
|
26123
26114
|
"data-row-id": String(itemData.id),
|
|
26124
26115
|
"aria-label": action.label,
|
|
26125
26116
|
title: action.label,
|
|
26126
|
-
className: cn(
|
|
26127
|
-
action.variant === "primary" ? void 0 : "text-muted-foreground hover:text-foreground",
|
|
26128
|
-
action.icon && "px-2"
|
|
26129
|
-
),
|
|
26117
|
+
className: cn(action.icon && "px-2"),
|
|
26130
26118
|
children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
|
|
26131
26119
|
},
|
|
26132
26120
|
idx
|
|
26133
26121
|
)),
|
|
26134
|
-
|
|
26122
|
+
menuCardActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
26135
26123
|
Menu,
|
|
26136
26124
|
{
|
|
26137
26125
|
position: "bottom-end",
|
|
26138
26126
|
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" }) }),
|
|
26139
|
-
items:
|
|
26127
|
+
items: menuCardActions.map((action) => ({
|
|
26140
26128
|
label: action.label,
|
|
26141
26129
|
icon: action.icon,
|
|
26142
|
-
|
|
26130
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
26143
26131
|
onClick: () => fireAction(action, itemData)
|
|
26144
26132
|
}))
|
|
26145
26133
|
}
|
|
26146
|
-
)
|
|
26147
|
-
dangerActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
26148
|
-
Button,
|
|
26149
|
-
{
|
|
26150
|
-
variant: "ghost",
|
|
26151
|
-
size: "sm",
|
|
26152
|
-
onClick: handleActionClick(action, itemData),
|
|
26153
|
-
"data-testid": `action-${action.event}`,
|
|
26154
|
-
"data-row-id": String(itemData.id),
|
|
26155
|
-
"aria-label": action.label,
|
|
26156
|
-
title: action.label,
|
|
26157
|
-
className: "text-error hover:text-error hover:bg-error/10 px-2",
|
|
26158
|
-
children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
|
|
26159
|
-
},
|
|
26160
|
-
`danger-${idx}`
|
|
26161
|
-
))
|
|
26134
|
+
)
|
|
26162
26135
|
] })
|
|
26163
26136
|
] }) }),
|
|
26164
26137
|
bodyFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-4 pt-2 pb-4 flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
@@ -26179,8 +26152,8 @@ function DataGrid({
|
|
|
26179
26152
|
}
|
|
26180
26153
|
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
26181
26154
|
field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
26182
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
26183
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", children: formatValue(value, field.format) })
|
|
26155
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", className: "sr-only", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
26156
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: formatValue(value, field.format) })
|
|
26184
26157
|
] }, field.name);
|
|
26185
26158
|
}) })
|
|
26186
26159
|
] }) })
|
|
@@ -26400,54 +26373,59 @@ function DataList({
|
|
|
26400
26373
|
if (!itemActions || itemActions.length === 0) return null;
|
|
26401
26374
|
const inline = maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions;
|
|
26402
26375
|
const overflow = maxInlineActions != null ? itemActions.slice(maxInlineActions) : [];
|
|
26403
|
-
return
|
|
26404
|
-
|
|
26405
|
-
|
|
26406
|
-
|
|
26407
|
-
|
|
26408
|
-
|
|
26409
|
-
|
|
26410
|
-
|
|
26411
|
-
|
|
26412
|
-
|
|
26413
|
-
action
|
|
26414
|
-
|
|
26415
|
-
|
|
26416
|
-
|
|
26417
|
-
|
|
26418
|
-
|
|
26419
|
-
|
|
26420
|
-
|
|
26421
|
-
|
|
26422
|
-
|
|
26423
|
-
|
|
26424
|
-
|
|
26425
|
-
|
|
26426
|
-
|
|
26427
|
-
|
|
26428
|
-
|
|
26429
|
-
|
|
26430
|
-
|
|
26431
|
-
|
|
26432
|
-
|
|
26433
|
-
|
|
26434
|
-
|
|
26435
|
-
|
|
26436
|
-
|
|
26437
|
-
|
|
26438
|
-
|
|
26439
|
-
|
|
26440
|
-
|
|
26441
|
-
|
|
26442
|
-
|
|
26376
|
+
return (
|
|
26377
|
+
// stopPropagation at the cluster: the "⋯" trigger opens the overflow
|
|
26378
|
+
// menu without also firing the row's default click (inline buttons
|
|
26379
|
+
// already stop it in handleActionClick; the Menu panel is portaled).
|
|
26380
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", onClick: rowClickEvent ? (e) => e.stopPropagation() : void 0, className: "flex-shrink-0", children: [
|
|
26381
|
+
inline.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
26382
|
+
Button,
|
|
26383
|
+
{
|
|
26384
|
+
variant: action.variant ?? "ghost",
|
|
26385
|
+
size: "sm",
|
|
26386
|
+
onClick: handleActionClick(action, itemData),
|
|
26387
|
+
"data-testid": `action-${action.event}`,
|
|
26388
|
+
"data-row-id": String(itemData.id),
|
|
26389
|
+
className: cn(
|
|
26390
|
+
action.variant === "danger" && "text-error hover:bg-error/10",
|
|
26391
|
+
// Must sit on the Button itself: the variant's own text colour
|
|
26392
|
+
// beats an inherited one from the row wrapper.
|
|
26393
|
+
onPrimary && "!text-primary-foreground hover:bg-primary-foreground/15"
|
|
26394
|
+
),
|
|
26395
|
+
children: [
|
|
26396
|
+
action.icon && renderIconInput2(action.icon, { size: "xs", className: "mr-1" }),
|
|
26397
|
+
action.label
|
|
26398
|
+
]
|
|
26399
|
+
},
|
|
26400
|
+
idx
|
|
26401
|
+
)),
|
|
26402
|
+
overflow.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
26403
|
+
Menu,
|
|
26404
|
+
{
|
|
26405
|
+
position: "bottom-end",
|
|
26406
|
+
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" }) }),
|
|
26407
|
+
items: overflow.map((action) => ({
|
|
26408
|
+
label: action.label,
|
|
26409
|
+
icon: action.icon,
|
|
26410
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
26411
|
+
onClick: () => eventBus.emit(`UI:${action.event}`, {
|
|
26412
|
+
id: itemData.id,
|
|
26413
|
+
row: itemData
|
|
26414
|
+
})
|
|
26415
|
+
}))
|
|
26416
|
+
}
|
|
26417
|
+
)
|
|
26418
|
+
] })
|
|
26419
|
+
);
|
|
26443
26420
|
};
|
|
26421
|
+
const rowClickEvent = itemClickEvent || itemActions?.find((a) => a.variant !== "danger")?.event;
|
|
26444
26422
|
const handleRowClick = (itemData) => () => {
|
|
26445
|
-
if (!
|
|
26423
|
+
if (!rowClickEvent) return;
|
|
26446
26424
|
const payload = {
|
|
26447
26425
|
id: itemData.id,
|
|
26448
26426
|
row: itemData
|
|
26449
26427
|
};
|
|
26450
|
-
eventBus.emit(`UI:${
|
|
26428
|
+
eventBus.emit(`UI:${rowClickEvent}`, payload);
|
|
26451
26429
|
};
|
|
26452
26430
|
if (isLoading) {
|
|
26453
26431
|
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") }) });
|
|
@@ -26495,10 +26473,10 @@ function DataList({
|
|
|
26495
26473
|
{
|
|
26496
26474
|
"data-entity-row": true,
|
|
26497
26475
|
"data-entity-id": id,
|
|
26498
|
-
onClick:
|
|
26476
|
+
onClick: rowClickEvent ? handleRowClick(itemData) : void 0,
|
|
26499
26477
|
className: cn(
|
|
26500
26478
|
"flex px-4 group/rowactions",
|
|
26501
|
-
|
|
26479
|
+
rowClickEvent && "cursor-pointer",
|
|
26502
26480
|
isSent ? "justify-end" : "justify-start"
|
|
26503
26481
|
),
|
|
26504
26482
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -26574,7 +26552,7 @@ function DataList({
|
|
|
26574
26552
|
const id2 = itemData.id || String(index);
|
|
26575
26553
|
const actions = renderItemActions(itemData);
|
|
26576
26554
|
return wrapDnd(
|
|
26577
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick:
|
|
26555
|
+
/* @__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: [
|
|
26578
26556
|
children(itemData, index),
|
|
26579
26557
|
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: [
|
|
26580
26558
|
/* @__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 }),
|
|
@@ -26586,7 +26564,6 @@ function DataList({
|
|
|
26586
26564
|
items: (itemActions ?? []).map((action) => ({
|
|
26587
26565
|
label: action.label,
|
|
26588
26566
|
icon: action.icon,
|
|
26589
|
-
event: action.event,
|
|
26590
26567
|
variant: action.variant === "danger" ? "danger" : "default",
|
|
26591
26568
|
onClick: () => eventBus.emit(`UI:${action.event}`, {
|
|
26592
26569
|
id: itemData.id,
|
|
@@ -26603,12 +26580,16 @@ function DataList({
|
|
|
26603
26580
|
const id = itemData.id || String(index);
|
|
26604
26581
|
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
26605
26582
|
return wrapDnd(
|
|
26606
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id, onClick:
|
|
26583
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id, onClick: rowClickEvent ? handleRowClick(itemData) : void 0, className: cn(rowClickEvent && "cursor-pointer"), children: [
|
|
26607
26584
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
26608
26585
|
Box,
|
|
26609
26586
|
{
|
|
26610
26587
|
className: cn(
|
|
26611
|
-
|
|
26588
|
+
// items-start, not items-center: a multi-line row (title + meta +
|
|
26589
|
+
// progress) centred its action cluster in the vertical middle, so
|
|
26590
|
+
// the buttons floated between the meta fields instead of anchoring
|
|
26591
|
+
// to the title they act on (U-DATALIST-ACTIONS-FLOAT-MID-ROW).
|
|
26592
|
+
"group flex items-start gap-4 transition-all duration-fast",
|
|
26612
26593
|
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
26613
26594
|
"hover:bg-muted/80",
|
|
26614
26595
|
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
@@ -26639,11 +26620,19 @@ function DataList({
|
|
|
26639
26620
|
if (value === void 0 || value === null || value === "") return null;
|
|
26640
26621
|
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
26641
26622
|
field.icon && renderIconInput2(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
26642
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
26643
|
-
|
|
26644
|
-
|
|
26645
|
-
|
|
26646
|
-
|
|
26623
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
26624
|
+
Typography,
|
|
26625
|
+
{
|
|
26626
|
+
variant: "caption",
|
|
26627
|
+
color: "secondary",
|
|
26628
|
+
className: cn(field.format !== "boolean" && "sr-only"),
|
|
26629
|
+
children: [
|
|
26630
|
+
field.label ?? fieldLabel3(field.name),
|
|
26631
|
+
":"
|
|
26632
|
+
]
|
|
26633
|
+
}
|
|
26634
|
+
),
|
|
26635
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: formatValue2(value, field.format, { yes: t("common.yes"), no: t("common.no") }) })
|
|
26647
26636
|
] }, field.name);
|
|
26648
26637
|
}) }),
|
|
26649
26638
|
progressFields.map((field) => {
|
|
@@ -26662,7 +26651,7 @@ function DataList({
|
|
|
26662
26651
|
]
|
|
26663
26652
|
}
|
|
26664
26653
|
),
|
|
26665
|
-
isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "
|
|
26654
|
+
(isCard || isCompact) && !isLast && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("border-b border-border/40", isCompact ? "mx-4" : "mx-6") })
|
|
26666
26655
|
] }, id)
|
|
26667
26656
|
);
|
|
26668
26657
|
};
|
|
@@ -26672,7 +26661,13 @@ function DataList({
|
|
|
26672
26661
|
{
|
|
26673
26662
|
className: cn(
|
|
26674
26663
|
isCard && "bg-card rounded-xl border border-border shadow-elevation-dialog overflow-hidden",
|
|
26675
|
-
|
|
26664
|
+
// `gap-*` is inert on a block container, and Box only emits a display
|
|
26665
|
+
// class when its `display` prop is set — so every non-card list had
|
|
26666
|
+
// been asking for a gap that CSS silently dropped. flex-col makes it
|
|
26667
|
+
// real. `compact` keeps gap-0 on purpose: it separates with the row
|
|
26668
|
+
// divider above instead, never both (Almadar_UI_Beauty.md 6).
|
|
26669
|
+
!isCard && "flex flex-col",
|
|
26670
|
+
!isCard && !isCompact && gapClass,
|
|
26676
26671
|
listLookStyles[look],
|
|
26677
26672
|
className
|
|
26678
26673
|
),
|
|
@@ -31797,7 +31792,7 @@ var init_MapView = __esm({
|
|
|
31797
31792
|
shadowSize: [41, 41]
|
|
31798
31793
|
});
|
|
31799
31794
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
31800
|
-
const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback90, useState:
|
|
31795
|
+
const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback90, useState: useState94 } = React85__namespace.default;
|
|
31801
31796
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
31802
31797
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
31803
31798
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -31842,7 +31837,7 @@ var init_MapView = __esm({
|
|
|
31842
31837
|
showAttribution = true
|
|
31843
31838
|
}) {
|
|
31844
31839
|
const eventBus = useEventBus2();
|
|
31845
|
-
const [clickedPosition, setClickedPosition] =
|
|
31840
|
+
const [clickedPosition, setClickedPosition] = useState94(null);
|
|
31846
31841
|
const handleMapClick = useCallback90((lat, lng) => {
|
|
31847
31842
|
if (showClickedPin) {
|
|
31848
31843
|
setClickedPosition({ lat, lng });
|
|
@@ -36066,741 +36061,775 @@ var init_PositionedCanvas = __esm({
|
|
|
36066
36061
|
PositionedCanvas.displayName = "PositionedCanvas";
|
|
36067
36062
|
}
|
|
36068
36063
|
});
|
|
36069
|
-
function
|
|
36070
|
-
|
|
36071
|
-
|
|
36072
|
-
|
|
36064
|
+
function safeUrl(raw, kinds) {
|
|
36065
|
+
const url = raw.trim();
|
|
36066
|
+
if (url.startsWith("#") || url.startsWith("/")) return url;
|
|
36067
|
+
const lower = url.toLowerCase();
|
|
36068
|
+
for (const kind of kinds) {
|
|
36069
|
+
if (lower.startsWith(kind)) return url;
|
|
36070
|
+
}
|
|
36071
|
+
return null;
|
|
36073
36072
|
}
|
|
36074
|
-
function
|
|
36075
|
-
|
|
36076
|
-
|
|
36077
|
-
const
|
|
36078
|
-
|
|
36079
|
-
|
|
36080
|
-
|
|
36081
|
-
|
|
36082
|
-
|
|
36073
|
+
function sanitizeNode(el) {
|
|
36074
|
+
const children = Array.from(el.children);
|
|
36075
|
+
for (const child of children) {
|
|
36076
|
+
const tag = child.tagName.toLowerCase();
|
|
36077
|
+
if (DROP_TAGS.has(tag)) {
|
|
36078
|
+
child.remove();
|
|
36079
|
+
continue;
|
|
36080
|
+
}
|
|
36081
|
+
const allowed = ALLOWED_ATTRS[tag];
|
|
36082
|
+
if (!allowed) {
|
|
36083
|
+
sanitizeNode(child);
|
|
36084
|
+
child.replaceWith(...Array.from(child.childNodes));
|
|
36085
|
+
continue;
|
|
36086
|
+
}
|
|
36087
|
+
for (const attr of Array.from(child.attributes)) {
|
|
36088
|
+
const name = attr.name.toLowerCase();
|
|
36089
|
+
if (!allowed.includes(name)) {
|
|
36090
|
+
child.removeAttribute(attr.name);
|
|
36091
|
+
continue;
|
|
36092
|
+
}
|
|
36093
|
+
if (name === "href") {
|
|
36094
|
+
const url = safeUrl(attr.value, ["http://", "https://", "mailto:"]);
|
|
36095
|
+
if (url === null) child.removeAttribute(attr.name);
|
|
36096
|
+
else child.setAttribute("href", url);
|
|
36097
|
+
}
|
|
36098
|
+
if (name === "src") {
|
|
36099
|
+
const url = safeUrl(attr.value, ["http://", "https://", "data:image/"]);
|
|
36100
|
+
if (url === null) child.remove();
|
|
36101
|
+
else child.setAttribute("src", url);
|
|
36102
|
+
}
|
|
36103
|
+
}
|
|
36104
|
+
sanitizeNode(child);
|
|
36105
|
+
}
|
|
36083
36106
|
}
|
|
36084
|
-
function
|
|
36085
|
-
|
|
36086
|
-
|
|
36087
|
-
|
|
36088
|
-
|
|
36089
|
-
|
|
36090
|
-
|
|
36091
|
-
children: [
|
|
36092
|
-
{ id: nextBlockId("li"), type: "paragraph", content: "" }
|
|
36093
|
-
]
|
|
36094
|
-
};
|
|
36095
|
-
case "image":
|
|
36096
|
-
return {
|
|
36097
|
-
id: nextBlockId(type),
|
|
36098
|
-
type,
|
|
36099
|
-
content: "",
|
|
36100
|
-
metadata: { url: "", caption: "" }
|
|
36101
|
-
};
|
|
36102
|
-
case "code":
|
|
36103
|
-
return {
|
|
36104
|
-
id: nextBlockId(type),
|
|
36105
|
-
type,
|
|
36106
|
-
content: "",
|
|
36107
|
-
metadata: { language: "plaintext" }
|
|
36108
|
-
};
|
|
36109
|
-
case "divider":
|
|
36110
|
-
return { id: nextBlockId(type), type };
|
|
36111
|
-
default:
|
|
36112
|
-
return { id: nextBlockId(type), type, content: "" };
|
|
36107
|
+
function sanitizeRichHtml(html) {
|
|
36108
|
+
if (!html || typeof html !== "string") return "";
|
|
36109
|
+
if (typeof window === "undefined" || typeof DOMParser === "undefined") return "";
|
|
36110
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
36111
|
+
sanitizeNode(doc.body);
|
|
36112
|
+
if (!doc.body.querySelector("img, hr") && (doc.body.textContent ?? "").trim().length === 0) {
|
|
36113
|
+
return "";
|
|
36113
36114
|
}
|
|
36115
|
+
return doc.body.innerHTML.replace(//g, "");
|
|
36114
36116
|
}
|
|
36115
|
-
function
|
|
36116
|
-
|
|
36117
|
+
function htmlIsEmpty(el) {
|
|
36118
|
+
if (el.querySelector("img, hr")) return false;
|
|
36119
|
+
return (el.textContent ?? "").trim().length === 0;
|
|
36117
36120
|
}
|
|
36118
|
-
function
|
|
36119
|
-
|
|
36121
|
+
function closestBlock(node, root) {
|
|
36122
|
+
let cur = node;
|
|
36123
|
+
while (cur && cur !== root) {
|
|
36124
|
+
if (cur instanceof Element && BLOCK_TAGS.has(cur.tagName)) return cur;
|
|
36125
|
+
cur = cur.parentNode;
|
|
36126
|
+
}
|
|
36127
|
+
return null;
|
|
36120
36128
|
}
|
|
36121
|
-
function
|
|
36129
|
+
function RichTextStyles() {
|
|
36130
|
+
return /* @__PURE__ */ jsxRuntime.jsx("style", { children: RICH_TEXT_CSS });
|
|
36131
|
+
}
|
|
36132
|
+
function readToolbarState(root) {
|
|
36133
|
+
const sel = window.getSelection();
|
|
36134
|
+
if (!sel || sel.rangeCount === 0) return IDLE_TOOLBAR;
|
|
36135
|
+
const anchor = sel.anchorNode;
|
|
36136
|
+
if (!anchor || !root.contains(anchor)) return IDLE_TOOLBAR;
|
|
36137
|
+
let block = null;
|
|
36138
|
+
let link = false;
|
|
36139
|
+
let node = anchor;
|
|
36140
|
+
while (node && node !== root) {
|
|
36141
|
+
if (node instanceof Element) {
|
|
36142
|
+
const tag = node.tagName.toLowerCase();
|
|
36143
|
+
if (!block && (tag === "h1" || tag === "h2" || tag === "h3" || tag === "blockquote" || tag === "pre")) {
|
|
36144
|
+
block = tag;
|
|
36145
|
+
}
|
|
36146
|
+
if (tag === "a") link = true;
|
|
36147
|
+
}
|
|
36148
|
+
node = node.parentNode;
|
|
36149
|
+
}
|
|
36122
36150
|
return {
|
|
36123
|
-
|
|
36124
|
-
|
|
36125
|
-
|
|
36126
|
-
|
|
36127
|
-
|
|
36128
|
-
|
|
36129
|
-
|
|
36151
|
+
bold: document.queryCommandState("bold"),
|
|
36152
|
+
italic: document.queryCommandState("italic"),
|
|
36153
|
+
underline: document.queryCommandState("underline"),
|
|
36154
|
+
strikeThrough: document.queryCommandState("strikeThrough"),
|
|
36155
|
+
block,
|
|
36156
|
+
bullets: document.queryCommandState("insertUnorderedList"),
|
|
36157
|
+
numbers: document.queryCommandState("insertOrderedList"),
|
|
36158
|
+
link
|
|
36130
36159
|
};
|
|
36131
36160
|
}
|
|
36132
|
-
function
|
|
36133
|
-
|
|
36134
|
-
|
|
36135
|
-
|
|
36136
|
-
|
|
36137
|
-
|
|
36138
|
-
|
|
36139
|
-
|
|
36140
|
-
|
|
36141
|
-
|
|
36142
|
-
|
|
36143
|
-
|
|
36161
|
+
function ToolbarButton({ icon: IconCmp, label, active, onExec }) {
|
|
36162
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36163
|
+
Button,
|
|
36164
|
+
{
|
|
36165
|
+
type: "button",
|
|
36166
|
+
variant: "ghost",
|
|
36167
|
+
size: "sm",
|
|
36168
|
+
"aria-label": label,
|
|
36169
|
+
"aria-pressed": active,
|
|
36170
|
+
title: label,
|
|
36171
|
+
className: cn(
|
|
36172
|
+
"h-8 w-8 p-0 gap-0 justify-center",
|
|
36173
|
+
active && "bg-muted text-foreground"
|
|
36174
|
+
),
|
|
36175
|
+
onMouseDown: (e) => {
|
|
36176
|
+
e.preventDefault();
|
|
36177
|
+
onExec();
|
|
36178
|
+
},
|
|
36179
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(IconCmp, { size: 15 })
|
|
36144
36180
|
}
|
|
36145
|
-
|
|
36146
|
-
|
|
36147
|
-
|
|
36148
|
-
|
|
36149
|
-
|
|
36150
|
-
|
|
36151
|
-
|
|
36152
|
-
|
|
36153
|
-
|
|
36154
|
-
|
|
36155
|
-
|
|
36156
|
-
|
|
36157
|
-
|
|
36158
|
-
|
|
36159
|
-
|
|
36160
|
-
|
|
36161
|
-
|
|
36162
|
-
|
|
36163
|
-
|
|
36164
|
-
|
|
36165
|
-
|
|
36166
|
-
|
|
36167
|
-
|
|
36168
|
-
|
|
36169
|
-
|
|
36170
|
-
|
|
36181
|
+
);
|
|
36182
|
+
}
|
|
36183
|
+
var CHANGE_DEBOUNCE_MS, ALLOWED_ATTRS, DROP_TAGS, MD_BLOCK_PREFIXES, BLOCK_TAGS, MD_INLINE_RULES, RICH_TEXT_CSS, IDLE_TOOLBAR, RichTextEditor;
|
|
36184
|
+
var init_RichTextEditor = __esm({
|
|
36185
|
+
"components/core/molecules/RichTextEditor.tsx"() {
|
|
36186
|
+
"use client";
|
|
36187
|
+
init_cn();
|
|
36188
|
+
init_Box();
|
|
36189
|
+
init_Button();
|
|
36190
|
+
init_useEventBus();
|
|
36191
|
+
CHANGE_DEBOUNCE_MS = 400;
|
|
36192
|
+
ALLOWED_ATTRS = {
|
|
36193
|
+
p: [],
|
|
36194
|
+
h1: [],
|
|
36195
|
+
h2: [],
|
|
36196
|
+
h3: [],
|
|
36197
|
+
h4: [],
|
|
36198
|
+
ul: [],
|
|
36199
|
+
ol: [],
|
|
36200
|
+
li: [],
|
|
36201
|
+
blockquote: [],
|
|
36202
|
+
pre: [],
|
|
36203
|
+
code: [],
|
|
36204
|
+
b: [],
|
|
36205
|
+
strong: [],
|
|
36206
|
+
i: [],
|
|
36207
|
+
em: [],
|
|
36208
|
+
u: [],
|
|
36209
|
+
s: [],
|
|
36210
|
+
strike: [],
|
|
36211
|
+
br: [],
|
|
36212
|
+
hr: [],
|
|
36213
|
+
div: [],
|
|
36214
|
+
span: [],
|
|
36215
|
+
a: ["href"],
|
|
36216
|
+
img: ["src", "alt"]
|
|
36217
|
+
};
|
|
36218
|
+
DROP_TAGS = /* @__PURE__ */ new Set(["script", "style", "iframe", "object", "embed", "link", "meta", "form", "input", "button", "textarea", "select"]);
|
|
36219
|
+
MD_BLOCK_PREFIXES = {
|
|
36220
|
+
"#": { kind: "block", tag: "h1" },
|
|
36221
|
+
"##": { kind: "block", tag: "h2" },
|
|
36222
|
+
"###": { kind: "block", tag: "h3" },
|
|
36223
|
+
">": { kind: "block", tag: "blockquote" },
|
|
36224
|
+
"```": { kind: "block", tag: "pre" },
|
|
36225
|
+
"-": { kind: "list", command: "insertUnorderedList" },
|
|
36226
|
+
"*": { kind: "list", command: "insertUnorderedList" },
|
|
36227
|
+
"1.": { kind: "list", command: "insertOrderedList" }
|
|
36228
|
+
};
|
|
36229
|
+
BLOCK_TAGS = /* @__PURE__ */ new Set(["P", "DIV", "LI", "H1", "H2", "H3", "H4", "BLOCKQUOTE", "PRE"]);
|
|
36230
|
+
MD_INLINE_RULES = [
|
|
36231
|
+
{ pattern: /\*\*([^*\n]+)\*\*$/, wrap: "strong" },
|
|
36232
|
+
{ pattern: /(^|[^*])\*([^*\n]+)\*$/, wrap: "em" },
|
|
36233
|
+
{ pattern: /`([^`\n]+)`$/, wrap: "code" }
|
|
36234
|
+
];
|
|
36235
|
+
RICH_TEXT_CSS = `
|
|
36236
|
+
.almadar-rich-text { line-height: 1.7; color: var(--color-foreground); }
|
|
36237
|
+
.almadar-rich-text h1 { font-size: 1.875rem; font-weight: 700; line-height: 1.25; margin: 1.25em 0 0.4em; }
|
|
36238
|
+
.almadar-rich-text h2 { font-size: 1.5rem; font-weight: 650; line-height: 1.3; margin: 1.1em 0 0.4em; }
|
|
36239
|
+
.almadar-rich-text h3 { font-size: 1.25rem; font-weight: 600; line-height: 1.35; margin: 1em 0 0.35em; }
|
|
36240
|
+
.almadar-rich-text h1:first-child, .almadar-rich-text h2:first-child, .almadar-rich-text h3:first-child { margin-top: 0; }
|
|
36241
|
+
.almadar-rich-text p { margin: 0.5em 0; }
|
|
36242
|
+
.almadar-rich-text ul { list-style: disc; padding-inline-start: 1.5rem; margin: 0.5em 0; }
|
|
36243
|
+
.almadar-rich-text ol { list-style: decimal; padding-inline-start: 1.5rem; margin: 0.5em 0; }
|
|
36244
|
+
.almadar-rich-text li { margin: 0.25em 0; }
|
|
36245
|
+
.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; }
|
|
36246
|
+
.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; }
|
|
36247
|
+
.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; }
|
|
36248
|
+
.almadar-rich-text pre code { background: transparent; padding: 0; }
|
|
36249
|
+
.almadar-rich-text a { color: var(--color-primary); text-decoration: underline; }
|
|
36250
|
+
.almadar-rich-text hr { border: none; border-top: 1px solid var(--color-border); margin: 1.25em 0; }
|
|
36251
|
+
.almadar-rich-text img { max-width: 100%; border-radius: 0.375rem; }
|
|
36252
|
+
`;
|
|
36253
|
+
IDLE_TOOLBAR = {
|
|
36254
|
+
bold: false,
|
|
36255
|
+
italic: false,
|
|
36256
|
+
underline: false,
|
|
36257
|
+
strikeThrough: false,
|
|
36258
|
+
block: null,
|
|
36259
|
+
bullets: false,
|
|
36260
|
+
numbers: false,
|
|
36261
|
+
link: false
|
|
36262
|
+
};
|
|
36263
|
+
RichTextEditor = ({
|
|
36264
|
+
value,
|
|
36265
|
+
onChange,
|
|
36266
|
+
changeEvent,
|
|
36267
|
+
readOnly = false,
|
|
36268
|
+
placeholder,
|
|
36269
|
+
showToolbar = true,
|
|
36270
|
+
className
|
|
36271
|
+
}) => {
|
|
36272
|
+
const { t } = hooks.useTranslate();
|
|
36273
|
+
const ref = React85.useRef(null);
|
|
36274
|
+
const [toolbar, setToolbar] = React85.useState(IDLE_TOOLBAR);
|
|
36275
|
+
const [empty, setEmpty] = React85.useState(() => !value || !sanitizeRichHtml(value).trim());
|
|
36276
|
+
const eventBus = useEventBus();
|
|
36277
|
+
const onChangeRef = React85.useRef(onChange);
|
|
36278
|
+
const changeEventRef = React85.useRef(changeEvent);
|
|
36279
|
+
React85.useEffect(() => {
|
|
36280
|
+
onChangeRef.current = onChange;
|
|
36281
|
+
changeEventRef.current = changeEvent;
|
|
36282
|
+
}, [onChange, changeEvent]);
|
|
36283
|
+
const emitTimerRef = React85.useRef(null);
|
|
36284
|
+
const emitNow = React85.useCallback(() => {
|
|
36285
|
+
const el = ref.current;
|
|
36286
|
+
if (!el) return;
|
|
36287
|
+
const html = sanitizeRichHtml(el.innerHTML);
|
|
36288
|
+
onChangeRef.current?.(html);
|
|
36289
|
+
const evt = changeEventRef.current;
|
|
36290
|
+
if (evt) eventBus.emit(`UI:${evt}`, { value: html });
|
|
36291
|
+
}, [eventBus]);
|
|
36292
|
+
const scheduleEmit = React85.useCallback(() => {
|
|
36293
|
+
if (emitTimerRef.current) clearTimeout(emitTimerRef.current);
|
|
36294
|
+
emitTimerRef.current = setTimeout(() => {
|
|
36295
|
+
emitTimerRef.current = null;
|
|
36296
|
+
emitNow();
|
|
36297
|
+
}, CHANGE_DEBOUNCE_MS);
|
|
36298
|
+
}, [emitNow]);
|
|
36299
|
+
const flushEmit = React85.useCallback(() => {
|
|
36300
|
+
if (!emitTimerRef.current) return;
|
|
36301
|
+
clearTimeout(emitTimerRef.current);
|
|
36302
|
+
emitTimerRef.current = null;
|
|
36303
|
+
emitNow();
|
|
36304
|
+
}, [emitNow]);
|
|
36305
|
+
React85.useEffect(() => () => {
|
|
36306
|
+
if (emitTimerRef.current) {
|
|
36307
|
+
clearTimeout(emitTimerRef.current);
|
|
36308
|
+
emitTimerRef.current = null;
|
|
36309
|
+
emitNow();
|
|
36310
|
+
}
|
|
36311
|
+
}, [emitNow]);
|
|
36312
|
+
React85.useEffect(() => {
|
|
36313
|
+
if (readOnly) return;
|
|
36314
|
+
const el = ref.current;
|
|
36315
|
+
if (!el) return;
|
|
36316
|
+
if (document.activeElement === el) return;
|
|
36317
|
+
const next = sanitizeRichHtml(value ?? "") || "<p><br></p>";
|
|
36318
|
+
if (el.innerHTML !== next) {
|
|
36319
|
+
el.innerHTML = next;
|
|
36320
|
+
setEmpty(htmlIsEmpty(el));
|
|
36321
|
+
}
|
|
36322
|
+
}, [readOnly, value]);
|
|
36323
|
+
React85.useEffect(() => {
|
|
36324
|
+
if (readOnly) return;
|
|
36325
|
+
document.execCommand("defaultParagraphSeparator", false, "p");
|
|
36326
|
+
}, [readOnly]);
|
|
36327
|
+
React85.useEffect(() => {
|
|
36328
|
+
if (readOnly || !showToolbar) return;
|
|
36329
|
+
const onSelectionChange = () => {
|
|
36330
|
+
const el = ref.current;
|
|
36331
|
+
if (!el) return;
|
|
36332
|
+
setToolbar(readToolbarState(el));
|
|
36333
|
+
};
|
|
36334
|
+
document.addEventListener("selectionchange", onSelectionChange);
|
|
36335
|
+
return () => document.removeEventListener("selectionchange", onSelectionChange);
|
|
36336
|
+
}, [readOnly, showToolbar]);
|
|
36337
|
+
const tryInlineMarkdown = React85.useCallback(() => {
|
|
36338
|
+
const root = ref.current;
|
|
36339
|
+
if (!root) return false;
|
|
36340
|
+
const sel = window.getSelection();
|
|
36341
|
+
if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return false;
|
|
36342
|
+
const node = sel.anchorNode;
|
|
36343
|
+
if (!node || node.nodeType !== Node.TEXT_NODE || !root.contains(node)) return false;
|
|
36344
|
+
if (node.parentElement?.closest("code, pre")) return false;
|
|
36345
|
+
const text = (node.textContent ?? "").slice(0, sel.anchorOffset);
|
|
36346
|
+
for (const rule of MD_INLINE_RULES) {
|
|
36347
|
+
const m = rule.pattern.exec(text);
|
|
36348
|
+
if (!m) continue;
|
|
36349
|
+
const inner = rule.wrap === "em" ? m[2] : m[1];
|
|
36350
|
+
if (!inner || !inner.trim()) continue;
|
|
36351
|
+
const lead = rule.wrap === "em" ? m[1]?.length ?? 0 : 0;
|
|
36352
|
+
const range = document.createRange();
|
|
36353
|
+
range.setStart(node, m.index + lead);
|
|
36354
|
+
range.setEnd(node, sel.anchorOffset);
|
|
36355
|
+
const el = document.createElement(rule.wrap);
|
|
36356
|
+
el.textContent = inner;
|
|
36357
|
+
range.deleteContents();
|
|
36358
|
+
range.insertNode(el);
|
|
36359
|
+
const after = document.createTextNode("\u200B");
|
|
36360
|
+
el.parentNode?.insertBefore(after, el.nextSibling);
|
|
36361
|
+
const caret = document.createRange();
|
|
36362
|
+
caret.setStart(after, 1);
|
|
36363
|
+
caret.collapse(true);
|
|
36364
|
+
sel.removeAllRanges();
|
|
36365
|
+
sel.addRange(caret);
|
|
36366
|
+
return true;
|
|
36367
|
+
}
|
|
36368
|
+
return false;
|
|
36369
|
+
}, []);
|
|
36370
|
+
const tryBlockMarkdown = React85.useCallback(() => {
|
|
36371
|
+
const root = ref.current;
|
|
36372
|
+
if (!root) return false;
|
|
36373
|
+
const sel = window.getSelection();
|
|
36374
|
+
if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return false;
|
|
36375
|
+
const node = sel.anchorNode;
|
|
36376
|
+
if (!node || node.nodeType !== Node.TEXT_NODE || !root.contains(node)) return false;
|
|
36377
|
+
const block = closestBlock(node, root);
|
|
36378
|
+
if (block ? block.firstChild !== node : root.firstChild !== node) return false;
|
|
36379
|
+
const prefix = (node.textContent ?? "").slice(0, sel.anchorOffset);
|
|
36380
|
+
const rule = MD_BLOCK_PREFIXES[prefix];
|
|
36381
|
+
if (!rule) return false;
|
|
36382
|
+
if (node.parentElement?.closest("pre, code")) return false;
|
|
36383
|
+
if (rule.kind === "list" && node.parentElement?.closest("li")) return false;
|
|
36384
|
+
node.deleteData(0, prefix.length);
|
|
36385
|
+
const caret = document.createRange();
|
|
36386
|
+
caret.setStart(node, 0);
|
|
36387
|
+
caret.collapse(true);
|
|
36388
|
+
sel.removeAllRanges();
|
|
36389
|
+
sel.addRange(caret);
|
|
36390
|
+
if (rule.kind === "list") {
|
|
36391
|
+
const container = block ?? node.parentElement;
|
|
36392
|
+
const list = document.createElement(rule.command === "insertOrderedList" ? "ol" : "ul");
|
|
36393
|
+
const li = document.createElement("li");
|
|
36394
|
+
if (block) {
|
|
36395
|
+
while (block.firstChild) li.appendChild(block.firstChild);
|
|
36396
|
+
list.appendChild(li);
|
|
36397
|
+
block.replaceWith(list);
|
|
36398
|
+
} else if (container) {
|
|
36399
|
+
li.appendChild(node);
|
|
36400
|
+
list.appendChild(li);
|
|
36401
|
+
container.appendChild(list);
|
|
36402
|
+
}
|
|
36403
|
+
if (!li.firstChild) li.appendChild(document.createElement("br"));
|
|
36404
|
+
const liCaret = document.createRange();
|
|
36405
|
+
liCaret.selectNodeContents(li);
|
|
36406
|
+
liCaret.collapse(true);
|
|
36407
|
+
sel.removeAllRanges();
|
|
36408
|
+
sel.addRange(liCaret);
|
|
36409
|
+
} else {
|
|
36410
|
+
document.execCommand("formatBlock", false, rule.tag);
|
|
36411
|
+
}
|
|
36412
|
+
return true;
|
|
36413
|
+
}, []);
|
|
36414
|
+
const afterEdit = React85.useCallback(() => {
|
|
36415
|
+
const el = ref.current;
|
|
36416
|
+
if (!el) return;
|
|
36417
|
+
tryInlineMarkdown();
|
|
36418
|
+
setEmpty(htmlIsEmpty(el));
|
|
36419
|
+
setToolbar(readToolbarState(el));
|
|
36420
|
+
scheduleEmit();
|
|
36421
|
+
}, [scheduleEmit, tryInlineMarkdown]);
|
|
36422
|
+
const handleKeyDown = React85.useCallback((e) => {
|
|
36423
|
+
if (e.key === " " && tryBlockMarkdown()) {
|
|
36424
|
+
e.preventDefault();
|
|
36425
|
+
afterEdit();
|
|
36426
|
+
}
|
|
36427
|
+
}, [afterEdit, tryBlockMarkdown]);
|
|
36428
|
+
const execInline = React85.useCallback((command) => {
|
|
36429
|
+
document.execCommand(command, false);
|
|
36430
|
+
afterEdit();
|
|
36431
|
+
}, [afterEdit]);
|
|
36432
|
+
const execBlock = React85.useCallback((tag) => {
|
|
36433
|
+
const next = toolbar.block === tag ? "p" : tag;
|
|
36434
|
+
document.execCommand("formatBlock", false, next);
|
|
36435
|
+
afterEdit();
|
|
36436
|
+
}, [afterEdit, toolbar.block]);
|
|
36437
|
+
const execList = React85.useCallback((command) => {
|
|
36438
|
+
document.execCommand(command, false);
|
|
36439
|
+
afterEdit();
|
|
36440
|
+
}, [afterEdit]);
|
|
36441
|
+
const execLink = React85.useCallback(() => {
|
|
36442
|
+
if (toolbar.link) {
|
|
36443
|
+
document.execCommand("unlink", false);
|
|
36444
|
+
afterEdit();
|
|
36445
|
+
return;
|
|
36446
|
+
}
|
|
36447
|
+
const url = window.prompt(t("richTextEditor.linkPrompt"));
|
|
36448
|
+
if (!url) return;
|
|
36449
|
+
const safe = safeUrl(url, ["http://", "https://", "mailto:"]) ?? `https://${url}`;
|
|
36450
|
+
document.execCommand("createLink", false, safe);
|
|
36451
|
+
afterEdit();
|
|
36452
|
+
}, [afterEdit, t, toolbar.link]);
|
|
36453
|
+
const execRule = React85.useCallback(() => {
|
|
36454
|
+
document.execCommand("insertHorizontalRule", false);
|
|
36455
|
+
afterEdit();
|
|
36456
|
+
}, [afterEdit]);
|
|
36457
|
+
if (readOnly) {
|
|
36458
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("almadar-rich-text max-w-none", className), children: [
|
|
36459
|
+
/* @__PURE__ */ jsxRuntime.jsx(RichTextStyles, {}),
|
|
36460
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { dangerouslySetInnerHTML: { __html: sanitizeRichHtml(value ?? "") } })
|
|
36461
|
+
] });
|
|
36462
|
+
}
|
|
36463
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex flex-col gap-2", className), children: [
|
|
36464
|
+
/* @__PURE__ */ jsxRuntime.jsx(RichTextStyles, {}),
|
|
36465
|
+
showToolbar && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
36466
|
+
Box,
|
|
36467
|
+
{
|
|
36468
|
+
role: "toolbar",
|
|
36469
|
+
"aria-label": t("richTextEditor.editorToolbar"),
|
|
36470
|
+
className: cn(
|
|
36471
|
+
"sticky top-0 z-10 flex flex-wrap items-center gap-0.5 self-start",
|
|
36472
|
+
"rounded-md border border-border bg-background/95 px-1 py-0.5 shadow-sm"
|
|
36473
|
+
),
|
|
36474
|
+
children: [
|
|
36475
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Bold, label: t("richTextEditor.bold"), active: toolbar.bold, onExec: () => execInline("bold") }),
|
|
36476
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Italic, label: t("richTextEditor.italic"), active: toolbar.italic, onExec: () => execInline("italic") }),
|
|
36477
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Underline, label: t("richTextEditor.underline"), active: toolbar.underline, onExec: () => execInline("underline") }),
|
|
36478
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Strikethrough, label: t("richTextEditor.strikethrough"), active: toolbar.strikeThrough, onExec: () => execInline("strikeThrough") }),
|
|
36479
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
36480
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Heading1, label: t("richTextEditor.heading1"), active: toolbar.block === "h1", onExec: () => execBlock("h1") }),
|
|
36481
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Heading2, label: t("richTextEditor.heading2"), active: toolbar.block === "h2", onExec: () => execBlock("h2") }),
|
|
36482
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Heading3, label: t("richTextEditor.heading3"), active: toolbar.block === "h3", onExec: () => execBlock("h3") }),
|
|
36483
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
36484
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.List, label: t("richTextEditor.bulletList"), active: toolbar.bullets, onExec: () => execList("insertUnorderedList") }),
|
|
36485
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.ListOrdered, label: t("richTextEditor.numberedList"), active: toolbar.numbers, onExec: () => execList("insertOrderedList") }),
|
|
36486
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
36487
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Quote, label: t("richTextEditor.quote"), active: toolbar.block === "blockquote", onExec: () => execBlock("blockquote") }),
|
|
36488
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Code, label: t("richTextEditor.code"), active: toolbar.block === "pre", onExec: () => execBlock("pre") }),
|
|
36489
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Link, label: toolbar.link ? t("richTextEditor.removeLink") : t("richTextEditor.link"), active: toolbar.link, onExec: execLink }),
|
|
36490
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Minus, label: t("richTextEditor.divider"), onExec: execRule })
|
|
36491
|
+
]
|
|
36492
|
+
}
|
|
36493
|
+
),
|
|
36494
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
36495
|
+
Box,
|
|
36496
|
+
{
|
|
36497
|
+
ref,
|
|
36498
|
+
contentEditable: true,
|
|
36499
|
+
suppressContentEditableWarning: true,
|
|
36500
|
+
role: "textbox",
|
|
36501
|
+
"aria-multiline": "true",
|
|
36502
|
+
"aria-label": t("richTextEditor.editorSurface"),
|
|
36503
|
+
"data-placeholder": placeholder ?? t("richTextEditor.placeholder"),
|
|
36504
|
+
"data-empty": empty ? "true" : "false",
|
|
36505
|
+
className: cn(
|
|
36506
|
+
"almadar-rich-text max-w-none min-h-[8rem] outline-none",
|
|
36507
|
+
"data-[empty=true]:before:content-[attr(data-placeholder)]",
|
|
36508
|
+
"data-[empty=true]:before:text-muted-foreground/60",
|
|
36509
|
+
"data-[empty=true]:before:pointer-events-none",
|
|
36510
|
+
"data-[empty=true]:before:absolute",
|
|
36511
|
+
"relative cursor-text"
|
|
36512
|
+
),
|
|
36513
|
+
onInput: afterEdit,
|
|
36514
|
+
onKeyDown: handleKeyDown,
|
|
36515
|
+
onBlur: flushEmit
|
|
36516
|
+
}
|
|
36517
|
+
)
|
|
36518
|
+
] });
|
|
36171
36519
|
};
|
|
36520
|
+
RichTextEditor.displayName = "RichTextEditor";
|
|
36172
36521
|
}
|
|
36173
|
-
|
|
36174
|
-
|
|
36522
|
+
});
|
|
36523
|
+
function renderIconInput4(icon, props) {
|
|
36524
|
+
return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, ...props });
|
|
36175
36525
|
}
|
|
36176
|
-
function
|
|
36526
|
+
function DocumentPanel({
|
|
36527
|
+
entity,
|
|
36528
|
+
title,
|
|
36529
|
+
subtitle,
|
|
36530
|
+
value,
|
|
36531
|
+
actions,
|
|
36532
|
+
maxInlineActions,
|
|
36533
|
+
editing = false,
|
|
36534
|
+
titleCommitEvent,
|
|
36535
|
+
contentChangeEvent,
|
|
36536
|
+
editEvent,
|
|
36537
|
+
doneEvent,
|
|
36538
|
+
editLabel,
|
|
36539
|
+
doneLabel,
|
|
36540
|
+
autosaveHint,
|
|
36541
|
+
placeholder,
|
|
36542
|
+
className
|
|
36543
|
+
}) {
|
|
36544
|
+
const eventBus = useEventBus();
|
|
36177
36545
|
const { t } = hooks.useTranslate();
|
|
36178
|
-
const [
|
|
36179
|
-
const
|
|
36180
|
-
|
|
36181
|
-
|
|
36182
|
-
|
|
36183
|
-
|
|
36184
|
-
|
|
36185
|
-
|
|
36546
|
+
const [titleDraft, setTitleDraft] = React85.useState(null);
|
|
36547
|
+
const recordId = entity?.id !== void 0 && entity?.id !== null ? String(entity.id) : "";
|
|
36548
|
+
const actionDefs = actions ?? [];
|
|
36549
|
+
const inlineCap = Math.min(maxInlineActions ?? 1, 1);
|
|
36550
|
+
const inlineActions = actionDefs.filter((a) => a.variant === "primary").slice(0, inlineCap);
|
|
36551
|
+
const menuActions = actionDefs.filter((a) => !inlineActions.includes(a));
|
|
36552
|
+
const fireAction = (action) => {
|
|
36553
|
+
if (!action.event) return;
|
|
36554
|
+
eventBus.emit(`UI:${action.event}`, { id: recordId, row: entity });
|
|
36555
|
+
};
|
|
36556
|
+
const commitTitle = () => {
|
|
36557
|
+
if (!titleCommitEvent) return;
|
|
36558
|
+
const next = (titleDraft ?? "").trim();
|
|
36559
|
+
setTitleDraft(null);
|
|
36560
|
+
if (!next || next === title) return;
|
|
36561
|
+
eventBus.emit(`UI:${titleCommitEvent}`, { title: next, id: recordId });
|
|
36562
|
+
};
|
|
36563
|
+
const untitled = t("documentPanel.untitled") || "Untitled";
|
|
36564
|
+
const titleNode = titleCommitEvent && titleDraft !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
36565
|
+
Input,
|
|
36566
|
+
{
|
|
36567
|
+
value: titleDraft,
|
|
36568
|
+
autoFocus: true,
|
|
36569
|
+
"aria-label": t("common.title"),
|
|
36570
|
+
className: "h-auto py-1 text-3xl font-bold tracking-tight",
|
|
36571
|
+
onFocus: (e) => e.currentTarget.select(),
|
|
36572
|
+
onChange: (e) => setTitleDraft(e.target.value),
|
|
36573
|
+
onBlur: commitTitle,
|
|
36574
|
+
onKeyDown: (e) => {
|
|
36575
|
+
if (e.key === "Enter") {
|
|
36576
|
+
e.preventDefault();
|
|
36577
|
+
commitTitle();
|
|
36578
|
+
} else if (e.key === "Escape") {
|
|
36579
|
+
e.preventDefault();
|
|
36580
|
+
setTitleDraft(null);
|
|
36581
|
+
}
|
|
36582
|
+
},
|
|
36583
|
+
"data-testid": "document-title-input"
|
|
36186
36584
|
}
|
|
36187
|
-
|
|
36188
|
-
|
|
36189
|
-
|
|
36190
|
-
|
|
36191
|
-
|
|
36192
|
-
|
|
36193
|
-
|
|
36194
|
-
{
|
|
36195
|
-
|
|
36196
|
-
|
|
36197
|
-
|
|
36198
|
-
|
|
36199
|
-
|
|
36200
|
-
|
|
36201
|
-
|
|
36202
|
-
|
|
36203
|
-
|
|
36204
|
-
|
|
36205
|
-
|
|
36206
|
-
|
|
36207
|
-
|
|
36208
|
-
|
|
36209
|
-
|
|
36585
|
+
) : titleCommitEvent ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
36586
|
+
Box,
|
|
36587
|
+
{
|
|
36588
|
+
role: "button",
|
|
36589
|
+
tabIndex: 0,
|
|
36590
|
+
className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
36591
|
+
onClick: () => setTitleDraft(title ?? ""),
|
|
36592
|
+
onKeyDown: (e) => {
|
|
36593
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
36594
|
+
e.preventDefault();
|
|
36595
|
+
setTitleDraft(title ?? "");
|
|
36596
|
+
}
|
|
36597
|
+
},
|
|
36598
|
+
"data-testid": "document-title-editable",
|
|
36599
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", className: cn(!title && "text-muted-foreground"), children: title || untitled })
|
|
36600
|
+
}
|
|
36601
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || untitled });
|
|
36602
|
+
const emitWithId = (event) => () => {
|
|
36603
|
+
if (event) eventBus.emit(`UI:${event}`, { id: recordId });
|
|
36604
|
+
};
|
|
36605
|
+
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: [
|
|
36606
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
36607
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
36608
|
+
titleNode,
|
|
36609
|
+
subtitle ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
36610
|
+
] }),
|
|
36611
|
+
/* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
36612
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
36613
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
36614
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
36615
|
+
editEvent && /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
36616
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
36617
|
+
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
36618
|
+
] }),
|
|
36619
|
+
inlineActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
36620
|
+
Button,
|
|
36621
|
+
{
|
|
36622
|
+
variant: "primary",
|
|
36623
|
+
size: "sm",
|
|
36624
|
+
onClick: () => fireAction(action),
|
|
36625
|
+
"data-testid": `action-${action.event}`,
|
|
36626
|
+
children: [
|
|
36627
|
+
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
36628
|
+
action.label
|
|
36629
|
+
]
|
|
36630
|
+
},
|
|
36631
|
+
idx
|
|
36632
|
+
)),
|
|
36633
|
+
menuActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
36634
|
+
Menu,
|
|
36635
|
+
{
|
|
36636
|
+
position: "bottom-end",
|
|
36637
|
+
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" }) }),
|
|
36638
|
+
items: menuActions.map((action) => ({
|
|
36639
|
+
label: action.label,
|
|
36640
|
+
icon: action.icon,
|
|
36641
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
36642
|
+
onClick: () => fireAction(action)
|
|
36643
|
+
}))
|
|
36644
|
+
}
|
|
36645
|
+
)
|
|
36646
|
+
] }) })
|
|
36647
|
+
] }),
|
|
36648
|
+
editing ? /* @__PURE__ */ jsxRuntime.jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
36210
36649
|
Box,
|
|
36211
36650
|
{
|
|
36212
|
-
|
|
36651
|
+
onClick: emitWithId(editEvent),
|
|
36213
36652
|
className: cn(
|
|
36214
|
-
"
|
|
36215
|
-
"
|
|
36216
|
-
"py-1 text-sm"
|
|
36653
|
+
"rounded-md px-1 -mx-1 min-h-[16rem]",
|
|
36654
|
+
editEvent && "cursor-text transition-colors hover:bg-muted/30"
|
|
36217
36655
|
),
|
|
36218
|
-
|
|
36219
|
-
|
|
36220
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
36221
|
-
Button,
|
|
36222
|
-
{
|
|
36223
|
-
type: "button",
|
|
36224
|
-
variant: "ghost",
|
|
36225
|
-
role: "menuitem",
|
|
36226
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left justify-start rounded-none",
|
|
36227
|
-
onClick: () => {
|
|
36228
|
-
onDuplicate();
|
|
36229
|
-
setOpen(false);
|
|
36230
|
-
},
|
|
36231
|
-
children: [
|
|
36232
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "plus", className: "w-3.5 h-3.5" }),
|
|
36233
|
-
" ",
|
|
36234
|
-
t("richBlockEditor.duplicate")
|
|
36235
|
-
]
|
|
36236
|
-
}
|
|
36237
|
-
),
|
|
36238
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
36239
|
-
Button,
|
|
36240
|
-
{
|
|
36241
|
-
type: "button",
|
|
36242
|
-
variant: "ghost",
|
|
36243
|
-
role: "menuitem",
|
|
36244
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left text-destructive hover:bg-muted justify-start rounded-none",
|
|
36245
|
-
onClick: () => {
|
|
36246
|
-
onDelete();
|
|
36247
|
-
setOpen(false);
|
|
36248
|
-
},
|
|
36249
|
-
children: [
|
|
36250
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "trash", className: "w-3.5 h-3.5" }),
|
|
36251
|
-
" ",
|
|
36252
|
-
t("common.delete")
|
|
36253
|
-
]
|
|
36254
|
-
}
|
|
36255
|
-
),
|
|
36256
|
-
CHANGEABLE_TYPES.includes(block.type) && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
36257
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "my-1 border-t border-border" }),
|
|
36258
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-2 py-1 text-xs uppercase tracking-wide text-muted-foreground", children: t("richBlockEditor.turnInto") }),
|
|
36259
|
-
CHANGEABLE_TYPES.filter((bt) => bt !== block.type).map((bt) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
36260
|
-
Button,
|
|
36261
|
-
{
|
|
36262
|
-
type: "button",
|
|
36263
|
-
variant: "ghost",
|
|
36264
|
-
role: "menuitem",
|
|
36265
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left justify-start rounded-none",
|
|
36266
|
-
onClick: () => {
|
|
36267
|
-
onChangeType(bt);
|
|
36268
|
-
setOpen(false);
|
|
36269
|
-
},
|
|
36270
|
-
children: t(BLOCK_TYPE_LABEL_KEY[bt])
|
|
36271
|
-
},
|
|
36272
|
-
bt
|
|
36273
|
-
))
|
|
36274
|
-
] })
|
|
36275
|
-
]
|
|
36656
|
+
"data-testid": "document-body",
|
|
36657
|
+
children: value && value !== "" ? /* @__PURE__ */ jsxRuntime.jsx(RichTextEditor, { value, readOnly: true }) : /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "muted", children: placeholder ?? (t("documentPanel.placeholder") || "") })
|
|
36276
36658
|
}
|
|
36277
36659
|
)
|
|
36278
|
-
] });
|
|
36660
|
+
] }) });
|
|
36279
36661
|
}
|
|
36280
|
-
|
|
36281
|
-
|
|
36282
|
-
|
|
36283
|
-
|
|
36284
|
-
|
|
36285
|
-
|
|
36286
|
-
|
|
36287
|
-
|
|
36288
|
-
|
|
36289
|
-
|
|
36290
|
-
|
|
36291
|
-
|
|
36292
|
-
|
|
36293
|
-
|
|
36294
|
-
|
|
36295
|
-
|
|
36296
|
-
|
|
36297
|
-
},
|
|
36298
|
-
const handleInput = React85.useCallback(
|
|
36299
|
-
(e) => {
|
|
36300
|
-
onValueChange(e.currentTarget.textContent ?? "");
|
|
36301
|
-
},
|
|
36302
|
-
[onValueChange]
|
|
36303
|
-
);
|
|
36304
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36305
|
-
Box,
|
|
36306
|
-
{
|
|
36307
|
-
as: tag,
|
|
36308
|
-
ref,
|
|
36309
|
-
contentEditable: !readOnly,
|
|
36310
|
-
suppressContentEditableWarning: true,
|
|
36311
|
-
role: readOnly ? void 0 : "textbox",
|
|
36312
|
-
"aria-label": ariaLabel,
|
|
36313
|
-
"aria-multiline": "true",
|
|
36314
|
-
"data-placeholder": placeholder,
|
|
36315
|
-
className: cn(
|
|
36316
|
-
"outline-none focus-visible:ring-1 focus-visible:ring-ring rounded-sm",
|
|
36317
|
-
"empty:before:content-[attr(data-placeholder)] empty:before:text-muted-foreground/60",
|
|
36318
|
-
className
|
|
36319
|
-
),
|
|
36320
|
-
onInput: handleInput
|
|
36321
|
-
}
|
|
36322
|
-
);
|
|
36662
|
+
var init_DocumentPanel = __esm({
|
|
36663
|
+
"components/core/molecules/DocumentPanel.tsx"() {
|
|
36664
|
+
"use client";
|
|
36665
|
+
init_cn();
|
|
36666
|
+
init_useEventBus();
|
|
36667
|
+
init_Box();
|
|
36668
|
+
init_Stack();
|
|
36669
|
+
init_Typography();
|
|
36670
|
+
init_Button();
|
|
36671
|
+
init_Card();
|
|
36672
|
+
init_Icon();
|
|
36673
|
+
init_Input();
|
|
36674
|
+
init_Menu();
|
|
36675
|
+
init_RichTextEditor();
|
|
36676
|
+
}
|
|
36677
|
+
});
|
|
36678
|
+
function renderIconInput5(icon, props) {
|
|
36679
|
+
return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, ...props });
|
|
36323
36680
|
}
|
|
36324
|
-
function
|
|
36325
|
-
|
|
36326
|
-
|
|
36327
|
-
|
|
36328
|
-
|
|
36329
|
-
|
|
36330
|
-
|
|
36331
|
-
|
|
36332
|
-
|
|
36681
|
+
function fieldName(field) {
|
|
36682
|
+
return field.name ?? field.key ?? "";
|
|
36683
|
+
}
|
|
36684
|
+
function relationLabel(value) {
|
|
36685
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date) return null;
|
|
36686
|
+
for (const key of ["name", "title", "label"]) {
|
|
36687
|
+
const candidate = value[key];
|
|
36688
|
+
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
36689
|
+
}
|
|
36690
|
+
const id = value.id;
|
|
36691
|
+
return id !== void 0 && id !== null ? String(id) : null;
|
|
36692
|
+
}
|
|
36693
|
+
function fieldKind(field, value) {
|
|
36694
|
+
if (field.kind) return field.kind;
|
|
36695
|
+
if (field.options && field.options.length > 0) return "select";
|
|
36696
|
+
if (typeof value === "boolean" || field.format === "boolean") return "boolean";
|
|
36697
|
+
if (Array.isArray(value) || relationLabel(value ?? null) !== null) return "readonly";
|
|
36698
|
+
return "text";
|
|
36699
|
+
}
|
|
36700
|
+
function DocumentDetails({
|
|
36701
|
+
entity,
|
|
36702
|
+
fields,
|
|
36703
|
+
metaCommitEvent,
|
|
36704
|
+
title,
|
|
36705
|
+
className
|
|
36333
36706
|
}) {
|
|
36707
|
+
const eventBus = useEventBus();
|
|
36334
36708
|
const { t } = hooks.useTranslate();
|
|
36335
|
-
const
|
|
36336
|
-
|
|
36337
|
-
|
|
36338
|
-
);
|
|
36339
|
-
const
|
|
36340
|
-
(
|
|
36341
|
-
|
|
36342
|
-
|
|
36343
|
-
|
|
36344
|
-
|
|
36345
|
-
|
|
36346
|
-
|
|
36347
|
-
|
|
36348
|
-
|
|
36349
|
-
|
|
36350
|
-
|
|
36351
|
-
|
|
36352
|
-
|
|
36353
|
-
|
|
36354
|
-
|
|
36355
|
-
|
|
36356
|
-
|
|
36357
|
-
|
|
36358
|
-
|
|
36359
|
-
|
|
36360
|
-
|
|
36361
|
-
|
|
36362
|
-
|
|
36363
|
-
|
|
36364
|
-
|
|
36365
|
-
|
|
36366
|
-
|
|
36367
|
-
|
|
36368
|
-
|
|
36369
|
-
|
|
36370
|
-
|
|
36371
|
-
|
|
36372
|
-
}
|
|
36373
|
-
|
|
36374
|
-
|
|
36375
|
-
|
|
36376
|
-
|
|
36377
|
-
|
|
36378
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36379
|
-
Editable,
|
|
36380
|
-
{
|
|
36381
|
-
tag: "h1",
|
|
36382
|
-
value: block.content ?? "",
|
|
36383
|
-
readOnly,
|
|
36384
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.heading1"),
|
|
36385
|
-
ariaLabel: t("richBlockEditor.aria.heading1Block"),
|
|
36386
|
-
className: "text-3xl font-bold leading-tight",
|
|
36387
|
-
onValueChange: setContent
|
|
36388
|
-
}
|
|
36389
|
-
);
|
|
36390
|
-
case "heading-2":
|
|
36391
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36392
|
-
Editable,
|
|
36393
|
-
{
|
|
36394
|
-
tag: "h2",
|
|
36395
|
-
value: block.content ?? "",
|
|
36396
|
-
readOnly,
|
|
36397
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.heading2"),
|
|
36398
|
-
ariaLabel: t("richBlockEditor.aria.heading2Block"),
|
|
36399
|
-
className: "text-2xl font-semibold leading-tight",
|
|
36400
|
-
onValueChange: setContent
|
|
36401
|
-
}
|
|
36402
|
-
);
|
|
36403
|
-
case "heading-3":
|
|
36404
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36405
|
-
Editable,
|
|
36406
|
-
{
|
|
36407
|
-
tag: "h3",
|
|
36408
|
-
value: block.content ?? "",
|
|
36409
|
-
readOnly,
|
|
36410
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.heading3"),
|
|
36411
|
-
ariaLabel: t("richBlockEditor.aria.heading3Block"),
|
|
36412
|
-
className: "text-xl font-semibold leading-tight",
|
|
36413
|
-
onValueChange: setContent
|
|
36414
|
-
}
|
|
36415
|
-
);
|
|
36416
|
-
case "quote":
|
|
36417
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36418
|
-
Editable,
|
|
36419
|
-
{
|
|
36420
|
-
tag: "blockquote",
|
|
36421
|
-
value: block.content ?? "",
|
|
36422
|
-
readOnly,
|
|
36423
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.quote"),
|
|
36424
|
-
ariaLabel: t("richBlockEditor.aria.quoteBlock"),
|
|
36425
|
-
className: "border-l-4 border-primary/60 pl-4 italic text-muted-foreground",
|
|
36426
|
-
onValueChange: setContent
|
|
36427
|
-
}
|
|
36428
|
-
);
|
|
36429
|
-
case "code":
|
|
36430
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "rounded-md border border-border bg-muted/40", children: [
|
|
36431
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center justify-between border-b border-border px-3 py-1 text-xs text-muted-foreground", children: [
|
|
36432
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", variant: "caption", className: "uppercase tracking-wide", children: t("richBlockEditor.blockType.code") }),
|
|
36433
|
-
!readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
36434
|
-
Input,
|
|
36435
|
-
{
|
|
36436
|
-
inputType: "text",
|
|
36437
|
-
value: String(block.metadata?.language ?? "plaintext"),
|
|
36438
|
-
"aria-label": t("richBlockEditor.aria.codeLanguage"),
|
|
36439
|
-
className: cn(
|
|
36440
|
-
"h-6 w-32 rounded-sm border border-border bg-background",
|
|
36441
|
-
"px-2 text-xs outline-none focus:ring-1 focus:ring-ring"
|
|
36442
|
-
),
|
|
36443
|
-
onChange: (e) => setMetadata("language", e.target.value)
|
|
36444
|
-
}
|
|
36445
|
-
),
|
|
36446
|
-
readOnly && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", variant: "caption", className: "text-xs", children: String(block.metadata?.language ?? "plaintext") })
|
|
36447
|
-
] }),
|
|
36448
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
36449
|
-
Editable,
|
|
36450
|
-
{
|
|
36451
|
-
tag: "pre",
|
|
36452
|
-
value: block.content ?? "",
|
|
36453
|
-
readOnly,
|
|
36454
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.code"),
|
|
36455
|
-
ariaLabel: t("richBlockEditor.aria.codeBlock"),
|
|
36456
|
-
className: "block whitespace-pre-wrap p-3 font-mono text-sm leading-relaxed",
|
|
36457
|
-
onValueChange: setContent
|
|
36458
|
-
}
|
|
36459
|
-
)
|
|
36460
|
-
] });
|
|
36461
|
-
case "divider":
|
|
36462
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Divider, { className: "my-2" });
|
|
36463
|
-
case "image": {
|
|
36464
|
-
const url = String(block.metadata?.url ?? "");
|
|
36465
|
-
const caption = String(block.metadata?.caption ?? "");
|
|
36466
|
-
const imgProps = {
|
|
36467
|
-
src: url,
|
|
36468
|
-
alt: caption || t("richBlockEditor.embeddedImage"),
|
|
36469
|
-
className: "max-h-96 w-full rounded-md border border-border object-contain"
|
|
36470
|
-
};
|
|
36471
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "space-y-2", children: [
|
|
36472
|
-
url ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "img", ...imgProps }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
36473
|
-
Box,
|
|
36474
|
-
{
|
|
36475
|
-
className: cn(
|
|
36476
|
-
"flex h-32 items-center justify-center",
|
|
36477
|
-
"rounded-md border border-dashed border-border",
|
|
36478
|
-
"text-sm text-muted-foreground"
|
|
36479
|
-
),
|
|
36480
|
-
children: [
|
|
36481
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "image", className: "mr-2 w-4 h-4" }),
|
|
36482
|
-
" ",
|
|
36483
|
-
t("richBlockEditor.noImageUrl")
|
|
36484
|
-
]
|
|
36485
|
-
}
|
|
36486
|
-
),
|
|
36487
|
-
!readOnly && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col gap-2 sm:flex-row", children: [
|
|
36488
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
36489
|
-
Input,
|
|
36490
|
-
{
|
|
36491
|
-
inputType: "url",
|
|
36492
|
-
value: url,
|
|
36493
|
-
placeholder: "https://example.com/image.png",
|
|
36494
|
-
"aria-label": t("richBlockEditor.aria.imageUrl"),
|
|
36495
|
-
className: cn(
|
|
36496
|
-
"h-8 flex-1 rounded-sm border border-border bg-background",
|
|
36497
|
-
"px-2 text-sm outline-none focus:ring-1 focus:ring-ring"
|
|
36498
|
-
),
|
|
36499
|
-
onChange: (e) => setMetadata("url", e.target.value)
|
|
36500
|
-
}
|
|
36501
|
-
),
|
|
36502
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
36503
|
-
Input,
|
|
36504
|
-
{
|
|
36505
|
-
inputType: "text",
|
|
36506
|
-
value: caption,
|
|
36507
|
-
placeholder: t("richBlockEditor.placeholder.caption"),
|
|
36508
|
-
"aria-label": t("richBlockEditor.aria.imageCaption"),
|
|
36509
|
-
className: cn(
|
|
36510
|
-
"h-8 flex-1 rounded-sm border border-border bg-background",
|
|
36511
|
-
"px-2 text-sm outline-none focus:ring-1 focus:ring-ring"
|
|
36512
|
-
),
|
|
36513
|
-
onChange: (e) => setMetadata("caption", e.target.value)
|
|
36514
|
-
}
|
|
36515
|
-
)
|
|
36516
|
-
] }),
|
|
36517
|
-
readOnly && caption && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-center text-muted-foreground", children: caption })
|
|
36518
|
-
] });
|
|
36709
|
+
const [fieldDraft, setFieldDraft] = React85.useState(null);
|
|
36710
|
+
const recordId = entity?.id !== void 0 && entity?.id !== null ? String(entity.id) : "";
|
|
36711
|
+
const fieldDefs = (fields ?? []).filter((f3) => fieldName(f3) !== "");
|
|
36712
|
+
if (fieldDefs.length === 0) return null;
|
|
36713
|
+
const commitField = (name, next, current) => {
|
|
36714
|
+
setFieldDraft(null);
|
|
36715
|
+
if (!metaCommitEvent || next === current) return;
|
|
36716
|
+
eventBus.emit(`UI:${metaCommitEvent}`, { id: recordId, patch: { id: recordId, [name]: next } });
|
|
36717
|
+
};
|
|
36718
|
+
const renderValue = (field) => {
|
|
36719
|
+
const name = fieldName(field);
|
|
36720
|
+
const raw = getNestedValue(entity ?? {}, name);
|
|
36721
|
+
const kind = fieldKind(field, raw);
|
|
36722
|
+
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
36723
|
+
if (kind === "boolean") {
|
|
36724
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36725
|
+
Switch,
|
|
36726
|
+
{
|
|
36727
|
+
checked: Boolean(raw),
|
|
36728
|
+
disabled: !metaCommitEvent,
|
|
36729
|
+
"aria-label": label,
|
|
36730
|
+
onChange: (checked) => commitField(name, checked, Boolean(raw))
|
|
36731
|
+
}
|
|
36732
|
+
);
|
|
36733
|
+
}
|
|
36734
|
+
if (kind === "select") {
|
|
36735
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36736
|
+
Select,
|
|
36737
|
+
{
|
|
36738
|
+
value: raw !== void 0 && raw !== null ? String(raw) : "",
|
|
36739
|
+
disabled: !metaCommitEvent,
|
|
36740
|
+
"aria-label": label,
|
|
36741
|
+
className: "h-8 w-full",
|
|
36742
|
+
options: (field.options ?? []).map((opt) => ({ value: opt, label: humanizeEnumValue(opt) })),
|
|
36743
|
+
onChange: (e) => commitField(name, e.target.value, raw)
|
|
36744
|
+
}
|
|
36745
|
+
);
|
|
36746
|
+
}
|
|
36747
|
+
if (kind === "readonly" || !metaCommitEvent) {
|
|
36748
|
+
if (Array.isArray(raw)) {
|
|
36749
|
+
if (raw.length === 0) {
|
|
36750
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
36751
|
+
}
|
|
36752
|
+
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)) });
|
|
36519
36753
|
}
|
|
36520
|
-
|
|
36521
|
-
|
|
36522
|
-
|
|
36523
|
-
|
|
36524
|
-
|
|
36525
|
-
|
|
36526
|
-
|
|
36527
|
-
|
|
36528
|
-
|
|
36529
|
-
|
|
36530
|
-
|
|
36531
|
-
|
|
36532
|
-
|
|
36533
|
-
|
|
36534
|
-
|
|
36535
|
-
|
|
36536
|
-
|
|
36537
|
-
|
|
36538
|
-
|
|
36539
|
-
|
|
36540
|
-
|
|
36541
|
-
|
|
36542
|
-
|
|
36543
|
-
|
|
36544
|
-
|
|
36545
|
-
|
|
36546
|
-
|
|
36547
|
-
|
|
36548
|
-
|
|
36549
|
-
|
|
36550
|
-
|
|
36551
|
-
|
|
36552
|
-
|
|
36553
|
-
|
|
36554
|
-
|
|
36555
|
-
|
|
36556
|
-
|
|
36557
|
-
|
|
36558
|
-
|
|
36559
|
-
|
|
36560
|
-
|
|
36561
|
-
Button,
|
|
36562
|
-
{
|
|
36563
|
-
type: "button",
|
|
36564
|
-
variant: "ghost",
|
|
36565
|
-
className: cn(
|
|
36566
|
-
"inline-flex items-center gap-1 text-xs text-muted-foreground",
|
|
36567
|
-
"hover:text-foreground p-0 h-auto"
|
|
36568
|
-
),
|
|
36569
|
-
onClick: addListItem,
|
|
36570
|
-
children: [
|
|
36571
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "plus", className: "w-3 h-3" }),
|
|
36572
|
-
" ",
|
|
36573
|
-
t("richBlockEditor.addItem")
|
|
36574
|
-
]
|
|
36575
|
-
}
|
|
36576
|
-
) })
|
|
36577
|
-
]
|
|
36754
|
+
const shown2 = raw === void 0 || raw === null || raw === "" ? "\u2014" : relationLabel(raw) ?? formatValue(raw, field.format);
|
|
36755
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "break-words", children: shown2 });
|
|
36756
|
+
}
|
|
36757
|
+
if (fieldDraft?.name === name) {
|
|
36758
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36759
|
+
Input,
|
|
36760
|
+
{
|
|
36761
|
+
value: fieldDraft.value,
|
|
36762
|
+
autoFocus: true,
|
|
36763
|
+
"aria-label": label,
|
|
36764
|
+
className: "h-8 w-full",
|
|
36765
|
+
onChange: (e) => setFieldDraft({ name, value: e.target.value }),
|
|
36766
|
+
onBlur: () => commitField(name, fieldDraft.value.trim(), raw),
|
|
36767
|
+
onKeyDown: (e) => {
|
|
36768
|
+
if (e.key === "Enter") {
|
|
36769
|
+
e.preventDefault();
|
|
36770
|
+
commitField(name, fieldDraft.value.trim(), raw);
|
|
36771
|
+
} else if (e.key === "Escape") {
|
|
36772
|
+
e.preventDefault();
|
|
36773
|
+
setFieldDraft(null);
|
|
36774
|
+
}
|
|
36775
|
+
},
|
|
36776
|
+
"data-testid": `document-property-input-${name}`
|
|
36777
|
+
}
|
|
36778
|
+
);
|
|
36779
|
+
}
|
|
36780
|
+
const shown = raw === void 0 || raw === null || raw === "" ? "\u2014" : relationLabel(raw) ?? formatValue(raw, field.format);
|
|
36781
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36782
|
+
Box,
|
|
36783
|
+
{
|
|
36784
|
+
role: "button",
|
|
36785
|
+
tabIndex: 0,
|
|
36786
|
+
className: cn(
|
|
36787
|
+
"cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
36788
|
+
(raw === void 0 || raw === null || raw === "") && "text-muted-foreground"
|
|
36789
|
+
),
|
|
36790
|
+
onClick: () => setFieldDraft({ name, value: raw !== void 0 && raw !== null ? String(raw) : "" }),
|
|
36791
|
+
onKeyDown: (e) => {
|
|
36792
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
36793
|
+
e.preventDefault();
|
|
36794
|
+
setFieldDraft({ name, value: raw !== void 0 && raw !== null ? String(raw) : "" });
|
|
36578
36795
|
}
|
|
36579
|
-
|
|
36796
|
+
},
|
|
36797
|
+
"data-testid": `document-property-${name}`,
|
|
36798
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "break-words", children: shown })
|
|
36580
36799
|
}
|
|
36581
|
-
|
|
36582
|
-
default:
|
|
36583
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36584
|
-
Editable,
|
|
36585
|
-
{
|
|
36586
|
-
tag: "p",
|
|
36587
|
-
value: block.content ?? "",
|
|
36588
|
-
readOnly,
|
|
36589
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.paragraph"),
|
|
36590
|
-
ariaLabel: t("richBlockEditor.aria.paragraphBlock"),
|
|
36591
|
-
className: "leading-7",
|
|
36592
|
-
onValueChange: setContent
|
|
36593
|
-
}
|
|
36594
|
-
);
|
|
36595
|
-
}
|
|
36800
|
+
);
|
|
36596
36801
|
};
|
|
36597
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
36598
|
-
|
|
36599
|
-
{
|
|
36600
|
-
|
|
36601
|
-
|
|
36602
|
-
|
|
36603
|
-
|
|
36604
|
-
|
|
36605
|
-
|
|
36606
|
-
|
|
36607
|
-
|
|
36608
|
-
|
|
36609
|
-
|
|
36610
|
-
|
|
36611
|
-
readOnly,
|
|
36612
|
-
onDelete,
|
|
36613
|
-
onDuplicate,
|
|
36614
|
-
onChangeType
|
|
36615
|
-
}
|
|
36616
|
-
) }),
|
|
36617
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "min-w-0 flex-1", children: renderBody() })
|
|
36618
|
-
]
|
|
36619
|
-
}
|
|
36620
|
-
);
|
|
36802
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Card, { variant: "bordered", className: cn("w-full", className), children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", className: "p-4", children: [
|
|
36803
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", weight: "medium", className: "uppercase tracking-wide", children: title ?? (t("documentDetails.title") || "Details") }),
|
|
36804
|
+
/* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "sm", children: fieldDefs.map((field) => {
|
|
36805
|
+
const name = fieldName(field);
|
|
36806
|
+
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
36807
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
36808
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
36809
|
+
field.icon && renderIconInput5(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
36810
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "muted", children: label })
|
|
36811
|
+
] }),
|
|
36812
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "min-w-0", children: renderValue(field) })
|
|
36813
|
+
] }, name);
|
|
36814
|
+
}) })
|
|
36815
|
+
] }) });
|
|
36621
36816
|
}
|
|
36622
|
-
var
|
|
36623
|
-
|
|
36624
|
-
"components/core/molecules/RichBlockEditor.tsx"() {
|
|
36817
|
+
var init_DocumentDetails = __esm({
|
|
36818
|
+
"components/core/molecules/DocumentDetails.tsx"() {
|
|
36625
36819
|
"use client";
|
|
36626
36820
|
init_cn();
|
|
36627
|
-
|
|
36628
|
-
|
|
36629
|
-
|
|
36821
|
+
init_format();
|
|
36822
|
+
init_getNestedValue();
|
|
36823
|
+
init_useEventBus();
|
|
36630
36824
|
init_Box();
|
|
36631
|
-
|
|
36632
|
-
|
|
36825
|
+
init_Stack();
|
|
36826
|
+
init_Typography();
|
|
36827
|
+
init_Badge();
|
|
36828
|
+
init_Card();
|
|
36633
36829
|
init_Icon();
|
|
36634
|
-
|
|
36635
|
-
|
|
36636
|
-
|
|
36637
|
-
{ type: "heading-1", labelKey: "richBlockEditor.toolbar.h1", icon: LucideIcons2.Heading1 },
|
|
36638
|
-
{ type: "heading-2", labelKey: "richBlockEditor.toolbar.h2", icon: LucideIcons2.Heading2 },
|
|
36639
|
-
{ type: "heading-3", labelKey: "richBlockEditor.toolbar.h3", icon: LucideIcons2.Heading3 },
|
|
36640
|
-
{ type: "bullet-list", labelKey: "richBlockEditor.toolbar.bulletList", icon: LucideIcons2.List },
|
|
36641
|
-
{ type: "numbered-list", labelKey: "richBlockEditor.toolbar.numbered", icon: LucideIcons2.ListOrdered },
|
|
36642
|
-
{ type: "quote", labelKey: "richBlockEditor.toolbar.quote", icon: LucideIcons2.Quote },
|
|
36643
|
-
{ type: "code", labelKey: "richBlockEditor.toolbar.code", icon: LucideIcons2.Code },
|
|
36644
|
-
{ type: "divider", labelKey: "richBlockEditor.toolbar.divider", icon: LucideIcons2.Minus },
|
|
36645
|
-
{ type: "image", labelKey: "richBlockEditor.toolbar.image", icon: LucideIcons2.Image }
|
|
36646
|
-
];
|
|
36647
|
-
BLOCK_TYPE_LABEL_KEY = {
|
|
36648
|
-
paragraph: "richBlockEditor.blockType.paragraph",
|
|
36649
|
-
"heading-1": "richBlockEditor.blockType.heading1",
|
|
36650
|
-
"heading-2": "richBlockEditor.blockType.heading2",
|
|
36651
|
-
"heading-3": "richBlockEditor.blockType.heading3",
|
|
36652
|
-
"bullet-list": "richBlockEditor.blockType.bulletList",
|
|
36653
|
-
"numbered-list": "richBlockEditor.blockType.numberedList",
|
|
36654
|
-
quote: "richBlockEditor.blockType.quote",
|
|
36655
|
-
code: "richBlockEditor.blockType.code",
|
|
36656
|
-
divider: "richBlockEditor.blockType.divider",
|
|
36657
|
-
image: "richBlockEditor.blockType.image"
|
|
36658
|
-
};
|
|
36659
|
-
CHANGEABLE_TYPES = [
|
|
36660
|
-
"paragraph",
|
|
36661
|
-
"heading-1",
|
|
36662
|
-
"heading-2",
|
|
36663
|
-
"heading-3",
|
|
36664
|
-
"bullet-list",
|
|
36665
|
-
"numbered-list",
|
|
36666
|
-
"quote",
|
|
36667
|
-
"code"
|
|
36668
|
-
];
|
|
36669
|
-
_idSeq = 0;
|
|
36670
|
-
BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
36671
|
-
"paragraph",
|
|
36672
|
-
"heading-1",
|
|
36673
|
-
"heading-2",
|
|
36674
|
-
"heading-3",
|
|
36675
|
-
"bullet-list",
|
|
36676
|
-
"numbered-list",
|
|
36677
|
-
"quote",
|
|
36678
|
-
"code",
|
|
36679
|
-
"divider",
|
|
36680
|
-
"image"
|
|
36681
|
-
]);
|
|
36682
|
-
RichBlockEditor = ({
|
|
36683
|
-
initialBlocks,
|
|
36684
|
-
onChange,
|
|
36685
|
-
changeEvent,
|
|
36686
|
-
readOnly = false,
|
|
36687
|
-
placeholder,
|
|
36688
|
-
enableBlocks = true,
|
|
36689
|
-
showToolbar = true,
|
|
36690
|
-
className
|
|
36691
|
-
}) => {
|
|
36692
|
-
const { t } = hooks.useTranslate();
|
|
36693
|
-
const [blocks, setBlocks] = React85.useState(
|
|
36694
|
-
() => normalizeBlocks(initialBlocks)
|
|
36695
|
-
);
|
|
36696
|
-
const onChangeRef = React85.useRef(onChange);
|
|
36697
|
-
React85.useEffect(() => {
|
|
36698
|
-
onChangeRef.current = onChange;
|
|
36699
|
-
}, [onChange]);
|
|
36700
|
-
const eventBus = useEventBus();
|
|
36701
|
-
const changeEventRef = React85.useRef(changeEvent);
|
|
36702
|
-
React85.useEffect(() => {
|
|
36703
|
-
changeEventRef.current = changeEvent;
|
|
36704
|
-
}, [changeEvent]);
|
|
36705
|
-
const commit = React85.useCallback((next) => {
|
|
36706
|
-
setBlocks(next);
|
|
36707
|
-
onChangeRef.current?.(next);
|
|
36708
|
-
const evt = changeEventRef.current;
|
|
36709
|
-
if (evt) eventBus.emit(`UI:${evt}`, { blocks: next });
|
|
36710
|
-
}, [eventBus]);
|
|
36711
|
-
const handleAppend = React85.useCallback(
|
|
36712
|
-
(type) => {
|
|
36713
|
-
if (readOnly) return;
|
|
36714
|
-
commit([...blocks, createBlock(type)]);
|
|
36715
|
-
},
|
|
36716
|
-
[blocks, commit, readOnly]
|
|
36717
|
-
);
|
|
36718
|
-
const handleUpdate = React85.useCallback(
|
|
36719
|
-
(id, updater) => {
|
|
36720
|
-
commit(replaceBlock(blocks, id, updater));
|
|
36721
|
-
},
|
|
36722
|
-
[blocks, commit]
|
|
36723
|
-
);
|
|
36724
|
-
const handleDelete = React85.useCallback(
|
|
36725
|
-
(id) => {
|
|
36726
|
-
const next = removeBlock(blocks, id);
|
|
36727
|
-
commit(next.length > 0 ? next : [createBlock("paragraph")]);
|
|
36728
|
-
},
|
|
36729
|
-
[blocks, commit]
|
|
36730
|
-
);
|
|
36731
|
-
const handleDuplicate = React85.useCallback(
|
|
36732
|
-
(id) => {
|
|
36733
|
-
const target = blocks.find((b) => b.id === id);
|
|
36734
|
-
if (!target) return;
|
|
36735
|
-
commit(insertAfter(blocks, id, duplicateBlock(target)));
|
|
36736
|
-
},
|
|
36737
|
-
[blocks, commit]
|
|
36738
|
-
);
|
|
36739
|
-
const handleChangeType = React85.useCallback(
|
|
36740
|
-
(id, type) => {
|
|
36741
|
-
commit(
|
|
36742
|
-
replaceBlock(blocks, id, (b) => changeBlockType(b, type))
|
|
36743
|
-
);
|
|
36744
|
-
},
|
|
36745
|
-
[blocks, commit]
|
|
36746
|
-
);
|
|
36747
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
36748
|
-
Card,
|
|
36749
|
-
{
|
|
36750
|
-
variant: "bordered",
|
|
36751
|
-
padding: "none",
|
|
36752
|
-
className: cn("flex flex-col text-card-foreground", className),
|
|
36753
|
-
children: [
|
|
36754
|
-
enableBlocks && showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
36755
|
-
Box,
|
|
36756
|
-
{
|
|
36757
|
-
role: "toolbar",
|
|
36758
|
-
"aria-label": t("richBlockEditor.editorToolbar"),
|
|
36759
|
-
className: cn(
|
|
36760
|
-
"flex flex-wrap items-center gap-1",
|
|
36761
|
-
"border-b border-border bg-muted/30 px-2 py-2"
|
|
36762
|
-
),
|
|
36763
|
-
children: TOOLBAR_ENTRIES.map((entry) => {
|
|
36764
|
-
const Icon2 = entry.icon;
|
|
36765
|
-
const entryLabel = t(entry.labelKey);
|
|
36766
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
36767
|
-
Button,
|
|
36768
|
-
{
|
|
36769
|
-
type: "button",
|
|
36770
|
-
variant: "ghost",
|
|
36771
|
-
size: "sm",
|
|
36772
|
-
"aria-label": t("richBlockEditor.insertEntry", { label: entryLabel }),
|
|
36773
|
-
title: entryLabel,
|
|
36774
|
-
onClick: () => handleAppend(entry.type),
|
|
36775
|
-
children: [
|
|
36776
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon2, { size: 14 }),
|
|
36777
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", variant: "caption", className: "ml-1 hidden text-xs sm:inline", children: entryLabel })
|
|
36778
|
-
]
|
|
36779
|
-
},
|
|
36780
|
-
entry.type
|
|
36781
|
-
);
|
|
36782
|
-
})
|
|
36783
|
-
}
|
|
36784
|
-
),
|
|
36785
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-1 px-3 py-3", children: blocks.map((block) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
36786
|
-
BlockRow,
|
|
36787
|
-
{
|
|
36788
|
-
block,
|
|
36789
|
-
readOnly,
|
|
36790
|
-
showAffordances: enableBlocks,
|
|
36791
|
-
placeholder,
|
|
36792
|
-
onUpdate: (updater) => handleUpdate(block.id, updater),
|
|
36793
|
-
onDelete: () => handleDelete(block.id),
|
|
36794
|
-
onDuplicate: () => handleDuplicate(block.id),
|
|
36795
|
-
onChangeType: (type) => handleChangeType(block.id, type)
|
|
36796
|
-
},
|
|
36797
|
-
block.id
|
|
36798
|
-
)) })
|
|
36799
|
-
]
|
|
36800
|
-
}
|
|
36801
|
-
);
|
|
36802
|
-
};
|
|
36803
|
-
RichBlockEditor.displayName = "RichBlockEditor";
|
|
36830
|
+
init_Input();
|
|
36831
|
+
init_Select();
|
|
36832
|
+
init_Switch();
|
|
36804
36833
|
}
|
|
36805
36834
|
});
|
|
36806
36835
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
@@ -41749,8 +41778,8 @@ var init_DataTable = __esm({
|
|
|
41749
41778
|
DataTable.displayName = "DataTable";
|
|
41750
41779
|
}
|
|
41751
41780
|
});
|
|
41752
|
-
function getBadgeVariant(
|
|
41753
|
-
const name =
|
|
41781
|
+
function getBadgeVariant(fieldName2, value) {
|
|
41782
|
+
const name = fieldName2.toLowerCase();
|
|
41754
41783
|
const val = String(value).toLowerCase();
|
|
41755
41784
|
if (name.includes("status")) {
|
|
41756
41785
|
if (val.includes("complete") || val.includes("done") || val.includes("active"))
|
|
@@ -41766,12 +41795,12 @@ function getBadgeVariant(fieldName, value) {
|
|
|
41766
41795
|
}
|
|
41767
41796
|
return "default";
|
|
41768
41797
|
}
|
|
41769
|
-
function formatFieldValue2(value,
|
|
41798
|
+
function formatFieldValue2(value, fieldName2) {
|
|
41770
41799
|
if (typeof value === "number") {
|
|
41771
|
-
if (
|
|
41800
|
+
if (fieldName2.toLowerCase().includes("progress") || fieldName2.toLowerCase().includes("percent")) {
|
|
41772
41801
|
return `${value}%`;
|
|
41773
41802
|
}
|
|
41774
|
-
if (
|
|
41803
|
+
if (fieldName2.toLowerCase().includes("budget") || fieldName2.toLowerCase().includes("cost")) {
|
|
41775
41804
|
return `$${value.toLocaleString()}`;
|
|
41776
41805
|
}
|
|
41777
41806
|
return value.toLocaleString();
|
|
@@ -41781,7 +41810,7 @@ function formatFieldValue2(value, fieldName) {
|
|
|
41781
41810
|
}
|
|
41782
41811
|
return String(value);
|
|
41783
41812
|
}
|
|
41784
|
-
function renderRichFieldValue(value,
|
|
41813
|
+
function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
41785
41814
|
if (value === void 0 || value === null) return "\u2014";
|
|
41786
41815
|
const str = String(value);
|
|
41787
41816
|
switch (fieldType) {
|
|
@@ -41792,7 +41821,7 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
|
|
|
41792
41821
|
"img",
|
|
41793
41822
|
{
|
|
41794
41823
|
src: str,
|
|
41795
|
-
alt: formatFieldLabel(
|
|
41824
|
+
alt: formatFieldLabel(fieldName2),
|
|
41796
41825
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
41797
41826
|
loading: "lazy"
|
|
41798
41827
|
}
|
|
@@ -41927,9 +41956,9 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
|
|
|
41927
41956
|
return /* @__PURE__ */ jsxRuntime.jsx("a", { href: `tel:${str}`, className: "text-primary hover:underline", children: str });
|
|
41928
41957
|
default:
|
|
41929
41958
|
if (meta?.values && meta.values.length > 0 && meta.values.includes(str)) {
|
|
41930
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: getBadgeVariant(
|
|
41959
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: getBadgeVariant(fieldName2, str), children: humanizeEnumValue(str) });
|
|
41931
41960
|
}
|
|
41932
|
-
return formatFieldValue2(value,
|
|
41961
|
+
return formatFieldValue2(value, fieldName2);
|
|
41933
41962
|
}
|
|
41934
41963
|
}
|
|
41935
41964
|
function normalizeFieldDefs(fields) {
|
|
@@ -42399,16 +42428,11 @@ var init_DetailPanel = __esm({
|
|
|
42399
42428
|
footer
|
|
42400
42429
|
] })
|
|
42401
42430
|
] }) });
|
|
42402
|
-
|
|
42403
|
-
Box,
|
|
42404
|
-
|
|
42405
|
-
|
|
42406
|
-
|
|
42407
|
-
className
|
|
42408
|
-
),
|
|
42409
|
-
children: content
|
|
42410
|
-
}
|
|
42411
|
-
);
|
|
42431
|
+
if (!slideOver) {
|
|
42432
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className, children: content });
|
|
42433
|
+
}
|
|
42434
|
+
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 });
|
|
42435
|
+
return typeof document === "undefined" ? panel : reactDom.createPortal(panel, document.body);
|
|
42412
42436
|
};
|
|
42413
42437
|
DetailPanel.displayName = "DetailPanel";
|
|
42414
42438
|
}
|
|
@@ -42777,7 +42801,21 @@ var init_Form = __esm({
|
|
|
42777
42801
|
const normalizedInitialData = React85__namespace.default.useMemo(() => {
|
|
42778
42802
|
const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
|
|
42779
42803
|
const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
|
|
42780
|
-
|
|
42804
|
+
const merged = entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
|
|
42805
|
+
const toId = (value) => {
|
|
42806
|
+
if (value === null || value === void 0 || typeof value !== "object" || value instanceof Date) return value;
|
|
42807
|
+
if (Array.isArray(value)) {
|
|
42808
|
+
return value.map(
|
|
42809
|
+
(item) => item !== null && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && item.id !== void 0 && item.id !== null ? String(item.id) : item
|
|
42810
|
+
);
|
|
42811
|
+
}
|
|
42812
|
+
return value.id !== void 0 && value.id !== null ? String(value.id) : value;
|
|
42813
|
+
};
|
|
42814
|
+
const normalized = {};
|
|
42815
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
42816
|
+
normalized[key] = key === "id" ? value : toId(value);
|
|
42817
|
+
}
|
|
42818
|
+
return normalized;
|
|
42781
42819
|
}, [entity, initialData]);
|
|
42782
42820
|
const entityDerivedFields = React85__namespace.default.useMemo(() => {
|
|
42783
42821
|
if (fields && fields.length > 0) return void 0;
|
|
@@ -42906,8 +42944,8 @@ var init_Form = __esm({
|
|
|
42906
42944
|
checkViolations(name, newFormData);
|
|
42907
42945
|
};
|
|
42908
42946
|
const isFieldVisible = React85__namespace.default.useCallback(
|
|
42909
|
-
(
|
|
42910
|
-
const condition = conditionalFields[
|
|
42947
|
+
(fieldName2) => {
|
|
42948
|
+
const condition = conditionalFields[fieldName2];
|
|
42911
42949
|
if (!condition) return true;
|
|
42912
42950
|
return Boolean(evaluateFormExpression(condition, evalContext));
|
|
42913
42951
|
},
|
|
@@ -42953,9 +42991,9 @@ var init_Form = __esm({
|
|
|
42953
42991
|
};
|
|
42954
42992
|
const handleInvalid = (e) => {
|
|
42955
42993
|
const target = e.target;
|
|
42956
|
-
const
|
|
42994
|
+
const fieldName2 = target.getAttribute("data-field-name") ?? target.name ?? "";
|
|
42957
42995
|
const fieldMessage = target.validationMessage || "Invalid value";
|
|
42958
|
-
debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
|
|
42996
|
+
debug("forms", "invalid", { mode: formMode, fieldName: fieldName2, fieldMessage });
|
|
42959
42997
|
queueMicrotask(() => {
|
|
42960
42998
|
const form = formRef.current;
|
|
42961
42999
|
if (!form) return;
|
|
@@ -42991,22 +43029,22 @@ var init_Form = __esm({
|
|
|
42991
43029
|
};
|
|
42992
43030
|
const renderField = React85__namespace.default.useCallback(
|
|
42993
43031
|
(field) => {
|
|
42994
|
-
const
|
|
42995
|
-
if (!
|
|
42996
|
-
if (!isFieldVisible(
|
|
43032
|
+
const fieldName2 = field.name || field.field;
|
|
43033
|
+
if (!fieldName2) return null;
|
|
43034
|
+
if (!isFieldVisible(fieldName2)) {
|
|
42997
43035
|
return null;
|
|
42998
43036
|
}
|
|
42999
43037
|
const inputType = determineInputType(field);
|
|
43000
|
-
const label = field.label ||
|
|
43001
|
-
const currentValue = formData[
|
|
43002
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", "data-field":
|
|
43038
|
+
const label = field.label || fieldName2.charAt(0).toUpperCase() + fieldName2.slice(1).replace(/([A-Z])/g, " $1");
|
|
43039
|
+
const currentValue = formData[fieldName2] ?? field.defaultValue ?? "";
|
|
43040
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", "data-field": fieldName2, children: [
|
|
43003
43041
|
inputType !== "checkbox" && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "label", variant: "label", weight: "bold", children: [
|
|
43004
43042
|
label,
|
|
43005
43043
|
field.required && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", color: "error", className: "ml-1", children: "*" })
|
|
43006
43044
|
] }),
|
|
43007
|
-
renderFieldInput(field,
|
|
43045
|
+
renderFieldInput(field, fieldName2, inputType, currentValue, label),
|
|
43008
43046
|
field.hint && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "muted", children: field.hint })
|
|
43009
|
-
] },
|
|
43047
|
+
] }, fieldName2);
|
|
43010
43048
|
},
|
|
43011
43049
|
[formData, isFieldVisible, relationsData, relationsLoading, isLoading]
|
|
43012
43050
|
);
|
|
@@ -43035,8 +43073,8 @@ var init_Form = __esm({
|
|
|
43035
43073
|
}
|
|
43036
43074
|
return field;
|
|
43037
43075
|
}).map((field) => {
|
|
43038
|
-
const
|
|
43039
|
-
const override = fieldOverrides?.find((o) => o.name ===
|
|
43076
|
+
const fieldName2 = field.name || field.field;
|
|
43077
|
+
const override = fieldOverrides?.find((o) => o.name === fieldName2);
|
|
43040
43078
|
if (!override) return field;
|
|
43041
43079
|
return {
|
|
43042
43080
|
...field,
|
|
@@ -43092,11 +43130,11 @@ var init_Form = __esm({
|
|
|
43092
43130
|
] }, section.id);
|
|
43093
43131
|
}).filter(Boolean);
|
|
43094
43132
|
}, [sections, isSectionVisible, collapsedSections, renderField, gap]);
|
|
43095
|
-
function renderFieldInput(field,
|
|
43133
|
+
function renderFieldInput(field, fieldName2, inputType, currentValue, label) {
|
|
43096
43134
|
const commonProps = {
|
|
43097
|
-
id:
|
|
43098
|
-
name:
|
|
43099
|
-
"data-field-name":
|
|
43135
|
+
id: fieldName2,
|
|
43136
|
+
name: fieldName2,
|
|
43137
|
+
"data-field-name": fieldName2,
|
|
43100
43138
|
required: field.required,
|
|
43101
43139
|
disabled: isLoading,
|
|
43102
43140
|
placeholder: field.placeholder,
|
|
@@ -43110,7 +43148,7 @@ var init_Form = __esm({
|
|
|
43110
43148
|
...commonProps,
|
|
43111
43149
|
label: label + (field.required ? " *" : ""),
|
|
43112
43150
|
checked: Boolean(currentValue),
|
|
43113
|
-
onChange: (e) => handleChange(
|
|
43151
|
+
onChange: (e) => handleChange(fieldName2, e.target.checked)
|
|
43114
43152
|
}
|
|
43115
43153
|
);
|
|
43116
43154
|
case "textarea":
|
|
@@ -43119,7 +43157,7 @@ var init_Form = __esm({
|
|
|
43119
43157
|
{
|
|
43120
43158
|
...commonProps,
|
|
43121
43159
|
value: String(currentValue),
|
|
43122
|
-
onChange: (e) => handleChange(
|
|
43160
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43123
43161
|
minLength: field.min,
|
|
43124
43162
|
maxLength: field.max
|
|
43125
43163
|
}
|
|
@@ -43132,14 +43170,14 @@ var init_Form = __esm({
|
|
|
43132
43170
|
...commonProps,
|
|
43133
43171
|
options,
|
|
43134
43172
|
value: String(currentValue),
|
|
43135
|
-
onValueChange: (v) => handleChange(
|
|
43173
|
+
onValueChange: (v) => handleChange(fieldName2, v),
|
|
43136
43174
|
placeholder: field.placeholder || `Select ${label}...`
|
|
43137
43175
|
}
|
|
43138
43176
|
);
|
|
43139
43177
|
}
|
|
43140
43178
|
case "relation": {
|
|
43141
|
-
const relationOptions = relationsData[
|
|
43142
|
-
const relationLoading = relationsLoading[
|
|
43179
|
+
const relationOptions = relationsData[fieldName2] || [];
|
|
43180
|
+
const relationLoading = relationsLoading[fieldName2] || false;
|
|
43143
43181
|
if (field.relation?.cardinality !== void 0 && MANY_CARDINALITIES.includes(field.relation.cardinality)) {
|
|
43144
43182
|
const selectedValues = Array.isArray(currentValue) ? currentValue.map((v) => String(v)) : [];
|
|
43145
43183
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -43151,7 +43189,7 @@ var init_Form = __esm({
|
|
|
43151
43189
|
clearable: true,
|
|
43152
43190
|
options: [...relationOptions],
|
|
43153
43191
|
value: selectedValues,
|
|
43154
|
-
onValueChange: (value) => handleChange(
|
|
43192
|
+
onValueChange: (value) => handleChange(fieldName2, Array.isArray(value) ? value : [value]),
|
|
43155
43193
|
placeholder: field.placeholder || `Select ${label}...`
|
|
43156
43194
|
}
|
|
43157
43195
|
);
|
|
@@ -43161,7 +43199,7 @@ var init_Form = __esm({
|
|
|
43161
43199
|
{
|
|
43162
43200
|
...commonProps,
|
|
43163
43201
|
value: currentValue ? String(currentValue) : void 0,
|
|
43164
|
-
onChange: (value) => handleChange(
|
|
43202
|
+
onChange: (value) => handleChange(fieldName2, value),
|
|
43165
43203
|
options: relationOptions,
|
|
43166
43204
|
isLoading: relationLoading,
|
|
43167
43205
|
placeholder: field.placeholder || `Select ${label}...`,
|
|
@@ -43178,7 +43216,7 @@ var init_Form = __esm({
|
|
|
43178
43216
|
placeholder: field.placeholder,
|
|
43179
43217
|
disabled: isLoading,
|
|
43180
43218
|
value: arrayValue,
|
|
43181
|
-
onChange: (next) => handleChange(
|
|
43219
|
+
onChange: (next) => handleChange(fieldName2, [...next])
|
|
43182
43220
|
}
|
|
43183
43221
|
);
|
|
43184
43222
|
}
|
|
@@ -43190,7 +43228,7 @@ var init_Form = __esm({
|
|
|
43190
43228
|
type: "number",
|
|
43191
43229
|
value: currentValue !== void 0 && currentValue !== "" ? String(currentValue) : "",
|
|
43192
43230
|
onChange: (e) => handleChange(
|
|
43193
|
-
|
|
43231
|
+
fieldName2,
|
|
43194
43232
|
e.target.value ? Number(e.target.value) : void 0
|
|
43195
43233
|
),
|
|
43196
43234
|
min: field.min,
|
|
@@ -43207,7 +43245,7 @@ var init_Form = __esm({
|
|
|
43207
43245
|
icon: LucideIcons2.DollarSign,
|
|
43208
43246
|
value: currentValue !== void 0 && currentValue !== "" ? String(currentValue) : "",
|
|
43209
43247
|
onChange: (e) => handleChange(
|
|
43210
|
-
|
|
43248
|
+
fieldName2,
|
|
43211
43249
|
e.target.value ? Number(e.target.value) : void 0
|
|
43212
43250
|
),
|
|
43213
43251
|
min: field.min,
|
|
@@ -43225,7 +43263,7 @@ var init_Form = __esm({
|
|
|
43225
43263
|
const f3 = files[0];
|
|
43226
43264
|
if (!f3) return;
|
|
43227
43265
|
const reader = new FileReader();
|
|
43228
|
-
reader.onload = () => handleChange(
|
|
43266
|
+
reader.onload = () => handleChange(fieldName2, {
|
|
43229
43267
|
name: f3.name,
|
|
43230
43268
|
mimeType: f3.type,
|
|
43231
43269
|
sizeBytes: f3.size,
|
|
@@ -43242,7 +43280,7 @@ var init_Form = __esm({
|
|
|
43242
43280
|
...commonProps,
|
|
43243
43281
|
type: "date",
|
|
43244
43282
|
value: formatDateValue(currentValue),
|
|
43245
|
-
onChange: (e) => handleChange(
|
|
43283
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
43246
43284
|
}
|
|
43247
43285
|
);
|
|
43248
43286
|
case "datetime-local":
|
|
@@ -43252,7 +43290,7 @@ var init_Form = __esm({
|
|
|
43252
43290
|
...commonProps,
|
|
43253
43291
|
type: "datetime-local",
|
|
43254
43292
|
value: formatDateTimeValue(currentValue),
|
|
43255
|
-
onChange: (e) => handleChange(
|
|
43293
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
43256
43294
|
}
|
|
43257
43295
|
);
|
|
43258
43296
|
case "email":
|
|
@@ -43262,7 +43300,7 @@ var init_Form = __esm({
|
|
|
43262
43300
|
...commonProps,
|
|
43263
43301
|
type: "email",
|
|
43264
43302
|
value: String(currentValue),
|
|
43265
|
-
onChange: (e) => handleChange(
|
|
43303
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43266
43304
|
minLength: field.min,
|
|
43267
43305
|
maxLength: field.max
|
|
43268
43306
|
}
|
|
@@ -43274,7 +43312,7 @@ var init_Form = __esm({
|
|
|
43274
43312
|
...commonProps,
|
|
43275
43313
|
type: "url",
|
|
43276
43314
|
value: String(currentValue),
|
|
43277
|
-
onChange: (e) => handleChange(
|
|
43315
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43278
43316
|
minLength: field.min,
|
|
43279
43317
|
maxLength: field.max
|
|
43280
43318
|
}
|
|
@@ -43286,7 +43324,7 @@ var init_Form = __esm({
|
|
|
43286
43324
|
...commonProps,
|
|
43287
43325
|
type: "password",
|
|
43288
43326
|
value: String(currentValue),
|
|
43289
|
-
onChange: (e) => handleChange(
|
|
43327
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43290
43328
|
minLength: field.min,
|
|
43291
43329
|
maxLength: field.max
|
|
43292
43330
|
}
|
|
@@ -43299,7 +43337,7 @@ var init_Form = __esm({
|
|
|
43299
43337
|
...commonProps,
|
|
43300
43338
|
type: "text",
|
|
43301
43339
|
value: String(currentValue),
|
|
43302
|
-
onChange: (e) => handleChange(
|
|
43340
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43303
43341
|
minLength: field.min,
|
|
43304
43342
|
maxLength: field.max
|
|
43305
43343
|
}
|
|
@@ -43656,7 +43694,7 @@ function entityFieldsFromListItem(item) {
|
|
|
43656
43694
|
}
|
|
43657
43695
|
return result;
|
|
43658
43696
|
}
|
|
43659
|
-
function getStatusStyle(
|
|
43697
|
+
function getStatusStyle(fieldName2, value) {
|
|
43660
43698
|
const val = String(value).toLowerCase();
|
|
43661
43699
|
if (val.includes("complete") || val.includes("done"))
|
|
43662
43700
|
return STATUS_STYLES.complete;
|
|
@@ -43672,12 +43710,12 @@ function getStatusStyle(fieldName, value) {
|
|
|
43672
43710
|
if (val.includes("low")) return STATUS_STYLES.low;
|
|
43673
43711
|
return STATUS_STYLES.default;
|
|
43674
43712
|
}
|
|
43675
|
-
function formatValue3(value,
|
|
43713
|
+
function formatValue3(value, fieldName2) {
|
|
43676
43714
|
if (typeof value === "number") {
|
|
43677
|
-
if (
|
|
43715
|
+
if (fieldName2.toLowerCase().includes("progress") || fieldName2.toLowerCase().includes("percent")) {
|
|
43678
43716
|
return `${value}%`;
|
|
43679
43717
|
}
|
|
43680
|
-
if (
|
|
43718
|
+
if (fieldName2.toLowerCase().includes("budget") || fieldName2.toLowerCase().includes("cost")) {
|
|
43681
43719
|
return new Intl.NumberFormat("en-US", {
|
|
43682
43720
|
style: "currency",
|
|
43683
43721
|
currency: "USD",
|
|
@@ -43700,8 +43738,8 @@ function formatValue3(value, fieldName) {
|
|
|
43700
43738
|
}
|
|
43701
43739
|
return String(value);
|
|
43702
43740
|
}
|
|
43703
|
-
function formatFieldLabel2(
|
|
43704
|
-
return humanizeFieldName(
|
|
43741
|
+
function formatFieldLabel2(fieldName2) {
|
|
43742
|
+
return humanizeFieldName(fieldName2).replace(/\sId$/, "").trim();
|
|
43705
43743
|
}
|
|
43706
43744
|
var STATUS_STYLES, StatusBadge, ProgressIndicator, List3;
|
|
43707
43745
|
var init_List = __esm({
|
|
@@ -43769,9 +43807,9 @@ var init_List = __esm({
|
|
|
43769
43807
|
};
|
|
43770
43808
|
StatusBadge = ({
|
|
43771
43809
|
value,
|
|
43772
|
-
fieldName
|
|
43810
|
+
fieldName: fieldName2
|
|
43773
43811
|
}) => {
|
|
43774
|
-
const style = getStatusStyle(
|
|
43812
|
+
const style = getStatusStyle(fieldName2, value);
|
|
43775
43813
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
43776
43814
|
Typography,
|
|
43777
43815
|
{
|
|
@@ -46703,8 +46741,8 @@ var init_StatCard = __esm({
|
|
|
46703
46741
|
return items.length;
|
|
46704
46742
|
}
|
|
46705
46743
|
if (field.includes(":")) {
|
|
46706
|
-
const [
|
|
46707
|
-
return items.filter((item) => item[
|
|
46744
|
+
const [fieldName2, fieldValue] = field.split(":");
|
|
46745
|
+
return items.filter((item) => item[fieldName2] === fieldValue).length;
|
|
46708
46746
|
}
|
|
46709
46747
|
const fieldExistsOnItems = items.some((item) => field in item);
|
|
46710
46748
|
if (fieldExistsOnItems) {
|
|
@@ -48224,6 +48262,8 @@ var init_component_registry_generated = __esm({
|
|
|
48224
48262
|
init_DocSearch();
|
|
48225
48263
|
init_DocSidebar();
|
|
48226
48264
|
init_DocTOC();
|
|
48265
|
+
init_DocumentDetails();
|
|
48266
|
+
init_DocumentPanel();
|
|
48227
48267
|
init_DocumentViewer();
|
|
48228
48268
|
init_DrawFxLayer();
|
|
48229
48269
|
init_DrawGroup();
|
|
@@ -48333,7 +48373,7 @@ var init_component_registry_generated = __esm({
|
|
|
48333
48373
|
init_RelationSelect();
|
|
48334
48374
|
init_RepeatableFormSection();
|
|
48335
48375
|
init_ReplyTree();
|
|
48336
|
-
|
|
48376
|
+
init_RichTextEditor();
|
|
48337
48377
|
init_RuntimeDebugger2();
|
|
48338
48378
|
init_ScaledDiagram();
|
|
48339
48379
|
init_ScoreDisplay();
|
|
@@ -48496,6 +48536,8 @@ var init_component_registry_generated = __esm({
|
|
|
48496
48536
|
"DocSearch": DocSearch,
|
|
48497
48537
|
"DocSidebar": DocSidebar,
|
|
48498
48538
|
"DocTOC": DocTOC,
|
|
48539
|
+
"DocumentDetails": DocumentDetails,
|
|
48540
|
+
"DocumentPanel": DocumentPanel,
|
|
48499
48541
|
"DocumentViewer": DocumentViewer,
|
|
48500
48542
|
"DrawFxLayer": DrawFxLayer,
|
|
48501
48543
|
"DrawGroup": DrawGroup,
|
|
@@ -48607,7 +48649,7 @@ var init_component_registry_generated = __esm({
|
|
|
48607
48649
|
"RelationSelect": RelationSelect,
|
|
48608
48650
|
"RepeatableFormSection": RepeatableFormSection,
|
|
48609
48651
|
"ReplyTree": ReplyTree,
|
|
48610
|
-
"
|
|
48652
|
+
"RichTextEditor": RichTextEditor,
|
|
48611
48653
|
"RuntimeDebugger": RuntimeDebugger,
|
|
48612
48654
|
"ScaledDiagram": ScaledDiagram,
|
|
48613
48655
|
"ScoreDisplay": ScoreDisplay,
|
|
@@ -48761,10 +48803,10 @@ function enrichFormFields(fields, entityDef) {
|
|
|
48761
48803
|
}
|
|
48762
48804
|
if (field && typeof field === "object" && !Array.isArray(field) && !React85__namespace.default.isValidElement(field) && !(field instanceof Date)) {
|
|
48763
48805
|
const obj = field;
|
|
48764
|
-
const
|
|
48765
|
-
if (!
|
|
48806
|
+
const fieldName2 = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
|
|
48807
|
+
if (!fieldName2) return field;
|
|
48766
48808
|
if (obj.type || obj.inputType) return field;
|
|
48767
|
-
const entityField = fieldMap.get(
|
|
48809
|
+
const entityField = fieldMap.get(fieldName2);
|
|
48768
48810
|
if (!entityField) return field;
|
|
48769
48811
|
const enriched = { ...obj, type: entityField.type };
|
|
48770
48812
|
if (entityField.required && !("required" in obj)) {
|
|
@@ -48814,9 +48856,9 @@ function enrichDetailFields(fields, entityDef) {
|
|
|
48814
48856
|
}
|
|
48815
48857
|
if (field && typeof field === "object" && !Array.isArray(field) && !React85__namespace.default.isValidElement(field) && !(field instanceof Date)) {
|
|
48816
48858
|
const obj = field;
|
|
48817
|
-
const
|
|
48818
|
-
if (!
|
|
48819
|
-
const meta = metaFor(
|
|
48859
|
+
const fieldName2 = typeof obj.key === "string" ? obj.key : typeof obj.name === "string" ? obj.name : void 0;
|
|
48860
|
+
if (!fieldName2 || obj.type) return field;
|
|
48861
|
+
const meta = metaFor(fieldName2);
|
|
48820
48862
|
return meta ? { ...obj, ...meta } : field;
|
|
48821
48863
|
}
|
|
48822
48864
|
return field;
|
|
@@ -49655,9 +49697,9 @@ function UISlotRenderer({
|
|
|
49655
49697
|
"ui-slot-renderer relative min-h-full",
|
|
49656
49698
|
className
|
|
49657
49699
|
), children: [
|
|
49658
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex min-h-full", children: [
|
|
49659
|
-
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "sidebar", className: "ui-slot-sidebar min-w-0 shrink-0" }),
|
|
49660
|
-
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "main", className: "ui-slot-main flex-1 min-h-[200px]" })
|
|
49700
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex min-h-full flex-col lg:flex-row", children: [
|
|
49701
|
+
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "sidebar", className: "ui-slot-sidebar min-w-0 lg:shrink-0" }),
|
|
49702
|
+
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "main", className: "ui-slot-main flex-1 min-w-0 min-h-[200px]" })
|
|
49661
49703
|
] }),
|
|
49662
49704
|
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "modal", portal: true }),
|
|
49663
49705
|
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "drawer", portal: true }),
|
|
@@ -50180,7 +50222,7 @@ function buildTraitRenderConfig(binding, traitConfigsByName, payload) {
|
|
|
50180
50222
|
}
|
|
50181
50223
|
return void 0;
|
|
50182
50224
|
}
|
|
50183
|
-
function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
|
|
50225
|
+
function createSharedEntityWriter(binding, tick, traitStatesRef, emit, traitConfigsByName) {
|
|
50184
50226
|
return (scratch) => {
|
|
50185
50227
|
const traitName = binding.trait.name;
|
|
50186
50228
|
const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
|
|
@@ -50189,9 +50231,13 @@ function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
|
|
|
50189
50231
|
const writes = [];
|
|
50190
50232
|
const ctx = evaluator.createMinimalContext(scratchEntity, {}, currentState);
|
|
50191
50233
|
const declaredDefaults = runtime.collectDeclaredConfigDefaults(binding.trait);
|
|
50192
|
-
const
|
|
50193
|
-
|
|
50194
|
-
|
|
50234
|
+
const resolvedByName = traitConfigsByName?.[traitName];
|
|
50235
|
+
const callSiteRaw = getBindingConfig(binding);
|
|
50236
|
+
const callSiteConfig = callSiteRaw ? Object.fromEntries(
|
|
50237
|
+
Object.entries(callSiteRaw).filter(([, v]) => !containsConfigForward(v))
|
|
50238
|
+
) : void 0;
|
|
50239
|
+
if (declaredDefaults || resolvedByName || callSiteConfig) {
|
|
50240
|
+
ctx.config = { ...declaredDefaults ?? {}, ...resolvedByName ?? {}, ...callSiteConfig ?? {} };
|
|
50195
50241
|
}
|
|
50196
50242
|
ctx.mutateEntity = (changes) => {
|
|
50197
50243
|
for (const [field, value] of Object.entries(changes)) {
|
|
@@ -50794,7 +50840,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50794
50840
|
const interval = entries[0].tick.interval;
|
|
50795
50841
|
const onDue = timedTick(`tick:shared:${group.storeKey}@${String(interval)}`, () => {
|
|
50796
50842
|
const writers = entries.map(
|
|
50797
|
-
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
|
|
50843
|
+
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter, traitConfigsByName)
|
|
50798
50844
|
);
|
|
50799
50845
|
runTickFrame(group.storeKey, writers, sharedEntityStore);
|
|
50800
50846
|
});
|