@almadar/ui 4.46.0 → 4.47.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.
@@ -9981,8 +9981,8 @@ function Seigaiha({ size, color, strokeWidth }) {
9981
9981
  [s, s * 0.1]
9982
9982
  ];
9983
9983
  for (const [cx, cy] of centers) {
9984
- for (let ring = 1; ring <= 3; ring++) {
9985
- const cr = r2 * (ring / 3);
9984
+ for (let ring2 = 1; ring2 <= 3; ring2++) {
9985
+ const cr = r2 * (ring2 / 3);
9986
9986
  paths.push(
9987
9987
  `M ${f(cx - cr)},${f(cy)} A ${f(cr)} ${f(cr)} 0 0 1 ${f(cx + cr)},${f(cy)}`
9988
9988
  );
@@ -10079,8 +10079,8 @@ function Arch({ size, color, strokeWidth }) {
10079
10079
  const h = size * 1.5;
10080
10080
  const cx = w / 2;
10081
10081
  const paths = [];
10082
- for (let ring = 0; ring < 4; ring++) {
10083
- const scale = 1 - ring * 0.2;
10082
+ for (let ring2 = 0; ring2 < 4; ring2++) {
10083
+ const scale = 1 - ring2 * 0.2;
10084
10084
  const archW = w * 0.48 * scale;
10085
10085
  const archH = h * 0.7 * scale;
10086
10086
  const baseY = h * 0.85;
@@ -10095,7 +10095,7 @@ function Arch({ size, color, strokeWidth }) {
10095
10095
  paths.push(
10096
10096
  `M ${f(lx)},${f(baseY)} A ${f(radius)} ${f(radius)} 0 0 1 ${f(cx)},${f(tipY)} A ${f(radius)} ${f(radius)} 0 0 1 ${f(rx)},${f(baseY)}`
10097
10097
  );
10098
- if (ring === 0) {
10098
+ if (ring2 === 0) {
10099
10099
  paths.push(`M ${f(lx)},${f(baseY)} L ${f(rx)},${f(baseY)}`);
10100
10100
  }
10101
10101
  }
@@ -21749,20 +21749,20 @@ function CanvasEffectEngine({
21749
21749
  return img?.complete ? img : void 0;
21750
21750
  }, []);
21751
21751
  React147.useEffect(() => {
21752
- const now = performance.now();
21752
+ const now2 = performance.now();
21753
21753
  const effectX = x || width / 2;
21754
21754
  const effectY = y || height / 2;
21755
21755
  const preset = presets[actionType](effectX, effectY);
21756
21756
  const state = stateRef.current;
21757
21757
  for (const emitter of preset.particles) {
21758
21758
  const scaledEmitter = { ...emitter, count: Math.round(emitter.count * intensity) };
21759
- state.particles.push(...spawnParticles(scaledEmitter, now));
21759
+ state.particles.push(...spawnParticles(scaledEmitter, now2));
21760
21760
  }
21761
21761
  for (const seqConfig of preset.sequences) {
21762
- state.sequences.push(spawnSequence(seqConfig, now));
21762
+ state.sequences.push(spawnSequence(seqConfig, now2));
21763
21763
  }
21764
21764
  for (const ovConfig of preset.overlays) {
21765
- state.overlays.push(spawnOverlay(ovConfig, now));
21765
+ state.overlays.push(spawnOverlay(ovConfig, now2));
21766
21766
  }
21767
21767
  if (preset.screenShake > 0) {
21768
21768
  shakeRef.current.intensity = preset.screenShake * intensity;
@@ -42472,7 +42472,7 @@ function getAllEvents(traits2) {
42472
42472
  }
42473
42473
  function EventDispatcherTab({ traits: traits2, schema }) {
42474
42474
  const eventBus = useEventBus();
42475
- const [log18, setLog] = React147__namespace.useState([]);
42475
+ const [log19, setLog] = React147__namespace.useState([]);
42476
42476
  const prevStatesRef = React147__namespace.useRef(/* @__PURE__ */ new Map());
42477
42477
  React147__namespace.useEffect(() => {
42478
42478
  for (const trait of traits2) {
@@ -42536,9 +42536,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
42536
42536
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Other Events (not available from current state)" }),
42537
42537
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
42538
42538
  ] }),
42539
- log18.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
42539
+ log19.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
42540
42540
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Recent Transitions" }),
42541
- /* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log18.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
42541
+ /* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log19.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
42542
42542
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400", children: entry.traitName }),
42543
42543
  " ",
42544
42544
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -56507,11 +56507,11 @@ function VerificationProvider({
56507
56507
  runtimeManager,
56508
56508
  traitStateGetter
56509
56509
  }) {
56510
- const isEnabled = enabled ?? (typeof process !== "undefined" && process.env?.NODE_ENV !== "production");
56510
+ const isEnabled2 = enabled ?? (typeof process !== "undefined" && process.env?.NODE_ENV !== "production");
56511
56511
  const eventBus = useEventBus();
56512
56512
  const pendingRef = React147.useRef(/* @__PURE__ */ new Map());
56513
56513
  React147.useEffect(() => {
56514
- if (!isEnabled) return;
56514
+ if (!isEnabled2) return;
56515
56515
  if (!eventBus.onAny) return;
56516
56516
  const verificationProviderLifecycleListener = (evt) => {
56517
56517
  const parsed = parseLifecycleEvent(evt.type);
@@ -56614,9 +56614,9 @@ function VerificationProvider({
56614
56614
  "pass"
56615
56615
  );
56616
56616
  return unsub;
56617
- }, [isEnabled, eventBus]);
56617
+ }, [isEnabled2, eventBus]);
56618
56618
  React147.useEffect(() => {
56619
- if (!isEnabled) return;
56619
+ if (!isEnabled2) return;
56620
56620
  if (!runtimeManager) return;
56621
56621
  runtimeManager.setObserver({
56622
56622
  onTransition(trace) {
@@ -56636,20 +56636,20 @@ function VerificationProvider({
56636
56636
  "VerificationProvider active (runtime path)",
56637
56637
  "pass"
56638
56638
  );
56639
- }, [isEnabled, runtimeManager]);
56639
+ }, [isEnabled2, runtimeManager]);
56640
56640
  React147.useEffect(() => {
56641
- if (!isEnabled) return;
56641
+ if (!isEnabled2) return;
56642
56642
  bindEventBus(eventBus);
56643
- }, [isEnabled, eventBus]);
56643
+ }, [isEnabled2, eventBus]);
56644
56644
  React147.useEffect(() => {
56645
- if (!isEnabled) return;
56645
+ if (!isEnabled2) return;
56646
56646
  if (traitStateGetter) {
56647
56647
  bindTraitStateGetter(traitStateGetter);
56648
56648
  } else if (runtimeManager?.getState) {
56649
56649
  const mgr = runtimeManager;
56650
56650
  bindTraitStateGetter((traitName) => mgr.getState(traitName));
56651
56651
  }
56652
- }, [isEnabled, traitStateGetter, runtimeManager]);
56652
+ }, [isEnabled2, traitStateGetter, runtimeManager]);
56653
56653
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
56654
56654
  }
56655
56655
  VerificationProvider.displayName = "VerificationProvider";
@@ -57863,6 +57863,66 @@ function ServerBridgeProvider({
57863
57863
  // runtime/OrbPreview.tsx
57864
57864
  init_navigation();
57865
57865
  init_verificationRegistry();
57866
+ var PERF_NAMESPACE = "almadar:perf:canvas";
57867
+ var log17 = logger.createLogger(PERF_NAMESPACE);
57868
+ var RING_SIZE = 50;
57869
+ var ring = [];
57870
+ var writeIdx = 0;
57871
+ var subscribers = /* @__PURE__ */ new Set();
57872
+ function push(entry) {
57873
+ if (ring.length < RING_SIZE) {
57874
+ ring.push(entry);
57875
+ } else {
57876
+ ring[writeIdx] = entry;
57877
+ }
57878
+ writeIdx = (writeIdx + 1) % RING_SIZE;
57879
+ for (const fn of subscribers) fn();
57880
+ }
57881
+ function isEnabled() {
57882
+ return logger.isLogLevelEnabled("DEBUG", PERF_NAMESPACE);
57883
+ }
57884
+ function now() {
57885
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
57886
+ }
57887
+ function perfStart(name) {
57888
+ if (!isEnabled()) return -1;
57889
+ if (typeof performance !== "undefined" && typeof performance.mark === "function") {
57890
+ try {
57891
+ performance.mark(`${name}-start`);
57892
+ } catch {
57893
+ }
57894
+ }
57895
+ return now();
57896
+ }
57897
+ function perfEnd(name, startToken, detail) {
57898
+ if (startToken < 0 || !isEnabled()) return;
57899
+ const endTs = now();
57900
+ const durationMs = endTs - startToken;
57901
+ if (typeof performance !== "undefined" && typeof performance.measure === "function") {
57902
+ try {
57903
+ performance.mark(`${name}-end`);
57904
+ performance.measure(name, `${name}-start`, `${name}-end`);
57905
+ } catch {
57906
+ }
57907
+ }
57908
+ push({ name, durationMs, ts: endTs, detail });
57909
+ log17.debug(name, () => ({ durationMs, ...detail ?? {} }));
57910
+ }
57911
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
57912
+ if (!isEnabled()) return;
57913
+ push({
57914
+ name: `profiler:${id}:${phase}`,
57915
+ durationMs: actualDuration,
57916
+ ts: commitTime,
57917
+ detail: { baseDuration }
57918
+ });
57919
+ log17.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
57920
+ };
57921
+ function bumpRevision() {
57922
+ }
57923
+ subscribers.add(bumpRevision);
57924
+
57925
+ // runtime/prepareSchemaForPreview.ts
57866
57926
  function generateEntityRow(entity, idx) {
57867
57927
  const row = { id: String(idx) };
57868
57928
  for (const f3 of entity.fields) {
@@ -57888,6 +57948,7 @@ function generateFieldValue(entityName, field, idx) {
57888
57948
  }
57889
57949
  }
57890
57950
  function buildMockData(schema) {
57951
+ const t = perfStart("build-mock-data");
57891
57952
  const result = {};
57892
57953
  for (const orbital of schema.orbitals) {
57893
57954
  const entity = orbital.entity;
@@ -57905,6 +57966,7 @@ function buildMockData(schema) {
57905
57966
  );
57906
57967
  result[entityName] = rows;
57907
57968
  }
57969
+ perfEnd("build-mock-data", t, { orbitalCount: schema.orbitals.length, entityCount: Object.keys(result).length });
57908
57970
  return result;
57909
57971
  }
57910
57972
  function isInlineTrait2(traitRef) {
@@ -59827,9 +59889,16 @@ function FlowCanvasInner({
59827
59889
  }), [selectedPattern]);
59828
59890
  const [atBehaviorLevel, setAtBehaviorLevel] = React147.useState(composeLevel === "behavior");
59829
59891
  const { composeNodes, composeEdges, overviewNodes, overviewEdges, expandedNodes, expandedEdges } = React147.useMemo(() => {
59892
+ const t = perfStart("compose-graph");
59830
59893
  const compose = composeLevel === "behavior" && behaviorEntries?.length ? behaviorsToComposeGraph(behaviorEntries, behaviorWires ?? [], layoutHint) : { nodes: [], edges: [] };
59831
59894
  const overview = schemaToOverviewGraph(parsedSchema, mockData, behaviorMeta, layoutHint);
59832
59895
  const expanded = expandedOrbital ? orbitalToExpandedGraph(parsedSchema, expandedOrbital, mockData) : { nodes: [], edges: [] };
59896
+ perfEnd("compose-graph", t, {
59897
+ composeNodes: compose.nodes.length,
59898
+ overviewNodes: overview.nodes.length,
59899
+ expandedNodes: expanded.nodes.length,
59900
+ orbitalCount: parsedSchema.orbitals?.length ?? 0
59901
+ });
59833
59902
  return {
59834
59903
  composeNodes: compose.nodes,
59835
59904
  composeEdges: compose.edges,
@@ -59838,7 +59907,7 @@ function FlowCanvasInner({
59838
59907
  expandedNodes: expanded.nodes,
59839
59908
  expandedEdges: expanded.edges
59840
59909
  };
59841
- }, [parsedSchema, expandedOrbital, behaviorMeta, layoutHint, composeLevel, behaviorEntries, behaviorWires]);
59910
+ }, [parsedSchema, expandedOrbital, behaviorMeta, layoutHint, composeLevel, behaviorEntries, behaviorWires, mockData]);
59842
59911
  const activeNodes = atBehaviorLevel && composeNodes.length > 0 ? composeNodes : level === "overview" ? overviewNodes : expandedNodes;
59843
59912
  const activeEdges = atBehaviorLevel && composeEdges.length > 0 ? composeEdges : level === "overview" ? overviewEdges : expandedEdges;
59844
59913
  const [nodes, setNodes, onNodesChange] = react.useNodesState(activeNodes);
@@ -60096,7 +60165,7 @@ function FlowCanvasInner({
60096
60165
  ) }) });
60097
60166
  }
60098
60167
  var FlowCanvas = (props) => {
60099
- return /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(FlowCanvasInner, { ...props }) });
60168
+ return /* @__PURE__ */ jsxRuntime.jsx(React147.Profiler, { id: "flow-canvas", onRender: profilerOnRender, children: /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(FlowCanvasInner, { ...props }) }) });
60100
60169
  };
60101
60170
  FlowCanvas.displayName = "FlowCanvas";
60102
60171
  var BAND_LABELS = {
@@ -60223,7 +60292,7 @@ init_AvlTransitionLane();
60223
60292
  init_AvlSwimLane();
60224
60293
  init_types();
60225
60294
  init_avl_elk_layout();
60226
- var log17 = logger.createLogger("almadar:ui:avl:trait-scene");
60295
+ var log18 = logger.createLogger("almadar:ui:avl:trait-scene");
60227
60296
  var SWIM_GUTTER2 = 120;
60228
60297
  var CENTER_W2 = 360;
60229
60298
  var AvlTraitScene = ({
@@ -60235,7 +60304,7 @@ var AvlTraitScene = ({
60235
60304
  const dataKey = React147.useMemo(() => JSON.stringify(data), [data]);
60236
60305
  React147.useEffect(() => {
60237
60306
  computeTraitLayout(data).then(setLayout).catch((error) => {
60238
- log17.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
60307
+ log18.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
60239
60308
  });
60240
60309
  }, [dataKey]);
60241
60310
  if (!layout) {
package/dist/avl/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { OrbitControls as OrbitControls$1, Grid as Grid$1, Stars, Sparkles, Html, RoundedBox } from '@react-three/drei';
3
3
  import * as React147 from 'react';
4
- import React147__default, { createContext, useState, useEffect, useMemo, useContext, useRef, useCallback, Suspense, useLayoutEffect, useReducer, lazy, useId, forwardRef, useImperativeHandle, Component } from 'react';
4
+ import React147__default, { createContext, useState, useEffect, useMemo, useContext, useRef, useCallback, Suspense, useLayoutEffect, Profiler, useReducer, lazy, useId, forwardRef, useImperativeHandle, Component } from 'react';
5
5
  import { createLogger, isLogLevelEnabled } from '@almadar/logger';
6
6
  import ELK from 'elkjs/lib/elk.bundled.js';
7
7
  import { MarkerType, Handle, Position, getBezierPath, EdgeLabelRenderer, BaseEdge, ReactFlowProvider, useNodesState, useEdgesState, useReactFlow, ReactFlow, Controls, Background, BackgroundVariant } from '@xyflow/react';
@@ -9935,8 +9935,8 @@ function Seigaiha({ size, color, strokeWidth }) {
9935
9935
  [s, s * 0.1]
9936
9936
  ];
9937
9937
  for (const [cx, cy] of centers) {
9938
- for (let ring = 1; ring <= 3; ring++) {
9939
- const cr = r2 * (ring / 3);
9938
+ for (let ring2 = 1; ring2 <= 3; ring2++) {
9939
+ const cr = r2 * (ring2 / 3);
9940
9940
  paths.push(
9941
9941
  `M ${f(cx - cr)},${f(cy)} A ${f(cr)} ${f(cr)} 0 0 1 ${f(cx + cr)},${f(cy)}`
9942
9942
  );
@@ -10033,8 +10033,8 @@ function Arch({ size, color, strokeWidth }) {
10033
10033
  const h = size * 1.5;
10034
10034
  const cx = w / 2;
10035
10035
  const paths = [];
10036
- for (let ring = 0; ring < 4; ring++) {
10037
- const scale = 1 - ring * 0.2;
10036
+ for (let ring2 = 0; ring2 < 4; ring2++) {
10037
+ const scale = 1 - ring2 * 0.2;
10038
10038
  const archW = w * 0.48 * scale;
10039
10039
  const archH = h * 0.7 * scale;
10040
10040
  const baseY = h * 0.85;
@@ -10049,7 +10049,7 @@ function Arch({ size, color, strokeWidth }) {
10049
10049
  paths.push(
10050
10050
  `M ${f(lx)},${f(baseY)} A ${f(radius)} ${f(radius)} 0 0 1 ${f(cx)},${f(tipY)} A ${f(radius)} ${f(radius)} 0 0 1 ${f(rx)},${f(baseY)}`
10051
10051
  );
10052
- if (ring === 0) {
10052
+ if (ring2 === 0) {
10053
10053
  paths.push(`M ${f(lx)},${f(baseY)} L ${f(rx)},${f(baseY)}`);
10054
10054
  }
10055
10055
  }
@@ -21703,20 +21703,20 @@ function CanvasEffectEngine({
21703
21703
  return img?.complete ? img : void 0;
21704
21704
  }, []);
21705
21705
  useEffect(() => {
21706
- const now = performance.now();
21706
+ const now2 = performance.now();
21707
21707
  const effectX = x || width / 2;
21708
21708
  const effectY = y || height / 2;
21709
21709
  const preset = presets[actionType](effectX, effectY);
21710
21710
  const state = stateRef.current;
21711
21711
  for (const emitter of preset.particles) {
21712
21712
  const scaledEmitter = { ...emitter, count: Math.round(emitter.count * intensity) };
21713
- state.particles.push(...spawnParticles(scaledEmitter, now));
21713
+ state.particles.push(...spawnParticles(scaledEmitter, now2));
21714
21714
  }
21715
21715
  for (const seqConfig of preset.sequences) {
21716
- state.sequences.push(spawnSequence(seqConfig, now));
21716
+ state.sequences.push(spawnSequence(seqConfig, now2));
21717
21717
  }
21718
21718
  for (const ovConfig of preset.overlays) {
21719
- state.overlays.push(spawnOverlay(ovConfig, now));
21719
+ state.overlays.push(spawnOverlay(ovConfig, now2));
21720
21720
  }
21721
21721
  if (preset.screenShake > 0) {
21722
21722
  shakeRef.current.intensity = preset.screenShake * intensity;
@@ -42426,7 +42426,7 @@ function getAllEvents(traits2) {
42426
42426
  }
42427
42427
  function EventDispatcherTab({ traits: traits2, schema }) {
42428
42428
  const eventBus = useEventBus();
42429
- const [log18, setLog] = React147.useState([]);
42429
+ const [log19, setLog] = React147.useState([]);
42430
42430
  const prevStatesRef = React147.useRef(/* @__PURE__ */ new Map());
42431
42431
  React147.useEffect(() => {
42432
42432
  for (const trait of traits2) {
@@ -42490,9 +42490,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
42490
42490
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Other Events (not available from current state)" }),
42491
42491
  /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
42492
42492
  ] }),
42493
- log18.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
42493
+ log19.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
42494
42494
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Recent Transitions" }),
42495
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log18.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
42495
+ /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log19.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
42496
42496
  /* @__PURE__ */ jsx("span", { className: "text-purple-400", children: entry.traitName }),
42497
42497
  " ",
42498
42498
  /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -56461,11 +56461,11 @@ function VerificationProvider({
56461
56461
  runtimeManager,
56462
56462
  traitStateGetter
56463
56463
  }) {
56464
- const isEnabled = enabled ?? (typeof process !== "undefined" && process.env?.NODE_ENV !== "production");
56464
+ const isEnabled2 = enabled ?? (typeof process !== "undefined" && process.env?.NODE_ENV !== "production");
56465
56465
  const eventBus = useEventBus();
56466
56466
  const pendingRef = useRef(/* @__PURE__ */ new Map());
56467
56467
  useEffect(() => {
56468
- if (!isEnabled) return;
56468
+ if (!isEnabled2) return;
56469
56469
  if (!eventBus.onAny) return;
56470
56470
  const verificationProviderLifecycleListener = (evt) => {
56471
56471
  const parsed = parseLifecycleEvent(evt.type);
@@ -56568,9 +56568,9 @@ function VerificationProvider({
56568
56568
  "pass"
56569
56569
  );
56570
56570
  return unsub;
56571
- }, [isEnabled, eventBus]);
56571
+ }, [isEnabled2, eventBus]);
56572
56572
  useEffect(() => {
56573
- if (!isEnabled) return;
56573
+ if (!isEnabled2) return;
56574
56574
  if (!runtimeManager) return;
56575
56575
  runtimeManager.setObserver({
56576
56576
  onTransition(trace) {
@@ -56590,20 +56590,20 @@ function VerificationProvider({
56590
56590
  "VerificationProvider active (runtime path)",
56591
56591
  "pass"
56592
56592
  );
56593
- }, [isEnabled, runtimeManager]);
56593
+ }, [isEnabled2, runtimeManager]);
56594
56594
  useEffect(() => {
56595
- if (!isEnabled) return;
56595
+ if (!isEnabled2) return;
56596
56596
  bindEventBus(eventBus);
56597
- }, [isEnabled, eventBus]);
56597
+ }, [isEnabled2, eventBus]);
56598
56598
  useEffect(() => {
56599
- if (!isEnabled) return;
56599
+ if (!isEnabled2) return;
56600
56600
  if (traitStateGetter) {
56601
56601
  bindTraitStateGetter(traitStateGetter);
56602
56602
  } else if (runtimeManager?.getState) {
56603
56603
  const mgr = runtimeManager;
56604
56604
  bindTraitStateGetter((traitName) => mgr.getState(traitName));
56605
56605
  }
56606
- }, [isEnabled, traitStateGetter, runtimeManager]);
56606
+ }, [isEnabled2, traitStateGetter, runtimeManager]);
56607
56607
  return /* @__PURE__ */ jsx(Fragment, { children });
56608
56608
  }
56609
56609
  VerificationProvider.displayName = "VerificationProvider";
@@ -57817,6 +57817,66 @@ function ServerBridgeProvider({
57817
57817
  // runtime/OrbPreview.tsx
57818
57818
  init_navigation();
57819
57819
  init_verificationRegistry();
57820
+ var PERF_NAMESPACE = "almadar:perf:canvas";
57821
+ var log17 = createLogger(PERF_NAMESPACE);
57822
+ var RING_SIZE = 50;
57823
+ var ring = [];
57824
+ var writeIdx = 0;
57825
+ var subscribers = /* @__PURE__ */ new Set();
57826
+ function push(entry) {
57827
+ if (ring.length < RING_SIZE) {
57828
+ ring.push(entry);
57829
+ } else {
57830
+ ring[writeIdx] = entry;
57831
+ }
57832
+ writeIdx = (writeIdx + 1) % RING_SIZE;
57833
+ for (const fn of subscribers) fn();
57834
+ }
57835
+ function isEnabled() {
57836
+ return isLogLevelEnabled("DEBUG", PERF_NAMESPACE);
57837
+ }
57838
+ function now() {
57839
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
57840
+ }
57841
+ function perfStart(name) {
57842
+ if (!isEnabled()) return -1;
57843
+ if (typeof performance !== "undefined" && typeof performance.mark === "function") {
57844
+ try {
57845
+ performance.mark(`${name}-start`);
57846
+ } catch {
57847
+ }
57848
+ }
57849
+ return now();
57850
+ }
57851
+ function perfEnd(name, startToken, detail) {
57852
+ if (startToken < 0 || !isEnabled()) return;
57853
+ const endTs = now();
57854
+ const durationMs = endTs - startToken;
57855
+ if (typeof performance !== "undefined" && typeof performance.measure === "function") {
57856
+ try {
57857
+ performance.mark(`${name}-end`);
57858
+ performance.measure(name, `${name}-start`, `${name}-end`);
57859
+ } catch {
57860
+ }
57861
+ }
57862
+ push({ name, durationMs, ts: endTs, detail });
57863
+ log17.debug(name, () => ({ durationMs, ...detail ?? {} }));
57864
+ }
57865
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
57866
+ if (!isEnabled()) return;
57867
+ push({
57868
+ name: `profiler:${id}:${phase}`,
57869
+ durationMs: actualDuration,
57870
+ ts: commitTime,
57871
+ detail: { baseDuration }
57872
+ });
57873
+ log17.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
57874
+ };
57875
+ function bumpRevision() {
57876
+ }
57877
+ subscribers.add(bumpRevision);
57878
+
57879
+ // runtime/prepareSchemaForPreview.ts
57820
57880
  function generateEntityRow(entity, idx) {
57821
57881
  const row = { id: String(idx) };
57822
57882
  for (const f3 of entity.fields) {
@@ -57842,6 +57902,7 @@ function generateFieldValue(entityName, field, idx) {
57842
57902
  }
57843
57903
  }
57844
57904
  function buildMockData(schema) {
57905
+ const t = perfStart("build-mock-data");
57845
57906
  const result = {};
57846
57907
  for (const orbital of schema.orbitals) {
57847
57908
  const entity = orbital.entity;
@@ -57859,6 +57920,7 @@ function buildMockData(schema) {
57859
57920
  );
57860
57921
  result[entityName] = rows;
57861
57922
  }
57923
+ perfEnd("build-mock-data", t, { orbitalCount: schema.orbitals.length, entityCount: Object.keys(result).length });
57862
57924
  return result;
57863
57925
  }
57864
57926
  function isInlineTrait2(traitRef) {
@@ -59781,9 +59843,16 @@ function FlowCanvasInner({
59781
59843
  }), [selectedPattern]);
59782
59844
  const [atBehaviorLevel, setAtBehaviorLevel] = useState(composeLevel === "behavior");
59783
59845
  const { composeNodes, composeEdges, overviewNodes, overviewEdges, expandedNodes, expandedEdges } = useMemo(() => {
59846
+ const t = perfStart("compose-graph");
59784
59847
  const compose = composeLevel === "behavior" && behaviorEntries?.length ? behaviorsToComposeGraph(behaviorEntries, behaviorWires ?? [], layoutHint) : { nodes: [], edges: [] };
59785
59848
  const overview = schemaToOverviewGraph(parsedSchema, mockData, behaviorMeta, layoutHint);
59786
59849
  const expanded = expandedOrbital ? orbitalToExpandedGraph(parsedSchema, expandedOrbital, mockData) : { nodes: [], edges: [] };
59850
+ perfEnd("compose-graph", t, {
59851
+ composeNodes: compose.nodes.length,
59852
+ overviewNodes: overview.nodes.length,
59853
+ expandedNodes: expanded.nodes.length,
59854
+ orbitalCount: parsedSchema.orbitals?.length ?? 0
59855
+ });
59787
59856
  return {
59788
59857
  composeNodes: compose.nodes,
59789
59858
  composeEdges: compose.edges,
@@ -59792,7 +59861,7 @@ function FlowCanvasInner({
59792
59861
  expandedNodes: expanded.nodes,
59793
59862
  expandedEdges: expanded.edges
59794
59863
  };
59795
- }, [parsedSchema, expandedOrbital, behaviorMeta, layoutHint, composeLevel, behaviorEntries, behaviorWires]);
59864
+ }, [parsedSchema, expandedOrbital, behaviorMeta, layoutHint, composeLevel, behaviorEntries, behaviorWires, mockData]);
59796
59865
  const activeNodes = atBehaviorLevel && composeNodes.length > 0 ? composeNodes : level === "overview" ? overviewNodes : expandedNodes;
59797
59866
  const activeEdges = atBehaviorLevel && composeEdges.length > 0 ? composeEdges : level === "overview" ? overviewEdges : expandedEdges;
59798
59867
  const [nodes, setNodes, onNodesChange] = useNodesState(activeNodes);
@@ -60050,7 +60119,7 @@ function FlowCanvasInner({
60050
60119
  ) }) });
60051
60120
  }
60052
60121
  var FlowCanvas = (props) => {
60053
- return /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(FlowCanvasInner, { ...props }) });
60122
+ return /* @__PURE__ */ jsx(Profiler, { id: "flow-canvas", onRender: profilerOnRender, children: /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(FlowCanvasInner, { ...props }) }) });
60054
60123
  };
60055
60124
  FlowCanvas.displayName = "FlowCanvas";
60056
60125
  var BAND_LABELS = {
@@ -60177,7 +60246,7 @@ init_AvlTransitionLane();
60177
60246
  init_AvlSwimLane();
60178
60247
  init_types();
60179
60248
  init_avl_elk_layout();
60180
- var log17 = createLogger("almadar:ui:avl:trait-scene");
60249
+ var log18 = createLogger("almadar:ui:avl:trait-scene");
60181
60250
  var SWIM_GUTTER2 = 120;
60182
60251
  var CENTER_W2 = 360;
60183
60252
  var AvlTraitScene = ({
@@ -60189,7 +60258,7 @@ var AvlTraitScene = ({
60189
60258
  const dataKey = useMemo(() => JSON.stringify(data), [data]);
60190
60259
  useEffect(() => {
60191
60260
  computeTraitLayout(data).then(setLayout).catch((error) => {
60192
- log17.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
60261
+ log18.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
60193
60262
  });
60194
60263
  }, [dataKey]);
60195
60264
  if (!layout) {
@@ -5630,8 +5630,8 @@ function Seigaiha({ size, color, strokeWidth }) {
5630
5630
  [s, s * 0.1]
5631
5631
  ];
5632
5632
  for (const [cx, cy] of centers) {
5633
- for (let ring = 1; ring <= 3; ring++) {
5634
- const cr = r * (ring / 3);
5633
+ for (let ring2 = 1; ring2 <= 3; ring2++) {
5634
+ const cr = r * (ring2 / 3);
5635
5635
  paths.push(
5636
5636
  `M ${f(cx - cr)},${f(cy)} A ${f(cr)} ${f(cr)} 0 0 1 ${f(cx + cr)},${f(cy)}`
5637
5637
  );
@@ -5728,8 +5728,8 @@ function Arch({ size, color, strokeWidth }) {
5728
5728
  const h = size * 1.5;
5729
5729
  const cx = w / 2;
5730
5730
  const paths = [];
5731
- for (let ring = 0; ring < 4; ring++) {
5732
- const scale = 1 - ring * 0.2;
5731
+ for (let ring2 = 0; ring2 < 4; ring2++) {
5732
+ const scale = 1 - ring2 * 0.2;
5733
5733
  const archW = w * 0.48 * scale;
5734
5734
  const archH = h * 0.7 * scale;
5735
5735
  const baseY = h * 0.85;
@@ -5744,7 +5744,7 @@ function Arch({ size, color, strokeWidth }) {
5744
5744
  paths.push(
5745
5745
  `M ${f(lx)},${f(baseY)} A ${f(radius)} ${f(radius)} 0 0 1 ${f(cx)},${f(tipY)} A ${f(radius)} ${f(radius)} 0 0 1 ${f(rx)},${f(baseY)}`
5746
5746
  );
5747
- if (ring === 0) {
5747
+ if (ring2 === 0) {
5748
5748
  paths.push(`M ${f(lx)},${f(baseY)} L ${f(rx)},${f(baseY)}`);
5749
5749
  }
5750
5750
  }
@@ -17947,20 +17947,20 @@ function CanvasEffectEngine({
17947
17947
  return img?.complete ? img : void 0;
17948
17948
  }, []);
17949
17949
  React135.useEffect(() => {
17950
- const now = performance.now();
17950
+ const now2 = performance.now();
17951
17951
  const effectX = x || width / 2;
17952
17952
  const effectY = y || height / 2;
17953
17953
  const preset = presets[actionType](effectX, effectY);
17954
17954
  const state = stateRef.current;
17955
17955
  for (const emitter of preset.particles) {
17956
17956
  const scaledEmitter = { ...emitter, count: Math.round(emitter.count * intensity) };
17957
- state.particles.push(...spawnParticles(scaledEmitter, now));
17957
+ state.particles.push(...spawnParticles(scaledEmitter, now2));
17958
17958
  }
17959
17959
  for (const seqConfig of preset.sequences) {
17960
- state.sequences.push(spawnSequence(seqConfig, now));
17960
+ state.sequences.push(spawnSequence(seqConfig, now2));
17961
17961
  }
17962
17962
  for (const ovConfig of preset.overlays) {
17963
- state.overlays.push(spawnOverlay(ovConfig, now));
17963
+ state.overlays.push(spawnOverlay(ovConfig, now2));
17964
17964
  }
17965
17965
  if (preset.screenShake > 0) {
17966
17966
  shakeRef.current.intensity = preset.screenShake * intensity;
@@ -38857,7 +38857,7 @@ function getAllEvents(traits2) {
38857
38857
  }
38858
38858
  function EventDispatcherTab({ traits: traits2, schema }) {
38859
38859
  const eventBus = useEventBus();
38860
- const [log11, setLog] = React135__namespace.useState([]);
38860
+ const [log12, setLog] = React135__namespace.useState([]);
38861
38861
  const prevStatesRef = React135__namespace.useRef(/* @__PURE__ */ new Map());
38862
38862
  React135__namespace.useEffect(() => {
38863
38863
  for (const trait of traits2) {
@@ -38921,9 +38921,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
38921
38921
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Other Events (not available from current state)" }),
38922
38922
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
38923
38923
  ] }),
38924
- log11.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
38924
+ log12.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
38925
38925
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Recent Transitions" }),
38926
- /* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log11.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
38926
+ /* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log12.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
38927
38927
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400", children: entry.traitName }),
38928
38928
  " ",
38929
38929
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -45720,6 +45720,103 @@ function ServerBridgeProvider({
45720
45720
  // runtime/OrbPreview.tsx
45721
45721
  init_navigation();
45722
45722
  init_verificationRegistry();
45723
+ var PERF_NAMESPACE = "almadar:perf:canvas";
45724
+ var log11 = logger.createLogger(PERF_NAMESPACE);
45725
+ var RING_SIZE = 50;
45726
+ var ring = [];
45727
+ var writeIdx = 0;
45728
+ var subscribers = /* @__PURE__ */ new Set();
45729
+ function push(entry) {
45730
+ if (ring.length < RING_SIZE) {
45731
+ ring.push(entry);
45732
+ } else {
45733
+ ring[writeIdx] = entry;
45734
+ }
45735
+ writeIdx = (writeIdx + 1) % RING_SIZE;
45736
+ for (const fn of subscribers) fn();
45737
+ }
45738
+ function isEnabled() {
45739
+ return logger.isLogLevelEnabled("DEBUG", PERF_NAMESPACE);
45740
+ }
45741
+ function now() {
45742
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
45743
+ }
45744
+ function perfStart(name) {
45745
+ if (!isEnabled()) return -1;
45746
+ if (typeof performance !== "undefined" && typeof performance.mark === "function") {
45747
+ try {
45748
+ performance.mark(`${name}-start`);
45749
+ } catch {
45750
+ }
45751
+ }
45752
+ return now();
45753
+ }
45754
+ function perfEnd(name, startToken, detail) {
45755
+ if (startToken < 0 || !isEnabled()) return;
45756
+ const endTs = now();
45757
+ const durationMs = endTs - startToken;
45758
+ if (typeof performance !== "undefined" && typeof performance.measure === "function") {
45759
+ try {
45760
+ performance.mark(`${name}-end`);
45761
+ performance.measure(name, `${name}-start`, `${name}-end`);
45762
+ } catch {
45763
+ }
45764
+ }
45765
+ push({ name, durationMs, ts: endTs, detail });
45766
+ log11.debug(name, () => ({ durationMs, ...detail ?? {} }));
45767
+ }
45768
+ function perfTime(name, fn, detail) {
45769
+ const t = perfStart(name);
45770
+ try {
45771
+ return fn();
45772
+ } finally {
45773
+ perfEnd(name, t, detail);
45774
+ }
45775
+ }
45776
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
45777
+ if (!isEnabled()) return;
45778
+ push({
45779
+ name: `profiler:${id}:${phase}`,
45780
+ durationMs: actualDuration,
45781
+ ts: commitTime,
45782
+ detail: { baseDuration }
45783
+ });
45784
+ log11.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
45785
+ };
45786
+ function getPerfSnapshot() {
45787
+ if (ring.length < RING_SIZE) return ring.slice();
45788
+ return [...ring.slice(writeIdx), ...ring.slice(0, writeIdx)];
45789
+ }
45790
+ var cachedSnapshot = [];
45791
+ var cachedRevision = -1;
45792
+ var revision = 0;
45793
+ function bumpRevision() {
45794
+ revision++;
45795
+ }
45796
+ subscribers.add(bumpRevision);
45797
+ function getSnapshot2() {
45798
+ if (cachedRevision !== revision) {
45799
+ cachedSnapshot = getPerfSnapshot();
45800
+ cachedRevision = revision;
45801
+ }
45802
+ return cachedSnapshot;
45803
+ }
45804
+ function subscribe(fn) {
45805
+ subscribers.add(fn);
45806
+ return () => {
45807
+ subscribers.delete(fn);
45808
+ };
45809
+ }
45810
+ function usePerfBuffer() {
45811
+ return React135.useSyncExternalStore(subscribe, getSnapshot2, getSnapshot2);
45812
+ }
45813
+ function clearPerf() {
45814
+ ring.length = 0;
45815
+ writeIdx = 0;
45816
+ for (const fn of subscribers) fn();
45817
+ }
45818
+
45819
+ // runtime/prepareSchemaForPreview.ts
45723
45820
  function generateEntityRow(entity, idx) {
45724
45821
  const row = { id: String(idx) };
45725
45822
  for (const f3 of entity.fields) {
@@ -45745,6 +45842,7 @@ function generateFieldValue(entityName, field, idx) {
45745
45842
  }
45746
45843
  }
45747
45844
  function buildMockData(schema) {
45845
+ const t = perfStart("build-mock-data");
45748
45846
  const result = {};
45749
45847
  for (const orbital of schema.orbitals) {
45750
45848
  const entity = orbital.entity;
@@ -45762,6 +45860,7 @@ function buildMockData(schema) {
45762
45860
  );
45763
45861
  result[entityName] = rows;
45764
45862
  }
45863
+ perfEnd("build-mock-data", t, { orbitalCount: schema.orbitals.length, entityCount: Object.keys(result).length });
45765
45864
  return result;
45766
45865
  }
45767
45866
  function isInlineTrait2(traitRef) {
@@ -46281,17 +46380,25 @@ function BrowserPlayground({
46281
46380
  exports.BrowserPlayground = BrowserPlayground;
46282
46381
  exports.EntitySchemaProvider = EntitySchemaProvider;
46283
46382
  exports.OrbPreview = OrbPreview;
46383
+ exports.PERF_NAMESPACE = PERF_NAMESPACE;
46284
46384
  exports.ServerBridgeProvider = ServerBridgeProvider;
46285
46385
  exports.TraitContext = TraitContext;
46286
46386
  exports.TraitProvider = TraitProvider;
46287
46387
  exports.adjustSchemaForMockData = adjustSchemaForMockData;
46288
46388
  exports.buildMockData = buildMockData;
46389
+ exports.clearPerf = clearPerf;
46289
46390
  exports.clearSchemaCache = clearSchemaCache;
46290
46391
  exports.createClientEffectHandlers = createClientEffectHandlers;
46392
+ exports.getPerfSnapshot = getPerfSnapshot;
46393
+ exports.perfEnd = perfEnd;
46394
+ exports.perfStart = perfStart;
46395
+ exports.perfTime = perfTime;
46291
46396
  exports.prepareSchemaForPreview = prepareSchemaForPreview;
46397
+ exports.profilerOnRender = profilerOnRender;
46292
46398
  exports.useEntityDefinition = useEntityDefinition;
46293
46399
  exports.useEntitySchema = useEntitySchema;
46294
46400
  exports.useEntitySchemaOptional = useEntitySchemaOptional;
46401
+ exports.usePerfBuffer = usePerfBuffer;
46295
46402
  exports.useResolvedSchema = useResolvedSchema;
46296
46403
  exports.useServerBridge = useServerBridge;
46297
46404
  exports.useTrait = useTrait;
@@ -18,3 +18,4 @@ export { BrowserPlayground, type BrowserPlaygroundProps } from './BrowserPlaygro
18
18
  export { prepareSchemaForPreview, buildMockData, adjustSchemaForMockData, type PreparedPreviewSchema, } from './prepareSchemaForPreview';
19
19
  export { ServerBridgeProvider, useServerBridge, type ServerBridgeContextValue, type ServerBridgeTransport, type ServerClientEffect } from './ServerBridge';
20
20
  export type { ResolvedTraitBinding, ResolvedTrait, ResolvedEntity, ResolvedPage, ResolvedIR, } from './types';
21
+ export { PERF_NAMESPACE, perfStart, perfEnd, perfTime, profilerOnRender, getPerfSnapshot, usePerfBuffer, clearPerf, type PerfEntry, } from './perf';
@@ -1,5 +1,5 @@
1
1
  import * as React135 from 'react';
2
- import React135__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useLayoutEffect, lazy, useId } from 'react';
2
+ import React135__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useSyncExternalStore, useLayoutEffect, lazy, useId } from 'react';
3
3
  import { EventBusContext, useTraitScope, OrbitalProvider, TraitScopeProvider, VerificationProvider } from '@almadar/ui/providers';
4
4
  import { createLogger, isLogLevelEnabled } from '@almadar/logger';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -5584,8 +5584,8 @@ function Seigaiha({ size, color, strokeWidth }) {
5584
5584
  [s, s * 0.1]
5585
5585
  ];
5586
5586
  for (const [cx, cy] of centers) {
5587
- for (let ring = 1; ring <= 3; ring++) {
5588
- const cr = r * (ring / 3);
5587
+ for (let ring2 = 1; ring2 <= 3; ring2++) {
5588
+ const cr = r * (ring2 / 3);
5589
5589
  paths.push(
5590
5590
  `M ${f(cx - cr)},${f(cy)} A ${f(cr)} ${f(cr)} 0 0 1 ${f(cx + cr)},${f(cy)}`
5591
5591
  );
@@ -5682,8 +5682,8 @@ function Arch({ size, color, strokeWidth }) {
5682
5682
  const h = size * 1.5;
5683
5683
  const cx = w / 2;
5684
5684
  const paths = [];
5685
- for (let ring = 0; ring < 4; ring++) {
5686
- const scale = 1 - ring * 0.2;
5685
+ for (let ring2 = 0; ring2 < 4; ring2++) {
5686
+ const scale = 1 - ring2 * 0.2;
5687
5687
  const archW = w * 0.48 * scale;
5688
5688
  const archH = h * 0.7 * scale;
5689
5689
  const baseY = h * 0.85;
@@ -5698,7 +5698,7 @@ function Arch({ size, color, strokeWidth }) {
5698
5698
  paths.push(
5699
5699
  `M ${f(lx)},${f(baseY)} A ${f(radius)} ${f(radius)} 0 0 1 ${f(cx)},${f(tipY)} A ${f(radius)} ${f(radius)} 0 0 1 ${f(rx)},${f(baseY)}`
5700
5700
  );
5701
- if (ring === 0) {
5701
+ if (ring2 === 0) {
5702
5702
  paths.push(`M ${f(lx)},${f(baseY)} L ${f(rx)},${f(baseY)}`);
5703
5703
  }
5704
5704
  }
@@ -17901,20 +17901,20 @@ function CanvasEffectEngine({
17901
17901
  return img?.complete ? img : void 0;
17902
17902
  }, []);
17903
17903
  useEffect(() => {
17904
- const now = performance.now();
17904
+ const now2 = performance.now();
17905
17905
  const effectX = x || width / 2;
17906
17906
  const effectY = y || height / 2;
17907
17907
  const preset = presets[actionType](effectX, effectY);
17908
17908
  const state = stateRef.current;
17909
17909
  for (const emitter of preset.particles) {
17910
17910
  const scaledEmitter = { ...emitter, count: Math.round(emitter.count * intensity) };
17911
- state.particles.push(...spawnParticles(scaledEmitter, now));
17911
+ state.particles.push(...spawnParticles(scaledEmitter, now2));
17912
17912
  }
17913
17913
  for (const seqConfig of preset.sequences) {
17914
- state.sequences.push(spawnSequence(seqConfig, now));
17914
+ state.sequences.push(spawnSequence(seqConfig, now2));
17915
17915
  }
17916
17916
  for (const ovConfig of preset.overlays) {
17917
- state.overlays.push(spawnOverlay(ovConfig, now));
17917
+ state.overlays.push(spawnOverlay(ovConfig, now2));
17918
17918
  }
17919
17919
  if (preset.screenShake > 0) {
17920
17920
  shakeRef.current.intensity = preset.screenShake * intensity;
@@ -38811,7 +38811,7 @@ function getAllEvents(traits2) {
38811
38811
  }
38812
38812
  function EventDispatcherTab({ traits: traits2, schema }) {
38813
38813
  const eventBus = useEventBus();
38814
- const [log11, setLog] = React135.useState([]);
38814
+ const [log12, setLog] = React135.useState([]);
38815
38815
  const prevStatesRef = React135.useRef(/* @__PURE__ */ new Map());
38816
38816
  React135.useEffect(() => {
38817
38817
  for (const trait of traits2) {
@@ -38875,9 +38875,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
38875
38875
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Other Events (not available from current state)" }),
38876
38876
  /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
38877
38877
  ] }),
38878
- log11.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
38878
+ log12.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
38879
38879
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Recent Transitions" }),
38880
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log11.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
38880
+ /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log12.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
38881
38881
  /* @__PURE__ */ jsx("span", { className: "text-purple-400", children: entry.traitName }),
38882
38882
  " ",
38883
38883
  /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -45674,6 +45674,103 @@ function ServerBridgeProvider({
45674
45674
  // runtime/OrbPreview.tsx
45675
45675
  init_navigation();
45676
45676
  init_verificationRegistry();
45677
+ var PERF_NAMESPACE = "almadar:perf:canvas";
45678
+ var log11 = createLogger(PERF_NAMESPACE);
45679
+ var RING_SIZE = 50;
45680
+ var ring = [];
45681
+ var writeIdx = 0;
45682
+ var subscribers = /* @__PURE__ */ new Set();
45683
+ function push(entry) {
45684
+ if (ring.length < RING_SIZE) {
45685
+ ring.push(entry);
45686
+ } else {
45687
+ ring[writeIdx] = entry;
45688
+ }
45689
+ writeIdx = (writeIdx + 1) % RING_SIZE;
45690
+ for (const fn of subscribers) fn();
45691
+ }
45692
+ function isEnabled() {
45693
+ return isLogLevelEnabled("DEBUG", PERF_NAMESPACE);
45694
+ }
45695
+ function now() {
45696
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
45697
+ }
45698
+ function perfStart(name) {
45699
+ if (!isEnabled()) return -1;
45700
+ if (typeof performance !== "undefined" && typeof performance.mark === "function") {
45701
+ try {
45702
+ performance.mark(`${name}-start`);
45703
+ } catch {
45704
+ }
45705
+ }
45706
+ return now();
45707
+ }
45708
+ function perfEnd(name, startToken, detail) {
45709
+ if (startToken < 0 || !isEnabled()) return;
45710
+ const endTs = now();
45711
+ const durationMs = endTs - startToken;
45712
+ if (typeof performance !== "undefined" && typeof performance.measure === "function") {
45713
+ try {
45714
+ performance.mark(`${name}-end`);
45715
+ performance.measure(name, `${name}-start`, `${name}-end`);
45716
+ } catch {
45717
+ }
45718
+ }
45719
+ push({ name, durationMs, ts: endTs, detail });
45720
+ log11.debug(name, () => ({ durationMs, ...detail ?? {} }));
45721
+ }
45722
+ function perfTime(name, fn, detail) {
45723
+ const t = perfStart(name);
45724
+ try {
45725
+ return fn();
45726
+ } finally {
45727
+ perfEnd(name, t, detail);
45728
+ }
45729
+ }
45730
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
45731
+ if (!isEnabled()) return;
45732
+ push({
45733
+ name: `profiler:${id}:${phase}`,
45734
+ durationMs: actualDuration,
45735
+ ts: commitTime,
45736
+ detail: { baseDuration }
45737
+ });
45738
+ log11.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
45739
+ };
45740
+ function getPerfSnapshot() {
45741
+ if (ring.length < RING_SIZE) return ring.slice();
45742
+ return [...ring.slice(writeIdx), ...ring.slice(0, writeIdx)];
45743
+ }
45744
+ var cachedSnapshot = [];
45745
+ var cachedRevision = -1;
45746
+ var revision = 0;
45747
+ function bumpRevision() {
45748
+ revision++;
45749
+ }
45750
+ subscribers.add(bumpRevision);
45751
+ function getSnapshot2() {
45752
+ if (cachedRevision !== revision) {
45753
+ cachedSnapshot = getPerfSnapshot();
45754
+ cachedRevision = revision;
45755
+ }
45756
+ return cachedSnapshot;
45757
+ }
45758
+ function subscribe(fn) {
45759
+ subscribers.add(fn);
45760
+ return () => {
45761
+ subscribers.delete(fn);
45762
+ };
45763
+ }
45764
+ function usePerfBuffer() {
45765
+ return useSyncExternalStore(subscribe, getSnapshot2, getSnapshot2);
45766
+ }
45767
+ function clearPerf() {
45768
+ ring.length = 0;
45769
+ writeIdx = 0;
45770
+ for (const fn of subscribers) fn();
45771
+ }
45772
+
45773
+ // runtime/prepareSchemaForPreview.ts
45677
45774
  function generateEntityRow(entity, idx) {
45678
45775
  const row = { id: String(idx) };
45679
45776
  for (const f3 of entity.fields) {
@@ -45699,6 +45796,7 @@ function generateFieldValue(entityName, field, idx) {
45699
45796
  }
45700
45797
  }
45701
45798
  function buildMockData(schema) {
45799
+ const t = perfStart("build-mock-data");
45702
45800
  const result = {};
45703
45801
  for (const orbital of schema.orbitals) {
45704
45802
  const entity = orbital.entity;
@@ -45716,6 +45814,7 @@ function buildMockData(schema) {
45716
45814
  );
45717
45815
  result[entityName] = rows;
45718
45816
  }
45817
+ perfEnd("build-mock-data", t, { orbitalCount: schema.orbitals.length, entityCount: Object.keys(result).length });
45719
45818
  return result;
45720
45819
  }
45721
45820
  function isInlineTrait2(traitRef) {
@@ -46232,4 +46331,4 @@ function BrowserPlayground({
46232
46331
  );
46233
46332
  }
46234
46333
 
46235
- export { BrowserPlayground, EntitySchemaProvider, OrbPreview, ServerBridgeProvider, TraitContext, TraitProvider, adjustSchemaForMockData, buildMockData, clearSchemaCache, createClientEffectHandlers, prepareSchemaForPreview, useEntityDefinition, useEntitySchema, useEntitySchemaOptional, useResolvedSchema, useServerBridge, useTrait, useTraitContext, useTraitStateMachine, wrapCallbackForEvent };
46334
+ export { BrowserPlayground, EntitySchemaProvider, OrbPreview, PERF_NAMESPACE, ServerBridgeProvider, TraitContext, TraitProvider, adjustSchemaForMockData, buildMockData, clearPerf, clearSchemaCache, createClientEffectHandlers, getPerfSnapshot, perfEnd, perfStart, perfTime, prepareSchemaForPreview, profilerOnRender, useEntityDefinition, useEntitySchema, useEntitySchemaOptional, usePerfBuffer, useResolvedSchema, useServerBridge, useTrait, useTraitContext, useTraitStateMachine, wrapCallbackForEvent };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @almadar/ui/runtime — perf instrumentation
3
+ *
4
+ * Ring buffer of timing events for the canvas render path, plus mark/measure
5
+ * helpers and a React.Profiler onRender callback. All gated behind
6
+ * `createLogger('almadar:perf:canvas')` so production (LOG_LEVEL >= WARN)
7
+ * skips both `performance.*` calls and the ring write.
8
+ */
9
+ import type { ProfilerOnRenderCallback } from 'react';
10
+ export declare const PERF_NAMESPACE = "almadar:perf:canvas";
11
+ export interface PerfEntry {
12
+ readonly name: string;
13
+ readonly durationMs: number;
14
+ readonly ts: number;
15
+ readonly detail?: Readonly<Record<string, unknown>>;
16
+ }
17
+ /**
18
+ * Start a phase. Returns an opaque token; pass to {@link perfEnd}.
19
+ * Returns -1 when the namespace is gated off, so call sites pay only one comparison.
20
+ */
21
+ export declare function perfStart(name: string): number;
22
+ export declare function perfEnd(name: string, startToken: number, detail?: Record<string, unknown>): void;
23
+ /** Synchronous wrapper that times a fn end-to-end. */
24
+ export declare function perfTime<T>(name: string, fn: () => T, detail?: Record<string, unknown>): T;
25
+ /**
26
+ * React.Profiler `onRender` callback. Records `actualDuration` per commit.
27
+ * Phase is `"mount" | "update" | "nested-update"`.
28
+ */
29
+ export declare const profilerOnRender: ProfilerOnRenderCallback;
30
+ /** Snapshot in insertion order (oldest first). Stable identity until next push. */
31
+ export declare function getPerfSnapshot(): readonly PerfEntry[];
32
+ /** React hook: returns the current ring snapshot, re-renders on push. */
33
+ export declare function usePerfBuffer(): readonly PerfEntry[];
34
+ export declare function clearPerf(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.46.0",
3
+ "version": "4.47.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [