@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.
@@ -23168,6 +23168,8 @@ function DataGrid({
23168
23168
  fields,
23169
23169
  columns,
23170
23170
  itemActions,
23171
+ maxInlineActions,
23172
+ scrollX = false,
23171
23173
  cols,
23172
23174
  gap = "md",
23173
23175
  minCardWidth = 280,
@@ -23307,8 +23309,8 @@ function DataGrid({
23307
23309
  /* @__PURE__ */ jsx(
23308
23310
  Box,
23309
23311
  {
23310
- className: cn("grid", gapStyles6[gap], colsClass, lookStyles5[look], className),
23311
- style: gridTemplateColumns ? { gridTemplateColumns } : void 0,
23312
+ className: cn("grid", gapStyles6[gap], scrollX ? "grid-flow-col overflow-x-auto" : colsClass, lookStyles5[look], className),
23313
+ style: scrollX ? { gridAutoFlow: "column", gridAutoColumns: `minmax(${minCardWidth}px, 1fr)` } : gridTemplateColumns ? { gridTemplateColumns } : void 0,
23312
23314
  children: data.map((item, index) => {
23313
23315
  const itemData = item;
23314
23316
  const id = itemData.id || String(index);
@@ -23435,21 +23437,39 @@ function DataGrid({
23435
23437
  )
23436
23438
  ] }, field.name);
23437
23439
  }) }) }),
23438
- 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(
23439
- Button,
23440
- {
23441
- variant: action.variant === "primary" ? "primary" : "ghost",
23442
- size: "sm",
23443
- onClick: handleActionClick(action, itemData),
23444
- "data-testid": `action-${action.event}`,
23445
- "data-row-id": String(itemData.id),
23446
- children: [
23447
- action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
23448
- action.label
23449
- ]
23450
- },
23451
- idx
23452
- )) }) })
23440
+ 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: [
23441
+ (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxs(
23442
+ Button,
23443
+ {
23444
+ variant: action.variant === "primary" ? "primary" : "ghost",
23445
+ size: "sm",
23446
+ onClick: handleActionClick(action, itemData),
23447
+ "data-testid": `action-${action.event}`,
23448
+ "data-row-id": String(itemData.id),
23449
+ children: [
23450
+ action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
23451
+ action.label
23452
+ ]
23453
+ },
23454
+ idx
23455
+ )),
23456
+ maxInlineActions != null && primaryActions.length > maxInlineActions && /* @__PURE__ */ jsx(
23457
+ Menu,
23458
+ {
23459
+ position: "bottom-end",
23460
+ 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" }) }),
23461
+ items: primaryActions.slice(maxInlineActions).map((action) => ({
23462
+ label: action.label,
23463
+ icon: action.icon,
23464
+ event: action.event,
23465
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
23466
+ id: itemData.id,
23467
+ row: itemData
23468
+ })
23469
+ }))
23470
+ }
23471
+ )
23472
+ ] }) })
23453
23473
  ]
23454
23474
  },
23455
23475
  id
@@ -23499,6 +23519,7 @@ var init_DataGrid = __esm({
23499
23519
  init_Button();
23500
23520
  init_Icon();
23501
23521
  init_InfiniteScrollSentinel();
23522
+ init_Menu();
23502
23523
  init_useDataDnd();
23503
23524
  dataGridLog = createLogger("almadar:ui:data-grid");
23504
23525
  BADGE_VARIANTS = /* @__PURE__ */ new Set([
@@ -23578,6 +23599,7 @@ function DataList({
23578
23599
  fields,
23579
23600
  columns,
23580
23601
  itemActions,
23602
+ maxInlineActions,
23581
23603
  itemClickEvent,
23582
23604
  gap = "none",
23583
23605
  variant = "default",
@@ -23668,6 +23690,46 @@ function DataList({
23668
23690
  };
23669
23691
  eventBus.emit(`UI:${action.event}`, payload);
23670
23692
  };
23693
+ const renderItemActions = (itemData) => {
23694
+ if (!itemActions || itemActions.length === 0) return null;
23695
+ const inline = maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions;
23696
+ const overflow = maxInlineActions != null ? itemActions.slice(maxInlineActions) : [];
23697
+ return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "flex-shrink-0", children: [
23698
+ inline.map((action, idx) => /* @__PURE__ */ jsxs(
23699
+ Button,
23700
+ {
23701
+ variant: action.variant ?? "ghost",
23702
+ size: "sm",
23703
+ onClick: handleActionClick(action, itemData),
23704
+ "data-testid": `action-${action.event}`,
23705
+ "data-row-id": String(itemData.id),
23706
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
23707
+ children: [
23708
+ action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
23709
+ action.label
23710
+ ]
23711
+ },
23712
+ idx
23713
+ )),
23714
+ overflow.length > 0 && /* @__PURE__ */ jsx(
23715
+ Menu,
23716
+ {
23717
+ position: "bottom-end",
23718
+ 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" }) }),
23719
+ items: overflow.map((action) => ({
23720
+ label: action.label,
23721
+ icon: action.icon,
23722
+ event: action.event,
23723
+ variant: action.variant === "danger" ? "danger" : "default",
23724
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
23725
+ id: itemData.id,
23726
+ row: itemData
23727
+ })
23728
+ }))
23729
+ }
23730
+ )
23731
+ ] });
23732
+ };
23671
23733
  const handleRowClick = (itemData) => () => {
23672
23734
  if (!itemClickEvent) return;
23673
23735
  const payload = {
@@ -23757,31 +23819,7 @@ function DataList({
23757
23819
  /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick: itemClickEvent ? handleRowClick(itemData) : void 0, className: cn(itemClickEvent && "cursor-pointer"), children: [
23758
23820
  /* @__PURE__ */ jsxs(Box, { className: "group flex items-stretch gap-2", children: [
23759
23821
  /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(itemData, index) }),
23760
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(
23761
- HStack,
23762
- {
23763
- gap: "xs",
23764
- className: "flex-shrink-0",
23765
- children: itemActions.map((action, idx) => /* @__PURE__ */ jsxs(
23766
- Button,
23767
- {
23768
- variant: action.variant ?? "ghost",
23769
- size: "sm",
23770
- onClick: handleActionClick(action, itemData),
23771
- "data-testid": `action-${action.event}`,
23772
- "data-row-id": String(itemData.id),
23773
- className: cn(
23774
- action.variant === "danger" && "text-error hover:bg-error/10"
23775
- ),
23776
- children: [
23777
- action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
23778
- action.label
23779
- ]
23780
- },
23781
- idx
23782
- ))
23783
- }
23784
- )
23822
+ renderItemActions(itemData)
23785
23823
  ] }),
23786
23824
  isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-border/40" })
23787
23825
  ] }, id2)
@@ -23852,24 +23890,7 @@ function DataList({
23852
23890
  ] }, field.name);
23853
23891
  })
23854
23892
  ] }),
23855
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0", children: itemActions.map((action, idx) => /* @__PURE__ */ jsxs(
23856
- Button,
23857
- {
23858
- variant: action.variant ?? "ghost",
23859
- size: "sm",
23860
- onClick: handleActionClick(action, itemData),
23861
- "data-testid": `action-${action.event}`,
23862
- "data-row-id": String(itemData.id),
23863
- className: cn(
23864
- action.variant === "danger" && "text-error hover:bg-error/10"
23865
- ),
23866
- children: [
23867
- action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
23868
- action.label
23869
- ]
23870
- },
23871
- idx
23872
- )) })
23893
+ renderItemActions(itemData)
23873
23894
  ]
23874
23895
  }
23875
23896
  ),
@@ -23939,6 +23960,7 @@ var init_DataList = __esm({
23939
23960
  init_ProgressBar();
23940
23961
  init_Divider();
23941
23962
  init_InfiniteScrollSentinel();
23963
+ init_Menu();
23942
23964
  init_useDataDnd();
23943
23965
  dataListLog = createLogger("almadar:ui:data-list");
23944
23966
  listLookStyles = {
@@ -28984,6 +29006,7 @@ function TableView({
28984
29006
  columns,
28985
29007
  fields,
28986
29008
  itemActions,
29009
+ maxInlineActions,
28987
29010
  selectable = false,
28988
29011
  selectEvent,
28989
29012
  selectedIds,
@@ -29076,10 +29099,13 @@ function TableView({
29076
29099
  }
29077
29100
  const lk = LOOKS[look];
29078
29101
  const hasActions = Boolean(itemActions && itemActions.length > 0);
29102
+ const inlineActionCount = hasActions ? maxInlineActions != null ? Math.min(itemActions.length, maxInlineActions) : itemActions.length : 0;
29103
+ const hasOverflowActions = hasActions && maxInlineActions != null && itemActions.length > maxInlineActions;
29104
+ const actionsTrack = hasActions ? `${inlineActionCount * 6 + (hasOverflowActions ? 3 : 0)}rem` : null;
29079
29105
  const gridTemplateColumns = [
29080
29106
  selectable ? "auto" : null,
29081
29107
  ...colDefs.map((c) => c.width ?? "minmax(0, 1fr)"),
29082
- hasActions ? "auto" : null
29108
+ actionsTrack
29083
29109
  ].filter(Boolean).join(" ");
29084
29110
  const header = /* @__PURE__ */ jsxs(
29085
29111
  Box,
@@ -29166,22 +29192,41 @@ function TableView({
29166
29192
  }
29167
29193
  return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
29168
29194
  }),
29169
- 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(
29170
- Button,
29171
- {
29172
- variant: action.variant ?? "ghost",
29173
- size: "sm",
29174
- onClick: handleActionClick(action, row),
29175
- "data-testid": `action-${action.event}`,
29176
- "data-row-id": String(row.id),
29177
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
29178
- children: [
29179
- action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
29180
- action.label
29181
- ]
29182
- },
29183
- i
29184
- )) })
29195
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "justify-end flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: [
29196
+ (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
29197
+ Button,
29198
+ {
29199
+ variant: action.variant ?? "ghost",
29200
+ size: "sm",
29201
+ onClick: handleActionClick(action, row),
29202
+ "data-testid": `action-${action.event}`,
29203
+ "data-row-id": String(row.id),
29204
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
29205
+ children: [
29206
+ action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
29207
+ action.label
29208
+ ]
29209
+ },
29210
+ i
29211
+ )),
29212
+ maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsx(
29213
+ Menu,
29214
+ {
29215
+ position: "bottom-end",
29216
+ 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" }) }),
29217
+ items: itemActions.slice(maxInlineActions).map((action) => ({
29218
+ label: action.label,
29219
+ icon: action.icon,
29220
+ event: action.event,
29221
+ variant: action.variant === "danger" ? "danger" : "default",
29222
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
29223
+ id: row.id,
29224
+ row
29225
+ })
29226
+ }))
29227
+ }
29228
+ )
29229
+ ] })
29185
29230
  ]
29186
29231
  }
29187
29232
  );
@@ -29229,6 +29274,7 @@ var init_TableView = __esm({
29229
29274
  init_Icon();
29230
29275
  init_Checkbox();
29231
29276
  init_Divider();
29277
+ init_Menu();
29232
29278
  init_useDataDnd();
29233
29279
  createLogger("almadar:ui:table-view");
29234
29280
  alignClass = {
@@ -29242,11 +29288,11 @@ var init_TableView = __esm({
29242
29288
  semibold: "font-semibold"
29243
29289
  };
29244
29290
  LOOKS = {
29245
- dense: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true },
29246
- spacious: { rowPad: "px-5 py-4", headPad: "px-5 py-3", striped: false, divider: true },
29247
- striped: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: true, divider: false },
29248
- borderless: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: false },
29249
- bordered: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true }
29291
+ dense: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true },
29292
+ spacious: { rowPad: "px-card-lg py-card-md", headPad: "px-card-lg py-card-sm", striped: false, divider: true },
29293
+ striped: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: true, divider: false },
29294
+ borderless: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: false },
29295
+ bordered: { rowPad: "px-card-md py-card-sm", headPad: "px-card-md py-card-sm", striped: false, divider: true }
29250
29296
  };
29251
29297
  TableView.displayName = "TableView";
29252
29298
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.9.10",
3
+ "version": "5.12.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [