@almadar/ui 4.6.14 → 4.8.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.
@@ -245,6 +245,8 @@ interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
245
245
  subtitle?: string;
246
246
  /** Shadow size override */
247
247
  shadow?: CardShadow;
248
+ /** Card content */
249
+ children?: React.ReactNode;
248
250
  }
249
251
  declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
250
252
 
@@ -1772,6 +1772,7 @@ var init_SlotsContext = __esm({
1772
1772
  "runtime/ui/SlotsContext.tsx"() {
1773
1773
  init_logger();
1774
1774
  slotLog = createLogger("almadar:ui:slot-render");
1775
+ createLogger("almadar:runtime:cross-orbital");
1775
1776
  refIds = /* @__PURE__ */ new WeakMap();
1776
1777
  nextRefId = 1;
1777
1778
  React116.createContext({});
@@ -9057,9 +9058,9 @@ function bindEventBus(eventBus) {
9057
9058
  log2.info("bindEventBus", { hasOnAny: !!eventBus.onAny });
9058
9059
  exposeOnWindow();
9059
9060
  if (window.__orbitalVerification) {
9060
- window.__orbitalVerification.sendEvent = (event, payload) => {
9061
- const prefixed = event.startsWith("UI:") ? event : `UI:${event}`;
9062
- log2.debug("sendEvent", { event: prefixed, payloadKeys: payload ? Object.keys(payload) : [] });
9061
+ window.__orbitalVerification.sendEvent = (event, payload, traitScope) => {
9062
+ const prefixed = event.startsWith("UI:") ? event : traitScope ? `UI:${traitScope}.${event}` : `UI:${event}`;
9063
+ log2.debug("sendEvent", { event: prefixed, traitScope, payloadKeys: payload ? Object.keys(payload) : [] });
9063
9064
  eventBus.emit(prefixed, payload);
9064
9065
  };
9065
9066
  const eventLog = [];
@@ -18650,8 +18651,7 @@ function formatValue(value, format) {
18650
18651
  }
18651
18652
  function DataGrid({
18652
18653
  entity,
18653
- fields: fieldsProp,
18654
- columns: columnsProp,
18654
+ fields,
18655
18655
  itemActions,
18656
18656
  cols,
18657
18657
  gap = "md",
@@ -18672,7 +18672,6 @@ function DataGrid({
18672
18672
  const { t } = useTranslate();
18673
18673
  const [selectedIds, setSelectedIds] = React116.useState(/* @__PURE__ */ new Set());
18674
18674
  const [visibleCount, setVisibleCount] = React116.useState(pageSize || Infinity);
18675
- const fields = fieldsProp ?? columnsProp ?? [];
18676
18675
  const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
18677
18676
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
18678
18677
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
@@ -19015,8 +19014,7 @@ function groupData(items, field) {
19015
19014
  }
19016
19015
  function DataList({
19017
19016
  entity,
19018
- fields: fieldsProp,
19019
- columns: columnsProp,
19017
+ fields,
19020
19018
  itemActions,
19021
19019
  gap = "none",
19022
19020
  variant = "default",
@@ -19045,7 +19043,6 @@ function DataList({
19045
19043
  const eventBus = useEventBus();
19046
19044
  const { t } = useTranslate();
19047
19045
  const [visibleCount, setVisibleCount] = React116__namespace.default.useState(pageSize || Infinity);
19048
- const fields = fieldsProp ?? columnsProp ?? [];
19049
19046
  const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
19050
19047
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
19051
19048
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
@@ -1727,6 +1727,7 @@ var init_SlotsContext = __esm({
1727
1727
  "runtime/ui/SlotsContext.tsx"() {
1728
1728
  init_logger();
1729
1729
  slotLog = createLogger("almadar:ui:slot-render");
1730
+ createLogger("almadar:runtime:cross-orbital");
1730
1731
  refIds = /* @__PURE__ */ new WeakMap();
1731
1732
  nextRefId = 1;
1732
1733
  createContext({});
@@ -9012,9 +9013,9 @@ function bindEventBus(eventBus) {
9012
9013
  log2.info("bindEventBus", { hasOnAny: !!eventBus.onAny });
9013
9014
  exposeOnWindow();
9014
9015
  if (window.__orbitalVerification) {
9015
- window.__orbitalVerification.sendEvent = (event, payload) => {
9016
- const prefixed = event.startsWith("UI:") ? event : `UI:${event}`;
9017
- log2.debug("sendEvent", { event: prefixed, payloadKeys: payload ? Object.keys(payload) : [] });
9016
+ window.__orbitalVerification.sendEvent = (event, payload, traitScope) => {
9017
+ const prefixed = event.startsWith("UI:") ? event : traitScope ? `UI:${traitScope}.${event}` : `UI:${event}`;
9018
+ log2.debug("sendEvent", { event: prefixed, traitScope, payloadKeys: payload ? Object.keys(payload) : [] });
9018
9019
  eventBus.emit(prefixed, payload);
9019
9020
  };
9020
9021
  const eventLog = [];
@@ -18605,8 +18606,7 @@ function formatValue(value, format) {
18605
18606
  }
18606
18607
  function DataGrid({
18607
18608
  entity,
18608
- fields: fieldsProp,
18609
- columns: columnsProp,
18609
+ fields,
18610
18610
  itemActions,
18611
18611
  cols,
18612
18612
  gap = "md",
@@ -18627,7 +18627,6 @@ function DataGrid({
18627
18627
  const { t } = useTranslate();
18628
18628
  const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
18629
18629
  const [visibleCount, setVisibleCount] = useState(pageSize || Infinity);
18630
- const fields = fieldsProp ?? columnsProp ?? [];
18631
18630
  const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
18632
18631
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
18633
18632
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
@@ -18970,8 +18969,7 @@ function groupData(items, field) {
18970
18969
  }
18971
18970
  function DataList({
18972
18971
  entity,
18973
- fields: fieldsProp,
18974
- columns: columnsProp,
18972
+ fields,
18975
18973
  itemActions,
18976
18974
  gap = "none",
18977
18975
  variant = "default",
@@ -19000,7 +18998,6 @@ function DataList({
19000
18998
  const eventBus = useEventBus();
19001
18999
  const { t } = useTranslate();
19002
19000
  const [visibleCount, setVisibleCount] = React116__default.useState(pageSize || Infinity);
19003
- const fields = fieldsProp ?? columnsProp ?? [];
19004
19001
  const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
19005
19002
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
19006
19003
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
@@ -42,6 +42,14 @@ export interface OrbPreviewProps {
42
42
  className?: string;
43
43
  /** Server URL for dual execution (e.g. "/api/orbitals"). When set, events are forwarded to the server. */
44
44
  serverUrl?: string;
45
+ /**
46
+ * Initial page path to render (e.g. `/deals`). Resolves against the
47
+ * schema's `pages[]` to seed `currentPage` so the right orbital's traits
48
+ * mount on first render. Without this the playground falls back to the
49
+ * schema's first page binding (gap #13 Phase 5). runtime-verify uses this
50
+ * to walk DealCreate, NoteCompose, etc. on their owning pages.
51
+ */
52
+ initialPagePath?: string;
45
53
  }
46
54
  /**
47
55
  * Renders a live preview of an Orbital schema.
@@ -56,7 +64,7 @@ export interface OrbPreviewProps {
56
64
  * <OrbPreview schema={schema} serverUrl="/api/orbitals" />
57
65
  * ```
58
66
  */
59
- export declare function OrbPreview({ schema, mockData, autoMock, height, className, serverUrl, }: OrbPreviewProps): React.ReactElement;
67
+ export declare function OrbPreview({ schema, mockData, autoMock, height, className, serverUrl, initialPagePath, }: OrbPreviewProps): React.ReactElement;
60
68
  export declare namespace OrbPreview {
61
69
  var displayName: string;
62
70
  }
@@ -1116,13 +1116,23 @@ function SlotsProvider({ children }) {
1116
1116
  const setSlotPatterns = React115.useCallback((slot, patterns, source) => {
1117
1117
  const sourceKey = source?.trait ?? DEFAULT_SOURCE_KEY;
1118
1118
  const entityProp = patterns[0]?.pattern && typeof patterns[0].pattern === "object" ? patterns[0].pattern.entity : void 0;
1119
+ const firstPatternType = patterns[0]?.pattern && typeof patterns[0].pattern === "object" ? patterns[0].pattern.type : void 0;
1119
1120
  slotLog.debug("setSlotPatterns", {
1120
1121
  slot,
1121
1122
  sourceKey,
1122
1123
  patternCount: patterns.length,
1123
- firstPatternType: patterns[0]?.pattern && typeof patterns[0].pattern === "object" ? patterns[0].pattern.type : void 0,
1124
+ firstPatternType,
1124
1125
  entityRefId: refId(entityProp)
1125
1126
  });
1127
+ if (source?.trait) {
1128
+ xOrbitalLog.info("slot-set", {
1129
+ slot,
1130
+ sourceTrait: source.trait,
1131
+ patternCount: patterns.length,
1132
+ firstPatternType,
1133
+ state: source.state
1134
+ });
1135
+ }
1126
1136
  setSlots((prev) => {
1127
1137
  const prevSlot = prev[slot] ?? {};
1128
1138
  return {
@@ -1144,6 +1154,7 @@ function SlotsProvider({ children }) {
1144
1154
  });
1145
1155
  }, []);
1146
1156
  const clearSlotForSource = React115.useCallback((slot, sourceTrait) => {
1157
+ xOrbitalLog.info("slot-clear-source", { slot, sourceTrait });
1147
1158
  setSlots((prev) => {
1148
1159
  const existing = prev[slot];
1149
1160
  if (!existing || !(sourceTrait in existing)) return prev;
@@ -1184,11 +1195,12 @@ function useSlotsActions() {
1184
1195
  }
1185
1196
  return actions;
1186
1197
  }
1187
- var slotLog, refIds, nextRefId, DEFAULT_SOURCE_KEY, SlotsStateContext, SlotsActionsContext;
1198
+ var slotLog, xOrbitalLog, refIds, nextRefId, DEFAULT_SOURCE_KEY, SlotsStateContext, SlotsActionsContext;
1188
1199
  var init_SlotsContext = __esm({
1189
1200
  "runtime/ui/SlotsContext.tsx"() {
1190
1201
  init_logger();
1191
1202
  slotLog = createLogger("almadar:ui:slot-render");
1203
+ xOrbitalLog = createLogger("almadar:runtime:cross-orbital");
1192
1204
  refIds = /* @__PURE__ */ new WeakMap();
1193
1205
  nextRefId = 1;
1194
1206
  DEFAULT_SOURCE_KEY = "__default__";
@@ -8182,7 +8194,7 @@ var init_MapView = __esm({
8182
8194
  shadowSize: [41, 41]
8183
8195
  });
8184
8196
  L.Marker.prototype.options.icon = defaultIcon;
8185
- const { useEffect: useEffect68, useRef: useRef65, useCallback: useCallback110, useState: useState103 } = React115__namespace.default;
8197
+ const { useEffect: useEffect68, useRef: useRef65, useCallback: useCallback110, useState: useState102 } = React115__namespace.default;
8186
8198
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
8187
8199
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
8188
8200
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -8226,7 +8238,7 @@ var init_MapView = __esm({
8226
8238
  showAttribution = true
8227
8239
  }) {
8228
8240
  const eventBus = useEventBus2();
8229
- const [clickedPosition, setClickedPosition] = useState103(null);
8241
+ const [clickedPosition, setClickedPosition] = useState102(null);
8230
8242
  const handleMapClick = useCallback110((lat, lng) => {
8231
8243
  if (showClickedPin) {
8232
8244
  setClickedPosition({ lat, lng });
@@ -18539,8 +18551,7 @@ function formatValue(value, format) {
18539
18551
  }
18540
18552
  function DataGrid({
18541
18553
  entity,
18542
- fields: fieldsProp,
18543
- columns: columnsProp,
18554
+ fields,
18544
18555
  itemActions,
18545
18556
  cols,
18546
18557
  gap = "md",
@@ -18561,7 +18572,6 @@ function DataGrid({
18561
18572
  const { t } = useTranslate();
18562
18573
  const [selectedIds, setSelectedIds] = React115.useState(/* @__PURE__ */ new Set());
18563
18574
  const [visibleCount, setVisibleCount] = React115.useState(pageSize || Infinity);
18564
- const fields = fieldsProp ?? columnsProp ?? [];
18565
18575
  const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
18566
18576
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
18567
18577
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
@@ -18904,8 +18914,7 @@ function groupData(items, field) {
18904
18914
  }
18905
18915
  function DataList({
18906
18916
  entity,
18907
- fields: fieldsProp,
18908
- columns: columnsProp,
18917
+ fields,
18909
18918
  itemActions,
18910
18919
  gap = "none",
18911
18920
  variant = "default",
@@ -18934,7 +18943,6 @@ function DataList({
18934
18943
  const eventBus = useEventBus();
18935
18944
  const { t } = useTranslate();
18936
18945
  const [visibleCount, setVisibleCount] = React115__namespace.default.useState(pageSize || Infinity);
18937
- const fields = fieldsProp ?? columnsProp ?? [];
18938
18946
  const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
18939
18947
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
18940
18948
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
@@ -38179,6 +38187,7 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38179
38187
  const eventBus = useEventBus();
38180
38188
  const { entities } = useEntitySchema();
38181
38189
  const traitConfigsByName = options?.traitConfigsByName;
38190
+ const orbitalsByTrait = options?.orbitalsByTrait;
38182
38191
  const manager = React115.useMemo(() => {
38183
38192
  const traitDefs = traitBindings.map(toTraitDefinition);
38184
38193
  const m = new runtime.StateMachineManager(traitDefs);
@@ -38627,7 +38636,10 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38627
38636
  if (!LIFECYCLE_EVENTS.has(normalizedEvent)) {
38628
38637
  for (const { traitName, result } of results) {
38629
38638
  if (!result.executed) continue;
38630
- eventBus.emit(normalizedEvent, payload, {
38639
+ const orbitalName = orbitalsByTrait?.[traitName];
38640
+ if (!orbitalName) continue;
38641
+ eventBus.emit(`UI:${orbitalName}.${traitName}.${normalizedEvent}`, payload, {
38642
+ orbital: orbitalName,
38631
38643
  trait: traitName,
38632
38644
  fromBridge: true
38633
38645
  });
@@ -38638,7 +38650,13 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38638
38650
  }
38639
38651
  const onEventProcessed = optionsRef.current?.onEventProcessed;
38640
38652
  if (onEventProcessed) {
38641
- await onEventProcessed(normalizedEvent, payload);
38653
+ const dispatchedOrbitals = /* @__PURE__ */ new Set();
38654
+ for (const { traitName, result } of results) {
38655
+ if (!result.executed) continue;
38656
+ const orbital = orbitalsByTrait?.[traitName];
38657
+ if (orbital) dispatchedOrbitals.add(orbital);
38658
+ }
38659
+ await onEventProcessed(normalizedEvent, payload, dispatchedOrbitals);
38642
38660
  }
38643
38661
  }, [entities, eventBus]);
38644
38662
  const drainEventQueue = React115.useCallback(async () => {
@@ -38682,26 +38700,34 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38682
38700
  }
38683
38701
  console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
38684
38702
  const unsubscribes = [];
38685
- for (const eventKey of allEvents) {
38686
- if (eventKey === "INIT" || eventKey === "LOAD" || eventKey === "$MOUNT") {
38687
- continue;
38703
+ for (const binding of traitBindings) {
38704
+ const traitName = binding.trait.name;
38705
+ const orbitalName = orbitalsByTrait?.[traitName];
38706
+ if (!orbitalName) continue;
38707
+ for (const transition of binding.trait.transitions) {
38708
+ const eventKey = transition.event;
38709
+ if (eventKey === "INIT" || eventKey === "LOAD" || eventKey === "$MOUNT") {
38710
+ continue;
38711
+ }
38712
+ const unsub = eventBus.on(`UI:${orbitalName}.${traitName}.${eventKey}`, (event) => {
38713
+ if (event.source && event.source.fromBridge) {
38714
+ return;
38715
+ }
38716
+ enqueueAndDrain(eventKey, event.payload);
38717
+ });
38718
+ unsubscribes.push(unsub);
38688
38719
  }
38689
- const unsub = eventBus.on(`UI:${eventKey}`, (event) => {
38690
- console.log("[TraitStateMachine] Received event:", `UI:${eventKey}`, event);
38691
- enqueueAndDrain(eventKey, event.payload);
38692
- });
38693
- unsubscribes.push(unsub);
38694
38720
  }
38695
38721
  for (const binding of traitBindings) {
38722
+ const ownOrbital = orbitalsByTrait?.[binding.trait.name];
38696
38723
  const listens = binding.trait.listens ?? [];
38697
38724
  for (const listen of listens) {
38698
- const expectedTrait = listen.source?.trait;
38699
- const unsub = eventBus.on(listen.event, (event) => {
38700
- if (expectedTrait) {
38701
- const emitTrait = event.source?.trait;
38702
- if (emitTrait !== expectedTrait) return;
38703
- }
38704
- console.log("[TraitStateMachine] listens", binding.trait.name, listen.event, "\u2192", listen.triggers, "from", event.source?.trait);
38725
+ const sourceTrait = listen.source?.trait;
38726
+ if (!sourceTrait) continue;
38727
+ const sourceOrbital = listen.source?.orbital ?? ownOrbital;
38728
+ if (!sourceOrbital) continue;
38729
+ const busKey = `UI:${sourceOrbital}.${sourceTrait}.${listen.event}`;
38730
+ const unsub = eventBus.on(busKey, (event) => {
38705
38731
  enqueueAndDrain(listen.triggers, event.payload);
38706
38732
  });
38707
38733
  unsubscribes.push(unsub);
@@ -38848,6 +38874,8 @@ init_EntitySchemaContext();
38848
38874
 
38849
38875
  // runtime/ServerBridge.tsx
38850
38876
  init_useEventBus();
38877
+ init_logger();
38878
+ var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
38851
38879
  var ServerBridgeContext = React115.createContext(null);
38852
38880
  function useServerBridge() {
38853
38881
  const ctx = React115.useContext(ServerBridgeContext);
@@ -38925,8 +38953,22 @@ function ServerBridgeProvider({
38925
38953
  }
38926
38954
  if (result.emittedEvents) {
38927
38955
  for (const emitted of result.emittedEvents) {
38928
- eventBus.emit(`UI:${emitted.event}`, emitted.payload);
38929
- eventBus.emit(emitted.event, emitted.payload);
38956
+ const evTrait = emitted.source?.trait;
38957
+ if (!evTrait) {
38958
+ xOrbitalLog2.warn("emit:dropped-no-source", {
38959
+ event: emitted.event,
38960
+ dispatchOrbital: orbitalName
38961
+ });
38962
+ continue;
38963
+ }
38964
+ const key = emitted.source?.orbital ? `UI:${emitted.source.orbital}.${evTrait}.${emitted.event}` : `UI:${evTrait}.${emitted.event}`;
38965
+ xOrbitalLog2.info("emit:rebroadcast", {
38966
+ busKey: key,
38967
+ sourceOrbital: emitted.source?.orbital,
38968
+ sourceTrait: evTrait,
38969
+ dispatchOrbital: orbitalName
38970
+ });
38971
+ eventBus.emit(key, emitted.payload);
38930
38972
  }
38931
38973
  }
38932
38974
  } else if (result.error) {
@@ -39047,6 +39089,10 @@ function prepareSchemaForPreview(input) {
39047
39089
  const schema = adjustSchemaForMockData(parsed, mockData);
39048
39090
  return { schema, mockData };
39049
39091
  }
39092
+
39093
+ // runtime/OrbPreview.tsx
39094
+ init_logger();
39095
+ var xOrbitalLog3 = createLogger("almadar:runtime:cross-orbital");
39050
39096
  function normalizeChild(child) {
39051
39097
  if (typeof child === "string") return child;
39052
39098
  if (child === null || typeof child !== "object" || Array.isArray(child)) {
@@ -39126,6 +39172,11 @@ function applyServerEffects(effects, uiSlots, onNavigate) {
39126
39172
  const patternRecord = eff.pattern;
39127
39173
  const { type: patternType, children, ...inlineProps } = patternRecord;
39128
39174
  const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
39175
+ xOrbitalLog3.info("slot-write", {
39176
+ slot: eff.slot,
39177
+ sourceTrait: eff.traitName ?? "server",
39178
+ patternType: typeof patternType === "string" ? patternType : void 0
39179
+ });
39129
39180
  uiSlots.render({
39130
39181
  target: eff.slot,
39131
39182
  pattern: patternType,
@@ -39140,19 +39191,26 @@ function applyServerEffects(effects, uiSlots, onNavigate) {
39140
39191
  }
39141
39192
  }
39142
39193
  }
39143
- function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName }) {
39194
+ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait }) {
39144
39195
  const slotsActions = useSlotsActions();
39145
39196
  const bridge = useServerBridge();
39146
39197
  const uiSlots = context.useUISlots();
39147
- const onEventProcessed = React115.useCallback(async (event, payload) => {
39198
+ const onEventProcessed = React115.useCallback(async (event, payload, dispatchedOrbitals) => {
39148
39199
  if (!bridge.connected || !orbitalNames?.length) return;
39149
- for (const name of orbitalNames) {
39200
+ const targets = dispatchedOrbitals && dispatchedOrbitals.size > 0 ? orbitalNames.filter((n) => dispatchedOrbitals.has(n)) : orbitalNames;
39201
+ xOrbitalLog3.info("TraitInitializer:fanout", {
39202
+ event,
39203
+ sentTo: targets,
39204
+ skipped: orbitalNames.filter((n) => !targets.includes(n)),
39205
+ dispatchedOrbitalsSize: dispatchedOrbitals?.size ?? 0
39206
+ });
39207
+ for (const name of targets) {
39150
39208
  const { effects, meta } = await bridge.sendEvent(name, event, payload);
39151
39209
  recordServerResponse(name, event, meta);
39152
39210
  applyServerEffects(effects, uiSlots, onNavigate);
39153
39211
  }
39154
39212
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate]);
39155
- const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName } : { navigate: onNavigate, persistence, traitConfigsByName };
39213
+ const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait };
39156
39214
  const { sendEvent } = useTraitStateMachine(traits2, slotsActions, opts);
39157
39215
  const initSentRef = React115.useRef(false);
39158
39216
  React115.useEffect(() => {
@@ -39202,27 +39260,68 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
39202
39260
  const allPageTraits = React115.useMemo(() => {
39203
39261
  if (pageName && traits2.length > 0) return traits2;
39204
39262
  if (!ir?.pages || ir.pages.size <= 1) return traits2;
39205
- const combined = [];
39263
+ const firstPage = ir.pages.values().next().value;
39264
+ if (!firstPage) return traits2;
39265
+ const firstPageTraits = [];
39206
39266
  const seen = /* @__PURE__ */ new Set();
39207
- for (const page of ir.pages.values()) {
39208
- for (const t of page.traits) {
39209
- const binding = t;
39210
- const traitObj = binding.trait;
39211
- const name = traitObj?.name ?? binding.name ?? "";
39212
- if (name && !seen.has(name)) {
39213
- seen.add(name);
39214
- combined.push(t);
39215
- }
39267
+ for (const binding of firstPage.traits) {
39268
+ const name = binding.trait.name;
39269
+ if (name && !seen.has(name)) {
39270
+ seen.add(name);
39271
+ firstPageTraits.push(binding);
39216
39272
  }
39217
39273
  }
39218
- return combined.length > 0 ? combined : traits2;
39274
+ return firstPageTraits.length > 0 ? firstPageTraits : traits2;
39219
39275
  }, [ir, traits2, pageName]);
39220
- const orbitalNames = React115.useMemo(() => {
39276
+ React115.useMemo(() => {
39221
39277
  const parsed = schema;
39222
39278
  const orbitals = parsed?.orbitals;
39223
39279
  if (!orbitals) return [];
39224
39280
  return orbitals.filter((o) => typeof o.name === "string").map((o) => o.name);
39225
39281
  }, [schema]);
39282
+ const orbitalsByTrait = React115.useMemo(() => {
39283
+ const map = {};
39284
+ const parsed = schema;
39285
+ if (!parsed?.orbitals) return map;
39286
+ for (const orb of parsed.orbitals) {
39287
+ for (const traitRef of orb.traits) {
39288
+ let traitName;
39289
+ if (typeof traitRef === "string") {
39290
+ const parts = traitRef.split(".");
39291
+ traitName = parts[parts.length - 1];
39292
+ } else if ("ref" in traitRef && typeof traitRef.ref === "string") {
39293
+ const parts = traitRef.ref.split(".");
39294
+ traitName = traitRef.name ?? parts[parts.length - 1];
39295
+ } else if ("name" in traitRef && typeof traitRef.name === "string") {
39296
+ traitName = traitRef.name;
39297
+ }
39298
+ if (traitName) map[traitName] = orb.name;
39299
+ }
39300
+ }
39301
+ return map;
39302
+ }, [schema]);
39303
+ const pageOrbitalNames = React115.useMemo(() => {
39304
+ const set = /* @__PURE__ */ new Set();
39305
+ for (const binding of allPageTraits) {
39306
+ const orb = orbitalsByTrait[binding.trait.name];
39307
+ if (orb) set.add(orb);
39308
+ }
39309
+ return Array.from(set);
39310
+ }, [allPageTraits, orbitalsByTrait]);
39311
+ React115.useEffect(() => {
39312
+ const traitNames = allPageTraits.map((b) => b.trait.name);
39313
+ const orbitalsByTraitForPage = {};
39314
+ for (const name of traitNames) {
39315
+ const orb = orbitalsByTrait[name];
39316
+ if (orb) orbitalsByTraitForPage[name] = orb;
39317
+ }
39318
+ xOrbitalLog3.info("SchemaRunner:mount", {
39319
+ pageName,
39320
+ traitNames,
39321
+ orbitalsByTraitForPage,
39322
+ pageOrbitalNames: pageOrbitalNames.join(",")
39323
+ });
39324
+ }, [pageName, allPageTraits, orbitalsByTrait, pageOrbitalNames]);
39226
39325
  const traitConfigsByName = React115.useMemo(() => {
39227
39326
  const map = {};
39228
39327
  const parsed = schema;
@@ -39263,8 +39362,9 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
39263
39362
  TraitInitializer,
39264
39363
  {
39265
39364
  traits: allPageTraits,
39266
- orbitalNames: serverUrl ? orbitalNames : void 0,
39365
+ orbitalNames: serverUrl ? pageOrbitalNames : void 0,
39267
39366
  traitConfigsByName,
39367
+ orbitalsByTrait,
39268
39368
  onNavigate,
39269
39369
  onLocalFallback,
39270
39370
  persistence
@@ -39286,7 +39386,8 @@ function OrbPreview({
39286
39386
  autoMock = false,
39287
39387
  height = "400px",
39288
39388
  className,
39289
- serverUrl
39389
+ serverUrl,
39390
+ initialPagePath
39290
39391
  }) {
39291
39392
  const [localFallback, setLocalFallback] = React115.useState(false);
39292
39393
  const eventBus = useEventBus();
@@ -39332,7 +39433,17 @@ function OrbPreview({
39332
39433
  return [];
39333
39434
  }
39334
39435
  }, [parsedSchema]);
39335
- const [currentPage, setCurrentPage] = React115.useState(void 0);
39436
+ const initialPageName = React115.useMemo(() => {
39437
+ if (!initialPagePath) return void 0;
39438
+ const match = pages.find(({ page }) => page.path === initialPagePath);
39439
+ return match?.page.name;
39440
+ }, [pages, initialPagePath]);
39441
+ const [currentPage, setCurrentPage] = React115.useState(initialPageName);
39442
+ React115.useEffect(() => {
39443
+ if (initialPageName && initialPageName !== currentPage) {
39444
+ setCurrentPage(initialPageName);
39445
+ }
39446
+ }, [initialPageName, currentPage]);
39336
39447
  const handleNavigate = React115.useCallback((path) => {
39337
39448
  const match = pages.find(({ page }) => page.path === path);
39338
39449
  if (match) {