@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.
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import * as React74 from 'react';
3
- import React74__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, useState, useLayoutEffect, Suspense, lazy, useSyncExternalStore, useId } from 'react';
3
+ import React74__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, useState, useLayoutEffect, Suspense, useSyncExternalStore, lazy, useId } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { EventBusContext, useTraitScopeChain, useCurrentPagePath, useGameAudioContextOptional, useEntitySchemaOptional, TraitScopeProvider } from '@almadar/ui/providers';
@@ -1782,7 +1782,7 @@ var init_Button = __esm({
1782
1782
  "cursor-pointer",
1783
1783
  "chrome-button",
1784
1784
  "transition-all duration-normal",
1785
- "focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-ring focus:ring-offset-[length:var(--focus-ring-offset)]",
1785
+ "focus:outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-offset-[length:var(--focus-ring-offset)]",
1786
1786
  "disabled:opacity-50 disabled:cursor-not-allowed",
1787
1787
  variantStyles[variant],
1788
1788
  sizeStyles[size],
@@ -2080,7 +2080,7 @@ function NativeSelect({
2080
2080
  "block w-full border-[length:var(--border-width)] shadow-sm appearance-none",
2081
2081
  "px-3 py-2 pr-10 text-sm text-foreground font-medium",
2082
2082
  "bg-card",
2083
- "focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-ring",
2083
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-ring",
2084
2084
  "disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed",
2085
2085
  error ? "border-error focus:border-error" : "border-border focus:border-primary",
2086
2086
  className
@@ -2187,7 +2187,7 @@ function RichSelect({
2187
2187
  "block w-full border-[length:var(--border-width)] shadow-sm",
2188
2188
  "px-3 py-2 pr-10 text-sm text-start font-medium",
2189
2189
  "bg-card rounded-sm",
2190
- "focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-ring",
2190
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-ring",
2191
2191
  "disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed",
2192
2192
  error ? "border-error focus:border-error" : "border-border focus:border-primary",
2193
2193
  !hasValue && "text-muted-foreground"
@@ -2535,6 +2535,8 @@ var init_Badge = __esm({
2535
2535
  };
2536
2536
  const iconPx = size === "lg" ? 20 : 16;
2537
2537
  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;
2538
+ const hasText = Boolean(children) || amount != null || label !== void 0 && label !== null && label !== "";
2539
+ if (!hasText && !resolvedIcon && !onRemove) return null;
2538
2540
  return /* @__PURE__ */ jsxs(
2539
2541
  "span",
2540
2542
  {
@@ -2561,7 +2563,7 @@ var init_Badge = __esm({
2561
2563
  },
2562
2564
  className: cn(
2563
2565
  "inline-flex items-center justify-center rounded-sm",
2564
- "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
2566
+ "hover:bg-foreground/10 focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2565
2567
  "transition-colors",
2566
2568
  size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
2567
2569
  ),
@@ -3461,9 +3463,9 @@ var init_Radio = __esm({
3461
3463
  "flex items-center justify-center",
3462
3464
  "border-[length:var(--border-width)] transition-all cursor-pointer",
3463
3465
  sizeClasses3[size],
3464
- hasError ? "border-error peer-focus:ring-error/20" : "border-border peer-focus:ring-ring/20",
3466
+ hasError ? "border-error peer-focus-visible:ring-error/20" : "border-border peer-focus-visible:ring-ring/20",
3465
3467
  isChecked2 ? hasError ? "border-error" : "border-primary bg-primary" : "",
3466
- "peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-offset-2",
3468
+ "peer-focus:outline-none peer-focus-visible:ring-2 peer-focus-visible:ring-offset-2",
3467
3469
  disabled && "opacity-50 cursor-not-allowed",
3468
3470
  !disabled && "hover:border-[var(--color-border-hover)]"
3469
3471
  ),
@@ -4058,7 +4060,7 @@ var init_ThemeToggle = __esm({
4058
4060
  "inline-flex items-center justify-center gap-2",
4059
4061
  "text-foreground",
4060
4062
  "hover:bg-muted border-[length:var(--border-width)] border-transparent hover:border-border",
4061
- "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
4063
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
4062
4064
  "transition-colors duration-fast",
4063
4065
  sizeClasses4[size],
4064
4066
  className
@@ -4631,11 +4633,13 @@ var init_TrendIndicator = __esm({
4631
4633
  size = "md",
4632
4634
  ...props
4633
4635
  }, ref) => {
4634
- const dir = resolveDirection(value, direction);
4636
+ const hasValue = typeof value === "number" && Number.isFinite(value);
4637
+ if (!hasValue && !direction) return null;
4638
+ const dir = resolveDirection(hasValue ? value : void 0, direction);
4635
4639
  const colorClass = resolveColor(dir, invert);
4636
4640
  const iconName = iconNameMap[dir];
4637
4641
  const styles = sizeStyles6[size];
4638
- const formattedValue = value !== void 0 ? `${value > 0 ? "+" : ""}${value}%` : void 0;
4642
+ const formattedValue = hasValue ? `${value > 0 ? "+" : ""}${value}%` : void 0;
4639
4643
  const ariaLabel = label ?? (formattedValue ? `${dir} ${formattedValue}` : dir);
4640
4644
  return /* @__PURE__ */ jsxs(
4641
4645
  "span",
@@ -6957,10 +6961,12 @@ var init_Container = __esm({
6957
6961
  };
6958
6962
  paddingStyles3 = {
6959
6963
  none: "px-0",
6960
- sm: "px-4",
6961
- md: "px-6",
6962
- lg: "px-8",
6963
- xl: "px-12"
6964
+ // Mobile-tighter, desktop-identical: fixed px-6 on a 360px phone eats ~13% of
6965
+ // the viewport, so each token steps down below the sm breakpoint.
6966
+ sm: "px-3 sm:px-4",
6967
+ md: "px-4 sm:px-6",
6968
+ lg: "px-4 sm:px-6 md:px-8",
6969
+ xl: "px-4 sm:px-8 md:px-12"
6964
6970
  };
6965
6971
  Container = ({
6966
6972
  size,
@@ -7659,7 +7665,7 @@ var init_Accordion = __esm({
7659
7665
  "bg-card",
7660
7666
  "hover:bg-muted",
7661
7667
  "transition-colors duration-fast",
7662
- "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-inset",
7668
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset",
7663
7669
  "disabled:opacity-50 disabled:cursor-not-allowed",
7664
7670
  isOpen && "bg-muted font-bold"
7665
7671
  ),
@@ -13655,26 +13661,19 @@ var init_BookViewer = __esm({
13655
13661
  function BoxPattern({
13656
13662
  p,
13657
13663
  m,
13658
- bg = "transparent",
13659
- border = false,
13660
- radius = "none",
13661
- shadow = "none",
13662
- className,
13663
- style,
13664
- children
13664
+ radius,
13665
+ isLoading: _isLoading,
13666
+ error: _error,
13667
+ entity: _entity,
13668
+ ...boxProps
13665
13669
  }) {
13666
13670
  return /* @__PURE__ */ jsx(
13667
13671
  Box,
13668
13672
  {
13669
- padding: p,
13670
- margin: m,
13671
- bg,
13672
- border,
13673
- rounded: radius,
13674
- shadow,
13675
- className,
13676
- style,
13677
- children
13673
+ padding: boxProps.padding ?? p,
13674
+ margin: boxProps.margin ?? m,
13675
+ rounded: boxProps.rounded ?? radius,
13676
+ ...boxProps
13678
13677
  }
13679
13678
  );
13680
13679
  }
@@ -14263,7 +14262,7 @@ var init_Breadcrumb = __esm({
14263
14262
  },
14264
14263
  className: cn(
14265
14264
  "flex items-center gap-1.5 transition-colors",
14266
- "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
14265
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
14267
14266
  isLast ? "text-foreground font-bold cursor-default" : "text-muted-foreground hover:text-foreground"
14268
14267
  ),
14269
14268
  "aria-current": isLast ? "page" : void 0,
@@ -19329,17 +19328,19 @@ var init_DashboardLayout = __esm({
19329
19328
  const [sidebarOpen, setSidebarOpen] = useState(false);
19330
19329
  const [userMenuOpen, setUserMenuOpen] = useState(false);
19331
19330
  const layoutRef = useRef(null);
19332
- const [isMobile, setIsMobile] = useState(false);
19331
+ const [layoutWidth, setLayoutWidth] = useState(null);
19333
19332
  useEffect(() => {
19334
19333
  const el = layoutRef.current;
19335
19334
  if (!el || typeof ResizeObserver === "undefined") return;
19336
19335
  const ro = new ResizeObserver((entries) => {
19337
19336
  const w = entries[0]?.contentRect.width ?? el.clientWidth;
19338
- setIsMobile(w < 1024);
19337
+ setLayoutWidth(w);
19339
19338
  });
19340
19339
  ro.observe(el);
19341
19340
  return () => ro.disconnect();
19342
19341
  }, []);
19342
+ const isMobile = layoutWidth !== null && layoutWidth < 768;
19343
+ const isRail = layoutWidth !== null && layoutWidth >= 768 && layoutWidth < 1024;
19343
19344
  useEffect(() => {
19344
19345
  if (!isMobile && sidebarOpen) setSidebarOpen(false);
19345
19346
  }, [isMobile, sidebarOpen]);
@@ -19376,7 +19377,8 @@ var init_DashboardLayout = __esm({
19376
19377
  {
19377
19378
  as: "aside",
19378
19379
  className: cn(
19379
- "z-30 w-64 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
19380
+ "z-30 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
19381
+ isRail ? "w-16" : "w-64",
19380
19382
  "flex flex-col"
19381
19383
  ),
19382
19384
  style: isMobile ? {
@@ -19392,10 +19394,10 @@ var init_DashboardLayout = __esm({
19392
19394
  HStack,
19393
19395
  {
19394
19396
  align: "center",
19395
- justify: "between",
19396
- className: "h-16 px-4 border-b border-border dark:border-border",
19397
+ justify: isRail ? "center" : "between",
19398
+ className: cn("h-16 border-b border-border dark:border-border", isRail ? "px-2" : "px-4"),
19397
19399
  children: [
19398
- /* @__PURE__ */ jsxs(Link, { to: "/", className: "flex items-center gap-2", children: [
19400
+ /* @__PURE__ */ jsxs(Link, { to: "/", className: "flex items-center gap-2", title: isRail ? appName : void 0, children: [
19399
19401
  logo || /* @__PURE__ */ jsx(Box, { className: "w-8 h-8 bg-primary rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsx(
19400
19402
  Typography,
19401
19403
  {
@@ -19405,7 +19407,7 @@ var init_DashboardLayout = __esm({
19405
19407
  children: appName.charAt(0).toUpperCase()
19406
19408
  }
19407
19409
  ) }),
19408
- /* @__PURE__ */ jsx(
19410
+ !isRail && /* @__PURE__ */ jsx(
19409
19411
  Typography,
19410
19412
  {
19411
19413
  variant: "label",
@@ -19432,12 +19434,13 @@ var init_DashboardLayout = __esm({
19432
19434
  {
19433
19435
  as: "nav",
19434
19436
  gap: "none",
19435
- className: "flex-1 px-3 py-4 space-y-1 overflow-y-auto",
19437
+ className: cn("flex-1 py-4 space-y-1 overflow-y-auto", isRail ? "px-2" : "px-3"),
19436
19438
  children: navItems.map((item) => /* @__PURE__ */ jsx(
19437
19439
  NavLink,
19438
19440
  {
19439
19441
  item,
19440
- currentPath: activePath
19442
+ currentPath: activePath,
19443
+ compact: isRail
19441
19444
  },
19442
19445
  item.href
19443
19446
  ))
@@ -19692,13 +19695,40 @@ var init_DashboardLayout = __esm({
19692
19695
  DashboardLayout.displayName = "DashboardLayout";
19693
19696
  NavLink = ({
19694
19697
  item,
19695
- currentPath
19698
+ currentPath,
19699
+ compact = false
19696
19700
  }) => {
19697
19701
  const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
19698
19702
  const iconClassName = cn(
19699
19703
  "h-5 w-5",
19700
19704
  isActive ? "text-primary-foreground" : "text-muted-foreground"
19701
19705
  );
19706
+ if (compact) {
19707
+ return /* @__PURE__ */ jsx(
19708
+ Link,
19709
+ {
19710
+ to: item.href,
19711
+ title: item.label,
19712
+ "aria-label": item.label,
19713
+ className: cn(
19714
+ "flex items-center justify-center px-2 py-2 rounded-lg transition-colors",
19715
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
19716
+ ),
19717
+ children: /* @__PURE__ */ jsxs(Box, { as: "span", className: "relative inline-flex", children: [
19718
+ 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() }),
19719
+ item.badge && /* @__PURE__ */ jsx(
19720
+ Badge,
19721
+ {
19722
+ variant: isActive ? "primary" : "default",
19723
+ size: "sm",
19724
+ className: "absolute -top-2 -right-2 px-1 py-0 text-[10px] leading-4",
19725
+ children: item.badge
19726
+ }
19727
+ )
19728
+ ] })
19729
+ }
19730
+ );
19731
+ }
19702
19732
  return /* @__PURE__ */ jsxs(
19703
19733
  Link,
19704
19734
  {
@@ -20764,40 +20794,55 @@ function DataGrid({
20764
20794
  {
20765
20795
  "data-entity-row": true,
20766
20796
  "data-entity-id": id,
20767
- className: cn(isSelected && "ring-2 ring-primary rounded-lg"),
20797
+ className: cn("relative group/rowactions", isSelected && "ring-2 ring-primary rounded-lg"),
20768
20798
  children: [
20769
20799
  children(itemData, index),
20770
- 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: [
20771
- (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxs(
20772
- Button,
20773
- {
20774
- variant: action.variant === "primary" ? "primary" : "ghost",
20775
- size: "sm",
20776
- onClick: handleActionClick(action, itemData),
20777
- "data-testid": `action-${action.event}`,
20778
- "data-row-id": String(itemData.id),
20779
- className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
20780
- children: [
20781
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
20782
- action.label
20783
- ]
20784
- },
20785
- idx
20786
- )),
20787
- maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
20800
+ 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: [
20801
+ /* @__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: [
20802
+ (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxs(
20803
+ Button,
20804
+ {
20805
+ variant: action.variant === "primary" ? "primary" : "ghost",
20806
+ size: "sm",
20807
+ onClick: handleActionClick(action, itemData),
20808
+ "data-testid": `action-${action.event}`,
20809
+ "data-row-id": String(itemData.id),
20810
+ className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
20811
+ children: [
20812
+ action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
20813
+ action.label
20814
+ ]
20815
+ },
20816
+ idx
20817
+ )),
20818
+ maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
20819
+ Menu,
20820
+ {
20821
+ position: "bottom-end",
20822
+ 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" }) }),
20823
+ items: actionDefs.slice(maxInlineActions).map((action) => ({
20824
+ label: action.label,
20825
+ icon: action.icon,
20826
+ event: action.event,
20827
+ onClick: () => fireAction(action, itemData)
20828
+ }))
20829
+ }
20830
+ )
20831
+ ] }),
20832
+ /* @__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(
20788
20833
  Menu,
20789
20834
  {
20790
20835
  position: "bottom-end",
20791
20836
  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" }) }),
20792
- items: actionDefs.slice(maxInlineActions).map((action) => ({
20837
+ items: actionDefs.map((action) => ({
20793
20838
  label: action.label,
20794
20839
  icon: action.icon,
20795
20840
  event: action.event,
20796
20841
  onClick: () => fireAction(action, itemData)
20797
20842
  }))
20798
20843
  }
20799
- )
20800
- ] }) })
20844
+ ) })
20845
+ ] })
20801
20846
  ]
20802
20847
  },
20803
20848
  id
@@ -20833,7 +20878,7 @@ function DataGrid({
20833
20878
  }
20834
20879
  ) });
20835
20880
  })(),
20836
- /* @__PURE__ */ jsx(Box, { className: "p-4 pb-0", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
20881
+ /* @__PURE__ */ jsx(Box, { className: cn("p-4", bodyFields.length > 0 && "pb-0"), children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
20837
20882
  selectable && /* @__PURE__ */ jsx(
20838
20883
  "input",
20839
20884
  {
@@ -20866,79 +20911,77 @@ function DataGrid({
20866
20911
  ] }, field.name);
20867
20912
  }) })
20868
20913
  ] }),
20869
- dangerActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsxs(
20870
- Button,
20871
- {
20872
- variant: "ghost",
20873
- size: "sm",
20874
- onClick: handleActionClick(action, itemData),
20875
- "data-testid": `action-${action.event}`,
20876
- "data-row-id": String(itemData.id),
20877
- className: "text-error hover:text-error hover:bg-error/10 px-2",
20878
- children: [
20879
- action.icon && renderIconInput(action.icon, { size: "xs" }),
20880
- action.label
20881
- ]
20882
- },
20883
- idx
20884
- )) })
20885
- ] }) }),
20886
- bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: bodyFields.map((field) => {
20887
- const value = getNestedValue(itemData, field.name);
20888
- if (value === void 0 || value === null || value === "") return null;
20889
- if (field.format === "boolean") {
20890
- return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
20891
- /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
20892
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
20893
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
20894
- ] }),
20895
- /* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
20896
- ] }, field.name);
20897
- }
20898
- return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
20899
- /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
20900
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
20901
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
20902
- ] }),
20903
- /* @__PURE__ */ jsx(
20904
- Typography,
20914
+ (primaryActions.length > 0 || dangerActions.length > 0) && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "flex-shrink-0", children: [
20915
+ (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsx(
20916
+ Button,
20905
20917
  {
20906
- variant: field.variant === "caption" ? "caption" : "small",
20907
- className: "text-right truncate max-w-[60%]",
20908
- children: formatValue(value, field.format)
20918
+ variant: action.variant === "primary" ? "primary" : "ghost",
20919
+ size: "sm",
20920
+ onClick: handleActionClick(action, itemData),
20921
+ "data-testid": `action-${action.event}`,
20922
+ "data-row-id": String(itemData.id),
20923
+ "aria-label": action.label,
20924
+ title: action.label,
20925
+ className: cn(
20926
+ action.variant === "primary" ? void 0 : "text-muted-foreground hover:text-foreground",
20927
+ action.icon && "px-2"
20928
+ ),
20929
+ children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
20930
+ },
20931
+ idx
20932
+ )),
20933
+ maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsx(
20934
+ Menu,
20935
+ {
20936
+ position: "bottom-end",
20937
+ 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" }) }),
20938
+ items: primaryActions.slice(maxInlineActions).map((action) => ({
20939
+ label: action.label,
20940
+ icon: action.icon,
20941
+ event: action.event,
20942
+ onClick: () => fireAction(action, itemData)
20943
+ }))
20909
20944
  }
20910
- )
20911
- ] }, field.name);
20912
- }) }) }),
20913
- 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: [
20914
- (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxs(
20915
- Button,
20916
- {
20917
- variant: action.variant === "primary" ? "primary" : "ghost",
20918
- size: "sm",
20919
- onClick: handleActionClick(action, itemData),
20920
- "data-testid": `action-${action.event}`,
20921
- "data-row-id": String(itemData.id),
20922
- children: [
20923
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
20924
- action.label
20925
- ]
20926
- },
20927
- idx
20928
- )),
20929
- maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsx(
20930
- Menu,
20931
- {
20932
- position: "bottom-end",
20933
- 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" }) }),
20934
- items: primaryActions.slice(maxInlineActions).map((action) => ({
20935
- label: action.label,
20936
- icon: action.icon,
20937
- event: action.event,
20938
- onClick: () => fireAction(action, itemData)
20939
- }))
20945
+ ),
20946
+ dangerActions.map((action, idx) => /* @__PURE__ */ jsx(
20947
+ 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
+ `danger-${idx}`
20960
+ ))
20961
+ ] })
20962
+ ] }) }),
20963
+ bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 pt-2 pb-4 flex-1", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
20964
+ bodyFields.filter((f3) => f3.variant === "caption" && f3.format !== "boolean").map((field) => {
20965
+ const value = getNestedValue(itemData, field.name);
20966
+ if (value === void 0 || value === null || value === "") return null;
20967
+ return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", className: "line-clamp-2", children: formatValue(value, field.format) }, field.name);
20968
+ }),
20969
+ /* @__PURE__ */ jsx(HStack, { gap: "md", className: "flex-wrap gap-y-1", children: bodyFields.filter((f3) => f3.variant !== "caption" || f3.format === "boolean").map((field) => {
20970
+ const value = getNestedValue(itemData, field.name);
20971
+ if (value === void 0 || value === null || value === "") return null;
20972
+ if (field.format === "boolean") {
20973
+ return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
20974
+ field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
20975
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) }),
20976
+ /* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
20977
+ ] }, field.name);
20940
20978
  }
20941
- )
20979
+ return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
20980
+ field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
20981
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
20982
+ /* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue(value, field.format) })
20983
+ ] }, field.name);
20984
+ }) })
20942
20985
  ] }) })
20943
20986
  ]
20944
20987
  },
@@ -21286,11 +21329,29 @@ function DataList({
21286
21329
  const wrapDnd = (node) => dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: dndId, children: node }, dndId) : node;
21287
21330
  if (hasRenderProp) {
21288
21331
  const id2 = itemData.id || String(index);
21332
+ const actions = renderItemActions(itemData);
21289
21333
  return wrapDnd(
21290
- /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick: itemClickEvent ? handleRowClick(itemData) : void 0, className: cn(itemClickEvent && "cursor-pointer"), children: [
21291
- /* @__PURE__ */ jsxs(Box, { className: "group flex items-stretch gap-2", children: [
21292
- /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
21293
- renderItemActions(itemData)
21334
+ /* @__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: [
21335
+ children(itemData, index),
21336
+ 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: [
21337
+ /* @__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 }),
21338
+ /* @__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(
21339
+ Menu,
21340
+ {
21341
+ position: "bottom-end",
21342
+ 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" }) }),
21343
+ items: (itemActions ?? []).map((action) => ({
21344
+ label: action.label,
21345
+ icon: action.icon,
21346
+ event: action.event,
21347
+ variant: action.variant === "danger" ? "danger" : "default",
21348
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
21349
+ id: itemData.id,
21350
+ row: itemData
21351
+ })
21352
+ }))
21353
+ }
21354
+ ) })
21294
21355
  ] }),
21295
21356
  isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-border/40" })
21296
21357
  ] }, id2)
@@ -21330,7 +21391,7 @@ function DataList({
21330
21391
  ] }, field.name);
21331
21392
  })
21332
21393
  ] }),
21333
- bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsx(HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
21394
+ bodyFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "md", className: cn("flex-wrap", isCompact ? "mt-0.5" : "mt-1.5"), children: bodyFields.map((field) => {
21334
21395
  const value = getNestedValue(itemData, field.name);
21335
21396
  if (value === void 0 || value === null || value === "") return null;
21336
21397
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
@@ -22514,10 +22575,7 @@ var init_FileTree = __esm({
22514
22575
  className,
22515
22576
  indent = 16
22516
22577
  }) => {
22517
- const { t } = useTranslate();
22518
- if (tree.length === 0) {
22519
- return /* @__PURE__ */ jsx(Box, { className: `p-4 ${className ?? ""}`, children: /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: t("fileTree.noFiles") }) });
22520
- }
22578
+ if (tree.length === 0) return null;
22521
22579
  return /* @__PURE__ */ jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: tree.map((node) => /* @__PURE__ */ jsx(
22522
22580
  TreeNodeItem,
22523
22581
  {
@@ -28583,7 +28641,7 @@ var init_MapView = __esm({
28583
28641
  shadowSize: [41, 41]
28584
28642
  });
28585
28643
  L.Marker.prototype.options.icon = defaultIcon;
28586
- const { useEffect: useEffect65, useRef: useRef63, useCallback: useCallback105, useState: useState102 } = React74__default;
28644
+ const { useEffect: useEffect65, useRef: useRef63, useCallback: useCallback106, useState: useState102 } = React74__default;
28587
28645
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
28588
28646
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
28589
28647
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -28629,7 +28687,7 @@ var init_MapView = __esm({
28629
28687
  }) {
28630
28688
  const eventBus = useEventBus2();
28631
28689
  const [clickedPosition, setClickedPosition] = useState102(null);
28632
- const handleMapClick = useCallback105((lat, lng) => {
28690
+ const handleMapClick = useCallback106((lat, lng) => {
28633
28691
  if (showClickedPin) {
28634
28692
  setClickedPosition({ lat, lng });
28635
28693
  }
@@ -28638,7 +28696,7 @@ var init_MapView = __esm({
28638
28696
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
28639
28697
  }
28640
28698
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
28641
- const handleMarkerClick = useCallback105((marker) => {
28699
+ const handleMarkerClick = useCallback106((marker) => {
28642
28700
  onMarkerClick?.(marker);
28643
28701
  if (markerClickEvent) {
28644
28702
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -28840,7 +28898,7 @@ var init_NumberStepper = __esm({
28840
28898
  "active:bg-muted",
28841
28899
  "transition-colors duration-instant",
28842
28900
  "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent",
28843
- "focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-ring focus:ring-inset",
28901
+ "focus:outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-inset",
28844
28902
  styles.button
28845
28903
  ),
28846
28904
  "aria-label": t("aria.decrease"),
@@ -28881,7 +28939,7 @@ var init_NumberStepper = __esm({
28881
28939
  "active:bg-muted",
28882
28940
  "transition-colors duration-instant",
28883
28941
  "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent",
28884
- "focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-ring focus:ring-inset",
28942
+ "focus:outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-inset",
28885
28943
  styles.button
28886
28944
  ),
28887
28945
  "aria-label": t("aria.increase"),
@@ -29337,7 +29395,7 @@ var init_Lightbox = __esm({
29337
29395
  "p-2 rounded-full",
29338
29396
  "text-[var(--color-foreground)] bg-[var(--color-card)]",
29339
29397
  "hover:bg-opacity-70 transition-opacity",
29340
- "focus:outline-none focus:ring-2 focus:ring-ring"
29398
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
29341
29399
  ),
29342
29400
  "aria-label": t("aria.closeModal"),
29343
29401
  children: /* @__PURE__ */ jsx(Icon, { name: "x", className: "w-6 h-6" })
@@ -29356,7 +29414,7 @@ var init_Lightbox = __esm({
29356
29414
  "p-2 rounded-full",
29357
29415
  "text-[var(--color-foreground)] bg-[var(--color-card)]",
29358
29416
  "hover:bg-opacity-70 transition-opacity",
29359
- "focus:outline-none focus:ring-2 focus:ring-ring"
29417
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
29360
29418
  ),
29361
29419
  "aria-label": t("aria.previousImage"),
29362
29420
  children: /* @__PURE__ */ jsx(Icon, { name: "chevron-left", className: "w-8 h-8" })
@@ -29393,7 +29451,7 @@ var init_Lightbox = __esm({
29393
29451
  "p-2 rounded-full",
29394
29452
  "text-[var(--color-foreground)] bg-[var(--color-card)]",
29395
29453
  "hover:bg-opacity-70 transition-opacity",
29396
- "focus:outline-none focus:ring-2 focus:ring-ring"
29454
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
29397
29455
  ),
29398
29456
  "aria-label": t("aria.nextImage"),
29399
29457
  children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", className: "w-8 h-8" })
@@ -29414,6 +29472,26 @@ var init_Lightbox = __esm({
29414
29472
  Lightbox.displayName = "Lightbox";
29415
29473
  }
29416
29474
  });
29475
+ function useMediaQuery(query) {
29476
+ const subscribe = useCallback(
29477
+ (onChange) => {
29478
+ const mql = window.matchMedia(query);
29479
+ mql.addEventListener("change", onChange);
29480
+ return () => mql.removeEventListener("change", onChange);
29481
+ },
29482
+ [query]
29483
+ );
29484
+ return useSyncExternalStore(
29485
+ subscribe,
29486
+ () => window.matchMedia(query).matches,
29487
+ () => false
29488
+ );
29489
+ }
29490
+ var init_useMediaQuery = __esm({
29491
+ "hooks/useMediaQuery.ts"() {
29492
+ "use client";
29493
+ }
29494
+ });
29417
29495
  function renderIconInput3(icon, props) {
29418
29496
  return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
29419
29497
  }
@@ -29520,6 +29598,7 @@ function TableView({
29520
29598
  const hasMore = pageSize > 0 && visibleCount < ordered.length;
29521
29599
  const hasRenderProp = typeof children === "function";
29522
29600
  const idField = dndItemIdField ?? "id";
29601
+ const isCoarsePointer = useMediaQuery("(pointer: coarse)");
29523
29602
  const selected = selectedIds ? new Set(selectedIds) : localSelected;
29524
29603
  const emitSelection = (next) => {
29525
29604
  if (!selectedIds) setLocalSelected(next);
@@ -29552,6 +29631,17 @@ function TableView({
29552
29631
  };
29553
29632
  eventBus.emit(`UI:${action.event}`, payload);
29554
29633
  };
29634
+ const colFloors = React74__default.useMemo(
29635
+ () => colDefs.map((col) => {
29636
+ const longest = data.reduce((widest, row) => {
29637
+ const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
29638
+ return Math.max(widest, cell.length);
29639
+ }, columnLabel(col).length);
29640
+ const chrome = col.format === "badge" ? BADGE_CHROME_CH : 0;
29641
+ return Math.min(longest + chrome, MAX_MEASURED_COL_CH);
29642
+ }),
29643
+ [colDefs, data]
29644
+ );
29555
29645
  if (isLoading) {
29556
29646
  return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") }) });
29557
29647
  }
@@ -29564,19 +29654,10 @@ function TableView({
29564
29654
  }
29565
29655
  const lk = LOOKS[look];
29566
29656
  const hasActions = Boolean(itemActions && itemActions.length > 0);
29567
- const inlineActionCount = hasActions ? maxInlineActions != null ? Math.min(itemActions.length, maxInlineActions) : itemActions.length : 0;
29568
- const hasOverflowActions = hasActions && maxInlineActions != null && itemActions.length > maxInlineActions;
29657
+ const effectiveMaxInline = isCoarsePointer ? 0 : maxInlineActions;
29658
+ const inlineActionCount = hasActions ? effectiveMaxInline != null ? Math.min(itemActions.length, effectiveMaxInline) : itemActions.length : 0;
29659
+ const hasOverflowActions = hasActions && effectiveMaxInline != null && itemActions.length > effectiveMaxInline;
29569
29660
  const actionsTrack = hasActions ? `${inlineActionCount * 6 + (hasOverflowActions ? 3 : 0)}rem` : null;
29570
- const colFloors = React74__default.useMemo(
29571
- () => colDefs.map((col) => {
29572
- const longest = data.reduce((widest, row) => {
29573
- const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
29574
- return Math.max(widest, cell.length);
29575
- }, columnLabel(col).length);
29576
- return Math.min(longest, MAX_MEASURED_COL_CH);
29577
- }),
29578
- [colDefs, data]
29579
- );
29580
29661
  const gridTemplateColumns = [
29581
29662
  selectable ? "auto" : null,
29582
29663
  ...colDefs.map((c, i) => c.width ?? `minmax(${colFloors[i]}ch, 1fr)`),
@@ -29663,9 +29744,9 @@ function TableView({
29663
29744
  col.className
29664
29745
  );
29665
29746
  if (col.format === "badge" && raw != null && raw !== "") {
29666
- return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx(Badge, { variant: statusVariant4(String(raw)), size: "sm", children: String(raw) }) }, col.key);
29747
+ 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);
29667
29748
  }
29668
- return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
29749
+ return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format) }) }, col.key);
29669
29750
  }),
29670
29751
  itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxs(
29671
29752
  HStack,
@@ -29679,15 +29760,15 @@ function TableView({
29679
29760
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
29680
29761
  ),
29681
29762
  children: [
29682
- (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
29763
+ (effectiveMaxInline != null ? itemActions.slice(0, effectiveMaxInline) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
29683
29764
  Button,
29684
29765
  {
29685
- variant: action.variant ?? "ghost",
29766
+ variant: action.variant === "primary" ? "primary" : "ghost",
29686
29767
  size: "sm",
29687
29768
  onClick: handleActionClick(action, row),
29688
29769
  "data-testid": `action-${action.event}`,
29689
29770
  "data-row-id": String(row.id),
29690
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
29771
+ className: cn(action.variant === "danger" && "text-error hover:text-error hover:bg-error/10"),
29691
29772
  children: [
29692
29773
  action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
29693
29774
  action.label
@@ -29695,12 +29776,12 @@ function TableView({
29695
29776
  },
29696
29777
  i
29697
29778
  )),
29698
- maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsx(
29779
+ effectiveMaxInline != null && itemActions.length > effectiveMaxInline && /* @__PURE__ */ jsx(
29699
29780
  Menu,
29700
29781
  {
29701
29782
  position: "bottom-end",
29702
29783
  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" }) }),
29703
- items: itemActions.slice(maxInlineActions).map((action) => ({
29784
+ items: itemActions.slice(effectiveMaxInline).map((action) => ({
29704
29785
  label: action.label,
29705
29786
  icon: action.icon,
29706
29787
  event: action.event,
@@ -29746,13 +29827,14 @@ function TableView({
29746
29827
  }
29747
29828
  );
29748
29829
  }
29749
- var MAX_MEASURED_COL_CH, alignClass, weightClass, LOOKS;
29830
+ var MAX_MEASURED_COL_CH, BADGE_CHROME_CH, alignClass, weightClass, LOOKS;
29750
29831
  var init_TableView = __esm({
29751
29832
  "components/core/molecules/TableView.tsx"() {
29752
29833
  "use client";
29753
29834
  init_cn();
29754
29835
  init_getNestedValue();
29755
29836
  init_useEventBus();
29837
+ init_useMediaQuery();
29756
29838
  init_Box();
29757
29839
  init_Stack();
29758
29840
  init_Typography();
@@ -29765,6 +29847,7 @@ var init_TableView = __esm({
29765
29847
  init_useDataDnd();
29766
29848
  createLogger("almadar:ui:table-view");
29767
29849
  MAX_MEASURED_COL_CH = 32;
29850
+ BADGE_CHROME_CH = 4;
29768
29851
  alignClass = {
29769
29852
  left: "justify-start text-left",
29770
29853
  center: "justify-center text-center",
@@ -29776,7 +29859,7 @@ var init_TableView = __esm({
29776
29859
  semibold: "font-semibold"
29777
29860
  };
29778
29861
  LOOKS = {
29779
- dense: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true },
29862
+ dense: { rowPad: "px-card-md py-2", headPad: "px-card-md py-2", striped: false, divider: true },
29780
29863
  spacious: { rowPad: "px-card-lg py-card-md", headPad: "px-card-lg py-card-sm", striped: false, divider: true },
29781
29864
  striped: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: true, divider: false },
29782
29865
  borderless: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: false },
@@ -32000,7 +32083,7 @@ var init_VoteStack = __esm({
32000
32083
  "active:bg-muted",
32001
32084
  "transition-colors duration-instant",
32002
32085
  "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent",
32003
- "focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-ring focus:ring-inset",
32086
+ "focus:outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-inset",
32004
32087
  styles.button
32005
32088
  ),
32006
32089
  children: /* @__PURE__ */ jsx(Icon, { name: "chevron-up", className: styles.icon })
@@ -32037,7 +32120,7 @@ var init_VoteStack = __esm({
32037
32120
  "active:bg-muted",
32038
32121
  "transition-colors duration-instant",
32039
32122
  "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent",
32040
- "focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-ring focus:ring-inset",
32123
+ "focus:outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-inset",
32041
32124
  styles.button
32042
32125
  ),
32043
32126
  children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", className: styles.icon })
@@ -32558,7 +32641,7 @@ var init_QrScanner = __esm({
32558
32641
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32559
32642
  "rounded-full bg-black bg-opacity-60 p-2 text-white",
32560
32643
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32561
- "hover:bg-opacity-80 focus:outline-none focus:ring-2 focus:ring-white"
32644
+ "hover:bg-opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-white"
32562
32645
  ),
32563
32646
  "aria-label": isPaused ? t("qrScanner.resumeScanning") : t("qrScanner.pauseScanning"),
32564
32647
  children: isPaused ? /* @__PURE__ */ jsx(Icon, { name: "play", className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Icon, { name: "pause", className: "h-4 w-4" })
@@ -32573,7 +32656,7 @@ var init_QrScanner = __esm({
32573
32656
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32574
32657
  "rounded-full bg-black bg-opacity-60 p-2 text-white",
32575
32658
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32576
- "hover:bg-opacity-80 focus:outline-none focus:ring-2 focus:ring-white"
32659
+ "hover:bg-opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-white"
32577
32660
  ),
32578
32661
  "aria-label": currentFacing === "environment" ? t("qrScanner.switchToFrontCamera") : t("qrScanner.switchToRearCamera"),
32579
32662
  children: /* @__PURE__ */ jsx(Icon, { name: "refresh-cw", className: "h-4 w-4" })
@@ -32588,7 +32671,7 @@ var init_QrScanner = __esm({
32588
32671
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32589
32672
  "rounded-full bg-black bg-opacity-60 px-3 py-2 text-xs text-white",
32590
32673
  // eslint-disable-next-line almadar/no-hardcoded-colors -- media overlay: always over a dark scrim
32591
- "hover:bg-opacity-80 focus:outline-none focus:ring-2 focus:ring-white"
32674
+ "hover:bg-opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-white"
32592
32675
  ),
32593
32676
  "aria-label": t("aria.mockScanDev"),
32594
32677
  children: t("qrScanner.mockScan")
@@ -41054,27 +41137,24 @@ var init_MasterDetailLayout = __esm({
41054
41137
  masterClassName,
41055
41138
  detailClassName
41056
41139
  }) => {
41057
- masterWidth.endsWith("%") ? parseInt(masterWidth, 10) : 30;
41058
41140
  return /* @__PURE__ */ jsxs(
41059
41141
  "div",
41060
41142
  {
41061
- className: cn("flex h-full w-full", className),
41062
- style: {
41063
- display: "grid",
41064
- gridTemplateColumns: masterWidth.endsWith("%") ? `${masterWidth} 1fr` : `${masterWidth} 1fr`
41065
- },
41143
+ className: cn("w-full h-full md:grid md:grid-cols-[var(--master-detail-cols)]", className),
41144
+ style: { "--master-detail-cols": `${masterWidth} 1fr` },
41066
41145
  children: [
41067
41146
  /* @__PURE__ */ jsx(
41068
41147
  "div",
41069
41148
  {
41070
41149
  className: cn(
41071
- "border-r-2 border-border overflow-auto",
41150
+ "border-r border-border overflow-auto",
41151
+ hasSelection && "hidden md:block",
41072
41152
  masterClassName
41073
41153
  ),
41074
41154
  children: master
41075
41155
  }
41076
41156
  ),
41077
- /* @__PURE__ */ jsx("div", { className: cn("overflow-auto", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsx(DefaultEmptyDetail, {}) })
41157
+ /* @__PURE__ */ jsx("div", { className: cn("overflow-auto", !hasSelection && "hidden md:block", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsx(DefaultEmptyDetail, {}) })
41078
41158
  ]
41079
41159
  }
41080
41160
  );
@@ -44627,7 +44707,7 @@ var init_TabbedContainer = __esm({
44627
44707
  onClick: () => !isDisabled && handleTabChange(tab.id),
44628
44708
  className: cn(
44629
44709
  "flex items-center gap-2 px-4 py-3 text-sm font-medium transition-colors",
44630
- "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
44710
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
44631
44711
  "disabled:opacity-50 disabled:cursor-not-allowed",
44632
44712
  isActive ? "bg-primary text-primary-foreground" : "bg-card text-foreground hover:bg-muted",
44633
44713
  isVertical ? "justify-start" : "justify-center"
@@ -48634,7 +48714,7 @@ var I18nContext = createContext({
48634
48714
  });
48635
48715
  I18nContext.displayName = "I18nContext";
48636
48716
  var I18nProvider = I18nContext.Provider;
48637
- function useTranslate115() {
48717
+ function useTranslate114() {
48638
48718
  return useContext(I18nContext);
48639
48719
  }
48640
48720
  function createTranslate(messages) {
@@ -48654,6 +48734,7 @@ init_useAuthContext();
48654
48734
  init_useSwipeGesture();
48655
48735
  init_useLongPress();
48656
48736
  init_useDragReorder();
48737
+ init_useMediaQuery();
48657
48738
  init_useInfiniteScroll();
48658
48739
  init_usePullToRefresh();
48659
48740
  init_useCanvasGestures();
@@ -48899,4 +48980,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
48899
48980
  });
48900
48981
  }
48901
48982
 
48902
- export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioToggle, GameHud, GameIcon, GameMenu, GameShell, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, ImportPreviewTree, ImportProgress, ImportSourcePicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, Modal, ModalSlot, ModuleCard, Navigation, NodeSlotEditor, NotifyListener, NumberStepper, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, PageTransition, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, Presence, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, RichBlockEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, ServiceCatalog, SharedEntityStoreContext, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateGraph, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VersionDiff, ViolationAlert, VoteStack, WizardContainer, WizardNavigation, WizardProgress, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, registerCodeLanguageLoader, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useOrbitalHistory, usePresence, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useSwipeGesture, useTapReveal, useTraitListens, useTranslate115 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };
48983
+ export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioToggle, GameHud, GameIcon, GameMenu, GameShell, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, ImportPreviewTree, ImportProgress, ImportSourcePicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, Modal, ModalSlot, ModuleCard, Navigation, NodeSlotEditor, NotifyListener, NumberStepper, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, PageTransition, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, Presence, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, RichBlockEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, ServiceCatalog, SharedEntityStoreContext, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateGraph, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VersionDiff, ViolationAlert, VoteStack, WizardContainer, WizardNavigation, WizardProgress, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, registerCodeLanguageLoader, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useMediaQuery, useOrbitalHistory, usePresence, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useSwipeGesture, useTapReveal, useTraitListens, useTranslate114 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };