@almadar/ui 2.61.1 → 3.1.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.
Files changed (48) hide show
  1. package/dist/avl/index.cjs +1344 -1507
  2. package/dist/avl/index.css +7 -2
  3. package/dist/avl/index.js +268 -431
  4. package/dist/components/index.cjs +40 -38
  5. package/dist/components/index.css +7 -2
  6. package/dist/components/index.js +41 -39
  7. package/dist/components/organisms/DataTable.d.ts +3 -2
  8. package/dist/components/organisms/JazariStateMachine.d.ts +10 -37
  9. package/dist/components/organisms/MasterDetail.d.ts +4 -3
  10. package/dist/components/organisms/MediaGallery.d.ts +3 -2
  11. package/dist/components/organisms/Sidebar.d.ts +7 -2
  12. package/dist/components/organisms/StateMachineView.d.ts +7 -2
  13. package/dist/components/organisms/Table.d.ts +2 -1
  14. package/dist/components/organisms/Timeline.d.ts +15 -2
  15. package/dist/components/organisms/book/BookChapterView.d.ts +3 -2
  16. package/dist/components/organisms/book/BookCoverPage.d.ts +3 -3
  17. package/dist/components/organisms/book/BookNavBar.d.ts +3 -3
  18. package/dist/components/organisms/book/BookTableOfContents.d.ts +3 -2
  19. package/dist/components/organisms/book/BookViewer.d.ts +2 -2
  20. package/dist/components/organisms/book/types.d.ts +9 -4
  21. package/dist/components/organisms/game/WorldMapBoard.d.ts +9 -3
  22. package/dist/components/organisms/game/three/index.cjs +8 -4
  23. package/dist/components/organisms/game/three/index.js +8 -4
  24. package/dist/components/organisms/marketing-types.d.ts +22 -12
  25. package/dist/components/organisms/types.d.ts +24 -12
  26. package/dist/components/templates/types.d.ts +7 -2
  27. package/dist/docs/index.cjs +6 -2
  28. package/dist/docs/index.d.cts +1 -1
  29. package/dist/docs/index.js +6 -2
  30. package/dist/hooks/event-bus-types.d.ts +19 -27
  31. package/dist/hooks/index.cjs +13 -6
  32. package/dist/hooks/index.d.ts +1 -1
  33. package/dist/hooks/index.js +13 -6
  34. package/dist/hooks/useEventBus.d.ts +3 -3
  35. package/dist/lib/index.cjs +5 -2
  36. package/dist/lib/index.js +5 -2
  37. package/dist/lib/verificationRegistry.d.ts +3 -5
  38. package/dist/marketing/index.cjs +6 -2
  39. package/dist/marketing/index.js +6 -2
  40. package/dist/providers/index.cjs +997 -1168
  41. package/dist/providers/index.css +7 -2
  42. package/dist/providers/index.d.ts +0 -2
  43. package/dist/providers/index.js +241 -406
  44. package/dist/runtime/index.cjs +47 -70
  45. package/dist/runtime/index.css +7 -2
  46. package/dist/runtime/index.js +48 -71
  47. package/package.json +4 -4
  48. package/dist/providers/EntityStoreProvider.d.ts +0 -63
@@ -34,8 +34,8 @@ var langDiff = require('react-syntax-highlighter/dist/esm/languages/prism/diff.j
34
34
  var langToml = require('react-syntax-highlighter/dist/esm/languages/prism/toml.js');
35
35
  var langGo = require('react-syntax-highlighter/dist/esm/languages/prism/go.js');
36
36
  var langGraphql = require('react-syntax-highlighter/dist/esm/languages/prism/graphql.js');
37
- require('@tanstack/react-query');
38
37
  var core = require('@almadar/core');
38
+ require('@tanstack/react-query');
39
39
  var runtime = require('@almadar/runtime');
40
40
 
41
41
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -202,8 +202,8 @@ function useEventListener(event, handler) {
202
202
  function useEmitEvent() {
203
203
  const eventBus = useEventBus();
204
204
  return React116.useCallback(
205
- (type, payload) => {
206
- eventBus.emit(type, payload);
205
+ (type, payload, source) => {
206
+ eventBus.emit(type, payload, source);
207
207
  },
208
208
  [eventBus]
209
209
  );
@@ -218,11 +218,15 @@ var init_useEventBus = __esm({
218
218
  fallbackListeners = /* @__PURE__ */ new Map();
219
219
  fallbackAnyListeners = /* @__PURE__ */ new Set();
220
220
  fallbackEventBus = {
221
- emit: (type, payload) => {
221
+ emit: (type, payload, source) => {
222
222
  const event = {
223
223
  type,
224
+ // Narrow at the bus boundary: public emit accepts an opaque object so
225
+ // generic UI emit sites don't require casts; the envelope stores the
226
+ // payload as EventPayload which listeners consume directly.
224
227
  payload,
225
- timestamp: Date.now()
228
+ timestamp: Date.now(),
229
+ source
226
230
  };
227
231
  const handlers = fallbackListeners.get(type);
228
232
  log.debug("emit", { type, payloadKeys: payload ? Object.keys(payload).length : 0, listenerCount: (handlers?.size ?? 0) + fallbackAnyListeners.size });
@@ -10409,9 +10413,9 @@ var init_ScaledDiagram = __esm({
10409
10413
  }
10410
10414
  });
10411
10415
 
10412
- // node_modules/.pnpm/katex@0.16.33/node_modules/katex/dist/katex.min.css
10416
+ // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
10413
10417
  var init_katex_min = __esm({
10414
- "node_modules/.pnpm/katex@0.16.33/node_modules/katex/dist/katex.min.css"() {
10418
+ "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
10415
10419
  }
10416
10420
  });
10417
10421
  var MarkdownContent;
@@ -12410,7 +12414,9 @@ function extractTrait(schema, trait, traitIndex) {
12410
12414
  for (const orbital of schema.orbitals) {
12411
12415
  const traits2 = orbital.traits ?? [];
12412
12416
  if (traitIndex < traits2.length) {
12413
- return traits2[traitIndex];
12417
+ const traitRef = traits2[traitIndex];
12418
+ if (core.isInlineTrait(traitRef)) return traitRef;
12419
+ return null;
12414
12420
  }
12415
12421
  }
12416
12422
  return null;
@@ -12418,8 +12424,10 @@ function extractTrait(schema, trait, traitIndex) {
12418
12424
  function extractEntityFields(schema) {
12419
12425
  if (!schema?.orbitals?.length) return [];
12420
12426
  const entity = schema.orbitals[0].entity;
12421
- if (!entity?.fields) return [];
12422
- return entity.fields.map((f3) => f3.name);
12427
+ if (!entity || typeof entity !== "object" || !("fields" in entity)) return [];
12428
+ const inlineEntity = entity;
12429
+ if (!inlineEntity.fields) return [];
12430
+ return inlineEntity.fields.map((f3) => f3.name);
12423
12431
  }
12424
12432
  function toStateMachineDefinition(sm) {
12425
12433
  return {
@@ -12714,12 +12722,18 @@ var init_ContentRenderer = __esm({
12714
12722
  );
12715
12723
  case "orbital": {
12716
12724
  const parsed = segment.schema;
12725
+ const inlineTrait = {
12726
+ name: "inline",
12727
+ scope: "instance",
12728
+ stateMachine: parsed
12729
+ };
12717
12730
  const schema = Array.isArray(parsed.orbitals) ? parsed : {
12731
+ name: "inline",
12718
12732
  orbitals: [{
12719
- traits: [{
12720
- name: "inline",
12721
- stateMachine: parsed
12722
- }]
12733
+ name: "inline",
12734
+ entity: { name: "inline", fields: [] },
12735
+ traits: [inlineTrait],
12736
+ pages: []
12723
12737
  }]
12724
12738
  };
12725
12739
  return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
@@ -37574,19 +37588,15 @@ function SlotContentRenderer({
37574
37588
  patternPath
37575
37589
  }) {
37576
37590
  const entityProp = content.props.entity;
37577
- const entityType = typeof entityProp === "string" ? entityProp : "";
37578
- const storeData = providers.useEntityRef(entityType);
37579
- React116__namespace.default.useEffect(() => {
37580
- if (!entityType) return;
37581
- if (typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production") return;
37582
- if (STRING_ENTITY_WARNED.has(entityType)) return;
37583
- STRING_ENTITY_WARNED.add(entityType);
37584
- console.warn(
37585
- `[UISlotRenderer] String-entity binding '${entityType}' is deprecated. Pass 'items' or 'entity' as a value prop resolved from @payload.data. See docs/Almadar_Entity_V2_Plan.md \xA75.`
37586
- );
37587
- }, [entityType]);
37591
+ if (typeof entityProp === "string" && entityProp.length > 0) {
37592
+ if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production") {
37593
+ throw new Error(
37594
+ `[UISlotRenderer] Received string 'entity: "${entityProp}"' at render time. The V2 flow requires pre-resolved data; declare a fetch success listener and pass 'entity: @payload.data'. See docs/Almadar_Entity_V2_Plan.md \xA76.`
37595
+ );
37596
+ }
37597
+ }
37588
37598
  const schemaCtx = useEntitySchemaOptional();
37589
- const entityDef = entityType && schemaCtx ? schemaCtx.entities.get(entityType) : void 0;
37599
+ const entityDef = typeof entityProp === "string" && entityProp.length > 0 && schemaCtx ? schemaCtx.entities.get(entityProp) : void 0;
37590
37600
  const PatternComponent = getComponentForPattern(content.pattern);
37591
37601
  if (PatternComponent) {
37592
37602
  const childrenConfig = content.props.children;
@@ -37595,12 +37605,7 @@ function SlotContentRenderer({
37595
37605
  const renderedChildren = hasChildren ? renderPatternChildren(childrenConfig, onDismiss, content.id, myPath) : void 0;
37596
37606
  const { children: _childrenConfig, ...restProps } = content.props;
37597
37607
  const renderedProps = renderPatternProps(restProps, onDismiss);
37598
- let finalProps;
37599
- if (entityType) {
37600
- finalProps = { ...renderedProps, entity: storeData };
37601
- } else {
37602
- finalProps = renderedProps;
37603
- }
37608
+ const finalProps = renderedProps;
37604
37609
  const resolvedItems = Array.isArray(
37605
37610
  finalProps.entity
37606
37611
  ) ? finalProps.entity : null;
@@ -37614,9 +37619,6 @@ function SlotContentRenderer({
37614
37619
  const isFormPattern = FORM_PATTERNS.has(content.pattern) || content.pattern.includes("form");
37615
37620
  if (isFormPattern && entityDef && Array.isArray(finalProps.fields)) {
37616
37621
  finalProps.fields = enrichFormFields(finalProps.fields, entityDef);
37617
- if (finalProps.mode === "edit" && !finalProps.initialData && storeData.length > 0) {
37618
- finalProps.initialData = storeData[0];
37619
- }
37620
37622
  }
37621
37623
  const acceptsChildren = PATTERNS_WITH_CHILDREN.has(content.pattern);
37622
37624
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -37710,7 +37712,7 @@ function UISlotRenderer({
37710
37712
  }
37711
37713
  return wrapped;
37712
37714
  }
37713
- var TRAIT_BINDING_RE, STRING_ENTITY_WARNED, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, FORM_PATTERNS, PATTERNS_WITH_CHILDREN;
37715
+ var TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, FORM_PATTERNS, PATTERNS_WITH_CHILDREN;
37714
37716
  var init_UISlotRenderer = __esm({
37715
37717
  "components/organisms/UISlotRenderer.tsx"() {
37716
37718
  "use client";
@@ -37727,7 +37729,6 @@ var init_UISlotRenderer = __esm({
37727
37729
  init_TraitFrame();
37728
37730
  init_component_registry_generated();
37729
37731
  TRAIT_BINDING_RE = /^@trait\.([A-Z][A-Za-z0-9]*)$/;
37730
- STRING_ENTITY_WARNED = /* @__PURE__ */ new Set();
37731
37732
  SuspenseConfigContext = React116.createContext({ enabled: false });
37732
37733
  SlotContainedContext = React116.createContext(false);
37733
37734
  SuspenseConfigProvider.displayName = "SuspenseConfigProvider";
@@ -37943,6 +37944,9 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
37943
37944
  const currentState = traitStatesRef.current.get(binding.trait.name)?.currentState ?? "";
37944
37945
  if (tick.appliesTo.length > 0 && !tick.appliesTo.includes(currentState)) return;
37945
37946
  const bindingCtx = { entity: {}, payload: {}, state: currentState };
37947
+ if (binding.config) {
37948
+ bindingCtx.config = binding.config;
37949
+ }
37946
37950
  const evalCtx = runtime.createContextFromBindings(bindingCtx);
37947
37951
  if (tick.guard !== void 0) {
37948
37952
  const passed = runtime.interpolateValue(tick.guard, evalCtx);
@@ -38075,6 +38079,9 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38075
38079
  payload: payload || {},
38076
38080
  state: result.previousState
38077
38081
  };
38082
+ if (binding.config) {
38083
+ bindingCtx.config = binding.config;
38084
+ }
38078
38085
  const effectContext = {
38079
38086
  traitName: binding.trait.name,
38080
38087
  state: result.previousState,
@@ -38555,7 +38562,7 @@ function buildMockData(schema) {
38555
38562
  }
38556
38563
  return result;
38557
38564
  }
38558
- function isInlineTrait(traitRef) {
38565
+ function isInlineTrait2(traitRef) {
38559
38566
  return typeof traitRef === "object" && traitRef !== null && "stateMachine" in traitRef;
38560
38567
  }
38561
38568
  function findDataState(sm, initialStateName) {
@@ -38587,7 +38594,7 @@ function adjustSchemaForMockData(schema, mockData) {
38587
38594
  const updatedOrbitals = schema.orbitals.map((orbital) => {
38588
38595
  const traits2 = orbital.traits ?? [];
38589
38596
  const updatedTraits = traits2.map((traitRef) => {
38590
- if (!isInlineTrait(traitRef)) return traitRef;
38597
+ if (!isInlineTrait2(traitRef)) return traitRef;
38591
38598
  const updated = rewriteTraitInitialState(traitRef, mockData);
38592
38599
  if (updated !== traitRef) changed = true;
38593
38600
  return updated;
@@ -38665,23 +38672,14 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
38665
38672
  const slotsActions = useSlotsActions();
38666
38673
  const bridge = useServerBridge();
38667
38674
  const uiSlots = context.useUISlots();
38668
- const entityStore = providers.useEntityStore();
38669
38675
  const onEventProcessed = React116.useCallback(async (event, payload) => {
38670
38676
  if (!bridge.connected || !orbitalNames?.length) return;
38671
38677
  for (const name of orbitalNames) {
38672
38678
  const { effects, meta } = await bridge.sendEvent(name, event, payload);
38673
38679
  recordServerResponse(name, event, meta);
38674
- const responseData = meta?.data;
38675
- if (responseData) {
38676
- for (const [entityType, records] of Object.entries(responseData)) {
38677
- if (Array.isArray(records)) {
38678
- entityStore.setAll(entityType, records);
38679
- }
38680
- }
38681
- }
38682
38680
  applyServerEffects(effects, uiSlots, onNavigate);
38683
38681
  }
38684
- }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, entityStore]);
38682
+ }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate]);
38685
38683
  const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate } : { navigate: onNavigate };
38686
38684
  const { sendEvent } = useTraitStateMachine(traits2, slotsActions, opts);
38687
38685
  const initSentRef = React116.useRef(false);
@@ -38721,14 +38719,6 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
38721
38719
  effects: effectTraces,
38722
38720
  timestamp: Date.now()
38723
38721
  });
38724
- const initResponseData = meta?.data;
38725
- if (initResponseData) {
38726
- for (const [entityType, records] of Object.entries(initResponseData)) {
38727
- if (Array.isArray(records)) {
38728
- entityStore.setAll(entityType, records);
38729
- }
38730
- }
38731
- }
38732
38722
  applyServerEffects(effects, uiSlots, onNavigate);
38733
38723
  }
38734
38724
  })();
@@ -38761,19 +38751,6 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
38761
38751
  if (!orbitals) return [];
38762
38752
  return orbitals.filter((o) => typeof o.name === "string").map((o) => o.name);
38763
38753
  }, [schema]);
38764
- const entityStore = providers.useEntityStore();
38765
- const seededRef = React116.useRef("");
38766
- const mockKey = mockData ? Object.keys(mockData).sort().join(",") : "";
38767
- React116__namespace.default.useLayoutEffect(() => {
38768
- if (!serverUrl && mockData && seededRef.current !== mockKey) {
38769
- seededRef.current = mockKey;
38770
- for (const [entityType, records] of Object.entries(mockData)) {
38771
- if (Array.isArray(records)) {
38772
- entityStore.setAll(entityType, records);
38773
- }
38774
- }
38775
- }
38776
- }, [mockKey, serverUrl, mockData, entityStore]);
38777
38754
  const inner = /* @__PURE__ */ jsxRuntime.jsx(providers.VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxRuntime.jsx(SlotsProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(EntitySchemaProvider, { entities: Array.from(allEntities.values()), children: [
38778
38755
  /* @__PURE__ */ jsxRuntime.jsx(
38779
38756
  TraitInitializer,
@@ -1,4 +1,4 @@
1
- /* node_modules/.pnpm/katex@0.16.33/node_modules/katex/dist/katex.min.css */
1
+ /* node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css */
2
2
  @font-face {
3
3
  font-display: block;
4
4
  font-family: KaTeX_AMS;
@@ -205,6 +205,7 @@
205
205
  Times New Roman,
206
206
  serif;
207
207
  line-height: 1.2;
208
+ position: relative;
208
209
  text-indent: 0;
209
210
  text-rendering: auto;
210
211
  }
@@ -213,7 +214,7 @@
213
214
  border-color: currentColor;
214
215
  }
215
216
  .katex .katex-version:after {
216
- content: "0.16.33";
217
+ content: "0.16.45";
217
218
  }
218
219
  .katex .katex-mathml {
219
220
  clip: rect(1px, 1px, 1px, 1px);
@@ -389,6 +390,10 @@
389
390
  .katex .mspace {
390
391
  display: inline-block;
391
392
  }
393
+ .katex .smash {
394
+ display: inline;
395
+ line-height: 0;
396
+ }
392
397
  .katex .clap,
393
398
  .katex .llap,
394
399
  .katex .rlap {
@@ -1,6 +1,6 @@
1
1
  import * as React116 from 'react';
2
2
  import React116__default, { createContext, useContext, useRef, useEffect, useCallback, useMemo, Suspense, useState, useLayoutEffect, lazy, useId } from 'react';
3
- import { EventBusContext, useEntityRef, OrbitalProvider, useEntityStore, VerificationProvider } from '@almadar/ui/providers';
3
+ import { EventBusContext, OrbitalProvider, VerificationProvider } from '@almadar/ui/providers';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import { clsx } from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
@@ -34,8 +34,8 @@ import langDiff from 'react-syntax-highlighter/dist/esm/languages/prism/diff.js'
34
34
  import langToml from 'react-syntax-highlighter/dist/esm/languages/prism/toml.js';
35
35
  import langGo from 'react-syntax-highlighter/dist/esm/languages/prism/go.js';
36
36
  import langGraphql from 'react-syntax-highlighter/dist/esm/languages/prism/graphql.js';
37
+ import { isCircuitEvent, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, isEntityCall, isInlineTrait } from '@almadar/core';
37
38
  import '@tanstack/react-query';
38
- import { isCircuitEvent, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, isEntityCall } from '@almadar/core';
39
39
  import { StateMachineManager, createContextFromBindings, interpolateValue, EffectExecutor } from '@almadar/runtime';
40
40
 
41
41
  var __defProp = Object.defineProperty;
@@ -157,8 +157,8 @@ function useEventListener(event, handler) {
157
157
  function useEmitEvent() {
158
158
  const eventBus = useEventBus();
159
159
  return useCallback(
160
- (type, payload) => {
161
- eventBus.emit(type, payload);
160
+ (type, payload, source) => {
161
+ eventBus.emit(type, payload, source);
162
162
  },
163
163
  [eventBus]
164
164
  );
@@ -173,11 +173,15 @@ var init_useEventBus = __esm({
173
173
  fallbackListeners = /* @__PURE__ */ new Map();
174
174
  fallbackAnyListeners = /* @__PURE__ */ new Set();
175
175
  fallbackEventBus = {
176
- emit: (type, payload) => {
176
+ emit: (type, payload, source) => {
177
177
  const event = {
178
178
  type,
179
+ // Narrow at the bus boundary: public emit accepts an opaque object so
180
+ // generic UI emit sites don't require casts; the envelope stores the
181
+ // payload as EventPayload which listeners consume directly.
179
182
  payload,
180
- timestamp: Date.now()
183
+ timestamp: Date.now(),
184
+ source
181
185
  };
182
186
  const handlers = fallbackListeners.get(type);
183
187
  log.debug("emit", { type, payloadKeys: payload ? Object.keys(payload).length : 0, listenerCount: (handlers?.size ?? 0) + fallbackAnyListeners.size });
@@ -10364,9 +10368,9 @@ var init_ScaledDiagram = __esm({
10364
10368
  }
10365
10369
  });
10366
10370
 
10367
- // node_modules/.pnpm/katex@0.16.33/node_modules/katex/dist/katex.min.css
10371
+ // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
10368
10372
  var init_katex_min = __esm({
10369
- "node_modules/.pnpm/katex@0.16.33/node_modules/katex/dist/katex.min.css"() {
10373
+ "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
10370
10374
  }
10371
10375
  });
10372
10376
  var MarkdownContent;
@@ -12365,7 +12369,9 @@ function extractTrait(schema, trait, traitIndex) {
12365
12369
  for (const orbital of schema.orbitals) {
12366
12370
  const traits2 = orbital.traits ?? [];
12367
12371
  if (traitIndex < traits2.length) {
12368
- return traits2[traitIndex];
12372
+ const traitRef = traits2[traitIndex];
12373
+ if (isInlineTrait(traitRef)) return traitRef;
12374
+ return null;
12369
12375
  }
12370
12376
  }
12371
12377
  return null;
@@ -12373,8 +12379,10 @@ function extractTrait(schema, trait, traitIndex) {
12373
12379
  function extractEntityFields(schema) {
12374
12380
  if (!schema?.orbitals?.length) return [];
12375
12381
  const entity = schema.orbitals[0].entity;
12376
- if (!entity?.fields) return [];
12377
- return entity.fields.map((f3) => f3.name);
12382
+ if (!entity || typeof entity !== "object" || !("fields" in entity)) return [];
12383
+ const inlineEntity = entity;
12384
+ if (!inlineEntity.fields) return [];
12385
+ return inlineEntity.fields.map((f3) => f3.name);
12378
12386
  }
12379
12387
  function toStateMachineDefinition(sm) {
12380
12388
  return {
@@ -12669,12 +12677,18 @@ var init_ContentRenderer = __esm({
12669
12677
  );
12670
12678
  case "orbital": {
12671
12679
  const parsed = segment.schema;
12680
+ const inlineTrait = {
12681
+ name: "inline",
12682
+ scope: "instance",
12683
+ stateMachine: parsed
12684
+ };
12672
12685
  const schema = Array.isArray(parsed.orbitals) ? parsed : {
12686
+ name: "inline",
12673
12687
  orbitals: [{
12674
- traits: [{
12675
- name: "inline",
12676
- stateMachine: parsed
12677
- }]
12688
+ name: "inline",
12689
+ entity: { name: "inline", fields: [] },
12690
+ traits: [inlineTrait],
12691
+ pages: []
12678
12692
  }]
12679
12693
  };
12680
12694
  return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
@@ -37529,19 +37543,15 @@ function SlotContentRenderer({
37529
37543
  patternPath
37530
37544
  }) {
37531
37545
  const entityProp = content.props.entity;
37532
- const entityType = typeof entityProp === "string" ? entityProp : "";
37533
- const storeData = useEntityRef(entityType);
37534
- React116__default.useEffect(() => {
37535
- if (!entityType) return;
37536
- if (typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production") return;
37537
- if (STRING_ENTITY_WARNED.has(entityType)) return;
37538
- STRING_ENTITY_WARNED.add(entityType);
37539
- console.warn(
37540
- `[UISlotRenderer] String-entity binding '${entityType}' is deprecated. Pass 'items' or 'entity' as a value prop resolved from @payload.data. See docs/Almadar_Entity_V2_Plan.md \xA75.`
37541
- );
37542
- }, [entityType]);
37546
+ if (typeof entityProp === "string" && entityProp.length > 0) {
37547
+ if (typeof process !== "undefined" && process.env && process.env.NODE_ENV !== "production") {
37548
+ throw new Error(
37549
+ `[UISlotRenderer] Received string 'entity: "${entityProp}"' at render time. The V2 flow requires pre-resolved data; declare a fetch success listener and pass 'entity: @payload.data'. See docs/Almadar_Entity_V2_Plan.md \xA76.`
37550
+ );
37551
+ }
37552
+ }
37543
37553
  const schemaCtx = useEntitySchemaOptional();
37544
- const entityDef = entityType && schemaCtx ? schemaCtx.entities.get(entityType) : void 0;
37554
+ const entityDef = typeof entityProp === "string" && entityProp.length > 0 && schemaCtx ? schemaCtx.entities.get(entityProp) : void 0;
37545
37555
  const PatternComponent = getComponentForPattern(content.pattern);
37546
37556
  if (PatternComponent) {
37547
37557
  const childrenConfig = content.props.children;
@@ -37550,12 +37560,7 @@ function SlotContentRenderer({
37550
37560
  const renderedChildren = hasChildren ? renderPatternChildren(childrenConfig, onDismiss, content.id, myPath) : void 0;
37551
37561
  const { children: _childrenConfig, ...restProps } = content.props;
37552
37562
  const renderedProps = renderPatternProps(restProps, onDismiss);
37553
- let finalProps;
37554
- if (entityType) {
37555
- finalProps = { ...renderedProps, entity: storeData };
37556
- } else {
37557
- finalProps = renderedProps;
37558
- }
37563
+ const finalProps = renderedProps;
37559
37564
  const resolvedItems = Array.isArray(
37560
37565
  finalProps.entity
37561
37566
  ) ? finalProps.entity : null;
@@ -37569,9 +37574,6 @@ function SlotContentRenderer({
37569
37574
  const isFormPattern = FORM_PATTERNS.has(content.pattern) || content.pattern.includes("form");
37570
37575
  if (isFormPattern && entityDef && Array.isArray(finalProps.fields)) {
37571
37576
  finalProps.fields = enrichFormFields(finalProps.fields, entityDef);
37572
- if (finalProps.mode === "edit" && !finalProps.initialData && storeData.length > 0) {
37573
- finalProps.initialData = storeData[0];
37574
- }
37575
37577
  }
37576
37578
  const acceptsChildren = PATTERNS_WITH_CHILDREN.has(content.pattern);
37577
37579
  return /* @__PURE__ */ jsx(
@@ -37665,7 +37667,7 @@ function UISlotRenderer({
37665
37667
  }
37666
37668
  return wrapped;
37667
37669
  }
37668
- var TRAIT_BINDING_RE, STRING_ENTITY_WARNED, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, FORM_PATTERNS, PATTERNS_WITH_CHILDREN;
37670
+ var TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, FORM_PATTERNS, PATTERNS_WITH_CHILDREN;
37669
37671
  var init_UISlotRenderer = __esm({
37670
37672
  "components/organisms/UISlotRenderer.tsx"() {
37671
37673
  "use client";
@@ -37682,7 +37684,6 @@ var init_UISlotRenderer = __esm({
37682
37684
  init_TraitFrame();
37683
37685
  init_component_registry_generated();
37684
37686
  TRAIT_BINDING_RE = /^@trait\.([A-Z][A-Za-z0-9]*)$/;
37685
- STRING_ENTITY_WARNED = /* @__PURE__ */ new Set();
37686
37687
  SuspenseConfigContext = createContext({ enabled: false });
37687
37688
  SlotContainedContext = createContext(false);
37688
37689
  SuspenseConfigProvider.displayName = "SuspenseConfigProvider";
@@ -37898,6 +37899,9 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
37898
37899
  const currentState = traitStatesRef.current.get(binding.trait.name)?.currentState ?? "";
37899
37900
  if (tick.appliesTo.length > 0 && !tick.appliesTo.includes(currentState)) return;
37900
37901
  const bindingCtx = { entity: {}, payload: {}, state: currentState };
37902
+ if (binding.config) {
37903
+ bindingCtx.config = binding.config;
37904
+ }
37901
37905
  const evalCtx = createContextFromBindings(bindingCtx);
37902
37906
  if (tick.guard !== void 0) {
37903
37907
  const passed = interpolateValue(tick.guard, evalCtx);
@@ -38030,6 +38034,9 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38030
38034
  payload: payload || {},
38031
38035
  state: result.previousState
38032
38036
  };
38037
+ if (binding.config) {
38038
+ bindingCtx.config = binding.config;
38039
+ }
38033
38040
  const effectContext = {
38034
38041
  traitName: binding.trait.name,
38035
38042
  state: result.previousState,
@@ -38510,7 +38517,7 @@ function buildMockData(schema) {
38510
38517
  }
38511
38518
  return result;
38512
38519
  }
38513
- function isInlineTrait(traitRef) {
38520
+ function isInlineTrait2(traitRef) {
38514
38521
  return typeof traitRef === "object" && traitRef !== null && "stateMachine" in traitRef;
38515
38522
  }
38516
38523
  function findDataState(sm, initialStateName) {
@@ -38542,7 +38549,7 @@ function adjustSchemaForMockData(schema, mockData) {
38542
38549
  const updatedOrbitals = schema.orbitals.map((orbital) => {
38543
38550
  const traits2 = orbital.traits ?? [];
38544
38551
  const updatedTraits = traits2.map((traitRef) => {
38545
- if (!isInlineTrait(traitRef)) return traitRef;
38552
+ if (!isInlineTrait2(traitRef)) return traitRef;
38546
38553
  const updated = rewriteTraitInitialState(traitRef, mockData);
38547
38554
  if (updated !== traitRef) changed = true;
38548
38555
  return updated;
@@ -38620,23 +38627,14 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
38620
38627
  const slotsActions = useSlotsActions();
38621
38628
  const bridge = useServerBridge();
38622
38629
  const uiSlots = useUISlots();
38623
- const entityStore = useEntityStore();
38624
38630
  const onEventProcessed = useCallback(async (event, payload) => {
38625
38631
  if (!bridge.connected || !orbitalNames?.length) return;
38626
38632
  for (const name of orbitalNames) {
38627
38633
  const { effects, meta } = await bridge.sendEvent(name, event, payload);
38628
38634
  recordServerResponse(name, event, meta);
38629
- const responseData = meta?.data;
38630
- if (responseData) {
38631
- for (const [entityType, records] of Object.entries(responseData)) {
38632
- if (Array.isArray(records)) {
38633
- entityStore.setAll(entityType, records);
38634
- }
38635
- }
38636
- }
38637
38635
  applyServerEffects(effects, uiSlots, onNavigate);
38638
38636
  }
38639
- }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, entityStore]);
38637
+ }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate]);
38640
38638
  const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate } : { navigate: onNavigate };
38641
38639
  const { sendEvent } = useTraitStateMachine(traits2, slotsActions, opts);
38642
38640
  const initSentRef = useRef(false);
@@ -38676,14 +38674,6 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
38676
38674
  effects: effectTraces,
38677
38675
  timestamp: Date.now()
38678
38676
  });
38679
- const initResponseData = meta?.data;
38680
- if (initResponseData) {
38681
- for (const [entityType, records] of Object.entries(initResponseData)) {
38682
- if (Array.isArray(records)) {
38683
- entityStore.setAll(entityType, records);
38684
- }
38685
- }
38686
- }
38687
38677
  applyServerEffects(effects, uiSlots, onNavigate);
38688
38678
  }
38689
38679
  })();
@@ -38716,19 +38706,6 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
38716
38706
  if (!orbitals) return [];
38717
38707
  return orbitals.filter((o) => typeof o.name === "string").map((o) => o.name);
38718
38708
  }, [schema]);
38719
- const entityStore = useEntityStore();
38720
- const seededRef = useRef("");
38721
- const mockKey = mockData ? Object.keys(mockData).sort().join(",") : "";
38722
- React116__default.useLayoutEffect(() => {
38723
- if (!serverUrl && mockData && seededRef.current !== mockKey) {
38724
- seededRef.current = mockKey;
38725
- for (const [entityType, records] of Object.entries(mockData)) {
38726
- if (Array.isArray(records)) {
38727
- entityStore.setAll(entityType, records);
38728
- }
38729
- }
38730
- }
38731
- }, [mockKey, serverUrl, mockData, entityStore]);
38732
38709
  const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsx(SlotsProvider, { children: /* @__PURE__ */ jsxs(EntitySchemaProvider, { entities: Array.from(allEntities.values()), children: [
38733
38710
  /* @__PURE__ */ jsx(
38734
38711
  TraitInitializer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "2.61.1",
3
+ "version": "3.1.2",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",
@@ -118,10 +118,10 @@
118
118
  "access": "public"
119
119
  },
120
120
  "dependencies": {
121
- "@almadar/core": ">=4.8.2",
122
- "@almadar/evaluator": ">=2.8.1",
121
+ "@almadar/core": ">=5.3.1",
122
+ "@almadar/evaluator": ">=2.9.2",
123
123
  "@almadar/patterns": ">=2.14.1",
124
- "@almadar/runtime": ">=3.2.6",
124
+ "@almadar/runtime": ">=4.2.7",
125
125
  "@almadar/std": ">=6.4.1",
126
126
  "@almadar/syntax": ">=1.3.1",
127
127
  "@xyflow/react": "12.10.1",
@@ -1,63 +0,0 @@
1
- /**
2
- * EntityStoreProvider
3
- *
4
- * Normalized reactive entity store for Orbital applications.
5
- * Stores entities in ID-keyed Maps with ordered ID lists.
6
- * Provides operation-specific methods (setAll, upsertOne, addOne,
7
- * updateOne, removeOne) and selector hooks (useEntityRef for
8
- * collections, useEntityById for single entities).
9
- *
10
- * Every mutation creates new Map/array objects (immutable values).
11
- * Identity (the store key) advances to a new value on each write.
12
- * Follows the Clojure epochal time model from Almadar_Orb_IO.md.
13
- *
14
- * @packageDocumentation
15
- */
16
- import React, { type ReactNode } from 'react';
17
- type StoreListener = () => void;
18
- type WatchCallback = (oldData: unknown[], newData: unknown[]) => void;
19
- export declare function subscribeToStore(listener: StoreListener): () => void;
20
- /**
21
- * Subscribe to an entity collection reactively.
22
- * Returns the full ordered array. Re-renders when the collection changes.
23
- *
24
- * Client-side implementation of `["ref", "EntityType"]`.
25
- */
26
- export declare function useEntityRef(entityType: string): unknown[];
27
- /**
28
- * Subscribe to a single entity by ID reactively.
29
- * Returns the entity record or null. Re-renders when the entity changes.
30
- *
31
- * Client-side implementation of `["fetch", "EntityType", { id: ... }]`.
32
- */
33
- export declare function useEntityById(entityType: string, id: string | undefined): Record<string, unknown> | null;
34
- /**
35
- * Register a callback that fires when an entity collection changes.
36
- * Receives (oldData, newData) for side effects (notify, emit, log).
37
- *
38
- * Client-side implementation of `["watch", "EntityType", effects]`.
39
- */
40
- export declare function useEntityWatch(entityType: string, callback: WatchCallback): void;
41
- export interface EntityStoreContextValue {
42
- setAll: (entityType: string, records: unknown[]) => void;
43
- upsertOne: (entityType: string, record: Record<string, unknown>) => void;
44
- addOne: (entityType: string, record: Record<string, unknown>) => void;
45
- updateOne: (entityType: string, id: string, changes: Partial<Record<string, unknown>>) => void;
46
- removeOne: (entityType: string, id: string) => void;
47
- getSnapshot: (entityType: string) => unknown[];
48
- getById: (entityType: string, id: string) => Record<string, unknown> | null;
49
- }
50
- export declare const EntityStoreContext: React.Context<EntityStoreContextValue>;
51
- /**
52
- * Access the entity store operations.
53
- * Used by useOrbitalBridge and OrbPreview to push server response data into the store.
54
- */
55
- export declare function useEntityStore(): EntityStoreContextValue;
56
- /**
57
- * Provider component. Wrap the app or page with this to enable entity reactivity.
58
- * Already included in OrbitalProvider.
59
- */
60
- export declare function EntityStoreProvider({ children }: {
61
- children: ReactNode;
62
- }): React.ReactElement;
63
- export {};