@almadar/ui 4.24.0 → 4.26.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.
@@ -19,7 +19,7 @@
19
19
  * @packageDocumentation
20
20
  */
21
21
  import React from 'react';
22
- import { type UISlotManager, type UISlot, type SlotContent, type RenderUIConfig, type SlotAnimation, type SlotChangeCallback } from '../hooks/useUISlots';
22
+ import { type UISlotManager, type UISlot, type SlotContent, type SlotProps, type SlotPropValue, type SlotCallback, type RenderUIConfig, type SlotAnimation, type SlotChangeCallback } from '../hooks/useUISlots';
23
23
  /**
24
24
  * Context for the UI Slot Manager
25
25
  */
@@ -72,4 +72,4 @@ export declare function useSlotContent(slot: UISlot): SlotContent | null;
72
72
  * Hook to check if a slot has content.
73
73
  */
74
74
  export declare function useSlotHasContent(slot: UISlot): boolean;
75
- export { UISlotContext, type UISlotManager, type UISlot, type SlotContent, type RenderUIConfig, type SlotAnimation, type SlotChangeCallback, };
75
+ export { UISlotContext, type UISlotManager, type UISlot, type SlotContent, type SlotProps, type SlotPropValue, type SlotCallback, type RenderUIConfig, type SlotAnimation, type SlotChangeCallback, };
@@ -1,4 +1,36 @@
1
- import type { EventPayload } from '@almadar/core';
1
+ /**
2
+ * useUISlots Hook
3
+ *
4
+ * Core hook for managing UI slot rendering in the trait-driven architecture.
5
+ * Traits use render_ui effects to dynamically render content into slots.
6
+ *
7
+ * Slots:
8
+ * - main: Primary content area
9
+ * - sidebar: Left/right sidebar
10
+ * - modal: Modal overlay
11
+ * - drawer: Slide-in drawer
12
+ * - overlay: Full-screen overlay
13
+ * - center: Centered popup
14
+ * - toast: Toast notifications
15
+ * - hud-top: Game HUD top bar
16
+ * - hud-bottom: Game HUD bottom bar
17
+ * - floating: Draggable floating panel
18
+ *
19
+ * Multi-source model (2026-04-24):
20
+ * A slot can receive renders from multiple source traits across independent
21
+ * batches (e.g. in the playground, ProbeCreate renders "main" on INIT, then
22
+ * later ProbePersistor cascades a render into "main" too). Prior code stored
23
+ * a single SlotContent per slot and last-writer-wins silently dropped
24
+ * earlier traits' frames. Internally the manager now holds a
25
+ * `Record<UISlot, Record<sourceKey, SlotContent>>` map and consumers see an
26
+ * aggregated view: a single SlotContent for single-source slots, or a
27
+ * synthetic `stack` wrapper when 2+ sources are active simultaneously.
28
+ * This mirrors the compiled-path page layout's VStack-of-trait-views.
29
+ *
30
+ * @packageDocumentation
31
+ */
32
+ import type React from 'react';
33
+ import type { EventPayloadValue, RenderItemLambda } from '@almadar/core';
2
34
  /**
3
35
  * Valid UI slot names
4
36
  */
@@ -8,13 +40,39 @@ export type UISlot = 'main' | 'sidebar' | 'modal' | 'drawer' | 'overlay' | 'cent
8
40
  */
9
41
  export type SlotAnimation = 'fade' | 'slide' | 'scale' | 'none';
10
42
  /**
11
- * Pattern-specific props carried by a rendered slot. Pattern authors decide
12
- * the concrete shape; the slot manager treats this as an opaque record of
13
- * field-like values sourced from the event-bus payload vocabulary so the
14
- * same types round-trip through render-ui useUISlots UISlotRenderer
15
- * without a private re-coercion boundary.
43
+ * Render-prop callback after fn-form-lambda conversion or
44
+ * `wrapCallbackForEvent` wrapping. Pattern components consume these as
45
+ * `renderItem` / `onTabChange` / `onClick` / etc. The arg list is
46
+ * contravariant (`never[]` accepts any caller shape event handlers,
47
+ * 2-arg `(item, index)` render-props, etc.); the return is the union of
48
+ * shapes seen at this layer. Pattern-level prop types narrow the
49
+ * signature for each consumer downstream.
50
+ */
51
+ export type SlotCallback = (...args: never[]) => void | React.ReactNode | EventPayloadValue;
52
+ /**
53
+ * Render-ui prop value: any leaf flowing from a `(render-ui slot {...})`
54
+ * effect into a React pattern component. The union enumerates every
55
+ * shape the renderer can receive — no `unknown` escape hatch.
56
+ *
57
+ * - JSON primitives (`string`, `number`, `boolean`, `Date`, `null`,
58
+ * `undefined`) come through `BindingResolver`.
59
+ * - `RenderItemLambda` is the unconverted tuple form `["fn", arg, body]`;
60
+ * `SlotCallback` is the post-conversion callable form.
61
+ * - `React.ReactNode` covers substituted `<TraitFrame>` elements.
62
+ * - The recursive array + object branches mirror the `EventPayloadValue`
63
+ * shape but with `SlotPropValue` leaves so functions and React nodes
64
+ * can appear at any depth (e.g. `tabs[].content: "@trait.X"` surviving
65
+ * substitution into a `ReactElement`).
66
+ */
67
+ export type SlotPropValue = string | number | boolean | Date | null | undefined | RenderItemLambda | SlotCallback | React.ReactElement | ReadonlyArray<SlotPropValue> | {
68
+ readonly [key: string]: SlotPropValue;
69
+ };
70
+ /**
71
+ * Pattern-specific props carried by a rendered slot. The slot manager
72
+ * routes these from `(render-ui slot {...})` effects to React pattern
73
+ * components without coercion.
16
74
  */
17
- export type SlotProps = Record<string, EventPayload[string] | unknown>;
75
+ export type SlotProps = Record<string, SlotPropValue>;
18
76
  /**
19
77
  * Content rendered in a slot
20
78
  */