@almadar/ui 3.9.1 → 4.0.1
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 +688 -607
- package/dist/avl/index.js +688 -607
- package/dist/components/index.cjs +595 -1210
- package/dist/components/index.js +591 -1192
- package/dist/components/molecules/DataGrid.d.ts +19 -8
- package/dist/components/molecules/DataList.d.ts +22 -7
- package/dist/components/molecules/WizardProgress.d.ts +2 -2
- package/dist/components/organisms/DetailPanel.d.ts +0 -2
- package/dist/components/organisms/Form.d.ts +0 -2
- package/dist/components/organisms/FormSection.d.ts +0 -2
- package/dist/hooks/index.cjs +222 -846
- package/dist/hooks/index.d.ts +0 -4
- package/dist/hooks/index.js +9 -613
- package/dist/providers/index.cjs +604 -762
- package/dist/providers/index.d.ts +0 -2
- package/dist/providers/index.js +605 -758
- package/dist/runtime/EntitySchemaContext.d.ts +7 -3
- package/dist/runtime/index.cjs +1599 -1518
- package/dist/runtime/index.js +830 -749
- package/dist/runtime/ui/SlotsContext.d.ts +57 -17
- package/package.json +1 -1
- package/dist/hooks/useEntityData.d.ts +0 -155
- package/dist/hooks/useEntityMutations.d.ts +0 -80
- package/dist/hooks/useOrbitalMutations.d.ts +0 -95
- package/dist/hooks/useResolvedEntity.d.ts +0 -32
- package/dist/providers/FetchedDataProvider.d.ts +0 -105
package/dist/avl/index.cjs
CHANGED
|
@@ -10929,13 +10929,13 @@ var init_MapView = __esm({
|
|
|
10929
10929
|
shadowSize: [41, 41]
|
|
10930
10930
|
});
|
|
10931
10931
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
10932
|
-
const { useEffect:
|
|
10932
|
+
const { useEffect: useEffect87, useRef: useRef87, useCallback: useCallback125, useState: useState125 } = React126__namespace.default;
|
|
10933
10933
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
10934
10934
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
10935
10935
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
10936
10936
|
const map = useMap();
|
|
10937
10937
|
const prevRef = useRef87({ centerLat, centerLng, zoom });
|
|
10938
|
-
|
|
10938
|
+
useEffect87(() => {
|
|
10939
10939
|
const prev = prevRef.current;
|
|
10940
10940
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
10941
10941
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -10946,7 +10946,7 @@ var init_MapView = __esm({
|
|
|
10946
10946
|
}
|
|
10947
10947
|
function MapClickHandler({ onMapClick }) {
|
|
10948
10948
|
const map = useMap();
|
|
10949
|
-
|
|
10949
|
+
useEffect87(() => {
|
|
10950
10950
|
if (!onMapClick) return;
|
|
10951
10951
|
const handler = (e) => {
|
|
10952
10952
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -10973,7 +10973,7 @@ var init_MapView = __esm({
|
|
|
10973
10973
|
showAttribution = true
|
|
10974
10974
|
}) {
|
|
10975
10975
|
const eventBus = useEventBus3();
|
|
10976
|
-
const [clickedPosition, setClickedPosition] =
|
|
10976
|
+
const [clickedPosition, setClickedPosition] = useState125(null);
|
|
10977
10977
|
const handleMapClick = useCallback125((lat, lng) => {
|
|
10978
10978
|
if (showClickedPin) {
|
|
10979
10979
|
setClickedPosition({ lat, lng });
|
|
@@ -21657,7 +21657,290 @@ function formatValue(value, format) {
|
|
|
21657
21657
|
return String(value);
|
|
21658
21658
|
}
|
|
21659
21659
|
}
|
|
21660
|
-
|
|
21660
|
+
function DataGrid({
|
|
21661
|
+
entity,
|
|
21662
|
+
fields: fieldsProp,
|
|
21663
|
+
columns: columnsProp,
|
|
21664
|
+
itemActions,
|
|
21665
|
+
cols,
|
|
21666
|
+
gap = "md",
|
|
21667
|
+
minCardWidth = 280,
|
|
21668
|
+
className,
|
|
21669
|
+
isLoading = false,
|
|
21670
|
+
error = null,
|
|
21671
|
+
imageField,
|
|
21672
|
+
selectable = false,
|
|
21673
|
+
selectionEvent,
|
|
21674
|
+
infiniteScroll,
|
|
21675
|
+
loadMoreEvent,
|
|
21676
|
+
hasMore,
|
|
21677
|
+
children,
|
|
21678
|
+
pageSize = 0
|
|
21679
|
+
}) {
|
|
21680
|
+
const eventBus = useEventBus();
|
|
21681
|
+
const { t } = useTranslate();
|
|
21682
|
+
const [selectedIds, setSelectedIds] = React126.useState(/* @__PURE__ */ new Set());
|
|
21683
|
+
const [visibleCount, setVisibleCount] = React126.useState(pageSize || Infinity);
|
|
21684
|
+
const fields = fieldsProp ?? columnsProp ?? [];
|
|
21685
|
+
const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
21686
|
+
const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
|
|
21687
|
+
const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
|
|
21688
|
+
const toggleSelection = React126.useCallback((id) => {
|
|
21689
|
+
setSelectedIds((prev) => {
|
|
21690
|
+
const next = new Set(prev);
|
|
21691
|
+
if (next.has(id)) next.delete(id);
|
|
21692
|
+
else next.add(id);
|
|
21693
|
+
if (selectionEvent) {
|
|
21694
|
+
const payload = { selectedIds: Array.from(next) };
|
|
21695
|
+
eventBus.emit(`UI:${selectionEvent}`, payload);
|
|
21696
|
+
}
|
|
21697
|
+
return next;
|
|
21698
|
+
});
|
|
21699
|
+
}, [selectionEvent, eventBus]);
|
|
21700
|
+
const toggleAll = React126.useCallback(() => {
|
|
21701
|
+
setSelectedIds((prev) => {
|
|
21702
|
+
const allIds2 = data.map((item, i) => item.id || String(i));
|
|
21703
|
+
const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
|
|
21704
|
+
const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
|
|
21705
|
+
if (selectionEvent) {
|
|
21706
|
+
const payload = { selectedIds: Array.from(next) };
|
|
21707
|
+
eventBus.emit(`UI:${selectionEvent}`, payload);
|
|
21708
|
+
}
|
|
21709
|
+
return next;
|
|
21710
|
+
});
|
|
21711
|
+
}, [data, selectionEvent, eventBus]);
|
|
21712
|
+
const titleField = fields.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fields[0];
|
|
21713
|
+
const badgeFields = fields.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
21714
|
+
const bodyFields = fields.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
|
|
21715
|
+
const primaryActions = itemActions?.filter((a) => a.variant !== "danger") ?? [];
|
|
21716
|
+
const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
|
|
21717
|
+
const handleActionClick = (action, itemData) => (e) => {
|
|
21718
|
+
e.stopPropagation();
|
|
21719
|
+
const payload = {
|
|
21720
|
+
id: itemData.id,
|
|
21721
|
+
row: itemData
|
|
21722
|
+
};
|
|
21723
|
+
eventBus.emit(`UI:${action.event}`, payload);
|
|
21724
|
+
};
|
|
21725
|
+
const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
|
|
21726
|
+
const colsClass = cols ? {
|
|
21727
|
+
1: "grid-cols-1",
|
|
21728
|
+
2: "sm:grid-cols-2",
|
|
21729
|
+
3: "sm:grid-cols-2 lg:grid-cols-3",
|
|
21730
|
+
4: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
|
|
21731
|
+
5: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5",
|
|
21732
|
+
6: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6"
|
|
21733
|
+
}[cols] : void 0;
|
|
21734
|
+
if (isLoading) {
|
|
21735
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
|
|
21736
|
+
}
|
|
21737
|
+
if (error) {
|
|
21738
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
21739
|
+
}
|
|
21740
|
+
if (data.length === 0) {
|
|
21741
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("empty.noItems") || "No items found" }) });
|
|
21742
|
+
}
|
|
21743
|
+
const hasRenderProp = typeof children === "function";
|
|
21744
|
+
const allIds = data.map((item, i) => item.id || String(i));
|
|
21745
|
+
const allSelected = allIds.length > 0 && allIds.every((id) => selectedIds.has(id));
|
|
21746
|
+
const someSelected = selectedIds.size > 0;
|
|
21747
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
21748
|
+
selectable && someSelected && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "items-center px-2 py-2 bg-muted rounded-sm", children: [
|
|
21749
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21750
|
+
"input",
|
|
21751
|
+
{
|
|
21752
|
+
type: "checkbox",
|
|
21753
|
+
checked: allSelected,
|
|
21754
|
+
onChange: toggleAll,
|
|
21755
|
+
className: "w-4 h-4 accent-primary",
|
|
21756
|
+
"aria-label": "Select all"
|
|
21757
|
+
}
|
|
21758
|
+
),
|
|
21759
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "font-semibold", children: [
|
|
21760
|
+
selectedIds.size,
|
|
21761
|
+
" ",
|
|
21762
|
+
t("common.selected") || "selected"
|
|
21763
|
+
] })
|
|
21764
|
+
] }),
|
|
21765
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21766
|
+
Box,
|
|
21767
|
+
{
|
|
21768
|
+
className: cn("grid", gapStyles6[gap], colsClass, className),
|
|
21769
|
+
style: gridTemplateColumns ? { gridTemplateColumns } : void 0,
|
|
21770
|
+
children: data.map((item, index) => {
|
|
21771
|
+
const itemData = item;
|
|
21772
|
+
const id = itemData.id || String(index);
|
|
21773
|
+
const isSelected = selectedIds.has(id);
|
|
21774
|
+
if (hasRenderProp) {
|
|
21775
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21776
|
+
Box,
|
|
21777
|
+
{
|
|
21778
|
+
"data-entity-row": true,
|
|
21779
|
+
"data-entity-id": id,
|
|
21780
|
+
className: cn(
|
|
21781
|
+
"bg-card rounded-lg",
|
|
21782
|
+
"border border-border",
|
|
21783
|
+
"shadow-sm hover:shadow-lg",
|
|
21784
|
+
"hover:border-primary transition-all",
|
|
21785
|
+
"p-4",
|
|
21786
|
+
isSelected && "ring-2 ring-primary border-primary"
|
|
21787
|
+
),
|
|
21788
|
+
children: children(itemData, index)
|
|
21789
|
+
},
|
|
21790
|
+
id
|
|
21791
|
+
);
|
|
21792
|
+
}
|
|
21793
|
+
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
21794
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21795
|
+
Box,
|
|
21796
|
+
{
|
|
21797
|
+
"data-entity-row": true,
|
|
21798
|
+
"data-entity-id": id,
|
|
21799
|
+
className: cn(
|
|
21800
|
+
"bg-card rounded-lg",
|
|
21801
|
+
"border border-border",
|
|
21802
|
+
"shadow-sm hover:shadow-lg",
|
|
21803
|
+
"hover:border-primary transition-all",
|
|
21804
|
+
"flex flex-col",
|
|
21805
|
+
isSelected && "ring-2 ring-primary border-primary"
|
|
21806
|
+
),
|
|
21807
|
+
children: [
|
|
21808
|
+
imageField && (() => {
|
|
21809
|
+
const imgUrl = getNestedValue(itemData, imageField);
|
|
21810
|
+
if (!imgUrl || typeof imgUrl !== "string") return null;
|
|
21811
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full aspect-video overflow-hidden rounded-t-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
21812
|
+
"img",
|
|
21813
|
+
{
|
|
21814
|
+
src: imgUrl,
|
|
21815
|
+
alt: titleValue !== void 0 ? String(titleValue) : "",
|
|
21816
|
+
className: "w-full h-full object-cover",
|
|
21817
|
+
loading: "lazy"
|
|
21818
|
+
}
|
|
21819
|
+
) });
|
|
21820
|
+
})(),
|
|
21821
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 pb-0", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
21822
|
+
selectable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21823
|
+
"input",
|
|
21824
|
+
{
|
|
21825
|
+
type: "checkbox",
|
|
21826
|
+
checked: isSelected,
|
|
21827
|
+
onChange: () => toggleSelection(id),
|
|
21828
|
+
onClick: (e) => e.stopPropagation(),
|
|
21829
|
+
className: "w-4 h-4 mt-1 flex-shrink-0 accent-primary",
|
|
21830
|
+
"aria-label": `Select ${titleValue !== void 0 ? String(titleValue) : "item"}`
|
|
21831
|
+
}
|
|
21832
|
+
),
|
|
21833
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
21834
|
+
titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21835
|
+
titleField?.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: titleField.icon, size: "sm", className: "text-primary flex-shrink-0" }),
|
|
21836
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21837
|
+
Typography,
|
|
21838
|
+
{
|
|
21839
|
+
variant: titleField?.variant === "h3" ? "h3" : "h4",
|
|
21840
|
+
className: "font-semibold truncate",
|
|
21841
|
+
children: String(titleValue)
|
|
21842
|
+
}
|
|
21843
|
+
)
|
|
21844
|
+
] }),
|
|
21845
|
+
badgeFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-wrap", children: badgeFields.map((field) => {
|
|
21846
|
+
const val = getNestedValue(itemData, field.name);
|
|
21847
|
+
if (val === void 0 || val === null) return null;
|
|
21848
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21849
|
+
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs" }),
|
|
21850
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: statusVariant2(String(val)), children: String(val) })
|
|
21851
|
+
] }, field.name);
|
|
21852
|
+
}) })
|
|
21853
|
+
] }),
|
|
21854
|
+
dangerActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21855
|
+
Button,
|
|
21856
|
+
{
|
|
21857
|
+
variant: "ghost",
|
|
21858
|
+
size: "sm",
|
|
21859
|
+
onClick: handleActionClick(action, itemData),
|
|
21860
|
+
"data-testid": `action-${action.event}`,
|
|
21861
|
+
className: "text-error hover:bg-error/10 px-2",
|
|
21862
|
+
children: [
|
|
21863
|
+
action.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, size: "xs" }),
|
|
21864
|
+
action.label
|
|
21865
|
+
]
|
|
21866
|
+
},
|
|
21867
|
+
idx
|
|
21868
|
+
)) })
|
|
21869
|
+
] }) }),
|
|
21870
|
+
bodyFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "xs", children: bodyFields.map((field) => {
|
|
21871
|
+
const value = getNestedValue(itemData, field.name);
|
|
21872
|
+
if (value === void 0 || value === null || value === "") return null;
|
|
21873
|
+
if (field.format === "boolean") {
|
|
21874
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
|
|
21875
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21876
|
+
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
21877
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
|
|
21878
|
+
] }),
|
|
21879
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
|
|
21880
|
+
] }, field.name);
|
|
21881
|
+
}
|
|
21882
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
|
|
21883
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21884
|
+
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
21885
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
|
|
21886
|
+
] }),
|
|
21887
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21888
|
+
Typography,
|
|
21889
|
+
{
|
|
21890
|
+
variant: field.variant === "caption" ? "caption" : "small",
|
|
21891
|
+
className: "text-right truncate max-w-[60%]",
|
|
21892
|
+
children: formatValue(value, field.format)
|
|
21893
|
+
}
|
|
21894
|
+
)
|
|
21895
|
+
] }, field.name);
|
|
21896
|
+
}) }) }),
|
|
21897
|
+
primaryActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "sm", className: "justify-end", children: primaryActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21898
|
+
Button,
|
|
21899
|
+
{
|
|
21900
|
+
variant: action.variant === "primary" ? "primary" : "ghost",
|
|
21901
|
+
size: "sm",
|
|
21902
|
+
onClick: handleActionClick(action, itemData),
|
|
21903
|
+
"data-testid": `action-${action.event}`,
|
|
21904
|
+
children: [
|
|
21905
|
+
action.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
21906
|
+
action.label
|
|
21907
|
+
]
|
|
21908
|
+
},
|
|
21909
|
+
idx
|
|
21910
|
+
)) }) })
|
|
21911
|
+
]
|
|
21912
|
+
},
|
|
21913
|
+
id
|
|
21914
|
+
);
|
|
21915
|
+
})
|
|
21916
|
+
}
|
|
21917
|
+
),
|
|
21918
|
+
hasMoreLocal && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21919
|
+
Button,
|
|
21920
|
+
{
|
|
21921
|
+
variant: "ghost",
|
|
21922
|
+
size: "sm",
|
|
21923
|
+
onClick: () => setVisibleCount((prev) => prev + (pageSize || 5)),
|
|
21924
|
+
children: [
|
|
21925
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
21926
|
+
t("common.showMore"),
|
|
21927
|
+
" (",
|
|
21928
|
+
allData.length - visibleCount,
|
|
21929
|
+
" remaining)"
|
|
21930
|
+
]
|
|
21931
|
+
}
|
|
21932
|
+
) }),
|
|
21933
|
+
infiniteScroll && loadMoreEvent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21934
|
+
InfiniteScrollSentinel,
|
|
21935
|
+
{
|
|
21936
|
+
loadMoreEvent,
|
|
21937
|
+
isLoading,
|
|
21938
|
+
hasMore
|
|
21939
|
+
}
|
|
21940
|
+
)
|
|
21941
|
+
] });
|
|
21942
|
+
}
|
|
21943
|
+
var gapStyles6;
|
|
21661
21944
|
var init_DataGrid = __esm({
|
|
21662
21945
|
"components/molecules/DataGrid.tsx"() {
|
|
21663
21946
|
"use client";
|
|
@@ -21679,289 +21962,6 @@ var init_DataGrid = __esm({
|
|
|
21679
21962
|
lg: "gap-6",
|
|
21680
21963
|
xl: "gap-8"
|
|
21681
21964
|
};
|
|
21682
|
-
DataGrid = ({
|
|
21683
|
-
entity,
|
|
21684
|
-
fields: fieldsProp,
|
|
21685
|
-
columns: columnsProp,
|
|
21686
|
-
itemActions,
|
|
21687
|
-
cols,
|
|
21688
|
-
gap = "md",
|
|
21689
|
-
minCardWidth = 280,
|
|
21690
|
-
className,
|
|
21691
|
-
isLoading = false,
|
|
21692
|
-
error = null,
|
|
21693
|
-
imageField,
|
|
21694
|
-
selectable = false,
|
|
21695
|
-
selectionEvent,
|
|
21696
|
-
infiniteScroll,
|
|
21697
|
-
loadMoreEvent,
|
|
21698
|
-
hasMore,
|
|
21699
|
-
children,
|
|
21700
|
-
pageSize = 0
|
|
21701
|
-
}) => {
|
|
21702
|
-
const eventBus = useEventBus();
|
|
21703
|
-
const { t } = useTranslate();
|
|
21704
|
-
const [selectedIds, setSelectedIds] = React126.useState(/* @__PURE__ */ new Set());
|
|
21705
|
-
const [visibleCount, setVisibleCount] = React126.useState(pageSize || Infinity);
|
|
21706
|
-
const fields = fieldsProp ?? columnsProp ?? [];
|
|
21707
|
-
const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
21708
|
-
const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
|
|
21709
|
-
const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
|
|
21710
|
-
const toggleSelection = React126.useCallback((id) => {
|
|
21711
|
-
setSelectedIds((prev) => {
|
|
21712
|
-
const next = new Set(prev);
|
|
21713
|
-
if (next.has(id)) next.delete(id);
|
|
21714
|
-
else next.add(id);
|
|
21715
|
-
if (selectionEvent) {
|
|
21716
|
-
const payload = { selectedIds: Array.from(next) };
|
|
21717
|
-
eventBus.emit(`UI:${selectionEvent}`, payload);
|
|
21718
|
-
}
|
|
21719
|
-
return next;
|
|
21720
|
-
});
|
|
21721
|
-
}, [selectionEvent, eventBus]);
|
|
21722
|
-
const toggleAll = React126.useCallback(() => {
|
|
21723
|
-
setSelectedIds((prev) => {
|
|
21724
|
-
const allIds2 = data.map((item, i) => item.id || String(i));
|
|
21725
|
-
const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
|
|
21726
|
-
const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
|
|
21727
|
-
if (selectionEvent) {
|
|
21728
|
-
const payload = { selectedIds: Array.from(next) };
|
|
21729
|
-
eventBus.emit(`UI:${selectionEvent}`, payload);
|
|
21730
|
-
}
|
|
21731
|
-
return next;
|
|
21732
|
-
});
|
|
21733
|
-
}, [data, selectionEvent, eventBus]);
|
|
21734
|
-
const titleField = fields.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fields[0];
|
|
21735
|
-
const badgeFields = fields.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
21736
|
-
const bodyFields = fields.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
|
|
21737
|
-
const primaryActions = itemActions?.filter((a) => a.variant !== "danger") ?? [];
|
|
21738
|
-
const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
|
|
21739
|
-
const handleActionClick = (action, itemData) => (e) => {
|
|
21740
|
-
e.stopPropagation();
|
|
21741
|
-
const payload = {
|
|
21742
|
-
id: itemData.id,
|
|
21743
|
-
row: itemData
|
|
21744
|
-
};
|
|
21745
|
-
eventBus.emit(`UI:${action.event}`, payload);
|
|
21746
|
-
};
|
|
21747
|
-
const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
|
|
21748
|
-
const colsClass = cols ? {
|
|
21749
|
-
1: "grid-cols-1",
|
|
21750
|
-
2: "sm:grid-cols-2",
|
|
21751
|
-
3: "sm:grid-cols-2 lg:grid-cols-3",
|
|
21752
|
-
4: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
|
|
21753
|
-
5: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5",
|
|
21754
|
-
6: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6"
|
|
21755
|
-
}[cols] : void 0;
|
|
21756
|
-
if (isLoading) {
|
|
21757
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
|
|
21758
|
-
}
|
|
21759
|
-
if (error) {
|
|
21760
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
21761
|
-
}
|
|
21762
|
-
if (data.length === 0) {
|
|
21763
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("empty.noItems") || "No items found" }) });
|
|
21764
|
-
}
|
|
21765
|
-
const hasRenderProp = typeof children === "function";
|
|
21766
|
-
const allIds = data.map((item, i) => item.id || String(i));
|
|
21767
|
-
const allSelected = allIds.length > 0 && allIds.every((id) => selectedIds.has(id));
|
|
21768
|
-
const someSelected = selectedIds.size > 0;
|
|
21769
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
21770
|
-
selectable && someSelected && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "items-center px-2 py-2 bg-muted rounded-sm", children: [
|
|
21771
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21772
|
-
"input",
|
|
21773
|
-
{
|
|
21774
|
-
type: "checkbox",
|
|
21775
|
-
checked: allSelected,
|
|
21776
|
-
onChange: toggleAll,
|
|
21777
|
-
className: "w-4 h-4 accent-primary",
|
|
21778
|
-
"aria-label": "Select all"
|
|
21779
|
-
}
|
|
21780
|
-
),
|
|
21781
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "font-semibold", children: [
|
|
21782
|
-
selectedIds.size,
|
|
21783
|
-
" ",
|
|
21784
|
-
t("common.selected") || "selected"
|
|
21785
|
-
] })
|
|
21786
|
-
] }),
|
|
21787
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21788
|
-
Box,
|
|
21789
|
-
{
|
|
21790
|
-
className: cn("grid", gapStyles6[gap], colsClass, className),
|
|
21791
|
-
style: gridTemplateColumns ? { gridTemplateColumns } : void 0,
|
|
21792
|
-
children: data.map((item, index) => {
|
|
21793
|
-
const itemData = item;
|
|
21794
|
-
const id = itemData.id || String(index);
|
|
21795
|
-
const isSelected = selectedIds.has(id);
|
|
21796
|
-
if (hasRenderProp) {
|
|
21797
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21798
|
-
Box,
|
|
21799
|
-
{
|
|
21800
|
-
"data-entity-row": true,
|
|
21801
|
-
"data-entity-id": id,
|
|
21802
|
-
className: cn(
|
|
21803
|
-
"bg-card rounded-lg",
|
|
21804
|
-
"border border-border",
|
|
21805
|
-
"shadow-sm hover:shadow-lg",
|
|
21806
|
-
"hover:border-primary transition-all",
|
|
21807
|
-
"p-4",
|
|
21808
|
-
isSelected && "ring-2 ring-primary border-primary"
|
|
21809
|
-
),
|
|
21810
|
-
children: children(itemData, index)
|
|
21811
|
-
},
|
|
21812
|
-
id
|
|
21813
|
-
);
|
|
21814
|
-
}
|
|
21815
|
-
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
21816
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21817
|
-
Box,
|
|
21818
|
-
{
|
|
21819
|
-
"data-entity-row": true,
|
|
21820
|
-
"data-entity-id": id,
|
|
21821
|
-
className: cn(
|
|
21822
|
-
"bg-card rounded-lg",
|
|
21823
|
-
"border border-border",
|
|
21824
|
-
"shadow-sm hover:shadow-lg",
|
|
21825
|
-
"hover:border-primary transition-all",
|
|
21826
|
-
"flex flex-col",
|
|
21827
|
-
isSelected && "ring-2 ring-primary border-primary"
|
|
21828
|
-
),
|
|
21829
|
-
children: [
|
|
21830
|
-
imageField && (() => {
|
|
21831
|
-
const imgUrl = getNestedValue(itemData, imageField);
|
|
21832
|
-
if (!imgUrl || typeof imgUrl !== "string") return null;
|
|
21833
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full aspect-video overflow-hidden rounded-t-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
21834
|
-
"img",
|
|
21835
|
-
{
|
|
21836
|
-
src: imgUrl,
|
|
21837
|
-
alt: titleValue !== void 0 ? String(titleValue) : "",
|
|
21838
|
-
className: "w-full h-full object-cover",
|
|
21839
|
-
loading: "lazy"
|
|
21840
|
-
}
|
|
21841
|
-
) });
|
|
21842
|
-
})(),
|
|
21843
|
-
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 pb-0", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
21844
|
-
selectable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21845
|
-
"input",
|
|
21846
|
-
{
|
|
21847
|
-
type: "checkbox",
|
|
21848
|
-
checked: isSelected,
|
|
21849
|
-
onChange: () => toggleSelection(id),
|
|
21850
|
-
onClick: (e) => e.stopPropagation(),
|
|
21851
|
-
className: "w-4 h-4 mt-1 flex-shrink-0 accent-primary",
|
|
21852
|
-
"aria-label": `Select ${titleValue !== void 0 ? String(titleValue) : "item"}`
|
|
21853
|
-
}
|
|
21854
|
-
),
|
|
21855
|
-
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
21856
|
-
titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21857
|
-
titleField?.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: titleField.icon, size: "sm", className: "text-primary flex-shrink-0" }),
|
|
21858
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21859
|
-
Typography,
|
|
21860
|
-
{
|
|
21861
|
-
variant: titleField?.variant === "h3" ? "h3" : "h4",
|
|
21862
|
-
className: "font-semibold truncate",
|
|
21863
|
-
children: String(titleValue)
|
|
21864
|
-
}
|
|
21865
|
-
)
|
|
21866
|
-
] }),
|
|
21867
|
-
badgeFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-wrap", children: badgeFields.map((field) => {
|
|
21868
|
-
const val = getNestedValue(itemData, field.name);
|
|
21869
|
-
if (val === void 0 || val === null) return null;
|
|
21870
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21871
|
-
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs" }),
|
|
21872
|
-
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: statusVariant2(String(val)), children: String(val) })
|
|
21873
|
-
] }, field.name);
|
|
21874
|
-
}) })
|
|
21875
|
-
] }),
|
|
21876
|
-
dangerActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21877
|
-
Button,
|
|
21878
|
-
{
|
|
21879
|
-
variant: "ghost",
|
|
21880
|
-
size: "sm",
|
|
21881
|
-
onClick: handleActionClick(action, itemData),
|
|
21882
|
-
"data-testid": `action-${action.event}`,
|
|
21883
|
-
className: "text-error hover:bg-error/10 px-2",
|
|
21884
|
-
children: [
|
|
21885
|
-
action.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, size: "xs" }),
|
|
21886
|
-
action.label
|
|
21887
|
-
]
|
|
21888
|
-
},
|
|
21889
|
-
idx
|
|
21890
|
-
)) })
|
|
21891
|
-
] }) }),
|
|
21892
|
-
bodyFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "xs", children: bodyFields.map((field) => {
|
|
21893
|
-
const value = getNestedValue(itemData, field.name);
|
|
21894
|
-
if (value === void 0 || value === null || value === "") return null;
|
|
21895
|
-
if (field.format === "boolean") {
|
|
21896
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
|
|
21897
|
-
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21898
|
-
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
21899
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
|
|
21900
|
-
] }),
|
|
21901
|
-
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
|
|
21902
|
-
] }, field.name);
|
|
21903
|
-
}
|
|
21904
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
|
|
21905
|
-
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21906
|
-
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
21907
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
|
|
21908
|
-
] }),
|
|
21909
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21910
|
-
Typography,
|
|
21911
|
-
{
|
|
21912
|
-
variant: field.variant === "caption" ? "caption" : "small",
|
|
21913
|
-
className: "text-right truncate max-w-[60%]",
|
|
21914
|
-
children: formatValue(value, field.format)
|
|
21915
|
-
}
|
|
21916
|
-
)
|
|
21917
|
-
] }, field.name);
|
|
21918
|
-
}) }) }),
|
|
21919
|
-
primaryActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "sm", className: "justify-end", children: primaryActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21920
|
-
Button,
|
|
21921
|
-
{
|
|
21922
|
-
variant: action.variant === "primary" ? "primary" : "ghost",
|
|
21923
|
-
size: "sm",
|
|
21924
|
-
onClick: handleActionClick(action, itemData),
|
|
21925
|
-
"data-testid": `action-${action.event}`,
|
|
21926
|
-
children: [
|
|
21927
|
-
action.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
21928
|
-
action.label
|
|
21929
|
-
]
|
|
21930
|
-
},
|
|
21931
|
-
idx
|
|
21932
|
-
)) }) })
|
|
21933
|
-
]
|
|
21934
|
-
},
|
|
21935
|
-
id
|
|
21936
|
-
);
|
|
21937
|
-
})
|
|
21938
|
-
}
|
|
21939
|
-
),
|
|
21940
|
-
hasMoreLocal && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21941
|
-
Button,
|
|
21942
|
-
{
|
|
21943
|
-
variant: "ghost",
|
|
21944
|
-
size: "sm",
|
|
21945
|
-
onClick: () => setVisibleCount((prev) => prev + (pageSize || 5)),
|
|
21946
|
-
children: [
|
|
21947
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
21948
|
-
t("common.showMore"),
|
|
21949
|
-
" (",
|
|
21950
|
-
allData.length - visibleCount,
|
|
21951
|
-
" remaining)"
|
|
21952
|
-
]
|
|
21953
|
-
}
|
|
21954
|
-
) }),
|
|
21955
|
-
infiniteScroll && loadMoreEvent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21956
|
-
InfiniteScrollSentinel,
|
|
21957
|
-
{
|
|
21958
|
-
loadMoreEvent,
|
|
21959
|
-
isLoading,
|
|
21960
|
-
hasMore
|
|
21961
|
-
}
|
|
21962
|
-
)
|
|
21963
|
-
] });
|
|
21964
|
-
};
|
|
21965
21965
|
DataGrid.displayName = "DataGrid";
|
|
21966
21966
|
}
|
|
21967
21967
|
});
|
|
@@ -22009,318 +22009,317 @@ function groupData(items, field) {
|
|
|
22009
22009
|
}
|
|
22010
22010
|
return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
|
|
22011
22011
|
}
|
|
22012
|
-
|
|
22013
|
-
|
|
22014
|
-
|
|
22015
|
-
|
|
22016
|
-
|
|
22017
|
-
|
|
22018
|
-
|
|
22019
|
-
|
|
22020
|
-
|
|
22021
|
-
|
|
22022
|
-
|
|
22023
|
-
|
|
22024
|
-
|
|
22025
|
-
|
|
22026
|
-
|
|
22027
|
-
|
|
22028
|
-
|
|
22029
|
-
|
|
22030
|
-
|
|
22031
|
-
|
|
22032
|
-
|
|
22033
|
-
|
|
22034
|
-
|
|
22035
|
-
|
|
22036
|
-
|
|
22037
|
-
|
|
22038
|
-
|
|
22039
|
-
|
|
22040
|
-
|
|
22041
|
-
|
|
22042
|
-
|
|
22043
|
-
|
|
22044
|
-
|
|
22045
|
-
|
|
22046
|
-
|
|
22047
|
-
|
|
22048
|
-
|
|
22049
|
-
|
|
22050
|
-
|
|
22051
|
-
|
|
22052
|
-
|
|
22053
|
-
|
|
22054
|
-
|
|
22055
|
-
|
|
22056
|
-
|
|
22057
|
-
|
|
22058
|
-
|
|
22059
|
-
|
|
22060
|
-
|
|
22061
|
-
|
|
22062
|
-
|
|
22063
|
-
|
|
22064
|
-
|
|
22065
|
-
|
|
22066
|
-
|
|
22067
|
-
|
|
22068
|
-
|
|
22069
|
-
|
|
22070
|
-
|
|
22071
|
-
|
|
22072
|
-
|
|
22073
|
-
|
|
22074
|
-
|
|
22075
|
-
|
|
22076
|
-
|
|
22077
|
-
|
|
22078
|
-
|
|
22079
|
-
|
|
22080
|
-
|
|
22081
|
-
|
|
22082
|
-
|
|
22083
|
-
|
|
22084
|
-
|
|
22085
|
-
|
|
22086
|
-
|
|
22087
|
-
|
|
22088
|
-
|
|
22089
|
-
|
|
22090
|
-
|
|
22091
|
-
|
|
22092
|
-
|
|
22093
|
-
|
|
22094
|
-
|
|
22095
|
-
|
|
22096
|
-
|
|
22097
|
-
|
|
22098
|
-
|
|
22099
|
-
|
|
22100
|
-
|
|
22101
|
-
return /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React126__namespace.default.Fragment, { children: [
|
|
22102
|
-
group.label && /* @__PURE__ */ jsxRuntime.jsx(Divider, { label: group.label, className: "my-2" }),
|
|
22103
|
-
group.items.map((itemData, index) => {
|
|
22104
|
-
const id = itemData.id || `${gi}-${index}`;
|
|
22105
|
-
const sender = senderField ? String(getNestedValue(itemData, senderField) ?? "") : "";
|
|
22106
|
-
const isSent = Boolean(currentUser && sender === currentUser);
|
|
22107
|
-
const content = getNestedValue(itemData, contentField);
|
|
22108
|
-
const timestampField = fields.find((f3) => f3.format === "date");
|
|
22109
|
-
const timestamp = timestampField ? getNestedValue(itemData, timestampField.name) : null;
|
|
22110
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
22111
|
-
Box,
|
|
22112
|
-
{
|
|
22113
|
-
className: cn(
|
|
22114
|
-
"flex px-4",
|
|
22115
|
-
isSent ? "justify-end" : "justify-start"
|
|
22116
|
-
),
|
|
22117
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
22118
|
-
Box,
|
|
22119
|
-
{
|
|
22120
|
-
className: cn(
|
|
22121
|
-
"max-w-[75%] px-4 py-2",
|
|
22122
|
-
isSent ? "bg-primary text-primary-foreground rounded-2xl rounded-br-sm" : "bg-muted text-foreground rounded-2xl rounded-bl-sm"
|
|
22123
|
-
),
|
|
22124
|
-
children: [
|
|
22125
|
-
!isSent && senderField && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "font-semibold mb-0.5", children: sender }),
|
|
22126
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: content !== void 0 && content !== null ? String(content) : "" }),
|
|
22127
|
-
timestamp != null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
22128
|
-
Typography,
|
|
22129
|
-
{
|
|
22130
|
-
variant: "caption",
|
|
22131
|
-
className: cn(
|
|
22132
|
-
"mt-1 text-[0.65rem]",
|
|
22133
|
-
isSent ? "opacity-70" : "text-muted-foreground"
|
|
22134
|
-
),
|
|
22135
|
-
children: formatDate3(timestamp)
|
|
22136
|
-
}
|
|
22137
|
-
) : null
|
|
22138
|
-
]
|
|
22139
|
-
}
|
|
22140
|
-
)
|
|
22141
|
-
},
|
|
22142
|
-
id
|
|
22143
|
-
);
|
|
22144
|
-
})
|
|
22145
|
-
] }, gi)) });
|
|
22146
|
-
}
|
|
22147
|
-
const hasRenderProp = typeof children === "function";
|
|
22148
|
-
const items = data.map((item) => item);
|
|
22149
|
-
const groups = groupBy ? groupData(items, groupBy) : [{ label: "", items }];
|
|
22150
|
-
const renderItem = (itemData, index, isLast) => {
|
|
22151
|
-
if (hasRenderProp) {
|
|
22152
|
-
const id2 = itemData.id || String(index);
|
|
22153
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, children: [
|
|
22154
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
22012
|
+
function DataList({
|
|
22013
|
+
entity,
|
|
22014
|
+
fields: fieldsProp,
|
|
22015
|
+
columns: columnsProp,
|
|
22016
|
+
itemActions,
|
|
22017
|
+
gap = "none",
|
|
22018
|
+
variant = "default",
|
|
22019
|
+
groupBy,
|
|
22020
|
+
senderField,
|
|
22021
|
+
currentUser,
|
|
22022
|
+
className,
|
|
22023
|
+
isLoading = false,
|
|
22024
|
+
error = null,
|
|
22025
|
+
// Gesture props: reorderable, swipeLeftEvent, swipeRightEvent, longPressEvent
|
|
22026
|
+
// are consumed by the compiler to wrap items in SwipeableRow/SortableList.
|
|
22027
|
+
// DataList destructures them here to prevent DOM passthrough.
|
|
22028
|
+
reorderable: _reorderable,
|
|
22029
|
+
reorderEvent: _reorderEvent,
|
|
22030
|
+
swipeLeftEvent: _swipeLeftEvent,
|
|
22031
|
+
swipeLeftActions: _swipeLeftActions,
|
|
22032
|
+
swipeRightEvent: _swipeRightEvent,
|
|
22033
|
+
swipeRightActions: _swipeRightActions,
|
|
22034
|
+
longPressEvent: _longPressEvent,
|
|
22035
|
+
infiniteScroll,
|
|
22036
|
+
loadMoreEvent,
|
|
22037
|
+
hasMore,
|
|
22038
|
+
children,
|
|
22039
|
+
pageSize = 5
|
|
22040
|
+
}) {
|
|
22041
|
+
const eventBus = useEventBus();
|
|
22042
|
+
const { t } = useTranslate();
|
|
22043
|
+
const [visibleCount, setVisibleCount] = React126__namespace.default.useState(pageSize || Infinity);
|
|
22044
|
+
const fields = fieldsProp ?? columnsProp ?? [];
|
|
22045
|
+
const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
22046
|
+
const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
|
|
22047
|
+
const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
|
|
22048
|
+
const titleField = fields.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fields[0];
|
|
22049
|
+
const badgeFields = fields.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
22050
|
+
const progressFields = fields.filter((f3) => f3.variant === "progress");
|
|
22051
|
+
const bodyFields = fields.filter(
|
|
22052
|
+
(f3) => f3 !== titleField && !badgeFields.includes(f3) && !progressFields.includes(f3)
|
|
22053
|
+
);
|
|
22054
|
+
const handleActionClick = (action, itemData) => (e) => {
|
|
22055
|
+
e.stopPropagation();
|
|
22056
|
+
const payload = {
|
|
22057
|
+
id: itemData.id,
|
|
22058
|
+
row: itemData
|
|
22059
|
+
};
|
|
22060
|
+
eventBus.emit(`UI:${action.event}`, payload);
|
|
22061
|
+
};
|
|
22062
|
+
if (isLoading) {
|
|
22063
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
|
|
22064
|
+
}
|
|
22065
|
+
if (error) {
|
|
22066
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
22067
|
+
}
|
|
22068
|
+
if (data.length === 0) {
|
|
22069
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("empty.noItems") || "No items found" }) });
|
|
22070
|
+
}
|
|
22071
|
+
const gapClass = {
|
|
22072
|
+
none: "",
|
|
22073
|
+
sm: "gap-1",
|
|
22074
|
+
md: "gap-2",
|
|
22075
|
+
lg: "gap-4"
|
|
22076
|
+
}[gap];
|
|
22077
|
+
const isCard = variant === "card";
|
|
22078
|
+
const isCompact = variant === "compact";
|
|
22079
|
+
const isMessage = variant === "message";
|
|
22080
|
+
if (isMessage) {
|
|
22081
|
+
const items2 = data.map((item) => item);
|
|
22082
|
+
const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
|
|
22083
|
+
const contentField = titleField?.name ?? fields[0]?.name ?? "";
|
|
22084
|
+
return /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React126__namespace.default.Fragment, { children: [
|
|
22085
|
+
group.label && /* @__PURE__ */ jsxRuntime.jsx(Divider, { label: group.label, className: "my-2" }),
|
|
22086
|
+
group.items.map((itemData, index) => {
|
|
22087
|
+
const id = itemData.id || `${gi}-${index}`;
|
|
22088
|
+
const sender = senderField ? String(getNestedValue(itemData, senderField) ?? "") : "";
|
|
22089
|
+
const isSent = Boolean(currentUser && sender === currentUser);
|
|
22090
|
+
const content = getNestedValue(itemData, contentField);
|
|
22091
|
+
const timestampField = fields.find((f3) => f3.format === "date");
|
|
22092
|
+
const timestamp = timestampField ? getNestedValue(itemData, timestampField.name) : null;
|
|
22093
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
22094
|
+
Box,
|
|
22095
|
+
{
|
|
22096
|
+
className: cn(
|
|
22097
|
+
"flex px-4",
|
|
22098
|
+
isSent ? "justify-end" : "justify-start"
|
|
22099
|
+
),
|
|
22100
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
22155
22101
|
Box,
|
|
22156
22102
|
{
|
|
22157
22103
|
className: cn(
|
|
22158
|
-
"
|
|
22159
|
-
|
|
22160
|
-
"hover:bg-muted/80",
|
|
22161
|
-
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
22104
|
+
"max-w-[75%] px-4 py-2",
|
|
22105
|
+
isSent ? "bg-primary text-primary-foreground rounded-2xl rounded-br-sm" : "bg-muted text-foreground rounded-2xl rounded-bl-sm"
|
|
22162
22106
|
),
|
|
22163
22107
|
children: [
|
|
22164
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22165
|
-
|
|
22166
|
-
|
|
22108
|
+
!isSent && senderField && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "font-semibold mb-0.5", children: sender }),
|
|
22109
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: content !== void 0 && content !== null ? String(content) : "" }),
|
|
22110
|
+
timestamp != null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
22111
|
+
Typography,
|
|
22167
22112
|
{
|
|
22168
|
-
|
|
22169
|
-
className:
|
|
22170
|
-
|
|
22171
|
-
|
|
22172
|
-
|
|
22173
|
-
|
|
22174
|
-
size: "sm",
|
|
22175
|
-
onClick: handleActionClick(action, itemData),
|
|
22176
|
-
"data-testid": `action-${action.event}`,
|
|
22177
|
-
className: cn(
|
|
22178
|
-
action.variant === "danger" && "text-error hover:bg-error/10"
|
|
22179
|
-
),
|
|
22180
|
-
children: [
|
|
22181
|
-
action.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
22182
|
-
action.label
|
|
22183
|
-
]
|
|
22184
|
-
},
|
|
22185
|
-
idx
|
|
22186
|
-
))
|
|
22113
|
+
variant: "caption",
|
|
22114
|
+
className: cn(
|
|
22115
|
+
"mt-1 text-[0.65rem]",
|
|
22116
|
+
isSent ? "opacity-70" : "text-muted-foreground"
|
|
22117
|
+
),
|
|
22118
|
+
children: formatDate3(timestamp)
|
|
22187
22119
|
}
|
|
22188
|
-
)
|
|
22120
|
+
) : null
|
|
22189
22121
|
]
|
|
22190
22122
|
}
|
|
22123
|
+
)
|
|
22124
|
+
},
|
|
22125
|
+
id
|
|
22126
|
+
);
|
|
22127
|
+
})
|
|
22128
|
+
] }, gi)) });
|
|
22129
|
+
}
|
|
22130
|
+
const hasRenderProp = typeof children === "function";
|
|
22131
|
+
const items = data.map((item) => item);
|
|
22132
|
+
const groups = groupBy ? groupData(items, groupBy) : [{ label: "", items }];
|
|
22133
|
+
const renderItem = (itemData, index, isLast) => {
|
|
22134
|
+
if (hasRenderProp) {
|
|
22135
|
+
const id2 = itemData.id || String(index);
|
|
22136
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, children: [
|
|
22137
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
22138
|
+
Box,
|
|
22139
|
+
{
|
|
22140
|
+
className: cn(
|
|
22141
|
+
"group flex items-center gap-4 transition-all duration-200",
|
|
22142
|
+
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
22143
|
+
"hover:bg-muted/80",
|
|
22144
|
+
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
22191
22145
|
),
|
|
22192
|
-
|
|
22193
|
-
|
|
22194
|
-
|
|
22195
|
-
|
|
22196
|
-
|
|
22197
|
-
|
|
22198
|
-
|
|
22199
|
-
|
|
22200
|
-
|
|
22201
|
-
|
|
22202
|
-
|
|
22203
|
-
|
|
22204
|
-
|
|
22205
|
-
|
|
22206
|
-
|
|
22207
|
-
|
|
22208
|
-
|
|
22209
|
-
|
|
22210
|
-
|
|
22211
|
-
|
|
22212
|
-
|
|
22213
|
-
|
|
22214
|
-
|
|
22215
|
-
|
|
22216
|
-
|
|
22217
|
-
|
|
22218
|
-
|
|
22219
|
-
|
|
22220
|
-
|
|
22221
|
-
|
|
22222
|
-
|
|
22223
|
-
|
|
22224
|
-
|
|
22225
|
-
|
|
22226
|
-
|
|
22227
|
-
|
|
22228
|
-
if (val === void 0 || val === null) return null;
|
|
22229
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
|
|
22230
|
-
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs" }),
|
|
22231
|
-
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: statusVariant3(String(val)), children: String(val) })
|
|
22232
|
-
] }, field.name);
|
|
22233
|
-
})
|
|
22234
|
-
] }),
|
|
22235
|
-
bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
|
|
22236
|
-
const value = getNestedValue(itemData, field.name);
|
|
22237
|
-
if (value === void 0 || value === null || value === "") return null;
|
|
22238
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
22239
|
-
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
22240
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", color: "secondary", children: [
|
|
22241
|
-
field.label ?? fieldLabel3(field.name),
|
|
22242
|
-
":"
|
|
22243
|
-
] }),
|
|
22244
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", children: formatValue2(value, field.format) })
|
|
22245
|
-
] }, field.name);
|
|
22246
|
-
}) }),
|
|
22247
|
-
progressFields.map((field) => {
|
|
22248
|
-
const value = getNestedValue(itemData, field.name);
|
|
22249
|
-
if (typeof value !== "number") return null;
|
|
22250
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "mt-2 max-w-xs", children: [
|
|
22251
|
-
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center mb-1", children: [
|
|
22252
|
-
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
22253
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel3(field.name) })
|
|
22254
|
-
] }),
|
|
22255
|
-
/* @__PURE__ */ jsxRuntime.jsx(ProgressBar, { value, max: 100 })
|
|
22256
|
-
] }, field.name);
|
|
22257
|
-
})
|
|
22258
|
-
] }),
|
|
22259
|
-
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: itemActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
22260
|
-
Button,
|
|
22261
|
-
{
|
|
22262
|
-
variant: action.variant ?? "ghost",
|
|
22263
|
-
size: "sm",
|
|
22264
|
-
onClick: handleActionClick(action, itemData),
|
|
22265
|
-
"data-testid": `action-${action.event}`,
|
|
22266
|
-
className: cn(
|
|
22267
|
-
action.variant === "danger" && "text-error hover:bg-error/10"
|
|
22268
|
-
),
|
|
22269
|
-
children: [
|
|
22270
|
-
action.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
22271
|
-
action.label
|
|
22272
|
-
]
|
|
22273
|
-
},
|
|
22274
|
-
idx
|
|
22275
|
-
)) })
|
|
22276
|
-
]
|
|
22277
|
-
}
|
|
22278
|
-
),
|
|
22279
|
-
isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mx-6 border-b border-border/40" })
|
|
22280
|
-
] }, id);
|
|
22281
|
-
};
|
|
22282
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
22146
|
+
children: [
|
|
22147
|
+
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
|
|
22148
|
+
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22149
|
+
HStack,
|
|
22150
|
+
{
|
|
22151
|
+
gap: "xs",
|
|
22152
|
+
className: "flex-shrink-0",
|
|
22153
|
+
children: itemActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
22154
|
+
Button,
|
|
22155
|
+
{
|
|
22156
|
+
variant: action.variant ?? "ghost",
|
|
22157
|
+
size: "sm",
|
|
22158
|
+
onClick: handleActionClick(action, itemData),
|
|
22159
|
+
"data-testid": `action-${action.event}`,
|
|
22160
|
+
className: cn(
|
|
22161
|
+
action.variant === "danger" && "text-error hover:bg-error/10"
|
|
22162
|
+
),
|
|
22163
|
+
children: [
|
|
22164
|
+
action.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
22165
|
+
action.label
|
|
22166
|
+
]
|
|
22167
|
+
},
|
|
22168
|
+
idx
|
|
22169
|
+
))
|
|
22170
|
+
}
|
|
22171
|
+
)
|
|
22172
|
+
]
|
|
22173
|
+
}
|
|
22174
|
+
),
|
|
22175
|
+
isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mx-6 border-b border-border/40" })
|
|
22176
|
+
] }, id2);
|
|
22177
|
+
}
|
|
22178
|
+
const id = itemData.id || String(index);
|
|
22179
|
+
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
22180
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id, children: [
|
|
22181
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
22283
22182
|
Box,
|
|
22284
22183
|
{
|
|
22285
22184
|
className: cn(
|
|
22286
|
-
|
|
22287
|
-
|
|
22288
|
-
|
|
22185
|
+
"group flex items-center gap-4 transition-all duration-200",
|
|
22186
|
+
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
22187
|
+
"hover:bg-muted/80",
|
|
22188
|
+
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
22289
22189
|
),
|
|
22290
22190
|
children: [
|
|
22291
|
-
|
|
22292
|
-
|
|
22293
|
-
|
|
22294
|
-
|
|
22295
|
-
|
|
22296
|
-
|
|
22297
|
-
|
|
22191
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex-1 min-w-0", children: [
|
|
22192
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "items-center", children: [
|
|
22193
|
+
titleField?.icon && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22194
|
+
Icon,
|
|
22195
|
+
{
|
|
22196
|
+
name: titleField.icon,
|
|
22197
|
+
size: isCompact ? "xs" : "sm",
|
|
22198
|
+
className: "text-primary flex-shrink-0"
|
|
22199
|
+
}
|
|
22200
|
+
),
|
|
22201
|
+
titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22202
|
+
Typography,
|
|
22203
|
+
{
|
|
22204
|
+
variant: titleField?.variant === "h3" ? "h3" : "h4",
|
|
22205
|
+
className: cn("font-semibold truncate flex-1", isCompact && "text-sm"),
|
|
22206
|
+
children: String(titleValue)
|
|
22207
|
+
}
|
|
22208
|
+
),
|
|
22209
|
+
badgeFields.map((field) => {
|
|
22210
|
+
const val = getNestedValue(itemData, field.name);
|
|
22211
|
+
if (val === void 0 || val === null) return null;
|
|
22212
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
|
|
22213
|
+
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs" }),
|
|
22214
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: statusVariant3(String(val)), children: String(val) })
|
|
22215
|
+
] }, field.name);
|
|
22216
|
+
})
|
|
22217
|
+
] }),
|
|
22218
|
+
bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
|
|
22219
|
+
const value = getNestedValue(itemData, field.name);
|
|
22220
|
+
if (value === void 0 || value === null || value === "") return null;
|
|
22221
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
22222
|
+
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
22223
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", color: "secondary", children: [
|
|
22224
|
+
field.label ?? fieldLabel3(field.name),
|
|
22225
|
+
":"
|
|
22226
|
+
] }),
|
|
22227
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", children: formatValue2(value, field.format) })
|
|
22228
|
+
] }, field.name);
|
|
22229
|
+
}) }),
|
|
22230
|
+
progressFields.map((field) => {
|
|
22231
|
+
const value = getNestedValue(itemData, field.name);
|
|
22232
|
+
if (typeof value !== "number") return null;
|
|
22233
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "mt-2 max-w-xs", children: [
|
|
22234
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center mb-1", children: [
|
|
22235
|
+
field.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
22236
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel3(field.name) })
|
|
22237
|
+
] }),
|
|
22238
|
+
/* @__PURE__ */ jsxRuntime.jsx(ProgressBar, { value, max: 100 })
|
|
22239
|
+
] }, field.name);
|
|
22240
|
+
})
|
|
22241
|
+
] }),
|
|
22242
|
+
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: itemActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
22298
22243
|
Button,
|
|
22299
22244
|
{
|
|
22300
|
-
variant: "ghost",
|
|
22245
|
+
variant: action.variant ?? "ghost",
|
|
22301
22246
|
size: "sm",
|
|
22302
|
-
onClick: (
|
|
22247
|
+
onClick: handleActionClick(action, itemData),
|
|
22248
|
+
"data-testid": `action-${action.event}`,
|
|
22249
|
+
className: cn(
|
|
22250
|
+
action.variant === "danger" && "text-error hover:bg-error/10"
|
|
22251
|
+
),
|
|
22303
22252
|
children: [
|
|
22304
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name:
|
|
22305
|
-
|
|
22306
|
-
" (",
|
|
22307
|
-
allData.length - visibleCount,
|
|
22308
|
-
" remaining)"
|
|
22253
|
+
action.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
22254
|
+
action.label
|
|
22309
22255
|
]
|
|
22310
|
-
}
|
|
22311
|
-
|
|
22312
|
-
|
|
22313
|
-
InfiniteScrollSentinel,
|
|
22314
|
-
{
|
|
22315
|
-
loadMoreEvent,
|
|
22316
|
-
isLoading,
|
|
22317
|
-
hasMore
|
|
22318
|
-
}
|
|
22319
|
-
)
|
|
22256
|
+
},
|
|
22257
|
+
idx
|
|
22258
|
+
)) })
|
|
22320
22259
|
]
|
|
22321
22260
|
}
|
|
22322
|
-
)
|
|
22323
|
-
|
|
22261
|
+
),
|
|
22262
|
+
isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mx-6 border-b border-border/40" })
|
|
22263
|
+
] }, id);
|
|
22264
|
+
};
|
|
22265
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
22266
|
+
Box,
|
|
22267
|
+
{
|
|
22268
|
+
className: cn(
|
|
22269
|
+
isCard && "bg-card rounded-xl border border-border shadow-lg overflow-hidden",
|
|
22270
|
+
!isCard && gapClass,
|
|
22271
|
+
className
|
|
22272
|
+
),
|
|
22273
|
+
children: [
|
|
22274
|
+
groups.map((group, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React126__namespace.default.Fragment, { children: [
|
|
22275
|
+
group.label && /* @__PURE__ */ jsxRuntime.jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
|
|
22276
|
+
group.items.map(
|
|
22277
|
+
(itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
|
|
22278
|
+
)
|
|
22279
|
+
] }, gi)),
|
|
22280
|
+
hasMoreLocal && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
22281
|
+
Button,
|
|
22282
|
+
{
|
|
22283
|
+
variant: "ghost",
|
|
22284
|
+
size: "sm",
|
|
22285
|
+
onClick: () => setVisibleCount((prev) => prev + (pageSize || 5)),
|
|
22286
|
+
children: [
|
|
22287
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
22288
|
+
t("common.showMore"),
|
|
22289
|
+
" (",
|
|
22290
|
+
allData.length - visibleCount,
|
|
22291
|
+
" remaining)"
|
|
22292
|
+
]
|
|
22293
|
+
}
|
|
22294
|
+
) }),
|
|
22295
|
+
infiniteScroll && loadMoreEvent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22296
|
+
InfiniteScrollSentinel,
|
|
22297
|
+
{
|
|
22298
|
+
loadMoreEvent,
|
|
22299
|
+
isLoading,
|
|
22300
|
+
hasMore
|
|
22301
|
+
}
|
|
22302
|
+
)
|
|
22303
|
+
]
|
|
22304
|
+
}
|
|
22305
|
+
);
|
|
22306
|
+
}
|
|
22307
|
+
var init_DataList = __esm({
|
|
22308
|
+
"components/molecules/DataList.tsx"() {
|
|
22309
|
+
"use client";
|
|
22310
|
+
init_cn();
|
|
22311
|
+
init_getNestedValue();
|
|
22312
|
+
init_useEventBus();
|
|
22313
|
+
init_useTranslate();
|
|
22314
|
+
init_Box();
|
|
22315
|
+
init_Stack();
|
|
22316
|
+
init_Typography();
|
|
22317
|
+
init_Badge();
|
|
22318
|
+
init_Button();
|
|
22319
|
+
init_Icon();
|
|
22320
|
+
init_ProgressBar();
|
|
22321
|
+
init_Divider();
|
|
22322
|
+
init_InfiniteScrollSentinel();
|
|
22324
22323
|
DataList.displayName = "DataList";
|
|
22325
22324
|
}
|
|
22326
22325
|
});
|
|
@@ -23521,7 +23520,10 @@ var init_WizardProgress = __esm({
|
|
|
23521
23520
|
stepClickEvent
|
|
23522
23521
|
}) => {
|
|
23523
23522
|
const eventBus = useEventBus();
|
|
23524
|
-
const
|
|
23523
|
+
const normalizedSteps = steps.map(
|
|
23524
|
+
(s, i) => typeof s === "string" ? { id: `step-${i}`, title: s } : s
|
|
23525
|
+
);
|
|
23526
|
+
const totalSteps = normalizedSteps.length;
|
|
23525
23527
|
const handleStepClick = (index) => {
|
|
23526
23528
|
const isCompleted = index < currentStep;
|
|
23527
23529
|
if (isCompleted && allowNavigation) {
|
|
@@ -23538,7 +23540,7 @@ var init_WizardProgress = __esm({
|
|
|
23538
23540
|
compact ? "px-4 py-2" : "px-6 py-4",
|
|
23539
23541
|
className
|
|
23540
23542
|
),
|
|
23541
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children:
|
|
23543
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
|
|
23542
23544
|
const isActive = index === currentStep;
|
|
23543
23545
|
const isCompleted = index < currentStep;
|
|
23544
23546
|
return /* @__PURE__ */ jsxRuntime.jsxs(React126__namespace.default.Fragment, { children: [
|
|
@@ -51032,18 +51034,12 @@ init_useUISlots();
|
|
|
51032
51034
|
|
|
51033
51035
|
// hooks/useUIEvents.ts
|
|
51034
51036
|
init_useEventBus();
|
|
51035
|
-
React126.createContext(null);
|
|
51036
51037
|
|
|
51037
51038
|
// hooks/index.ts
|
|
51038
51039
|
init_useQuerySingleton();
|
|
51039
51040
|
|
|
51040
|
-
// lib/api-client.ts
|
|
51041
|
-
typeof process !== "undefined" && process.env?.VITE_API_URL ? process.env.VITE_API_URL : "/api";
|
|
51042
|
-
|
|
51043
51041
|
// hooks/index.ts
|
|
51044
51042
|
init_useTranslate();
|
|
51045
|
-
|
|
51046
|
-
// hooks/index.ts
|
|
51047
51043
|
init_useAuthContext();
|
|
51048
51044
|
init_useSwipeGesture();
|
|
51049
51045
|
init_useLongPress();
|
|
@@ -51614,33 +51610,66 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
|
|
|
51614
51610
|
canHandleEvent
|
|
51615
51611
|
};
|
|
51616
51612
|
}
|
|
51613
|
+
var DEFAULT_SOURCE_KEY = "__default__";
|
|
51614
|
+
function slotEntriesInOrder(slot) {
|
|
51615
|
+
if (!slot) return [];
|
|
51616
|
+
const out = [];
|
|
51617
|
+
for (const [sourceKey, entry] of Object.entries(slot)) {
|
|
51618
|
+
if (entry.patterns.length > 0) {
|
|
51619
|
+
out.push({ sourceKey, entry });
|
|
51620
|
+
}
|
|
51621
|
+
}
|
|
51622
|
+
return out;
|
|
51623
|
+
}
|
|
51617
51624
|
var SlotsStateContext = React126.createContext({});
|
|
51618
51625
|
var SlotsActionsContext = React126.createContext(null);
|
|
51619
51626
|
function SlotsProvider({ children }) {
|
|
51620
51627
|
const [slots, setSlots] = React126.useState({});
|
|
51621
51628
|
const setSlotPatterns = React126.useCallback((slot, patterns, source) => {
|
|
51622
|
-
|
|
51623
|
-
|
|
51624
|
-
[slot]
|
|
51625
|
-
|
|
51629
|
+
const sourceKey = source?.trait ?? DEFAULT_SOURCE_KEY;
|
|
51630
|
+
setSlots((prev) => {
|
|
51631
|
+
const prevSlot = prev[slot] ?? {};
|
|
51632
|
+
return {
|
|
51633
|
+
...prev,
|
|
51634
|
+
[slot]: {
|
|
51635
|
+
...prevSlot,
|
|
51636
|
+
[sourceKey]: { patterns, source }
|
|
51637
|
+
}
|
|
51638
|
+
};
|
|
51639
|
+
});
|
|
51626
51640
|
}, []);
|
|
51627
51641
|
const clearSlot = React126.useCallback((slot) => {
|
|
51628
51642
|
setSlots((prev) => {
|
|
51629
51643
|
const existing = prev[slot];
|
|
51630
|
-
if (existing && existing.
|
|
51644
|
+
if (existing && Object.keys(existing).length === 0) {
|
|
51631
51645
|
return prev;
|
|
51632
51646
|
}
|
|
51633
|
-
return { ...prev, [slot]: {
|
|
51647
|
+
return { ...prev, [slot]: {} };
|
|
51648
|
+
});
|
|
51649
|
+
}, []);
|
|
51650
|
+
const clearSlotForSource = React126.useCallback((slot, sourceTrait) => {
|
|
51651
|
+
setSlots((prev) => {
|
|
51652
|
+
const existing = prev[slot];
|
|
51653
|
+
if (!existing || !(sourceTrait in existing)) return prev;
|
|
51654
|
+
const next = { ...existing };
|
|
51655
|
+
delete next[sourceTrait];
|
|
51656
|
+
return { ...prev, [slot]: next };
|
|
51634
51657
|
});
|
|
51635
51658
|
}, []);
|
|
51636
51659
|
const clearAllSlots = React126.useCallback(() => {
|
|
51637
51660
|
setSlots({});
|
|
51638
51661
|
}, []);
|
|
51639
|
-
const actionsRef = React126.useRef({
|
|
51640
|
-
|
|
51662
|
+
const actionsRef = React126.useRef({
|
|
51663
|
+
setSlotPatterns,
|
|
51664
|
+
clearSlot,
|
|
51665
|
+
clearSlotForSource,
|
|
51666
|
+
clearAllSlots
|
|
51667
|
+
});
|
|
51668
|
+
actionsRef.current = { setSlotPatterns, clearSlot, clearSlotForSource, clearAllSlots };
|
|
51641
51669
|
const [stableActions] = React126.useState(() => ({
|
|
51642
51670
|
setSlotPatterns: (...args) => actionsRef.current.setSlotPatterns(...args),
|
|
51643
51671
|
clearSlot: (...args) => actionsRef.current.clearSlot(...args),
|
|
51672
|
+
clearSlotForSource: (...args) => actionsRef.current.clearSlotForSource(...args),
|
|
51644
51673
|
clearAllSlots: () => actionsRef.current.clearAllSlots()
|
|
51645
51674
|
}));
|
|
51646
51675
|
return /* @__PURE__ */ jsxRuntime.jsx(SlotsActionsContext.Provider, { value: stableActions, children: /* @__PURE__ */ jsxRuntime.jsx(SlotsStateContext.Provider, { value: slots, children }) });
|
|
@@ -51876,34 +51905,60 @@ function SlotBridge() {
|
|
|
51876
51905
|
const { render, clear } = useUISlots();
|
|
51877
51906
|
React126.useEffect(() => {
|
|
51878
51907
|
for (const [slotName, slotState] of Object.entries(slots)) {
|
|
51879
|
-
|
|
51908
|
+
const entries = slotEntriesInOrder(slotState);
|
|
51909
|
+
if (entries.length === 0) {
|
|
51880
51910
|
clear(slotName);
|
|
51881
51911
|
continue;
|
|
51882
51912
|
}
|
|
51883
|
-
const
|
|
51884
|
-
|
|
51885
|
-
|
|
51886
|
-
|
|
51887
|
-
|
|
51888
|
-
|
|
51889
|
-
pattern: patternType,
|
|
51890
|
-
props: {
|
|
51913
|
+
const children = entries.map(({ entry }) => entry.patterns[entry.patterns.length - 1]).filter((p2) => Boolean(p2)).map((entry) => {
|
|
51914
|
+
const record = entry.pattern;
|
|
51915
|
+
const { type: patternType, children: nested, ...inlineProps } = record;
|
|
51916
|
+
const normalizedNested = Array.isArray(nested) ? nested.map((c) => normalizeChild(c)) : nested;
|
|
51917
|
+
return {
|
|
51918
|
+
type: patternType,
|
|
51891
51919
|
...inlineProps,
|
|
51892
51920
|
...entry.props,
|
|
51893
|
-
...
|
|
51894
|
-
}
|
|
51895
|
-
sourceTrait: slotState.source?.trait
|
|
51921
|
+
...normalizedNested !== void 0 ? { children: normalizedNested } : {}
|
|
51922
|
+
};
|
|
51896
51923
|
});
|
|
51924
|
+
if (children.length === 1) {
|
|
51925
|
+
const only = children[0];
|
|
51926
|
+
const { type, children: nested, ...rest } = only;
|
|
51927
|
+
const lastEntry = entries[entries.length - 1];
|
|
51928
|
+
render({
|
|
51929
|
+
target: slotName,
|
|
51930
|
+
pattern: type,
|
|
51931
|
+
props: {
|
|
51932
|
+
...rest,
|
|
51933
|
+
...nested !== void 0 ? { children: nested } : {}
|
|
51934
|
+
},
|
|
51935
|
+
sourceTrait: lastEntry.entry.source?.trait
|
|
51936
|
+
});
|
|
51937
|
+
} else {
|
|
51938
|
+
const lastEntry = entries[entries.length - 1];
|
|
51939
|
+
render({
|
|
51940
|
+
target: slotName,
|
|
51941
|
+
pattern: "stack",
|
|
51942
|
+
props: {
|
|
51943
|
+
direction: "vertical",
|
|
51944
|
+
gap: "lg",
|
|
51945
|
+
children
|
|
51946
|
+
},
|
|
51947
|
+
sourceTrait: lastEntry.entry.source?.trait
|
|
51948
|
+
});
|
|
51949
|
+
}
|
|
51897
51950
|
}
|
|
51898
51951
|
}, [slots, render, clear]);
|
|
51899
51952
|
return null;
|
|
51900
51953
|
}
|
|
51901
51954
|
function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
51955
|
+
const perSlotRenders = /* @__PURE__ */ new Map();
|
|
51902
51956
|
for (const eff of effects) {
|
|
51903
51957
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
51904
51958
|
const patternRecord = eff.pattern;
|
|
51905
51959
|
const { type: patternType, children, ...inlineProps } = patternRecord;
|
|
51906
51960
|
const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
|
|
51961
|
+
const sourceTrait = eff.traitName ?? "server";
|
|
51907
51962
|
uiSlots.render({
|
|
51908
51963
|
target: eff.slot,
|
|
51909
51964
|
pattern: patternType,
|
|
@@ -51911,12 +51966,38 @@ function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
|
51911
51966
|
...inlineProps,
|
|
51912
51967
|
...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
|
|
51913
51968
|
},
|
|
51914
|
-
sourceTrait
|
|
51969
|
+
sourceTrait
|
|
51970
|
+
});
|
|
51971
|
+
const bucket = perSlotRenders.get(eff.slot) ?? [];
|
|
51972
|
+
bucket.push({
|
|
51973
|
+
sourceTrait,
|
|
51974
|
+
pattern: {
|
|
51975
|
+
type: patternType,
|
|
51976
|
+
...inlineProps,
|
|
51977
|
+
...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
|
|
51978
|
+
}
|
|
51915
51979
|
});
|
|
51980
|
+
perSlotRenders.set(eff.slot, bucket);
|
|
51916
51981
|
} else if (eff.type === "navigate" && eff.route && onNavigate) {
|
|
51917
51982
|
onNavigate(eff.route, eff.params);
|
|
51918
51983
|
}
|
|
51919
51984
|
}
|
|
51985
|
+
for (const [slot, bucket] of perSlotRenders) {
|
|
51986
|
+
const distinctSources = new Set(bucket.map((b) => b.sourceTrait));
|
|
51987
|
+
if (distinctSources.size <= 1) continue;
|
|
51988
|
+
uiSlots.render({
|
|
51989
|
+
target: slot,
|
|
51990
|
+
pattern: "stack",
|
|
51991
|
+
props: {
|
|
51992
|
+
direction: "vertical",
|
|
51993
|
+
gap: "lg",
|
|
51994
|
+
children: bucket.map((b) => b.pattern)
|
|
51995
|
+
},
|
|
51996
|
+
// Use a synthetic wrapper source trait; individual traits' frames
|
|
51997
|
+
// already live in the per-trait index from the per-effect loop.
|
|
51998
|
+
sourceTrait: "__multi_source_stack__"
|
|
51999
|
+
});
|
|
52000
|
+
}
|
|
51920
52001
|
}
|
|
51921
52002
|
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence }) {
|
|
51922
52003
|
const slotsActions = useSlotsActions();
|