@almadar/ui 2.11.7 → 2.12.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.
@@ -1,20 +1,20 @@
1
1
  import { DEFAULT_CONFIG, renderStateMachineToDomData, parseContentSegments, isDebugEnabled, onDebugToggle, subscribeToTickChanges, subscribeToGuardChanges, subscribeToDebugEvents, getEntitySnapshot, getDebugEvents, getGuardHistory, getAllTicks } from '../chunk-4ZBSL37D.js';
2
- import { useAuthContext } from '../chunk-3FENGM4Y.js';
3
- export { ENTITY_EVENTS, useAgentChat, useAuthContext, useCompile, useConnectGitHub, useCreateEntity, useDeepAgentGeneration, useDeleteEntity, useDisconnectGitHub, useEntities, useEntitiesByType, useEntity as useEntityById, useEntityMutations, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInput, useOrbitalHistory, useOrbitalMutations, usePhysics, usePinchZoom, usePlayer, usePreview, useResolvedEntity, useSelectedEntity, useSendOrbitalEvent, useSingletonEntity, useUIEvents, useUpdateEntity, useValidation } from '../chunk-3FENGM4Y.js';
2
+ import { useAuthContext } from '../chunk-GTIAVPI5.js';
3
+ export { ENTITY_EVENTS, useAgentChat, useAuthContext, useCompile, useConnectGitHub, useCreateEntity, useDeepAgentGeneration, useDeleteEntity, useDisconnectGitHub, useEntities, useEntitiesByType, useEntity as useEntityById, useEntityMutations, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInput, useOrbitalHistory, useOrbitalMutations, usePhysics, usePinchZoom, usePlayer, usePreview, useResolvedEntity, useSelectedEntity, useSendOrbitalEvent, useSingletonEntity, useUIEvents, useUpdateEntity, useValidation } from '../chunk-GTIAVPI5.js';
4
4
  export { clearEntities, getAllEntities, getByType, getEntity, getSingleton, removeEntity, spawnEntity, updateEntity, updateSingleton } from '../chunk-N7MVUW4R.js';
5
5
  import { subscribeToTraitChanges, getAllTraits } from '../chunk-42YQ6JVR.js';
6
6
  import '../chunk-3HJHHULT.js';
7
- import { VStack, HStack, Typography, Button, Icon, Box, Card, Avatar, Badge, SearchInput, Checkbox, Menu as Menu$1, Pagination, LoadingState, EmptyState, Modal, ErrorState, QuizBlock, CodeBlock, ScaledDiagram, MarkdownContent, Divider, ProgressBar, isoToScreen, IsometricCanvas_default, Stack, Select, Drawer, Toast, Tabs, Input, ThemeToggle, TILE_WIDTH, EntityDisplayEvents, StateIndicator, Accordion, ButtonGroup, Container } from '../chunk-4NAQLJ2M.js';
8
- export { ALL_PRESETS, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, Alert, AnimatedCounter, Avatar, Badge, Box, Breadcrumb, Button, ButtonGroup, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, Center, Chart, ChartLegend, Checkbox, ChoiceButton, CodeBlock, CombatLog, ComboCounter, ConditionalWrapper, ConfettiEffect, Container, ControlButton, CraftingRecipe, DIAMOND_TOP_Y, DPad, DamageNumber, DataGrid, DataList, DataTable, DateRangeSelector, DayCell, DetailPanel, DialogueBox, DialogueBubble, Divider, Drawer, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, FEATURE_COLORS, FLOOR_HEIGHT, FilterGroup, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormField, FormSectionHeader, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GraphView, Grid, HStack, Heading, HealthBar, HealthPanel, Icon, InfiniteScrollSentinel, Input, InputGroup, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, Label, LawReferenceTooltip, Lightbox, LineChart, LoadingState, MapView, MarkdownContent, MasterDetail, Menu, Meter, MiniMap, Modal, NumberStepper, Overlay, PageHeader, Pagination, PlatformerCanvas, Popover, PowerupSlots, ProgressBar, ProgressDots, PullToRefresh, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ResourceBar, ResourceCounter, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Select, SidePanel, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, Skeleton, SlotContentRenderer, SortableList, Spacer, Spinner, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateIndicator, StatusDot, StatusEffect, SwipeableRow, Switch, TILE_HEIGHT, TILE_WIDTH, Tabs, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, TimerDisplay, Toast, Tooltip, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UnitCommandBar, UploadDropZone, VStack, ViolationAlert, WaypointMarker, WizardNavigation, WizardProgress, XPBar, drawSprite, isoToScreen, pendulum, projectileMotion, screenToIso, springOscillator, useCamera, useImageCache } from '../chunk-4NAQLJ2M.js';
9
- import '../chunk-YLKXEXBP.js';
10
- import { useTranslate } from '../chunk-RUL35VPK.js';
11
- export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useDragReorder, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useInfiniteScroll, useLongPress, usePullToRefresh, useQuerySingleton, useSwipeGesture, useTranslate } from '../chunk-RUL35VPK.js';
7
+ import { VStack, HStack, Typography, Button, Icon, Box, Card, Avatar, Badge, SearchInput, Checkbox, Menu as Menu$1, Pagination, LoadingState, EmptyState, Modal, ErrorState, QuizBlock, CodeBlock, ScaledDiagram, MarkdownContent, Divider, ProgressBar, isoToScreen, IsometricCanvas_default, Stack, Select, Drawer, Toast, Tabs, Input, ThemeToggle, TILE_WIDTH, EntityDisplayEvents, StateIndicator, Accordion, ButtonGroup, Container } from '../chunk-JDISOWHE.js';
8
+ export { ALL_PRESETS, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, Alert, AnimatedCounter, Avatar, Badge, Box, Breadcrumb, Button, ButtonGroup, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, Center, Chart, ChartLegend, Checkbox, ChoiceButton, CodeBlock, CombatLog, ComboCounter, ConditionalWrapper, ConfettiEffect, Container, ControlButton, CraftingRecipe, DIAMOND_TOP_Y, DPad, DamageNumber, DataGrid, DataList, DataTable, DateRangeSelector, DayCell, DetailPanel, DialogueBox, DialogueBubble, Divider, Drawer, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, FEATURE_COLORS, FLOOR_HEIGHT, FilterGroup, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormField, FormSectionHeader, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GraphView, Grid, HStack, Heading, HealthBar, HealthPanel, Icon, InfiniteScrollSentinel, Input, InputGroup, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, Label, LawReferenceTooltip, Lightbox, LineChart, LoadingState, MapView, MarkdownContent, MasterDetail, Menu, Meter, MiniMap, Modal, NumberStepper, Overlay, PageHeader, Pagination, PlatformerCanvas, Popover, PowerupSlots, ProgressBar, ProgressDots, PullToRefresh, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ResourceBar, ResourceCounter, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Select, SidePanel, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, Skeleton, SlotContentRenderer, SortableList, Spacer, Spinner, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateIndicator, StatusDot, StatusEffect, SwipeableRow, Switch, TILE_HEIGHT, TILE_WIDTH, Tabs, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, TimerDisplay, Toast, Tooltip, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UnitCommandBar, UploadDropZone, VStack, ViolationAlert, WaypointMarker, WizardNavigation, WizardProgress, XPBar, drawSprite, isoToScreen, pendulum, projectileMotion, screenToIso, springOscillator, useCamera, useImageCache } from '../chunk-JDISOWHE.js';
9
+ import '../chunk-DKQN5FVU.js';
10
+ import { useTranslate } from '../chunk-WGJIL4YR.js';
11
+ export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useDragReorder, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useInfiniteScroll, useLongPress, usePullToRefresh, useQuerySingleton, useSwipeGesture, useTranslate } from '../chunk-WGJIL4YR.js';
12
12
  import { useEventBus, useEventListener } from '../chunk-YXZM3WCF.js';
13
13
  export { useEmitEvent, useEventBus, useEventListener } from '../chunk-YXZM3WCF.js';
14
14
  export { DEFAULT_SLOTS, useUISlotManager } from '../chunk-3JGAROCW.js';
15
- import '../chunk-TSETXL2E.js';
16
15
  import { cn, getNestedValue, subscribeToVerification, getSummary, getBridgeHealth, getTransitions, getAllChecks } from '../chunk-WCTZ7WZX.js';
17
16
  export { cn } from '../chunk-WCTZ7WZX.js';
17
+ import '../chunk-TSETXL2E.js';
18
18
  import '../chunk-K2D5D3WK.js';
19
19
  import { __publicField } from '../chunk-PKBMQBKP.js';
20
20
  import * as React44 from 'react';
@@ -1,5 +1,5 @@
1
- import { ThemeProvider, useTheme } from '../chunk-YLKXEXBP.js';
2
- export { BUILT_IN_THEMES, ThemeContext_default as ThemeContext, ThemeProvider, UISlotContext, UISlotProvider, useSlotContent, useSlotHasContent, useTheme, useUISlots } from '../chunk-YLKXEXBP.js';
1
+ import { ThemeProvider, useTheme } from '../chunk-DKQN5FVU.js';
2
+ export { BUILT_IN_THEMES, ThemeContext_default as ThemeContext, ThemeProvider, UISlotContext, UISlotProvider, useSlotContent, useSlotHasContent, useTheme, useUISlots } from '../chunk-DKQN5FVU.js';
3
3
  import '../chunk-3JGAROCW.js';
4
4
  import '../chunk-PKBMQBKP.js';
5
5
  import { createContext, useCallback, useMemo, useContext } from 'react';
@@ -7,6 +7,67 @@ import React__default, { ReactNode } from 'react';
7
7
  import * as _tanstack_react_query from '@tanstack/react-query';
8
8
  import { Entity, getEntity, getByType, getAllEntities, getSingleton, spawnEntity, updateEntity, updateSingleton, removeEntity, clearEntities } from '../stores/index.js';
9
9
 
10
+ declare global {
11
+ interface Window {
12
+ __kflowEventBus?: EventBusContextType | null;
13
+ }
14
+ }
15
+ /**
16
+ * Hook for accessing the event bus.
17
+ *
18
+ * Uses EventBusProvider context if available, otherwise falls back to
19
+ * a simple in-memory event bus (for design system / Storybook).
20
+ *
21
+ * @returns Event bus instance with emit, on, once, and hasListeners methods
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * const eventBus = useEventBus();
26
+ *
27
+ * // Emit an event
28
+ * eventBus.emit('UI:CLICK', { id: '123' });
29
+ *
30
+ * // Subscribe to an event
31
+ * useEffect(() => {
32
+ * return eventBus.on('UI:CLICK', (event) => {
33
+ * console.log('Clicked:', event.payload);
34
+ * });
35
+ * }, []);
36
+ * ```
37
+ */
38
+ declare function useEventBus(): EventBusContextType;
39
+ /**
40
+ * Hook for subscribing to a specific event.
41
+ * Automatically cleans up subscription on unmount.
42
+ *
43
+ * @param event - Event name to subscribe to
44
+ * @param handler - Event handler function
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * useEventListener('UI:CLICK', (event) => {
49
+ * console.log('Clicked:', event.payload);
50
+ * });
51
+ * ```
52
+ */
53
+ declare function useEventListener(event: string, handler: EventListener): void;
54
+ /**
55
+ * Hook for emitting events.
56
+ * Returns a memoized emit function.
57
+ *
58
+ * @returns Function to emit events
59
+ *
60
+ * @example
61
+ * ```tsx
62
+ * const emit = useEmitEvent();
63
+ *
64
+ * const handleClick = () => {
65
+ * emit('UI:CLICK', { id: '123' });
66
+ * };
67
+ * ```
68
+ */
69
+ declare function useEmitEvent(): (type: string, payload?: Record<string, unknown>) => void;
70
+
10
71
  interface ChangeSummary {
11
72
  added: number;
12
73
  modified: number;
@@ -427,67 +488,6 @@ interface UseValidationResult {
427
488
  }
428
489
  declare function useValidation(): UseValidationResult;
429
490
 
430
- declare global {
431
- interface Window {
432
- __kflowEventBus?: EventBusContextType | null;
433
- }
434
- }
435
- /**
436
- * Hook for accessing the event bus.
437
- *
438
- * Uses EventBusProvider context if available, otherwise falls back to
439
- * a simple in-memory event bus (for design system / Storybook).
440
- *
441
- * @returns Event bus instance with emit, on, once, and hasListeners methods
442
- *
443
- * @example
444
- * ```tsx
445
- * const eventBus = useEventBus();
446
- *
447
- * // Emit an event
448
- * eventBus.emit('UI:CLICK', { id: '123' });
449
- *
450
- * // Subscribe to an event
451
- * useEffect(() => {
452
- * return eventBus.on('UI:CLICK', (event) => {
453
- * console.log('Clicked:', event.payload);
454
- * });
455
- * }, []);
456
- * ```
457
- */
458
- declare function useEventBus(): EventBusContextType;
459
- /**
460
- * Hook for subscribing to a specific event.
461
- * Automatically cleans up subscription on unmount.
462
- *
463
- * @param event - Event name to subscribe to
464
- * @param handler - Event handler function
465
- *
466
- * @example
467
- * ```tsx
468
- * useEventListener('UI:CLICK', (event) => {
469
- * console.log('Clicked:', event.payload);
470
- * });
471
- * ```
472
- */
473
- declare function useEventListener(event: string, handler: EventListener): void;
474
- /**
475
- * Hook for emitting events.
476
- * Returns a memoized emit function.
477
- *
478
- * @returns Function to emit events
479
- *
480
- * @example
481
- * ```tsx
482
- * const emit = useEmitEvent();
483
- *
484
- * const handleClick = () => {
485
- * emit('UI:CLICK', { id: '123' });
486
- * };
487
- * ```
488
- */
489
- declare function useEmitEvent(): (type: string, payload?: Record<string, unknown>) => void;
490
-
491
491
  /**
492
492
  * Hook to bridge UI events to state machine dispatch
493
493
  *
@@ -1,7 +1,7 @@
1
- export { ENTITY_EVENTS, useAgentChat, useAuthContext, useCompile, useConnectGitHub, useCreateEntity, useDeepAgentGeneration, useDeleteEntity, useDisconnectGitHub, useEntities, useEntitiesByType, useEntity as useEntityById, useEntityMutations, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInput, useOrbitalHistory, useOrbitalMutations, usePhysics, usePinchZoom, usePlayer, usePreview, useResolvedEntity, useSelectedEntity, useSendOrbitalEvent, useSingletonEntity, useUIEvents, useUpdateEntity, useValidation } from '../chunk-3FENGM4Y.js';
1
+ export { ENTITY_EVENTS, useAgentChat, useAuthContext, useCompile, useConnectGitHub, useCreateEntity, useDeepAgentGeneration, useDeleteEntity, useDisconnectGitHub, useEntities, useEntitiesByType, useEntity as useEntityById, useEntityMutations, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInput, useOrbitalHistory, useOrbitalMutations, usePhysics, usePinchZoom, usePlayer, usePreview, useResolvedEntity, useSelectedEntity, useSendOrbitalEvent, useSingletonEntity, useUIEvents, useUpdateEntity, useValidation } from '../chunk-GTIAVPI5.js';
2
2
  export { clearEntities, getAllEntities, getByType, getEntity, getSingleton, removeEntity, spawnEntity, updateEntity, updateSingleton } from '../chunk-N7MVUW4R.js';
3
3
  import '../chunk-3HJHHULT.js';
4
- export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useDragReorder, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useInfiniteScroll, useLongPress, usePullToRefresh, useQuerySingleton, useSwipeGesture, useTranslate } from '../chunk-RUL35VPK.js';
4
+ export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useDragReorder, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useInfiniteScroll, useLongPress, usePullToRefresh, useQuerySingleton, useSwipeGesture, useTranslate } from '../chunk-WGJIL4YR.js';
5
5
  export { useEmitEvent, useEventBus, useEventListener } from '../chunk-YXZM3WCF.js';
6
6
  export { DEFAULT_SLOTS, useUISlotManager } from '../chunk-3JGAROCW.js';
7
7
  import '../chunk-TSETXL2E.js';
@@ -1,10 +1,10 @@
1
- export { FetchedDataContext, FetchedDataProvider, OfflineModeProvider, OrbitalProvider, VerificationProvider, useFetchedData, useFetchedDataContext, useFetchedEntity, useOfflineMode, useOptionalOfflineMode } from '../chunk-5K3GTPBX.js';
2
- import '../chunk-4NAQLJ2M.js';
3
- import '../chunk-YLKXEXBP.js';
4
- export { SelectionContext, SelectionProvider, useSelection, useSelectionOptional } from '../chunk-RUL35VPK.js';
1
+ export { FetchedDataContext, FetchedDataProvider, OfflineModeProvider, OrbitalProvider, VerificationProvider, useFetchedData, useFetchedDataContext, useFetchedEntity, useOfflineMode, useOptionalOfflineMode } from '../chunk-TVP75XPM.js';
2
+ import '../chunk-JDISOWHE.js';
3
+ import '../chunk-DKQN5FVU.js';
4
+ export { SelectionContext, SelectionProvider, useSelection, useSelectionOptional } from '../chunk-WGJIL4YR.js';
5
5
  export { EventBusContext, EventBusProvider } from '../chunk-YXZM3WCF.js';
6
6
  import '../chunk-3JGAROCW.js';
7
- import '../chunk-TSETXL2E.js';
8
7
  import '../chunk-WCTZ7WZX.js';
8
+ import '../chunk-TSETXL2E.js';
9
9
  import '../chunk-K2D5D3WK.js';
10
10
  import '../chunk-PKBMQBKP.js';
@@ -1,20 +1,20 @@
1
- import '../chunk-3FENGM4Y.js';
1
+ import '../chunk-GTIAVPI5.js';
2
2
  import '../chunk-N7MVUW4R.js';
3
3
  import { registerTrait, unregisterTrait, updateTraitState } from '../chunk-42YQ6JVR.js';
4
4
  import '../chunk-3HJHHULT.js';
5
- import { useFetchedDataContext } from '../chunk-5K3GTPBX.js';
6
- import '../chunk-4NAQLJ2M.js';
7
- import '../chunk-YLKXEXBP.js';
8
- import '../chunk-RUL35VPK.js';
5
+ import { useFetchedDataContext } from '../chunk-TVP75XPM.js';
6
+ import '../chunk-JDISOWHE.js';
7
+ import '../chunk-DKQN5FVU.js';
8
+ import '../chunk-WGJIL4YR.js';
9
9
  import { useEventBus } from '../chunk-YXZM3WCF.js';
10
10
  import '../chunk-3JGAROCW.js';
11
- import '../chunk-TSETXL2E.js';
12
11
  import { recordTransition } from '../chunk-WCTZ7WZX.js';
12
+ import '../chunk-TSETXL2E.js';
13
13
  import '../chunk-K2D5D3WK.js';
14
14
  import '../chunk-PKBMQBKP.js';
15
15
  import { createContext, useMemo, useContext, useState, useRef, useEffect, useCallback } from 'react';
16
16
  import { isCircuitEvent, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1 } from '@almadar/core';
17
- import { StateMachineManager, EffectExecutor } from '@almadar/runtime';
17
+ import { StateMachineManager, createContextFromBindings, interpolateValue, EffectExecutor } from '@almadar/runtime';
18
18
  import { isEntityAwarePattern } from '@almadar/patterns';
19
19
  import { jsx } from 'react/jsx-runtime';
20
20
 
@@ -124,6 +124,14 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
124
124
  useEffect(() => {
125
125
  optionsRef.current = options;
126
126
  }, [options]);
127
+ const traitStatesRef = useRef(traitStates);
128
+ const fetchedDataContextRef = useRef(fetchedDataContext);
129
+ useEffect(() => {
130
+ traitStatesRef.current = traitStates;
131
+ }, [traitStates]);
132
+ useEffect(() => {
133
+ fetchedDataContextRef.current = fetchedDataContext;
134
+ }, [fetchedDataContext]);
127
135
  useEffect(() => {
128
136
  const mgr = managerRef.current;
129
137
  const bindings = traitBindingsRef.current;
@@ -166,6 +174,143 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
166
174
  Array.from(newManager.getAllStates().keys()).join(", ")
167
175
  );
168
176
  }, [traitBindings]);
177
+ const runTickEffects = useCallback((tick, binding) => {
178
+ const fdc = fetchedDataContextRef.current;
179
+ const actions = slotsActionsRef.current;
180
+ const linkedEntity = binding.linkedEntity ?? "";
181
+ const currentState = traitStatesRef.current.get(binding.trait.name)?.currentState ?? "";
182
+ if (tick.appliesTo.length > 0 && !tick.appliesTo.includes(currentState)) return;
183
+ const records = linkedEntity && fdc ? fdc.getData(linkedEntity) : [];
184
+ const entityData = records.length > 0 ? Object.assign([...records], records[0]) : {};
185
+ const bindingCtx = { entity: entityData, payload: {}, state: currentState };
186
+ const evalCtx = createContextFromBindings(bindingCtx);
187
+ if (tick.guard !== void 0) {
188
+ const passed = interpolateValue(tick.guard, evalCtx);
189
+ if (!passed) return;
190
+ }
191
+ const entityMutations = /* @__PURE__ */ new Map();
192
+ const pendingSlots = /* @__PURE__ */ new Map();
193
+ const slotSource = {
194
+ trait: binding.trait.name,
195
+ state: currentState,
196
+ transition: `${currentState}->tick:${tick.name}`,
197
+ effects: tick.effects,
198
+ traitDefinition: binding.trait
199
+ };
200
+ const enrichTickNode = (node) => {
201
+ if (!node || typeof node !== "object") return node;
202
+ const rec = node;
203
+ const nodeType = rec.type;
204
+ let enriched = rec;
205
+ if (Array.isArray(rec.children)) {
206
+ enriched = { ...rec, children: rec.children.map(enrichTickNode) };
207
+ }
208
+ if (nodeType && isEntityAwarePattern(nodeType) && fdc) {
209
+ let injected = false;
210
+ if (typeof enriched.entity === "string") {
211
+ const entityRecords = fdc.getData(enriched.entity);
212
+ if (entityRecords.length > 0) {
213
+ enriched = { ...enriched, entity: entityRecords };
214
+ injected = true;
215
+ }
216
+ } else if (!enriched.entity && linkedEntity) {
217
+ const entityRecords = fdc.getData(linkedEntity);
218
+ if (entityRecords.length > 0) {
219
+ enriched = { ...enriched, entity: entityRecords };
220
+ injected = true;
221
+ }
222
+ }
223
+ if (injected && !enriched.fields && !enriched.columns) {
224
+ const sample = enriched.entity[0];
225
+ if (sample && typeof sample === "object") {
226
+ const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
227
+ enriched = { ...enriched, fields: keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" })), children: void 0 };
228
+ }
229
+ }
230
+ }
231
+ return enriched;
232
+ };
233
+ for (const effect of tick.effects) {
234
+ if (!Array.isArray(effect)) continue;
235
+ const op = effect[0];
236
+ if (op === "set") {
237
+ const path = effect[1];
238
+ if (typeof path !== "string" || !path.startsWith("@entity.")) continue;
239
+ const field = path.slice("@entity.".length);
240
+ const updatedCtx = createContextFromBindings(bindingCtx);
241
+ const value = interpolateValue(effect[2], updatedCtx);
242
+ bindingCtx.entity[field] = value;
243
+ entityMutations.set(field, value);
244
+ } else if (op === "render-ui" || op === "render") {
245
+ const slot = effect[1];
246
+ const rawPattern = effect[2];
247
+ if (rawPattern === null || rawPattern === void 0) {
248
+ pendingSlots.set(slot, []);
249
+ continue;
250
+ }
251
+ const updatedCtx = createContextFromBindings(bindingCtx);
252
+ const resolved = interpolateValue(rawPattern, updatedCtx);
253
+ const enriched = enrichTickNode(resolved);
254
+ const existing = pendingSlots.get(slot) ?? [];
255
+ existing.push({ pattern: enriched, props: {} });
256
+ pendingSlots.set(slot, existing);
257
+ }
258
+ }
259
+ for (const [slot, patterns] of pendingSlots) {
260
+ if (patterns.length === 0) {
261
+ actions.clearSlot(slot);
262
+ } else {
263
+ actions.setSlotPatterns(slot, patterns, slotSource);
264
+ }
265
+ }
266
+ if (linkedEntity && entityMutations.size > 0 && fdc) {
267
+ const latestRecords = fdc.getData(linkedEntity);
268
+ if (latestRecords.length > 0) {
269
+ const updated = latestRecords.map(
270
+ (r, i) => i === 0 ? { ...r, ...Object.fromEntries(entityMutations) } : r
271
+ );
272
+ fdc.setData({ [linkedEntity]: updated });
273
+ }
274
+ }
275
+ }, []);
276
+ useEffect(() => {
277
+ const hasFrameTicks = traitBindingsRef.current.some(
278
+ (b) => b.trait.ticks?.some((t) => t.interval === "frame")
279
+ );
280
+ if (!hasFrameTicks) return;
281
+ let running = true;
282
+ let rafId = 0;
283
+ const frame = () => {
284
+ if (!running) return;
285
+ for (const binding of traitBindingsRef.current) {
286
+ for (const tick of binding.trait.ticks ?? []) {
287
+ if (tick.interval !== "frame") continue;
288
+ runTickEffects(tick, binding);
289
+ }
290
+ }
291
+ rafId = requestAnimationFrame(frame);
292
+ };
293
+ rafId = requestAnimationFrame(frame);
294
+ return () => {
295
+ running = false;
296
+ cancelAnimationFrame(rafId);
297
+ };
298
+ }, [traitBindings, runTickEffects]);
299
+ useEffect(() => {
300
+ const intervals = [];
301
+ for (const binding of traitBindings) {
302
+ for (const tick of binding.trait.ticks ?? []) {
303
+ if (tick.interval === "frame") continue;
304
+ const ms = tick.interval;
305
+ intervals.push(setInterval(() => {
306
+ runTickEffects(tick, binding);
307
+ }, ms));
308
+ }
309
+ }
310
+ return () => {
311
+ for (const id of intervals) clearInterval(id);
312
+ };
313
+ }, [traitBindings, runTickEffects]);
169
314
  const processEvent = useCallback((eventKey, payload) => {
170
315
  const normalizedEvent = normalizeEventKey(eventKey);
171
316
  const bindings = traitBindingsRef.current;
@@ -277,6 +422,19 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
277
422
  payload: payload || {},
278
423
  state: result.previousState
279
424
  };
425
+ const entityMutations = /* @__PURE__ */ new Map();
426
+ for (const effect of result.effects) {
427
+ if (!Array.isArray(effect) || effect[0] !== "set") continue;
428
+ const path = effect[1];
429
+ if (typeof path !== "string" || !path.startsWith("@entity.")) continue;
430
+ const field = path.slice("@entity.".length);
431
+ const evalCtx = createContextFromBindings(bindingCtx);
432
+ const value = interpolateValue(effect[2], evalCtx);
433
+ if (bindingCtx.entity !== null && typeof bindingCtx.entity === "object") {
434
+ bindingCtx.entity[field] = value;
435
+ }
436
+ entityMutations.set(field, value);
437
+ }
280
438
  const effectContext = {
281
439
  traitName: binding.trait.name,
282
440
  state: result.previousState,
@@ -297,6 +455,15 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
297
455
  actions.setSlotPatterns(slot, patterns, slotSource);
298
456
  }
299
457
  }
458
+ if (linkedEntity && entityMutations.size > 0 && fetchedDataContext) {
459
+ const records = fetchedDataContext.getData(linkedEntity);
460
+ if (records.length > 0) {
461
+ const updated = records.map(
462
+ (r, i) => i === 0 ? { ...r, ...Object.fromEntries(entityMutations) } : r
463
+ );
464
+ fetchedDataContext.setData({ [linkedEntity]: updated });
465
+ }
466
+ }
300
467
  }).catch((error) => {
301
468
  console.error(
302
469
  "[TraitStateMachine] Effect execution error:",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "2.11.7",
3
+ "version": "2.12.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",
@@ -93,6 +93,7 @@
93
93
  "@react-three/drei": "^9.92.0 || ^10.0.0",
94
94
  "@react-three/fiber": "^8.15.0",
95
95
  "@tanstack/react-query": "^5.0.0",
96
+ "@docusaurus/theme-common": "*",
96
97
  "react": ">=18.0.0",
97
98
  "react-dom": ">=18.0.0",
98
99
  "react-router-dom": "^7.0.0",
@@ -99,9 +99,6 @@
99
99
  --focus-ring-offset: 2px;
100
100
  --focus-ring-color: #14b8a6;
101
101
 
102
- /* Apply background and foreground colors */
103
- background-color: var(--color-background);
104
- color: var(--color-foreground);
105
102
  }
106
103
 
107
104
  /* ==========================================================================
@@ -198,7 +195,4 @@
198
195
  --focus-ring-offset: 2px;
199
196
  --focus-ring-color: #14b8a6;
200
197
 
201
- /* Apply background and foreground colors */
202
- background-color: var(--color-background);
203
- color: var(--color-foreground);
204
198
  }
package/themes/arctic.css CHANGED
@@ -100,9 +100,6 @@
100
100
  --focus-ring-offset: 2px;
101
101
  --focus-ring-color: #0284c7;
102
102
 
103
- /* Apply background and foreground colors */
104
- background-color: var(--color-background);
105
- color: var(--color-foreground);
106
103
  }
107
104
 
108
105
  /* ==========================================================================
@@ -197,7 +194,4 @@
197
194
  --focus-ring-offset: 2px;
198
195
  --focus-ring-color: #67e8f9;
199
196
 
200
- /* Apply background and foreground colors */
201
- background-color: var(--color-background);
202
- color: var(--color-foreground);
203
197
  }
package/themes/copper.css CHANGED
@@ -100,9 +100,6 @@
100
100
  --focus-ring-offset: 2px;
101
101
  --focus-ring-color: #b45309;
102
102
 
103
- /* Apply background and foreground colors */
104
- background-color: var(--color-background);
105
- color: var(--color-foreground);
106
103
  }
107
104
 
108
105
  /* ==========================================================================
@@ -197,7 +194,4 @@
197
194
  --focus-ring-offset: 2px;
198
195
  --focus-ring-color: #d97706;
199
196
 
200
- /* Apply background and foreground colors */
201
- background-color: var(--color-background);
202
- color: var(--color-foreground);
203
197
  }
package/themes/ember.css CHANGED
@@ -101,9 +101,6 @@
101
101
  --focus-ring-offset: 2px;
102
102
  --focus-ring-color: #dc2626;
103
103
 
104
- /* Apply background and foreground colors */
105
- background-color: var(--color-background);
106
- color: var(--color-foreground);
107
104
  }
108
105
 
109
106
  /* ==========================================================================
@@ -200,7 +197,4 @@
200
197
  --focus-ring-offset: 2px;
201
198
  --focus-ring-color: #f87171;
202
199
 
203
- /* Apply background and foreground colors */
204
- background-color: var(--color-background);
205
- color: var(--color-foreground);
206
200
  }
package/themes/forest.css CHANGED
@@ -101,9 +101,6 @@
101
101
  --focus-ring-offset: 2px;
102
102
  --focus-ring-color: #2d6a4f;
103
103
 
104
- /* Apply background and foreground colors */
105
- background-color: var(--color-background);
106
- color: var(--color-foreground);
107
104
  }
108
105
 
109
106
  /* ==========================================================================
@@ -200,7 +197,4 @@
200
197
  --focus-ring-offset: 2px;
201
198
  --focus-ring-color: #52b788;
202
199
 
203
- /* Apply background and foreground colors */
204
- background-color: var(--color-background);
205
- color: var(--color-foreground);
206
200
  }
@@ -98,9 +98,6 @@
98
98
  --focus-ring-offset: 2px;
99
99
  --focus-ring-color: #7c3aed;
100
100
 
101
- /* Apply background and foreground colors */
102
- background-color: var(--color-background);
103
- color: var(--color-foreground);
104
101
  }
105
102
 
106
103
  /* ==========================================================================
@@ -195,7 +192,4 @@
195
192
  --focus-ring-offset: 2px;
196
193
  --focus-ring-color: #a78bfa;
197
194
 
198
- /* Apply background and foreground colors */
199
- background-color: var(--color-background);
200
- color: var(--color-foreground);
201
195
  }
@@ -99,9 +99,6 @@
99
99
  --focus-ring-offset: 2px;
100
100
  --focus-ring-color: #6366f1;
101
101
 
102
- /* Apply background and foreground colors */
103
- background-color: var(--color-background);
104
- color: var(--color-foreground);
105
102
  }
106
103
 
107
104
  /* ==========================================================================
@@ -196,7 +193,4 @@
196
193
  --focus-ring-offset: 2px;
197
194
  --focus-ring-color: #818cf8;
198
195
 
199
- /* Apply background and foreground colors */
200
- background-color: var(--color-background);
201
- color: var(--color-foreground);
202
196
  }
@@ -98,9 +98,6 @@
98
98
  --focus-ring-offset: 2px;
99
99
  --focus-ring-color: #18181b;
100
100
 
101
- /* Apply background and foreground colors */
102
- background-color: var(--color-background);
103
- color: var(--color-foreground);
104
101
  }
105
102
 
106
103
  /* ==========================================================================
@@ -195,7 +192,4 @@
195
192
  --focus-ring-offset: 2px;
196
193
  --focus-ring-color: #fafafa;
197
194
 
198
- /* Apply background and foreground colors */
199
- background-color: var(--color-background);
200
- color: var(--color-foreground);
201
195
  }
package/themes/neon.css CHANGED
@@ -101,9 +101,6 @@
101
101
  --focus-ring-offset: 2px;
102
102
  --focus-ring-color: #22d3ee;
103
103
 
104
- /* Apply background and foreground colors */
105
- background-color: var(--color-background);
106
- color: var(--color-foreground);
107
104
  }
108
105
 
109
106
  /* ==========================================================================
@@ -202,7 +199,4 @@
202
199
  --focus-ring-offset: 2px;
203
200
  --focus-ring-color: #22d3ee;
204
201
 
205
- /* Apply background and foreground colors */
206
- background-color: var(--color-background);
207
- color: var(--color-foreground);
208
202
  }
package/themes/ocean.css CHANGED
@@ -101,9 +101,6 @@
101
101
  --focus-ring-offset: 2px;
102
102
  --focus-ring-color: #0077b6;
103
103
 
104
- /* Apply background and foreground colors */
105
- background-color: var(--color-background);
106
- color: var(--color-foreground);
107
104
  }
108
105
 
109
106
  /* ==========================================================================
@@ -200,7 +197,4 @@
200
197
  --focus-ring-offset: 2px;
201
198
  --focus-ring-color: #48cae4;
202
199
 
203
- /* Apply background and foreground colors */
204
- background-color: var(--color-background);
205
- color: var(--color-foreground);
206
200
  }
package/themes/rose.css CHANGED
@@ -98,9 +98,6 @@
98
98
  --focus-ring-offset: 2px;
99
99
  --focus-ring-color: #e11d48;
100
100
 
101
- /* Apply background and foreground colors */
102
- background-color: var(--color-background);
103
- color: var(--color-foreground);
104
101
  }
105
102
 
106
103
  /* ==========================================================================
@@ -195,7 +192,4 @@
195
192
  --focus-ring-offset: 2px;
196
193
  --focus-ring-color: #fb7185;
197
194
 
198
- /* Apply background and foreground colors */
199
- background-color: var(--color-background);
200
- color: var(--color-foreground);
201
195
  }