@almadar/ui 3.9.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: useEffect88, useRef: useRef87, useCallback: useCallback125, useState: useState126 } = React126__namespace.default;
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
- useEffect88(() => {
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
- useEffect88(() => {
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] = useState126(null);
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
- var gapStyles6, DataGrid;
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
- var DataList;
22013
- var init_DataList = __esm({
22014
- "components/molecules/DataList.tsx"() {
22015
- "use client";
22016
- init_cn();
22017
- init_getNestedValue();
22018
- init_useEventBus();
22019
- init_useTranslate();
22020
- init_Box();
22021
- init_Stack();
22022
- init_Typography();
22023
- init_Badge();
22024
- init_Button();
22025
- init_Icon();
22026
- init_ProgressBar();
22027
- init_Divider();
22028
- init_InfiniteScrollSentinel();
22029
- DataList = ({
22030
- entity,
22031
- fields: fieldsProp,
22032
- columns: columnsProp,
22033
- itemActions,
22034
- gap = "none",
22035
- variant = "default",
22036
- groupBy,
22037
- senderField,
22038
- currentUser,
22039
- className,
22040
- isLoading = false,
22041
- error = null,
22042
- // Gesture props: reorderable, swipeLeftEvent, swipeRightEvent, longPressEvent
22043
- // are consumed by the compiler to wrap items in SwipeableRow/SortableList.
22044
- // DataList destructures them here to prevent DOM passthrough.
22045
- reorderable: _reorderable,
22046
- reorderEvent: _reorderEvent,
22047
- swipeLeftEvent: _swipeLeftEvent,
22048
- swipeLeftActions: _swipeLeftActions,
22049
- swipeRightEvent: _swipeRightEvent,
22050
- swipeRightActions: _swipeRightActions,
22051
- longPressEvent: _longPressEvent,
22052
- infiniteScroll,
22053
- loadMoreEvent,
22054
- hasMore,
22055
- children,
22056
- pageSize = 5
22057
- }) => {
22058
- const eventBus = useEventBus();
22059
- const { t } = useTranslate();
22060
- const [visibleCount, setVisibleCount] = React126__namespace.default.useState(pageSize || Infinity);
22061
- const fields = fieldsProp ?? columnsProp ?? [];
22062
- const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
22063
- const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
22064
- const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
22065
- const titleField = fields.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fields[0];
22066
- const badgeFields = fields.filter((f3) => f3.variant === "badge" && f3 !== titleField);
22067
- const progressFields = fields.filter((f3) => f3.variant === "progress");
22068
- const bodyFields = fields.filter(
22069
- (f3) => f3 !== titleField && !badgeFields.includes(f3) && !progressFields.includes(f3)
22070
- );
22071
- const handleActionClick = (action, itemData) => (e) => {
22072
- e.stopPropagation();
22073
- const payload = {
22074
- id: itemData.id,
22075
- row: itemData
22076
- };
22077
- eventBus.emit(`UI:${action.event}`, payload);
22078
- };
22079
- if (isLoading) {
22080
- return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
22081
- }
22082
- if (error) {
22083
- return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "error", children: error.message }) });
22084
- }
22085
- if (data.length === 0) {
22086
- 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" }) });
22087
- }
22088
- const gapClass = {
22089
- none: "",
22090
- sm: "gap-1",
22091
- md: "gap-2",
22092
- lg: "gap-4"
22093
- }[gap];
22094
- const isCard = variant === "card";
22095
- const isCompact = variant === "compact";
22096
- const isMessage = variant === "message";
22097
- if (isMessage) {
22098
- const items2 = data.map((item) => item);
22099
- const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
22100
- const contentField = titleField?.name ?? fields[0]?.name ?? "";
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
- "group flex items-center gap-4 transition-all duration-200",
22159
- isCompact ? "px-4 py-2" : "px-6 py-4",
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(Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
22165
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
22166
- HStack,
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
- gap: "xs",
22169
- className: "flex-shrink-0",
22170
- children: itemActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
22171
- Button,
22172
- {
22173
- variant: action.variant ?? "ghost",
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
- isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mx-6 border-b border-border/40" })
22193
- ] }, id2);
22194
- }
22195
- const id = itemData.id || String(index);
22196
- const titleValue = getNestedValue(itemData, titleField?.name ?? "");
22197
- return /* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-entity-row": true, "data-entity-id": id, children: [
22198
- /* @__PURE__ */ jsxRuntime.jsxs(
22199
- Box,
22200
- {
22201
- className: cn(
22202
- "group flex items-center gap-4 transition-all duration-200",
22203
- isCompact ? "px-4 py-2" : "px-6 py-4",
22204
- "hover:bg-muted/80",
22205
- !isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
22206
- ),
22207
- children: [
22208
- /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex-1 min-w-0", children: [
22209
- /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "items-center", children: [
22210
- titleField?.icon && /* @__PURE__ */ jsxRuntime.jsx(
22211
- Icon,
22212
- {
22213
- name: titleField.icon,
22214
- size: isCompact ? "xs" : "sm",
22215
- className: "text-primary flex-shrink-0"
22216
- }
22217
- ),
22218
- titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxRuntime.jsx(
22219
- Typography,
22220
- {
22221
- variant: titleField?.variant === "h3" ? "h3" : "h4",
22222
- className: cn("font-semibold truncate flex-1", isCompact && "text-sm"),
22223
- children: String(titleValue)
22224
- }
22225
- ),
22226
- badgeFields.map((field) => {
22227
- const val = getNestedValue(itemData, field.name);
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
- isCard && "bg-card rounded-xl border border-border shadow-lg overflow-hidden",
22287
- !isCard && gapClass,
22288
- className
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
- groups.map((group, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React126__namespace.default.Fragment, { children: [
22292
- group.label && /* @__PURE__ */ jsxRuntime.jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
22293
- group.items.map(
22294
- (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
22295
- )
22296
- ] }, gi)),
22297
- hasMoreLocal && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
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: () => setVisibleCount((prev) => prev + (pageSize || 5)),
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: "chevron-down", size: "xs", className: "mr-1" }),
22305
- t("common.showMore"),
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
- infiniteScroll && loadMoreEvent && /* @__PURE__ */ jsxRuntime.jsx(
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 totalSteps = steps.length;
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: steps.map((step, index) => {
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();
@@ -51065,7 +51061,7 @@ function createClientEffectHandlers(options) {
51065
51061
  return {
51066
51062
  emit: (event, payload) => {
51067
51063
  const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
51068
- eventBus.emit(prefixedEvent, { payload });
51064
+ eventBus.emit(prefixedEvent, payload);
51069
51065
  },
51070
51066
  persist: async () => {
51071
51067
  console.warn("[ClientEffectHandlers] persist is server-side only, ignored on client");
@@ -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
- setSlots((prev) => ({
51623
- ...prev,
51624
- [slot]: { patterns, source }
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.patterns.length === 0 && !existing.source) {
51644
+ if (existing && Object.keys(existing).length === 0) {
51631
51645
  return prev;
51632
51646
  }
51633
- return { ...prev, [slot]: { patterns: [] } };
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({ setSlotPatterns, clearSlot, clearAllSlots });
51640
- actionsRef.current = { setSlotPatterns, clearSlot, clearAllSlots };
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,24 +51905,48 @@ function SlotBridge() {
51876
51905
  const { render, clear } = useUISlots();
51877
51906
  React126.useEffect(() => {
51878
51907
  for (const [slotName, slotState] of Object.entries(slots)) {
51879
- if (slotState.patterns.length === 0) {
51908
+ const entries = slotEntriesInOrder(slotState);
51909
+ if (entries.length === 0) {
51880
51910
  clear(slotName);
51881
51911
  continue;
51882
51912
  }
51883
- const entry = slotState.patterns[slotState.patterns.length - 1];
51884
- const patternRecord = entry.pattern;
51885
- const { type: patternType, children, ...inlineProps } = patternRecord;
51886
- const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
51887
- render({
51888
- target: slotName,
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
- ...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
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;