@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/runtime/index.js
CHANGED
|
@@ -24445,6 +24445,7 @@ var init_DashboardLayout = __esm({
|
|
|
24445
24445
|
onNotificationClick,
|
|
24446
24446
|
showThemeToggle = true,
|
|
24447
24447
|
sidebarFooter,
|
|
24448
|
+
sidebarContent,
|
|
24448
24449
|
onSignOut: onSignOutProp,
|
|
24449
24450
|
currentPath,
|
|
24450
24451
|
layoutMode = "sidebar",
|
|
@@ -24570,7 +24571,11 @@ var init_DashboardLayout = __esm({
|
|
|
24570
24571
|
{
|
|
24571
24572
|
as: "nav",
|
|
24572
24573
|
gap: "none",
|
|
24573
|
-
className: cn(
|
|
24574
|
+
className: cn(
|
|
24575
|
+
"py-4 space-y-1 overflow-y-auto",
|
|
24576
|
+
sidebarContent && !isRail ? "shrink-0" : "flex-1",
|
|
24577
|
+
isRail ? "px-2" : "px-3"
|
|
24578
|
+
),
|
|
24574
24579
|
children: navItems.map((item) => /* @__PURE__ */ jsx(
|
|
24575
24580
|
NavLink,
|
|
24576
24581
|
{
|
|
@@ -24582,6 +24587,7 @@ var init_DashboardLayout = __esm({
|
|
|
24582
24587
|
))
|
|
24583
24588
|
}
|
|
24584
24589
|
),
|
|
24590
|
+
sidebarContent && !isRail && /* @__PURE__ */ jsx(Box, { className: "flex-1 overflow-y-auto border-t border-border dark:border-border px-2 py-3", children: sidebarContent }),
|
|
24585
24591
|
sidebarFooter && /* @__PURE__ */ jsx(Box, { className: "p-4 border-t border-border dark:border-border", children: sidebarFooter })
|
|
24586
24592
|
]
|
|
24587
24593
|
}
|
|
@@ -26991,7 +26997,17 @@ function fileIcon(name) {
|
|
|
26991
26997
|
return "file";
|
|
26992
26998
|
}
|
|
26993
26999
|
}
|
|
26994
|
-
|
|
27000
|
+
function ancestorsOf(id, byId) {
|
|
27001
|
+
const out = /* @__PURE__ */ new Set();
|
|
27002
|
+
if (!id) return out;
|
|
27003
|
+
let cur = byId.get(id)?.parentId;
|
|
27004
|
+
while (cur && byId.has(cur) && !out.has(cur)) {
|
|
27005
|
+
out.add(cur);
|
|
27006
|
+
cur = byId.get(cur)?.parentId;
|
|
27007
|
+
}
|
|
27008
|
+
return out;
|
|
27009
|
+
}
|
|
27010
|
+
var TreeNodeItem, FlatTreeNodeItem, FlatFileTree, FileTree;
|
|
26995
27011
|
var init_FileTree = __esm({
|
|
26996
27012
|
"components/core/molecules/FileTree.tsx"() {
|
|
26997
27013
|
"use client";
|
|
@@ -27082,42 +27098,77 @@ var init_FileTree = __esm({
|
|
|
27082
27098
|
indent,
|
|
27083
27099
|
childrenByParent,
|
|
27084
27100
|
onNodeSelect,
|
|
27085
|
-
|
|
27101
|
+
onNodeAction,
|
|
27102
|
+
nodeActionIcon,
|
|
27103
|
+
nodeActionLabel,
|
|
27104
|
+
selectedId,
|
|
27105
|
+
look,
|
|
27106
|
+
isExpanded,
|
|
27107
|
+
onToggle
|
|
27086
27108
|
}) => {
|
|
27087
|
-
const [expanded, setExpanded] = useState(defaultExpanded || depth < 1);
|
|
27088
27109
|
const children = childrenByParent.get(item.id);
|
|
27089
27110
|
const hasChildren = !!children && children.length > 0;
|
|
27111
|
+
const expanded = hasChildren && isExpanded(item.id, depth);
|
|
27112
|
+
const isSelected = selectedId !== void 0 && selectedId !== "" && item.id === selectedId;
|
|
27113
|
+
const nav = look === "nav";
|
|
27090
27114
|
const handleClick = useCallback(() => {
|
|
27091
|
-
if (hasChildren)
|
|
27115
|
+
if (hasChildren && !onNodeSelect) onToggle(item.id, expanded);
|
|
27092
27116
|
onNodeSelect?.(item.id);
|
|
27093
|
-
}, [hasChildren, item.id, onNodeSelect]);
|
|
27117
|
+
}, [hasChildren, expanded, item.id, onNodeSelect, onToggle]);
|
|
27118
|
+
const handleChevron = useCallback((e) => {
|
|
27119
|
+
e.stopPropagation();
|
|
27120
|
+
onToggle(item.id, expanded);
|
|
27121
|
+
}, [item.id, expanded, onToggle]);
|
|
27122
|
+
const handleAction = useCallback((e) => {
|
|
27123
|
+
e.stopPropagation();
|
|
27124
|
+
onNodeAction?.(item.id);
|
|
27125
|
+
}, [item.id, onNodeAction]);
|
|
27094
27126
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
27095
27127
|
/* @__PURE__ */ jsxs(
|
|
27096
27128
|
Box,
|
|
27097
27129
|
{
|
|
27098
|
-
className:
|
|
27130
|
+
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"}`,
|
|
27099
27131
|
style: { paddingLeft: depth * indent + 8 },
|
|
27100
27132
|
onClick: handleClick,
|
|
27101
27133
|
role: "treeitem",
|
|
27134
|
+
"aria-selected": isSelected,
|
|
27102
27135
|
"aria-expanded": hasChildren ? expanded : void 0,
|
|
27103
27136
|
children: [
|
|
27104
|
-
hasChildren ? /* @__PURE__ */ jsx(
|
|
27137
|
+
hasChildren ? /* @__PURE__ */ jsx(Box, { onClick: handleChevron, className: "flex items-center flex-shrink-0", role: "button", "aria-label": expanded ? "Collapse" : "Expand", children: /* @__PURE__ */ jsx(
|
|
27105
27138
|
Icon,
|
|
27106
27139
|
{
|
|
27107
27140
|
name: expanded ? "chevron-down" : "chevron-right",
|
|
27108
27141
|
size: "xs",
|
|
27109
|
-
className: "text-[var(--color-muted-foreground)]
|
|
27142
|
+
className: isSelected ? "text-inherit" : "text-[var(--color-muted-foreground)]"
|
|
27110
27143
|
}
|
|
27111
|
-
) : /* @__PURE__ */ jsx(Box, { style: { width: 12, flexShrink: 0 } }),
|
|
27144
|
+
) }) : /* @__PURE__ */ jsx(Box, { style: { width: 12, flexShrink: 0 } }),
|
|
27112
27145
|
/* @__PURE__ */ jsx(
|
|
27113
27146
|
Icon,
|
|
27114
27147
|
{
|
|
27115
|
-
name: item.icon
|
|
27148
|
+
name: item.icon || (nav ? "file-text" : hasChildren ? expanded ? "folder-open" : "folder" : "file"),
|
|
27116
27149
|
size: "xs",
|
|
27117
|
-
className: hasChildren ? "text-[var(--color-
|
|
27150
|
+
className: isSelected ? "text-inherit" : nav || !hasChildren ? "text-[var(--color-muted-foreground)]" : "text-[var(--color-warning)]"
|
|
27118
27151
|
}
|
|
27119
27152
|
),
|
|
27120
|
-
/* @__PURE__ */ jsx(
|
|
27153
|
+
/* @__PURE__ */ jsx(
|
|
27154
|
+
Typography,
|
|
27155
|
+
{
|
|
27156
|
+
variant: "caption",
|
|
27157
|
+
className: `truncate ${nav ? "text-sm" : "font-mono text-xs"} !text-inherit ${isSelected ? "font-semibold" : ""}`,
|
|
27158
|
+
children: item.label
|
|
27159
|
+
}
|
|
27160
|
+
),
|
|
27161
|
+
onNodeAction && /* @__PURE__ */ jsx(
|
|
27162
|
+
Box,
|
|
27163
|
+
{
|
|
27164
|
+
onClick: handleAction,
|
|
27165
|
+
role: "button",
|
|
27166
|
+
"aria-label": nodeActionLabel ?? "Node action",
|
|
27167
|
+
title: nodeActionLabel,
|
|
27168
|
+
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"}`,
|
|
27169
|
+
children: /* @__PURE__ */ jsx(Icon, { name: nodeActionIcon ?? "plus", size: "xs", className: "text-inherit" })
|
|
27170
|
+
}
|
|
27171
|
+
)
|
|
27121
27172
|
]
|
|
27122
27173
|
}
|
|
27123
27174
|
),
|
|
@@ -27128,47 +27179,116 @@ var init_FileTree = __esm({
|
|
|
27128
27179
|
depth: depth + 1,
|
|
27129
27180
|
indent,
|
|
27130
27181
|
childrenByParent,
|
|
27131
|
-
onNodeSelect
|
|
27182
|
+
onNodeSelect,
|
|
27183
|
+
onNodeAction,
|
|
27184
|
+
nodeActionIcon,
|
|
27185
|
+
nodeActionLabel,
|
|
27186
|
+
selectedId,
|
|
27187
|
+
look,
|
|
27188
|
+
isExpanded,
|
|
27189
|
+
onToggle
|
|
27132
27190
|
},
|
|
27133
27191
|
child.id
|
|
27134
27192
|
)) })
|
|
27135
27193
|
] });
|
|
27136
27194
|
};
|
|
27195
|
+
FlatFileTree = ({
|
|
27196
|
+
items,
|
|
27197
|
+
selectedId,
|
|
27198
|
+
look = "files",
|
|
27199
|
+
onNodeSelect,
|
|
27200
|
+
onNodeAction,
|
|
27201
|
+
nodeActionIcon,
|
|
27202
|
+
nodeActionLabel,
|
|
27203
|
+
className,
|
|
27204
|
+
indent = 16
|
|
27205
|
+
}) => {
|
|
27206
|
+
const [overrides, setOverrides] = useState(() => /* @__PURE__ */ new Map());
|
|
27207
|
+
const byId = React85__default.useMemo(() => new Map(items.map((node) => [node.id, node])), [items]);
|
|
27208
|
+
const selectedAncestors = React85__default.useMemo(() => ancestorsOf(selectedId, byId), [selectedId, byId]);
|
|
27209
|
+
const lastSelectedRef = React85__default.useRef(selectedId);
|
|
27210
|
+
React85__default.useEffect(() => {
|
|
27211
|
+
if (selectedId === lastSelectedRef.current) return;
|
|
27212
|
+
lastSelectedRef.current = selectedId;
|
|
27213
|
+
setOverrides((prev) => {
|
|
27214
|
+
if (![...selectedAncestors].some((a) => prev.get(a) === false)) return prev;
|
|
27215
|
+
const next = new Map(prev);
|
|
27216
|
+
for (const a of selectedAncestors) if (next.get(a) === false) next.delete(a);
|
|
27217
|
+
return next;
|
|
27218
|
+
});
|
|
27219
|
+
}, [selectedId, selectedAncestors]);
|
|
27220
|
+
const isExpanded = useCallback(
|
|
27221
|
+
(id, depth) => overrides.get(id) ?? (depth < 1 || selectedAncestors.has(id)),
|
|
27222
|
+
[overrides, selectedAncestors]
|
|
27223
|
+
);
|
|
27224
|
+
const onToggle = useCallback((id, effective) => {
|
|
27225
|
+
setOverrides((prev) => {
|
|
27226
|
+
const next = new Map(prev);
|
|
27227
|
+
next.set(id, !effective);
|
|
27228
|
+
return next;
|
|
27229
|
+
});
|
|
27230
|
+
}, []);
|
|
27231
|
+
if (items.length === 0) return null;
|
|
27232
|
+
const ids = new Set(items.map((node) => node.id));
|
|
27233
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
27234
|
+
const roots = [];
|
|
27235
|
+
for (const item of items) {
|
|
27236
|
+
if (item.parentId && ids.has(item.parentId)) {
|
|
27237
|
+
const siblings = childrenByParent.get(item.parentId);
|
|
27238
|
+
if (siblings) siblings.push(item);
|
|
27239
|
+
else childrenByParent.set(item.parentId, [item]);
|
|
27240
|
+
} else {
|
|
27241
|
+
roots.push(item);
|
|
27242
|
+
}
|
|
27243
|
+
}
|
|
27244
|
+
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: roots.map((item) => /* @__PURE__ */ jsx(
|
|
27245
|
+
FlatTreeNodeItem,
|
|
27246
|
+
{
|
|
27247
|
+
item,
|
|
27248
|
+
depth: 0,
|
|
27249
|
+
indent,
|
|
27250
|
+
childrenByParent,
|
|
27251
|
+
onNodeSelect,
|
|
27252
|
+
onNodeAction,
|
|
27253
|
+
nodeActionIcon,
|
|
27254
|
+
nodeActionLabel,
|
|
27255
|
+
selectedId,
|
|
27256
|
+
look,
|
|
27257
|
+
isExpanded,
|
|
27258
|
+
onToggle
|
|
27259
|
+
},
|
|
27260
|
+
item.id
|
|
27261
|
+
)) });
|
|
27262
|
+
};
|
|
27137
27263
|
FileTree = ({
|
|
27138
27264
|
tree,
|
|
27139
27265
|
items,
|
|
27140
27266
|
selectedPath,
|
|
27267
|
+
selectedId,
|
|
27268
|
+
look = "files",
|
|
27141
27269
|
onFileSelect,
|
|
27142
27270
|
onNodeSelect,
|
|
27271
|
+
onNodeAction,
|
|
27272
|
+
nodeActionIcon,
|
|
27273
|
+
nodeActionLabel,
|
|
27143
27274
|
className,
|
|
27144
27275
|
indent = 16
|
|
27145
27276
|
}) => {
|
|
27146
27277
|
if (items) {
|
|
27147
|
-
|
|
27148
|
-
|
|
27149
|
-
const childrenByParent = /* @__PURE__ */ new Map();
|
|
27150
|
-
const roots = [];
|
|
27151
|
-
for (const item of items) {
|
|
27152
|
-
if (item.parentId && ids.has(item.parentId)) {
|
|
27153
|
-
const siblings = childrenByParent.get(item.parentId);
|
|
27154
|
-
if (siblings) siblings.push(item);
|
|
27155
|
-
else childrenByParent.set(item.parentId, [item]);
|
|
27156
|
-
} else {
|
|
27157
|
-
roots.push(item);
|
|
27158
|
-
}
|
|
27159
|
-
}
|
|
27160
|
-
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: roots.map((item) => /* @__PURE__ */ jsx(
|
|
27161
|
-
FlatTreeNodeItem,
|
|
27278
|
+
return /* @__PURE__ */ jsx(
|
|
27279
|
+
FlatFileTree,
|
|
27162
27280
|
{
|
|
27163
|
-
|
|
27164
|
-
|
|
27165
|
-
|
|
27166
|
-
childrenByParent,
|
|
27281
|
+
items,
|
|
27282
|
+
selectedId,
|
|
27283
|
+
look,
|
|
27167
27284
|
onNodeSelect,
|
|
27168
|
-
|
|
27169
|
-
|
|
27170
|
-
|
|
27171
|
-
|
|
27285
|
+
onNodeAction,
|
|
27286
|
+
nodeActionIcon,
|
|
27287
|
+
nodeActionLabel,
|
|
27288
|
+
className,
|
|
27289
|
+
indent
|
|
27290
|
+
}
|
|
27291
|
+
);
|
|
27172
27292
|
}
|
|
27173
27293
|
if (!tree || tree.length === 0) return null;
|
|
27174
27294
|
return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: tree.map((node) => /* @__PURE__ */ jsx(
|
|
@@ -32569,6 +32689,33 @@ var init_Lightbox = __esm({
|
|
|
32569
32689
|
Lightbox.displayName = "Lightbox";
|
|
32570
32690
|
}
|
|
32571
32691
|
});
|
|
32692
|
+
|
|
32693
|
+
// lib/relationLabel.ts
|
|
32694
|
+
function relationLabel(value) {
|
|
32695
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date)
|
|
32696
|
+
return null;
|
|
32697
|
+
for (const key of ["name", "title", "label"]) {
|
|
32698
|
+
const candidate = value[key];
|
|
32699
|
+
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
32700
|
+
}
|
|
32701
|
+
const id = value.id;
|
|
32702
|
+
return id !== void 0 && id !== null ? String(id) : null;
|
|
32703
|
+
}
|
|
32704
|
+
function relationDisplayLabels(value, options) {
|
|
32705
|
+
if (value === void 0 || value === null || value === "") return [];
|
|
32706
|
+
if (Array.isArray(value)) {
|
|
32707
|
+
return value.flatMap((item) => relationDisplayLabels(item, options));
|
|
32708
|
+
}
|
|
32709
|
+
const hydrated = relationLabel(value);
|
|
32710
|
+
if (hydrated !== null) return [hydrated];
|
|
32711
|
+
const raw = String(value);
|
|
32712
|
+
const match = options?.find((opt) => opt.value === raw);
|
|
32713
|
+
return [match ? match.label : raw];
|
|
32714
|
+
}
|
|
32715
|
+
var init_relationLabel = __esm({
|
|
32716
|
+
"lib/relationLabel.ts"() {
|
|
32717
|
+
}
|
|
32718
|
+
});
|
|
32572
32719
|
function renderIconInput3(icon, props) {
|
|
32573
32720
|
return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
|
|
32574
32721
|
}
|
|
@@ -32886,6 +33033,7 @@ var init_TableView = __esm({
|
|
|
32886
33033
|
"use client";
|
|
32887
33034
|
init_cn();
|
|
32888
33035
|
init_format();
|
|
33036
|
+
init_relationLabel();
|
|
32889
33037
|
init_getNestedValue();
|
|
32890
33038
|
init_useEventBus();
|
|
32891
33039
|
init_Box();
|
|
@@ -32899,7 +33047,13 @@ var init_TableView = __esm({
|
|
|
32899
33047
|
init_Menu();
|
|
32900
33048
|
init_useDataDnd();
|
|
32901
33049
|
tableViewLog = createLogger("almadar:ui:table-view");
|
|
32902
|
-
formatCell = (value, format) =>
|
|
33050
|
+
formatCell = (value, format) => {
|
|
33051
|
+
if (value !== null && value !== void 0 && typeof value === "object" && !(value instanceof Date)) {
|
|
33052
|
+
const labels = relationDisplayLabels(value);
|
|
33053
|
+
if (labels.length > 0) return labels.join(", ");
|
|
33054
|
+
}
|
|
33055
|
+
return formatValue(value, format);
|
|
33056
|
+
};
|
|
32903
33057
|
MAX_MEASURED_COL_CH = 32;
|
|
32904
33058
|
BADGE_CHROME_CH = 4;
|
|
32905
33059
|
alignClass = {
|
|
@@ -36376,6 +36530,35 @@ var init_RichTextEditor = __esm({
|
|
|
36376
36530
|
document.execCommand("createLink", false, safe);
|
|
36377
36531
|
afterEdit();
|
|
36378
36532
|
}, [afterEdit, t, toolbar.link]);
|
|
36533
|
+
const imageInputRef = useRef(null);
|
|
36534
|
+
const savedRangeRef = useRef(null);
|
|
36535
|
+
const execImage = useCallback(() => {
|
|
36536
|
+
const root = ref.current;
|
|
36537
|
+
const sel = window.getSelection();
|
|
36538
|
+
savedRangeRef.current = root && sel && sel.rangeCount > 0 && root.contains(sel.anchorNode) ? sel.getRangeAt(0).cloneRange() : null;
|
|
36539
|
+
imageInputRef.current?.click();
|
|
36540
|
+
}, []);
|
|
36541
|
+
const handleImageFile = useCallback((e) => {
|
|
36542
|
+
const file = e.target.files?.[0];
|
|
36543
|
+
e.target.value = "";
|
|
36544
|
+
if (!file) return;
|
|
36545
|
+
const reader = new FileReader();
|
|
36546
|
+
reader.onload = () => {
|
|
36547
|
+
const url = typeof reader.result === "string" ? reader.result : "";
|
|
36548
|
+
if (!url.startsWith("data:image/")) return;
|
|
36549
|
+
const root = ref.current;
|
|
36550
|
+
if (!root) return;
|
|
36551
|
+
root.focus();
|
|
36552
|
+
const sel = window.getSelection();
|
|
36553
|
+
if (sel && savedRangeRef.current && root.contains(savedRangeRef.current.startContainer)) {
|
|
36554
|
+
sel.removeAllRanges();
|
|
36555
|
+
sel.addRange(savedRangeRef.current);
|
|
36556
|
+
}
|
|
36557
|
+
document.execCommand("insertImage", false, url);
|
|
36558
|
+
afterEdit();
|
|
36559
|
+
};
|
|
36560
|
+
reader.readAsDataURL(file);
|
|
36561
|
+
}, [afterEdit]);
|
|
36379
36562
|
const execRule = useCallback(() => {
|
|
36380
36563
|
document.execCommand("insertHorizontalRule", false);
|
|
36381
36564
|
afterEdit();
|
|
@@ -36388,6 +36571,18 @@ var init_RichTextEditor = __esm({
|
|
|
36388
36571
|
}
|
|
36389
36572
|
return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col gap-2", className), children: [
|
|
36390
36573
|
/* @__PURE__ */ jsx(RichTextStyles, {}),
|
|
36574
|
+
/* @__PURE__ */ jsx(
|
|
36575
|
+
"input",
|
|
36576
|
+
{
|
|
36577
|
+
ref: imageInputRef,
|
|
36578
|
+
type: "file",
|
|
36579
|
+
accept: "image/*",
|
|
36580
|
+
className: "hidden",
|
|
36581
|
+
"aria-hidden": "true",
|
|
36582
|
+
tabIndex: -1,
|
|
36583
|
+
onChange: handleImageFile
|
|
36584
|
+
}
|
|
36585
|
+
),
|
|
36391
36586
|
showToolbar && /* @__PURE__ */ jsxs(
|
|
36392
36587
|
Box,
|
|
36393
36588
|
{
|
|
@@ -36413,6 +36608,7 @@ var init_RichTextEditor = __esm({
|
|
|
36413
36608
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Quote, label: t("richTextEditor.quote"), active: toolbar.block === "blockquote", onExec: () => execBlock("blockquote") }),
|
|
36414
36609
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Code, label: t("richTextEditor.code"), active: toolbar.block === "pre", onExec: () => execBlock("pre") }),
|
|
36415
36610
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Link$1, label: toolbar.link ? t("richTextEditor.removeLink") : t("richTextEditor.link"), active: toolbar.link, onExec: execLink }),
|
|
36611
|
+
/* @__PURE__ */ jsx(ToolbarButton, { icon: Image$1, label: t("richTextEditor.image"), onExec: execImage }),
|
|
36416
36612
|
/* @__PURE__ */ jsx(ToolbarButton, { icon: Minus, label: t("richTextEditor.divider"), onExec: execRule })
|
|
36417
36613
|
]
|
|
36418
36614
|
}
|
|
@@ -36453,6 +36649,8 @@ function DocumentPanel({
|
|
|
36453
36649
|
id,
|
|
36454
36650
|
title,
|
|
36455
36651
|
subtitle,
|
|
36652
|
+
coverImage,
|
|
36653
|
+
icon,
|
|
36456
36654
|
value,
|
|
36457
36655
|
actions,
|
|
36458
36656
|
maxInlineActions,
|
|
@@ -36528,62 +36726,74 @@ function DocumentPanel({
|
|
|
36528
36726
|
const emitWithId = (event) => () => {
|
|
36529
36727
|
if (event) eventBus.emit(`UI:${event}`, { id: recordId });
|
|
36530
36728
|
};
|
|
36531
|
-
return /* @__PURE__ */
|
|
36532
|
-
/* @__PURE__ */
|
|
36533
|
-
|
|
36534
|
-
titleNode,
|
|
36535
|
-
subtitle ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
36536
|
-
] }),
|
|
36537
|
-
/* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36538
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
36539
|
-
/* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
36540
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36541
|
-
editEvent && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
36542
|
-
/* @__PURE__ */ jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
36543
|
-
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
36544
|
-
] }),
|
|
36545
|
-
inlineActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
36546
|
-
Button,
|
|
36547
|
-
{
|
|
36548
|
-
variant: "primary",
|
|
36549
|
-
size: "sm",
|
|
36550
|
-
onClick: () => fireAction(action),
|
|
36551
|
-
"data-testid": `action-${action.event}`,
|
|
36552
|
-
children: [
|
|
36553
|
-
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
36554
|
-
action.label
|
|
36555
|
-
]
|
|
36556
|
-
},
|
|
36557
|
-
idx
|
|
36558
|
-
)),
|
|
36559
|
-
menuActions.length > 0 && /* @__PURE__ */ jsx(
|
|
36560
|
-
Menu,
|
|
36561
|
-
{
|
|
36562
|
-
position: "bottom-end",
|
|
36563
|
-
trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
|
|
36564
|
-
items: menuActions.map((action) => ({
|
|
36565
|
-
label: action.label,
|
|
36566
|
-
icon: action.icon,
|
|
36567
|
-
variant: action.variant === "danger" ? "danger" : "default",
|
|
36568
|
-
onClick: () => fireAction(action)
|
|
36569
|
-
}))
|
|
36570
|
-
}
|
|
36571
|
-
)
|
|
36572
|
-
] }) })
|
|
36573
|
-
] }),
|
|
36574
|
-
editing ? /* @__PURE__ */ jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsx(
|
|
36575
|
-
Box,
|
|
36729
|
+
return /* @__PURE__ */ jsxs(Card, { variant: "elevated", className: cn("w-full overflow-hidden", className), children: [
|
|
36730
|
+
coverImage ? /* @__PURE__ */ jsx(Box, { className: "h-44 w-full sm:h-52", "data-testid": "document-cover", children: /* @__PURE__ */ jsx(
|
|
36731
|
+
"img",
|
|
36576
36732
|
{
|
|
36577
|
-
|
|
36578
|
-
|
|
36579
|
-
|
|
36580
|
-
|
|
36581
|
-
|
|
36582
|
-
|
|
36583
|
-
|
|
36584
|
-
|
|
36585
|
-
|
|
36586
|
-
|
|
36733
|
+
src: coverImage,
|
|
36734
|
+
alt: "",
|
|
36735
|
+
"aria-hidden": "true",
|
|
36736
|
+
className: "h-full w-full object-cover"
|
|
36737
|
+
}
|
|
36738
|
+
) }) : null,
|
|
36739
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "p-6 sm:p-8", children: [
|
|
36740
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
36741
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
36742
|
+
icon ? /* @__PURE__ */ jsx(Box, { className: "text-muted-foreground", "data-testid": "document-icon", children: renderIconInput4(icon, { size: "lg" }) }) : null,
|
|
36743
|
+
titleNode,
|
|
36744
|
+
subtitle ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: subtitle }) : null
|
|
36745
|
+
] }),
|
|
36746
|
+
/* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 pt-1 items-center", children: editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36747
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "hidden sm:block", children: autosaveHint ?? (t("documentPanel.autosaveHint") || "") }),
|
|
36748
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: emitWithId(doneEvent), "data-testid": "document-done", children: doneLabel ?? (t("documentPanel.done") || "Done") })
|
|
36749
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36750
|
+
editEvent && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: emitWithId(editEvent), "data-testid": "document-edit", children: [
|
|
36751
|
+
/* @__PURE__ */ jsx(Icon, { name: "edit", size: "xs", className: "mr-1" }),
|
|
36752
|
+
editLabel ?? (t("documentPanel.edit") || "Edit")
|
|
36753
|
+
] }),
|
|
36754
|
+
inlineActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
36755
|
+
Button,
|
|
36756
|
+
{
|
|
36757
|
+
variant: "primary",
|
|
36758
|
+
size: "sm",
|
|
36759
|
+
onClick: () => fireAction(action),
|
|
36760
|
+
"data-testid": `action-${action.event}`,
|
|
36761
|
+
children: [
|
|
36762
|
+
action.icon && renderIconInput4(action.icon, { size: "xs", className: "mr-1" }),
|
|
36763
|
+
action.label
|
|
36764
|
+
]
|
|
36765
|
+
},
|
|
36766
|
+
idx
|
|
36767
|
+
)),
|
|
36768
|
+
menuActions.length > 0 && /* @__PURE__ */ jsx(
|
|
36769
|
+
Menu,
|
|
36770
|
+
{
|
|
36771
|
+
position: "bottom-end",
|
|
36772
|
+
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" }) }),
|
|
36773
|
+
items: menuActions.map((action) => ({
|
|
36774
|
+
label: action.label,
|
|
36775
|
+
icon: action.icon,
|
|
36776
|
+
variant: action.variant === "danger" ? "danger" : "default",
|
|
36777
|
+
onClick: () => fireAction(action)
|
|
36778
|
+
}))
|
|
36779
|
+
}
|
|
36780
|
+
)
|
|
36781
|
+
] }) })
|
|
36782
|
+
] }),
|
|
36783
|
+
editing ? /* @__PURE__ */ jsx(RichTextEditor, { value, changeEvent: contentChangeEvent, placeholder }) : /* @__PURE__ */ jsx(
|
|
36784
|
+
Box,
|
|
36785
|
+
{
|
|
36786
|
+
onClick: emitWithId(editEvent),
|
|
36787
|
+
className: cn(
|
|
36788
|
+
"rounded-md px-1 -mx-1 min-h-[16rem]",
|
|
36789
|
+
editEvent && "cursor-text transition-colors hover:bg-muted/30"
|
|
36790
|
+
),
|
|
36791
|
+
"data-testid": "document-body",
|
|
36792
|
+
children: value && value !== "" ? /* @__PURE__ */ jsx(RichTextEditor, { value, readOnly: true }) : /* @__PURE__ */ jsx(Typography, { variant: "body", color: "muted", children: placeholder ?? (t("documentPanel.placeholder") || "") })
|
|
36793
|
+
}
|
|
36794
|
+
)
|
|
36795
|
+
] })
|
|
36796
|
+
] });
|
|
36587
36797
|
}
|
|
36588
36798
|
var init_DocumentPanel = __esm({
|
|
36589
36799
|
"components/core/molecules/DocumentPanel.tsx"() {
|
|
@@ -36607,17 +36817,16 @@ function renderIconInput5(icon, props) {
|
|
|
36607
36817
|
function fieldName(field) {
|
|
36608
36818
|
return field.name ?? field.key ?? "";
|
|
36609
36819
|
}
|
|
36610
|
-
function
|
|
36611
|
-
if (value
|
|
36612
|
-
|
|
36613
|
-
|
|
36614
|
-
if (typeof candidate === "string" && candidate !== "") return candidate;
|
|
36820
|
+
function relationId(value) {
|
|
36821
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
|
|
36822
|
+
const id = value.id;
|
|
36823
|
+
if (id !== void 0 && id !== null) return String(id);
|
|
36615
36824
|
}
|
|
36616
|
-
|
|
36617
|
-
return id !== void 0 && id !== null ? String(id) : null;
|
|
36825
|
+
return String(value);
|
|
36618
36826
|
}
|
|
36619
36827
|
function fieldKind(field, value) {
|
|
36620
36828
|
if (field.kind) return field.kind;
|
|
36829
|
+
if (field.type === "image") return "image";
|
|
36621
36830
|
if (field.options && field.options.length > 0) return "select";
|
|
36622
36831
|
if (typeof value === "boolean" || field.format === "boolean") return "boolean";
|
|
36623
36832
|
if (Array.isArray(value) || relationLabel(value ?? null) !== null) return "readonly";
|
|
@@ -36627,6 +36836,7 @@ function DocumentDetails({
|
|
|
36627
36836
|
entity,
|
|
36628
36837
|
fields,
|
|
36629
36838
|
metaCommitEvent,
|
|
36839
|
+
relationEvent,
|
|
36630
36840
|
title,
|
|
36631
36841
|
className
|
|
36632
36842
|
}) {
|
|
@@ -36641,11 +36851,51 @@ function DocumentDetails({
|
|
|
36641
36851
|
if (!metaCommitEvent || next === current) return;
|
|
36642
36852
|
eventBus.emit(`UI:${metaCommitEvent}`, { id: recordId, patch: { id: recordId, [name]: next } });
|
|
36643
36853
|
};
|
|
36854
|
+
const relationChip = (item, name, key) => {
|
|
36855
|
+
const label = relationLabel(item) ?? humanizeEnumValue(String(item));
|
|
36856
|
+
if (!relationEvent) {
|
|
36857
|
+
return /* @__PURE__ */ jsx(Badge, { variant: "default", children: label }, key);
|
|
36858
|
+
}
|
|
36859
|
+
const emitClick = () => eventBus.emit(`UI:${relationEvent}`, { field: name, id: relationId(item), name: label });
|
|
36860
|
+
return /* @__PURE__ */ jsx(
|
|
36861
|
+
Badge,
|
|
36862
|
+
{
|
|
36863
|
+
variant: "default",
|
|
36864
|
+
role: "button",
|
|
36865
|
+
tabIndex: 0,
|
|
36866
|
+
className: "cursor-pointer transition-colors hover:bg-accent",
|
|
36867
|
+
onClick: emitClick,
|
|
36868
|
+
onKeyDown: (e) => {
|
|
36869
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
36870
|
+
e.preventDefault();
|
|
36871
|
+
emitClick();
|
|
36872
|
+
}
|
|
36873
|
+
},
|
|
36874
|
+
"data-testid": `relation-chip-${name}`,
|
|
36875
|
+
children: label
|
|
36876
|
+
},
|
|
36877
|
+
key
|
|
36878
|
+
);
|
|
36879
|
+
};
|
|
36644
36880
|
const renderValue = (field) => {
|
|
36645
36881
|
const name = fieldName(field);
|
|
36646
36882
|
const raw = getNestedValue(entity ?? {}, name);
|
|
36647
36883
|
const kind = fieldKind(field, raw);
|
|
36648
36884
|
const label = field.label ?? field.header ?? humanizeFieldName(name);
|
|
36885
|
+
if (kind === "image") {
|
|
36886
|
+
const url = typeof raw === "string" ? raw : "";
|
|
36887
|
+
if (!url) return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
36888
|
+
return /* @__PURE__ */ jsx(
|
|
36889
|
+
"img",
|
|
36890
|
+
{
|
|
36891
|
+
src: url,
|
|
36892
|
+
alt: label,
|
|
36893
|
+
loading: "lazy",
|
|
36894
|
+
className: "max-h-32 w-full rounded-md border border-border object-cover",
|
|
36895
|
+
"data-testid": `document-property-image-${name}`
|
|
36896
|
+
}
|
|
36897
|
+
);
|
|
36898
|
+
}
|
|
36649
36899
|
if (kind === "boolean") {
|
|
36650
36900
|
return /* @__PURE__ */ jsx(
|
|
36651
36901
|
Switch,
|
|
@@ -36675,9 +36925,12 @@ function DocumentDetails({
|
|
|
36675
36925
|
if (raw.length === 0) {
|
|
36676
36926
|
return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: "\u2014" });
|
|
36677
36927
|
}
|
|
36678
|
-
return /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) =>
|
|
36928
|
+
return /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: raw.map((item, i) => relationChip(item, name, i)) });
|
|
36679
36929
|
}
|
|
36680
|
-
|
|
36930
|
+
if (raw !== void 0 && raw !== null && raw !== "" && relationLabel(raw) !== null) {
|
|
36931
|
+
return relationChip(raw, name);
|
|
36932
|
+
}
|
|
36933
|
+
const shown2 = raw === void 0 || raw === null || raw === "" ? "\u2014" : formatValue(raw, field.format);
|
|
36681
36934
|
return /* @__PURE__ */ jsx(Typography, { variant: "small", className: "break-words", children: shown2 });
|
|
36682
36935
|
}
|
|
36683
36936
|
if (fieldDraft?.name === name) {
|
|
@@ -36746,6 +36999,7 @@ var init_DocumentDetails = __esm({
|
|
|
36746
36999
|
init_cn();
|
|
36747
37000
|
init_format();
|
|
36748
37001
|
init_getNestedValue();
|
|
37002
|
+
init_relationLabel();
|
|
36749
37003
|
init_useEventBus();
|
|
36750
37004
|
init_Box();
|
|
36751
37005
|
init_Stack();
|
|
@@ -41740,7 +41994,18 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
41740
41994
|
if (value === void 0 || value === null) return "\u2014";
|
|
41741
41995
|
const str = String(value);
|
|
41742
41996
|
switch (fieldType) {
|
|
41743
|
-
case "image":
|
|
41997
|
+
case "image": {
|
|
41998
|
+
if (!str) return "\u2014";
|
|
41999
|
+
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
42000
|
+
"img",
|
|
42001
|
+
{
|
|
42002
|
+
src: str,
|
|
42003
|
+
alt: formatFieldLabel(fieldName2),
|
|
42004
|
+
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
42005
|
+
loading: "lazy"
|
|
42006
|
+
}
|
|
42007
|
+
) });
|
|
42008
|
+
}
|
|
41744
42009
|
case "url": {
|
|
41745
42010
|
if (str.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str.startsWith("data:image/")) {
|
|
41746
42011
|
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
@@ -41753,7 +42018,7 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
41753
42018
|
}
|
|
41754
42019
|
) });
|
|
41755
42020
|
}
|
|
41756
|
-
if (
|
|
42021
|
+
if (/^https?:\/\//i.test(str)) {
|
|
41757
42022
|
return /* @__PURE__ */ jsx(
|
|
41758
42023
|
"a",
|
|
41759
42024
|
{
|
|
@@ -41839,8 +42104,10 @@ function renderRichFieldValue(value, fieldName2, fieldType, meta) {
|
|
|
41839
42104
|
return str;
|
|
41840
42105
|
}
|
|
41841
42106
|
case "relation": {
|
|
41842
|
-
const
|
|
41843
|
-
|
|
42107
|
+
const labels = relationDisplayLabels(value, meta?.options);
|
|
42108
|
+
if (labels.length === 0) return "\u2014";
|
|
42109
|
+
if (labels.length === 1) return labels[0];
|
|
42110
|
+
return /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: labels.map((label, i) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: label }, i)) });
|
|
41844
42111
|
}
|
|
41845
42112
|
case "file": {
|
|
41846
42113
|
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
@@ -41942,6 +42209,7 @@ var init_DetailPanel = __esm({
|
|
|
41942
42209
|
init_cn();
|
|
41943
42210
|
init_format();
|
|
41944
42211
|
init_getNestedValue();
|
|
42212
|
+
init_relationLabel();
|
|
41945
42213
|
init_useEventBus();
|
|
41946
42214
|
init_UploadDropZone();
|
|
41947
42215
|
formatFieldLabel = humanizeFieldName;
|
|
@@ -42600,6 +42868,8 @@ function determineInputType(field) {
|
|
|
42600
42868
|
return "url";
|
|
42601
42869
|
case "file":
|
|
42602
42870
|
return "file";
|
|
42871
|
+
case "image":
|
|
42872
|
+
return "image";
|
|
42603
42873
|
case "money":
|
|
42604
42874
|
return "currency";
|
|
42605
42875
|
case "number":
|
|
@@ -43199,6 +43469,50 @@ var init_Form = __esm({
|
|
|
43199
43469
|
}
|
|
43200
43470
|
}
|
|
43201
43471
|
);
|
|
43472
|
+
case "image": {
|
|
43473
|
+
const imageUrl = typeof currentValue === "string" ? currentValue : "";
|
|
43474
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
43475
|
+
imageUrl ? /* @__PURE__ */ jsx(
|
|
43476
|
+
"img",
|
|
43477
|
+
{
|
|
43478
|
+
src: imageUrl,
|
|
43479
|
+
alt: "",
|
|
43480
|
+
"aria-hidden": "true",
|
|
43481
|
+
className: "h-24 w-full max-w-xs rounded-md border border-border object-cover",
|
|
43482
|
+
"data-testid": `image-preview-${fieldName2}`
|
|
43483
|
+
}
|
|
43484
|
+
) : null,
|
|
43485
|
+
/* @__PURE__ */ jsx(
|
|
43486
|
+
UploadDropZone,
|
|
43487
|
+
{
|
|
43488
|
+
accept: "image/*",
|
|
43489
|
+
maxFiles: 1,
|
|
43490
|
+
maxSize: 2 * 1024 * 1024,
|
|
43491
|
+
disabled: isLoading,
|
|
43492
|
+
onFiles: (files) => {
|
|
43493
|
+
const f3 = files[0];
|
|
43494
|
+
if (!f3) return;
|
|
43495
|
+
const reader = new FileReader();
|
|
43496
|
+
reader.onload = () => handleChange(
|
|
43497
|
+
fieldName2,
|
|
43498
|
+
typeof reader.result === "string" ? reader.result : ""
|
|
43499
|
+
);
|
|
43500
|
+
reader.readAsDataURL(f3);
|
|
43501
|
+
}
|
|
43502
|
+
}
|
|
43503
|
+
),
|
|
43504
|
+
/* @__PURE__ */ jsx(
|
|
43505
|
+
Input,
|
|
43506
|
+
{
|
|
43507
|
+
...commonProps,
|
|
43508
|
+
type: "url",
|
|
43509
|
+
placeholder: t("form.imageUrlFallback"),
|
|
43510
|
+
value: imageUrl,
|
|
43511
|
+
onChange: (e) => handleChange(fieldName2, e.target.value)
|
|
43512
|
+
}
|
|
43513
|
+
)
|
|
43514
|
+
] });
|
|
43515
|
+
}
|
|
43202
43516
|
case "date":
|
|
43203
43517
|
return /* @__PURE__ */ jsx(
|
|
43204
43518
|
Input,
|