@almadar/ui 5.9.9 → 5.11.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,
@@ -28557,22 +28580,41 @@ function TableView({
28557
28580
  }
28558
28581
  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
28582
  }),
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
- )) })
28583
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: [
28584
+ (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxRuntime.jsxs(
28585
+ exports.Button,
28586
+ {
28587
+ variant: action.variant ?? "ghost",
28588
+ size: "sm",
28589
+ onClick: handleActionClick(action, row),
28590
+ "data-testid": `action-${action.event}`,
28591
+ "data-row-id": String(row.id),
28592
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
28593
+ children: [
28594
+ action.icon && /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: action.icon, size: "xs", className: "mr-1" }),
28595
+ action.label
28596
+ ]
28597
+ },
28598
+ i
28599
+ )),
28600
+ maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
28601
+ exports.Menu,
28602
+ {
28603
+ position: "bottom-end",
28604
+ 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" }) }),
28605
+ items: itemActions.slice(maxInlineActions).map((action) => ({
28606
+ label: action.label,
28607
+ icon: action.icon,
28608
+ event: action.event,
28609
+ variant: action.variant === "danger" ? "danger" : "default",
28610
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
28611
+ id: row.id,
28612
+ row
28613
+ })
28614
+ }))
28615
+ }
28616
+ )
28617
+ ] })
28576
28618
  ]
28577
28619
  }
28578
28620
  );
@@ -28620,6 +28662,7 @@ var init_TableView = __esm({
28620
28662
  init_Icon();
28621
28663
  init_Checkbox();
28622
28664
  init_Divider();
28665
+ init_Menu();
28623
28666
  init_useDataDnd();
28624
28667
  logger.createLogger("almadar:ui:table-view");
28625
28668
  alignClass = {
@@ -28633,11 +28676,11 @@ var init_TableView = __esm({
28633
28676
  semibold: "font-semibold"
28634
28677
  };
28635
28678
  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 }
28679
+ dense: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true },
28680
+ spacious: { rowPad: "px-card-lg py-card-md", headPad: "px-card-lg py-card-sm", striped: false, divider: true },
28681
+ striped: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: true, divider: false },
28682
+ borderless: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: false },
28683
+ bordered: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true }
28641
28684
  };
28642
28685
  TableView.displayName = "TableView";
28643
28686
  }
@@ -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,
@@ -28508,22 +28531,41 @@ function TableView({
28508
28531
  }
28509
28532
  return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
28510
28533
  }),
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
- )) })
28534
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: [
28535
+ (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
28536
+ Button,
28537
+ {
28538
+ variant: action.variant ?? "ghost",
28539
+ size: "sm",
28540
+ onClick: handleActionClick(action, row),
28541
+ "data-testid": `action-${action.event}`,
28542
+ "data-row-id": String(row.id),
28543
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
28544
+ children: [
28545
+ action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
28546
+ action.label
28547
+ ]
28548
+ },
28549
+ i
28550
+ )),
28551
+ maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsx(
28552
+ Menu,
28553
+ {
28554
+ position: "bottom-end",
28555
+ 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" }) }),
28556
+ items: itemActions.slice(maxInlineActions).map((action) => ({
28557
+ label: action.label,
28558
+ icon: action.icon,
28559
+ event: action.event,
28560
+ variant: action.variant === "danger" ? "danger" : "default",
28561
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
28562
+ id: row.id,
28563
+ row
28564
+ })
28565
+ }))
28566
+ }
28567
+ )
28568
+ ] })
28527
28569
  ]
28528
28570
  }
28529
28571
  );
@@ -28571,6 +28613,7 @@ var init_TableView = __esm({
28571
28613
  init_Icon();
28572
28614
  init_Checkbox();
28573
28615
  init_Divider();
28616
+ init_Menu();
28574
28617
  init_useDataDnd();
28575
28618
  createLogger("almadar:ui:table-view");
28576
28619
  alignClass = {
@@ -28584,11 +28627,11 @@ var init_TableView = __esm({
28584
28627
  semibold: "font-semibold"
28585
28628
  };
28586
28629
  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 }
28630
+ dense: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true },
28631
+ spacious: { rowPad: "px-card-lg py-card-md", headPad: "px-card-lg py-card-sm", striped: false, divider: true },
28632
+ striped: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: true, divider: false },
28633
+ borderless: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: false },
28634
+ bordered: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true }
28592
28635
  };
28593
28636
  TableView.displayName = "TableView";
28594
28637
  }
@@ -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
  }
@@ -56,6 +56,8 @@ export interface DataListProps<T extends EntityRow = EntityRow> extends DataDndP
56
56
  columns?: readonly DataListField[];
57
57
  /** Per-item action buttons */
58
58
  itemActions?: readonly DataListItemAction[];
59
+ /** Max inline action buttons before the rest collapse into a "⋯" overflow menu. Omit = all inline. */
60
+ maxInlineActions?: number;
59
61
  /** When set, the whole row is clickable and emits UI:{itemClickEvent} with
60
62
  * { id, row } (action-button clicks stopPropagation so they still win). */
61
63
  itemClickEvent?: EventKey;
@@ -125,7 +127,7 @@ export interface DataListProps<T extends EntityRow = EntityRow> extends DataDndP
125
127
  */
126
128
  look?: "dense" | "spacious" | "striped" | "borderless" | "card-rows";
127
129
  }
128
- export declare function DataList<T extends EntityRow = EntityRow>({ entity, fields, columns, itemActions, itemClickEvent, gap, variant, groupBy, senderField, currentUser, className, isLoading, error, reorderable: _reorderable, reorderEvent: _reorderEvent, swipeLeftEvent: _swipeLeftEvent, swipeLeftActions: _swipeLeftActions, swipeRightEvent: _swipeRightEvent, swipeRightActions: _swipeRightActions, longPressEvent: _longPressEvent, infiniteScroll, loadMoreEvent, hasMore, children, pageSize, renderItem: schemaRenderItem, dragGroup, accepts, sortable: sortableProp, dropEvent, reorderEvent: dndReorderEvent, positionEvent, dndItemIdField, dndRoot, look, }: DataListProps<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;
130
+ export declare function DataList<T extends EntityRow = EntityRow>({ entity, fields, columns, itemActions, maxInlineActions, itemClickEvent, gap, variant, groupBy, senderField, currentUser, className, isLoading, error, reorderable: _reorderable, reorderEvent: _reorderEvent, swipeLeftEvent: _swipeLeftEvent, swipeLeftActions: _swipeLeftActions, swipeRightEvent: _swipeRightEvent, swipeRightActions: _swipeRightActions, longPressEvent: _longPressEvent, infiniteScroll, loadMoreEvent, hasMore, children, pageSize, renderItem: schemaRenderItem, dragGroup, accepts, sortable: sortableProp, dropEvent, reorderEvent: dndReorderEvent, positionEvent, dndItemIdField, dndRoot, look, }: DataListProps<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;
129
131
  export declare namespace DataList {
130
132
  var displayName: string;
131
133
  }