@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.js
CHANGED
|
@@ -10883,13 +10883,13 @@ var init_MapView = __esm({
|
|
|
10883
10883
|
shadowSize: [41, 41]
|
|
10884
10884
|
});
|
|
10885
10885
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
10886
|
-
const { useEffect:
|
|
10886
|
+
const { useEffect: useEffect87, useRef: useRef87, useCallback: useCallback125, useState: useState125 } = React126__default;
|
|
10887
10887
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
10888
10888
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
10889
10889
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
10890
10890
|
const map = useMap();
|
|
10891
10891
|
const prevRef = useRef87({ centerLat, centerLng, zoom });
|
|
10892
|
-
|
|
10892
|
+
useEffect87(() => {
|
|
10893
10893
|
const prev = prevRef.current;
|
|
10894
10894
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
10895
10895
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -10900,7 +10900,7 @@ var init_MapView = __esm({
|
|
|
10900
10900
|
}
|
|
10901
10901
|
function MapClickHandler({ onMapClick }) {
|
|
10902
10902
|
const map = useMap();
|
|
10903
|
-
|
|
10903
|
+
useEffect87(() => {
|
|
10904
10904
|
if (!onMapClick) return;
|
|
10905
10905
|
const handler = (e) => {
|
|
10906
10906
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -10927,7 +10927,7 @@ var init_MapView = __esm({
|
|
|
10927
10927
|
showAttribution = true
|
|
10928
10928
|
}) {
|
|
10929
10929
|
const eventBus = useEventBus3();
|
|
10930
|
-
const [clickedPosition, setClickedPosition] =
|
|
10930
|
+
const [clickedPosition, setClickedPosition] = useState125(null);
|
|
10931
10931
|
const handleMapClick = useCallback125((lat, lng) => {
|
|
10932
10932
|
if (showClickedPin) {
|
|
10933
10933
|
setClickedPosition({ lat, lng });
|
|
@@ -21611,7 +21611,290 @@ function formatValue(value, format) {
|
|
|
21611
21611
|
return String(value);
|
|
21612
21612
|
}
|
|
21613
21613
|
}
|
|
21614
|
-
|
|
21614
|
+
function DataGrid({
|
|
21615
|
+
entity,
|
|
21616
|
+
fields: fieldsProp,
|
|
21617
|
+
columns: columnsProp,
|
|
21618
|
+
itemActions,
|
|
21619
|
+
cols,
|
|
21620
|
+
gap = "md",
|
|
21621
|
+
minCardWidth = 280,
|
|
21622
|
+
className,
|
|
21623
|
+
isLoading = false,
|
|
21624
|
+
error = null,
|
|
21625
|
+
imageField,
|
|
21626
|
+
selectable = false,
|
|
21627
|
+
selectionEvent,
|
|
21628
|
+
infiniteScroll,
|
|
21629
|
+
loadMoreEvent,
|
|
21630
|
+
hasMore,
|
|
21631
|
+
children,
|
|
21632
|
+
pageSize = 0
|
|
21633
|
+
}) {
|
|
21634
|
+
const eventBus = useEventBus();
|
|
21635
|
+
const { t } = useTranslate();
|
|
21636
|
+
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
21637
|
+
const [visibleCount, setVisibleCount] = useState(pageSize || Infinity);
|
|
21638
|
+
const fields = fieldsProp ?? columnsProp ?? [];
|
|
21639
|
+
const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
21640
|
+
const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
|
|
21641
|
+
const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
|
|
21642
|
+
const toggleSelection = useCallback((id) => {
|
|
21643
|
+
setSelectedIds((prev) => {
|
|
21644
|
+
const next = new Set(prev);
|
|
21645
|
+
if (next.has(id)) next.delete(id);
|
|
21646
|
+
else next.add(id);
|
|
21647
|
+
if (selectionEvent) {
|
|
21648
|
+
const payload = { selectedIds: Array.from(next) };
|
|
21649
|
+
eventBus.emit(`UI:${selectionEvent}`, payload);
|
|
21650
|
+
}
|
|
21651
|
+
return next;
|
|
21652
|
+
});
|
|
21653
|
+
}, [selectionEvent, eventBus]);
|
|
21654
|
+
const toggleAll = useCallback(() => {
|
|
21655
|
+
setSelectedIds((prev) => {
|
|
21656
|
+
const allIds2 = data.map((item, i) => item.id || String(i));
|
|
21657
|
+
const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
|
|
21658
|
+
const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
|
|
21659
|
+
if (selectionEvent) {
|
|
21660
|
+
const payload = { selectedIds: Array.from(next) };
|
|
21661
|
+
eventBus.emit(`UI:${selectionEvent}`, payload);
|
|
21662
|
+
}
|
|
21663
|
+
return next;
|
|
21664
|
+
});
|
|
21665
|
+
}, [data, selectionEvent, eventBus]);
|
|
21666
|
+
const titleField = fields.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fields[0];
|
|
21667
|
+
const badgeFields = fields.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
21668
|
+
const bodyFields = fields.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
|
|
21669
|
+
const primaryActions = itemActions?.filter((a) => a.variant !== "danger") ?? [];
|
|
21670
|
+
const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
|
|
21671
|
+
const handleActionClick = (action, itemData) => (e) => {
|
|
21672
|
+
e.stopPropagation();
|
|
21673
|
+
const payload = {
|
|
21674
|
+
id: itemData.id,
|
|
21675
|
+
row: itemData
|
|
21676
|
+
};
|
|
21677
|
+
eventBus.emit(`UI:${action.event}`, payload);
|
|
21678
|
+
};
|
|
21679
|
+
const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
|
|
21680
|
+
const colsClass = cols ? {
|
|
21681
|
+
1: "grid-cols-1",
|
|
21682
|
+
2: "sm:grid-cols-2",
|
|
21683
|
+
3: "sm:grid-cols-2 lg:grid-cols-3",
|
|
21684
|
+
4: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
|
|
21685
|
+
5: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5",
|
|
21686
|
+
6: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6"
|
|
21687
|
+
}[cols] : void 0;
|
|
21688
|
+
if (isLoading) {
|
|
21689
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
|
|
21690
|
+
}
|
|
21691
|
+
if (error) {
|
|
21692
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
21693
|
+
}
|
|
21694
|
+
if (data.length === 0) {
|
|
21695
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-12", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("empty.noItems") || "No items found" }) });
|
|
21696
|
+
}
|
|
21697
|
+
const hasRenderProp = typeof children === "function";
|
|
21698
|
+
const allIds = data.map((item, i) => item.id || String(i));
|
|
21699
|
+
const allSelected = allIds.length > 0 && allIds.every((id) => selectedIds.has(id));
|
|
21700
|
+
const someSelected = selectedIds.size > 0;
|
|
21701
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
21702
|
+
selectable && someSelected && /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "items-center px-2 py-2 bg-muted rounded-sm", children: [
|
|
21703
|
+
/* @__PURE__ */ jsx(
|
|
21704
|
+
"input",
|
|
21705
|
+
{
|
|
21706
|
+
type: "checkbox",
|
|
21707
|
+
checked: allSelected,
|
|
21708
|
+
onChange: toggleAll,
|
|
21709
|
+
className: "w-4 h-4 accent-primary",
|
|
21710
|
+
"aria-label": "Select all"
|
|
21711
|
+
}
|
|
21712
|
+
),
|
|
21713
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "font-semibold", children: [
|
|
21714
|
+
selectedIds.size,
|
|
21715
|
+
" ",
|
|
21716
|
+
t("common.selected") || "selected"
|
|
21717
|
+
] })
|
|
21718
|
+
] }),
|
|
21719
|
+
/* @__PURE__ */ jsx(
|
|
21720
|
+
Box,
|
|
21721
|
+
{
|
|
21722
|
+
className: cn("grid", gapStyles6[gap], colsClass, className),
|
|
21723
|
+
style: gridTemplateColumns ? { gridTemplateColumns } : void 0,
|
|
21724
|
+
children: data.map((item, index) => {
|
|
21725
|
+
const itemData = item;
|
|
21726
|
+
const id = itemData.id || String(index);
|
|
21727
|
+
const isSelected = selectedIds.has(id);
|
|
21728
|
+
if (hasRenderProp) {
|
|
21729
|
+
return /* @__PURE__ */ jsx(
|
|
21730
|
+
Box,
|
|
21731
|
+
{
|
|
21732
|
+
"data-entity-row": true,
|
|
21733
|
+
"data-entity-id": id,
|
|
21734
|
+
className: cn(
|
|
21735
|
+
"bg-card rounded-lg",
|
|
21736
|
+
"border border-border",
|
|
21737
|
+
"shadow-sm hover:shadow-lg",
|
|
21738
|
+
"hover:border-primary transition-all",
|
|
21739
|
+
"p-4",
|
|
21740
|
+
isSelected && "ring-2 ring-primary border-primary"
|
|
21741
|
+
),
|
|
21742
|
+
children: children(itemData, index)
|
|
21743
|
+
},
|
|
21744
|
+
id
|
|
21745
|
+
);
|
|
21746
|
+
}
|
|
21747
|
+
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
21748
|
+
return /* @__PURE__ */ jsxs(
|
|
21749
|
+
Box,
|
|
21750
|
+
{
|
|
21751
|
+
"data-entity-row": true,
|
|
21752
|
+
"data-entity-id": id,
|
|
21753
|
+
className: cn(
|
|
21754
|
+
"bg-card rounded-lg",
|
|
21755
|
+
"border border-border",
|
|
21756
|
+
"shadow-sm hover:shadow-lg",
|
|
21757
|
+
"hover:border-primary transition-all",
|
|
21758
|
+
"flex flex-col",
|
|
21759
|
+
isSelected && "ring-2 ring-primary border-primary"
|
|
21760
|
+
),
|
|
21761
|
+
children: [
|
|
21762
|
+
imageField && (() => {
|
|
21763
|
+
const imgUrl = getNestedValue(itemData, imageField);
|
|
21764
|
+
if (!imgUrl || typeof imgUrl !== "string") return null;
|
|
21765
|
+
return /* @__PURE__ */ jsx(Box, { className: "w-full aspect-video overflow-hidden rounded-t-lg", children: /* @__PURE__ */ jsx(
|
|
21766
|
+
"img",
|
|
21767
|
+
{
|
|
21768
|
+
src: imgUrl,
|
|
21769
|
+
alt: titleValue !== void 0 ? String(titleValue) : "",
|
|
21770
|
+
className: "w-full h-full object-cover",
|
|
21771
|
+
loading: "lazy"
|
|
21772
|
+
}
|
|
21773
|
+
) });
|
|
21774
|
+
})(),
|
|
21775
|
+
/* @__PURE__ */ jsx(Box, { className: "p-4 pb-0", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
21776
|
+
selectable && /* @__PURE__ */ jsx(
|
|
21777
|
+
"input",
|
|
21778
|
+
{
|
|
21779
|
+
type: "checkbox",
|
|
21780
|
+
checked: isSelected,
|
|
21781
|
+
onChange: () => toggleSelection(id),
|
|
21782
|
+
onClick: (e) => e.stopPropagation(),
|
|
21783
|
+
className: "w-4 h-4 mt-1 flex-shrink-0 accent-primary",
|
|
21784
|
+
"aria-label": `Select ${titleValue !== void 0 ? String(titleValue) : "item"}`
|
|
21785
|
+
}
|
|
21786
|
+
),
|
|
21787
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
21788
|
+
titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21789
|
+
titleField?.icon && /* @__PURE__ */ jsx(Icon, { name: titleField.icon, size: "sm", className: "text-primary flex-shrink-0" }),
|
|
21790
|
+
/* @__PURE__ */ jsx(
|
|
21791
|
+
Typography,
|
|
21792
|
+
{
|
|
21793
|
+
variant: titleField?.variant === "h3" ? "h3" : "h4",
|
|
21794
|
+
className: "font-semibold truncate",
|
|
21795
|
+
children: String(titleValue)
|
|
21796
|
+
}
|
|
21797
|
+
)
|
|
21798
|
+
] }),
|
|
21799
|
+
badgeFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: badgeFields.map((field) => {
|
|
21800
|
+
const val = getNestedValue(itemData, field.name);
|
|
21801
|
+
if (val === void 0 || val === null) return null;
|
|
21802
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21803
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs" }),
|
|
21804
|
+
/* @__PURE__ */ jsx(Badge, { variant: statusVariant2(String(val)), children: String(val) })
|
|
21805
|
+
] }, field.name);
|
|
21806
|
+
}) })
|
|
21807
|
+
] }),
|
|
21808
|
+
dangerActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
21809
|
+
Button,
|
|
21810
|
+
{
|
|
21811
|
+
variant: "ghost",
|
|
21812
|
+
size: "sm",
|
|
21813
|
+
onClick: handleActionClick(action, itemData),
|
|
21814
|
+
"data-testid": `action-${action.event}`,
|
|
21815
|
+
className: "text-error hover:bg-error/10 px-2",
|
|
21816
|
+
children: [
|
|
21817
|
+
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs" }),
|
|
21818
|
+
action.label
|
|
21819
|
+
]
|
|
21820
|
+
},
|
|
21821
|
+
idx
|
|
21822
|
+
)) })
|
|
21823
|
+
] }) }),
|
|
21824
|
+
bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: bodyFields.map((field) => {
|
|
21825
|
+
const value = getNestedValue(itemData, field.name);
|
|
21826
|
+
if (value === void 0 || value === null || value === "") return null;
|
|
21827
|
+
if (field.format === "boolean") {
|
|
21828
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
|
|
21829
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21830
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
21831
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
|
|
21832
|
+
] }),
|
|
21833
|
+
/* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
|
|
21834
|
+
] }, field.name);
|
|
21835
|
+
}
|
|
21836
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
|
|
21837
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21838
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
21839
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
|
|
21840
|
+
] }),
|
|
21841
|
+
/* @__PURE__ */ jsx(
|
|
21842
|
+
Typography,
|
|
21843
|
+
{
|
|
21844
|
+
variant: field.variant === "caption" ? "caption" : "small",
|
|
21845
|
+
className: "text-right truncate max-w-[60%]",
|
|
21846
|
+
children: formatValue(value, field.format)
|
|
21847
|
+
}
|
|
21848
|
+
)
|
|
21849
|
+
] }, field.name);
|
|
21850
|
+
}) }) }),
|
|
21851
|
+
primaryActions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsx(HStack, { gap: "sm", className: "justify-end", children: primaryActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
21852
|
+
Button,
|
|
21853
|
+
{
|
|
21854
|
+
variant: action.variant === "primary" ? "primary" : "ghost",
|
|
21855
|
+
size: "sm",
|
|
21856
|
+
onClick: handleActionClick(action, itemData),
|
|
21857
|
+
"data-testid": `action-${action.event}`,
|
|
21858
|
+
children: [
|
|
21859
|
+
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
21860
|
+
action.label
|
|
21861
|
+
]
|
|
21862
|
+
},
|
|
21863
|
+
idx
|
|
21864
|
+
)) }) })
|
|
21865
|
+
]
|
|
21866
|
+
},
|
|
21867
|
+
id
|
|
21868
|
+
);
|
|
21869
|
+
})
|
|
21870
|
+
}
|
|
21871
|
+
),
|
|
21872
|
+
hasMoreLocal && /* @__PURE__ */ jsx(Box, { className: "flex justify-center py-3", children: /* @__PURE__ */ jsxs(
|
|
21873
|
+
Button,
|
|
21874
|
+
{
|
|
21875
|
+
variant: "ghost",
|
|
21876
|
+
size: "sm",
|
|
21877
|
+
onClick: () => setVisibleCount((prev) => prev + (pageSize || 5)),
|
|
21878
|
+
children: [
|
|
21879
|
+
/* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
21880
|
+
t("common.showMore"),
|
|
21881
|
+
" (",
|
|
21882
|
+
allData.length - visibleCount,
|
|
21883
|
+
" remaining)"
|
|
21884
|
+
]
|
|
21885
|
+
}
|
|
21886
|
+
) }),
|
|
21887
|
+
infiniteScroll && loadMoreEvent && /* @__PURE__ */ jsx(
|
|
21888
|
+
InfiniteScrollSentinel,
|
|
21889
|
+
{
|
|
21890
|
+
loadMoreEvent,
|
|
21891
|
+
isLoading,
|
|
21892
|
+
hasMore
|
|
21893
|
+
}
|
|
21894
|
+
)
|
|
21895
|
+
] });
|
|
21896
|
+
}
|
|
21897
|
+
var gapStyles6;
|
|
21615
21898
|
var init_DataGrid = __esm({
|
|
21616
21899
|
"components/molecules/DataGrid.tsx"() {
|
|
21617
21900
|
"use client";
|
|
@@ -21633,289 +21916,6 @@ var init_DataGrid = __esm({
|
|
|
21633
21916
|
lg: "gap-6",
|
|
21634
21917
|
xl: "gap-8"
|
|
21635
21918
|
};
|
|
21636
|
-
DataGrid = ({
|
|
21637
|
-
entity,
|
|
21638
|
-
fields: fieldsProp,
|
|
21639
|
-
columns: columnsProp,
|
|
21640
|
-
itemActions,
|
|
21641
|
-
cols,
|
|
21642
|
-
gap = "md",
|
|
21643
|
-
minCardWidth = 280,
|
|
21644
|
-
className,
|
|
21645
|
-
isLoading = false,
|
|
21646
|
-
error = null,
|
|
21647
|
-
imageField,
|
|
21648
|
-
selectable = false,
|
|
21649
|
-
selectionEvent,
|
|
21650
|
-
infiniteScroll,
|
|
21651
|
-
loadMoreEvent,
|
|
21652
|
-
hasMore,
|
|
21653
|
-
children,
|
|
21654
|
-
pageSize = 0
|
|
21655
|
-
}) => {
|
|
21656
|
-
const eventBus = useEventBus();
|
|
21657
|
-
const { t } = useTranslate();
|
|
21658
|
-
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
21659
|
-
const [visibleCount, setVisibleCount] = useState(pageSize || Infinity);
|
|
21660
|
-
const fields = fieldsProp ?? columnsProp ?? [];
|
|
21661
|
-
const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
21662
|
-
const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
|
|
21663
|
-
const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
|
|
21664
|
-
const toggleSelection = useCallback((id) => {
|
|
21665
|
-
setSelectedIds((prev) => {
|
|
21666
|
-
const next = new Set(prev);
|
|
21667
|
-
if (next.has(id)) next.delete(id);
|
|
21668
|
-
else next.add(id);
|
|
21669
|
-
if (selectionEvent) {
|
|
21670
|
-
const payload = { selectedIds: Array.from(next) };
|
|
21671
|
-
eventBus.emit(`UI:${selectionEvent}`, payload);
|
|
21672
|
-
}
|
|
21673
|
-
return next;
|
|
21674
|
-
});
|
|
21675
|
-
}, [selectionEvent, eventBus]);
|
|
21676
|
-
const toggleAll = useCallback(() => {
|
|
21677
|
-
setSelectedIds((prev) => {
|
|
21678
|
-
const allIds2 = data.map((item, i) => item.id || String(i));
|
|
21679
|
-
const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
|
|
21680
|
-
const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
|
|
21681
|
-
if (selectionEvent) {
|
|
21682
|
-
const payload = { selectedIds: Array.from(next) };
|
|
21683
|
-
eventBus.emit(`UI:${selectionEvent}`, payload);
|
|
21684
|
-
}
|
|
21685
|
-
return next;
|
|
21686
|
-
});
|
|
21687
|
-
}, [data, selectionEvent, eventBus]);
|
|
21688
|
-
const titleField = fields.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fields[0];
|
|
21689
|
-
const badgeFields = fields.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
21690
|
-
const bodyFields = fields.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
|
|
21691
|
-
const primaryActions = itemActions?.filter((a) => a.variant !== "danger") ?? [];
|
|
21692
|
-
const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
|
|
21693
|
-
const handleActionClick = (action, itemData) => (e) => {
|
|
21694
|
-
e.stopPropagation();
|
|
21695
|
-
const payload = {
|
|
21696
|
-
id: itemData.id,
|
|
21697
|
-
row: itemData
|
|
21698
|
-
};
|
|
21699
|
-
eventBus.emit(`UI:${action.event}`, payload);
|
|
21700
|
-
};
|
|
21701
|
-
const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
|
|
21702
|
-
const colsClass = cols ? {
|
|
21703
|
-
1: "grid-cols-1",
|
|
21704
|
-
2: "sm:grid-cols-2",
|
|
21705
|
-
3: "sm:grid-cols-2 lg:grid-cols-3",
|
|
21706
|
-
4: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
|
|
21707
|
-
5: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5",
|
|
21708
|
-
6: "sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6"
|
|
21709
|
-
}[cols] : void 0;
|
|
21710
|
-
if (isLoading) {
|
|
21711
|
-
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
|
|
21712
|
-
}
|
|
21713
|
-
if (error) {
|
|
21714
|
-
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
21715
|
-
}
|
|
21716
|
-
if (data.length === 0) {
|
|
21717
|
-
return /* @__PURE__ */ jsx(Box, { className: "text-center py-12", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("empty.noItems") || "No items found" }) });
|
|
21718
|
-
}
|
|
21719
|
-
const hasRenderProp = typeof children === "function";
|
|
21720
|
-
const allIds = data.map((item, i) => item.id || String(i));
|
|
21721
|
-
const allSelected = allIds.length > 0 && allIds.every((id) => selectedIds.has(id));
|
|
21722
|
-
const someSelected = selectedIds.size > 0;
|
|
21723
|
-
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
21724
|
-
selectable && someSelected && /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "items-center px-2 py-2 bg-muted rounded-sm", children: [
|
|
21725
|
-
/* @__PURE__ */ jsx(
|
|
21726
|
-
"input",
|
|
21727
|
-
{
|
|
21728
|
-
type: "checkbox",
|
|
21729
|
-
checked: allSelected,
|
|
21730
|
-
onChange: toggleAll,
|
|
21731
|
-
className: "w-4 h-4 accent-primary",
|
|
21732
|
-
"aria-label": "Select all"
|
|
21733
|
-
}
|
|
21734
|
-
),
|
|
21735
|
-
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "font-semibold", children: [
|
|
21736
|
-
selectedIds.size,
|
|
21737
|
-
" ",
|
|
21738
|
-
t("common.selected") || "selected"
|
|
21739
|
-
] })
|
|
21740
|
-
] }),
|
|
21741
|
-
/* @__PURE__ */ jsx(
|
|
21742
|
-
Box,
|
|
21743
|
-
{
|
|
21744
|
-
className: cn("grid", gapStyles6[gap], colsClass, className),
|
|
21745
|
-
style: gridTemplateColumns ? { gridTemplateColumns } : void 0,
|
|
21746
|
-
children: data.map((item, index) => {
|
|
21747
|
-
const itemData = item;
|
|
21748
|
-
const id = itemData.id || String(index);
|
|
21749
|
-
const isSelected = selectedIds.has(id);
|
|
21750
|
-
if (hasRenderProp) {
|
|
21751
|
-
return /* @__PURE__ */ jsx(
|
|
21752
|
-
Box,
|
|
21753
|
-
{
|
|
21754
|
-
"data-entity-row": true,
|
|
21755
|
-
"data-entity-id": id,
|
|
21756
|
-
className: cn(
|
|
21757
|
-
"bg-card rounded-lg",
|
|
21758
|
-
"border border-border",
|
|
21759
|
-
"shadow-sm hover:shadow-lg",
|
|
21760
|
-
"hover:border-primary transition-all",
|
|
21761
|
-
"p-4",
|
|
21762
|
-
isSelected && "ring-2 ring-primary border-primary"
|
|
21763
|
-
),
|
|
21764
|
-
children: children(itemData, index)
|
|
21765
|
-
},
|
|
21766
|
-
id
|
|
21767
|
-
);
|
|
21768
|
-
}
|
|
21769
|
-
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
21770
|
-
return /* @__PURE__ */ jsxs(
|
|
21771
|
-
Box,
|
|
21772
|
-
{
|
|
21773
|
-
"data-entity-row": true,
|
|
21774
|
-
"data-entity-id": id,
|
|
21775
|
-
className: cn(
|
|
21776
|
-
"bg-card rounded-lg",
|
|
21777
|
-
"border border-border",
|
|
21778
|
-
"shadow-sm hover:shadow-lg",
|
|
21779
|
-
"hover:border-primary transition-all",
|
|
21780
|
-
"flex flex-col",
|
|
21781
|
-
isSelected && "ring-2 ring-primary border-primary"
|
|
21782
|
-
),
|
|
21783
|
-
children: [
|
|
21784
|
-
imageField && (() => {
|
|
21785
|
-
const imgUrl = getNestedValue(itemData, imageField);
|
|
21786
|
-
if (!imgUrl || typeof imgUrl !== "string") return null;
|
|
21787
|
-
return /* @__PURE__ */ jsx(Box, { className: "w-full aspect-video overflow-hidden rounded-t-lg", children: /* @__PURE__ */ jsx(
|
|
21788
|
-
"img",
|
|
21789
|
-
{
|
|
21790
|
-
src: imgUrl,
|
|
21791
|
-
alt: titleValue !== void 0 ? String(titleValue) : "",
|
|
21792
|
-
className: "w-full h-full object-cover",
|
|
21793
|
-
loading: "lazy"
|
|
21794
|
-
}
|
|
21795
|
-
) });
|
|
21796
|
-
})(),
|
|
21797
|
-
/* @__PURE__ */ jsx(Box, { className: "p-4 pb-0", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
|
|
21798
|
-
selectable && /* @__PURE__ */ jsx(
|
|
21799
|
-
"input",
|
|
21800
|
-
{
|
|
21801
|
-
type: "checkbox",
|
|
21802
|
-
checked: isSelected,
|
|
21803
|
-
onChange: () => toggleSelection(id),
|
|
21804
|
-
onClick: (e) => e.stopPropagation(),
|
|
21805
|
-
className: "w-4 h-4 mt-1 flex-shrink-0 accent-primary",
|
|
21806
|
-
"aria-label": `Select ${titleValue !== void 0 ? String(titleValue) : "item"}`
|
|
21807
|
-
}
|
|
21808
|
-
),
|
|
21809
|
-
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
|
|
21810
|
-
titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21811
|
-
titleField?.icon && /* @__PURE__ */ jsx(Icon, { name: titleField.icon, size: "sm", className: "text-primary flex-shrink-0" }),
|
|
21812
|
-
/* @__PURE__ */ jsx(
|
|
21813
|
-
Typography,
|
|
21814
|
-
{
|
|
21815
|
-
variant: titleField?.variant === "h3" ? "h3" : "h4",
|
|
21816
|
-
className: "font-semibold truncate",
|
|
21817
|
-
children: String(titleValue)
|
|
21818
|
-
}
|
|
21819
|
-
)
|
|
21820
|
-
] }),
|
|
21821
|
-
badgeFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: badgeFields.map((field) => {
|
|
21822
|
-
const val = getNestedValue(itemData, field.name);
|
|
21823
|
-
if (val === void 0 || val === null) return null;
|
|
21824
|
-
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21825
|
-
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs" }),
|
|
21826
|
-
/* @__PURE__ */ jsx(Badge, { variant: statusVariant2(String(val)), children: String(val) })
|
|
21827
|
-
] }, field.name);
|
|
21828
|
-
}) })
|
|
21829
|
-
] }),
|
|
21830
|
-
dangerActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
21831
|
-
Button,
|
|
21832
|
-
{
|
|
21833
|
-
variant: "ghost",
|
|
21834
|
-
size: "sm",
|
|
21835
|
-
onClick: handleActionClick(action, itemData),
|
|
21836
|
-
"data-testid": `action-${action.event}`,
|
|
21837
|
-
className: "text-error hover:bg-error/10 px-2",
|
|
21838
|
-
children: [
|
|
21839
|
-
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs" }),
|
|
21840
|
-
action.label
|
|
21841
|
-
]
|
|
21842
|
-
},
|
|
21843
|
-
idx
|
|
21844
|
-
)) })
|
|
21845
|
-
] }) }),
|
|
21846
|
-
bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: bodyFields.map((field) => {
|
|
21847
|
-
const value = getNestedValue(itemData, field.name);
|
|
21848
|
-
if (value === void 0 || value === null || value === "") return null;
|
|
21849
|
-
if (field.format === "boolean") {
|
|
21850
|
-
return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
|
|
21851
|
-
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21852
|
-
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
21853
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
|
|
21854
|
-
] }),
|
|
21855
|
-
/* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
|
|
21856
|
-
] }, field.name);
|
|
21857
|
-
}
|
|
21858
|
-
return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
|
|
21859
|
-
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
21860
|
-
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
21861
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
|
|
21862
|
-
] }),
|
|
21863
|
-
/* @__PURE__ */ jsx(
|
|
21864
|
-
Typography,
|
|
21865
|
-
{
|
|
21866
|
-
variant: field.variant === "caption" ? "caption" : "small",
|
|
21867
|
-
className: "text-right truncate max-w-[60%]",
|
|
21868
|
-
children: formatValue(value, field.format)
|
|
21869
|
-
}
|
|
21870
|
-
)
|
|
21871
|
-
] }, field.name);
|
|
21872
|
-
}) }) }),
|
|
21873
|
-
primaryActions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsx(HStack, { gap: "sm", className: "justify-end", children: primaryActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
21874
|
-
Button,
|
|
21875
|
-
{
|
|
21876
|
-
variant: action.variant === "primary" ? "primary" : "ghost",
|
|
21877
|
-
size: "sm",
|
|
21878
|
-
onClick: handleActionClick(action, itemData),
|
|
21879
|
-
"data-testid": `action-${action.event}`,
|
|
21880
|
-
children: [
|
|
21881
|
-
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
21882
|
-
action.label
|
|
21883
|
-
]
|
|
21884
|
-
},
|
|
21885
|
-
idx
|
|
21886
|
-
)) }) })
|
|
21887
|
-
]
|
|
21888
|
-
},
|
|
21889
|
-
id
|
|
21890
|
-
);
|
|
21891
|
-
})
|
|
21892
|
-
}
|
|
21893
|
-
),
|
|
21894
|
-
hasMoreLocal && /* @__PURE__ */ jsx(Box, { className: "flex justify-center py-3", children: /* @__PURE__ */ jsxs(
|
|
21895
|
-
Button,
|
|
21896
|
-
{
|
|
21897
|
-
variant: "ghost",
|
|
21898
|
-
size: "sm",
|
|
21899
|
-
onClick: () => setVisibleCount((prev) => prev + (pageSize || 5)),
|
|
21900
|
-
children: [
|
|
21901
|
-
/* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
21902
|
-
t("common.showMore"),
|
|
21903
|
-
" (",
|
|
21904
|
-
allData.length - visibleCount,
|
|
21905
|
-
" remaining)"
|
|
21906
|
-
]
|
|
21907
|
-
}
|
|
21908
|
-
) }),
|
|
21909
|
-
infiniteScroll && loadMoreEvent && /* @__PURE__ */ jsx(
|
|
21910
|
-
InfiniteScrollSentinel,
|
|
21911
|
-
{
|
|
21912
|
-
loadMoreEvent,
|
|
21913
|
-
isLoading,
|
|
21914
|
-
hasMore
|
|
21915
|
-
}
|
|
21916
|
-
)
|
|
21917
|
-
] });
|
|
21918
|
-
};
|
|
21919
21919
|
DataGrid.displayName = "DataGrid";
|
|
21920
21920
|
}
|
|
21921
21921
|
});
|
|
@@ -21963,318 +21963,317 @@ function groupData(items, field) {
|
|
|
21963
21963
|
}
|
|
21964
21964
|
return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
|
|
21965
21965
|
}
|
|
21966
|
-
|
|
21967
|
-
|
|
21968
|
-
|
|
21969
|
-
|
|
21970
|
-
|
|
21971
|
-
|
|
21972
|
-
|
|
21973
|
-
|
|
21974
|
-
|
|
21975
|
-
|
|
21976
|
-
|
|
21977
|
-
|
|
21978
|
-
|
|
21979
|
-
|
|
21980
|
-
|
|
21981
|
-
|
|
21982
|
-
|
|
21983
|
-
|
|
21984
|
-
|
|
21985
|
-
|
|
21986
|
-
|
|
21987
|
-
|
|
21988
|
-
|
|
21989
|
-
|
|
21990
|
-
|
|
21991
|
-
|
|
21992
|
-
|
|
21993
|
-
|
|
21994
|
-
|
|
21995
|
-
|
|
21996
|
-
|
|
21997
|
-
|
|
21998
|
-
|
|
21999
|
-
|
|
22000
|
-
|
|
22001
|
-
|
|
22002
|
-
|
|
22003
|
-
|
|
22004
|
-
|
|
22005
|
-
|
|
22006
|
-
|
|
22007
|
-
|
|
22008
|
-
|
|
22009
|
-
|
|
22010
|
-
|
|
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
|
-
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React126__default.Fragment, { children: [
|
|
22056
|
-
group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
|
|
22057
|
-
group.items.map((itemData, index) => {
|
|
22058
|
-
const id = itemData.id || `${gi}-${index}`;
|
|
22059
|
-
const sender = senderField ? String(getNestedValue(itemData, senderField) ?? "") : "";
|
|
22060
|
-
const isSent = Boolean(currentUser && sender === currentUser);
|
|
22061
|
-
const content = getNestedValue(itemData, contentField);
|
|
22062
|
-
const timestampField = fields.find((f3) => f3.format === "date");
|
|
22063
|
-
const timestamp = timestampField ? getNestedValue(itemData, timestampField.name) : null;
|
|
22064
|
-
return /* @__PURE__ */ jsx(
|
|
22065
|
-
Box,
|
|
22066
|
-
{
|
|
22067
|
-
className: cn(
|
|
22068
|
-
"flex px-4",
|
|
22069
|
-
isSent ? "justify-end" : "justify-start"
|
|
22070
|
-
),
|
|
22071
|
-
children: /* @__PURE__ */ jsxs(
|
|
22072
|
-
Box,
|
|
22073
|
-
{
|
|
22074
|
-
className: cn(
|
|
22075
|
-
"max-w-[75%] px-4 py-2",
|
|
22076
|
-
isSent ? "bg-primary text-primary-foreground rounded-2xl rounded-br-sm" : "bg-muted text-foreground rounded-2xl rounded-bl-sm"
|
|
22077
|
-
),
|
|
22078
|
-
children: [
|
|
22079
|
-
!isSent && senderField && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-semibold mb-0.5", children: sender }),
|
|
22080
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: content !== void 0 && content !== null ? String(content) : "" }),
|
|
22081
|
-
timestamp != null ? /* @__PURE__ */ jsx(
|
|
22082
|
-
Typography,
|
|
22083
|
-
{
|
|
22084
|
-
variant: "caption",
|
|
22085
|
-
className: cn(
|
|
22086
|
-
"mt-1 text-[0.65rem]",
|
|
22087
|
-
isSent ? "opacity-70" : "text-muted-foreground"
|
|
22088
|
-
),
|
|
22089
|
-
children: formatDate3(timestamp)
|
|
22090
|
-
}
|
|
22091
|
-
) : null
|
|
22092
|
-
]
|
|
22093
|
-
}
|
|
22094
|
-
)
|
|
22095
|
-
},
|
|
22096
|
-
id
|
|
22097
|
-
);
|
|
22098
|
-
})
|
|
22099
|
-
] }, gi)) });
|
|
22100
|
-
}
|
|
22101
|
-
const hasRenderProp = typeof children === "function";
|
|
22102
|
-
const items = data.map((item) => item);
|
|
22103
|
-
const groups = groupBy ? groupData(items, groupBy) : [{ label: "", items }];
|
|
22104
|
-
const renderItem = (itemData, index, isLast) => {
|
|
22105
|
-
if (hasRenderProp) {
|
|
22106
|
-
const id2 = itemData.id || String(index);
|
|
22107
|
-
return /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, children: [
|
|
22108
|
-
/* @__PURE__ */ jsxs(
|
|
21966
|
+
function DataList({
|
|
21967
|
+
entity,
|
|
21968
|
+
fields: fieldsProp,
|
|
21969
|
+
columns: columnsProp,
|
|
21970
|
+
itemActions,
|
|
21971
|
+
gap = "none",
|
|
21972
|
+
variant = "default",
|
|
21973
|
+
groupBy,
|
|
21974
|
+
senderField,
|
|
21975
|
+
currentUser,
|
|
21976
|
+
className,
|
|
21977
|
+
isLoading = false,
|
|
21978
|
+
error = null,
|
|
21979
|
+
// Gesture props: reorderable, swipeLeftEvent, swipeRightEvent, longPressEvent
|
|
21980
|
+
// are consumed by the compiler to wrap items in SwipeableRow/SortableList.
|
|
21981
|
+
// DataList destructures them here to prevent DOM passthrough.
|
|
21982
|
+
reorderable: _reorderable,
|
|
21983
|
+
reorderEvent: _reorderEvent,
|
|
21984
|
+
swipeLeftEvent: _swipeLeftEvent,
|
|
21985
|
+
swipeLeftActions: _swipeLeftActions,
|
|
21986
|
+
swipeRightEvent: _swipeRightEvent,
|
|
21987
|
+
swipeRightActions: _swipeRightActions,
|
|
21988
|
+
longPressEvent: _longPressEvent,
|
|
21989
|
+
infiniteScroll,
|
|
21990
|
+
loadMoreEvent,
|
|
21991
|
+
hasMore,
|
|
21992
|
+
children,
|
|
21993
|
+
pageSize = 5
|
|
21994
|
+
}) {
|
|
21995
|
+
const eventBus = useEventBus();
|
|
21996
|
+
const { t } = useTranslate();
|
|
21997
|
+
const [visibleCount, setVisibleCount] = React126__default.useState(pageSize || Infinity);
|
|
21998
|
+
const fields = fieldsProp ?? columnsProp ?? [];
|
|
21999
|
+
const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
22000
|
+
const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
|
|
22001
|
+
const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
|
|
22002
|
+
const titleField = fields.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fields[0];
|
|
22003
|
+
const badgeFields = fields.filter((f3) => f3.variant === "badge" && f3 !== titleField);
|
|
22004
|
+
const progressFields = fields.filter((f3) => f3.variant === "progress");
|
|
22005
|
+
const bodyFields = fields.filter(
|
|
22006
|
+
(f3) => f3 !== titleField && !badgeFields.includes(f3) && !progressFields.includes(f3)
|
|
22007
|
+
);
|
|
22008
|
+
const handleActionClick = (action, itemData) => (e) => {
|
|
22009
|
+
e.stopPropagation();
|
|
22010
|
+
const payload = {
|
|
22011
|
+
id: itemData.id,
|
|
22012
|
+
row: itemData
|
|
22013
|
+
};
|
|
22014
|
+
eventBus.emit(`UI:${action.event}`, payload);
|
|
22015
|
+
};
|
|
22016
|
+
if (isLoading) {
|
|
22017
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
|
|
22018
|
+
}
|
|
22019
|
+
if (error) {
|
|
22020
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
22021
|
+
}
|
|
22022
|
+
if (data.length === 0) {
|
|
22023
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-12", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("empty.noItems") || "No items found" }) });
|
|
22024
|
+
}
|
|
22025
|
+
const gapClass = {
|
|
22026
|
+
none: "",
|
|
22027
|
+
sm: "gap-1",
|
|
22028
|
+
md: "gap-2",
|
|
22029
|
+
lg: "gap-4"
|
|
22030
|
+
}[gap];
|
|
22031
|
+
const isCard = variant === "card";
|
|
22032
|
+
const isCompact = variant === "compact";
|
|
22033
|
+
const isMessage = variant === "message";
|
|
22034
|
+
if (isMessage) {
|
|
22035
|
+
const items2 = data.map((item) => item);
|
|
22036
|
+
const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
|
|
22037
|
+
const contentField = titleField?.name ?? fields[0]?.name ?? "";
|
|
22038
|
+
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React126__default.Fragment, { children: [
|
|
22039
|
+
group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
|
|
22040
|
+
group.items.map((itemData, index) => {
|
|
22041
|
+
const id = itemData.id || `${gi}-${index}`;
|
|
22042
|
+
const sender = senderField ? String(getNestedValue(itemData, senderField) ?? "") : "";
|
|
22043
|
+
const isSent = Boolean(currentUser && sender === currentUser);
|
|
22044
|
+
const content = getNestedValue(itemData, contentField);
|
|
22045
|
+
const timestampField = fields.find((f3) => f3.format === "date");
|
|
22046
|
+
const timestamp = timestampField ? getNestedValue(itemData, timestampField.name) : null;
|
|
22047
|
+
return /* @__PURE__ */ jsx(
|
|
22048
|
+
Box,
|
|
22049
|
+
{
|
|
22050
|
+
className: cn(
|
|
22051
|
+
"flex px-4",
|
|
22052
|
+
isSent ? "justify-end" : "justify-start"
|
|
22053
|
+
),
|
|
22054
|
+
children: /* @__PURE__ */ jsxs(
|
|
22109
22055
|
Box,
|
|
22110
22056
|
{
|
|
22111
22057
|
className: cn(
|
|
22112
|
-
"
|
|
22113
|
-
|
|
22114
|
-
"hover:bg-muted/80",
|
|
22115
|
-
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
22058
|
+
"max-w-[75%] px-4 py-2",
|
|
22059
|
+
isSent ? "bg-primary text-primary-foreground rounded-2xl rounded-br-sm" : "bg-muted text-foreground rounded-2xl rounded-bl-sm"
|
|
22116
22060
|
),
|
|
22117
22061
|
children: [
|
|
22118
|
-
/* @__PURE__ */ jsx(
|
|
22119
|
-
|
|
22120
|
-
|
|
22062
|
+
!isSent && senderField && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-semibold mb-0.5", children: sender }),
|
|
22063
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: content !== void 0 && content !== null ? String(content) : "" }),
|
|
22064
|
+
timestamp != null ? /* @__PURE__ */ jsx(
|
|
22065
|
+
Typography,
|
|
22121
22066
|
{
|
|
22122
|
-
|
|
22123
|
-
className:
|
|
22124
|
-
|
|
22125
|
-
|
|
22126
|
-
|
|
22127
|
-
|
|
22128
|
-
size: "sm",
|
|
22129
|
-
onClick: handleActionClick(action, itemData),
|
|
22130
|
-
"data-testid": `action-${action.event}`,
|
|
22131
|
-
className: cn(
|
|
22132
|
-
action.variant === "danger" && "text-error hover:bg-error/10"
|
|
22133
|
-
),
|
|
22134
|
-
children: [
|
|
22135
|
-
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
22136
|
-
action.label
|
|
22137
|
-
]
|
|
22138
|
-
},
|
|
22139
|
-
idx
|
|
22140
|
-
))
|
|
22067
|
+
variant: "caption",
|
|
22068
|
+
className: cn(
|
|
22069
|
+
"mt-1 text-[0.65rem]",
|
|
22070
|
+
isSent ? "opacity-70" : "text-muted-foreground"
|
|
22071
|
+
),
|
|
22072
|
+
children: formatDate3(timestamp)
|
|
22141
22073
|
}
|
|
22142
|
-
)
|
|
22074
|
+
) : null
|
|
22143
22075
|
]
|
|
22144
22076
|
}
|
|
22077
|
+
)
|
|
22078
|
+
},
|
|
22079
|
+
id
|
|
22080
|
+
);
|
|
22081
|
+
})
|
|
22082
|
+
] }, gi)) });
|
|
22083
|
+
}
|
|
22084
|
+
const hasRenderProp = typeof children === "function";
|
|
22085
|
+
const items = data.map((item) => item);
|
|
22086
|
+
const groups = groupBy ? groupData(items, groupBy) : [{ label: "", items }];
|
|
22087
|
+
const renderItem = (itemData, index, isLast) => {
|
|
22088
|
+
if (hasRenderProp) {
|
|
22089
|
+
const id2 = itemData.id || String(index);
|
|
22090
|
+
return /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, children: [
|
|
22091
|
+
/* @__PURE__ */ jsxs(
|
|
22092
|
+
Box,
|
|
22093
|
+
{
|
|
22094
|
+
className: cn(
|
|
22095
|
+
"group flex items-center gap-4 transition-all duration-200",
|
|
22096
|
+
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
22097
|
+
"hover:bg-muted/80",
|
|
22098
|
+
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
22145
22099
|
),
|
|
22146
|
-
|
|
22147
|
-
|
|
22148
|
-
|
|
22149
|
-
|
|
22150
|
-
|
|
22151
|
-
|
|
22152
|
-
|
|
22153
|
-
|
|
22154
|
-
|
|
22155
|
-
|
|
22156
|
-
|
|
22157
|
-
|
|
22158
|
-
|
|
22159
|
-
|
|
22160
|
-
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22165
|
-
|
|
22166
|
-
|
|
22167
|
-
|
|
22168
|
-
|
|
22169
|
-
|
|
22170
|
-
|
|
22171
|
-
|
|
22172
|
-
|
|
22173
|
-
|
|
22174
|
-
|
|
22175
|
-
|
|
22176
|
-
|
|
22177
|
-
|
|
22178
|
-
|
|
22179
|
-
|
|
22180
|
-
|
|
22181
|
-
|
|
22182
|
-
if (val === void 0 || val === null) return null;
|
|
22183
|
-
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
|
|
22184
|
-
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs" }),
|
|
22185
|
-
/* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: String(val) })
|
|
22186
|
-
] }, field.name);
|
|
22187
|
-
})
|
|
22188
|
-
] }),
|
|
22189
|
-
bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsx(HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
|
|
22190
|
-
const value = getNestedValue(itemData, field.name);
|
|
22191
|
-
if (value === void 0 || value === null || value === "") return null;
|
|
22192
|
-
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
22193
|
-
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
22194
|
-
/* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "secondary", children: [
|
|
22195
|
-
field.label ?? fieldLabel3(field.name),
|
|
22196
|
-
":"
|
|
22197
|
-
] }),
|
|
22198
|
-
/* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue2(value, field.format) })
|
|
22199
|
-
] }, field.name);
|
|
22200
|
-
}) }),
|
|
22201
|
-
progressFields.map((field) => {
|
|
22202
|
-
const value = getNestedValue(itemData, field.name);
|
|
22203
|
-
if (typeof value !== "number") return null;
|
|
22204
|
-
return /* @__PURE__ */ jsxs(Box, { className: "mt-2 max-w-xs", children: [
|
|
22205
|
-
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center mb-1", children: [
|
|
22206
|
-
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
22207
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel3(field.name) })
|
|
22208
|
-
] }),
|
|
22209
|
-
/* @__PURE__ */ jsx(ProgressBar, { value, max: 100 })
|
|
22210
|
-
] }, field.name);
|
|
22211
|
-
})
|
|
22212
|
-
] }),
|
|
22213
|
-
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: itemActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
22214
|
-
Button,
|
|
22215
|
-
{
|
|
22216
|
-
variant: action.variant ?? "ghost",
|
|
22217
|
-
size: "sm",
|
|
22218
|
-
onClick: handleActionClick(action, itemData),
|
|
22219
|
-
"data-testid": `action-${action.event}`,
|
|
22220
|
-
className: cn(
|
|
22221
|
-
action.variant === "danger" && "text-error hover:bg-error/10"
|
|
22222
|
-
),
|
|
22223
|
-
children: [
|
|
22224
|
-
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
22225
|
-
action.label
|
|
22226
|
-
]
|
|
22227
|
-
},
|
|
22228
|
-
idx
|
|
22229
|
-
)) })
|
|
22230
|
-
]
|
|
22231
|
-
}
|
|
22232
|
-
),
|
|
22233
|
-
isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-border/40" })
|
|
22234
|
-
] }, id);
|
|
22235
|
-
};
|
|
22236
|
-
return /* @__PURE__ */ jsxs(
|
|
22100
|
+
children: [
|
|
22101
|
+
/* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
|
|
22102
|
+
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(
|
|
22103
|
+
HStack,
|
|
22104
|
+
{
|
|
22105
|
+
gap: "xs",
|
|
22106
|
+
className: "flex-shrink-0",
|
|
22107
|
+
children: itemActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
22108
|
+
Button,
|
|
22109
|
+
{
|
|
22110
|
+
variant: action.variant ?? "ghost",
|
|
22111
|
+
size: "sm",
|
|
22112
|
+
onClick: handleActionClick(action, itemData),
|
|
22113
|
+
"data-testid": `action-${action.event}`,
|
|
22114
|
+
className: cn(
|
|
22115
|
+
action.variant === "danger" && "text-error hover:bg-error/10"
|
|
22116
|
+
),
|
|
22117
|
+
children: [
|
|
22118
|
+
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
22119
|
+
action.label
|
|
22120
|
+
]
|
|
22121
|
+
},
|
|
22122
|
+
idx
|
|
22123
|
+
))
|
|
22124
|
+
}
|
|
22125
|
+
)
|
|
22126
|
+
]
|
|
22127
|
+
}
|
|
22128
|
+
),
|
|
22129
|
+
isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-border/40" })
|
|
22130
|
+
] }, id2);
|
|
22131
|
+
}
|
|
22132
|
+
const id = itemData.id || String(index);
|
|
22133
|
+
const titleValue = getNestedValue(itemData, titleField?.name ?? "");
|
|
22134
|
+
return /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id, children: [
|
|
22135
|
+
/* @__PURE__ */ jsxs(
|
|
22237
22136
|
Box,
|
|
22238
22137
|
{
|
|
22239
22138
|
className: cn(
|
|
22240
|
-
|
|
22241
|
-
|
|
22242
|
-
|
|
22139
|
+
"group flex items-center gap-4 transition-all duration-200",
|
|
22140
|
+
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
22141
|
+
"hover:bg-muted/80",
|
|
22142
|
+
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
22243
22143
|
),
|
|
22244
22144
|
children: [
|
|
22245
|
-
|
|
22246
|
-
|
|
22247
|
-
|
|
22248
|
-
|
|
22249
|
-
|
|
22250
|
-
|
|
22251
|
-
|
|
22145
|
+
/* @__PURE__ */ jsxs(Box, { className: "flex-1 min-w-0", children: [
|
|
22146
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "items-center", children: [
|
|
22147
|
+
titleField?.icon && /* @__PURE__ */ jsx(
|
|
22148
|
+
Icon,
|
|
22149
|
+
{
|
|
22150
|
+
name: titleField.icon,
|
|
22151
|
+
size: isCompact ? "xs" : "sm",
|
|
22152
|
+
className: "text-primary flex-shrink-0"
|
|
22153
|
+
}
|
|
22154
|
+
),
|
|
22155
|
+
titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsx(
|
|
22156
|
+
Typography,
|
|
22157
|
+
{
|
|
22158
|
+
variant: titleField?.variant === "h3" ? "h3" : "h4",
|
|
22159
|
+
className: cn("font-semibold truncate flex-1", isCompact && "text-sm"),
|
|
22160
|
+
children: String(titleValue)
|
|
22161
|
+
}
|
|
22162
|
+
),
|
|
22163
|
+
badgeFields.map((field) => {
|
|
22164
|
+
const val = getNestedValue(itemData, field.name);
|
|
22165
|
+
if (val === void 0 || val === null) return null;
|
|
22166
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
|
|
22167
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs" }),
|
|
22168
|
+
/* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: String(val) })
|
|
22169
|
+
] }, field.name);
|
|
22170
|
+
})
|
|
22171
|
+
] }),
|
|
22172
|
+
bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsx(HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
|
|
22173
|
+
const value = getNestedValue(itemData, field.name);
|
|
22174
|
+
if (value === void 0 || value === null || value === "") return null;
|
|
22175
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
22176
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
22177
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "secondary", children: [
|
|
22178
|
+
field.label ?? fieldLabel3(field.name),
|
|
22179
|
+
":"
|
|
22180
|
+
] }),
|
|
22181
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue2(value, field.format) })
|
|
22182
|
+
] }, field.name);
|
|
22183
|
+
}) }),
|
|
22184
|
+
progressFields.map((field) => {
|
|
22185
|
+
const value = getNestedValue(itemData, field.name);
|
|
22186
|
+
if (typeof value !== "number") return null;
|
|
22187
|
+
return /* @__PURE__ */ jsxs(Box, { className: "mt-2 max-w-xs", children: [
|
|
22188
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center mb-1", children: [
|
|
22189
|
+
field.icon && /* @__PURE__ */ jsx(Icon, { name: field.icon, size: "xs", className: "text-muted-foreground" }),
|
|
22190
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel3(field.name) })
|
|
22191
|
+
] }),
|
|
22192
|
+
/* @__PURE__ */ jsx(ProgressBar, { value, max: 100 })
|
|
22193
|
+
] }, field.name);
|
|
22194
|
+
})
|
|
22195
|
+
] }),
|
|
22196
|
+
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: itemActions.map((action, idx) => /* @__PURE__ */ jsxs(
|
|
22252
22197
|
Button,
|
|
22253
22198
|
{
|
|
22254
|
-
variant: "ghost",
|
|
22199
|
+
variant: action.variant ?? "ghost",
|
|
22255
22200
|
size: "sm",
|
|
22256
|
-
onClick: (
|
|
22201
|
+
onClick: handleActionClick(action, itemData),
|
|
22202
|
+
"data-testid": `action-${action.event}`,
|
|
22203
|
+
className: cn(
|
|
22204
|
+
action.variant === "danger" && "text-error hover:bg-error/10"
|
|
22205
|
+
),
|
|
22257
22206
|
children: [
|
|
22258
|
-
/* @__PURE__ */ jsx(Icon, { name:
|
|
22259
|
-
|
|
22260
|
-
" (",
|
|
22261
|
-
allData.length - visibleCount,
|
|
22262
|
-
" remaining)"
|
|
22207
|
+
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
22208
|
+
action.label
|
|
22263
22209
|
]
|
|
22264
|
-
}
|
|
22265
|
-
|
|
22266
|
-
|
|
22267
|
-
InfiniteScrollSentinel,
|
|
22268
|
-
{
|
|
22269
|
-
loadMoreEvent,
|
|
22270
|
-
isLoading,
|
|
22271
|
-
hasMore
|
|
22272
|
-
}
|
|
22273
|
-
)
|
|
22210
|
+
},
|
|
22211
|
+
idx
|
|
22212
|
+
)) })
|
|
22274
22213
|
]
|
|
22275
22214
|
}
|
|
22276
|
-
)
|
|
22277
|
-
|
|
22215
|
+
),
|
|
22216
|
+
isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-border/40" })
|
|
22217
|
+
] }, id);
|
|
22218
|
+
};
|
|
22219
|
+
return /* @__PURE__ */ jsxs(
|
|
22220
|
+
Box,
|
|
22221
|
+
{
|
|
22222
|
+
className: cn(
|
|
22223
|
+
isCard && "bg-card rounded-xl border border-border shadow-lg overflow-hidden",
|
|
22224
|
+
!isCard && gapClass,
|
|
22225
|
+
className
|
|
22226
|
+
),
|
|
22227
|
+
children: [
|
|
22228
|
+
groups.map((group, gi) => /* @__PURE__ */ jsxs(React126__default.Fragment, { children: [
|
|
22229
|
+
group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
|
|
22230
|
+
group.items.map(
|
|
22231
|
+
(itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
|
|
22232
|
+
)
|
|
22233
|
+
] }, gi)),
|
|
22234
|
+
hasMoreLocal && /* @__PURE__ */ jsx(Box, { className: "flex justify-center py-3", children: /* @__PURE__ */ jsxs(
|
|
22235
|
+
Button,
|
|
22236
|
+
{
|
|
22237
|
+
variant: "ghost",
|
|
22238
|
+
size: "sm",
|
|
22239
|
+
onClick: () => setVisibleCount((prev) => prev + (pageSize || 5)),
|
|
22240
|
+
children: [
|
|
22241
|
+
/* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
22242
|
+
t("common.showMore"),
|
|
22243
|
+
" (",
|
|
22244
|
+
allData.length - visibleCount,
|
|
22245
|
+
" remaining)"
|
|
22246
|
+
]
|
|
22247
|
+
}
|
|
22248
|
+
) }),
|
|
22249
|
+
infiniteScroll && loadMoreEvent && /* @__PURE__ */ jsx(
|
|
22250
|
+
InfiniteScrollSentinel,
|
|
22251
|
+
{
|
|
22252
|
+
loadMoreEvent,
|
|
22253
|
+
isLoading,
|
|
22254
|
+
hasMore
|
|
22255
|
+
}
|
|
22256
|
+
)
|
|
22257
|
+
]
|
|
22258
|
+
}
|
|
22259
|
+
);
|
|
22260
|
+
}
|
|
22261
|
+
var init_DataList = __esm({
|
|
22262
|
+
"components/molecules/DataList.tsx"() {
|
|
22263
|
+
"use client";
|
|
22264
|
+
init_cn();
|
|
22265
|
+
init_getNestedValue();
|
|
22266
|
+
init_useEventBus();
|
|
22267
|
+
init_useTranslate();
|
|
22268
|
+
init_Box();
|
|
22269
|
+
init_Stack();
|
|
22270
|
+
init_Typography();
|
|
22271
|
+
init_Badge();
|
|
22272
|
+
init_Button();
|
|
22273
|
+
init_Icon();
|
|
22274
|
+
init_ProgressBar();
|
|
22275
|
+
init_Divider();
|
|
22276
|
+
init_InfiniteScrollSentinel();
|
|
22278
22277
|
DataList.displayName = "DataList";
|
|
22279
22278
|
}
|
|
22280
22279
|
});
|
|
@@ -23475,7 +23474,10 @@ var init_WizardProgress = __esm({
|
|
|
23475
23474
|
stepClickEvent
|
|
23476
23475
|
}) => {
|
|
23477
23476
|
const eventBus = useEventBus();
|
|
23478
|
-
const
|
|
23477
|
+
const normalizedSteps = steps.map(
|
|
23478
|
+
(s, i) => typeof s === "string" ? { id: `step-${i}`, title: s } : s
|
|
23479
|
+
);
|
|
23480
|
+
const totalSteps = normalizedSteps.length;
|
|
23479
23481
|
const handleStepClick = (index) => {
|
|
23480
23482
|
const isCompleted = index < currentStep;
|
|
23481
23483
|
if (isCompleted && allowNavigation) {
|
|
@@ -23492,7 +23494,7 @@ var init_WizardProgress = __esm({
|
|
|
23492
23494
|
compact ? "px-4 py-2" : "px-6 py-4",
|
|
23493
23495
|
className
|
|
23494
23496
|
),
|
|
23495
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children:
|
|
23497
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
|
|
23496
23498
|
const isActive = index === currentStep;
|
|
23497
23499
|
const isCompleted = index < currentStep;
|
|
23498
23500
|
return /* @__PURE__ */ jsxs(React126__default.Fragment, { children: [
|
|
@@ -50986,18 +50988,12 @@ init_useUISlots();
|
|
|
50986
50988
|
|
|
50987
50989
|
// hooks/useUIEvents.ts
|
|
50988
50990
|
init_useEventBus();
|
|
50989
|
-
createContext(null);
|
|
50990
50991
|
|
|
50991
50992
|
// hooks/index.ts
|
|
50992
50993
|
init_useQuerySingleton();
|
|
50993
50994
|
|
|
50994
|
-
// lib/api-client.ts
|
|
50995
|
-
typeof process !== "undefined" && process.env?.VITE_API_URL ? process.env.VITE_API_URL : "/api";
|
|
50996
|
-
|
|
50997
50995
|
// hooks/index.ts
|
|
50998
50996
|
init_useTranslate();
|
|
50999
|
-
|
|
51000
|
-
// hooks/index.ts
|
|
51001
50997
|
init_useAuthContext();
|
|
51002
50998
|
init_useSwipeGesture();
|
|
51003
50999
|
init_useLongPress();
|
|
@@ -51568,33 +51564,66 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
|
|
|
51568
51564
|
canHandleEvent
|
|
51569
51565
|
};
|
|
51570
51566
|
}
|
|
51567
|
+
var DEFAULT_SOURCE_KEY = "__default__";
|
|
51568
|
+
function slotEntriesInOrder(slot) {
|
|
51569
|
+
if (!slot) return [];
|
|
51570
|
+
const out = [];
|
|
51571
|
+
for (const [sourceKey, entry] of Object.entries(slot)) {
|
|
51572
|
+
if (entry.patterns.length > 0) {
|
|
51573
|
+
out.push({ sourceKey, entry });
|
|
51574
|
+
}
|
|
51575
|
+
}
|
|
51576
|
+
return out;
|
|
51577
|
+
}
|
|
51571
51578
|
var SlotsStateContext = createContext({});
|
|
51572
51579
|
var SlotsActionsContext = createContext(null);
|
|
51573
51580
|
function SlotsProvider({ children }) {
|
|
51574
51581
|
const [slots, setSlots] = useState({});
|
|
51575
51582
|
const setSlotPatterns = useCallback((slot, patterns, source) => {
|
|
51576
|
-
|
|
51577
|
-
|
|
51578
|
-
[slot]
|
|
51579
|
-
|
|
51583
|
+
const sourceKey = source?.trait ?? DEFAULT_SOURCE_KEY;
|
|
51584
|
+
setSlots((prev) => {
|
|
51585
|
+
const prevSlot = prev[slot] ?? {};
|
|
51586
|
+
return {
|
|
51587
|
+
...prev,
|
|
51588
|
+
[slot]: {
|
|
51589
|
+
...prevSlot,
|
|
51590
|
+
[sourceKey]: { patterns, source }
|
|
51591
|
+
}
|
|
51592
|
+
};
|
|
51593
|
+
});
|
|
51580
51594
|
}, []);
|
|
51581
51595
|
const clearSlot = useCallback((slot) => {
|
|
51582
51596
|
setSlots((prev) => {
|
|
51583
51597
|
const existing = prev[slot];
|
|
51584
|
-
if (existing && existing.
|
|
51598
|
+
if (existing && Object.keys(existing).length === 0) {
|
|
51585
51599
|
return prev;
|
|
51586
51600
|
}
|
|
51587
|
-
return { ...prev, [slot]: {
|
|
51601
|
+
return { ...prev, [slot]: {} };
|
|
51602
|
+
});
|
|
51603
|
+
}, []);
|
|
51604
|
+
const clearSlotForSource = useCallback((slot, sourceTrait) => {
|
|
51605
|
+
setSlots((prev) => {
|
|
51606
|
+
const existing = prev[slot];
|
|
51607
|
+
if (!existing || !(sourceTrait in existing)) return prev;
|
|
51608
|
+
const next = { ...existing };
|
|
51609
|
+
delete next[sourceTrait];
|
|
51610
|
+
return { ...prev, [slot]: next };
|
|
51588
51611
|
});
|
|
51589
51612
|
}, []);
|
|
51590
51613
|
const clearAllSlots = useCallback(() => {
|
|
51591
51614
|
setSlots({});
|
|
51592
51615
|
}, []);
|
|
51593
|
-
const actionsRef = useRef({
|
|
51594
|
-
|
|
51616
|
+
const actionsRef = useRef({
|
|
51617
|
+
setSlotPatterns,
|
|
51618
|
+
clearSlot,
|
|
51619
|
+
clearSlotForSource,
|
|
51620
|
+
clearAllSlots
|
|
51621
|
+
});
|
|
51622
|
+
actionsRef.current = { setSlotPatterns, clearSlot, clearSlotForSource, clearAllSlots };
|
|
51595
51623
|
const [stableActions] = useState(() => ({
|
|
51596
51624
|
setSlotPatterns: (...args) => actionsRef.current.setSlotPatterns(...args),
|
|
51597
51625
|
clearSlot: (...args) => actionsRef.current.clearSlot(...args),
|
|
51626
|
+
clearSlotForSource: (...args) => actionsRef.current.clearSlotForSource(...args),
|
|
51598
51627
|
clearAllSlots: () => actionsRef.current.clearAllSlots()
|
|
51599
51628
|
}));
|
|
51600
51629
|
return /* @__PURE__ */ jsx(SlotsActionsContext.Provider, { value: stableActions, children: /* @__PURE__ */ jsx(SlotsStateContext.Provider, { value: slots, children }) });
|
|
@@ -51830,34 +51859,60 @@ function SlotBridge() {
|
|
|
51830
51859
|
const { render, clear } = useUISlots();
|
|
51831
51860
|
useEffect(() => {
|
|
51832
51861
|
for (const [slotName, slotState] of Object.entries(slots)) {
|
|
51833
|
-
|
|
51862
|
+
const entries = slotEntriesInOrder(slotState);
|
|
51863
|
+
if (entries.length === 0) {
|
|
51834
51864
|
clear(slotName);
|
|
51835
51865
|
continue;
|
|
51836
51866
|
}
|
|
51837
|
-
const
|
|
51838
|
-
|
|
51839
|
-
|
|
51840
|
-
|
|
51841
|
-
|
|
51842
|
-
|
|
51843
|
-
pattern: patternType,
|
|
51844
|
-
props: {
|
|
51867
|
+
const children = entries.map(({ entry }) => entry.patterns[entry.patterns.length - 1]).filter((p2) => Boolean(p2)).map((entry) => {
|
|
51868
|
+
const record = entry.pattern;
|
|
51869
|
+
const { type: patternType, children: nested, ...inlineProps } = record;
|
|
51870
|
+
const normalizedNested = Array.isArray(nested) ? nested.map((c) => normalizeChild(c)) : nested;
|
|
51871
|
+
return {
|
|
51872
|
+
type: patternType,
|
|
51845
51873
|
...inlineProps,
|
|
51846
51874
|
...entry.props,
|
|
51847
|
-
...
|
|
51848
|
-
}
|
|
51849
|
-
sourceTrait: slotState.source?.trait
|
|
51875
|
+
...normalizedNested !== void 0 ? { children: normalizedNested } : {}
|
|
51876
|
+
};
|
|
51850
51877
|
});
|
|
51878
|
+
if (children.length === 1) {
|
|
51879
|
+
const only = children[0];
|
|
51880
|
+
const { type, children: nested, ...rest } = only;
|
|
51881
|
+
const lastEntry = entries[entries.length - 1];
|
|
51882
|
+
render({
|
|
51883
|
+
target: slotName,
|
|
51884
|
+
pattern: type,
|
|
51885
|
+
props: {
|
|
51886
|
+
...rest,
|
|
51887
|
+
...nested !== void 0 ? { children: nested } : {}
|
|
51888
|
+
},
|
|
51889
|
+
sourceTrait: lastEntry.entry.source?.trait
|
|
51890
|
+
});
|
|
51891
|
+
} else {
|
|
51892
|
+
const lastEntry = entries[entries.length - 1];
|
|
51893
|
+
render({
|
|
51894
|
+
target: slotName,
|
|
51895
|
+
pattern: "stack",
|
|
51896
|
+
props: {
|
|
51897
|
+
direction: "vertical",
|
|
51898
|
+
gap: "lg",
|
|
51899
|
+
children
|
|
51900
|
+
},
|
|
51901
|
+
sourceTrait: lastEntry.entry.source?.trait
|
|
51902
|
+
});
|
|
51903
|
+
}
|
|
51851
51904
|
}
|
|
51852
51905
|
}, [slots, render, clear]);
|
|
51853
51906
|
return null;
|
|
51854
51907
|
}
|
|
51855
51908
|
function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
51909
|
+
const perSlotRenders = /* @__PURE__ */ new Map();
|
|
51856
51910
|
for (const eff of effects) {
|
|
51857
51911
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
51858
51912
|
const patternRecord = eff.pattern;
|
|
51859
51913
|
const { type: patternType, children, ...inlineProps } = patternRecord;
|
|
51860
51914
|
const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
|
|
51915
|
+
const sourceTrait = eff.traitName ?? "server";
|
|
51861
51916
|
uiSlots.render({
|
|
51862
51917
|
target: eff.slot,
|
|
51863
51918
|
pattern: patternType,
|
|
@@ -51865,12 +51920,38 @@ function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
|
51865
51920
|
...inlineProps,
|
|
51866
51921
|
...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
|
|
51867
51922
|
},
|
|
51868
|
-
sourceTrait
|
|
51923
|
+
sourceTrait
|
|
51924
|
+
});
|
|
51925
|
+
const bucket = perSlotRenders.get(eff.slot) ?? [];
|
|
51926
|
+
bucket.push({
|
|
51927
|
+
sourceTrait,
|
|
51928
|
+
pattern: {
|
|
51929
|
+
type: patternType,
|
|
51930
|
+
...inlineProps,
|
|
51931
|
+
...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
|
|
51932
|
+
}
|
|
51869
51933
|
});
|
|
51934
|
+
perSlotRenders.set(eff.slot, bucket);
|
|
51870
51935
|
} else if (eff.type === "navigate" && eff.route && onNavigate) {
|
|
51871
51936
|
onNavigate(eff.route, eff.params);
|
|
51872
51937
|
}
|
|
51873
51938
|
}
|
|
51939
|
+
for (const [slot, bucket] of perSlotRenders) {
|
|
51940
|
+
const distinctSources = new Set(bucket.map((b) => b.sourceTrait));
|
|
51941
|
+
if (distinctSources.size <= 1) continue;
|
|
51942
|
+
uiSlots.render({
|
|
51943
|
+
target: slot,
|
|
51944
|
+
pattern: "stack",
|
|
51945
|
+
props: {
|
|
51946
|
+
direction: "vertical",
|
|
51947
|
+
gap: "lg",
|
|
51948
|
+
children: bucket.map((b) => b.pattern)
|
|
51949
|
+
},
|
|
51950
|
+
// Use a synthetic wrapper source trait; individual traits' frames
|
|
51951
|
+
// already live in the per-trait index from the per-effect loop.
|
|
51952
|
+
sourceTrait: "__multi_source_stack__"
|
|
51953
|
+
});
|
|
51954
|
+
}
|
|
51874
51955
|
}
|
|
51875
51956
|
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence }) {
|
|
51876
51957
|
const slotsActions = useSlotsActions();
|