@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/providers/index.js
CHANGED
|
@@ -8,7 +8,7 @@ export { ANONYMOUS_USER } from '@almadar/core';
|
|
|
8
8
|
import { clsx } from 'clsx';
|
|
9
9
|
import { twMerge } from 'tailwind-merge';
|
|
10
10
|
import * as LucideIcons2 from 'lucide-react';
|
|
11
|
-
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,
|
|
11
|
+
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';
|
|
12
12
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
13
13
|
import { createPortal } from 'react-dom';
|
|
14
14
|
import { useTranslate } from '@almadar/ui/hooks';
|
|
@@ -26264,8 +26264,9 @@ function DataGrid({
|
|
|
26264
26264
|
const titleField = fieldDefs.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fieldDefs[0];
|
|
26265
26265
|
const badgeFields = fieldDefs.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
26266
26266
|
const bodyFields = fieldDefs.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
|
|
26267
|
-
const
|
|
26268
|
-
const
|
|
26267
|
+
const inlineCap = Math.min(maxInlineActions ?? 1, 1);
|
|
26268
|
+
const inlineCardActions = actionDefs.filter((a) => a.variant === "primary").slice(0, inlineCap);
|
|
26269
|
+
const menuCardActions = actionDefs.filter((a) => !inlineCardActions.includes(a));
|
|
26269
26270
|
const fireAction = (action, itemData) => {
|
|
26270
26271
|
if (action.navigatesTo) {
|
|
26271
26272
|
const url = action.navigatesTo.replace(
|
|
@@ -26285,6 +26286,9 @@ function DataGrid({
|
|
|
26285
26286
|
e.stopPropagation();
|
|
26286
26287
|
fireAction(action, itemData);
|
|
26287
26288
|
};
|
|
26289
|
+
const cardClickAction = actionDefs.find((a) => a.variant !== "danger");
|
|
26290
|
+
const handleCardClick = cardClickAction ? (itemData) => () => fireAction(cardClickAction, itemData) : void 0;
|
|
26291
|
+
const stopCardClick = handleCardClick ? (e) => e.stopPropagation() : void 0;
|
|
26288
26292
|
const hasRenderProp = typeof children === "function";
|
|
26289
26293
|
useEffect(() => {
|
|
26290
26294
|
if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
|
|
@@ -26356,55 +26360,40 @@ function DataGrid({
|
|
|
26356
26360
|
{
|
|
26357
26361
|
"data-entity-row": true,
|
|
26358
26362
|
"data-entity-id": id,
|
|
26359
|
-
|
|
26363
|
+
onClick: handleCardClick?.(itemData),
|
|
26364
|
+
className: cn("relative group/rowactions", handleCardClick && "cursor-pointer", isSelected && "ring-2 ring-primary rounded-lg"),
|
|
26360
26365
|
children: [
|
|
26361
26366
|
children(itemData, index),
|
|
26362
|
-
actionDefs.length > 0 && /* @__PURE__ */
|
|
26363
|
-
/* @__PURE__ */ jsxs(
|
|
26364
|
-
|
|
26365
|
-
|
|
26366
|
-
|
|
26367
|
-
|
|
26368
|
-
|
|
26369
|
-
|
|
26370
|
-
|
|
26371
|
-
|
|
26372
|
-
|
|
26373
|
-
|
|
26374
|
-
|
|
26375
|
-
|
|
26376
|
-
|
|
26377
|
-
|
|
26378
|
-
|
|
26379
|
-
)),
|
|
26380
|
-
maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
|
|
26381
|
-
Menu,
|
|
26382
|
-
{
|
|
26383
|
-
position: "bottom-end",
|
|
26384
|
-
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" }) }),
|
|
26385
|
-
items: actionDefs.slice(maxInlineActions).map((action) => ({
|
|
26386
|
-
label: action.label,
|
|
26387
|
-
icon: action.icon,
|
|
26388
|
-
event: action.event,
|
|
26389
|
-
onClick: () => fireAction(action, itemData)
|
|
26390
|
-
}))
|
|
26391
|
-
}
|
|
26392
|
-
)
|
|
26393
|
-
] }),
|
|
26394
|
-
/* @__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(
|
|
26367
|
+
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: [
|
|
26368
|
+
inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
26369
|
+
Button,
|
|
26370
|
+
{
|
|
26371
|
+
variant: "primary",
|
|
26372
|
+
size: "sm",
|
|
26373
|
+
onClick: handleActionClick(action, itemData),
|
|
26374
|
+
"data-testid": `action-${action.event}`,
|
|
26375
|
+
"data-row-id": String(itemData.id),
|
|
26376
|
+
children: [
|
|
26377
|
+
action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
|
|
26378
|
+
action.label
|
|
26379
|
+
]
|
|
26380
|
+
},
|
|
26381
|
+
idx
|
|
26382
|
+
)),
|
|
26383
|
+
menuCardActions.length > 0 && /* @__PURE__ */ jsx(
|
|
26395
26384
|
Menu,
|
|
26396
26385
|
{
|
|
26397
26386
|
position: "bottom-end",
|
|
26398
26387
|
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" }) }),
|
|
26399
|
-
items:
|
|
26388
|
+
items: menuCardActions.map((action) => ({
|
|
26400
26389
|
label: action.label,
|
|
26401
26390
|
icon: action.icon,
|
|
26402
|
-
|
|
26391
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
26403
26392
|
onClick: () => fireAction(action, itemData)
|
|
26404
26393
|
}))
|
|
26405
26394
|
}
|
|
26406
|
-
)
|
|
26407
|
-
] })
|
|
26395
|
+
)
|
|
26396
|
+
] }) })
|
|
26408
26397
|
]
|
|
26409
26398
|
},
|
|
26410
26399
|
id
|
|
@@ -26418,12 +26407,14 @@ function DataGrid({
|
|
|
26418
26407
|
{
|
|
26419
26408
|
"data-entity-row": true,
|
|
26420
26409
|
"data-entity-id": id,
|
|
26410
|
+
onClick: handleCardClick?.(itemData),
|
|
26421
26411
|
className: cn(
|
|
26422
26412
|
"bg-card rounded-lg",
|
|
26423
26413
|
"border border-border",
|
|
26424
26414
|
"shadow-elevation-card hover:shadow-elevation-dialog",
|
|
26425
26415
|
"hover:border-primary transition-all",
|
|
26426
26416
|
"flex flex-col",
|
|
26417
|
+
handleCardClick && "cursor-pointer",
|
|
26427
26418
|
isSelected && "ring-2 ring-primary border-primary"
|
|
26428
26419
|
),
|
|
26429
26420
|
children: [
|
|
@@ -26473,53 +26464,35 @@ function DataGrid({
|
|
|
26473
26464
|
] }, field.name);
|
|
26474
26465
|
}) })
|
|
26475
26466
|
] }),
|
|
26476
|
-
|
|
26477
|
-
|
|
26467
|
+
actionDefs.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", onClick: stopCardClick, className: "flex-shrink-0", children: [
|
|
26468
|
+
inlineCardActions.map((action, idx) => /* @__PURE__ */ jsx(
|
|
26478
26469
|
Button,
|
|
26479
26470
|
{
|
|
26480
|
-
variant:
|
|
26471
|
+
variant: "primary",
|
|
26481
26472
|
size: "sm",
|
|
26482
26473
|
onClick: handleActionClick(action, itemData),
|
|
26483
26474
|
"data-testid": `action-${action.event}`,
|
|
26484
26475
|
"data-row-id": String(itemData.id),
|
|
26485
26476
|
"aria-label": action.label,
|
|
26486
26477
|
title: action.label,
|
|
26487
|
-
className: cn(
|
|
26488
|
-
action.variant === "primary" ? void 0 : "text-muted-foreground hover:text-foreground",
|
|
26489
|
-
action.icon && "px-2"
|
|
26490
|
-
),
|
|
26478
|
+
className: cn(action.icon && "px-2"),
|
|
26491
26479
|
children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
|
|
26492
26480
|
},
|
|
26493
26481
|
idx
|
|
26494
26482
|
)),
|
|
26495
|
-
|
|
26483
|
+
menuCardActions.length > 0 && /* @__PURE__ */ jsx(
|
|
26496
26484
|
Menu,
|
|
26497
26485
|
{
|
|
26498
26486
|
position: "bottom-end",
|
|
26499
26487
|
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" }) }),
|
|
26500
|
-
items:
|
|
26488
|
+
items: menuCardActions.map((action) => ({
|
|
26501
26489
|
label: action.label,
|
|
26502
26490
|
icon: action.icon,
|
|
26503
|
-
|
|
26491
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
26504
26492
|
onClick: () => fireAction(action, itemData)
|
|
26505
26493
|
}))
|
|
26506
26494
|
}
|
|
26507
|
-
)
|
|
26508
|
-
dangerActions.map((action, idx) => /* @__PURE__ */ jsx(
|
|
26509
|
-
Button,
|
|
26510
|
-
{
|
|
26511
|
-
variant: "ghost",
|
|
26512
|
-
size: "sm",
|
|
26513
|
-
onClick: handleActionClick(action, itemData),
|
|
26514
|
-
"data-testid": `action-${action.event}`,
|
|
26515
|
-
"data-row-id": String(itemData.id),
|
|
26516
|
-
"aria-label": action.label,
|
|
26517
|
-
title: action.label,
|
|
26518
|
-
className: "text-error hover:text-error hover:bg-error/10 px-2",
|
|
26519
|
-
children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
|
|
26520
|
-
},
|
|
26521
|
-
`danger-${idx}`
|
|
26522
|
-
))
|
|
26495
|
+
)
|
|
26523
26496
|
] })
|
|
26524
26497
|
] }) }),
|
|
26525
26498
|
bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 pt-2 pb-4 flex-1", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
@@ -26540,8 +26513,8 @@ function DataGrid({
|
|
|
26540
26513
|
}
|
|
26541
26514
|
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
26542
26515
|
field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
26543
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
26544
|
-
/* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue(value, field.format) })
|
|
26516
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "sr-only", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
26517
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: formatValue(value, field.format) })
|
|
26545
26518
|
] }, field.name);
|
|
26546
26519
|
}) })
|
|
26547
26520
|
] }) })
|
|
@@ -26761,54 +26734,59 @@ function DataList({
|
|
|
26761
26734
|
if (!itemActions || itemActions.length === 0) return null;
|
|
26762
26735
|
const inline = maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions;
|
|
26763
26736
|
const overflow = maxInlineActions != null ? itemActions.slice(maxInlineActions) : [];
|
|
26764
|
-
return
|
|
26765
|
-
|
|
26766
|
-
|
|
26767
|
-
|
|
26768
|
-
|
|
26769
|
-
|
|
26770
|
-
|
|
26771
|
-
|
|
26772
|
-
|
|
26773
|
-
|
|
26774
|
-
action
|
|
26775
|
-
|
|
26776
|
-
|
|
26777
|
-
|
|
26778
|
-
|
|
26779
|
-
|
|
26780
|
-
|
|
26781
|
-
|
|
26782
|
-
|
|
26783
|
-
|
|
26784
|
-
|
|
26785
|
-
|
|
26786
|
-
|
|
26787
|
-
|
|
26788
|
-
|
|
26789
|
-
|
|
26790
|
-
|
|
26791
|
-
|
|
26792
|
-
|
|
26793
|
-
|
|
26794
|
-
|
|
26795
|
-
|
|
26796
|
-
|
|
26797
|
-
|
|
26798
|
-
|
|
26799
|
-
|
|
26800
|
-
|
|
26801
|
-
|
|
26802
|
-
|
|
26803
|
-
|
|
26737
|
+
return (
|
|
26738
|
+
// stopPropagation at the cluster: the "⋯" trigger opens the overflow
|
|
26739
|
+
// menu without also firing the row's default click (inline buttons
|
|
26740
|
+
// already stop it in handleActionClick; the Menu panel is portaled).
|
|
26741
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", onClick: rowClickEvent ? (e) => e.stopPropagation() : void 0, className: "flex-shrink-0", children: [
|
|
26742
|
+
inline.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
26743
|
+
Button,
|
|
26744
|
+
{
|
|
26745
|
+
variant: action.variant ?? "ghost",
|
|
26746
|
+
size: "sm",
|
|
26747
|
+
onClick: handleActionClick(action, itemData),
|
|
26748
|
+
"data-testid": `action-${action.event}`,
|
|
26749
|
+
"data-row-id": String(itemData.id),
|
|
26750
|
+
className: cn(
|
|
26751
|
+
action.variant === "danger" && "text-error hover:bg-error/10",
|
|
26752
|
+
// Must sit on the Button itself: the variant's own text colour
|
|
26753
|
+
// beats an inherited one from the row wrapper.
|
|
26754
|
+
onPrimary && "!text-primary-foreground hover:bg-primary-foreground/15"
|
|
26755
|
+
),
|
|
26756
|
+
children: [
|
|
26757
|
+
action.icon && renderIconInput2(action.icon, { size: "xs", className: "mr-1" }),
|
|
26758
|
+
action.label
|
|
26759
|
+
]
|
|
26760
|
+
},
|
|
26761
|
+
idx
|
|
26762
|
+
)),
|
|
26763
|
+
overflow.length > 0 && /* @__PURE__ */ jsx(
|
|
26764
|
+
Menu,
|
|
26765
|
+
{
|
|
26766
|
+
position: "bottom-end",
|
|
26767
|
+
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" }) }),
|
|
26768
|
+
items: overflow.map((action) => ({
|
|
26769
|
+
label: action.label,
|
|
26770
|
+
icon: action.icon,
|
|
26771
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
26772
|
+
onClick: () => eventBus.emit(`UI:${action.event}`, {
|
|
26773
|
+
id: itemData.id,
|
|
26774
|
+
row: itemData
|
|
26775
|
+
})
|
|
26776
|
+
}))
|
|
26777
|
+
}
|
|
26778
|
+
)
|
|
26779
|
+
] })
|
|
26780
|
+
);
|
|
26804
26781
|
};
|
|
26782
|
+
const rowClickEvent = itemClickEvent || itemActions?.find((a) => a.variant !== "danger")?.event;
|
|
26805
26783
|
const handleRowClick = (itemData) => () => {
|
|
26806
|
-
if (!
|
|
26784
|
+
if (!rowClickEvent) return;
|
|
26807
26785
|
const payload = {
|
|
26808
26786
|
id: itemData.id,
|
|
26809
26787
|
row: itemData
|
|
26810
26788
|
};
|
|
26811
|
-
eventBus.emit(`UI:${
|
|
26789
|
+
eventBus.emit(`UI:${rowClickEvent}`, payload);
|
|
26812
26790
|
};
|
|
26813
26791
|
if (isLoading) {
|
|
26814
26792
|
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") }) });
|
|
@@ -26856,10 +26834,10 @@ function DataList({
|
|
|
26856
26834
|
{
|
|
26857
26835
|
"data-entity-row": true,
|
|
26858
26836
|
"data-entity-id": id,
|
|
26859
|
-
onClick:
|
|
26837
|
+
onClick: rowClickEvent ? handleRowClick(itemData) : void 0,
|
|
26860
26838
|
className: cn(
|
|
26861
26839
|
"flex px-4 group/rowactions",
|
|
26862
|
-
|
|
26840
|
+
rowClickEvent && "cursor-pointer",
|
|
26863
26841
|
isSent ? "justify-end" : "justify-start"
|
|
26864
26842
|
),
|
|
26865
26843
|
children: /* @__PURE__ */ jsxs(
|
|
@@ -26935,7 +26913,7 @@ function DataList({
|
|
|
26935
26913
|
const id2 = itemData.id || String(index);
|
|
26936
26914
|
const actions = renderItemActions(itemData);
|
|
26937
26915
|
return wrapDnd(
|
|
26938
|
-
/* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick:
|
|
26916
|
+
/* @__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: [
|
|
26939
26917
|
children(itemData, index),
|
|
26940
26918
|
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: [
|
|
26941
26919
|
/* @__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 }),
|
|
@@ -26947,7 +26925,6 @@ function DataList({
|
|
|
26947
26925
|
items: (itemActions ?? []).map((action) => ({
|
|
26948
26926
|
label: action.label,
|
|
26949
26927
|
icon: action.icon,
|
|
26950
|
-
event: action.event,
|
|
26951
26928
|
variant: action.variant === "danger" ? "danger" : "default",
|
|
26952
26929
|
onClick: () => eventBus.emit(`UI:${action.event}`, {
|
|
26953
26930
|
id: itemData.id,
|
|
@@ -26964,12 +26941,16 @@ function DataList({
|
|
|
26964
26941
|
const id = itemData.id || String(index);
|
|
26965
26942
|
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
26966
26943
|
return wrapDnd(
|
|
26967
|
-
/* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id, onClick:
|
|
26944
|
+
/* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id, onClick: rowClickEvent ? handleRowClick(itemData) : void 0, className: cn(rowClickEvent && "cursor-pointer"), children: [
|
|
26968
26945
|
/* @__PURE__ */ jsxs(
|
|
26969
26946
|
Box,
|
|
26970
26947
|
{
|
|
26971
26948
|
className: cn(
|
|
26972
|
-
|
|
26949
|
+
// items-start, not items-center: a multi-line row (title + meta +
|
|
26950
|
+
// progress) centred its action cluster in the vertical middle, so
|
|
26951
|
+
// the buttons floated between the meta fields instead of anchoring
|
|
26952
|
+
// to the title they act on (U-DATALIST-ACTIONS-FLOAT-MID-ROW).
|
|
26953
|
+
"group flex items-start gap-4 transition-all duration-fast",
|
|
26973
26954
|
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
26974
26955
|
"hover:bg-muted/80",
|
|
26975
26956
|
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
@@ -27000,11 +26981,19 @@ function DataList({
|
|
|
27000
26981
|
if (value === void 0 || value === null || value === "") return null;
|
|
27001
26982
|
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
27002
26983
|
field.icon && renderIconInput2(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
27003
|
-
/* @__PURE__ */ jsxs(
|
|
27004
|
-
|
|
27005
|
-
|
|
27006
|
-
|
|
27007
|
-
|
|
26984
|
+
/* @__PURE__ */ jsxs(
|
|
26985
|
+
Typography,
|
|
26986
|
+
{
|
|
26987
|
+
variant: "caption",
|
|
26988
|
+
color: "secondary",
|
|
26989
|
+
className: cn(field.format !== "boolean" && "sr-only"),
|
|
26990
|
+
children: [
|
|
26991
|
+
field.label ?? fieldLabel3(field.name),
|
|
26992
|
+
":"
|
|
26993
|
+
]
|
|
26994
|
+
}
|
|
26995
|
+
),
|
|
26996
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: formatValue2(value, field.format, { yes: t("common.yes"), no: t("common.no") }) })
|
|
27008
26997
|
] }, field.name);
|
|
27009
26998
|
}) }),
|
|
27010
26999
|
progressFields.map((field) => {
|
|
@@ -27023,7 +27012,7 @@ function DataList({
|
|
|
27023
27012
|
]
|
|
27024
27013
|
}
|
|
27025
27014
|
),
|
|
27026
|
-
isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "
|
|
27015
|
+
(isCard || isCompact) && !isLast && /* @__PURE__ */ jsx(Box, { className: cn("border-b border-border/40", isCompact ? "mx-4" : "mx-6") })
|
|
27027
27016
|
] }, id)
|
|
27028
27017
|
);
|
|
27029
27018
|
};
|
|
@@ -27033,7 +27022,13 @@ function DataList({
|
|
|
27033
27022
|
{
|
|
27034
27023
|
className: cn(
|
|
27035
27024
|
isCard && "bg-card rounded-xl border border-border shadow-elevation-dialog overflow-hidden",
|
|
27036
|
-
|
|
27025
|
+
// `gap-*` is inert on a block container, and Box only emits a display
|
|
27026
|
+
// class when its `display` prop is set — so every non-card list had
|
|
27027
|
+
// been asking for a gap that CSS silently dropped. flex-col makes it
|
|
27028
|
+
// real. `compact` keeps gap-0 on purpose: it separates with the row
|
|
27029
|
+
// divider above instead, never both (Almadar_UI_Beauty.md 6).
|
|
27030
|
+
!isCard && "flex flex-col",
|
|
27031
|
+
!isCard && !isCompact && gapClass,
|
|
27037
27032
|
listLookStyles[look],
|
|
27038
27033
|
className
|
|
27039
27034
|
),
|
|
@@ -32222,7 +32217,7 @@ var init_MapView = __esm({
|
|
|
32222
32217
|
shadowSize: [41, 41]
|
|
32223
32218
|
});
|
|
32224
32219
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
32225
|
-
const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback97, useState:
|
|
32220
|
+
const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback97, useState: useState97 } = React87__default;
|
|
32226
32221
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
32227
32222
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
32228
32223
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -32267,7 +32262,7 @@ var init_MapView = __esm({
|
|
|
32267
32262
|
showAttribution = true
|
|
32268
32263
|
}) {
|
|
32269
32264
|
const eventBus = useEventBus2();
|
|
32270
|
-
const [clickedPosition, setClickedPosition] =
|
|
32265
|
+
const [clickedPosition, setClickedPosition] = useState97(null);
|
|
32271
32266
|
const handleMapClick = useCallback97((lat, lng) => {
|
|
32272
32267
|
if (showClickedPin) {
|
|
32273
32268
|
setClickedPosition({ lat, lng });
|
|
@@ -36629,741 +36624,775 @@ var init_PositionedCanvas = __esm({
|
|
|
36629
36624
|
PositionedCanvas.displayName = "PositionedCanvas";
|
|
36630
36625
|
}
|
|
36631
36626
|
});
|
|
36632
|
-
function
|
|
36633
|
-
|
|
36634
|
-
|
|
36635
|
-
|
|
36636
|
-
|
|
36637
|
-
|
|
36638
|
-
if (!Array.isArray(raw) || raw.length === 0) return [createBlock("paragraph")];
|
|
36639
|
-
return raw.map((row) => {
|
|
36640
|
-
const entity = row;
|
|
36641
|
-
const rawType = entity.type;
|
|
36642
|
-
const type = typeof rawType === "string" && BLOCK_TYPES.has(rawType) ? rawType : "paragraph";
|
|
36643
|
-
const id = typeof entity.id === "string" && entity.id ? entity.id : nextBlockId(type);
|
|
36644
|
-
return { ...entity, id, type };
|
|
36645
|
-
});
|
|
36646
|
-
}
|
|
36647
|
-
function createBlock(type) {
|
|
36648
|
-
switch (type) {
|
|
36649
|
-
case "bullet-list":
|
|
36650
|
-
case "numbered-list":
|
|
36651
|
-
return {
|
|
36652
|
-
id: nextBlockId(type),
|
|
36653
|
-
type,
|
|
36654
|
-
children: [
|
|
36655
|
-
{ id: nextBlockId("li"), type: "paragraph", content: "" }
|
|
36656
|
-
]
|
|
36657
|
-
};
|
|
36658
|
-
case "image":
|
|
36659
|
-
return {
|
|
36660
|
-
id: nextBlockId(type),
|
|
36661
|
-
type,
|
|
36662
|
-
content: "",
|
|
36663
|
-
metadata: { url: "", caption: "" }
|
|
36664
|
-
};
|
|
36665
|
-
case "code":
|
|
36666
|
-
return {
|
|
36667
|
-
id: nextBlockId(type),
|
|
36668
|
-
type,
|
|
36669
|
-
content: "",
|
|
36670
|
-
metadata: { language: "plaintext" }
|
|
36671
|
-
};
|
|
36672
|
-
case "divider":
|
|
36673
|
-
return { id: nextBlockId(type), type };
|
|
36674
|
-
default:
|
|
36675
|
-
return { id: nextBlockId(type), type, content: "" };
|
|
36627
|
+
function safeUrl(raw, kinds) {
|
|
36628
|
+
const url = raw.trim();
|
|
36629
|
+
if (url.startsWith("#") || url.startsWith("/")) return url;
|
|
36630
|
+
const lower = url.toLowerCase();
|
|
36631
|
+
for (const kind of kinds) {
|
|
36632
|
+
if (lower.startsWith(kind)) return url;
|
|
36676
36633
|
}
|
|
36634
|
+
return null;
|
|
36677
36635
|
}
|
|
36678
|
-
function
|
|
36679
|
-
|
|
36680
|
-
|
|
36681
|
-
|
|
36682
|
-
|
|
36683
|
-
|
|
36684
|
-
|
|
36685
|
-
return {
|
|
36686
|
-
...block,
|
|
36687
|
-
id: nextBlockId(block.type),
|
|
36688
|
-
children: block.children?.map((child) => ({
|
|
36689
|
-
...child,
|
|
36690
|
-
id: nextBlockId("li")
|
|
36691
|
-
})),
|
|
36692
|
-
metadata: block.metadata ? { ...block.metadata } : void 0
|
|
36693
|
-
};
|
|
36694
|
-
}
|
|
36695
|
-
function insertAfter(blocks, targetId, inserted) {
|
|
36696
|
-
const idx = blocks.findIndex((b) => b.id === targetId);
|
|
36697
|
-
if (idx === -1) return [...blocks, inserted];
|
|
36698
|
-
const next = blocks.slice();
|
|
36699
|
-
next.splice(idx + 1, 0, inserted);
|
|
36700
|
-
return next;
|
|
36701
|
-
}
|
|
36702
|
-
function changeBlockType(block, type) {
|
|
36703
|
-
if (block.type === type) return block;
|
|
36704
|
-
if (type === "bullet-list" || type === "numbered-list") {
|
|
36705
|
-
if (block.children && block.children.length > 0) {
|
|
36706
|
-
return { ...block, type };
|
|
36636
|
+
function sanitizeNode(el) {
|
|
36637
|
+
const children = Array.from(el.children);
|
|
36638
|
+
for (const child of children) {
|
|
36639
|
+
const tag = child.tagName.toLowerCase();
|
|
36640
|
+
if (DROP_TAGS.has(tag)) {
|
|
36641
|
+
child.remove();
|
|
36642
|
+
continue;
|
|
36707
36643
|
}
|
|
36708
|
-
const
|
|
36709
|
-
|
|
36710
|
-
|
|
36711
|
-
|
|
36712
|
-
|
|
36713
|
-
|
|
36714
|
-
|
|
36715
|
-
|
|
36716
|
-
|
|
36717
|
-
|
|
36718
|
-
|
|
36644
|
+
const allowed = ALLOWED_ATTRS[tag];
|
|
36645
|
+
if (!allowed) {
|
|
36646
|
+
sanitizeNode(child);
|
|
36647
|
+
child.replaceWith(...Array.from(child.childNodes));
|
|
36648
|
+
continue;
|
|
36649
|
+
}
|
|
36650
|
+
for (const attr of Array.from(child.attributes)) {
|
|
36651
|
+
const name = attr.name.toLowerCase();
|
|
36652
|
+
if (!allowed.includes(name)) {
|
|
36653
|
+
child.removeAttribute(attr.name);
|
|
36654
|
+
continue;
|
|
36655
|
+
}
|
|
36656
|
+
if (name === "href") {
|
|
36657
|
+
const url = safeUrl(attr.value, ["http://", "https://", "mailto:"]);
|
|
36658
|
+
if (url === null) child.removeAttribute(attr.name);
|
|
36659
|
+
else child.setAttribute("href", url);
|
|
36660
|
+
}
|
|
36661
|
+
if (name === "src") {
|
|
36662
|
+
const url = safeUrl(attr.value, ["http://", "https://", "data:image/"]);
|
|
36663
|
+
if (url === null) child.remove();
|
|
36664
|
+
else child.setAttribute("src", url);
|
|
36665
|
+
}
|
|
36666
|
+
}
|
|
36667
|
+
sanitizeNode(child);
|
|
36719
36668
|
}
|
|
36720
|
-
|
|
36721
|
-
|
|
36722
|
-
|
|
36723
|
-
|
|
36724
|
-
|
|
36725
|
-
|
|
36726
|
-
|
|
36669
|
+
}
|
|
36670
|
+
function sanitizeRichHtml(html) {
|
|
36671
|
+
if (!html || typeof html !== "string") return "";
|
|
36672
|
+
if (typeof window === "undefined" || typeof DOMParser === "undefined") return "";
|
|
36673
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
36674
|
+
sanitizeNode(doc.body);
|
|
36675
|
+
if (!doc.body.querySelector("img, hr") && (doc.body.textContent ?? "").trim().length === 0) {
|
|
36676
|
+
return "";
|
|
36727
36677
|
}
|
|
36728
|
-
|
|
36729
|
-
|
|
36730
|
-
|
|
36731
|
-
|
|
36732
|
-
|
|
36733
|
-
|
|
36734
|
-
|
|
36678
|
+
return doc.body.innerHTML.replace(//g, "");
|
|
36679
|
+
}
|
|
36680
|
+
function htmlIsEmpty(el) {
|
|
36681
|
+
if (el.querySelector("img, hr")) return false;
|
|
36682
|
+
return (el.textContent ?? "").trim().length === 0;
|
|
36683
|
+
}
|
|
36684
|
+
function closestBlock(node, root) {
|
|
36685
|
+
let cur = node;
|
|
36686
|
+
while (cur && cur !== root) {
|
|
36687
|
+
if (cur instanceof Element && BLOCK_TAGS.has(cur.tagName)) return cur;
|
|
36688
|
+
cur = cur.parentNode;
|
|
36735
36689
|
}
|
|
36736
|
-
|
|
36737
|
-
return { id: block.id, type, content: seed };
|
|
36690
|
+
return null;
|
|
36738
36691
|
}
|
|
36739
|
-
function
|
|
36740
|
-
|
|
36741
|
-
|
|
36742
|
-
|
|
36743
|
-
|
|
36744
|
-
|
|
36745
|
-
|
|
36746
|
-
|
|
36747
|
-
|
|
36692
|
+
function RichTextStyles() {
|
|
36693
|
+
return /* @__PURE__ */ jsx("style", { children: RICH_TEXT_CSS });
|
|
36694
|
+
}
|
|
36695
|
+
function readToolbarState(root) {
|
|
36696
|
+
const sel = window.getSelection();
|
|
36697
|
+
if (!sel || sel.rangeCount === 0) return IDLE_TOOLBAR;
|
|
36698
|
+
const anchor = sel.anchorNode;
|
|
36699
|
+
if (!anchor || !root.contains(anchor)) return IDLE_TOOLBAR;
|
|
36700
|
+
let block = null;
|
|
36701
|
+
let link = false;
|
|
36702
|
+
let node = anchor;
|
|
36703
|
+
while (node && node !== root) {
|
|
36704
|
+
if (node instanceof Element) {
|
|
36705
|
+
const tag = node.tagName.toLowerCase();
|
|
36706
|
+
if (!block && (tag === "h1" || tag === "h2" || tag === "h3" || tag === "blockquote" || tag === "pre")) {
|
|
36707
|
+
block = tag;
|
|
36748
36708
|
}
|
|
36709
|
+
if (tag === "a") link = true;
|
|
36749
36710
|
}
|
|
36750
|
-
|
|
36751
|
-
|
|
36752
|
-
|
|
36753
|
-
|
|
36754
|
-
|
|
36755
|
-
|
|
36756
|
-
|
|
36757
|
-
|
|
36758
|
-
|
|
36759
|
-
|
|
36760
|
-
|
|
36761
|
-
|
|
36762
|
-
"inline-flex items-center justify-center",
|
|
36763
|
-
"h-6 w-6 rounded-sm p-0 gap-0",
|
|
36764
|
-
"text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
36765
|
-
"opacity-0 group-hover:opacity-100 focus-visible:opacity-100",
|
|
36766
|
-
"transition-opacity"
|
|
36767
|
-
),
|
|
36768
|
-
onClick: () => setOpen((v) => !v),
|
|
36769
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", className: "w-3.5 h-3.5" })
|
|
36770
|
-
}
|
|
36771
|
-
),
|
|
36772
|
-
open && /* @__PURE__ */ jsxs(
|
|
36773
|
-
Box,
|
|
36774
|
-
{
|
|
36775
|
-
role: "menu",
|
|
36776
|
-
className: cn(
|
|
36777
|
-
"absolute right-0 z-10 mt-1 w-44",
|
|
36778
|
-
"rounded-container border border-border bg-popover shadow-elevation-popover",
|
|
36779
|
-
"py-1 text-sm"
|
|
36780
|
-
),
|
|
36781
|
-
children: [
|
|
36782
|
-
/* @__PURE__ */ jsx(Box, { className: "px-2 py-1 text-xs uppercase tracking-wide text-muted-foreground", children: t(BLOCK_TYPE_LABEL_KEY[block.type]) }),
|
|
36783
|
-
/* @__PURE__ */ jsxs(
|
|
36784
|
-
Button,
|
|
36785
|
-
{
|
|
36786
|
-
type: "button",
|
|
36787
|
-
variant: "ghost",
|
|
36788
|
-
role: "menuitem",
|
|
36789
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left justify-start rounded-none",
|
|
36790
|
-
onClick: () => {
|
|
36791
|
-
onDuplicate();
|
|
36792
|
-
setOpen(false);
|
|
36793
|
-
},
|
|
36794
|
-
children: [
|
|
36795
|
-
/* @__PURE__ */ jsx(Icon, { name: "plus", className: "w-3.5 h-3.5" }),
|
|
36796
|
-
" ",
|
|
36797
|
-
t("richBlockEditor.duplicate")
|
|
36798
|
-
]
|
|
36799
|
-
}
|
|
36800
|
-
),
|
|
36801
|
-
/* @__PURE__ */ jsxs(
|
|
36802
|
-
Button,
|
|
36803
|
-
{
|
|
36804
|
-
type: "button",
|
|
36805
|
-
variant: "ghost",
|
|
36806
|
-
role: "menuitem",
|
|
36807
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left text-destructive hover:bg-muted justify-start rounded-none",
|
|
36808
|
-
onClick: () => {
|
|
36809
|
-
onDelete();
|
|
36810
|
-
setOpen(false);
|
|
36811
|
-
},
|
|
36812
|
-
children: [
|
|
36813
|
-
/* @__PURE__ */ jsx(Icon, { name: "trash", className: "w-3.5 h-3.5" }),
|
|
36814
|
-
" ",
|
|
36815
|
-
t("common.delete")
|
|
36816
|
-
]
|
|
36817
|
-
}
|
|
36818
|
-
),
|
|
36819
|
-
CHANGEABLE_TYPES.includes(block.type) && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36820
|
-
/* @__PURE__ */ jsx(Box, { className: "my-1 border-t border-border" }),
|
|
36821
|
-
/* @__PURE__ */ jsx(Box, { className: "px-2 py-1 text-xs uppercase tracking-wide text-muted-foreground", children: t("richBlockEditor.turnInto") }),
|
|
36822
|
-
CHANGEABLE_TYPES.filter((bt) => bt !== block.type).map((bt) => /* @__PURE__ */ jsx(
|
|
36823
|
-
Button,
|
|
36824
|
-
{
|
|
36825
|
-
type: "button",
|
|
36826
|
-
variant: "ghost",
|
|
36827
|
-
role: "menuitem",
|
|
36828
|
-
className: "flex w-full items-center gap-2 px-2 py-1.5 text-left justify-start rounded-none",
|
|
36829
|
-
onClick: () => {
|
|
36830
|
-
onChangeType(bt);
|
|
36831
|
-
setOpen(false);
|
|
36832
|
-
},
|
|
36833
|
-
children: t(BLOCK_TYPE_LABEL_KEY[bt])
|
|
36834
|
-
},
|
|
36835
|
-
bt
|
|
36836
|
-
))
|
|
36837
|
-
] })
|
|
36838
|
-
]
|
|
36839
|
-
}
|
|
36840
|
-
)
|
|
36841
|
-
] });
|
|
36711
|
+
node = node.parentNode;
|
|
36712
|
+
}
|
|
36713
|
+
return {
|
|
36714
|
+
bold: document.queryCommandState("bold"),
|
|
36715
|
+
italic: document.queryCommandState("italic"),
|
|
36716
|
+
underline: document.queryCommandState("underline"),
|
|
36717
|
+
strikeThrough: document.queryCommandState("strikeThrough"),
|
|
36718
|
+
block,
|
|
36719
|
+
bullets: document.queryCommandState("insertUnorderedList"),
|
|
36720
|
+
numbers: document.queryCommandState("insertOrderedList"),
|
|
36721
|
+
link
|
|
36722
|
+
};
|
|
36842
36723
|
}
|
|
36843
|
-
function
|
|
36844
|
-
tag,
|
|
36845
|
-
value,
|
|
36846
|
-
readOnly,
|
|
36847
|
-
placeholder,
|
|
36848
|
-
className,
|
|
36849
|
-
ariaLabel,
|
|
36850
|
-
onValueChange
|
|
36851
|
-
}) {
|
|
36852
|
-
const ref = useRef(null);
|
|
36853
|
-
useEffect(() => {
|
|
36854
|
-
const el = ref.current;
|
|
36855
|
-
if (!el) return;
|
|
36856
|
-
const isFocused = document.activeElement === el;
|
|
36857
|
-
if (!isFocused && el.textContent !== value) {
|
|
36858
|
-
el.textContent = value;
|
|
36859
|
-
}
|
|
36860
|
-
}, [value]);
|
|
36861
|
-
const handleInput = useCallback(
|
|
36862
|
-
(e) => {
|
|
36863
|
-
onValueChange(e.currentTarget.textContent ?? "");
|
|
36864
|
-
},
|
|
36865
|
-
[onValueChange]
|
|
36866
|
-
);
|
|
36724
|
+
function ToolbarButton({ icon: IconCmp, label, active, onExec }) {
|
|
36867
36725
|
return /* @__PURE__ */ jsx(
|
|
36868
|
-
|
|
36726
|
+
Button,
|
|
36869
36727
|
{
|
|
36870
|
-
|
|
36871
|
-
|
|
36872
|
-
|
|
36873
|
-
|
|
36874
|
-
|
|
36875
|
-
|
|
36876
|
-
"aria-multiline": "true",
|
|
36877
|
-
"data-placeholder": placeholder,
|
|
36728
|
+
type: "button",
|
|
36729
|
+
variant: "ghost",
|
|
36730
|
+
size: "sm",
|
|
36731
|
+
"aria-label": label,
|
|
36732
|
+
"aria-pressed": active,
|
|
36733
|
+
title: label,
|
|
36878
36734
|
className: cn(
|
|
36879
|
-
"
|
|
36880
|
-
"
|
|
36881
|
-
className
|
|
36735
|
+
"h-8 w-8 p-0 gap-0 justify-center",
|
|
36736
|
+
active && "bg-muted text-foreground"
|
|
36882
36737
|
),
|
|
36883
|
-
|
|
36738
|
+
onMouseDown: (e) => {
|
|
36739
|
+
e.preventDefault();
|
|
36740
|
+
onExec();
|
|
36741
|
+
},
|
|
36742
|
+
children: /* @__PURE__ */ jsx(IconCmp, { size: 15 })
|
|
36884
36743
|
}
|
|
36885
36744
|
);
|
|
36886
36745
|
}
|
|
36887
|
-
|
|
36888
|
-
|
|
36889
|
-
|
|
36890
|
-
|
|
36891
|
-
|
|
36892
|
-
|
|
36893
|
-
|
|
36894
|
-
|
|
36895
|
-
|
|
36896
|
-
|
|
36897
|
-
|
|
36898
|
-
|
|
36899
|
-
|
|
36900
|
-
|
|
36901
|
-
|
|
36902
|
-
|
|
36903
|
-
|
|
36904
|
-
|
|
36905
|
-
|
|
36906
|
-
|
|
36907
|
-
|
|
36908
|
-
|
|
36909
|
-
|
|
36910
|
-
|
|
36911
|
-
|
|
36912
|
-
|
|
36913
|
-
|
|
36914
|
-
|
|
36915
|
-
|
|
36916
|
-
|
|
36917
|
-
|
|
36918
|
-
|
|
36919
|
-
|
|
36920
|
-
|
|
36921
|
-
|
|
36922
|
-
|
|
36923
|
-
|
|
36924
|
-
|
|
36925
|
-
|
|
36926
|
-
|
|
36927
|
-
|
|
36928
|
-
|
|
36929
|
-
|
|
36930
|
-
|
|
36931
|
-
|
|
36932
|
-
|
|
36933
|
-
|
|
36934
|
-
|
|
36935
|
-
|
|
36936
|
-
|
|
36937
|
-
|
|
36938
|
-
|
|
36939
|
-
|
|
36940
|
-
|
|
36941
|
-
|
|
36942
|
-
|
|
36943
|
-
|
|
36944
|
-
|
|
36945
|
-
|
|
36946
|
-
|
|
36947
|
-
|
|
36948
|
-
|
|
36949
|
-
|
|
36950
|
-
|
|
36951
|
-
|
|
36952
|
-
|
|
36953
|
-
|
|
36954
|
-
|
|
36955
|
-
|
|
36956
|
-
|
|
36957
|
-
|
|
36958
|
-
|
|
36959
|
-
|
|
36960
|
-
|
|
36961
|
-
|
|
36962
|
-
|
|
36963
|
-
|
|
36964
|
-
|
|
36965
|
-
|
|
36966
|
-
|
|
36967
|
-
|
|
36968
|
-
|
|
36969
|
-
|
|
36970
|
-
|
|
36971
|
-
|
|
36972
|
-
|
|
36973
|
-
|
|
36974
|
-
|
|
36975
|
-
|
|
36976
|
-
|
|
36977
|
-
|
|
36978
|
-
|
|
36979
|
-
|
|
36980
|
-
|
|
36981
|
-
|
|
36982
|
-
|
|
36983
|
-
|
|
36984
|
-
|
|
36985
|
-
|
|
36986
|
-
|
|
36987
|
-
|
|
36988
|
-
|
|
36989
|
-
|
|
36990
|
-
|
|
36991
|
-
);
|
|
36992
|
-
|
|
36993
|
-
|
|
36994
|
-
|
|
36995
|
-
|
|
36996
|
-
|
|
36997
|
-
|
|
36998
|
-
|
|
36999
|
-
|
|
37000
|
-
|
|
37001
|
-
|
|
37002
|
-
|
|
37003
|
-
|
|
37004
|
-
|
|
37005
|
-
|
|
37006
|
-
|
|
37007
|
-
|
|
37008
|
-
|
|
37009
|
-
|
|
37010
|
-
|
|
37011
|
-
|
|
37012
|
-
|
|
37013
|
-
|
|
37014
|
-
|
|
37015
|
-
|
|
37016
|
-
|
|
37017
|
-
|
|
37018
|
-
|
|
37019
|
-
|
|
37020
|
-
|
|
37021
|
-
|
|
37022
|
-
|
|
37023
|
-
|
|
37024
|
-
|
|
37025
|
-
|
|
37026
|
-
|
|
37027
|
-
|
|
37028
|
-
|
|
37029
|
-
|
|
37030
|
-
|
|
37031
|
-
|
|
37032
|
-
|
|
36746
|
+
var CHANGE_DEBOUNCE_MS, ALLOWED_ATTRS, DROP_TAGS, MD_BLOCK_PREFIXES, BLOCK_TAGS, MD_INLINE_RULES, RICH_TEXT_CSS, IDLE_TOOLBAR, RichTextEditor;
|
|
36747
|
+
var init_RichTextEditor = __esm({
|
|
36748
|
+
"components/core/molecules/RichTextEditor.tsx"() {
|
|
36749
|
+
"use client";
|
|
36750
|
+
init_cn();
|
|
36751
|
+
init_Box();
|
|
36752
|
+
init_Button();
|
|
36753
|
+
init_useEventBus();
|
|
36754
|
+
CHANGE_DEBOUNCE_MS = 400;
|
|
36755
|
+
ALLOWED_ATTRS = {
|
|
36756
|
+
p: [],
|
|
36757
|
+
h1: [],
|
|
36758
|
+
h2: [],
|
|
36759
|
+
h3: [],
|
|
36760
|
+
h4: [],
|
|
36761
|
+
ul: [],
|
|
36762
|
+
ol: [],
|
|
36763
|
+
li: [],
|
|
36764
|
+
blockquote: [],
|
|
36765
|
+
pre: [],
|
|
36766
|
+
code: [],
|
|
36767
|
+
b: [],
|
|
36768
|
+
strong: [],
|
|
36769
|
+
i: [],
|
|
36770
|
+
em: [],
|
|
36771
|
+
u: [],
|
|
36772
|
+
s: [],
|
|
36773
|
+
strike: [],
|
|
36774
|
+
br: [],
|
|
36775
|
+
hr: [],
|
|
36776
|
+
div: [],
|
|
36777
|
+
span: [],
|
|
36778
|
+
a: ["href"],
|
|
36779
|
+
img: ["src", "alt"]
|
|
36780
|
+
};
|
|
36781
|
+
DROP_TAGS = /* @__PURE__ */ new Set(["script", "style", "iframe", "object", "embed", "link", "meta", "form", "input", "button", "textarea", "select"]);
|
|
36782
|
+
MD_BLOCK_PREFIXES = {
|
|
36783
|
+
"#": { kind: "block", tag: "h1" },
|
|
36784
|
+
"##": { kind: "block", tag: "h2" },
|
|
36785
|
+
"###": { kind: "block", tag: "h3" },
|
|
36786
|
+
">": { kind: "block", tag: "blockquote" },
|
|
36787
|
+
"```": { kind: "block", tag: "pre" },
|
|
36788
|
+
"-": { kind: "list", command: "insertUnorderedList" },
|
|
36789
|
+
"*": { kind: "list", command: "insertUnorderedList" },
|
|
36790
|
+
"1.": { kind: "list", command: "insertOrderedList" }
|
|
36791
|
+
};
|
|
36792
|
+
BLOCK_TAGS = /* @__PURE__ */ new Set(["P", "DIV", "LI", "H1", "H2", "H3", "H4", "BLOCKQUOTE", "PRE"]);
|
|
36793
|
+
MD_INLINE_RULES = [
|
|
36794
|
+
{ pattern: /\*\*([^*\n]+)\*\*$/, wrap: "strong" },
|
|
36795
|
+
{ pattern: /(^|[^*])\*([^*\n]+)\*$/, wrap: "em" },
|
|
36796
|
+
{ pattern: /`([^`\n]+)`$/, wrap: "code" }
|
|
36797
|
+
];
|
|
36798
|
+
RICH_TEXT_CSS = `
|
|
36799
|
+
.almadar-rich-text { line-height: 1.7; color: var(--color-foreground); }
|
|
36800
|
+
.almadar-rich-text h1 { font-size: 1.875rem; font-weight: 700; line-height: 1.25; margin: 1.25em 0 0.4em; }
|
|
36801
|
+
.almadar-rich-text h2 { font-size: 1.5rem; font-weight: 650; line-height: 1.3; margin: 1.1em 0 0.4em; }
|
|
36802
|
+
.almadar-rich-text h3 { font-size: 1.25rem; font-weight: 600; line-height: 1.35; margin: 1em 0 0.35em; }
|
|
36803
|
+
.almadar-rich-text h1:first-child, .almadar-rich-text h2:first-child, .almadar-rich-text h3:first-child { margin-top: 0; }
|
|
36804
|
+
.almadar-rich-text p { margin: 0.5em 0; }
|
|
36805
|
+
.almadar-rich-text ul { list-style: disc; padding-inline-start: 1.5rem; margin: 0.5em 0; }
|
|
36806
|
+
.almadar-rich-text ol { list-style: decimal; padding-inline-start: 1.5rem; margin: 0.5em 0; }
|
|
36807
|
+
.almadar-rich-text li { margin: 0.25em 0; }
|
|
36808
|
+
.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; }
|
|
36809
|
+
.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; }
|
|
36810
|
+
.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; }
|
|
36811
|
+
.almadar-rich-text pre code { background: transparent; padding: 0; }
|
|
36812
|
+
.almadar-rich-text a { color: var(--color-primary); text-decoration: underline; }
|
|
36813
|
+
.almadar-rich-text hr { border: none; border-top: 1px solid var(--color-border); margin: 1.25em 0; }
|
|
36814
|
+
.almadar-rich-text img { max-width: 100%; border-radius: 0.375rem; }
|
|
36815
|
+
`;
|
|
36816
|
+
IDLE_TOOLBAR = {
|
|
36817
|
+
bold: false,
|
|
36818
|
+
italic: false,
|
|
36819
|
+
underline: false,
|
|
36820
|
+
strikeThrough: false,
|
|
36821
|
+
block: null,
|
|
36822
|
+
bullets: false,
|
|
36823
|
+
numbers: false,
|
|
36824
|
+
link: false
|
|
36825
|
+
};
|
|
36826
|
+
RichTextEditor = ({
|
|
36827
|
+
value,
|
|
36828
|
+
onChange,
|
|
36829
|
+
changeEvent,
|
|
36830
|
+
readOnly = false,
|
|
36831
|
+
placeholder,
|
|
36832
|
+
showToolbar = true,
|
|
36833
|
+
className
|
|
36834
|
+
}) => {
|
|
36835
|
+
const { t } = useTranslate();
|
|
36836
|
+
const ref = useRef(null);
|
|
36837
|
+
const [toolbar, setToolbar] = useState(IDLE_TOOLBAR);
|
|
36838
|
+
const [empty, setEmpty] = useState(() => !value || !sanitizeRichHtml(value).trim());
|
|
36839
|
+
const eventBus = useEventBus();
|
|
36840
|
+
const onChangeRef = useRef(onChange);
|
|
36841
|
+
const changeEventRef = useRef(changeEvent);
|
|
36842
|
+
useEffect(() => {
|
|
36843
|
+
onChangeRef.current = onChange;
|
|
36844
|
+
changeEventRef.current = changeEvent;
|
|
36845
|
+
}, [onChange, changeEvent]);
|
|
36846
|
+
const emitTimerRef = useRef(null);
|
|
36847
|
+
const emitNow = useCallback(() => {
|
|
36848
|
+
const el = ref.current;
|
|
36849
|
+
if (!el) return;
|
|
36850
|
+
const html = sanitizeRichHtml(el.innerHTML);
|
|
36851
|
+
onChangeRef.current?.(html);
|
|
36852
|
+
const evt = changeEventRef.current;
|
|
36853
|
+
if (evt) eventBus.emit(`UI:${evt}`, { value: html });
|
|
36854
|
+
}, [eventBus]);
|
|
36855
|
+
const scheduleEmit = useCallback(() => {
|
|
36856
|
+
if (emitTimerRef.current) clearTimeout(emitTimerRef.current);
|
|
36857
|
+
emitTimerRef.current = setTimeout(() => {
|
|
36858
|
+
emitTimerRef.current = null;
|
|
36859
|
+
emitNow();
|
|
36860
|
+
}, CHANGE_DEBOUNCE_MS);
|
|
36861
|
+
}, [emitNow]);
|
|
36862
|
+
const flushEmit = useCallback(() => {
|
|
36863
|
+
if (!emitTimerRef.current) return;
|
|
36864
|
+
clearTimeout(emitTimerRef.current);
|
|
36865
|
+
emitTimerRef.current = null;
|
|
36866
|
+
emitNow();
|
|
36867
|
+
}, [emitNow]);
|
|
36868
|
+
useEffect(() => () => {
|
|
36869
|
+
if (emitTimerRef.current) {
|
|
36870
|
+
clearTimeout(emitTimerRef.current);
|
|
36871
|
+
emitTimerRef.current = null;
|
|
36872
|
+
emitNow();
|
|
36873
|
+
}
|
|
36874
|
+
}, [emitNow]);
|
|
36875
|
+
useEffect(() => {
|
|
36876
|
+
if (readOnly) return;
|
|
36877
|
+
const el = ref.current;
|
|
36878
|
+
if (!el) return;
|
|
36879
|
+
if (document.activeElement === el) return;
|
|
36880
|
+
const next = sanitizeRichHtml(value ?? "") || "<p><br></p>";
|
|
36881
|
+
if (el.innerHTML !== next) {
|
|
36882
|
+
el.innerHTML = next;
|
|
36883
|
+
setEmpty(htmlIsEmpty(el));
|
|
36884
|
+
}
|
|
36885
|
+
}, [readOnly, value]);
|
|
36886
|
+
useEffect(() => {
|
|
36887
|
+
if (readOnly) return;
|
|
36888
|
+
document.execCommand("defaultParagraphSeparator", false, "p");
|
|
36889
|
+
}, [readOnly]);
|
|
36890
|
+
useEffect(() => {
|
|
36891
|
+
if (readOnly || !showToolbar) return;
|
|
36892
|
+
const onSelectionChange = () => {
|
|
36893
|
+
const el = ref.current;
|
|
36894
|
+
if (!el) return;
|
|
36895
|
+
setToolbar(readToolbarState(el));
|
|
37033
36896
|
};
|
|
37034
|
-
|
|
37035
|
-
|
|
37036
|
-
|
|
37037
|
-
|
|
37038
|
-
|
|
37039
|
-
|
|
37040
|
-
|
|
37041
|
-
|
|
37042
|
-
|
|
37043
|
-
|
|
37044
|
-
|
|
37045
|
-
|
|
37046
|
-
|
|
37047
|
-
|
|
37048
|
-
|
|
37049
|
-
|
|
37050
|
-
!
|
|
37051
|
-
|
|
37052
|
-
|
|
37053
|
-
|
|
37054
|
-
|
|
37055
|
-
|
|
37056
|
-
|
|
37057
|
-
|
|
37058
|
-
|
|
37059
|
-
|
|
37060
|
-
|
|
37061
|
-
|
|
37062
|
-
|
|
37063
|
-
|
|
37064
|
-
|
|
37065
|
-
|
|
37066
|
-
|
|
37067
|
-
|
|
37068
|
-
|
|
37069
|
-
|
|
37070
|
-
|
|
37071
|
-
|
|
37072
|
-
|
|
37073
|
-
|
|
37074
|
-
|
|
37075
|
-
|
|
37076
|
-
|
|
37077
|
-
|
|
37078
|
-
|
|
37079
|
-
|
|
37080
|
-
|
|
36897
|
+
document.addEventListener("selectionchange", onSelectionChange);
|
|
36898
|
+
return () => document.removeEventListener("selectionchange", onSelectionChange);
|
|
36899
|
+
}, [readOnly, showToolbar]);
|
|
36900
|
+
const tryInlineMarkdown = useCallback(() => {
|
|
36901
|
+
const root = ref.current;
|
|
36902
|
+
if (!root) return false;
|
|
36903
|
+
const sel = window.getSelection();
|
|
36904
|
+
if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return false;
|
|
36905
|
+
const node = sel.anchorNode;
|
|
36906
|
+
if (!node || node.nodeType !== Node.TEXT_NODE || !root.contains(node)) return false;
|
|
36907
|
+
if (node.parentElement?.closest("code, pre")) return false;
|
|
36908
|
+
const text = (node.textContent ?? "").slice(0, sel.anchorOffset);
|
|
36909
|
+
for (const rule of MD_INLINE_RULES) {
|
|
36910
|
+
const m = rule.pattern.exec(text);
|
|
36911
|
+
if (!m) continue;
|
|
36912
|
+
const inner = rule.wrap === "em" ? m[2] : m[1];
|
|
36913
|
+
if (!inner || !inner.trim()) continue;
|
|
36914
|
+
const lead = rule.wrap === "em" ? m[1]?.length ?? 0 : 0;
|
|
36915
|
+
const range = document.createRange();
|
|
36916
|
+
range.setStart(node, m.index + lead);
|
|
36917
|
+
range.setEnd(node, sel.anchorOffset);
|
|
36918
|
+
const el = document.createElement(rule.wrap);
|
|
36919
|
+
el.textContent = inner;
|
|
36920
|
+
range.deleteContents();
|
|
36921
|
+
range.insertNode(el);
|
|
36922
|
+
const after = document.createTextNode("\u200B");
|
|
36923
|
+
el.parentNode?.insertBefore(after, el.nextSibling);
|
|
36924
|
+
const caret = document.createRange();
|
|
36925
|
+
caret.setStart(after, 1);
|
|
36926
|
+
caret.collapse(true);
|
|
36927
|
+
sel.removeAllRanges();
|
|
36928
|
+
sel.addRange(caret);
|
|
36929
|
+
return true;
|
|
36930
|
+
}
|
|
36931
|
+
return false;
|
|
36932
|
+
}, []);
|
|
36933
|
+
const tryBlockMarkdown = useCallback(() => {
|
|
36934
|
+
const root = ref.current;
|
|
36935
|
+
if (!root) return false;
|
|
36936
|
+
const sel = window.getSelection();
|
|
36937
|
+
if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return false;
|
|
36938
|
+
const node = sel.anchorNode;
|
|
36939
|
+
if (!node || node.nodeType !== Node.TEXT_NODE || !root.contains(node)) return false;
|
|
36940
|
+
const block = closestBlock(node, root);
|
|
36941
|
+
if (block ? block.firstChild !== node : root.firstChild !== node) return false;
|
|
36942
|
+
const prefix = (node.textContent ?? "").slice(0, sel.anchorOffset);
|
|
36943
|
+
const rule = MD_BLOCK_PREFIXES[prefix];
|
|
36944
|
+
if (!rule) return false;
|
|
36945
|
+
if (node.parentElement?.closest("pre, code")) return false;
|
|
36946
|
+
if (rule.kind === "list" && node.parentElement?.closest("li")) return false;
|
|
36947
|
+
node.deleteData(0, prefix.length);
|
|
36948
|
+
const caret = document.createRange();
|
|
36949
|
+
caret.setStart(node, 0);
|
|
36950
|
+
caret.collapse(true);
|
|
36951
|
+
sel.removeAllRanges();
|
|
36952
|
+
sel.addRange(caret);
|
|
36953
|
+
if (rule.kind === "list") {
|
|
36954
|
+
const container = block ?? node.parentElement;
|
|
36955
|
+
const list = document.createElement(rule.command === "insertOrderedList" ? "ol" : "ul");
|
|
36956
|
+
const li = document.createElement("li");
|
|
36957
|
+
if (block) {
|
|
36958
|
+
while (block.firstChild) li.appendChild(block.firstChild);
|
|
36959
|
+
list.appendChild(li);
|
|
36960
|
+
block.replaceWith(list);
|
|
36961
|
+
} else if (container) {
|
|
36962
|
+
li.appendChild(node);
|
|
36963
|
+
list.appendChild(li);
|
|
36964
|
+
container.appendChild(list);
|
|
36965
|
+
}
|
|
36966
|
+
if (!li.firstChild) li.appendChild(document.createElement("br"));
|
|
36967
|
+
const liCaret = document.createRange();
|
|
36968
|
+
liCaret.selectNodeContents(li);
|
|
36969
|
+
liCaret.collapse(true);
|
|
36970
|
+
sel.removeAllRanges();
|
|
36971
|
+
sel.addRange(liCaret);
|
|
36972
|
+
} else {
|
|
36973
|
+
document.execCommand("formatBlock", false, rule.tag);
|
|
36974
|
+
}
|
|
36975
|
+
return true;
|
|
36976
|
+
}, []);
|
|
36977
|
+
const afterEdit = useCallback(() => {
|
|
36978
|
+
const el = ref.current;
|
|
36979
|
+
if (!el) return;
|
|
36980
|
+
tryInlineMarkdown();
|
|
36981
|
+
setEmpty(htmlIsEmpty(el));
|
|
36982
|
+
setToolbar(readToolbarState(el));
|
|
36983
|
+
scheduleEmit();
|
|
36984
|
+
}, [scheduleEmit, tryInlineMarkdown]);
|
|
36985
|
+
const handleKeyDown = useCallback((e) => {
|
|
36986
|
+
if (e.key === " " && tryBlockMarkdown()) {
|
|
36987
|
+
e.preventDefault();
|
|
36988
|
+
afterEdit();
|
|
36989
|
+
}
|
|
36990
|
+
}, [afterEdit, tryBlockMarkdown]);
|
|
36991
|
+
const execInline = useCallback((command) => {
|
|
36992
|
+
document.execCommand(command, false);
|
|
36993
|
+
afterEdit();
|
|
36994
|
+
}, [afterEdit]);
|
|
36995
|
+
const execBlock = useCallback((tag) => {
|
|
36996
|
+
const next = toolbar.block === tag ? "p" : tag;
|
|
36997
|
+
document.execCommand("formatBlock", false, next);
|
|
36998
|
+
afterEdit();
|
|
36999
|
+
}, [afterEdit, toolbar.block]);
|
|
37000
|
+
const execList = useCallback((command) => {
|
|
37001
|
+
document.execCommand(command, false);
|
|
37002
|
+
afterEdit();
|
|
37003
|
+
}, [afterEdit]);
|
|
37004
|
+
const execLink = useCallback(() => {
|
|
37005
|
+
if (toolbar.link) {
|
|
37006
|
+
document.execCommand("unlink", false);
|
|
37007
|
+
afterEdit();
|
|
37008
|
+
return;
|
|
37009
|
+
}
|
|
37010
|
+
const url = window.prompt(t("richTextEditor.linkPrompt"));
|
|
37011
|
+
if (!url) return;
|
|
37012
|
+
const safe = safeUrl(url, ["http://", "https://", "mailto:"]) ?? `https://${url}`;
|
|
37013
|
+
document.execCommand("createLink", false, safe);
|
|
37014
|
+
afterEdit();
|
|
37015
|
+
}, [afterEdit, t, toolbar.link]);
|
|
37016
|
+
const execRule = useCallback(() => {
|
|
37017
|
+
document.execCommand("insertHorizontalRule", false);
|
|
37018
|
+
afterEdit();
|
|
37019
|
+
}, [afterEdit]);
|
|
37020
|
+
if (readOnly) {
|
|
37021
|
+
return /* @__PURE__ */ jsxs(Box, { className: cn("almadar-rich-text max-w-none", className), children: [
|
|
37022
|
+
/* @__PURE__ */ jsx(RichTextStyles, {}),
|
|
37023
|
+
/* @__PURE__ */ jsx(Box, { dangerouslySetInnerHTML: { __html: sanitizeRichHtml(value ?? "") } })
|
|
37081
37024
|
] });
|
|
37082
37025
|
}
|
|
37083
|
-
|
|
37084
|
-
|
|
37085
|
-
|
|
37086
|
-
return /* @__PURE__ */ jsxs(
|
|
37026
|
+
return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col gap-2", className), children: [
|
|
37027
|
+
/* @__PURE__ */ jsx(RichTextStyles, {}),
|
|
37028
|
+
showToolbar && /* @__PURE__ */ jsxs(
|
|
37087
37029
|
Box,
|
|
37088
37030
|
{
|
|
37089
|
-
|
|
37031
|
+
role: "toolbar",
|
|
37032
|
+
"aria-label": t("richTextEditor.editorToolbar"),
|
|
37090
37033
|
className: cn(
|
|
37091
|
-
"
|
|
37092
|
-
|
|
37034
|
+
"sticky top-0 z-10 flex flex-wrap items-center gap-0.5 self-start",
|
|
37035
|
+
"rounded-md border border-border bg-background/95 px-1 py-0.5 shadow-sm"
|
|
37093
37036
|
),
|
|
37094
37037
|
children: [
|
|
37095
|
-
|
|
37096
|
-
|
|
37097
|
-
|
|
37098
|
-
|
|
37099
|
-
|
|
37100
|
-
|
|
37101
|
-
|
|
37102
|
-
|
|
37103
|
-
|
|
37104
|
-
|
|
37105
|
-
|
|
37106
|
-
|
|
37107
|
-
|
|
37108
|
-
|
|
37109
|
-
|
|
37110
|
-
|
|
37111
|
-
type: "button",
|
|
37112
|
-
variant: "ghost",
|
|
37113
|
-
"aria-label": t("richBlockEditor.aria.removeListItem"),
|
|
37114
|
-
className: cn(
|
|
37115
|
-
"h-5 w-5 shrink-0 rounded-sm text-muted-foreground p-0 gap-0",
|
|
37116
|
-
"opacity-0 group-hover/item:opacity-100 hover:bg-muted hover:text-foreground"
|
|
37117
|
-
),
|
|
37118
|
-
onClick: () => removeListItem(child.id),
|
|
37119
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "trash", className: "w-3 h-3" })
|
|
37120
|
-
}
|
|
37121
|
-
)
|
|
37122
|
-
] }, child.id)),
|
|
37123
|
-
!readOnly && showAffordances && /* @__PURE__ */ jsx(Box, { as: "li", className: "list-none pl-0", children: /* @__PURE__ */ jsxs(
|
|
37124
|
-
Button,
|
|
37125
|
-
{
|
|
37126
|
-
type: "button",
|
|
37127
|
-
variant: "ghost",
|
|
37128
|
-
className: cn(
|
|
37129
|
-
"inline-flex items-center gap-1 text-xs text-muted-foreground",
|
|
37130
|
-
"hover:text-foreground p-0 h-auto"
|
|
37131
|
-
),
|
|
37132
|
-
onClick: addListItem,
|
|
37133
|
-
children: [
|
|
37134
|
-
/* @__PURE__ */ jsx(Icon, { name: "plus", className: "w-3 h-3" }),
|
|
37135
|
-
" ",
|
|
37136
|
-
t("richBlockEditor.addItem")
|
|
37137
|
-
]
|
|
37138
|
-
}
|
|
37139
|
-
) })
|
|
37038
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Bold, label: t("richTextEditor.bold"), active: toolbar.bold, onExec: () => execInline("bold") }),
|
|
37039
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Italic, label: t("richTextEditor.italic"), active: toolbar.italic, onExec: () => execInline("italic") }),
|
|
37040
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Underline, label: t("richTextEditor.underline"), active: toolbar.underline, onExec: () => execInline("underline") }),
|
|
37041
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Strikethrough, label: t("richTextEditor.strikethrough"), active: toolbar.strikeThrough, onExec: () => execInline("strikeThrough") }),
|
|
37042
|
+
/* @__PURE__ */ jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
37043
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Heading1, label: t("richTextEditor.heading1"), active: toolbar.block === "h1", onExec: () => execBlock("h1") }),
|
|
37044
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Heading2, label: t("richTextEditor.heading2"), active: toolbar.block === "h2", onExec: () => execBlock("h2") }),
|
|
37045
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Heading3, label: t("richTextEditor.heading3"), active: toolbar.block === "h3", onExec: () => execBlock("h3") }),
|
|
37046
|
+
/* @__PURE__ */ jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
37047
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: List, label: t("richTextEditor.bulletList"), active: toolbar.bullets, onExec: () => execList("insertUnorderedList") }),
|
|
37048
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: ListOrdered, label: t("richTextEditor.numberedList"), active: toolbar.numbers, onExec: () => execList("insertOrderedList") }),
|
|
37049
|
+
/* @__PURE__ */ jsx(Box, { className: "mx-1 h-5 w-px bg-border" }),
|
|
37050
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Quote, label: t("richTextEditor.quote"), active: toolbar.block === "blockquote", onExec: () => execBlock("blockquote") }),
|
|
37051
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Code, label: t("richTextEditor.code"), active: toolbar.block === "pre", onExec: () => execBlock("pre") }),
|
|
37052
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Link$1, label: toolbar.link ? t("richTextEditor.removeLink") : t("richTextEditor.link"), active: toolbar.link, onExec: execLink }),
|
|
37053
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Minus, label: t("richTextEditor.divider"), onExec: execRule })
|
|
37140
37054
|
]
|
|
37141
37055
|
}
|
|
37142
|
-
)
|
|
37143
|
-
|
|
37144
|
-
|
|
37145
|
-
default:
|
|
37146
|
-
return /* @__PURE__ */ jsx(
|
|
37147
|
-
Editable,
|
|
37056
|
+
),
|
|
37057
|
+
/* @__PURE__ */ jsx(
|
|
37058
|
+
Box,
|
|
37148
37059
|
{
|
|
37149
|
-
|
|
37150
|
-
|
|
37151
|
-
|
|
37152
|
-
|
|
37153
|
-
|
|
37154
|
-
|
|
37155
|
-
|
|
37060
|
+
ref,
|
|
37061
|
+
contentEditable: true,
|
|
37062
|
+
suppressContentEditableWarning: true,
|
|
37063
|
+
role: "textbox",
|
|
37064
|
+
"aria-multiline": "true",
|
|
37065
|
+
"aria-label": t("richTextEditor.editorSurface"),
|
|
37066
|
+
"data-placeholder": placeholder ?? t("richTextEditor.placeholder"),
|
|
37067
|
+
"data-empty": empty ? "true" : "false",
|
|
37068
|
+
className: cn(
|
|
37069
|
+
"almadar-rich-text max-w-none min-h-[8rem] outline-none",
|
|
37070
|
+
"data-[empty=true]:before:content-[attr(data-placeholder)]",
|
|
37071
|
+
"data-[empty=true]:before:text-muted-foreground/60",
|
|
37072
|
+
"data-[empty=true]:before:pointer-events-none",
|
|
37073
|
+
"data-[empty=true]:before:absolute",
|
|
37074
|
+
"relative cursor-text"
|
|
37075
|
+
),
|
|
37076
|
+
onInput: afterEdit,
|
|
37077
|
+
onKeyDown: handleKeyDown,
|
|
37078
|
+
onBlur: flushEmit
|
|
37156
37079
|
}
|
|
37157
|
-
)
|
|
37158
|
-
|
|
37080
|
+
)
|
|
37081
|
+
] });
|
|
37082
|
+
};
|
|
37083
|
+
RichTextEditor.displayName = "RichTextEditor";
|
|
37084
|
+
}
|
|
37085
|
+
});
|
|
37086
|
+
function renderIconInput4(icon, props) {
|
|
37087
|
+
return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
|
|
37088
|
+
}
|
|
37089
|
+
function DocumentPanel({
|
|
37090
|
+
entity,
|
|
37091
|
+
title,
|
|
37092
|
+
subtitle,
|
|
37093
|
+
value,
|
|
37094
|
+
actions,
|
|
37095
|
+
maxInlineActions,
|
|
37096
|
+
editing = false,
|
|
37097
|
+
titleCommitEvent,
|
|
37098
|
+
contentChangeEvent,
|
|
37099
|
+
editEvent,
|
|
37100
|
+
doneEvent,
|
|
37101
|
+
editLabel,
|
|
37102
|
+
doneLabel,
|
|
37103
|
+
autosaveHint,
|
|
37104
|
+
placeholder,
|
|
37105
|
+
className
|
|
37106
|
+
}) {
|
|
37107
|
+
const eventBus = useEventBus();
|
|
37108
|
+
const { t } = useTranslate();
|
|
37109
|
+
const [titleDraft, setTitleDraft] = useState(null);
|
|
37110
|
+
const recordId = entity?.id !== void 0 && entity?.id !== null ? String(entity.id) : "";
|
|
37111
|
+
const actionDefs = actions ?? [];
|
|
37112
|
+
const inlineCap = Math.min(maxInlineActions ?? 1, 1);
|
|
37113
|
+
const inlineActions = actionDefs.filter((a) => a.variant === "primary").slice(0, inlineCap);
|
|
37114
|
+
const menuActions = actionDefs.filter((a) => !inlineActions.includes(a));
|
|
37115
|
+
const fireAction = (action) => {
|
|
37116
|
+
if (!action.event) return;
|
|
37117
|
+
eventBus.emit(`UI:${action.event}`, { id: recordId, row: entity });
|
|
37159
37118
|
};
|
|
37160
|
-
|
|
37119
|
+
const commitTitle = () => {
|
|
37120
|
+
if (!titleCommitEvent) return;
|
|
37121
|
+
const next = (titleDraft ?? "").trim();
|
|
37122
|
+
setTitleDraft(null);
|
|
37123
|
+
if (!next || next === title) return;
|
|
37124
|
+
eventBus.emit(`UI:${titleCommitEvent}`, { title: next, id: recordId });
|
|
37125
|
+
};
|
|
37126
|
+
const untitled = t("documentPanel.untitled") || "Untitled";
|
|
37127
|
+
const titleNode = titleCommitEvent && titleDraft !== null ? /* @__PURE__ */ jsx(
|
|
37128
|
+
Input,
|
|
37129
|
+
{
|
|
37130
|
+
value: titleDraft,
|
|
37131
|
+
autoFocus: true,
|
|
37132
|
+
"aria-label": t("common.title"),
|
|
37133
|
+
className: "h-auto py-1 text-3xl font-bold tracking-tight",
|
|
37134
|
+
onFocus: (e) => e.currentTarget.select(),
|
|
37135
|
+
onChange: (e) => setTitleDraft(e.target.value),
|
|
37136
|
+
onBlur: commitTitle,
|
|
37137
|
+
onKeyDown: (e) => {
|
|
37138
|
+
if (e.key === "Enter") {
|
|
37139
|
+
e.preventDefault();
|
|
37140
|
+
commitTitle();
|
|
37141
|
+
} else if (e.key === "Escape") {
|
|
37142
|
+
e.preventDefault();
|
|
37143
|
+
setTitleDraft(null);
|
|
37144
|
+
}
|
|
37145
|
+
},
|
|
37146
|
+
"data-testid": "document-title-input"
|
|
37147
|
+
}
|
|
37148
|
+
) : titleCommitEvent ? /* @__PURE__ */ jsx(
|
|
37161
37149
|
Box,
|
|
37162
37150
|
{
|
|
37163
|
-
|
|
37164
|
-
|
|
37165
|
-
|
|
37166
|
-
),
|
|
37167
|
-
|
|
37168
|
-
|
|
37169
|
-
|
|
37170
|
-
|
|
37171
|
-
|
|
37151
|
+
role: "button",
|
|
37152
|
+
tabIndex: 0,
|
|
37153
|
+
className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
37154
|
+
onClick: () => setTitleDraft(title ?? ""),
|
|
37155
|
+
onKeyDown: (e) => {
|
|
37156
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
37157
|
+
e.preventDefault();
|
|
37158
|
+
setTitleDraft(title ?? "");
|
|
37159
|
+
}
|
|
37160
|
+
},
|
|
37161
|
+
"data-testid": "document-title-editable",
|
|
37162
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", className: cn(!title && "text-muted-foreground"), children: title || untitled })
|
|
37163
|
+
}
|
|
37164
|
+
) : /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || untitled });
|
|
37165
|
+
const emitWithId = (event) => () => {
|
|
37166
|
+
if (event) eventBus.emit(`UI:${event}`, { id: recordId });
|
|
37167
|
+
};
|
|
37168
|
+
return /* @__PURE__ */ jsx(Card, { variant: "elevated", className: cn("w-full", className), children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "p-6 sm:p-8", children: [
|
|
37169
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
37170
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
37171
|
+
titleNode,
|
|
37172
|
+
subtitle ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
37173
|
+
] }),
|
|
37174
|
+
/* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37175
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
37176
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
37177
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37178
|
+
editEvent && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
37179
|
+
/* @__PURE__ */ jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
37180
|
+
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
37181
|
+
] }),
|
|
37182
|
+
inlineActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
37183
|
+
Button,
|
|
37172
37184
|
{
|
|
37173
|
-
|
|
37174
|
-
|
|
37175
|
-
|
|
37176
|
-
|
|
37177
|
-
|
|
37185
|
+
variant: "primary",
|
|
37186
|
+
size: "sm",
|
|
37187
|
+
onClick: () => fireAction(action),
|
|
37188
|
+
"data-testid": `action-${action.event}`,
|
|
37189
|
+
children: [
|
|
37190
|
+
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
37191
|
+
action.label
|
|
37192
|
+
]
|
|
37193
|
+
},
|
|
37194
|
+
idx
|
|
37195
|
+
)),
|
|
37196
|
+
menuActions.length > 0 && /* @__PURE__ */ jsx(
|
|
37197
|
+
Menu,
|
|
37198
|
+
{
|
|
37199
|
+
position: "bottom-end",
|
|
37200
|
+
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" }) }),
|
|
37201
|
+
items: menuActions.map((action) => ({
|
|
37202
|
+
label: action.label,
|
|
37203
|
+
icon: action.icon,
|
|
37204
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
37205
|
+
onClick: () => fireAction(action)
|
|
37206
|
+
}))
|
|
37178
37207
|
}
|
|
37179
|
-
)
|
|
37180
|
-
|
|
37181
|
-
|
|
37182
|
-
}
|
|
37183
|
-
|
|
37208
|
+
)
|
|
37209
|
+
] }) })
|
|
37210
|
+
] }),
|
|
37211
|
+
editing ? /* @__PURE__ */ jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsx(
|
|
37212
|
+
Box,
|
|
37213
|
+
{
|
|
37214
|
+
onClick: emitWithId(editEvent),
|
|
37215
|
+
className: cn(
|
|
37216
|
+
"rounded-md px-1 -mx-1 min-h-[16rem]",
|
|
37217
|
+
editEvent && "cursor-text transition-colors hover:bg-muted/30"
|
|
37218
|
+
),
|
|
37219
|
+
"data-testid": "document-body",
|
|
37220
|
+
children: value && value !== "" ? /* @__PURE__ */ jsx(RichTextEditor, { value, readOnly: true }) : /* @__PURE__ */ jsx(Typography, { variant: "body", color: "muted", children: placeholder ?? (t("documentPanel.placeholder") || "") })
|
|
37221
|
+
}
|
|
37222
|
+
)
|
|
37223
|
+
] }) });
|
|
37184
37224
|
}
|
|
37185
|
-
var
|
|
37186
|
-
|
|
37187
|
-
"components/core/molecules/RichBlockEditor.tsx"() {
|
|
37225
|
+
var init_DocumentPanel = __esm({
|
|
37226
|
+
"components/core/molecules/DocumentPanel.tsx"() {
|
|
37188
37227
|
"use client";
|
|
37189
37228
|
init_cn();
|
|
37190
|
-
|
|
37229
|
+
init_useEventBus();
|
|
37230
|
+
init_Box();
|
|
37231
|
+
init_Stack();
|
|
37191
37232
|
init_Typography();
|
|
37192
37233
|
init_Button();
|
|
37193
|
-
|
|
37194
|
-
init_Divider();
|
|
37195
|
-
init_Input();
|
|
37234
|
+
init_Card();
|
|
37196
37235
|
init_Icon();
|
|
37197
|
-
|
|
37198
|
-
|
|
37199
|
-
|
|
37200
|
-
|
|
37201
|
-
|
|
37202
|
-
|
|
37203
|
-
|
|
37204
|
-
|
|
37205
|
-
|
|
37206
|
-
|
|
37207
|
-
|
|
37208
|
-
|
|
37209
|
-
|
|
37210
|
-
|
|
37211
|
-
|
|
37212
|
-
|
|
37213
|
-
|
|
37214
|
-
|
|
37215
|
-
|
|
37216
|
-
|
|
37217
|
-
|
|
37218
|
-
|
|
37219
|
-
|
|
37220
|
-
|
|
37221
|
-
|
|
37222
|
-
|
|
37223
|
-
|
|
37224
|
-
|
|
37225
|
-
|
|
37226
|
-
|
|
37227
|
-
|
|
37228
|
-
|
|
37229
|
-
|
|
37230
|
-
|
|
37231
|
-
|
|
37232
|
-
|
|
37233
|
-
|
|
37234
|
-
|
|
37235
|
-
|
|
37236
|
-
|
|
37237
|
-
|
|
37238
|
-
|
|
37239
|
-
|
|
37240
|
-
|
|
37241
|
-
|
|
37242
|
-
|
|
37243
|
-
|
|
37244
|
-
|
|
37245
|
-
|
|
37246
|
-
|
|
37247
|
-
|
|
37248
|
-
|
|
37249
|
-
|
|
37250
|
-
|
|
37251
|
-
|
|
37252
|
-
|
|
37253
|
-
|
|
37254
|
-
|
|
37255
|
-
|
|
37256
|
-
const [blocks, setBlocks] = useState(
|
|
37257
|
-
() => normalizeBlocks(initialBlocks)
|
|
37258
|
-
);
|
|
37259
|
-
const onChangeRef = useRef(onChange);
|
|
37260
|
-
useEffect(() => {
|
|
37261
|
-
onChangeRef.current = onChange;
|
|
37262
|
-
}, [onChange]);
|
|
37263
|
-
const eventBus = useEventBus();
|
|
37264
|
-
const changeEventRef = useRef(changeEvent);
|
|
37265
|
-
useEffect(() => {
|
|
37266
|
-
changeEventRef.current = changeEvent;
|
|
37267
|
-
}, [changeEvent]);
|
|
37268
|
-
const commit = useCallback((next) => {
|
|
37269
|
-
setBlocks(next);
|
|
37270
|
-
onChangeRef.current?.(next);
|
|
37271
|
-
const evt = changeEventRef.current;
|
|
37272
|
-
if (evt) eventBus.emit(`UI:${evt}`, { blocks: next });
|
|
37273
|
-
}, [eventBus]);
|
|
37274
|
-
const handleAppend = useCallback(
|
|
37275
|
-
(type) => {
|
|
37276
|
-
if (readOnly) return;
|
|
37277
|
-
commit([...blocks, createBlock(type)]);
|
|
37278
|
-
},
|
|
37279
|
-
[blocks, commit, readOnly]
|
|
37280
|
-
);
|
|
37281
|
-
const handleUpdate = useCallback(
|
|
37282
|
-
(id, updater) => {
|
|
37283
|
-
commit(replaceBlock(blocks, id, updater));
|
|
37284
|
-
},
|
|
37285
|
-
[blocks, commit]
|
|
37286
|
-
);
|
|
37287
|
-
const handleDelete = useCallback(
|
|
37288
|
-
(id) => {
|
|
37289
|
-
const next = removeBlock(blocks, id);
|
|
37290
|
-
commit(next.length > 0 ? next : [createBlock("paragraph")]);
|
|
37291
|
-
},
|
|
37292
|
-
[blocks, commit]
|
|
37293
|
-
);
|
|
37294
|
-
const handleDuplicate = useCallback(
|
|
37295
|
-
(id) => {
|
|
37296
|
-
const target = blocks.find((b) => b.id === id);
|
|
37297
|
-
if (!target) return;
|
|
37298
|
-
commit(insertAfter(blocks, id, duplicateBlock(target)));
|
|
37299
|
-
},
|
|
37300
|
-
[blocks, commit]
|
|
37236
|
+
init_Input();
|
|
37237
|
+
init_Menu();
|
|
37238
|
+
init_RichTextEditor();
|
|
37239
|
+
}
|
|
37240
|
+
});
|
|
37241
|
+
function renderIconInput5(icon, props) {
|
|
37242
|
+
return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
|
|
37243
|
+
}
|
|
37244
|
+
function fieldName(field) {
|
|
37245
|
+
return field.name ?? field.key ?? "";
|
|
37246
|
+
}
|
|
37247
|
+
function relationLabel(value) {
|
|
37248
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date) return null;
|
|
37249
|
+
for (const key of ["name", "title", "label"]) {
|
|
37250
|
+
const candidate = value[key];
|
|
37251
|
+
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
37252
|
+
}
|
|
37253
|
+
const id = value.id;
|
|
37254
|
+
return id !== void 0 && id !== null ? String(id) : null;
|
|
37255
|
+
}
|
|
37256
|
+
function fieldKind(field, value) {
|
|
37257
|
+
if (field.kind) return field.kind;
|
|
37258
|
+
if (field.options && field.options.length > 0) return "select";
|
|
37259
|
+
if (typeof value === "boolean" || field.format === "boolean") return "boolean";
|
|
37260
|
+
if (Array.isArray(value) || relationLabel(value ?? null) !== null) return "readonly";
|
|
37261
|
+
return "text";
|
|
37262
|
+
}
|
|
37263
|
+
function DocumentDetails({
|
|
37264
|
+
entity,
|
|
37265
|
+
fields,
|
|
37266
|
+
metaCommitEvent,
|
|
37267
|
+
title,
|
|
37268
|
+
className
|
|
37269
|
+
}) {
|
|
37270
|
+
const eventBus = useEventBus();
|
|
37271
|
+
const { t } = useTranslate();
|
|
37272
|
+
const [fieldDraft, setFieldDraft] = useState(null);
|
|
37273
|
+
const recordId = entity?.id !== void 0 && entity?.id !== null ? String(entity.id) : "";
|
|
37274
|
+
const fieldDefs = (fields ?? []).filter((f3) => fieldName(f3) !== "");
|
|
37275
|
+
if (fieldDefs.length === 0) return null;
|
|
37276
|
+
const commitField = (name, next, current) => {
|
|
37277
|
+
setFieldDraft(null);
|
|
37278
|
+
if (!metaCommitEvent || next === current) return;
|
|
37279
|
+
eventBus.emit(`UI:${metaCommitEvent}`, { id: recordId, patch: { id: recordId, [name]: next } });
|
|
37280
|
+
};
|
|
37281
|
+
const renderValue = (field) => {
|
|
37282
|
+
const name = fieldName(field);
|
|
37283
|
+
const raw = getNestedValue(entity ?? {}, name);
|
|
37284
|
+
const kind = fieldKind(field, raw);
|
|
37285
|
+
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
37286
|
+
if (kind === "boolean") {
|
|
37287
|
+
return /* @__PURE__ */ jsx(
|
|
37288
|
+
Switch,
|
|
37289
|
+
{
|
|
37290
|
+
checked: Boolean(raw),
|
|
37291
|
+
disabled: !metaCommitEvent,
|
|
37292
|
+
"aria-label": label,
|
|
37293
|
+
onChange: (checked) => commitField(name, checked, Boolean(raw))
|
|
37294
|
+
}
|
|
37301
37295
|
);
|
|
37302
|
-
|
|
37303
|
-
|
|
37304
|
-
|
|
37305
|
-
|
|
37306
|
-
|
|
37307
|
-
|
|
37308
|
-
|
|
37296
|
+
}
|
|
37297
|
+
if (kind === "select") {
|
|
37298
|
+
return /* @__PURE__ */ jsx(
|
|
37299
|
+
Select,
|
|
37300
|
+
{
|
|
37301
|
+
value: raw !== void 0 && raw !== null ? String(raw) : "",
|
|
37302
|
+
disabled: !metaCommitEvent,
|
|
37303
|
+
"aria-label": label,
|
|
37304
|
+
className: "h-8 w-full",
|
|
37305
|
+
options: (field.options ?? []).map((opt) => ({ value: opt, label: humanizeEnumValue(opt) })),
|
|
37306
|
+
onChange: (e) => commitField(name, e.target.value, raw)
|
|
37307
|
+
}
|
|
37309
37308
|
);
|
|
37310
|
-
|
|
37311
|
-
|
|
37309
|
+
}
|
|
37310
|
+
if (kind === "readonly" || !metaCommitEvent) {
|
|
37311
|
+
if (Array.isArray(raw)) {
|
|
37312
|
+
if (raw.length === 0) {
|
|
37313
|
+
return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
37314
|
+
}
|
|
37315
|
+
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)) });
|
|
37316
|
+
}
|
|
37317
|
+
const shown2 = raw === void 0 || raw === null || raw === "" ? "\u2014" : relationLabel(raw) ?? formatValue(raw, field.format);
|
|
37318
|
+
return /* @__PURE__ */ jsx(Typography, { variant: "small", className: "break-words", children: shown2 });
|
|
37319
|
+
}
|
|
37320
|
+
if (fieldDraft?.name === name) {
|
|
37321
|
+
return /* @__PURE__ */ jsx(
|
|
37322
|
+
Input,
|
|
37312
37323
|
{
|
|
37313
|
-
|
|
37314
|
-
|
|
37315
|
-
|
|
37316
|
-
|
|
37317
|
-
|
|
37318
|
-
|
|
37319
|
-
|
|
37320
|
-
|
|
37321
|
-
|
|
37322
|
-
|
|
37323
|
-
|
|
37324
|
-
|
|
37325
|
-
|
|
37326
|
-
|
|
37327
|
-
|
|
37328
|
-
|
|
37329
|
-
return /* @__PURE__ */ jsxs(
|
|
37330
|
-
Button,
|
|
37331
|
-
{
|
|
37332
|
-
type: "button",
|
|
37333
|
-
variant: "ghost",
|
|
37334
|
-
size: "sm",
|
|
37335
|
-
"aria-label": t("richBlockEditor.insertEntry", { label: entryLabel }),
|
|
37336
|
-
title: entryLabel,
|
|
37337
|
-
onClick: () => handleAppend(entry.type),
|
|
37338
|
-
children: [
|
|
37339
|
-
/* @__PURE__ */ jsx(Icon2, { size: 14 }),
|
|
37340
|
-
/* @__PURE__ */ jsx(Typography, { as: "span", variant: "caption", className: "ml-1 hidden text-xs sm:inline", children: entryLabel })
|
|
37341
|
-
]
|
|
37342
|
-
},
|
|
37343
|
-
entry.type
|
|
37344
|
-
);
|
|
37345
|
-
})
|
|
37346
|
-
}
|
|
37347
|
-
),
|
|
37348
|
-
/* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-1 px-3 py-3", children: blocks.map((block) => /* @__PURE__ */ jsx(
|
|
37349
|
-
BlockRow,
|
|
37350
|
-
{
|
|
37351
|
-
block,
|
|
37352
|
-
readOnly,
|
|
37353
|
-
showAffordances: enableBlocks,
|
|
37354
|
-
placeholder,
|
|
37355
|
-
onUpdate: (updater) => handleUpdate(block.id, updater),
|
|
37356
|
-
onDelete: () => handleDelete(block.id),
|
|
37357
|
-
onDuplicate: () => handleDuplicate(block.id),
|
|
37358
|
-
onChangeType: (type) => handleChangeType(block.id, type)
|
|
37359
|
-
},
|
|
37360
|
-
block.id
|
|
37361
|
-
)) })
|
|
37362
|
-
]
|
|
37324
|
+
value: fieldDraft.value,
|
|
37325
|
+
autoFocus: true,
|
|
37326
|
+
"aria-label": label,
|
|
37327
|
+
className: "h-8 w-full",
|
|
37328
|
+
onChange: (e) => setFieldDraft({ name, value: e.target.value }),
|
|
37329
|
+
onBlur: () => commitField(name, fieldDraft.value.trim(), raw),
|
|
37330
|
+
onKeyDown: (e) => {
|
|
37331
|
+
if (e.key === "Enter") {
|
|
37332
|
+
e.preventDefault();
|
|
37333
|
+
commitField(name, fieldDraft.value.trim(), raw);
|
|
37334
|
+
} else if (e.key === "Escape") {
|
|
37335
|
+
e.preventDefault();
|
|
37336
|
+
setFieldDraft(null);
|
|
37337
|
+
}
|
|
37338
|
+
},
|
|
37339
|
+
"data-testid": `document-property-input-${name}`
|
|
37363
37340
|
}
|
|
37364
37341
|
);
|
|
37365
|
-
}
|
|
37366
|
-
|
|
37342
|
+
}
|
|
37343
|
+
const shown = raw === void 0 || raw === null || raw === "" ? "\u2014" : relationLabel(raw) ?? formatValue(raw, field.format);
|
|
37344
|
+
return /* @__PURE__ */ jsx(
|
|
37345
|
+
Box,
|
|
37346
|
+
{
|
|
37347
|
+
role: "button",
|
|
37348
|
+
tabIndex: 0,
|
|
37349
|
+
className: cn(
|
|
37350
|
+
"cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
37351
|
+
(raw === void 0 || raw === null || raw === "") && "text-muted-foreground"
|
|
37352
|
+
),
|
|
37353
|
+
onClick: () => setFieldDraft({ name, value: raw !== void 0 && raw !== null ? String(raw) : "" }),
|
|
37354
|
+
onKeyDown: (e) => {
|
|
37355
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
37356
|
+
e.preventDefault();
|
|
37357
|
+
setFieldDraft({ name, value: raw !== void 0 && raw !== null ? String(raw) : "" });
|
|
37358
|
+
}
|
|
37359
|
+
},
|
|
37360
|
+
"data-testid": `document-property-${name}`,
|
|
37361
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "break-words", children: shown })
|
|
37362
|
+
}
|
|
37363
|
+
);
|
|
37364
|
+
};
|
|
37365
|
+
return /* @__PURE__ */ jsx(Card, { variant: "bordered", className: cn("w-full", className), children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "p-4", children: [
|
|
37366
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", weight: "medium", className: "uppercase tracking-wide", children: title ?? (t("documentDetails.title") || "Details") }),
|
|
37367
|
+
/* @__PURE__ */ jsx(VStack, { gap: "sm", children: fieldDefs.map((field) => {
|
|
37368
|
+
const name = fieldName(field);
|
|
37369
|
+
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
37370
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
37371
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
37372
|
+
field.icon && renderIconInput5(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
37373
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: label })
|
|
37374
|
+
] }),
|
|
37375
|
+
/* @__PURE__ */ jsx(Box, { className: "min-w-0", children: renderValue(field) })
|
|
37376
|
+
] }, name);
|
|
37377
|
+
}) })
|
|
37378
|
+
] }) });
|
|
37379
|
+
}
|
|
37380
|
+
var init_DocumentDetails = __esm({
|
|
37381
|
+
"components/core/molecules/DocumentDetails.tsx"() {
|
|
37382
|
+
"use client";
|
|
37383
|
+
init_cn();
|
|
37384
|
+
init_format();
|
|
37385
|
+
init_getNestedValue();
|
|
37386
|
+
init_useEventBus();
|
|
37387
|
+
init_Box();
|
|
37388
|
+
init_Stack();
|
|
37389
|
+
init_Typography();
|
|
37390
|
+
init_Badge();
|
|
37391
|
+
init_Card();
|
|
37392
|
+
init_Icon();
|
|
37393
|
+
init_Input();
|
|
37394
|
+
init_Select();
|
|
37395
|
+
init_Switch();
|
|
37367
37396
|
}
|
|
37368
37397
|
});
|
|
37369
37398
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
@@ -42312,8 +42341,8 @@ var init_DataTable = __esm({
|
|
|
42312
42341
|
DataTable.displayName = "DataTable";
|
|
42313
42342
|
}
|
|
42314
42343
|
});
|
|
42315
|
-
function getBadgeVariant(
|
|
42316
|
-
const name =
|
|
42344
|
+
function getBadgeVariant(fieldName2, value) {
|
|
42345
|
+
const name = fieldName2.toLowerCase();
|
|
42317
42346
|
const val = String(value).toLowerCase();
|
|
42318
42347
|
if (name.includes("status")) {
|
|
42319
42348
|
if (val.includes("complete") || val.includes("done") || val.includes("active"))
|
|
@@ -42329,12 +42358,12 @@ function getBadgeVariant(fieldName, value) {
|
|
|
42329
42358
|
}
|
|
42330
42359
|
return "default";
|
|
42331
42360
|
}
|
|
42332
|
-
function formatFieldValue2(value,
|
|
42361
|
+
function formatFieldValue2(value, fieldName2) {
|
|
42333
42362
|
if (typeof value === "number") {
|
|
42334
|
-
if (
|
|
42363
|
+
if (fieldName2.toLowerCase().includes("progress") || fieldName2.toLowerCase().includes("percent")) {
|
|
42335
42364
|
return `${value}%`;
|
|
42336
42365
|
}
|
|
42337
|
-
if (
|
|
42366
|
+
if (fieldName2.toLowerCase().includes("budget") || fieldName2.toLowerCase().includes("cost")) {
|
|
42338
42367
|
return `$${value.toLocaleString()}`;
|
|
42339
42368
|
}
|
|
42340
42369
|
return value.toLocaleString();
|
|
@@ -42344,7 +42373,7 @@ function formatFieldValue2(value, fieldName) {
|
|
|
42344
42373
|
}
|
|
42345
42374
|
return String(value);
|
|
42346
42375
|
}
|
|
42347
|
-
function renderRichFieldValue(value,
|
|
42376
|
+
function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
42348
42377
|
if (value === void 0 || value === null) return "\u2014";
|
|
42349
42378
|
const str = String(value);
|
|
42350
42379
|
switch (fieldType) {
|
|
@@ -42355,7 +42384,7 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
|
|
|
42355
42384
|
"img",
|
|
42356
42385
|
{
|
|
42357
42386
|
src: str,
|
|
42358
|
-
alt: formatFieldLabel(
|
|
42387
|
+
alt: formatFieldLabel(fieldName2),
|
|
42359
42388
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
42360
42389
|
loading: "lazy"
|
|
42361
42390
|
}
|
|
@@ -42490,9 +42519,9 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
|
|
|
42490
42519
|
return /* @__PURE__ */ jsx("a", { href: `tel:${str}`, className: "text-primary hover:underline", children: str });
|
|
42491
42520
|
default:
|
|
42492
42521
|
if (meta?.values && meta.values.length > 0 && meta.values.includes(str)) {
|
|
42493
|
-
return /* @__PURE__ */ jsx(Badge, { variant: getBadgeVariant(
|
|
42522
|
+
return /* @__PURE__ */ jsx(Badge, { variant: getBadgeVariant(fieldName2, str), children: humanizeEnumValue(str) });
|
|
42494
42523
|
}
|
|
42495
|
-
return formatFieldValue2(value,
|
|
42524
|
+
return formatFieldValue2(value, fieldName2);
|
|
42496
42525
|
}
|
|
42497
42526
|
}
|
|
42498
42527
|
function normalizeFieldDefs(fields) {
|
|
@@ -42962,16 +42991,11 @@ var init_DetailPanel = __esm({
|
|
|
42962
42991
|
footer
|
|
42963
42992
|
] })
|
|
42964
42993
|
] }) });
|
|
42965
|
-
|
|
42966
|
-
Box,
|
|
42967
|
-
|
|
42968
|
-
|
|
42969
|
-
|
|
42970
|
-
className
|
|
42971
|
-
),
|
|
42972
|
-
children: content
|
|
42973
|
-
}
|
|
42974
|
-
);
|
|
42994
|
+
if (!slideOver) {
|
|
42995
|
+
return /* @__PURE__ */ jsx(Box, { className, children: content });
|
|
42996
|
+
}
|
|
42997
|
+
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 });
|
|
42998
|
+
return typeof document === "undefined" ? panel : createPortal(panel, document.body);
|
|
42975
42999
|
};
|
|
42976
43000
|
DetailPanel.displayName = "DetailPanel";
|
|
42977
43001
|
}
|
|
@@ -43340,7 +43364,21 @@ var init_Form = __esm({
|
|
|
43340
43364
|
const normalizedInitialData = React87__default.useMemo(() => {
|
|
43341
43365
|
const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
|
|
43342
43366
|
const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
|
|
43343
|
-
|
|
43367
|
+
const merged = entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
|
|
43368
|
+
const toId = (value) => {
|
|
43369
|
+
if (value === null || value === void 0 || typeof value !== "object" || value instanceof Date) return value;
|
|
43370
|
+
if (Array.isArray(value)) {
|
|
43371
|
+
return value.map(
|
|
43372
|
+
(item) => item !== null && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && item.id !== void 0 && item.id !== null ? String(item.id) : item
|
|
43373
|
+
);
|
|
43374
|
+
}
|
|
43375
|
+
return value.id !== void 0 && value.id !== null ? String(value.id) : value;
|
|
43376
|
+
};
|
|
43377
|
+
const normalized = {};
|
|
43378
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
43379
|
+
normalized[key] = key === "id" ? value : toId(value);
|
|
43380
|
+
}
|
|
43381
|
+
return normalized;
|
|
43344
43382
|
}, [entity, initialData]);
|
|
43345
43383
|
const entityDerivedFields = React87__default.useMemo(() => {
|
|
43346
43384
|
if (fields && fields.length > 0) return void 0;
|
|
@@ -43469,8 +43507,8 @@ var init_Form = __esm({
|
|
|
43469
43507
|
checkViolations(name, newFormData);
|
|
43470
43508
|
};
|
|
43471
43509
|
const isFieldVisible = React87__default.useCallback(
|
|
43472
|
-
(
|
|
43473
|
-
const condition = conditionalFields[
|
|
43510
|
+
(fieldName2) => {
|
|
43511
|
+
const condition = conditionalFields[fieldName2];
|
|
43474
43512
|
if (!condition) return true;
|
|
43475
43513
|
return Boolean(evaluateFormExpression(condition, evalContext));
|
|
43476
43514
|
},
|
|
@@ -43516,9 +43554,9 @@ var init_Form = __esm({
|
|
|
43516
43554
|
};
|
|
43517
43555
|
const handleInvalid = (e) => {
|
|
43518
43556
|
const target = e.target;
|
|
43519
|
-
const
|
|
43557
|
+
const fieldName2 = target.getAttribute("data-field-name") ?? target.name ?? "";
|
|
43520
43558
|
const fieldMessage = target.validationMessage || "Invalid value";
|
|
43521
|
-
debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
|
|
43559
|
+
debug("forms", "invalid", { mode: formMode, fieldName: fieldName2, fieldMessage });
|
|
43522
43560
|
queueMicrotask(() => {
|
|
43523
43561
|
const form = formRef.current;
|
|
43524
43562
|
if (!form) return;
|
|
@@ -43554,22 +43592,22 @@ var init_Form = __esm({
|
|
|
43554
43592
|
};
|
|
43555
43593
|
const renderField = React87__default.useCallback(
|
|
43556
43594
|
(field) => {
|
|
43557
|
-
const
|
|
43558
|
-
if (!
|
|
43559
|
-
if (!isFieldVisible(
|
|
43595
|
+
const fieldName2 = field.name || field.field;
|
|
43596
|
+
if (!fieldName2) return null;
|
|
43597
|
+
if (!isFieldVisible(fieldName2)) {
|
|
43560
43598
|
return null;
|
|
43561
43599
|
}
|
|
43562
43600
|
const inputType = determineInputType(field);
|
|
43563
|
-
const label = field.label ||
|
|
43564
|
-
const currentValue = formData[
|
|
43565
|
-
return /* @__PURE__ */ jsxs(VStack, { gap: "xs", "data-field":
|
|
43601
|
+
const label = field.label || fieldName2.charAt(0).toUpperCase() + fieldName2.slice(1).replace(/([A-Z])/g, " $1");
|
|
43602
|
+
const currentValue = formData[fieldName2] ?? field.defaultValue ?? "";
|
|
43603
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "xs", "data-field": fieldName2, children: [
|
|
43566
43604
|
inputType !== "checkbox" && /* @__PURE__ */ jsxs(Typography, { as: "label", variant: "label", weight: "bold", children: [
|
|
43567
43605
|
label,
|
|
43568
43606
|
field.required && /* @__PURE__ */ jsx(Typography, { as: "span", color: "error", className: "ml-1", children: "*" })
|
|
43569
43607
|
] }),
|
|
43570
|
-
renderFieldInput(field,
|
|
43608
|
+
renderFieldInput(field, fieldName2, inputType, currentValue, label),
|
|
43571
43609
|
field.hint && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: field.hint })
|
|
43572
|
-
] },
|
|
43610
|
+
] }, fieldName2);
|
|
43573
43611
|
},
|
|
43574
43612
|
[formData, isFieldVisible, relationsData, relationsLoading, isLoading]
|
|
43575
43613
|
);
|
|
@@ -43598,8 +43636,8 @@ var init_Form = __esm({
|
|
|
43598
43636
|
}
|
|
43599
43637
|
return field;
|
|
43600
43638
|
}).map((field) => {
|
|
43601
|
-
const
|
|
43602
|
-
const override = fieldOverrides?.find((o) => o.name ===
|
|
43639
|
+
const fieldName2 = field.name || field.field;
|
|
43640
|
+
const override = fieldOverrides?.find((o) => o.name === fieldName2);
|
|
43603
43641
|
if (!override) return field;
|
|
43604
43642
|
return {
|
|
43605
43643
|
...field,
|
|
@@ -43655,11 +43693,11 @@ var init_Form = __esm({
|
|
|
43655
43693
|
] }, section.id);
|
|
43656
43694
|
}).filter(Boolean);
|
|
43657
43695
|
}, [sections, isSectionVisible, collapsedSections, renderField, gap]);
|
|
43658
|
-
function renderFieldInput(field,
|
|
43696
|
+
function renderFieldInput(field, fieldName2, inputType, currentValue, label) {
|
|
43659
43697
|
const commonProps = {
|
|
43660
|
-
id:
|
|
43661
|
-
name:
|
|
43662
|
-
"data-field-name":
|
|
43698
|
+
id: fieldName2,
|
|
43699
|
+
name: fieldName2,
|
|
43700
|
+
"data-field-name": fieldName2,
|
|
43663
43701
|
required: field.required,
|
|
43664
43702
|
disabled: isLoading,
|
|
43665
43703
|
placeholder: field.placeholder,
|
|
@@ -43673,7 +43711,7 @@ var init_Form = __esm({
|
|
|
43673
43711
|
...commonProps,
|
|
43674
43712
|
label: label + (field.required ? " *" : ""),
|
|
43675
43713
|
checked: Boolean(currentValue),
|
|
43676
|
-
onChange: (e) => handleChange(
|
|
43714
|
+
onChange: (e) => handleChange(fieldName2, e.target.checked)
|
|
43677
43715
|
}
|
|
43678
43716
|
);
|
|
43679
43717
|
case "textarea":
|
|
@@ -43682,7 +43720,7 @@ var init_Form = __esm({
|
|
|
43682
43720
|
{
|
|
43683
43721
|
...commonProps,
|
|
43684
43722
|
value: String(currentValue),
|
|
43685
|
-
onChange: (e) => handleChange(
|
|
43723
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43686
43724
|
minLength: field.min,
|
|
43687
43725
|
maxLength: field.max
|
|
43688
43726
|
}
|
|
@@ -43695,14 +43733,14 @@ var init_Form = __esm({
|
|
|
43695
43733
|
...commonProps,
|
|
43696
43734
|
options,
|
|
43697
43735
|
value: String(currentValue),
|
|
43698
|
-
onValueChange: (v) => handleChange(
|
|
43736
|
+
onValueChange: (v) => handleChange(fieldName2, v),
|
|
43699
43737
|
placeholder: field.placeholder || `Select ${label}...`
|
|
43700
43738
|
}
|
|
43701
43739
|
);
|
|
43702
43740
|
}
|
|
43703
43741
|
case "relation": {
|
|
43704
|
-
const relationOptions = relationsData[
|
|
43705
|
-
const relationLoading = relationsLoading[
|
|
43742
|
+
const relationOptions = relationsData[fieldName2] || [];
|
|
43743
|
+
const relationLoading = relationsLoading[fieldName2] || false;
|
|
43706
43744
|
if (field.relation?.cardinality !== void 0 && MANY_CARDINALITIES.includes(field.relation.cardinality)) {
|
|
43707
43745
|
const selectedValues = Array.isArray(currentValue) ? currentValue.map((v) => String(v)) : [];
|
|
43708
43746
|
return /* @__PURE__ */ jsx(
|
|
@@ -43714,7 +43752,7 @@ var init_Form = __esm({
|
|
|
43714
43752
|
clearable: true,
|
|
43715
43753
|
options: [...relationOptions],
|
|
43716
43754
|
value: selectedValues,
|
|
43717
|
-
onValueChange: (value) => handleChange(
|
|
43755
|
+
onValueChange: (value) => handleChange(fieldName2, Array.isArray(value) ? value : [value]),
|
|
43718
43756
|
placeholder: field.placeholder || `Select ${label}...`
|
|
43719
43757
|
}
|
|
43720
43758
|
);
|
|
@@ -43724,7 +43762,7 @@ var init_Form = __esm({
|
|
|
43724
43762
|
{
|
|
43725
43763
|
...commonProps,
|
|
43726
43764
|
value: currentValue ? String(currentValue) : void 0,
|
|
43727
|
-
onChange: (value) => handleChange(
|
|
43765
|
+
onChange: (value) => handleChange(fieldName2, value),
|
|
43728
43766
|
options: relationOptions,
|
|
43729
43767
|
isLoading: relationLoading,
|
|
43730
43768
|
placeholder: field.placeholder || `Select ${label}...`,
|
|
@@ -43741,7 +43779,7 @@ var init_Form = __esm({
|
|
|
43741
43779
|
placeholder: field.placeholder,
|
|
43742
43780
|
disabled: isLoading,
|
|
43743
43781
|
value: arrayValue,
|
|
43744
|
-
onChange: (next) => handleChange(
|
|
43782
|
+
onChange: (next) => handleChange(fieldName2, [...next])
|
|
43745
43783
|
}
|
|
43746
43784
|
);
|
|
43747
43785
|
}
|
|
@@ -43753,7 +43791,7 @@ var init_Form = __esm({
|
|
|
43753
43791
|
type: "number",
|
|
43754
43792
|
value: currentValue !== void 0 && currentValue !== "" ? String(currentValue) : "",
|
|
43755
43793
|
onChange: (e) => handleChange(
|
|
43756
|
-
|
|
43794
|
+
fieldName2,
|
|
43757
43795
|
e.target.value ? Number(e.target.value) : void 0
|
|
43758
43796
|
),
|
|
43759
43797
|
min: field.min,
|
|
@@ -43770,7 +43808,7 @@ var init_Form = __esm({
|
|
|
43770
43808
|
icon: DollarSign,
|
|
43771
43809
|
value: currentValue !== void 0 && currentValue !== "" ? String(currentValue) : "",
|
|
43772
43810
|
onChange: (e) => handleChange(
|
|
43773
|
-
|
|
43811
|
+
fieldName2,
|
|
43774
43812
|
e.target.value ? Number(e.target.value) : void 0
|
|
43775
43813
|
),
|
|
43776
43814
|
min: field.min,
|
|
@@ -43788,7 +43826,7 @@ var init_Form = __esm({
|
|
|
43788
43826
|
const f3 = files[0];
|
|
43789
43827
|
if (!f3) return;
|
|
43790
43828
|
const reader = new FileReader();
|
|
43791
|
-
reader.onload = () => handleChange(
|
|
43829
|
+
reader.onload = () => handleChange(fieldName2, {
|
|
43792
43830
|
name: f3.name,
|
|
43793
43831
|
mimeType: f3.type,
|
|
43794
43832
|
sizeBytes: f3.size,
|
|
@@ -43805,7 +43843,7 @@ var init_Form = __esm({
|
|
|
43805
43843
|
...commonProps,
|
|
43806
43844
|
type: "date",
|
|
43807
43845
|
value: formatDateValue(currentValue),
|
|
43808
|
-
onChange: (e) => handleChange(
|
|
43846
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
43809
43847
|
}
|
|
43810
43848
|
);
|
|
43811
43849
|
case "datetime-local":
|
|
@@ -43815,7 +43853,7 @@ var init_Form = __esm({
|
|
|
43815
43853
|
...commonProps,
|
|
43816
43854
|
type: "datetime-local",
|
|
43817
43855
|
value: formatDateTimeValue(currentValue),
|
|
43818
|
-
onChange: (e) => handleChange(
|
|
43856
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
43819
43857
|
}
|
|
43820
43858
|
);
|
|
43821
43859
|
case "email":
|
|
@@ -43825,7 +43863,7 @@ var init_Form = __esm({
|
|
|
43825
43863
|
...commonProps,
|
|
43826
43864
|
type: "email",
|
|
43827
43865
|
value: String(currentValue),
|
|
43828
|
-
onChange: (e) => handleChange(
|
|
43866
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43829
43867
|
minLength: field.min,
|
|
43830
43868
|
maxLength: field.max
|
|
43831
43869
|
}
|
|
@@ -43837,7 +43875,7 @@ var init_Form = __esm({
|
|
|
43837
43875
|
...commonProps,
|
|
43838
43876
|
type: "url",
|
|
43839
43877
|
value: String(currentValue),
|
|
43840
|
-
onChange: (e) => handleChange(
|
|
43878
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43841
43879
|
minLength: field.min,
|
|
43842
43880
|
maxLength: field.max
|
|
43843
43881
|
}
|
|
@@ -43849,7 +43887,7 @@ var init_Form = __esm({
|
|
|
43849
43887
|
...commonProps,
|
|
43850
43888
|
type: "password",
|
|
43851
43889
|
value: String(currentValue),
|
|
43852
|
-
onChange: (e) => handleChange(
|
|
43890
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43853
43891
|
minLength: field.min,
|
|
43854
43892
|
maxLength: field.max
|
|
43855
43893
|
}
|
|
@@ -43862,7 +43900,7 @@ var init_Form = __esm({
|
|
|
43862
43900
|
...commonProps,
|
|
43863
43901
|
type: "text",
|
|
43864
43902
|
value: String(currentValue),
|
|
43865
|
-
onChange: (e) => handleChange(
|
|
43903
|
+
onChange: (e) => handleChange(fieldName2, e.target.value),
|
|
43866
43904
|
minLength: field.min,
|
|
43867
43905
|
maxLength: field.max
|
|
43868
43906
|
}
|
|
@@ -44219,7 +44257,7 @@ function entityFieldsFromListItem(item) {
|
|
|
44219
44257
|
}
|
|
44220
44258
|
return result;
|
|
44221
44259
|
}
|
|
44222
|
-
function getStatusStyle(
|
|
44260
|
+
function getStatusStyle(fieldName2, value) {
|
|
44223
44261
|
const val = String(value).toLowerCase();
|
|
44224
44262
|
if (val.includes("complete") || val.includes("done"))
|
|
44225
44263
|
return STATUS_STYLES.complete;
|
|
@@ -44235,12 +44273,12 @@ function getStatusStyle(fieldName, value) {
|
|
|
44235
44273
|
if (val.includes("low")) return STATUS_STYLES.low;
|
|
44236
44274
|
return STATUS_STYLES.default;
|
|
44237
44275
|
}
|
|
44238
|
-
function formatValue3(value,
|
|
44276
|
+
function formatValue3(value, fieldName2) {
|
|
44239
44277
|
if (typeof value === "number") {
|
|
44240
|
-
if (
|
|
44278
|
+
if (fieldName2.toLowerCase().includes("progress") || fieldName2.toLowerCase().includes("percent")) {
|
|
44241
44279
|
return `${value}%`;
|
|
44242
44280
|
}
|
|
44243
|
-
if (
|
|
44281
|
+
if (fieldName2.toLowerCase().includes("budget") || fieldName2.toLowerCase().includes("cost")) {
|
|
44244
44282
|
return new Intl.NumberFormat("en-US", {
|
|
44245
44283
|
style: "currency",
|
|
44246
44284
|
currency: "USD",
|
|
@@ -44263,8 +44301,8 @@ function formatValue3(value, fieldName) {
|
|
|
44263
44301
|
}
|
|
44264
44302
|
return String(value);
|
|
44265
44303
|
}
|
|
44266
|
-
function formatFieldLabel2(
|
|
44267
|
-
return humanizeFieldName(
|
|
44304
|
+
function formatFieldLabel2(fieldName2) {
|
|
44305
|
+
return humanizeFieldName(fieldName2).replace(/\sId$/, "").trim();
|
|
44268
44306
|
}
|
|
44269
44307
|
var STATUS_STYLES, StatusBadge, ProgressIndicator, List3;
|
|
44270
44308
|
var init_List = __esm({
|
|
@@ -44332,9 +44370,9 @@ var init_List = __esm({
|
|
|
44332
44370
|
};
|
|
44333
44371
|
StatusBadge = ({
|
|
44334
44372
|
value,
|
|
44335
|
-
fieldName
|
|
44373
|
+
fieldName: fieldName2
|
|
44336
44374
|
}) => {
|
|
44337
|
-
const style = getStatusStyle(
|
|
44375
|
+
const style = getStatusStyle(fieldName2, value);
|
|
44338
44376
|
return /* @__PURE__ */ jsxs(
|
|
44339
44377
|
Typography,
|
|
44340
44378
|
{
|
|
@@ -47247,8 +47285,8 @@ var init_StatCard = __esm({
|
|
|
47247
47285
|
return items.length;
|
|
47248
47286
|
}
|
|
47249
47287
|
if (field.includes(":")) {
|
|
47250
|
-
const [
|
|
47251
|
-
return items.filter((item) => item[
|
|
47288
|
+
const [fieldName2, fieldValue] = field.split(":");
|
|
47289
|
+
return items.filter((item) => item[fieldName2] === fieldValue).length;
|
|
47252
47290
|
}
|
|
47253
47291
|
const fieldExistsOnItems = items.some((item) => field in item);
|
|
47254
47292
|
if (fieldExistsOnItems) {
|
|
@@ -48768,6 +48806,8 @@ var init_component_registry_generated = __esm({
|
|
|
48768
48806
|
init_DocSearch();
|
|
48769
48807
|
init_DocSidebar();
|
|
48770
48808
|
init_DocTOC();
|
|
48809
|
+
init_DocumentDetails();
|
|
48810
|
+
init_DocumentPanel();
|
|
48771
48811
|
init_DocumentViewer();
|
|
48772
48812
|
init_DrawFxLayer();
|
|
48773
48813
|
init_DrawGroup();
|
|
@@ -48877,7 +48917,7 @@ var init_component_registry_generated = __esm({
|
|
|
48877
48917
|
init_RelationSelect();
|
|
48878
48918
|
init_RepeatableFormSection();
|
|
48879
48919
|
init_ReplyTree();
|
|
48880
|
-
|
|
48920
|
+
init_RichTextEditor();
|
|
48881
48921
|
init_RuntimeDebugger2();
|
|
48882
48922
|
init_ScaledDiagram();
|
|
48883
48923
|
init_ScoreDisplay();
|
|
@@ -49040,6 +49080,8 @@ var init_component_registry_generated = __esm({
|
|
|
49040
49080
|
"DocSearch": DocSearch,
|
|
49041
49081
|
"DocSidebar": DocSidebar,
|
|
49042
49082
|
"DocTOC": DocTOC,
|
|
49083
|
+
"DocumentDetails": DocumentDetails,
|
|
49084
|
+
"DocumentPanel": DocumentPanel,
|
|
49043
49085
|
"DocumentViewer": DocumentViewer,
|
|
49044
49086
|
"DrawFxLayer": DrawFxLayer,
|
|
49045
49087
|
"DrawGroup": DrawGroup,
|
|
@@ -49151,7 +49193,7 @@ var init_component_registry_generated = __esm({
|
|
|
49151
49193
|
"RelationSelect": RelationSelect,
|
|
49152
49194
|
"RepeatableFormSection": RepeatableFormSection,
|
|
49153
49195
|
"ReplyTree": ReplyTree,
|
|
49154
|
-
"
|
|
49196
|
+
"RichTextEditor": RichTextEditor,
|
|
49155
49197
|
"RuntimeDebugger": RuntimeDebugger,
|
|
49156
49198
|
"ScaledDiagram": ScaledDiagram,
|
|
49157
49199
|
"ScoreDisplay": ScoreDisplay,
|
|
@@ -49305,10 +49347,10 @@ function enrichFormFields(fields, entityDef) {
|
|
|
49305
49347
|
}
|
|
49306
49348
|
if (field && typeof field === "object" && !Array.isArray(field) && !React87__default.isValidElement(field) && !(field instanceof Date)) {
|
|
49307
49349
|
const obj = field;
|
|
49308
|
-
const
|
|
49309
|
-
if (!
|
|
49350
|
+
const fieldName2 = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
|
|
49351
|
+
if (!fieldName2) return field;
|
|
49310
49352
|
if (obj.type || obj.inputType) return field;
|
|
49311
|
-
const entityField = fieldMap.get(
|
|
49353
|
+
const entityField = fieldMap.get(fieldName2);
|
|
49312
49354
|
if (!entityField) return field;
|
|
49313
49355
|
const enriched = { ...obj, type: entityField.type };
|
|
49314
49356
|
if (entityField.required && !("required" in obj)) {
|
|
@@ -49358,9 +49400,9 @@ function enrichDetailFields(fields, entityDef) {
|
|
|
49358
49400
|
}
|
|
49359
49401
|
if (field && typeof field === "object" && !Array.isArray(field) && !React87__default.isValidElement(field) && !(field instanceof Date)) {
|
|
49360
49402
|
const obj = field;
|
|
49361
|
-
const
|
|
49362
|
-
if (!
|
|
49363
|
-
const meta = metaFor(
|
|
49403
|
+
const fieldName2 = typeof obj.key === "string" ? obj.key : typeof obj.name === "string" ? obj.name : void 0;
|
|
49404
|
+
if (!fieldName2 || obj.type) return field;
|
|
49405
|
+
const meta = metaFor(fieldName2);
|
|
49364
49406
|
return meta ? { ...obj, ...meta } : field;
|
|
49365
49407
|
}
|
|
49366
49408
|
return field;
|
|
@@ -50199,9 +50241,9 @@ function UISlotRenderer({
|
|
|
50199
50241
|
"ui-slot-renderer relative min-h-full",
|
|
50200
50242
|
className
|
|
50201
50243
|
), children: [
|
|
50202
|
-
/* @__PURE__ */ jsxs(Box, { className: "flex min-h-full", children: [
|
|
50203
|
-
/* @__PURE__ */ jsx(UISlotComponent, { slot: "sidebar", className: "ui-slot-sidebar min-w-0 shrink-0" }),
|
|
50204
|
-
/* @__PURE__ */ jsx(UISlotComponent, { slot: "main", className: "ui-slot-main flex-1 min-h-[200px]" })
|
|
50244
|
+
/* @__PURE__ */ jsxs(Box, { className: "flex min-h-full flex-col lg:flex-row", children: [
|
|
50245
|
+
/* @__PURE__ */ jsx(UISlotComponent, { slot: "sidebar", className: "ui-slot-sidebar min-w-0 lg:shrink-0" }),
|
|
50246
|
+
/* @__PURE__ */ jsx(UISlotComponent, { slot: "main", className: "ui-slot-main flex-1 min-w-0 min-h-[200px]" })
|
|
50205
50247
|
] }),
|
|
50206
50248
|
/* @__PURE__ */ jsx(UISlotComponent, { slot: "modal", portal: true }),
|
|
50207
50249
|
/* @__PURE__ */ jsx(UISlotComponent, { slot: "drawer", portal: true }),
|