@almadar/ui 5.131.0 → 5.133.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.
@@ -2610,6 +2610,8 @@ var init_Badge = __esm({
2610
2610
  };
2611
2611
  const iconPx = size === "lg" ? 20 : 16;
2612
2612
  const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ jsxRuntime.jsx(AtlasImage, { asset: iconAsset, size: iconPx, alt: iconAsset.name ?? iconAsset.category ?? "", className: "flex-shrink-0" }) : typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon, className: iconSizes3[size] }) : null;
2613
+ const hasText = Boolean(children) || amount != null || label !== void 0 && label !== null && label !== "";
2614
+ if (!hasText && !resolvedIcon && !onRemove) return null;
2613
2615
  return /* @__PURE__ */ jsxRuntime.jsxs(
2614
2616
  "span",
2615
2617
  {
@@ -4706,11 +4708,13 @@ var init_TrendIndicator = __esm({
4706
4708
  size = "md",
4707
4709
  ...props
4708
4710
  }, ref) => {
4709
- const dir = resolveDirection(value, direction);
4711
+ const hasValue = typeof value === "number" && Number.isFinite(value);
4712
+ if (!hasValue && !direction) return null;
4713
+ const dir = resolveDirection(hasValue ? value : void 0, direction);
4710
4714
  const colorClass = resolveColor(dir, invert);
4711
4715
  const iconName = iconNameMap[dir];
4712
4716
  const styles = sizeStyles6[size];
4713
- const formattedValue = value !== void 0 ? `${value > 0 ? "+" : ""}${value}%` : void 0;
4717
+ const formattedValue = hasValue ? `${value > 0 ? "+" : ""}${value}%` : void 0;
4714
4718
  const ariaLabel = label ?? (formattedValue ? `${dir} ${formattedValue}` : dir);
4715
4719
  return /* @__PURE__ */ jsxRuntime.jsxs(
4716
4720
  "span",
@@ -13732,26 +13736,19 @@ var init_BookViewer = __esm({
13732
13736
  function BoxPattern({
13733
13737
  p,
13734
13738
  m,
13735
- bg = "transparent",
13736
- border = false,
13737
- radius = "none",
13738
- shadow = "none",
13739
- className,
13740
- style,
13741
- children
13739
+ radius,
13740
+ isLoading: _isLoading,
13741
+ error: _error,
13742
+ entity: _entity,
13743
+ ...boxProps
13742
13744
  }) {
13743
13745
  return /* @__PURE__ */ jsxRuntime.jsx(
13744
13746
  exports.Box,
13745
13747
  {
13746
- padding: p,
13747
- margin: m,
13748
- bg,
13749
- border,
13750
- rounded: radius,
13751
- shadow,
13752
- className,
13753
- style,
13754
- children
13748
+ padding: boxProps.padding ?? p,
13749
+ margin: boxProps.margin ?? m,
13750
+ rounded: boxProps.rounded ?? radius,
13751
+ ...boxProps
13755
13752
  }
13756
13753
  );
13757
13754
  }
@@ -19406,17 +19403,19 @@ var init_DashboardLayout = __esm({
19406
19403
  const [sidebarOpen, setSidebarOpen] = React74.useState(false);
19407
19404
  const [userMenuOpen, setUserMenuOpen] = React74.useState(false);
19408
19405
  const layoutRef = React74.useRef(null);
19409
- const [isMobile, setIsMobile] = React74.useState(false);
19406
+ const [layoutWidth, setLayoutWidth] = React74.useState(null);
19410
19407
  React74.useEffect(() => {
19411
19408
  const el = layoutRef.current;
19412
19409
  if (!el || typeof ResizeObserver === "undefined") return;
19413
19410
  const ro = new ResizeObserver((entries) => {
19414
19411
  const w = entries[0]?.contentRect.width ?? el.clientWidth;
19415
- setIsMobile(w < 1024);
19412
+ setLayoutWidth(w);
19416
19413
  });
19417
19414
  ro.observe(el);
19418
19415
  return () => ro.disconnect();
19419
19416
  }, []);
19417
+ const isMobile = layoutWidth !== null && layoutWidth < 768;
19418
+ const isRail = layoutWidth !== null && layoutWidth >= 768 && layoutWidth < 1024;
19420
19419
  React74.useEffect(() => {
19421
19420
  if (!isMobile && sidebarOpen) setSidebarOpen(false);
19422
19421
  }, [isMobile, sidebarOpen]);
@@ -19453,7 +19452,8 @@ var init_DashboardLayout = __esm({
19453
19452
  {
19454
19453
  as: "aside",
19455
19454
  className: cn(
19456
- "z-30 w-64 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
19455
+ "z-30 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
19456
+ isRail ? "w-16" : "w-64",
19457
19457
  "flex flex-col"
19458
19458
  ),
19459
19459
  style: isMobile ? {
@@ -19469,10 +19469,10 @@ var init_DashboardLayout = __esm({
19469
19469
  exports.HStack,
19470
19470
  {
19471
19471
  align: "center",
19472
- justify: "between",
19473
- className: "h-16 px-4 border-b border-border dark:border-border",
19472
+ justify: isRail ? "center" : "between",
19473
+ className: cn("h-16 border-b border-border dark:border-border", isRail ? "px-2" : "px-4"),
19474
19474
  children: [
19475
- /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Link, { to: "/", className: "flex items-center gap-2", children: [
19475
+ /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Link, { to: "/", className: "flex items-center gap-2", title: isRail ? appName : void 0, children: [
19476
19476
  logo || /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "w-8 h-8 bg-primary rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
19477
19477
  exports.Typography,
19478
19478
  {
@@ -19482,7 +19482,7 @@ var init_DashboardLayout = __esm({
19482
19482
  children: appName.charAt(0).toUpperCase()
19483
19483
  }
19484
19484
  ) }),
19485
- /* @__PURE__ */ jsxRuntime.jsx(
19485
+ !isRail && /* @__PURE__ */ jsxRuntime.jsx(
19486
19486
  exports.Typography,
19487
19487
  {
19488
19488
  variant: "label",
@@ -19509,12 +19509,13 @@ var init_DashboardLayout = __esm({
19509
19509
  {
19510
19510
  as: "nav",
19511
19511
  gap: "none",
19512
- className: "flex-1 px-3 py-4 space-y-1 overflow-y-auto",
19512
+ className: cn("flex-1 py-4 space-y-1 overflow-y-auto", isRail ? "px-2" : "px-3"),
19513
19513
  children: navItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
19514
19514
  NavLink,
19515
19515
  {
19516
19516
  item,
19517
- currentPath: activePath
19517
+ currentPath: activePath,
19518
+ compact: isRail
19518
19519
  },
19519
19520
  item.href
19520
19521
  ))
@@ -19769,13 +19770,40 @@ var init_DashboardLayout = __esm({
19769
19770
  exports.DashboardLayout.displayName = "DashboardLayout";
19770
19771
  NavLink = ({
19771
19772
  item,
19772
- currentPath
19773
+ currentPath,
19774
+ compact = false
19773
19775
  }) => {
19774
19776
  const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
19775
19777
  const iconClassName = cn(
19776
19778
  "h-5 w-5",
19777
19779
  isActive ? "text-primary-foreground" : "text-muted-foreground"
19778
19780
  );
19781
+ if (compact) {
19782
+ return /* @__PURE__ */ jsxRuntime.jsx(
19783
+ reactRouterDom.Link,
19784
+ {
19785
+ to: item.href,
19786
+ title: item.label,
19787
+ "aria-label": item.label,
19788
+ className: cn(
19789
+ "flex items-center justify-center px-2 py-2 rounded-lg transition-colors",
19790
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
19791
+ ),
19792
+ children: /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { as: "span", className: "relative inline-flex", children: [
19793
+ item.icon ? typeof item.icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: item.icon, className: iconClassName }) : /* @__PURE__ */ jsxRuntime.jsx(item.icon, { className: iconClassName }) : /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", className: "font-semibold", as: "span", children: item.label.charAt(0).toUpperCase() }),
19794
+ item.badge && /* @__PURE__ */ jsxRuntime.jsx(
19795
+ exports.Badge,
19796
+ {
19797
+ variant: isActive ? "primary" : "default",
19798
+ size: "sm",
19799
+ className: "absolute -top-2 -right-2 px-1 py-0 text-[10px] leading-4",
19800
+ children: item.badge
19801
+ }
19802
+ )
19803
+ ] })
19804
+ }
19805
+ );
19806
+ }
19779
19807
  return /* @__PURE__ */ jsxRuntime.jsxs(
19780
19808
  reactRouterDom.Link,
19781
19809
  {
@@ -20841,40 +20869,55 @@ function DataGrid({
20841
20869
  {
20842
20870
  "data-entity-row": true,
20843
20871
  "data-entity-id": id,
20844
- className: cn(isSelected && "ring-2 ring-primary rounded-lg"),
20872
+ className: cn("relative group/rowactions", isSelected && "ring-2 ring-primary rounded-lg"),
20845
20873
  children: [
20846
20874
  children(itemData, index),
20847
- actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "px-4 py-3 border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-end", children: [
20848
- (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
20849
- exports.Button,
20850
- {
20851
- variant: action.variant === "primary" ? "primary" : "ghost",
20852
- size: "sm",
20853
- onClick: handleActionClick(action, itemData),
20854
- "data-testid": `action-${action.event}`,
20855
- "data-row-id": String(itemData.id),
20856
- className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
20857
- children: [
20858
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
20859
- action.label
20860
- ]
20861
- },
20862
- idx
20863
- )),
20864
- maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
20875
+ actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(exports.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: [
20876
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.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: [
20877
+ (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
20878
+ exports.Button,
20879
+ {
20880
+ variant: action.variant === "primary" ? "primary" : "ghost",
20881
+ size: "sm",
20882
+ onClick: handleActionClick(action, itemData),
20883
+ "data-testid": `action-${action.event}`,
20884
+ "data-row-id": String(itemData.id),
20885
+ className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
20886
+ children: [
20887
+ action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
20888
+ action.label
20889
+ ]
20890
+ },
20891
+ idx
20892
+ )),
20893
+ maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
20894
+ exports.Menu,
20895
+ {
20896
+ position: "bottom-end",
20897
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
20898
+ items: actionDefs.slice(maxInlineActions).map((action) => ({
20899
+ label: action.label,
20900
+ icon: action.icon,
20901
+ event: action.event,
20902
+ onClick: () => fireAction(action, itemData)
20903
+ }))
20904
+ }
20905
+ )
20906
+ ] }),
20907
+ /* @__PURE__ */ jsxRuntime.jsx(exports.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__ */ jsxRuntime.jsx(
20865
20908
  exports.Menu,
20866
20909
  {
20867
20910
  position: "bottom-end",
20868
20911
  trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
20869
- items: actionDefs.slice(maxInlineActions).map((action) => ({
20912
+ items: actionDefs.map((action) => ({
20870
20913
  label: action.label,
20871
20914
  icon: action.icon,
20872
20915
  event: action.event,
20873
20916
  onClick: () => fireAction(action, itemData)
20874
20917
  }))
20875
20918
  }
20876
- )
20877
- ] }) })
20919
+ ) })
20920
+ ] })
20878
20921
  ]
20879
20922
  },
20880
20923
  id
@@ -20910,7 +20953,7 @@ function DataGrid({
20910
20953
  }
20911
20954
  ) });
20912
20955
  })(),
20913
- /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "p-4 pb-0", children: /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-between items-start", children: [
20956
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: cn("p-4", bodyFields.length > 0 && "pb-0"), children: /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-between items-start", children: [
20914
20957
  selectable && /* @__PURE__ */ jsxRuntime.jsx(
20915
20958
  "input",
20916
20959
  {
@@ -20943,78 +20986,77 @@ function DataGrid({
20943
20986
  ] }, field.name);
20944
20987
  }) })
20945
20988
  ] }),
20946
- dangerActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
20947
- exports.Button,
20948
- {
20949
- variant: "ghost",
20950
- size: "sm",
20951
- onClick: handleActionClick(action, itemData),
20952
- "data-testid": `action-${action.event}`,
20953
- "data-row-id": String(itemData.id),
20954
- "aria-label": action.label,
20955
- title: action.label,
20956
- className: "text-error hover:text-error hover:bg-error/10 px-2",
20957
- children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
20958
- },
20959
- idx
20960
- )) })
20961
- ] }) }),
20962
- bodyFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(exports.VStack, { gap: "xs", children: bodyFields.map((field) => {
20963
- const value = getNestedValue(itemData, field.name);
20964
- if (value === void 0 || value === null || value === "") return null;
20965
- if (field.format === "boolean") {
20966
- return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-between items-center", children: [
20967
- /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
20968
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
20969
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
20970
- ] }),
20971
- /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
20972
- ] }, field.name);
20973
- }
20974
- return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-between items-center", children: [
20975
- /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
20976
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
20977
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
20978
- ] }),
20979
- /* @__PURE__ */ jsxRuntime.jsx(
20980
- exports.Typography,
20989
+ (primaryActions.length > 0 || dangerActions.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "flex-shrink-0", children: [
20990
+ (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
20991
+ exports.Button,
20992
+ {
20993
+ variant: action.variant === "primary" ? "primary" : "ghost",
20994
+ size: "sm",
20995
+ onClick: handleActionClick(action, itemData),
20996
+ "data-testid": `action-${action.event}`,
20997
+ "data-row-id": String(itemData.id),
20998
+ "aria-label": action.label,
20999
+ title: action.label,
21000
+ className: cn(
21001
+ action.variant === "primary" ? void 0 : "text-muted-foreground hover:text-foreground",
21002
+ action.icon && "px-2"
21003
+ ),
21004
+ children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
21005
+ },
21006
+ idx
21007
+ )),
21008
+ maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
21009
+ exports.Menu,
20981
21010
  {
20982
- variant: field.variant === "caption" ? "caption" : "small",
20983
- className: "text-right truncate max-w-[60%]",
20984
- children: formatValue(value, field.format)
21011
+ position: "bottom-end",
21012
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
21013
+ items: primaryActions.slice(maxInlineActions).map((action) => ({
21014
+ label: action.label,
21015
+ icon: action.icon,
21016
+ event: action.event,
21017
+ onClick: () => fireAction(action, itemData)
21018
+ }))
20985
21019
  }
20986
- )
20987
- ] }, field.name);
20988
- }) }) }),
20989
- primaryActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-end flex-wrap", children: [
20990
- (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
20991
- exports.Button,
20992
- {
20993
- variant: action.variant === "primary" ? "primary" : "ghost",
20994
- size: "sm",
20995
- onClick: handleActionClick(action, itemData),
20996
- "data-testid": `action-${action.event}`,
20997
- "data-row-id": String(itemData.id),
20998
- children: [
20999
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
21000
- action.label
21001
- ]
21002
- },
21003
- idx
21004
- )),
21005
- maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
21006
- exports.Menu,
21007
- {
21008
- position: "bottom-end",
21009
- trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
21010
- items: primaryActions.slice(maxInlineActions).map((action) => ({
21011
- label: action.label,
21012
- icon: action.icon,
21013
- event: action.event,
21014
- onClick: () => fireAction(action, itemData)
21015
- }))
21020
+ ),
21021
+ dangerActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
21022
+ exports.Button,
21023
+ {
21024
+ variant: "ghost",
21025
+ size: "sm",
21026
+ onClick: handleActionClick(action, itemData),
21027
+ "data-testid": `action-${action.event}`,
21028
+ "data-row-id": String(itemData.id),
21029
+ "aria-label": action.label,
21030
+ title: action.label,
21031
+ className: "text-error hover:text-error hover:bg-error/10 px-2",
21032
+ children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
21033
+ },
21034
+ `danger-${idx}`
21035
+ ))
21036
+ ] })
21037
+ ] }) }),
21038
+ bodyFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "px-4 pt-2 pb-4 flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", children: [
21039
+ bodyFields.filter((f3) => f3.variant === "caption" && f3.format !== "boolean").map((field) => {
21040
+ const value = getNestedValue(itemData, field.name);
21041
+ if (value === void 0 || value === null || value === "") return null;
21042
+ return /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", color: "secondary", className: "line-clamp-2", children: formatValue(value, field.format) }, field.name);
21043
+ }),
21044
+ /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "md", className: "flex-wrap gap-y-1", children: bodyFields.filter((f3) => f3.variant !== "caption" || f3.format === "boolean").map((field) => {
21045
+ const value = getNestedValue(itemData, field.name);
21046
+ if (value === void 0 || value === null || value === "") return null;
21047
+ if (field.format === "boolean") {
21048
+ return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
21049
+ field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
21050
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) }),
21051
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
21052
+ ] }, field.name);
21016
21053
  }
21017
- )
21054
+ return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
21055
+ field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
21056
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
21057
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", children: formatValue(value, field.format) })
21058
+ ] }, field.name);
21059
+ }) })
21018
21060
  ] }) })
21019
21061
  ]
21020
21062
  },
@@ -21362,11 +21404,29 @@ function DataList({
21362
21404
  const wrapDnd = (node) => dnd.isZone ? /* @__PURE__ */ jsxRuntime.jsx(dnd.SortableItem, { id: dndId, children: node }, dndId) : node;
21363
21405
  if (hasRenderProp) {
21364
21406
  const id2 = itemData.id || String(index);
21407
+ const actions = renderItemActions(itemData);
21365
21408
  return wrapDnd(
21366
- /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { "data-entity-row": true, "data-entity-id": id2, onClick: itemClickEvent ? handleRowClick(itemData) : void 0, className: cn(itemClickEvent && "cursor-pointer"), children: [
21367
- /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "group flex items-stretch gap-2", children: [
21368
- /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
21369
- renderItemActions(itemData)
21409
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { "data-entity-row": true, "data-entity-id": id2, onClick: itemClickEvent ? handleRowClick(itemData) : void 0, className: cn("relative group/rowactions", itemClickEvent && "cursor-pointer"), children: [
21410
+ children(itemData, index),
21411
+ actions && /* @__PURE__ */ jsxRuntime.jsxs(exports.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: [
21412
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5 [@media(pointer:coarse)]:hidden", children: actions }),
21413
+ /* @__PURE__ */ jsxRuntime.jsx(exports.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__ */ jsxRuntime.jsx(
21414
+ exports.Menu,
21415
+ {
21416
+ position: "bottom-end",
21417
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
21418
+ items: (itemActions ?? []).map((action) => ({
21419
+ label: action.label,
21420
+ icon: action.icon,
21421
+ event: action.event,
21422
+ variant: action.variant === "danger" ? "danger" : "default",
21423
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
21424
+ id: itemData.id,
21425
+ row: itemData
21426
+ })
21427
+ }))
21428
+ }
21429
+ ) })
21370
21430
  ] }),
21371
21431
  isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "mx-6 border-b border-border/40" })
21372
21432
  ] }, id2)
@@ -21406,7 +21466,7 @@ function DataList({
21406
21466
  ] }, field.name);
21407
21467
  })
21408
21468
  ] }),
21409
- bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
21469
+ bodyFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "md", className: cn("flex-wrap", isCompact ? "mt-0.5" : "mt-1.5"), children: bodyFields.map((field) => {
21410
21470
  const value = getNestedValue(itemData, field.name);
21411
21471
  if (value === void 0 || value === null || value === "") return null;
21412
21472
  return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
@@ -28656,7 +28716,7 @@ var init_MapView = __esm({
28656
28716
  shadowSize: [41, 41]
28657
28717
  });
28658
28718
  L.Marker.prototype.options.icon = defaultIcon;
28659
- const { useEffect: useEffect65, useRef: useRef63, useCallback: useCallback105, useState: useState102 } = React74__namespace.default;
28719
+ const { useEffect: useEffect65, useRef: useRef63, useCallback: useCallback106, useState: useState102 } = React74__namespace.default;
28660
28720
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
28661
28721
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
28662
28722
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -28702,7 +28762,7 @@ var init_MapView = __esm({
28702
28762
  }) {
28703
28763
  const eventBus = useEventBus2();
28704
28764
  const [clickedPosition, setClickedPosition] = useState102(null);
28705
- const handleMapClick = useCallback105((lat, lng) => {
28765
+ const handleMapClick = useCallback106((lat, lng) => {
28706
28766
  if (showClickedPin) {
28707
28767
  setClickedPosition({ lat, lng });
28708
28768
  }
@@ -28711,7 +28771,7 @@ var init_MapView = __esm({
28711
28771
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
28712
28772
  }
28713
28773
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
28714
- const handleMarkerClick = useCallback105((marker) => {
28774
+ const handleMarkerClick = useCallback106((marker) => {
28715
28775
  onMarkerClick?.(marker);
28716
28776
  if (markerClickEvent) {
28717
28777
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -29487,6 +29547,26 @@ var init_Lightbox = __esm({
29487
29547
  exports.Lightbox.displayName = "Lightbox";
29488
29548
  }
29489
29549
  });
29550
+ function useMediaQuery(query) {
29551
+ const subscribe = React74.useCallback(
29552
+ (onChange) => {
29553
+ const mql = window.matchMedia(query);
29554
+ mql.addEventListener("change", onChange);
29555
+ return () => mql.removeEventListener("change", onChange);
29556
+ },
29557
+ [query]
29558
+ );
29559
+ return React74.useSyncExternalStore(
29560
+ subscribe,
29561
+ () => window.matchMedia(query).matches,
29562
+ () => false
29563
+ );
29564
+ }
29565
+ var init_useMediaQuery = __esm({
29566
+ "hooks/useMediaQuery.ts"() {
29567
+ "use client";
29568
+ }
29569
+ });
29490
29570
  function renderIconInput3(icon, props) {
29491
29571
  return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon, ...props });
29492
29572
  }
@@ -29593,6 +29673,7 @@ function TableView({
29593
29673
  const hasMore = pageSize > 0 && visibleCount < ordered.length;
29594
29674
  const hasRenderProp = typeof children === "function";
29595
29675
  const idField = dndItemIdField ?? "id";
29676
+ const isCoarsePointer = useMediaQuery("(pointer: coarse)");
29596
29677
  const selected = selectedIds ? new Set(selectedIds) : localSelected;
29597
29678
  const emitSelection = (next) => {
29598
29679
  if (!selectedIds) setLocalSelected(next);
@@ -29625,6 +29706,17 @@ function TableView({
29625
29706
  };
29626
29707
  eventBus.emit(`UI:${action.event}`, payload);
29627
29708
  };
29709
+ const colFloors = React74__namespace.default.useMemo(
29710
+ () => colDefs.map((col) => {
29711
+ const longest = data.reduce((widest, row) => {
29712
+ const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
29713
+ return Math.max(widest, cell.length);
29714
+ }, columnLabel(col).length);
29715
+ const chrome = col.format === "badge" ? BADGE_CHROME_CH : 0;
29716
+ return Math.min(longest + chrome, MAX_MEASURED_COL_CH);
29717
+ }),
29718
+ [colDefs, data]
29719
+ );
29628
29720
  if (isLoading) {
29629
29721
  return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "body", color: "secondary", children: t("loading.items") }) });
29630
29722
  }
@@ -29637,20 +29729,10 @@ function TableView({
29637
29729
  }
29638
29730
  const lk = LOOKS[look];
29639
29731
  const hasActions = Boolean(itemActions && itemActions.length > 0);
29640
- const inlineActionCount = hasActions ? maxInlineActions != null ? Math.min(itemActions.length, maxInlineActions) : itemActions.length : 0;
29641
- const hasOverflowActions = hasActions && maxInlineActions != null && itemActions.length > maxInlineActions;
29732
+ const effectiveMaxInline = isCoarsePointer ? 0 : maxInlineActions;
29733
+ const inlineActionCount = hasActions ? effectiveMaxInline != null ? Math.min(itemActions.length, effectiveMaxInline) : itemActions.length : 0;
29734
+ const hasOverflowActions = hasActions && effectiveMaxInline != null && itemActions.length > effectiveMaxInline;
29642
29735
  const actionsTrack = hasActions ? `${inlineActionCount * 6 + (hasOverflowActions ? 3 : 0)}rem` : null;
29643
- const colFloors = React74__namespace.default.useMemo(
29644
- () => colDefs.map((col) => {
29645
- const longest = data.reduce((widest, row) => {
29646
- const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
29647
- return Math.max(widest, cell.length);
29648
- }, columnLabel(col).length);
29649
- const chrome = col.format === "badge" ? BADGE_CHROME_CH : 0;
29650
- return Math.min(longest + chrome, MAX_MEASURED_COL_CH);
29651
- }),
29652
- [colDefs, data]
29653
- );
29654
29736
  const gridTemplateColumns = [
29655
29737
  selectable ? "auto" : null,
29656
29738
  ...colDefs.map((c, i) => c.width ?? `minmax(${colFloors[i]}ch, 1fr)`),
@@ -29739,7 +29821,7 @@ function TableView({
29739
29821
  if (col.format === "badge" && raw != null && raw !== "") {
29740
29822
  return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: statusVariant4(String(raw)), size: "sm", className: "whitespace-nowrap", children: String(raw) }) }, col.key);
29741
29823
  }
29742
- return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
29824
+ return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format) }) }, col.key);
29743
29825
  }),
29744
29826
  itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
29745
29827
  exports.HStack,
@@ -29753,15 +29835,15 @@ function TableView({
29753
29835
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
29754
29836
  ),
29755
29837
  children: [
29756
- (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxRuntime.jsxs(
29838
+ (effectiveMaxInline != null ? itemActions.slice(0, effectiveMaxInline) : itemActions).map((action, i) => /* @__PURE__ */ jsxRuntime.jsxs(
29757
29839
  exports.Button,
29758
29840
  {
29759
- variant: action.variant ?? "ghost",
29841
+ variant: action.variant === "primary" ? "primary" : "ghost",
29760
29842
  size: "sm",
29761
29843
  onClick: handleActionClick(action, row),
29762
29844
  "data-testid": `action-${action.event}`,
29763
29845
  "data-row-id": String(row.id),
29764
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
29846
+ className: cn(action.variant === "danger" && "text-error hover:text-error hover:bg-error/10"),
29765
29847
  children: [
29766
29848
  action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
29767
29849
  action.label
@@ -29769,12 +29851,12 @@ function TableView({
29769
29851
  },
29770
29852
  i
29771
29853
  )),
29772
- maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
29854
+ effectiveMaxInline != null && itemActions.length > effectiveMaxInline && /* @__PURE__ */ jsxRuntime.jsx(
29773
29855
  exports.Menu,
29774
29856
  {
29775
29857
  position: "bottom-end",
29776
29858
  trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
29777
- items: itemActions.slice(maxInlineActions).map((action) => ({
29859
+ items: itemActions.slice(effectiveMaxInline).map((action) => ({
29778
29860
  label: action.label,
29779
29861
  icon: action.icon,
29780
29862
  event: action.event,
@@ -29827,6 +29909,7 @@ var init_TableView = __esm({
29827
29909
  init_cn();
29828
29910
  init_getNestedValue();
29829
29911
  init_useEventBus();
29912
+ init_useMediaQuery();
29830
29913
  init_Box();
29831
29914
  init_Stack();
29832
29915
  init_Typography();
@@ -29851,7 +29934,7 @@ var init_TableView = __esm({
29851
29934
  semibold: "font-semibold"
29852
29935
  };
29853
29936
  LOOKS = {
29854
- dense: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true },
29937
+ dense: { rowPad: "px-card-md py-2", headPad: "px-card-md py-2", striped: false, divider: true },
29855
29938
  spacious: { rowPad: "px-card-lg py-card-md", headPad: "px-card-lg py-card-sm", striped: false, divider: true },
29856
29939
  striped: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: true, divider: false },
29857
29940
  borderless: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: false },
@@ -38526,7 +38609,17 @@ function DataTable({
38526
38609
  const currentPageSize = pageSize ?? 20;
38527
38610
  const total = totalCount ?? items.length;
38528
38611
  const totalPages = Math.ceil(total / currentPageSize);
38529
- const rowActions = externalRowActions ?? itemActions?.filter((a) => a.placement !== "bulk").map((action) => ({
38612
+ const withEventClick = (action) => {
38613
+ if (action.onClick || !action.event) return action;
38614
+ const event = action.event;
38615
+ return {
38616
+ ...action,
38617
+ onClick: (row) => {
38618
+ eventBus.emit(`UI:${event}`, { row });
38619
+ }
38620
+ };
38621
+ };
38622
+ const rowActions = (externalRowActions ?? itemActions?.filter((a) => a.placement !== "bulk").map((action) => ({
38530
38623
  label: action.label,
38531
38624
  icon: action.icon,
38532
38625
  variant: action.variant,
@@ -38546,7 +38639,17 @@ function DataTable({
38546
38639
  });
38547
38640
  }
38548
38641
  }
38549
- }));
38642
+ })))?.map(withEventClick);
38643
+ const normalizedBulkActions = bulkActions?.map((action) => {
38644
+ if (action.onClick || !action.event) return action;
38645
+ const event = action.event;
38646
+ return {
38647
+ ...action,
38648
+ onClick: (selectedRows2) => {
38649
+ eventBus.emit(`UI:${event}`, { rows: selectedRows2 });
38650
+ }
38651
+ };
38652
+ });
38550
38653
  const viewAction = itemActions?.find(
38551
38654
  (a) => a.event === "VIEW" || a.navigatesTo
38552
38655
  );
@@ -38654,7 +38757,7 @@ function DataTable({
38654
38757
  }
38655
38758
  )
38656
38759
  ] }),
38657
- bulkActions && selectedIds.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { className: "items-center gap-2 pl-0 sm:pl-3 border-l-0 sm:border-l border-border", children: [
38760
+ normalizedBulkActions && selectedIds.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { className: "items-center gap-2 pl-0 sm:pl-3 border-l-0 sm:border-l border-border", children: [
38658
38761
  /* @__PURE__ */ jsxRuntime.jsx(
38659
38762
  exports.Typography,
38660
38763
  {
@@ -38665,13 +38768,13 @@ function DataTable({
38665
38768
  })
38666
38769
  }
38667
38770
  ),
38668
- /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { className: "flex-wrap gap-2", children: bulkActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
38771
+ /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { className: "flex-wrap gap-2", children: normalizedBulkActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
38669
38772
  exports.Button,
38670
38773
  {
38671
38774
  variant: action.variant === "danger" ? "danger" : "secondary",
38672
38775
  size: "sm",
38673
38776
  leftIcon: action.icon,
38674
- onClick: () => action.onClick(selectedRows),
38777
+ onClick: () => action.onClick?.(selectedRows),
38675
38778
  children: action.label
38676
38779
  },
38677
38780
  idx
@@ -38833,7 +38936,7 @@ function DataTable({
38833
38936
  ),
38834
38937
  onClick: (e) => {
38835
38938
  e.stopPropagation();
38836
- action.onClick(row);
38939
+ action.onClick?.(row);
38837
38940
  setOpenActionMenu(null);
38838
38941
  },
38839
38942
  children: [
@@ -41129,27 +41232,24 @@ var init_MasterDetailLayout = __esm({
41129
41232
  masterClassName,
41130
41233
  detailClassName
41131
41234
  }) => {
41132
- masterWidth.endsWith("%") ? parseInt(masterWidth, 10) : 30;
41133
41235
  return /* @__PURE__ */ jsxRuntime.jsxs(
41134
41236
  "div",
41135
41237
  {
41136
- className: cn("flex h-full w-full", className),
41137
- style: {
41138
- display: "grid",
41139
- gridTemplateColumns: masterWidth.endsWith("%") ? `${masterWidth} 1fr` : `${masterWidth} 1fr`
41140
- },
41238
+ className: cn("w-full h-full md:grid md:grid-cols-[var(--master-detail-cols)]", className),
41239
+ style: { "--master-detail-cols": `${masterWidth} 1fr` },
41141
41240
  children: [
41142
41241
  /* @__PURE__ */ jsxRuntime.jsx(
41143
41242
  "div",
41144
41243
  {
41145
41244
  className: cn(
41146
- "border-r-2 border-border overflow-auto",
41245
+ "border-r border-border overflow-auto",
41246
+ hasSelection && "hidden md:block",
41147
41247
  masterClassName
41148
41248
  ),
41149
41249
  children: master
41150
41250
  }
41151
41251
  ),
41152
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("overflow-auto", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsxRuntime.jsx(DefaultEmptyDetail, {}) })
41252
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("overflow-auto", !hasSelection && "hidden md:block", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsxRuntime.jsx(DefaultEmptyDetail, {}) })
41153
41253
  ]
41154
41254
  }
41155
41255
  );
@@ -48729,6 +48829,7 @@ init_useAuthContext();
48729
48829
  init_useSwipeGesture();
48730
48830
  init_useLongPress();
48731
48831
  init_useDragReorder();
48832
+ init_useMediaQuery();
48732
48833
  init_useInfiniteScroll();
48733
48834
  init_usePullToRefresh();
48734
48835
  init_useCanvasGestures();
@@ -49116,6 +49217,7 @@ exports.useGitHubStatus = useGitHubStatus;
49116
49217
  exports.useImageCache = useImageCache;
49117
49218
  exports.useInfiniteScroll = useInfiniteScroll;
49118
49219
  exports.useLongPress = useLongPress;
49220
+ exports.useMediaQuery = useMediaQuery;
49119
49221
  exports.useOrbitalHistory = useOrbitalHistory;
49120
49222
  exports.usePresence = usePresence;
49121
49223
  exports.usePreview = usePreview;