@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.
package/dist/avl/index.js CHANGED
@@ -5647,6 +5647,8 @@ var init_Badge = __esm({
5647
5647
  };
5648
5648
  const iconPx = size === "lg" ? 20 : 16;
5649
5649
  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;
5650
+ const hasText = Boolean(children) || amount != null || label !== void 0 && label !== null && label !== "";
5651
+ if (!hasText && !resolvedIcon && !onRemove) return null;
5650
5652
  return /* @__PURE__ */ jsxs(
5651
5653
  "span",
5652
5654
  {
@@ -8884,11 +8886,13 @@ var init_TrendIndicator = __esm({
8884
8886
  size = "md",
8885
8887
  ...props
8886
8888
  }, ref) => {
8887
- const dir = resolveDirection(value, direction);
8889
+ const hasValue = typeof value === "number" && Number.isFinite(value);
8890
+ if (!hasValue && !direction) return null;
8891
+ const dir = resolveDirection(hasValue ? value : void 0, direction);
8888
8892
  const colorClass = resolveColor(dir, invert);
8889
8893
  const iconName = iconNameMap[dir];
8890
8894
  const styles = sizeStyles6[size];
8891
- const formattedValue = value !== void 0 ? `${value > 0 ? "+" : ""}${value}%` : void 0;
8895
+ const formattedValue = hasValue ? `${value > 0 ? "+" : ""}${value}%` : void 0;
8892
8896
  const ariaLabel = label ?? (formattedValue ? `${dir} ${formattedValue}` : dir);
8893
8897
  return /* @__PURE__ */ jsxs(
8894
8898
  "span",
@@ -20310,26 +20314,19 @@ var init_BookViewer = __esm({
20310
20314
  function BoxPattern({
20311
20315
  p,
20312
20316
  m,
20313
- bg = "transparent",
20314
- border = false,
20315
- radius = "none",
20316
- shadow = "none",
20317
- className,
20318
- style,
20319
- children
20317
+ radius,
20318
+ isLoading: _isLoading,
20319
+ error: _error,
20320
+ entity: _entity,
20321
+ ...boxProps
20320
20322
  }) {
20321
20323
  return /* @__PURE__ */ jsx(
20322
20324
  Box,
20323
20325
  {
20324
- padding: p,
20325
- margin: m,
20326
- bg,
20327
- border,
20328
- rounded: radius,
20329
- shadow,
20330
- className,
20331
- style,
20332
- children
20326
+ padding: boxProps.padding ?? p,
20327
+ margin: boxProps.margin ?? m,
20328
+ rounded: boxProps.rounded ?? radius,
20329
+ ...boxProps
20333
20330
  }
20334
20331
  );
20335
20332
  }
@@ -24020,17 +24017,19 @@ var init_DashboardLayout = __esm({
24020
24017
  const [sidebarOpen, setSidebarOpen] = useState(false);
24021
24018
  const [userMenuOpen, setUserMenuOpen] = useState(false);
24022
24019
  const layoutRef = useRef(null);
24023
- const [isMobile, setIsMobile] = useState(false);
24020
+ const [layoutWidth, setLayoutWidth] = useState(null);
24024
24021
  useEffect(() => {
24025
24022
  const el = layoutRef.current;
24026
24023
  if (!el || typeof ResizeObserver === "undefined") return;
24027
24024
  const ro = new ResizeObserver((entries) => {
24028
24025
  const w = entries[0]?.contentRect.width ?? el.clientWidth;
24029
- setIsMobile(w < 1024);
24026
+ setLayoutWidth(w);
24030
24027
  });
24031
24028
  ro.observe(el);
24032
24029
  return () => ro.disconnect();
24033
24030
  }, []);
24031
+ const isMobile = layoutWidth !== null && layoutWidth < 768;
24032
+ const isRail = layoutWidth !== null && layoutWidth >= 768 && layoutWidth < 1024;
24034
24033
  useEffect(() => {
24035
24034
  if (!isMobile && sidebarOpen) setSidebarOpen(false);
24036
24035
  }, [isMobile, sidebarOpen]);
@@ -24063,7 +24062,8 @@ var init_DashboardLayout = __esm({
24063
24062
  {
24064
24063
  as: "aside",
24065
24064
  className: cn(
24066
- "z-30 w-64 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
24065
+ "z-30 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
24066
+ isRail ? "w-16" : "w-64",
24067
24067
  "flex flex-col"
24068
24068
  ),
24069
24069
  style: isMobile ? {
@@ -24079,10 +24079,10 @@ var init_DashboardLayout = __esm({
24079
24079
  HStack,
24080
24080
  {
24081
24081
  align: "center",
24082
- justify: "between",
24083
- className: "h-16 px-4 border-b border-border dark:border-border",
24082
+ justify: isRail ? "center" : "between",
24083
+ className: cn("h-16 border-b border-border dark:border-border", isRail ? "px-2" : "px-4"),
24084
24084
  children: [
24085
- /* @__PURE__ */ jsxs(Link, { to: "/", className: "flex items-center gap-2", children: [
24085
+ /* @__PURE__ */ jsxs(Link, { to: "/", className: "flex items-center gap-2", title: isRail ? appName : void 0, children: [
24086
24086
  logo || /* @__PURE__ */ jsx(Box, { className: "w-8 h-8 bg-primary rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsx(
24087
24087
  Typography,
24088
24088
  {
@@ -24092,7 +24092,7 @@ var init_DashboardLayout = __esm({
24092
24092
  children: appName.charAt(0).toUpperCase()
24093
24093
  }
24094
24094
  ) }),
24095
- /* @__PURE__ */ jsx(
24095
+ !isRail && /* @__PURE__ */ jsx(
24096
24096
  Typography,
24097
24097
  {
24098
24098
  variant: "label",
@@ -24119,12 +24119,13 @@ var init_DashboardLayout = __esm({
24119
24119
  {
24120
24120
  as: "nav",
24121
24121
  gap: "none",
24122
- className: "flex-1 px-3 py-4 space-y-1 overflow-y-auto",
24122
+ className: cn("flex-1 py-4 space-y-1 overflow-y-auto", isRail ? "px-2" : "px-3"),
24123
24123
  children: navItems.map((item) => /* @__PURE__ */ jsx(
24124
24124
  NavLink,
24125
24125
  {
24126
24126
  item,
24127
- currentPath: activePath
24127
+ currentPath: activePath,
24128
+ compact: isRail
24128
24129
  },
24129
24130
  item.href
24130
24131
  ))
@@ -24379,13 +24380,40 @@ var init_DashboardLayout = __esm({
24379
24380
  DashboardLayout.displayName = "DashboardLayout";
24380
24381
  NavLink = ({
24381
24382
  item,
24382
- currentPath
24383
+ currentPath,
24384
+ compact = false
24383
24385
  }) => {
24384
24386
  const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
24385
24387
  const iconClassName = cn(
24386
24388
  "h-5 w-5",
24387
24389
  isActive ? "text-primary-foreground" : "text-muted-foreground"
24388
24390
  );
24391
+ if (compact) {
24392
+ return /* @__PURE__ */ jsx(
24393
+ Link,
24394
+ {
24395
+ to: item.href,
24396
+ title: item.label,
24397
+ "aria-label": item.label,
24398
+ className: cn(
24399
+ "flex items-center justify-center px-2 py-2 rounded-lg transition-colors",
24400
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
24401
+ ),
24402
+ children: /* @__PURE__ */ jsxs(Box, { as: "span", className: "relative inline-flex", children: [
24403
+ 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() }),
24404
+ item.badge && /* @__PURE__ */ jsx(
24405
+ Badge,
24406
+ {
24407
+ variant: isActive ? "primary" : "default",
24408
+ size: "sm",
24409
+ className: "absolute -top-2 -right-2 px-1 py-0 text-[10px] leading-4",
24410
+ children: item.badge
24411
+ }
24412
+ )
24413
+ ] })
24414
+ }
24415
+ );
24416
+ }
24389
24417
  return /* @__PURE__ */ jsxs(
24390
24418
  Link,
24391
24419
  {
@@ -25451,40 +25479,55 @@ function DataGrid({
25451
25479
  {
25452
25480
  "data-entity-row": true,
25453
25481
  "data-entity-id": id,
25454
- className: cn(isSelected && "ring-2 ring-primary rounded-lg"),
25482
+ className: cn("relative group/rowactions", isSelected && "ring-2 ring-primary rounded-lg"),
25455
25483
  children: [
25456
25484
  children(itemData, index),
25457
- 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: [
25458
- (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxs(
25459
- Button,
25460
- {
25461
- variant: action.variant === "primary" ? "primary" : "ghost",
25462
- size: "sm",
25463
- onClick: handleActionClick(action, itemData),
25464
- "data-testid": `action-${action.event}`,
25465
- "data-row-id": String(itemData.id),
25466
- className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
25467
- children: [
25468
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
25469
- action.label
25470
- ]
25471
- },
25472
- idx
25473
- )),
25474
- maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
25485
+ 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: [
25486
+ /* @__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: [
25487
+ (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxs(
25488
+ Button,
25489
+ {
25490
+ variant: action.variant === "primary" ? "primary" : "ghost",
25491
+ size: "sm",
25492
+ onClick: handleActionClick(action, itemData),
25493
+ "data-testid": `action-${action.event}`,
25494
+ "data-row-id": String(itemData.id),
25495
+ className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
25496
+ children: [
25497
+ action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
25498
+ action.label
25499
+ ]
25500
+ },
25501
+ idx
25502
+ )),
25503
+ maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
25504
+ Menu,
25505
+ {
25506
+ position: "bottom-end",
25507
+ 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" }) }),
25508
+ items: actionDefs.slice(maxInlineActions).map((action) => ({
25509
+ label: action.label,
25510
+ icon: action.icon,
25511
+ event: action.event,
25512
+ onClick: () => fireAction(action, itemData)
25513
+ }))
25514
+ }
25515
+ )
25516
+ ] }),
25517
+ /* @__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(
25475
25518
  Menu,
25476
25519
  {
25477
25520
  position: "bottom-end",
25478
25521
  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" }) }),
25479
- items: actionDefs.slice(maxInlineActions).map((action) => ({
25522
+ items: actionDefs.map((action) => ({
25480
25523
  label: action.label,
25481
25524
  icon: action.icon,
25482
25525
  event: action.event,
25483
25526
  onClick: () => fireAction(action, itemData)
25484
25527
  }))
25485
25528
  }
25486
- )
25487
- ] }) })
25529
+ ) })
25530
+ ] })
25488
25531
  ]
25489
25532
  },
25490
25533
  id
@@ -25520,7 +25563,7 @@ function DataGrid({
25520
25563
  }
25521
25564
  ) });
25522
25565
  })(),
25523
- /* @__PURE__ */ jsx(Box, { className: "p-4 pb-0", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
25566
+ /* @__PURE__ */ jsx(Box, { className: cn("p-4", bodyFields.length > 0 && "pb-0"), children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
25524
25567
  selectable && /* @__PURE__ */ jsx(
25525
25568
  "input",
25526
25569
  {
@@ -25553,78 +25596,77 @@ function DataGrid({
25553
25596
  ] }, field.name);
25554
25597
  }) })
25555
25598
  ] }),
25556
- dangerActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsx(
25557
- Button,
25558
- {
25559
- variant: "ghost",
25560
- size: "sm",
25561
- onClick: handleActionClick(action, itemData),
25562
- "data-testid": `action-${action.event}`,
25563
- "data-row-id": String(itemData.id),
25564
- "aria-label": action.label,
25565
- title: action.label,
25566
- className: "text-error hover:text-error hover:bg-error/10 px-2",
25567
- children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
25568
- },
25569
- idx
25570
- )) })
25571
- ] }) }),
25572
- bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: bodyFields.map((field) => {
25573
- const value = getNestedValue(itemData, field.name);
25574
- if (value === void 0 || value === null || value === "") return null;
25575
- if (field.format === "boolean") {
25576
- return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
25577
- /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
25578
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
25579
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
25580
- ] }),
25581
- /* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
25582
- ] }, field.name);
25583
- }
25584
- return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
25585
- /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
25586
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
25587
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
25588
- ] }),
25589
- /* @__PURE__ */ jsx(
25590
- Typography,
25599
+ (primaryActions.length > 0 || dangerActions.length > 0) && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "flex-shrink-0", children: [
25600
+ (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsx(
25601
+ Button,
25602
+ {
25603
+ variant: action.variant === "primary" ? "primary" : "ghost",
25604
+ size: "sm",
25605
+ onClick: handleActionClick(action, itemData),
25606
+ "data-testid": `action-${action.event}`,
25607
+ "data-row-id": String(itemData.id),
25608
+ "aria-label": action.label,
25609
+ title: action.label,
25610
+ className: cn(
25611
+ action.variant === "primary" ? void 0 : "text-muted-foreground hover:text-foreground",
25612
+ action.icon && "px-2"
25613
+ ),
25614
+ children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
25615
+ },
25616
+ idx
25617
+ )),
25618
+ maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsx(
25619
+ Menu,
25591
25620
  {
25592
- variant: field.variant === "caption" ? "caption" : "small",
25593
- className: "text-right truncate max-w-[60%]",
25594
- children: formatValue(value, field.format)
25621
+ position: "bottom-end",
25622
+ 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" }) }),
25623
+ items: primaryActions.slice(maxInlineActions).map((action) => ({
25624
+ label: action.label,
25625
+ icon: action.icon,
25626
+ event: action.event,
25627
+ onClick: () => fireAction(action, itemData)
25628
+ }))
25595
25629
  }
25596
- )
25597
- ] }, field.name);
25598
- }) }) }),
25599
- 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: [
25600
- (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxs(
25601
- Button,
25602
- {
25603
- variant: action.variant === "primary" ? "primary" : "ghost",
25604
- size: "sm",
25605
- onClick: handleActionClick(action, itemData),
25606
- "data-testid": `action-${action.event}`,
25607
- "data-row-id": String(itemData.id),
25608
- children: [
25609
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
25610
- action.label
25611
- ]
25612
- },
25613
- idx
25614
- )),
25615
- maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsx(
25616
- Menu,
25617
- {
25618
- position: "bottom-end",
25619
- 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" }) }),
25620
- items: primaryActions.slice(maxInlineActions).map((action) => ({
25621
- label: action.label,
25622
- icon: action.icon,
25623
- event: action.event,
25624
- onClick: () => fireAction(action, itemData)
25625
- }))
25630
+ ),
25631
+ dangerActions.map((action, idx) => /* @__PURE__ */ jsx(
25632
+ Button,
25633
+ {
25634
+ variant: "ghost",
25635
+ size: "sm",
25636
+ onClick: handleActionClick(action, itemData),
25637
+ "data-testid": `action-${action.event}`,
25638
+ "data-row-id": String(itemData.id),
25639
+ "aria-label": action.label,
25640
+ title: action.label,
25641
+ className: "text-error hover:text-error hover:bg-error/10 px-2",
25642
+ children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
25643
+ },
25644
+ `danger-${idx}`
25645
+ ))
25646
+ ] })
25647
+ ] }) }),
25648
+ bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 pt-2 pb-4 flex-1", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
25649
+ bodyFields.filter((f3) => f3.variant === "caption" && f3.format !== "boolean").map((field) => {
25650
+ const value = getNestedValue(itemData, field.name);
25651
+ if (value === void 0 || value === null || value === "") return null;
25652
+ return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", className: "line-clamp-2", children: formatValue(value, field.format) }, field.name);
25653
+ }),
25654
+ /* @__PURE__ */ jsx(HStack, { gap: "md", className: "flex-wrap gap-y-1", children: bodyFields.filter((f3) => f3.variant !== "caption" || f3.format === "boolean").map((field) => {
25655
+ const value = getNestedValue(itemData, field.name);
25656
+ if (value === void 0 || value === null || value === "") return null;
25657
+ if (field.format === "boolean") {
25658
+ return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
25659
+ field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
25660
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) }),
25661
+ /* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
25662
+ ] }, field.name);
25626
25663
  }
25627
- )
25664
+ return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
25665
+ field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
25666
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
25667
+ /* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue(value, field.format) })
25668
+ ] }, field.name);
25669
+ }) })
25628
25670
  ] }) })
25629
25671
  ]
25630
25672
  },
@@ -25972,11 +26014,29 @@ function DataList({
25972
26014
  const wrapDnd = (node) => dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: dndId, children: node }, dndId) : node;
25973
26015
  if (hasRenderProp) {
25974
26016
  const id2 = itemData.id || String(index);
26017
+ const actions = renderItemActions(itemData);
25975
26018
  return wrapDnd(
25976
- /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick: itemClickEvent ? handleRowClick(itemData) : void 0, className: cn(itemClickEvent && "cursor-pointer"), children: [
25977
- /* @__PURE__ */ jsxs(Box, { className: "group flex items-stretch gap-2", children: [
25978
- /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
25979
- renderItemActions(itemData)
26019
+ /* @__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: [
26020
+ children(itemData, index),
26021
+ 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: [
26022
+ /* @__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 }),
26023
+ /* @__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(
26024
+ Menu,
26025
+ {
26026
+ position: "bottom-end",
26027
+ 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" }) }),
26028
+ items: (itemActions ?? []).map((action) => ({
26029
+ label: action.label,
26030
+ icon: action.icon,
26031
+ event: action.event,
26032
+ variant: action.variant === "danger" ? "danger" : "default",
26033
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
26034
+ id: itemData.id,
26035
+ row: itemData
26036
+ })
26037
+ }))
26038
+ }
26039
+ ) })
25980
26040
  ] }),
25981
26041
  isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-border/40" })
25982
26042
  ] }, id2)
@@ -26016,7 +26076,7 @@ function DataList({
26016
26076
  ] }, field.name);
26017
26077
  })
26018
26078
  ] }),
26019
- bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsx(HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
26079
+ bodyFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "md", className: cn("flex-wrap", isCompact ? "mt-0.5" : "mt-1.5"), children: bodyFields.map((field) => {
26020
26080
  const value = getNestedValue(itemData, field.name);
26021
26081
  if (value === void 0 || value === null || value === "") return null;
26022
26082
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
@@ -29612,7 +29672,7 @@ var init_MapView = __esm({
29612
29672
  shadowSize: [41, 41]
29613
29673
  });
29614
29674
  L.Marker.prototype.options.icon = defaultIcon;
29615
- const { useEffect: useEffect63, useRef: useRef62, useCallback: useCallback93, useState: useState97 } = React91__default;
29675
+ const { useEffect: useEffect63, useRef: useRef62, useCallback: useCallback94, useState: useState97 } = React91__default;
29616
29676
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29617
29677
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29618
29678
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -29658,7 +29718,7 @@ var init_MapView = __esm({
29658
29718
  }) {
29659
29719
  const eventBus = useEventBus2();
29660
29720
  const [clickedPosition, setClickedPosition] = useState97(null);
29661
- const handleMapClick = useCallback93((lat, lng) => {
29721
+ const handleMapClick = useCallback94((lat, lng) => {
29662
29722
  if (showClickedPin) {
29663
29723
  setClickedPosition({ lat, lng });
29664
29724
  }
@@ -29667,7 +29727,7 @@ var init_MapView = __esm({
29667
29727
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
29668
29728
  }
29669
29729
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
29670
- const handleMarkerClick = useCallback93((marker) => {
29730
+ const handleMarkerClick = useCallback94((marker) => {
29671
29731
  onMarkerClick?.(marker);
29672
29732
  if (markerClickEvent) {
29673
29733
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -30443,6 +30503,26 @@ var init_Lightbox = __esm({
30443
30503
  Lightbox.displayName = "Lightbox";
30444
30504
  }
30445
30505
  });
30506
+ function useMediaQuery(query) {
30507
+ const subscribe = useCallback(
30508
+ (onChange) => {
30509
+ const mql = window.matchMedia(query);
30510
+ mql.addEventListener("change", onChange);
30511
+ return () => mql.removeEventListener("change", onChange);
30512
+ },
30513
+ [query]
30514
+ );
30515
+ return useSyncExternalStore(
30516
+ subscribe,
30517
+ () => window.matchMedia(query).matches,
30518
+ () => false
30519
+ );
30520
+ }
30521
+ var init_useMediaQuery = __esm({
30522
+ "hooks/useMediaQuery.ts"() {
30523
+ "use client";
30524
+ }
30525
+ });
30446
30526
  function renderIconInput3(icon, props) {
30447
30527
  return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
30448
30528
  }
@@ -30549,6 +30629,7 @@ function TableView({
30549
30629
  const hasMore = pageSize > 0 && visibleCount < ordered.length;
30550
30630
  const hasRenderProp = typeof children === "function";
30551
30631
  const idField = dndItemIdField ?? "id";
30632
+ const isCoarsePointer = useMediaQuery("(pointer: coarse)");
30552
30633
  const selected = selectedIds ? new Set(selectedIds) : localSelected;
30553
30634
  const emitSelection = (next) => {
30554
30635
  if (!selectedIds) setLocalSelected(next);
@@ -30581,6 +30662,17 @@ function TableView({
30581
30662
  };
30582
30663
  eventBus.emit(`UI:${action.event}`, payload);
30583
30664
  };
30665
+ const colFloors = React91__default.useMemo(
30666
+ () => colDefs.map((col) => {
30667
+ const longest = data.reduce((widest, row) => {
30668
+ const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
30669
+ return Math.max(widest, cell.length);
30670
+ }, columnLabel(col).length);
30671
+ const chrome = col.format === "badge" ? BADGE_CHROME_CH : 0;
30672
+ return Math.min(longest + chrome, MAX_MEASURED_COL_CH);
30673
+ }),
30674
+ [colDefs, data]
30675
+ );
30584
30676
  if (isLoading) {
30585
30677
  return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") }) });
30586
30678
  }
@@ -30593,20 +30685,10 @@ function TableView({
30593
30685
  }
30594
30686
  const lk = LOOKS[look];
30595
30687
  const hasActions = Boolean(itemActions && itemActions.length > 0);
30596
- const inlineActionCount = hasActions ? maxInlineActions != null ? Math.min(itemActions.length, maxInlineActions) : itemActions.length : 0;
30597
- const hasOverflowActions = hasActions && maxInlineActions != null && itemActions.length > maxInlineActions;
30688
+ const effectiveMaxInline = isCoarsePointer ? 0 : maxInlineActions;
30689
+ const inlineActionCount = hasActions ? effectiveMaxInline != null ? Math.min(itemActions.length, effectiveMaxInline) : itemActions.length : 0;
30690
+ const hasOverflowActions = hasActions && effectiveMaxInline != null && itemActions.length > effectiveMaxInline;
30598
30691
  const actionsTrack = hasActions ? `${inlineActionCount * 6 + (hasOverflowActions ? 3 : 0)}rem` : null;
30599
- const colFloors = React91__default.useMemo(
30600
- () => colDefs.map((col) => {
30601
- const longest = data.reduce((widest, row) => {
30602
- const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
30603
- return Math.max(widest, cell.length);
30604
- }, columnLabel(col).length);
30605
- const chrome = col.format === "badge" ? BADGE_CHROME_CH : 0;
30606
- return Math.min(longest + chrome, MAX_MEASURED_COL_CH);
30607
- }),
30608
- [colDefs, data]
30609
- );
30610
30692
  const gridTemplateColumns = [
30611
30693
  selectable ? "auto" : null,
30612
30694
  ...colDefs.map((c, i) => c.width ?? `minmax(${colFloors[i]}ch, 1fr)`),
@@ -30695,7 +30777,7 @@ function TableView({
30695
30777
  if (col.format === "badge" && raw != null && raw !== "") {
30696
30778
  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);
30697
30779
  }
30698
- return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
30780
+ return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format) }) }, col.key);
30699
30781
  }),
30700
30782
  itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxs(
30701
30783
  HStack,
@@ -30709,15 +30791,15 @@ function TableView({
30709
30791
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
30710
30792
  ),
30711
30793
  children: [
30712
- (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
30794
+ (effectiveMaxInline != null ? itemActions.slice(0, effectiveMaxInline) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
30713
30795
  Button,
30714
30796
  {
30715
- variant: action.variant ?? "ghost",
30797
+ variant: action.variant === "primary" ? "primary" : "ghost",
30716
30798
  size: "sm",
30717
30799
  onClick: handleActionClick(action, row),
30718
30800
  "data-testid": `action-${action.event}`,
30719
30801
  "data-row-id": String(row.id),
30720
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
30802
+ className: cn(action.variant === "danger" && "text-error hover:text-error hover:bg-error/10"),
30721
30803
  children: [
30722
30804
  action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
30723
30805
  action.label
@@ -30725,12 +30807,12 @@ function TableView({
30725
30807
  },
30726
30808
  i
30727
30809
  )),
30728
- maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsx(
30810
+ effectiveMaxInline != null && itemActions.length > effectiveMaxInline && /* @__PURE__ */ jsx(
30729
30811
  Menu,
30730
30812
  {
30731
30813
  position: "bottom-end",
30732
30814
  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" }) }),
30733
- items: itemActions.slice(maxInlineActions).map((action) => ({
30815
+ items: itemActions.slice(effectiveMaxInline).map((action) => ({
30734
30816
  label: action.label,
30735
30817
  icon: action.icon,
30736
30818
  event: action.event,
@@ -30783,6 +30865,7 @@ var init_TableView = __esm({
30783
30865
  init_cn();
30784
30866
  init_getNestedValue();
30785
30867
  init_useEventBus();
30868
+ init_useMediaQuery();
30786
30869
  init_Box();
30787
30870
  init_Stack();
30788
30871
  init_Typography();
@@ -30807,7 +30890,7 @@ var init_TableView = __esm({
30807
30890
  semibold: "font-semibold"
30808
30891
  };
30809
30892
  LOOKS = {
30810
- dense: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true },
30893
+ dense: { rowPad: "px-card-md py-2", headPad: "px-card-md py-2", striped: false, divider: true },
30811
30894
  spacious: { rowPad: "px-card-lg py-card-md", headPad: "px-card-lg py-card-sm", striped: false, divider: true },
30812
30895
  striped: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: true, divider: false },
30813
30896
  borderless: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: false },
@@ -38852,7 +38935,17 @@ function DataTable({
38852
38935
  const currentPageSize = pageSize ?? 20;
38853
38936
  const total = totalCount ?? items.length;
38854
38937
  const totalPages = Math.ceil(total / currentPageSize);
38855
- const rowActions = externalRowActions ?? itemActions?.filter((a) => a.placement !== "bulk").map((action) => ({
38938
+ const withEventClick = (action) => {
38939
+ if (action.onClick || !action.event) return action;
38940
+ const event = action.event;
38941
+ return {
38942
+ ...action,
38943
+ onClick: (row) => {
38944
+ eventBus.emit(`UI:${event}`, { row });
38945
+ }
38946
+ };
38947
+ };
38948
+ const rowActions = (externalRowActions ?? itemActions?.filter((a) => a.placement !== "bulk").map((action) => ({
38856
38949
  label: action.label,
38857
38950
  icon: action.icon,
38858
38951
  variant: action.variant,
@@ -38872,7 +38965,17 @@ function DataTable({
38872
38965
  });
38873
38966
  }
38874
38967
  }
38875
- }));
38968
+ })))?.map(withEventClick);
38969
+ const normalizedBulkActions = bulkActions?.map((action) => {
38970
+ if (action.onClick || !action.event) return action;
38971
+ const event = action.event;
38972
+ return {
38973
+ ...action,
38974
+ onClick: (selectedRows2) => {
38975
+ eventBus.emit(`UI:${event}`, { rows: selectedRows2 });
38976
+ }
38977
+ };
38978
+ });
38876
38979
  const viewAction = itemActions?.find(
38877
38980
  (a) => a.event === "VIEW" || a.navigatesTo
38878
38981
  );
@@ -38980,7 +39083,7 @@ function DataTable({
38980
39083
  }
38981
39084
  )
38982
39085
  ] }),
38983
- bulkActions && selectedIds.length > 0 && /* @__PURE__ */ jsxs(HStack, { className: "items-center gap-2 pl-0 sm:pl-3 border-l-0 sm:border-l border-border", children: [
39086
+ normalizedBulkActions && selectedIds.length > 0 && /* @__PURE__ */ jsxs(HStack, { className: "items-center gap-2 pl-0 sm:pl-3 border-l-0 sm:border-l border-border", children: [
38984
39087
  /* @__PURE__ */ jsx(
38985
39088
  Typography,
38986
39089
  {
@@ -38991,13 +39094,13 @@ function DataTable({
38991
39094
  })
38992
39095
  }
38993
39096
  ),
38994
- /* @__PURE__ */ jsx(HStack, { className: "flex-wrap gap-2", children: bulkActions.map((action, idx) => /* @__PURE__ */ jsx(
39097
+ /* @__PURE__ */ jsx(HStack, { className: "flex-wrap gap-2", children: normalizedBulkActions.map((action, idx) => /* @__PURE__ */ jsx(
38995
39098
  Button,
38996
39099
  {
38997
39100
  variant: action.variant === "danger" ? "danger" : "secondary",
38998
39101
  size: "sm",
38999
39102
  leftIcon: action.icon,
39000
- onClick: () => action.onClick(selectedRows),
39103
+ onClick: () => action.onClick?.(selectedRows),
39001
39104
  children: action.label
39002
39105
  },
39003
39106
  idx
@@ -39159,7 +39262,7 @@ function DataTable({
39159
39262
  ),
39160
39263
  onClick: (e) => {
39161
39264
  e.stopPropagation();
39162
- action.onClick(row);
39265
+ action.onClick?.(row);
39163
39266
  setOpenActionMenu(null);
39164
39267
  },
39165
39268
  children: [
@@ -41455,27 +41558,24 @@ var init_MasterDetailLayout = __esm({
41455
41558
  masterClassName,
41456
41559
  detailClassName
41457
41560
  }) => {
41458
- masterWidth.endsWith("%") ? parseInt(masterWidth, 10) : 30;
41459
41561
  return /* @__PURE__ */ jsxs(
41460
41562
  "div",
41461
41563
  {
41462
- className: cn("flex h-full w-full", className),
41463
- style: {
41464
- display: "grid",
41465
- gridTemplateColumns: masterWidth.endsWith("%") ? `${masterWidth} 1fr` : `${masterWidth} 1fr`
41466
- },
41564
+ className: cn("w-full h-full md:grid md:grid-cols-[var(--master-detail-cols)]", className),
41565
+ style: { "--master-detail-cols": `${masterWidth} 1fr` },
41467
41566
  children: [
41468
41567
  /* @__PURE__ */ jsx(
41469
41568
  "div",
41470
41569
  {
41471
41570
  className: cn(
41472
- "border-r-2 border-border overflow-auto",
41571
+ "border-r border-border overflow-auto",
41572
+ hasSelection && "hidden md:block",
41473
41573
  masterClassName
41474
41574
  ),
41475
41575
  children: master
41476
41576
  }
41477
41577
  ),
41478
- /* @__PURE__ */ jsx("div", { className: cn("overflow-auto", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsx(DefaultEmptyDetail, {}) })
41578
+ /* @__PURE__ */ jsx("div", { className: cn("overflow-auto", !hasSelection && "hidden md:block", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsx(DefaultEmptyDetail, {}) })
41479
41579
  ]
41480
41580
  }
41481
41581
  );