@almadar/ui 5.158.0 → 5.159.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.
@@ -272,4 +272,4 @@ declare function useEntityBindingSnapshot(traitName: string | undefined): {
272
272
  state: string;
273
273
  };
274
274
 
275
- export { EntityBindingContext as E, type SendEventResult as S, TraitContext as T, type EntityBindingSource as a, type EntitySchemaContextValue as b, EntitySchemaProvider as c, type EntitySchemaProviderProps as d, type ServerBridgeContextValue as e, ServerBridgeProvider as f, type ServerBridgeProviderProps as g, type ServerBridgeTransport as h, type ServerClientEffect as i, type ServerResponseMeta as j, type TraitContextValue as k, type TraitInstance as l, TraitProvider as m, type TraitProviderProps as n, useEntitySchema as o, useEntitySchemaOptional as p, useServerBridge as q, useTrait as r, useTraitContext as s, useEntityBindingSnapshot as u };
275
+ export { type EntityBindingSource as E, type ServerBridgeTransport as S, TraitContext as T, type EntitySchemaContextValue as a, EntitySchemaProvider as b, type EntitySchemaProviderProps as c, type ServerBridgeContextValue as d, ServerBridgeProvider as e, type ServerClientEffect as f, type TraitContextValue as g, type TraitInstance as h, TraitProvider as i, type TraitProviderProps as j, useEntitySchemaOptional as k, useServerBridge as l, useTrait as m, useTraitContext as n, EntityBindingContext as o, type SendEventResult as p, type ServerBridgeProviderProps as q, type ServerResponseMeta as r, useEntityBindingSnapshot as s, useEntitySchema as u };
@@ -272,4 +272,4 @@ declare function useEntityBindingSnapshot(traitName: string | undefined): {
272
272
  state: string;
273
273
  };
274
274
 
275
- export { EntityBindingContext as E, type SendEventResult as S, TraitContext as T, type EntityBindingSource as a, type EntitySchemaContextValue as b, EntitySchemaProvider as c, type EntitySchemaProviderProps as d, type ServerBridgeContextValue as e, ServerBridgeProvider as f, type ServerBridgeProviderProps as g, type ServerBridgeTransport as h, type ServerClientEffect as i, type ServerResponseMeta as j, type TraitContextValue as k, type TraitInstance as l, TraitProvider as m, type TraitProviderProps as n, useEntitySchema as o, useEntitySchemaOptional as p, useServerBridge as q, useTrait as r, useTraitContext as s, useEntityBindingSnapshot as u };
275
+ export { type EntityBindingSource as E, type ServerBridgeTransport as S, TraitContext as T, type EntitySchemaContextValue as a, EntitySchemaProvider as b, type EntitySchemaProviderProps as c, type ServerBridgeContextValue as d, ServerBridgeProvider as e, type ServerClientEffect as f, type TraitContextValue as g, type TraitInstance as h, TraitProvider as i, type TraitProviderProps as j, useEntitySchemaOptional as k, useServerBridge as l, useTrait as m, useTraitContext as n, EntityBindingContext as o, type SendEventResult as p, type ServerBridgeProviderProps as q, type ServerResponseMeta as r, useEntityBindingSnapshot as s, useEntitySchema as u };
@@ -4664,7 +4664,16 @@ function isPlainObject(value) {
4664
4664
  if (typeof value === "function") return false;
4665
4665
  return true;
4666
4666
  }
4667
+ function isEvaluatorResolvedData(value) {
4668
+ return evaluatorResolvedData.has(value);
4669
+ }
4670
+ function brandResolved(value) {
4671
+ if (value !== null && typeof value === "object" && !React94__namespace.default.isValidElement(value) && !(value instanceof Date)) {
4672
+ resolvedMarkerFree.add(value);
4673
+ }
4674
+ }
4667
4675
  function subtreeHasMarker(value) {
4676
+ if (resolvedMarkerFree.has(value)) return false;
4668
4677
  const cached = markerPresenceCache.get(value);
4669
4678
  if (cached !== void 0) return cached;
4670
4679
  let found = false;
@@ -4686,10 +4695,23 @@ function subtreeHasMarker(value) {
4686
4695
  }
4687
4696
  function walkValue(value, scopeTrait, entity, config, state) {
4688
4697
  if (core.isRenderBindingMarker(value)) {
4689
- return { resolved: resolveMarkerExpression(value.expression, entity, config, state), changed: true };
4698
+ const cached = markerResolutionCache.get(value);
4699
+ if (cached !== void 0 && cached.entity === entity && cached.config === config && cached.state === state) {
4700
+ return { resolved: cached.resolved, changed: false };
4701
+ }
4702
+ const resolved = resolveMarkerExpression(value.expression, entity, config, state);
4703
+ markerResolutionCache.set(value, { entity, config, state, resolved });
4704
+ if (resolved !== null && typeof resolved === "object" && !React94__namespace.default.isValidElement(resolved) && !(resolved instanceof Date)) {
4705
+ resolvedMarkerFree.add(resolved);
4706
+ evaluatorResolvedData.add(resolved);
4707
+ }
4708
+ return { resolved, changed: true };
4690
4709
  }
4691
4710
  if (Array.isArray(value)) {
4692
- if (!subtreeHasMarker(value)) return { resolved: value, changed: false };
4711
+ if (!subtreeHasMarker(value)) {
4712
+ brandResolved(value);
4713
+ return { resolved: value, changed: false };
4714
+ }
4693
4715
  const out = [];
4694
4716
  let changed = false;
4695
4717
  for (const item of value) {
@@ -4704,10 +4726,14 @@ function walkValue(value, scopeTrait, entity, config, state) {
4704
4726
  out.push(resolved);
4705
4727
  if (itemChanged) changed = true;
4706
4728
  }
4729
+ brandResolved(out);
4707
4730
  return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
4708
4731
  }
4709
4732
  if (isPlainObject(value)) {
4710
- if (!subtreeHasMarker(value)) return { resolved: value, changed: false };
4733
+ if (!subtreeHasMarker(value)) {
4734
+ brandResolved(value);
4735
+ return { resolved: value, changed: false };
4736
+ }
4711
4737
  const sourceTrait = value._sourceTrait;
4712
4738
  if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
4713
4739
  return { resolved: value, changed: false };
@@ -4719,11 +4745,13 @@ function walkValue(value, scopeTrait, entity, config, state) {
4719
4745
  out[key] = resolved;
4720
4746
  if (itemChanged) changed = true;
4721
4747
  }
4748
+ brandResolved(out);
4722
4749
  return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
4723
4750
  }
4724
4751
  return { resolved: value, changed: false };
4725
4752
  }
4726
4753
  function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
4754
+ if (resolvedMarkerFree.has(props)) return props;
4727
4755
  const out = {};
4728
4756
  let changed = false;
4729
4757
  for (const [key, value] of Object.entries(props)) {
@@ -4731,13 +4759,17 @@ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
4731
4759
  out[key] = resolved;
4732
4760
  if (propChanged) changed = true;
4733
4761
  }
4762
+ brandResolved(out);
4734
4763
  return changed ? out : props;
4735
4764
  }
4736
- var markerPresenceCache;
4765
+ var markerPresenceCache, markerResolutionCache, resolvedMarkerFree, evaluatorResolvedData;
4737
4766
  var init_resolve_render_bindings = __esm({
4738
4767
  "lib/resolve-render-bindings.ts"() {
4739
4768
  "use client";
4740
4769
  markerPresenceCache = /* @__PURE__ */ new WeakMap();
4770
+ markerResolutionCache = /* @__PURE__ */ new WeakMap();
4771
+ resolvedMarkerFree = /* @__PURE__ */ new WeakSet();
4772
+ evaluatorResolvedData = /* @__PURE__ */ new WeakSet();
4741
4773
  }
4742
4774
  });
4743
4775
  function getCurrentIconFamily() {
@@ -15342,6 +15374,19 @@ var init_molecules = __esm({
15342
15374
  init_puzzleObject();
15343
15375
  }
15344
15376
  });
15377
+ var profilerOnRender;
15378
+ var init_perf = __esm({
15379
+ "lib/perf.ts"() {
15380
+ profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
15381
+ ui.pushPerfEntry({
15382
+ name: `profiler:${id}:${phase}`,
15383
+ durationMs: actualDuration,
15384
+ ts: commitTime,
15385
+ detail: { baseDuration }
15386
+ });
15387
+ };
15388
+ }
15389
+ });
15345
15390
  function themeBodyFont(el) {
15346
15391
  if (typeof getComputedStyle !== "function") return "system-ui, sans-serif";
15347
15392
  const v = getComputedStyle(el).getPropertyValue("--font-family-body").trim();
@@ -15690,6 +15735,7 @@ var init_LearningCanvas = __esm({
15690
15735
  "components/learning/atoms/LearningCanvas.tsx"() {
15691
15736
  "use client";
15692
15737
  init_cn();
15738
+ init_perf();
15693
15739
  init_useEventBus();
15694
15740
  DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
15695
15741
  TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
@@ -15733,6 +15779,7 @@ var init_LearningCanvas = __esm({
15733
15779
  return [...shapes, ...traceOut, ...readoutOut];
15734
15780
  }, [shapes, traces, readouts, width, height]);
15735
15781
  const draw = React94.useCallback(() => {
15782
+ const _perfT = ui.perfStart("learningcanvas:paint");
15736
15783
  const canvas = canvasRef.current;
15737
15784
  if (!canvas) return;
15738
15785
  const ctx = canvas.getContext("2d");
@@ -15754,6 +15801,7 @@ var init_LearningCanvas = __esm({
15754
15801
  for (const shape of derivedShapes) {
15755
15802
  if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
15756
15803
  }
15804
+ ui.perfEnd("learningcanvas:paint", _perfT);
15757
15805
  }, [width, height, backgroundColor, derivedShapes]);
15758
15806
  React94.useEffect(() => {
15759
15807
  draw();
@@ -32948,6 +32996,7 @@ var init_MathCanvas = __esm({
32948
32996
  "components/learning/molecules/MathCanvas.tsx"() {
32949
32997
  "use client";
32950
32998
  init_useEventBus();
32999
+ init_perf();
32951
33000
  init_atoms();
32952
33001
  init_Stack();
32953
33002
  init_LearningCanvas();
@@ -33013,6 +33062,7 @@ var init_MathCanvas = __esm({
33013
33062
  };
33014
33063
  }, [stableKeyMap, stableKeyUpMap, eventBus]);
33015
33064
  const derivedShapes = React94.useMemo(() => {
33065
+ const _perfT = ui.perfStart("mathcanvas:derive");
33016
33066
  const out = [];
33017
33067
  const margin = 24;
33018
33068
  const plotW = width - margin * 2;
@@ -33256,6 +33306,7 @@ var init_MathCanvas = __esm({
33256
33306
  }
33257
33307
  }
33258
33308
  out.push(...shapes);
33309
+ ui.perfEnd("mathcanvas:derive", _perfT);
33259
33310
  return out;
33260
33311
  }, [
33261
33312
  width,
@@ -39609,7 +39660,7 @@ var init_RichBlockEditor = __esm({
39609
39660
  {
39610
39661
  variant: "bordered",
39611
39662
  padding: "none",
39612
- className: cn("flex flex-col", className),
39663
+ className: cn("flex flex-col text-card-foreground", className),
39613
39664
  children: [
39614
39665
  enableBlocks && showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
39615
39666
  Box,
@@ -44428,6 +44479,7 @@ var init_DetailPanel = __esm({
44428
44479
  "use client";
44429
44480
  init_atoms();
44430
44481
  init_Box();
44482
+ init_Input();
44431
44483
  init_Stack();
44432
44484
  init_SimpleGrid();
44433
44485
  init_Menu();
@@ -44443,6 +44495,7 @@ var init_DetailPanel = __esm({
44443
44495
  ReactMarkdown2 = React94.lazy(() => import('react-markdown'));
44444
44496
  DetailPanel = ({
44445
44497
  title: propTitle,
44498
+ onTitleCommit,
44446
44499
  subtitle,
44447
44500
  status,
44448
44501
  avatar,
@@ -44464,6 +44517,7 @@ var init_DetailPanel = __esm({
44464
44517
  }) => {
44465
44518
  const eventBus = useEventBus();
44466
44519
  const { t } = hooks.useTranslate();
44520
+ const [titleDraft, setTitleDraft] = React94__namespace.default.useState(null);
44467
44521
  const isFieldDefArray = (arr) => {
44468
44522
  if (!arr || arr.length === 0) return false;
44469
44523
  const first = arr[0];
@@ -44684,6 +44738,50 @@ var init_DetailPanel = __esm({
44684
44738
  }),
44685
44739
  status && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: status.variant ?? "default", children: status.label })
44686
44740
  ] });
44741
+ const commitTitle = () => {
44742
+ if (!onTitleCommit) return;
44743
+ const next = (titleDraft ?? "").trim();
44744
+ setTitleDraft(null);
44745
+ if (!next || next === title) return;
44746
+ onTitleCommit(next, normalizedData?.id !== void 0 ? String(normalizedData.id) : "");
44747
+ };
44748
+ const titleNode = onTitleCommit && titleDraft !== null ? /* @__PURE__ */ jsxRuntime.jsx(
44749
+ Input,
44750
+ {
44751
+ value: titleDraft,
44752
+ autoFocus: true,
44753
+ "aria-label": t("common.title"),
44754
+ className: "h-auto py-1 text-3xl font-bold tracking-tight",
44755
+ onChange: (e) => setTitleDraft(e.target.value),
44756
+ onBlur: commitTitle,
44757
+ onKeyDown: (e) => {
44758
+ if (e.key === "Enter") {
44759
+ e.preventDefault();
44760
+ commitTitle();
44761
+ } else if (e.key === "Escape") {
44762
+ e.preventDefault();
44763
+ setTitleDraft(null);
44764
+ }
44765
+ },
44766
+ "data-testid": "detail-title-input"
44767
+ }
44768
+ ) : onTitleCommit ? /* @__PURE__ */ jsxRuntime.jsx(
44769
+ Box,
44770
+ {
44771
+ role: "button",
44772
+ tabIndex: 0,
44773
+ className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
44774
+ onClick: () => setTitleDraft(title ?? ""),
44775
+ onKeyDown: (e) => {
44776
+ if (e.key === "Enter" || e.key === " ") {
44777
+ e.preventDefault();
44778
+ setTitleDraft(title ?? "");
44779
+ }
44780
+ },
44781
+ "data-testid": "detail-title-editable",
44782
+ children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" })
44783
+ }
44784
+ ) : /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" });
44687
44785
  const content = /* @__PURE__ */ jsxRuntime.jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", className: "p-6", children: [
44688
44786
  /* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "between", align: "start", gap: "md", children: [
44689
44787
  /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", gap: "sm", className: "min-w-0", children: [
@@ -44703,7 +44801,7 @@ var init_DetailPanel = __esm({
44703
44801
  avatar,
44704
44802
  /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "min-w-0", children: [
44705
44803
  /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "center", gap: "sm", wrap: true, children: [
44706
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" }),
44804
+ titleNode,
44707
44805
  statusBadges
44708
44806
  ] }),
44709
44807
  subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: subtitle })
@@ -45264,7 +45362,7 @@ var init_Form = __esm({
45264
45362
  });
45265
45363
  debug(
45266
45364
  "forms",
45267
- `Calculation triggered: ${calc.variableName} = ${value}`
45365
+ `Calculation triggered: ${calc.variableName} = ${String(value)}`
45268
45366
  );
45269
45367
  }
45270
45368
  });
@@ -51763,6 +51861,7 @@ function isPlainConfigObject(value) {
51763
51861
  return proto === Object.prototype || proto === null;
51764
51862
  }
51765
51863
  function subtreeHasTraitRef(value) {
51864
+ if (isEvaluatorResolvedData(value)) return false;
51766
51865
  const cached = traitRefPresenceCache.get(value);
51767
51866
  if (cached !== void 0) return cached;
51768
51867
  let found = false;
@@ -51835,6 +51934,10 @@ function renderPatternProps(props, onDismiss, propsSchema) {
51835
51934
  };
51836
51935
  rendered[key] = /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss });
51837
51936
  } else if (Array.isArray(value)) {
51937
+ if (!isEvaluatorResolvedData(value) && value.some((el) => isPatternConfig(el))) ; else if (!subtreeHasTraitRef(value)) {
51938
+ rendered[key] = value;
51939
+ continue;
51940
+ }
51838
51941
  const isDataArray = propsSchema?.[key]?.items?.types?.includes("object") ?? false;
51839
51942
  rendered[key] = value.map((item, i) => {
51840
51943
  const el = item;
@@ -55861,6 +55964,7 @@ function enqueueEvent(queue, entry) {
55861
55964
  }
55862
55965
 
55863
55966
  // hooks/useTraitStateMachine.ts
55967
+ init_perf();
55864
55968
  init_traitRegistry();
55865
55969
  init_verificationRegistry();
55866
55970
  var crossTraitLog = logger.createLogger("almadar:ui:cross-trait");
@@ -56547,6 +56651,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
56547
56651
  }, [eventBus]);
56548
56652
  React94.useEffect(() => {
56549
56653
  const scheduler = runtime.createTickScheduler();
56654
+ const timedTick = (key, fn) => () => ui.perfTimeAsync(key, fn);
56550
56655
  const pureWriterTickKeys = /* @__PURE__ */ new Set();
56551
56656
  for (const group of sharedGroups.values()) {
56552
56657
  const ticksByInterval = /* @__PURE__ */ new Map();
@@ -56563,12 +56668,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
56563
56668
  }
56564
56669
  for (const entries of ticksByInterval.values()) {
56565
56670
  const interval = entries[0].tick.interval;
56566
- const onDue = () => {
56671
+ const onDue = timedTick(`tick:shared:${group.storeKey}@${String(interval)}`, () => {
56567
56672
  const writers = entries.map(
56568
56673
  ({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
56569
56674
  );
56570
56675
  runTickFrame(group.storeKey, writers, sharedEntityStore);
56571
- };
56676
+ });
56572
56677
  if (interval === "frame") {
56573
56678
  scheduler.add(0, onDue);
56574
56679
  } else if (typeof interval === "number") {
@@ -56586,14 +56691,15 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
56586
56691
  if (sharedKey !== void 0 && pureWriterTickKeys.has(`${binding.trait.name}::${tick.name}`)) {
56587
56692
  continue;
56588
56693
  }
56694
+ const tickKey = `tick:${binding.trait.name}::${tick.name}`;
56589
56695
  if (tick.interval === "frame") {
56590
- scheduler.add(0, () => runTickEffects(tick, binding));
56696
+ scheduler.add(0, timedTick(tickKey, () => runTickEffects(tick, binding)));
56591
56697
  } else if (typeof tick.interval === "number") {
56592
- scheduler.add(tick.interval, () => runTickEffects(tick, binding));
56698
+ scheduler.add(tick.interval, timedTick(tickKey, () => runTickEffects(tick, binding)));
56593
56699
  } else if (runtime.isValidCronExpression(tick.interval)) {
56594
- scheduler.addCron(tick.interval, () => runTickEffects(tick, binding));
56700
+ scheduler.addCron(tick.interval, timedTick(tickKey, () => runTickEffects(tick, binding)));
56595
56701
  } else {
56596
- scheduler.add(runtime.parseDurationString(tick.interval), () => runTickEffects(tick, binding));
56702
+ scheduler.add(runtime.parseDurationString(tick.interval), timedTick(tickKey, () => runTickEffects(tick, binding)));
56597
56703
  }
56598
56704
  }
56599
56705
  }
@@ -56601,6 +56707,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
56601
56707
  }, [traitBindings, runTickEffects, sharedGroups, sharedEntityStore, emitFromSharedWriter]);
56602
56708
  const processEventQueued = React94.useCallback(async (eventKey, payload, targetTrait, tick, sourceTrait) => {
56603
56709
  const normalizedEvent = normalizeEventKey(eventKey);
56710
+ const _perfT0 = ui.perfStart("processEvent:total");
56604
56711
  const bindings = traitBindingsRef.current;
56605
56712
  const currentManager = managerRef.current;
56606
56713
  crossTraitLog.debug("processEvent:enter", () => ({
@@ -56624,6 +56731,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
56624
56731
  entityByTrait[name] = { ...sharedEntityStore.getSnapshot(sharedKey) };
56625
56732
  }
56626
56733
  }
56734
+ const _perfT1 = ui.perfStart("processEvent:guardMatch");
56627
56735
  const results = currentManager.sendEvent(
56628
56736
  normalizedEvent,
56629
56737
  payload,
@@ -56632,6 +56740,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
56632
56740
  void 0,
56633
56741
  targetTrait
56634
56742
  );
56743
+ ui.perfEnd("processEvent:guardMatch", _perfT1);
56635
56744
  crossTraitLog.debug("processEvent:results", {
56636
56745
  event: normalizedEvent,
56637
56746
  executedCount: results.length,
@@ -56681,6 +56790,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
56681
56790
  transition: `${result.previousState} -> ${result.newState}`,
56682
56791
  effects: JSON.stringify(result.effects)
56683
56792
  }));
56793
+ const _perfT2 = ui.perfStart("processEvent:executeAll");
56684
56794
  const emittedDuringExec = await executeTransitionEffects({
56685
56795
  binding,
56686
56796
  // upstream gap: /runtime TransitionResult.effects is unknown[] — they are SExpr at runtime (see Almadar_UI_Gaps.md)
@@ -56692,6 +56802,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
56692
56802
  syncOnly: false,
56693
56803
  log: stateLog
56694
56804
  });
56805
+ ui.perfEnd("processEvent:executeAll", _perfT2);
56695
56806
  emittedByTrait.set(traitName, emittedDuringExec);
56696
56807
  for (const emittedKey of emittedDuringExec) {
56697
56808
  bridgeEchoPendingRef.current.set(
@@ -56788,27 +56899,31 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
56788
56899
  if (orbital) dispatchedOrbitals.add(orbital);
56789
56900
  }
56790
56901
  const relayPayload = targetTrait !== void 0 ? { ...payload ?? {}, _targetTrait: targetTrait } : payload;
56791
- if (tick !== void 0) {
56792
- void onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals, tick, sourceTrait);
56793
- } else {
56794
- await onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals);
56795
- }
56902
+ void onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals, tick, sourceTrait);
56796
56903
  }
56904
+ ui.perfEnd("processEvent:total", _perfT0);
56905
+ ui.perfEnd(`event:${normalizedEvent}`, _perfT0);
56797
56906
  }, [entities, eventBus, sharedEntityStore]);
56798
56907
  const drainEventQueue = React94.useCallback(async () => {
56799
56908
  if (processingRef.current) return;
56800
56909
  processingRef.current = true;
56910
+ const _perfT = ui.perfStart("drain:pass");
56911
+ let _perfN = 0;
56801
56912
  try {
56802
56913
  while (eventQueueRef.current.length > 0) {
56803
56914
  const entry = eventQueueRef.current.shift();
56915
+ _perfN++;
56804
56916
  await processEventQueued(entry.eventKey, entry.payload, entry.targetTrait, entry.tick, entry.sourceTrait);
56805
56917
  }
56806
56918
  } finally {
56807
56919
  processingRef.current = false;
56920
+ ui.perfEnd("drain:pass", _perfT);
56921
+ ui.perfGauge("drain:passEntries", _perfN);
56808
56922
  }
56809
56923
  }, [processEventQueued]);
56810
56924
  const enqueueAndDrain = React94.useCallback((eventKey, payload, targetTrait, tick, sourceTrait) => {
56811
56925
  enqueueEvent(eventQueueRef.current, { eventKey, payload, targetTrait, tick, sourceTrait });
56926
+ ui.perfGauge("queue:depthAtEnqueue", eventQueueRef.current.length);
56812
56927
  void drainEventQueue();
56813
56928
  }, [drainEventQueue]);
56814
56929
  React94.useCallback((eventKey, payload) => {
@@ -57107,7 +57222,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
57107
57222
  [serverActiveTraits]
57108
57223
  );
57109
57224
  const uiSlots = context.useUISlots();
57110
- const onEventProcessed = React94.useCallback(async (event, payload, dispatchedOrbitals, tick, sourceTrait) => {
57225
+ const onEventProcessed = React94.useCallback((event, payload, dispatchedOrbitals, tick, sourceTrait) => {
57111
57226
  if (!bridge.connected || !orbitalNames?.length) return;
57112
57227
  const targets = dispatchedOrbitals && dispatchedOrbitals.size > 0 ? orbitalNames.filter((n) => dispatchedOrbitals.has(n)) : orbitalNames;
57113
57228
  xOrbitalLog.debug("TraitInitializer:fanout", () => ({
@@ -57121,9 +57236,10 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
57121
57236
  void bridge.sendEvent(name, event, withActiveTraits(payload), tick, sourceTrait);
57122
57237
  continue;
57123
57238
  }
57124
- const { effects, meta } = await bridge.sendEvent(name, event, withActiveTraits(payload));
57125
- recordServerResponse(name, event, meta);
57126
- applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames, onNavigateBack);
57239
+ void bridge.sendEvent(name, event, withActiveTraits(payload)).then(({ effects, meta }) => {
57240
+ recordServerResponse(name, event, meta);
57241
+ applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames, onNavigateBack);
57242
+ });
57127
57243
  }
57128
57244
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits]);
57129
57245
  const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
@@ -57441,14 +57557,15 @@ function OrbPreview({
57441
57557
  return pattern.replace(/:([A-Za-z0-9_]+)/g, (whole, key) => routeParams[key] ?? whole);
57442
57558
  }, [currentPagePath, routeParams]);
57443
57559
  const navStackRef = React94.useRef(null);
57444
- const handleNavigate = React94.useCallback((path) => {
57560
+ const handleNavigate = React94.useCallback((path, navState) => {
57445
57561
  const hit = providers.matchPathAmong(pages, path, (entry) => entry.page.path);
57446
57562
  const match = hit?.candidate;
57447
- const params = hit?.params ?? {};
57563
+ const params = { ...hit?.params ?? {}, ...navState ?? {} };
57448
57564
  navLog.debug("handleNavigate", () => ({
57449
57565
  path,
57450
57566
  matched: match?.page.name ?? null,
57451
57567
  params,
57568
+ navState: navState ? JSON.stringify(navState) : void 0,
57452
57569
  availablePaths: pages.map((p) => p.page.path)
57453
57570
  }));
57454
57571
  if (match?.page.name) {
@@ -57463,9 +57580,9 @@ function OrbPreview({
57463
57580
  }
57464
57581
  }, [pages]);
57465
57582
  const handleNavigateEffect = React94.useCallback(
57466
- (path, _params, crumb) => {
57583
+ (path, params, crumb) => {
57467
57584
  navStackRef.current?.beginNavigate(path, crumb);
57468
- handleNavigate(path);
57585
+ handleNavigate(path, params);
57469
57586
  },
57470
57587
  [handleNavigate]
57471
57588
  );
@@ -59782,14 +59899,7 @@ TraitCardNode.displayName = "TraitCardNode";
59782
59899
 
59783
59900
  // components/avl/organisms/FlowCanvas.tsx
59784
59901
  init_useEventBus();
59785
- var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
59786
- ui.pushPerfEntry({
59787
- name: `profiler:${id}:${phase}`,
59788
- durationMs: actualDuration,
59789
- ts: commitTime,
59790
- detail: { baseDuration }
59791
- });
59792
- };
59902
+ init_perf();
59793
59903
  var flowCanvasLog = logger.createLogger("almadar:ui:flow-canvas");
59794
59904
  var NODE_TYPES = {
59795
59905
  preview: OrbPreviewNode,