@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/components/index.js
CHANGED
|
@@ -22562,6 +22562,7 @@ var init_DashboardLayout = __esm({
|
|
|
22562
22562
|
onNotificationClick,
|
|
22563
22563
|
showThemeToggle = true,
|
|
22564
22564
|
sidebarFooter,
|
|
22565
|
+
sidebarContent,
|
|
22565
22566
|
onSignOut: onSignOutProp,
|
|
22566
22567
|
currentPath,
|
|
22567
22568
|
layoutMode = "sidebar",
|
|
@@ -22691,7 +22692,11 @@ var init_DashboardLayout = __esm({
|
|
|
22691
22692
|
{
|
|
22692
22693
|
as: "nav",
|
|
22693
22694
|
gap: "none",
|
|
22694
|
-
className: cn(
|
|
22695
|
+
className: cn(
|
|
22696
|
+
"py-4 space-y-1 overflow-y-auto",
|
|
22697
|
+
sidebarContent && !isRail ? "shrink-0" : "flex-1",
|
|
22698
|
+
isRail ? "px-2" : "px-3"
|
|
22699
|
+
),
|
|
22695
22700
|
children: navItems.map((item) => /* @__PURE__ */ jsx(
|
|
22696
22701
|
NavLink,
|
|
22697
22702
|
{
|
|
@@ -22703,6 +22708,7 @@ var init_DashboardLayout = __esm({
|
|
|
22703
22708
|
))
|
|
22704
22709
|
}
|
|
22705
22710
|
),
|
|
22711
|
+
sidebarContent && !isRail && /* @__PURE__ */ jsx(Box, { className: "flex-1 overflow-y-auto border-t border-border dark:border-border px-2 py-3", children: sidebarContent }),
|
|
22706
22712
|
sidebarFooter && /* @__PURE__ */ jsx(Box, { className: "p-4 border-t border-border dark:border-border", children: sidebarFooter })
|
|
22707
22713
|
]
|
|
22708
22714
|
}
|
|
@@ -25773,7 +25779,17 @@ function fileIcon(name) {
|
|
|
25773
25779
|
return "file";
|
|
25774
25780
|
}
|
|
25775
25781
|
}
|
|
25776
|
-
|
|
25782
|
+
function ancestorsOf(id, byId) {
|
|
25783
|
+
const out = /* @__PURE__ */ new Set();
|
|
25784
|
+
if (!id) return out;
|
|
25785
|
+
let cur = byId.get(id)?.parentId;
|
|
25786
|
+
while (cur && byId.has(cur) && !out.has(cur)) {
|
|
25787
|
+
out.add(cur);
|
|
25788
|
+
cur = byId.get(cur)?.parentId;
|
|
25789
|
+
}
|
|
25790
|
+
return out;
|
|
25791
|
+
}
|
|
25792
|
+
var TreeNodeItem, FlatTreeNodeItem, FlatFileTree, FileTree;
|
|
25777
25793
|
var init_FileTree = __esm({
|
|
25778
25794
|
"components/core/molecules/FileTree.tsx"() {
|
|
25779
25795
|
"use client";
|
|
@@ -25864,42 +25880,77 @@ var init_FileTree = __esm({
|
|
|
25864
25880
|
indent,
|
|
25865
25881
|
childrenByParent,
|
|
25866
25882
|
onNodeSelect,
|
|
25867
|
-
|
|
25883
|
+
onNodeAction,
|
|
25884
|
+
nodeActionIcon,
|
|
25885
|
+
nodeActionLabel,
|
|
25886
|
+
selectedId,
|
|
25887
|
+
look,
|
|
25888
|
+
isExpanded,
|
|
25889
|
+
onToggle
|
|
25868
25890
|
}) => {
|
|
25869
|
-
const [expanded, setExpanded] = useState(defaultExpanded || depth < 1);
|
|
25870
25891
|
const children = childrenByParent.get(item.id);
|
|
25871
25892
|
const hasChildren = !!children && children.length > 0;
|
|
25893
|
+
const expanded = hasChildren && isExpanded(item.id, depth);
|
|
25894
|
+
const isSelected = selectedId !== void 0 && selectedId !== "" && item.id === selectedId;
|
|
25895
|
+
const nav = look === "nav";
|
|
25872
25896
|
const handleClick = useCallback(() => {
|
|
25873
|
-
if (hasChildren)
|
|
25897
|
+
if (hasChildren && !onNodeSelect) onToggle(item.id, expanded);
|
|
25874
25898
|
onNodeSelect?.(item.id);
|
|
25875
|
-
}, [hasChildren, item.id, onNodeSelect]);
|
|
25899
|
+
}, [hasChildren, expanded, item.id, onNodeSelect, onToggle]);
|
|
25900
|
+
const handleChevron = useCallback((e) => {
|
|
25901
|
+
e.stopPropagation();
|
|
25902
|
+
onToggle(item.id, expanded);
|
|
25903
|
+
}, [item.id, expanded, onToggle]);
|
|
25904
|
+
const handleAction = useCallback((e) => {
|
|
25905
|
+
e.stopPropagation();
|
|
25906
|
+
onNodeAction?.(item.id);
|
|
25907
|
+
}, [item.id, onNodeAction]);
|
|
25876
25908
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
25877
25909
|
/* @__PURE__ */ jsxs(
|
|
25878
25910
|
Box,
|
|
25879
25911
|
{
|
|
25880
|
-
className:
|
|
25912
|
+
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"}`,
|
|
25881
25913
|
style: { paddingLeft: depth * indent + 8 },
|
|
25882
25914
|
onClick: handleClick,
|
|
25883
25915
|
role: "treeitem",
|
|
25916
|
+
"aria-selected": isSelected,
|
|
25884
25917
|
"aria-expanded": hasChildren ? expanded : void 0,
|
|
25885
25918
|
children: [
|
|
25886
|
-
hasChildren ? /* @__PURE__ */ jsx(
|
|
25919
|
+
hasChildren ? /* @__PURE__ */ jsx(Box, { onClick: handleChevron, className: "flex items-center flex-shrink-0", role: "button", "aria-label": expanded ? "Collapse" : "Expand", children: /* @__PURE__ */ jsx(
|
|
25887
25920
|
Icon,
|
|
25888
25921
|
{
|
|
25889
25922
|
name: expanded ? "chevron-down" : "chevron-right",
|
|
25890
25923
|
size: "xs",
|
|
25891
|
-
className: "text-[var(--color-muted-foreground)]
|
|
25924
|
+
className: isSelected ? "text-inherit" : "text-[var(--color-muted-foreground)]"
|
|
25892
25925
|
}
|
|
25893
|
-
) : /* @__PURE__ */ jsx(Box, { style: { width: 12, flexShrink: 0 } }),
|
|
25926
|
+
) }) : /* @__PURE__ */ jsx(Box, { style: { width: 12, flexShrink: 0 } }),
|
|
25894
25927
|
/* @__PURE__ */ jsx(
|
|
25895
25928
|
Icon,
|
|
25896
25929
|
{
|
|
25897
|
-
name: item.icon
|
|
25930
|
+
name: item.icon || (nav ? "file-text" : hasChildren ? expanded ? "folder-open" : "folder" : "file"),
|
|
25898
25931
|
size: "xs",
|
|
25899
|
-
className: hasChildren ? "text-[var(--color-
|
|
25932
|
+
className: isSelected ? "text-inherit" : nav || !hasChildren ? "text-[var(--color-muted-foreground)]" : "text-[var(--color-warning)]"
|
|
25900
25933
|
}
|
|
25901
25934
|
),
|
|
25902
|
-
/* @__PURE__ */ jsx(
|
|
25935
|
+
/* @__PURE__ */ jsx(
|
|
25936
|
+
Typography,
|
|
25937
|
+
{
|
|
25938
|
+
variant: "caption",
|
|
25939
|
+
className: `truncate ${nav ? "text-sm" : "font-mono text-xs"} !text-inherit ${isSelected ? "font-semibold" : ""}`,
|
|
25940
|
+
children: item.label
|
|
25941
|
+
}
|
|
25942
|
+
),
|
|
25943
|
+
onNodeAction && /* @__PURE__ */ jsx(
|
|
25944
|
+
Box,
|
|
25945
|
+
{
|
|
25946
|
+
onClick: handleAction,
|
|
25947
|
+
role: "button",
|
|
25948
|
+
"aria-label": nodeActionLabel ?? "Node action",
|
|
25949
|
+
title: nodeActionLabel,
|
|
25950
|
+
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"}`,
|
|
25951
|
+
children: /* @__PURE__ */ jsx(Icon, { name: nodeActionIcon ?? "plus", size: "xs", className: "text-inherit" })
|
|
25952
|
+
}
|
|
25953
|
+
)
|
|
25903
25954
|
]
|
|
25904
25955
|
}
|
|
25905
25956
|
),
|
|
@@ -25910,47 +25961,116 @@ var init_FileTree = __esm({
|
|
|
25910
25961
|
depth: depth + 1,
|
|
25911
25962
|
indent,
|
|
25912
25963
|
childrenByParent,
|
|
25913
|
-
onNodeSelect
|
|
25964
|
+
onNodeSelect,
|
|
25965
|
+
onNodeAction,
|
|
25966
|
+
nodeActionIcon,
|
|
25967
|
+
nodeActionLabel,
|
|
25968
|
+
selectedId,
|
|
25969
|
+
look,
|
|
25970
|
+
isExpanded,
|
|
25971
|
+
onToggle
|
|
25914
25972
|
},
|
|
25915
25973
|
child.id
|
|
25916
25974
|
)) })
|
|
25917
25975
|
] });
|
|
25918
25976
|
};
|
|
25977
|
+
FlatFileTree = ({
|
|
25978
|
+
items,
|
|
25979
|
+
selectedId,
|
|
25980
|
+
look = "files",
|
|
25981
|
+
onNodeSelect,
|
|
25982
|
+
onNodeAction,
|
|
25983
|
+
nodeActionIcon,
|
|
25984
|
+
nodeActionLabel,
|
|
25985
|
+
className,
|
|
25986
|
+
indent = 16
|
|
25987
|
+
}) => {
|
|
25988
|
+
const [overrides, setOverrides] = useState(() => /* @__PURE__ */ new Map());
|
|
25989
|
+
const byId = React77__default.useMemo(() => new Map(items.map((node) => [node.id, node])), [items]);
|
|
25990
|
+
const selectedAncestors = React77__default.useMemo(() => ancestorsOf(selectedId, byId), [selectedId, byId]);
|
|
25991
|
+
const lastSelectedRef = React77__default.useRef(selectedId);
|
|
25992
|
+
React77__default.useEffect(() => {
|
|
25993
|
+
if (selectedId === lastSelectedRef.current) return;
|
|
25994
|
+
lastSelectedRef.current = selectedId;
|
|
25995
|
+
setOverrides((prev) => {
|
|
25996
|
+
if (![...selectedAncestors].some((a) => prev.get(a) === false)) return prev;
|
|
25997
|
+
const next = new Map(prev);
|
|
25998
|
+
for (const a of selectedAncestors) if (next.get(a) === false) next.delete(a);
|
|
25999
|
+
return next;
|
|
26000
|
+
});
|
|
26001
|
+
}, [selectedId, selectedAncestors]);
|
|
26002
|
+
const isExpanded = useCallback(
|
|
26003
|
+
(id, depth) => overrides.get(id) ?? (depth < 1 || selectedAncestors.has(id)),
|
|
26004
|
+
[overrides, selectedAncestors]
|
|
26005
|
+
);
|
|
26006
|
+
const onToggle = useCallback((id, effective) => {
|
|
26007
|
+
setOverrides((prev) => {
|
|
26008
|
+
const next = new Map(prev);
|
|
26009
|
+
next.set(id, !effective);
|
|
26010
|
+
return next;
|
|
26011
|
+
});
|
|
26012
|
+
}, []);
|
|
26013
|
+
if (items.length === 0) return null;
|
|
26014
|
+
const ids = new Set(items.map((node) => node.id));
|
|
26015
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
26016
|
+
const roots = [];
|
|
26017
|
+
for (const item of items) {
|
|
26018
|
+
if (item.parentId && ids.has(item.parentId)) {
|
|
26019
|
+
const siblings = childrenByParent.get(item.parentId);
|
|
26020
|
+
if (siblings) siblings.push(item);
|
|
26021
|
+
else childrenByParent.set(item.parentId, [item]);
|
|
26022
|
+
} else {
|
|
26023
|
+
roots.push(item);
|
|
26024
|
+
}
|
|
26025
|
+
}
|
|
26026
|
+
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: roots.map((item) => /* @__PURE__ */ jsx(
|
|
26027
|
+
FlatTreeNodeItem,
|
|
26028
|
+
{
|
|
26029
|
+
item,
|
|
26030
|
+
depth: 0,
|
|
26031
|
+
indent,
|
|
26032
|
+
childrenByParent,
|
|
26033
|
+
onNodeSelect,
|
|
26034
|
+
onNodeAction,
|
|
26035
|
+
nodeActionIcon,
|
|
26036
|
+
nodeActionLabel,
|
|
26037
|
+
selectedId,
|
|
26038
|
+
look,
|
|
26039
|
+
isExpanded,
|
|
26040
|
+
onToggle
|
|
26041
|
+
},
|
|
26042
|
+
item.id
|
|
26043
|
+
)) });
|
|
26044
|
+
};
|
|
25919
26045
|
FileTree = ({
|
|
25920
26046
|
tree,
|
|
25921
26047
|
items,
|
|
25922
26048
|
selectedPath,
|
|
26049
|
+
selectedId,
|
|
26050
|
+
look = "files",
|
|
25923
26051
|
onFileSelect,
|
|
25924
26052
|
onNodeSelect,
|
|
26053
|
+
onNodeAction,
|
|
26054
|
+
nodeActionIcon,
|
|
26055
|
+
nodeActionLabel,
|
|
25925
26056
|
className,
|
|
25926
26057
|
indent = 16
|
|
25927
26058
|
}) => {
|
|
25928
26059
|
if (items) {
|
|
25929
|
-
|
|
25930
|
-
|
|
25931
|
-
const childrenByParent = /* @__PURE__ */ new Map();
|
|
25932
|
-
const roots = [];
|
|
25933
|
-
for (const item of items) {
|
|
25934
|
-
if (item.parentId && ids.has(item.parentId)) {
|
|
25935
|
-
const siblings = childrenByParent.get(item.parentId);
|
|
25936
|
-
if (siblings) siblings.push(item);
|
|
25937
|
-
else childrenByParent.set(item.parentId, [item]);
|
|
25938
|
-
} else {
|
|
25939
|
-
roots.push(item);
|
|
25940
|
-
}
|
|
25941
|
-
}
|
|
25942
|
-
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: roots.map((item) => /* @__PURE__ */ jsx(
|
|
25943
|
-
FlatTreeNodeItem,
|
|
26060
|
+
return /* @__PURE__ */ jsx(
|
|
26061
|
+
FlatFileTree,
|
|
25944
26062
|
{
|
|
25945
|
-
|
|
25946
|
-
|
|
25947
|
-
|
|
25948
|
-
childrenByParent,
|
|
26063
|
+
items,
|
|
26064
|
+
selectedId,
|
|
26065
|
+
look,
|
|
25949
26066
|
onNodeSelect,
|
|
25950
|
-
|
|
25951
|
-
|
|
25952
|
-
|
|
25953
|
-
|
|
26067
|
+
onNodeAction,
|
|
26068
|
+
nodeActionIcon,
|
|
26069
|
+
nodeActionLabel,
|
|
26070
|
+
className,
|
|
26071
|
+
indent
|
|
26072
|
+
}
|
|
26073
|
+
);
|
|
25954
26074
|
}
|
|
25955
26075
|
if (!tree || tree.length === 0) return null;
|
|
25956
26076
|
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: tree.map((node) => /* @__PURE__ */ jsx(
|
|
@@ -34105,6 +34225,33 @@ var init_Lightbox = __esm({
|
|
|
34105
34225
|
Lightbox.displayName = "Lightbox";
|
|
34106
34226
|
}
|
|
34107
34227
|
});
|
|
34228
|
+
|
|
34229
|
+
// lib/relationLabel.ts
|
|
34230
|
+
function relationLabel(value) {
|
|
34231
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date)
|
|
34232
|
+
return null;
|
|
34233
|
+
for (const key of ["name", "title", "label"]) {
|
|
34234
|
+
const candidate = value[key];
|
|
34235
|
+
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
34236
|
+
}
|
|
34237
|
+
const id = value.id;
|
|
34238
|
+
return id !== void 0 && id !== null ? String(id) : null;
|
|
34239
|
+
}
|
|
34240
|
+
function relationDisplayLabels(value, options) {
|
|
34241
|
+
if (value === void 0 || value === null || value === "") return [];
|
|
34242
|
+
if (Array.isArray(value)) {
|
|
34243
|
+
return value.flatMap((item) => relationDisplayLabels(item, options));
|
|
34244
|
+
}
|
|
34245
|
+
const hydrated = relationLabel(value);
|
|
34246
|
+
if (hydrated !== null) return [hydrated];
|
|
34247
|
+
const raw = String(value);
|
|
34248
|
+
const match = options?.find((opt) => opt.value === raw);
|
|
34249
|
+
return [match ? match.label : raw];
|
|
34250
|
+
}
|
|
34251
|
+
var init_relationLabel = __esm({
|
|
34252
|
+
"lib/relationLabel.ts"() {
|
|
34253
|
+
}
|
|
34254
|
+
});
|
|
34108
34255
|
function renderIconInput3(icon, props) {
|
|
34109
34256
|
return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
|
|
34110
34257
|
}
|
|
@@ -34422,6 +34569,7 @@ var init_TableView = __esm({
|
|
|
34422
34569
|
"use client";
|
|
34423
34570
|
init_cn();
|
|
34424
34571
|
init_format();
|
|
34572
|
+
init_relationLabel();
|
|
34425
34573
|
init_getNestedValue();
|
|
34426
34574
|
init_useEventBus();
|
|
34427
34575
|
init_Box();
|
|
@@ -34435,7 +34583,13 @@ var init_TableView = __esm({
|
|
|
34435
34583
|
init_Menu();
|
|
34436
34584
|
init_useDataDnd();
|
|
34437
34585
|
tableViewLog = createLogger("almadar:ui:table-view");
|
|
34438
|
-
formatCell = (value, format) =>
|
|
34586
|
+
formatCell = (value, format) => {
|
|
34587
|
+
if (value !== null && value !== void 0 && typeof value === "object" && !(value instanceof Date)) {
|
|
34588
|
+
const labels = relationDisplayLabels(value);
|
|
34589
|
+
if (labels.length > 0) return labels.join(", ");
|
|
34590
|
+
}
|
|
34591
|
+
return formatValue(value, format);
|
|
34592
|
+
};
|
|
34439
34593
|
MAX_MEASURED_COL_CH = 32;
|
|
34440
34594
|
BADGE_CHROME_CH = 4;
|
|
34441
34595
|
alignClass = {
|
|
@@ -38050,6 +38204,35 @@ var init_RichTextEditor = __esm({
|
|
|
38050
38204
|
document.execCommand("createLink", false, safe);
|
|
38051
38205
|
afterEdit();
|
|
38052
38206
|
}, [afterEdit, t, toolbar.link]);
|
|
38207
|
+
const imageInputRef = useRef(null);
|
|
38208
|
+
const savedRangeRef = useRef(null);
|
|
38209
|
+
const execImage = useCallback(() => {
|
|
38210
|
+
const root = ref.current;
|
|
38211
|
+
const sel = window.getSelection();
|
|
38212
|
+
savedRangeRef.current = root && sel && sel.rangeCount > 0 && root.contains(sel.anchorNode) ? sel.getRangeAt(0).cloneRange() : null;
|
|
38213
|
+
imageInputRef.current?.click();
|
|
38214
|
+
}, []);
|
|
38215
|
+
const handleImageFile = useCallback((e) => {
|
|
38216
|
+
const file = e.target.files?.[0];
|
|
38217
|
+
e.target.value = "";
|
|
38218
|
+
if (!file) return;
|
|
38219
|
+
const reader = new FileReader();
|
|
38220
|
+
reader.onload = () => {
|
|
38221
|
+
const url = typeof reader.result === "string" ? reader.result : "";
|
|
38222
|
+
if (!url.startsWith("data:image/")) return;
|
|
38223
|
+
const root = ref.current;
|
|
38224
|
+
if (!root) return;
|
|
38225
|
+
root.focus();
|
|
38226
|
+
const sel = window.getSelection();
|
|
38227
|
+
if (sel && savedRangeRef.current && root.contains(savedRangeRef.current.startContainer)) {
|
|
38228
|
+
sel.removeAllRanges();
|
|
38229
|
+
sel.addRange(savedRangeRef.current);
|
|
38230
|
+
}
|
|
38231
|
+
document.execCommand("insertImage", false, url);
|
|
38232
|
+
afterEdit();
|
|
38233
|
+
};
|
|
38234
|
+
reader.readAsDataURL(file);
|
|
38235
|
+
}, [afterEdit]);
|
|
38053
38236
|
const execRule = useCallback(() => {
|
|
38054
38237
|
document.execCommand("insertHorizontalRule", false);
|
|
38055
38238
|
afterEdit();
|
|
@@ -38062,6 +38245,18 @@ var init_RichTextEditor = __esm({
|
|
|
38062
38245
|
}
|
|
38063
38246
|
return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col gap-2", className), children: [
|
|
38064
38247
|
/* @__PURE__ */ jsx(RichTextStyles, {}),
|
|
38248
|
+
/* @__PURE__ */ jsx(
|
|
38249
|
+
"input",
|
|
38250
|
+
{
|
|
38251
|
+
ref: imageInputRef,
|
|
38252
|
+
type: "file",
|
|
38253
|
+
accept: "image/*",
|
|
38254
|
+
className: "hidden",
|
|
38255
|
+
"aria-hidden": "true",
|
|
38256
|
+
tabIndex: -1,
|
|
38257
|
+
onChange: handleImageFile
|
|
38258
|
+
}
|
|
38259
|
+
),
|
|
38065
38260
|
showToolbar && /* @__PURE__ */ jsxs(
|
|
38066
38261
|
Box,
|
|
38067
38262
|
{
|
|
@@ -38087,6 +38282,7 @@ var init_RichTextEditor = __esm({
|
|
|
38087
38282
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Quote, label: t("richTextEditor.quote"), active: toolbar.block === "blockquote", onExec: () => execBlock("blockquote") }),
|
|
38088
38283
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Code, label: t("richTextEditor.code"), active: toolbar.block === "pre", onExec: () => execBlock("pre") }),
|
|
38089
38284
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Link$1, label: toolbar.link ? t("richTextEditor.removeLink") : t("richTextEditor.link"), active: toolbar.link, onExec: execLink }),
|
|
38285
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Image$1, label: t("richTextEditor.image"), onExec: execImage }),
|
|
38090
38286
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Minus, label: t("richTextEditor.divider"), onExec: execRule })
|
|
38091
38287
|
]
|
|
38092
38288
|
}
|
|
@@ -38127,6 +38323,8 @@ function DocumentPanel({
|
|
|
38127
38323
|
id,
|
|
38128
38324
|
title,
|
|
38129
38325
|
subtitle,
|
|
38326
|
+
coverImage,
|
|
38327
|
+
icon,
|
|
38130
38328
|
value,
|
|
38131
38329
|
actions,
|
|
38132
38330
|
maxInlineActions,
|
|
@@ -38202,62 +38400,74 @@ function DocumentPanel({
|
|
|
38202
38400
|
const emitWithId = (event) => () => {
|
|
38203
38401
|
if (event) eventBus.emit(`UI:${event}`, { id: recordId });
|
|
38204
38402
|
};
|
|
38205
|
-
return /* @__PURE__ */
|
|
38206
|
-
/* @__PURE__ */
|
|
38207
|
-
|
|
38208
|
-
titleNode,
|
|
38209
|
-
subtitle ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
38210
|
-
] }),
|
|
38211
|
-
/* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38212
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
38213
|
-
/* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
38214
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38215
|
-
editEvent && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
38216
|
-
/* @__PURE__ */ jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
38217
|
-
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
38218
|
-
] }),
|
|
38219
|
-
inlineActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
38220
|
-
Button,
|
|
38221
|
-
{
|
|
38222
|
-
variant: "primary",
|
|
38223
|
-
size: "sm",
|
|
38224
|
-
onClick: () => fireAction(action),
|
|
38225
|
-
"data-testid": `action-${action.event}`,
|
|
38226
|
-
children: [
|
|
38227
|
-
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
38228
|
-
action.label
|
|
38229
|
-
]
|
|
38230
|
-
},
|
|
38231
|
-
idx
|
|
38232
|
-
)),
|
|
38233
|
-
menuActions.length > 0 && /* @__PURE__ */ jsx(
|
|
38234
|
-
Menu,
|
|
38235
|
-
{
|
|
38236
|
-
position: "bottom-end",
|
|
38237
|
-
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" }) }),
|
|
38238
|
-
items: menuActions.map((action) => ({
|
|
38239
|
-
label: action.label,
|
|
38240
|
-
icon: action.icon,
|
|
38241
|
-
variant: action.variant === "danger" ? "danger" : "default",
|
|
38242
|
-
onClick: () => fireAction(action)
|
|
38243
|
-
}))
|
|
38244
|
-
}
|
|
38245
|
-
)
|
|
38246
|
-
] }) })
|
|
38247
|
-
] }),
|
|
38248
|
-
editing ? /* @__PURE__ */ jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsx(
|
|
38249
|
-
Box,
|
|
38403
|
+
return /* @__PURE__ */ jsxs(Card, { variant: "elevated", className: cn("w-full overflow-hidden", className), children: [
|
|
38404
|
+
coverImage ? /* @__PURE__ */ jsx(Box, { className: "h-44 w-full sm:h-52", "data-testid": "document-cover", children: /* @__PURE__ */ jsx(
|
|
38405
|
+
"img",
|
|
38250
38406
|
{
|
|
38251
|
-
|
|
38252
|
-
|
|
38253
|
-
|
|
38254
|
-
|
|
38255
|
-
|
|
38256
|
-
|
|
38257
|
-
|
|
38258
|
-
|
|
38259
|
-
|
|
38260
|
-
|
|
38407
|
+
src: coverImage,
|
|
38408
|
+
alt: "",
|
|
38409
|
+
"aria-hidden": "true",
|
|
38410
|
+
className: "h-full w-full object-cover"
|
|
38411
|
+
}
|
|
38412
|
+
) }) : null,
|
|
38413
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "p-6 sm:p-8", children: [
|
|
38414
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
38415
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
38416
|
+
icon ? /* @__PURE__ */ jsx(Box, { className: "text-muted-foreground", "data-testid": "document-icon", children: renderIconInput4(icon, { size: "lg" }) }) : null,
|
|
38417
|
+
titleNode,
|
|
38418
|
+
subtitle ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
38419
|
+
] }),
|
|
38420
|
+
/* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38421
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
38422
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
38423
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38424
|
+
editEvent && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
38425
|
+
/* @__PURE__ */ jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
38426
|
+
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
38427
|
+
] }),
|
|
38428
|
+
inlineActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
38429
|
+
Button,
|
|
38430
|
+
{
|
|
38431
|
+
variant: "primary",
|
|
38432
|
+
size: "sm",
|
|
38433
|
+
onClick: () => fireAction(action),
|
|
38434
|
+
"data-testid": `action-${action.event}`,
|
|
38435
|
+
children: [
|
|
38436
|
+
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
38437
|
+
action.label
|
|
38438
|
+
]
|
|
38439
|
+
},
|
|
38440
|
+
idx
|
|
38441
|
+
)),
|
|
38442
|
+
menuActions.length > 0 && /* @__PURE__ */ jsx(
|
|
38443
|
+
Menu,
|
|
38444
|
+
{
|
|
38445
|
+
position: "bottom-end",
|
|
38446
|
+
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" }) }),
|
|
38447
|
+
items: menuActions.map((action) => ({
|
|
38448
|
+
label: action.label,
|
|
38449
|
+
icon: action.icon,
|
|
38450
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
38451
|
+
onClick: () => fireAction(action)
|
|
38452
|
+
}))
|
|
38453
|
+
}
|
|
38454
|
+
)
|
|
38455
|
+
] }) })
|
|
38456
|
+
] }),
|
|
38457
|
+
editing ? /* @__PURE__ */ jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsx(
|
|
38458
|
+
Box,
|
|
38459
|
+
{
|
|
38460
|
+
onClick: emitWithId(editEvent),
|
|
38461
|
+
className: cn(
|
|
38462
|
+
"rounded-md px-1 -mx-1 min-h-[16rem]",
|
|
38463
|
+
editEvent && "cursor-text transition-colors hover:bg-muted/30"
|
|
38464
|
+
),
|
|
38465
|
+
"data-testid": "document-body",
|
|
38466
|
+
children: value && value !== "" ? /* @__PURE__ */ jsx(RichTextEditor, { value, readOnly: true }) : /* @__PURE__ */ jsx(Typography, { variant: "body", color: "muted", children: placeholder ?? (t("documentPanel.placeholder") || "") })
|
|
38467
|
+
}
|
|
38468
|
+
)
|
|
38469
|
+
] })
|
|
38470
|
+
] });
|
|
38261
38471
|
}
|
|
38262
38472
|
var init_DocumentPanel = __esm({
|
|
38263
38473
|
"components/core/molecules/DocumentPanel.tsx"() {
|
|
@@ -38281,17 +38491,16 @@ function renderIconInput5(icon, props) {
|
|
|
38281
38491
|
function fieldName(field) {
|
|
38282
38492
|
return field.name ?? field.key ?? "";
|
|
38283
38493
|
}
|
|
38284
|
-
function
|
|
38285
|
-
if (value
|
|
38286
|
-
|
|
38287
|
-
|
|
38288
|
-
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
38494
|
+
function relationId(value) {
|
|
38495
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
|
|
38496
|
+
const id = value.id;
|
|
38497
|
+
if (id !== void 0 && id !== null) return String(id);
|
|
38289
38498
|
}
|
|
38290
|
-
|
|
38291
|
-
return id !== void 0 && id !== null ? String(id) : null;
|
|
38499
|
+
return String(value);
|
|
38292
38500
|
}
|
|
38293
38501
|
function fieldKind(field, value) {
|
|
38294
38502
|
if (field.kind) return field.kind;
|
|
38503
|
+
if (field.type === "image") return "image";
|
|
38295
38504
|
if (field.options && field.options.length > 0) return "select";
|
|
38296
38505
|
if (typeof value === "boolean" || field.format === "boolean") return "boolean";
|
|
38297
38506
|
if (Array.isArray(value) || relationLabel(value ?? null) !== null) return "readonly";
|
|
@@ -38301,6 +38510,7 @@ function DocumentDetails({
|
|
|
38301
38510
|
entity,
|
|
38302
38511
|
fields,
|
|
38303
38512
|
metaCommitEvent,
|
|
38513
|
+
relationEvent,
|
|
38304
38514
|
title,
|
|
38305
38515
|
className
|
|
38306
38516
|
}) {
|
|
@@ -38315,11 +38525,51 @@ function DocumentDetails({
|
|
|
38315
38525
|
if (!metaCommitEvent || next === current) return;
|
|
38316
38526
|
eventBus.emit(`UI:${metaCommitEvent}`, { id: recordId, patch: { id: recordId, [name]: next } });
|
|
38317
38527
|
};
|
|
38528
|
+
const relationChip = (item, name, key) => {
|
|
38529
|
+
const label = relationLabel(item) ?? humanizeEnumValue(String(item));
|
|
38530
|
+
if (!relationEvent) {
|
|
38531
|
+
return /* @__PURE__ */ jsx(Badge, { variant: "default", children: label }, key);
|
|
38532
|
+
}
|
|
38533
|
+
const emitClick = () => eventBus.emit(`UI:${relationEvent}`, { field: name, id: relationId(item), name: label });
|
|
38534
|
+
return /* @__PURE__ */ jsx(
|
|
38535
|
+
Badge,
|
|
38536
|
+
{
|
|
38537
|
+
variant: "default",
|
|
38538
|
+
role: "button",
|
|
38539
|
+
tabIndex: 0,
|
|
38540
|
+
className: "cursor-pointer transition-colors hover:bg-accent",
|
|
38541
|
+
onClick: emitClick,
|
|
38542
|
+
onKeyDown: (e) => {
|
|
38543
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
38544
|
+
e.preventDefault();
|
|
38545
|
+
emitClick();
|
|
38546
|
+
}
|
|
38547
|
+
},
|
|
38548
|
+
"data-testid": `relation-chip-${name}`,
|
|
38549
|
+
children: label
|
|
38550
|
+
},
|
|
38551
|
+
key
|
|
38552
|
+
);
|
|
38553
|
+
};
|
|
38318
38554
|
const renderValue = (field) => {
|
|
38319
38555
|
const name = fieldName(field);
|
|
38320
38556
|
const raw = getNestedValue(entity ?? {}, name);
|
|
38321
38557
|
const kind = fieldKind(field, raw);
|
|
38322
38558
|
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
38559
|
+
if (kind === "image") {
|
|
38560
|
+
const url = typeof raw === "string" ? raw : "";
|
|
38561
|
+
if (!url) return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
38562
|
+
return /* @__PURE__ */ jsx(
|
|
38563
|
+
"img",
|
|
38564
|
+
{
|
|
38565
|
+
src: url,
|
|
38566
|
+
alt: label,
|
|
38567
|
+
loading: "lazy",
|
|
38568
|
+
className: "max-h-32 w-full rounded-md border border-border object-cover",
|
|
38569
|
+
"data-testid": `document-property-image-${name}`
|
|
38570
|
+
}
|
|
38571
|
+
);
|
|
38572
|
+
}
|
|
38323
38573
|
if (kind === "boolean") {
|
|
38324
38574
|
return /* @__PURE__ */ jsx(
|
|
38325
38575
|
Switch,
|
|
@@ -38349,9 +38599,12 @@ function DocumentDetails({
|
|
|
38349
38599
|
if (raw.length === 0) {
|
|
38350
38600
|
return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
38351
38601
|
}
|
|
38352
|
-
return /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) =>
|
|
38602
|
+
return /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) => relationChip(item, name, i)) });
|
|
38353
38603
|
}
|
|
38354
|
-
|
|
38604
|
+
if (raw !== void 0 && raw !== null && raw !== "" && relationLabel(raw) !== null) {
|
|
38605
|
+
return relationChip(raw, name);
|
|
38606
|
+
}
|
|
38607
|
+
const shown2 = raw === void 0 || raw === null || raw === "" ? "\u2014" : formatValue(raw, field.format);
|
|
38355
38608
|
return /* @__PURE__ */ jsx(Typography, { variant: "small", className: "break-words", children: shown2 });
|
|
38356
38609
|
}
|
|
38357
38610
|
if (fieldDraft?.name === name) {
|
|
@@ -38420,6 +38673,7 @@ var init_DocumentDetails = __esm({
|
|
|
38420
38673
|
init_cn();
|
|
38421
38674
|
init_format();
|
|
38422
38675
|
init_getNestedValue();
|
|
38676
|
+
init_relationLabel();
|
|
38423
38677
|
init_useEventBus();
|
|
38424
38678
|
init_Box();
|
|
38425
38679
|
init_Stack();
|
|
@@ -43641,7 +43895,18 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
43641
43895
|
if (value === void 0 || value === null) return "\u2014";
|
|
43642
43896
|
const str2 = String(value);
|
|
43643
43897
|
switch (fieldType) {
|
|
43644
|
-
case "image":
|
|
43898
|
+
case "image": {
|
|
43899
|
+
if (!str2) return "\u2014";
|
|
43900
|
+
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
43901
|
+
"img",
|
|
43902
|
+
{
|
|
43903
|
+
src: str2,
|
|
43904
|
+
alt: formatFieldLabel(fieldName2),
|
|
43905
|
+
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
43906
|
+
loading: "lazy"
|
|
43907
|
+
}
|
|
43908
|
+
) });
|
|
43909
|
+
}
|
|
43645
43910
|
case "url": {
|
|
43646
43911
|
if (str2.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str2.startsWith("data:image/")) {
|
|
43647
43912
|
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
@@ -43654,7 +43919,7 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
43654
43919
|
}
|
|
43655
43920
|
) });
|
|
43656
43921
|
}
|
|
43657
|
-
if (
|
|
43922
|
+
if (/^https?:\/\//i.test(str2)) {
|
|
43658
43923
|
return /* @__PURE__ */ jsx(
|
|
43659
43924
|
"a",
|
|
43660
43925
|
{
|
|
@@ -43740,8 +44005,10 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
43740
44005
|
return str2;
|
|
43741
44006
|
}
|
|
43742
44007
|
case "relation": {
|
|
43743
|
-
const
|
|
43744
|
-
|
|
44008
|
+
const labels = relationDisplayLabels(value, meta?.options);
|
|
44009
|
+
if (labels.length === 0) return "\u2014";
|
|
44010
|
+
if (labels.length === 1) return labels[0];
|
|
44011
|
+
return /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: labels.map((label, i) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: label }, i)) });
|
|
43745
44012
|
}
|
|
43746
44013
|
case "file": {
|
|
43747
44014
|
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
@@ -43843,6 +44110,7 @@ var init_DetailPanel = __esm({
|
|
|
43843
44110
|
init_cn();
|
|
43844
44111
|
init_format();
|
|
43845
44112
|
init_getNestedValue();
|
|
44113
|
+
init_relationLabel();
|
|
43846
44114
|
init_useEventBus();
|
|
43847
44115
|
init_UploadDropZone();
|
|
43848
44116
|
formatFieldLabel = humanizeFieldName;
|
|
@@ -44501,6 +44769,8 @@ function determineInputType(field) {
|
|
|
44501
44769
|
return "url";
|
|
44502
44770
|
case "file":
|
|
44503
44771
|
return "file";
|
|
44772
|
+
case "image":
|
|
44773
|
+
return "image";
|
|
44504
44774
|
case "money":
|
|
44505
44775
|
return "currency";
|
|
44506
44776
|
case "number":
|
|
@@ -45100,6 +45370,50 @@ var init_Form = __esm({
|
|
|
45100
45370
|
}
|
|
45101
45371
|
}
|
|
45102
45372
|
);
|
|
45373
|
+
case "image": {
|
|
45374
|
+
const imageUrl = typeof currentValue2 === "string" ? currentValue2 : "";
|
|
45375
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
45376
|
+
imageUrl ? /* @__PURE__ */ jsx(
|
|
45377
|
+
"img",
|
|
45378
|
+
{
|
|
45379
|
+
src: imageUrl,
|
|
45380
|
+
alt: "",
|
|
45381
|
+
"aria-hidden": "true",
|
|
45382
|
+
className: "h-24 w-full max-w-xs rounded-md border border-border object-cover",
|
|
45383
|
+
"data-testid": `image-preview-${fieldName2}`
|
|
45384
|
+
}
|
|
45385
|
+
) : null,
|
|
45386
|
+
/* @__PURE__ */ jsx(
|
|
45387
|
+
UploadDropZone,
|
|
45388
|
+
{
|
|
45389
|
+
accept: "image/*",
|
|
45390
|
+
maxFiles: 1,
|
|
45391
|
+
maxSize: 2 * 1024 * 1024,
|
|
45392
|
+
disabled: isLoading,
|
|
45393
|
+
onFiles: (files) => {
|
|
45394
|
+
const f3 = files[0];
|
|
45395
|
+
if (!f3) return;
|
|
45396
|
+
const reader = new FileReader();
|
|
45397
|
+
reader.onload = () => handleChange(
|
|
45398
|
+
fieldName2,
|
|
45399
|
+
typeof reader.result === "string" ? reader.result : ""
|
|
45400
|
+
);
|
|
45401
|
+
reader.readAsDataURL(f3);
|
|
45402
|
+
}
|
|
45403
|
+
}
|
|
45404
|
+
),
|
|
45405
|
+
/* @__PURE__ */ jsx(
|
|
45406
|
+
Input,
|
|
45407
|
+
{
|
|
45408
|
+
...commonProps,
|
|
45409
|
+
type: "url",
|
|
45410
|
+
placeholder: t("form.imageUrlFallback"),
|
|
45411
|
+
value: imageUrl,
|
|
45412
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
45413
|
+
}
|
|
45414
|
+
)
|
|
45415
|
+
] });
|
|
45416
|
+
}
|
|
45103
45417
|
case "date":
|
|
45104
45418
|
return /* @__PURE__ */ jsx(
|
|
45105
45419
|
Input,
|
|
@@ -53866,7 +54180,10 @@ var en_default = {
|
|
|
53866
54180
|
"richTextEditor.removeLink": "Remove link",
|
|
53867
54181
|
"richTextEditor.divider": "Divider",
|
|
53868
54182
|
"richTextEditor.linkPrompt": "Link address",
|
|
53869
|
-
"richTextEditor.
|
|
54183
|
+
"richTextEditor.image": "Insert image",
|
|
54184
|
+
"richTextEditor.imagePrompt": "Image URL",
|
|
54185
|
+
"richTextEditor.placeholder": "Start writing\u2026",
|
|
54186
|
+
"form.imageUrlFallback": "\u2026or paste an image address"
|
|
53870
54187
|
};
|
|
53871
54188
|
|
|
53872
54189
|
// hooks/useTranslate.ts
|