@almadar/ui 5.130.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.
@@ -1857,7 +1857,7 @@ var init_Button = __esm({
1857
1857
  "cursor-pointer",
1858
1858
  "chrome-button",
1859
1859
  "transition-all duration-normal",
1860
- "focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-ring focus:ring-offset-[length:var(--focus-ring-offset)]",
1860
+ "focus:outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-offset-[length:var(--focus-ring-offset)]",
1861
1861
  "disabled:opacity-50 disabled:cursor-not-allowed",
1862
1862
  variantStyles[variant],
1863
1863
  sizeStyles[size],
@@ -2155,7 +2155,7 @@ function NativeSelect({
2155
2155
  "block w-full border-[length:var(--border-width)] shadow-sm appearance-none",
2156
2156
  "px-3 py-2 pr-10 text-sm text-foreground font-medium",
2157
2157
  "bg-card",
2158
- "focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-ring",
2158
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-ring",
2159
2159
  "disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed",
2160
2160
  error ? "border-error focus:border-error" : "border-border focus:border-primary",
2161
2161
  className
@@ -2262,7 +2262,7 @@ function RichSelect({
2262
2262
  "block w-full border-[length:var(--border-width)] shadow-sm",
2263
2263
  "px-3 py-2 pr-10 text-sm text-start font-medium",
2264
2264
  "bg-card rounded-sm",
2265
- "focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-ring",
2265
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-ring",
2266
2266
  "disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed",
2267
2267
  error ? "border-error focus:border-error" : "border-border focus:border-primary",
2268
2268
  !hasValue && "text-muted-foreground"
@@ -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
  {
@@ -2636,7 +2638,7 @@ var init_Badge = __esm({
2636
2638
  },
2637
2639
  className: cn(
2638
2640
  "inline-flex items-center justify-center rounded-sm",
2639
- "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
2641
+ "hover:bg-foreground/10 focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2640
2642
  "transition-colors",
2641
2643
  size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
2642
2644
  ),
@@ -3536,9 +3538,9 @@ var init_Radio = __esm({
3536
3538
  "flex items-center justify-center",
3537
3539
  "border-[length:var(--border-width)] transition-all cursor-pointer",
3538
3540
  sizeClasses3[size],
3539
- hasError ? "border-error peer-focus:ring-error/20" : "border-border peer-focus:ring-ring/20",
3541
+ hasError ? "border-error peer-focus-visible:ring-error/20" : "border-border peer-focus-visible:ring-ring/20",
3540
3542
  isChecked2 ? hasError ? "border-error" : "border-primary bg-primary" : "",
3541
- "peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-offset-2",
3543
+ "peer-focus:outline-none peer-focus-visible:ring-2 peer-focus-visible:ring-offset-2",
3542
3544
  disabled && "opacity-50 cursor-not-allowed",
3543
3545
  !disabled && "hover:border-[var(--color-border-hover)]"
3544
3546
  ),
@@ -4133,7 +4135,7 @@ var init_ThemeToggle = __esm({
4133
4135
  "inline-flex items-center justify-center gap-2",
4134
4136
  "text-foreground",
4135
4137
  "hover:bg-muted border-[length:var(--border-width)] border-transparent hover:border-border",
4136
- "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
4138
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
4137
4139
  "transition-colors duration-fast",
4138
4140
  sizeClasses4[size],
4139
4141
  className
@@ -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",
@@ -7032,10 +7036,12 @@ var init_Container = __esm({
7032
7036
  };
7033
7037
  paddingStyles3 = {
7034
7038
  none: "px-0",
7035
- sm: "px-4",
7036
- md: "px-6",
7037
- lg: "px-8",
7038
- xl: "px-12"
7039
+ // Mobile-tighter, desktop-identical: fixed px-6 on a 360px phone eats ~13% of
7040
+ // the viewport, so each token steps down below the sm breakpoint.
7041
+ sm: "px-3 sm:px-4",
7042
+ md: "px-4 sm:px-6",
7043
+ lg: "px-4 sm:px-6 md:px-8",
7044
+ xl: "px-4 sm:px-8 md:px-12"
7039
7045
  };
7040
7046
  exports.Container = ({
7041
7047
  size,
@@ -7734,7 +7740,7 @@ var init_Accordion = __esm({
7734
7740
  "bg-card",
7735
7741
  "hover:bg-muted",
7736
7742
  "transition-colors duration-fast",
7737
- "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-inset",
7743
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset",
7738
7744
  "disabled:opacity-50 disabled:cursor-not-allowed",
7739
7745
  isOpen && "bg-muted font-bold"
7740
7746
  ),
@@ -13730,26 +13736,19 @@ var init_BookViewer = __esm({
13730
13736
  function BoxPattern({
13731
13737
  p,
13732
13738
  m,
13733
- bg = "transparent",
13734
- border = false,
13735
- radius = "none",
13736
- shadow = "none",
13737
- className,
13738
- style,
13739
- children
13739
+ radius,
13740
+ isLoading: _isLoading,
13741
+ error: _error,
13742
+ entity: _entity,
13743
+ ...boxProps
13740
13744
  }) {
13741
13745
  return /* @__PURE__ */ jsxRuntime.jsx(
13742
13746
  exports.Box,
13743
13747
  {
13744
- padding: p,
13745
- margin: m,
13746
- bg,
13747
- border,
13748
- rounded: radius,
13749
- shadow,
13750
- className,
13751
- style,
13752
- children
13748
+ padding: boxProps.padding ?? p,
13749
+ margin: boxProps.margin ?? m,
13750
+ rounded: boxProps.rounded ?? radius,
13751
+ ...boxProps
13753
13752
  }
13754
13753
  );
13755
13754
  }
@@ -14338,7 +14337,7 @@ var init_Breadcrumb = __esm({
14338
14337
  },
14339
14338
  className: cn(
14340
14339
  "flex items-center gap-1.5 transition-colors",
14341
- "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
14340
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
14342
14341
  isLast ? "text-foreground font-bold cursor-default" : "text-muted-foreground hover:text-foreground"
14343
14342
  ),
14344
14343
  "aria-current": isLast ? "page" : void 0,
@@ -19404,17 +19403,19 @@ var init_DashboardLayout = __esm({
19404
19403
  const [sidebarOpen, setSidebarOpen] = React74.useState(false);
19405
19404
  const [userMenuOpen, setUserMenuOpen] = React74.useState(false);
19406
19405
  const layoutRef = React74.useRef(null);
19407
- const [isMobile, setIsMobile] = React74.useState(false);
19406
+ const [layoutWidth, setLayoutWidth] = React74.useState(null);
19408
19407
  React74.useEffect(() => {
19409
19408
  const el = layoutRef.current;
19410
19409
  if (!el || typeof ResizeObserver === "undefined") return;
19411
19410
  const ro = new ResizeObserver((entries) => {
19412
19411
  const w = entries[0]?.contentRect.width ?? el.clientWidth;
19413
- setIsMobile(w < 1024);
19412
+ setLayoutWidth(w);
19414
19413
  });
19415
19414
  ro.observe(el);
19416
19415
  return () => ro.disconnect();
19417
19416
  }, []);
19417
+ const isMobile = layoutWidth !== null && layoutWidth < 768;
19418
+ const isRail = layoutWidth !== null && layoutWidth >= 768 && layoutWidth < 1024;
19418
19419
  React74.useEffect(() => {
19419
19420
  if (!isMobile && sidebarOpen) setSidebarOpen(false);
19420
19421
  }, [isMobile, sidebarOpen]);
@@ -19451,7 +19452,8 @@ var init_DashboardLayout = __esm({
19451
19452
  {
19452
19453
  as: "aside",
19453
19454
  className: cn(
19454
- "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",
19455
19457
  "flex flex-col"
19456
19458
  ),
19457
19459
  style: isMobile ? {
@@ -19467,10 +19469,10 @@ var init_DashboardLayout = __esm({
19467
19469
  exports.HStack,
19468
19470
  {
19469
19471
  align: "center",
19470
- justify: "between",
19471
- 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"),
19472
19474
  children: [
19473
- /* @__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: [
19474
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(
19475
19477
  exports.Typography,
19476
19478
  {
@@ -19480,7 +19482,7 @@ var init_DashboardLayout = __esm({
19480
19482
  children: appName.charAt(0).toUpperCase()
19481
19483
  }
19482
19484
  ) }),
19483
- /* @__PURE__ */ jsxRuntime.jsx(
19485
+ !isRail && /* @__PURE__ */ jsxRuntime.jsx(
19484
19486
  exports.Typography,
19485
19487
  {
19486
19488
  variant: "label",
@@ -19507,12 +19509,13 @@ var init_DashboardLayout = __esm({
19507
19509
  {
19508
19510
  as: "nav",
19509
19511
  gap: "none",
19510
- 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"),
19511
19513
  children: navItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
19512
19514
  NavLink,
19513
19515
  {
19514
19516
  item,
19515
- currentPath: activePath
19517
+ currentPath: activePath,
19518
+ compact: isRail
19516
19519
  },
19517
19520
  item.href
19518
19521
  ))
@@ -19767,13 +19770,40 @@ var init_DashboardLayout = __esm({
19767
19770
  exports.DashboardLayout.displayName = "DashboardLayout";
19768
19771
  NavLink = ({
19769
19772
  item,
19770
- currentPath
19773
+ currentPath,
19774
+ compact = false
19771
19775
  }) => {
19772
19776
  const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
19773
19777
  const iconClassName = cn(
19774
19778
  "h-5 w-5",
19775
19779
  isActive ? "text-primary-foreground" : "text-muted-foreground"
19776
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
+ }
19777
19807
  return /* @__PURE__ */ jsxRuntime.jsxs(
19778
19808
  reactRouterDom.Link,
19779
19809
  {
@@ -20839,40 +20869,55 @@ function DataGrid({
20839
20869
  {
20840
20870
  "data-entity-row": true,
20841
20871
  "data-entity-id": id,
20842
- className: cn(isSelected && "ring-2 ring-primary rounded-lg"),
20872
+ className: cn("relative group/rowactions", isSelected && "ring-2 ring-primary rounded-lg"),
20843
20873
  children: [
20844
20874
  children(itemData, index),
20845
- 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: [
20846
- (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
20847
- exports.Button,
20848
- {
20849
- variant: action.variant === "primary" ? "primary" : "ghost",
20850
- size: "sm",
20851
- onClick: handleActionClick(action, itemData),
20852
- "data-testid": `action-${action.event}`,
20853
- "data-row-id": String(itemData.id),
20854
- className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
20855
- children: [
20856
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
20857
- action.label
20858
- ]
20859
- },
20860
- idx
20861
- )),
20862
- 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(
20863
20908
  exports.Menu,
20864
20909
  {
20865
20910
  position: "bottom-end",
20866
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" }) }),
20867
- items: actionDefs.slice(maxInlineActions).map((action) => ({
20912
+ items: actionDefs.map((action) => ({
20868
20913
  label: action.label,
20869
20914
  icon: action.icon,
20870
20915
  event: action.event,
20871
20916
  onClick: () => fireAction(action, itemData)
20872
20917
  }))
20873
20918
  }
20874
- )
20875
- ] }) })
20919
+ ) })
20920
+ ] })
20876
20921
  ]
20877
20922
  },
20878
20923
  id
@@ -20908,7 +20953,7 @@ function DataGrid({
20908
20953
  }
20909
20954
  ) });
20910
20955
  })(),
20911
- /* @__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: [
20912
20957
  selectable && /* @__PURE__ */ jsxRuntime.jsx(
20913
20958
  "input",
20914
20959
  {
@@ -20941,79 +20986,77 @@ function DataGrid({
20941
20986
  ] }, field.name);
20942
20987
  }) })
20943
20988
  ] }),
20944
- dangerActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
20945
- exports.Button,
20946
- {
20947
- variant: "ghost",
20948
- size: "sm",
20949
- onClick: handleActionClick(action, itemData),
20950
- "data-testid": `action-${action.event}`,
20951
- "data-row-id": String(itemData.id),
20952
- className: "text-error hover:text-error hover:bg-error/10 px-2",
20953
- children: [
20954
- action.icon && renderIconInput(action.icon, { size: "xs" }),
20955
- action.label
20956
- ]
20957
- },
20958
- idx
20959
- )) })
20960
- ] }) }),
20961
- 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) => {
20962
- const value = getNestedValue(itemData, field.name);
20963
- if (value === void 0 || value === null || value === "") return null;
20964
- if (field.format === "boolean") {
20965
- return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-between items-center", children: [
20966
- /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
20967
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
20968
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
20969
- ] }),
20970
- /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
20971
- ] }, field.name);
20972
- }
20973
- return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-between items-center", children: [
20974
- /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
20975
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
20976
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
20977
- ] }),
20978
- /* @__PURE__ */ jsxRuntime.jsx(
20979
- 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,
20980
20992
  {
20981
- variant: field.variant === "caption" ? "caption" : "small",
20982
- className: "text-right truncate max-w-[60%]",
20983
- children: formatValue(value, field.format)
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,
21010
+ {
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
+ }))
20984
21019
  }
20985
- )
20986
- ] }, field.name);
20987
- }) }) }),
20988
- 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: [
20989
- (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
20990
- exports.Button,
20991
- {
20992
- variant: action.variant === "primary" ? "primary" : "ghost",
20993
- size: "sm",
20994
- onClick: handleActionClick(action, itemData),
20995
- "data-testid": `action-${action.event}`,
20996
- "data-row-id": String(itemData.id),
20997
- children: [
20998
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
20999
- action.label
21000
- ]
21001
- },
21002
- idx
21003
- )),
21004
- maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
21005
- exports.Menu,
21006
- {
21007
- position: "bottom-end",
21008
- 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" }) }),
21009
- items: primaryActions.slice(maxInlineActions).map((action) => ({
21010
- label: action.label,
21011
- icon: action.icon,
21012
- event: action.event,
21013
- onClick: () => fireAction(action, itemData)
21014
- }))
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);
21015
21053
  }
21016
- )
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
+ }) })
21017
21060
  ] }) })
21018
21061
  ]
21019
21062
  },
@@ -21361,11 +21404,29 @@ function DataList({
21361
21404
  const wrapDnd = (node) => dnd.isZone ? /* @__PURE__ */ jsxRuntime.jsx(dnd.SortableItem, { id: dndId, children: node }, dndId) : node;
21362
21405
  if (hasRenderProp) {
21363
21406
  const id2 = itemData.id || String(index);
21407
+ const actions = renderItemActions(itemData);
21364
21408
  return wrapDnd(
21365
- /* @__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: [
21366
- /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "group flex items-stretch gap-2", children: [
21367
- /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
21368
- 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
+ ) })
21369
21430
  ] }),
21370
21431
  isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "mx-6 border-b border-border/40" })
21371
21432
  ] }, id2)
@@ -21405,7 +21466,7 @@ function DataList({
21405
21466
  ] }, field.name);
21406
21467
  })
21407
21468
  ] }),
21408
- 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) => {
21409
21470
  const value = getNestedValue(itemData, field.name);
21410
21471
  if (value === void 0 || value === null || value === "") return null;
21411
21472
  return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
@@ -22589,10 +22650,7 @@ var init_FileTree = __esm({
22589
22650
  className,
22590
22651
  indent = 16
22591
22652
  }) => {
22592
- const { t } = hooks.useTranslate();
22593
- if (tree.length === 0) {
22594
- return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: `p-4 ${className ?? ""}`, children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "muted", children: t("fileTree.noFiles") }) });
22595
- }
22653
+ if (tree.length === 0) return null;
22596
22654
  return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: tree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
22597
22655
  TreeNodeItem,
22598
22656
  {
@@ -28658,7 +28716,7 @@ var init_MapView = __esm({
28658
28716
  shadowSize: [41, 41]
28659
28717
  });
28660
28718
  L.Marker.prototype.options.icon = defaultIcon;
28661
- 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;
28662
28720
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
28663
28721
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
28664
28722
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -28704,7 +28762,7 @@ var init_MapView = __esm({
28704
28762
  }) {
28705
28763
  const eventBus = useEventBus2();
28706
28764
  const [clickedPosition, setClickedPosition] = useState102(null);
28707
- const handleMapClick = useCallback105((lat, lng) => {
28765
+ const handleMapClick = useCallback106((lat, lng) => {
28708
28766
  if (showClickedPin) {
28709
28767
  setClickedPosition({ lat, lng });
28710
28768
  }
@@ -28713,7 +28771,7 @@ var init_MapView = __esm({
28713
28771
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
28714
28772
  }
28715
28773
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
28716
- const handleMarkerClick = useCallback105((marker) => {
28774
+ const handleMarkerClick = useCallback106((marker) => {
28717
28775
  onMarkerClick?.(marker);
28718
28776
  if (markerClickEvent) {
28719
28777
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -28915,7 +28973,7 @@ var init_NumberStepper = __esm({
28915
28973
  "active:bg-muted",
28916
28974
  "transition-colors duration-instant",
28917
28975
  "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent",
28918
- "focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-ring focus:ring-inset",
28976
+ "focus:outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-inset",
28919
28977
  styles.button
28920
28978
  ),
28921
28979
  "aria-label": t("aria.decrease"),
@@ -28956,7 +29014,7 @@ var init_NumberStepper = __esm({
28956
29014
  "active:bg-muted",
28957
29015
  "transition-colors duration-instant",
28958
29016
  "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent",
28959
- "focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-ring focus:ring-inset",
29017
+ "focus:outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-inset",
28960
29018
  styles.button
28961
29019
  ),
28962
29020
  "aria-label": t("aria.increase"),
@@ -29412,7 +29470,7 @@ var init_Lightbox = __esm({
29412
29470
  "p-2 rounded-full",
29413
29471
  "text-[var(--color-foreground)] bg-[var(--color-card)]",
29414
29472
  "hover:bg-opacity-70 transition-opacity",
29415
- "focus:outline-none focus:ring-2 focus:ring-ring"
29473
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
29416
29474
  ),
29417
29475
  "aria-label": t("aria.closeModal"),
29418
29476
  children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "x", className: "w-6 h-6" })
@@ -29431,7 +29489,7 @@ var init_Lightbox = __esm({
29431
29489
  "p-2 rounded-full",
29432
29490
  "text-[var(--color-foreground)] bg-[var(--color-card)]",
29433
29491
  "hover:bg-opacity-70 transition-opacity",
29434
- "focus:outline-none focus:ring-2 focus:ring-ring"
29492
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
29435
29493
  ),
29436
29494
  "aria-label": t("aria.previousImage"),
29437
29495
  children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "chevron-left", className: "w-8 h-8" })
@@ -29468,7 +29526,7 @@ var init_Lightbox = __esm({
29468
29526
  "p-2 rounded-full",
29469
29527
  "text-[var(--color-foreground)] bg-[var(--color-card)]",
29470
29528
  "hover:bg-opacity-70 transition-opacity",
29471
- "focus:outline-none focus:ring-2 focus:ring-ring"
29529
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
29472
29530
  ),
29473
29531
  "aria-label": t("aria.nextImage"),
29474
29532
  children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "chevron-right", className: "w-8 h-8" })
@@ -29489,6 +29547,26 @@ var init_Lightbox = __esm({
29489
29547
  exports.Lightbox.displayName = "Lightbox";
29490
29548
  }
29491
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
+ });
29492
29570
  function renderIconInput3(icon, props) {
29493
29571
  return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon, ...props });
29494
29572
  }
@@ -29595,6 +29673,7 @@ function TableView({
29595
29673
  const hasMore = pageSize > 0 && visibleCount < ordered.length;
29596
29674
  const hasRenderProp = typeof children === "function";
29597
29675
  const idField = dndItemIdField ?? "id";
29676
+ const isCoarsePointer = useMediaQuery("(pointer: coarse)");
29598
29677
  const selected = selectedIds ? new Set(selectedIds) : localSelected;
29599
29678
  const emitSelection = (next) => {
29600
29679
  if (!selectedIds) setLocalSelected(next);
@@ -29627,6 +29706,17 @@ function TableView({
29627
29706
  };
29628
29707
  eventBus.emit(`UI:${action.event}`, payload);
29629
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
+ );
29630
29720
  if (isLoading) {
29631
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") }) });
29632
29722
  }
@@ -29639,19 +29729,10 @@ function TableView({
29639
29729
  }
29640
29730
  const lk = LOOKS[look];
29641
29731
  const hasActions = Boolean(itemActions && itemActions.length > 0);
29642
- const inlineActionCount = hasActions ? maxInlineActions != null ? Math.min(itemActions.length, maxInlineActions) : itemActions.length : 0;
29643
- 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;
29644
29735
  const actionsTrack = hasActions ? `${inlineActionCount * 6 + (hasOverflowActions ? 3 : 0)}rem` : null;
29645
- const colFloors = React74__namespace.default.useMemo(
29646
- () => colDefs.map((col) => {
29647
- const longest = data.reduce((widest, row) => {
29648
- const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
29649
- return Math.max(widest, cell.length);
29650
- }, columnLabel(col).length);
29651
- return Math.min(longest, MAX_MEASURED_COL_CH);
29652
- }),
29653
- [colDefs, data]
29654
- );
29655
29736
  const gridTemplateColumns = [
29656
29737
  selectable ? "auto" : null,
29657
29738
  ...colDefs.map((c, i) => c.width ?? `minmax(${colFloors[i]}ch, 1fr)`),
@@ -29738,9 +29819,9 @@ function TableView({
29738
29819
  col.className
29739
29820
  );
29740
29821
  if (col.format === "badge" && raw != null && raw !== "") {
29741
- return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: statusVariant4(String(raw)), size: "sm", children: String(raw) }) }, col.key);
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);
29742
29823
  }
29743
- 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);
29744
29825
  }),
29745
29826
  itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
29746
29827
  exports.HStack,
@@ -29754,15 +29835,15 @@ function TableView({
29754
29835
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
29755
29836
  ),
29756
29837
  children: [
29757
- (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(
29758
29839
  exports.Button,
29759
29840
  {
29760
- variant: action.variant ?? "ghost",
29841
+ variant: action.variant === "primary" ? "primary" : "ghost",
29761
29842
  size: "sm",
29762
29843
  onClick: handleActionClick(action, row),
29763
29844
  "data-testid": `action-${action.event}`,
29764
29845
  "data-row-id": String(row.id),
29765
- 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"),
29766
29847
  children: [
29767
29848
  action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
29768
29849
  action.label
@@ -29770,12 +29851,12 @@ function TableView({
29770
29851
  },
29771
29852
  i
29772
29853
  )),
29773
- maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
29854
+ effectiveMaxInline != null && itemActions.length > effectiveMaxInline && /* @__PURE__ */ jsxRuntime.jsx(
29774
29855
  exports.Menu,
29775
29856
  {
29776
29857
  position: "bottom-end",
29777
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" }) }),
29778
- items: itemActions.slice(maxInlineActions).map((action) => ({
29859
+ items: itemActions.slice(effectiveMaxInline).map((action) => ({
29779
29860
  label: action.label,
29780
29861
  icon: action.icon,
29781
29862
  event: action.event,
@@ -29821,13 +29902,14 @@ function TableView({
29821
29902
  }
29822
29903
  );
29823
29904
  }
29824
- var MAX_MEASURED_COL_CH, alignClass, weightClass, LOOKS;
29905
+ var MAX_MEASURED_COL_CH, BADGE_CHROME_CH, alignClass, weightClass, LOOKS;
29825
29906
  var init_TableView = __esm({
29826
29907
  "components/core/molecules/TableView.tsx"() {
29827
29908
  "use client";
29828
29909
  init_cn();
29829
29910
  init_getNestedValue();
29830
29911
  init_useEventBus();
29912
+ init_useMediaQuery();
29831
29913
  init_Box();
29832
29914
  init_Stack();
29833
29915
  init_Typography();
@@ -29840,6 +29922,7 @@ var init_TableView = __esm({
29840
29922
  init_useDataDnd();
29841
29923
  logger.createLogger("almadar:ui:table-view");
29842
29924
  MAX_MEASURED_COL_CH = 32;
29925
+ BADGE_CHROME_CH = 4;
29843
29926
  alignClass = {
29844
29927
  left: "justify-start text-left",
29845
29928
  center: "justify-center text-center",
@@ -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 },
@@ -32075,7 +32158,7 @@ var init_VoteStack = __esm({
32075
32158
  "active:bg-muted",
32076
32159
  "transition-colors duration-instant",
32077
32160
  "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent",
32078
- "focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-ring focus:ring-inset",
32161
+ "focus:outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-inset",
32079
32162
  styles.button
32080
32163
  ),
32081
32164
  children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "chevron-up", className: styles.icon })
@@ -32112,7 +32195,7 @@ var init_VoteStack = __esm({
32112
32195
  "active:bg-muted",
32113
32196
  "transition-colors duration-instant",
32114
32197
  "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent",
32115
- "focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-ring focus:ring-inset",
32198
+ "focus:outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-inset",
32116
32199
  styles.button
32117
32200
  ),
32118
32201
  children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "chevron-down", className: styles.icon })
@@ -32633,7 +32716,7 @@ var init_QrScanner = __esm({
32633
32716
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32634
32717
  "rounded-full bg-black bg-opacity-60 p-2 text-white",
32635
32718
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32636
- "hover:bg-opacity-80 focus:outline-none focus:ring-2 focus:ring-white"
32719
+ "hover:bg-opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-white"
32637
32720
  ),
32638
32721
  "aria-label": isPaused ? t("qrScanner.resumeScanning") : t("qrScanner.pauseScanning"),
32639
32722
  children: isPaused ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "play", className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "pause", className: "h-4 w-4" })
@@ -32648,7 +32731,7 @@ var init_QrScanner = __esm({
32648
32731
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32649
32732
  "rounded-full bg-black bg-opacity-60 p-2 text-white",
32650
32733
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32651
- "hover:bg-opacity-80 focus:outline-none focus:ring-2 focus:ring-white"
32734
+ "hover:bg-opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-white"
32652
32735
  ),
32653
32736
  "aria-label": currentFacing === "environment" ? t("qrScanner.switchToFrontCamera") : t("qrScanner.switchToRearCamera"),
32654
32737
  children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "refresh-cw", className: "h-4 w-4" })
@@ -32663,7 +32746,7 @@ var init_QrScanner = __esm({
32663
32746
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32664
32747
  "rounded-full bg-black bg-opacity-60 px-3 py-2 text-xs text-white",
32665
32748
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32666
- "hover:bg-opacity-80 focus:outline-none focus:ring-2 focus:ring-white"
32749
+ "hover:bg-opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-white"
32667
32750
  ),
32668
32751
  "aria-label": t("aria.mockScanDev"),
32669
32752
  children: t("qrScanner.mockScan")
@@ -41129,27 +41212,24 @@ var init_MasterDetailLayout = __esm({
41129
41212
  masterClassName,
41130
41213
  detailClassName
41131
41214
  }) => {
41132
- masterWidth.endsWith("%") ? parseInt(masterWidth, 10) : 30;
41133
41215
  return /* @__PURE__ */ jsxRuntime.jsxs(
41134
41216
  "div",
41135
41217
  {
41136
- className: cn("flex h-full w-full", className),
41137
- style: {
41138
- display: "grid",
41139
- gridTemplateColumns: masterWidth.endsWith("%") ? `${masterWidth} 1fr` : `${masterWidth} 1fr`
41140
- },
41218
+ className: cn("w-full h-full md:grid md:grid-cols-[var(--master-detail-cols)]", className),
41219
+ style: { "--master-detail-cols": `${masterWidth} 1fr` },
41141
41220
  children: [
41142
41221
  /* @__PURE__ */ jsxRuntime.jsx(
41143
41222
  "div",
41144
41223
  {
41145
41224
  className: cn(
41146
- "border-r-2 border-border overflow-auto",
41225
+ "border-r border-border overflow-auto",
41226
+ hasSelection && "hidden md:block",
41147
41227
  masterClassName
41148
41228
  ),
41149
41229
  children: master
41150
41230
  }
41151
41231
  ),
41152
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("overflow-auto", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsxRuntime.jsx(DefaultEmptyDetail, {}) })
41232
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("overflow-auto", !hasSelection && "hidden md:block", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsxRuntime.jsx(DefaultEmptyDetail, {}) })
41153
41233
  ]
41154
41234
  }
41155
41235
  );
@@ -44702,7 +44782,7 @@ var init_TabbedContainer = __esm({
44702
44782
  onClick: () => !isDisabled && handleTabChange(tab.id),
44703
44783
  className: cn(
44704
44784
  "flex items-center gap-2 px-4 py-3 text-sm font-medium transition-colors",
44705
- "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
44785
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
44706
44786
  "disabled:opacity-50 disabled:cursor-not-allowed",
44707
44787
  isActive ? "bg-primary text-primary-foreground" : "bg-card text-foreground hover:bg-muted",
44708
44788
  isVertical ? "justify-start" : "justify-center"
@@ -48709,7 +48789,7 @@ var I18nContext = React74.createContext({
48709
48789
  });
48710
48790
  I18nContext.displayName = "I18nContext";
48711
48791
  var I18nProvider = I18nContext.Provider;
48712
- function useTranslate115() {
48792
+ function useTranslate114() {
48713
48793
  return React74.useContext(I18nContext);
48714
48794
  }
48715
48795
  function createTranslate(messages) {
@@ -48729,6 +48809,7 @@ init_useAuthContext();
48729
48809
  init_useSwipeGesture();
48730
48810
  init_useLongPress();
48731
48811
  init_useDragReorder();
48812
+ init_useMediaQuery();
48732
48813
  init_useInfiniteScroll();
48733
48814
  init_usePullToRefresh();
48734
48815
  init_useCanvasGestures();
@@ -49116,6 +49197,7 @@ exports.useGitHubStatus = useGitHubStatus;
49116
49197
  exports.useImageCache = useImageCache;
49117
49198
  exports.useInfiniteScroll = useInfiniteScroll;
49118
49199
  exports.useLongPress = useLongPress;
49200
+ exports.useMediaQuery = useMediaQuery;
49119
49201
  exports.useOrbitalHistory = useOrbitalHistory;
49120
49202
  exports.usePresence = usePresence;
49121
49203
  exports.usePreview = usePreview;
@@ -49128,7 +49210,7 @@ exports.useSharedEntityStoreContext = useSharedEntityStoreContext;
49128
49210
  exports.useSwipeGesture = useSwipeGesture;
49129
49211
  exports.useTapReveal = useTapReveal;
49130
49212
  exports.useTraitListens = useTraitListens;
49131
- exports.useTranslate = useTranslate115;
49213
+ exports.useTranslate = useTranslate114;
49132
49214
  exports.useUIEvents = useUIEvents;
49133
49215
  exports.useUISlotManager = useUISlotManager;
49134
49216
  exports.useUnitSpriteAtlas = useUnitSpriteAtlas;