@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
|
@@ -24025,8 +24025,9 @@ function DataGrid({
|
|
|
24025
24025
|
const titleField = fieldDefs.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fieldDefs[0];
|
|
24026
24026
|
const badgeFields = fieldDefs.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
24027
24027
|
const bodyFields = fieldDefs.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
|
|
24028
|
-
const
|
|
24029
|
-
const
|
|
24028
|
+
const inlineCap = Math.min(maxInlineActions ?? 1, 1);
|
|
24029
|
+
const inlineCardActions = actionDefs.filter((a) => a.variant === "primary").slice(0, inlineCap);
|
|
24030
|
+
const menuCardActions = actionDefs.filter((a) => !inlineCardActions.includes(a));
|
|
24030
24031
|
const fireAction = (action, itemData) => {
|
|
24031
24032
|
if (action.navigatesTo) {
|
|
24032
24033
|
const url = action.navigatesTo.replace(
|
|
@@ -24046,6 +24047,9 @@ function DataGrid({
|
|
|
24046
24047
|
e.stopPropagation();
|
|
24047
24048
|
fireAction(action, itemData);
|
|
24048
24049
|
};
|
|
24050
|
+
const cardClickAction = actionDefs.find((a) => a.variant !== "danger");
|
|
24051
|
+
const handleCardClick = cardClickAction ? (itemData) => () => fireAction(cardClickAction, itemData) : void 0;
|
|
24052
|
+
const stopCardClick = handleCardClick ? (e) => e.stopPropagation() : void 0;
|
|
24049
24053
|
const hasRenderProp = typeof children === "function";
|
|
24050
24054
|
React77.useEffect(() => {
|
|
24051
24055
|
if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
|
|
@@ -24117,55 +24121,40 @@ function DataGrid({
|
|
|
24117
24121
|
{
|
|
24118
24122
|
"data-entity-row": true,
|
|
24119
24123
|
"data-entity-id": id,
|
|
24120
|
-
|
|
24124
|
+
onClick: handleCardClick?.(itemData),
|
|
24125
|
+
className: cn("relative group/rowactions", handleCardClick && "cursor-pointer", isSelected && "ring-2 ring-primary rounded-lg"),
|
|
24121
24126
|
children: [
|
|
24122
24127
|
children(itemData, index),
|
|
24123
|
-
actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.
|
|
24124
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
24125
|
-
|
|
24126
|
-
|
|
24127
|
-
|
|
24128
|
-
|
|
24129
|
-
|
|
24130
|
-
|
|
24131
|
-
|
|
24132
|
-
|
|
24133
|
-
|
|
24134
|
-
|
|
24135
|
-
|
|
24136
|
-
|
|
24137
|
-
|
|
24138
|
-
|
|
24139
|
-
|
|
24140
|
-
)),
|
|
24141
|
-
maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
|
|
24142
|
-
exports.Menu,
|
|
24143
|
-
{
|
|
24144
|
-
position: "bottom-end",
|
|
24145
|
-
trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
24146
|
-
items: actionDefs.slice(maxInlineActions).map((action) => ({
|
|
24147
|
-
label: action.label,
|
|
24148
|
-
icon: action.icon,
|
|
24149
|
-
event: action.event,
|
|
24150
|
-
onClick: () => fireAction(action, itemData)
|
|
24151
|
-
}))
|
|
24152
|
-
}
|
|
24153
|
-
)
|
|
24154
|
-
] }),
|
|
24155
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.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(
|
|
24128
|
+
actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.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(exports.HStack, { gap: "xs", className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5", children: [
|
|
24129
|
+
inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
24130
|
+
exports.Button,
|
|
24131
|
+
{
|
|
24132
|
+
variant: "primary",
|
|
24133
|
+
size: "sm",
|
|
24134
|
+
onClick: handleActionClick(action, itemData),
|
|
24135
|
+
"data-testid": `action-${action.event}`,
|
|
24136
|
+
"data-row-id": String(itemData.id),
|
|
24137
|
+
children: [
|
|
24138
|
+
action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
|
|
24139
|
+
action.label
|
|
24140
|
+
]
|
|
24141
|
+
},
|
|
24142
|
+
idx
|
|
24143
|
+
)),
|
|
24144
|
+
menuCardActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
24156
24145
|
exports.Menu,
|
|
24157
24146
|
{
|
|
24158
24147
|
position: "bottom-end",
|
|
24159
24148
|
trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
24160
|
-
items:
|
|
24149
|
+
items: menuCardActions.map((action) => ({
|
|
24161
24150
|
label: action.label,
|
|
24162
24151
|
icon: action.icon,
|
|
24163
|
-
|
|
24152
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
24164
24153
|
onClick: () => fireAction(action, itemData)
|
|
24165
24154
|
}))
|
|
24166
24155
|
}
|
|
24167
|
-
)
|
|
24168
|
-
] })
|
|
24156
|
+
)
|
|
24157
|
+
] }) })
|
|
24169
24158
|
]
|
|
24170
24159
|
},
|
|
24171
24160
|
id
|
|
@@ -24179,12 +24168,14 @@ function DataGrid({
|
|
|
24179
24168
|
{
|
|
24180
24169
|
"data-entity-row": true,
|
|
24181
24170
|
"data-entity-id": id,
|
|
24171
|
+
onClick: handleCardClick?.(itemData),
|
|
24182
24172
|
className: cn(
|
|
24183
24173
|
"bg-card rounded-lg",
|
|
24184
24174
|
"border border-border",
|
|
24185
24175
|
"shadow-elevation-card hover:shadow-elevation-dialog",
|
|
24186
24176
|
"hover:border-primary transition-all",
|
|
24187
24177
|
"flex flex-col",
|
|
24178
|
+
handleCardClick && "cursor-pointer",
|
|
24188
24179
|
isSelected && "ring-2 ring-primary border-primary"
|
|
24189
24180
|
),
|
|
24190
24181
|
children: [
|
|
@@ -24234,53 +24225,35 @@ function DataGrid({
|
|
|
24234
24225
|
] }, field.name);
|
|
24235
24226
|
}) })
|
|
24236
24227
|
] }),
|
|
24237
|
-
|
|
24238
|
-
|
|
24228
|
+
actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", onClick: stopCardClick, className: "flex-shrink-0", children: [
|
|
24229
|
+
inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
24239
24230
|
exports.Button,
|
|
24240
24231
|
{
|
|
24241
|
-
variant:
|
|
24232
|
+
variant: "primary",
|
|
24242
24233
|
size: "sm",
|
|
24243
24234
|
onClick: handleActionClick(action, itemData),
|
|
24244
24235
|
"data-testid": `action-${action.event}`,
|
|
24245
24236
|
"data-row-id": String(itemData.id),
|
|
24246
24237
|
"aria-label": action.label,
|
|
24247
24238
|
title: action.label,
|
|
24248
|
-
className: cn(
|
|
24249
|
-
action.variant === "primary" ? void 0 : "text-muted-foreground hover:text-foreground",
|
|
24250
|
-
action.icon && "px-2"
|
|
24251
|
-
),
|
|
24239
|
+
className: cn(action.icon && "px-2"),
|
|
24252
24240
|
children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
|
|
24253
24241
|
},
|
|
24254
24242
|
idx
|
|
24255
24243
|
)),
|
|
24256
|
-
|
|
24244
|
+
menuCardActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
24257
24245
|
exports.Menu,
|
|
24258
24246
|
{
|
|
24259
24247
|
position: "bottom-end",
|
|
24260
24248
|
trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
24261
|
-
items:
|
|
24249
|
+
items: menuCardActions.map((action) => ({
|
|
24262
24250
|
label: action.label,
|
|
24263
24251
|
icon: action.icon,
|
|
24264
|
-
|
|
24252
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
24265
24253
|
onClick: () => fireAction(action, itemData)
|
|
24266
24254
|
}))
|
|
24267
24255
|
}
|
|
24268
|
-
)
|
|
24269
|
-
dangerActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
24270
|
-
exports.Button,
|
|
24271
|
-
{
|
|
24272
|
-
variant: "ghost",
|
|
24273
|
-
size: "sm",
|
|
24274
|
-
onClick: handleActionClick(action, itemData),
|
|
24275
|
-
"data-testid": `action-${action.event}`,
|
|
24276
|
-
"data-row-id": String(itemData.id),
|
|
24277
|
-
"aria-label": action.label,
|
|
24278
|
-
title: action.label,
|
|
24279
|
-
className: "text-error hover:text-error hover:bg-error/10 px-2",
|
|
24280
|
-
children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
|
|
24281
|
-
},
|
|
24282
|
-
`danger-${idx}`
|
|
24283
|
-
))
|
|
24256
|
+
)
|
|
24284
24257
|
] })
|
|
24285
24258
|
] }) }),
|
|
24286
24259
|
bodyFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "px-4 pt-2 pb-4 flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", children: [
|
|
@@ -24301,8 +24274,8 @@ function DataGrid({
|
|
|
24301
24274
|
}
|
|
24302
24275
|
return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
|
|
24303
24276
|
field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
24304
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
24305
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", children: formatValue(value, field.format) })
|
|
24277
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", className: "sr-only", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
24278
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", color: "secondary", children: formatValue(value, field.format) })
|
|
24306
24279
|
] }, field.name);
|
|
24307
24280
|
}) })
|
|
24308
24281
|
] }) })
|
|
@@ -24522,54 +24495,59 @@ function DataList({
|
|
|
24522
24495
|
if (!itemActions || itemActions.length === 0) return null;
|
|
24523
24496
|
const inline = maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions;
|
|
24524
24497
|
const overflow = maxInlineActions != null ? itemActions.slice(maxInlineActions) : [];
|
|
24525
|
-
return
|
|
24526
|
-
|
|
24527
|
-
|
|
24528
|
-
|
|
24529
|
-
|
|
24530
|
-
|
|
24531
|
-
|
|
24532
|
-
|
|
24533
|
-
|
|
24534
|
-
|
|
24535
|
-
action
|
|
24536
|
-
|
|
24537
|
-
|
|
24538
|
-
|
|
24539
|
-
|
|
24540
|
-
|
|
24541
|
-
|
|
24542
|
-
|
|
24543
|
-
|
|
24544
|
-
|
|
24545
|
-
|
|
24546
|
-
|
|
24547
|
-
|
|
24548
|
-
|
|
24549
|
-
|
|
24550
|
-
|
|
24551
|
-
|
|
24552
|
-
|
|
24553
|
-
|
|
24554
|
-
|
|
24555
|
-
|
|
24556
|
-
|
|
24557
|
-
|
|
24558
|
-
|
|
24559
|
-
|
|
24560
|
-
|
|
24561
|
-
|
|
24562
|
-
|
|
24563
|
-
|
|
24564
|
-
|
|
24498
|
+
return (
|
|
24499
|
+
// stopPropagation at the cluster: the "⋯" trigger opens the overflow
|
|
24500
|
+
// menu without also firing the row's default click (inline buttons
|
|
24501
|
+
// already stop it in handleActionClick; the Menu panel is portaled).
|
|
24502
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", onClick: rowClickEvent ? (e) => e.stopPropagation() : void 0, className: "flex-shrink-0", children: [
|
|
24503
|
+
inline.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
24504
|
+
exports.Button,
|
|
24505
|
+
{
|
|
24506
|
+
variant: action.variant ?? "ghost",
|
|
24507
|
+
size: "sm",
|
|
24508
|
+
onClick: handleActionClick(action, itemData),
|
|
24509
|
+
"data-testid": `action-${action.event}`,
|
|
24510
|
+
"data-row-id": String(itemData.id),
|
|
24511
|
+
className: cn(
|
|
24512
|
+
action.variant === "danger" && "text-error hover:bg-error/10",
|
|
24513
|
+
// Must sit on the Button itself: the variant's own text colour
|
|
24514
|
+
// beats an inherited one from the row wrapper.
|
|
24515
|
+
onPrimary && "!text-primary-foreground hover:bg-primary-foreground/15"
|
|
24516
|
+
),
|
|
24517
|
+
children: [
|
|
24518
|
+
action.icon && renderIconInput2(action.icon, { size: "xs", className: "mr-1" }),
|
|
24519
|
+
action.label
|
|
24520
|
+
]
|
|
24521
|
+
},
|
|
24522
|
+
idx
|
|
24523
|
+
)),
|
|
24524
|
+
overflow.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
24525
|
+
exports.Menu,
|
|
24526
|
+
{
|
|
24527
|
+
position: "bottom-end",
|
|
24528
|
+
trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
24529
|
+
items: overflow.map((action) => ({
|
|
24530
|
+
label: action.label,
|
|
24531
|
+
icon: action.icon,
|
|
24532
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
24533
|
+
onClick: () => eventBus.emit(`UI:${action.event}`, {
|
|
24534
|
+
id: itemData.id,
|
|
24535
|
+
row: itemData
|
|
24536
|
+
})
|
|
24537
|
+
}))
|
|
24538
|
+
}
|
|
24539
|
+
)
|
|
24540
|
+
] })
|
|
24541
|
+
);
|
|
24565
24542
|
};
|
|
24543
|
+
const rowClickEvent = itemClickEvent || itemActions?.find((a) => a.variant !== "danger")?.event;
|
|
24566
24544
|
const handleRowClick = (itemData) => () => {
|
|
24567
|
-
if (!
|
|
24545
|
+
if (!rowClickEvent) return;
|
|
24568
24546
|
const payload = {
|
|
24569
24547
|
id: itemData.id,
|
|
24570
24548
|
row: itemData
|
|
24571
24549
|
};
|
|
24572
|
-
eventBus.emit(`UI:${
|
|
24550
|
+
eventBus.emit(`UI:${rowClickEvent}`, payload);
|
|
24573
24551
|
};
|
|
24574
24552
|
if (isLoading) {
|
|
24575
24553
|
return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "body", color: "secondary", children: t("loading.items") }) });
|
|
@@ -24617,10 +24595,10 @@ function DataList({
|
|
|
24617
24595
|
{
|
|
24618
24596
|
"data-entity-row": true,
|
|
24619
24597
|
"data-entity-id": id,
|
|
24620
|
-
onClick:
|
|
24598
|
+
onClick: rowClickEvent ? handleRowClick(itemData) : void 0,
|
|
24621
24599
|
className: cn(
|
|
24622
24600
|
"flex px-4 group/rowactions",
|
|
24623
|
-
|
|
24601
|
+
rowClickEvent && "cursor-pointer",
|
|
24624
24602
|
isSent ? "justify-end" : "justify-start"
|
|
24625
24603
|
),
|
|
24626
24604
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -24696,7 +24674,7 @@ function DataList({
|
|
|
24696
24674
|
const id2 = itemData.id || String(index);
|
|
24697
24675
|
const actions = renderItemActions(itemData);
|
|
24698
24676
|
return wrapDnd(
|
|
24699
|
-
/* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { "data-entity-row": true, "data-entity-id": id2, onClick:
|
|
24677
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { "data-entity-row": true, "data-entity-id": id2, onClick: rowClickEvent ? handleRowClick(itemData) : void 0, className: cn("relative group/rowactions", rowClickEvent && "cursor-pointer"), children: [
|
|
24700
24678
|
children(itemData, index),
|
|
24701
24679
|
actions && /* @__PURE__ */ jsxRuntime.jsxs(exports.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: [
|
|
24702
24680
|
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5 [@media(pointer:coarse)]:hidden", children: actions }),
|
|
@@ -24708,7 +24686,6 @@ function DataList({
|
|
|
24708
24686
|
items: (itemActions ?? []).map((action) => ({
|
|
24709
24687
|
label: action.label,
|
|
24710
24688
|
icon: action.icon,
|
|
24711
|
-
event: action.event,
|
|
24712
24689
|
variant: action.variant === "danger" ? "danger" : "default",
|
|
24713
24690
|
onClick: () => eventBus.emit(`UI:${action.event}`, {
|
|
24714
24691
|
id: itemData.id,
|
|
@@ -24725,12 +24702,16 @@ function DataList({
|
|
|
24725
24702
|
const id = itemData.id || String(index);
|
|
24726
24703
|
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
24727
24704
|
return wrapDnd(
|
|
24728
|
-
/* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { "data-entity-row": true, "data-entity-id": id, onClick:
|
|
24705
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { "data-entity-row": true, "data-entity-id": id, onClick: rowClickEvent ? handleRowClick(itemData) : void 0, className: cn(rowClickEvent && "cursor-pointer"), children: [
|
|
24729
24706
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
24730
24707
|
exports.Box,
|
|
24731
24708
|
{
|
|
24732
24709
|
className: cn(
|
|
24733
|
-
|
|
24710
|
+
// items-start, not items-center: a multi-line row (title + meta +
|
|
24711
|
+
// progress) centred its action cluster in the vertical middle, so
|
|
24712
|
+
// the buttons floated between the meta fields instead of anchoring
|
|
24713
|
+
// to the title they act on (U-DATALIST-ACTIONS-FLOAT-MID-ROW).
|
|
24714
|
+
"group flex items-start gap-4 transition-all duration-fast",
|
|
24734
24715
|
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
24735
24716
|
"hover:bg-muted/80",
|
|
24736
24717
|
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
@@ -24761,11 +24742,19 @@ function DataList({
|
|
|
24761
24742
|
if (value === void 0 || value === null || value === "") return null;
|
|
24762
24743
|
return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
|
|
24763
24744
|
field.icon && renderIconInput2(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
24764
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
24765
|
-
|
|
24766
|
-
|
|
24767
|
-
|
|
24768
|
-
|
|
24745
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
24746
|
+
exports.Typography,
|
|
24747
|
+
{
|
|
24748
|
+
variant: "caption",
|
|
24749
|
+
color: "secondary",
|
|
24750
|
+
className: cn(field.format !== "boolean" && "sr-only"),
|
|
24751
|
+
children: [
|
|
24752
|
+
field.label ?? fieldLabel3(field.name),
|
|
24753
|
+
":"
|
|
24754
|
+
]
|
|
24755
|
+
}
|
|
24756
|
+
),
|
|
24757
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", color: "secondary", children: formatValue2(value, field.format, { yes: t("common.yes"), no: t("common.no") }) })
|
|
24769
24758
|
] }, field.name);
|
|
24770
24759
|
}) }),
|
|
24771
24760
|
progressFields.map((field) => {
|
|
@@ -24784,7 +24773,7 @@ function DataList({
|
|
|
24784
24773
|
]
|
|
24785
24774
|
}
|
|
24786
24775
|
),
|
|
24787
|
-
isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "
|
|
24776
|
+
(isCard || isCompact) && !isLast && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: cn("border-b border-border/40", isCompact ? "mx-4" : "mx-6") })
|
|
24788
24777
|
] }, id)
|
|
24789
24778
|
);
|
|
24790
24779
|
};
|
|
@@ -24794,7 +24783,13 @@ function DataList({
|
|
|
24794
24783
|
{
|
|
24795
24784
|
className: cn(
|
|
24796
24785
|
isCard && "bg-card rounded-xl border border-border shadow-elevation-dialog overflow-hidden",
|
|
24797
|
-
|
|
24786
|
+
// `gap-*` is inert on a block container, and Box only emits a display
|
|
24787
|
+
// class when its `display` prop is set — so every non-card list had
|
|
24788
|
+
// been asking for a gap that CSS silently dropped. flex-col makes it
|
|
24789
|
+
// real. `compact` keeps gap-0 on purpose: it separates with the row
|
|
24790
|
+
// divider above instead, never both (Almadar_UI_Beauty.md 6).
|
|
24791
|
+
!isCard && "flex flex-col",
|
|
24792
|
+
!isCard && !isCompact && gapClass,
|
|
24798
24793
|
listLookStyles[look],
|
|
24799
24794
|
className
|
|
24800
24795
|
),
|
|
@@ -33334,7 +33329,7 @@ var init_MapView = __esm({
|
|
|
33334
33329
|
shadowSize: [41, 41]
|
|
33335
33330
|
});
|
|
33336
33331
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
33337
|
-
const { useEffect: useEffect69, useRef: useRef65, useCallback: useCallback108, useState:
|
|
33332
|
+
const { useEffect: useEffect69, useRef: useRef65, useCallback: useCallback108, useState: useState106 } = React77__namespace.default;
|
|
33338
33333
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
33339
33334
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
33340
33335
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -33379,7 +33374,7 @@ var init_MapView = __esm({
|
|
|
33379
33374
|
showAttribution = true
|
|
33380
33375
|
}) {
|
|
33381
33376
|
const eventBus = useEventBus2();
|
|
33382
|
-
const [clickedPosition, setClickedPosition] =
|
|
33377
|
+
const [clickedPosition, setClickedPosition] = useState106(null);
|
|
33383
33378
|
const handleMapClick = useCallback108((lat, lng) => {
|
|
33384
33379
|
if (showClickedPin) {
|
|
33385
33380
|
setClickedPosition({ lat, lng });
|
|
@@ -37741,741 +37736,775 @@ var init_PositionedCanvas = __esm({
|
|
|
37741
37736
|
exports.PositionedCanvas.displayName = "PositionedCanvas";
|
|
37742
37737
|
}
|
|
37743
37738
|
});
|
|
37744
|
-
function
|
|
37745
|
-
|
|
37746
|
-
|
|
37747
|
-
|
|
37739
|
+
function safeUrl(raw, kinds) {
|
|
37740
|
+
const url = raw.trim();
|
|
37741
|
+
if (url.startsWith("#") || url.startsWith("/")) return url;
|
|
37742
|
+
const lower = url.toLowerCase();
|
|
37743
|
+
for (const kind of kinds) {
|
|
37744
|
+
if (lower.startsWith(kind)) return url;
|
|
37745
|
+
}
|
|
37746
|
+
return null;
|
|
37748
37747
|
}
|
|
37749
|
-
function
|
|
37750
|
-
|
|
37751
|
-
|
|
37752
|
-
const
|
|
37753
|
-
|
|
37754
|
-
|
|
37755
|
-
|
|
37756
|
-
|
|
37757
|
-
|
|
37748
|
+
function sanitizeNode(el) {
|
|
37749
|
+
const children = Array.from(el.children);
|
|
37750
|
+
for (const child of children) {
|
|
37751
|
+
const tag = child.tagName.toLowerCase();
|
|
37752
|
+
if (DROP_TAGS.has(tag)) {
|
|
37753
|
+
child.remove();
|
|
37754
|
+
continue;
|
|
37755
|
+
}
|
|
37756
|
+
const allowed = ALLOWED_ATTRS[tag];
|
|
37757
|
+
if (!allowed) {
|
|
37758
|
+
sanitizeNode(child);
|
|
37759
|
+
child.replaceWith(...Array.from(child.childNodes));
|
|
37760
|
+
continue;
|
|
37761
|
+
}
|
|
37762
|
+
for (const attr of Array.from(child.attributes)) {
|
|
37763
|
+
const name = attr.name.toLowerCase();
|
|
37764
|
+
if (!allowed.includes(name)) {
|
|
37765
|
+
child.removeAttribute(attr.name);
|
|
37766
|
+
continue;
|
|
37767
|
+
}
|
|
37768
|
+
if (name === "href") {
|
|
37769
|
+
const url = safeUrl(attr.value, ["http://", "https://", "mailto:"]);
|
|
37770
|
+
if (url === null) child.removeAttribute(attr.name);
|
|
37771
|
+
else child.setAttribute("href", url);
|
|
37772
|
+
}
|
|
37773
|
+
if (name === "src") {
|
|
37774
|
+
const url = safeUrl(attr.value, ["http://", "https://", "data:image/"]);
|
|
37775
|
+
if (url === null) child.remove();
|
|
37776
|
+
else child.setAttribute("src", url);
|
|
37777
|
+
}
|
|
37778
|
+
}
|
|
37779
|
+
sanitizeNode(child);
|
|
37780
|
+
}
|
|
37758
37781
|
}
|
|
37759
|
-
function
|
|
37760
|
-
|
|
37761
|
-
|
|
37762
|
-
|
|
37763
|
-
|
|
37764
|
-
|
|
37765
|
-
|
|
37766
|
-
children: [
|
|
37767
|
-
{ id: nextBlockId("li"), type: "paragraph", content: "" }
|
|
37768
|
-
]
|
|
37769
|
-
};
|
|
37770
|
-
case "image":
|
|
37771
|
-
return {
|
|
37772
|
-
id: nextBlockId(type),
|
|
37773
|
-
type,
|
|
37774
|
-
content: "",
|
|
37775
|
-
metadata: { url: "", caption: "" }
|
|
37776
|
-
};
|
|
37777
|
-
case "code":
|
|
37778
|
-
return {
|
|
37779
|
-
id: nextBlockId(type),
|
|
37780
|
-
type,
|
|
37781
|
-
content: "",
|
|
37782
|
-
metadata: { language: "plaintext" }
|
|
37783
|
-
};
|
|
37784
|
-
case "divider":
|
|
37785
|
-
return { id: nextBlockId(type), type };
|
|
37786
|
-
default:
|
|
37787
|
-
return { id: nextBlockId(type), type, content: "" };
|
|
37782
|
+
function sanitizeRichHtml(html) {
|
|
37783
|
+
if (!html || typeof html !== "string") return "";
|
|
37784
|
+
if (typeof window === "undefined" || typeof DOMParser === "undefined") return "";
|
|
37785
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
37786
|
+
sanitizeNode(doc.body);
|
|
37787
|
+
if (!doc.body.querySelector("img, hr") && (doc.body.textContent ?? "").trim().length === 0) {
|
|
37788
|
+
return "";
|
|
37788
37789
|
}
|
|
37790
|
+
return doc.body.innerHTML.replace(//g, "");
|
|
37791
|
+
}
|
|
37792
|
+
function htmlIsEmpty(el) {
|
|
37793
|
+
if (el.querySelector("img, hr")) return false;
|
|
37794
|
+
return (el.textContent ?? "").trim().length === 0;
|
|
37789
37795
|
}
|
|
37790
|
-
function
|
|
37791
|
-
|
|
37796
|
+
function closestBlock(node, root) {
|
|
37797
|
+
let cur = node;
|
|
37798
|
+
while (cur && cur !== root) {
|
|
37799
|
+
if (cur instanceof Element && BLOCK_TAGS.has(cur.tagName)) return cur;
|
|
37800
|
+
cur = cur.parentNode;
|
|
37801
|
+
}
|
|
37802
|
+
return null;
|
|
37792
37803
|
}
|
|
37793
|
-
function
|
|
37794
|
-
return
|
|
37804
|
+
function RichTextStyles() {
|
|
37805
|
+
return /* @__PURE__ */ jsxRuntime.jsx("style", { children: RICH_TEXT_CSS });
|
|
37795
37806
|
}
|
|
37796
|
-
function
|
|
37807
|
+
function readToolbarState(root) {
|
|
37808
|
+
const sel = window.getSelection();
|
|
37809
|
+
if (!sel || sel.rangeCount === 0) return IDLE_TOOLBAR;
|
|
37810
|
+
const anchor = sel.anchorNode;
|
|
37811
|
+
if (!anchor || !root.contains(anchor)) return IDLE_TOOLBAR;
|
|
37812
|
+
let block = null;
|
|
37813
|
+
let link = false;
|
|
37814
|
+
let node = anchor;
|
|
37815
|
+
while (node && node !== root) {
|
|
37816
|
+
if (node instanceof Element) {
|
|
37817
|
+
const tag = node.tagName.toLowerCase();
|
|
37818
|
+
if (!block && (tag === "h1" || tag === "h2" || tag === "h3" || tag === "blockquote" || tag === "pre")) {
|
|
37819
|
+
block = tag;
|
|
37820
|
+
}
|
|
37821
|
+
if (tag === "a") link = true;
|
|
37822
|
+
}
|
|
37823
|
+
node = node.parentNode;
|
|
37824
|
+
}
|
|
37797
37825
|
return {
|
|
37798
|
-
|
|
37799
|
-
|
|
37800
|
-
|
|
37801
|
-
|
|
37802
|
-
|
|
37803
|
-
|
|
37804
|
-
|
|
37826
|
+
bold: document.queryCommandState("bold"),
|
|
37827
|
+
italic: document.queryCommandState("italic"),
|
|
37828
|
+
underline: document.queryCommandState("underline"),
|
|
37829
|
+
strikeThrough: document.queryCommandState("strikeThrough"),
|
|
37830
|
+
block,
|
|
37831
|
+
bullets: document.queryCommandState("insertUnorderedList"),
|
|
37832
|
+
numbers: document.queryCommandState("insertOrderedList"),
|
|
37833
|
+
link
|
|
37805
37834
|
};
|
|
37806
37835
|
}
|
|
37807
|
-
function
|
|
37808
|
-
|
|
37809
|
-
|
|
37810
|
-
|
|
37811
|
-
|
|
37812
|
-
|
|
37813
|
-
|
|
37814
|
-
|
|
37815
|
-
|
|
37816
|
-
|
|
37817
|
-
|
|
37818
|
-
|
|
37836
|
+
function ToolbarButton({ icon: IconCmp, label, active, onExec }) {
|
|
37837
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
37838
|
+
exports.Button,
|
|
37839
|
+
{
|
|
37840
|
+
type: "button",
|
|
37841
|
+
variant: "ghost",
|
|
37842
|
+
size: "sm",
|
|
37843
|
+
"aria-label": label,
|
|
37844
|
+
"aria-pressed": active,
|
|
37845
|
+
title: label,
|
|
37846
|
+
className: cn(
|
|
37847
|
+
"h-8 w-8 p-0 gap-0 justify-center",
|
|
37848
|
+
active && "bg-muted text-foreground"
|
|
37849
|
+
),
|
|
37850
|
+
onMouseDown: (e) => {
|
|
37851
|
+
e.preventDefault();
|
|
37852
|
+
onExec();
|
|
37853
|
+
},
|
|
37854
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(IconCmp, { size: 15 })
|
|
37819
37855
|
}
|
|
37820
|
-
|
|
37821
|
-
|
|
37822
|
-
|
|
37823
|
-
|
|
37824
|
-
|
|
37825
|
-
|
|
37826
|
-
|
|
37827
|
-
|
|
37828
|
-
|
|
37829
|
-
|
|
37830
|
-
|
|
37831
|
-
|
|
37832
|
-
|
|
37833
|
-
|
|
37834
|
-
|
|
37835
|
-
|
|
37836
|
-
|
|
37837
|
-
|
|
37838
|
-
|
|
37839
|
-
|
|
37840
|
-
|
|
37841
|
-
|
|
37842
|
-
|
|
37843
|
-
|
|
37844
|
-
|
|
37845
|
-
|
|
37856
|
+
);
|
|
37857
|
+
}
|
|
37858
|
+
var CHANGE_DEBOUNCE_MS, ALLOWED_ATTRS, DROP_TAGS, MD_BLOCK_PREFIXES, BLOCK_TAGS, MD_INLINE_RULES, RICH_TEXT_CSS, IDLE_TOOLBAR; exports.RichTextEditor = void 0;
|
|
37859
|
+
var init_RichTextEditor = __esm({
|
|
37860
|
+
"components/core/molecules/RichTextEditor.tsx"() {
|
|
37861
|
+
"use client";
|
|
37862
|
+
init_cn();
|
|
37863
|
+
init_Box();
|
|
37864
|
+
init_Button();
|
|
37865
|
+
init_useEventBus();
|
|
37866
|
+
CHANGE_DEBOUNCE_MS = 400;
|
|
37867
|
+
ALLOWED_ATTRS = {
|
|
37868
|
+
p: [],
|
|
37869
|
+
h1: [],
|
|
37870
|
+
h2: [],
|
|
37871
|
+
h3: [],
|
|
37872
|
+
h4: [],
|
|
37873
|
+
ul: [],
|
|
37874
|
+
ol: [],
|
|
37875
|
+
li: [],
|
|
37876
|
+
blockquote: [],
|
|
37877
|
+
pre: [],
|
|
37878
|
+
code: [],
|
|
37879
|
+
b: [],
|
|
37880
|
+
strong: [],
|
|
37881
|
+
i: [],
|
|
37882
|
+
em: [],
|
|
37883
|
+
u: [],
|
|
37884
|
+
s: [],
|
|
37885
|
+
strike: [],
|
|
37886
|
+
br: [],
|
|
37887
|
+
hr: [],
|
|
37888
|
+
div: [],
|
|
37889
|
+
span: [],
|
|
37890
|
+
a: ["href"],
|
|
37891
|
+
img: ["src", "alt"]
|
|
37892
|
+
};
|
|
37893
|
+
DROP_TAGS = /* @__PURE__ */ new Set(["script", "style", "iframe", "object", "embed", "link", "meta", "form", "input", "button", "textarea", "select"]);
|
|
37894
|
+
MD_BLOCK_PREFIXES = {
|
|
37895
|
+
"#": { kind: "block", tag: "h1" },
|
|
37896
|
+
"##": { kind: "block", tag: "h2" },
|
|
37897
|
+
"###": { kind: "block", tag: "h3" },
|
|
37898
|
+
">": { kind: "block", tag: "blockquote" },
|
|
37899
|
+
"```": { kind: "block", tag: "pre" },
|
|
37900
|
+
"-": { kind: "list", command: "insertUnorderedList" },
|
|
37901
|
+
"*": { kind: "list", command: "insertUnorderedList" },
|
|
37902
|
+
"1.": { kind: "list", command: "insertOrderedList" }
|
|
37903
|
+
};
|
|
37904
|
+
BLOCK_TAGS = /* @__PURE__ */ new Set(["P", "DIV", "LI", "H1", "H2", "H3", "H4", "BLOCKQUOTE", "PRE"]);
|
|
37905
|
+
MD_INLINE_RULES = [
|
|
37906
|
+
{ pattern: /\*\*([^*\n]+)\*\*$/, wrap: "strong" },
|
|
37907
|
+
{ pattern: /(^|[^*])\*([^*\n]+)\*$/, wrap: "em" },
|
|
37908
|
+
{ pattern: /`([^`\n]+)`$/, wrap: "code" }
|
|
37909
|
+
];
|
|
37910
|
+
RICH_TEXT_CSS = `
|
|
37911
|
+
.almadar-rich-text { line-height: 1.7; color: var(--color-foreground); }
|
|
37912
|
+
.almadar-rich-text h1 { font-size: 1.875rem; font-weight: 700; line-height: 1.25; margin: 1.25em 0 0.4em; }
|
|
37913
|
+
.almadar-rich-text h2 { font-size: 1.5rem; font-weight: 650; line-height: 1.3; margin: 1.1em 0 0.4em; }
|
|
37914
|
+
.almadar-rich-text h3 { font-size: 1.25rem; font-weight: 600; line-height: 1.35; margin: 1em 0 0.35em; }
|
|
37915
|
+
.almadar-rich-text h1:first-child, .almadar-rich-text h2:first-child, .almadar-rich-text h3:first-child { margin-top: 0; }
|
|
37916
|
+
.almadar-rich-text p { margin: 0.5em 0; }
|
|
37917
|
+
.almadar-rich-text ul { list-style: disc; padding-inline-start: 1.5rem; margin: 0.5em 0; }
|
|
37918
|
+
.almadar-rich-text ol { list-style: decimal; padding-inline-start: 1.5rem; margin: 0.5em 0; }
|
|
37919
|
+
.almadar-rich-text li { margin: 0.25em 0; }
|
|
37920
|
+
.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; }
|
|
37921
|
+
.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; }
|
|
37922
|
+
.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; }
|
|
37923
|
+
.almadar-rich-text pre code { background: transparent; padding: 0; }
|
|
37924
|
+
.almadar-rich-text a { color: var(--color-primary); text-decoration: underline; }
|
|
37925
|
+
.almadar-rich-text hr { border: none; border-top: 1px solid var(--color-border); margin: 1.25em 0; }
|
|
37926
|
+
.almadar-rich-text img { max-width: 100%; border-radius: 0.375rem; }
|
|
37927
|
+
`;
|
|
37928
|
+
IDLE_TOOLBAR = {
|
|
37929
|
+
bold: false,
|
|
37930
|
+
italic: false,
|
|
37931
|
+
underline: false,
|
|
37932
|
+
strikeThrough: false,
|
|
37933
|
+
block: null,
|
|
37934
|
+
bullets: false,
|
|
37935
|
+
numbers: false,
|
|
37936
|
+
link: false
|
|
37937
|
+
};
|
|
37938
|
+
exports.RichTextEditor = ({
|
|
37939
|
+
value,
|
|
37940
|
+
onChange,
|
|
37941
|
+
changeEvent,
|
|
37942
|
+
readOnly = false,
|
|
37943
|
+
placeholder,
|
|
37944
|
+
showToolbar = true,
|
|
37945
|
+
className
|
|
37946
|
+
}) => {
|
|
37947
|
+
const { t } = hooks.useTranslate();
|
|
37948
|
+
const ref = React77.useRef(null);
|
|
37949
|
+
const [toolbar, setToolbar] = React77.useState(IDLE_TOOLBAR);
|
|
37950
|
+
const [empty, setEmpty] = React77.useState(() => !value || !sanitizeRichHtml(value).trim());
|
|
37951
|
+
const eventBus = useEventBus();
|
|
37952
|
+
const onChangeRef = React77.useRef(onChange);
|
|
37953
|
+
const changeEventRef = React77.useRef(changeEvent);
|
|
37954
|
+
React77.useEffect(() => {
|
|
37955
|
+
onChangeRef.current = onChange;
|
|
37956
|
+
changeEventRef.current = changeEvent;
|
|
37957
|
+
}, [onChange, changeEvent]);
|
|
37958
|
+
const emitTimerRef = React77.useRef(null);
|
|
37959
|
+
const emitNow = React77.useCallback(() => {
|
|
37960
|
+
const el = ref.current;
|
|
37961
|
+
if (!el) return;
|
|
37962
|
+
const html = sanitizeRichHtml(el.innerHTML);
|
|
37963
|
+
onChangeRef.current?.(html);
|
|
37964
|
+
const evt = changeEventRef.current;
|
|
37965
|
+
if (evt) eventBus.emit(`UI:${evt}`, { value: html });
|
|
37966
|
+
}, [eventBus]);
|
|
37967
|
+
const scheduleEmit = React77.useCallback(() => {
|
|
37968
|
+
if (emitTimerRef.current) clearTimeout(emitTimerRef.current);
|
|
37969
|
+
emitTimerRef.current = setTimeout(() => {
|
|
37970
|
+
emitTimerRef.current = null;
|
|
37971
|
+
emitNow();
|
|
37972
|
+
}, CHANGE_DEBOUNCE_MS);
|
|
37973
|
+
}, [emitNow]);
|
|
37974
|
+
const flushEmit = React77.useCallback(() => {
|
|
37975
|
+
if (!emitTimerRef.current) return;
|
|
37976
|
+
clearTimeout(emitTimerRef.current);
|
|
37977
|
+
emitTimerRef.current = null;
|
|
37978
|
+
emitNow();
|
|
37979
|
+
}, [emitNow]);
|
|
37980
|
+
React77.useEffect(() => () => {
|
|
37981
|
+
if (emitTimerRef.current) {
|
|
37982
|
+
clearTimeout(emitTimerRef.current);
|
|
37983
|
+
emitTimerRef.current = null;
|
|
37984
|
+
emitNow();
|
|
37985
|
+
}
|
|
37986
|
+
}, [emitNow]);
|
|
37987
|
+
React77.useEffect(() => {
|
|
37988
|
+
if (readOnly) return;
|
|
37989
|
+
const el = ref.current;
|
|
37990
|
+
if (!el) return;
|
|
37991
|
+
if (document.activeElement === el) return;
|
|
37992
|
+
const next = sanitizeRichHtml(value ?? "") || "<p><br></p>";
|
|
37993
|
+
if (el.innerHTML !== next) {
|
|
37994
|
+
el.innerHTML = next;
|
|
37995
|
+
setEmpty(htmlIsEmpty(el));
|
|
37996
|
+
}
|
|
37997
|
+
}, [readOnly, value]);
|
|
37998
|
+
React77.useEffect(() => {
|
|
37999
|
+
if (readOnly) return;
|
|
38000
|
+
document.execCommand("defaultParagraphSeparator", false, "p");
|
|
38001
|
+
}, [readOnly]);
|
|
38002
|
+
React77.useEffect(() => {
|
|
38003
|
+
if (readOnly || !showToolbar) return;
|
|
38004
|
+
const onSelectionChange = () => {
|
|
38005
|
+
const el = ref.current;
|
|
38006
|
+
if (!el) return;
|
|
38007
|
+
setToolbar(readToolbarState(el));
|
|
38008
|
+
};
|
|
38009
|
+
document.addEventListener("selectionchange", onSelectionChange);
|
|
38010
|
+
return () => document.removeEventListener("selectionchange", onSelectionChange);
|
|
38011
|
+
}, [readOnly, showToolbar]);
|
|
38012
|
+
const tryInlineMarkdown = React77.useCallback(() => {
|
|
38013
|
+
const root = ref.current;
|
|
38014
|
+
if (!root) return false;
|
|
38015
|
+
const sel = window.getSelection();
|
|
38016
|
+
if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return false;
|
|
38017
|
+
const node = sel.anchorNode;
|
|
38018
|
+
if (!node || node.nodeType !== Node.TEXT_NODE || !root.contains(node)) return false;
|
|
38019
|
+
if (node.parentElement?.closest("code, pre")) return false;
|
|
38020
|
+
const text = (node.textContent ?? "").slice(0, sel.anchorOffset);
|
|
38021
|
+
for (const rule of MD_INLINE_RULES) {
|
|
38022
|
+
const m = rule.pattern.exec(text);
|
|
38023
|
+
if (!m) continue;
|
|
38024
|
+
const inner = rule.wrap === "em" ? m[2] : m[1];
|
|
38025
|
+
if (!inner || !inner.trim()) continue;
|
|
38026
|
+
const lead = rule.wrap === "em" ? m[1]?.length ?? 0 : 0;
|
|
38027
|
+
const range = document.createRange();
|
|
38028
|
+
range.setStart(node, m.index + lead);
|
|
38029
|
+
range.setEnd(node, sel.anchorOffset);
|
|
38030
|
+
const el = document.createElement(rule.wrap);
|
|
38031
|
+
el.textContent = inner;
|
|
38032
|
+
range.deleteContents();
|
|
38033
|
+
range.insertNode(el);
|
|
38034
|
+
const after = document.createTextNode("\u200B");
|
|
38035
|
+
el.parentNode?.insertBefore(after, el.nextSibling);
|
|
38036
|
+
const caret = document.createRange();
|
|
38037
|
+
caret.setStart(after, 1);
|
|
38038
|
+
caret.collapse(true);
|
|
38039
|
+
sel.removeAllRanges();
|
|
38040
|
+
sel.addRange(caret);
|
|
38041
|
+
return true;
|
|
38042
|
+
}
|
|
38043
|
+
return false;
|
|
38044
|
+
}, []);
|
|
38045
|
+
const tryBlockMarkdown = React77.useCallback(() => {
|
|
38046
|
+
const root = ref.current;
|
|
38047
|
+
if (!root) return false;
|
|
38048
|
+
const sel = window.getSelection();
|
|
38049
|
+
if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return false;
|
|
38050
|
+
const node = sel.anchorNode;
|
|
38051
|
+
if (!node || node.nodeType !== Node.TEXT_NODE || !root.contains(node)) return false;
|
|
38052
|
+
const block = closestBlock(node, root);
|
|
38053
|
+
if (block ? block.firstChild !== node : root.firstChild !== node) return false;
|
|
38054
|
+
const prefix = (node.textContent ?? "").slice(0, sel.anchorOffset);
|
|
38055
|
+
const rule = MD_BLOCK_PREFIXES[prefix];
|
|
38056
|
+
if (!rule) return false;
|
|
38057
|
+
if (node.parentElement?.closest("pre, code")) return false;
|
|
38058
|
+
if (rule.kind === "list" && node.parentElement?.closest("li")) return false;
|
|
38059
|
+
node.deleteData(0, prefix.length);
|
|
38060
|
+
const caret = document.createRange();
|
|
38061
|
+
caret.setStart(node, 0);
|
|
38062
|
+
caret.collapse(true);
|
|
38063
|
+
sel.removeAllRanges();
|
|
38064
|
+
sel.addRange(caret);
|
|
38065
|
+
if (rule.kind === "list") {
|
|
38066
|
+
const container = block ?? node.parentElement;
|
|
38067
|
+
const list = document.createElement(rule.command === "insertOrderedList" ? "ol" : "ul");
|
|
38068
|
+
const li = document.createElement("li");
|
|
38069
|
+
if (block) {
|
|
38070
|
+
while (block.firstChild) li.appendChild(block.firstChild);
|
|
38071
|
+
list.appendChild(li);
|
|
38072
|
+
block.replaceWith(list);
|
|
38073
|
+
} else if (container) {
|
|
38074
|
+
li.appendChild(node);
|
|
38075
|
+
list.appendChild(li);
|
|
38076
|
+
container.appendChild(list);
|
|
38077
|
+
}
|
|
38078
|
+
if (!li.firstChild) li.appendChild(document.createElement("br"));
|
|
38079
|
+
const liCaret = document.createRange();
|
|
38080
|
+
liCaret.selectNodeContents(li);
|
|
38081
|
+
liCaret.collapse(true);
|
|
38082
|
+
sel.removeAllRanges();
|
|
38083
|
+
sel.addRange(liCaret);
|
|
38084
|
+
} else {
|
|
38085
|
+
document.execCommand("formatBlock", false, rule.tag);
|
|
38086
|
+
}
|
|
38087
|
+
return true;
|
|
38088
|
+
}, []);
|
|
38089
|
+
const afterEdit = React77.useCallback(() => {
|
|
38090
|
+
const el = ref.current;
|
|
38091
|
+
if (!el) return;
|
|
38092
|
+
tryInlineMarkdown();
|
|
38093
|
+
setEmpty(htmlIsEmpty(el));
|
|
38094
|
+
setToolbar(readToolbarState(el));
|
|
38095
|
+
scheduleEmit();
|
|
38096
|
+
}, [scheduleEmit, tryInlineMarkdown]);
|
|
38097
|
+
const handleKeyDown = React77.useCallback((e) => {
|
|
38098
|
+
if (e.key === " " && tryBlockMarkdown()) {
|
|
38099
|
+
e.preventDefault();
|
|
38100
|
+
afterEdit();
|
|
38101
|
+
}
|
|
38102
|
+
}, [afterEdit, tryBlockMarkdown]);
|
|
38103
|
+
const execInline = React77.useCallback((command) => {
|
|
38104
|
+
document.execCommand(command, false);
|
|
38105
|
+
afterEdit();
|
|
38106
|
+
}, [afterEdit]);
|
|
38107
|
+
const execBlock = React77.useCallback((tag) => {
|
|
38108
|
+
const next = toolbar.block === tag ? "p" : tag;
|
|
38109
|
+
document.execCommand("formatBlock", false, next);
|
|
38110
|
+
afterEdit();
|
|
38111
|
+
}, [afterEdit, toolbar.block]);
|
|
38112
|
+
const execList = React77.useCallback((command) => {
|
|
38113
|
+
document.execCommand(command, false);
|
|
38114
|
+
afterEdit();
|
|
38115
|
+
}, [afterEdit]);
|
|
38116
|
+
const execLink = React77.useCallback(() => {
|
|
38117
|
+
if (toolbar.link) {
|
|
38118
|
+
document.execCommand("unlink", false);
|
|
38119
|
+
afterEdit();
|
|
38120
|
+
return;
|
|
38121
|
+
}
|
|
38122
|
+
const url = window.prompt(t("richTextEditor.linkPrompt"));
|
|
38123
|
+
if (!url) return;
|
|
38124
|
+
const safe = safeUrl(url, ["http://", "https://", "mailto:"]) ?? `https://${url}`;
|
|
38125
|
+
document.execCommand("createLink", false, safe);
|
|
38126
|
+
afterEdit();
|
|
38127
|
+
}, [afterEdit, t, toolbar.link]);
|
|
38128
|
+
const execRule = React77.useCallback(() => {
|
|
38129
|
+
document.execCommand("insertHorizontalRule", false);
|
|
38130
|
+
afterEdit();
|
|
38131
|
+
}, [afterEdit]);
|
|
38132
|
+
if (readOnly) {
|
|
38133
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: cn("almadar-rich-text max-w-none", className), children: [
|
|
38134
|
+
/* @__PURE__ */ jsxRuntime.jsx(RichTextStyles, {}),
|
|
38135
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { dangerouslySetInnerHTML: { __html: sanitizeRichHtml(value ?? "") } })
|
|
38136
|
+
] });
|
|
38137
|
+
}
|
|
38138
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: cn("flex flex-col gap-2", className), children: [
|
|
38139
|
+
/* @__PURE__ */ jsxRuntime.jsx(RichTextStyles, {}),
|
|
38140
|
+
showToolbar && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
38141
|
+
exports.Box,
|
|
38142
|
+
{
|
|
38143
|
+
role: "toolbar",
|
|
38144
|
+
"aria-label": t("richTextEditor.editorToolbar"),
|
|
38145
|
+
className: cn(
|
|
38146
|
+
"sticky top-0 z-10 flex flex-wrap items-center gap-0.5 self-start",
|
|
38147
|
+
"rounded-md border border-border bg-background/95 px-1 py-0.5 shadow-sm"
|
|
38148
|
+
),
|
|
38149
|
+
children: [
|
|
38150
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Bold, label: t("richTextEditor.bold"), active: toolbar.bold, onExec: () => execInline("bold") }),
|
|
38151
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Italic, label: t("richTextEditor.italic"), active: toolbar.italic, onExec: () => execInline("italic") }),
|
|
38152
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Underline, label: t("richTextEditor.underline"), active: toolbar.underline, onExec: () => execInline("underline") }),
|
|
38153
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Strikethrough, label: t("richTextEditor.strikethrough"), active: toolbar.strikeThrough, onExec: () => execInline("strikeThrough") }),
|
|
38154
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
38155
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Heading1, label: t("richTextEditor.heading1"), active: toolbar.block === "h1", onExec: () => execBlock("h1") }),
|
|
38156
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Heading2, label: t("richTextEditor.heading2"), active: toolbar.block === "h2", onExec: () => execBlock("h2") }),
|
|
38157
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Heading3, label: t("richTextEditor.heading3"), active: toolbar.block === "h3", onExec: () => execBlock("h3") }),
|
|
38158
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
38159
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.List, label: t("richTextEditor.bulletList"), active: toolbar.bullets, onExec: () => execList("insertUnorderedList") }),
|
|
38160
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.ListOrdered, label: t("richTextEditor.numberedList"), active: toolbar.numbers, onExec: () => execList("insertOrderedList") }),
|
|
38161
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
38162
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Quote, label: t("richTextEditor.quote"), active: toolbar.block === "blockquote", onExec: () => execBlock("blockquote") }),
|
|
38163
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Code, label: t("richTextEditor.code"), active: toolbar.block === "pre", onExec: () => execBlock("pre") }),
|
|
38164
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Link, label: toolbar.link ? t("richTextEditor.removeLink") : t("richTextEditor.link"), active: toolbar.link, onExec: execLink }),
|
|
38165
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { icon: LucideIcons2.Minus, label: t("richTextEditor.divider"), onExec: execRule })
|
|
38166
|
+
]
|
|
38167
|
+
}
|
|
38168
|
+
),
|
|
38169
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
38170
|
+
exports.Box,
|
|
38171
|
+
{
|
|
38172
|
+
ref,
|
|
38173
|
+
contentEditable: true,
|
|
38174
|
+
suppressContentEditableWarning: true,
|
|
38175
|
+
role: "textbox",
|
|
38176
|
+
"aria-multiline": "true",
|
|
38177
|
+
"aria-label": t("richTextEditor.editorSurface"),
|
|
38178
|
+
"data-placeholder": placeholder ?? t("richTextEditor.placeholder"),
|
|
38179
|
+
"data-empty": empty ? "true" : "false",
|
|
38180
|
+
className: cn(
|
|
38181
|
+
"almadar-rich-text max-w-none min-h-[8rem] outline-none",
|
|
38182
|
+
"data-[empty=true]:before:content-[attr(data-placeholder)]",
|
|
38183
|
+
"data-[empty=true]:before:text-muted-foreground/60",
|
|
38184
|
+
"data-[empty=true]:before:pointer-events-none",
|
|
38185
|
+
"data-[empty=true]:before:absolute",
|
|
38186
|
+
"relative cursor-text"
|
|
38187
|
+
),
|
|
38188
|
+
onInput: afterEdit,
|
|
38189
|
+
onKeyDown: handleKeyDown,
|
|
38190
|
+
onBlur: flushEmit
|
|
38191
|
+
}
|
|
38192
|
+
)
|
|
38193
|
+
] });
|
|
37846
38194
|
};
|
|
38195
|
+
exports.RichTextEditor.displayName = "RichTextEditor";
|
|
37847
38196
|
}
|
|
37848
|
-
|
|
37849
|
-
|
|
38197
|
+
});
|
|
38198
|
+
function renderIconInput4(icon, props) {
|
|
38199
|
+
return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon, ...props });
|
|
37850
38200
|
}
|
|
37851
|
-
function
|
|
38201
|
+
function DocumentPanel({
|
|
38202
|
+
entity,
|
|
38203
|
+
title,
|
|
38204
|
+
subtitle,
|
|
38205
|
+
value,
|
|
38206
|
+
actions,
|
|
38207
|
+
maxInlineActions,
|
|
38208
|
+
editing = false,
|
|
38209
|
+
titleCommitEvent,
|
|
38210
|
+
contentChangeEvent,
|
|
38211
|
+
editEvent,
|
|
38212
|
+
doneEvent,
|
|
38213
|
+
editLabel,
|
|
38214
|
+
doneLabel,
|
|
38215
|
+
autosaveHint,
|
|
38216
|
+
placeholder,
|
|
38217
|
+
className
|
|
38218
|
+
}) {
|
|
38219
|
+
const eventBus = useEventBus();
|
|
37852
38220
|
const { t } = hooks.useTranslate();
|
|
37853
|
-
const [
|
|
37854
|
-
const
|
|
37855
|
-
|
|
37856
|
-
|
|
37857
|
-
|
|
37858
|
-
|
|
37859
|
-
|
|
37860
|
-
|
|
38221
|
+
const [titleDraft, setTitleDraft] = React77.useState(null);
|
|
38222
|
+
const recordId = entity?.id !== void 0 && entity?.id !== null ? String(entity.id) : "";
|
|
38223
|
+
const actionDefs = actions ?? [];
|
|
38224
|
+
const inlineCap = Math.min(maxInlineActions ?? 1, 1);
|
|
38225
|
+
const inlineActions = actionDefs.filter((a) => a.variant === "primary").slice(0, inlineCap);
|
|
38226
|
+
const menuActions = actionDefs.filter((a) => !inlineActions.includes(a));
|
|
38227
|
+
const fireAction = (action) => {
|
|
38228
|
+
if (!action.event) return;
|
|
38229
|
+
eventBus.emit(`UI:${action.event}`, { id: recordId, row: entity });
|
|
38230
|
+
};
|
|
38231
|
+
const commitTitle = () => {
|
|
38232
|
+
if (!titleCommitEvent) return;
|
|
38233
|
+
const next = (titleDraft ?? "").trim();
|
|
38234
|
+
setTitleDraft(null);
|
|
38235
|
+
if (!next || next === title) return;
|
|
38236
|
+
eventBus.emit(`UI:${titleCommitEvent}`, { title: next, id: recordId });
|
|
38237
|
+
};
|
|
38238
|
+
const untitled = t("documentPanel.untitled") || "Untitled";
|
|
38239
|
+
const titleNode = titleCommitEvent && titleDraft !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
38240
|
+
exports.Input,
|
|
38241
|
+
{
|
|
38242
|
+
value: titleDraft,
|
|
38243
|
+
autoFocus: true,
|
|
38244
|
+
"aria-label": t("common.title"),
|
|
38245
|
+
className: "h-auto py-1 text-3xl font-bold tracking-tight",
|
|
38246
|
+
onFocus: (e) => e.currentTarget.select(),
|
|
38247
|
+
onChange: (e) => setTitleDraft(e.target.value),
|
|
38248
|
+
onBlur: commitTitle,
|
|
38249
|
+
onKeyDown: (e) => {
|
|
38250
|
+
if (e.key === "Enter") {
|
|
38251
|
+
e.preventDefault();
|
|
38252
|
+
commitTitle();
|
|
38253
|
+
} else if (e.key === "Escape") {
|
|
38254
|
+
e.preventDefault();
|
|
38255
|
+
setTitleDraft(null);
|
|
38256
|
+
}
|
|
38257
|
+
},
|
|
38258
|
+
"data-testid": "document-title-input"
|
|
37861
38259
|
}
|
|
37862
|
-
|
|
37863
|
-
|
|
37864
|
-
|
|
37865
|
-
|
|
37866
|
-
|
|
37867
|
-
|
|
37868
|
-
|
|
38260
|
+
) : titleCommitEvent ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
38261
|
+
exports.Box,
|
|
38262
|
+
{
|
|
38263
|
+
role: "button",
|
|
38264
|
+
tabIndex: 0,
|
|
38265
|
+
className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
38266
|
+
onClick: () => setTitleDraft(title ?? ""),
|
|
38267
|
+
onKeyDown: (e) => {
|
|
38268
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
38269
|
+
e.preventDefault();
|
|
38270
|
+
setTitleDraft(title ?? "");
|
|
38271
|
+
}
|
|
38272
|
+
},
|
|
38273
|
+
"data-testid": "document-title-editable",
|
|
38274
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h2", weight: "bold", className: cn(!title && "text-muted-foreground"), children: title || untitled })
|
|
38275
|
+
}
|
|
38276
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h2", weight: "bold", children: title || untitled });
|
|
38277
|
+
const emitWithId = (event) => () => {
|
|
38278
|
+
if (event) eventBus.emit(`UI:${event}`, { id: recordId });
|
|
38279
|
+
};
|
|
38280
|
+
return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { variant: "elevated", className: cn("w-full", className), children: /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "sm", className: "p-6 sm:p-8", children: [
|
|
38281
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
38282
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
38283
|
+
titleNode,
|
|
38284
|
+
subtitle ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
38285
|
+
] }),
|
|
38286
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
38287
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
38288
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
38289
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
38290
|
+
editEvent && /* @__PURE__ */ jsxRuntime.jsxs(exports.Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
38291
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
38292
|
+
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
38293
|
+
] }),
|
|
38294
|
+
inlineActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
38295
|
+
exports.Button,
|
|
38296
|
+
{
|
|
38297
|
+
variant: "primary",
|
|
38298
|
+
size: "sm",
|
|
38299
|
+
onClick: () => fireAction(action),
|
|
38300
|
+
"data-testid": `action-${action.event}`,
|
|
38301
|
+
children: [
|
|
38302
|
+
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
38303
|
+
action.label
|
|
38304
|
+
]
|
|
38305
|
+
},
|
|
38306
|
+
idx
|
|
38307
|
+
)),
|
|
38308
|
+
menuActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
38309
|
+
exports.Menu,
|
|
38310
|
+
{
|
|
38311
|
+
position: "bottom-end",
|
|
38312
|
+
trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
38313
|
+
items: menuActions.map((action) => ({
|
|
38314
|
+
label: action.label,
|
|
38315
|
+
icon: action.icon,
|
|
38316
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
38317
|
+
onClick: () => fireAction(action)
|
|
38318
|
+
}))
|
|
38319
|
+
}
|
|
38320
|
+
)
|
|
38321
|
+
] }) })
|
|
38322
|
+
] }),
|
|
38323
|
+
editing ? /* @__PURE__ */ jsxRuntime.jsx(exports.RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
38324
|
+
exports.Box,
|
|
37869
38325
|
{
|
|
37870
|
-
|
|
37871
|
-
variant: "ghost",
|
|
37872
|
-
"aria-label": t("richBlockEditor.blockActions"),
|
|
38326
|
+
onClick: emitWithId(editEvent),
|
|
37873
38327
|
className: cn(
|
|
37874
|
-
"
|
|
37875
|
-
|
|
37876
|
-
"text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
37877
|
-
"opacity-0 group-hover:opacity-100 focus-visible:opacity-100",
|
|
37878
|
-
"transition-opacity"
|
|
38328
|
+
"rounded-md px-1 -mx-1 min-h-[16rem]",
|
|
38329
|
+
editEvent && "cursor-text transition-colors hover:bg-muted/30"
|
|
37879
38330
|
),
|
|
37880
|
-
|
|
37881
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(exports.
|
|
37882
|
-
}
|
|
37883
|
-
),
|
|
37884
|
-
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
37885
|
-
exports.Box,
|
|
37886
|
-
{
|
|
37887
|
-
role: "menu",
|
|
37888
|
-
className: cn(
|
|
37889
|
-
"absolute right-0 z-10 mt-1 w-44",
|
|
37890
|
-
"rounded-container border border-border bg-popover shadow-elevation-popover",
|
|
37891
|
-
"py-1 text-sm"
|
|
37892
|
-
),
|
|
37893
|
-
children: [
|
|
37894
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "px-2 py-1 text-xs uppercase tracking-wide text-muted-foreground", children: t(BLOCK_TYPE_LABEL_KEY[block.type]) }),
|
|
37895
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
37896
|
-
exports.Button,
|
|
37897
|
-
{
|
|
37898
|
-
type: "button",
|
|
37899
|
-
variant: "ghost",
|
|
37900
|
-
role: "menuitem",
|
|
37901
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left justify-start rounded-none",
|
|
37902
|
-
onClick: () => {
|
|
37903
|
-
onDuplicate();
|
|
37904
|
-
setOpen(false);
|
|
37905
|
-
},
|
|
37906
|
-
children: [
|
|
37907
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "plus", className: "w-3.5 h-3.5" }),
|
|
37908
|
-
" ",
|
|
37909
|
-
t("richBlockEditor.duplicate")
|
|
37910
|
-
]
|
|
37911
|
-
}
|
|
37912
|
-
),
|
|
37913
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
37914
|
-
exports.Button,
|
|
37915
|
-
{
|
|
37916
|
-
type: "button",
|
|
37917
|
-
variant: "ghost",
|
|
37918
|
-
role: "menuitem",
|
|
37919
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left text-destructive hover:bg-muted justify-start rounded-none",
|
|
37920
|
-
onClick: () => {
|
|
37921
|
-
onDelete();
|
|
37922
|
-
setOpen(false);
|
|
37923
|
-
},
|
|
37924
|
-
children: [
|
|
37925
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "trash", className: "w-3.5 h-3.5" }),
|
|
37926
|
-
" ",
|
|
37927
|
-
t("common.delete")
|
|
37928
|
-
]
|
|
37929
|
-
}
|
|
37930
|
-
),
|
|
37931
|
-
CHANGEABLE_TYPES.includes(block.type) && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
37932
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "my-1 border-t border-border" }),
|
|
37933
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "px-2 py-1 text-xs uppercase tracking-wide text-muted-foreground", children: t("richBlockEditor.turnInto") }),
|
|
37934
|
-
CHANGEABLE_TYPES.filter((bt) => bt !== block.type).map((bt) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
37935
|
-
exports.Button,
|
|
37936
|
-
{
|
|
37937
|
-
type: "button",
|
|
37938
|
-
variant: "ghost",
|
|
37939
|
-
role: "menuitem",
|
|
37940
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left justify-start rounded-none",
|
|
37941
|
-
onClick: () => {
|
|
37942
|
-
onChangeType(bt);
|
|
37943
|
-
setOpen(false);
|
|
37944
|
-
},
|
|
37945
|
-
children: t(BLOCK_TYPE_LABEL_KEY[bt])
|
|
37946
|
-
},
|
|
37947
|
-
bt
|
|
37948
|
-
))
|
|
37949
|
-
] })
|
|
37950
|
-
]
|
|
38331
|
+
"data-testid": "document-body",
|
|
38332
|
+
children: value && value !== "" ? /* @__PURE__ */ jsxRuntime.jsx(exports.RichTextEditor, { value, readOnly: true }) : /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "body", color: "muted", children: placeholder ?? (t("documentPanel.placeholder") || "") })
|
|
37951
38333
|
}
|
|
37952
38334
|
)
|
|
37953
|
-
] });
|
|
38335
|
+
] }) });
|
|
37954
38336
|
}
|
|
37955
|
-
|
|
37956
|
-
|
|
37957
|
-
|
|
37958
|
-
|
|
37959
|
-
|
|
37960
|
-
|
|
37961
|
-
|
|
37962
|
-
|
|
37963
|
-
|
|
37964
|
-
|
|
37965
|
-
|
|
37966
|
-
|
|
37967
|
-
|
|
37968
|
-
|
|
37969
|
-
|
|
37970
|
-
|
|
37971
|
-
|
|
37972
|
-
},
|
|
37973
|
-
const handleInput = React77.useCallback(
|
|
37974
|
-
(e) => {
|
|
37975
|
-
onValueChange(e.currentTarget.textContent ?? "");
|
|
37976
|
-
},
|
|
37977
|
-
[onValueChange]
|
|
37978
|
-
);
|
|
37979
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
37980
|
-
exports.Box,
|
|
37981
|
-
{
|
|
37982
|
-
as: tag,
|
|
37983
|
-
ref,
|
|
37984
|
-
contentEditable: !readOnly,
|
|
37985
|
-
suppressContentEditableWarning: true,
|
|
37986
|
-
role: readOnly ? void 0 : "textbox",
|
|
37987
|
-
"aria-label": ariaLabel,
|
|
37988
|
-
"aria-multiline": "true",
|
|
37989
|
-
"data-placeholder": placeholder,
|
|
37990
|
-
className: cn(
|
|
37991
|
-
"outline-none focus-visible:ring-1 focus-visible:ring-ring rounded-sm",
|
|
37992
|
-
"empty:before:content-[attr(data-placeholder)] empty:before:text-muted-foreground/60",
|
|
37993
|
-
className
|
|
37994
|
-
),
|
|
37995
|
-
onInput: handleInput
|
|
37996
|
-
}
|
|
37997
|
-
);
|
|
38337
|
+
var init_DocumentPanel = __esm({
|
|
38338
|
+
"components/core/molecules/DocumentPanel.tsx"() {
|
|
38339
|
+
"use client";
|
|
38340
|
+
init_cn();
|
|
38341
|
+
init_useEventBus();
|
|
38342
|
+
init_Box();
|
|
38343
|
+
init_Stack();
|
|
38344
|
+
init_Typography();
|
|
38345
|
+
init_Button();
|
|
38346
|
+
init_Card();
|
|
38347
|
+
init_Icon();
|
|
38348
|
+
init_Input();
|
|
38349
|
+
init_Menu();
|
|
38350
|
+
init_RichTextEditor();
|
|
38351
|
+
}
|
|
38352
|
+
});
|
|
38353
|
+
function renderIconInput5(icon, props) {
|
|
38354
|
+
return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon, ...props });
|
|
37998
38355
|
}
|
|
37999
|
-
function
|
|
38000
|
-
|
|
38001
|
-
|
|
38002
|
-
|
|
38003
|
-
|
|
38004
|
-
|
|
38005
|
-
|
|
38006
|
-
|
|
38007
|
-
|
|
38356
|
+
function fieldName(field) {
|
|
38357
|
+
return field.name ?? field.key ?? "";
|
|
38358
|
+
}
|
|
38359
|
+
function relationLabel(value) {
|
|
38360
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date) return null;
|
|
38361
|
+
for (const key of ["name", "title", "label"]) {
|
|
38362
|
+
const candidate = value[key];
|
|
38363
|
+
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
38364
|
+
}
|
|
38365
|
+
const id = value.id;
|
|
38366
|
+
return id !== void 0 && id !== null ? String(id) : null;
|
|
38367
|
+
}
|
|
38368
|
+
function fieldKind(field, value) {
|
|
38369
|
+
if (field.kind) return field.kind;
|
|
38370
|
+
if (field.options && field.options.length > 0) return "select";
|
|
38371
|
+
if (typeof value === "boolean" || field.format === "boolean") return "boolean";
|
|
38372
|
+
if (Array.isArray(value) || relationLabel(value ?? null) !== null) return "readonly";
|
|
38373
|
+
return "text";
|
|
38374
|
+
}
|
|
38375
|
+
function DocumentDetails({
|
|
38376
|
+
entity,
|
|
38377
|
+
fields,
|
|
38378
|
+
metaCommitEvent,
|
|
38379
|
+
title,
|
|
38380
|
+
className
|
|
38008
38381
|
}) {
|
|
38382
|
+
const eventBus = useEventBus();
|
|
38009
38383
|
const { t } = hooks.useTranslate();
|
|
38010
|
-
const
|
|
38011
|
-
|
|
38012
|
-
|
|
38013
|
-
);
|
|
38014
|
-
const
|
|
38015
|
-
(
|
|
38016
|
-
|
|
38017
|
-
|
|
38018
|
-
|
|
38019
|
-
|
|
38020
|
-
|
|
38021
|
-
|
|
38022
|
-
|
|
38023
|
-
|
|
38024
|
-
|
|
38025
|
-
|
|
38026
|
-
|
|
38027
|
-
|
|
38028
|
-
|
|
38029
|
-
|
|
38030
|
-
|
|
38031
|
-
|
|
38032
|
-
|
|
38033
|
-
|
|
38034
|
-
|
|
38035
|
-
|
|
38036
|
-
|
|
38037
|
-
|
|
38038
|
-
|
|
38039
|
-
|
|
38040
|
-
|
|
38041
|
-
|
|
38042
|
-
|
|
38043
|
-
|
|
38044
|
-
|
|
38045
|
-
|
|
38046
|
-
|
|
38047
|
-
}
|
|
38048
|
-
|
|
38049
|
-
|
|
38050
|
-
|
|
38051
|
-
|
|
38052
|
-
|
|
38053
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38054
|
-
Editable,
|
|
38055
|
-
{
|
|
38056
|
-
tag: "h1",
|
|
38057
|
-
value: block.content ?? "",
|
|
38058
|
-
readOnly,
|
|
38059
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.heading1"),
|
|
38060
|
-
ariaLabel: t("richBlockEditor.aria.heading1Block"),
|
|
38061
|
-
className: "text-3xl font-bold leading-tight",
|
|
38062
|
-
onValueChange: setContent
|
|
38063
|
-
}
|
|
38064
|
-
);
|
|
38065
|
-
case "heading-2":
|
|
38066
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38067
|
-
Editable,
|
|
38068
|
-
{
|
|
38069
|
-
tag: "h2",
|
|
38070
|
-
value: block.content ?? "",
|
|
38071
|
-
readOnly,
|
|
38072
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.heading2"),
|
|
38073
|
-
ariaLabel: t("richBlockEditor.aria.heading2Block"),
|
|
38074
|
-
className: "text-2xl font-semibold leading-tight",
|
|
38075
|
-
onValueChange: setContent
|
|
38076
|
-
}
|
|
38077
|
-
);
|
|
38078
|
-
case "heading-3":
|
|
38079
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38080
|
-
Editable,
|
|
38081
|
-
{
|
|
38082
|
-
tag: "h3",
|
|
38083
|
-
value: block.content ?? "",
|
|
38084
|
-
readOnly,
|
|
38085
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.heading3"),
|
|
38086
|
-
ariaLabel: t("richBlockEditor.aria.heading3Block"),
|
|
38087
|
-
className: "text-xl font-semibold leading-tight",
|
|
38088
|
-
onValueChange: setContent
|
|
38089
|
-
}
|
|
38090
|
-
);
|
|
38091
|
-
case "quote":
|
|
38092
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38093
|
-
Editable,
|
|
38094
|
-
{
|
|
38095
|
-
tag: "blockquote",
|
|
38096
|
-
value: block.content ?? "",
|
|
38097
|
-
readOnly,
|
|
38098
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.quote"),
|
|
38099
|
-
ariaLabel: t("richBlockEditor.aria.quoteBlock"),
|
|
38100
|
-
className: "border-l-4 border-primary/60 pl-4 italic text-muted-foreground",
|
|
38101
|
-
onValueChange: setContent
|
|
38102
|
-
}
|
|
38103
|
-
);
|
|
38104
|
-
case "code":
|
|
38105
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "rounded-md border border-border bg-muted/40", children: [
|
|
38106
|
-
/* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "flex items-center justify-between border-b border-border px-3 py-1 text-xs text-muted-foreground", children: [
|
|
38107
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { as: "span", variant: "caption", className: "uppercase tracking-wide", children: t("richBlockEditor.blockType.code") }),
|
|
38108
|
-
!readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
38109
|
-
exports.Input,
|
|
38110
|
-
{
|
|
38111
|
-
inputType: "text",
|
|
38112
|
-
value: String(block.metadata?.language ?? "plaintext"),
|
|
38113
|
-
"aria-label": t("richBlockEditor.aria.codeLanguage"),
|
|
38114
|
-
className: cn(
|
|
38115
|
-
"h-6 w-32 rounded-sm border border-border bg-background",
|
|
38116
|
-
"px-2 text-xs outline-none focus:ring-1 focus:ring-ring"
|
|
38117
|
-
),
|
|
38118
|
-
onChange: (e) => setMetadata("language", e.target.value)
|
|
38119
|
-
}
|
|
38120
|
-
),
|
|
38121
|
-
readOnly && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { as: "span", variant: "caption", className: "text-xs", children: String(block.metadata?.language ?? "plaintext") })
|
|
38122
|
-
] }),
|
|
38123
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
38124
|
-
Editable,
|
|
38125
|
-
{
|
|
38126
|
-
tag: "pre",
|
|
38127
|
-
value: block.content ?? "",
|
|
38128
|
-
readOnly,
|
|
38129
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.code"),
|
|
38130
|
-
ariaLabel: t("richBlockEditor.aria.codeBlock"),
|
|
38131
|
-
className: "block whitespace-pre-wrap p-3 font-mono text-sm leading-relaxed",
|
|
38132
|
-
onValueChange: setContent
|
|
38133
|
-
}
|
|
38134
|
-
)
|
|
38135
|
-
] });
|
|
38136
|
-
case "divider":
|
|
38137
|
-
return /* @__PURE__ */ jsxRuntime.jsx(exports.Divider, { className: "my-2" });
|
|
38138
|
-
case "image": {
|
|
38139
|
-
const url = String(block.metadata?.url ?? "");
|
|
38140
|
-
const caption = String(block.metadata?.caption ?? "");
|
|
38141
|
-
const imgProps = {
|
|
38142
|
-
src: url,
|
|
38143
|
-
alt: caption || t("richBlockEditor.embeddedImage"),
|
|
38144
|
-
className: "max-h-96 w-full rounded-md border border-border object-contain"
|
|
38145
|
-
};
|
|
38146
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "space-y-2", children: [
|
|
38147
|
-
url ? /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { as: "img", ...imgProps }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
38148
|
-
exports.Box,
|
|
38149
|
-
{
|
|
38150
|
-
className: cn(
|
|
38151
|
-
"flex h-32 items-center justify-center",
|
|
38152
|
-
"rounded-md border border-dashed border-border",
|
|
38153
|
-
"text-sm text-muted-foreground"
|
|
38154
|
-
),
|
|
38155
|
-
children: [
|
|
38156
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "image", className: "mr-2 w-4 h-4" }),
|
|
38157
|
-
" ",
|
|
38158
|
-
t("richBlockEditor.noImageUrl")
|
|
38159
|
-
]
|
|
38160
|
-
}
|
|
38161
|
-
),
|
|
38162
|
-
!readOnly && /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "flex flex-col gap-2 sm:flex-row", children: [
|
|
38163
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
38164
|
-
exports.Input,
|
|
38165
|
-
{
|
|
38166
|
-
inputType: "url",
|
|
38167
|
-
value: url,
|
|
38168
|
-
placeholder: "https://example.com/image.png",
|
|
38169
|
-
"aria-label": t("richBlockEditor.aria.imageUrl"),
|
|
38170
|
-
className: cn(
|
|
38171
|
-
"h-8 flex-1 rounded-sm border border-border bg-background",
|
|
38172
|
-
"px-2 text-sm outline-none focus:ring-1 focus:ring-ring"
|
|
38173
|
-
),
|
|
38174
|
-
onChange: (e) => setMetadata("url", e.target.value)
|
|
38175
|
-
}
|
|
38176
|
-
),
|
|
38177
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
38178
|
-
exports.Input,
|
|
38179
|
-
{
|
|
38180
|
-
inputType: "text",
|
|
38181
|
-
value: caption,
|
|
38182
|
-
placeholder: t("richBlockEditor.placeholder.caption"),
|
|
38183
|
-
"aria-label": t("richBlockEditor.aria.imageCaption"),
|
|
38184
|
-
className: cn(
|
|
38185
|
-
"h-8 flex-1 rounded-sm border border-border bg-background",
|
|
38186
|
-
"px-2 text-sm outline-none focus:ring-1 focus:ring-ring"
|
|
38187
|
-
),
|
|
38188
|
-
onChange: (e) => setMetadata("caption", e.target.value)
|
|
38189
|
-
}
|
|
38190
|
-
)
|
|
38191
|
-
] }),
|
|
38192
|
-
readOnly && caption && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: "text-center text-muted-foreground", children: caption })
|
|
38193
|
-
] });
|
|
38384
|
+
const [fieldDraft, setFieldDraft] = React77.useState(null);
|
|
38385
|
+
const recordId = entity?.id !== void 0 && entity?.id !== null ? String(entity.id) : "";
|
|
38386
|
+
const fieldDefs = (fields ?? []).filter((f3) => fieldName(f3) !== "");
|
|
38387
|
+
if (fieldDefs.length === 0) return null;
|
|
38388
|
+
const commitField = (name, next, current) => {
|
|
38389
|
+
setFieldDraft(null);
|
|
38390
|
+
if (!metaCommitEvent || next === current) return;
|
|
38391
|
+
eventBus.emit(`UI:${metaCommitEvent}`, { id: recordId, patch: { id: recordId, [name]: next } });
|
|
38392
|
+
};
|
|
38393
|
+
const renderValue = (field) => {
|
|
38394
|
+
const name = fieldName(field);
|
|
38395
|
+
const raw = getNestedValue(entity ?? {}, name);
|
|
38396
|
+
const kind = fieldKind(field, raw);
|
|
38397
|
+
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
38398
|
+
if (kind === "boolean") {
|
|
38399
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38400
|
+
exports.Switch,
|
|
38401
|
+
{
|
|
38402
|
+
checked: Boolean(raw),
|
|
38403
|
+
disabled: !metaCommitEvent,
|
|
38404
|
+
"aria-label": label,
|
|
38405
|
+
onChange: (checked) => commitField(name, checked, Boolean(raw))
|
|
38406
|
+
}
|
|
38407
|
+
);
|
|
38408
|
+
}
|
|
38409
|
+
if (kind === "select") {
|
|
38410
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38411
|
+
exports.Select,
|
|
38412
|
+
{
|
|
38413
|
+
value: raw !== void 0 && raw !== null ? String(raw) : "",
|
|
38414
|
+
disabled: !metaCommitEvent,
|
|
38415
|
+
"aria-label": label,
|
|
38416
|
+
className: "h-8 w-full",
|
|
38417
|
+
options: (field.options ?? []).map((opt) => ({ value: opt, label: humanizeEnumValue(opt) })),
|
|
38418
|
+
onChange: (e) => commitField(name, e.target.value, raw)
|
|
38419
|
+
}
|
|
38420
|
+
);
|
|
38421
|
+
}
|
|
38422
|
+
if (kind === "readonly" || !metaCommitEvent) {
|
|
38423
|
+
if (Array.isArray(raw)) {
|
|
38424
|
+
if (raw.length === 0) {
|
|
38425
|
+
return /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
38426
|
+
}
|
|
38427
|
+
return /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: "default", children: relationLabel(item) ?? humanizeEnumValue(String(item)) }, i)) });
|
|
38194
38428
|
}
|
|
38195
|
-
|
|
38196
|
-
|
|
38197
|
-
|
|
38198
|
-
|
|
38199
|
-
|
|
38200
|
-
|
|
38201
|
-
|
|
38202
|
-
|
|
38203
|
-
|
|
38204
|
-
|
|
38205
|
-
|
|
38206
|
-
|
|
38207
|
-
|
|
38208
|
-
|
|
38209
|
-
|
|
38210
|
-
|
|
38211
|
-
|
|
38212
|
-
|
|
38213
|
-
|
|
38214
|
-
|
|
38215
|
-
|
|
38216
|
-
|
|
38217
|
-
|
|
38218
|
-
|
|
38219
|
-
|
|
38220
|
-
|
|
38221
|
-
|
|
38222
|
-
|
|
38223
|
-
|
|
38224
|
-
|
|
38225
|
-
|
|
38226
|
-
|
|
38227
|
-
|
|
38228
|
-
|
|
38229
|
-
|
|
38230
|
-
|
|
38231
|
-
|
|
38232
|
-
|
|
38233
|
-
|
|
38234
|
-
|
|
38235
|
-
|
|
38236
|
-
exports.Button,
|
|
38237
|
-
{
|
|
38238
|
-
type: "button",
|
|
38239
|
-
variant: "ghost",
|
|
38240
|
-
className: cn(
|
|
38241
|
-
"inline-flex items-center gap-1 text-xs text-muted-foreground",
|
|
38242
|
-
"hover:text-foreground p-0 h-auto"
|
|
38243
|
-
),
|
|
38244
|
-
onClick: addListItem,
|
|
38245
|
-
children: [
|
|
38246
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "plus", className: "w-3 h-3" }),
|
|
38247
|
-
" ",
|
|
38248
|
-
t("richBlockEditor.addItem")
|
|
38249
|
-
]
|
|
38250
|
-
}
|
|
38251
|
-
) })
|
|
38252
|
-
]
|
|
38429
|
+
const shown2 = raw === void 0 || raw === null || raw === "" ? "\u2014" : relationLabel(raw) ?? formatValue(raw, field.format);
|
|
38430
|
+
return /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", className: "break-words", children: shown2 });
|
|
38431
|
+
}
|
|
38432
|
+
if (fieldDraft?.name === name) {
|
|
38433
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38434
|
+
exports.Input,
|
|
38435
|
+
{
|
|
38436
|
+
value: fieldDraft.value,
|
|
38437
|
+
autoFocus: true,
|
|
38438
|
+
"aria-label": label,
|
|
38439
|
+
className: "h-8 w-full",
|
|
38440
|
+
onChange: (e) => setFieldDraft({ name, value: e.target.value }),
|
|
38441
|
+
onBlur: () => commitField(name, fieldDraft.value.trim(), raw),
|
|
38442
|
+
onKeyDown: (e) => {
|
|
38443
|
+
if (e.key === "Enter") {
|
|
38444
|
+
e.preventDefault();
|
|
38445
|
+
commitField(name, fieldDraft.value.trim(), raw);
|
|
38446
|
+
} else if (e.key === "Escape") {
|
|
38447
|
+
e.preventDefault();
|
|
38448
|
+
setFieldDraft(null);
|
|
38449
|
+
}
|
|
38450
|
+
},
|
|
38451
|
+
"data-testid": `document-property-input-${name}`
|
|
38452
|
+
}
|
|
38453
|
+
);
|
|
38454
|
+
}
|
|
38455
|
+
const shown = raw === void 0 || raw === null || raw === "" ? "\u2014" : relationLabel(raw) ?? formatValue(raw, field.format);
|
|
38456
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38457
|
+
exports.Box,
|
|
38458
|
+
{
|
|
38459
|
+
role: "button",
|
|
38460
|
+
tabIndex: 0,
|
|
38461
|
+
className: cn(
|
|
38462
|
+
"cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
38463
|
+
(raw === void 0 || raw === null || raw === "") && "text-muted-foreground"
|
|
38464
|
+
),
|
|
38465
|
+
onClick: () => setFieldDraft({ name, value: raw !== void 0 && raw !== null ? String(raw) : "" }),
|
|
38466
|
+
onKeyDown: (e) => {
|
|
38467
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
38468
|
+
e.preventDefault();
|
|
38469
|
+
setFieldDraft({ name, value: raw !== void 0 && raw !== null ? String(raw) : "" });
|
|
38253
38470
|
}
|
|
38254
|
-
|
|
38471
|
+
},
|
|
38472
|
+
"data-testid": `document-property-${name}`,
|
|
38473
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", className: "break-words", children: shown })
|
|
38255
38474
|
}
|
|
38256
|
-
|
|
38257
|
-
default:
|
|
38258
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38259
|
-
Editable,
|
|
38260
|
-
{
|
|
38261
|
-
tag: "p",
|
|
38262
|
-
value: block.content ?? "",
|
|
38263
|
-
readOnly,
|
|
38264
|
-
placeholder: placeholder ?? t("richBlockEditor.placeholder.paragraph"),
|
|
38265
|
-
ariaLabel: t("richBlockEditor.aria.paragraphBlock"),
|
|
38266
|
-
className: "leading-7",
|
|
38267
|
-
onValueChange: setContent
|
|
38268
|
-
}
|
|
38269
|
-
);
|
|
38270
|
-
}
|
|
38475
|
+
);
|
|
38271
38476
|
};
|
|
38272
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
38273
|
-
exports.
|
|
38274
|
-
{
|
|
38275
|
-
|
|
38276
|
-
|
|
38277
|
-
|
|
38278
|
-
|
|
38279
|
-
|
|
38280
|
-
|
|
38281
|
-
|
|
38282
|
-
|
|
38283
|
-
|
|
38284
|
-
|
|
38285
|
-
|
|
38286
|
-
readOnly,
|
|
38287
|
-
onDelete,
|
|
38288
|
-
onDuplicate,
|
|
38289
|
-
onChangeType
|
|
38290
|
-
}
|
|
38291
|
-
) }),
|
|
38292
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "min-w-0 flex-1", children: renderBody() })
|
|
38293
|
-
]
|
|
38294
|
-
}
|
|
38295
|
-
);
|
|
38477
|
+
return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { variant: "bordered", className: cn("w-full", className), children: /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "sm", className: "p-4", children: [
|
|
38478
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", weight: "medium", className: "uppercase tracking-wide", children: title ?? (t("documentDetails.title") || "Details") }),
|
|
38479
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.VStack, { gap: "sm", children: fieldDefs.map((field) => {
|
|
38480
|
+
const name = fieldName(field);
|
|
38481
|
+
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
38482
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", children: [
|
|
38483
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
|
|
38484
|
+
field.icon && renderIconInput5(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
38485
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "muted", children: label })
|
|
38486
|
+
] }),
|
|
38487
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "min-w-0", children: renderValue(field) })
|
|
38488
|
+
] }, name);
|
|
38489
|
+
}) })
|
|
38490
|
+
] }) });
|
|
38296
38491
|
}
|
|
38297
|
-
var
|
|
38298
|
-
|
|
38299
|
-
"components/core/molecules/RichBlockEditor.tsx"() {
|
|
38492
|
+
var init_DocumentDetails = __esm({
|
|
38493
|
+
"components/core/molecules/DocumentDetails.tsx"() {
|
|
38300
38494
|
"use client";
|
|
38301
38495
|
init_cn();
|
|
38302
|
-
|
|
38303
|
-
|
|
38304
|
-
|
|
38496
|
+
init_format();
|
|
38497
|
+
init_getNestedValue();
|
|
38498
|
+
init_useEventBus();
|
|
38305
38499
|
init_Box();
|
|
38306
|
-
|
|
38307
|
-
|
|
38500
|
+
init_Stack();
|
|
38501
|
+
init_Typography();
|
|
38502
|
+
init_Badge();
|
|
38503
|
+
init_Card();
|
|
38308
38504
|
init_Icon();
|
|
38309
|
-
|
|
38310
|
-
|
|
38311
|
-
|
|
38312
|
-
{ type: "heading-1", labelKey: "richBlockEditor.toolbar.h1", icon: LucideIcons2.Heading1 },
|
|
38313
|
-
{ type: "heading-2", labelKey: "richBlockEditor.toolbar.h2", icon: LucideIcons2.Heading2 },
|
|
38314
|
-
{ type: "heading-3", labelKey: "richBlockEditor.toolbar.h3", icon: LucideIcons2.Heading3 },
|
|
38315
|
-
{ type: "bullet-list", labelKey: "richBlockEditor.toolbar.bulletList", icon: LucideIcons2.List },
|
|
38316
|
-
{ type: "numbered-list", labelKey: "richBlockEditor.toolbar.numbered", icon: LucideIcons2.ListOrdered },
|
|
38317
|
-
{ type: "quote", labelKey: "richBlockEditor.toolbar.quote", icon: LucideIcons2.Quote },
|
|
38318
|
-
{ type: "code", labelKey: "richBlockEditor.toolbar.code", icon: LucideIcons2.Code },
|
|
38319
|
-
{ type: "divider", labelKey: "richBlockEditor.toolbar.divider", icon: LucideIcons2.Minus },
|
|
38320
|
-
{ type: "image", labelKey: "richBlockEditor.toolbar.image", icon: LucideIcons2.Image }
|
|
38321
|
-
];
|
|
38322
|
-
BLOCK_TYPE_LABEL_KEY = {
|
|
38323
|
-
paragraph: "richBlockEditor.blockType.paragraph",
|
|
38324
|
-
"heading-1": "richBlockEditor.blockType.heading1",
|
|
38325
|
-
"heading-2": "richBlockEditor.blockType.heading2",
|
|
38326
|
-
"heading-3": "richBlockEditor.blockType.heading3",
|
|
38327
|
-
"bullet-list": "richBlockEditor.blockType.bulletList",
|
|
38328
|
-
"numbered-list": "richBlockEditor.blockType.numberedList",
|
|
38329
|
-
quote: "richBlockEditor.blockType.quote",
|
|
38330
|
-
code: "richBlockEditor.blockType.code",
|
|
38331
|
-
divider: "richBlockEditor.blockType.divider",
|
|
38332
|
-
image: "richBlockEditor.blockType.image"
|
|
38333
|
-
};
|
|
38334
|
-
CHANGEABLE_TYPES = [
|
|
38335
|
-
"paragraph",
|
|
38336
|
-
"heading-1",
|
|
38337
|
-
"heading-2",
|
|
38338
|
-
"heading-3",
|
|
38339
|
-
"bullet-list",
|
|
38340
|
-
"numbered-list",
|
|
38341
|
-
"quote",
|
|
38342
|
-
"code"
|
|
38343
|
-
];
|
|
38344
|
-
_idSeq = 0;
|
|
38345
|
-
BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
38346
|
-
"paragraph",
|
|
38347
|
-
"heading-1",
|
|
38348
|
-
"heading-2",
|
|
38349
|
-
"heading-3",
|
|
38350
|
-
"bullet-list",
|
|
38351
|
-
"numbered-list",
|
|
38352
|
-
"quote",
|
|
38353
|
-
"code",
|
|
38354
|
-
"divider",
|
|
38355
|
-
"image"
|
|
38356
|
-
]);
|
|
38357
|
-
exports.RichBlockEditor = ({
|
|
38358
|
-
initialBlocks,
|
|
38359
|
-
onChange,
|
|
38360
|
-
changeEvent,
|
|
38361
|
-
readOnly = false,
|
|
38362
|
-
placeholder,
|
|
38363
|
-
enableBlocks = true,
|
|
38364
|
-
showToolbar = true,
|
|
38365
|
-
className
|
|
38366
|
-
}) => {
|
|
38367
|
-
const { t } = hooks.useTranslate();
|
|
38368
|
-
const [blocks, setBlocks] = React77.useState(
|
|
38369
|
-
() => normalizeBlocks(initialBlocks)
|
|
38370
|
-
);
|
|
38371
|
-
const onChangeRef = React77.useRef(onChange);
|
|
38372
|
-
React77.useEffect(() => {
|
|
38373
|
-
onChangeRef.current = onChange;
|
|
38374
|
-
}, [onChange]);
|
|
38375
|
-
const eventBus = useEventBus();
|
|
38376
|
-
const changeEventRef = React77.useRef(changeEvent);
|
|
38377
|
-
React77.useEffect(() => {
|
|
38378
|
-
changeEventRef.current = changeEvent;
|
|
38379
|
-
}, [changeEvent]);
|
|
38380
|
-
const commit = React77.useCallback((next) => {
|
|
38381
|
-
setBlocks(next);
|
|
38382
|
-
onChangeRef.current?.(next);
|
|
38383
|
-
const evt = changeEventRef.current;
|
|
38384
|
-
if (evt) eventBus.emit(`UI:${evt}`, { blocks: next });
|
|
38385
|
-
}, [eventBus]);
|
|
38386
|
-
const handleAppend = React77.useCallback(
|
|
38387
|
-
(type) => {
|
|
38388
|
-
if (readOnly) return;
|
|
38389
|
-
commit([...blocks, createBlock(type)]);
|
|
38390
|
-
},
|
|
38391
|
-
[blocks, commit, readOnly]
|
|
38392
|
-
);
|
|
38393
|
-
const handleUpdate = React77.useCallback(
|
|
38394
|
-
(id, updater) => {
|
|
38395
|
-
commit(replaceBlock(blocks, id, updater));
|
|
38396
|
-
},
|
|
38397
|
-
[blocks, commit]
|
|
38398
|
-
);
|
|
38399
|
-
const handleDelete = React77.useCallback(
|
|
38400
|
-
(id) => {
|
|
38401
|
-
const next = removeBlock(blocks, id);
|
|
38402
|
-
commit(next.length > 0 ? next : [createBlock("paragraph")]);
|
|
38403
|
-
},
|
|
38404
|
-
[blocks, commit]
|
|
38405
|
-
);
|
|
38406
|
-
const handleDuplicate = React77.useCallback(
|
|
38407
|
-
(id) => {
|
|
38408
|
-
const target = blocks.find((b) => b.id === id);
|
|
38409
|
-
if (!target) return;
|
|
38410
|
-
commit(insertAfter(blocks, id, duplicateBlock(target)));
|
|
38411
|
-
},
|
|
38412
|
-
[blocks, commit]
|
|
38413
|
-
);
|
|
38414
|
-
const handleChangeType = React77.useCallback(
|
|
38415
|
-
(id, type) => {
|
|
38416
|
-
commit(
|
|
38417
|
-
replaceBlock(blocks, id, (b) => changeBlockType(b, type))
|
|
38418
|
-
);
|
|
38419
|
-
},
|
|
38420
|
-
[blocks, commit]
|
|
38421
|
-
);
|
|
38422
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
38423
|
-
exports.Card,
|
|
38424
|
-
{
|
|
38425
|
-
variant: "bordered",
|
|
38426
|
-
padding: "none",
|
|
38427
|
-
className: cn("flex flex-col text-card-foreground", className),
|
|
38428
|
-
children: [
|
|
38429
|
-
enableBlocks && showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
38430
|
-
exports.Box,
|
|
38431
|
-
{
|
|
38432
|
-
role: "toolbar",
|
|
38433
|
-
"aria-label": t("richBlockEditor.editorToolbar"),
|
|
38434
|
-
className: cn(
|
|
38435
|
-
"flex flex-wrap items-center gap-1",
|
|
38436
|
-
"border-b border-border bg-muted/30 px-2 py-2"
|
|
38437
|
-
),
|
|
38438
|
-
children: TOOLBAR_ENTRIES.map((entry) => {
|
|
38439
|
-
const Icon2 = entry.icon;
|
|
38440
|
-
const entryLabel = t(entry.labelKey);
|
|
38441
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
38442
|
-
exports.Button,
|
|
38443
|
-
{
|
|
38444
|
-
type: "button",
|
|
38445
|
-
variant: "ghost",
|
|
38446
|
-
size: "sm",
|
|
38447
|
-
"aria-label": t("richBlockEditor.insertEntry", { label: entryLabel }),
|
|
38448
|
-
title: entryLabel,
|
|
38449
|
-
onClick: () => handleAppend(entry.type),
|
|
38450
|
-
children: [
|
|
38451
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon2, { size: 14 }),
|
|
38452
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { as: "span", variant: "caption", className: "ml-1 hidden text-xs sm:inline", children: entryLabel })
|
|
38453
|
-
]
|
|
38454
|
-
},
|
|
38455
|
-
entry.type
|
|
38456
|
-
);
|
|
38457
|
-
})
|
|
38458
|
-
}
|
|
38459
|
-
),
|
|
38460
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "flex flex-col gap-1 px-3 py-3", children: blocks.map((block) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
38461
|
-
BlockRow,
|
|
38462
|
-
{
|
|
38463
|
-
block,
|
|
38464
|
-
readOnly,
|
|
38465
|
-
showAffordances: enableBlocks,
|
|
38466
|
-
placeholder,
|
|
38467
|
-
onUpdate: (updater) => handleUpdate(block.id, updater),
|
|
38468
|
-
onDelete: () => handleDelete(block.id),
|
|
38469
|
-
onDuplicate: () => handleDuplicate(block.id),
|
|
38470
|
-
onChangeType: (type) => handleChangeType(block.id, type)
|
|
38471
|
-
},
|
|
38472
|
-
block.id
|
|
38473
|
-
)) })
|
|
38474
|
-
]
|
|
38475
|
-
}
|
|
38476
|
-
);
|
|
38477
|
-
};
|
|
38478
|
-
exports.RichBlockEditor.displayName = "RichBlockEditor";
|
|
38505
|
+
init_Input();
|
|
38506
|
+
init_Select();
|
|
38507
|
+
init_Switch();
|
|
38479
38508
|
}
|
|
38480
38509
|
});
|
|
38481
38510
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
@@ -43149,7 +43178,9 @@ var init_molecules2 = __esm({
|
|
|
43149
43178
|
init_QrScanner();
|
|
43150
43179
|
init_OptionConstraintGroup();
|
|
43151
43180
|
init_PositionedCanvas();
|
|
43152
|
-
|
|
43181
|
+
init_RichTextEditor();
|
|
43182
|
+
init_DocumentPanel();
|
|
43183
|
+
init_DocumentDetails();
|
|
43153
43184
|
init_ReplyTree();
|
|
43154
43185
|
init_BranchingLogicBuilder();
|
|
43155
43186
|
init_VersionDiff();
|
|
@@ -43649,8 +43680,8 @@ var init_DataTable = __esm({
|
|
|
43649
43680
|
DataTable.displayName = "DataTable";
|
|
43650
43681
|
}
|
|
43651
43682
|
});
|
|
43652
|
-
function getBadgeVariant(
|
|
43653
|
-
const name =
|
|
43683
|
+
function getBadgeVariant(fieldName2, value) {
|
|
43684
|
+
const name = fieldName2.toLowerCase();
|
|
43654
43685
|
const val = String(value).toLowerCase();
|
|
43655
43686
|
if (name.includes("status")) {
|
|
43656
43687
|
if (val.includes("complete") || val.includes("done") || val.includes("active"))
|
|
@@ -43666,12 +43697,12 @@ function getBadgeVariant(fieldName, value) {
|
|
|
43666
43697
|
}
|
|
43667
43698
|
return "default";
|
|
43668
43699
|
}
|
|
43669
|
-
function formatFieldValue2(value,
|
|
43700
|
+
function formatFieldValue2(value, fieldName2) {
|
|
43670
43701
|
if (typeof value === "number") {
|
|
43671
|
-
if (
|
|
43702
|
+
if (fieldName2.toLowerCase().includes("progress") || fieldName2.toLowerCase().includes("percent")) {
|
|
43672
43703
|
return `${value}%`;
|
|
43673
43704
|
}
|
|
43674
|
-
if (
|
|
43705
|
+
if (fieldName2.toLowerCase().includes("budget") || fieldName2.toLowerCase().includes("cost")) {
|
|
43675
43706
|
return `$${value.toLocaleString()}`;
|
|
43676
43707
|
}
|
|
43677
43708
|
return value.toLocaleString();
|
|
@@ -43681,7 +43712,7 @@ function formatFieldValue2(value, fieldName) {
|
|
|
43681
43712
|
}
|
|
43682
43713
|
return String(value);
|
|
43683
43714
|
}
|
|
43684
|
-
function renderRichFieldValue(value,
|
|
43715
|
+
function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
43685
43716
|
if (value === void 0 || value === null) return "\u2014";
|
|
43686
43717
|
const str2 = String(value);
|
|
43687
43718
|
switch (fieldType) {
|
|
@@ -43692,7 +43723,7 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
|
|
|
43692
43723
|
"img",
|
|
43693
43724
|
{
|
|
43694
43725
|
src: str2,
|
|
43695
|
-
alt: formatFieldLabel(
|
|
43726
|
+
alt: formatFieldLabel(fieldName2),
|
|
43696
43727
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
43697
43728
|
loading: "lazy"
|
|
43698
43729
|
}
|
|
@@ -43827,9 +43858,9 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
|
|
|
43827
43858
|
return /* @__PURE__ */ jsxRuntime.jsx("a", { href: `tel:${str2}`, className: "text-primary hover:underline", children: str2 });
|
|
43828
43859
|
default:
|
|
43829
43860
|
if (meta?.values && meta.values.length > 0 && meta.values.includes(str2)) {
|
|
43830
|
-
return /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: getBadgeVariant(
|
|
43861
|
+
return /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: getBadgeVariant(fieldName2, str2), children: humanizeEnumValue(str2) });
|
|
43831
43862
|
}
|
|
43832
|
-
return formatFieldValue2(value,
|
|
43863
|
+
return formatFieldValue2(value, fieldName2);
|
|
43833
43864
|
}
|
|
43834
43865
|
}
|
|
43835
43866
|
function normalizeFieldDefs(fields) {
|
|
@@ -44299,16 +44330,11 @@ var init_DetailPanel = __esm({
|
|
|
44299
44330
|
footer
|
|
44300
44331
|
] })
|
|
44301
44332
|
] }) });
|
|
44302
|
-
|
|
44303
|
-
exports.Box,
|
|
44304
|
-
|
|
44305
|
-
|
|
44306
|
-
|
|
44307
|
-
className
|
|
44308
|
-
),
|
|
44309
|
-
children: content
|
|
44310
|
-
}
|
|
44311
|
-
);
|
|
44333
|
+
if (!slideOver) {
|
|
44334
|
+
return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className, children: content });
|
|
44335
|
+
}
|
|
44336
|
+
const panel = /* @__PURE__ */ jsxRuntime.jsx(exports.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 });
|
|
44337
|
+
return typeof document === "undefined" ? panel : reactDom.createPortal(panel, document.body);
|
|
44312
44338
|
};
|
|
44313
44339
|
exports.DetailPanel.displayName = "DetailPanel";
|
|
44314
44340
|
}
|
|
@@ -44677,7 +44703,21 @@ var init_Form = __esm({
|
|
|
44677
44703
|
const normalizedInitialData = React77__namespace.default.useMemo(() => {
|
|
44678
44704
|
const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
|
|
44679
44705
|
const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
|
|
44680
|
-
|
|
44706
|
+
const merged = entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
|
|
44707
|
+
const toId = (value) => {
|
|
44708
|
+
if (value === null || value === void 0 || typeof value !== "object" || value instanceof Date) return value;
|
|
44709
|
+
if (Array.isArray(value)) {
|
|
44710
|
+
return value.map(
|
|
44711
|
+
(item) => item !== null && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && item.id !== void 0 && item.id !== null ? String(item.id) : item
|
|
44712
|
+
);
|
|
44713
|
+
}
|
|
44714
|
+
return value.id !== void 0 && value.id !== null ? String(value.id) : value;
|
|
44715
|
+
};
|
|
44716
|
+
const normalized = {};
|
|
44717
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
44718
|
+
normalized[key] = key === "id" ? value : toId(value);
|
|
44719
|
+
}
|
|
44720
|
+
return normalized;
|
|
44681
44721
|
}, [entity, initialData]);
|
|
44682
44722
|
const entityDerivedFields = React77__namespace.default.useMemo(() => {
|
|
44683
44723
|
if (fields && fields.length > 0) return void 0;
|
|
@@ -44806,8 +44846,8 @@ var init_Form = __esm({
|
|
|
44806
44846
|
checkViolations(name, newFormData);
|
|
44807
44847
|
};
|
|
44808
44848
|
const isFieldVisible = React77__namespace.default.useCallback(
|
|
44809
|
-
(
|
|
44810
|
-
const condition = conditionalFields[
|
|
44849
|
+
(fieldName2) => {
|
|
44850
|
+
const condition = conditionalFields[fieldName2];
|
|
44811
44851
|
if (!condition) return true;
|
|
44812
44852
|
return Boolean(evaluateFormExpression(condition, evalContext));
|
|
44813
44853
|
},
|
|
@@ -44853,9 +44893,9 @@ var init_Form = __esm({
|
|
|
44853
44893
|
};
|
|
44854
44894
|
const handleInvalid = (e) => {
|
|
44855
44895
|
const target = e.target;
|
|
44856
|
-
const
|
|
44896
|
+
const fieldName2 = target.getAttribute("data-field-name") ?? target.name ?? "";
|
|
44857
44897
|
const fieldMessage = target.validationMessage || "Invalid value";
|
|
44858
|
-
debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
|
|
44898
|
+
debug("forms", "invalid", { mode: formMode, fieldName: fieldName2, fieldMessage });
|
|
44859
44899
|
queueMicrotask(() => {
|
|
44860
44900
|
const form = formRef.current;
|
|
44861
44901
|
if (!form) return;
|
|
@@ -44891,22 +44931,22 @@ var init_Form = __esm({
|
|
|
44891
44931
|
};
|
|
44892
44932
|
const renderField = React77__namespace.default.useCallback(
|
|
44893
44933
|
(field) => {
|
|
44894
|
-
const
|
|
44895
|
-
if (!
|
|
44896
|
-
if (!isFieldVisible(
|
|
44934
|
+
const fieldName2 = field.name || field.field;
|
|
44935
|
+
if (!fieldName2) return null;
|
|
44936
|
+
if (!isFieldVisible(fieldName2)) {
|
|
44897
44937
|
return null;
|
|
44898
44938
|
}
|
|
44899
44939
|
const inputType = determineInputType(field);
|
|
44900
|
-
const label = field.label ||
|
|
44901
|
-
const currentValue2 = formData[
|
|
44902
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", "data-field":
|
|
44940
|
+
const label = field.label || fieldName2.charAt(0).toUpperCase() + fieldName2.slice(1).replace(/([A-Z])/g, " $1");
|
|
44941
|
+
const currentValue2 = formData[fieldName2] ?? field.defaultValue ?? "";
|
|
44942
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", "data-field": fieldName2, children: [
|
|
44903
44943
|
inputType !== "checkbox" && /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { as: "label", variant: "label", weight: "bold", children: [
|
|
44904
44944
|
label,
|
|
44905
44945
|
field.required && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { as: "span", color: "error", className: "ml-1", children: "*" })
|
|
44906
44946
|
] }),
|
|
44907
|
-
renderFieldInput(field,
|
|
44947
|
+
renderFieldInput(field, fieldName2, inputType, currentValue2, label),
|
|
44908
44948
|
field.hint && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "muted", children: field.hint })
|
|
44909
|
-
] },
|
|
44949
|
+
] }, fieldName2);
|
|
44910
44950
|
},
|
|
44911
44951
|
[formData, isFieldVisible, relationsData, relationsLoading, isLoading]
|
|
44912
44952
|
);
|
|
@@ -44935,8 +44975,8 @@ var init_Form = __esm({
|
|
|
44935
44975
|
}
|
|
44936
44976
|
return field;
|
|
44937
44977
|
}).map((field) => {
|
|
44938
|
-
const
|
|
44939
|
-
const override = fieldOverrides?.find((o) => o.name ===
|
|
44978
|
+
const fieldName2 = field.name || field.field;
|
|
44979
|
+
const override = fieldOverrides?.find((o) => o.name === fieldName2);
|
|
44940
44980
|
if (!override) return field;
|
|
44941
44981
|
return {
|
|
44942
44982
|
...field,
|
|
@@ -44992,11 +45032,11 @@ var init_Form = __esm({
|
|
|
44992
45032
|
] }, section.id);
|
|
44993
45033
|
}).filter(Boolean);
|
|
44994
45034
|
}, [sections, isSectionVisible, collapsedSections, renderField, gap]);
|
|
44995
|
-
function renderFieldInput(field,
|
|
45035
|
+
function renderFieldInput(field, fieldName2, inputType, currentValue2, label) {
|
|
44996
45036
|
const commonProps = {
|
|
44997
|
-
id:
|
|
44998
|
-
name:
|
|
44999
|
-
"data-field-name":
|
|
45037
|
+
id: fieldName2,
|
|
45038
|
+
name: fieldName2,
|
|
45039
|
+
"data-field-name": fieldName2,
|
|
45000
45040
|
required: field.required,
|
|
45001
45041
|
disabled: isLoading,
|
|
45002
45042
|
placeholder: field.placeholder,
|
|
@@ -45010,7 +45050,7 @@ var init_Form = __esm({
|
|
|
45010
45050
|
...commonProps,
|
|
45011
45051
|
label: label + (field.required ? " *" : ""),
|
|
45012
45052
|
checked: Boolean(currentValue2),
|
|
45013
|
-
onChange: (e) => handleChange(
|
|
45053
|
+
onChange: (e) => handleChange(fieldName2, e.target.checked)
|
|
45014
45054
|
}
|
|
45015
45055
|
);
|
|
45016
45056
|
case "textarea":
|
|
@@ -45019,7 +45059,7 @@ var init_Form = __esm({
|
|
|
45019
45059
|
{
|
|
45020
45060
|
...commonProps,
|
|
45021
45061
|
value: String(currentValue2),
|
|
45022
|
-
onChange: (e) => handleChange(
|
|
45062
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
45023
45063
|
minLength: field.min,
|
|
45024
45064
|
maxLength: field.max
|
|
45025
45065
|
}
|
|
@@ -45032,14 +45072,14 @@ var init_Form = __esm({
|
|
|
45032
45072
|
...commonProps,
|
|
45033
45073
|
options,
|
|
45034
45074
|
value: String(currentValue2),
|
|
45035
|
-
onValueChange: (v) => handleChange(
|
|
45075
|
+
onValueChange: (v) => handleChange(fieldName2, v),
|
|
45036
45076
|
placeholder: field.placeholder || `Select ${label}...`
|
|
45037
45077
|
}
|
|
45038
45078
|
);
|
|
45039
45079
|
}
|
|
45040
45080
|
case "relation": {
|
|
45041
|
-
const relationOptions = relationsData[
|
|
45042
|
-
const relationLoading = relationsLoading[
|
|
45081
|
+
const relationOptions = relationsData[fieldName2] || [];
|
|
45082
|
+
const relationLoading = relationsLoading[fieldName2] || false;
|
|
45043
45083
|
if (field.relation?.cardinality !== void 0 && MANY_CARDINALITIES.includes(field.relation.cardinality)) {
|
|
45044
45084
|
const selectedValues = Array.isArray(currentValue2) ? currentValue2.map((v) => String(v)) : [];
|
|
45045
45085
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -45051,7 +45091,7 @@ var init_Form = __esm({
|
|
|
45051
45091
|
clearable: true,
|
|
45052
45092
|
options: [...relationOptions],
|
|
45053
45093
|
value: selectedValues,
|
|
45054
|
-
onValueChange: (value) => handleChange(
|
|
45094
|
+
onValueChange: (value) => handleChange(fieldName2, Array.isArray(value) ? value : [value]),
|
|
45055
45095
|
placeholder: field.placeholder || `Select ${label}...`
|
|
45056
45096
|
}
|
|
45057
45097
|
);
|
|
@@ -45061,7 +45101,7 @@ var init_Form = __esm({
|
|
|
45061
45101
|
{
|
|
45062
45102
|
...commonProps,
|
|
45063
45103
|
value: currentValue2 ? String(currentValue2) : void 0,
|
|
45064
|
-
onChange: (value) => handleChange(
|
|
45104
|
+
onChange: (value) => handleChange(fieldName2, value),
|
|
45065
45105
|
options: relationOptions,
|
|
45066
45106
|
isLoading: relationLoading,
|
|
45067
45107
|
placeholder: field.placeholder || `Select ${label}...`,
|
|
@@ -45078,7 +45118,7 @@ var init_Form = __esm({
|
|
|
45078
45118
|
placeholder: field.placeholder,
|
|
45079
45119
|
disabled: isLoading,
|
|
45080
45120
|
value: arrayValue,
|
|
45081
|
-
onChange: (next) => handleChange(
|
|
45121
|
+
onChange: (next) => handleChange(fieldName2, [...next])
|
|
45082
45122
|
}
|
|
45083
45123
|
);
|
|
45084
45124
|
}
|
|
@@ -45090,7 +45130,7 @@ var init_Form = __esm({
|
|
|
45090
45130
|
type: "number",
|
|
45091
45131
|
value: currentValue2 !== void 0 && currentValue2 !== "" ? String(currentValue2) : "",
|
|
45092
45132
|
onChange: (e) => handleChange(
|
|
45093
|
-
|
|
45133
|
+
fieldName2,
|
|
45094
45134
|
e.target.value ? Number(e.target.value) : void 0
|
|
45095
45135
|
),
|
|
45096
45136
|
min: field.min,
|
|
@@ -45107,7 +45147,7 @@ var init_Form = __esm({
|
|
|
45107
45147
|
icon: LucideIcons2.DollarSign,
|
|
45108
45148
|
value: currentValue2 !== void 0 && currentValue2 !== "" ? String(currentValue2) : "",
|
|
45109
45149
|
onChange: (e) => handleChange(
|
|
45110
|
-
|
|
45150
|
+
fieldName2,
|
|
45111
45151
|
e.target.value ? Number(e.target.value) : void 0
|
|
45112
45152
|
),
|
|
45113
45153
|
min: field.min,
|
|
@@ -45125,7 +45165,7 @@ var init_Form = __esm({
|
|
|
45125
45165
|
const f3 = files[0];
|
|
45126
45166
|
if (!f3) return;
|
|
45127
45167
|
const reader = new FileReader();
|
|
45128
|
-
reader.onload = () => handleChange(
|
|
45168
|
+
reader.onload = () => handleChange(fieldName2, {
|
|
45129
45169
|
name: f3.name,
|
|
45130
45170
|
mimeType: f3.type,
|
|
45131
45171
|
sizeBytes: f3.size,
|
|
@@ -45142,7 +45182,7 @@ var init_Form = __esm({
|
|
|
45142
45182
|
...commonProps,
|
|
45143
45183
|
type: "date",
|
|
45144
45184
|
value: formatDateValue(currentValue2),
|
|
45145
|
-
onChange: (e) => handleChange(
|
|
45185
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
45146
45186
|
}
|
|
45147
45187
|
);
|
|
45148
45188
|
case "datetime-local":
|
|
@@ -45152,7 +45192,7 @@ var init_Form = __esm({
|
|
|
45152
45192
|
...commonProps,
|
|
45153
45193
|
type: "datetime-local",
|
|
45154
45194
|
value: formatDateTimeValue(currentValue2),
|
|
45155
|
-
onChange: (e) => handleChange(
|
|
45195
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
45156
45196
|
}
|
|
45157
45197
|
);
|
|
45158
45198
|
case "email":
|
|
@@ -45162,7 +45202,7 @@ var init_Form = __esm({
|
|
|
45162
45202
|
...commonProps,
|
|
45163
45203
|
type: "email",
|
|
45164
45204
|
value: String(currentValue2),
|
|
45165
|
-
onChange: (e) => handleChange(
|
|
45205
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
45166
45206
|
minLength: field.min,
|
|
45167
45207
|
maxLength: field.max
|
|
45168
45208
|
}
|
|
@@ -45174,7 +45214,7 @@ var init_Form = __esm({
|
|
|
45174
45214
|
...commonProps,
|
|
45175
45215
|
type: "url",
|
|
45176
45216
|
value: String(currentValue2),
|
|
45177
|
-
onChange: (e) => handleChange(
|
|
45217
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
45178
45218
|
minLength: field.min,
|
|
45179
45219
|
maxLength: field.max
|
|
45180
45220
|
}
|
|
@@ -45186,7 +45226,7 @@ var init_Form = __esm({
|
|
|
45186
45226
|
...commonProps,
|
|
45187
45227
|
type: "password",
|
|
45188
45228
|
value: String(currentValue2),
|
|
45189
|
-
onChange: (e) => handleChange(
|
|
45229
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
45190
45230
|
minLength: field.min,
|
|
45191
45231
|
maxLength: field.max
|
|
45192
45232
|
}
|
|
@@ -45199,7 +45239,7 @@ var init_Form = __esm({
|
|
|
45199
45239
|
...commonProps,
|
|
45200
45240
|
type: "text",
|
|
45201
45241
|
value: String(currentValue2),
|
|
45202
|
-
onChange: (e) => handleChange(
|
|
45242
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
45203
45243
|
minLength: field.min,
|
|
45204
45244
|
maxLength: field.max
|
|
45205
45245
|
}
|
|
@@ -45556,7 +45596,7 @@ function entityFieldsFromListItem(item) {
|
|
|
45556
45596
|
}
|
|
45557
45597
|
return result;
|
|
45558
45598
|
}
|
|
45559
|
-
function getStatusStyle(
|
|
45599
|
+
function getStatusStyle(fieldName2, value) {
|
|
45560
45600
|
const val = String(value).toLowerCase();
|
|
45561
45601
|
if (val.includes("complete") || val.includes("done"))
|
|
45562
45602
|
return STATUS_STYLES.complete;
|
|
@@ -45572,12 +45612,12 @@ function getStatusStyle(fieldName, value) {
|
|
|
45572
45612
|
if (val.includes("low")) return STATUS_STYLES.low;
|
|
45573
45613
|
return STATUS_STYLES.default;
|
|
45574
45614
|
}
|
|
45575
|
-
function formatValue3(value,
|
|
45615
|
+
function formatValue3(value, fieldName2) {
|
|
45576
45616
|
if (typeof value === "number") {
|
|
45577
|
-
if (
|
|
45617
|
+
if (fieldName2.toLowerCase().includes("progress") || fieldName2.toLowerCase().includes("percent")) {
|
|
45578
45618
|
return `${value}%`;
|
|
45579
45619
|
}
|
|
45580
|
-
if (
|
|
45620
|
+
if (fieldName2.toLowerCase().includes("budget") || fieldName2.toLowerCase().includes("cost")) {
|
|
45581
45621
|
return new Intl.NumberFormat("en-US", {
|
|
45582
45622
|
style: "currency",
|
|
45583
45623
|
currency: "USD",
|
|
@@ -45600,8 +45640,8 @@ function formatValue3(value, fieldName) {
|
|
|
45600
45640
|
}
|
|
45601
45641
|
return String(value);
|
|
45602
45642
|
}
|
|
45603
|
-
function formatFieldLabel2(
|
|
45604
|
-
return humanizeFieldName(
|
|
45643
|
+
function formatFieldLabel2(fieldName2) {
|
|
45644
|
+
return humanizeFieldName(fieldName2).replace(/\sId$/, "").trim();
|
|
45605
45645
|
}
|
|
45606
45646
|
var STATUS_STYLES, StatusBadge, ProgressIndicator; exports.List = void 0;
|
|
45607
45647
|
var init_List = __esm({
|
|
@@ -45669,9 +45709,9 @@ var init_List = __esm({
|
|
|
45669
45709
|
};
|
|
45670
45710
|
StatusBadge = ({
|
|
45671
45711
|
value,
|
|
45672
|
-
fieldName
|
|
45712
|
+
fieldName: fieldName2
|
|
45673
45713
|
}) => {
|
|
45674
|
-
const style = getStatusStyle(
|
|
45714
|
+
const style = getStatusStyle(fieldName2, value);
|
|
45675
45715
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
45676
45716
|
exports.Typography,
|
|
45677
45717
|
{
|
|
@@ -48584,8 +48624,8 @@ var init_StatCard = __esm({
|
|
|
48584
48624
|
return items.length;
|
|
48585
48625
|
}
|
|
48586
48626
|
if (field.includes(":")) {
|
|
48587
|
-
const [
|
|
48588
|
-
return items.filter((item) => item[
|
|
48627
|
+
const [fieldName2, fieldValue] = field.split(":");
|
|
48628
|
+
return items.filter((item) => item[fieldName2] === fieldValue).length;
|
|
48589
48629
|
}
|
|
48590
48630
|
const fieldExistsOnItems = items.some((item) => field in item);
|
|
48591
48631
|
if (fieldExistsOnItems) {
|
|
@@ -50105,6 +50145,8 @@ var init_component_registry_generated = __esm({
|
|
|
50105
50145
|
init_DocSearch();
|
|
50106
50146
|
init_DocSidebar();
|
|
50107
50147
|
init_DocTOC();
|
|
50148
|
+
init_DocumentDetails();
|
|
50149
|
+
init_DocumentPanel();
|
|
50108
50150
|
init_DocumentViewer();
|
|
50109
50151
|
init_DrawFxLayer();
|
|
50110
50152
|
init_DrawGroup();
|
|
@@ -50214,7 +50256,7 @@ var init_component_registry_generated = __esm({
|
|
|
50214
50256
|
init_RelationSelect();
|
|
50215
50257
|
init_RepeatableFormSection();
|
|
50216
50258
|
init_ReplyTree();
|
|
50217
|
-
|
|
50259
|
+
init_RichTextEditor();
|
|
50218
50260
|
init_RuntimeDebugger2();
|
|
50219
50261
|
init_ScaledDiagram();
|
|
50220
50262
|
init_ScoreDisplay();
|
|
@@ -50377,6 +50419,8 @@ var init_component_registry_generated = __esm({
|
|
|
50377
50419
|
"DocSearch": DocSearch,
|
|
50378
50420
|
"DocSidebar": exports.DocSidebar,
|
|
50379
50421
|
"DocTOC": exports.DocTOC,
|
|
50422
|
+
"DocumentDetails": DocumentDetails,
|
|
50423
|
+
"DocumentPanel": DocumentPanel,
|
|
50380
50424
|
"DocumentViewer": exports.DocumentViewer,
|
|
50381
50425
|
"DrawFxLayer": DrawFxLayer,
|
|
50382
50426
|
"DrawGroup": DrawGroup,
|
|
@@ -50488,7 +50532,7 @@ var init_component_registry_generated = __esm({
|
|
|
50488
50532
|
"RelationSelect": exports.RelationSelect,
|
|
50489
50533
|
"RepeatableFormSection": exports.RepeatableFormSection,
|
|
50490
50534
|
"ReplyTree": exports.ReplyTree,
|
|
50491
|
-
"
|
|
50535
|
+
"RichTextEditor": exports.RichTextEditor,
|
|
50492
50536
|
"RuntimeDebugger": RuntimeDebugger,
|
|
50493
50537
|
"ScaledDiagram": exports.ScaledDiagram,
|
|
50494
50538
|
"ScoreDisplay": ScoreDisplay,
|
|
@@ -50642,10 +50686,10 @@ function enrichFormFields(fields, entityDef) {
|
|
|
50642
50686
|
}
|
|
50643
50687
|
if (field && typeof field === "object" && !Array.isArray(field) && !React77__namespace.default.isValidElement(field) && !(field instanceof Date)) {
|
|
50644
50688
|
const obj = field;
|
|
50645
|
-
const
|
|
50646
|
-
if (!
|
|
50689
|
+
const fieldName2 = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
|
|
50690
|
+
if (!fieldName2) return field;
|
|
50647
50691
|
if (obj.type || obj.inputType) return field;
|
|
50648
|
-
const entityField = fieldMap.get(
|
|
50692
|
+
const entityField = fieldMap.get(fieldName2);
|
|
50649
50693
|
if (!entityField) return field;
|
|
50650
50694
|
const enriched = { ...obj, type: entityField.type };
|
|
50651
50695
|
if (entityField.required && !("required" in obj)) {
|
|
@@ -50695,9 +50739,9 @@ function enrichDetailFields(fields, entityDef) {
|
|
|
50695
50739
|
}
|
|
50696
50740
|
if (field && typeof field === "object" && !Array.isArray(field) && !React77__namespace.default.isValidElement(field) && !(field instanceof Date)) {
|
|
50697
50741
|
const obj = field;
|
|
50698
|
-
const
|
|
50699
|
-
if (!
|
|
50700
|
-
const meta = metaFor(
|
|
50742
|
+
const fieldName2 = typeof obj.key === "string" ? obj.key : typeof obj.name === "string" ? obj.name : void 0;
|
|
50743
|
+
if (!fieldName2 || obj.type) return field;
|
|
50744
|
+
const meta = metaFor(fieldName2);
|
|
50701
50745
|
return meta ? { ...obj, ...meta } : field;
|
|
50702
50746
|
}
|
|
50703
50747
|
return field;
|
|
@@ -51536,9 +51580,9 @@ function UISlotRenderer({
|
|
|
51536
51580
|
"ui-slot-renderer relative min-h-full",
|
|
51537
51581
|
className
|
|
51538
51582
|
), children: [
|
|
51539
|
-
/* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "flex min-h-full", children: [
|
|
51540
|
-
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "sidebar", className: "ui-slot-sidebar min-w-0 shrink-0" }),
|
|
51541
|
-
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "main", className: "ui-slot-main flex-1 min-h-[200px]" })
|
|
51583
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "flex min-h-full flex-col lg:flex-row", children: [
|
|
51584
|
+
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "sidebar", className: "ui-slot-sidebar min-w-0 lg:shrink-0" }),
|
|
51585
|
+
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "main", className: "ui-slot-main flex-1 min-w-0 min-h-[200px]" })
|
|
51542
51586
|
] }),
|
|
51543
51587
|
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "modal", portal: true }),
|
|
51544
51588
|
/* @__PURE__ */ jsxRuntime.jsx(UISlotComponent, { slot: "drawer", portal: true }),
|
|
@@ -53526,54 +53570,6 @@ var en_default = {
|
|
|
53526
53570
|
"template.faq": "Frequently Asked Questions",
|
|
53527
53571
|
"template.ourTeam": "Our Team",
|
|
53528
53572
|
"template.caseStudies": "Case Studies",
|
|
53529
|
-
"richBlockEditor.toolbar.text": "Text",
|
|
53530
|
-
"richBlockEditor.toolbar.h1": "H1",
|
|
53531
|
-
"richBlockEditor.toolbar.h2": "H2",
|
|
53532
|
-
"richBlockEditor.toolbar.h3": "H3",
|
|
53533
|
-
"richBlockEditor.toolbar.bulletList": "Bullet list",
|
|
53534
|
-
"richBlockEditor.toolbar.numbered": "Numbered",
|
|
53535
|
-
"richBlockEditor.toolbar.quote": "Quote",
|
|
53536
|
-
"richBlockEditor.toolbar.code": "Code",
|
|
53537
|
-
"richBlockEditor.toolbar.divider": "Divider",
|
|
53538
|
-
"richBlockEditor.toolbar.image": "Image",
|
|
53539
|
-
"richBlockEditor.blockType.paragraph": "Text",
|
|
53540
|
-
"richBlockEditor.blockType.heading1": "Heading 1",
|
|
53541
|
-
"richBlockEditor.blockType.heading2": "Heading 2",
|
|
53542
|
-
"richBlockEditor.blockType.heading3": "Heading 3",
|
|
53543
|
-
"richBlockEditor.blockType.bulletList": "Bullet list",
|
|
53544
|
-
"richBlockEditor.blockType.numberedList": "Numbered list",
|
|
53545
|
-
"richBlockEditor.blockType.quote": "Quote",
|
|
53546
|
-
"richBlockEditor.blockType.code": "Code",
|
|
53547
|
-
"richBlockEditor.blockType.divider": "Divider",
|
|
53548
|
-
"richBlockEditor.blockType.image": "Image",
|
|
53549
|
-
"richBlockEditor.blockActions": "Block actions",
|
|
53550
|
-
"richBlockEditor.duplicate": "Duplicate",
|
|
53551
|
-
"richBlockEditor.turnInto": "Turn into",
|
|
53552
|
-
"richBlockEditor.placeholder.heading1": "Heading 1",
|
|
53553
|
-
"richBlockEditor.placeholder.heading2": "Heading 2",
|
|
53554
|
-
"richBlockEditor.placeholder.heading3": "Heading 3",
|
|
53555
|
-
"richBlockEditor.placeholder.quote": "Quote",
|
|
53556
|
-
"richBlockEditor.placeholder.code": "Enter code",
|
|
53557
|
-
"richBlockEditor.placeholder.paragraph": "Start writing...",
|
|
53558
|
-
"richBlockEditor.placeholder.listItem": "List item",
|
|
53559
|
-
"richBlockEditor.placeholder.caption": "Caption (optional)",
|
|
53560
|
-
"richBlockEditor.aria.heading1Block": "Heading 1 block",
|
|
53561
|
-
"richBlockEditor.aria.heading2Block": "Heading 2 block",
|
|
53562
|
-
"richBlockEditor.aria.heading3Block": "Heading 3 block",
|
|
53563
|
-
"richBlockEditor.aria.quoteBlock": "Quote block",
|
|
53564
|
-
"richBlockEditor.aria.codeBlock": "Code block",
|
|
53565
|
-
"richBlockEditor.aria.codeLanguage": "Code language",
|
|
53566
|
-
"richBlockEditor.aria.imageUrl": "Image URL",
|
|
53567
|
-
"richBlockEditor.aria.imageCaption": "Image caption",
|
|
53568
|
-
"richBlockEditor.aria.listItem": "List item",
|
|
53569
|
-
"richBlockEditor.aria.removeListItem": "Remove list item",
|
|
53570
|
-
"richBlockEditor.aria.paragraphBlock": "Paragraph block",
|
|
53571
|
-
"richBlockEditor.embeddedImage": "Embedded image",
|
|
53572
|
-
"richBlockEditor.noImageUrl": "No image URL set",
|
|
53573
|
-
"richBlockEditor.addItem": "Add item",
|
|
53574
|
-
"richBlockEditor.insertParagraphBelow": "Insert paragraph below",
|
|
53575
|
-
"richBlockEditor.editorToolbar": "Block editor toolbar",
|
|
53576
|
-
"richBlockEditor.insertEntry": "Insert {{label}}",
|
|
53577
53573
|
"versionDiff.compare": "Compare",
|
|
53578
53574
|
"versionDiff.to": "to",
|
|
53579
53575
|
"versionDiff.beforeRevision": "Before revision",
|
|
@@ -53921,7 +53917,31 @@ var en_default = {
|
|
|
53921
53917
|
"td.survivedAllWaves": "Survived all waves!",
|
|
53922
53918
|
"td.victory": "Victory!",
|
|
53923
53919
|
"td.wave": "Wave",
|
|
53924
|
-
"td.waveInProgress": "Wave in progress\u2026"
|
|
53920
|
+
"td.waveInProgress": "Wave in progress\u2026",
|
|
53921
|
+
"documentDetails.title": "Details",
|
|
53922
|
+
"documentPanel.untitled": "Untitled",
|
|
53923
|
+
"documentPanel.edit": "Edit",
|
|
53924
|
+
"documentPanel.done": "Done",
|
|
53925
|
+
"documentPanel.autosaveHint": "Saves as you type",
|
|
53926
|
+
"documentPanel.placeholder": "Start writing\u2026",
|
|
53927
|
+
"richTextEditor.editorToolbar": "Formatting toolbar",
|
|
53928
|
+
"richTextEditor.editorSurface": "Rich text editor",
|
|
53929
|
+
"richTextEditor.bold": "Bold",
|
|
53930
|
+
"richTextEditor.italic": "Italic",
|
|
53931
|
+
"richTextEditor.underline": "Underline",
|
|
53932
|
+
"richTextEditor.strikethrough": "Strikethrough",
|
|
53933
|
+
"richTextEditor.heading1": "Heading 1",
|
|
53934
|
+
"richTextEditor.heading2": "Heading 2",
|
|
53935
|
+
"richTextEditor.heading3": "Heading 3",
|
|
53936
|
+
"richTextEditor.bulletList": "Bullet list",
|
|
53937
|
+
"richTextEditor.numberedList": "Numbered list",
|
|
53938
|
+
"richTextEditor.quote": "Quote",
|
|
53939
|
+
"richTextEditor.code": "Code",
|
|
53940
|
+
"richTextEditor.link": "Add link",
|
|
53941
|
+
"richTextEditor.removeLink": "Remove link",
|
|
53942
|
+
"richTextEditor.divider": "Divider",
|
|
53943
|
+
"richTextEditor.linkPrompt": "Link address",
|
|
53944
|
+
"richTextEditor.placeholder": "Start writing\u2026"
|
|
53925
53945
|
};
|
|
53926
53946
|
|
|
53927
53947
|
// hooks/useTranslate.ts
|
|
@@ -53942,7 +53962,7 @@ var I18nContext = React77.createContext({
|
|
|
53942
53962
|
});
|
|
53943
53963
|
I18nContext.displayName = "I18nContext";
|
|
53944
53964
|
var I18nProvider = I18nContext.Provider;
|
|
53945
|
-
function
|
|
53965
|
+
function useTranslate116() {
|
|
53946
53966
|
return React77.useContext(I18nContext);
|
|
53947
53967
|
}
|
|
53948
53968
|
function createTranslate(messages) {
|
|
@@ -54262,6 +54282,8 @@ exports.DayCell = DayCell;
|
|
|
54262
54282
|
exports.DialogueBubble = DialogueBubble;
|
|
54263
54283
|
exports.DocPagination = DocPagination;
|
|
54264
54284
|
exports.DocSearch = DocSearch;
|
|
54285
|
+
exports.DocumentDetails = DocumentDetails;
|
|
54286
|
+
exports.DocumentPanel = DocumentPanel;
|
|
54265
54287
|
exports.DomStateMachineVisualizer = exports.StateMachineView;
|
|
54266
54288
|
exports.EditorCheckbox = EditorCheckbox;
|
|
54267
54289
|
exports.EditorSelect = EditorSelect;
|
|
@@ -54342,6 +54364,7 @@ exports.resolveFrame = resolveFrame;
|
|
|
54342
54364
|
exports.resolveSheetDirection = resolveSheetDirection;
|
|
54343
54365
|
exports.rows = rows;
|
|
54344
54366
|
exports.runTickFrame = runTickFrame;
|
|
54367
|
+
exports.sanitizeRichHtml = sanitizeRichHtml;
|
|
54345
54368
|
exports.screenToIso = screenToIso;
|
|
54346
54369
|
exports.str = str;
|
|
54347
54370
|
exports.tickAnimationState = tickAnimationState;
|
|
@@ -54390,7 +54413,7 @@ exports.useSharedEntityStoreContext = useSharedEntityStoreContext;
|
|
|
54390
54413
|
exports.useSwipeGesture = useSwipeGesture;
|
|
54391
54414
|
exports.useTapReveal = useTapReveal;
|
|
54392
54415
|
exports.useTraitListens = useTraitListens;
|
|
54393
|
-
exports.useTranslate =
|
|
54416
|
+
exports.useTranslate = useTranslate116;
|
|
54394
54417
|
exports.useUIEvents = useUIEvents;
|
|
54395
54418
|
exports.useUISlotManager = useUISlotManager;
|
|
54396
54419
|
exports.useUnitSpriteAtlas = useUnitSpriteAtlas;
|