@almadar/ui 4.46.0 → 4.47.1

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,72 @@ 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
+ var notifyScheduled = false;
57873
+ function scheduleNotify() {
57874
+ if (notifyScheduled) return;
57875
+ notifyScheduled = true;
57876
+ queueMicrotask(() => {
57877
+ notifyScheduled = false;
57878
+ for (const fn of subscribers) fn();
57879
+ });
57880
+ }
57881
+ function push(entry) {
57882
+ if (ring.length < RING_SIZE) {
57883
+ ring.push(entry);
57884
+ } else {
57885
+ ring[writeIdx] = entry;
57886
+ }
57887
+ writeIdx = (writeIdx + 1) % RING_SIZE;
57888
+ scheduleNotify();
57889
+ }
57890
+ function isEnabled() {
57891
+ return logger.isLogLevelEnabled("DEBUG", PERF_NAMESPACE);
57892
+ }
57893
+ function now() {
57894
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
57895
+ }
57896
+ function perfStart(name) {
57897
+ if (!isEnabled()) return -1;
57898
+ if (typeof performance !== "undefined" && typeof performance.mark === "function") {
57899
+ try {
57900
+ performance.mark(`${name}-start`);
57901
+ } catch {
57902
+ }
57903
+ }
57904
+ return now();
57905
+ }
57906
+ function perfEnd(name, startToken, detail) {
57907
+ if (startToken < 0 || !isEnabled()) return;
57908
+ const endTs = now();
57909
+ const durationMs = endTs - startToken;
57910
+ if (typeof performance !== "undefined" && typeof performance.measure === "function") {
57911
+ try {
57912
+ performance.mark(`${name}-end`);
57913
+ performance.measure(name, `${name}-start`, `${name}-end`);
57914
+ } catch {
57915
+ }
57916
+ }
57917
+ push({ name, durationMs, ts: endTs, detail });
57918
+ log17.debug(name, () => ({ durationMs, ...detail ?? {} }));
57919
+ }
57920
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
57921
+ if (!isEnabled()) return;
57922
+ push({
57923
+ name: `profiler:${id}:${phase}`,
57924
+ durationMs: actualDuration,
57925
+ ts: commitTime,
57926
+ detail: { baseDuration }
57927
+ });
57928
+ log17.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
57929
+ };
57930
+
57931
+ // runtime/prepareSchemaForPreview.ts
57866
57932
  function generateEntityRow(entity, idx) {
57867
57933
  const row = { id: String(idx) };
57868
57934
  for (const f3 of entity.fields) {
@@ -57888,6 +57954,7 @@ function generateFieldValue(entityName, field, idx) {
57888
57954
  }
57889
57955
  }
57890
57956
  function buildMockData(schema) {
57957
+ const t = perfStart("build-mock-data");
57891
57958
  const result = {};
57892
57959
  for (const orbital of schema.orbitals) {
57893
57960
  const entity = orbital.entity;
@@ -57905,6 +57972,7 @@ function buildMockData(schema) {
57905
57972
  );
57906
57973
  result[entityName] = rows;
57907
57974
  }
57975
+ perfEnd("build-mock-data", t, { orbitalCount: schema.orbitals.length, entityCount: Object.keys(result).length });
57908
57976
  return result;
57909
57977
  }
57910
57978
  function isInlineTrait2(traitRef) {
@@ -59827,9 +59895,16 @@ function FlowCanvasInner({
59827
59895
  }), [selectedPattern]);
59828
59896
  const [atBehaviorLevel, setAtBehaviorLevel] = React147.useState(composeLevel === "behavior");
59829
59897
  const { composeNodes, composeEdges, overviewNodes, overviewEdges, expandedNodes, expandedEdges } = React147.useMemo(() => {
59898
+ const t = perfStart("compose-graph");
59830
59899
  const compose = composeLevel === "behavior" && behaviorEntries?.length ? behaviorsToComposeGraph(behaviorEntries, behaviorWires ?? [], layoutHint) : { nodes: [], edges: [] };
59831
59900
  const overview = schemaToOverviewGraph(parsedSchema, mockData, behaviorMeta, layoutHint);
59832
59901
  const expanded = expandedOrbital ? orbitalToExpandedGraph(parsedSchema, expandedOrbital, mockData) : { nodes: [], edges: [] };
59902
+ perfEnd("compose-graph", t, {
59903
+ composeNodes: compose.nodes.length,
59904
+ overviewNodes: overview.nodes.length,
59905
+ expandedNodes: expanded.nodes.length,
59906
+ orbitalCount: parsedSchema.orbitals?.length ?? 0
59907
+ });
59833
59908
  return {
59834
59909
  composeNodes: compose.nodes,
59835
59910
  composeEdges: compose.edges,
@@ -59838,7 +59913,7 @@ function FlowCanvasInner({
59838
59913
  expandedNodes: expanded.nodes,
59839
59914
  expandedEdges: expanded.edges
59840
59915
  };
59841
- }, [parsedSchema, expandedOrbital, behaviorMeta, layoutHint, composeLevel, behaviorEntries, behaviorWires]);
59916
+ }, [parsedSchema, expandedOrbital, behaviorMeta, layoutHint, composeLevel, behaviorEntries, behaviorWires, mockData]);
59842
59917
  const activeNodes = atBehaviorLevel && composeNodes.length > 0 ? composeNodes : level === "overview" ? overviewNodes : expandedNodes;
59843
59918
  const activeEdges = atBehaviorLevel && composeEdges.length > 0 ? composeEdges : level === "overview" ? overviewEdges : expandedEdges;
59844
59919
  const [nodes, setNodes, onNodesChange] = react.useNodesState(activeNodes);
@@ -60096,7 +60171,7 @@ function FlowCanvasInner({
60096
60171
  ) }) });
60097
60172
  }
60098
60173
  var FlowCanvas = (props) => {
60099
- return /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(FlowCanvasInner, { ...props }) });
60174
+ return /* @__PURE__ */ jsxRuntime.jsx(React147.Profiler, { id: "flow-canvas", onRender: profilerOnRender, children: /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(FlowCanvasInner, { ...props }) }) });
60100
60175
  };
60101
60176
  FlowCanvas.displayName = "FlowCanvas";
60102
60177
  var BAND_LABELS = {
@@ -60223,7 +60298,7 @@ init_AvlTransitionLane();
60223
60298
  init_AvlSwimLane();
60224
60299
  init_types();
60225
60300
  init_avl_elk_layout();
60226
- var log17 = logger.createLogger("almadar:ui:avl:trait-scene");
60301
+ var log18 = logger.createLogger("almadar:ui:avl:trait-scene");
60227
60302
  var SWIM_GUTTER2 = 120;
60228
60303
  var CENTER_W2 = 360;
60229
60304
  var AvlTraitScene = ({
@@ -60235,7 +60310,7 @@ var AvlTraitScene = ({
60235
60310
  const dataKey = React147.useMemo(() => JSON.stringify(data), [data]);
60236
60311
  React147.useEffect(() => {
60237
60312
  computeTraitLayout(data).then(setLayout).catch((error) => {
60238
- log17.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
60313
+ log18.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
60239
60314
  });
60240
60315
  }, [dataKey]);
60241
60316
  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,72 @@ 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
+ var notifyScheduled = false;
57827
+ function scheduleNotify() {
57828
+ if (notifyScheduled) return;
57829
+ notifyScheduled = true;
57830
+ queueMicrotask(() => {
57831
+ notifyScheduled = false;
57832
+ for (const fn of subscribers) fn();
57833
+ });
57834
+ }
57835
+ function push(entry) {
57836
+ if (ring.length < RING_SIZE) {
57837
+ ring.push(entry);
57838
+ } else {
57839
+ ring[writeIdx] = entry;
57840
+ }
57841
+ writeIdx = (writeIdx + 1) % RING_SIZE;
57842
+ scheduleNotify();
57843
+ }
57844
+ function isEnabled() {
57845
+ return isLogLevelEnabled("DEBUG", PERF_NAMESPACE);
57846
+ }
57847
+ function now() {
57848
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
57849
+ }
57850
+ function perfStart(name) {
57851
+ if (!isEnabled()) return -1;
57852
+ if (typeof performance !== "undefined" && typeof performance.mark === "function") {
57853
+ try {
57854
+ performance.mark(`${name}-start`);
57855
+ } catch {
57856
+ }
57857
+ }
57858
+ return now();
57859
+ }
57860
+ function perfEnd(name, startToken, detail) {
57861
+ if (startToken < 0 || !isEnabled()) return;
57862
+ const endTs = now();
57863
+ const durationMs = endTs - startToken;
57864
+ if (typeof performance !== "undefined" && typeof performance.measure === "function") {
57865
+ try {
57866
+ performance.mark(`${name}-end`);
57867
+ performance.measure(name, `${name}-start`, `${name}-end`);
57868
+ } catch {
57869
+ }
57870
+ }
57871
+ push({ name, durationMs, ts: endTs, detail });
57872
+ log17.debug(name, () => ({ durationMs, ...detail ?? {} }));
57873
+ }
57874
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
57875
+ if (!isEnabled()) return;
57876
+ push({
57877
+ name: `profiler:${id}:${phase}`,
57878
+ durationMs: actualDuration,
57879
+ ts: commitTime,
57880
+ detail: { baseDuration }
57881
+ });
57882
+ log17.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
57883
+ };
57884
+
57885
+ // runtime/prepareSchemaForPreview.ts
57820
57886
  function generateEntityRow(entity, idx) {
57821
57887
  const row = { id: String(idx) };
57822
57888
  for (const f3 of entity.fields) {
@@ -57842,6 +57908,7 @@ function generateFieldValue(entityName, field, idx) {
57842
57908
  }
57843
57909
  }
57844
57910
  function buildMockData(schema) {
57911
+ const t = perfStart("build-mock-data");
57845
57912
  const result = {};
57846
57913
  for (const orbital of schema.orbitals) {
57847
57914
  const entity = orbital.entity;
@@ -57859,6 +57926,7 @@ function buildMockData(schema) {
57859
57926
  );
57860
57927
  result[entityName] = rows;
57861
57928
  }
57929
+ perfEnd("build-mock-data", t, { orbitalCount: schema.orbitals.length, entityCount: Object.keys(result).length });
57862
57930
  return result;
57863
57931
  }
57864
57932
  function isInlineTrait2(traitRef) {
@@ -59781,9 +59849,16 @@ function FlowCanvasInner({
59781
59849
  }), [selectedPattern]);
59782
59850
  const [atBehaviorLevel, setAtBehaviorLevel] = useState(composeLevel === "behavior");
59783
59851
  const { composeNodes, composeEdges, overviewNodes, overviewEdges, expandedNodes, expandedEdges } = useMemo(() => {
59852
+ const t = perfStart("compose-graph");
59784
59853
  const compose = composeLevel === "behavior" && behaviorEntries?.length ? behaviorsToComposeGraph(behaviorEntries, behaviorWires ?? [], layoutHint) : { nodes: [], edges: [] };
59785
59854
  const overview = schemaToOverviewGraph(parsedSchema, mockData, behaviorMeta, layoutHint);
59786
59855
  const expanded = expandedOrbital ? orbitalToExpandedGraph(parsedSchema, expandedOrbital, mockData) : { nodes: [], edges: [] };
59856
+ perfEnd("compose-graph", t, {
59857
+ composeNodes: compose.nodes.length,
59858
+ overviewNodes: overview.nodes.length,
59859
+ expandedNodes: expanded.nodes.length,
59860
+ orbitalCount: parsedSchema.orbitals?.length ?? 0
59861
+ });
59787
59862
  return {
59788
59863
  composeNodes: compose.nodes,
59789
59864
  composeEdges: compose.edges,
@@ -59792,7 +59867,7 @@ function FlowCanvasInner({
59792
59867
  expandedNodes: expanded.nodes,
59793
59868
  expandedEdges: expanded.edges
59794
59869
  };
59795
- }, [parsedSchema, expandedOrbital, behaviorMeta, layoutHint, composeLevel, behaviorEntries, behaviorWires]);
59870
+ }, [parsedSchema, expandedOrbital, behaviorMeta, layoutHint, composeLevel, behaviorEntries, behaviorWires, mockData]);
59796
59871
  const activeNodes = atBehaviorLevel && composeNodes.length > 0 ? composeNodes : level === "overview" ? overviewNodes : expandedNodes;
59797
59872
  const activeEdges = atBehaviorLevel && composeEdges.length > 0 ? composeEdges : level === "overview" ? overviewEdges : expandedEdges;
59798
59873
  const [nodes, setNodes, onNodesChange] = useNodesState(activeNodes);
@@ -60050,7 +60125,7 @@ function FlowCanvasInner({
60050
60125
  ) }) });
60051
60126
  }
60052
60127
  var FlowCanvas = (props) => {
60053
- return /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(FlowCanvasInner, { ...props }) });
60128
+ return /* @__PURE__ */ jsx(Profiler, { id: "flow-canvas", onRender: profilerOnRender, children: /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(FlowCanvasInner, { ...props }) }) });
60054
60129
  };
60055
60130
  FlowCanvas.displayName = "FlowCanvas";
60056
60131
  var BAND_LABELS = {
@@ -60177,7 +60252,7 @@ init_AvlTransitionLane();
60177
60252
  init_AvlSwimLane();
60178
60253
  init_types();
60179
60254
  init_avl_elk_layout();
60180
- var log17 = createLogger("almadar:ui:avl:trait-scene");
60255
+ var log18 = createLogger("almadar:ui:avl:trait-scene");
60181
60256
  var SWIM_GUTTER2 = 120;
60182
60257
  var CENTER_W2 = 360;
60183
60258
  var AvlTraitScene = ({
@@ -60189,7 +60264,7 @@ var AvlTraitScene = ({
60189
60264
  const dataKey = useMemo(() => JSON.stringify(data), [data]);
60190
60265
  useEffect(() => {
60191
60266
  computeTraitLayout(data).then(setLayout).catch((error) => {
60192
- log17.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
60267
+ log18.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
60193
60268
  });
60194
60269
  }, [dataKey]);
60195
60270
  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,109 @@ 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
+ var notifyScheduled = false;
45730
+ var revision = 0;
45731
+ var cachedSnapshot = [];
45732
+ var cachedRevision = -1;
45733
+ function scheduleNotify() {
45734
+ if (notifyScheduled) return;
45735
+ notifyScheduled = true;
45736
+ queueMicrotask(() => {
45737
+ notifyScheduled = false;
45738
+ revision++;
45739
+ for (const fn of subscribers) fn();
45740
+ });
45741
+ }
45742
+ function push(entry) {
45743
+ if (ring.length < RING_SIZE) {
45744
+ ring.push(entry);
45745
+ } else {
45746
+ ring[writeIdx] = entry;
45747
+ }
45748
+ writeIdx = (writeIdx + 1) % RING_SIZE;
45749
+ scheduleNotify();
45750
+ }
45751
+ function isEnabled() {
45752
+ return logger.isLogLevelEnabled("DEBUG", PERF_NAMESPACE);
45753
+ }
45754
+ function now() {
45755
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
45756
+ }
45757
+ function perfStart(name) {
45758
+ if (!isEnabled()) return -1;
45759
+ if (typeof performance !== "undefined" && typeof performance.mark === "function") {
45760
+ try {
45761
+ performance.mark(`${name}-start`);
45762
+ } catch {
45763
+ }
45764
+ }
45765
+ return now();
45766
+ }
45767
+ function perfEnd(name, startToken, detail) {
45768
+ if (startToken < 0 || !isEnabled()) return;
45769
+ const endTs = now();
45770
+ const durationMs = endTs - startToken;
45771
+ if (typeof performance !== "undefined" && typeof performance.measure === "function") {
45772
+ try {
45773
+ performance.mark(`${name}-end`);
45774
+ performance.measure(name, `${name}-start`, `${name}-end`);
45775
+ } catch {
45776
+ }
45777
+ }
45778
+ push({ name, durationMs, ts: endTs, detail });
45779
+ log11.debug(name, () => ({ durationMs, ...detail ?? {} }));
45780
+ }
45781
+ function perfTime(name, fn, detail) {
45782
+ const t = perfStart(name);
45783
+ try {
45784
+ return fn();
45785
+ } finally {
45786
+ perfEnd(name, t, detail);
45787
+ }
45788
+ }
45789
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
45790
+ if (!isEnabled()) return;
45791
+ push({
45792
+ name: `profiler:${id}:${phase}`,
45793
+ durationMs: actualDuration,
45794
+ ts: commitTime,
45795
+ detail: { baseDuration }
45796
+ });
45797
+ log11.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
45798
+ };
45799
+ function getPerfSnapshot() {
45800
+ if (ring.length < RING_SIZE) return ring.slice();
45801
+ return [...ring.slice(writeIdx), ...ring.slice(0, writeIdx)];
45802
+ }
45803
+ function getSnapshot2() {
45804
+ if (cachedRevision !== revision) {
45805
+ cachedSnapshot = getPerfSnapshot();
45806
+ cachedRevision = revision;
45807
+ }
45808
+ return cachedSnapshot;
45809
+ }
45810
+ function subscribe(fn) {
45811
+ subscribers.add(fn);
45812
+ return () => {
45813
+ subscribers.delete(fn);
45814
+ };
45815
+ }
45816
+ function usePerfBuffer() {
45817
+ return React135.useSyncExternalStore(subscribe, getSnapshot2, getSnapshot2);
45818
+ }
45819
+ function clearPerf() {
45820
+ ring.length = 0;
45821
+ writeIdx = 0;
45822
+ scheduleNotify();
45823
+ }
45824
+
45825
+ // runtime/prepareSchemaForPreview.ts
45723
45826
  function generateEntityRow(entity, idx) {
45724
45827
  const row = { id: String(idx) };
45725
45828
  for (const f3 of entity.fields) {
@@ -45745,6 +45848,7 @@ function generateFieldValue(entityName, field, idx) {
45745
45848
  }
45746
45849
  }
45747
45850
  function buildMockData(schema) {
45851
+ const t = perfStart("build-mock-data");
45748
45852
  const result = {};
45749
45853
  for (const orbital of schema.orbitals) {
45750
45854
  const entity = orbital.entity;
@@ -45762,6 +45866,7 @@ function buildMockData(schema) {
45762
45866
  );
45763
45867
  result[entityName] = rows;
45764
45868
  }
45869
+ perfEnd("build-mock-data", t, { orbitalCount: schema.orbitals.length, entityCount: Object.keys(result).length });
45765
45870
  return result;
45766
45871
  }
45767
45872
  function isInlineTrait2(traitRef) {
@@ -46281,17 +46386,25 @@ function BrowserPlayground({
46281
46386
  exports.BrowserPlayground = BrowserPlayground;
46282
46387
  exports.EntitySchemaProvider = EntitySchemaProvider;
46283
46388
  exports.OrbPreview = OrbPreview;
46389
+ exports.PERF_NAMESPACE = PERF_NAMESPACE;
46284
46390
  exports.ServerBridgeProvider = ServerBridgeProvider;
46285
46391
  exports.TraitContext = TraitContext;
46286
46392
  exports.TraitProvider = TraitProvider;
46287
46393
  exports.adjustSchemaForMockData = adjustSchemaForMockData;
46288
46394
  exports.buildMockData = buildMockData;
46395
+ exports.clearPerf = clearPerf;
46289
46396
  exports.clearSchemaCache = clearSchemaCache;
46290
46397
  exports.createClientEffectHandlers = createClientEffectHandlers;
46398
+ exports.getPerfSnapshot = getPerfSnapshot;
46399
+ exports.perfEnd = perfEnd;
46400
+ exports.perfStart = perfStart;
46401
+ exports.perfTime = perfTime;
46291
46402
  exports.prepareSchemaForPreview = prepareSchemaForPreview;
46403
+ exports.profilerOnRender = profilerOnRender;
46292
46404
  exports.useEntityDefinition = useEntityDefinition;
46293
46405
  exports.useEntitySchema = useEntitySchema;
46294
46406
  exports.useEntitySchemaOptional = useEntitySchemaOptional;
46407
+ exports.usePerfBuffer = usePerfBuffer;
46295
46408
  exports.useResolvedSchema = useResolvedSchema;
46296
46409
  exports.useServerBridge = useServerBridge;
46297
46410
  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,109 @@ 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
+ var notifyScheduled = false;
45684
+ var revision = 0;
45685
+ var cachedSnapshot = [];
45686
+ var cachedRevision = -1;
45687
+ function scheduleNotify() {
45688
+ if (notifyScheduled) return;
45689
+ notifyScheduled = true;
45690
+ queueMicrotask(() => {
45691
+ notifyScheduled = false;
45692
+ revision++;
45693
+ for (const fn of subscribers) fn();
45694
+ });
45695
+ }
45696
+ function push(entry) {
45697
+ if (ring.length < RING_SIZE) {
45698
+ ring.push(entry);
45699
+ } else {
45700
+ ring[writeIdx] = entry;
45701
+ }
45702
+ writeIdx = (writeIdx + 1) % RING_SIZE;
45703
+ scheduleNotify();
45704
+ }
45705
+ function isEnabled() {
45706
+ return isLogLevelEnabled("DEBUG", PERF_NAMESPACE);
45707
+ }
45708
+ function now() {
45709
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
45710
+ }
45711
+ function perfStart(name) {
45712
+ if (!isEnabled()) return -1;
45713
+ if (typeof performance !== "undefined" && typeof performance.mark === "function") {
45714
+ try {
45715
+ performance.mark(`${name}-start`);
45716
+ } catch {
45717
+ }
45718
+ }
45719
+ return now();
45720
+ }
45721
+ function perfEnd(name, startToken, detail) {
45722
+ if (startToken < 0 || !isEnabled()) return;
45723
+ const endTs = now();
45724
+ const durationMs = endTs - startToken;
45725
+ if (typeof performance !== "undefined" && typeof performance.measure === "function") {
45726
+ try {
45727
+ performance.mark(`${name}-end`);
45728
+ performance.measure(name, `${name}-start`, `${name}-end`);
45729
+ } catch {
45730
+ }
45731
+ }
45732
+ push({ name, durationMs, ts: endTs, detail });
45733
+ log11.debug(name, () => ({ durationMs, ...detail ?? {} }));
45734
+ }
45735
+ function perfTime(name, fn, detail) {
45736
+ const t = perfStart(name);
45737
+ try {
45738
+ return fn();
45739
+ } finally {
45740
+ perfEnd(name, t, detail);
45741
+ }
45742
+ }
45743
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
45744
+ if (!isEnabled()) return;
45745
+ push({
45746
+ name: `profiler:${id}:${phase}`,
45747
+ durationMs: actualDuration,
45748
+ ts: commitTime,
45749
+ detail: { baseDuration }
45750
+ });
45751
+ log11.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
45752
+ };
45753
+ function getPerfSnapshot() {
45754
+ if (ring.length < RING_SIZE) return ring.slice();
45755
+ return [...ring.slice(writeIdx), ...ring.slice(0, writeIdx)];
45756
+ }
45757
+ function getSnapshot2() {
45758
+ if (cachedRevision !== revision) {
45759
+ cachedSnapshot = getPerfSnapshot();
45760
+ cachedRevision = revision;
45761
+ }
45762
+ return cachedSnapshot;
45763
+ }
45764
+ function subscribe(fn) {
45765
+ subscribers.add(fn);
45766
+ return () => {
45767
+ subscribers.delete(fn);
45768
+ };
45769
+ }
45770
+ function usePerfBuffer() {
45771
+ return useSyncExternalStore(subscribe, getSnapshot2, getSnapshot2);
45772
+ }
45773
+ function clearPerf() {
45774
+ ring.length = 0;
45775
+ writeIdx = 0;
45776
+ scheduleNotify();
45777
+ }
45778
+
45779
+ // runtime/prepareSchemaForPreview.ts
45677
45780
  function generateEntityRow(entity, idx) {
45678
45781
  const row = { id: String(idx) };
45679
45782
  for (const f3 of entity.fields) {
@@ -45699,6 +45802,7 @@ function generateFieldValue(entityName, field, idx) {
45699
45802
  }
45700
45803
  }
45701
45804
  function buildMockData(schema) {
45805
+ const t = perfStart("build-mock-data");
45702
45806
  const result = {};
45703
45807
  for (const orbital of schema.orbitals) {
45704
45808
  const entity = orbital.entity;
@@ -45716,6 +45820,7 @@ function buildMockData(schema) {
45716
45820
  );
45717
45821
  result[entityName] = rows;
45718
45822
  }
45823
+ perfEnd("build-mock-data", t, { orbitalCount: schema.orbitals.length, entityCount: Object.keys(result).length });
45719
45824
  return result;
45720
45825
  }
45721
45826
  function isInlineTrait2(traitRef) {
@@ -46232,4 +46337,4 @@ function BrowserPlayground({
46232
46337
  );
46233
46338
  }
46234
46339
 
46235
- export { BrowserPlayground, EntitySchemaProvider, OrbPreview, ServerBridgeProvider, TraitContext, TraitProvider, adjustSchemaForMockData, buildMockData, clearSchemaCache, createClientEffectHandlers, prepareSchemaForPreview, useEntityDefinition, useEntitySchema, useEntitySchemaOptional, useResolvedSchema, useServerBridge, useTrait, useTraitContext, useTraitStateMachine, wrapCallbackForEvent };
46340
+ 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.1",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [