@almadar/ui 5.12.1 → 5.13.2

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.
@@ -21491,6 +21491,7 @@ function CalendarGrid({
21491
21491
  swipeRightEvent,
21492
21492
  dayWindow = "auto"
21493
21493
  }) {
21494
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
21494
21495
  const eventBus = useEventBus();
21495
21496
  const longPressTimer = React98.useRef(null);
21496
21497
  const resolvedWeekStart = React98.useMemo(
@@ -21539,7 +21540,7 @@ function CalendarGrid({
21539
21540
  [onEventClick]
21540
21541
  );
21541
21542
  const eventsForDayCount = React98.useCallback(
21542
- (day) => events2.filter(
21543
+ (day) => evs.filter(
21543
21544
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
21544
21545
  ).length,
21545
21546
  [events2]
@@ -21654,7 +21655,7 @@ function CalendarGrid({
21654
21655
  }
21655
21656
  ) }),
21656
21657
  visibleDays.map((day) => {
21657
- const slotEvents = events2.filter(
21658
+ const slotEvents = evs.filter(
21658
21659
  (ev) => eventInSlot(ev, day, time)
21659
21660
  );
21660
21661
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -33879,7 +33880,7 @@ function useSafeEventBus10() {
33879
33880
  }
33880
33881
  }
33881
33882
  function SortableListInner({
33882
- items: initialItems = EMPTY_ITEMS,
33883
+ items: initialItemsProp = EMPTY_ITEMS,
33883
33884
  renderItem,
33884
33885
  reorderEvent,
33885
33886
  reorderPayload,
@@ -33887,6 +33888,7 @@ function SortableListInner({
33887
33888
  className
33888
33889
  }) {
33889
33890
  const eventBus = useSafeEventBus10();
33891
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
33890
33892
  const handleReorder = React98.useCallback(
33891
33893
  (fromIndex, toIndex, item) => {
33892
33894
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -37383,9 +37385,10 @@ var init_ReplyTree = __esm({
37383
37385
  showActions = true,
37384
37386
  className
37385
37387
  }) => {
37388
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
37386
37389
  const [collapsedSet, setCollapsedSet] = React98.useState(() => {
37387
37390
  const acc = /* @__PURE__ */ new Set();
37388
- collectInitiallyCollapsed(nodes, acc);
37391
+ collectInitiallyCollapsed(nodeList, acc);
37389
37392
  return acc;
37390
37393
  });
37391
37394
  const toggleCollapse = React98.useCallback((id) => {
@@ -37399,10 +37402,10 @@ var init_ReplyTree = __esm({
37399
37402
  return next;
37400
37403
  });
37401
37404
  }, []);
37402
- if (nodes.length === 0) {
37405
+ if (nodeList.length === 0) {
37403
37406
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
37404
37407
  }
37405
- return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
37408
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
37406
37409
  ReplyTreeNode,
37407
37410
  {
37408
37411
  node,
package/dist/avl/index.js CHANGED
@@ -21442,6 +21442,7 @@ function CalendarGrid({
21442
21442
  swipeRightEvent,
21443
21443
  dayWindow = "auto"
21444
21444
  }) {
21445
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
21445
21446
  const eventBus = useEventBus();
21446
21447
  const longPressTimer = useRef(null);
21447
21448
  const resolvedWeekStart = useMemo(
@@ -21490,7 +21491,7 @@ function CalendarGrid({
21490
21491
  [onEventClick]
21491
21492
  );
21492
21493
  const eventsForDayCount = useCallback(
21493
- (day) => events2.filter(
21494
+ (day) => evs.filter(
21494
21495
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
21495
21496
  ).length,
21496
21497
  [events2]
@@ -21605,7 +21606,7 @@ function CalendarGrid({
21605
21606
  }
21606
21607
  ) }),
21607
21608
  visibleDays.map((day) => {
21608
- const slotEvents = events2.filter(
21609
+ const slotEvents = evs.filter(
21609
21610
  (ev) => eventInSlot(ev, day, time)
21610
21611
  );
21611
21612
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -33830,7 +33831,7 @@ function useSafeEventBus10() {
33830
33831
  }
33831
33832
  }
33832
33833
  function SortableListInner({
33833
- items: initialItems = EMPTY_ITEMS,
33834
+ items: initialItemsProp = EMPTY_ITEMS,
33834
33835
  renderItem,
33835
33836
  reorderEvent,
33836
33837
  reorderPayload,
@@ -33838,6 +33839,7 @@ function SortableListInner({
33838
33839
  className
33839
33840
  }) {
33840
33841
  const eventBus = useSafeEventBus10();
33842
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
33841
33843
  const handleReorder = useCallback(
33842
33844
  (fromIndex, toIndex, item) => {
33843
33845
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -37334,9 +37336,10 @@ var init_ReplyTree = __esm({
37334
37336
  showActions = true,
37335
37337
  className
37336
37338
  }) => {
37339
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
37337
37340
  const [collapsedSet, setCollapsedSet] = useState(() => {
37338
37341
  const acc = /* @__PURE__ */ new Set();
37339
- collectInitiallyCollapsed(nodes, acc);
37342
+ collectInitiallyCollapsed(nodeList, acc);
37340
37343
  return acc;
37341
37344
  });
37342
37345
  const toggleCollapse = useCallback((id) => {
@@ -37350,10 +37353,10 @@ var init_ReplyTree = __esm({
37350
37353
  return next;
37351
37354
  });
37352
37355
  }, []);
37353
- if (nodes.length === 0) {
37356
+ if (nodeList.length === 0) {
37354
37357
  return /* @__PURE__ */ jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
37355
37358
  }
37356
- return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsx(
37359
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsx(
37357
37360
  ReplyTreeNode,
37358
37361
  {
37359
37362
  node,
@@ -34,4 +34,4 @@ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElem
34
34
  /** onChange handler - accepts events from input, select, or textarea */
35
35
  onChange?: React.ChangeEventHandler<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>;
36
36
  }
37
- export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>>;
37
+ export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLSelectElement | HTMLInputElement | HTMLTextAreaElement>>;
@@ -16427,6 +16427,7 @@ function CalendarGrid({
16427
16427
  swipeRightEvent,
16428
16428
  dayWindow = "auto"
16429
16429
  }) {
16430
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
16430
16431
  const eventBus = useEventBus();
16431
16432
  const longPressTimer = React80.useRef(null);
16432
16433
  const resolvedWeekStart = React80.useMemo(
@@ -16475,7 +16476,7 @@ function CalendarGrid({
16475
16476
  [onEventClick]
16476
16477
  );
16477
16478
  const eventsForDayCount = React80.useCallback(
16478
- (day) => events2.filter(
16479
+ (day) => evs.filter(
16479
16480
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
16480
16481
  ).length,
16481
16482
  [events2]
@@ -16590,7 +16591,7 @@ function CalendarGrid({
16590
16591
  }
16591
16592
  ) }),
16592
16593
  visibleDays.map((day) => {
16593
- const slotEvents = events2.filter(
16594
+ const slotEvents = evs.filter(
16594
16595
  (ev) => eventInSlot(ev, day, time)
16595
16596
  );
16596
16597
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -29338,7 +29339,7 @@ function useSafeEventBus10() {
29338
29339
  }
29339
29340
  }
29340
29341
  function SortableListInner({
29341
- items: initialItems = EMPTY_ITEMS,
29342
+ items: initialItemsProp = EMPTY_ITEMS,
29342
29343
  renderItem,
29343
29344
  reorderEvent,
29344
29345
  reorderPayload,
@@ -29346,6 +29347,7 @@ function SortableListInner({
29346
29347
  className
29347
29348
  }) {
29348
29349
  const eventBus = useSafeEventBus10();
29350
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
29349
29351
  const handleReorder = React80.useCallback(
29350
29352
  (fromIndex, toIndex, item) => {
29351
29353
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -32842,9 +32844,10 @@ var init_ReplyTree = __esm({
32842
32844
  showActions = true,
32843
32845
  className
32844
32846
  }) => {
32847
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
32845
32848
  const [collapsedSet, setCollapsedSet] = React80.useState(() => {
32846
32849
  const acc = /* @__PURE__ */ new Set();
32847
- collectInitiallyCollapsed(nodes, acc);
32850
+ collectInitiallyCollapsed(nodeList, acc);
32848
32851
  return acc;
32849
32852
  });
32850
32853
  const toggleCollapse = React80.useCallback((id) => {
@@ -32858,10 +32861,10 @@ var init_ReplyTree = __esm({
32858
32861
  return next;
32859
32862
  });
32860
32863
  }, []);
32861
- if (nodes.length === 0) {
32864
+ if (nodeList.length === 0) {
32862
32865
  return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
32863
32866
  }
32864
- return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
32867
+ return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
32865
32868
  ReplyTreeNode,
32866
32869
  {
32867
32870
  node,
@@ -16378,6 +16378,7 @@ function CalendarGrid({
16378
16378
  swipeRightEvent,
16379
16379
  dayWindow = "auto"
16380
16380
  }) {
16381
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
16381
16382
  const eventBus = useEventBus();
16382
16383
  const longPressTimer = useRef(null);
16383
16384
  const resolvedWeekStart = useMemo(
@@ -16426,7 +16427,7 @@ function CalendarGrid({
16426
16427
  [onEventClick]
16427
16428
  );
16428
16429
  const eventsForDayCount = useCallback(
16429
- (day) => events2.filter(
16430
+ (day) => evs.filter(
16430
16431
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
16431
16432
  ).length,
16432
16433
  [events2]
@@ -16541,7 +16542,7 @@ function CalendarGrid({
16541
16542
  }
16542
16543
  ) }),
16543
16544
  visibleDays.map((day) => {
16544
- const slotEvents = events2.filter(
16545
+ const slotEvents = evs.filter(
16545
16546
  (ev) => eventInSlot(ev, day, time)
16546
16547
  );
16547
16548
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -29289,7 +29290,7 @@ function useSafeEventBus10() {
29289
29290
  }
29290
29291
  }
29291
29292
  function SortableListInner({
29292
- items: initialItems = EMPTY_ITEMS,
29293
+ items: initialItemsProp = EMPTY_ITEMS,
29293
29294
  renderItem,
29294
29295
  reorderEvent,
29295
29296
  reorderPayload,
@@ -29297,6 +29298,7 @@ function SortableListInner({
29297
29298
  className
29298
29299
  }) {
29299
29300
  const eventBus = useSafeEventBus10();
29301
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
29300
29302
  const handleReorder = useCallback(
29301
29303
  (fromIndex, toIndex, item) => {
29302
29304
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -32793,9 +32795,10 @@ var init_ReplyTree = __esm({
32793
32795
  showActions = true,
32794
32796
  className
32795
32797
  }) => {
32798
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
32796
32799
  const [collapsedSet, setCollapsedSet] = useState(() => {
32797
32800
  const acc = /* @__PURE__ */ new Set();
32798
- collectInitiallyCollapsed(nodes, acc);
32801
+ collectInitiallyCollapsed(nodeList, acc);
32799
32802
  return acc;
32800
32803
  });
32801
32804
  const toggleCollapse = useCallback((id) => {
@@ -32809,10 +32812,10 @@ var init_ReplyTree = __esm({
32809
32812
  return next;
32810
32813
  });
32811
32814
  }, []);
32812
- if (nodes.length === 0) {
32815
+ if (nodeList.length === 0) {
32813
32816
  return /* @__PURE__ */ jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
32814
32817
  }
32815
- return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsx(
32818
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsx(
32816
32819
  ReplyTreeNode,
32817
32820
  {
32818
32821
  node,
@@ -6,7 +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 { EventEmit, EventPayload } from "@almadar/core";
9
+ import type { EventEmit, EventPayload, EntityCollection } from "@almadar/core";
10
10
  export interface CalendarEvent {
11
11
  id: string;
12
12
  title: string;
@@ -26,7 +26,7 @@ export interface CalendarGridProps {
26
26
  /** Time slot labels (defaults to 09:00-17:00) */
27
27
  timeSlots?: string[];
28
28
  /** Events to display on the grid */
29
- events?: CalendarEvent[];
29
+ events?: EntityCollection<CalendarEvent>;
30
30
  /** Called when a time slot is clicked */
31
31
  onSlotClick?: (day: Date, time: string) => void;
32
32
  /** Called when a day header is clicked */
@@ -11,7 +11,7 @@
11
11
  * Uses atoms only internally: Box, VStack, HStack, Typography, Badge, Button, Icon.
12
12
  */
13
13
  import React from 'react';
14
- import type { EntityRow, EventKey } from '@almadar/core';
14
+ import type { EntityRow, EventKey, EntityCollection } from '@almadar/core';
15
15
  import { type DataDndProps } from './useDataDnd';
16
16
  export interface DataGridField {
17
17
  /** Entity field name (dot-notation supported) */
@@ -54,8 +54,14 @@ export interface DataGridProps<T extends EntityRow = EntityRow> extends DataDndP
54
54
  * without widening. The generic `T` lets consumers pass a narrower
55
55
  * entity (e.g. `CartItem`) and have the `children` render function
56
56
  * receive cards typed to that exact shape.
57
+ *
58
+ * Declared as the pattern's data INLET via `EntityCollection<T>` (the inlet
59
+ * half of the circuit, symmetric with the `EventKey` outlet props below):
60
+ * pattern-sync tags it `kind:"entity", cardinality:"collection"` so consumers
61
+ * bind the domain entity without name-matching the prop. Structurally still
62
+ * `T | readonly T[]` — see the brand's doc.
57
63
  */
58
- entity: T | readonly T[];
64
+ entity: EntityCollection<T>;
59
65
  /**
60
66
  * Field definitions for rendering each card. The pattern contract in
61
67
  * `@almadar/patterns` documents `columns` as the wire-format alias the
@@ -11,7 +11,7 @@
11
11
  * Uses atoms only internally: Box, VStack, HStack, Typography, Badge, Button, Icon.
12
12
  */
13
13
  import React from 'react';
14
- import type { EntityRow, EventKey } from "@almadar/core";
14
+ import type { EntityRow, EntityCollection, EventKey } from "@almadar/core";
15
15
  import { type DataDndProps } from './useDataDnd';
16
16
  export interface DataListField {
17
17
  /** Entity field name (dot-notation supported) */
@@ -45,7 +45,7 @@ export interface DataListProps<T extends EntityRow = EntityRow> extends DataDndP
45
45
  * entity (e.g. `CartItem`) and have the `children` render function
46
46
  * receive items of that exact shape.
47
47
  */
48
- entity: T | readonly T[];
48
+ entity: EntityCollection<T>;
49
49
  /**
50
50
  * Field definitions for rendering each row. The pattern contract in
51
51
  * `@almadar/patterns` documents `columns` as the wire-format alias the
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { EventEmit, EventPayloadValue } from "@almadar/core";
2
+ import type { EventEmit, EntityCollection } from "@almadar/core";
3
3
  export type CanvasItemStatus = 'empty' | 'seated' | 'ordered' | 'awaiting-bill' | 'cleaning';
4
4
  export type CanvasItemShape = 'round' | 'rectangle' | 'square';
5
5
  export interface CanvasItem {
@@ -20,7 +20,7 @@ export interface PositionedCanvasProps {
20
20
  * molecule narrows non-array values to `[]` and validates element shape at
21
21
  * render time via the `id` / `x` / `y` guards.
22
22
  */
23
- items: readonly CanvasItem[] | EventPayloadValue;
23
+ items: EntityCollection<CanvasItem>;
24
24
  width?: number;
25
25
  height?: number;
26
26
  selectedId?: string | null;
@@ -5,7 +5,7 @@
5
5
  * Composes the VoteStack molecule + Avatar/Typography/Button atoms.
6
6
  */
7
7
  import React from "react";
8
- import type { EventEmit } from "@almadar/core";
8
+ import type { EventEmit, EntityCollection } from "@almadar/core";
9
9
  import { type VoteValue } from "../molecules/VoteStack";
10
10
  export interface ReplyNode {
11
11
  id: string;
@@ -19,7 +19,7 @@ export interface ReplyNode {
19
19
  collapsed?: boolean;
20
20
  }
21
21
  export interface ReplyTreeProps {
22
- nodes: ReplyNode[];
22
+ nodes: EntityCollection<ReplyNode>;
23
23
  maxDepth?: number;
24
24
  onVote?: (nodeId: string, vote: VoteValue) => void;
25
25
  onReply?: (parentNodeId: string) => void;
@@ -6,9 +6,9 @@
6
6
  * Shows a drop indicator line at the target position during drag.
7
7
  */
8
8
  import React from 'react';
9
- import type { EventKey, EventPayload, EventPayloadValue } from "@almadar/core";
9
+ import type { EntityCollection, EventKey, EventPayload, EventPayloadValue } from "@almadar/core";
10
10
  export interface SortableListProps<T extends EventPayloadValue = EventPayload> {
11
- items: T[];
11
+ items: EntityCollection<T>;
12
12
  renderItem: (item: T, index: number) => React.ReactNode;
13
13
  reorderEvent: EventKey;
14
14
  reorderPayload?: EventPayload;
@@ -12,7 +12,7 @@
12
12
  * Icon, Checkbox, Divider.
13
13
  */
14
14
  import React from 'react';
15
- import type { EntityRow, EventKey } from '@almadar/core';
15
+ import type { EntityRow, EventKey, EntityCollection } from '@almadar/core';
16
16
  import { type DataDndProps } from './useDataDnd';
17
17
  export interface TableViewColumn {
18
18
  /** Stable column key (React key + default value lookup). */
@@ -52,7 +52,7 @@ export interface TableViewItemAction {
52
52
  }
53
53
  export interface TableViewProps<T extends EntityRow = EntityRow> extends DataDndProps {
54
54
  /** Schema entity data — single record or collection. */
55
- entity: T | readonly T[];
55
+ entity: EntityCollection<T>;
56
56
  /** Column definitions. The compiler emits `columns`; `fields` is the alias. */
57
57
  columns?: readonly TableViewColumn[];
58
58
  /** Alias for `columns`. */
@@ -7,6 +7,7 @@
7
7
  * See EntityDisplayProps in ./types.ts for base prop contract.
8
8
  */
9
9
  import React from "react";
10
+ import type { EntityRecord, EntityRow } from "@almadar/core";
10
11
  import type { LucideIcon } from "lucide-react";
11
12
  import type { EntityDisplayProps } from "./types";
12
13
  export interface DetailField {
@@ -44,6 +45,8 @@ export type FieldDef = string | {
44
45
  type: string;
45
46
  };
46
47
  export interface DetailPanelProps extends EntityDisplayProps {
48
+ /** RECORD-cardinality override: renders ONE record (see body collapse below). */
49
+ entity?: EntityRecord<EntityRow>;
47
50
  title?: string;
48
51
  subtitle?: string;
49
52
  status?: {
@@ -10,9 +10,11 @@
10
10
  * - Never listens to events
11
11
  */
12
12
  import React from 'react';
13
+ import type { EntityRecord } from '@almadar/core';
13
14
  import type { EntityDisplayProps } from './types';
14
15
  import type { HeroEntity } from './marketing-types';
15
16
  export interface HeroOrganismProps extends EntityDisplayProps<HeroEntity> {
17
+ entity?: EntityRecord<HeroEntity>;
16
18
  children?: React.ReactNode;
17
19
  }
18
20
  export declare const HeroOrganism: React.FC<HeroOrganismProps>;
@@ -12,7 +12,7 @@
12
12
  */
13
13
  import React from "react";
14
14
  import type { EventKey } from "@almadar/core";
15
- import type { EntityRow } from "@almadar/core";
15
+ import type { EntityCollection, EntityRow } from "@almadar/core";
16
16
  import type { LucideIcon } from "lucide-react";
17
17
  export type TimelineItemStatus = "complete" | "active" | "pending" | "error";
18
18
  /**
@@ -55,7 +55,7 @@ export interface TimelineProps {
55
55
  * TimelineItem fields (`icon`, callbacks) cannot round-trip through the
56
56
  * event bus, so decorative stories that need them pass `items` directly.
57
57
  */
58
- entity?: EntityRow | readonly EntityRow[];
58
+ entity?: EntityCollection<EntityRow>;
59
59
  /** Timeline title */
60
60
  title?: string;
61
61
  /** Timeline items */
@@ -17,9 +17,12 @@
17
17
  * - Listens: UI:BOOK_START, UI:BOOK_NAVIGATE, UI:BOOK_PAGE_PREV/NEXT, UI:BOOK_PRINT, UI:BOOK_SHOW_TOC
18
18
  */
19
19
  import React from 'react';
20
+ import type { EntityRecord, EntityRow } from '@almadar/core';
20
21
  import type { EntityDisplayProps } from '../types';
21
22
  import type { BookFieldMap } from './types';
22
23
  export interface BookViewerProps extends EntityDisplayProps {
24
+ /** Renders ONE record (the book), not a collection */
25
+ entity?: EntityRecord<EntityRow>;
23
26
  /** Initial page index (default: 0 = cover) */
24
27
  initialPage?: number;
25
28
  /** Field name translation map — a BookFieldMap object or locale key ("ar") */
@@ -7,7 +7,7 @@
7
7
  * Exception: Form manages local `formData` state for field input tracking.
8
8
  * This is the ONE allowed exception — documented here.
9
9
  */
10
- import type { EntityRow } from '@almadar/core';
10
+ import type { EntityRow, EntityInlet } from '@almadar/core';
11
11
  export declare const EntityDisplayEvents: {
12
12
  readonly SORT: "SORT";
13
13
  readonly PAGINATE: "PAGINATE";
@@ -61,7 +61,7 @@ export interface EntityDisplayProps<T extends EntityRow = EntityRow> {
61
61
  * extend `EntityRow`. They surface `EntityDisplayProps<T>` constraint errors.
62
62
  * Tracked as a Phase 7 follow-up in `docs/Almadar_Entity_V2_Plan.md` §10.
63
63
  */
64
- entity?: T | readonly T[];
64
+ entity?: EntityInlet<T>;
65
65
  /** Additional CSS classes */
66
66
  className?: string;
67
67
  /** Loading state indicator */
@@ -318,7 +318,7 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "
318
318
  /** onChange handler - accepts events from input, select, or textarea */
319
319
  onChange?: React.ChangeEventHandler<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>;
320
320
  }
321
- declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>>;
321
+ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLSelectElement | HTMLInputElement | HTMLTextAreaElement>>;
322
322
 
323
323
  /**
324
324
  * DocSidebar Molecule Component
@@ -17903,6 +17903,7 @@ function CalendarGrid({
17903
17903
  swipeRightEvent,
17904
17904
  dayWindow = "auto"
17905
17905
  }) {
17906
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
17906
17907
  const eventBus = useEventBus();
17907
17908
  const longPressTimer = React86.useRef(null);
17908
17909
  const resolvedWeekStart = React86.useMemo(
@@ -17951,7 +17952,7 @@ function CalendarGrid({
17951
17952
  [onEventClick]
17952
17953
  );
17953
17954
  const eventsForDayCount = React86.useCallback(
17954
- (day) => events2.filter(
17955
+ (day) => evs.filter(
17955
17956
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
17956
17957
  ).length,
17957
17958
  [events2]
@@ -18066,7 +18067,7 @@ function CalendarGrid({
18066
18067
  }
18067
18068
  ) }),
18068
18069
  visibleDays.map((day) => {
18069
- const slotEvents = events2.filter(
18070
+ const slotEvents = evs.filter(
18070
18071
  (ev) => eventInSlot(ev, day, time)
18071
18072
  );
18072
18073
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -30291,7 +30292,7 @@ function useSafeEventBus10() {
30291
30292
  }
30292
30293
  }
30293
30294
  function SortableListInner({
30294
- items: initialItems = EMPTY_ITEMS,
30295
+ items: initialItemsProp = EMPTY_ITEMS,
30295
30296
  renderItem,
30296
30297
  reorderEvent,
30297
30298
  reorderPayload,
@@ -30299,6 +30300,7 @@ function SortableListInner({
30299
30300
  className
30300
30301
  }) {
30301
30302
  const eventBus = useSafeEventBus10();
30303
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
30302
30304
  const handleReorder = React86.useCallback(
30303
30305
  (fromIndex, toIndex, item) => {
30304
30306
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -33795,9 +33797,10 @@ var init_ReplyTree = __esm({
33795
33797
  showActions = true,
33796
33798
  className
33797
33799
  }) => {
33800
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
33798
33801
  const [collapsedSet, setCollapsedSet] = React86.useState(() => {
33799
33802
  const acc = /* @__PURE__ */ new Set();
33800
- collectInitiallyCollapsed(nodes, acc);
33803
+ collectInitiallyCollapsed(nodeList, acc);
33801
33804
  return acc;
33802
33805
  });
33803
33806
  const toggleCollapse = React86.useCallback((id) => {
@@ -33811,10 +33814,10 @@ var init_ReplyTree = __esm({
33811
33814
  return next;
33812
33815
  });
33813
33816
  }, []);
33814
- if (nodes.length === 0) {
33817
+ if (nodeList.length === 0) {
33815
33818
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
33816
33819
  }
33817
- return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
33820
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
33818
33821
  ReplyTreeNode,
33819
33822
  {
33820
33823
  node,
@@ -17854,6 +17854,7 @@ function CalendarGrid({
17854
17854
  swipeRightEvent,
17855
17855
  dayWindow = "auto"
17856
17856
  }) {
17857
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
17857
17858
  const eventBus = useEventBus();
17858
17859
  const longPressTimer = useRef(null);
17859
17860
  const resolvedWeekStart = useMemo(
@@ -17902,7 +17903,7 @@ function CalendarGrid({
17902
17903
  [onEventClick]
17903
17904
  );
17904
17905
  const eventsForDayCount = useCallback(
17905
- (day) => events2.filter(
17906
+ (day) => evs.filter(
17906
17907
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
17907
17908
  ).length,
17908
17909
  [events2]
@@ -18017,7 +18018,7 @@ function CalendarGrid({
18017
18018
  }
18018
18019
  ) }),
18019
18020
  visibleDays.map((day) => {
18020
- const slotEvents = events2.filter(
18021
+ const slotEvents = evs.filter(
18021
18022
  (ev) => eventInSlot(ev, day, time)
18022
18023
  );
18023
18024
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -30242,7 +30243,7 @@ function useSafeEventBus10() {
30242
30243
  }
30243
30244
  }
30244
30245
  function SortableListInner({
30245
- items: initialItems = EMPTY_ITEMS,
30246
+ items: initialItemsProp = EMPTY_ITEMS,
30246
30247
  renderItem,
30247
30248
  reorderEvent,
30248
30249
  reorderPayload,
@@ -30250,6 +30251,7 @@ function SortableListInner({
30250
30251
  className
30251
30252
  }) {
30252
30253
  const eventBus = useSafeEventBus10();
30254
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
30253
30255
  const handleReorder = useCallback(
30254
30256
  (fromIndex, toIndex, item) => {
30255
30257
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -33746,9 +33748,10 @@ var init_ReplyTree = __esm({
33746
33748
  showActions = true,
33747
33749
  className
33748
33750
  }) => {
33751
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
33749
33752
  const [collapsedSet, setCollapsedSet] = useState(() => {
33750
33753
  const acc = /* @__PURE__ */ new Set();
33751
- collectInitiallyCollapsed(nodes, acc);
33754
+ collectInitiallyCollapsed(nodeList, acc);
33752
33755
  return acc;
33753
33756
  });
33754
33757
  const toggleCollapse = useCallback((id) => {
@@ -33762,10 +33765,10 @@ var init_ReplyTree = __esm({
33762
33765
  return next;
33763
33766
  });
33764
33767
  }, []);
33765
- if (nodes.length === 0) {
33768
+ if (nodeList.length === 0) {
33766
33769
  return /* @__PURE__ */ jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
33767
33770
  }
33768
- return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsx(
33771
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsx(
33769
33772
  ReplyTreeNode,
33770
33773
  {
33771
33774
  node,
@@ -17686,6 +17686,7 @@ function CalendarGrid({
17686
17686
  swipeRightEvent,
17687
17687
  dayWindow = "auto"
17688
17688
  }) {
17689
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
17689
17690
  const eventBus = useEventBus();
17690
17691
  const longPressTimer = React85.useRef(null);
17691
17692
  const resolvedWeekStart = React85.useMemo(
@@ -17734,7 +17735,7 @@ function CalendarGrid({
17734
17735
  [onEventClick]
17735
17736
  );
17736
17737
  const eventsForDayCount = React85.useCallback(
17737
- (day) => events2.filter(
17738
+ (day) => evs.filter(
17738
17739
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
17739
17740
  ).length,
17740
17741
  [events2]
@@ -17849,7 +17850,7 @@ function CalendarGrid({
17849
17850
  }
17850
17851
  ) }),
17851
17852
  visibleDays.map((day) => {
17852
- const slotEvents = events2.filter(
17853
+ const slotEvents = evs.filter(
17853
17854
  (ev) => eventInSlot(ev, day, time)
17854
17855
  );
17855
17856
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -29923,7 +29924,7 @@ function useSafeEventBus10() {
29923
29924
  }
29924
29925
  }
29925
29926
  function SortableListInner({
29926
- items: initialItems = EMPTY_ITEMS,
29927
+ items: initialItemsProp = EMPTY_ITEMS,
29927
29928
  renderItem,
29928
29929
  reorderEvent,
29929
29930
  reorderPayload,
@@ -29931,6 +29932,7 @@ function SortableListInner({
29931
29932
  className
29932
29933
  }) {
29933
29934
  const eventBus = useSafeEventBus10();
29935
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
29934
29936
  const handleReorder = React85.useCallback(
29935
29937
  (fromIndex, toIndex, item) => {
29936
29938
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -33362,9 +33364,10 @@ var init_ReplyTree = __esm({
33362
33364
  showActions = true,
33363
33365
  className
33364
33366
  }) => {
33367
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
33365
33368
  const [collapsedSet, setCollapsedSet] = React85.useState(() => {
33366
33369
  const acc = /* @__PURE__ */ new Set();
33367
- collectInitiallyCollapsed(nodes, acc);
33370
+ collectInitiallyCollapsed(nodeList, acc);
33368
33371
  return acc;
33369
33372
  });
33370
33373
  const toggleCollapse = React85.useCallback((id) => {
@@ -33378,10 +33381,10 @@ var init_ReplyTree = __esm({
33378
33381
  return next;
33379
33382
  });
33380
33383
  }, []);
33381
- if (nodes.length === 0) {
33384
+ if (nodeList.length === 0) {
33382
33385
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
33383
33386
  }
33384
- return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
33387
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
33385
33388
  ReplyTreeNode,
33386
33389
  {
33387
33390
  node,
@@ -17637,6 +17637,7 @@ function CalendarGrid({
17637
17637
  swipeRightEvent,
17638
17638
  dayWindow = "auto"
17639
17639
  }) {
17640
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
17640
17641
  const eventBus = useEventBus();
17641
17642
  const longPressTimer = useRef(null);
17642
17643
  const resolvedWeekStart = useMemo(
@@ -17685,7 +17686,7 @@ function CalendarGrid({
17685
17686
  [onEventClick]
17686
17687
  );
17687
17688
  const eventsForDayCount = useCallback(
17688
- (day) => events2.filter(
17689
+ (day) => evs.filter(
17689
17690
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
17690
17691
  ).length,
17691
17692
  [events2]
@@ -17800,7 +17801,7 @@ function CalendarGrid({
17800
17801
  }
17801
17802
  ) }),
17802
17803
  visibleDays.map((day) => {
17803
- const slotEvents = events2.filter(
17804
+ const slotEvents = evs.filter(
17804
17805
  (ev) => eventInSlot(ev, day, time)
17805
17806
  );
17806
17807
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -29874,7 +29875,7 @@ function useSafeEventBus10() {
29874
29875
  }
29875
29876
  }
29876
29877
  function SortableListInner({
29877
- items: initialItems = EMPTY_ITEMS,
29878
+ items: initialItemsProp = EMPTY_ITEMS,
29878
29879
  renderItem,
29879
29880
  reorderEvent,
29880
29881
  reorderPayload,
@@ -29882,6 +29883,7 @@ function SortableListInner({
29882
29883
  className
29883
29884
  }) {
29884
29885
  const eventBus = useSafeEventBus10();
29886
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
29885
29887
  const handleReorder = useCallback(
29886
29888
  (fromIndex, toIndex, item) => {
29887
29889
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -33313,9 +33315,10 @@ var init_ReplyTree = __esm({
33313
33315
  showActions = true,
33314
33316
  className
33315
33317
  }) => {
33318
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
33316
33319
  const [collapsedSet, setCollapsedSet] = useState(() => {
33317
33320
  const acc = /* @__PURE__ */ new Set();
33318
- collectInitiallyCollapsed(nodes, acc);
33321
+ collectInitiallyCollapsed(nodeList, acc);
33319
33322
  return acc;
33320
33323
  });
33321
33324
  const toggleCollapse = useCallback((id) => {
@@ -33329,10 +33332,10 @@ var init_ReplyTree = __esm({
33329
33332
  return next;
33330
33333
  });
33331
33334
  }, []);
33332
- if (nodes.length === 0) {
33335
+ if (nodeList.length === 0) {
33333
33336
  return /* @__PURE__ */ jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
33334
33337
  }
33335
- return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsx(
33338
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsx(
33336
33339
  ReplyTreeNode,
33337
33340
  {
33338
33341
  node,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.12.1",
3
+ "version": "5.13.2",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -129,10 +129,10 @@
129
129
  "typecheck": "tsc --noEmit"
130
130
  },
131
131
  "dependencies": {
132
- "@almadar/core": "^9.0.0",
132
+ "@almadar/core": ">=9.8.0",
133
133
  "@almadar/evaluator": ">=2.9.2",
134
134
  "@almadar/logger": "^1.3.0",
135
- "@almadar/patterns": "^2.26.0",
135
+ "@almadar/patterns": ">=2.35.0",
136
136
  "@almadar/runtime": "^6.7.0",
137
137
  "@almadar/std": ">=6.4.1",
138
138
  "@almadar/syntax": ">=1.3.1",
@@ -232,5 +232,8 @@
232
232
  "@types/react": "^19.0.0",
233
233
  "@types/react-dom": "^19.0.0"
234
234
  }
235
+ },
236
+ "overrides": {
237
+ "@almadar/core": "$@almadar/core"
235
238
  }
236
239
  }