@almadar/ui 5.131.0 → 5.132.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.
@@ -538,6 +538,26 @@ var init_useDragReorder = __esm({
538
538
  "use client";
539
539
  }
540
540
  });
541
+ function useMediaQuery(query) {
542
+ const subscribe = useCallback(
543
+ (onChange) => {
544
+ const mql = window.matchMedia(query);
545
+ mql.addEventListener("change", onChange);
546
+ return () => mql.removeEventListener("change", onChange);
547
+ },
548
+ [query]
549
+ );
550
+ return useSyncExternalStore(
551
+ subscribe,
552
+ () => window.matchMedia(query).matches,
553
+ () => false
554
+ );
555
+ }
556
+ var init_useMediaQuery = __esm({
557
+ "hooks/useMediaQuery.ts"() {
558
+ "use client";
559
+ }
560
+ });
541
561
  function useInfiniteScroll(onLoadMore, options = {}) {
542
562
  const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
543
563
  const observerRef = useRef(null);
@@ -2298,6 +2318,8 @@ var init_Badge = __esm({
2298
2318
  };
2299
2319
  const iconPx = size === "lg" ? 20 : 16;
2300
2320
  const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ jsx(AtlasImage, { asset: iconAsset, size: iconPx, alt: iconAsset.name ?? iconAsset.category ?? "", className: "flex-shrink-0" }) : typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2321
+ const hasText = Boolean(children) || amount != null || label !== void 0 && label !== null && label !== "";
2322
+ if (!hasText && !resolvedIcon && !onRemove) return null;
2301
2323
  return /* @__PURE__ */ jsxs(
2302
2324
  "span",
2303
2325
  {
@@ -5620,11 +5642,13 @@ var init_TrendIndicator = __esm({
5620
5642
  size = "md",
5621
5643
  ...props
5622
5644
  }, ref) => {
5623
- const dir = resolveDirection(value, direction);
5645
+ const hasValue = typeof value === "number" && Number.isFinite(value);
5646
+ if (!hasValue && !direction) return null;
5647
+ const dir = resolveDirection(hasValue ? value : void 0, direction);
5624
5648
  const colorClass = resolveColor(dir, invert);
5625
5649
  const iconName = iconNameMap[dir];
5626
5650
  const styles = sizeStyles6[size];
5627
- const formattedValue = value !== void 0 ? `${value > 0 ? "+" : ""}${value}%` : void 0;
5651
+ const formattedValue = hasValue ? `${value > 0 ? "+" : ""}${value}%` : void 0;
5628
5652
  const ariaLabel = label ?? (formattedValue ? `${dir} ${formattedValue}` : dir);
5629
5653
  return /* @__PURE__ */ jsxs(
5630
5654
  "span",
@@ -17681,26 +17705,19 @@ var init_BookViewer = __esm({
17681
17705
  function BoxPattern({
17682
17706
  p,
17683
17707
  m,
17684
- bg = "transparent",
17685
- border = false,
17686
- radius = "none",
17687
- shadow = "none",
17688
- className,
17689
- style,
17690
- children
17708
+ radius,
17709
+ isLoading: _isLoading,
17710
+ error: _error,
17711
+ entity: _entity,
17712
+ ...boxProps
17691
17713
  }) {
17692
17714
  return /* @__PURE__ */ jsx(
17693
17715
  Box,
17694
17716
  {
17695
- padding: p,
17696
- margin: m,
17697
- bg,
17698
- border,
17699
- rounded: radius,
17700
- shadow,
17701
- className,
17702
- style,
17703
- children
17717
+ padding: boxProps.padding ?? p,
17718
+ margin: boxProps.margin ?? m,
17719
+ rounded: boxProps.rounded ?? radius,
17720
+ ...boxProps
17704
17721
  }
17705
17722
  );
17706
17723
  }
@@ -21310,17 +21327,19 @@ var init_DashboardLayout = __esm({
21310
21327
  const [sidebarOpen, setSidebarOpen] = useState(false);
21311
21328
  const [userMenuOpen, setUserMenuOpen] = useState(false);
21312
21329
  const layoutRef = useRef(null);
21313
- const [isMobile, setIsMobile] = useState(false);
21330
+ const [layoutWidth, setLayoutWidth] = useState(null);
21314
21331
  useEffect(() => {
21315
21332
  const el = layoutRef.current;
21316
21333
  if (!el || typeof ResizeObserver === "undefined") return;
21317
21334
  const ro = new ResizeObserver((entries) => {
21318
21335
  const w = entries[0]?.contentRect.width ?? el.clientWidth;
21319
- setIsMobile(w < 1024);
21336
+ setLayoutWidth(w);
21320
21337
  });
21321
21338
  ro.observe(el);
21322
21339
  return () => ro.disconnect();
21323
21340
  }, []);
21341
+ const isMobile = layoutWidth !== null && layoutWidth < 768;
21342
+ const isRail = layoutWidth !== null && layoutWidth >= 768 && layoutWidth < 1024;
21324
21343
  useEffect(() => {
21325
21344
  if (!isMobile && sidebarOpen) setSidebarOpen(false);
21326
21345
  }, [isMobile, sidebarOpen]);
@@ -21353,7 +21372,8 @@ var init_DashboardLayout = __esm({
21353
21372
  {
21354
21373
  as: "aside",
21355
21374
  className: cn(
21356
- "z-30 w-64 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
21375
+ "z-30 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
21376
+ isRail ? "w-16" : "w-64",
21357
21377
  "flex flex-col"
21358
21378
  ),
21359
21379
  style: isMobile ? {
@@ -21369,10 +21389,10 @@ var init_DashboardLayout = __esm({
21369
21389
  HStack,
21370
21390
  {
21371
21391
  align: "center",
21372
- justify: "between",
21373
- className: "h-16 px-4 border-b border-border dark:border-border",
21392
+ justify: isRail ? "center" : "between",
21393
+ className: cn("h-16 border-b border-border dark:border-border", isRail ? "px-2" : "px-4"),
21374
21394
  children: [
21375
- /* @__PURE__ */ jsxs(Link, { to: "/", className: "flex items-center gap-2", children: [
21395
+ /* @__PURE__ */ jsxs(Link, { to: "/", className: "flex items-center gap-2", title: isRail ? appName : void 0, children: [
21376
21396
  logo || /* @__PURE__ */ jsx(Box, { className: "w-8 h-8 bg-primary rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsx(
21377
21397
  Typography,
21378
21398
  {
@@ -21382,7 +21402,7 @@ var init_DashboardLayout = __esm({
21382
21402
  children: appName.charAt(0).toUpperCase()
21383
21403
  }
21384
21404
  ) }),
21385
- /* @__PURE__ */ jsx(
21405
+ !isRail && /* @__PURE__ */ jsx(
21386
21406
  Typography,
21387
21407
  {
21388
21408
  variant: "label",
@@ -21409,12 +21429,13 @@ var init_DashboardLayout = __esm({
21409
21429
  {
21410
21430
  as: "nav",
21411
21431
  gap: "none",
21412
- className: "flex-1 px-3 py-4 space-y-1 overflow-y-auto",
21432
+ className: cn("flex-1 py-4 space-y-1 overflow-y-auto", isRail ? "px-2" : "px-3"),
21413
21433
  children: navItems.map((item) => /* @__PURE__ */ jsx(
21414
21434
  NavLink,
21415
21435
  {
21416
21436
  item,
21417
- currentPath: activePath
21437
+ currentPath: activePath,
21438
+ compact: isRail
21418
21439
  },
21419
21440
  item.href
21420
21441
  ))
@@ -21669,13 +21690,40 @@ var init_DashboardLayout = __esm({
21669
21690
  DashboardLayout.displayName = "DashboardLayout";
21670
21691
  NavLink = ({
21671
21692
  item,
21672
- currentPath
21693
+ currentPath,
21694
+ compact = false
21673
21695
  }) => {
21674
21696
  const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
21675
21697
  const iconClassName = cn(
21676
21698
  "h-5 w-5",
21677
21699
  isActive ? "text-primary-foreground" : "text-muted-foreground"
21678
21700
  );
21701
+ if (compact) {
21702
+ return /* @__PURE__ */ jsx(
21703
+ Link,
21704
+ {
21705
+ to: item.href,
21706
+ title: item.label,
21707
+ "aria-label": item.label,
21708
+ className: cn(
21709
+ "flex items-center justify-center px-2 py-2 rounded-lg transition-colors",
21710
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
21711
+ ),
21712
+ children: /* @__PURE__ */ jsxs(Box, { as: "span", className: "relative inline-flex", children: [
21713
+ item.icon ? typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, className: iconClassName }) : /* @__PURE__ */ jsx(item.icon, { className: iconClassName }) : /* @__PURE__ */ jsx(Typography, { variant: "small", className: "font-semibold", as: "span", children: item.label.charAt(0).toUpperCase() }),
21714
+ item.badge && /* @__PURE__ */ jsx(
21715
+ Badge,
21716
+ {
21717
+ variant: isActive ? "primary" : "default",
21718
+ size: "sm",
21719
+ className: "absolute -top-2 -right-2 px-1 py-0 text-[10px] leading-4",
21720
+ children: item.badge
21721
+ }
21722
+ )
21723
+ ] })
21724
+ }
21725
+ );
21726
+ }
21679
21727
  return /* @__PURE__ */ jsxs(
21680
21728
  Link,
21681
21729
  {
@@ -22741,40 +22789,55 @@ function DataGrid({
22741
22789
  {
22742
22790
  "data-entity-row": true,
22743
22791
  "data-entity-id": id,
22744
- className: cn(isSelected && "ring-2 ring-primary rounded-lg"),
22792
+ className: cn("relative group/rowactions", isSelected && "ring-2 ring-primary rounded-lg"),
22745
22793
  children: [
22746
22794
  children(itemData, index),
22747
- actionDefs.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 border-t border-border", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-end", children: [
22748
- (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxs(
22749
- Button,
22750
- {
22751
- variant: action.variant === "primary" ? "primary" : "ghost",
22752
- size: "sm",
22753
- onClick: handleActionClick(action, itemData),
22754
- "data-testid": `action-${action.event}`,
22755
- "data-row-id": String(itemData.id),
22756
- className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
22757
- children: [
22758
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
22759
- action.label
22760
- ]
22761
- },
22762
- idx
22763
- )),
22764
- maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
22795
+ actionDefs.length > 0 && /* @__PURE__ */ jsxs(Box, { className: "absolute top-2 right-2 z-10 opacity-0 group-hover/rowactions:opacity-100 focus-within:opacity-100 [@media(pointer:coarse)]:opacity-100 transition-opacity duration-fast", children: [
22796
+ /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5 [@media(pointer:coarse)]:hidden", children: [
22797
+ (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxs(
22798
+ Button,
22799
+ {
22800
+ variant: action.variant === "primary" ? "primary" : "ghost",
22801
+ size: "sm",
22802
+ onClick: handleActionClick(action, itemData),
22803
+ "data-testid": `action-${action.event}`,
22804
+ "data-row-id": String(itemData.id),
22805
+ className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
22806
+ children: [
22807
+ action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
22808
+ action.label
22809
+ ]
22810
+ },
22811
+ idx
22812
+ )),
22813
+ maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
22814
+ Menu,
22815
+ {
22816
+ position: "bottom-end",
22817
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
22818
+ items: actionDefs.slice(maxInlineActions).map((action) => ({
22819
+ label: action.label,
22820
+ icon: action.icon,
22821
+ event: action.event,
22822
+ onClick: () => fireAction(action, itemData)
22823
+ }))
22824
+ }
22825
+ )
22826
+ ] }),
22827
+ /* @__PURE__ */ jsx(Box, { className: "hidden [@media(pointer:coarse)]:block rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5", children: /* @__PURE__ */ jsx(
22765
22828
  Menu,
22766
22829
  {
22767
22830
  position: "bottom-end",
22768
22831
  trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
22769
- items: actionDefs.slice(maxInlineActions).map((action) => ({
22832
+ items: actionDefs.map((action) => ({
22770
22833
  label: action.label,
22771
22834
  icon: action.icon,
22772
22835
  event: action.event,
22773
22836
  onClick: () => fireAction(action, itemData)
22774
22837
  }))
22775
22838
  }
22776
- )
22777
- ] }) })
22839
+ ) })
22840
+ ] })
22778
22841
  ]
22779
22842
  },
22780
22843
  id
@@ -22810,7 +22873,7 @@ function DataGrid({
22810
22873
  }
22811
22874
  ) });
22812
22875
  })(),
22813
- /* @__PURE__ */ jsx(Box, { className: "p-4 pb-0", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
22876
+ /* @__PURE__ */ jsx(Box, { className: cn("p-4", bodyFields.length > 0 && "pb-0"), children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
22814
22877
  selectable && /* @__PURE__ */ jsx(
22815
22878
  "input",
22816
22879
  {
@@ -22843,78 +22906,77 @@ function DataGrid({
22843
22906
  ] }, field.name);
22844
22907
  }) })
22845
22908
  ] }),
22846
- dangerActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsx(
22847
- Button,
22848
- {
22849
- variant: "ghost",
22850
- size: "sm",
22851
- onClick: handleActionClick(action, itemData),
22852
- "data-testid": `action-${action.event}`,
22853
- "data-row-id": String(itemData.id),
22854
- "aria-label": action.label,
22855
- title: action.label,
22856
- className: "text-error hover:text-error hover:bg-error/10 px-2",
22857
- children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
22858
- },
22859
- idx
22860
- )) })
22861
- ] }) }),
22862
- bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: bodyFields.map((field) => {
22863
- const value = getNestedValue(itemData, field.name);
22864
- if (value === void 0 || value === null || value === "") return null;
22865
- if (field.format === "boolean") {
22866
- return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
22867
- /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
22868
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
22869
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
22870
- ] }),
22871
- /* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
22872
- ] }, field.name);
22873
- }
22874
- return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
22875
- /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
22876
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
22877
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
22878
- ] }),
22879
- /* @__PURE__ */ jsx(
22880
- Typography,
22909
+ (primaryActions.length > 0 || dangerActions.length > 0) && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "flex-shrink-0", children: [
22910
+ (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsx(
22911
+ Button,
22881
22912
  {
22882
- variant: field.variant === "caption" ? "caption" : "small",
22883
- className: "text-right truncate max-w-[60%]",
22884
- children: formatValue(value, field.format)
22913
+ variant: action.variant === "primary" ? "primary" : "ghost",
22914
+ size: "sm",
22915
+ onClick: handleActionClick(action, itemData),
22916
+ "data-testid": `action-${action.event}`,
22917
+ "data-row-id": String(itemData.id),
22918
+ "aria-label": action.label,
22919
+ title: action.label,
22920
+ className: cn(
22921
+ action.variant === "primary" ? void 0 : "text-muted-foreground hover:text-foreground",
22922
+ action.icon && "px-2"
22923
+ ),
22924
+ children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
22925
+ },
22926
+ idx
22927
+ )),
22928
+ maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsx(
22929
+ Menu,
22930
+ {
22931
+ position: "bottom-end",
22932
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
22933
+ items: primaryActions.slice(maxInlineActions).map((action) => ({
22934
+ label: action.label,
22935
+ icon: action.icon,
22936
+ event: action.event,
22937
+ onClick: () => fireAction(action, itemData)
22938
+ }))
22885
22939
  }
22886
- )
22887
- ] }, field.name);
22888
- }) }) }),
22889
- primaryActions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-end flex-wrap", children: [
22890
- (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxs(
22891
- Button,
22892
- {
22893
- variant: action.variant === "primary" ? "primary" : "ghost",
22894
- size: "sm",
22895
- onClick: handleActionClick(action, itemData),
22896
- "data-testid": `action-${action.event}`,
22897
- "data-row-id": String(itemData.id),
22898
- children: [
22899
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
22900
- action.label
22901
- ]
22902
- },
22903
- idx
22904
- )),
22905
- maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsx(
22906
- Menu,
22907
- {
22908
- position: "bottom-end",
22909
- trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
22910
- items: primaryActions.slice(maxInlineActions).map((action) => ({
22911
- label: action.label,
22912
- icon: action.icon,
22913
- event: action.event,
22914
- onClick: () => fireAction(action, itemData)
22915
- }))
22940
+ ),
22941
+ dangerActions.map((action, idx) => /* @__PURE__ */ jsx(
22942
+ Button,
22943
+ {
22944
+ variant: "ghost",
22945
+ size: "sm",
22946
+ onClick: handleActionClick(action, itemData),
22947
+ "data-testid": `action-${action.event}`,
22948
+ "data-row-id": String(itemData.id),
22949
+ "aria-label": action.label,
22950
+ title: action.label,
22951
+ className: "text-error hover:text-error hover:bg-error/10 px-2",
22952
+ children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
22953
+ },
22954
+ `danger-${idx}`
22955
+ ))
22956
+ ] })
22957
+ ] }) }),
22958
+ bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 pt-2 pb-4 flex-1", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
22959
+ bodyFields.filter((f3) => f3.variant === "caption" && f3.format !== "boolean").map((field) => {
22960
+ const value = getNestedValue(itemData, field.name);
22961
+ if (value === void 0 || value === null || value === "") return null;
22962
+ return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", className: "line-clamp-2", children: formatValue(value, field.format) }, field.name);
22963
+ }),
22964
+ /* @__PURE__ */ jsx(HStack, { gap: "md", className: "flex-wrap gap-y-1", children: bodyFields.filter((f3) => f3.variant !== "caption" || f3.format === "boolean").map((field) => {
22965
+ const value = getNestedValue(itemData, field.name);
22966
+ if (value === void 0 || value === null || value === "") return null;
22967
+ if (field.format === "boolean") {
22968
+ return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
22969
+ field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
22970
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) }),
22971
+ /* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
22972
+ ] }, field.name);
22916
22973
  }
22917
- )
22974
+ return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
22975
+ field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
22976
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
22977
+ /* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue(value, field.format) })
22978
+ ] }, field.name);
22979
+ }) })
22918
22980
  ] }) })
22919
22981
  ]
22920
22982
  },
@@ -23262,11 +23324,29 @@ function DataList({
23262
23324
  const wrapDnd = (node) => dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: dndId, children: node }, dndId) : node;
23263
23325
  if (hasRenderProp) {
23264
23326
  const id2 = itemData.id || String(index);
23327
+ const actions = renderItemActions(itemData);
23265
23328
  return wrapDnd(
23266
- /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick: itemClickEvent ? handleRowClick(itemData) : void 0, className: cn(itemClickEvent && "cursor-pointer"), children: [
23267
- /* @__PURE__ */ jsxs(Box, { className: "group flex items-stretch gap-2", children: [
23268
- /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
23269
- renderItemActions(itemData)
23329
+ /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick: itemClickEvent ? handleRowClick(itemData) : void 0, className: cn("relative group/rowactions", itemClickEvent && "cursor-pointer"), children: [
23330
+ children(itemData, index),
23331
+ actions && /* @__PURE__ */ jsxs(Box, { className: "absolute top-2 right-2 z-10 opacity-0 group-hover/rowactions:opacity-100 focus-within:opacity-100 [@media(pointer:coarse)]:opacity-100 transition-opacity duration-fast", children: [
23332
+ /* @__PURE__ */ jsx(Box, { className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5 [@media(pointer:coarse)]:hidden", children: actions }),
23333
+ /* @__PURE__ */ jsx(Box, { className: "hidden [@media(pointer:coarse)]:block rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5", children: /* @__PURE__ */ jsx(
23334
+ Menu,
23335
+ {
23336
+ position: "bottom-end",
23337
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
23338
+ items: (itemActions ?? []).map((action) => ({
23339
+ label: action.label,
23340
+ icon: action.icon,
23341
+ event: action.event,
23342
+ variant: action.variant === "danger" ? "danger" : "default",
23343
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
23344
+ id: itemData.id,
23345
+ row: itemData
23346
+ })
23347
+ }))
23348
+ }
23349
+ ) })
23270
23350
  ] }),
23271
23351
  isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-border/40" })
23272
23352
  ] }, id2)
@@ -23306,7 +23386,7 @@ function DataList({
23306
23386
  ] }, field.name);
23307
23387
  })
23308
23388
  ] }),
23309
- bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsx(HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
23389
+ bodyFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "md", className: cn("flex-wrap", isCompact ? "mt-0.5" : "mt-1.5"), children: bodyFields.map((field) => {
23310
23390
  const value = getNestedValue(itemData, field.name);
23311
23391
  if (value === void 0 || value === null || value === "") return null;
23312
23392
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
@@ -26838,7 +26918,7 @@ var init_MapView = __esm({
26838
26918
  shadowSize: [41, 41]
26839
26919
  });
26840
26920
  L.Marker.prototype.options.icon = defaultIcon;
26841
- const { useEffect: useEffect59, useRef: useRef60, useCallback: useCallback87, useState: useState89 } = React82__default;
26921
+ const { useEffect: useEffect59, useRef: useRef60, useCallback: useCallback88, useState: useState89 } = React82__default;
26842
26922
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
26843
26923
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
26844
26924
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -26884,7 +26964,7 @@ var init_MapView = __esm({
26884
26964
  }) {
26885
26965
  const eventBus = useEventBus2();
26886
26966
  const [clickedPosition, setClickedPosition] = useState89(null);
26887
- const handleMapClick = useCallback87((lat, lng) => {
26967
+ const handleMapClick = useCallback88((lat, lng) => {
26888
26968
  if (showClickedPin) {
26889
26969
  setClickedPosition({ lat, lng });
26890
26970
  }
@@ -26893,7 +26973,7 @@ var init_MapView = __esm({
26893
26973
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
26894
26974
  }
26895
26975
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
26896
- const handleMarkerClick = useCallback87((marker) => {
26976
+ const handleMarkerClick = useCallback88((marker) => {
26897
26977
  onMarkerClick?.(marker);
26898
26978
  if (markerClickEvent) {
26899
26979
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -27775,6 +27855,7 @@ function TableView({
27775
27855
  const hasMore = pageSize > 0 && visibleCount < ordered.length;
27776
27856
  const hasRenderProp = typeof children === "function";
27777
27857
  const idField = dndItemIdField ?? "id";
27858
+ const isCoarsePointer = useMediaQuery("(pointer: coarse)");
27778
27859
  const selected = selectedIds ? new Set(selectedIds) : localSelected;
27779
27860
  const emitSelection = (next) => {
27780
27861
  if (!selectedIds) setLocalSelected(next);
@@ -27807,6 +27888,17 @@ function TableView({
27807
27888
  };
27808
27889
  eventBus.emit(`UI:${action.event}`, payload);
27809
27890
  };
27891
+ const colFloors = React82__default.useMemo(
27892
+ () => colDefs.map((col) => {
27893
+ const longest = data.reduce((widest, row) => {
27894
+ const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
27895
+ return Math.max(widest, cell.length);
27896
+ }, columnLabel(col).length);
27897
+ const chrome = col.format === "badge" ? BADGE_CHROME_CH : 0;
27898
+ return Math.min(longest + chrome, MAX_MEASURED_COL_CH);
27899
+ }),
27900
+ [colDefs, data]
27901
+ );
27810
27902
  if (isLoading) {
27811
27903
  return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") }) });
27812
27904
  }
@@ -27819,20 +27911,10 @@ function TableView({
27819
27911
  }
27820
27912
  const lk = LOOKS[look];
27821
27913
  const hasActions = Boolean(itemActions && itemActions.length > 0);
27822
- const inlineActionCount = hasActions ? maxInlineActions != null ? Math.min(itemActions.length, maxInlineActions) : itemActions.length : 0;
27823
- const hasOverflowActions = hasActions && maxInlineActions != null && itemActions.length > maxInlineActions;
27914
+ const effectiveMaxInline = isCoarsePointer ? 0 : maxInlineActions;
27915
+ const inlineActionCount = hasActions ? effectiveMaxInline != null ? Math.min(itemActions.length, effectiveMaxInline) : itemActions.length : 0;
27916
+ const hasOverflowActions = hasActions && effectiveMaxInline != null && itemActions.length > effectiveMaxInline;
27824
27917
  const actionsTrack = hasActions ? `${inlineActionCount * 6 + (hasOverflowActions ? 3 : 0)}rem` : null;
27825
- const colFloors = React82__default.useMemo(
27826
- () => colDefs.map((col) => {
27827
- const longest = data.reduce((widest, row) => {
27828
- const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
27829
- return Math.max(widest, cell.length);
27830
- }, columnLabel(col).length);
27831
- const chrome = col.format === "badge" ? BADGE_CHROME_CH : 0;
27832
- return Math.min(longest + chrome, MAX_MEASURED_COL_CH);
27833
- }),
27834
- [colDefs, data]
27835
- );
27836
27918
  const gridTemplateColumns = [
27837
27919
  selectable ? "auto" : null,
27838
27920
  ...colDefs.map((c, i) => c.width ?? `minmax(${colFloors[i]}ch, 1fr)`),
@@ -27921,7 +28003,7 @@ function TableView({
27921
28003
  if (col.format === "badge" && raw != null && raw !== "") {
27922
28004
  return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx(Badge, { variant: statusVariant4(String(raw)), size: "sm", className: "whitespace-nowrap", children: String(raw) }) }, col.key);
27923
28005
  }
27924
- return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
28006
+ return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format) }) }, col.key);
27925
28007
  }),
27926
28008
  itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxs(
27927
28009
  HStack,
@@ -27935,15 +28017,15 @@ function TableView({
27935
28017
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
27936
28018
  ),
27937
28019
  children: [
27938
- (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
28020
+ (effectiveMaxInline != null ? itemActions.slice(0, effectiveMaxInline) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
27939
28021
  Button,
27940
28022
  {
27941
- variant: action.variant ?? "ghost",
28023
+ variant: action.variant === "primary" ? "primary" : "ghost",
27942
28024
  size: "sm",
27943
28025
  onClick: handleActionClick(action, row),
27944
28026
  "data-testid": `action-${action.event}`,
27945
28027
  "data-row-id": String(row.id),
27946
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
28028
+ className: cn(action.variant === "danger" && "text-error hover:text-error hover:bg-error/10"),
27947
28029
  children: [
27948
28030
  action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
27949
28031
  action.label
@@ -27951,12 +28033,12 @@ function TableView({
27951
28033
  },
27952
28034
  i
27953
28035
  )),
27954
- maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsx(
28036
+ effectiveMaxInline != null && itemActions.length > effectiveMaxInline && /* @__PURE__ */ jsx(
27955
28037
  Menu,
27956
28038
  {
27957
28039
  position: "bottom-end",
27958
28040
  trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
27959
- items: itemActions.slice(maxInlineActions).map((action) => ({
28041
+ items: itemActions.slice(effectiveMaxInline).map((action) => ({
27960
28042
  label: action.label,
27961
28043
  icon: action.icon,
27962
28044
  event: action.event,
@@ -28009,6 +28091,7 @@ var init_TableView = __esm({
28009
28091
  init_cn();
28010
28092
  init_getNestedValue();
28011
28093
  init_useEventBus();
28094
+ init_useMediaQuery();
28012
28095
  init_Box();
28013
28096
  init_Stack();
28014
28097
  init_Typography();
@@ -28033,7 +28116,7 @@ var init_TableView = __esm({
28033
28116
  semibold: "font-semibold"
28034
28117
  };
28035
28118
  LOOKS = {
28036
- dense: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true },
28119
+ dense: { rowPad: "px-card-md py-2", headPad: "px-card-md py-2", striped: false, divider: true },
28037
28120
  spacious: { rowPad: "px-card-lg py-card-md", headPad: "px-card-lg py-card-sm", striped: false, divider: true },
28038
28121
  striped: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: true, divider: false },
28039
28122
  borderless: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: false },
@@ -38952,27 +39035,24 @@ var init_MasterDetailLayout = __esm({
38952
39035
  masterClassName,
38953
39036
  detailClassName
38954
39037
  }) => {
38955
- masterWidth.endsWith("%") ? parseInt(masterWidth, 10) : 30;
38956
39038
  return /* @__PURE__ */ jsxs(
38957
39039
  "div",
38958
39040
  {
38959
- className: cn("flex h-full w-full", className),
38960
- style: {
38961
- display: "grid",
38962
- gridTemplateColumns: masterWidth.endsWith("%") ? `${masterWidth} 1fr` : `${masterWidth} 1fr`
38963
- },
39041
+ className: cn("w-full h-full md:grid md:grid-cols-[var(--master-detail-cols)]", className),
39042
+ style: { "--master-detail-cols": `${masterWidth} 1fr` },
38964
39043
  children: [
38965
39044
  /* @__PURE__ */ jsx(
38966
39045
  "div",
38967
39046
  {
38968
39047
  className: cn(
38969
- "border-r-2 border-border overflow-auto",
39048
+ "border-r border-border overflow-auto",
39049
+ hasSelection && "hidden md:block",
38970
39050
  masterClassName
38971
39051
  ),
38972
39052
  children: master
38973
39053
  }
38974
39054
  ),
38975
- /* @__PURE__ */ jsx("div", { className: cn("overflow-auto", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsx(DefaultEmptyDetail, {}) })
39055
+ /* @__PURE__ */ jsx("div", { className: cn("overflow-auto", !hasSelection && "hidden md:block", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsx(DefaultEmptyDetail, {}) })
38976
39056
  ]
38977
39057
  }
38978
39058
  );