@almadar/ui 5.9.10 → 5.12.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.
@@ -22203,6 +22203,8 @@ function DataGrid({
22203
22203
  fields,
22204
22204
  columns,
22205
22205
  itemActions,
22206
+ maxInlineActions,
22207
+ scrollX = false,
22206
22208
  cols,
22207
22209
  gap = "md",
22208
22210
  minCardWidth = 280,
@@ -22342,8 +22344,8 @@ function DataGrid({
22342
22344
  /* @__PURE__ */ jsxRuntime.jsx(
22343
22345
  exports.Box,
22344
22346
  {
22345
- className: cn("grid", gapStyles6[gap], colsClass, lookStyles5[look], className),
22346
- style: gridTemplateColumns ? { gridTemplateColumns } : void 0,
22347
+ className: cn("grid", gapStyles6[gap], scrollX ? "grid-flow-col overflow-x-auto" : colsClass, lookStyles5[look], className),
22348
+ style: scrollX ? { gridAutoFlow: "column", gridAutoColumns: `minmax(${minCardWidth}px, 1fr)` } : gridTemplateColumns ? { gridTemplateColumns } : void 0,
22347
22349
  children: data.map((item, index) => {
22348
22350
  const itemData = item;
22349
22351
  const id = itemData.id || String(index);
@@ -22470,21 +22472,39 @@ function DataGrid({
22470
22472
  )
22471
22473
  ] }, field.name);
22472
22474
  }) }) }),
22473
- primaryActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "sm", className: "justify-end", children: primaryActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
22474
- exports.Button,
22475
- {
22476
- variant: action.variant === "primary" ? "primary" : "ghost",
22477
- size: "sm",
22478
- onClick: handleActionClick(action, itemData),
22479
- "data-testid": `action-${action.event}`,
22480
- "data-row-id": String(itemData.id),
22481
- children: [
22482
- action.icon && /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: action.icon, size: "xs", className: "mr-1" }),
22483
- action.label
22484
- ]
22485
- },
22486
- idx
22487
- )) }) })
22475
+ primaryActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-end", children: [
22476
+ (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
22477
+ exports.Button,
22478
+ {
22479
+ variant: action.variant === "primary" ? "primary" : "ghost",
22480
+ size: "sm",
22481
+ onClick: handleActionClick(action, itemData),
22482
+ "data-testid": `action-${action.event}`,
22483
+ "data-row-id": String(itemData.id),
22484
+ children: [
22485
+ action.icon && /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: action.icon, size: "xs", className: "mr-1" }),
22486
+ action.label
22487
+ ]
22488
+ },
22489
+ idx
22490
+ )),
22491
+ maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
22492
+ exports.Menu,
22493
+ {
22494
+ position: "bottom-end",
22495
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": "More actions", "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
22496
+ items: primaryActions.slice(maxInlineActions).map((action) => ({
22497
+ label: action.label,
22498
+ icon: action.icon,
22499
+ event: action.event,
22500
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
22501
+ id: itemData.id,
22502
+ row: itemData
22503
+ })
22504
+ }))
22505
+ }
22506
+ )
22507
+ ] }) })
22488
22508
  ]
22489
22509
  },
22490
22510
  id
@@ -22534,6 +22554,7 @@ var init_DataGrid = __esm({
22534
22554
  init_Button();
22535
22555
  init_Icon();
22536
22556
  init_InfiniteScrollSentinel();
22557
+ init_Menu();
22537
22558
  init_useDataDnd();
22538
22559
  dataGridLog = logger.createLogger("almadar:ui:data-grid");
22539
22560
  BADGE_VARIANTS = /* @__PURE__ */ new Set([
@@ -22613,6 +22634,7 @@ function DataList({
22613
22634
  fields,
22614
22635
  columns,
22615
22636
  itemActions,
22637
+ maxInlineActions,
22616
22638
  itemClickEvent,
22617
22639
  gap = "none",
22618
22640
  variant = "default",
@@ -22703,6 +22725,46 @@ function DataList({
22703
22725
  };
22704
22726
  eventBus.emit(`UI:${action.event}`, payload);
22705
22727
  };
22728
+ const renderItemActions = (itemData) => {
22729
+ if (!itemActions || itemActions.length === 0) return null;
22730
+ const inline = maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions;
22731
+ const overflow = maxInlineActions != null ? itemActions.slice(maxInlineActions) : [];
22732
+ return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "flex-shrink-0", children: [
22733
+ inline.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
22734
+ exports.Button,
22735
+ {
22736
+ variant: action.variant ?? "ghost",
22737
+ size: "sm",
22738
+ onClick: handleActionClick(action, itemData),
22739
+ "data-testid": `action-${action.event}`,
22740
+ "data-row-id": String(itemData.id),
22741
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
22742
+ children: [
22743
+ action.icon && /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: action.icon, size: "xs", className: "mr-1" }),
22744
+ action.label
22745
+ ]
22746
+ },
22747
+ idx
22748
+ )),
22749
+ overflow.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
22750
+ exports.Menu,
22751
+ {
22752
+ position: "bottom-end",
22753
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": "More actions", "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
22754
+ items: overflow.map((action) => ({
22755
+ label: action.label,
22756
+ icon: action.icon,
22757
+ event: action.event,
22758
+ variant: action.variant === "danger" ? "danger" : "default",
22759
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
22760
+ id: itemData.id,
22761
+ row: itemData
22762
+ })
22763
+ }))
22764
+ }
22765
+ )
22766
+ ] });
22767
+ };
22706
22768
  const handleRowClick = (itemData) => () => {
22707
22769
  if (!itemClickEvent) return;
22708
22770
  const payload = {
@@ -22792,31 +22854,7 @@ function DataList({
22792
22854
  /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { "data-entity-row": true, "data-entity-id": id2, onClick: itemClickEvent ? handleRowClick(itemData) : void 0, className: cn(itemClickEvent && "cursor-pointer"), children: [
22793
22855
  /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "group flex items-stretch gap-2", children: [
22794
22856
  /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
22795
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
22796
- exports.HStack,
22797
- {
22798
- gap: "xs",
22799
- className: "flex-shrink-0",
22800
- children: itemActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
22801
- exports.Button,
22802
- {
22803
- variant: action.variant ?? "ghost",
22804
- size: "sm",
22805
- onClick: handleActionClick(action, itemData),
22806
- "data-testid": `action-${action.event}`,
22807
- "data-row-id": String(itemData.id),
22808
- className: cn(
22809
- action.variant === "danger" && "text-error hover:bg-error/10"
22810
- ),
22811
- children: [
22812
- action.icon && /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: action.icon, size: "xs", className: "mr-1" }),
22813
- action.label
22814
- ]
22815
- },
22816
- idx
22817
- ))
22818
- }
22819
- )
22857
+ renderItemActions(itemData)
22820
22858
  ] }),
22821
22859
  isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "mx-6 border-b border-border/40" })
22822
22860
  ] }, id2)
@@ -22887,24 +22925,7 @@ function DataList({
22887
22925
  ] }, field.name);
22888
22926
  })
22889
22927
  ] }),
22890
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", className: "flex-shrink-0", children: itemActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
22891
- exports.Button,
22892
- {
22893
- variant: action.variant ?? "ghost",
22894
- size: "sm",
22895
- onClick: handleActionClick(action, itemData),
22896
- "data-testid": `action-${action.event}`,
22897
- "data-row-id": String(itemData.id),
22898
- className: cn(
22899
- action.variant === "danger" && "text-error hover:bg-error/10"
22900
- ),
22901
- children: [
22902
- action.icon && /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: action.icon, size: "xs", className: "mr-1" }),
22903
- action.label
22904
- ]
22905
- },
22906
- idx
22907
- )) })
22928
+ renderItemActions(itemData)
22908
22929
  ]
22909
22930
  }
22910
22931
  ),
@@ -22974,6 +22995,7 @@ var init_DataList = __esm({
22974
22995
  init_ProgressBar();
22975
22996
  init_Divider();
22976
22997
  init_InfiniteScrollSentinel();
22998
+ init_Menu();
22977
22999
  init_useDataDnd();
22978
23000
  dataListLog = logger.createLogger("almadar:ui:data-list");
22979
23001
  listLookStyles = {
@@ -28375,6 +28397,7 @@ function TableView({
28375
28397
  columns,
28376
28398
  fields,
28377
28399
  itemActions,
28400
+ maxInlineActions,
28378
28401
  selectable = false,
28379
28402
  selectEvent,
28380
28403
  selectedIds,
@@ -28467,10 +28490,13 @@ function TableView({
28467
28490
  }
28468
28491
  const lk = LOOKS[look];
28469
28492
  const hasActions = Boolean(itemActions && itemActions.length > 0);
28493
+ const inlineActionCount = hasActions ? maxInlineActions != null ? Math.min(itemActions.length, maxInlineActions) : itemActions.length : 0;
28494
+ const hasOverflowActions = hasActions && maxInlineActions != null && itemActions.length > maxInlineActions;
28495
+ const actionsTrack = hasActions ? `${inlineActionCount * 6 + (hasOverflowActions ? 3 : 0)}rem` : null;
28470
28496
  const gridTemplateColumns = [
28471
28497
  selectable ? "auto" : null,
28472
28498
  ...colDefs.map((c) => c.width ?? "minmax(0, 1fr)"),
28473
- hasActions ? "auto" : null
28499
+ actionsTrack
28474
28500
  ].filter(Boolean).join(" ");
28475
28501
  const header = /* @__PURE__ */ jsxRuntime.jsxs(
28476
28502
  exports.Box,
@@ -28557,22 +28583,41 @@ function TableView({
28557
28583
  }
28558
28584
  return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
28559
28585
  }),
28560
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", className: "flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: itemActions.map((action, i) => /* @__PURE__ */ jsxRuntime.jsxs(
28561
- exports.Button,
28562
- {
28563
- variant: action.variant ?? "ghost",
28564
- size: "sm",
28565
- onClick: handleActionClick(action, row),
28566
- "data-testid": `action-${action.event}`,
28567
- "data-row-id": String(row.id),
28568
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
28569
- children: [
28570
- action.icon && /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: action.icon, size: "xs", className: "mr-1" }),
28571
- action.label
28572
- ]
28573
- },
28574
- i
28575
- )) })
28586
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "justify-end flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: [
28587
+ (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxRuntime.jsxs(
28588
+ exports.Button,
28589
+ {
28590
+ variant: action.variant ?? "ghost",
28591
+ size: "sm",
28592
+ onClick: handleActionClick(action, row),
28593
+ "data-testid": `action-${action.event}`,
28594
+ "data-row-id": String(row.id),
28595
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
28596
+ children: [
28597
+ action.icon && /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: action.icon, size: "xs", className: "mr-1" }),
28598
+ action.label
28599
+ ]
28600
+ },
28601
+ i
28602
+ )),
28603
+ maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
28604
+ exports.Menu,
28605
+ {
28606
+ position: "bottom-end",
28607
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": "More actions", "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
28608
+ items: itemActions.slice(maxInlineActions).map((action) => ({
28609
+ label: action.label,
28610
+ icon: action.icon,
28611
+ event: action.event,
28612
+ variant: action.variant === "danger" ? "danger" : "default",
28613
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
28614
+ id: row.id,
28615
+ row
28616
+ })
28617
+ }))
28618
+ }
28619
+ )
28620
+ ] })
28576
28621
  ]
28577
28622
  }
28578
28623
  );
@@ -28620,6 +28665,7 @@ var init_TableView = __esm({
28620
28665
  init_Icon();
28621
28666
  init_Checkbox();
28622
28667
  init_Divider();
28668
+ init_Menu();
28623
28669
  init_useDataDnd();
28624
28670
  logger.createLogger("almadar:ui:table-view");
28625
28671
  alignClass = {
@@ -28633,11 +28679,11 @@ var init_TableView = __esm({
28633
28679
  semibold: "font-semibold"
28634
28680
  };
28635
28681
  LOOKS = {
28636
- dense: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true },
28637
- spacious: { rowPad: "px-5 py-4", headPad: "px-5 py-3", striped: false, divider: true },
28638
- striped: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: true, divider: false },
28639
- borderless: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: false },
28640
- bordered: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true }
28682
+ dense: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true },
28683
+ spacious: { rowPad: "px-card-lg py-card-md", headPad: "px-card-lg py-card-sm", striped: false, divider: true },
28684
+ striped: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: true, divider: false },
28685
+ borderless: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: false },
28686
+ bordered: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true }
28641
28687
  };
28642
28688
  TableView.displayName = "TableView";
28643
28689
  }
@@ -22154,6 +22154,8 @@ function DataGrid({
22154
22154
  fields,
22155
22155
  columns,
22156
22156
  itemActions,
22157
+ maxInlineActions,
22158
+ scrollX = false,
22157
22159
  cols,
22158
22160
  gap = "md",
22159
22161
  minCardWidth = 280,
@@ -22293,8 +22295,8 @@ function DataGrid({
22293
22295
  /* @__PURE__ */ jsx(
22294
22296
  Box,
22295
22297
  {
22296
- className: cn("grid", gapStyles6[gap], colsClass, lookStyles5[look], className),
22297
- style: gridTemplateColumns ? { gridTemplateColumns } : void 0,
22298
+ className: cn("grid", gapStyles6[gap], scrollX ? "grid-flow-col overflow-x-auto" : colsClass, lookStyles5[look], className),
22299
+ style: scrollX ? { gridAutoFlow: "column", gridAutoColumns: `minmax(${minCardWidth}px, 1fr)` } : gridTemplateColumns ? { gridTemplateColumns } : void 0,
22298
22300
  children: data.map((item, index) => {
22299
22301
  const itemData = item;
22300
22302
  const id = itemData.id || String(index);
@@ -22421,21 +22423,39 @@ function DataGrid({
22421
22423
  )
22422
22424
  ] }, field.name);
22423
22425
  }) }) }),
22424
- primaryActions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsx(HStack, { gap: "sm", className: "justify-end", children: primaryActions.map((action, idx) => /* @__PURE__ */ jsxs(
22425
- Button,
22426
- {
22427
- variant: action.variant === "primary" ? "primary" : "ghost",
22428
- size: "sm",
22429
- onClick: handleActionClick(action, itemData),
22430
- "data-testid": `action-${action.event}`,
22431
- "data-row-id": String(itemData.id),
22432
- children: [
22433
- action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
22434
- action.label
22435
- ]
22436
- },
22437
- idx
22438
- )) }) })
22426
+ 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", children: [
22427
+ (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxs(
22428
+ Button,
22429
+ {
22430
+ variant: action.variant === "primary" ? "primary" : "ghost",
22431
+ size: "sm",
22432
+ onClick: handleActionClick(action, itemData),
22433
+ "data-testid": `action-${action.event}`,
22434
+ "data-row-id": String(itemData.id),
22435
+ children: [
22436
+ action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
22437
+ action.label
22438
+ ]
22439
+ },
22440
+ idx
22441
+ )),
22442
+ maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsx(
22443
+ Menu,
22444
+ {
22445
+ position: "bottom-end",
22446
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": "More actions", "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
22447
+ items: primaryActions.slice(maxInlineActions).map((action) => ({
22448
+ label: action.label,
22449
+ icon: action.icon,
22450
+ event: action.event,
22451
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
22452
+ id: itemData.id,
22453
+ row: itemData
22454
+ })
22455
+ }))
22456
+ }
22457
+ )
22458
+ ] }) })
22439
22459
  ]
22440
22460
  },
22441
22461
  id
@@ -22485,6 +22505,7 @@ var init_DataGrid = __esm({
22485
22505
  init_Button();
22486
22506
  init_Icon();
22487
22507
  init_InfiniteScrollSentinel();
22508
+ init_Menu();
22488
22509
  init_useDataDnd();
22489
22510
  dataGridLog = createLogger("almadar:ui:data-grid");
22490
22511
  BADGE_VARIANTS = /* @__PURE__ */ new Set([
@@ -22564,6 +22585,7 @@ function DataList({
22564
22585
  fields,
22565
22586
  columns,
22566
22587
  itemActions,
22588
+ maxInlineActions,
22567
22589
  itemClickEvent,
22568
22590
  gap = "none",
22569
22591
  variant = "default",
@@ -22654,6 +22676,46 @@ function DataList({
22654
22676
  };
22655
22677
  eventBus.emit(`UI:${action.event}`, payload);
22656
22678
  };
22679
+ const renderItemActions = (itemData) => {
22680
+ if (!itemActions || itemActions.length === 0) return null;
22681
+ const inline = maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions;
22682
+ const overflow = maxInlineActions != null ? itemActions.slice(maxInlineActions) : [];
22683
+ return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "flex-shrink-0", children: [
22684
+ inline.map((action, idx) => /* @__PURE__ */ jsxs(
22685
+ Button,
22686
+ {
22687
+ variant: action.variant ?? "ghost",
22688
+ size: "sm",
22689
+ onClick: handleActionClick(action, itemData),
22690
+ "data-testid": `action-${action.event}`,
22691
+ "data-row-id": String(itemData.id),
22692
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
22693
+ children: [
22694
+ action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
22695
+ action.label
22696
+ ]
22697
+ },
22698
+ idx
22699
+ )),
22700
+ overflow.length > 0 && /* @__PURE__ */ jsx(
22701
+ Menu,
22702
+ {
22703
+ position: "bottom-end",
22704
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": "More actions", "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
22705
+ items: overflow.map((action) => ({
22706
+ label: action.label,
22707
+ icon: action.icon,
22708
+ event: action.event,
22709
+ variant: action.variant === "danger" ? "danger" : "default",
22710
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
22711
+ id: itemData.id,
22712
+ row: itemData
22713
+ })
22714
+ }))
22715
+ }
22716
+ )
22717
+ ] });
22718
+ };
22657
22719
  const handleRowClick = (itemData) => () => {
22658
22720
  if (!itemClickEvent) return;
22659
22721
  const payload = {
@@ -22743,31 +22805,7 @@ function DataList({
22743
22805
  /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick: itemClickEvent ? handleRowClick(itemData) : void 0, className: cn(itemClickEvent && "cursor-pointer"), children: [
22744
22806
  /* @__PURE__ */ jsxs(Box, { className: "group flex items-stretch gap-2", children: [
22745
22807
  /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
22746
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(
22747
- HStack,
22748
- {
22749
- gap: "xs",
22750
- className: "flex-shrink-0",
22751
- children: itemActions.map((action, idx) => /* @__PURE__ */ jsxs(
22752
- Button,
22753
- {
22754
- variant: action.variant ?? "ghost",
22755
- size: "sm",
22756
- onClick: handleActionClick(action, itemData),
22757
- "data-testid": `action-${action.event}`,
22758
- "data-row-id": String(itemData.id),
22759
- className: cn(
22760
- action.variant === "danger" && "text-error hover:bg-error/10"
22761
- ),
22762
- children: [
22763
- action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
22764
- action.label
22765
- ]
22766
- },
22767
- idx
22768
- ))
22769
- }
22770
- )
22808
+ renderItemActions(itemData)
22771
22809
  ] }),
22772
22810
  isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-border/40" })
22773
22811
  ] }, id2)
@@ -22838,24 +22876,7 @@ function DataList({
22838
22876
  ] }, field.name);
22839
22877
  })
22840
22878
  ] }),
22841
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: itemActions.map((action, idx) => /* @__PURE__ */ jsxs(
22842
- Button,
22843
- {
22844
- variant: action.variant ?? "ghost",
22845
- size: "sm",
22846
- onClick: handleActionClick(action, itemData),
22847
- "data-testid": `action-${action.event}`,
22848
- "data-row-id": String(itemData.id),
22849
- className: cn(
22850
- action.variant === "danger" && "text-error hover:bg-error/10"
22851
- ),
22852
- children: [
22853
- action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
22854
- action.label
22855
- ]
22856
- },
22857
- idx
22858
- )) })
22879
+ renderItemActions(itemData)
22859
22880
  ]
22860
22881
  }
22861
22882
  ),
@@ -22925,6 +22946,7 @@ var init_DataList = __esm({
22925
22946
  init_ProgressBar();
22926
22947
  init_Divider();
22927
22948
  init_InfiniteScrollSentinel();
22949
+ init_Menu();
22928
22950
  init_useDataDnd();
22929
22951
  dataListLog = createLogger("almadar:ui:data-list");
22930
22952
  listLookStyles = {
@@ -28326,6 +28348,7 @@ function TableView({
28326
28348
  columns,
28327
28349
  fields,
28328
28350
  itemActions,
28351
+ maxInlineActions,
28329
28352
  selectable = false,
28330
28353
  selectEvent,
28331
28354
  selectedIds,
@@ -28418,10 +28441,13 @@ function TableView({
28418
28441
  }
28419
28442
  const lk = LOOKS[look];
28420
28443
  const hasActions = Boolean(itemActions && itemActions.length > 0);
28444
+ const inlineActionCount = hasActions ? maxInlineActions != null ? Math.min(itemActions.length, maxInlineActions) : itemActions.length : 0;
28445
+ const hasOverflowActions = hasActions && maxInlineActions != null && itemActions.length > maxInlineActions;
28446
+ const actionsTrack = hasActions ? `${inlineActionCount * 6 + (hasOverflowActions ? 3 : 0)}rem` : null;
28421
28447
  const gridTemplateColumns = [
28422
28448
  selectable ? "auto" : null,
28423
28449
  ...colDefs.map((c) => c.width ?? "minmax(0, 1fr)"),
28424
- hasActions ? "auto" : null
28450
+ actionsTrack
28425
28451
  ].filter(Boolean).join(" ");
28426
28452
  const header = /* @__PURE__ */ jsxs(
28427
28453
  Box,
@@ -28508,22 +28534,41 @@ function TableView({
28508
28534
  }
28509
28535
  return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
28510
28536
  }),
28511
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: itemActions.map((action, i) => /* @__PURE__ */ jsxs(
28512
- Button,
28513
- {
28514
- variant: action.variant ?? "ghost",
28515
- size: "sm",
28516
- onClick: handleActionClick(action, row),
28517
- "data-testid": `action-${action.event}`,
28518
- "data-row-id": String(row.id),
28519
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
28520
- children: [
28521
- action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
28522
- action.label
28523
- ]
28524
- },
28525
- i
28526
- )) })
28537
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "justify-end flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: [
28538
+ (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
28539
+ Button,
28540
+ {
28541
+ variant: action.variant ?? "ghost",
28542
+ size: "sm",
28543
+ onClick: handleActionClick(action, row),
28544
+ "data-testid": `action-${action.event}`,
28545
+ "data-row-id": String(row.id),
28546
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
28547
+ children: [
28548
+ action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
28549
+ action.label
28550
+ ]
28551
+ },
28552
+ i
28553
+ )),
28554
+ maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsx(
28555
+ Menu,
28556
+ {
28557
+ position: "bottom-end",
28558
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": "More actions", "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
28559
+ items: itemActions.slice(maxInlineActions).map((action) => ({
28560
+ label: action.label,
28561
+ icon: action.icon,
28562
+ event: action.event,
28563
+ variant: action.variant === "danger" ? "danger" : "default",
28564
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
28565
+ id: row.id,
28566
+ row
28567
+ })
28568
+ }))
28569
+ }
28570
+ )
28571
+ ] })
28527
28572
  ]
28528
28573
  }
28529
28574
  );
@@ -28571,6 +28616,7 @@ var init_TableView = __esm({
28571
28616
  init_Icon();
28572
28617
  init_Checkbox();
28573
28618
  init_Divider();
28619
+ init_Menu();
28574
28620
  init_useDataDnd();
28575
28621
  createLogger("almadar:ui:table-view");
28576
28622
  alignClass = {
@@ -28584,11 +28630,11 @@ var init_TableView = __esm({
28584
28630
  semibold: "font-semibold"
28585
28631
  };
28586
28632
  LOOKS = {
28587
- dense: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true },
28588
- spacious: { rowPad: "px-5 py-4", headPad: "px-5 py-3", striped: false, divider: true },
28589
- striped: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: true, divider: false },
28590
- borderless: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: false },
28591
- bordered: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true }
28633
+ dense: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true },
28634
+ spacious: { rowPad: "px-card-lg py-card-md", headPad: "px-card-lg py-card-sm", striped: false, divider: true },
28635
+ striped: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: true, divider: false },
28636
+ borderless: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: false },
28637
+ bordered: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true }
28592
28638
  };
28593
28639
  TableView.displayName = "TableView";
28594
28640
  }
@@ -66,6 +66,10 @@ export interface DataGridProps<T extends EntityRow = EntityRow> extends DataDndP
66
66
  columns?: readonly DataGridField[];
67
67
  /** Per-item action buttons */
68
68
  itemActions?: readonly DataGridItemAction[];
69
+ /** Max inline primary action buttons before the rest collapse into a "⋯" overflow menu. Omit = all inline. */
70
+ maxInlineActions?: number;
71
+ /** Lay items in a single horizontally-scrolling row (kanban columns) sized to `minCardWidth` instead of a wrapping grid. */
72
+ scrollX?: boolean;
69
73
  /** Number of columns (uses auto-fit if omitted) */
70
74
  cols?: 1 | 2 | 3 | 4 | 5 | 6;
71
75
  /** Gap between cards */
@@ -108,7 +112,7 @@ export interface DataGridProps<T extends EntityRow = EntityRow> extends DataDndP
108
112
  */
109
113
  look?: "dense" | "spacious" | "striped" | "borderless" | "card-rows";
110
114
  }
111
- export declare function DataGrid<T extends EntityRow = EntityRow>({ entity, fields, columns, itemActions, cols, gap, minCardWidth, className, isLoading, error, imageField, selectable, selectionEvent, infiniteScroll, loadMoreEvent, hasMore, children, pageSize, renderItem: schemaRenderItem, dragGroup, accepts, sortable, dropEvent, reorderEvent, positionEvent, dndItemIdField, dndRoot, look, }: DataGridProps<T>): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined;
115
+ export declare function DataGrid<T extends EntityRow = EntityRow>({ entity, fields, columns, itemActions, maxInlineActions, scrollX, cols, gap, minCardWidth, className, isLoading, error, imageField, selectable, selectionEvent, infiniteScroll, loadMoreEvent, hasMore, children, pageSize, renderItem: schemaRenderItem, dragGroup, accepts, sortable, dropEvent, reorderEvent, positionEvent, dndItemIdField, dndRoot, look, }: DataGridProps<T>): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined;
112
116
  export declare namespace DataGrid {
113
117
  var displayName: string;
114
118
  }