@almadar/ui 5.131.0 → 5.133.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1820,6 +1820,8 @@ var init_Badge = __esm({
1820
1820
  };
1821
1821
  const iconPx = size === "lg" ? 20 : 16;
1822
1822
  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;
1823
+ const hasText = Boolean(children) || amount != null || label !== void 0 && label !== null && label !== "";
1824
+ if (!hasText && !resolvedIcon && !onRemove) return null;
1823
1825
  return /* @__PURE__ */ jsxs(
1824
1826
  "span",
1825
1827
  {
@@ -5142,11 +5144,13 @@ var init_TrendIndicator = __esm({
5142
5144
  size = "md",
5143
5145
  ...props
5144
5146
  }, ref) => {
5145
- const dir = resolveDirection(value, direction);
5147
+ const hasValue = typeof value === "number" && Number.isFinite(value);
5148
+ if (!hasValue && !direction) return null;
5149
+ const dir = resolveDirection(hasValue ? value : void 0, direction);
5146
5150
  const colorClass = resolveColor(dir, invert);
5147
5151
  const iconName = iconNameMap[dir];
5148
5152
  const styles = sizeStyles6[size];
5149
- const formattedValue = value !== void 0 ? `${value > 0 ? "+" : ""}${value}%` : void 0;
5153
+ const formattedValue = hasValue ? `${value > 0 ? "+" : ""}${value}%` : void 0;
5150
5154
  const ariaLabel = label ?? (formattedValue ? `${dir} ${formattedValue}` : dir);
5151
5155
  return /* @__PURE__ */ jsxs(
5152
5156
  "span",
@@ -18046,26 +18050,19 @@ var init_BookViewer = __esm({
18046
18050
  function BoxPattern({
18047
18051
  p,
18048
18052
  m,
18049
- bg = "transparent",
18050
- border = false,
18051
- radius = "none",
18052
- shadow = "none",
18053
- className,
18054
- style,
18055
- children
18053
+ radius,
18054
+ isLoading: _isLoading,
18055
+ error: _error,
18056
+ entity: _entity,
18057
+ ...boxProps
18056
18058
  }) {
18057
18059
  return /* @__PURE__ */ jsx(
18058
18060
  Box,
18059
18061
  {
18060
- padding: p,
18061
- margin: m,
18062
- bg,
18063
- border,
18064
- rounded: radius,
18065
- shadow,
18066
- className,
18067
- style,
18068
- children
18062
+ padding: boxProps.padding ?? p,
18063
+ margin: boxProps.margin ?? m,
18064
+ rounded: boxProps.rounded ?? radius,
18065
+ ...boxProps
18069
18066
  }
18070
18067
  );
18071
18068
  }
@@ -21756,17 +21753,19 @@ var init_DashboardLayout = __esm({
21756
21753
  const [sidebarOpen, setSidebarOpen] = useState(false);
21757
21754
  const [userMenuOpen, setUserMenuOpen] = useState(false);
21758
21755
  const layoutRef = useRef(null);
21759
- const [isMobile, setIsMobile] = useState(false);
21756
+ const [layoutWidth, setLayoutWidth] = useState(null);
21760
21757
  useEffect(() => {
21761
21758
  const el = layoutRef.current;
21762
21759
  if (!el || typeof ResizeObserver === "undefined") return;
21763
21760
  const ro = new ResizeObserver((entries) => {
21764
21761
  const w = entries[0]?.contentRect.width ?? el.clientWidth;
21765
- setIsMobile(w < 1024);
21762
+ setLayoutWidth(w);
21766
21763
  });
21767
21764
  ro.observe(el);
21768
21765
  return () => ro.disconnect();
21769
21766
  }, []);
21767
+ const isMobile = layoutWidth !== null && layoutWidth < 768;
21768
+ const isRail = layoutWidth !== null && layoutWidth >= 768 && layoutWidth < 1024;
21770
21769
  useEffect(() => {
21771
21770
  if (!isMobile && sidebarOpen) setSidebarOpen(false);
21772
21771
  }, [isMobile, sidebarOpen]);
@@ -21799,7 +21798,8 @@ var init_DashboardLayout = __esm({
21799
21798
  {
21800
21799
  as: "aside",
21801
21800
  className: cn(
21802
- "z-30 w-64 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
21801
+ "z-30 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
21802
+ isRail ? "w-16" : "w-64",
21803
21803
  "flex flex-col"
21804
21804
  ),
21805
21805
  style: isMobile ? {
@@ -21815,10 +21815,10 @@ var init_DashboardLayout = __esm({
21815
21815
  HStack,
21816
21816
  {
21817
21817
  align: "center",
21818
- justify: "between",
21819
- className: "h-16 px-4 border-b border-border dark:border-border",
21818
+ justify: isRail ? "center" : "between",
21819
+ className: cn("h-16 border-b border-border dark:border-border", isRail ? "px-2" : "px-4"),
21820
21820
  children: [
21821
- /* @__PURE__ */ jsxs(Link, { to: "/", className: "flex items-center gap-2", children: [
21821
+ /* @__PURE__ */ jsxs(Link, { to: "/", className: "flex items-center gap-2", title: isRail ? appName : void 0, children: [
21822
21822
  logo || /* @__PURE__ */ jsx(Box, { className: "w-8 h-8 bg-primary rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsx(
21823
21823
  Typography,
21824
21824
  {
@@ -21828,7 +21828,7 @@ var init_DashboardLayout = __esm({
21828
21828
  children: appName.charAt(0).toUpperCase()
21829
21829
  }
21830
21830
  ) }),
21831
- /* @__PURE__ */ jsx(
21831
+ !isRail && /* @__PURE__ */ jsx(
21832
21832
  Typography,
21833
21833
  {
21834
21834
  variant: "label",
@@ -21855,12 +21855,13 @@ var init_DashboardLayout = __esm({
21855
21855
  {
21856
21856
  as: "nav",
21857
21857
  gap: "none",
21858
- className: "flex-1 px-3 py-4 space-y-1 overflow-y-auto",
21858
+ className: cn("flex-1 py-4 space-y-1 overflow-y-auto", isRail ? "px-2" : "px-3"),
21859
21859
  children: navItems.map((item) => /* @__PURE__ */ jsx(
21860
21860
  NavLink,
21861
21861
  {
21862
21862
  item,
21863
- currentPath: activePath
21863
+ currentPath: activePath,
21864
+ compact: isRail
21864
21865
  },
21865
21866
  item.href
21866
21867
  ))
@@ -22115,13 +22116,40 @@ var init_DashboardLayout = __esm({
22115
22116
  DashboardLayout.displayName = "DashboardLayout";
22116
22117
  NavLink = ({
22117
22118
  item,
22118
- currentPath
22119
+ currentPath,
22120
+ compact = false
22119
22121
  }) => {
22120
22122
  const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
22121
22123
  const iconClassName = cn(
22122
22124
  "h-5 w-5",
22123
22125
  isActive ? "text-primary-foreground" : "text-muted-foreground"
22124
22126
  );
22127
+ if (compact) {
22128
+ return /* @__PURE__ */ jsx(
22129
+ Link,
22130
+ {
22131
+ to: item.href,
22132
+ title: item.label,
22133
+ "aria-label": item.label,
22134
+ className: cn(
22135
+ "flex items-center justify-center px-2 py-2 rounded-lg transition-colors",
22136
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
22137
+ ),
22138
+ children: /* @__PURE__ */ jsxs(Box, { as: "span", className: "relative inline-flex", children: [
22139
+ 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() }),
22140
+ item.badge && /* @__PURE__ */ jsx(
22141
+ Badge,
22142
+ {
22143
+ variant: isActive ? "primary" : "default",
22144
+ size: "sm",
22145
+ className: "absolute -top-2 -right-2 px-1 py-0 text-[10px] leading-4",
22146
+ children: item.badge
22147
+ }
22148
+ )
22149
+ ] })
22150
+ }
22151
+ );
22152
+ }
22125
22153
  return /* @__PURE__ */ jsxs(
22126
22154
  Link,
22127
22155
  {
@@ -23187,40 +23215,55 @@ function DataGrid({
23187
23215
  {
23188
23216
  "data-entity-row": true,
23189
23217
  "data-entity-id": id,
23190
- className: cn(isSelected && "ring-2 ring-primary rounded-lg"),
23218
+ className: cn("relative group/rowactions", isSelected && "ring-2 ring-primary rounded-lg"),
23191
23219
  children: [
23192
23220
  children(itemData, index),
23193
- 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: [
23194
- (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxs(
23195
- Button,
23196
- {
23197
- variant: action.variant === "primary" ? "primary" : "ghost",
23198
- size: "sm",
23199
- onClick: handleActionClick(action, itemData),
23200
- "data-testid": `action-${action.event}`,
23201
- "data-row-id": String(itemData.id),
23202
- className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
23203
- children: [
23204
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
23205
- action.label
23206
- ]
23207
- },
23208
- idx
23209
- )),
23210
- maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
23221
+ 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: [
23222
+ /* @__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: [
23223
+ (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxs(
23224
+ Button,
23225
+ {
23226
+ variant: action.variant === "primary" ? "primary" : "ghost",
23227
+ size: "sm",
23228
+ onClick: handleActionClick(action, itemData),
23229
+ "data-testid": `action-${action.event}`,
23230
+ "data-row-id": String(itemData.id),
23231
+ className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
23232
+ children: [
23233
+ action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
23234
+ action.label
23235
+ ]
23236
+ },
23237
+ idx
23238
+ )),
23239
+ maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
23240
+ Menu,
23241
+ {
23242
+ position: "bottom-end",
23243
+ 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" }) }),
23244
+ items: actionDefs.slice(maxInlineActions).map((action) => ({
23245
+ label: action.label,
23246
+ icon: action.icon,
23247
+ event: action.event,
23248
+ onClick: () => fireAction(action, itemData)
23249
+ }))
23250
+ }
23251
+ )
23252
+ ] }),
23253
+ /* @__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(
23211
23254
  Menu,
23212
23255
  {
23213
23256
  position: "bottom-end",
23214
23257
  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" }) }),
23215
- items: actionDefs.slice(maxInlineActions).map((action) => ({
23258
+ items: actionDefs.map((action) => ({
23216
23259
  label: action.label,
23217
23260
  icon: action.icon,
23218
23261
  event: action.event,
23219
23262
  onClick: () => fireAction(action, itemData)
23220
23263
  }))
23221
23264
  }
23222
- )
23223
- ] }) })
23265
+ ) })
23266
+ ] })
23224
23267
  ]
23225
23268
  },
23226
23269
  id
@@ -23256,7 +23299,7 @@ function DataGrid({
23256
23299
  }
23257
23300
  ) });
23258
23301
  })(),
23259
- /* @__PURE__ */ jsx(Box, { className: "p-4 pb-0", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
23302
+ /* @__PURE__ */ jsx(Box, { className: cn("p-4", bodyFields.length > 0 && "pb-0"), children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-start", children: [
23260
23303
  selectable && /* @__PURE__ */ jsx(
23261
23304
  "input",
23262
23305
  {
@@ -23289,78 +23332,77 @@ function DataGrid({
23289
23332
  ] }, field.name);
23290
23333
  }) })
23291
23334
  ] }),
23292
- dangerActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: dangerActions.map((action, idx) => /* @__PURE__ */ jsx(
23293
- Button,
23294
- {
23295
- variant: "ghost",
23296
- size: "sm",
23297
- onClick: handleActionClick(action, itemData),
23298
- "data-testid": `action-${action.event}`,
23299
- "data-row-id": String(itemData.id),
23300
- "aria-label": action.label,
23301
- title: action.label,
23302
- className: "text-error hover:text-error hover:bg-error/10 px-2",
23303
- children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
23304
- },
23305
- idx
23306
- )) })
23307
- ] }) }),
23308
- bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: bodyFields.map((field) => {
23309
- const value = getNestedValue(itemData, field.name);
23310
- if (value === void 0 || value === null || value === "") return null;
23311
- if (field.format === "boolean") {
23312
- return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
23313
- /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
23314
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
23315
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
23316
- ] }),
23317
- /* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
23318
- ] }, field.name);
23319
- }
23320
- return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between items-center", children: [
23321
- /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
23322
- field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
23323
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) })
23324
- ] }),
23325
- /* @__PURE__ */ jsx(
23326
- Typography,
23335
+ (primaryActions.length > 0 || dangerActions.length > 0) && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "flex-shrink-0", children: [
23336
+ (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsx(
23337
+ Button,
23338
+ {
23339
+ variant: action.variant === "primary" ? "primary" : "ghost",
23340
+ size: "sm",
23341
+ onClick: handleActionClick(action, itemData),
23342
+ "data-testid": `action-${action.event}`,
23343
+ "data-row-id": String(itemData.id),
23344
+ "aria-label": action.label,
23345
+ title: action.label,
23346
+ className: cn(
23347
+ action.variant === "primary" ? void 0 : "text-muted-foreground hover:text-foreground",
23348
+ action.icon && "px-2"
23349
+ ),
23350
+ children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
23351
+ },
23352
+ idx
23353
+ )),
23354
+ maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsx(
23355
+ Menu,
23327
23356
  {
23328
- variant: field.variant === "caption" ? "caption" : "small",
23329
- className: "text-right truncate max-w-[60%]",
23330
- children: formatValue(value, field.format)
23357
+ position: "bottom-end",
23358
+ 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" }) }),
23359
+ items: primaryActions.slice(maxInlineActions).map((action) => ({
23360
+ label: action.label,
23361
+ icon: action.icon,
23362
+ event: action.event,
23363
+ onClick: () => fireAction(action, itemData)
23364
+ }))
23331
23365
  }
23332
- )
23333
- ] }, field.name);
23334
- }) }) }),
23335
- 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: [
23336
- (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxs(
23337
- Button,
23338
- {
23339
- variant: action.variant === "primary" ? "primary" : "ghost",
23340
- size: "sm",
23341
- onClick: handleActionClick(action, itemData),
23342
- "data-testid": `action-${action.event}`,
23343
- "data-row-id": String(itemData.id),
23344
- children: [
23345
- action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
23346
- action.label
23347
- ]
23348
- },
23349
- idx
23350
- )),
23351
- maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsx(
23352
- Menu,
23353
- {
23354
- position: "bottom-end",
23355
- 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" }) }),
23356
- items: primaryActions.slice(maxInlineActions).map((action) => ({
23357
- label: action.label,
23358
- icon: action.icon,
23359
- event: action.event,
23360
- onClick: () => fireAction(action, itemData)
23361
- }))
23366
+ ),
23367
+ dangerActions.map((action, idx) => /* @__PURE__ */ jsx(
23368
+ Button,
23369
+ {
23370
+ variant: "ghost",
23371
+ size: "sm",
23372
+ onClick: handleActionClick(action, itemData),
23373
+ "data-testid": `action-${action.event}`,
23374
+ "data-row-id": String(itemData.id),
23375
+ "aria-label": action.label,
23376
+ title: action.label,
23377
+ className: "text-error hover:text-error hover:bg-error/10 px-2",
23378
+ children: action.icon ? renderIconInput(action.icon, { size: "xs" }) : action.label
23379
+ },
23380
+ `danger-${idx}`
23381
+ ))
23382
+ ] })
23383
+ ] }) }),
23384
+ bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 pt-2 pb-4 flex-1", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
23385
+ bodyFields.filter((f3) => f3.variant === "caption" && f3.format !== "boolean").map((field) => {
23386
+ const value = getNestedValue(itemData, field.name);
23387
+ if (value === void 0 || value === null || value === "") return null;
23388
+ return /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", className: "line-clamp-2", children: formatValue(value, field.format) }, field.name);
23389
+ }),
23390
+ /* @__PURE__ */ jsx(HStack, { gap: "md", className: "flex-wrap gap-y-1", children: bodyFields.filter((f3) => f3.variant !== "caption" || f3.format === "boolean").map((field) => {
23391
+ const value = getNestedValue(itemData, field.name);
23392
+ if (value === void 0 || value === null || value === "") return null;
23393
+ if (field.format === "boolean") {
23394
+ return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
23395
+ field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
23396
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: field.label ?? fieldLabel2(field.name) }),
23397
+ /* @__PURE__ */ jsx(Badge, { variant: value ? "success" : "neutral", children: value ? t("common.yes") || "Yes" : t("common.no") || "No" })
23398
+ ] }, field.name);
23362
23399
  }
23363
- )
23400
+ return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
23401
+ field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
23402
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
23403
+ /* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue(value, field.format) })
23404
+ ] }, field.name);
23405
+ }) })
23364
23406
  ] }) })
23365
23407
  ]
23366
23408
  },
@@ -23708,11 +23750,29 @@ function DataList({
23708
23750
  const wrapDnd = (node) => dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: dndId, children: node }, dndId) : node;
23709
23751
  if (hasRenderProp) {
23710
23752
  const id2 = itemData.id || String(index);
23753
+ const actions = renderItemActions(itemData);
23711
23754
  return wrapDnd(
23712
- /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick: itemClickEvent ? handleRowClick(itemData) : void 0, className: cn(itemClickEvent && "cursor-pointer"), children: [
23713
- /* @__PURE__ */ jsxs(Box, { className: "group flex items-stretch gap-2", children: [
23714
- /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
23715
- renderItemActions(itemData)
23755
+ /* @__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: [
23756
+ children(itemData, index),
23757
+ 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: [
23758
+ /* @__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 }),
23759
+ /* @__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(
23760
+ Menu,
23761
+ {
23762
+ position: "bottom-end",
23763
+ 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" }) }),
23764
+ items: (itemActions ?? []).map((action) => ({
23765
+ label: action.label,
23766
+ icon: action.icon,
23767
+ event: action.event,
23768
+ variant: action.variant === "danger" ? "danger" : "default",
23769
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
23770
+ id: itemData.id,
23771
+ row: itemData
23772
+ })
23773
+ }))
23774
+ }
23775
+ ) })
23716
23776
  ] }),
23717
23777
  isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-border/40" })
23718
23778
  ] }, id2)
@@ -23752,7 +23812,7 @@ function DataList({
23752
23812
  ] }, field.name);
23753
23813
  })
23754
23814
  ] }),
23755
- bodyFields.length > 0 && !isCompact && /* @__PURE__ */ jsx(HStack, { gap: "md", className: "mt-1.5 flex-wrap", children: bodyFields.map((field) => {
23815
+ bodyFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "md", className: cn("flex-wrap", isCompact ? "mt-0.5" : "mt-1.5"), children: bodyFields.map((field) => {
23756
23816
  const value = getNestedValue(itemData, field.name);
23757
23817
  if (value === void 0 || value === null || value === "") return null;
23758
23818
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
@@ -27348,7 +27408,7 @@ var init_MapView = __esm({
27348
27408
  shadowSize: [41, 41]
27349
27409
  });
27350
27410
  L.Marker.prototype.options.icon = defaultIcon;
27351
- const { useEffect: useEffect62, useRef: useRef60, useCallback: useCallback93, useState: useState91 } = React84__default;
27411
+ const { useEffect: useEffect62, useRef: useRef60, useCallback: useCallback94, useState: useState91 } = React84__default;
27352
27412
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
27353
27413
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
27354
27414
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -27394,7 +27454,7 @@ var init_MapView = __esm({
27394
27454
  }) {
27395
27455
  const eventBus = useEventBus2();
27396
27456
  const [clickedPosition, setClickedPosition] = useState91(null);
27397
- const handleMapClick = useCallback93((lat, lng) => {
27457
+ const handleMapClick = useCallback94((lat, lng) => {
27398
27458
  if (showClickedPin) {
27399
27459
  setClickedPosition({ lat, lng });
27400
27460
  }
@@ -27403,7 +27463,7 @@ var init_MapView = __esm({
27403
27463
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
27404
27464
  }
27405
27465
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
27406
- const handleMarkerClick = useCallback93((marker) => {
27466
+ const handleMarkerClick = useCallback94((marker) => {
27407
27467
  onMarkerClick?.(marker);
27408
27468
  if (markerClickEvent) {
27409
27469
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -28179,6 +28239,26 @@ var init_Lightbox = __esm({
28179
28239
  Lightbox.displayName = "Lightbox";
28180
28240
  }
28181
28241
  });
28242
+ function useMediaQuery(query) {
28243
+ const subscribe = useCallback(
28244
+ (onChange) => {
28245
+ const mql = window.matchMedia(query);
28246
+ mql.addEventListener("change", onChange);
28247
+ return () => mql.removeEventListener("change", onChange);
28248
+ },
28249
+ [query]
28250
+ );
28251
+ return useSyncExternalStore(
28252
+ subscribe,
28253
+ () => window.matchMedia(query).matches,
28254
+ () => false
28255
+ );
28256
+ }
28257
+ var init_useMediaQuery = __esm({
28258
+ "hooks/useMediaQuery.ts"() {
28259
+ "use client";
28260
+ }
28261
+ });
28182
28262
  function renderIconInput3(icon, props) {
28183
28263
  return typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsx(Icon, { icon, ...props });
28184
28264
  }
@@ -28285,6 +28365,7 @@ function TableView({
28285
28365
  const hasMore = pageSize > 0 && visibleCount < ordered.length;
28286
28366
  const hasRenderProp = typeof children === "function";
28287
28367
  const idField = dndItemIdField ?? "id";
28368
+ const isCoarsePointer = useMediaQuery("(pointer: coarse)");
28288
28369
  const selected = selectedIds ? new Set(selectedIds) : localSelected;
28289
28370
  const emitSelection = (next) => {
28290
28371
  if (!selectedIds) setLocalSelected(next);
@@ -28317,6 +28398,17 @@ function TableView({
28317
28398
  };
28318
28399
  eventBus.emit(`UI:${action.event}`, payload);
28319
28400
  };
28401
+ const colFloors = React84__default.useMemo(
28402
+ () => colDefs.map((col) => {
28403
+ const longest = data.reduce((widest, row) => {
28404
+ const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
28405
+ return Math.max(widest, cell.length);
28406
+ }, columnLabel(col).length);
28407
+ const chrome = col.format === "badge" ? BADGE_CHROME_CH : 0;
28408
+ return Math.min(longest + chrome, MAX_MEASURED_COL_CH);
28409
+ }),
28410
+ [colDefs, data]
28411
+ );
28320
28412
  if (isLoading) {
28321
28413
  return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") }) });
28322
28414
  }
@@ -28329,20 +28421,10 @@ function TableView({
28329
28421
  }
28330
28422
  const lk = LOOKS[look];
28331
28423
  const hasActions = Boolean(itemActions && itemActions.length > 0);
28332
- const inlineActionCount = hasActions ? maxInlineActions != null ? Math.min(itemActions.length, maxInlineActions) : itemActions.length : 0;
28333
- const hasOverflowActions = hasActions && maxInlineActions != null && itemActions.length > maxInlineActions;
28424
+ const effectiveMaxInline = isCoarsePointer ? 0 : maxInlineActions;
28425
+ const inlineActionCount = hasActions ? effectiveMaxInline != null ? Math.min(itemActions.length, effectiveMaxInline) : itemActions.length : 0;
28426
+ const hasOverflowActions = hasActions && effectiveMaxInline != null && itemActions.length > effectiveMaxInline;
28334
28427
  const actionsTrack = hasActions ? `${inlineActionCount * 6 + (hasOverflowActions ? 3 : 0)}rem` : null;
28335
- const colFloors = React84__default.useMemo(
28336
- () => colDefs.map((col) => {
28337
- const longest = data.reduce((widest, row) => {
28338
- const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
28339
- return Math.max(widest, cell.length);
28340
- }, columnLabel(col).length);
28341
- const chrome = col.format === "badge" ? BADGE_CHROME_CH : 0;
28342
- return Math.min(longest + chrome, MAX_MEASURED_COL_CH);
28343
- }),
28344
- [colDefs, data]
28345
- );
28346
28428
  const gridTemplateColumns = [
28347
28429
  selectable ? "auto" : null,
28348
28430
  ...colDefs.map((c, i) => c.width ?? `minmax(${colFloors[i]}ch, 1fr)`),
@@ -28431,7 +28513,7 @@ function TableView({
28431
28513
  if (col.format === "badge" && raw != null && raw !== "") {
28432
28514
  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);
28433
28515
  }
28434
- return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
28516
+ return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format) }) }, col.key);
28435
28517
  }),
28436
28518
  itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxs(
28437
28519
  HStack,
@@ -28445,15 +28527,15 @@ function TableView({
28445
28527
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
28446
28528
  ),
28447
28529
  children: [
28448
- (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
28530
+ (effectiveMaxInline != null ? itemActions.slice(0, effectiveMaxInline) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
28449
28531
  Button,
28450
28532
  {
28451
- variant: action.variant ?? "ghost",
28533
+ variant: action.variant === "primary" ? "primary" : "ghost",
28452
28534
  size: "sm",
28453
28535
  onClick: handleActionClick(action, row),
28454
28536
  "data-testid": `action-${action.event}`,
28455
28537
  "data-row-id": String(row.id),
28456
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
28538
+ className: cn(action.variant === "danger" && "text-error hover:text-error hover:bg-error/10"),
28457
28539
  children: [
28458
28540
  action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
28459
28541
  action.label
@@ -28461,12 +28543,12 @@ function TableView({
28461
28543
  },
28462
28544
  i
28463
28545
  )),
28464
- maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsx(
28546
+ effectiveMaxInline != null && itemActions.length > effectiveMaxInline && /* @__PURE__ */ jsx(
28465
28547
  Menu,
28466
28548
  {
28467
28549
  position: "bottom-end",
28468
28550
  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" }) }),
28469
- items: itemActions.slice(maxInlineActions).map((action) => ({
28551
+ items: itemActions.slice(effectiveMaxInline).map((action) => ({
28470
28552
  label: action.label,
28471
28553
  icon: action.icon,
28472
28554
  event: action.event,
@@ -28519,6 +28601,7 @@ var init_TableView = __esm({
28519
28601
  init_cn();
28520
28602
  init_getNestedValue();
28521
28603
  init_useEventBus();
28604
+ init_useMediaQuery();
28522
28605
  init_Box();
28523
28606
  init_Stack();
28524
28607
  init_Typography();
@@ -28543,7 +28626,7 @@ var init_TableView = __esm({
28543
28626
  semibold: "font-semibold"
28544
28627
  };
28545
28628
  LOOKS = {
28546
- dense: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true },
28629
+ dense: { rowPad: "px-card-md py-2", headPad: "px-card-md py-2", striped: false, divider: true },
28547
28630
  spacious: { rowPad: "px-card-lg py-card-md", headPad: "px-card-lg py-card-sm", striped: false, divider: true },
28548
28631
  striped: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: true, divider: false },
28549
28632
  borderless: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: false },
@@ -36997,7 +37080,17 @@ function DataTable({
36997
37080
  const currentPageSize = pageSize ?? 20;
36998
37081
  const total = totalCount ?? items.length;
36999
37082
  const totalPages = Math.ceil(total / currentPageSize);
37000
- const rowActions = externalRowActions ?? itemActions?.filter((a) => a.placement !== "bulk").map((action) => ({
37083
+ const withEventClick = (action) => {
37084
+ if (action.onClick || !action.event) return action;
37085
+ const event = action.event;
37086
+ return {
37087
+ ...action,
37088
+ onClick: (row) => {
37089
+ eventBus.emit(`UI:${event}`, { row });
37090
+ }
37091
+ };
37092
+ };
37093
+ const rowActions = (externalRowActions ?? itemActions?.filter((a) => a.placement !== "bulk").map((action) => ({
37001
37094
  label: action.label,
37002
37095
  icon: action.icon,
37003
37096
  variant: action.variant,
@@ -37017,7 +37110,17 @@ function DataTable({
37017
37110
  });
37018
37111
  }
37019
37112
  }
37020
- }));
37113
+ })))?.map(withEventClick);
37114
+ const normalizedBulkActions = bulkActions?.map((action) => {
37115
+ if (action.onClick || !action.event) return action;
37116
+ const event = action.event;
37117
+ return {
37118
+ ...action,
37119
+ onClick: (selectedRows2) => {
37120
+ eventBus.emit(`UI:${event}`, { rows: selectedRows2 });
37121
+ }
37122
+ };
37123
+ });
37021
37124
  const viewAction = itemActions?.find(
37022
37125
  (a) => a.event === "VIEW" || a.navigatesTo
37023
37126
  );
@@ -37125,7 +37228,7 @@ function DataTable({
37125
37228
  }
37126
37229
  )
37127
37230
  ] }),
37128
- bulkActions && selectedIds.length > 0 && /* @__PURE__ */ jsxs(HStack, { className: "items-center gap-2 pl-0 sm:pl-3 border-l-0 sm:border-l border-border", children: [
37231
+ normalizedBulkActions && selectedIds.length > 0 && /* @__PURE__ */ jsxs(HStack, { className: "items-center gap-2 pl-0 sm:pl-3 border-l-0 sm:border-l border-border", children: [
37129
37232
  /* @__PURE__ */ jsx(
37130
37233
  Typography,
37131
37234
  {
@@ -37136,13 +37239,13 @@ function DataTable({
37136
37239
  })
37137
37240
  }
37138
37241
  ),
37139
- /* @__PURE__ */ jsx(HStack, { className: "flex-wrap gap-2", children: bulkActions.map((action, idx) => /* @__PURE__ */ jsx(
37242
+ /* @__PURE__ */ jsx(HStack, { className: "flex-wrap gap-2", children: normalizedBulkActions.map((action, idx) => /* @__PURE__ */ jsx(
37140
37243
  Button,
37141
37244
  {
37142
37245
  variant: action.variant === "danger" ? "danger" : "secondary",
37143
37246
  size: "sm",
37144
37247
  leftIcon: action.icon,
37145
- onClick: () => action.onClick(selectedRows),
37248
+ onClick: () => action.onClick?.(selectedRows),
37146
37249
  children: action.label
37147
37250
  },
37148
37251
  idx
@@ -37304,7 +37407,7 @@ function DataTable({
37304
37407
  ),
37305
37408
  onClick: (e) => {
37306
37409
  e.stopPropagation();
37307
- action.onClick(row);
37410
+ action.onClick?.(row);
37308
37411
  setOpenActionMenu(null);
37309
37412
  },
37310
37413
  children: [
@@ -39600,27 +39703,24 @@ var init_MasterDetailLayout = __esm({
39600
39703
  masterClassName,
39601
39704
  detailClassName
39602
39705
  }) => {
39603
- masterWidth.endsWith("%") ? parseInt(masterWidth, 10) : 30;
39604
39706
  return /* @__PURE__ */ jsxs(
39605
39707
  "div",
39606
39708
  {
39607
- className: cn("flex h-full w-full", className),
39608
- style: {
39609
- display: "grid",
39610
- gridTemplateColumns: masterWidth.endsWith("%") ? `${masterWidth} 1fr` : `${masterWidth} 1fr`
39611
- },
39709
+ className: cn("w-full h-full md:grid md:grid-cols-[var(--master-detail-cols)]", className),
39710
+ style: { "--master-detail-cols": `${masterWidth} 1fr` },
39612
39711
  children: [
39613
39712
  /* @__PURE__ */ jsx(
39614
39713
  "div",
39615
39714
  {
39616
39715
  className: cn(
39617
- "border-r-2 border-border overflow-auto",
39716
+ "border-r border-border overflow-auto",
39717
+ hasSelection && "hidden md:block",
39618
39718
  masterClassName
39619
39719
  ),
39620
39720
  children: master
39621
39721
  }
39622
39722
  ),
39623
- /* @__PURE__ */ jsx("div", { className: cn("overflow-auto", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsx(DefaultEmptyDetail, {}) })
39723
+ /* @__PURE__ */ jsx("div", { className: cn("overflow-auto", !hasSelection && "hidden md:block", detailClassName), children: hasSelection ? detail : emptyDetail || /* @__PURE__ */ jsx(DefaultEmptyDetail, {}) })
39624
39724
  ]
39625
39725
  }
39626
39726
  );