@almadar/ui 4.6.13 → 4.7.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.
@@ -5374,13 +5374,23 @@ function SlotsProvider({ children }) {
5374
5374
  const setSlotPatterns = React127.useCallback((slot, patterns, source) => {
5375
5375
  const sourceKey = source?.trait ?? DEFAULT_SOURCE_KEY2;
5376
5376
  const entityProp = patterns[0]?.pattern && typeof patterns[0].pattern === "object" ? patterns[0].pattern.entity : void 0;
5377
+ const firstPatternType = patterns[0]?.pattern && typeof patterns[0].pattern === "object" ? patterns[0].pattern.type : void 0;
5377
5378
  slotLog.debug("setSlotPatterns", {
5378
5379
  slot,
5379
5380
  sourceKey,
5380
5381
  patternCount: patterns.length,
5381
- firstPatternType: patterns[0]?.pattern && typeof patterns[0].pattern === "object" ? patterns[0].pattern.type : void 0,
5382
+ firstPatternType,
5382
5383
  entityRefId: refId(entityProp)
5383
5384
  });
5385
+ if (source?.trait) {
5386
+ xOrbitalLog.info("slot-set", {
5387
+ slot,
5388
+ sourceTrait: source.trait,
5389
+ patternCount: patterns.length,
5390
+ firstPatternType,
5391
+ state: source.state
5392
+ });
5393
+ }
5384
5394
  setSlots((prev) => {
5385
5395
  const prevSlot = prev[slot] ?? {};
5386
5396
  return {
@@ -5402,6 +5412,7 @@ function SlotsProvider({ children }) {
5402
5412
  });
5403
5413
  }, []);
5404
5414
  const clearSlotForSource = React127.useCallback((slot, sourceTrait) => {
5415
+ xOrbitalLog.info("slot-clear-source", { slot, sourceTrait });
5405
5416
  setSlots((prev) => {
5406
5417
  const existing = prev[slot];
5407
5418
  if (!existing || !(sourceTrait in existing)) return prev;
@@ -5438,11 +5449,12 @@ function useSlotsActions() {
5438
5449
  }
5439
5450
  return actions;
5440
5451
  }
5441
- var slotLog, refIds, nextRefId, DEFAULT_SOURCE_KEY2, SlotsStateContext, SlotsActionsContext;
5452
+ var slotLog, xOrbitalLog, refIds, nextRefId, DEFAULT_SOURCE_KEY2, SlotsStateContext, SlotsActionsContext;
5442
5453
  var init_SlotsContext = __esm({
5443
5454
  "runtime/ui/SlotsContext.tsx"() {
5444
5455
  init_logger();
5445
5456
  slotLog = createLogger("almadar:ui:slot-render");
5457
+ xOrbitalLog = createLogger("almadar:runtime:cross-orbital");
5446
5458
  refIds = /* @__PURE__ */ new WeakMap();
5447
5459
  nextRefId = 1;
5448
5460
  DEFAULT_SOURCE_KEY2 = "__default__";
@@ -11178,7 +11190,7 @@ var init_MapView = __esm({
11178
11190
  shadowSize: [41, 41]
11179
11191
  });
11180
11192
  L.Marker.prototype.options.icon = defaultIcon;
11181
- const { useEffect: useEffect87, useRef: useRef87, useCallback: useCallback125, useState: useState125 } = React127__namespace.default;
11193
+ const { useEffect: useEffect87, useRef: useRef87, useCallback: useCallback125, useState: useState124 } = React127__namespace.default;
11182
11194
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
11183
11195
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
11184
11196
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -11222,7 +11234,7 @@ var init_MapView = __esm({
11222
11234
  showAttribution = true
11223
11235
  }) {
11224
11236
  const eventBus = useEventBus3();
11225
- const [clickedPosition, setClickedPosition] = useState125(null);
11237
+ const [clickedPosition, setClickedPosition] = useState124(null);
11226
11238
  const handleMapClick = useCallback125((lat, lng) => {
11227
11239
  if (showClickedPin) {
11228
11240
  setClickedPosition({ lat, lng });
@@ -12323,9 +12335,9 @@ function bindEventBus(eventBus) {
12323
12335
  log2.info("bindEventBus", { hasOnAny: !!eventBus.onAny });
12324
12336
  exposeOnWindow();
12325
12337
  if (window.__orbitalVerification) {
12326
- window.__orbitalVerification.sendEvent = (event, payload) => {
12327
- const prefixed = event.startsWith("UI:") ? event : `UI:${event}`;
12328
- log2.debug("sendEvent", { event: prefixed, payloadKeys: payload ? Object.keys(payload) : [] });
12338
+ window.__orbitalVerification.sendEvent = (event, payload, traitScope) => {
12339
+ const prefixed = event.startsWith("UI:") ? event : traitScope ? `UI:${traitScope}.${event}` : `UI:${event}`;
12340
+ log2.debug("sendEvent", { event: prefixed, traitScope, payloadKeys: payload ? Object.keys(payload) : [] });
12329
12341
  eventBus.emit(prefixed, payload);
12330
12342
  };
12331
12343
  const eventLog = [];
@@ -51500,6 +51512,7 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
51500
51512
  const eventBus = useEventBus();
51501
51513
  const { entities } = useEntitySchema();
51502
51514
  const traitConfigsByName = options?.traitConfigsByName;
51515
+ const orbitalsByTrait = options?.orbitalsByTrait;
51503
51516
  const manager = React127.useMemo(() => {
51504
51517
  const traitDefs = traitBindings.map(toTraitDefinition);
51505
51518
  const m = new runtime.StateMachineManager(traitDefs);
@@ -51712,24 +51725,7 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
51712
51725
  const actions = slotsActionsRef.current;
51713
51726
  console.log("[TraitStateMachine] Processing event:", normalizedEvent, "payload:", payload);
51714
51727
  const bindingMap = new Map(bindings.map((b) => [b.trait.name, b]));
51715
- for (const traitName of bindingMap.keys()) {
51716
- const traitState = currentManager.getState(traitName);
51717
- eventBus.emit(`${traitName}:DISPATCH`, {
51718
- event: normalizedEvent,
51719
- payload,
51720
- currentState: traitState?.currentState
51721
- });
51722
- }
51723
51728
  const results = currentManager.sendEvent(normalizedEvent, payload);
51724
- for (const { traitName, result } of results) {
51725
- const suffix = result.executed ? "SUCCESS" : "ERROR";
51726
- eventBus.emit(`${traitName}:${normalizedEvent}:${suffix}`, {
51727
- event: normalizedEvent,
51728
- payload,
51729
- newState: result.newState,
51730
- currentState: result.previousState
51731
- });
51732
- }
51733
51729
  const emittedByTrait = /* @__PURE__ */ new Map();
51734
51730
  for (const { traitName, result } of results) {
51735
51731
  const binding = bindingMap.get(traitName);
@@ -51965,7 +51961,10 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
51965
51961
  if (!LIFECYCLE_EVENTS.has(normalizedEvent)) {
51966
51962
  for (const { traitName, result } of results) {
51967
51963
  if (!result.executed) continue;
51968
- eventBus.emit(normalizedEvent, payload, {
51964
+ const orbitalName = orbitalsByTrait?.[traitName];
51965
+ if (!orbitalName) continue;
51966
+ eventBus.emit(`UI:${orbitalName}.${traitName}.${normalizedEvent}`, payload, {
51967
+ orbital: orbitalName,
51969
51968
  trait: traitName,
51970
51969
  fromBridge: true
51971
51970
  });
@@ -51976,7 +51975,13 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
51976
51975
  }
51977
51976
  const onEventProcessed = optionsRef.current?.onEventProcessed;
51978
51977
  if (onEventProcessed) {
51979
- await onEventProcessed(normalizedEvent, payload);
51978
+ const dispatchedOrbitals = /* @__PURE__ */ new Set();
51979
+ for (const { traitName, result } of results) {
51980
+ if (!result.executed) continue;
51981
+ const orbital = orbitalsByTrait?.[traitName];
51982
+ if (orbital) dispatchedOrbitals.add(orbital);
51983
+ }
51984
+ await onEventProcessed(normalizedEvent, payload, dispatchedOrbitals);
51980
51985
  }
51981
51986
  }, [entities, eventBus]);
51982
51987
  const drainEventQueue = React127.useCallback(async () => {
@@ -52020,26 +52025,34 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
52020
52025
  }
52021
52026
  console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
52022
52027
  const unsubscribes = [];
52023
- for (const eventKey of allEvents) {
52024
- if (eventKey === "INIT" || eventKey === "LOAD" || eventKey === "$MOUNT") {
52025
- continue;
52028
+ for (const binding of traitBindings) {
52029
+ const traitName = binding.trait.name;
52030
+ const orbitalName = orbitalsByTrait?.[traitName];
52031
+ if (!orbitalName) continue;
52032
+ for (const transition of binding.trait.transitions) {
52033
+ const eventKey = transition.event;
52034
+ if (eventKey === "INIT" || eventKey === "LOAD" || eventKey === "$MOUNT") {
52035
+ continue;
52036
+ }
52037
+ const unsub = eventBus.on(`UI:${orbitalName}.${traitName}.${eventKey}`, (event) => {
52038
+ if (event.source && event.source.fromBridge) {
52039
+ return;
52040
+ }
52041
+ enqueueAndDrain(eventKey, event.payload);
52042
+ });
52043
+ unsubscribes.push(unsub);
52026
52044
  }
52027
- const unsub = eventBus.on(`UI:${eventKey}`, (event) => {
52028
- console.log("[TraitStateMachine] Received event:", `UI:${eventKey}`, event);
52029
- enqueueAndDrain(eventKey, event.payload);
52030
- });
52031
- unsubscribes.push(unsub);
52032
52045
  }
52033
52046
  for (const binding of traitBindings) {
52047
+ const ownOrbital = orbitalsByTrait?.[binding.trait.name];
52034
52048
  const listens = binding.trait.listens ?? [];
52035
52049
  for (const listen of listens) {
52036
- const expectedTrait = listen.source?.trait;
52037
- const unsub = eventBus.on(listen.event, (event) => {
52038
- if (expectedTrait) {
52039
- const emitTrait = event.source?.trait;
52040
- if (emitTrait !== expectedTrait) return;
52041
- }
52042
- console.log("[TraitStateMachine] listens", binding.trait.name, listen.event, "\u2192", listen.triggers, "from", event.source?.trait);
52050
+ const sourceTrait = listen.source?.trait;
52051
+ if (!sourceTrait) continue;
52052
+ const sourceOrbital = listen.source?.orbital ?? ownOrbital;
52053
+ if (!sourceOrbital) continue;
52054
+ const busKey = `UI:${sourceOrbital}.${sourceTrait}.${listen.event}`;
52055
+ const unsub = eventBus.on(busKey, (event) => {
52043
52056
  enqueueAndDrain(listen.triggers, event.payload);
52044
52057
  });
52045
52058
  unsubscribes.push(unsub);
@@ -52065,6 +52078,8 @@ init_EntitySchemaContext();
52065
52078
 
52066
52079
  // runtime/ServerBridge.tsx
52067
52080
  init_useEventBus();
52081
+ init_logger();
52082
+ var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
52068
52083
  var ServerBridgeContext = React127.createContext(null);
52069
52084
  function useServerBridge() {
52070
52085
  const ctx = React127.useContext(ServerBridgeContext);
@@ -52142,8 +52157,22 @@ function ServerBridgeProvider({
52142
52157
  }
52143
52158
  if (result.emittedEvents) {
52144
52159
  for (const emitted of result.emittedEvents) {
52145
- eventBus.emit(`UI:${emitted.event}`, emitted.payload);
52146
- eventBus.emit(emitted.event, emitted.payload);
52160
+ const evTrait = emitted.source?.trait;
52161
+ if (!evTrait) {
52162
+ xOrbitalLog2.warn("emit:dropped-no-source", {
52163
+ event: emitted.event,
52164
+ dispatchOrbital: orbitalName
52165
+ });
52166
+ continue;
52167
+ }
52168
+ const key = emitted.source?.orbital ? `UI:${emitted.source.orbital}.${evTrait}.${emitted.event}` : `UI:${evTrait}.${emitted.event}`;
52169
+ xOrbitalLog2.info("emit:rebroadcast", {
52170
+ busKey: key,
52171
+ sourceOrbital: emitted.source?.orbital,
52172
+ sourceTrait: evTrait,
52173
+ dispatchOrbital: orbitalName
52174
+ });
52175
+ eventBus.emit(key, emitted.payload);
52147
52176
  }
52148
52177
  }
52149
52178
  } else if (result.error) {
@@ -52264,6 +52293,10 @@ function prepareSchemaForPreview(input) {
52264
52293
  const schema = adjustSchemaForMockData(parsed, mockData);
52265
52294
  return { schema, mockData };
52266
52295
  }
52296
+
52297
+ // runtime/OrbPreview.tsx
52298
+ init_logger();
52299
+ var xOrbitalLog3 = createLogger("almadar:runtime:cross-orbital");
52267
52300
  function normalizeChild(child) {
52268
52301
  if (typeof child === "string") return child;
52269
52302
  if (child === null || typeof child !== "object" || Array.isArray(child)) {
@@ -52343,6 +52376,11 @@ function applyServerEffects(effects, uiSlots, onNavigate) {
52343
52376
  const patternRecord = eff.pattern;
52344
52377
  const { type: patternType, children, ...inlineProps } = patternRecord;
52345
52378
  const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
52379
+ xOrbitalLog3.info("slot-write", {
52380
+ slot: eff.slot,
52381
+ sourceTrait: eff.traitName ?? "server",
52382
+ patternType: typeof patternType === "string" ? patternType : void 0
52383
+ });
52346
52384
  uiSlots.render({
52347
52385
  target: eff.slot,
52348
52386
  pattern: patternType,
@@ -52357,19 +52395,26 @@ function applyServerEffects(effects, uiSlots, onNavigate) {
52357
52395
  }
52358
52396
  }
52359
52397
  }
52360
- function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName }) {
52398
+ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait }) {
52361
52399
  const slotsActions = useSlotsActions();
52362
52400
  const bridge = useServerBridge();
52363
52401
  const uiSlots = useUISlots();
52364
- const onEventProcessed = React127.useCallback(async (event, payload) => {
52402
+ const onEventProcessed = React127.useCallback(async (event, payload, dispatchedOrbitals) => {
52365
52403
  if (!bridge.connected || !orbitalNames?.length) return;
52366
- for (const name of orbitalNames) {
52404
+ const targets = dispatchedOrbitals && dispatchedOrbitals.size > 0 ? orbitalNames.filter((n) => dispatchedOrbitals.has(n)) : orbitalNames;
52405
+ xOrbitalLog3.info("TraitInitializer:fanout", {
52406
+ event,
52407
+ sentTo: targets,
52408
+ skipped: orbitalNames.filter((n) => !targets.includes(n)),
52409
+ dispatchedOrbitalsSize: dispatchedOrbitals?.size ?? 0
52410
+ });
52411
+ for (const name of targets) {
52367
52412
  const { effects, meta } = await bridge.sendEvent(name, event, payload);
52368
52413
  recordServerResponse(name, event, meta);
52369
52414
  applyServerEffects(effects, uiSlots, onNavigate);
52370
52415
  }
52371
52416
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate]);
52372
- const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName } : { navigate: onNavigate, persistence, traitConfigsByName };
52417
+ const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait };
52373
52418
  const { sendEvent } = useTraitStateMachine(traits2, slotsActions, opts);
52374
52419
  const initSentRef = React127.useRef(false);
52375
52420
  React127.useEffect(() => {
@@ -52419,27 +52464,68 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
52419
52464
  const allPageTraits = React127.useMemo(() => {
52420
52465
  if (pageName && traits2.length > 0) return traits2;
52421
52466
  if (!ir?.pages || ir.pages.size <= 1) return traits2;
52422
- const combined = [];
52467
+ const firstPage = ir.pages.values().next().value;
52468
+ if (!firstPage) return traits2;
52469
+ const firstPageTraits = [];
52423
52470
  const seen = /* @__PURE__ */ new Set();
52424
- for (const page of ir.pages.values()) {
52425
- for (const t of page.traits) {
52426
- const binding = t;
52427
- const traitObj = binding.trait;
52428
- const name = traitObj?.name ?? binding.name ?? "";
52429
- if (name && !seen.has(name)) {
52430
- seen.add(name);
52431
- combined.push(t);
52432
- }
52471
+ for (const binding of firstPage.traits) {
52472
+ const name = binding.trait.name;
52473
+ if (name && !seen.has(name)) {
52474
+ seen.add(name);
52475
+ firstPageTraits.push(binding);
52433
52476
  }
52434
52477
  }
52435
- return combined.length > 0 ? combined : traits2;
52478
+ return firstPageTraits.length > 0 ? firstPageTraits : traits2;
52436
52479
  }, [ir, traits2, pageName]);
52437
- const orbitalNames = React127.useMemo(() => {
52480
+ React127.useMemo(() => {
52438
52481
  const parsed = schema;
52439
52482
  const orbitals = parsed?.orbitals;
52440
52483
  if (!orbitals) return [];
52441
52484
  return orbitals.filter((o) => typeof o.name === "string").map((o) => o.name);
52442
52485
  }, [schema]);
52486
+ const orbitalsByTrait = React127.useMemo(() => {
52487
+ const map = {};
52488
+ const parsed = schema;
52489
+ if (!parsed?.orbitals) return map;
52490
+ for (const orb of parsed.orbitals) {
52491
+ for (const traitRef of orb.traits) {
52492
+ let traitName;
52493
+ if (typeof traitRef === "string") {
52494
+ const parts = traitRef.split(".");
52495
+ traitName = parts[parts.length - 1];
52496
+ } else if ("ref" in traitRef && typeof traitRef.ref === "string") {
52497
+ const parts = traitRef.ref.split(".");
52498
+ traitName = traitRef.name ?? parts[parts.length - 1];
52499
+ } else if ("name" in traitRef && typeof traitRef.name === "string") {
52500
+ traitName = traitRef.name;
52501
+ }
52502
+ if (traitName) map[traitName] = orb.name;
52503
+ }
52504
+ }
52505
+ return map;
52506
+ }, [schema]);
52507
+ const pageOrbitalNames = React127.useMemo(() => {
52508
+ const set = /* @__PURE__ */ new Set();
52509
+ for (const binding of allPageTraits) {
52510
+ const orb = orbitalsByTrait[binding.trait.name];
52511
+ if (orb) set.add(orb);
52512
+ }
52513
+ return Array.from(set);
52514
+ }, [allPageTraits, orbitalsByTrait]);
52515
+ React127.useEffect(() => {
52516
+ const traitNames = allPageTraits.map((b) => b.trait.name);
52517
+ const orbitalsByTraitForPage = {};
52518
+ for (const name of traitNames) {
52519
+ const orb = orbitalsByTrait[name];
52520
+ if (orb) orbitalsByTraitForPage[name] = orb;
52521
+ }
52522
+ xOrbitalLog3.info("SchemaRunner:mount", {
52523
+ pageName,
52524
+ traitNames,
52525
+ orbitalsByTraitForPage,
52526
+ pageOrbitalNames: pageOrbitalNames.join(",")
52527
+ });
52528
+ }, [pageName, allPageTraits, orbitalsByTrait, pageOrbitalNames]);
52443
52529
  const traitConfigsByName = React127.useMemo(() => {
52444
52530
  const map = {};
52445
52531
  const parsed = schema;
@@ -52480,8 +52566,9 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
52480
52566
  TraitInitializer,
52481
52567
  {
52482
52568
  traits: allPageTraits,
52483
- orbitalNames: serverUrl ? orbitalNames : void 0,
52569
+ orbitalNames: serverUrl ? pageOrbitalNames : void 0,
52484
52570
  traitConfigsByName,
52571
+ orbitalsByTrait,
52485
52572
  onNavigate,
52486
52573
  onLocalFallback,
52487
52574
  persistence
@@ -52503,7 +52590,8 @@ function OrbPreview({
52503
52590
  autoMock = false,
52504
52591
  height = "400px",
52505
52592
  className,
52506
- serverUrl
52593
+ serverUrl,
52594
+ initialPagePath
52507
52595
  }) {
52508
52596
  const [localFallback, setLocalFallback] = React127.useState(false);
52509
52597
  const eventBus = useEventBus();
@@ -52549,7 +52637,17 @@ function OrbPreview({
52549
52637
  return [];
52550
52638
  }
52551
52639
  }, [parsedSchema]);
52552
- const [currentPage, setCurrentPage] = React127.useState(void 0);
52640
+ const initialPageName = React127.useMemo(() => {
52641
+ if (!initialPagePath) return void 0;
52642
+ const match = pages.find(({ page }) => page.path === initialPagePath);
52643
+ return match?.page.name;
52644
+ }, [pages, initialPagePath]);
52645
+ const [currentPage, setCurrentPage] = React127.useState(initialPageName);
52646
+ React127.useEffect(() => {
52647
+ if (initialPageName && initialPageName !== currentPage) {
52648
+ setCurrentPage(initialPageName);
52649
+ }
52650
+ }, [initialPageName, currentPage]);
52553
52651
  const handleNavigate = React127.useCallback((path) => {
52554
52652
  const match = pages.find(({ page }) => page.path === path);
52555
52653
  if (match) {