@almadar/ui 2.11.6 → 2.11.9

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,7 +1,7 @@
1
1
  import { useTheme, useUISlots } from './chunk-DKQN5FVU.js';
2
+ import { cn, debugGroup, debug, debugGroupEnd, updateAssetStatus, bindCanvasCapture, getNestedValue, isDebugEnabled } from './chunk-WCTZ7WZX.js';
2
3
  import { useTranslate, useInfiniteScroll, useQuerySingleton, useLongPress, useSwipeGesture, useDragReorder, usePullToRefresh } from './chunk-WGJIL4YR.js';
3
4
  import { useEventBus } from './chunk-YXZM3WCF.js';
4
- import { cn, debugGroup, debug, debugGroupEnd, updateAssetStatus, bindCanvasCapture, getNestedValue, isDebugEnabled } from './chunk-WCTZ7WZX.js';
5
5
  import { isPortalSlot } from './chunk-K2D5D3WK.js';
6
6
  import { __publicField } from './chunk-PKBMQBKP.js';
7
7
  import * as LucideIcons from 'lucide-react';
@@ -9614,17 +9614,17 @@ function InventoryPanel({
9614
9614
  onMouseEnter: (e) => handleMouseEnter(e, index),
9615
9615
  onMouseLeave: handleMouseLeave,
9616
9616
  tabIndex: 0,
9617
- "aria-label": item ? `${item.name || item.type}, quantity: ${item.quantity}` : `Empty slot ${index + 1}`,
9617
+ "aria-label": item ? `${item.name || item.type || "Item"}, quantity: ${item.quantity}` : `Empty slot ${index + 1}`,
9618
9618
  children: item && /* @__PURE__ */ jsxs(Fragment, { children: [
9619
9619
  item.sprite ? /* @__PURE__ */ jsx(
9620
9620
  "img",
9621
9621
  {
9622
9622
  src: item.sprite,
9623
- alt: item.name || item.type,
9623
+ alt: item.name || item.type || "Item",
9624
9624
  className: "w-8 h-8 object-contain",
9625
9625
  style: { imageRendering: "pixelated" }
9626
9626
  }
9627
- ) : /* @__PURE__ */ jsx("div", { className: "w-8 h-8 bg-gray-600 rounded flex items-center justify-center text-xs text-gray-300", children: item.type.charAt(0).toUpperCase() }),
9627
+ ) : /* @__PURE__ */ jsx("div", { className: "w-8 h-8 bg-gray-600 rounded flex items-center justify-center text-xs text-gray-300", children: (item.type ?? item.name ?? "I").charAt(0).toUpperCase() }),
9628
9628
  item.quantity > 1 && /* @__PURE__ */ jsx("span", { className: "absolute bottom-0 right-0 bg-black bg-opacity-70 text-white text-xs px-1 rounded-tl", children: item.quantity })
9629
9629
  ] })
9630
9630
  },
@@ -1,8 +1,8 @@
1
- import { SuspenseConfigProvider } from './chunk-4LBNLALH.js';
1
+ import { SuspenseConfigProvider } from './chunk-7FVLOH5L.js';
2
2
  import { ThemeProvider } from './chunk-DKQN5FVU.js';
3
+ import { recordTransition, registerCheck, bindEventBus, bindTraitStateGetter } from './chunk-WCTZ7WZX.js';
3
4
  import { SelectionProvider, EntityDataProvider } from './chunk-WGJIL4YR.js';
4
5
  import { useEventBus, EventBusProvider } from './chunk-YXZM3WCF.js';
5
- import { recordTransition, registerCheck, bindEventBus, bindTraitStateGetter } from './chunk-WCTZ7WZX.js';
6
6
  import { useOfflineExecutor } from './chunk-K2D5D3WK.js';
7
7
  import { createContext, useState, useCallback, useMemo, useContext, useRef, useEffect } from 'react';
8
8
  import { jsx, Fragment } from 'react/jsx-runtime';
@@ -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 { subscribeToTraitChanges, getAllTraits } from '../chunk-42YQ6JVR.js';
2
3
  import { useAuthContext } from '../chunk-GTIAVPI5.js';
3
4
  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
5
  export { clearEntities, getAllEntities, getByType, getEntity, getSingleton, removeEntity, spawnEntity, updateEntity, updateSingleton } from '../chunk-N7MVUW4R.js';
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-4LBNLALH.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-4LBNLALH.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-7FVLOH5L.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-7FVLOH5L.js';
9
9
  import '../chunk-DKQN5FVU.js';
10
+ import { cn, getNestedValue, subscribeToVerification, getSummary, getBridgeHealth, getTransitions, getAllChecks } from '../chunk-WCTZ7WZX.js';
11
+ export { cn } from '../chunk-WCTZ7WZX.js';
10
12
  import { useTranslate } from '../chunk-WGJIL4YR.js';
11
13
  export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useDragReorder, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useInfiniteScroll, useLongPress, usePullToRefresh, useQuerySingleton, useSwipeGesture, useTranslate } from '../chunk-WGJIL4YR.js';
12
14
  import { useEventBus, useEventListener } from '../chunk-YXZM3WCF.js';
13
15
  export { useEmitEvent, useEventBus, useEventListener } from '../chunk-YXZM3WCF.js';
14
16
  export { DEFAULT_SLOTS, useUISlotManager } from '../chunk-3JGAROCW.js';
15
17
  import '../chunk-TSETXL2E.js';
16
- import { cn, getNestedValue, subscribeToVerification, getSummary, getBridgeHealth, getTransitions, getAllChecks } from '../chunk-WCTZ7WZX.js';
17
- export { cn } from '../chunk-WCTZ7WZX.js';
18
18
  import '../chunk-K2D5D3WK.js';
19
19
  import { __publicField } from '../chunk-PKBMQBKP.js';
20
20
  import * as React44 from 'react';
@@ -1,10 +1,10 @@
1
- export { FetchedDataContext, FetchedDataProvider, OfflineModeProvider, OrbitalProvider, VerificationProvider, useFetchedData, useFetchedDataContext, useFetchedEntity, useOfflineMode, useOptionalOfflineMode } from '../chunk-A2NPH2P3.js';
2
- import '../chunk-4LBNLALH.js';
1
+ export { FetchedDataContext, FetchedDataProvider, OfflineModeProvider, OrbitalProvider, VerificationProvider, useFetchedData, useFetchedDataContext, useFetchedEntity, useOfflineMode, useOptionalOfflineMode } from '../chunk-XWAVGJKL.js';
2
+ import '../chunk-7FVLOH5L.js';
3
3
  import '../chunk-DKQN5FVU.js';
4
+ import '../chunk-WCTZ7WZX.js';
4
5
  export { SelectionContext, SelectionProvider, useSelection, useSelectionOptional } from '../chunk-WGJIL4YR.js';
5
6
  export { EventBusContext, EventBusProvider } from '../chunk-YXZM3WCF.js';
6
7
  import '../chunk-3JGAROCW.js';
7
8
  import '../chunk-TSETXL2E.js';
8
- import '../chunk-WCTZ7WZX.js';
9
9
  import '../chunk-K2D5D3WK.js';
10
10
  import '../chunk-PKBMQBKP.js';
@@ -1,20 +1,20 @@
1
+ import { registerTrait, unregisterTrait, updateTraitState } from '../chunk-42YQ6JVR.js';
1
2
  import '../chunk-GTIAVPI5.js';
2
3
  import '../chunk-N7MVUW4R.js';
3
- import { registerTrait, unregisterTrait, updateTraitState } from '../chunk-42YQ6JVR.js';
4
4
  import '../chunk-3HJHHULT.js';
5
- import { useFetchedDataContext } from '../chunk-A2NPH2P3.js';
6
- import '../chunk-4LBNLALH.js';
5
+ import { useFetchedDataContext } from '../chunk-XWAVGJKL.js';
6
+ import '../chunk-7FVLOH5L.js';
7
7
  import '../chunk-DKQN5FVU.js';
8
+ import { recordTransition } from '../chunk-WCTZ7WZX.js';
8
9
  import '../chunk-WGJIL4YR.js';
9
10
  import { useEventBus } from '../chunk-YXZM3WCF.js';
10
11
  import '../chunk-3JGAROCW.js';
11
12
  import '../chunk-TSETXL2E.js';
12
- import { recordTransition } from '../chunk-WCTZ7WZX.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.6",
3
+ "version": "2.11.9",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",