@almadar/ui 5.162.0 → 5.164.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 +420 -106
- package/dist/avl/index.js +420 -106
- package/dist/components/index.cjs +424 -107
- package/dist/components/index.d.cts +44 -5
- package/dist/components/index.d.ts +44 -5
- package/dist/components/index.js +424 -107
- package/dist/hooks/index.cjs +4 -1
- package/dist/hooks/index.js +4 -1
- package/dist/locales/index.cjs +12 -3
- package/dist/locales/index.js +12 -3
- package/dist/providers/index.cjs +420 -106
- package/dist/providers/index.js +420 -106
- package/dist/runtime/index.cjs +420 -106
- package/dist/runtime/index.js +420 -106
- package/locales/ar.json +10 -7
- package/locales/en.json +5 -2
- package/locales/sl.json +5 -2
- package/package.json +4 -4
package/dist/providers/index.js
CHANGED
|
@@ -24880,6 +24880,7 @@ var init_DashboardLayout = __esm({
|
|
|
24880
24880
|
onNotificationClick,
|
|
24881
24881
|
showThemeToggle = true,
|
|
24882
24882
|
sidebarFooter,
|
|
24883
|
+
sidebarContent,
|
|
24883
24884
|
onSignOut: onSignOutProp,
|
|
24884
24885
|
currentPath,
|
|
24885
24886
|
layoutMode = "sidebar",
|
|
@@ -25005,7 +25006,11 @@ var init_DashboardLayout = __esm({
|
|
|
25005
25006
|
{
|
|
25006
25007
|
as: "nav",
|
|
25007
25008
|
gap: "none",
|
|
25008
|
-
className: cn(
|
|
25009
|
+
className: cn(
|
|
25010
|
+
"py-4 space-y-1 overflow-y-auto",
|
|
25011
|
+
sidebarContent && !isRail ? "shrink-0" : "flex-1",
|
|
25012
|
+
isRail ? "px-2" : "px-3"
|
|
25013
|
+
),
|
|
25009
25014
|
children: navItems.map((item) => /* @__PURE__ */ jsx(
|
|
25010
25015
|
NavLink,
|
|
25011
25016
|
{
|
|
@@ -25017,6 +25022,7 @@ var init_DashboardLayout = __esm({
|
|
|
25017
25022
|
))
|
|
25018
25023
|
}
|
|
25019
25024
|
),
|
|
25025
|
+
sidebarContent && !isRail && /* @__PURE__ */ jsx(Box, { className: "flex-1 overflow-y-auto border-t border-border dark:border-border px-2 py-3", children: sidebarContent }),
|
|
25020
25026
|
sidebarFooter && /* @__PURE__ */ jsx(Box, { className: "p-4 border-t border-border dark:border-border", children: sidebarFooter })
|
|
25021
25027
|
]
|
|
25022
25028
|
}
|
|
@@ -27426,7 +27432,17 @@ function fileIcon(name) {
|
|
|
27426
27432
|
return "file";
|
|
27427
27433
|
}
|
|
27428
27434
|
}
|
|
27429
|
-
|
|
27435
|
+
function ancestorsOf(id, byId) {
|
|
27436
|
+
const out = /* @__PURE__ */ new Set();
|
|
27437
|
+
if (!id) return out;
|
|
27438
|
+
let cur = byId.get(id)?.parentId;
|
|
27439
|
+
while (cur && byId.has(cur) && !out.has(cur)) {
|
|
27440
|
+
out.add(cur);
|
|
27441
|
+
cur = byId.get(cur)?.parentId;
|
|
27442
|
+
}
|
|
27443
|
+
return out;
|
|
27444
|
+
}
|
|
27445
|
+
var TreeNodeItem, FlatTreeNodeItem, FlatFileTree, FileTree;
|
|
27430
27446
|
var init_FileTree = __esm({
|
|
27431
27447
|
"components/core/molecules/FileTree.tsx"() {
|
|
27432
27448
|
"use client";
|
|
@@ -27517,42 +27533,77 @@ var init_FileTree = __esm({
|
|
|
27517
27533
|
indent,
|
|
27518
27534
|
childrenByParent,
|
|
27519
27535
|
onNodeSelect,
|
|
27520
|
-
|
|
27536
|
+
onNodeAction,
|
|
27537
|
+
nodeActionIcon,
|
|
27538
|
+
nodeActionLabel,
|
|
27539
|
+
selectedId,
|
|
27540
|
+
look,
|
|
27541
|
+
isExpanded,
|
|
27542
|
+
onToggle
|
|
27521
27543
|
}) => {
|
|
27522
|
-
const [expanded, setExpanded] = useState(defaultExpanded || depth < 1);
|
|
27523
27544
|
const children = childrenByParent.get(item.id);
|
|
27524
27545
|
const hasChildren = !!children && children.length > 0;
|
|
27546
|
+
const expanded = hasChildren && isExpanded(item.id, depth);
|
|
27547
|
+
const isSelected = selectedId !== void 0 && selectedId !== "" && item.id === selectedId;
|
|
27548
|
+
const nav = look === "nav";
|
|
27525
27549
|
const handleClick = useCallback(() => {
|
|
27526
|
-
if (hasChildren)
|
|
27550
|
+
if (hasChildren && !onNodeSelect) onToggle(item.id, expanded);
|
|
27527
27551
|
onNodeSelect?.(item.id);
|
|
27528
|
-
}, [hasChildren, item.id, onNodeSelect]);
|
|
27552
|
+
}, [hasChildren, expanded, item.id, onNodeSelect, onToggle]);
|
|
27553
|
+
const handleChevron = useCallback((e) => {
|
|
27554
|
+
e.stopPropagation();
|
|
27555
|
+
onToggle(item.id, expanded);
|
|
27556
|
+
}, [item.id, expanded, onToggle]);
|
|
27557
|
+
const handleAction = useCallback((e) => {
|
|
27558
|
+
e.stopPropagation();
|
|
27559
|
+
onNodeAction?.(item.id);
|
|
27560
|
+
}, [item.id, onNodeAction]);
|
|
27529
27561
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
27530
27562
|
/* @__PURE__ */ jsxs(
|
|
27531
27563
|
Box,
|
|
27532
27564
|
{
|
|
27533
|
-
className:
|
|
27565
|
+
className: `group/treerow flex items-center gap-1.5 px-2 cursor-pointer rounded-sm transition-colors ${nav ? "py-1" : "py-0.5"} ${isSelected ? "bg-primary text-primary-foreground" : nav ? "text-foreground hover:bg-muted" : "hover:bg-muted"}`,
|
|
27534
27566
|
style: { paddingLeft: depth * indent + 8 },
|
|
27535
27567
|
onClick: handleClick,
|
|
27536
27568
|
role: "treeitem",
|
|
27569
|
+
"aria-selected": isSelected,
|
|
27537
27570
|
"aria-expanded": hasChildren ? expanded : void 0,
|
|
27538
27571
|
children: [
|
|
27539
|
-
hasChildren ? /* @__PURE__ */ jsx(
|
|
27572
|
+
hasChildren ? /* @__PURE__ */ jsx(Box, { onClick: handleChevron, className: "flex items-center flex-shrink-0", role: "button", "aria-label": expanded ? "Collapse" : "Expand", children: /* @__PURE__ */ jsx(
|
|
27540
27573
|
Icon,
|
|
27541
27574
|
{
|
|
27542
27575
|
name: expanded ? "chevron-down" : "chevron-right",
|
|
27543
27576
|
size: "xs",
|
|
27544
|
-
className: "text-[var(--color-muted-foreground)]
|
|
27577
|
+
className: isSelected ? "text-inherit" : "text-[var(--color-muted-foreground)]"
|
|
27545
27578
|
}
|
|
27546
|
-
) : /* @__PURE__ */ jsx(Box, { style: { width: 12, flexShrink: 0 } }),
|
|
27579
|
+
) }) : /* @__PURE__ */ jsx(Box, { style: { width: 12, flexShrink: 0 } }),
|
|
27547
27580
|
/* @__PURE__ */ jsx(
|
|
27548
27581
|
Icon,
|
|
27549
27582
|
{
|
|
27550
|
-
name: item.icon
|
|
27583
|
+
name: item.icon || (nav ? "file-text" : hasChildren ? expanded ? "folder-open" : "folder" : "file"),
|
|
27551
27584
|
size: "xs",
|
|
27552
|
-
className: hasChildren ? "text-[var(--color-
|
|
27585
|
+
className: isSelected ? "text-inherit" : nav || !hasChildren ? "text-[var(--color-muted-foreground)]" : "text-[var(--color-warning)]"
|
|
27553
27586
|
}
|
|
27554
27587
|
),
|
|
27555
|
-
/* @__PURE__ */ jsx(
|
|
27588
|
+
/* @__PURE__ */ jsx(
|
|
27589
|
+
Typography,
|
|
27590
|
+
{
|
|
27591
|
+
variant: "caption",
|
|
27592
|
+
className: `truncate ${nav ? "text-sm" : "font-mono text-xs"} !text-inherit ${isSelected ? "font-semibold" : ""}`,
|
|
27593
|
+
children: item.label
|
|
27594
|
+
}
|
|
27595
|
+
),
|
|
27596
|
+
onNodeAction && /* @__PURE__ */ jsx(
|
|
27597
|
+
Box,
|
|
27598
|
+
{
|
|
27599
|
+
onClick: handleAction,
|
|
27600
|
+
role: "button",
|
|
27601
|
+
"aria-label": nodeActionLabel ?? "Node action",
|
|
27602
|
+
title: nodeActionLabel,
|
|
27603
|
+
className: `ml-auto flex-shrink-0 rounded-sm p-0.5 opacity-0 group-hover/treerow:opacity-100 transition-opacity ${isSelected ? "hover:bg-primary-foreground/20" : "hover:bg-border"}`,
|
|
27604
|
+
children: /* @__PURE__ */ jsx(Icon, { name: nodeActionIcon ?? "plus", size: "xs", className: "text-inherit" })
|
|
27605
|
+
}
|
|
27606
|
+
)
|
|
27556
27607
|
]
|
|
27557
27608
|
}
|
|
27558
27609
|
),
|
|
@@ -27563,47 +27614,116 @@ var init_FileTree = __esm({
|
|
|
27563
27614
|
depth: depth + 1,
|
|
27564
27615
|
indent,
|
|
27565
27616
|
childrenByParent,
|
|
27566
|
-
onNodeSelect
|
|
27617
|
+
onNodeSelect,
|
|
27618
|
+
onNodeAction,
|
|
27619
|
+
nodeActionIcon,
|
|
27620
|
+
nodeActionLabel,
|
|
27621
|
+
selectedId,
|
|
27622
|
+
look,
|
|
27623
|
+
isExpanded,
|
|
27624
|
+
onToggle
|
|
27567
27625
|
},
|
|
27568
27626
|
child.id
|
|
27569
27627
|
)) })
|
|
27570
27628
|
] });
|
|
27571
27629
|
};
|
|
27630
|
+
FlatFileTree = ({
|
|
27631
|
+
items,
|
|
27632
|
+
selectedId,
|
|
27633
|
+
look = "files",
|
|
27634
|
+
onNodeSelect,
|
|
27635
|
+
onNodeAction,
|
|
27636
|
+
nodeActionIcon,
|
|
27637
|
+
nodeActionLabel,
|
|
27638
|
+
className,
|
|
27639
|
+
indent = 16
|
|
27640
|
+
}) => {
|
|
27641
|
+
const [overrides, setOverrides] = useState(() => /* @__PURE__ */ new Map());
|
|
27642
|
+
const byId = React87__default.useMemo(() => new Map(items.map((node) => [node.id, node])), [items]);
|
|
27643
|
+
const selectedAncestors = React87__default.useMemo(() => ancestorsOf(selectedId, byId), [selectedId, byId]);
|
|
27644
|
+
const lastSelectedRef = React87__default.useRef(selectedId);
|
|
27645
|
+
React87__default.useEffect(() => {
|
|
27646
|
+
if (selectedId === lastSelectedRef.current) return;
|
|
27647
|
+
lastSelectedRef.current = selectedId;
|
|
27648
|
+
setOverrides((prev) => {
|
|
27649
|
+
if (![...selectedAncestors].some((a) => prev.get(a) === false)) return prev;
|
|
27650
|
+
const next = new Map(prev);
|
|
27651
|
+
for (const a of selectedAncestors) if (next.get(a) === false) next.delete(a);
|
|
27652
|
+
return next;
|
|
27653
|
+
});
|
|
27654
|
+
}, [selectedId, selectedAncestors]);
|
|
27655
|
+
const isExpanded = useCallback(
|
|
27656
|
+
(id, depth) => overrides.get(id) ?? (depth < 1 || selectedAncestors.has(id)),
|
|
27657
|
+
[overrides, selectedAncestors]
|
|
27658
|
+
);
|
|
27659
|
+
const onToggle = useCallback((id, effective) => {
|
|
27660
|
+
setOverrides((prev) => {
|
|
27661
|
+
const next = new Map(prev);
|
|
27662
|
+
next.set(id, !effective);
|
|
27663
|
+
return next;
|
|
27664
|
+
});
|
|
27665
|
+
}, []);
|
|
27666
|
+
if (items.length === 0) return null;
|
|
27667
|
+
const ids = new Set(items.map((node) => node.id));
|
|
27668
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
27669
|
+
const roots = [];
|
|
27670
|
+
for (const item of items) {
|
|
27671
|
+
if (item.parentId && ids.has(item.parentId)) {
|
|
27672
|
+
const siblings = childrenByParent.get(item.parentId);
|
|
27673
|
+
if (siblings) siblings.push(item);
|
|
27674
|
+
else childrenByParent.set(item.parentId, [item]);
|
|
27675
|
+
} else {
|
|
27676
|
+
roots.push(item);
|
|
27677
|
+
}
|
|
27678
|
+
}
|
|
27679
|
+
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: roots.map((item) => /* @__PURE__ */ jsx(
|
|
27680
|
+
FlatTreeNodeItem,
|
|
27681
|
+
{
|
|
27682
|
+
item,
|
|
27683
|
+
depth: 0,
|
|
27684
|
+
indent,
|
|
27685
|
+
childrenByParent,
|
|
27686
|
+
onNodeSelect,
|
|
27687
|
+
onNodeAction,
|
|
27688
|
+
nodeActionIcon,
|
|
27689
|
+
nodeActionLabel,
|
|
27690
|
+
selectedId,
|
|
27691
|
+
look,
|
|
27692
|
+
isExpanded,
|
|
27693
|
+
onToggle
|
|
27694
|
+
},
|
|
27695
|
+
item.id
|
|
27696
|
+
)) });
|
|
27697
|
+
};
|
|
27572
27698
|
FileTree = ({
|
|
27573
27699
|
tree,
|
|
27574
27700
|
items,
|
|
27575
27701
|
selectedPath,
|
|
27702
|
+
selectedId,
|
|
27703
|
+
look = "files",
|
|
27576
27704
|
onFileSelect,
|
|
27577
27705
|
onNodeSelect,
|
|
27706
|
+
onNodeAction,
|
|
27707
|
+
nodeActionIcon,
|
|
27708
|
+
nodeActionLabel,
|
|
27578
27709
|
className,
|
|
27579
27710
|
indent = 16
|
|
27580
27711
|
}) => {
|
|
27581
27712
|
if (items) {
|
|
27582
|
-
|
|
27583
|
-
|
|
27584
|
-
const childrenByParent = /* @__PURE__ */ new Map();
|
|
27585
|
-
const roots = [];
|
|
27586
|
-
for (const item of items) {
|
|
27587
|
-
if (item.parentId && ids.has(item.parentId)) {
|
|
27588
|
-
const siblings = childrenByParent.get(item.parentId);
|
|
27589
|
-
if (siblings) siblings.push(item);
|
|
27590
|
-
else childrenByParent.set(item.parentId, [item]);
|
|
27591
|
-
} else {
|
|
27592
|
-
roots.push(item);
|
|
27593
|
-
}
|
|
27594
|
-
}
|
|
27595
|
-
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: roots.map((item) => /* @__PURE__ */ jsx(
|
|
27596
|
-
FlatTreeNodeItem,
|
|
27713
|
+
return /* @__PURE__ */ jsx(
|
|
27714
|
+
FlatFileTree,
|
|
27597
27715
|
{
|
|
27598
|
-
|
|
27599
|
-
|
|
27600
|
-
|
|
27601
|
-
childrenByParent,
|
|
27716
|
+
items,
|
|
27717
|
+
selectedId,
|
|
27718
|
+
look,
|
|
27602
27719
|
onNodeSelect,
|
|
27603
|
-
|
|
27604
|
-
|
|
27605
|
-
|
|
27606
|
-
|
|
27720
|
+
onNodeAction,
|
|
27721
|
+
nodeActionIcon,
|
|
27722
|
+
nodeActionLabel,
|
|
27723
|
+
className,
|
|
27724
|
+
indent
|
|
27725
|
+
}
|
|
27726
|
+
);
|
|
27607
27727
|
}
|
|
27608
27728
|
if (!tree || tree.length === 0) return null;
|
|
27609
27729
|
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: tree.map((node) => /* @__PURE__ */ jsx(
|
|
@@ -33068,6 +33188,33 @@ var init_Lightbox = __esm({
|
|
|
33068
33188
|
Lightbox.displayName = "Lightbox";
|
|
33069
33189
|
}
|
|
33070
33190
|
});
|
|
33191
|
+
|
|
33192
|
+
// lib/relationLabel.ts
|
|
33193
|
+
function relationLabel(value) {
|
|
33194
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date)
|
|
33195
|
+
return null;
|
|
33196
|
+
for (const key of ["name", "title", "label"]) {
|
|
33197
|
+
const candidate = value[key];
|
|
33198
|
+
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
33199
|
+
}
|
|
33200
|
+
const id = value.id;
|
|
33201
|
+
return id !== void 0 && id !== null ? String(id) : null;
|
|
33202
|
+
}
|
|
33203
|
+
function relationDisplayLabels(value, options) {
|
|
33204
|
+
if (value === void 0 || value === null || value === "") return [];
|
|
33205
|
+
if (Array.isArray(value)) {
|
|
33206
|
+
return value.flatMap((item) => relationDisplayLabels(item, options));
|
|
33207
|
+
}
|
|
33208
|
+
const hydrated = relationLabel(value);
|
|
33209
|
+
if (hydrated !== null) return [hydrated];
|
|
33210
|
+
const raw = String(value);
|
|
33211
|
+
const match = options?.find((opt) => opt.value === raw);
|
|
33212
|
+
return [match ? match.label : raw];
|
|
33213
|
+
}
|
|
33214
|
+
var init_relationLabel = __esm({
|
|
33215
|
+
"lib/relationLabel.ts"() {
|
|
33216
|
+
}
|
|
33217
|
+
});
|
|
33071
33218
|
function renderIconInput3(icon, props) {
|
|
33072
33219
|
return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
|
|
33073
33220
|
}
|
|
@@ -33385,6 +33532,7 @@ var init_TableView = __esm({
|
|
|
33385
33532
|
"use client";
|
|
33386
33533
|
init_cn();
|
|
33387
33534
|
init_format();
|
|
33535
|
+
init_relationLabel();
|
|
33388
33536
|
init_getNestedValue();
|
|
33389
33537
|
init_useEventBus();
|
|
33390
33538
|
init_Box();
|
|
@@ -33398,7 +33546,13 @@ var init_TableView = __esm({
|
|
|
33398
33546
|
init_Menu();
|
|
33399
33547
|
init_useDataDnd();
|
|
33400
33548
|
tableViewLog = createLogger("almadar:ui:table-view");
|
|
33401
|
-
formatCell = (value, format) =>
|
|
33549
|
+
formatCell = (value, format) => {
|
|
33550
|
+
if (value !== null && value !== void 0 && typeof value === "object" && !(value instanceof Date)) {
|
|
33551
|
+
const labels = relationDisplayLabels(value);
|
|
33552
|
+
if (labels.length > 0) return labels.join(", ");
|
|
33553
|
+
}
|
|
33554
|
+
return formatValue(value, format);
|
|
33555
|
+
};
|
|
33402
33556
|
MAX_MEASURED_COL_CH = 32;
|
|
33403
33557
|
BADGE_CHROME_CH = 4;
|
|
33404
33558
|
alignClass = {
|
|
@@ -37013,6 +37167,35 @@ var init_RichTextEditor = __esm({
|
|
|
37013
37167
|
document.execCommand("createLink", false, safe);
|
|
37014
37168
|
afterEdit();
|
|
37015
37169
|
}, [afterEdit, t, toolbar.link]);
|
|
37170
|
+
const imageInputRef = useRef(null);
|
|
37171
|
+
const savedRangeRef = useRef(null);
|
|
37172
|
+
const execImage = useCallback(() => {
|
|
37173
|
+
const root = ref.current;
|
|
37174
|
+
const sel = window.getSelection();
|
|
37175
|
+
savedRangeRef.current = root && sel && sel.rangeCount > 0 && root.contains(sel.anchorNode) ? sel.getRangeAt(0).cloneRange() : null;
|
|
37176
|
+
imageInputRef.current?.click();
|
|
37177
|
+
}, []);
|
|
37178
|
+
const handleImageFile = useCallback((e) => {
|
|
37179
|
+
const file = e.target.files?.[0];
|
|
37180
|
+
e.target.value = "";
|
|
37181
|
+
if (!file) return;
|
|
37182
|
+
const reader = new FileReader();
|
|
37183
|
+
reader.onload = () => {
|
|
37184
|
+
const url = typeof reader.result === "string" ? reader.result : "";
|
|
37185
|
+
if (!url.startsWith("data:image/")) return;
|
|
37186
|
+
const root = ref.current;
|
|
37187
|
+
if (!root) return;
|
|
37188
|
+
root.focus();
|
|
37189
|
+
const sel = window.getSelection();
|
|
37190
|
+
if (sel && savedRangeRef.current && root.contains(savedRangeRef.current.startContainer)) {
|
|
37191
|
+
sel.removeAllRanges();
|
|
37192
|
+
sel.addRange(savedRangeRef.current);
|
|
37193
|
+
}
|
|
37194
|
+
document.execCommand("insertImage", false, url);
|
|
37195
|
+
afterEdit();
|
|
37196
|
+
};
|
|
37197
|
+
reader.readAsDataURL(file);
|
|
37198
|
+
}, [afterEdit]);
|
|
37016
37199
|
const execRule = useCallback(() => {
|
|
37017
37200
|
document.execCommand("insertHorizontalRule", false);
|
|
37018
37201
|
afterEdit();
|
|
@@ -37025,6 +37208,18 @@ var init_RichTextEditor = __esm({
|
|
|
37025
37208
|
}
|
|
37026
37209
|
return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col gap-2", className), children: [
|
|
37027
37210
|
/* @__PURE__ */ jsx(RichTextStyles, {}),
|
|
37211
|
+
/* @__PURE__ */ jsx(
|
|
37212
|
+
"input",
|
|
37213
|
+
{
|
|
37214
|
+
ref: imageInputRef,
|
|
37215
|
+
type: "file",
|
|
37216
|
+
accept: "image/*",
|
|
37217
|
+
className: "hidden",
|
|
37218
|
+
"aria-hidden": "true",
|
|
37219
|
+
tabIndex: -1,
|
|
37220
|
+
onChange: handleImageFile
|
|
37221
|
+
}
|
|
37222
|
+
),
|
|
37028
37223
|
showToolbar && /* @__PURE__ */ jsxs(
|
|
37029
37224
|
Box,
|
|
37030
37225
|
{
|
|
@@ -37050,6 +37245,7 @@ var init_RichTextEditor = __esm({
|
|
|
37050
37245
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Quote, label: t("richTextEditor.quote"), active: toolbar.block === "blockquote", onExec: () => execBlock("blockquote") }),
|
|
37051
37246
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Code, label: t("richTextEditor.code"), active: toolbar.block === "pre", onExec: () => execBlock("pre") }),
|
|
37052
37247
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Link$1, label: toolbar.link ? t("richTextEditor.removeLink") : t("richTextEditor.link"), active: toolbar.link, onExec: execLink }),
|
|
37248
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Image$1, label: t("richTextEditor.image"), onExec: execImage }),
|
|
37053
37249
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Minus, label: t("richTextEditor.divider"), onExec: execRule })
|
|
37054
37250
|
]
|
|
37055
37251
|
}
|
|
@@ -37090,6 +37286,8 @@ function DocumentPanel({
|
|
|
37090
37286
|
id,
|
|
37091
37287
|
title,
|
|
37092
37288
|
subtitle,
|
|
37289
|
+
coverImage,
|
|
37290
|
+
icon,
|
|
37093
37291
|
value,
|
|
37094
37292
|
actions,
|
|
37095
37293
|
maxInlineActions,
|
|
@@ -37165,62 +37363,74 @@ function DocumentPanel({
|
|
|
37165
37363
|
const emitWithId = (event) => () => {
|
|
37166
37364
|
if (event) eventBus.emit(`UI:${event}`, { id: recordId });
|
|
37167
37365
|
};
|
|
37168
|
-
return /* @__PURE__ */
|
|
37169
|
-
/* @__PURE__ */
|
|
37170
|
-
|
|
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,
|
|
37184
|
-
{
|
|
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
|
-
}))
|
|
37207
|
-
}
|
|
37208
|
-
)
|
|
37209
|
-
] }) })
|
|
37210
|
-
] }),
|
|
37211
|
-
editing ? /* @__PURE__ */ jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsx(
|
|
37212
|
-
Box,
|
|
37366
|
+
return /* @__PURE__ */ jsxs(Card, { variant: "elevated", className: cn("w-full overflow-hidden", className), children: [
|
|
37367
|
+
coverImage ? /* @__PURE__ */ jsx(Box, { className: "h-44 w-full sm:h-52", "data-testid": "document-cover", children: /* @__PURE__ */ jsx(
|
|
37368
|
+
"img",
|
|
37213
37369
|
{
|
|
37214
|
-
|
|
37215
|
-
|
|
37216
|
-
|
|
37217
|
-
|
|
37218
|
-
|
|
37219
|
-
|
|
37220
|
-
|
|
37221
|
-
|
|
37222
|
-
|
|
37223
|
-
|
|
37370
|
+
src: coverImage,
|
|
37371
|
+
alt: "",
|
|
37372
|
+
"aria-hidden": "true",
|
|
37373
|
+
className: "h-full w-full object-cover"
|
|
37374
|
+
}
|
|
37375
|
+
) }) : null,
|
|
37376
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "p-6 sm:p-8", children: [
|
|
37377
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
37378
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
37379
|
+
icon ? /* @__PURE__ */ jsx(Box, { className: "text-muted-foreground", "data-testid": "document-icon", children: renderIconInput4(icon, { size: "lg" }) }) : null,
|
|
37380
|
+
titleNode,
|
|
37381
|
+
subtitle ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
37382
|
+
] }),
|
|
37383
|
+
/* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37384
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
37385
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
37386
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37387
|
+
editEvent && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
37388
|
+
/* @__PURE__ */ jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
37389
|
+
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
37390
|
+
] }),
|
|
37391
|
+
inlineActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
37392
|
+
Button,
|
|
37393
|
+
{
|
|
37394
|
+
variant: "primary",
|
|
37395
|
+
size: "sm",
|
|
37396
|
+
onClick: () => fireAction(action),
|
|
37397
|
+
"data-testid": `action-${action.event}`,
|
|
37398
|
+
children: [
|
|
37399
|
+
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
37400
|
+
action.label
|
|
37401
|
+
]
|
|
37402
|
+
},
|
|
37403
|
+
idx
|
|
37404
|
+
)),
|
|
37405
|
+
menuActions.length > 0 && /* @__PURE__ */ jsx(
|
|
37406
|
+
Menu,
|
|
37407
|
+
{
|
|
37408
|
+
position: "bottom-end",
|
|
37409
|
+
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" }) }),
|
|
37410
|
+
items: menuActions.map((action) => ({
|
|
37411
|
+
label: action.label,
|
|
37412
|
+
icon: action.icon,
|
|
37413
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
37414
|
+
onClick: () => fireAction(action)
|
|
37415
|
+
}))
|
|
37416
|
+
}
|
|
37417
|
+
)
|
|
37418
|
+
] }) })
|
|
37419
|
+
] }),
|
|
37420
|
+
editing ? /* @__PURE__ */ jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsx(
|
|
37421
|
+
Box,
|
|
37422
|
+
{
|
|
37423
|
+
onClick: emitWithId(editEvent),
|
|
37424
|
+
className: cn(
|
|
37425
|
+
"rounded-md px-1 -mx-1 min-h-[16rem]",
|
|
37426
|
+
editEvent && "cursor-text transition-colors hover:bg-muted/30"
|
|
37427
|
+
),
|
|
37428
|
+
"data-testid": "document-body",
|
|
37429
|
+
children: value && value !== "" ? /* @__PURE__ */ jsx(RichTextEditor, { value, readOnly: true }) : /* @__PURE__ */ jsx(Typography, { variant: "body", color: "muted", children: placeholder ?? (t("documentPanel.placeholder") || "") })
|
|
37430
|
+
}
|
|
37431
|
+
)
|
|
37432
|
+
] })
|
|
37433
|
+
] });
|
|
37224
37434
|
}
|
|
37225
37435
|
var init_DocumentPanel = __esm({
|
|
37226
37436
|
"components/core/molecules/DocumentPanel.tsx"() {
|
|
@@ -37244,17 +37454,16 @@ function renderIconInput5(icon, props) {
|
|
|
37244
37454
|
function fieldName(field) {
|
|
37245
37455
|
return field.name ?? field.key ?? "";
|
|
37246
37456
|
}
|
|
37247
|
-
function
|
|
37248
|
-
if (value
|
|
37249
|
-
|
|
37250
|
-
|
|
37251
|
-
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
37457
|
+
function relationId(value) {
|
|
37458
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
|
|
37459
|
+
const id = value.id;
|
|
37460
|
+
if (id !== void 0 && id !== null) return String(id);
|
|
37252
37461
|
}
|
|
37253
|
-
|
|
37254
|
-
return id !== void 0 && id !== null ? String(id) : null;
|
|
37462
|
+
return String(value);
|
|
37255
37463
|
}
|
|
37256
37464
|
function fieldKind(field, value) {
|
|
37257
37465
|
if (field.kind) return field.kind;
|
|
37466
|
+
if (field.type === "image") return "image";
|
|
37258
37467
|
if (field.options && field.options.length > 0) return "select";
|
|
37259
37468
|
if (typeof value === "boolean" || field.format === "boolean") return "boolean";
|
|
37260
37469
|
if (Array.isArray(value) || relationLabel(value ?? null) !== null) return "readonly";
|
|
@@ -37264,6 +37473,7 @@ function DocumentDetails({
|
|
|
37264
37473
|
entity,
|
|
37265
37474
|
fields,
|
|
37266
37475
|
metaCommitEvent,
|
|
37476
|
+
relationEvent,
|
|
37267
37477
|
title,
|
|
37268
37478
|
className
|
|
37269
37479
|
}) {
|
|
@@ -37278,11 +37488,51 @@ function DocumentDetails({
|
|
|
37278
37488
|
if (!metaCommitEvent || next === current) return;
|
|
37279
37489
|
eventBus.emit(`UI:${metaCommitEvent}`, { id: recordId, patch: { id: recordId, [name]: next } });
|
|
37280
37490
|
};
|
|
37491
|
+
const relationChip = (item, name, key) => {
|
|
37492
|
+
const label = relationLabel(item) ?? humanizeEnumValue(String(item));
|
|
37493
|
+
if (!relationEvent) {
|
|
37494
|
+
return /* @__PURE__ */ jsx(Badge, { variant: "default", children: label }, key);
|
|
37495
|
+
}
|
|
37496
|
+
const emitClick = () => eventBus.emit(`UI:${relationEvent}`, { field: name, id: relationId(item), name: label });
|
|
37497
|
+
return /* @__PURE__ */ jsx(
|
|
37498
|
+
Badge,
|
|
37499
|
+
{
|
|
37500
|
+
variant: "default",
|
|
37501
|
+
role: "button",
|
|
37502
|
+
tabIndex: 0,
|
|
37503
|
+
className: "cursor-pointer transition-colors hover:bg-accent",
|
|
37504
|
+
onClick: emitClick,
|
|
37505
|
+
onKeyDown: (e) => {
|
|
37506
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
37507
|
+
e.preventDefault();
|
|
37508
|
+
emitClick();
|
|
37509
|
+
}
|
|
37510
|
+
},
|
|
37511
|
+
"data-testid": `relation-chip-${name}`,
|
|
37512
|
+
children: label
|
|
37513
|
+
},
|
|
37514
|
+
key
|
|
37515
|
+
);
|
|
37516
|
+
};
|
|
37281
37517
|
const renderValue = (field) => {
|
|
37282
37518
|
const name = fieldName(field);
|
|
37283
37519
|
const raw = getNestedValue(entity ?? {}, name);
|
|
37284
37520
|
const kind = fieldKind(field, raw);
|
|
37285
37521
|
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
37522
|
+
if (kind === "image") {
|
|
37523
|
+
const url = typeof raw === "string" ? raw : "";
|
|
37524
|
+
if (!url) return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
37525
|
+
return /* @__PURE__ */ jsx(
|
|
37526
|
+
"img",
|
|
37527
|
+
{
|
|
37528
|
+
src: url,
|
|
37529
|
+
alt: label,
|
|
37530
|
+
loading: "lazy",
|
|
37531
|
+
className: "max-h-32 w-full rounded-md border border-border object-cover",
|
|
37532
|
+
"data-testid": `document-property-image-${name}`
|
|
37533
|
+
}
|
|
37534
|
+
);
|
|
37535
|
+
}
|
|
37286
37536
|
if (kind === "boolean") {
|
|
37287
37537
|
return /* @__PURE__ */ jsx(
|
|
37288
37538
|
Switch,
|
|
@@ -37312,9 +37562,12 @@ function DocumentDetails({
|
|
|
37312
37562
|
if (raw.length === 0) {
|
|
37313
37563
|
return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
37314
37564
|
}
|
|
37315
|
-
return /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) =>
|
|
37565
|
+
return /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) => relationChip(item, name, i)) });
|
|
37316
37566
|
}
|
|
37317
|
-
|
|
37567
|
+
if (raw !== void 0 && raw !== null && raw !== "" && relationLabel(raw) !== null) {
|
|
37568
|
+
return relationChip(raw, name);
|
|
37569
|
+
}
|
|
37570
|
+
const shown2 = raw === void 0 || raw === null || raw === "" ? "\u2014" : formatValue(raw, field.format);
|
|
37318
37571
|
return /* @__PURE__ */ jsx(Typography, { variant: "small", className: "break-words", children: shown2 });
|
|
37319
37572
|
}
|
|
37320
37573
|
if (fieldDraft?.name === name) {
|
|
@@ -37383,6 +37636,7 @@ var init_DocumentDetails = __esm({
|
|
|
37383
37636
|
init_cn();
|
|
37384
37637
|
init_format();
|
|
37385
37638
|
init_getNestedValue();
|
|
37639
|
+
init_relationLabel();
|
|
37386
37640
|
init_useEventBus();
|
|
37387
37641
|
init_Box();
|
|
37388
37642
|
init_Stack();
|
|
@@ -42377,7 +42631,18 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
42377
42631
|
if (value === void 0 || value === null) return "\u2014";
|
|
42378
42632
|
const str = String(value);
|
|
42379
42633
|
switch (fieldType) {
|
|
42380
|
-
case "image":
|
|
42634
|
+
case "image": {
|
|
42635
|
+
if (!str) return "\u2014";
|
|
42636
|
+
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
42637
|
+
"img",
|
|
42638
|
+
{
|
|
42639
|
+
src: str,
|
|
42640
|
+
alt: formatFieldLabel(fieldName2),
|
|
42641
|
+
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
42642
|
+
loading: "lazy"
|
|
42643
|
+
}
|
|
42644
|
+
) });
|
|
42645
|
+
}
|
|
42381
42646
|
case "url": {
|
|
42382
42647
|
if (str.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str.startsWith("data:image/")) {
|
|
42383
42648
|
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
@@ -42390,7 +42655,7 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
42390
42655
|
}
|
|
42391
42656
|
) });
|
|
42392
42657
|
}
|
|
42393
|
-
if (
|
|
42658
|
+
if (/^https?:\/\//i.test(str)) {
|
|
42394
42659
|
return /* @__PURE__ */ jsx(
|
|
42395
42660
|
"a",
|
|
42396
42661
|
{
|
|
@@ -42476,8 +42741,10 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
42476
42741
|
return str;
|
|
42477
42742
|
}
|
|
42478
42743
|
case "relation": {
|
|
42479
|
-
const
|
|
42480
|
-
|
|
42744
|
+
const labels = relationDisplayLabels(value, meta?.options);
|
|
42745
|
+
if (labels.length === 0) return "\u2014";
|
|
42746
|
+
if (labels.length === 1) return labels[0];
|
|
42747
|
+
return /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: labels.map((label, i) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: label }, i)) });
|
|
42481
42748
|
}
|
|
42482
42749
|
case "file": {
|
|
42483
42750
|
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
@@ -42579,6 +42846,7 @@ var init_DetailPanel = __esm({
|
|
|
42579
42846
|
init_cn();
|
|
42580
42847
|
init_format();
|
|
42581
42848
|
init_getNestedValue();
|
|
42849
|
+
init_relationLabel();
|
|
42582
42850
|
init_useEventBus();
|
|
42583
42851
|
init_UploadDropZone();
|
|
42584
42852
|
formatFieldLabel = humanizeFieldName;
|
|
@@ -43237,6 +43505,8 @@ function determineInputType(field) {
|
|
|
43237
43505
|
return "url";
|
|
43238
43506
|
case "file":
|
|
43239
43507
|
return "file";
|
|
43508
|
+
case "image":
|
|
43509
|
+
return "image";
|
|
43240
43510
|
case "money":
|
|
43241
43511
|
return "currency";
|
|
43242
43512
|
case "number":
|
|
@@ -43836,6 +44106,50 @@ var init_Form = __esm({
|
|
|
43836
44106
|
}
|
|
43837
44107
|
}
|
|
43838
44108
|
);
|
|
44109
|
+
case "image": {
|
|
44110
|
+
const imageUrl = typeof currentValue === "string" ? currentValue : "";
|
|
44111
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
44112
|
+
imageUrl ? /* @__PURE__ */ jsx(
|
|
44113
|
+
"img",
|
|
44114
|
+
{
|
|
44115
|
+
src: imageUrl,
|
|
44116
|
+
alt: "",
|
|
44117
|
+
"aria-hidden": "true",
|
|
44118
|
+
className: "h-24 w-full max-w-xs rounded-md border border-border object-cover",
|
|
44119
|
+
"data-testid": `image-preview-${fieldName2}`
|
|
44120
|
+
}
|
|
44121
|
+
) : null,
|
|
44122
|
+
/* @__PURE__ */ jsx(
|
|
44123
|
+
UploadDropZone,
|
|
44124
|
+
{
|
|
44125
|
+
accept: "image/*",
|
|
44126
|
+
maxFiles: 1,
|
|
44127
|
+
maxSize: 2 * 1024 * 1024,
|
|
44128
|
+
disabled: isLoading,
|
|
44129
|
+
onFiles: (files) => {
|
|
44130
|
+
const f3 = files[0];
|
|
44131
|
+
if (!f3) return;
|
|
44132
|
+
const reader = new FileReader();
|
|
44133
|
+
reader.onload = () => handleChange(
|
|
44134
|
+
fieldName2,
|
|
44135
|
+
typeof reader.result === "string" ? reader.result : ""
|
|
44136
|
+
);
|
|
44137
|
+
reader.readAsDataURL(f3);
|
|
44138
|
+
}
|
|
44139
|
+
}
|
|
44140
|
+
),
|
|
44141
|
+
/* @__PURE__ */ jsx(
|
|
44142
|
+
Input,
|
|
44143
|
+
{
|
|
44144
|
+
...commonProps,
|
|
44145
|
+
type: "url",
|
|
44146
|
+
placeholder: t("form.imageUrlFallback"),
|
|
44147
|
+
value: imageUrl,
|
|
44148
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
44149
|
+
}
|
|
44150
|
+
)
|
|
44151
|
+
] });
|
|
44152
|
+
}
|
|
43839
44153
|
case "date":
|
|
43840
44154
|
return /* @__PURE__ */ jsx(
|
|
43841
44155
|
Input,
|