@almadar/ui 4.10.0 → 4.10.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.
@@ -51429,6 +51429,10 @@ OrbitalProvider.displayName = "OrbitalProvider";
51429
51429
  init_UISlotContext();
51430
51430
  init_UISlotRenderer();
51431
51431
  init_useEventBus();
51432
+
51433
+ // runtime/useResolvedSchema.ts
51434
+ init_logger();
51435
+ var resolvedSchemaLog = createLogger("almadar:ui:resolved-schema");
51432
51436
  function useResolvedSchema(schema, pageName) {
51433
51437
  const [loading, setLoading] = React128.useState(true);
51434
51438
  const [error, setError] = React128.useState(null);
@@ -51436,31 +51440,37 @@ function useResolvedSchema(schema, pageName) {
51436
51440
  if (!schema) return null;
51437
51441
  try {
51438
51442
  const resolved = core.schemaToIR(schema);
51439
- const sourceListsByTrait = /* @__PURE__ */ new Map();
51440
- const orbitals = schema.orbitals;
51441
- if (Array.isArray(orbitals)) {
51442
- for (const orb of orbitals) {
51443
- const traits2 = orb.traits;
51444
- if (!Array.isArray(traits2)) continue;
51445
- for (const trait of traits2) {
51446
- const t = trait;
51447
- if (typeof t.name !== "string" || !Array.isArray(t.listens)) continue;
51448
- const sources = t.listens.map((listen) => {
51449
- const l = listen;
51450
- return l.source;
51451
- });
51452
- sourceListsByTrait.set(t.name, sources);
51453
- }
51443
+ const callSiteListensByTrait = /* @__PURE__ */ new Map();
51444
+ for (const orb of schema.orbitals) {
51445
+ for (const traitRef of orb.traits ?? []) {
51446
+ if (typeof traitRef === "string") continue;
51447
+ const t = traitRef;
51448
+ const inlineListens = t.listens?.length ? t.listens : void 0;
51449
+ const resolvedListens = t._resolved?.listens?.length ? t._resolved.listens : void 0;
51450
+ const listens = inlineListens ?? resolvedListens;
51451
+ const traitName = t.name ?? t._resolved?.name;
51452
+ if (typeof traitName !== "string" || !listens) continue;
51453
+ callSiteListensByTrait.set(traitName, listens);
51454
51454
  }
51455
51455
  }
51456
51456
  for (const [traitName, trait] of resolved.traits) {
51457
- const sources = sourceListsByTrait.get(traitName);
51458
- if (!sources) continue;
51459
- trait.listens.forEach((listen, i) => {
51460
- const src = sources[i];
51461
- if (src !== void 0) {
51462
- listen.source = src;
51463
- }
51457
+ const callSiteListens = callSiteListensByTrait.get(traitName);
51458
+ if (!callSiteListens) continue;
51459
+ const beforeCount = trait.listens.length;
51460
+ trait.listens = callSiteListens.map((l) => ({
51461
+ event: l.event,
51462
+ triggers: l.triggers,
51463
+ source: l.source
51464
+ }));
51465
+ resolvedSchemaLog.info("listens:restored", {
51466
+ trait: traitName,
51467
+ beforeCount,
51468
+ afterCount: trait.listens.length,
51469
+ listens: callSiteListens.map((l) => {
51470
+ const src = l.source;
51471
+ const label = !src ? "(no-source)" : src.kind === "any" ? "*" : src.trait;
51472
+ return `${label}.${l.event}->${l.triggers}`;
51473
+ }).join(",")
51464
51474
  });
51465
51475
  }
51466
51476
  return resolved;
@@ -51535,6 +51545,9 @@ var ALMADAR_DND_MIME = "application/x-almadar-dnd";
51535
51545
  init_useEventBus();
51536
51546
  typeof process !== "undefined" && process.env?.VITE_API_URL ? process.env.VITE_API_URL : "http://localhost:3000";
51537
51547
 
51548
+ // runtime/useTraitStateMachine.ts
51549
+ init_logger();
51550
+
51538
51551
  // runtime/createClientEffectHandlers.ts
51539
51552
  function createClientEffectHandlers(options) {
51540
51553
  const { eventBus, slotSetter, navigate, notify } = options;
@@ -51573,6 +51586,7 @@ function createClientEffectHandlers(options) {
51573
51586
  init_EntitySchemaContext();
51574
51587
  init_traitRegistry();
51575
51588
  init_verificationRegistry();
51589
+ var crossTraitLog = createLogger("almadar:ui:cross-trait");
51576
51590
  function toTraitDefinition(binding) {
51577
51591
  return {
51578
51592
  name: binding.trait.name,
@@ -51800,8 +51814,19 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
51800
51814
  const currentManager = managerRef.current;
51801
51815
  const actions = slotsActionsRef.current;
51802
51816
  console.log("[TraitStateMachine] Processing event:", normalizedEvent, "payload:", payload);
51817
+ crossTraitLog.debug("processEvent:enter", {
51818
+ event: normalizedEvent,
51819
+ traitCount: bindings.length,
51820
+ traitNames: bindings.map((b) => b.trait.name).join(","),
51821
+ orbitalsByTrait: JSON.stringify(orbitalsByTrait ?? null)
51822
+ });
51803
51823
  const bindingMap = new Map(bindings.map((b) => [b.trait.name, b]));
51804
51824
  const results = currentManager.sendEvent(normalizedEvent, payload);
51825
+ crossTraitLog.debug("processEvent:results", {
51826
+ event: normalizedEvent,
51827
+ executedCount: results.length,
51828
+ executedTraits: results.map((r2) => r2.traitName).join(",")
51829
+ });
51805
51830
  const emittedByTrait = /* @__PURE__ */ new Map();
51806
51831
  for (const { traitName, result } of results) {
51807
51832
  const binding = bindingMap.get(traitName);
@@ -52045,6 +52070,32 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
52045
52070
  fromBridge: true
52046
52071
  });
52047
52072
  }
52073
+ const executedTraits = new Set(results.map((r2) => r2.traitName));
52074
+ for (const binding of bindings) {
52075
+ const traitName = binding.trait.name;
52076
+ if (executedTraits.has(traitName)) continue;
52077
+ const { events: traitEvents, transitions: traitTransitions } = binding.trait;
52078
+ const eventDeclared = traitEvents.some((e) => e.key === normalizedEvent);
52079
+ const hasTransition = traitTransitions.some((t) => t.event === normalizedEvent);
52080
+ crossTraitLog.debug("rebroadcast:second-pass:candidate", {
52081
+ event: normalizedEvent,
52082
+ traitName,
52083
+ eventDeclared,
52084
+ hasTransition,
52085
+ orbitalName: orbitalsByTrait?.[traitName],
52086
+ traitEventKeys: traitEvents.map((e) => e.key).join(",")
52087
+ });
52088
+ if (!eventDeclared || hasTransition) continue;
52089
+ const orbitalName = orbitalsByTrait?.[traitName];
52090
+ if (!orbitalName) continue;
52091
+ const busKey = `UI:${orbitalName}.${traitName}.${normalizedEvent}`;
52092
+ crossTraitLog.info("rebroadcast:emit", { busKey, traitName, event: normalizedEvent });
52093
+ eventBus.emit(busKey, payload, {
52094
+ orbital: orbitalName,
52095
+ trait: traitName,
52096
+ fromBridge: true
52097
+ });
52098
+ }
52048
52099
  }
52049
52100
  if (results.length > 0) {
52050
52101
  setTraitStates(currentManager.getAllStates());
@@ -52122,13 +52173,21 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
52122
52173
  for (const binding of traitBindings) {
52123
52174
  const ownOrbital = orbitalsByTrait?.[binding.trait.name];
52124
52175
  const listens = binding.trait.listens ?? [];
52176
+ crossTraitLog.debug("listen:subscribe", {
52177
+ trait: binding.trait.name,
52178
+ ownOrbital,
52179
+ listenCount: listens.length,
52180
+ listens: listens.map((l) => `${l.source?.trait ?? "?"}.${l.event}->${l.triggers}`).join(",")
52181
+ });
52125
52182
  for (const listen of listens) {
52126
52183
  const sourceTrait = listen.source?.trait;
52127
52184
  if (!sourceTrait) continue;
52128
52185
  const sourceOrbital = listen.source?.orbital ?? ownOrbital;
52129
52186
  if (!sourceOrbital) continue;
52130
52187
  const busKey = `UI:${sourceOrbital}.${sourceTrait}.${listen.event}`;
52188
+ crossTraitLog.debug("listen:subscribed", { busKey, targetTrait: binding.trait.name, triggers: listen.triggers });
52131
52189
  const unsub = eventBus.on(busKey, (event) => {
52190
+ crossTraitLog.info("listen:fired", { busKey, targetTrait: binding.trait.name, triggers: listen.triggers });
52132
52191
  enqueueAndDrain(listen.triggers, event.payload);
52133
52192
  });
52134
52193
  unsubscribes.push(unsub);
package/dist/avl/index.js CHANGED
@@ -51383,6 +51383,10 @@ OrbitalProvider.displayName = "OrbitalProvider";
51383
51383
  init_UISlotContext();
51384
51384
  init_UISlotRenderer();
51385
51385
  init_useEventBus();
51386
+
51387
+ // runtime/useResolvedSchema.ts
51388
+ init_logger();
51389
+ var resolvedSchemaLog = createLogger("almadar:ui:resolved-schema");
51386
51390
  function useResolvedSchema(schema, pageName) {
51387
51391
  const [loading, setLoading] = useState(true);
51388
51392
  const [error, setError] = useState(null);
@@ -51390,31 +51394,37 @@ function useResolvedSchema(schema, pageName) {
51390
51394
  if (!schema) return null;
51391
51395
  try {
51392
51396
  const resolved = schemaToIR(schema);
51393
- const sourceListsByTrait = /* @__PURE__ */ new Map();
51394
- const orbitals = schema.orbitals;
51395
- if (Array.isArray(orbitals)) {
51396
- for (const orb of orbitals) {
51397
- const traits2 = orb.traits;
51398
- if (!Array.isArray(traits2)) continue;
51399
- for (const trait of traits2) {
51400
- const t = trait;
51401
- if (typeof t.name !== "string" || !Array.isArray(t.listens)) continue;
51402
- const sources = t.listens.map((listen) => {
51403
- const l = listen;
51404
- return l.source;
51405
- });
51406
- sourceListsByTrait.set(t.name, sources);
51407
- }
51397
+ const callSiteListensByTrait = /* @__PURE__ */ new Map();
51398
+ for (const orb of schema.orbitals) {
51399
+ for (const traitRef of orb.traits ?? []) {
51400
+ if (typeof traitRef === "string") continue;
51401
+ const t = traitRef;
51402
+ const inlineListens = t.listens?.length ? t.listens : void 0;
51403
+ const resolvedListens = t._resolved?.listens?.length ? t._resolved.listens : void 0;
51404
+ const listens = inlineListens ?? resolvedListens;
51405
+ const traitName = t.name ?? t._resolved?.name;
51406
+ if (typeof traitName !== "string" || !listens) continue;
51407
+ callSiteListensByTrait.set(traitName, listens);
51408
51408
  }
51409
51409
  }
51410
51410
  for (const [traitName, trait] of resolved.traits) {
51411
- const sources = sourceListsByTrait.get(traitName);
51412
- if (!sources) continue;
51413
- trait.listens.forEach((listen, i) => {
51414
- const src = sources[i];
51415
- if (src !== void 0) {
51416
- listen.source = src;
51417
- }
51411
+ const callSiteListens = callSiteListensByTrait.get(traitName);
51412
+ if (!callSiteListens) continue;
51413
+ const beforeCount = trait.listens.length;
51414
+ trait.listens = callSiteListens.map((l) => ({
51415
+ event: l.event,
51416
+ triggers: l.triggers,
51417
+ source: l.source
51418
+ }));
51419
+ resolvedSchemaLog.info("listens:restored", {
51420
+ trait: traitName,
51421
+ beforeCount,
51422
+ afterCount: trait.listens.length,
51423
+ listens: callSiteListens.map((l) => {
51424
+ const src = l.source;
51425
+ const label = !src ? "(no-source)" : src.kind === "any" ? "*" : src.trait;
51426
+ return `${label}.${l.event}->${l.triggers}`;
51427
+ }).join(",")
51418
51428
  });
51419
51429
  }
51420
51430
  return resolved;
@@ -51489,6 +51499,9 @@ var ALMADAR_DND_MIME = "application/x-almadar-dnd";
51489
51499
  init_useEventBus();
51490
51500
  typeof process !== "undefined" && process.env?.VITE_API_URL ? process.env.VITE_API_URL : "http://localhost:3000";
51491
51501
 
51502
+ // runtime/useTraitStateMachine.ts
51503
+ init_logger();
51504
+
51492
51505
  // runtime/createClientEffectHandlers.ts
51493
51506
  function createClientEffectHandlers(options) {
51494
51507
  const { eventBus, slotSetter, navigate, notify } = options;
@@ -51527,6 +51540,7 @@ function createClientEffectHandlers(options) {
51527
51540
  init_EntitySchemaContext();
51528
51541
  init_traitRegistry();
51529
51542
  init_verificationRegistry();
51543
+ var crossTraitLog = createLogger("almadar:ui:cross-trait");
51530
51544
  function toTraitDefinition(binding) {
51531
51545
  return {
51532
51546
  name: binding.trait.name,
@@ -51754,8 +51768,19 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
51754
51768
  const currentManager = managerRef.current;
51755
51769
  const actions = slotsActionsRef.current;
51756
51770
  console.log("[TraitStateMachine] Processing event:", normalizedEvent, "payload:", payload);
51771
+ crossTraitLog.debug("processEvent:enter", {
51772
+ event: normalizedEvent,
51773
+ traitCount: bindings.length,
51774
+ traitNames: bindings.map((b) => b.trait.name).join(","),
51775
+ orbitalsByTrait: JSON.stringify(orbitalsByTrait ?? null)
51776
+ });
51757
51777
  const bindingMap = new Map(bindings.map((b) => [b.trait.name, b]));
51758
51778
  const results = currentManager.sendEvent(normalizedEvent, payload);
51779
+ crossTraitLog.debug("processEvent:results", {
51780
+ event: normalizedEvent,
51781
+ executedCount: results.length,
51782
+ executedTraits: results.map((r2) => r2.traitName).join(",")
51783
+ });
51759
51784
  const emittedByTrait = /* @__PURE__ */ new Map();
51760
51785
  for (const { traitName, result } of results) {
51761
51786
  const binding = bindingMap.get(traitName);
@@ -51999,6 +52024,32 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
51999
52024
  fromBridge: true
52000
52025
  });
52001
52026
  }
52027
+ const executedTraits = new Set(results.map((r2) => r2.traitName));
52028
+ for (const binding of bindings) {
52029
+ const traitName = binding.trait.name;
52030
+ if (executedTraits.has(traitName)) continue;
52031
+ const { events: traitEvents, transitions: traitTransitions } = binding.trait;
52032
+ const eventDeclared = traitEvents.some((e) => e.key === normalizedEvent);
52033
+ const hasTransition = traitTransitions.some((t) => t.event === normalizedEvent);
52034
+ crossTraitLog.debug("rebroadcast:second-pass:candidate", {
52035
+ event: normalizedEvent,
52036
+ traitName,
52037
+ eventDeclared,
52038
+ hasTransition,
52039
+ orbitalName: orbitalsByTrait?.[traitName],
52040
+ traitEventKeys: traitEvents.map((e) => e.key).join(",")
52041
+ });
52042
+ if (!eventDeclared || hasTransition) continue;
52043
+ const orbitalName = orbitalsByTrait?.[traitName];
52044
+ if (!orbitalName) continue;
52045
+ const busKey = `UI:${orbitalName}.${traitName}.${normalizedEvent}`;
52046
+ crossTraitLog.info("rebroadcast:emit", { busKey, traitName, event: normalizedEvent });
52047
+ eventBus.emit(busKey, payload, {
52048
+ orbital: orbitalName,
52049
+ trait: traitName,
52050
+ fromBridge: true
52051
+ });
52052
+ }
52002
52053
  }
52003
52054
  if (results.length > 0) {
52004
52055
  setTraitStates(currentManager.getAllStates());
@@ -52076,13 +52127,21 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
52076
52127
  for (const binding of traitBindings) {
52077
52128
  const ownOrbital = orbitalsByTrait?.[binding.trait.name];
52078
52129
  const listens = binding.trait.listens ?? [];
52130
+ crossTraitLog.debug("listen:subscribe", {
52131
+ trait: binding.trait.name,
52132
+ ownOrbital,
52133
+ listenCount: listens.length,
52134
+ listens: listens.map((l) => `${l.source?.trait ?? "?"}.${l.event}->${l.triggers}`).join(",")
52135
+ });
52079
52136
  for (const listen of listens) {
52080
52137
  const sourceTrait = listen.source?.trait;
52081
52138
  if (!sourceTrait) continue;
52082
52139
  const sourceOrbital = listen.source?.orbital ?? ownOrbital;
52083
52140
  if (!sourceOrbital) continue;
52084
52141
  const busKey = `UI:${sourceOrbital}.${sourceTrait}.${listen.event}`;
52142
+ crossTraitLog.debug("listen:subscribed", { busKey, targetTrait: binding.trait.name, triggers: listen.triggers });
52085
52143
  const unsub = eventBus.on(busKey, (event) => {
52144
+ crossTraitLog.info("listen:fired", { busKey, targetTrait: binding.trait.name, triggers: listen.triggers });
52086
52145
  enqueueAndDrain(listen.triggers, event.payload);
52087
52146
  });
52088
52147
  unsubscribes.push(unsub);
@@ -38166,6 +38166,9 @@ init_useEventBus();
38166
38166
  init_useEventBus();
38167
38167
  typeof process !== "undefined" && process.env?.VITE_API_URL ? process.env.VITE_API_URL : "http://localhost:3000";
38168
38168
 
38169
+ // runtime/useTraitStateMachine.ts
38170
+ init_logger();
38171
+
38169
38172
  // runtime/createClientEffectHandlers.ts
38170
38173
  function createClientEffectHandlers(options) {
38171
38174
  const { eventBus, slotSetter, navigate, notify } = options;
@@ -38204,6 +38207,7 @@ function createClientEffectHandlers(options) {
38204
38207
  init_EntitySchemaContext();
38205
38208
  init_traitRegistry();
38206
38209
  init_verificationRegistry();
38210
+ var crossTraitLog = createLogger("almadar:ui:cross-trait");
38207
38211
  function toTraitDefinition(binding) {
38208
38212
  return {
38209
38213
  name: binding.trait.name,
@@ -38431,8 +38435,19 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38431
38435
  const currentManager = managerRef.current;
38432
38436
  const actions = slotsActionsRef.current;
38433
38437
  console.log("[TraitStateMachine] Processing event:", normalizedEvent, "payload:", payload);
38438
+ crossTraitLog.debug("processEvent:enter", {
38439
+ event: normalizedEvent,
38440
+ traitCount: bindings.length,
38441
+ traitNames: bindings.map((b) => b.trait.name).join(","),
38442
+ orbitalsByTrait: JSON.stringify(orbitalsByTrait ?? null)
38443
+ });
38434
38444
  const bindingMap = new Map(bindings.map((b) => [b.trait.name, b]));
38435
38445
  const results = currentManager.sendEvent(normalizedEvent, payload);
38446
+ crossTraitLog.debug("processEvent:results", {
38447
+ event: normalizedEvent,
38448
+ executedCount: results.length,
38449
+ executedTraits: results.map((r) => r.traitName).join(",")
38450
+ });
38436
38451
  const emittedByTrait = /* @__PURE__ */ new Map();
38437
38452
  for (const { traitName, result } of results) {
38438
38453
  const binding = bindingMap.get(traitName);
@@ -38676,6 +38691,32 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38676
38691
  fromBridge: true
38677
38692
  });
38678
38693
  }
38694
+ const executedTraits = new Set(results.map((r) => r.traitName));
38695
+ for (const binding of bindings) {
38696
+ const traitName = binding.trait.name;
38697
+ if (executedTraits.has(traitName)) continue;
38698
+ const { events: traitEvents, transitions: traitTransitions } = binding.trait;
38699
+ const eventDeclared = traitEvents.some((e) => e.key === normalizedEvent);
38700
+ const hasTransition = traitTransitions.some((t) => t.event === normalizedEvent);
38701
+ crossTraitLog.debug("rebroadcast:second-pass:candidate", {
38702
+ event: normalizedEvent,
38703
+ traitName,
38704
+ eventDeclared,
38705
+ hasTransition,
38706
+ orbitalName: orbitalsByTrait?.[traitName],
38707
+ traitEventKeys: traitEvents.map((e) => e.key).join(",")
38708
+ });
38709
+ if (!eventDeclared || hasTransition) continue;
38710
+ const orbitalName = orbitalsByTrait?.[traitName];
38711
+ if (!orbitalName) continue;
38712
+ const busKey = `UI:${orbitalName}.${traitName}.${normalizedEvent}`;
38713
+ crossTraitLog.info("rebroadcast:emit", { busKey, traitName, event: normalizedEvent });
38714
+ eventBus.emit(busKey, payload, {
38715
+ orbital: orbitalName,
38716
+ trait: traitName,
38717
+ fromBridge: true
38718
+ });
38719
+ }
38679
38720
  }
38680
38721
  if (results.length > 0) {
38681
38722
  setTraitStates(currentManager.getAllStates());
@@ -38753,13 +38794,21 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38753
38794
  for (const binding of traitBindings) {
38754
38795
  const ownOrbital = orbitalsByTrait?.[binding.trait.name];
38755
38796
  const listens = binding.trait.listens ?? [];
38797
+ crossTraitLog.debug("listen:subscribe", {
38798
+ trait: binding.trait.name,
38799
+ ownOrbital,
38800
+ listenCount: listens.length,
38801
+ listens: listens.map((l) => `${l.source?.trait ?? "?"}.${l.event}->${l.triggers}`).join(",")
38802
+ });
38756
38803
  for (const listen of listens) {
38757
38804
  const sourceTrait = listen.source?.trait;
38758
38805
  if (!sourceTrait) continue;
38759
38806
  const sourceOrbital = listen.source?.orbital ?? ownOrbital;
38760
38807
  if (!sourceOrbital) continue;
38761
38808
  const busKey = `UI:${sourceOrbital}.${sourceTrait}.${listen.event}`;
38809
+ crossTraitLog.debug("listen:subscribed", { busKey, targetTrait: binding.trait.name, triggers: listen.triggers });
38762
38810
  const unsub = eventBus.on(busKey, (event) => {
38811
+ crossTraitLog.info("listen:fired", { busKey, targetTrait: binding.trait.name, triggers: listen.triggers });
38763
38812
  enqueueAndDrain(listen.triggers, event.payload);
38764
38813
  });
38765
38814
  unsubscribes.push(unsub);
@@ -38778,6 +38827,10 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38778
38827
  canHandleEvent
38779
38828
  };
38780
38829
  }
38830
+
38831
+ // runtime/useResolvedSchema.ts
38832
+ init_logger();
38833
+ var resolvedSchemaLog = createLogger("almadar:ui:resolved-schema");
38781
38834
  function useResolvedSchema(schema, pageName) {
38782
38835
  const [loading, setLoading] = React115.useState(true);
38783
38836
  const [error, setError] = React115.useState(null);
@@ -38785,31 +38838,37 @@ function useResolvedSchema(schema, pageName) {
38785
38838
  if (!schema) return null;
38786
38839
  try {
38787
38840
  const resolved = core.schemaToIR(schema);
38788
- const sourceListsByTrait = /* @__PURE__ */ new Map();
38789
- const orbitals = schema.orbitals;
38790
- if (Array.isArray(orbitals)) {
38791
- for (const orb of orbitals) {
38792
- const traits2 = orb.traits;
38793
- if (!Array.isArray(traits2)) continue;
38794
- for (const trait of traits2) {
38795
- const t = trait;
38796
- if (typeof t.name !== "string" || !Array.isArray(t.listens)) continue;
38797
- const sources = t.listens.map((listen) => {
38798
- const l = listen;
38799
- return l.source;
38800
- });
38801
- sourceListsByTrait.set(t.name, sources);
38802
- }
38841
+ const callSiteListensByTrait = /* @__PURE__ */ new Map();
38842
+ for (const orb of schema.orbitals) {
38843
+ for (const traitRef of orb.traits ?? []) {
38844
+ if (typeof traitRef === "string") continue;
38845
+ const t = traitRef;
38846
+ const inlineListens = t.listens?.length ? t.listens : void 0;
38847
+ const resolvedListens = t._resolved?.listens?.length ? t._resolved.listens : void 0;
38848
+ const listens = inlineListens ?? resolvedListens;
38849
+ const traitName = t.name ?? t._resolved?.name;
38850
+ if (typeof traitName !== "string" || !listens) continue;
38851
+ callSiteListensByTrait.set(traitName, listens);
38803
38852
  }
38804
38853
  }
38805
38854
  for (const [traitName, trait] of resolved.traits) {
38806
- const sources = sourceListsByTrait.get(traitName);
38807
- if (!sources) continue;
38808
- trait.listens.forEach((listen, i) => {
38809
- const src = sources[i];
38810
- if (src !== void 0) {
38811
- listen.source = src;
38812
- }
38855
+ const callSiteListens = callSiteListensByTrait.get(traitName);
38856
+ if (!callSiteListens) continue;
38857
+ const beforeCount = trait.listens.length;
38858
+ trait.listens = callSiteListens.map((l) => ({
38859
+ event: l.event,
38860
+ triggers: l.triggers,
38861
+ source: l.source
38862
+ }));
38863
+ resolvedSchemaLog.info("listens:restored", {
38864
+ trait: traitName,
38865
+ beforeCount,
38866
+ afterCount: trait.listens.length,
38867
+ listens: callSiteListens.map((l) => {
38868
+ const src = l.source;
38869
+ const label = !src ? "(no-source)" : src.kind === "any" ? "*" : src.trait;
38870
+ return `${label}.${l.event}->${l.triggers}`;
38871
+ }).join(",")
38813
38872
  });
38814
38873
  }
38815
38874
  return resolved;
@@ -38121,6 +38121,9 @@ init_useEventBus();
38121
38121
  init_useEventBus();
38122
38122
  typeof process !== "undefined" && process.env?.VITE_API_URL ? process.env.VITE_API_URL : "http://localhost:3000";
38123
38123
 
38124
+ // runtime/useTraitStateMachine.ts
38125
+ init_logger();
38126
+
38124
38127
  // runtime/createClientEffectHandlers.ts
38125
38128
  function createClientEffectHandlers(options) {
38126
38129
  const { eventBus, slotSetter, navigate, notify } = options;
@@ -38159,6 +38162,7 @@ function createClientEffectHandlers(options) {
38159
38162
  init_EntitySchemaContext();
38160
38163
  init_traitRegistry();
38161
38164
  init_verificationRegistry();
38165
+ var crossTraitLog = createLogger("almadar:ui:cross-trait");
38162
38166
  function toTraitDefinition(binding) {
38163
38167
  return {
38164
38168
  name: binding.trait.name,
@@ -38386,8 +38390,19 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38386
38390
  const currentManager = managerRef.current;
38387
38391
  const actions = slotsActionsRef.current;
38388
38392
  console.log("[TraitStateMachine] Processing event:", normalizedEvent, "payload:", payload);
38393
+ crossTraitLog.debug("processEvent:enter", {
38394
+ event: normalizedEvent,
38395
+ traitCount: bindings.length,
38396
+ traitNames: bindings.map((b) => b.trait.name).join(","),
38397
+ orbitalsByTrait: JSON.stringify(orbitalsByTrait ?? null)
38398
+ });
38389
38399
  const bindingMap = new Map(bindings.map((b) => [b.trait.name, b]));
38390
38400
  const results = currentManager.sendEvent(normalizedEvent, payload);
38401
+ crossTraitLog.debug("processEvent:results", {
38402
+ event: normalizedEvent,
38403
+ executedCount: results.length,
38404
+ executedTraits: results.map((r) => r.traitName).join(",")
38405
+ });
38391
38406
  const emittedByTrait = /* @__PURE__ */ new Map();
38392
38407
  for (const { traitName, result } of results) {
38393
38408
  const binding = bindingMap.get(traitName);
@@ -38631,6 +38646,32 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38631
38646
  fromBridge: true
38632
38647
  });
38633
38648
  }
38649
+ const executedTraits = new Set(results.map((r) => r.traitName));
38650
+ for (const binding of bindings) {
38651
+ const traitName = binding.trait.name;
38652
+ if (executedTraits.has(traitName)) continue;
38653
+ const { events: traitEvents, transitions: traitTransitions } = binding.trait;
38654
+ const eventDeclared = traitEvents.some((e) => e.key === normalizedEvent);
38655
+ const hasTransition = traitTransitions.some((t) => t.event === normalizedEvent);
38656
+ crossTraitLog.debug("rebroadcast:second-pass:candidate", {
38657
+ event: normalizedEvent,
38658
+ traitName,
38659
+ eventDeclared,
38660
+ hasTransition,
38661
+ orbitalName: orbitalsByTrait?.[traitName],
38662
+ traitEventKeys: traitEvents.map((e) => e.key).join(",")
38663
+ });
38664
+ if (!eventDeclared || hasTransition) continue;
38665
+ const orbitalName = orbitalsByTrait?.[traitName];
38666
+ if (!orbitalName) continue;
38667
+ const busKey = `UI:${orbitalName}.${traitName}.${normalizedEvent}`;
38668
+ crossTraitLog.info("rebroadcast:emit", { busKey, traitName, event: normalizedEvent });
38669
+ eventBus.emit(busKey, payload, {
38670
+ orbital: orbitalName,
38671
+ trait: traitName,
38672
+ fromBridge: true
38673
+ });
38674
+ }
38634
38675
  }
38635
38676
  if (results.length > 0) {
38636
38677
  setTraitStates(currentManager.getAllStates());
@@ -38708,13 +38749,21 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38708
38749
  for (const binding of traitBindings) {
38709
38750
  const ownOrbital = orbitalsByTrait?.[binding.trait.name];
38710
38751
  const listens = binding.trait.listens ?? [];
38752
+ crossTraitLog.debug("listen:subscribe", {
38753
+ trait: binding.trait.name,
38754
+ ownOrbital,
38755
+ listenCount: listens.length,
38756
+ listens: listens.map((l) => `${l.source?.trait ?? "?"}.${l.event}->${l.triggers}`).join(",")
38757
+ });
38711
38758
  for (const listen of listens) {
38712
38759
  const sourceTrait = listen.source?.trait;
38713
38760
  if (!sourceTrait) continue;
38714
38761
  const sourceOrbital = listen.source?.orbital ?? ownOrbital;
38715
38762
  if (!sourceOrbital) continue;
38716
38763
  const busKey = `UI:${sourceOrbital}.${sourceTrait}.${listen.event}`;
38764
+ crossTraitLog.debug("listen:subscribed", { busKey, targetTrait: binding.trait.name, triggers: listen.triggers });
38717
38765
  const unsub = eventBus.on(busKey, (event) => {
38766
+ crossTraitLog.info("listen:fired", { busKey, targetTrait: binding.trait.name, triggers: listen.triggers });
38718
38767
  enqueueAndDrain(listen.triggers, event.payload);
38719
38768
  });
38720
38769
  unsubscribes.push(unsub);
@@ -38733,6 +38782,10 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
38733
38782
  canHandleEvent
38734
38783
  };
38735
38784
  }
38785
+
38786
+ // runtime/useResolvedSchema.ts
38787
+ init_logger();
38788
+ var resolvedSchemaLog = createLogger("almadar:ui:resolved-schema");
38736
38789
  function useResolvedSchema(schema, pageName) {
38737
38790
  const [loading, setLoading] = useState(true);
38738
38791
  const [error, setError] = useState(null);
@@ -38740,31 +38793,37 @@ function useResolvedSchema(schema, pageName) {
38740
38793
  if (!schema) return null;
38741
38794
  try {
38742
38795
  const resolved = schemaToIR(schema);
38743
- const sourceListsByTrait = /* @__PURE__ */ new Map();
38744
- const orbitals = schema.orbitals;
38745
- if (Array.isArray(orbitals)) {
38746
- for (const orb of orbitals) {
38747
- const traits2 = orb.traits;
38748
- if (!Array.isArray(traits2)) continue;
38749
- for (const trait of traits2) {
38750
- const t = trait;
38751
- if (typeof t.name !== "string" || !Array.isArray(t.listens)) continue;
38752
- const sources = t.listens.map((listen) => {
38753
- const l = listen;
38754
- return l.source;
38755
- });
38756
- sourceListsByTrait.set(t.name, sources);
38757
- }
38796
+ const callSiteListensByTrait = /* @__PURE__ */ new Map();
38797
+ for (const orb of schema.orbitals) {
38798
+ for (const traitRef of orb.traits ?? []) {
38799
+ if (typeof traitRef === "string") continue;
38800
+ const t = traitRef;
38801
+ const inlineListens = t.listens?.length ? t.listens : void 0;
38802
+ const resolvedListens = t._resolved?.listens?.length ? t._resolved.listens : void 0;
38803
+ const listens = inlineListens ?? resolvedListens;
38804
+ const traitName = t.name ?? t._resolved?.name;
38805
+ if (typeof traitName !== "string" || !listens) continue;
38806
+ callSiteListensByTrait.set(traitName, listens);
38758
38807
  }
38759
38808
  }
38760
38809
  for (const [traitName, trait] of resolved.traits) {
38761
- const sources = sourceListsByTrait.get(traitName);
38762
- if (!sources) continue;
38763
- trait.listens.forEach((listen, i) => {
38764
- const src = sources[i];
38765
- if (src !== void 0) {
38766
- listen.source = src;
38767
- }
38810
+ const callSiteListens = callSiteListensByTrait.get(traitName);
38811
+ if (!callSiteListens) continue;
38812
+ const beforeCount = trait.listens.length;
38813
+ trait.listens = callSiteListens.map((l) => ({
38814
+ event: l.event,
38815
+ triggers: l.triggers,
38816
+ source: l.source
38817
+ }));
38818
+ resolvedSchemaLog.info("listens:restored", {
38819
+ trait: traitName,
38820
+ beforeCount,
38821
+ afterCount: trait.listens.length,
38822
+ listens: callSiteListens.map((l) => {
38823
+ const src = l.source;
38824
+ const label = !src ? "(no-source)" : src.kind === "any" ? "*" : src.trait;
38825
+ return `${label}.${l.event}->${l.triggers}`;
38826
+ }).join(",")
38768
38827
  });
38769
38828
  }
38770
38829
  return resolved;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.10.0",
3
+ "version": "4.10.2",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",