@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/avl/index.js
CHANGED
|
@@ -27152,6 +27152,7 @@ var init_DashboardLayout = __esm({
|
|
|
27152
27152
|
onNotificationClick,
|
|
27153
27153
|
showThemeToggle = true,
|
|
27154
27154
|
sidebarFooter,
|
|
27155
|
+
sidebarContent,
|
|
27155
27156
|
onSignOut: onSignOutProp,
|
|
27156
27157
|
currentPath,
|
|
27157
27158
|
layoutMode = "sidebar",
|
|
@@ -27277,7 +27278,11 @@ var init_DashboardLayout = __esm({
|
|
|
27277
27278
|
{
|
|
27278
27279
|
as: "nav",
|
|
27279
27280
|
gap: "none",
|
|
27280
|
-
className: cn(
|
|
27281
|
+
className: cn(
|
|
27282
|
+
"py-4 space-y-1 overflow-y-auto",
|
|
27283
|
+
sidebarContent && !isRail ? "shrink-0" : "flex-1",
|
|
27284
|
+
isRail ? "px-2" : "px-3"
|
|
27285
|
+
),
|
|
27281
27286
|
children: navItems.map((item) => /* @__PURE__ */ jsx(
|
|
27282
27287
|
NavLink,
|
|
27283
27288
|
{
|
|
@@ -27289,6 +27294,7 @@ var init_DashboardLayout = __esm({
|
|
|
27289
27294
|
))
|
|
27290
27295
|
}
|
|
27291
27296
|
),
|
|
27297
|
+
sidebarContent && !isRail && /* @__PURE__ */ jsx(Box, { className: "flex-1 overflow-y-auto border-t border-border dark:border-border px-2 py-3", children: sidebarContent }),
|
|
27292
27298
|
sidebarFooter && /* @__PURE__ */ jsx(Box, { className: "p-4 border-t border-border dark:border-border", children: sidebarFooter })
|
|
27293
27299
|
]
|
|
27294
27300
|
}
|
|
@@ -29698,7 +29704,17 @@ function fileIcon(name) {
|
|
|
29698
29704
|
return "file";
|
|
29699
29705
|
}
|
|
29700
29706
|
}
|
|
29701
|
-
|
|
29707
|
+
function ancestorsOf(id, byId) {
|
|
29708
|
+
const out = /* @__PURE__ */ new Set();
|
|
29709
|
+
if (!id) return out;
|
|
29710
|
+
let cur = byId.get(id)?.parentId;
|
|
29711
|
+
while (cur && byId.has(cur) && !out.has(cur)) {
|
|
29712
|
+
out.add(cur);
|
|
29713
|
+
cur = byId.get(cur)?.parentId;
|
|
29714
|
+
}
|
|
29715
|
+
return out;
|
|
29716
|
+
}
|
|
29717
|
+
var TreeNodeItem, FlatTreeNodeItem, FlatFileTree, FileTree;
|
|
29702
29718
|
var init_FileTree = __esm({
|
|
29703
29719
|
"components/core/molecules/FileTree.tsx"() {
|
|
29704
29720
|
"use client";
|
|
@@ -29789,42 +29805,77 @@ var init_FileTree = __esm({
|
|
|
29789
29805
|
indent,
|
|
29790
29806
|
childrenByParent,
|
|
29791
29807
|
onNodeSelect,
|
|
29792
|
-
|
|
29808
|
+
onNodeAction,
|
|
29809
|
+
nodeActionIcon,
|
|
29810
|
+
nodeActionLabel,
|
|
29811
|
+
selectedId,
|
|
29812
|
+
look,
|
|
29813
|
+
isExpanded,
|
|
29814
|
+
onToggle
|
|
29793
29815
|
}) => {
|
|
29794
|
-
const [expanded, setExpanded] = useState(defaultExpanded || depth < 1);
|
|
29795
29816
|
const children = childrenByParent.get(item.id);
|
|
29796
29817
|
const hasChildren = !!children && children.length > 0;
|
|
29818
|
+
const expanded = hasChildren && isExpanded(item.id, depth);
|
|
29819
|
+
const isSelected = selectedId !== void 0 && selectedId !== "" && item.id === selectedId;
|
|
29820
|
+
const nav = look === "nav";
|
|
29797
29821
|
const handleClick = useCallback(() => {
|
|
29798
|
-
if (hasChildren)
|
|
29822
|
+
if (hasChildren && !onNodeSelect) onToggle(item.id, expanded);
|
|
29799
29823
|
onNodeSelect?.(item.id);
|
|
29800
|
-
}, [hasChildren, item.id, onNodeSelect]);
|
|
29824
|
+
}, [hasChildren, expanded, item.id, onNodeSelect, onToggle]);
|
|
29825
|
+
const handleChevron = useCallback((e) => {
|
|
29826
|
+
e.stopPropagation();
|
|
29827
|
+
onToggle(item.id, expanded);
|
|
29828
|
+
}, [item.id, expanded, onToggle]);
|
|
29829
|
+
const handleAction = useCallback((e) => {
|
|
29830
|
+
e.stopPropagation();
|
|
29831
|
+
onNodeAction?.(item.id);
|
|
29832
|
+
}, [item.id, onNodeAction]);
|
|
29801
29833
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
29802
29834
|
/* @__PURE__ */ jsxs(
|
|
29803
29835
|
Box,
|
|
29804
29836
|
{
|
|
29805
|
-
className:
|
|
29837
|
+
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"}`,
|
|
29806
29838
|
style: { paddingLeft: depth * indent + 8 },
|
|
29807
29839
|
onClick: handleClick,
|
|
29808
29840
|
role: "treeitem",
|
|
29841
|
+
"aria-selected": isSelected,
|
|
29809
29842
|
"aria-expanded": hasChildren ? expanded : void 0,
|
|
29810
29843
|
children: [
|
|
29811
|
-
hasChildren ? /* @__PURE__ */ jsx(
|
|
29844
|
+
hasChildren ? /* @__PURE__ */ jsx(Box, { onClick: handleChevron, className: "flex items-center flex-shrink-0", role: "button", "aria-label": expanded ? "Collapse" : "Expand", children: /* @__PURE__ */ jsx(
|
|
29812
29845
|
Icon,
|
|
29813
29846
|
{
|
|
29814
29847
|
name: expanded ? "chevron-down" : "chevron-right",
|
|
29815
29848
|
size: "xs",
|
|
29816
|
-
className: "text-[var(--color-muted-foreground)]
|
|
29849
|
+
className: isSelected ? "text-inherit" : "text-[var(--color-muted-foreground)]"
|
|
29817
29850
|
}
|
|
29818
|
-
) : /* @__PURE__ */ jsx(Box, { style: { width: 12, flexShrink: 0 } }),
|
|
29851
|
+
) }) : /* @__PURE__ */ jsx(Box, { style: { width: 12, flexShrink: 0 } }),
|
|
29819
29852
|
/* @__PURE__ */ jsx(
|
|
29820
29853
|
Icon,
|
|
29821
29854
|
{
|
|
29822
|
-
name: item.icon
|
|
29855
|
+
name: item.icon || (nav ? "file-text" : hasChildren ? expanded ? "folder-open" : "folder" : "file"),
|
|
29823
29856
|
size: "xs",
|
|
29824
|
-
className: hasChildren ? "text-[var(--color-
|
|
29857
|
+
className: isSelected ? "text-inherit" : nav || !hasChildren ? "text-[var(--color-muted-foreground)]" : "text-[var(--color-warning)]"
|
|
29825
29858
|
}
|
|
29826
29859
|
),
|
|
29827
|
-
/* @__PURE__ */ jsx(
|
|
29860
|
+
/* @__PURE__ */ jsx(
|
|
29861
|
+
Typography,
|
|
29862
|
+
{
|
|
29863
|
+
variant: "caption",
|
|
29864
|
+
className: `truncate ${nav ? "text-sm" : "font-mono text-xs"} !text-inherit ${isSelected ? "font-semibold" : ""}`,
|
|
29865
|
+
children: item.label
|
|
29866
|
+
}
|
|
29867
|
+
),
|
|
29868
|
+
onNodeAction && /* @__PURE__ */ jsx(
|
|
29869
|
+
Box,
|
|
29870
|
+
{
|
|
29871
|
+
onClick: handleAction,
|
|
29872
|
+
role: "button",
|
|
29873
|
+
"aria-label": nodeActionLabel ?? "Node action",
|
|
29874
|
+
title: nodeActionLabel,
|
|
29875
|
+
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"}`,
|
|
29876
|
+
children: /* @__PURE__ */ jsx(Icon, { name: nodeActionIcon ?? "plus", size: "xs", className: "text-inherit" })
|
|
29877
|
+
}
|
|
29878
|
+
)
|
|
29828
29879
|
]
|
|
29829
29880
|
}
|
|
29830
29881
|
),
|
|
@@ -29835,47 +29886,116 @@ var init_FileTree = __esm({
|
|
|
29835
29886
|
depth: depth + 1,
|
|
29836
29887
|
indent,
|
|
29837
29888
|
childrenByParent,
|
|
29838
|
-
onNodeSelect
|
|
29889
|
+
onNodeSelect,
|
|
29890
|
+
onNodeAction,
|
|
29891
|
+
nodeActionIcon,
|
|
29892
|
+
nodeActionLabel,
|
|
29893
|
+
selectedId,
|
|
29894
|
+
look,
|
|
29895
|
+
isExpanded,
|
|
29896
|
+
onToggle
|
|
29839
29897
|
},
|
|
29840
29898
|
child.id
|
|
29841
29899
|
)) })
|
|
29842
29900
|
] });
|
|
29843
29901
|
};
|
|
29902
|
+
FlatFileTree = ({
|
|
29903
|
+
items,
|
|
29904
|
+
selectedId,
|
|
29905
|
+
look = "files",
|
|
29906
|
+
onNodeSelect,
|
|
29907
|
+
onNodeAction,
|
|
29908
|
+
nodeActionIcon,
|
|
29909
|
+
nodeActionLabel,
|
|
29910
|
+
className,
|
|
29911
|
+
indent = 16
|
|
29912
|
+
}) => {
|
|
29913
|
+
const [overrides, setOverrides] = useState(() => /* @__PURE__ */ new Map());
|
|
29914
|
+
const byId = React94__default.useMemo(() => new Map(items.map((node) => [node.id, node])), [items]);
|
|
29915
|
+
const selectedAncestors = React94__default.useMemo(() => ancestorsOf(selectedId, byId), [selectedId, byId]);
|
|
29916
|
+
const lastSelectedRef = React94__default.useRef(selectedId);
|
|
29917
|
+
React94__default.useEffect(() => {
|
|
29918
|
+
if (selectedId === lastSelectedRef.current) return;
|
|
29919
|
+
lastSelectedRef.current = selectedId;
|
|
29920
|
+
setOverrides((prev) => {
|
|
29921
|
+
if (![...selectedAncestors].some((a) => prev.get(a) === false)) return prev;
|
|
29922
|
+
const next = new Map(prev);
|
|
29923
|
+
for (const a of selectedAncestors) if (next.get(a) === false) next.delete(a);
|
|
29924
|
+
return next;
|
|
29925
|
+
});
|
|
29926
|
+
}, [selectedId, selectedAncestors]);
|
|
29927
|
+
const isExpanded = useCallback(
|
|
29928
|
+
(id, depth) => overrides.get(id) ?? (depth < 1 || selectedAncestors.has(id)),
|
|
29929
|
+
[overrides, selectedAncestors]
|
|
29930
|
+
);
|
|
29931
|
+
const onToggle = useCallback((id, effective) => {
|
|
29932
|
+
setOverrides((prev) => {
|
|
29933
|
+
const next = new Map(prev);
|
|
29934
|
+
next.set(id, !effective);
|
|
29935
|
+
return next;
|
|
29936
|
+
});
|
|
29937
|
+
}, []);
|
|
29938
|
+
if (items.length === 0) return null;
|
|
29939
|
+
const ids = new Set(items.map((node) => node.id));
|
|
29940
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
29941
|
+
const roots = [];
|
|
29942
|
+
for (const item of items) {
|
|
29943
|
+
if (item.parentId && ids.has(item.parentId)) {
|
|
29944
|
+
const siblings = childrenByParent.get(item.parentId);
|
|
29945
|
+
if (siblings) siblings.push(item);
|
|
29946
|
+
else childrenByParent.set(item.parentId, [item]);
|
|
29947
|
+
} else {
|
|
29948
|
+
roots.push(item);
|
|
29949
|
+
}
|
|
29950
|
+
}
|
|
29951
|
+
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: roots.map((item) => /* @__PURE__ */ jsx(
|
|
29952
|
+
FlatTreeNodeItem,
|
|
29953
|
+
{
|
|
29954
|
+
item,
|
|
29955
|
+
depth: 0,
|
|
29956
|
+
indent,
|
|
29957
|
+
childrenByParent,
|
|
29958
|
+
onNodeSelect,
|
|
29959
|
+
onNodeAction,
|
|
29960
|
+
nodeActionIcon,
|
|
29961
|
+
nodeActionLabel,
|
|
29962
|
+
selectedId,
|
|
29963
|
+
look,
|
|
29964
|
+
isExpanded,
|
|
29965
|
+
onToggle
|
|
29966
|
+
},
|
|
29967
|
+
item.id
|
|
29968
|
+
)) });
|
|
29969
|
+
};
|
|
29844
29970
|
FileTree = ({
|
|
29845
29971
|
tree,
|
|
29846
29972
|
items,
|
|
29847
29973
|
selectedPath,
|
|
29974
|
+
selectedId,
|
|
29975
|
+
look = "files",
|
|
29848
29976
|
onFileSelect,
|
|
29849
29977
|
onNodeSelect,
|
|
29978
|
+
onNodeAction,
|
|
29979
|
+
nodeActionIcon,
|
|
29980
|
+
nodeActionLabel,
|
|
29850
29981
|
className,
|
|
29851
29982
|
indent = 16
|
|
29852
29983
|
}) => {
|
|
29853
29984
|
if (items) {
|
|
29854
|
-
|
|
29855
|
-
|
|
29856
|
-
const childrenByParent = /* @__PURE__ */ new Map();
|
|
29857
|
-
const roots = [];
|
|
29858
|
-
for (const item of items) {
|
|
29859
|
-
if (item.parentId && ids.has(item.parentId)) {
|
|
29860
|
-
const siblings = childrenByParent.get(item.parentId);
|
|
29861
|
-
if (siblings) siblings.push(item);
|
|
29862
|
-
else childrenByParent.set(item.parentId, [item]);
|
|
29863
|
-
} else {
|
|
29864
|
-
roots.push(item);
|
|
29865
|
-
}
|
|
29866
|
-
}
|
|
29867
|
-
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: roots.map((item) => /* @__PURE__ */ jsx(
|
|
29868
|
-
FlatTreeNodeItem,
|
|
29985
|
+
return /* @__PURE__ */ jsx(
|
|
29986
|
+
FlatFileTree,
|
|
29869
29987
|
{
|
|
29870
|
-
|
|
29871
|
-
|
|
29872
|
-
|
|
29873
|
-
childrenByParent,
|
|
29988
|
+
items,
|
|
29989
|
+
selectedId,
|
|
29990
|
+
look,
|
|
29874
29991
|
onNodeSelect,
|
|
29875
|
-
|
|
29876
|
-
|
|
29877
|
-
|
|
29878
|
-
|
|
29992
|
+
onNodeAction,
|
|
29993
|
+
nodeActionIcon,
|
|
29994
|
+
nodeActionLabel,
|
|
29995
|
+
className,
|
|
29996
|
+
indent
|
|
29997
|
+
}
|
|
29998
|
+
);
|
|
29879
29999
|
}
|
|
29880
30000
|
if (!tree || tree.length === 0) return null;
|
|
29881
30001
|
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: tree.map((node) => /* @__PURE__ */ jsx(
|
|
@@ -35340,6 +35460,33 @@ var init_Lightbox = __esm({
|
|
|
35340
35460
|
Lightbox.displayName = "Lightbox";
|
|
35341
35461
|
}
|
|
35342
35462
|
});
|
|
35463
|
+
|
|
35464
|
+
// lib/relationLabel.ts
|
|
35465
|
+
function relationLabel(value) {
|
|
35466
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date)
|
|
35467
|
+
return null;
|
|
35468
|
+
for (const key of ["name", "title", "label"]) {
|
|
35469
|
+
const candidate = value[key];
|
|
35470
|
+
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
35471
|
+
}
|
|
35472
|
+
const id = value.id;
|
|
35473
|
+
return id !== void 0 && id !== null ? String(id) : null;
|
|
35474
|
+
}
|
|
35475
|
+
function relationDisplayLabels(value, options) {
|
|
35476
|
+
if (value === void 0 || value === null || value === "") return [];
|
|
35477
|
+
if (Array.isArray(value)) {
|
|
35478
|
+
return value.flatMap((item) => relationDisplayLabels(item, options));
|
|
35479
|
+
}
|
|
35480
|
+
const hydrated = relationLabel(value);
|
|
35481
|
+
if (hydrated !== null) return [hydrated];
|
|
35482
|
+
const raw = String(value);
|
|
35483
|
+
const match = options?.find((opt) => opt.value === raw);
|
|
35484
|
+
return [match ? match.label : raw];
|
|
35485
|
+
}
|
|
35486
|
+
var init_relationLabel = __esm({
|
|
35487
|
+
"lib/relationLabel.ts"() {
|
|
35488
|
+
}
|
|
35489
|
+
});
|
|
35343
35490
|
function renderIconInput3(icon, props) {
|
|
35344
35491
|
return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
|
|
35345
35492
|
}
|
|
@@ -35657,6 +35804,7 @@ var init_TableView = __esm({
|
|
|
35657
35804
|
"use client";
|
|
35658
35805
|
init_cn();
|
|
35659
35806
|
init_format();
|
|
35807
|
+
init_relationLabel();
|
|
35660
35808
|
init_getNestedValue();
|
|
35661
35809
|
init_useEventBus();
|
|
35662
35810
|
init_Box();
|
|
@@ -35670,7 +35818,13 @@ var init_TableView = __esm({
|
|
|
35670
35818
|
init_Menu();
|
|
35671
35819
|
init_useDataDnd();
|
|
35672
35820
|
tableViewLog = createLogger("almadar:ui:table-view");
|
|
35673
|
-
formatCell = (value, format) =>
|
|
35821
|
+
formatCell = (value, format) => {
|
|
35822
|
+
if (value !== null && value !== void 0 && typeof value === "object" && !(value instanceof Date)) {
|
|
35823
|
+
const labels = relationDisplayLabels(value);
|
|
35824
|
+
if (labels.length > 0) return labels.join(", ");
|
|
35825
|
+
}
|
|
35826
|
+
return formatValue(value, format);
|
|
35827
|
+
};
|
|
35674
35828
|
MAX_MEASURED_COL_CH = 32;
|
|
35675
35829
|
BADGE_CHROME_CH = 4;
|
|
35676
35830
|
alignClass = {
|
|
@@ -39285,6 +39439,35 @@ var init_RichTextEditor = __esm({
|
|
|
39285
39439
|
document.execCommand("createLink", false, safe);
|
|
39286
39440
|
afterEdit();
|
|
39287
39441
|
}, [afterEdit, t, toolbar.link]);
|
|
39442
|
+
const imageInputRef = useRef(null);
|
|
39443
|
+
const savedRangeRef = useRef(null);
|
|
39444
|
+
const execImage = useCallback(() => {
|
|
39445
|
+
const root = ref.current;
|
|
39446
|
+
const sel = window.getSelection();
|
|
39447
|
+
savedRangeRef.current = root && sel && sel.rangeCount > 0 && root.contains(sel.anchorNode) ? sel.getRangeAt(0).cloneRange() : null;
|
|
39448
|
+
imageInputRef.current?.click();
|
|
39449
|
+
}, []);
|
|
39450
|
+
const handleImageFile = useCallback((e) => {
|
|
39451
|
+
const file = e.target.files?.[0];
|
|
39452
|
+
e.target.value = "";
|
|
39453
|
+
if (!file) return;
|
|
39454
|
+
const reader = new FileReader();
|
|
39455
|
+
reader.onload = () => {
|
|
39456
|
+
const url = typeof reader.result === "string" ? reader.result : "";
|
|
39457
|
+
if (!url.startsWith("data:image/")) return;
|
|
39458
|
+
const root = ref.current;
|
|
39459
|
+
if (!root) return;
|
|
39460
|
+
root.focus();
|
|
39461
|
+
const sel = window.getSelection();
|
|
39462
|
+
if (sel && savedRangeRef.current && root.contains(savedRangeRef.current.startContainer)) {
|
|
39463
|
+
sel.removeAllRanges();
|
|
39464
|
+
sel.addRange(savedRangeRef.current);
|
|
39465
|
+
}
|
|
39466
|
+
document.execCommand("insertImage", false, url);
|
|
39467
|
+
afterEdit();
|
|
39468
|
+
};
|
|
39469
|
+
reader.readAsDataURL(file);
|
|
39470
|
+
}, [afterEdit]);
|
|
39288
39471
|
const execRule = useCallback(() => {
|
|
39289
39472
|
document.execCommand("insertHorizontalRule", false);
|
|
39290
39473
|
afterEdit();
|
|
@@ -39297,6 +39480,18 @@ var init_RichTextEditor = __esm({
|
|
|
39297
39480
|
}
|
|
39298
39481
|
return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col gap-2", className), children: [
|
|
39299
39482
|
/* @__PURE__ */ jsx(RichTextStyles, {}),
|
|
39483
|
+
/* @__PURE__ */ jsx(
|
|
39484
|
+
"input",
|
|
39485
|
+
{
|
|
39486
|
+
ref: imageInputRef,
|
|
39487
|
+
type: "file",
|
|
39488
|
+
accept: "image/*",
|
|
39489
|
+
className: "hidden",
|
|
39490
|
+
"aria-hidden": "true",
|
|
39491
|
+
tabIndex: -1,
|
|
39492
|
+
onChange: handleImageFile
|
|
39493
|
+
}
|
|
39494
|
+
),
|
|
39300
39495
|
showToolbar && /* @__PURE__ */ jsxs(
|
|
39301
39496
|
Box,
|
|
39302
39497
|
{
|
|
@@ -39322,6 +39517,7 @@ var init_RichTextEditor = __esm({
|
|
|
39322
39517
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Quote, label: t("richTextEditor.quote"), active: toolbar.block === "blockquote", onExec: () => execBlock("blockquote") }),
|
|
39323
39518
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Code, label: t("richTextEditor.code"), active: toolbar.block === "pre", onExec: () => execBlock("pre") }),
|
|
39324
39519
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Link$1, label: toolbar.link ? t("richTextEditor.removeLink") : t("richTextEditor.link"), active: toolbar.link, onExec: execLink }),
|
|
39520
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Image$1, label: t("richTextEditor.image"), onExec: execImage }),
|
|
39325
39521
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Minus, label: t("richTextEditor.divider"), onExec: execRule })
|
|
39326
39522
|
]
|
|
39327
39523
|
}
|
|
@@ -39362,6 +39558,8 @@ function DocumentPanel({
|
|
|
39362
39558
|
id,
|
|
39363
39559
|
title,
|
|
39364
39560
|
subtitle,
|
|
39561
|
+
coverImage,
|
|
39562
|
+
icon,
|
|
39365
39563
|
value,
|
|
39366
39564
|
actions,
|
|
39367
39565
|
maxInlineActions,
|
|
@@ -39437,62 +39635,74 @@ function DocumentPanel({
|
|
|
39437
39635
|
const emitWithId = (event) => () => {
|
|
39438
39636
|
if (event) eventBus.emit(`UI:${event}`, { id: recordId });
|
|
39439
39637
|
};
|
|
39440
|
-
return /* @__PURE__ */
|
|
39441
|
-
/* @__PURE__ */
|
|
39442
|
-
|
|
39443
|
-
titleNode,
|
|
39444
|
-
subtitle ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
39445
|
-
] }),
|
|
39446
|
-
/* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39447
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
39448
|
-
/* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
39449
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39450
|
-
editEvent && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
39451
|
-
/* @__PURE__ */ jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
39452
|
-
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
39453
|
-
] }),
|
|
39454
|
-
inlineActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
39455
|
-
Button,
|
|
39456
|
-
{
|
|
39457
|
-
variant: "primary",
|
|
39458
|
-
size: "sm",
|
|
39459
|
-
onClick: () => fireAction(action),
|
|
39460
|
-
"data-testid": `action-${action.event}`,
|
|
39461
|
-
children: [
|
|
39462
|
-
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
39463
|
-
action.label
|
|
39464
|
-
]
|
|
39465
|
-
},
|
|
39466
|
-
idx
|
|
39467
|
-
)),
|
|
39468
|
-
menuActions.length > 0 && /* @__PURE__ */ jsx(
|
|
39469
|
-
Menu,
|
|
39470
|
-
{
|
|
39471
|
-
position: "bottom-end",
|
|
39472
|
-
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" }) }),
|
|
39473
|
-
items: menuActions.map((action) => ({
|
|
39474
|
-
label: action.label,
|
|
39475
|
-
icon: action.icon,
|
|
39476
|
-
variant: action.variant === "danger" ? "danger" : "default",
|
|
39477
|
-
onClick: () => fireAction(action)
|
|
39478
|
-
}))
|
|
39479
|
-
}
|
|
39480
|
-
)
|
|
39481
|
-
] }) })
|
|
39482
|
-
] }),
|
|
39483
|
-
editing ? /* @__PURE__ */ jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsx(
|
|
39484
|
-
Box,
|
|
39638
|
+
return /* @__PURE__ */ jsxs(Card, { variant: "elevated", className: cn("w-full overflow-hidden", className), children: [
|
|
39639
|
+
coverImage ? /* @__PURE__ */ jsx(Box, { className: "h-44 w-full sm:h-52", "data-testid": "document-cover", children: /* @__PURE__ */ jsx(
|
|
39640
|
+
"img",
|
|
39485
39641
|
{
|
|
39486
|
-
|
|
39487
|
-
|
|
39488
|
-
|
|
39489
|
-
|
|
39490
|
-
|
|
39491
|
-
|
|
39492
|
-
|
|
39493
|
-
|
|
39494
|
-
|
|
39495
|
-
|
|
39642
|
+
src: coverImage,
|
|
39643
|
+
alt: "",
|
|
39644
|
+
"aria-hidden": "true",
|
|
39645
|
+
className: "h-full w-full object-cover"
|
|
39646
|
+
}
|
|
39647
|
+
) }) : null,
|
|
39648
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "p-6 sm:p-8", children: [
|
|
39649
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
39650
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
39651
|
+
icon ? /* @__PURE__ */ jsx(Box, { className: "text-muted-foreground", "data-testid": "document-icon", children: renderIconInput4(icon, { size: "lg" }) }) : null,
|
|
39652
|
+
titleNode,
|
|
39653
|
+
subtitle ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
39654
|
+
] }),
|
|
39655
|
+
/* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39656
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
39657
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
39658
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39659
|
+
editEvent && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
39660
|
+
/* @__PURE__ */ jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
39661
|
+
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
39662
|
+
] }),
|
|
39663
|
+
inlineActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
39664
|
+
Button,
|
|
39665
|
+
{
|
|
39666
|
+
variant: "primary",
|
|
39667
|
+
size: "sm",
|
|
39668
|
+
onClick: () => fireAction(action),
|
|
39669
|
+
"data-testid": `action-${action.event}`,
|
|
39670
|
+
children: [
|
|
39671
|
+
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
39672
|
+
action.label
|
|
39673
|
+
]
|
|
39674
|
+
},
|
|
39675
|
+
idx
|
|
39676
|
+
)),
|
|
39677
|
+
menuActions.length > 0 && /* @__PURE__ */ jsx(
|
|
39678
|
+
Menu,
|
|
39679
|
+
{
|
|
39680
|
+
position: "bottom-end",
|
|
39681
|
+
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" }) }),
|
|
39682
|
+
items: menuActions.map((action) => ({
|
|
39683
|
+
label: action.label,
|
|
39684
|
+
icon: action.icon,
|
|
39685
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
39686
|
+
onClick: () => fireAction(action)
|
|
39687
|
+
}))
|
|
39688
|
+
}
|
|
39689
|
+
)
|
|
39690
|
+
] }) })
|
|
39691
|
+
] }),
|
|
39692
|
+
editing ? /* @__PURE__ */ jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsx(
|
|
39693
|
+
Box,
|
|
39694
|
+
{
|
|
39695
|
+
onClick: emitWithId(editEvent),
|
|
39696
|
+
className: cn(
|
|
39697
|
+
"rounded-md px-1 -mx-1 min-h-[16rem]",
|
|
39698
|
+
editEvent && "cursor-text transition-colors hover:bg-muted/30"
|
|
39699
|
+
),
|
|
39700
|
+
"data-testid": "document-body",
|
|
39701
|
+
children: value && value !== "" ? /* @__PURE__ */ jsx(RichTextEditor, { value, readOnly: true }) : /* @__PURE__ */ jsx(Typography, { variant: "body", color: "muted", children: placeholder ?? (t("documentPanel.placeholder") || "") })
|
|
39702
|
+
}
|
|
39703
|
+
)
|
|
39704
|
+
] })
|
|
39705
|
+
] });
|
|
39496
39706
|
}
|
|
39497
39707
|
var init_DocumentPanel = __esm({
|
|
39498
39708
|
"components/core/molecules/DocumentPanel.tsx"() {
|
|
@@ -39516,17 +39726,16 @@ function renderIconInput5(icon, props) {
|
|
|
39516
39726
|
function fieldName(field) {
|
|
39517
39727
|
return field.name ?? field.key ?? "";
|
|
39518
39728
|
}
|
|
39519
|
-
function
|
|
39520
|
-
if (value
|
|
39521
|
-
|
|
39522
|
-
|
|
39523
|
-
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
39729
|
+
function relationId(value) {
|
|
39730
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
|
|
39731
|
+
const id = value.id;
|
|
39732
|
+
if (id !== void 0 && id !== null) return String(id);
|
|
39524
39733
|
}
|
|
39525
|
-
|
|
39526
|
-
return id !== void 0 && id !== null ? String(id) : null;
|
|
39734
|
+
return String(value);
|
|
39527
39735
|
}
|
|
39528
39736
|
function fieldKind(field, value) {
|
|
39529
39737
|
if (field.kind) return field.kind;
|
|
39738
|
+
if (field.type === "image") return "image";
|
|
39530
39739
|
if (field.options && field.options.length > 0) return "select";
|
|
39531
39740
|
if (typeof value === "boolean" || field.format === "boolean") return "boolean";
|
|
39532
39741
|
if (Array.isArray(value) || relationLabel(value ?? null) !== null) return "readonly";
|
|
@@ -39536,6 +39745,7 @@ function DocumentDetails({
|
|
|
39536
39745
|
entity,
|
|
39537
39746
|
fields,
|
|
39538
39747
|
metaCommitEvent,
|
|
39748
|
+
relationEvent,
|
|
39539
39749
|
title,
|
|
39540
39750
|
className
|
|
39541
39751
|
}) {
|
|
@@ -39550,11 +39760,51 @@ function DocumentDetails({
|
|
|
39550
39760
|
if (!metaCommitEvent || next === current) return;
|
|
39551
39761
|
eventBus.emit(`UI:${metaCommitEvent}`, { id: recordId, patch: { id: recordId, [name]: next } });
|
|
39552
39762
|
};
|
|
39763
|
+
const relationChip = (item, name, key) => {
|
|
39764
|
+
const label = relationLabel(item) ?? humanizeEnumValue(String(item));
|
|
39765
|
+
if (!relationEvent) {
|
|
39766
|
+
return /* @__PURE__ */ jsx(Badge, { variant: "default", children: label }, key);
|
|
39767
|
+
}
|
|
39768
|
+
const emitClick = () => eventBus.emit(`UI:${relationEvent}`, { field: name, id: relationId(item), name: label });
|
|
39769
|
+
return /* @__PURE__ */ jsx(
|
|
39770
|
+
Badge,
|
|
39771
|
+
{
|
|
39772
|
+
variant: "default",
|
|
39773
|
+
role: "button",
|
|
39774
|
+
tabIndex: 0,
|
|
39775
|
+
className: "cursor-pointer transition-colors hover:bg-accent",
|
|
39776
|
+
onClick: emitClick,
|
|
39777
|
+
onKeyDown: (e) => {
|
|
39778
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
39779
|
+
e.preventDefault();
|
|
39780
|
+
emitClick();
|
|
39781
|
+
}
|
|
39782
|
+
},
|
|
39783
|
+
"data-testid": `relation-chip-${name}`,
|
|
39784
|
+
children: label
|
|
39785
|
+
},
|
|
39786
|
+
key
|
|
39787
|
+
);
|
|
39788
|
+
};
|
|
39553
39789
|
const renderValue = (field) => {
|
|
39554
39790
|
const name = fieldName(field);
|
|
39555
39791
|
const raw = getNestedValue(entity ?? {}, name);
|
|
39556
39792
|
const kind = fieldKind(field, raw);
|
|
39557
39793
|
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
39794
|
+
if (kind === "image") {
|
|
39795
|
+
const url = typeof raw === "string" ? raw : "";
|
|
39796
|
+
if (!url) return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
39797
|
+
return /* @__PURE__ */ jsx(
|
|
39798
|
+
"img",
|
|
39799
|
+
{
|
|
39800
|
+
src: url,
|
|
39801
|
+
alt: label,
|
|
39802
|
+
loading: "lazy",
|
|
39803
|
+
className: "max-h-32 w-full rounded-md border border-border object-cover",
|
|
39804
|
+
"data-testid": `document-property-image-${name}`
|
|
39805
|
+
}
|
|
39806
|
+
);
|
|
39807
|
+
}
|
|
39558
39808
|
if (kind === "boolean") {
|
|
39559
39809
|
return /* @__PURE__ */ jsx(
|
|
39560
39810
|
Switch,
|
|
@@ -39584,9 +39834,12 @@ function DocumentDetails({
|
|
|
39584
39834
|
if (raw.length === 0) {
|
|
39585
39835
|
return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
39586
39836
|
}
|
|
39587
|
-
return /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) =>
|
|
39837
|
+
return /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) => relationChip(item, name, i)) });
|
|
39588
39838
|
}
|
|
39589
|
-
|
|
39839
|
+
if (raw !== void 0 && raw !== null && raw !== "" && relationLabel(raw) !== null) {
|
|
39840
|
+
return relationChip(raw, name);
|
|
39841
|
+
}
|
|
39842
|
+
const shown2 = raw === void 0 || raw === null || raw === "" ? "\u2014" : formatValue(raw, field.format);
|
|
39590
39843
|
return /* @__PURE__ */ jsx(Typography, { variant: "small", className: "break-words", children: shown2 });
|
|
39591
39844
|
}
|
|
39592
39845
|
if (fieldDraft?.name === name) {
|
|
@@ -39655,6 +39908,7 @@ var init_DocumentDetails = __esm({
|
|
|
39655
39908
|
init_cn();
|
|
39656
39909
|
init_format();
|
|
39657
39910
|
init_getNestedValue();
|
|
39911
|
+
init_relationLabel();
|
|
39658
39912
|
init_useEventBus();
|
|
39659
39913
|
init_Box();
|
|
39660
39914
|
init_Stack();
|
|
@@ -44240,7 +44494,18 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
44240
44494
|
if (value === void 0 || value === null) return "\u2014";
|
|
44241
44495
|
const str = String(value);
|
|
44242
44496
|
switch (fieldType) {
|
|
44243
|
-
case "image":
|
|
44497
|
+
case "image": {
|
|
44498
|
+
if (!str) return "\u2014";
|
|
44499
|
+
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
44500
|
+
"img",
|
|
44501
|
+
{
|
|
44502
|
+
src: str,
|
|
44503
|
+
alt: formatFieldLabel(fieldName2),
|
|
44504
|
+
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
44505
|
+
loading: "lazy"
|
|
44506
|
+
}
|
|
44507
|
+
) });
|
|
44508
|
+
}
|
|
44244
44509
|
case "url": {
|
|
44245
44510
|
if (str.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str.startsWith("data:image/")) {
|
|
44246
44511
|
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
@@ -44253,7 +44518,7 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
44253
44518
|
}
|
|
44254
44519
|
) });
|
|
44255
44520
|
}
|
|
44256
|
-
if (
|
|
44521
|
+
if (/^https?:\/\//i.test(str)) {
|
|
44257
44522
|
return /* @__PURE__ */ jsx(
|
|
44258
44523
|
"a",
|
|
44259
44524
|
{
|
|
@@ -44339,8 +44604,10 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
44339
44604
|
return str;
|
|
44340
44605
|
}
|
|
44341
44606
|
case "relation": {
|
|
44342
|
-
const
|
|
44343
|
-
|
|
44607
|
+
const labels = relationDisplayLabels(value, meta?.options);
|
|
44608
|
+
if (labels.length === 0) return "\u2014";
|
|
44609
|
+
if (labels.length === 1) return labels[0];
|
|
44610
|
+
return /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: labels.map((label, i) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: label }, i)) });
|
|
44344
44611
|
}
|
|
44345
44612
|
case "file": {
|
|
44346
44613
|
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
@@ -44442,6 +44709,7 @@ var init_DetailPanel = __esm({
|
|
|
44442
44709
|
init_cn();
|
|
44443
44710
|
init_format();
|
|
44444
44711
|
init_getNestedValue();
|
|
44712
|
+
init_relationLabel();
|
|
44445
44713
|
init_useEventBus();
|
|
44446
44714
|
init_UploadDropZone();
|
|
44447
44715
|
formatFieldLabel = humanizeFieldName;
|
|
@@ -45100,6 +45368,8 @@ function determineInputType(field) {
|
|
|
45100
45368
|
return "url";
|
|
45101
45369
|
case "file":
|
|
45102
45370
|
return "file";
|
|
45371
|
+
case "image":
|
|
45372
|
+
return "image";
|
|
45103
45373
|
case "money":
|
|
45104
45374
|
return "currency";
|
|
45105
45375
|
case "number":
|
|
@@ -45699,6 +45969,50 @@ var init_Form = __esm({
|
|
|
45699
45969
|
}
|
|
45700
45970
|
}
|
|
45701
45971
|
);
|
|
45972
|
+
case "image": {
|
|
45973
|
+
const imageUrl = typeof currentValue === "string" ? currentValue : "";
|
|
45974
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
45975
|
+
imageUrl ? /* @__PURE__ */ jsx(
|
|
45976
|
+
"img",
|
|
45977
|
+
{
|
|
45978
|
+
src: imageUrl,
|
|
45979
|
+
alt: "",
|
|
45980
|
+
"aria-hidden": "true",
|
|
45981
|
+
className: "h-24 w-full max-w-xs rounded-md border border-border object-cover",
|
|
45982
|
+
"data-testid": `image-preview-${fieldName2}`
|
|
45983
|
+
}
|
|
45984
|
+
) : null,
|
|
45985
|
+
/* @__PURE__ */ jsx(
|
|
45986
|
+
UploadDropZone,
|
|
45987
|
+
{
|
|
45988
|
+
accept: "image/*",
|
|
45989
|
+
maxFiles: 1,
|
|
45990
|
+
maxSize: 2 * 1024 * 1024,
|
|
45991
|
+
disabled: isLoading,
|
|
45992
|
+
onFiles: (files) => {
|
|
45993
|
+
const f3 = files[0];
|
|
45994
|
+
if (!f3) return;
|
|
45995
|
+
const reader = new FileReader();
|
|
45996
|
+
reader.onload = () => handleChange(
|
|
45997
|
+
fieldName2,
|
|
45998
|
+
typeof reader.result === "string" ? reader.result : ""
|
|
45999
|
+
);
|
|
46000
|
+
reader.readAsDataURL(f3);
|
|
46001
|
+
}
|
|
46002
|
+
}
|
|
46003
|
+
),
|
|
46004
|
+
/* @__PURE__ */ jsx(
|
|
46005
|
+
Input,
|
|
46006
|
+
{
|
|
46007
|
+
...commonProps,
|
|
46008
|
+
type: "url",
|
|
46009
|
+
placeholder: t("form.imageUrlFallback"),
|
|
46010
|
+
value: imageUrl,
|
|
46011
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
46012
|
+
}
|
|
46013
|
+
)
|
|
46014
|
+
] });
|
|
46015
|
+
}
|
|
45702
46016
|
case "date":
|
|
45703
46017
|
return /* @__PURE__ */ jsx(
|
|
45704
46018
|
Input,
|