@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
@@ -227,9 +227,6 @@ var init_useEventBus = __esm({
227
227
  emit: (type, payload, source) => {
228
228
  const event = {
229
229
  type,
230
- // Narrow at the bus boundary: public emit accepts an opaque object so
231
- // generic UI emit sites don't require casts; the envelope stores the
232
- // payload as EventPayload which listeners consume directly.
233
230
  payload,
234
231
  timestamp: Date.now(),
235
232
  source
@@ -14451,7 +14448,11 @@ var init_CardGrid = __esm({
14451
14448
  return;
14452
14449
  }
14453
14450
  if (action.event) {
14454
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
14451
+ const payload = {
14452
+ id: itemData.id,
14453
+ row: itemData
14454
+ };
14455
+ eventBus.emit(`UI:${action.event}`, payload);
14455
14456
  }
14456
14457
  if (action.onClick) {
14457
14458
  action.onClick(itemData);
@@ -17366,7 +17367,8 @@ var init_DataGrid = __esm({
17366
17367
  if (next.has(id)) next.delete(id);
17367
17368
  else next.add(id);
17368
17369
  if (selectionEvent) {
17369
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
17370
+ const payload = { selectedIds: Array.from(next) };
17371
+ eventBus.emit(`UI:${selectionEvent}`, payload);
17370
17372
  }
17371
17373
  return next;
17372
17374
  });
@@ -17377,7 +17379,8 @@ var init_DataGrid = __esm({
17377
17379
  const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
17378
17380
  const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
17379
17381
  if (selectionEvent) {
17380
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
17382
+ const payload = { selectedIds: Array.from(next) };
17383
+ eventBus.emit(`UI:${selectionEvent}`, payload);
17381
17384
  }
17382
17385
  return next;
17383
17386
  });
@@ -17389,7 +17392,11 @@ var init_DataGrid = __esm({
17389
17392
  const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
17390
17393
  const handleActionClick = (action, itemData) => (e) => {
17391
17394
  e.stopPropagation();
17392
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
17395
+ const payload = {
17396
+ id: itemData.id,
17397
+ row: itemData
17398
+ };
17399
+ eventBus.emit(`UI:${action.event}`, payload);
17393
17400
  };
17394
17401
  const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
17395
17402
  const colsClass = cols ? {
@@ -17717,7 +17724,11 @@ var init_DataList = __esm({
17717
17724
  );
17718
17725
  const handleActionClick = (action, itemData) => (e) => {
17719
17726
  e.stopPropagation();
17720
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
17727
+ const payload = {
17728
+ id: itemData.id,
17729
+ row: itemData
17730
+ };
17731
+ eventBus.emit(`UI:${action.event}`, payload);
17721
17732
  };
17722
17733
  if (isLoading) {
17723
17734
  return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
@@ -26371,7 +26382,8 @@ var init_DetailPanel = __esm({
26371
26382
  return;
26372
26383
  }
26373
26384
  if (action.event) {
26374
- eventBus.emit(`UI:${action.event}`, { id: data2?.id, row: data2 });
26385
+ const payload = data2 ? { id: data2.id, row: data2 } : {};
26386
+ eventBus.emit(`UI:${action.event}`, payload);
26375
26387
  }
26376
26388
  if (action.onClick) {
26377
26389
  action.onClick();
@@ -27908,9 +27920,10 @@ var init_Form = __esm({
27908
27920
  };
27909
27921
  const handleSubmit = (e) => {
27910
27922
  e.preventDefault();
27911
- eventBus.emit(`UI:${submitEvent}`, { data: formData });
27923
+ const payload = { data: formData };
27924
+ eventBus.emit(`UI:${submitEvent}`, payload);
27912
27925
  if (onSubmit) {
27913
- eventBus.emit(`UI:${onSubmit}`, { data: formData });
27926
+ eventBus.emit(`UI:${onSubmit}`, payload);
27914
27927
  }
27915
27928
  };
27916
27929
  const handleCancel = () => {
@@ -29278,6 +29291,31 @@ function normalizeFields2(fields) {
29278
29291
  if (!fields) return [];
29279
29292
  return fields.map((f3) => typeof f3 === "string" ? f3 : f3.key ?? f3.name ?? "");
29280
29293
  }
29294
+ function entityFieldsFromListItem(item) {
29295
+ const {
29296
+ icon: _icon,
29297
+ metadata: _metadata,
29298
+ onClick: _onClick,
29299
+ avatar: _avatar,
29300
+ _fields,
29301
+ ...rest
29302
+ } = item;
29303
+ const result = {};
29304
+ for (const [key, value] of Object.entries(rest)) {
29305
+ if (typeof value === "function" || value !== null && typeof value === "object" && "$$typeof" in value) {
29306
+ continue;
29307
+ }
29308
+ result[key] = value;
29309
+ }
29310
+ if (_fields && typeof _fields === "object") {
29311
+ for (const [k, v] of Object.entries(_fields)) {
29312
+ if (typeof v !== "function") {
29313
+ result[k] = v;
29314
+ }
29315
+ }
29316
+ }
29317
+ return result;
29318
+ }
29281
29319
  function getStatusStyle(fieldName, value) {
29282
29320
  const val = String(value).toLowerCase();
29283
29321
  if (val.includes("complete") || val.includes("done"))
@@ -29481,18 +29519,17 @@ var init_List = __esm({
29481
29519
  label: action.label,
29482
29520
  event: action.event,
29483
29521
  onClick: () => {
29522
+ const row = entityFieldsFromListItem(item);
29484
29523
  if (action.navigatesTo) {
29485
29524
  const url = action.navigatesTo.replace(
29486
29525
  /\{\{(\w+)\}\}/g,
29487
- (_, key) => String(item[key] || item.id || "")
29526
+ (_, key) => String(row[key] ?? item.id ?? "")
29488
29527
  );
29489
- eventBus.emit("UI:NAVIGATE", { url, row: item });
29528
+ eventBus.emit("UI:NAVIGATE", { url, row });
29490
29529
  return;
29491
29530
  }
29492
29531
  if (action.event) {
29493
- eventBus.emit(`UI:${action.event}`, {
29494
- row: item
29495
- });
29532
+ eventBus.emit(`UI:${action.event}`, { row });
29496
29533
  }
29497
29534
  }
29498
29535
  }));
@@ -29572,7 +29609,7 @@ var init_List = __esm({
29572
29609
  );
29573
29610
  const hasExplicitClick = !!(viewAction?.event || item.onClick);
29574
29611
  const rowAction = viewAction?.event ?? "VIEW";
29575
- const rowActionPayload = { row: item };
29612
+ const rowActionPayload = { row: entityFieldsFromListItem(item) };
29576
29613
  const primaryField = effectiveFieldNames?.[0];
29577
29614
  const statusField = effectiveFieldNames?.find(
29578
29615
  (f3) => f3.toLowerCase().includes("status")
@@ -35727,16 +35764,19 @@ var init_Timeline = __esm({
35727
35764
  ] }),
35728
35765
  item.description && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", color: "secondary", children: item.description }),
35729
35766
  item.tags && item.tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", wrap: true, children: item.tags.map((tag, tagIdx) => /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: "default", children: tag }, tagIdx)) }),
35730
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => /* @__PURE__ */ jsxRuntime.jsx(
35731
- exports.Box,
35732
- {
35733
- action: action.event,
35734
- actionPayload: { row: item },
35735
- className: "cursor-pointer hover:opacity-80 transition-opacity",
35736
- children: /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: "default", children: action.label })
35737
- },
35738
- actionIdx
35739
- )) })
35767
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => {
35768
+ const { icon: _icon, ...rowSafe } = item;
35769
+ return /* @__PURE__ */ jsxRuntime.jsx(
35770
+ exports.Box,
35771
+ {
35772
+ action: action.event,
35773
+ actionPayload: { row: rowSafe },
35774
+ className: "cursor-pointer hover:opacity-80 transition-opacity",
35775
+ children: /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: "default", children: action.label })
35776
+ },
35777
+ actionIdx
35778
+ );
35779
+ }) })
35740
35780
  ] })
35741
35781
  ] }, item.id);
35742
35782
  }) })
@@ -182,9 +182,6 @@ var init_useEventBus = __esm({
182
182
  emit: (type, payload, source) => {
183
183
  const event = {
184
184
  type,
185
- // Narrow at the bus boundary: public emit accepts an opaque object so
186
- // generic UI emit sites don't require casts; the envelope stores the
187
- // payload as EventPayload which listeners consume directly.
188
185
  payload,
189
186
  timestamp: Date.now(),
190
187
  source
@@ -14406,7 +14403,11 @@ var init_CardGrid = __esm({
14406
14403
  return;
14407
14404
  }
14408
14405
  if (action.event) {
14409
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
14406
+ const payload = {
14407
+ id: itemData.id,
14408
+ row: itemData
14409
+ };
14410
+ eventBus.emit(`UI:${action.event}`, payload);
14410
14411
  }
14411
14412
  if (action.onClick) {
14412
14413
  action.onClick(itemData);
@@ -17321,7 +17322,8 @@ var init_DataGrid = __esm({
17321
17322
  if (next.has(id)) next.delete(id);
17322
17323
  else next.add(id);
17323
17324
  if (selectionEvent) {
17324
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
17325
+ const payload = { selectedIds: Array.from(next) };
17326
+ eventBus.emit(`UI:${selectionEvent}`, payload);
17325
17327
  }
17326
17328
  return next;
17327
17329
  });
@@ -17332,7 +17334,8 @@ var init_DataGrid = __esm({
17332
17334
  const allSelected2 = allIds2.length > 0 && allIds2.every((id) => prev.has(id));
17333
17335
  const next = allSelected2 ? /* @__PURE__ */ new Set() : new Set(allIds2);
17334
17336
  if (selectionEvent) {
17335
- eventBus.emit(`UI:${selectionEvent}`, { selectedIds: Array.from(next) });
17337
+ const payload = { selectedIds: Array.from(next) };
17338
+ eventBus.emit(`UI:${selectionEvent}`, payload);
17336
17339
  }
17337
17340
  return next;
17338
17341
  });
@@ -17344,7 +17347,11 @@ var init_DataGrid = __esm({
17344
17347
  const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
17345
17348
  const handleActionClick = (action, itemData) => (e) => {
17346
17349
  e.stopPropagation();
17347
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
17350
+ const payload = {
17351
+ id: itemData.id,
17352
+ row: itemData
17353
+ };
17354
+ eventBus.emit(`UI:${action.event}`, payload);
17348
17355
  };
17349
17356
  const gridTemplateColumns = cols ? void 0 : `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
17350
17357
  const colsClass = cols ? {
@@ -17672,7 +17679,11 @@ var init_DataList = __esm({
17672
17679
  );
17673
17680
  const handleActionClick = (action, itemData) => (e) => {
17674
17681
  e.stopPropagation();
17675
- eventBus.emit(`UI:${action.event}`, { id: itemData.id, row: itemData });
17682
+ const payload = {
17683
+ id: itemData.id,
17684
+ row: itemData
17685
+ };
17686
+ eventBus.emit(`UI:${action.event}`, payload);
17676
17687
  };
17677
17688
  if (isLoading) {
17678
17689
  return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading..." }) });
@@ -26326,7 +26337,8 @@ var init_DetailPanel = __esm({
26326
26337
  return;
26327
26338
  }
26328
26339
  if (action.event) {
26329
- eventBus.emit(`UI:${action.event}`, { id: data2?.id, row: data2 });
26340
+ const payload = data2 ? { id: data2.id, row: data2 } : {};
26341
+ eventBus.emit(`UI:${action.event}`, payload);
26330
26342
  }
26331
26343
  if (action.onClick) {
26332
26344
  action.onClick();
@@ -27863,9 +27875,10 @@ var init_Form = __esm({
27863
27875
  };
27864
27876
  const handleSubmit = (e) => {
27865
27877
  e.preventDefault();
27866
- eventBus.emit(`UI:${submitEvent}`, { data: formData });
27878
+ const payload = { data: formData };
27879
+ eventBus.emit(`UI:${submitEvent}`, payload);
27867
27880
  if (onSubmit) {
27868
- eventBus.emit(`UI:${onSubmit}`, { data: formData });
27881
+ eventBus.emit(`UI:${onSubmit}`, payload);
27869
27882
  }
27870
27883
  };
27871
27884
  const handleCancel = () => {
@@ -29233,6 +29246,31 @@ function normalizeFields2(fields) {
29233
29246
  if (!fields) return [];
29234
29247
  return fields.map((f3) => typeof f3 === "string" ? f3 : f3.key ?? f3.name ?? "");
29235
29248
  }
29249
+ function entityFieldsFromListItem(item) {
29250
+ const {
29251
+ icon: _icon,
29252
+ metadata: _metadata,
29253
+ onClick: _onClick,
29254
+ avatar: _avatar,
29255
+ _fields,
29256
+ ...rest
29257
+ } = item;
29258
+ const result = {};
29259
+ for (const [key, value] of Object.entries(rest)) {
29260
+ if (typeof value === "function" || value !== null && typeof value === "object" && "$$typeof" in value) {
29261
+ continue;
29262
+ }
29263
+ result[key] = value;
29264
+ }
29265
+ if (_fields && typeof _fields === "object") {
29266
+ for (const [k, v] of Object.entries(_fields)) {
29267
+ if (typeof v !== "function") {
29268
+ result[k] = v;
29269
+ }
29270
+ }
29271
+ }
29272
+ return result;
29273
+ }
29236
29274
  function getStatusStyle(fieldName, value) {
29237
29275
  const val = String(value).toLowerCase();
29238
29276
  if (val.includes("complete") || val.includes("done"))
@@ -29436,18 +29474,17 @@ var init_List = __esm({
29436
29474
  label: action.label,
29437
29475
  event: action.event,
29438
29476
  onClick: () => {
29477
+ const row = entityFieldsFromListItem(item);
29439
29478
  if (action.navigatesTo) {
29440
29479
  const url = action.navigatesTo.replace(
29441
29480
  /\{\{(\w+)\}\}/g,
29442
- (_, key) => String(item[key] || item.id || "")
29481
+ (_, key) => String(row[key] ?? item.id ?? "")
29443
29482
  );
29444
- eventBus.emit("UI:NAVIGATE", { url, row: item });
29483
+ eventBus.emit("UI:NAVIGATE", { url, row });
29445
29484
  return;
29446
29485
  }
29447
29486
  if (action.event) {
29448
- eventBus.emit(`UI:${action.event}`, {
29449
- row: item
29450
- });
29487
+ eventBus.emit(`UI:${action.event}`, { row });
29451
29488
  }
29452
29489
  }
29453
29490
  }));
@@ -29527,7 +29564,7 @@ var init_List = __esm({
29527
29564
  );
29528
29565
  const hasExplicitClick = !!(viewAction?.event || item.onClick);
29529
29566
  const rowAction = viewAction?.event ?? "VIEW";
29530
- const rowActionPayload = { row: item };
29567
+ const rowActionPayload = { row: entityFieldsFromListItem(item) };
29531
29568
  const primaryField = effectiveFieldNames?.[0];
29532
29569
  const statusField = effectiveFieldNames?.find(
29533
29570
  (f3) => f3.toLowerCase().includes("status")
@@ -35682,16 +35719,19 @@ var init_Timeline = __esm({
35682
35719
  ] }),
35683
35720
  item.description && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: item.description }),
35684
35721
  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)) }),
35685
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => /* @__PURE__ */ jsx(
35686
- Box,
35687
- {
35688
- action: action.event,
35689
- actionPayload: { row: item },
35690
- className: "cursor-pointer hover:opacity-80 transition-opacity",
35691
- children: /* @__PURE__ */ jsx(Badge, { variant: "default", children: action.label })
35692
- },
35693
- actionIdx
35694
- )) })
35722
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => {
35723
+ const { icon: _icon, ...rowSafe } = item;
35724
+ return /* @__PURE__ */ jsx(
35725
+ Box,
35726
+ {
35727
+ action: action.event,
35728
+ actionPayload: { row: rowSafe },
35729
+ className: "cursor-pointer hover:opacity-80 transition-opacity",
35730
+ children: /* @__PURE__ */ jsx(Badge, { variant: "default", children: action.label })
35731
+ },
35732
+ actionIdx
35733
+ );
35734
+ }) })
35695
35735
  ] })
35696
35736
  ] }, item.id);
35697
35737
  }) })
@@ -5,6 +5,7 @@
5
5
  * Uses theme-aware CSS variables for styling.
6
6
  */
7
7
  import React from "react";
8
+ import type { EventKey } from "@almadar/core";
8
9
  export type AlertVariant = "info" | "success" | "warning" | "error";
9
10
  export interface AlertProps {
10
11
  /** Alert content (children or message) */
@@ -19,6 +20,6 @@ export interface AlertProps {
19
20
  actions?: React.ReactNode;
20
21
  className?: string;
21
22
  /** Declarative dismiss event — emits UI:{dismissEvent} via eventBus when alert is dismissed */
22
- dismissEvent?: string;
23
+ dismissEvent?: EventKey;
23
24
  }
24
25
  export declare const Alert: React.FC<AlertProps>;
@@ -6,6 +6,7 @@
6
6
  * Composes DayCell and TimeSlotCell atoms into a 7-day grid.
7
7
  */
8
8
  import React from "react";
9
+ import type { EventPayload } from "@almadar/core";
9
10
  export interface CalendarEvent {
10
11
  id: string;
11
12
  title: string;
@@ -31,7 +32,7 @@ export interface CalendarGridProps {
31
32
  /** Event emitted on long-press of a time slot: UI:{longPressEvent} with { date, time } */
32
33
  longPressEvent?: string;
33
34
  /** Additional payload for long-press events */
34
- longPressPayload?: Record<string, unknown>;
35
+ longPressPayload?: EventPayload;
35
36
  /** Event emitted on swipe left (next week): UI:{swipeLeftEvent} */
36
37
  swipeLeftEvent?: string;
37
38
  /** Event emitted on swipe right (prev week): UI:{swipeRightEvent} */
@@ -7,7 +7,7 @@
7
7
  * @generated by Orbital Compiler
8
8
  */
9
9
  import React from "react";
10
- import type { EventKey } from "@almadar/core";
10
+ import type { EventKey, EventPayload } from "@almadar/core";
11
11
  export interface CardAction {
12
12
  label: string;
13
13
  onClick?: () => void;
@@ -45,7 +45,7 @@ export interface CardProps {
45
45
  /** Event emitted on long press: UI:{longPressEvent} */
46
46
  longPressEvent?: string;
47
47
  /** Additional payload for long-press events */
48
- longPressPayload?: Record<string, unknown>;
48
+ longPressPayload?: EventPayload;
49
49
  }
50
50
  /**
51
51
  * Card component for displaying content in a contained box
@@ -61,11 +61,11 @@ export interface DataGridProps {
61
61
  /** Enable multi-select with checkboxes */
62
62
  selectable?: boolean;
63
63
  /** Selection change event name (emits UI:{selectionEvent} with { selectedIds: string[] }) */
64
- selectionEvent?: string;
64
+ selectionEvent?: EventKey;
65
65
  /** Enable infinite scroll loading */
66
66
  infiniteScroll?: boolean;
67
67
  /** Event emitted when more items needed: UI:{loadMoreEvent} */
68
- loadMoreEvent?: string;
68
+ loadMoreEvent?: EventKey;
69
69
  /** Whether more items are available for infinite scroll */
70
70
  hasMore?: boolean;
71
71
  /** Render prop for custom per-item content. When provided, `fields` and `itemActions` are ignored. */
@@ -63,9 +63,9 @@ export interface DataListProps {
63
63
  /** Enable drag-to-reorder with grip handles */
64
64
  reorderable?: boolean;
65
65
  /** Event emitted on reorder: UI:{reorderEvent} with { fromIndex, toIndex } */
66
- reorderEvent?: string;
66
+ reorderEvent?: EventKey;
67
67
  /** Event emitted on left swipe: UI:{swipeLeftEvent} with { row } */
68
- swipeLeftEvent?: string;
68
+ swipeLeftEvent?: EventKey;
69
69
  /** Actions revealed on left swipe */
70
70
  swipeLeftActions?: readonly {
71
71
  label: string;
@@ -73,7 +73,7 @@ export interface DataListProps {
73
73
  variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
74
74
  }[];
75
75
  /** Event emitted on right swipe: UI:{swipeRightEvent} with { row } */
76
- swipeRightEvent?: string;
76
+ swipeRightEvent?: EventKey;
77
77
  /** Actions revealed on right swipe */
78
78
  swipeRightActions?: readonly {
79
79
  label: string;
@@ -81,11 +81,11 @@ export interface DataListProps {
81
81
  variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
82
82
  }[];
83
83
  /** Event emitted on long press: UI:{longPressEvent} with { row } */
84
- longPressEvent?: string;
84
+ longPressEvent?: EventKey;
85
85
  /** Enable infinite scroll loading */
86
86
  infiniteScroll?: boolean;
87
87
  /** Event emitted when more items needed: UI:{loadMoreEvent} */
88
- loadMoreEvent?: string;
88
+ loadMoreEvent?: EventKey;
89
89
  /** Whether more items are available for infinite scroll */
90
90
  hasMore?: boolean;
91
91
  /** Render prop for custom per-item content. When provided, `fields` and `itemActions` are ignored. */
@@ -15,6 +15,7 @@
15
15
  * @packageDocumentation
16
16
  */
17
17
  import React from "react";
18
+ import type { EventKey } from "@almadar/core";
18
19
  export type DrawerPosition = "left" | "right";
19
20
  export type DrawerSize = "sm" | "md" | "lg" | "xl" | "full";
20
21
  export interface DrawerProps {
@@ -41,6 +42,6 @@ export interface DrawerProps {
41
42
  /** Additional class name */
42
43
  className?: string;
43
44
  /** Declarative close event — emits UI:{closeEvent} via eventBus when drawer should close */
44
- closeEvent?: string;
45
+ closeEvent?: EventKey;
45
46
  }
46
47
  export declare const Drawer: React.FC<DrawerProps>;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { EventKey } from "@almadar/core";
2
+ import type { EventKey, EventPayload } from "@almadar/core";
3
3
  export type NumberStepperSize = "sm" | "md" | "lg";
4
4
  export interface NumberStepperProps {
5
5
  /** Current value */
@@ -19,7 +19,7 @@ export interface NumberStepperProps {
19
19
  /** Declarative event name for value changes */
20
20
  action?: EventKey;
21
21
  /** Payload to include with the action event */
22
- actionPayload?: Record<string, unknown>;
22
+ actionPayload?: EventPayload;
23
23
  /** Additional CSS classes */
24
24
  className?: string;
25
25
  /** Accessible label */
@@ -6,11 +6,12 @@
6
6
  * a refresh event via the event bus when the threshold is met.
7
7
  */
8
8
  import React from 'react';
9
+ import type { EventKey, EventPayload } from "@almadar/core";
9
10
  export interface PullToRefreshProps {
10
11
  /** Event name to emit on refresh (emitted as UI:{refreshEvent}) */
11
- refreshEvent: string;
12
+ refreshEvent: EventKey;
12
13
  /** Payload to include with the refresh event */
13
- refreshPayload?: Record<string, unknown>;
14
+ refreshPayload?: EventPayload;
14
15
  /** Pull distance threshold to trigger refresh in px (default: 60) */
15
16
  threshold?: number;
16
17
  /** Content to wrap */
@@ -6,12 +6,13 @@
6
6
  * Shows a drop indicator line at the target position during drag.
7
7
  */
8
8
  import React from 'react';
9
- export interface SortableListProps<T = Record<string, unknown>> {
9
+ import type { EventKey, EventPayload, EventPayloadValue } from "@almadar/core";
10
+ export interface SortableListProps<T extends EventPayloadValue = EventPayload> {
10
11
  items: T[];
11
12
  renderItem: (item: T, index: number) => React.ReactNode;
12
- reorderEvent: string;
13
- reorderPayload?: Record<string, unknown>;
13
+ reorderEvent: EventKey;
14
+ reorderPayload?: EventPayload;
14
15
  dragHandlePosition?: 'left' | 'right';
15
16
  className?: string;
16
17
  }
17
- export declare const SortableList: <T = Record<string, unknown>>(props: SortableListProps<T>) => React.ReactElement;
18
+ export declare const SortableList: <T extends EventPayloadValue = EventPayload>(props: SortableListProps<T>) => React.ReactElement;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { EventKey } from "@almadar/core";
2
+ import type { EventKey, EventPayload } from "@almadar/core";
3
3
  export type StarRatingSize = "sm" | "md" | "lg";
4
4
  export type StarRatingPrecision = "full" | "half";
5
5
  export interface StarRatingProps {
@@ -16,7 +16,7 @@ export interface StarRatingProps {
16
16
  /** Declarative event name for rating changes */
17
17
  action?: EventKey;
18
18
  /** Payload to include with the action event */
19
- actionPayload?: Record<string, unknown>;
19
+ actionPayload?: EventPayload;
20
20
  /** Direct onChange callback */
21
21
  onChange?: (value: number) => void;
22
22
  /** Additional CSS classes */
@@ -6,20 +6,20 @@
6
6
  * Uses useSwipeGesture for gesture detection and useEventBus for event emission.
7
7
  */
8
8
  import React from 'react';
9
- import type { EventKey } from "@almadar/core";
9
+ import type { EventKey, EventPayload } from "@almadar/core";
10
10
  export interface SwipeAction {
11
11
  label: string;
12
12
  icon?: string;
13
13
  variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
14
14
  event: EventKey;
15
- eventPayload?: Record<string, unknown>;
15
+ eventPayload?: EventPayload;
16
16
  }
17
17
  export interface SwipeableRowProps {
18
18
  leftActions?: SwipeAction[];
19
19
  rightActions?: SwipeAction[];
20
20
  threshold?: number;
21
21
  children: React.ReactNode;
22
- itemData?: Record<string, unknown>;
22
+ itemData?: EventPayload;
23
23
  className?: string;
24
24
  }
25
25
  export declare const SwipeableRow: React.FC<SwipeableRowProps>;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { EventKey } from "@almadar/core";
2
+ import type { EventKey, EventPayload } from "@almadar/core";
3
3
  export interface UploadDropZoneProps {
4
4
  /** Accepted MIME types (e.g., "image/*", "application/pdf") */
5
5
  accept?: string;
@@ -18,7 +18,7 @@ export interface UploadDropZoneProps {
18
18
  /** Declarative event name for file selection */
19
19
  action?: EventKey;
20
20
  /** Payload to include with the action event */
21
- actionPayload?: Record<string, unknown>;
21
+ actionPayload?: EventPayload;
22
22
  /** Direct onFiles callback */
23
23
  onFiles?: (files: File[]) => void;
24
24
  /** Additional CSS classes */
@@ -12,12 +12,13 @@
12
12
  * concern analogous to Form's `formData`.
13
13
  */
14
14
  import React from 'react';
15
- export interface DialogueChoice {
15
+ import type { EventPayload } from '@almadar/core';
16
+ export type DialogueChoice = EventPayload & {
16
17
  text: string;
17
18
  action?: string;
18
19
  next?: string;
19
20
  disabled?: boolean;
20
- }
21
+ };
21
22
  export interface DialogueNode {
22
23
  id?: string;
23
24
  speaker: string;
@@ -1,6 +1,6 @@
1
- import type { EventKey } from "@almadar/core";
1
+ import type { EventKey, EventPayload } from "@almadar/core";
2
2
  import { type EventBusContextType } from "../../../hooks/useEventBus";
3
- export interface MenuOption {
3
+ export type MenuOption = EventPayload & {
4
4
  /** Optional ID (generated from index if not provided) */
5
5
  id?: string;
6
6
  /** Display label */
@@ -17,7 +17,7 @@ export interface MenuOption {
17
17
  subLabel?: string;
18
18
  /** Action identifier (alternative to event) */
19
19
  action?: EventKey;
20
- }
20
+ };
21
21
  export interface GameMenuProps {
22
22
  /** Menu title */
23
23
  title: string;
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import type { EventPayload } from "@almadar/core";
2
3
  import { type EventBusContextType } from "../../../hooks/useEventBus";
3
4
  export interface GameOverStat {
4
5
  /** Stat label */
@@ -16,7 +17,7 @@ export interface GameOverStat {
16
17
  /** Icon */
17
18
  icon?: React.ReactNode;
18
19
  }
19
- export interface GameOverAction {
20
+ export type GameOverAction = EventPayload & {
20
21
  /** Display label */
21
22
  label: string;
22
23
  /** Event to emit on click */
@@ -25,7 +26,7 @@ export interface GameOverAction {
25
26
  navigatesTo?: string;
26
27
  /** Button variant */
27
28
  variant?: "primary" | "secondary" | "ghost";
28
- }
29
+ };
29
30
  export interface GameOverScreenProps {
30
31
  /** Screen title (e.g., "Game Over", "Victory!") */
31
32
  title: string;