@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
@@ -11,14 +11,15 @@
11
11
  * Local state is hover/tooltip only — rendering-only concerns.
12
12
  */
13
13
  import React from 'react';
14
- export interface InventoryItem {
14
+ import type { EventPayload } from "@almadar/core";
15
+ export type InventoryItem = EventPayload & {
15
16
  id: string;
16
17
  type: string;
17
18
  quantity: number;
18
19
  sprite?: string;
19
20
  name?: string;
20
21
  description?: string;
21
- }
22
+ };
22
23
  export interface InventoryPanelProps {
23
24
  /** Array of items in inventory */
24
25
  items: InventoryItem[];
@@ -8,7 +8,7 @@
8
8
  * @packageDocumentation
9
9
  */
10
10
  import React from "react";
11
- import type { EventKey } from "@almadar/core";
11
+ import type { EventKey, EventPayload } from "@almadar/core";
12
12
  /**
13
13
  * Allowed element types for custom patterns.
14
14
  */
@@ -34,7 +34,7 @@ export interface CustomPatternProps {
34
34
  /** Event to emit on click (REQUIRED for interactive elements) */
35
35
  action?: EventKey;
36
36
  /** Event payload */
37
- payload?: Record<string, unknown>;
37
+ payload?: EventPayload;
38
38
  /** Nested children patterns */
39
39
  children?: React.ReactNode;
40
40
  /** Image source (for img elements) */
@@ -83,7 +83,7 @@ export interface CustomPatternConfig {
83
83
  token?: string | string[];
84
84
  content?: string;
85
85
  action?: EventKey;
86
- payload?: Record<string, unknown>;
86
+ payload?: EventPayload;
87
87
  children?: CustomPatternConfig[];
88
88
  src?: string;
89
89
  alt?: string;
@@ -11,7 +11,8 @@
11
11
  * - className for external styling
12
12
  */
13
13
  import React from "react";
14
- export interface GraphNode {
14
+ import type { EventPayload } from "@almadar/core";
15
+ export type GraphNode = EventPayload & {
15
16
  id: string;
16
17
  label?: string;
17
18
  group?: string;
@@ -20,7 +21,7 @@ export interface GraphNode {
20
21
  /** Position (optional, computed if missing) */
21
22
  x?: number;
22
23
  y?: number;
23
- }
24
+ };
24
25
  export interface GraphEdge {
25
26
  source: string;
26
27
  target: string;
@@ -1439,9 +1439,6 @@ var fallbackEventBus = {
1439
1439
  emit: (type, payload, source) => {
1440
1440
  const event = {
1441
1441
  type,
1442
- // Narrow at the bus boundary: public emit accepts an opaque object so
1443
- // generic UI emit sites don't require casts; the envelope stores the
1444
- // payload as EventPayload which listeners consume directly.
1445
1442
  payload,
1446
1443
  timestamp: Date.now(),
1447
1444
  source
@@ -1415,9 +1415,6 @@ var fallbackEventBus = {
1415
1415
  emit: (type, payload, source) => {
1416
1416
  const event = {
1417
1417
  type,
1418
- // Narrow at the bus boundary: public emit accepts an opaque object so
1419
- // generic UI emit sites don't require casts; the envelope stores the
1420
- // payload as EventPayload which listeners consume directly.
1421
1418
  payload,
1422
1419
  timestamp: Date.now(),
1423
1420
  source
@@ -2573,9 +2573,6 @@ var fallbackEventBus = {
2573
2573
  emit: (type, payload, source) => {
2574
2574
  const event = {
2575
2575
  type,
2576
- // Narrow at the bus boundary: public emit accepts an opaque object so
2577
- // generic UI emit sites don't require casts; the envelope stores the
2578
- // payload as EventPayload which listeners consume directly.
2579
2576
  payload,
2580
2577
  timestamp: Date.now(),
2581
2578
  source
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { EventKey } from '@almadar/core';
2
+ import { EventKey, EventPayload } from '@almadar/core';
3
3
  import { LucideIcon } from 'lucide-react';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
 
@@ -51,9 +51,9 @@ interface BoxProps extends React.HTMLAttributes<HTMLDivElement> {
51
51
  /** Declarative event name — emits UI:{action} via eventBus on click */
52
52
  action?: EventKey;
53
53
  /** Payload to include with the action event */
54
- actionPayload?: Record<string, unknown>;
54
+ actionPayload?: EventPayload;
55
55
  /** Declarative hover event — emits UI:{hoverEvent} with { hovered: true/false } on mouseEnter/mouseLeave */
56
- hoverEvent?: string;
56
+ hoverEvent?: EventKey;
57
57
  /** Maximum width (CSS value, e.g., "550px", "80rem") */
58
58
  maxWidth?: string;
59
59
  /** Children elements */
@@ -109,7 +109,7 @@ interface StackProps {
109
109
  /** Declarative event name — emits UI:{action} via eventBus on click */
110
110
  action?: EventKey;
111
111
  /** Payload to include with the action event */
112
- actionPayload?: Record<string, unknown>;
112
+ actionPayload?: EventPayload;
113
113
  /** When true, horizontal stacks flip to vertical below the md breakpoint (768px) */
114
114
  responsive?: boolean;
115
115
  }
@@ -183,7 +183,7 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
183
183
  /** Declarative event name — emits UI:{action} via eventBus on click */
184
184
  action?: EventKey;
185
185
  /** Payload to include with the action event */
186
- actionPayload?: Record<string, unknown>;
186
+ actionPayload?: EventPayload;
187
187
  /** Button label text (alternative to children for schema-driven rendering) */
188
188
  label?: string;
189
189
  }
@@ -2549,9 +2549,6 @@ var fallbackEventBus = {
2549
2549
  emit: (type, payload, source) => {
2550
2550
  const event = {
2551
2551
  type,
2552
- // Narrow at the bus boundary: public emit accepts an opaque object so
2553
- // generic UI emit sites don't require casts; the envelope stores the
2554
- // payload as EventPayload which listeners consume directly.
2555
2552
  payload,
2556
2553
  timestamp: Date.now(),
2557
2554
  source
@@ -7,28 +7,28 @@
7
7
  *
8
8
  * @packageDocumentation
9
9
  */
10
- import type { BusEvent, BusEventSource, BusEventListener, Unsubscribe } from "@almadar/core";
11
- export type { BusEvent, BusEventSource, Unsubscribe };
10
+ import type { BusEvent, BusEventSource, BusEventListener, EventPayload, Unsubscribe } from "@almadar/core";
11
+ export type { BusEvent, BusEventSource, EventPayload, Unsubscribe };
12
12
  export type EventListener = BusEventListener;
13
13
  /**
14
14
  * Event bus context type.
15
15
  *
16
- * `emit` accepts `Record<string, unknown>` on its public surface so
17
- * generic UI components (DataGrid, SortableList, ...) can pass
18
- * consumer-defined row data without a cast at every emit site. The
19
- * envelope stored in `BusEvent.payload` is narrowed to `EventPayload`
20
- * inside the bus implementation listeners always receive the typed
21
- * shape.
16
+ * `emit` accepts `EventPayload` from `@almadar/core` the canonical
17
+ * object shape (index signature over `EventPayloadValue`) that the bus
18
+ * envelope stores and listeners consume. Pattern-specific payload types
19
+ * from `@almadar/patterns` (`ItemActionPayload`, `SelectionChangePayload`,
20
+ * `FormSubmitPayload`, ...) are structural subtypes of `EventPayload`,
21
+ * so components can pass them in without casts.
22
22
  */
23
23
  export interface EventBusContextType {
24
24
  /**
25
25
  * Emit an event to all listeners.
26
26
  *
27
27
  * @param type - Event type identifier
28
- * @param payload - Optional payload data (object-shaped)
28
+ * @param payload - Optional payload data (shape matches {@link EventPayload})
29
29
  * @param source - Optional origin info (orbital/trait/...)
30
30
  */
31
- emit: (type: string, payload?: Record<string, unknown>, source?: BusEventSource) => void;
31
+ emit: (type: string, payload?: EventPayload, source?: BusEventSource) => void;
32
32
  /**
33
33
  * Subscribe to an event type.
34
34
  *
@@ -938,9 +938,6 @@ var fallbackEventBus = {
938
938
  emit: (type, payload, source) => {
939
939
  const event = {
940
940
  type,
941
- // Narrow at the bus boundary: public emit accepts an opaque object so
942
- // generic UI emit sites don't require casts; the envelope stores the
943
- // payload as EventPayload which listeners consume directly.
944
941
  payload,
945
942
  timestamp: Date.now(),
946
943
  source
@@ -932,9 +932,6 @@ var fallbackEventBus = {
932
932
  emit: (type, payload, source) => {
933
933
  const event = {
934
934
  type,
935
- // Narrow at the bus boundary: public emit accepts an opaque object so
936
- // generic UI emit sites don't require casts; the envelope stores the
937
- // payload as EventPayload which listeners consume directly.
938
935
  payload,
939
936
  timestamp: Date.now(),
940
937
  source
@@ -1,7 +1,8 @@
1
+ import type { EventPayload } from '@almadar/core';
1
2
  /** Discriminated payload carried by every drag operation. */
2
3
  export interface DraggablePayload {
3
4
  kind: 'pattern' | 'behavior' | 'tree-node' | 'event-wire';
4
- data: Record<string, unknown>;
5
+ data: EventPayload;
5
6
  }
6
7
  export interface UseDraggableOptions {
7
8
  /** The payload that will be serialised into dataTransfer. */
@@ -1,4 +1,5 @@
1
1
  import type { BusEvent, BusEventSource, EventListener, Unsubscribe, EventBusContextType } from './event-bus-types';
2
+ import type { EventPayload } from '@almadar/core';
2
3
  export type { BusEvent, BusEventSource, EventListener, Unsubscribe, EventBusContextType };
3
4
  declare global {
4
5
  interface Window {
@@ -92,5 +93,5 @@ export declare const useEventSubscription: typeof useEventListener;
92
93
  * };
93
94
  * ```
94
95
  */
95
- export declare function useEmitEvent(): (type: string, payload?: Record<string, unknown>, source?: BusEventSource) => void;
96
+ export declare function useEmitEvent(): (type: string, payload?: EventPayload, source?: BusEventSource) => void;
96
97
  export default useEventBus;
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * @packageDocumentation
11
11
  */
12
- import type { AssetLoadStatus, BridgeHealth, BusEvent, CheckStatus, EffectTrace, EventLogEntry, OrbitalVerificationAPI, ServerResponseTrace, TraitStateSnapshot, TransitionTrace, VerificationCheck, VerificationSnapshot, VerificationSummary } from '@almadar/core';
12
+ import type { AssetLoadStatus, BridgeHealth, BusEvent, CheckStatus, EffectTrace, EventLogEntry, EventPayload, OrbitalVerificationAPI, ServerResponseTrace, TraitStateSnapshot, TransitionTrace, VerificationCheck, VerificationSnapshot, VerificationSummary } from '@almadar/core';
13
13
  export type { AssetLoadStatus, BridgeHealth, CheckStatus, EffectTrace, EventLogEntry, OrbitalVerificationAPI, ServerResponseTrace, TraitStateSnapshot, TransitionTrace, VerificationCheck, VerificationSnapshot, VerificationSummary, };
14
14
  type ChangeListener = () => void;
15
15
  /**
@@ -59,7 +59,7 @@ export declare function waitForTransition(event: string, timeoutMs?: number): Pr
59
59
  * Call this during app initialization.
60
60
  */
61
61
  export declare function bindEventBus(eventBus: {
62
- emit: (type: string, payload?: Record<string, unknown>) => void;
62
+ emit: (type: string, payload?: EventPayload) => void;
63
63
  onAny?: (listener: (event: BusEvent) => void) => () => void;
64
64
  }): void;
65
65
  /**
@@ -2573,9 +2573,6 @@ var fallbackEventBus = {
2573
2573
  emit: (type, payload, source) => {
2574
2574
  const event = {
2575
2575
  type,
2576
- // Narrow at the bus boundary: public emit accepts an opaque object so
2577
- // generic UI emit sites don't require casts; the envelope stores the
2578
- // payload as EventPayload which listeners consume directly.
2579
2576
  payload,
2580
2577
  timestamp: Date.now(),
2581
2578
  source
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { EventKey } from '@almadar/core';
2
+ import { EventKey, EventPayload } from '@almadar/core';
3
3
  import { LucideIcon } from 'lucide-react';
4
4
 
5
5
  /**
@@ -50,9 +50,9 @@ interface BoxProps extends React.HTMLAttributes<HTMLDivElement> {
50
50
  /** Declarative event name — emits UI:{action} via eventBus on click */
51
51
  action?: EventKey;
52
52
  /** Payload to include with the action event */
53
- actionPayload?: Record<string, unknown>;
53
+ actionPayload?: EventPayload;
54
54
  /** Declarative hover event — emits UI:{hoverEvent} with { hovered: true/false } on mouseEnter/mouseLeave */
55
- hoverEvent?: string;
55
+ hoverEvent?: EventKey;
56
56
  /** Maximum width (CSS value, e.g., "550px", "80rem") */
57
57
  maxWidth?: string;
58
58
  /** Children elements */
@@ -108,7 +108,7 @@ interface StackProps {
108
108
  /** Declarative event name — emits UI:{action} via eventBus on click */
109
109
  action?: EventKey;
110
110
  /** Payload to include with the action event */
111
- actionPayload?: Record<string, unknown>;
111
+ actionPayload?: EventPayload;
112
112
  /** When true, horizontal stacks flip to vertical below the md breakpoint (768px) */
113
113
  responsive?: boolean;
114
114
  }
@@ -182,7 +182,7 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
182
182
  /** Declarative event name — emits UI:{action} via eventBus on click */
183
183
  action?: EventKey;
184
184
  /** Payload to include with the action event */
185
- actionPayload?: Record<string, unknown>;
185
+ actionPayload?: EventPayload;
186
186
  /** Button label text (alternative to children for schema-driven rendering) */
187
187
  label?: string;
188
188
  }
@@ -2549,9 +2549,6 @@ var fallbackEventBus = {
2549
2549
  emit: (type, payload, source) => {
2550
2550
  const event = {
2551
2551
  type,
2552
- // Narrow at the bus boundary: public emit accepts an opaque object so
2553
- // generic UI emit sites don't require casts; the envelope stores the
2554
- // payload as EventPayload which listeners consume directly.
2555
2552
  payload,
2556
2553
  timestamp: Date.now(),
2557
2554
  source
@@ -474,9 +474,6 @@ var init_useEventBus = __esm({
474
474
  emit: (type, payload, source) => {
475
475
  const event = {
476
476
  type,
477
- // Narrow at the bus boundary: public emit accepts an opaque object so
478
- // generic UI emit sites don't require casts; the envelope stores the
479
- // payload as EventPayload which listeners consume directly.
480
477
  payload,
481
478
  timestamp: Date.now(),
482
479
  source
@@ -15994,7 +15991,11 @@ var init_CardGrid = __esm({
15994
15991
  return;
15995
15992
  }
15996
15993
  if (action.event) {
15997
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
15994
+ const payload = {
15995
+ id: itemData.id,
15996
+ row: itemData
15997
+ };
15998
+ eventBus.emit(`UI:${action.event}`, payload);
15998
15999
  }
15999
16000
  if (action.onClick) {
16000
16001
  action.onClick(itemData);
@@ -18678,7 +18679,8 @@ var init_DataGrid = __esm({
18678
18679
  if (next.has(id)) next.delete(id);
18679
18680
  else next.add(id);
18680
18681
  if (selectionEvent) {
18681
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
18682
+ const payload = { selectedIds: Array.from(next) };
18683
+ eventBus.emit(`UI:${selectionEvent}`, payload);
18682
18684
  }
18683
18685
  return next;
18684
18686
  });
@@ -18689,7 +18691,8 @@ var init_DataGrid = __esm({
18689
18691
  const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
18690
18692
  const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
18691
18693
  if (selectionEvent) {
18692
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
18694
+ const payload = { selectedIds: Array.from(next) };
18695
+ eventBus.emit(`UI:${selectionEvent}`, payload);
18693
18696
  }
18694
18697
  return next;
18695
18698
  });
@@ -18701,7 +18704,11 @@ var init_DataGrid = __esm({
18701
18704
  const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
18702
18705
  const handleActionClick = (action, itemData) => (e) => {
18703
18706
  e.stopPropagation();
18704
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
18707
+ const payload = {
18708
+ id: itemData.id,
18709
+ row: itemData
18710
+ };
18711
+ eventBus.emit(`UI:${action.event}`, payload);
18705
18712
  };
18706
18713
  const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
18707
18714
  const colsClass = cols ? {
@@ -19029,7 +19036,11 @@ var init_DataList = __esm({
19029
19036
  );
19030
19037
  const handleActionClick = (action, itemData) => (e) => {
19031
19038
  e.stopPropagation();
19032
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
19039
+ const payload = {
19040
+ id: itemData.id,
19041
+ row: itemData
19042
+ };
19043
+ eventBus.emit(`UI:${action.event}`, payload);
19033
19044
  };
19034
19045
  if (isLoading) {
19035
19046
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
@@ -27413,7 +27424,8 @@ var init_DetailPanel = __esm({
27413
27424
  return;
27414
27425
  }
27415
27426
  if (action.event) {
27416
- eventBus.emit(`UI:${action.event}`, { id: data2?.id, row: data2 });
27427
+ const payload = data2 ? { id: data2.id, row: data2 } : {};
27428
+ eventBus.emit(`UI:${action.event}`, payload);
27417
27429
  }
27418
27430
  if (action.onClick) {
27419
27431
  action.onClick();
@@ -28855,9 +28867,10 @@ var init_Form = __esm({
28855
28867
  };
28856
28868
  const handleSubmit = (e) => {
28857
28869
  e.preventDefault();
28858
- eventBus.emit(`UI:${submitEvent}`, { data: formData });
28870
+ const payload = { data: formData };
28871
+ eventBus.emit(`UI:${submitEvent}`, payload);
28859
28872
  if (onSubmit) {
28860
- eventBus.emit(`UI:${onSubmit}`, { data: formData });
28873
+ eventBus.emit(`UI:${onSubmit}`, payload);
28861
28874
  }
28862
28875
  };
28863
28876
  const handleCancel = () => {
@@ -30225,6 +30238,31 @@ function normalizeFields2(fields) {
30225
30238
  if (!fields) return [];
30226
30239
  return fields.map((f3) => typeof f3 === "string" ? f3 : f3.key ?? f3.name ?? "");
30227
30240
  }
30241
+ function entityFieldsFromListItem(item) {
30242
+ const {
30243
+ icon: _icon,
30244
+ metadata: _metadata,
30245
+ onClick: _onClick,
30246
+ avatar: _avatar,
30247
+ _fields,
30248
+ ...rest
30249
+ } = item;
30250
+ const result = {};
30251
+ for (const [key, value] of Object.entries(rest)) {
30252
+ if (typeof value === "function" || value !== null && typeof value === "object" && "$$typeof" in value) {
30253
+ continue;
30254
+ }
30255
+ result[key] = value;
30256
+ }
30257
+ if (_fields && typeof _fields === "object") {
30258
+ for (const [k, v] of Object.entries(_fields)) {
30259
+ if (typeof v !== "function") {
30260
+ result[k] = v;
30261
+ }
30262
+ }
30263
+ }
30264
+ return result;
30265
+ }
30228
30266
  function getStatusStyle(fieldName, value) {
30229
30267
  const val = String(value).toLowerCase();
30230
30268
  if (val.includes("complete") || val.includes("done"))
@@ -30428,18 +30466,17 @@ var init_List = __esm({
30428
30466
  label: action.label,
30429
30467
  event: action.event,
30430
30468
  onClick: () => {
30469
+ const row = entityFieldsFromListItem(item);
30431
30470
  if (action.navigatesTo) {
30432
30471
  const url = action.navigatesTo.replace(
30433
30472
  /\{\{(\w+)\}\}/g,
30434
- (_, key) => String(item[key] || item.id || "")
30473
+ (_, key) => String(row[key] ?? item.id ?? "")
30435
30474
  );
30436
- eventBus.emit("UI:NAVIGATE", { url, row: item });
30475
+ eventBus.emit("UI:NAVIGATE", { url, row });
30437
30476
  return;
30438
30477
  }
30439
30478
  if (action.event) {
30440
- eventBus.emit(`UI:${action.event}`, {
30441
- row: item
30442
- });
30479
+ eventBus.emit(`UI:${action.event}`, { row });
30443
30480
  }
30444
30481
  }
30445
30482
  }));
@@ -30519,7 +30556,7 @@ var init_List = __esm({
30519
30556
  );
30520
30557
  const hasExplicitClick = !!(viewAction?.event || item.onClick);
30521
30558
  const rowAction = viewAction?.event ?? "VIEW";
30522
- const rowActionPayload = { row: item };
30559
+ const rowActionPayload = { row: entityFieldsFromListItem(item) };
30523
30560
  const primaryField = effectiveFieldNames?.[0];
30524
30561
  const statusField = effectiveFieldNames?.find(
30525
30562
  (f3) => f3.toLowerCase().includes("status")
@@ -36354,16 +36391,19 @@ var init_Timeline = __esm({
36354
36391
  ] }),
36355
36392
  item.description && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: item.description }),
36356
36393
  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)) }),
36357
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => /* @__PURE__ */ jsxRuntime.jsx(
36358
- Box,
36359
- {
36360
- action: action.event,
36361
- actionPayload: { row: item },
36362
- className: "cursor-pointer hover:opacity-80 transition-opacity",
36363
- children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", children: action.label })
36364
- },
36365
- actionIdx
36366
- )) })
36394
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => {
36395
+ const { icon: _icon, ...rowSafe } = item;
36396
+ return /* @__PURE__ */ jsxRuntime.jsx(
36397
+ Box,
36398
+ {
36399
+ action: action.event,
36400
+ actionPayload: { row: rowSafe },
36401
+ className: "cursor-pointer hover:opacity-80 transition-opacity",
36402
+ children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", children: action.label })
36403
+ },
36404
+ actionIdx
36405
+ );
36406
+ }) })
36367
36407
  ] })
36368
36408
  ] }, item.id);
36369
36409
  }) })
@@ -38258,9 +38298,6 @@ function EventBusProvider({ children, debug: debug2 = false }) {
38258
38298
  const emit = React115.useCallback((type, payload, source) => {
38259
38299
  const event = {
38260
38300
  type,
38261
- // Narrow at the bus boundary: public emit takes Record for ergonomics
38262
- // (generic UI components pass consumer-defined rows) while the envelope
38263
- // stores the payload as EventPayload for listeners.
38264
38301
  payload,
38265
38302
  timestamp: Date.now(),
38266
38303
  source