@almadar/ui 3.4.0 → 3.5.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.
Files changed (50) hide show
  1. package/dist/avl/index.cjs +67 -30
  2. package/dist/avl/index.js +67 -30
  3. package/dist/components/atoms/Avatar.d.ts +2 -2
  4. package/dist/components/atoms/Box.d.ts +3 -3
  5. package/dist/components/atoms/Button.d.ts +2 -2
  6. package/dist/components/atoms/InfiniteScrollSentinel.d.ts +3 -2
  7. package/dist/components/atoms/RangeSlider.d.ts +2 -2
  8. package/dist/components/atoms/Stack.d.ts +2 -2
  9. package/dist/components/atoms/TextHighlight.d.ts +1 -1
  10. package/dist/components/atoms/game/ControlButton.d.ts +3 -2
  11. package/dist/components/index.cjs +67 -27
  12. package/dist/components/index.js +67 -27
  13. package/dist/components/molecules/Alert.d.ts +2 -1
  14. package/dist/components/molecules/CalendarGrid.d.ts +2 -1
  15. package/dist/components/molecules/Card.d.ts +2 -2
  16. package/dist/components/molecules/DataGrid.d.ts +2 -2
  17. package/dist/components/molecules/DataList.d.ts +5 -5
  18. package/dist/components/molecules/Drawer.d.ts +2 -1
  19. package/dist/components/molecules/NumberStepper.d.ts +2 -2
  20. package/dist/components/molecules/PullToRefresh.d.ts +3 -2
  21. package/dist/components/molecules/SortableList.d.ts +5 -4
  22. package/dist/components/molecules/StarRating.d.ts +2 -2
  23. package/dist/components/molecules/SwipeableRow.d.ts +3 -3
  24. package/dist/components/molecules/UploadDropZone.d.ts +2 -2
  25. package/dist/components/molecules/game/DialogueBox.d.ts +3 -2
  26. package/dist/components/molecules/game/GameMenu.d.ts +3 -3
  27. package/dist/components/molecules/game/GameOverScreen.d.ts +3 -2
  28. package/dist/components/molecules/game/InventoryPanel.d.ts +3 -2
  29. package/dist/components/organisms/CustomPattern.d.ts +3 -3
  30. package/dist/components/organisms/GraphCanvas.d.ts +3 -2
  31. package/dist/components/organisms/game/three/index.cjs +0 -3
  32. package/dist/components/organisms/game/three/index.js +0 -3
  33. package/dist/docs/index.cjs +0 -3
  34. package/dist/docs/index.d.cts +5 -5
  35. package/dist/docs/index.js +0 -3
  36. package/dist/hooks/event-bus-types.d.ts +10 -10
  37. package/dist/hooks/index.cjs +0 -3
  38. package/dist/hooks/index.js +0 -3
  39. package/dist/hooks/useDraggable.d.ts +2 -1
  40. package/dist/hooks/useEventBus.d.ts +2 -1
  41. package/dist/lib/verificationRegistry.d.ts +2 -2
  42. package/dist/marketing/index.cjs +0 -3
  43. package/dist/marketing/index.d.cts +5 -5
  44. package/dist/marketing/index.js +0 -3
  45. package/dist/providers/index.cjs +67 -30
  46. package/dist/providers/index.js +67 -30
  47. package/dist/runtime/createClientEffectHandlers.d.ts +2 -1
  48. package/dist/runtime/index.cjs +67 -27
  49. package/dist/runtime/index.js +67 -27
  50. package/package.json +3 -3
@@ -429,9 +429,6 @@ var init_useEventBus = __esm({
429
429
  emit: (type, payload, source) => {
430
430
  const event = {
431
431
  type,
432
- // Narrow at the bus boundary: public emit accepts an opaque object so
433
- // generic UI emit sites don't require casts; the envelope stores the
434
- // payload as EventPayload which listeners consume directly.
435
432
  payload,
436
433
  timestamp: Date.now(),
437
434
  source
@@ -15949,7 +15946,11 @@ var init_CardGrid = __esm({
15949
15946
  return;
15950
15947
  }
15951
15948
  if (action.event) {
15952
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
15949
+ const payload = {
15950
+ id: itemData.id,
15951
+ row: itemData
15952
+ };
15953
+ eventBus.emit(`UI:${action.event}`, payload);
15953
15954
  }
15954
15955
  if (action.onClick) {
15955
15956
  action.onClick(itemData);
@@ -18633,7 +18634,8 @@ var init_DataGrid = __esm({
18633
18634
  if (next.has(id)) next.delete(id);
18634
18635
  else next.add(id);
18635
18636
  if (selectionEvent) {
18636
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
18637
+ const payload = { selectedIds: Array.from(next) };
18638
+ eventBus.emit(`UI:${selectionEvent}`, payload);
18637
18639
  }
18638
18640
  return next;
18639
18641
  });
@@ -18644,7 +18646,8 @@ var init_DataGrid = __esm({
18644
18646
  const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
18645
18647
  const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
18646
18648
  if (selectionEvent) {
18647
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
18649
+ const payload = { selectedIds: Array.from(next) };
18650
+ eventBus.emit(`UI:${selectionEvent}`, payload);
18648
18651
  }
18649
18652
  return next;
18650
18653
  });
@@ -18656,7 +18659,11 @@ var init_DataGrid = __esm({
18656
18659
  const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
18657
18660
  const handleActionClick = (action, itemData) => (e) => {
18658
18661
  e.stopPropagation();
18659
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
18662
+ const payload = {
18663
+ id: itemData.id,
18664
+ row: itemData
18665
+ };
18666
+ eventBus.emit(`UI:${action.event}`, payload);
18660
18667
  };
18661
18668
  const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
18662
18669
  const colsClass = cols ? {
@@ -18984,7 +18991,11 @@ var init_DataList = __esm({
18984
18991
  );
18985
18992
  const handleActionClick = (action, itemData) => (e) => {
18986
18993
  e.stopPropagation();
18987
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
18994
+ const payload = {
18995
+ id: itemData.id,
18996
+ row: itemData
18997
+ };
18998
+ eventBus.emit(`UI:${action.event}`, payload);
18988
18999
  };
18989
19000
  if (isLoading) {
18990
19001
  return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
@@ -27368,7 +27379,8 @@ var init_DetailPanel = __esm({
27368
27379
  return;
27369
27380
  }
27370
27381
  if (action.event) {
27371
- eventBus.emit(`UI:${action.event}`, { id: data2?.id, row: data2 });
27382
+ const payload = data2 ? { id: data2.id, row: data2 } : {};
27383
+ eventBus.emit(`UI:${action.event}`, payload);
27372
27384
  }
27373
27385
  if (action.onClick) {
27374
27386
  action.onClick();
@@ -28810,9 +28822,10 @@ var init_Form = __esm({
28810
28822
  };
28811
28823
  const handleSubmit = (e) => {
28812
28824
  e.preventDefault();
28813
- eventBus.emit(`UI:${submitEvent}`, { data: formData });
28825
+ const payload = { data: formData };
28826
+ eventBus.emit(`UI:${submitEvent}`, payload);
28814
28827
  if (onSubmit) {
28815
- eventBus.emit(`UI:${onSubmit}`, { data: formData });
28828
+ eventBus.emit(`UI:${onSubmit}`, payload);
28816
28829
  }
28817
28830
  };
28818
28831
  const handleCancel = () => {
@@ -30180,6 +30193,31 @@ function normalizeFields2(fields) {
30180
30193
  if (!fields) return [];
30181
30194
  return fields.map((f3) => typeof f3 === "string" ? f3 : f3.key ?? f3.name ?? "");
30182
30195
  }
30196
+ function entityFieldsFromListItem(item) {
30197
+ const {
30198
+ icon: _icon,
30199
+ metadata: _metadata,
30200
+ onClick: _onClick,
30201
+ avatar: _avatar,
30202
+ _fields,
30203
+ ...rest
30204
+ } = item;
30205
+ const result = {};
30206
+ for (const [key, value] of Object.entries(rest)) {
30207
+ if (typeof value === "function" || value !== null && typeof value === "object" && "$$typeof" in value) {
30208
+ continue;
30209
+ }
30210
+ result[key] = value;
30211
+ }
30212
+ if (_fields && typeof _fields === "object") {
30213
+ for (const [k, v] of Object.entries(_fields)) {
30214
+ if (typeof v !== "function") {
30215
+ result[k] = v;
30216
+ }
30217
+ }
30218
+ }
30219
+ return result;
30220
+ }
30183
30221
  function getStatusStyle(fieldName, value) {
30184
30222
  const val = String(value).toLowerCase();
30185
30223
  if (val.includes("complete") || val.includes("done"))
@@ -30383,18 +30421,17 @@ var init_List = __esm({
30383
30421
  label: action.label,
30384
30422
  event: action.event,
30385
30423
  onClick: () => {
30424
+ const row = entityFieldsFromListItem(item);
30386
30425
  if (action.navigatesTo) {
30387
30426
  const url = action.navigatesTo.replace(
30388
30427
  /\{\{(\w+)\}\}/g,
30389
- (_, key) => String(item[key] || item.id || "")
30428
+ (_, key) => String(row[key] ?? item.id ?? "")
30390
30429
  );
30391
- eventBus.emit("UI:NAVIGATE", { url, row: item });
30430
+ eventBus.emit("UI:NAVIGATE", { url, row });
30392
30431
  return;
30393
30432
  }
30394
30433
  if (action.event) {
30395
- eventBus.emit(`UI:${action.event}`, {
30396
- row: item
30397
- });
30434
+ eventBus.emit(`UI:${action.event}`, { row });
30398
30435
  }
30399
30436
  }
30400
30437
  }));
@@ -30474,7 +30511,7 @@ var init_List = __esm({
30474
30511
  );
30475
30512
  const hasExplicitClick = !!(viewAction?.event || item.onClick);
30476
30513
  const rowAction = viewAction?.event ?? "VIEW";
30477
- const rowActionPayload = { row: item };
30514
+ const rowActionPayload = { row: entityFieldsFromListItem(item) };
30478
30515
  const primaryField = effectiveFieldNames?.[0];
30479
30516
  const statusField = effectiveFieldNames?.find(
30480
30517
  (f3) => f3.toLowerCase().includes("status")
@@ -36309,16 +36346,19 @@ var init_Timeline = __esm({
36309
36346
  ] }),
36310
36347
  item.description && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: item.description }),
36311
36348
  item.tags && item.tags.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: item.tags.map((tag, tagIdx) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: tag }, tagIdx)) }),
36312
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => /* @__PURE__ */ jsx(
36313
- Box,
36314
- {
36315
- action: action.event,
36316
- actionPayload: { row: item },
36317
- className: "cursor-pointer hover:opacity-80 transition-opacity",
36318
- children: /* @__PURE__ */ jsx(Badge, { variant: "default", children: action.label })
36319
- },
36320
- actionIdx
36321
- )) })
36349
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => {
36350
+ const { icon: _icon, ...rowSafe } = item;
36351
+ return /* @__PURE__ */ jsx(
36352
+ Box,
36353
+ {
36354
+ action: action.event,
36355
+ actionPayload: { row: rowSafe },
36356
+ className: "cursor-pointer hover:opacity-80 transition-opacity",
36357
+ children: /* @__PURE__ */ jsx(Badge, { variant: "default", children: action.label })
36358
+ },
36359
+ actionIdx
36360
+ );
36361
+ }) })
36322
36362
  ] })
36323
36363
  ] }, item.id);
36324
36364
  }) })
@@ -38213,9 +38253,6 @@ function EventBusProvider({ children, debug: debug2 = false }) {
38213
38253
  const emit = useCallback((type, payload, source) => {
38214
38254
  const event = {
38215
38255
  type,
38216
- // Narrow at the bus boundary: public emit takes Record for ergonomics
38217
- // (generic UI components pass consumer-defined rows) while the envelope
38218
- // stores the payload as EventPayload for listeners.
38219
38256
  payload,
38220
38257
  timestamp: Date.now(),
38221
38258
  source
@@ -5,9 +5,10 @@
5
5
  *
6
6
  * @packageDocumentation
7
7
  */
8
+ import type { EventPayload } from '@almadar/core';
8
9
  import type { EffectHandlers } from '@almadar/runtime';
9
10
  export interface ClientEventBus {
10
- emit: (type: string, payload?: Record<string, unknown>) => void;
11
+ emit: (type: string, payload?: EventPayload) => void;
11
12
  }
12
13
  export interface SlotSetter {
13
14
  addPattern: (slot: string, pattern: unknown, props?: Record<string, unknown>) => void;
@@ -221,9 +221,6 @@ var init_useEventBus = __esm({
221
221
  emit: (type, payload, source) => {
222
222
  const event = {
223
223
  type,
224
- // Narrow at the bus boundary: public emit accepts an opaque object so
225
- // generic UI emit sites don't require casts; the envelope stores the
226
- // payload as EventPayload which listeners consume directly.
227
224
  payload,
228
225
  timestamp: Date.now(),
229
226
  source
@@ -15798,7 +15795,11 @@ var init_CardGrid = __esm({
15798
15795
  return;
15799
15796
  }
15800
15797
  if (action.event) {
15801
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
15798
+ const payload = {
15799
+ id: itemData.id,
15800
+ row: itemData
15801
+ };
15802
+ eventBus.emit(`UI:${action.event}`, payload);
15802
15803
  }
15803
15804
  if (action.onClick) {
15804
15805
  action.onClick(itemData);
@@ -18468,7 +18469,8 @@ var init_DataGrid = __esm({
18468
18469
  if (next.has(id)) next.delete(id);
18469
18470
  else next.add(id);
18470
18471
  if (selectionEvent) {
18471
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
18472
+ const payload = { selectedIds: Array.from(next) };
18473
+ eventBus.emit(`UI:${selectionEvent}`, payload);
18472
18474
  }
18473
18475
  return next;
18474
18476
  });
@@ -18479,7 +18481,8 @@ var init_DataGrid = __esm({
18479
18481
  const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
18480
18482
  const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
18481
18483
  if (selectionEvent) {
18482
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
18484
+ const payload = { selectedIds: Array.from(next) };
18485
+ eventBus.emit(`UI:${selectionEvent}`, payload);
18483
18486
  }
18484
18487
  return next;
18485
18488
  });
@@ -18491,7 +18494,11 @@ var init_DataGrid = __esm({
18491
18494
  const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
18492
18495
  const handleActionClick = (action, itemData) => (e) => {
18493
18496
  e.stopPropagation();
18494
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
18497
+ const payload = {
18498
+ id: itemData.id,
18499
+ row: itemData
18500
+ };
18501
+ eventBus.emit(`UI:${action.event}`, payload);
18495
18502
  };
18496
18503
  const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
18497
18504
  const colsClass = cols ? {
@@ -18819,7 +18826,11 @@ var init_DataList = __esm({
18819
18826
  );
18820
18827
  const handleActionClick = (action, itemData) => (e) => {
18821
18828
  e.stopPropagation();
18822
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
18829
+ const payload = {
18830
+ id: itemData.id,
18831
+ row: itemData
18832
+ };
18833
+ eventBus.emit(`UI:${action.event}`, payload);
18823
18834
  };
18824
18835
  if (isLoading) {
18825
18836
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
@@ -27001,7 +27012,8 @@ var init_DetailPanel = __esm({
27001
27012
  return;
27002
27013
  }
27003
27014
  if (action.event) {
27004
- eventBus.emit(`UI:${action.event}`, { id: data2?.id, row: data2 });
27015
+ const payload = data2 ? { id: data2.id, row: data2 } : {};
27016
+ eventBus.emit(`UI:${action.event}`, payload);
27005
27017
  }
27006
27018
  if (action.onClick) {
27007
27019
  action.onClick();
@@ -28443,9 +28455,10 @@ var init_Form = __esm({
28443
28455
  };
28444
28456
  const handleSubmit = (e) => {
28445
28457
  e.preventDefault();
28446
- eventBus.emit(`UI:${submitEvent}`, { data: formData });
28458
+ const payload = { data: formData };
28459
+ eventBus.emit(`UI:${submitEvent}`, payload);
28447
28460
  if (onSubmit) {
28448
- eventBus.emit(`UI:${onSubmit}`, { data: formData });
28461
+ eventBus.emit(`UI:${onSubmit}`, payload);
28449
28462
  }
28450
28463
  };
28451
28464
  const handleCancel = () => {
@@ -29813,6 +29826,31 @@ function normalizeFields2(fields) {
29813
29826
  if (!fields) return [];
29814
29827
  return fields.map((f3) => typeof f3 === "string" ? f3 : f3.key ?? f3.name ?? "");
29815
29828
  }
29829
+ function entityFieldsFromListItem(item) {
29830
+ const {
29831
+ icon: _icon,
29832
+ metadata: _metadata,
29833
+ onClick: _onClick,
29834
+ avatar: _avatar,
29835
+ _fields,
29836
+ ...rest
29837
+ } = item;
29838
+ const result = {};
29839
+ for (const [key, value] of Object.entries(rest)) {
29840
+ if (typeof value === "function" || value !== null && typeof value === "object" && "$$typeof" in value) {
29841
+ continue;
29842
+ }
29843
+ result[key] = value;
29844
+ }
29845
+ if (_fields && typeof _fields === "object") {
29846
+ for (const [k, v] of Object.entries(_fields)) {
29847
+ if (typeof v !== "function") {
29848
+ result[k] = v;
29849
+ }
29850
+ }
29851
+ }
29852
+ return result;
29853
+ }
29816
29854
  function getStatusStyle(fieldName, value) {
29817
29855
  const val = String(value).toLowerCase();
29818
29856
  if (val.includes("complete") || val.includes("done"))
@@ -30016,18 +30054,17 @@ var init_List = __esm({
30016
30054
  label: action.label,
30017
30055
  event: action.event,
30018
30056
  onClick: () => {
30057
+ const row = entityFieldsFromListItem(item);
30019
30058
  if (action.navigatesTo) {
30020
30059
  const url = action.navigatesTo.replace(
30021
30060
  /\{\{(\w+)\}\}/g,
30022
- (_, key) => String(item[key] || item.id || "")
30061
+ (_, key) => String(row[key] ?? item.id ?? "")
30023
30062
  );
30024
- eventBus.emit("UI:NAVIGATE", { url, row: item });
30063
+ eventBus.emit("UI:NAVIGATE", { url, row });
30025
30064
  return;
30026
30065
  }
30027
30066
  if (action.event) {
30028
- eventBus.emit(`UI:${action.event}`, {
30029
- row: item
30030
- });
30067
+ eventBus.emit(`UI:${action.event}`, { row });
30031
30068
  }
30032
30069
  }
30033
30070
  }));
@@ -30107,7 +30144,7 @@ var init_List = __esm({
30107
30144
  );
30108
30145
  const hasExplicitClick = !!(viewAction?.event || item.onClick);
30109
30146
  const rowAction = viewAction?.event ?? "VIEW";
30110
- const rowActionPayload = { row: item };
30147
+ const rowActionPayload = { row: entityFieldsFromListItem(item) };
30111
30148
  const primaryField = effectiveFieldNames?.[0];
30112
30149
  const statusField = effectiveFieldNames?.find(
30113
30150
  (f3) => f3.toLowerCase().includes("status")
@@ -35926,16 +35963,19 @@ var init_Timeline = __esm({
35926
35963
  ] }),
35927
35964
  item.description && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: item.description }),
35928
35965
  item.tags && item.tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: item.tags.map((tag, tagIdx) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", children: tag }, tagIdx)) }),
35929
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => /* @__PURE__ */ jsxRuntime.jsx(
35930
- Box,
35931
- {
35932
- action: action.event,
35933
- actionPayload: { row: item },
35934
- className: "cursor-pointer hover:opacity-80 transition-opacity",
35935
- children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", children: action.label })
35936
- },
35937
- actionIdx
35938
- )) })
35966
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => {
35967
+ const { icon: _icon, ...rowSafe } = item;
35968
+ return /* @__PURE__ */ jsxRuntime.jsx(
35969
+ Box,
35970
+ {
35971
+ action: action.event,
35972
+ actionPayload: { row: rowSafe },
35973
+ className: "cursor-pointer hover:opacity-80 transition-opacity",
35974
+ children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", children: action.label })
35975
+ },
35976
+ actionIdx
35977
+ );
35978
+ }) })
35939
35979
  ] })
35940
35980
  ] }, item.id);
35941
35981
  }) })
@@ -176,9 +176,6 @@ var init_useEventBus = __esm({
176
176
  emit: (type, payload, source) => {
177
177
  const event = {
178
178
  type,
179
- // Narrow at the bus boundary: public emit accepts an opaque object so
180
- // generic UI emit sites don't require casts; the envelope stores the
181
- // payload as EventPayload which listeners consume directly.
182
179
  payload,
183
180
  timestamp: Date.now(),
184
181
  source
@@ -15753,7 +15750,11 @@ var init_CardGrid = __esm({
15753
15750
  return;
15754
15751
  }
15755
15752
  if (action.event) {
15756
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
15753
+ const payload = {
15754
+ id: itemData.id,
15755
+ row: itemData
15756
+ };
15757
+ eventBus.emit(`UI:${action.event}`, payload);
15757
15758
  }
15758
15759
  if (action.onClick) {
15759
15760
  action.onClick(itemData);
@@ -18423,7 +18424,8 @@ var init_DataGrid = __esm({
18423
18424
  if (next.has(id)) next.delete(id);
18424
18425
  else next.add(id);
18425
18426
  if (selectionEvent) {
18426
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
18427
+ const payload = { selectedIds: Array.from(next) };
18428
+ eventBus.emit(`UI:${selectionEvent}`, payload);
18427
18429
  }
18428
18430
  return next;
18429
18431
  });
@@ -18434,7 +18436,8 @@ var init_DataGrid = __esm({
18434
18436
  const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
18435
18437
  const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
18436
18438
  if (selectionEvent) {
18437
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
18439
+ const payload = { selectedIds: Array.from(next) };
18440
+ eventBus.emit(`UI:${selectionEvent}`, payload);
18438
18441
  }
18439
18442
  return next;
18440
18443
  });
@@ -18446,7 +18449,11 @@ var init_DataGrid = __esm({
18446
18449
  const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
18447
18450
  const handleActionClick = (action, itemData) => (e) => {
18448
18451
  e.stopPropagation();
18449
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
18452
+ const payload = {
18453
+ id: itemData.id,
18454
+ row: itemData
18455
+ };
18456
+ eventBus.emit(`UI:${action.event}`, payload);
18450
18457
  };
18451
18458
  const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
18452
18459
  const colsClass = cols ? {
@@ -18774,7 +18781,11 @@ var init_DataList = __esm({
18774
18781
  );
18775
18782
  const handleActionClick = (action, itemData) => (e) => {
18776
18783
  e.stopPropagation();
18777
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
18784
+ const payload = {
18785
+ id: itemData.id,
18786
+ row: itemData
18787
+ };
18788
+ eventBus.emit(`UI:${action.event}`, payload);
18778
18789
  };
18779
18790
  if (isLoading) {
18780
18791
  return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
@@ -26956,7 +26967,8 @@ var init_DetailPanel = __esm({
26956
26967
  return;
26957
26968
  }
26958
26969
  if (action.event) {
26959
- eventBus.emit(`UI:${action.event}`, { id: data2?.id, row: data2 });
26970
+ const payload = data2 ? { id: data2.id, row: data2 } : {};
26971
+ eventBus.emit(`UI:${action.event}`, payload);
26960
26972
  }
26961
26973
  if (action.onClick) {
26962
26974
  action.onClick();
@@ -28398,9 +28410,10 @@ var init_Form = __esm({
28398
28410
  };
28399
28411
  const handleSubmit = (e) => {
28400
28412
  e.preventDefault();
28401
- eventBus.emit(`UI:${submitEvent}`, { data: formData });
28413
+ const payload = { data: formData };
28414
+ eventBus.emit(`UI:${submitEvent}`, payload);
28402
28415
  if (onSubmit) {
28403
- eventBus.emit(`UI:${onSubmit}`, { data: formData });
28416
+ eventBus.emit(`UI:${onSubmit}`, payload);
28404
28417
  }
28405
28418
  };
28406
28419
  const handleCancel = () => {
@@ -29768,6 +29781,31 @@ function normalizeFields2(fields) {
29768
29781
  if (!fields) return [];
29769
29782
  return fields.map((f3) => typeof f3 === "string" ? f3 : f3.key ?? f3.name ?? "");
29770
29783
  }
29784
+ function entityFieldsFromListItem(item) {
29785
+ const {
29786
+ icon: _icon,
29787
+ metadata: _metadata,
29788
+ onClick: _onClick,
29789
+ avatar: _avatar,
29790
+ _fields,
29791
+ ...rest
29792
+ } = item;
29793
+ const result = {};
29794
+ for (const [key, value] of Object.entries(rest)) {
29795
+ if (typeof value === "function" || value !== null && typeof value === "object" && "$$typeof" in value) {
29796
+ continue;
29797
+ }
29798
+ result[key] = value;
29799
+ }
29800
+ if (_fields && typeof _fields === "object") {
29801
+ for (const [k, v] of Object.entries(_fields)) {
29802
+ if (typeof v !== "function") {
29803
+ result[k] = v;
29804
+ }
29805
+ }
29806
+ }
29807
+ return result;
29808
+ }
29771
29809
  function getStatusStyle(fieldName, value) {
29772
29810
  const val = String(value).toLowerCase();
29773
29811
  if (val.includes("complete") || val.includes("done"))
@@ -29971,18 +30009,17 @@ var init_List = __esm({
29971
30009
  label: action.label,
29972
30010
  event: action.event,
29973
30011
  onClick: () => {
30012
+ const row = entityFieldsFromListItem(item);
29974
30013
  if (action.navigatesTo) {
29975
30014
  const url = action.navigatesTo.replace(
29976
30015
  /\{\{(\w+)\}\}/g,
29977
- (_, key) => String(item[key] || item.id || "")
30016
+ (_, key) => String(row[key] ?? item.id ?? "")
29978
30017
  );
29979
- eventBus.emit("UI:NAVIGATE", { url, row: item });
30018
+ eventBus.emit("UI:NAVIGATE", { url, row });
29980
30019
  return;
29981
30020
  }
29982
30021
  if (action.event) {
29983
- eventBus.emit(`UI:${action.event}`, {
29984
- row: item
29985
- });
30022
+ eventBus.emit(`UI:${action.event}`, { row });
29986
30023
  }
29987
30024
  }
29988
30025
  }));
@@ -30062,7 +30099,7 @@ var init_List = __esm({
30062
30099
  );
30063
30100
  const hasExplicitClick = !!(viewAction?.event || item.onClick);
30064
30101
  const rowAction = viewAction?.event ?? "VIEW";
30065
- const rowActionPayload = { row: item };
30102
+ const rowActionPayload = { row: entityFieldsFromListItem(item) };
30066
30103
  const primaryField = effectiveFieldNames?.[0];
30067
30104
  const statusField = effectiveFieldNames?.find(
30068
30105
  (f3) => f3.toLowerCase().includes("status")
@@ -35881,16 +35918,19 @@ var init_Timeline = __esm({
35881
35918
  ] }),
35882
35919
  item.description && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: item.description }),
35883
35920
  item.tags && item.tags.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: item.tags.map((tag, tagIdx) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: tag }, tagIdx)) }),
35884
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => /* @__PURE__ */ jsx(
35885
- Box,
35886
- {
35887
- action: action.event,
35888
- actionPayload: { row: item },
35889
- className: "cursor-pointer hover:opacity-80 transition-opacity",
35890
- children: /* @__PURE__ */ jsx(Badge, { variant: "default", children: action.label })
35891
- },
35892
- actionIdx
35893
- )) })
35921
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => {
35922
+ const { icon: _icon, ...rowSafe } = item;
35923
+ return /* @__PURE__ */ jsx(
35924
+ Box,
35925
+ {
35926
+ action: action.event,
35927
+ actionPayload: { row: rowSafe },
35928
+ className: "cursor-pointer hover:opacity-80 transition-opacity",
35929
+ children: /* @__PURE__ */ jsx(Badge, { variant: "default", children: action.label })
35930
+ },
35931
+ actionIdx
35932
+ );
35933
+ }) })
35894
35934
  ] })
35895
35935
  ] }, item.id);
35896
35936
  }) })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",
@@ -118,9 +118,9 @@
118
118
  "access": "public"
119
119
  },
120
120
  "dependencies": {
121
- "@almadar/core": ">=5.6.0",
121
+ "@almadar/core": ">=5.6.1",
122
122
  "@almadar/evaluator": ">=2.9.2",
123
- "@almadar/patterns": ">=2.16.0",
123
+ "@almadar/patterns": ">=2.17.1",
124
124
  "@almadar/runtime": ">=4.3.0",
125
125
  "@almadar/std": ">=6.4.1",
126
126
  "@almadar/syntax": ">=1.3.1",