@almadar/ui 5.159.0 → 5.161.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avl/index.cjs +958 -912
- package/dist/avl/index.js +947 -901
- package/dist/components/index.cjs +978 -955
- package/dist/components/index.d.cts +156 -31
- package/dist/components/index.d.ts +156 -31
- package/dist/components/index.js +964 -944
- package/dist/hooks/index.cjs +25 -49
- package/dist/hooks/index.js +25 -49
- package/dist/locales/index.cjs +75 -147
- package/dist/locales/index.js +75 -147
- package/dist/providers/index.cjs +934 -892
- package/dist/providers/index.js +934 -892
- package/dist/runtime/index.cjs +953 -907
- package/dist/runtime/index.js +943 -897
- package/locales/ar.json +25 -49
- package/locales/en.json +25 -49
- package/locales/sl.json +25 -49
- package/package.json +5 -5
package/dist/runtime/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, schemaToIR
|
|
|
10
10
|
import { clsx } from 'clsx';
|
|
11
11
|
import { twMerge } from 'tailwind-merge';
|
|
12
12
|
import * as LucideIcons2 from 'lucide-react';
|
|
13
|
-
import { Loader2, X, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, Code, FileText, WrapText, Check, Copy, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ArrowLeft, ZoomOut, ZoomIn, Download, DollarSign, ChevronDown, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, HelpCircle, PauseCircle, Search,
|
|
13
|
+
import { Loader2, X, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, Code, FileText, WrapText, Check, Copy, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ArrowLeft, ZoomOut, ZoomIn, Download, DollarSign, ChevronDown, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, HelpCircle, PauseCircle, Search, Bold, Italic, Underline, Strikethrough, Heading1, Heading2, Heading3, ListOrdered, Quote, Link as Link$1, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, ChevronUp } from 'lucide-react';
|
|
14
14
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
15
15
|
import { createPortal } from 'react-dom';
|
|
16
16
|
import { useTranslate } from '@almadar/ui/hooks';
|
|
@@ -25829,8 +25829,9 @@ function DataGrid({
|
|
|
25829
25829
|
const titleField = fieldDefs.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fieldDefs[0];
|
|
25830
25830
|
const badgeFields = fieldDefs.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
25831
25831
|
const bodyFields = fieldDefs.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
|
|
25832
|
-
const
|
|
25833
|
-
const
|
|
25832
|
+
const inlineCap = Math.min(maxInlineActions ?? 1, 1);
|
|
25833
|
+
const inlineCardActions = actionDefs.filter((a) => a.variant === "primary").slice(0, inlineCap);
|
|
25834
|
+
const menuCardActions = actionDefs.filter((a) => !inlineCardActions.includes(a));
|
|
25834
25835
|
const fireAction = (action, itemData) => {
|
|
25835
25836
|
if (action.navigatesTo) {
|
|
25836
25837
|
const url = action.navigatesTo.replace(
|
|
@@ -25850,6 +25851,9 @@ function DataGrid({
|
|
|
25850
25851
|
e.stopPropagation();
|
|
25851
25852
|
fireAction(action, itemData);
|
|
25852
25853
|
};
|
|
25854
|
+
const cardClickAction = actionDefs.find((a) => a.variant !== "danger");
|
|
25855
|
+
const handleCardClick = cardClickAction ? (itemData) => () => fireAction(cardClickAction, itemData) : void 0;
|
|
25856
|
+
const stopCardClick = handleCardClick ? (e) => e.stopPropagation() : void 0;
|
|
25853
25857
|
const hasRenderProp = typeof children === "function";
|
|
25854
25858
|
useEffect(() => {
|
|
25855
25859
|
if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
|
|
@@ -25921,55 +25925,40 @@ function DataGrid({
|
|
|
25921
25925
|
{
|
|
25922
25926
|
"data-entity-row": true,
|
|
25923
25927
|
"data-entity-id": id,
|
|
25924
|
-
|
|
25928
|
+
onClick: handleCardClick?.(itemData),
|
|
25929
|
+
className: cn("relative group/rowactions", handleCardClick && "cursor-pointer", isSelected && "ring-2 ring-primary rounded-lg"),
|
|
25925
25930
|
children: [
|
|
25926
25931
|
children(itemData, index),
|
|
25927
|
-
actionDefs.length > 0 && /* @__PURE__ */
|
|
25928
|
-
/* @__PURE__ */ jsxs(
|
|
25929
|
-
|
|
25930
|
-
|
|
25931
|
-
|
|
25932
|
-
|
|
25933
|
-
|
|
25934
|
-
|
|
25935
|
-
|
|
25936
|
-
|
|
25937
|
-
|
|
25938
|
-
|
|
25939
|
-
|
|
25940
|
-
|
|
25941
|
-
|
|
25942
|
-
|
|
25943
|
-
|
|
25944
|
-
)),
|
|
25945
|
-
maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
|
|
25946
|
-
Menu,
|
|
25947
|
-
{
|
|
25948
|
-
position: "bottom-end",
|
|
25949
|
-
trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
25950
|
-
items: actionDefs.slice(maxInlineActions).map((action) => ({
|
|
25951
|
-
label: action.label,
|
|
25952
|
-
icon: action.icon,
|
|
25953
|
-
event: action.event,
|
|
25954
|
-
onClick: () => fireAction(action, itemData)
|
|
25955
|
-
}))
|
|
25956
|
-
}
|
|
25957
|
-
)
|
|
25958
|
-
] }),
|
|
25959
|
-
/* @__PURE__ */ jsx(Box, { className: "hidden [@media(pointer:coarse)]:block rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5", children: /* @__PURE__ */ jsx(
|
|
25932
|
+
actionDefs.length > 0 && /* @__PURE__ */ jsx(Box, { onClick: stopCardClick, className: "absolute top-2 right-2 z-10 opacity-0 group-hover/rowactions:opacity-100 focus-within:opacity-100 [@media(pointer:coarse)]:opacity-100 transition-opacity duration-fast", children: /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5", children: [
|
|
25933
|
+
inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
25934
|
+
Button,
|
|
25935
|
+
{
|
|
25936
|
+
variant: "primary",
|
|
25937
|
+
size: "sm",
|
|
25938
|
+
onClick: handleActionClick(action, itemData),
|
|
25939
|
+
"data-testid": `action-${action.event}`,
|
|
25940
|
+
"data-row-id": String(itemData.id),
|
|
25941
|
+
children: [
|
|
25942
|
+
action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
|
|
25943
|
+
action.label
|
|
25944
|
+
]
|
|
25945
|
+
},
|
|
25946
|
+
idx
|
|
25947
|
+
)),
|
|
25948
|
+
menuCardActions.length > 0 && /* @__PURE__ */ jsx(
|
|
25960
25949
|
Menu,
|
|
25961
25950
|
{
|
|
25962
25951
|
position: "bottom-end",
|
|
25963
25952
|
trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
25964
|
-
items:
|
|
25953
|
+
items: menuCardActions.map((action) => ({
|
|
25965
25954
|
label: action.label,
|
|
25966
25955
|
icon: action.icon,
|
|
25967
|
-
|
|
25956
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
25968
25957
|
onClick: () => fireAction(action, itemData)
|
|
25969
25958
|
}))
|
|
25970
25959
|
}
|
|
25971
|
-
)
|
|
25972
|
-
] })
|
|
25960
|
+
)
|
|
25961
|
+
] }) })
|
|
25973
25962
|
]
|
|
25974
25963
|
},
|
|
25975
25964
|
id
|
|
@@ -25983,12 +25972,14 @@ function DataGrid({
|
|
|
25983
25972
|
{
|
|
25984
25973
|
"data-entity-row": true,
|
|
25985
25974
|
"data-entity-id": id,
|
|
25975
|
+
onClick: handleCardClick?.(itemData),
|
|
25986
25976
|
className: cn(
|
|
25987
25977
|
"bg-card rounded-lg",
|
|
25988
25978
|
"border border-border",
|
|
25989
25979
|
"shadow-elevation-card hover:shadow-elevation-dialog",
|
|
25990
25980
|
"hover:border-primary transition-all",
|
|
25991
25981
|
"flex flex-col",
|
|
25982
|
+
handleCardClick && "cursor-pointer",
|
|
25992
25983
|
isSelected && "ring-2 ring-primary border-primary"
|
|
25993
25984
|
),
|
|
25994
25985
|
children: [
|
|
@@ -26038,53 +26029,35 @@ function DataGrid({
|
|
|
26038
26029
|
] }, field.name);
|
|
26039
26030
|
}) })
|
|
26040
26031
|
] }),
|
|
26041
|
-
|
|
26042
|
-
|
|
26032
|
+
actionDefs.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", onClick: stopCardClick, className: "flex-shrink-0", children: [
|
|
26033
|
+
inlineCardActions.map((action, idx) => /* @__PURE__ */ jsx(
|
|
26043
26034
|
Button,
|
|
26044
26035
|
{
|
|
26045
|
-
variant:
|
|
26036
|
+
variant: "primary",
|
|
26046
26037
|
size: "sm",
|
|
26047
26038
|
onClick: handleActionClick(action, itemData),
|
|
26048
26039
|
"data-testid": `action-${action.event}`,
|
|
26049
26040
|
"data-row-id": String(itemData.id),
|
|
26050
26041
|
"aria-label": action.label,
|
|
26051
26042
|
title: action.label,
|
|
26052
|
-
className: cn(
|
|
26053
|
-
action.variant === "primary" ? void 0 : "text-muted-foreground hover:text-foreground",
|
|
26054
|
-
action.icon && "px-2"
|
|
26055
|
-
),
|
|
26043
|
+
className: cn(action.icon && "px-2"),
|
|
26056
26044
|
children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
|
|
26057
26045
|
},
|
|
26058
26046
|
idx
|
|
26059
26047
|
)),
|
|
26060
|
-
|
|
26048
|
+
menuCardActions.length > 0 && /* @__PURE__ */ jsx(
|
|
26061
26049
|
Menu,
|
|
26062
26050
|
{
|
|
26063
26051
|
position: "bottom-end",
|
|
26064
26052
|
trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
26065
|
-
items:
|
|
26053
|
+
items: menuCardActions.map((action) => ({
|
|
26066
26054
|
label: action.label,
|
|
26067
26055
|
icon: action.icon,
|
|
26068
|
-
|
|
26056
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
26069
26057
|
onClick: () => fireAction(action, itemData)
|
|
26070
26058
|
}))
|
|
26071
26059
|
}
|
|
26072
|
-
)
|
|
26073
|
-
dangerActions.map((action, idx) => /* @__PURE__ */ jsx(
|
|
26074
|
-
Button,
|
|
26075
|
-
{
|
|
26076
|
-
variant: "ghost",
|
|
26077
|
-
size: "sm",
|
|
26078
|
-
onClick: handleActionClick(action, itemData),
|
|
26079
|
-
"data-testid": `action-${action.event}`,
|
|
26080
|
-
"data-row-id": String(itemData.id),
|
|
26081
|
-
"aria-label": action.label,
|
|
26082
|
-
title: action.label,
|
|
26083
|
-
className: "text-error hover:text-error hover:bg-error/10 px-2",
|
|
26084
|
-
children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
|
|
26085
|
-
},
|
|
26086
|
-
`danger-${idx}`
|
|
26087
|
-
))
|
|
26060
|
+
)
|
|
26088
26061
|
] })
|
|
26089
26062
|
] }) }),
|
|
26090
26063
|
bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 pt-2 pb-4 flex-1", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
@@ -26105,8 +26078,8 @@ function DataGrid({
|
|
|
26105
26078
|
}
|
|
26106
26079
|
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
26107
26080
|
field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
26108
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
26109
|
-
/* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue(value, field.format) })
|
|
26081
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "sr-only", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
26082
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: formatValue(value, field.format) })
|
|
26110
26083
|
] }, field.name);
|
|
26111
26084
|
}) })
|
|
26112
26085
|
] }) })
|
|
@@ -26326,54 +26299,59 @@ function DataList({
|
|
|
26326
26299
|
if (!itemActions || itemActions.length === 0) return null;
|
|
26327
26300
|
const inline = maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions;
|
|
26328
26301
|
const overflow = maxInlineActions != null ? itemActions.slice(maxInlineActions) : [];
|
|
26329
|
-
return
|
|
26330
|
-
|
|
26331
|
-
|
|
26332
|
-
|
|
26333
|
-
|
|
26334
|
-
|
|
26335
|
-
|
|
26336
|
-
|
|
26337
|
-
|
|
26338
|
-
|
|
26339
|
-
action
|
|
26340
|
-
|
|
26341
|
-
|
|
26342
|
-
|
|
26343
|
-
|
|
26344
|
-
|
|
26345
|
-
|
|
26346
|
-
|
|
26347
|
-
|
|
26348
|
-
|
|
26349
|
-
|
|
26350
|
-
|
|
26351
|
-
|
|
26352
|
-
|
|
26353
|
-
|
|
26354
|
-
|
|
26355
|
-
|
|
26356
|
-
|
|
26357
|
-
|
|
26358
|
-
|
|
26359
|
-
|
|
26360
|
-
|
|
26361
|
-
|
|
26362
|
-
|
|
26363
|
-
|
|
26364
|
-
|
|
26365
|
-
|
|
26366
|
-
|
|
26367
|
-
|
|
26368
|
-
|
|
26302
|
+
return (
|
|
26303
|
+
// stopPropagation at the cluster: the "⋯" trigger opens the overflow
|
|
26304
|
+
// menu without also firing the row's default click (inline buttons
|
|
26305
|
+
// already stop it in handleActionClick; the Menu panel is portaled).
|
|
26306
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", onClick: rowClickEvent ? (e) => e.stopPropagation() : void 0, className: "flex-shrink-0", children: [
|
|
26307
|
+
inline.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
26308
|
+
Button,
|
|
26309
|
+
{
|
|
26310
|
+
variant: action.variant ?? "ghost",
|
|
26311
|
+
size: "sm",
|
|
26312
|
+
onClick: handleActionClick(action, itemData),
|
|
26313
|
+
"data-testid": `action-${action.event}`,
|
|
26314
|
+
"data-row-id": String(itemData.id),
|
|
26315
|
+
className: cn(
|
|
26316
|
+
action.variant === "danger" && "text-error hover:bg-error/10",
|
|
26317
|
+
// Must sit on the Button itself: the variant's own text colour
|
|
26318
|
+
// beats an inherited one from the row wrapper.
|
|
26319
|
+
onPrimary && "!text-primary-foreground hover:bg-primary-foreground/15"
|
|
26320
|
+
),
|
|
26321
|
+
children: [
|
|
26322
|
+
action.icon && renderIconInput2(action.icon, { size: "xs", className: "mr-1" }),
|
|
26323
|
+
action.label
|
|
26324
|
+
]
|
|
26325
|
+
},
|
|
26326
|
+
idx
|
|
26327
|
+
)),
|
|
26328
|
+
overflow.length > 0 && /* @__PURE__ */ jsx(
|
|
26329
|
+
Menu,
|
|
26330
|
+
{
|
|
26331
|
+
position: "bottom-end",
|
|
26332
|
+
trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
26333
|
+
items: overflow.map((action) => ({
|
|
26334
|
+
label: action.label,
|
|
26335
|
+
icon: action.icon,
|
|
26336
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
26337
|
+
onClick: () => eventBus.emit(`UI:${action.event}`, {
|
|
26338
|
+
id: itemData.id,
|
|
26339
|
+
row: itemData
|
|
26340
|
+
})
|
|
26341
|
+
}))
|
|
26342
|
+
}
|
|
26343
|
+
)
|
|
26344
|
+
] })
|
|
26345
|
+
);
|
|
26369
26346
|
};
|
|
26347
|
+
const rowClickEvent = itemClickEvent || itemActions?.find((a) => a.variant !== "danger")?.event;
|
|
26370
26348
|
const handleRowClick = (itemData) => () => {
|
|
26371
|
-
if (!
|
|
26349
|
+
if (!rowClickEvent) return;
|
|
26372
26350
|
const payload = {
|
|
26373
26351
|
id: itemData.id,
|
|
26374
26352
|
row: itemData
|
|
26375
26353
|
};
|
|
26376
|
-
eventBus.emit(`UI:${
|
|
26354
|
+
eventBus.emit(`UI:${rowClickEvent}`, payload);
|
|
26377
26355
|
};
|
|
26378
26356
|
if (isLoading) {
|
|
26379
26357
|
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") }) });
|
|
@@ -26421,10 +26399,10 @@ function DataList({
|
|
|
26421
26399
|
{
|
|
26422
26400
|
"data-entity-row": true,
|
|
26423
26401
|
"data-entity-id": id,
|
|
26424
|
-
onClick:
|
|
26402
|
+
onClick: rowClickEvent ? handleRowClick(itemData) : void 0,
|
|
26425
26403
|
className: cn(
|
|
26426
26404
|
"flex px-4 group/rowactions",
|
|
26427
|
-
|
|
26405
|
+
rowClickEvent && "cursor-pointer",
|
|
26428
26406
|
isSent ? "justify-end" : "justify-start"
|
|
26429
26407
|
),
|
|
26430
26408
|
children: /* @__PURE__ */ jsxs(
|
|
@@ -26500,7 +26478,7 @@ function DataList({
|
|
|
26500
26478
|
const id2 = itemData.id || String(index);
|
|
26501
26479
|
const actions = renderItemActions(itemData);
|
|
26502
26480
|
return wrapDnd(
|
|
26503
|
-
/* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick:
|
|
26481
|
+
/* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick: rowClickEvent ? handleRowClick(itemData) : void 0, className: cn("relative group/rowactions", rowClickEvent && "cursor-pointer"), children: [
|
|
26504
26482
|
children(itemData, index),
|
|
26505
26483
|
actions && /* @__PURE__ */ jsxs(Box, { className: "absolute top-2 right-2 z-10 opacity-0 group-hover/rowactions:opacity-100 focus-within:opacity-100 [@media(pointer:coarse)]:opacity-100 transition-opacity duration-fast", children: [
|
|
26506
26484
|
/* @__PURE__ */ jsx(Box, { className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5 [@media(pointer:coarse)]:hidden", children: actions }),
|
|
@@ -26512,7 +26490,6 @@ function DataList({
|
|
|
26512
26490
|
items: (itemActions ?? []).map((action) => ({
|
|
26513
26491
|
label: action.label,
|
|
26514
26492
|
icon: action.icon,
|
|
26515
|
-
event: action.event,
|
|
26516
26493
|
variant: action.variant === "danger" ? "danger" : "default",
|
|
26517
26494
|
onClick: () => eventBus.emit(`UI:${action.event}`, {
|
|
26518
26495
|
id: itemData.id,
|
|
@@ -26529,12 +26506,16 @@ function DataList({
|
|
|
26529
26506
|
const id = itemData.id || String(index);
|
|
26530
26507
|
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
26531
26508
|
return wrapDnd(
|
|
26532
|
-
/* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id, onClick:
|
|
26509
|
+
/* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id, onClick: rowClickEvent ? handleRowClick(itemData) : void 0, className: cn(rowClickEvent && "cursor-pointer"), children: [
|
|
26533
26510
|
/* @__PURE__ */ jsxs(
|
|
26534
26511
|
Box,
|
|
26535
26512
|
{
|
|
26536
26513
|
className: cn(
|
|
26537
|
-
|
|
26514
|
+
// items-start, not items-center: a multi-line row (title + meta +
|
|
26515
|
+
// progress) centred its action cluster in the vertical middle, so
|
|
26516
|
+
// the buttons floated between the meta fields instead of anchoring
|
|
26517
|
+
// to the title they act on (U-DATALIST-ACTIONS-FLOAT-MID-ROW).
|
|
26518
|
+
"group flex items-start gap-4 transition-all duration-fast",
|
|
26538
26519
|
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
26539
26520
|
"hover:bg-muted/80",
|
|
26540
26521
|
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
@@ -26565,11 +26546,19 @@ function DataList({
|
|
|
26565
26546
|
if (value === void 0 || value === null || value === "") return null;
|
|
26566
26547
|
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
26567
26548
|
field.icon && renderIconInput2(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
26568
|
-
/* @__PURE__ */ jsxs(
|
|
26569
|
-
|
|
26570
|
-
|
|
26571
|
-
|
|
26572
|
-
|
|
26549
|
+
/* @__PURE__ */ jsxs(
|
|
26550
|
+
Typography,
|
|
26551
|
+
{
|
|
26552
|
+
variant: "caption",
|
|
26553
|
+
color: "secondary",
|
|
26554
|
+
className: cn(field.format !== "boolean" && "sr-only"),
|
|
26555
|
+
children: [
|
|
26556
|
+
field.label ?? fieldLabel3(field.name),
|
|
26557
|
+
":"
|
|
26558
|
+
]
|
|
26559
|
+
}
|
|
26560
|
+
),
|
|
26561
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: formatValue2(value, field.format, { yes: t("common.yes"), no: t("common.no") }) })
|
|
26573
26562
|
] }, field.name);
|
|
26574
26563
|
}) }),
|
|
26575
26564
|
progressFields.map((field) => {
|
|
@@ -26588,7 +26577,7 @@ function DataList({
|
|
|
26588
26577
|
]
|
|
26589
26578
|
}
|
|
26590
26579
|
),
|
|
26591
|
-
isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "
|
|
26580
|
+
(isCard || isCompact) && !isLast && /* @__PURE__ */ jsx(Box, { className: cn("border-b border-border/40", isCompact ? "mx-4" : "mx-6") })
|
|
26592
26581
|
] }, id)
|
|
26593
26582
|
);
|
|
26594
26583
|
};
|
|
@@ -26598,7 +26587,13 @@ function DataList({
|
|
|
26598
26587
|
{
|
|
26599
26588
|
className: cn(
|
|
26600
26589
|
isCard && "bg-card rounded-xl border border-border shadow-elevation-dialog overflow-hidden",
|
|
26601
|
-
|
|
26590
|
+
// `gap-*` is inert on a block container, and Box only emits a display
|
|
26591
|
+
// class when its `display` prop is set — so every non-card list had
|
|
26592
|
+
// been asking for a gap that CSS silently dropped. flex-col makes it
|
|
26593
|
+
// real. `compact` keeps gap-0 on purpose: it separates with the row
|
|
26594
|
+
// divider above instead, never both (Almadar_UI_Beauty.md 6).
|
|
26595
|
+
!isCard && "flex flex-col",
|
|
26596
|
+
!isCard && !isCompact && gapClass,
|
|
26602
26597
|
listLookStyles[look],
|
|
26603
26598
|
className
|
|
26604
26599
|
),
|
|
@@ -31723,7 +31718,7 @@ var init_MapView = __esm({
|
|
|
31723
31718
|
shadowSize: [41, 41]
|
|
31724
31719
|
});
|
|
31725
31720
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
31726
|
-
const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback90, useState:
|
|
31721
|
+
const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback90, useState: useState94 } = React85__default;
|
|
31727
31722
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
31728
31723
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
31729
31724
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -31768,7 +31763,7 @@ var init_MapView = __esm({
|
|
|
31768
31763
|
showAttribution = true
|
|
31769
31764
|
}) {
|
|
31770
31765
|
const eventBus = useEventBus2();
|
|
31771
|
-
const [clickedPosition, setClickedPosition] =
|
|
31766
|
+
const [clickedPosition, setClickedPosition] = useState94(null);
|
|
31772
31767
|
const handleMapClick = useCallback90((lat, lng) => {
|
|
31773
31768
|
if (showClickedPin) {
|
|
31774
31769
|
setClickedPosition({ lat, lng });
|
|
@@ -35992,741 +35987,775 @@ var init_PositionedCanvas = __esm({
|
|
|
35992
35987
|
PositionedCanvas.displayName = "PositionedCanvas";
|
|
35993
35988
|
}
|
|
35994
35989
|
});
|
|
35995
|
-
function
|
|
35996
|
-
|
|
35997
|
-
|
|
35998
|
-
|
|
35999
|
-
|
|
36000
|
-
|
|
36001
|
-
if (!Array.isArray(raw) || raw.length === 0) return [createBlock("paragraph")];
|
|
36002
|
-
return raw.map((row) => {
|
|
36003
|
-
const entity = row;
|
|
36004
|
-
const rawType = entity.type;
|
|
36005
|
-
const type = typeof rawType === "string" && BLOCK_TYPES.has(rawType) ? rawType : "paragraph";
|
|
36006
|
-
const id = typeof entity.id === "string" && entity.id ? entity.id : nextBlockId(type);
|
|
36007
|
-
return { ...entity, id, type };
|
|
36008
|
-
});
|
|
36009
|
-
}
|
|
36010
|
-
function createBlock(type) {
|
|
36011
|
-
switch (type) {
|
|
36012
|
-
case "bullet-list":
|
|
36013
|
-
case "numbered-list":
|
|
36014
|
-
return {
|
|
36015
|
-
id: nextBlockId(type),
|
|
36016
|
-
type,
|
|
36017
|
-
children: [
|
|
36018
|
-
{ id: nextBlockId("li"), type: "paragraph", content: "" }
|
|
36019
|
-
]
|
|
36020
|
-
};
|
|
36021
|
-
case "image":
|
|
36022
|
-
return {
|
|
36023
|
-
id: nextBlockId(type),
|
|
36024
|
-
type,
|
|
36025
|
-
content: "",
|
|
36026
|
-
metadata: { url: "", caption: "" }
|
|
36027
|
-
};
|
|
36028
|
-
case "code":
|
|
36029
|
-
return {
|
|
36030
|
-
id: nextBlockId(type),
|
|
36031
|
-
type,
|
|
36032
|
-
content: "",
|
|
36033
|
-
metadata: { language: "plaintext" }
|
|
36034
|
-
};
|
|
36035
|
-
case "divider":
|
|
36036
|
-
return { id: nextBlockId(type), type };
|
|
36037
|
-
default:
|
|
36038
|
-
return { id: nextBlockId(type), type, content: "" };
|
|
35990
|
+
function safeUrl(raw, kinds) {
|
|
35991
|
+
const url = raw.trim();
|
|
35992
|
+
if (url.startsWith("#") || url.startsWith("/")) return url;
|
|
35993
|
+
const lower = url.toLowerCase();
|
|
35994
|
+
for (const kind of kinds) {
|
|
35995
|
+
if (lower.startsWith(kind)) return url;
|
|
36039
35996
|
}
|
|
35997
|
+
return null;
|
|
36040
35998
|
}
|
|
36041
|
-
function
|
|
36042
|
-
|
|
36043
|
-
|
|
36044
|
-
|
|
36045
|
-
|
|
36046
|
-
|
|
36047
|
-
|
|
36048
|
-
return {
|
|
36049
|
-
...block,
|
|
36050
|
-
id: nextBlockId(block.type),
|
|
36051
|
-
children: block.children?.map((child) => ({
|
|
36052
|
-
...child,
|
|
36053
|
-
id: nextBlockId("li")
|
|
36054
|
-
})),
|
|
36055
|
-
metadata: block.metadata ? { ...block.metadata } : void 0
|
|
36056
|
-
};
|
|
36057
|
-
}
|
|
36058
|
-
function insertAfter(blocks, targetId, inserted) {
|
|
36059
|
-
const idx = blocks.findIndex((b) => b.id === targetId);
|
|
36060
|
-
if (idx === -1) return [...blocks, inserted];
|
|
36061
|
-
const next = blocks.slice();
|
|
36062
|
-
next.splice(idx + 1, 0, inserted);
|
|
36063
|
-
return next;
|
|
36064
|
-
}
|
|
36065
|
-
function changeBlockType(block, type) {
|
|
36066
|
-
if (block.type === type) return block;
|
|
36067
|
-
if (type === "bullet-list" || type === "numbered-list") {
|
|
36068
|
-
if (block.children && block.children.length > 0) {
|
|
36069
|
-
return { ...block, type };
|
|
35999
|
+
function sanitizeNode(el) {
|
|
36000
|
+
const children = Array.from(el.children);
|
|
36001
|
+
for (const child of children) {
|
|
36002
|
+
const tag = child.tagName.toLowerCase();
|
|
36003
|
+
if (DROP_TAGS.has(tag)) {
|
|
36004
|
+
child.remove();
|
|
36005
|
+
continue;
|
|
36070
36006
|
}
|
|
36071
|
-
const
|
|
36072
|
-
|
|
36073
|
-
|
|
36074
|
-
|
|
36075
|
-
|
|
36076
|
-
|
|
36077
|
-
|
|
36078
|
-
|
|
36079
|
-
|
|
36080
|
-
|
|
36081
|
-
|
|
36007
|
+
const allowed = ALLOWED_ATTRS[tag];
|
|
36008
|
+
if (!allowed) {
|
|
36009
|
+
sanitizeNode(child);
|
|
36010
|
+
child.replaceWith(...Array.from(child.childNodes));
|
|
36011
|
+
continue;
|
|
36012
|
+
}
|
|
36013
|
+
for (const attr of Array.from(child.attributes)) {
|
|
36014
|
+
const name = attr.name.toLowerCase();
|
|
36015
|
+
if (!allowed.includes(name)) {
|
|
36016
|
+
child.removeAttribute(attr.name);
|
|
36017
|
+
continue;
|
|
36018
|
+
}
|
|
36019
|
+
if (name === "href") {
|
|
36020
|
+
const url = safeUrl(attr.value, ["http://", "https://", "mailto:"]);
|
|
36021
|
+
if (url === null) child.removeAttribute(attr.name);
|
|
36022
|
+
else child.setAttribute("href", url);
|
|
36023
|
+
}
|
|
36024
|
+
if (name === "src") {
|
|
36025
|
+
const url = safeUrl(attr.value, ["http://", "https://", "data:image/"]);
|
|
36026
|
+
if (url === null) child.remove();
|
|
36027
|
+
else child.setAttribute("src", url);
|
|
36028
|
+
}
|
|
36029
|
+
}
|
|
36030
|
+
sanitizeNode(child);
|
|
36082
36031
|
}
|
|
36083
|
-
|
|
36084
|
-
|
|
36085
|
-
|
|
36086
|
-
|
|
36087
|
-
|
|
36088
|
-
|
|
36089
|
-
|
|
36032
|
+
}
|
|
36033
|
+
function sanitizeRichHtml(html) {
|
|
36034
|
+
if (!html || typeof html !== "string") return "";
|
|
36035
|
+
if (typeof window === "undefined" || typeof DOMParser === "undefined") return "";
|
|
36036
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
36037
|
+
sanitizeNode(doc.body);
|
|
36038
|
+
if (!doc.body.querySelector("img, hr") && (doc.body.textContent ?? "").trim().length === 0) {
|
|
36039
|
+
return "";
|
|
36090
36040
|
}
|
|
36091
|
-
|
|
36092
|
-
|
|
36093
|
-
|
|
36094
|
-
|
|
36095
|
-
|
|
36096
|
-
|
|
36097
|
-
|
|
36041
|
+
return doc.body.innerHTML.replace(//g, "");
|
|
36042
|
+
}
|
|
36043
|
+
function htmlIsEmpty(el) {
|
|
36044
|
+
if (el.querySelector("img, hr")) return false;
|
|
36045
|
+
return (el.textContent ?? "").trim().length === 0;
|
|
36046
|
+
}
|
|
36047
|
+
function closestBlock(node, root) {
|
|
36048
|
+
let cur = node;
|
|
36049
|
+
while (cur && cur !== root) {
|
|
36050
|
+
if (cur instanceof Element && BLOCK_TAGS.has(cur.tagName)) return cur;
|
|
36051
|
+
cur = cur.parentNode;
|
|
36098
36052
|
}
|
|
36099
|
-
|
|
36100
|
-
return { id: block.id, type, content: seed };
|
|
36053
|
+
return null;
|
|
36101
36054
|
}
|
|
36102
|
-
function
|
|
36103
|
-
|
|
36104
|
-
|
|
36105
|
-
|
|
36106
|
-
|
|
36107
|
-
|
|
36108
|
-
|
|
36109
|
-
|
|
36110
|
-
|
|
36055
|
+
function RichTextStyles() {
|
|
36056
|
+
return /* @__PURE__ */ jsx("style", { children: RICH_TEXT_CSS });
|
|
36057
|
+
}
|
|
36058
|
+
function readToolbarState(root) {
|
|
36059
|
+
const sel = window.getSelection();
|
|
36060
|
+
if (!sel || sel.rangeCount === 0) return IDLE_TOOLBAR;
|
|
36061
|
+
const anchor = sel.anchorNode;
|
|
36062
|
+
if (!anchor || !root.contains(anchor)) return IDLE_TOOLBAR;
|
|
36063
|
+
let block = null;
|
|
36064
|
+
let link = false;
|
|
36065
|
+
let node = anchor;
|
|
36066
|
+
while (node && node !== root) {
|
|
36067
|
+
if (node instanceof Element) {
|
|
36068
|
+
const tag = node.tagName.toLowerCase();
|
|
36069
|
+
if (!block && (tag === "h1" || tag === "h2" || tag === "h3" || tag === "blockquote" || tag === "pre")) {
|
|
36070
|
+
block = tag;
|
|
36111
36071
|
}
|
|
36072
|
+
if (tag === "a") link = true;
|
|
36112
36073
|
}
|
|
36113
|
-
|
|
36114
|
-
|
|
36115
|
-
|
|
36116
|
-
|
|
36117
|
-
|
|
36118
|
-
|
|
36119
|
-
|
|
36120
|
-
|
|
36121
|
-
|
|
36122
|
-
|
|
36123
|
-
|
|
36124
|
-
|
|
36125
|
-
"inline-flex items-center justify-center",
|
|
36126
|
-
"h-6 w-6 rounded-sm p-0 gap-0",
|
|
36127
|
-
"text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
36128
|
-
"opacity-0 group-hover:opacity-100 focus-visible:opacity-100",
|
|
36129
|
-
"transition-opacity"
|
|
36130
|
-
),
|
|
36131
|
-
onClick: () => setOpen((v) => !v),
|
|
36132
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", className: "w-3.5 h-3.5" })
|
|
36133
|
-
}
|
|
36134
|
-
),
|
|
36135
|
-
open && /* @__PURE__ */ jsxs(
|
|
36136
|
-
Box,
|
|
36137
|
-
{
|
|
36138
|
-
role: "menu",
|
|
36139
|
-
className: cn(
|
|
36140
|
-
"absolute right-0 z-10 mt-1 w-44",
|
|
36141
|
-
"rounded-container border border-border bg-popover shadow-elevation-popover",
|
|
36142
|
-
"py-1 text-sm"
|
|
36143
|
-
),
|
|
36144
|
-
children: [
|
|
36145
|
-
/* @__PURE__ */ jsx(Box, { className: "px-2 py-1 text-xs uppercase tracking-wide text-muted-foreground", children: t(BLOCK_TYPE_LABEL_KEY[block.type]) }),
|
|
36146
|
-
/* @__PURE__ */ jsxs(
|
|
36147
|
-
Button,
|
|
36148
|
-
{
|
|
36149
|
-
type: "button",
|
|
36150
|
-
variant: "ghost",
|
|
36151
|
-
role: "menuitem",
|
|
36152
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left justify-start rounded-none",
|
|
36153
|
-
onClick: () => {
|
|
36154
|
-
onDuplicate();
|
|
36155
|
-
setOpen(false);
|
|
36156
|
-
},
|
|
36157
|
-
children: [
|
|
36158
|
-
/* @__PURE__ */ jsx(Icon, { name: "plus", className: "w-3.5 h-3.5" }),
|
|
36159
|
-
" ",
|
|
36160
|
-
t("richBlockEditor.duplicate")
|
|
36161
|
-
]
|
|
36162
|
-
}
|
|
36163
|
-
),
|
|
36164
|
-
/* @__PURE__ */ jsxs(
|
|
36165
|
-
Button,
|
|
36166
|
-
{
|
|
36167
|
-
type: "button",
|
|
36168
|
-
variant: "ghost",
|
|
36169
|
-
role: "menuitem",
|
|
36170
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left text-destructive hover:bg-muted justify-start rounded-none",
|
|
36171
|
-
onClick: () => {
|
|
36172
|
-
onDelete();
|
|
36173
|
-
setOpen(false);
|
|
36174
|
-
},
|
|
36175
|
-
children: [
|
|
36176
|
-
/* @__PURE__ */ jsx(Icon, { name: "trash", className: "w-3.5 h-3.5" }),
|
|
36177
|
-
" ",
|
|
36178
|
-
t("common.delete")
|
|
36179
|
-
]
|
|
36180
|
-
}
|
|
36181
|
-
),
|
|
36182
|
-
CHANGEABLE_TYPES.includes(block.type) && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36183
|
-
/* @__PURE__ */ jsx(Box, { className: "my-1 border-t border-border" }),
|
|
36184
|
-
/* @__PURE__ */ jsx(Box, { className: "px-2 py-1 text-xs uppercase tracking-wide text-muted-foreground", children: t("richBlockEditor.turnInto") }),
|
|
36185
|
-
CHANGEABLE_TYPES.filter((bt) => bt !== block.type).map((bt) => /* @__PURE__ */ jsx(
|
|
36186
|
-
Button,
|
|
36187
|
-
{
|
|
36188
|
-
type: "button",
|
|
36189
|
-
variant: "ghost",
|
|
36190
|
-
role: "menuitem",
|
|
36191
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left justify-start rounded-none",
|
|
36192
|
-
onClick: () => {
|
|
36193
|
-
onChangeType(bt);
|
|
36194
|
-
setOpen(false);
|
|
36195
|
-
},
|
|
36196
|
-
children: t(BLOCK_TYPE_LABEL_KEY[bt])
|
|
36197
|
-
},
|
|
36198
|
-
bt
|
|
36199
|
-
))
|
|
36200
|
-
] })
|
|
36201
|
-
]
|
|
36202
|
-
}
|
|
36203
|
-
)
|
|
36204
|
-
] });
|
|
36074
|
+
node = node.parentNode;
|
|
36075
|
+
}
|
|
36076
|
+
return {
|
|
36077
|
+
bold: document.queryCommandState("bold"),
|
|
36078
|
+
italic: document.queryCommandState("italic"),
|
|
36079
|
+
underline: document.queryCommandState("underline"),
|
|
36080
|
+
strikeThrough: document.queryCommandState("strikeThrough"),
|
|
36081
|
+
block,
|
|
36082
|
+
bullets: document.queryCommandState("insertUnorderedList"),
|
|
36083
|
+
numbers: document.queryCommandState("insertOrderedList"),
|
|
36084
|
+
link
|
|
36085
|
+
};
|
|
36205
36086
|
}
|
|
36206
|
-
function
|
|
36207
|
-
tag,
|
|
36208
|
-
value,
|
|
36209
|
-
readOnly,
|
|
36210
|
-
placeholder,
|
|
36211
|
-
className,
|
|
36212
|
-
ariaLabel,
|
|
36213
|
-
onValueChange
|
|
36214
|
-
}) {
|
|
36215
|
-
const ref = useRef(null);
|
|
36216
|
-
useEffect(() => {
|
|
36217
|
-
const el = ref.current;
|
|
36218
|
-
if (!el) return;
|
|
36219
|
-
const isFocused = document.activeElement === el;
|
|
36220
|
-
if (!isFocused && el.textContent !== value) {
|
|
36221
|
-
el.textContent = value;
|
|
36222
|
-
}
|
|
36223
|
-
}, [value]);
|
|
36224
|
-
const handleInput = useCallback(
|
|
36225
|
-
(e) => {
|
|
36226
|
-
onValueChange(e.currentTarget.textContent ?? "");
|
|
36227
|
-
},
|
|
36228
|
-
[onValueChange]
|
|
36229
|
-
);
|
|
36087
|
+
function ToolbarButton({ icon: IconCmp, label, active, onExec }) {
|
|
36230
36088
|
return /* @__PURE__ */ jsx(
|
|
36231
|
-
|
|
36089
|
+
Button,
|
|
36232
36090
|
{
|
|
36233
|
-
|
|
36234
|
-
|
|
36235
|
-
|
|
36236
|
-
|
|
36237
|
-
|
|
36238
|
-
|
|
36239
|
-
"aria-multiline": "true",
|
|
36240
|
-
"data-placeholder": placeholder,
|
|
36091
|
+
type: "button",
|
|
36092
|
+
variant: "ghost",
|
|
36093
|
+
size: "sm",
|
|
36094
|
+
"aria-label": label,
|
|
36095
|
+
"aria-pressed": active,
|
|
36096
|
+
title: label,
|
|
36241
36097
|
className: cn(
|
|
36242
|
-
"
|
|
36243
|
-
"
|
|
36244
|
-
className
|
|
36098
|
+
"h-8 w-8 p-0 gap-0 justify-center",
|
|
36099
|
+
active && "bg-muted text-foreground"
|
|
36245
36100
|
),
|
|
36246
|
-
|
|
36101
|
+
onMouseDown: (e) => {
|
|
36102
|
+
e.preventDefault();
|
|
36103
|
+
onExec();
|
|
36104
|
+
},
|
|
36105
|
+
children: /* @__PURE__ */ jsx(IconCmp, { size: 15 })
|
|
36247
36106
|
}
|
|
36248
36107
|
);
|
|
36249
36108
|
}
|
|
36250
|
-
|
|
36251
|
-
|
|
36252
|
-
|
|
36253
|
-
|
|
36254
|
-
|
|
36255
|
-
|
|
36256
|
-
|
|
36257
|
-
|
|
36258
|
-
|
|
36259
|
-
|
|
36260
|
-
|
|
36261
|
-
|
|
36262
|
-
|
|
36263
|
-
|
|
36264
|
-
|
|
36265
|
-
|
|
36266
|
-
|
|
36267
|
-
|
|
36268
|
-
|
|
36269
|
-
|
|
36270
|
-
|
|
36271
|
-
|
|
36272
|
-
|
|
36273
|
-
|
|
36274
|
-
|
|
36275
|
-
|
|
36276
|
-
|
|
36277
|
-
|
|
36278
|
-
|
|
36279
|
-
|
|
36280
|
-
|
|
36281
|
-
|
|
36282
|
-
|
|
36283
|
-
|
|
36284
|
-
|
|
36285
|
-
|
|
36286
|
-
|
|
36287
|
-
|
|
36288
|
-
|
|
36289
|
-
|
|
36290
|
-
|
|
36291
|
-
|
|
36292
|
-
|
|
36293
|
-
|
|
36294
|
-
|
|
36295
|
-
|
|
36296
|
-
|
|
36297
|
-
|
|
36298
|
-
|
|
36299
|
-
|
|
36300
|
-
|
|
36301
|
-
|
|
36302
|
-
|
|
36303
|
-
|
|
36304
|
-
|
|
36305
|
-
|
|
36306
|
-
|
|
36307
|
-
|
|
36308
|
-
|
|
36309
|
-
|
|
36310
|
-
|
|
36311
|
-
|
|
36312
|
-
|
|
36313
|
-
|
|
36314
|
-
|
|
36315
|
-
|
|
36316
|
-
|
|
36317
|
-
|
|
36318
|
-
|
|
36319
|
-
|
|
36320
|
-
|
|
36321
|
-
|
|
36322
|
-
|
|
36323
|
-
|
|
36324
|
-
|
|
36325
|
-
|
|
36326
|
-
|
|
36327
|
-
|
|
36328
|
-
|
|
36329
|
-
|
|
36330
|
-
|
|
36331
|
-
|
|
36332
|
-
|
|
36333
|
-
|
|
36334
|
-
|
|
36335
|
-
|
|
36336
|
-
|
|
36337
|
-
|
|
36338
|
-
|
|
36339
|
-
|
|
36340
|
-
|
|
36341
|
-
|
|
36342
|
-
|
|
36343
|
-
|
|
36344
|
-
|
|
36345
|
-
|
|
36346
|
-
|
|
36347
|
-
|
|
36348
|
-
|
|
36349
|
-
|
|
36350
|
-
|
|
36351
|
-
|
|
36352
|
-
|
|
36353
|
-
|
|
36354
|
-
);
|
|
36355
|
-
|
|
36356
|
-
|
|
36357
|
-
|
|
36358
|
-
|
|
36359
|
-
|
|
36360
|
-
|
|
36361
|
-
|
|
36362
|
-
|
|
36363
|
-
|
|
36364
|
-
|
|
36365
|
-
|
|
36366
|
-
|
|
36367
|
-
|
|
36368
|
-
|
|
36369
|
-
|
|
36370
|
-
|
|
36371
|
-
|
|
36372
|
-
|
|
36373
|
-
|
|
36374
|
-
|
|
36375
|
-
|
|
36376
|
-
|
|
36377
|
-
|
|
36378
|
-
|
|
36379
|
-
|
|
36380
|
-
|
|
36381
|
-
|
|
36382
|
-
|
|
36383
|
-
|
|
36384
|
-
|
|
36385
|
-
|
|
36386
|
-
|
|
36387
|
-
|
|
36388
|
-
|
|
36389
|
-
|
|
36390
|
-
|
|
36391
|
-
|
|
36392
|
-
|
|
36393
|
-
|
|
36394
|
-
|
|
36395
|
-
|
|
36109
|
+
var CHANGE_DEBOUNCE_MS, ALLOWED_ATTRS, DROP_TAGS, MD_BLOCK_PREFIXES, BLOCK_TAGS, MD_INLINE_RULES, RICH_TEXT_CSS, IDLE_TOOLBAR, RichTextEditor;
|
|
36110
|
+
var init_RichTextEditor = __esm({
|
|
36111
|
+
"components/core/molecules/RichTextEditor.tsx"() {
|
|
36112
|
+
"use client";
|
|
36113
|
+
init_cn();
|
|
36114
|
+
init_Box();
|
|
36115
|
+
init_Button();
|
|
36116
|
+
init_useEventBus();
|
|
36117
|
+
CHANGE_DEBOUNCE_MS = 400;
|
|
36118
|
+
ALLOWED_ATTRS = {
|
|
36119
|
+
p: [],
|
|
36120
|
+
h1: [],
|
|
36121
|
+
h2: [],
|
|
36122
|
+
h3: [],
|
|
36123
|
+
h4: [],
|
|
36124
|
+
ul: [],
|
|
36125
|
+
ol: [],
|
|
36126
|
+
li: [],
|
|
36127
|
+
blockquote: [],
|
|
36128
|
+
pre: [],
|
|
36129
|
+
code: [],
|
|
36130
|
+
b: [],
|
|
36131
|
+
strong: [],
|
|
36132
|
+
i: [],
|
|
36133
|
+
em: [],
|
|
36134
|
+
u: [],
|
|
36135
|
+
s: [],
|
|
36136
|
+
strike: [],
|
|
36137
|
+
br: [],
|
|
36138
|
+
hr: [],
|
|
36139
|
+
div: [],
|
|
36140
|
+
span: [],
|
|
36141
|
+
a: ["href"],
|
|
36142
|
+
img: ["src", "alt"]
|
|
36143
|
+
};
|
|
36144
|
+
DROP_TAGS = /* @__PURE__ */ new Set(["script", "style", "iframe", "object", "embed", "link", "meta", "form", "input", "button", "textarea", "select"]);
|
|
36145
|
+
MD_BLOCK_PREFIXES = {
|
|
36146
|
+
"#": { kind: "block", tag: "h1" },
|
|
36147
|
+
"##": { kind: "block", tag: "h2" },
|
|
36148
|
+
"###": { kind: "block", tag: "h3" },
|
|
36149
|
+
">": { kind: "block", tag: "blockquote" },
|
|
36150
|
+
"```": { kind: "block", tag: "pre" },
|
|
36151
|
+
"-": { kind: "list", command: "insertUnorderedList" },
|
|
36152
|
+
"*": { kind: "list", command: "insertUnorderedList" },
|
|
36153
|
+
"1.": { kind: "list", command: "insertOrderedList" }
|
|
36154
|
+
};
|
|
36155
|
+
BLOCK_TAGS = /* @__PURE__ */ new Set(["P", "DIV", "LI", "H1", "H2", "H3", "H4", "BLOCKQUOTE", "PRE"]);
|
|
36156
|
+
MD_INLINE_RULES = [
|
|
36157
|
+
{ pattern: /\*\*([^*\n]+)\*\*$/, wrap: "strong" },
|
|
36158
|
+
{ pattern: /(^|[^*])\*([^*\n]+)\*$/, wrap: "em" },
|
|
36159
|
+
{ pattern: /`([^`\n]+)`$/, wrap: "code" }
|
|
36160
|
+
];
|
|
36161
|
+
RICH_TEXT_CSS = `
|
|
36162
|
+
.almadar-rich-text { line-height: 1.7; color: var(--color-foreground); }
|
|
36163
|
+
.almadar-rich-text h1 { font-size: 1.875rem; font-weight: 700; line-height: 1.25; margin: 1.25em 0 0.4em; }
|
|
36164
|
+
.almadar-rich-text h2 { font-size: 1.5rem; font-weight: 650; line-height: 1.3; margin: 1.1em 0 0.4em; }
|
|
36165
|
+
.almadar-rich-text h3 { font-size: 1.25rem; font-weight: 600; line-height: 1.35; margin: 1em 0 0.35em; }
|
|
36166
|
+
.almadar-rich-text h1:first-child, .almadar-rich-text h2:first-child, .almadar-rich-text h3:first-child { margin-top: 0; }
|
|
36167
|
+
.almadar-rich-text p { margin: 0.5em 0; }
|
|
36168
|
+
.almadar-rich-text ul { list-style: disc; padding-inline-start: 1.5rem; margin: 0.5em 0; }
|
|
36169
|
+
.almadar-rich-text ol { list-style: decimal; padding-inline-start: 1.5rem; margin: 0.5em 0; }
|
|
36170
|
+
.almadar-rich-text li { margin: 0.25em 0; }
|
|
36171
|
+
.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; }
|
|
36172
|
+
.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; }
|
|
36173
|
+
.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; }
|
|
36174
|
+
.almadar-rich-text pre code { background: transparent; padding: 0; }
|
|
36175
|
+
.almadar-rich-text a { color: var(--color-primary); text-decoration: underline; }
|
|
36176
|
+
.almadar-rich-text hr { border: none; border-top: 1px solid var(--color-border); margin: 1.25em 0; }
|
|
36177
|
+
.almadar-rich-text img { max-width: 100%; border-radius: 0.375rem; }
|
|
36178
|
+
`;
|
|
36179
|
+
IDLE_TOOLBAR = {
|
|
36180
|
+
bold: false,
|
|
36181
|
+
italic: false,
|
|
36182
|
+
underline: false,
|
|
36183
|
+
strikeThrough: false,
|
|
36184
|
+
block: null,
|
|
36185
|
+
bullets: false,
|
|
36186
|
+
numbers: false,
|
|
36187
|
+
link: false
|
|
36188
|
+
};
|
|
36189
|
+
RichTextEditor = ({
|
|
36190
|
+
value,
|
|
36191
|
+
onChange,
|
|
36192
|
+
changeEvent,
|
|
36193
|
+
readOnly = false,
|
|
36194
|
+
placeholder,
|
|
36195
|
+
showToolbar = true,
|
|
36196
|
+
className
|
|
36197
|
+
}) => {
|
|
36198
|
+
const { t } = useTranslate();
|
|
36199
|
+
const ref = useRef(null);
|
|
36200
|
+
const [toolbar, setToolbar] = useState(IDLE_TOOLBAR);
|
|
36201
|
+
const [empty, setEmpty] = useState(() => !value || !sanitizeRichHtml(value).trim());
|
|
36202
|
+
const eventBus = useEventBus();
|
|
36203
|
+
const onChangeRef = useRef(onChange);
|
|
36204
|
+
const changeEventRef = useRef(changeEvent);
|
|
36205
|
+
useEffect(() => {
|
|
36206
|
+
onChangeRef.current = onChange;
|
|
36207
|
+
changeEventRef.current = changeEvent;
|
|
36208
|
+
}, [onChange, changeEvent]);
|
|
36209
|
+
const emitTimerRef = useRef(null);
|
|
36210
|
+
const emitNow = useCallback(() => {
|
|
36211
|
+
const el = ref.current;
|
|
36212
|
+
if (!el) return;
|
|
36213
|
+
const html = sanitizeRichHtml(el.innerHTML);
|
|
36214
|
+
onChangeRef.current?.(html);
|
|
36215
|
+
const evt = changeEventRef.current;
|
|
36216
|
+
if (evt) eventBus.emit(`UI:${evt}`, { value: html });
|
|
36217
|
+
}, [eventBus]);
|
|
36218
|
+
const scheduleEmit = useCallback(() => {
|
|
36219
|
+
if (emitTimerRef.current) clearTimeout(emitTimerRef.current);
|
|
36220
|
+
emitTimerRef.current = setTimeout(() => {
|
|
36221
|
+
emitTimerRef.current = null;
|
|
36222
|
+
emitNow();
|
|
36223
|
+
}, CHANGE_DEBOUNCE_MS);
|
|
36224
|
+
}, [emitNow]);
|
|
36225
|
+
const flushEmit = useCallback(() => {
|
|
36226
|
+
if (!emitTimerRef.current) return;
|
|
36227
|
+
clearTimeout(emitTimerRef.current);
|
|
36228
|
+
emitTimerRef.current = null;
|
|
36229
|
+
emitNow();
|
|
36230
|
+
}, [emitNow]);
|
|
36231
|
+
useEffect(() => () => {
|
|
36232
|
+
if (emitTimerRef.current) {
|
|
36233
|
+
clearTimeout(emitTimerRef.current);
|
|
36234
|
+
emitTimerRef.current = null;
|
|
36235
|
+
emitNow();
|
|
36236
|
+
}
|
|
36237
|
+
}, [emitNow]);
|
|
36238
|
+
useEffect(() => {
|
|
36239
|
+
if (readOnly) return;
|
|
36240
|
+
const el = ref.current;
|
|
36241
|
+
if (!el) return;
|
|
36242
|
+
if (document.activeElement === el) return;
|
|
36243
|
+
const next = sanitizeRichHtml(value ?? "") || "<p><br></p>";
|
|
36244
|
+
if (el.innerHTML !== next) {
|
|
36245
|
+
el.innerHTML = next;
|
|
36246
|
+
setEmpty(htmlIsEmpty(el));
|
|
36247
|
+
}
|
|
36248
|
+
}, [readOnly, value]);
|
|
36249
|
+
useEffect(() => {
|
|
36250
|
+
if (readOnly) return;
|
|
36251
|
+
document.execCommand("defaultParagraphSeparator", false, "p");
|
|
36252
|
+
}, [readOnly]);
|
|
36253
|
+
useEffect(() => {
|
|
36254
|
+
if (readOnly || !showToolbar) return;
|
|
36255
|
+
const onSelectionChange = () => {
|
|
36256
|
+
const el = ref.current;
|
|
36257
|
+
if (!el) return;
|
|
36258
|
+
setToolbar(readToolbarState(el));
|
|
36396
36259
|
};
|
|
36397
|
-
|
|
36398
|
-
|
|
36399
|
-
|
|
36400
|
-
|
|
36401
|
-
|
|
36402
|
-
|
|
36403
|
-
|
|
36404
|
-
|
|
36405
|
-
|
|
36406
|
-
|
|
36407
|
-
|
|
36408
|
-
|
|
36409
|
-
|
|
36410
|
-
|
|
36411
|
-
|
|
36412
|
-
|
|
36413
|
-
!
|
|
36414
|
-
|
|
36415
|
-
|
|
36416
|
-
|
|
36417
|
-
|
|
36418
|
-
|
|
36419
|
-
|
|
36420
|
-
|
|
36421
|
-
|
|
36422
|
-
|
|
36423
|
-
|
|
36424
|
-
|
|
36425
|
-
|
|
36426
|
-
|
|
36427
|
-
|
|
36428
|
-
|
|
36429
|
-
|
|
36430
|
-
|
|
36431
|
-
|
|
36432
|
-
|
|
36433
|
-
|
|
36434
|
-
|
|
36435
|
-
|
|
36436
|
-
|
|
36437
|
-
|
|
36438
|
-
|
|
36439
|
-
|
|
36440
|
-
|
|
36441
|
-
|
|
36442
|
-
|
|
36443
|
-
|
|
36260
|
+
document.addEventListener("selectionchange", onSelectionChange);
|
|
36261
|
+
return () => document.removeEventListener("selectionchange", onSelectionChange);
|
|
36262
|
+
}, [readOnly, showToolbar]);
|
|
36263
|
+
const tryInlineMarkdown = useCallback(() => {
|
|
36264
|
+
const root = ref.current;
|
|
36265
|
+
if (!root) return false;
|
|
36266
|
+
const sel = window.getSelection();
|
|
36267
|
+
if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return false;
|
|
36268
|
+
const node = sel.anchorNode;
|
|
36269
|
+
if (!node || node.nodeType !== Node.TEXT_NODE || !root.contains(node)) return false;
|
|
36270
|
+
if (node.parentElement?.closest("code, pre")) return false;
|
|
36271
|
+
const text = (node.textContent ?? "").slice(0, sel.anchorOffset);
|
|
36272
|
+
for (const rule of MD_INLINE_RULES) {
|
|
36273
|
+
const m = rule.pattern.exec(text);
|
|
36274
|
+
if (!m) continue;
|
|
36275
|
+
const inner = rule.wrap === "em" ? m[2] : m[1];
|
|
36276
|
+
if (!inner || !inner.trim()) continue;
|
|
36277
|
+
const lead = rule.wrap === "em" ? m[1]?.length ?? 0 : 0;
|
|
36278
|
+
const range = document.createRange();
|
|
36279
|
+
range.setStart(node, m.index + lead);
|
|
36280
|
+
range.setEnd(node, sel.anchorOffset);
|
|
36281
|
+
const el = document.createElement(rule.wrap);
|
|
36282
|
+
el.textContent = inner;
|
|
36283
|
+
range.deleteContents();
|
|
36284
|
+
range.insertNode(el);
|
|
36285
|
+
const after = document.createTextNode("\u200B");
|
|
36286
|
+
el.parentNode?.insertBefore(after, el.nextSibling);
|
|
36287
|
+
const caret = document.createRange();
|
|
36288
|
+
caret.setStart(after, 1);
|
|
36289
|
+
caret.collapse(true);
|
|
36290
|
+
sel.removeAllRanges();
|
|
36291
|
+
sel.addRange(caret);
|
|
36292
|
+
return true;
|
|
36293
|
+
}
|
|
36294
|
+
return false;
|
|
36295
|
+
}, []);
|
|
36296
|
+
const tryBlockMarkdown = useCallback(() => {
|
|
36297
|
+
const root = ref.current;
|
|
36298
|
+
if (!root) return false;
|
|
36299
|
+
const sel = window.getSelection();
|
|
36300
|
+
if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return false;
|
|
36301
|
+
const node = sel.anchorNode;
|
|
36302
|
+
if (!node || node.nodeType !== Node.TEXT_NODE || !root.contains(node)) return false;
|
|
36303
|
+
const block = closestBlock(node, root);
|
|
36304
|
+
if (block ? block.firstChild !== node : root.firstChild !== node) return false;
|
|
36305
|
+
const prefix = (node.textContent ?? "").slice(0, sel.anchorOffset);
|
|
36306
|
+
const rule = MD_BLOCK_PREFIXES[prefix];
|
|
36307
|
+
if (!rule) return false;
|
|
36308
|
+
if (node.parentElement?.closest("pre, code")) return false;
|
|
36309
|
+
if (rule.kind === "list" && node.parentElement?.closest("li")) return false;
|
|
36310
|
+
node.deleteData(0, prefix.length);
|
|
36311
|
+
const caret = document.createRange();
|
|
36312
|
+
caret.setStart(node, 0);
|
|
36313
|
+
caret.collapse(true);
|
|
36314
|
+
sel.removeAllRanges();
|
|
36315
|
+
sel.addRange(caret);
|
|
36316
|
+
if (rule.kind === "list") {
|
|
36317
|
+
const container = block ?? node.parentElement;
|
|
36318
|
+
const list = document.createElement(rule.command === "insertOrderedList" ? "ol" : "ul");
|
|
36319
|
+
const li = document.createElement("li");
|
|
36320
|
+
if (block) {
|
|
36321
|
+
while (block.firstChild) li.appendChild(block.firstChild);
|
|
36322
|
+
list.appendChild(li);
|
|
36323
|
+
block.replaceWith(list);
|
|
36324
|
+
} else if (container) {
|
|
36325
|
+
li.appendChild(node);
|
|
36326
|
+
list.appendChild(li);
|
|
36327
|
+
container.appendChild(list);
|
|
36328
|
+
}
|
|
36329
|
+
if (!li.firstChild) li.appendChild(document.createElement("br"));
|
|
36330
|
+
const liCaret = document.createRange();
|
|
36331
|
+
liCaret.selectNodeContents(li);
|
|
36332
|
+
liCaret.collapse(true);
|
|
36333
|
+
sel.removeAllRanges();
|
|
36334
|
+
sel.addRange(liCaret);
|
|
36335
|
+
} else {
|
|
36336
|
+
document.execCommand("formatBlock", false, rule.tag);
|
|
36337
|
+
}
|
|
36338
|
+
return true;
|
|
36339
|
+
}, []);
|
|
36340
|
+
const afterEdit = useCallback(() => {
|
|
36341
|
+
const el = ref.current;
|
|
36342
|
+
if (!el) return;
|
|
36343
|
+
tryInlineMarkdown();
|
|
36344
|
+
setEmpty(htmlIsEmpty(el));
|
|
36345
|
+
setToolbar(readToolbarState(el));
|
|
36346
|
+
scheduleEmit();
|
|
36347
|
+
}, [scheduleEmit, tryInlineMarkdown]);
|
|
36348
|
+
const handleKeyDown = useCallback((e) => {
|
|
36349
|
+
if (e.key === " " && tryBlockMarkdown()) {
|
|
36350
|
+
e.preventDefault();
|
|
36351
|
+
afterEdit();
|
|
36352
|
+
}
|
|
36353
|
+
}, [afterEdit, tryBlockMarkdown]);
|
|
36354
|
+
const execInline = useCallback((command) => {
|
|
36355
|
+
document.execCommand(command, false);
|
|
36356
|
+
afterEdit();
|
|
36357
|
+
}, [afterEdit]);
|
|
36358
|
+
const execBlock = useCallback((tag) => {
|
|
36359
|
+
const next = toolbar.block === tag ? "p" : tag;
|
|
36360
|
+
document.execCommand("formatBlock", false, next);
|
|
36361
|
+
afterEdit();
|
|
36362
|
+
}, [afterEdit, toolbar.block]);
|
|
36363
|
+
const execList = useCallback((command) => {
|
|
36364
|
+
document.execCommand(command, false);
|
|
36365
|
+
afterEdit();
|
|
36366
|
+
}, [afterEdit]);
|
|
36367
|
+
const execLink = useCallback(() => {
|
|
36368
|
+
if (toolbar.link) {
|
|
36369
|
+
document.execCommand("unlink", false);
|
|
36370
|
+
afterEdit();
|
|
36371
|
+
return;
|
|
36372
|
+
}
|
|
36373
|
+
const url = window.prompt(t("richTextEditor.linkPrompt"));
|
|
36374
|
+
if (!url) return;
|
|
36375
|
+
const safe = safeUrl(url, ["http://", "https://", "mailto:"]) ?? `https://${url}`;
|
|
36376
|
+
document.execCommand("createLink", false, safe);
|
|
36377
|
+
afterEdit();
|
|
36378
|
+
}, [afterEdit, t, toolbar.link]);
|
|
36379
|
+
const execRule = useCallback(() => {
|
|
36380
|
+
document.execCommand("insertHorizontalRule", false);
|
|
36381
|
+
afterEdit();
|
|
36382
|
+
}, [afterEdit]);
|
|
36383
|
+
if (readOnly) {
|
|
36384
|
+
return /* @__PURE__ */ jsxs(Box, { className: cn("almadar-rich-text max-w-none", className), children: [
|
|
36385
|
+
/* @__PURE__ */ jsx(RichTextStyles, {}),
|
|
36386
|
+
/* @__PURE__ */ jsx(Box, { dangerouslySetInnerHTML: { __html: sanitizeRichHtml(value ?? "") } })
|
|
36444
36387
|
] });
|
|
36445
36388
|
}
|
|
36446
|
-
|
|
36447
|
-
|
|
36448
|
-
|
|
36449
|
-
return /* @__PURE__ */ jsxs(
|
|
36389
|
+
return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col gap-2", className), children: [
|
|
36390
|
+
/* @__PURE__ */ jsx(RichTextStyles, {}),
|
|
36391
|
+
showToolbar && /* @__PURE__ */ jsxs(
|
|
36450
36392
|
Box,
|
|
36451
36393
|
{
|
|
36452
|
-
|
|
36394
|
+
role: "toolbar",
|
|
36395
|
+
"aria-label": t("richTextEditor.editorToolbar"),
|
|
36453
36396
|
className: cn(
|
|
36454
|
-
"
|
|
36455
|
-
|
|
36397
|
+
"sticky top-0 z-10 flex flex-wrap items-center gap-0.5 self-start",
|
|
36398
|
+
"rounded-md border border-border bg-background/95 px-1 py-0.5 shadow-sm"
|
|
36456
36399
|
),
|
|
36457
36400
|
children: [
|
|
36458
|
-
|
|
36459
|
-
|
|
36460
|
-
|
|
36461
|
-
|
|
36462
|
-
|
|
36463
|
-
|
|
36464
|
-
|
|
36465
|
-
|
|
36466
|
-
|
|
36467
|
-
|
|
36468
|
-
|
|
36469
|
-
|
|
36470
|
-
|
|
36471
|
-
|
|
36472
|
-
|
|
36473
|
-
|
|
36474
|
-
type: "button",
|
|
36475
|
-
variant: "ghost",
|
|
36476
|
-
"aria-label": t("richBlockEditor.aria.removeListItem"),
|
|
36477
|
-
className: cn(
|
|
36478
|
-
"h-5 w-5 shrink-0 rounded-sm text-muted-foreground p-0 gap-0",
|
|
36479
|
-
"opacity-0 group-hover/item:opacity-100 hover:bg-muted hover:text-foreground"
|
|
36480
|
-
),
|
|
36481
|
-
onClick: () => removeListItem(child.id),
|
|
36482
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "trash", className: "w-3 h-3" })
|
|
36483
|
-
}
|
|
36484
|
-
)
|
|
36485
|
-
] }, child.id)),
|
|
36486
|
-
!readOnly && showAffordances && /* @__PURE__ */ jsx(Box, { as: "li", className: "list-none pl-0", children: /* @__PURE__ */ jsxs(
|
|
36487
|
-
Button,
|
|
36488
|
-
{
|
|
36489
|
-
type: "button",
|
|
36490
|
-
variant: "ghost",
|
|
36491
|
-
className: cn(
|
|
36492
|
-
"inline-flex items-center gap-1 text-xs text-muted-foreground",
|
|
36493
|
-
"hover:text-foreground p-0 h-auto"
|
|
36494
|
-
),
|
|
36495
|
-
onClick: addListItem,
|
|
36496
|
-
children: [
|
|
36497
|
-
/* @__PURE__ */ jsx(Icon, { name: "plus", className: "w-3 h-3" }),
|
|
36498
|
-
" ",
|
|
36499
|
-
t("richBlockEditor.addItem")
|
|
36500
|
-
]
|
|
36501
|
-
}
|
|
36502
|
-
) })
|
|
36401
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Bold, label: t("richTextEditor.bold"), active: toolbar.bold, onExec: () => execInline("bold") }),
|
|
36402
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Italic, label: t("richTextEditor.italic"), active: toolbar.italic, onExec: () => execInline("italic") }),
|
|
36403
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Underline, label: t("richTextEditor.underline"), active: toolbar.underline, onExec: () => execInline("underline") }),
|
|
36404
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Strikethrough, label: t("richTextEditor.strikethrough"), active: toolbar.strikeThrough, onExec: () => execInline("strikeThrough") }),
|
|
36405
|
+
/* @__PURE__ */ jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
36406
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Heading1, label: t("richTextEditor.heading1"), active: toolbar.block === "h1", onExec: () => execBlock("h1") }),
|
|
36407
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Heading2, label: t("richTextEditor.heading2"), active: toolbar.block === "h2", onExec: () => execBlock("h2") }),
|
|
36408
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Heading3, label: t("richTextEditor.heading3"), active: toolbar.block === "h3", onExec: () => execBlock("h3") }),
|
|
36409
|
+
/* @__PURE__ */ jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
36410
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: List, label: t("richTextEditor.bulletList"), active: toolbar.bullets, onExec: () => execList("insertUnorderedList") }),
|
|
36411
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: ListOrdered, label: t("richTextEditor.numberedList"), active: toolbar.numbers, onExec: () => execList("insertOrderedList") }),
|
|
36412
|
+
/* @__PURE__ */ jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
36413
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Quote, label: t("richTextEditor.quote"), active: toolbar.block === "blockquote", onExec: () => execBlock("blockquote") }),
|
|
36414
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Code, label: t("richTextEditor.code"), active: toolbar.block === "pre", onExec: () => execBlock("pre") }),
|
|
36415
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Link$1, label: toolbar.link ? t("richTextEditor.removeLink") : t("richTextEditor.link"), active: toolbar.link, onExec: execLink }),
|
|
36416
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Minus, label: t("richTextEditor.divider"), onExec: execRule })
|
|
36503
36417
|
]
|
|
36504
36418
|
}
|
|
36505
|
-
)
|
|
36506
|
-
|
|
36507
|
-
|
|
36508
|
-
default:
|
|
36509
|
-
return /* @__PURE__ */ jsx(
|
|
36510
|
-
Editable,
|
|
36419
|
+
),
|
|
36420
|
+
/* @__PURE__ */ jsx(
|
|
36421
|
+
Box,
|
|
36511
36422
|
{
|
|
36512
|
-
|
|
36513
|
-
|
|
36514
|
-
|
|
36515
|
-
|
|
36516
|
-
|
|
36517
|
-
|
|
36518
|
-
|
|
36423
|
+
ref,
|
|
36424
|
+
contentEditable: true,
|
|
36425
|
+
suppressContentEditableWarning: true,
|
|
36426
|
+
role: "textbox",
|
|
36427
|
+
"aria-multiline": "true",
|
|
36428
|
+
"aria-label": t("richTextEditor.editorSurface"),
|
|
36429
|
+
"data-placeholder": placeholder ?? t("richTextEditor.placeholder"),
|
|
36430
|
+
"data-empty": empty ? "true" : "false",
|
|
36431
|
+
className: cn(
|
|
36432
|
+
"almadar-rich-text max-w-none min-h-[8rem] outline-none",
|
|
36433
|
+
"data-[empty=true]:before:content-[attr(data-placeholder)]",
|
|
36434
|
+
"data-[empty=true]:before:text-muted-foreground/60",
|
|
36435
|
+
"data-[empty=true]:before:pointer-events-none",
|
|
36436
|
+
"data-[empty=true]:before:absolute",
|
|
36437
|
+
"relative cursor-text"
|
|
36438
|
+
),
|
|
36439
|
+
onInput: afterEdit,
|
|
36440
|
+
onKeyDown: handleKeyDown,
|
|
36441
|
+
onBlur: flushEmit
|
|
36519
36442
|
}
|
|
36520
|
-
)
|
|
36521
|
-
|
|
36443
|
+
)
|
|
36444
|
+
] });
|
|
36445
|
+
};
|
|
36446
|
+
RichTextEditor.displayName = "RichTextEditor";
|
|
36447
|
+
}
|
|
36448
|
+
});
|
|
36449
|
+
function renderIconInput4(icon, props) {
|
|
36450
|
+
return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
|
|
36451
|
+
}
|
|
36452
|
+
function DocumentPanel({
|
|
36453
|
+
entity,
|
|
36454
|
+
title,
|
|
36455
|
+
subtitle,
|
|
36456
|
+
value,
|
|
36457
|
+
actions,
|
|
36458
|
+
maxInlineActions,
|
|
36459
|
+
editing = false,
|
|
36460
|
+
titleCommitEvent,
|
|
36461
|
+
contentChangeEvent,
|
|
36462
|
+
editEvent,
|
|
36463
|
+
doneEvent,
|
|
36464
|
+
editLabel,
|
|
36465
|
+
doneLabel,
|
|
36466
|
+
autosaveHint,
|
|
36467
|
+
placeholder,
|
|
36468
|
+
className
|
|
36469
|
+
}) {
|
|
36470
|
+
const eventBus = useEventBus();
|
|
36471
|
+
const { t } = useTranslate();
|
|
36472
|
+
const [titleDraft, setTitleDraft] = useState(null);
|
|
36473
|
+
const recordId = entity?.id !== void 0 && entity?.id !== null ? String(entity.id) : "";
|
|
36474
|
+
const actionDefs = actions ?? [];
|
|
36475
|
+
const inlineCap = Math.min(maxInlineActions ?? 1, 1);
|
|
36476
|
+
const inlineActions = actionDefs.filter((a) => a.variant === "primary").slice(0, inlineCap);
|
|
36477
|
+
const menuActions = actionDefs.filter((a) => !inlineActions.includes(a));
|
|
36478
|
+
const fireAction = (action) => {
|
|
36479
|
+
if (!action.event) return;
|
|
36480
|
+
eventBus.emit(`UI:${action.event}`, { id: recordId, row: entity });
|
|
36522
36481
|
};
|
|
36523
|
-
|
|
36482
|
+
const commitTitle = () => {
|
|
36483
|
+
if (!titleCommitEvent) return;
|
|
36484
|
+
const next = (titleDraft ?? "").trim();
|
|
36485
|
+
setTitleDraft(null);
|
|
36486
|
+
if (!next || next === title) return;
|
|
36487
|
+
eventBus.emit(`UI:${titleCommitEvent}`, { title: next, id: recordId });
|
|
36488
|
+
};
|
|
36489
|
+
const untitled = t("documentPanel.untitled") || "Untitled";
|
|
36490
|
+
const titleNode = titleCommitEvent && titleDraft !== null ? /* @__PURE__ */ jsx(
|
|
36491
|
+
Input,
|
|
36492
|
+
{
|
|
36493
|
+
value: titleDraft,
|
|
36494
|
+
autoFocus: true,
|
|
36495
|
+
"aria-label": t("common.title"),
|
|
36496
|
+
className: "h-auto py-1 text-3xl font-bold tracking-tight",
|
|
36497
|
+
onFocus: (e) => e.currentTarget.select(),
|
|
36498
|
+
onChange: (e) => setTitleDraft(e.target.value),
|
|
36499
|
+
onBlur: commitTitle,
|
|
36500
|
+
onKeyDown: (e) => {
|
|
36501
|
+
if (e.key === "Enter") {
|
|
36502
|
+
e.preventDefault();
|
|
36503
|
+
commitTitle();
|
|
36504
|
+
} else if (e.key === "Escape") {
|
|
36505
|
+
e.preventDefault();
|
|
36506
|
+
setTitleDraft(null);
|
|
36507
|
+
}
|
|
36508
|
+
},
|
|
36509
|
+
"data-testid": "document-title-input"
|
|
36510
|
+
}
|
|
36511
|
+
) : titleCommitEvent ? /* @__PURE__ */ jsx(
|
|
36524
36512
|
Box,
|
|
36525
36513
|
{
|
|
36526
|
-
|
|
36527
|
-
|
|
36528
|
-
|
|
36529
|
-
),
|
|
36530
|
-
|
|
36531
|
-
|
|
36532
|
-
|
|
36533
|
-
|
|
36534
|
-
|
|
36514
|
+
role: "button",
|
|
36515
|
+
tabIndex: 0,
|
|
36516
|
+
className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
36517
|
+
onClick: () => setTitleDraft(title ?? ""),
|
|
36518
|
+
onKeyDown: (e) => {
|
|
36519
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
36520
|
+
e.preventDefault();
|
|
36521
|
+
setTitleDraft(title ?? "");
|
|
36522
|
+
}
|
|
36523
|
+
},
|
|
36524
|
+
"data-testid": "document-title-editable",
|
|
36525
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", className: cn(!title && "text-muted-foreground"), children: title || untitled })
|
|
36526
|
+
}
|
|
36527
|
+
) : /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || untitled });
|
|
36528
|
+
const emitWithId = (event) => () => {
|
|
36529
|
+
if (event) eventBus.emit(`UI:${event}`, { id: recordId });
|
|
36530
|
+
};
|
|
36531
|
+
return /* @__PURE__ */ jsx(Card, { variant: "elevated", className: cn("w-full", className), children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "p-6 sm:p-8", children: [
|
|
36532
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
36533
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
36534
|
+
titleNode,
|
|
36535
|
+
subtitle ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
36536
|
+
] }),
|
|
36537
|
+
/* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36538
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
36539
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
36540
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36541
|
+
editEvent && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
36542
|
+
/* @__PURE__ */ jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
36543
|
+
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
36544
|
+
] }),
|
|
36545
|
+
inlineActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
36546
|
+
Button,
|
|
36535
36547
|
{
|
|
36536
|
-
|
|
36537
|
-
|
|
36538
|
-
|
|
36539
|
-
|
|
36540
|
-
|
|
36548
|
+
variant: "primary",
|
|
36549
|
+
size: "sm",
|
|
36550
|
+
onClick: () => fireAction(action),
|
|
36551
|
+
"data-testid": `action-${action.event}`,
|
|
36552
|
+
children: [
|
|
36553
|
+
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
36554
|
+
action.label
|
|
36555
|
+
]
|
|
36556
|
+
},
|
|
36557
|
+
idx
|
|
36558
|
+
)),
|
|
36559
|
+
menuActions.length > 0 && /* @__PURE__ */ jsx(
|
|
36560
|
+
Menu,
|
|
36561
|
+
{
|
|
36562
|
+
position: "bottom-end",
|
|
36563
|
+
trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
36564
|
+
items: menuActions.map((action) => ({
|
|
36565
|
+
label: action.label,
|
|
36566
|
+
icon: action.icon,
|
|
36567
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
36568
|
+
onClick: () => fireAction(action)
|
|
36569
|
+
}))
|
|
36541
36570
|
}
|
|
36542
|
-
)
|
|
36543
|
-
|
|
36544
|
-
|
|
36545
|
-
}
|
|
36546
|
-
|
|
36571
|
+
)
|
|
36572
|
+
] }) })
|
|
36573
|
+
] }),
|
|
36574
|
+
editing ? /* @__PURE__ */ jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsx(
|
|
36575
|
+
Box,
|
|
36576
|
+
{
|
|
36577
|
+
onClick: emitWithId(editEvent),
|
|
36578
|
+
className: cn(
|
|
36579
|
+
"rounded-md px-1 -mx-1 min-h-[16rem]",
|
|
36580
|
+
editEvent && "cursor-text transition-colors hover:bg-muted/30"
|
|
36581
|
+
),
|
|
36582
|
+
"data-testid": "document-body",
|
|
36583
|
+
children: value && value !== "" ? /* @__PURE__ */ jsx(RichTextEditor, { value, readOnly: true }) : /* @__PURE__ */ jsx(Typography, { variant: "body", color: "muted", children: placeholder ?? (t("documentPanel.placeholder") || "") })
|
|
36584
|
+
}
|
|
36585
|
+
)
|
|
36586
|
+
] }) });
|
|
36547
36587
|
}
|
|
36548
|
-
var
|
|
36549
|
-
|
|
36550
|
-
"components/core/molecules/RichBlockEditor.tsx"() {
|
|
36588
|
+
var init_DocumentPanel = __esm({
|
|
36589
|
+
"components/core/molecules/DocumentPanel.tsx"() {
|
|
36551
36590
|
"use client";
|
|
36552
36591
|
init_cn();
|
|
36553
|
-
|
|
36592
|
+
init_useEventBus();
|
|
36593
|
+
init_Box();
|
|
36594
|
+
init_Stack();
|
|
36554
36595
|
init_Typography();
|
|
36555
36596
|
init_Button();
|
|
36556
|
-
|
|
36557
|
-
init_Divider();
|
|
36558
|
-
init_Input();
|
|
36597
|
+
init_Card();
|
|
36559
36598
|
init_Icon();
|
|
36560
|
-
|
|
36561
|
-
|
|
36562
|
-
|
|
36563
|
-
|
|
36564
|
-
|
|
36565
|
-
|
|
36566
|
-
|
|
36567
|
-
|
|
36568
|
-
|
|
36569
|
-
|
|
36570
|
-
|
|
36571
|
-
|
|
36572
|
-
|
|
36573
|
-
|
|
36574
|
-
|
|
36575
|
-
|
|
36576
|
-
|
|
36577
|
-
|
|
36578
|
-
|
|
36579
|
-
|
|
36580
|
-
|
|
36581
|
-
|
|
36582
|
-
|
|
36583
|
-
|
|
36584
|
-
|
|
36585
|
-
|
|
36586
|
-
|
|
36587
|
-
|
|
36588
|
-
|
|
36589
|
-
|
|
36590
|
-
|
|
36591
|
-
|
|
36592
|
-
|
|
36593
|
-
|
|
36594
|
-
|
|
36595
|
-
|
|
36596
|
-
|
|
36597
|
-
|
|
36598
|
-
|
|
36599
|
-
|
|
36600
|
-
|
|
36601
|
-
|
|
36602
|
-
|
|
36603
|
-
|
|
36604
|
-
|
|
36605
|
-
|
|
36606
|
-
|
|
36607
|
-
|
|
36608
|
-
|
|
36609
|
-
|
|
36610
|
-
|
|
36611
|
-
|
|
36612
|
-
|
|
36613
|
-
|
|
36614
|
-
|
|
36615
|
-
|
|
36616
|
-
|
|
36617
|
-
|
|
36618
|
-
|
|
36619
|
-
const [blocks, setBlocks] = useState(
|
|
36620
|
-
() => normalizeBlocks(initialBlocks)
|
|
36621
|
-
);
|
|
36622
|
-
const onChangeRef = useRef(onChange);
|
|
36623
|
-
useEffect(() => {
|
|
36624
|
-
onChangeRef.current = onChange;
|
|
36625
|
-
}, [onChange]);
|
|
36626
|
-
const eventBus = useEventBus();
|
|
36627
|
-
const changeEventRef = useRef(changeEvent);
|
|
36628
|
-
useEffect(() => {
|
|
36629
|
-
changeEventRef.current = changeEvent;
|
|
36630
|
-
}, [changeEvent]);
|
|
36631
|
-
const commit = useCallback((next) => {
|
|
36632
|
-
setBlocks(next);
|
|
36633
|
-
onChangeRef.current?.(next);
|
|
36634
|
-
const evt = changeEventRef.current;
|
|
36635
|
-
if (evt) eventBus.emit(`UI:${evt}`, { blocks: next });
|
|
36636
|
-
}, [eventBus]);
|
|
36637
|
-
const handleAppend = useCallback(
|
|
36638
|
-
(type) => {
|
|
36639
|
-
if (readOnly) return;
|
|
36640
|
-
commit([...blocks, createBlock(type)]);
|
|
36641
|
-
},
|
|
36642
|
-
[blocks, commit, readOnly]
|
|
36643
|
-
);
|
|
36644
|
-
const handleUpdate = useCallback(
|
|
36645
|
-
(id, updater) => {
|
|
36646
|
-
commit(replaceBlock(blocks, id, updater));
|
|
36647
|
-
},
|
|
36648
|
-
[blocks, commit]
|
|
36649
|
-
);
|
|
36650
|
-
const handleDelete = useCallback(
|
|
36651
|
-
(id) => {
|
|
36652
|
-
const next = removeBlock(blocks, id);
|
|
36653
|
-
commit(next.length > 0 ? next : [createBlock("paragraph")]);
|
|
36654
|
-
},
|
|
36655
|
-
[blocks, commit]
|
|
36656
|
-
);
|
|
36657
|
-
const handleDuplicate = useCallback(
|
|
36658
|
-
(id) => {
|
|
36659
|
-
const target = blocks.find((b) => b.id === id);
|
|
36660
|
-
if (!target) return;
|
|
36661
|
-
commit(insertAfter(blocks, id, duplicateBlock(target)));
|
|
36662
|
-
},
|
|
36663
|
-
[blocks, commit]
|
|
36599
|
+
init_Input();
|
|
36600
|
+
init_Menu();
|
|
36601
|
+
init_RichTextEditor();
|
|
36602
|
+
}
|
|
36603
|
+
});
|
|
36604
|
+
function renderIconInput5(icon, props) {
|
|
36605
|
+
return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
|
|
36606
|
+
}
|
|
36607
|
+
function fieldName(field) {
|
|
36608
|
+
return field.name ?? field.key ?? "";
|
|
36609
|
+
}
|
|
36610
|
+
function relationLabel(value) {
|
|
36611
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date) return null;
|
|
36612
|
+
for (const key of ["name", "title", "label"]) {
|
|
36613
|
+
const candidate = value[key];
|
|
36614
|
+
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
36615
|
+
}
|
|
36616
|
+
const id = value.id;
|
|
36617
|
+
return id !== void 0 && id !== null ? String(id) : null;
|
|
36618
|
+
}
|
|
36619
|
+
function fieldKind(field, value) {
|
|
36620
|
+
if (field.kind) return field.kind;
|
|
36621
|
+
if (field.options && field.options.length > 0) return "select";
|
|
36622
|
+
if (typeof value === "boolean" || field.format === "boolean") return "boolean";
|
|
36623
|
+
if (Array.isArray(value) || relationLabel(value ?? null) !== null) return "readonly";
|
|
36624
|
+
return "text";
|
|
36625
|
+
}
|
|
36626
|
+
function DocumentDetails({
|
|
36627
|
+
entity,
|
|
36628
|
+
fields,
|
|
36629
|
+
metaCommitEvent,
|
|
36630
|
+
title,
|
|
36631
|
+
className
|
|
36632
|
+
}) {
|
|
36633
|
+
const eventBus = useEventBus();
|
|
36634
|
+
const { t } = useTranslate();
|
|
36635
|
+
const [fieldDraft, setFieldDraft] = useState(null);
|
|
36636
|
+
const recordId = entity?.id !== void 0 && entity?.id !== null ? String(entity.id) : "";
|
|
36637
|
+
const fieldDefs = (fields ?? []).filter((f3) => fieldName(f3) !== "");
|
|
36638
|
+
if (fieldDefs.length === 0) return null;
|
|
36639
|
+
const commitField = (name, next, current) => {
|
|
36640
|
+
setFieldDraft(null);
|
|
36641
|
+
if (!metaCommitEvent || next === current) return;
|
|
36642
|
+
eventBus.emit(`UI:${metaCommitEvent}`, { id: recordId, patch: { id: recordId, [name]: next } });
|
|
36643
|
+
};
|
|
36644
|
+
const renderValue = (field) => {
|
|
36645
|
+
const name = fieldName(field);
|
|
36646
|
+
const raw = getNestedValue(entity ?? {}, name);
|
|
36647
|
+
const kind = fieldKind(field, raw);
|
|
36648
|
+
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
36649
|
+
if (kind === "boolean") {
|
|
36650
|
+
return /* @__PURE__ */ jsx(
|
|
36651
|
+
Switch,
|
|
36652
|
+
{
|
|
36653
|
+
checked: Boolean(raw),
|
|
36654
|
+
disabled: !metaCommitEvent,
|
|
36655
|
+
"aria-label": label,
|
|
36656
|
+
onChange: (checked) => commitField(name, checked, Boolean(raw))
|
|
36657
|
+
}
|
|
36664
36658
|
);
|
|
36665
|
-
|
|
36666
|
-
|
|
36667
|
-
|
|
36668
|
-
|
|
36669
|
-
|
|
36670
|
-
|
|
36671
|
-
|
|
36659
|
+
}
|
|
36660
|
+
if (kind === "select") {
|
|
36661
|
+
return /* @__PURE__ */ jsx(
|
|
36662
|
+
Select,
|
|
36663
|
+
{
|
|
36664
|
+
value: raw !== void 0 && raw !== null ? String(raw) : "",
|
|
36665
|
+
disabled: !metaCommitEvent,
|
|
36666
|
+
"aria-label": label,
|
|
36667
|
+
className: "h-8 w-full",
|
|
36668
|
+
options: (field.options ?? []).map((opt) => ({ value: opt, label: humanizeEnumValue(opt) })),
|
|
36669
|
+
onChange: (e) => commitField(name, e.target.value, raw)
|
|
36670
|
+
}
|
|
36672
36671
|
);
|
|
36673
|
-
|
|
36674
|
-
|
|
36672
|
+
}
|
|
36673
|
+
if (kind === "readonly" || !metaCommitEvent) {
|
|
36674
|
+
if (Array.isArray(raw)) {
|
|
36675
|
+
if (raw.length === 0) {
|
|
36676
|
+
return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
36677
|
+
}
|
|
36678
|
+
return /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: relationLabel(item) ?? humanizeEnumValue(String(item)) }, i)) });
|
|
36679
|
+
}
|
|
36680
|
+
const shown2 = raw === void 0 || raw === null || raw === "" ? "\u2014" : relationLabel(raw) ?? formatValue(raw, field.format);
|
|
36681
|
+
return /* @__PURE__ */ jsx(Typography, { variant: "small", className: "break-words", children: shown2 });
|
|
36682
|
+
}
|
|
36683
|
+
if (fieldDraft?.name === name) {
|
|
36684
|
+
return /* @__PURE__ */ jsx(
|
|
36685
|
+
Input,
|
|
36675
36686
|
{
|
|
36676
|
-
|
|
36677
|
-
|
|
36678
|
-
|
|
36679
|
-
|
|
36680
|
-
|
|
36681
|
-
|
|
36682
|
-
|
|
36683
|
-
|
|
36684
|
-
|
|
36685
|
-
|
|
36686
|
-
|
|
36687
|
-
|
|
36688
|
-
|
|
36689
|
-
|
|
36690
|
-
|
|
36691
|
-
|
|
36692
|
-
return /* @__PURE__ */ jsxs(
|
|
36693
|
-
Button,
|
|
36694
|
-
{
|
|
36695
|
-
type: "button",
|
|
36696
|
-
variant: "ghost",
|
|
36697
|
-
size: "sm",
|
|
36698
|
-
"aria-label": t("richBlockEditor.insertEntry", { label: entryLabel }),
|
|
36699
|
-
title: entryLabel,
|
|
36700
|
-
onClick: () => handleAppend(entry.type),
|
|
36701
|
-
children: [
|
|
36702
|
-
/* @__PURE__ */ jsx(Icon2, { size: 14 }),
|
|
36703
|
-
/* @__PURE__ */ jsx(Typography, { as: "span", variant: "caption", className: "ml-1 hidden text-xs sm:inline", children: entryLabel })
|
|
36704
|
-
]
|
|
36705
|
-
},
|
|
36706
|
-
entry.type
|
|
36707
|
-
);
|
|
36708
|
-
})
|
|
36709
|
-
}
|
|
36710
|
-
),
|
|
36711
|
-
/* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-1 px-3 py-3", children: blocks.map((block) => /* @__PURE__ */ jsx(
|
|
36712
|
-
BlockRow,
|
|
36713
|
-
{
|
|
36714
|
-
block,
|
|
36715
|
-
readOnly,
|
|
36716
|
-
showAffordances: enableBlocks,
|
|
36717
|
-
placeholder,
|
|
36718
|
-
onUpdate: (updater) => handleUpdate(block.id, updater),
|
|
36719
|
-
onDelete: () => handleDelete(block.id),
|
|
36720
|
-
onDuplicate: () => handleDuplicate(block.id),
|
|
36721
|
-
onChangeType: (type) => handleChangeType(block.id, type)
|
|
36722
|
-
},
|
|
36723
|
-
block.id
|
|
36724
|
-
)) })
|
|
36725
|
-
]
|
|
36687
|
+
value: fieldDraft.value,
|
|
36688
|
+
autoFocus: true,
|
|
36689
|
+
"aria-label": label,
|
|
36690
|
+
className: "h-8 w-full",
|
|
36691
|
+
onChange: (e) => setFieldDraft({ name, value: e.target.value }),
|
|
36692
|
+
onBlur: () => commitField(name, fieldDraft.value.trim(), raw),
|
|
36693
|
+
onKeyDown: (e) => {
|
|
36694
|
+
if (e.key === "Enter") {
|
|
36695
|
+
e.preventDefault();
|
|
36696
|
+
commitField(name, fieldDraft.value.trim(), raw);
|
|
36697
|
+
} else if (e.key === "Escape") {
|
|
36698
|
+
e.preventDefault();
|
|
36699
|
+
setFieldDraft(null);
|
|
36700
|
+
}
|
|
36701
|
+
},
|
|
36702
|
+
"data-testid": `document-property-input-${name}`
|
|
36726
36703
|
}
|
|
36727
36704
|
);
|
|
36728
|
-
}
|
|
36729
|
-
|
|
36705
|
+
}
|
|
36706
|
+
const shown = raw === void 0 || raw === null || raw === "" ? "\u2014" : relationLabel(raw) ?? formatValue(raw, field.format);
|
|
36707
|
+
return /* @__PURE__ */ jsx(
|
|
36708
|
+
Box,
|
|
36709
|
+
{
|
|
36710
|
+
role: "button",
|
|
36711
|
+
tabIndex: 0,
|
|
36712
|
+
className: cn(
|
|
36713
|
+
"cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
36714
|
+
(raw === void 0 || raw === null || raw === "") && "text-muted-foreground"
|
|
36715
|
+
),
|
|
36716
|
+
onClick: () => setFieldDraft({ name, value: raw !== void 0 && raw !== null ? String(raw) : "" }),
|
|
36717
|
+
onKeyDown: (e) => {
|
|
36718
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
36719
|
+
e.preventDefault();
|
|
36720
|
+
setFieldDraft({ name, value: raw !== void 0 && raw !== null ? String(raw) : "" });
|
|
36721
|
+
}
|
|
36722
|
+
},
|
|
36723
|
+
"data-testid": `document-property-${name}`,
|
|
36724
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "break-words", children: shown })
|
|
36725
|
+
}
|
|
36726
|
+
);
|
|
36727
|
+
};
|
|
36728
|
+
return /* @__PURE__ */ jsx(Card, { variant: "bordered", className: cn("w-full", className), children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "p-4", children: [
|
|
36729
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", weight: "medium", className: "uppercase tracking-wide", children: title ?? (t("documentDetails.title") || "Details") }),
|
|
36730
|
+
/* @__PURE__ */ jsx(VStack, { gap: "sm", children: fieldDefs.map((field) => {
|
|
36731
|
+
const name = fieldName(field);
|
|
36732
|
+
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
36733
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
36734
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
36735
|
+
field.icon && renderIconInput5(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
36736
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: label })
|
|
36737
|
+
] }),
|
|
36738
|
+
/* @__PURE__ */ jsx(Box, { className: "min-w-0", children: renderValue(field) })
|
|
36739
|
+
] }, name);
|
|
36740
|
+
}) })
|
|
36741
|
+
] }) });
|
|
36742
|
+
}
|
|
36743
|
+
var init_DocumentDetails = __esm({
|
|
36744
|
+
"components/core/molecules/DocumentDetails.tsx"() {
|
|
36745
|
+
"use client";
|
|
36746
|
+
init_cn();
|
|
36747
|
+
init_format();
|
|
36748
|
+
init_getNestedValue();
|
|
36749
|
+
init_useEventBus();
|
|
36750
|
+
init_Box();
|
|
36751
|
+
init_Stack();
|
|
36752
|
+
init_Typography();
|
|
36753
|
+
init_Badge();
|
|
36754
|
+
init_Card();
|
|
36755
|
+
init_Icon();
|
|
36756
|
+
init_Input();
|
|
36757
|
+
init_Select();
|
|
36758
|
+
init_Switch();
|
|
36730
36759
|
}
|
|
36731
36760
|
});
|
|
36732
36761
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
@@ -41675,8 +41704,8 @@ var init_DataTable = __esm({
|
|
|
41675
41704
|
DataTable.displayName = "DataTable";
|
|
41676
41705
|
}
|
|
41677
41706
|
});
|
|
41678
|
-
function getBadgeVariant(
|
|
41679
|
-
const name =
|
|
41707
|
+
function getBadgeVariant(fieldName2, value) {
|
|
41708
|
+
const name = fieldName2.toLowerCase();
|
|
41680
41709
|
const val = String(value).toLowerCase();
|
|
41681
41710
|
if (name.includes("status")) {
|
|
41682
41711
|
if (val.includes("complete") || val.includes("done") || val.includes("active"))
|
|
@@ -41692,12 +41721,12 @@ function getBadgeVariant(fieldName, value) {
|
|
|
41692
41721
|
}
|
|
41693
41722
|
return "default";
|
|
41694
41723
|
}
|
|
41695
|
-
function formatFieldValue2(value,
|
|
41724
|
+
function formatFieldValue2(value, fieldName2) {
|
|
41696
41725
|
if (typeof value === "number") {
|
|
41697
|
-
if (
|
|
41726
|
+
if (fieldName2.toLowerCase().includes("progress") || fieldName2.toLowerCase().includes("percent")) {
|
|
41698
41727
|
return `${value}%`;
|
|
41699
41728
|
}
|
|
41700
|
-
if (
|
|
41729
|
+
if (fieldName2.toLowerCase().includes("budget") || fieldName2.toLowerCase().includes("cost")) {
|
|
41701
41730
|
return `$${value.toLocaleString()}`;
|
|
41702
41731
|
}
|
|
41703
41732
|
return value.toLocaleString();
|
|
@@ -41707,7 +41736,7 @@ function formatFieldValue2(value, fieldName) {
|
|
|
41707
41736
|
}
|
|
41708
41737
|
return String(value);
|
|
41709
41738
|
}
|
|
41710
|
-
function renderRichFieldValue(value,
|
|
41739
|
+
function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
41711
41740
|
if (value === void 0 || value === null) return "\u2014";
|
|
41712
41741
|
const str = String(value);
|
|
41713
41742
|
switch (fieldType) {
|
|
@@ -41718,7 +41747,7 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
|
|
|
41718
41747
|
"img",
|
|
41719
41748
|
{
|
|
41720
41749
|
src: str,
|
|
41721
|
-
alt: formatFieldLabel(
|
|
41750
|
+
alt: formatFieldLabel(fieldName2),
|
|
41722
41751
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
41723
41752
|
loading: "lazy"
|
|
41724
41753
|
}
|
|
@@ -41853,9 +41882,9 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
|
|
|
41853
41882
|
return /* @__PURE__ */ jsx("a", { href: `tel:${str}`, className: "text-primary hover:underline", children: str });
|
|
41854
41883
|
default:
|
|
41855
41884
|
if (meta?.values && meta.values.length > 0 && meta.values.includes(str)) {
|
|
41856
|
-
return /* @__PURE__ */ jsx(Badge, { variant: getBadgeVariant(
|
|
41885
|
+
return /* @__PURE__ */ jsx(Badge, { variant: getBadgeVariant(fieldName2, str), children: humanizeEnumValue(str) });
|
|
41857
41886
|
}
|
|
41858
|
-
return formatFieldValue2(value,
|
|
41887
|
+
return formatFieldValue2(value, fieldName2);
|
|
41859
41888
|
}
|
|
41860
41889
|
}
|
|
41861
41890
|
function normalizeFieldDefs(fields) {
|
|
@@ -42325,16 +42354,11 @@ var init_DetailPanel = __esm({
|
|
|
42325
42354
|
footer
|
|
42326
42355
|
] })
|
|
42327
42356
|
] }) });
|
|
42328
|
-
|
|
42329
|
-
Box,
|
|
42330
|
-
|
|
42331
|
-
|
|
42332
|
-
|
|
42333
|
-
className
|
|
42334
|
-
),
|
|
42335
|
-
children: content
|
|
42336
|
-
}
|
|
42337
|
-
);
|
|
42357
|
+
if (!slideOver) {
|
|
42358
|
+
return /* @__PURE__ */ jsx(Box, { className, children: content });
|
|
42359
|
+
}
|
|
42360
|
+
const panel = /* @__PURE__ */ jsx(Box, { className: cn("fixed inset-y-0 right-0 w-full max-w-2xl bg-card shadow-lg z-50 overflow-y-auto p-6", className), children: content });
|
|
42361
|
+
return typeof document === "undefined" ? panel : createPortal(panel, document.body);
|
|
42338
42362
|
};
|
|
42339
42363
|
DetailPanel.displayName = "DetailPanel";
|
|
42340
42364
|
}
|
|
@@ -42703,7 +42727,21 @@ var init_Form = __esm({
|
|
|
42703
42727
|
const normalizedInitialData = React85__default.useMemo(() => {
|
|
42704
42728
|
const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
|
|
42705
42729
|
const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
|
|
42706
|
-
|
|
42730
|
+
const merged = entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
|
|
42731
|
+
const toId = (value) => {
|
|
42732
|
+
if (value === null || value === void 0 || typeof value !== "object" || value instanceof Date) return value;
|
|
42733
|
+
if (Array.isArray(value)) {
|
|
42734
|
+
return value.map(
|
|
42735
|
+
(item) => item !== null && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && item.id !== void 0 && item.id !== null ? String(item.id) : item
|
|
42736
|
+
);
|
|
42737
|
+
}
|
|
42738
|
+
return value.id !== void 0 && value.id !== null ? String(value.id) : value;
|
|
42739
|
+
};
|
|
42740
|
+
const normalized = {};
|
|
42741
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
42742
|
+
normalized[key] = key === "id" ? value : toId(value);
|
|
42743
|
+
}
|
|
42744
|
+
return normalized;
|
|
42707
42745
|
}, [entity, initialData]);
|
|
42708
42746
|
const entityDerivedFields = React85__default.useMemo(() => {
|
|
42709
42747
|
if (fields && fields.length > 0) return void 0;
|
|
@@ -42832,8 +42870,8 @@ var init_Form = __esm({
|
|
|
42832
42870
|
checkViolations(name, newFormData);
|
|
42833
42871
|
};
|
|
42834
42872
|
const isFieldVisible = React85__default.useCallback(
|
|
42835
|
-
(
|
|
42836
|
-
const condition = conditionalFields[
|
|
42873
|
+
(fieldName2) => {
|
|
42874
|
+
const condition = conditionalFields[fieldName2];
|
|
42837
42875
|
if (!condition) return true;
|
|
42838
42876
|
return Boolean(evaluateFormExpression(condition, evalContext));
|
|
42839
42877
|
},
|
|
@@ -42879,9 +42917,9 @@ var init_Form = __esm({
|
|
|
42879
42917
|
};
|
|
42880
42918
|
const handleInvalid = (e) => {
|
|
42881
42919
|
const target = e.target;
|
|
42882
|
-
const
|
|
42920
|
+
const fieldName2 = target.getAttribute("data-field-name") ?? target.name ?? "";
|
|
42883
42921
|
const fieldMessage = target.validationMessage || "Invalid value";
|
|
42884
|
-
debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
|
|
42922
|
+
debug("forms", "invalid", { mode: formMode, fieldName: fieldName2, fieldMessage });
|
|
42885
42923
|
queueMicrotask(() => {
|
|
42886
42924
|
const form = formRef.current;
|
|
42887
42925
|
if (!form) return;
|
|
@@ -42917,22 +42955,22 @@ var init_Form = __esm({
|
|
|
42917
42955
|
};
|
|
42918
42956
|
const renderField = React85__default.useCallback(
|
|
42919
42957
|
(field) => {
|
|
42920
|
-
const
|
|
42921
|
-
if (!
|
|
42922
|
-
if (!isFieldVisible(
|
|
42958
|
+
const fieldName2 = field.name || field.field;
|
|
42959
|
+
if (!fieldName2) return null;
|
|
42960
|
+
if (!isFieldVisible(fieldName2)) {
|
|
42923
42961
|
return null;
|
|
42924
42962
|
}
|
|
42925
42963
|
const inputType = determineInputType(field);
|
|
42926
|
-
const label = field.label ||
|
|
42927
|
-
const currentValue = formData[
|
|
42928
|
-
return /* @__PURE__ */ jsxs(VStack, { gap: "xs", "data-field":
|
|
42964
|
+
const label = field.label || fieldName2.charAt(0).toUpperCase() + fieldName2.slice(1).replace(/([A-Z])/g, " $1");
|
|
42965
|
+
const currentValue = formData[fieldName2] ?? field.defaultValue ?? "";
|
|
42966
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "xs", "data-field": fieldName2, children: [
|
|
42929
42967
|
inputType !== "checkbox" && /* @__PURE__ */ jsxs(Typography, { as: "label", variant: "label", weight: "bold", children: [
|
|
42930
42968
|
label,
|
|
42931
42969
|
field.required && /* @__PURE__ */ jsx(Typography, { as: "span", color: "error", className: "ml-1", children: "*" })
|
|
42932
42970
|
] }),
|
|
42933
|
-
renderFieldInput(field,
|
|
42971
|
+
renderFieldInput(field, fieldName2, inputType, currentValue, label),
|
|
42934
42972
|
field.hint && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: field.hint })
|
|
42935
|
-
] },
|
|
42973
|
+
] }, fieldName2);
|
|
42936
42974
|
},
|
|
42937
42975
|
[formData, isFieldVisible, relationsData, relationsLoading, isLoading]
|
|
42938
42976
|
);
|
|
@@ -42961,8 +42999,8 @@ var init_Form = __esm({
|
|
|
42961
42999
|
}
|
|
42962
43000
|
return field;
|
|
42963
43001
|
}).map((field) => {
|
|
42964
|
-
const
|
|
42965
|
-
const override = fieldOverrides?.find((o) => o.name ===
|
|
43002
|
+
const fieldName2 = field.name || field.field;
|
|
43003
|
+
const override = fieldOverrides?.find((o) => o.name === fieldName2);
|
|
42966
43004
|
if (!override) return field;
|
|
42967
43005
|
return {
|
|
42968
43006
|
...field,
|
|
@@ -43018,11 +43056,11 @@ var init_Form = __esm({
|
|
|
43018
43056
|
] }, section.id);
|
|
43019
43057
|
}).filter(Boolean);
|
|
43020
43058
|
}, [sections, isSectionVisible, collapsedSections, renderField, gap]);
|
|
43021
|
-
function renderFieldInput(field,
|
|
43059
|
+
function renderFieldInput(field, fieldName2, inputType, currentValue, label) {
|
|
43022
43060
|
const commonProps = {
|
|
43023
|
-
id:
|
|
43024
|
-
name:
|
|
43025
|
-
"data-field-name":
|
|
43061
|
+
id: fieldName2,
|
|
43062
|
+
name: fieldName2,
|
|
43063
|
+
"data-field-name": fieldName2,
|
|
43026
43064
|
required: field.required,
|
|
43027
43065
|
disabled: isLoading,
|
|
43028
43066
|
placeholder: field.placeholder,
|
|
@@ -43036,7 +43074,7 @@ var init_Form = __esm({
|
|
|
43036
43074
|
...commonProps,
|
|
43037
43075
|
label: label + (field.required ? " *" : ""),
|
|
43038
43076
|
checked: Boolean(currentValue),
|
|
43039
|
-
onChange: (e) => handleChange(
|
|
43077
|
+
onChange: (e) => handleChange(fieldName2, e.target.checked)
|
|
43040
43078
|
}
|
|
43041
43079
|
);
|
|
43042
43080
|
case "textarea":
|
|
@@ -43045,7 +43083,7 @@ var init_Form = __esm({
|
|
|
43045
43083
|
{
|
|
43046
43084
|
...commonProps,
|
|
43047
43085
|
value: String(currentValue),
|
|
43048
|
-
onChange: (e) => handleChange(
|
|
43086
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43049
43087
|
minLength: field.min,
|
|
43050
43088
|
maxLength: field.max
|
|
43051
43089
|
}
|
|
@@ -43058,14 +43096,14 @@ var init_Form = __esm({
|
|
|
43058
43096
|
...commonProps,
|
|
43059
43097
|
options,
|
|
43060
43098
|
value: String(currentValue),
|
|
43061
|
-
onValueChange: (v) => handleChange(
|
|
43099
|
+
onValueChange: (v) => handleChange(fieldName2, v),
|
|
43062
43100
|
placeholder: field.placeholder || `Select ${label}...`
|
|
43063
43101
|
}
|
|
43064
43102
|
);
|
|
43065
43103
|
}
|
|
43066
43104
|
case "relation": {
|
|
43067
|
-
const relationOptions = relationsData[
|
|
43068
|
-
const relationLoading = relationsLoading[
|
|
43105
|
+
const relationOptions = relationsData[fieldName2] || [];
|
|
43106
|
+
const relationLoading = relationsLoading[fieldName2] || false;
|
|
43069
43107
|
if (field.relation?.cardinality !== void 0 && MANY_CARDINALITIES.includes(field.relation.cardinality)) {
|
|
43070
43108
|
const selectedValues = Array.isArray(currentValue) ? currentValue.map((v) => String(v)) : [];
|
|
43071
43109
|
return /* @__PURE__ */ jsx(
|
|
@@ -43077,7 +43115,7 @@ var init_Form = __esm({
|
|
|
43077
43115
|
clearable: true,
|
|
43078
43116
|
options: [...relationOptions],
|
|
43079
43117
|
value: selectedValues,
|
|
43080
|
-
onValueChange: (value) => handleChange(
|
|
43118
|
+
onValueChange: (value) => handleChange(fieldName2, Array.isArray(value) ? value : [value]),
|
|
43081
43119
|
placeholder: field.placeholder || `Select ${label}...`
|
|
43082
43120
|
}
|
|
43083
43121
|
);
|
|
@@ -43087,7 +43125,7 @@ var init_Form = __esm({
|
|
|
43087
43125
|
{
|
|
43088
43126
|
...commonProps,
|
|
43089
43127
|
value: currentValue ? String(currentValue) : void 0,
|
|
43090
|
-
onChange: (value) => handleChange(
|
|
43128
|
+
onChange: (value) => handleChange(fieldName2, value),
|
|
43091
43129
|
options: relationOptions,
|
|
43092
43130
|
isLoading: relationLoading,
|
|
43093
43131
|
placeholder: field.placeholder || `Select ${label}...`,
|
|
@@ -43104,7 +43142,7 @@ var init_Form = __esm({
|
|
|
43104
43142
|
placeholder: field.placeholder,
|
|
43105
43143
|
disabled: isLoading,
|
|
43106
43144
|
value: arrayValue,
|
|
43107
|
-
onChange: (next) => handleChange(
|
|
43145
|
+
onChange: (next) => handleChange(fieldName2, [...next])
|
|
43108
43146
|
}
|
|
43109
43147
|
);
|
|
43110
43148
|
}
|
|
@@ -43116,7 +43154,7 @@ var init_Form = __esm({
|
|
|
43116
43154
|
type: "number",
|
|
43117
43155
|
value: currentValue !== void 0 && currentValue !== "" ? String(currentValue) : "",
|
|
43118
43156
|
onChange: (e) => handleChange(
|
|
43119
|
-
|
|
43157
|
+
fieldName2,
|
|
43120
43158
|
e.target.value ? Number(e.target.value) : void 0
|
|
43121
43159
|
),
|
|
43122
43160
|
min: field.min,
|
|
@@ -43133,7 +43171,7 @@ var init_Form = __esm({
|
|
|
43133
43171
|
icon: DollarSign,
|
|
43134
43172
|
value: currentValue !== void 0 && currentValue !== "" ? String(currentValue) : "",
|
|
43135
43173
|
onChange: (e) => handleChange(
|
|
43136
|
-
|
|
43174
|
+
fieldName2,
|
|
43137
43175
|
e.target.value ? Number(e.target.value) : void 0
|
|
43138
43176
|
),
|
|
43139
43177
|
min: field.min,
|
|
@@ -43151,7 +43189,7 @@ var init_Form = __esm({
|
|
|
43151
43189
|
const f3 = files[0];
|
|
43152
43190
|
if (!f3) return;
|
|
43153
43191
|
const reader = new FileReader();
|
|
43154
|
-
reader.onload = () => handleChange(
|
|
43192
|
+
reader.onload = () => handleChange(fieldName2, {
|
|
43155
43193
|
name: f3.name,
|
|
43156
43194
|
mimeType: f3.type,
|
|
43157
43195
|
sizeBytes: f3.size,
|
|
@@ -43168,7 +43206,7 @@ var init_Form = __esm({
|
|
|
43168
43206
|
...commonProps,
|
|
43169
43207
|
type: "date",
|
|
43170
43208
|
value: formatDateValue(currentValue),
|
|
43171
|
-
onChange: (e) => handleChange(
|
|
43209
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
43172
43210
|
}
|
|
43173
43211
|
);
|
|
43174
43212
|
case "datetime-local":
|
|
@@ -43178,7 +43216,7 @@ var init_Form = __esm({
|
|
|
43178
43216
|
...commonProps,
|
|
43179
43217
|
type: "datetime-local",
|
|
43180
43218
|
value: formatDateTimeValue(currentValue),
|
|
43181
|
-
onChange: (e) => handleChange(
|
|
43219
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
43182
43220
|
}
|
|
43183
43221
|
);
|
|
43184
43222
|
case "email":
|
|
@@ -43188,7 +43226,7 @@ var init_Form = __esm({
|
|
|
43188
43226
|
...commonProps,
|
|
43189
43227
|
type: "email",
|
|
43190
43228
|
value: String(currentValue),
|
|
43191
|
-
onChange: (e) => handleChange(
|
|
43229
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43192
43230
|
minLength: field.min,
|
|
43193
43231
|
maxLength: field.max
|
|
43194
43232
|
}
|
|
@@ -43200,7 +43238,7 @@ var init_Form = __esm({
|
|
|
43200
43238
|
...commonProps,
|
|
43201
43239
|
type: "url",
|
|
43202
43240
|
value: String(currentValue),
|
|
43203
|
-
onChange: (e) => handleChange(
|
|
43241
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43204
43242
|
minLength: field.min,
|
|
43205
43243
|
maxLength: field.max
|
|
43206
43244
|
}
|
|
@@ -43212,7 +43250,7 @@ var init_Form = __esm({
|
|
|
43212
43250
|
...commonProps,
|
|
43213
43251
|
type: "password",
|
|
43214
43252
|
value: String(currentValue),
|
|
43215
|
-
onChange: (e) => handleChange(
|
|
43253
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43216
43254
|
minLength: field.min,
|
|
43217
43255
|
maxLength: field.max
|
|
43218
43256
|
}
|
|
@@ -43225,7 +43263,7 @@ var init_Form = __esm({
|
|
|
43225
43263
|
...commonProps,
|
|
43226
43264
|
type: "text",
|
|
43227
43265
|
value: String(currentValue),
|
|
43228
|
-
onChange: (e) => handleChange(
|
|
43266
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43229
43267
|
minLength: field.min,
|
|
43230
43268
|
maxLength: field.max
|
|
43231
43269
|
}
|
|
@@ -43582,7 +43620,7 @@ function entityFieldsFromListItem(item) {
|
|
|
43582
43620
|
}
|
|
43583
43621
|
return result;
|
|
43584
43622
|
}
|
|
43585
|
-
function getStatusStyle(
|
|
43623
|
+
function getStatusStyle(fieldName2, value) {
|
|
43586
43624
|
const val = String(value).toLowerCase();
|
|
43587
43625
|
if (val.includes("complete") || val.includes("done"))
|
|
43588
43626
|
return STATUS_STYLES.complete;
|
|
@@ -43598,12 +43636,12 @@ function getStatusStyle(fieldName, value) {
|
|
|
43598
43636
|
if (val.includes("low")) return STATUS_STYLES.low;
|
|
43599
43637
|
return STATUS_STYLES.default;
|
|
43600
43638
|
}
|
|
43601
|
-
function formatValue3(value,
|
|
43639
|
+
function formatValue3(value, fieldName2) {
|
|
43602
43640
|
if (typeof value === "number") {
|
|
43603
|
-
if (
|
|
43641
|
+
if (fieldName2.toLowerCase().includes("progress") || fieldName2.toLowerCase().includes("percent")) {
|
|
43604
43642
|
return `${value}%`;
|
|
43605
43643
|
}
|
|
43606
|
-
if (
|
|
43644
|
+
if (fieldName2.toLowerCase().includes("budget") || fieldName2.toLowerCase().includes("cost")) {
|
|
43607
43645
|
return new Intl.NumberFormat("en-US", {
|
|
43608
43646
|
style: "currency",
|
|
43609
43647
|
currency: "USD",
|
|
@@ -43626,8 +43664,8 @@ function formatValue3(value, fieldName) {
|
|
|
43626
43664
|
}
|
|
43627
43665
|
return String(value);
|
|
43628
43666
|
}
|
|
43629
|
-
function formatFieldLabel2(
|
|
43630
|
-
return humanizeFieldName(
|
|
43667
|
+
function formatFieldLabel2(fieldName2) {
|
|
43668
|
+
return humanizeFieldName(fieldName2).replace(/\sId$/, "").trim();
|
|
43631
43669
|
}
|
|
43632
43670
|
var STATUS_STYLES, StatusBadge, ProgressIndicator, List3;
|
|
43633
43671
|
var init_List = __esm({
|
|
@@ -43695,9 +43733,9 @@ var init_List = __esm({
|
|
|
43695
43733
|
};
|
|
43696
43734
|
StatusBadge = ({
|
|
43697
43735
|
value,
|
|
43698
|
-
fieldName
|
|
43736
|
+
fieldName: fieldName2
|
|
43699
43737
|
}) => {
|
|
43700
|
-
const style = getStatusStyle(
|
|
43738
|
+
const style = getStatusStyle(fieldName2, value);
|
|
43701
43739
|
return /* @__PURE__ */ jsxs(
|
|
43702
43740
|
Typography,
|
|
43703
43741
|
{
|
|
@@ -46629,8 +46667,8 @@ var init_StatCard = __esm({
|
|
|
46629
46667
|
return items.length;
|
|
46630
46668
|
}
|
|
46631
46669
|
if (field.includes(":")) {
|
|
46632
|
-
const [
|
|
46633
|
-
return items.filter((item) => item[
|
|
46670
|
+
const [fieldName2, fieldValue] = field.split(":");
|
|
46671
|
+
return items.filter((item) => item[fieldName2] === fieldValue).length;
|
|
46634
46672
|
}
|
|
46635
46673
|
const fieldExistsOnItems = items.some((item) => field in item);
|
|
46636
46674
|
if (fieldExistsOnItems) {
|
|
@@ -48150,6 +48188,8 @@ var init_component_registry_generated = __esm({
|
|
|
48150
48188
|
init_DocSearch();
|
|
48151
48189
|
init_DocSidebar();
|
|
48152
48190
|
init_DocTOC();
|
|
48191
|
+
init_DocumentDetails();
|
|
48192
|
+
init_DocumentPanel();
|
|
48153
48193
|
init_DocumentViewer();
|
|
48154
48194
|
init_DrawFxLayer();
|
|
48155
48195
|
init_DrawGroup();
|
|
@@ -48259,7 +48299,7 @@ var init_component_registry_generated = __esm({
|
|
|
48259
48299
|
init_RelationSelect();
|
|
48260
48300
|
init_RepeatableFormSection();
|
|
48261
48301
|
init_ReplyTree();
|
|
48262
|
-
|
|
48302
|
+
init_RichTextEditor();
|
|
48263
48303
|
init_RuntimeDebugger2();
|
|
48264
48304
|
init_ScaledDiagram();
|
|
48265
48305
|
init_ScoreDisplay();
|
|
@@ -48422,6 +48462,8 @@ var init_component_registry_generated = __esm({
|
|
|
48422
48462
|
"DocSearch": DocSearch,
|
|
48423
48463
|
"DocSidebar": DocSidebar,
|
|
48424
48464
|
"DocTOC": DocTOC,
|
|
48465
|
+
"DocumentDetails": DocumentDetails,
|
|
48466
|
+
"DocumentPanel": DocumentPanel,
|
|
48425
48467
|
"DocumentViewer": DocumentViewer,
|
|
48426
48468
|
"DrawFxLayer": DrawFxLayer,
|
|
48427
48469
|
"DrawGroup": DrawGroup,
|
|
@@ -48533,7 +48575,7 @@ var init_component_registry_generated = __esm({
|
|
|
48533
48575
|
"RelationSelect": RelationSelect,
|
|
48534
48576
|
"RepeatableFormSection": RepeatableFormSection,
|
|
48535
48577
|
"ReplyTree": ReplyTree,
|
|
48536
|
-
"
|
|
48578
|
+
"RichTextEditor": RichTextEditor,
|
|
48537
48579
|
"RuntimeDebugger": RuntimeDebugger,
|
|
48538
48580
|
"ScaledDiagram": ScaledDiagram,
|
|
48539
48581
|
"ScoreDisplay": ScoreDisplay,
|
|
@@ -48687,10 +48729,10 @@ function enrichFormFields(fields, entityDef) {
|
|
|
48687
48729
|
}
|
|
48688
48730
|
if (field && typeof field === "object" && !Array.isArray(field) && !React85__default.isValidElement(field) && !(field instanceof Date)) {
|
|
48689
48731
|
const obj = field;
|
|
48690
|
-
const
|
|
48691
|
-
if (!
|
|
48732
|
+
const fieldName2 = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
|
|
48733
|
+
if (!fieldName2) return field;
|
|
48692
48734
|
if (obj.type || obj.inputType) return field;
|
|
48693
|
-
const entityField = fieldMap.get(
|
|
48735
|
+
const entityField = fieldMap.get(fieldName2);
|
|
48694
48736
|
if (!entityField) return field;
|
|
48695
48737
|
const enriched = { ...obj, type: entityField.type };
|
|
48696
48738
|
if (entityField.required && !("required" in obj)) {
|
|
@@ -48740,9 +48782,9 @@ function enrichDetailFields(fields, entityDef) {
|
|
|
48740
48782
|
}
|
|
48741
48783
|
if (field && typeof field === "object" && !Array.isArray(field) && !React85__default.isValidElement(field) && !(field instanceof Date)) {
|
|
48742
48784
|
const obj = field;
|
|
48743
|
-
const
|
|
48744
|
-
if (!
|
|
48745
|
-
const meta = metaFor(
|
|
48785
|
+
const fieldName2 = typeof obj.key === "string" ? obj.key : typeof obj.name === "string" ? obj.name : void 0;
|
|
48786
|
+
if (!fieldName2 || obj.type) return field;
|
|
48787
|
+
const meta = metaFor(fieldName2);
|
|
48746
48788
|
return meta ? { ...obj, ...meta } : field;
|
|
48747
48789
|
}
|
|
48748
48790
|
return field;
|
|
@@ -49581,9 +49623,9 @@ function UISlotRenderer({
|
|
|
49581
49623
|
"ui-slot-renderer relative min-h-full",
|
|
49582
49624
|
className
|
|
49583
49625
|
), children: [
|
|
49584
|
-
/* @__PURE__ */ jsxs(Box, { className: "flex min-h-full", children: [
|
|
49585
|
-
/* @__PURE__ */ jsx(UISlotComponent, { slot: "sidebar", className: "ui-slot-sidebar min-w-0 shrink-0" }),
|
|
49586
|
-
/* @__PURE__ */ jsx(UISlotComponent, { slot: "main", className: "ui-slot-main flex-1 min-h-[200px]" })
|
|
49626
|
+
/* @__PURE__ */ jsxs(Box, { className: "flex min-h-full flex-col lg:flex-row", children: [
|
|
49627
|
+
/* @__PURE__ */ jsx(UISlotComponent, { slot: "sidebar", className: "ui-slot-sidebar min-w-0 lg:shrink-0" }),
|
|
49628
|
+
/* @__PURE__ */ jsx(UISlotComponent, { slot: "main", className: "ui-slot-main flex-1 min-w-0 min-h-[200px]" })
|
|
49587
49629
|
] }),
|
|
49588
49630
|
/* @__PURE__ */ jsx(UISlotComponent, { slot: "modal", portal: true }),
|
|
49589
49631
|
/* @__PURE__ */ jsx(UISlotComponent, { slot: "drawer", portal: true }),
|
|
@@ -50106,7 +50148,7 @@ function buildTraitRenderConfig(binding, traitConfigsByName, payload) {
|
|
|
50106
50148
|
}
|
|
50107
50149
|
return void 0;
|
|
50108
50150
|
}
|
|
50109
|
-
function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
|
|
50151
|
+
function createSharedEntityWriter(binding, tick, traitStatesRef, emit, traitConfigsByName) {
|
|
50110
50152
|
return (scratch) => {
|
|
50111
50153
|
const traitName = binding.trait.name;
|
|
50112
50154
|
const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
|
|
@@ -50115,9 +50157,13 @@ function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
|
|
|
50115
50157
|
const writes = [];
|
|
50116
50158
|
const ctx = createMinimalContext(scratchEntity, {}, currentState);
|
|
50117
50159
|
const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
|
|
50118
|
-
const
|
|
50119
|
-
|
|
50120
|
-
|
|
50160
|
+
const resolvedByName = traitConfigsByName?.[traitName];
|
|
50161
|
+
const callSiteRaw = getBindingConfig(binding);
|
|
50162
|
+
const callSiteConfig = callSiteRaw ? Object.fromEntries(
|
|
50163
|
+
Object.entries(callSiteRaw).filter(([, v]) => !containsConfigForward(v))
|
|
50164
|
+
) : void 0;
|
|
50165
|
+
if (declaredDefaults || resolvedByName || callSiteConfig) {
|
|
50166
|
+
ctx.config = { ...declaredDefaults ?? {}, ...resolvedByName ?? {}, ...callSiteConfig ?? {} };
|
|
50121
50167
|
}
|
|
50122
50168
|
ctx.mutateEntity = (changes) => {
|
|
50123
50169
|
for (const [field, value] of Object.entries(changes)) {
|
|
@@ -50720,7 +50766,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50720
50766
|
const interval = entries[0].tick.interval;
|
|
50721
50767
|
const onDue = timedTick(`tick:shared:${group.storeKey}@${String(interval)}`, () => {
|
|
50722
50768
|
const writers = entries.map(
|
|
50723
|
-
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
|
|
50769
|
+
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter, traitConfigsByName)
|
|
50724
50770
|
);
|
|
50725
50771
|
runTickFrame(group.storeKey, writers, sharedEntityStore);
|
|
50726
50772
|
});
|