@almadar/ui 5.93.0 → 5.94.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.
@@ -1523,12 +1523,300 @@ function parseContentSegments(content) {
1523
1523
  return segments;
1524
1524
  }
1525
1525
 
1526
+ // lib/jazari/layout.ts
1527
+ var GEAR_RADIUS = 35;
1528
+ var GEAR_SPACING = 130;
1529
+ var PADDING_X = 80;
1530
+ var PADDING_Y = 120;
1531
+ var ARC_HEIGHT = 70;
1532
+ var SELF_LOOP_RADIUS = 30;
1533
+ var PARALLEL_OFFSET = 24;
1534
+ function orderStates(states, transitions) {
1535
+ const initial = states.find((s) => s.isInitial);
1536
+ if (!initial) {
1537
+ return states.map((s) => s.name);
1538
+ }
1539
+ const adj = /* @__PURE__ */ new Map();
1540
+ for (const t of transitions) {
1541
+ const existing = adj.get(t.from) ?? [];
1542
+ existing.push(t.to);
1543
+ adj.set(t.from, existing);
1544
+ }
1545
+ const visited = /* @__PURE__ */ new Set();
1546
+ const order = [];
1547
+ const queue = [initial.name];
1548
+ visited.add(initial.name);
1549
+ while (queue.length > 0) {
1550
+ const current = queue.shift();
1551
+ order.push(current);
1552
+ const neighbors = adj.get(current) ?? [];
1553
+ for (const next of neighbors) {
1554
+ if (!visited.has(next)) {
1555
+ visited.add(next);
1556
+ queue.push(next);
1557
+ }
1558
+ }
1559
+ }
1560
+ for (const s of states) {
1561
+ if (!visited.has(s.name)) {
1562
+ order.push(s.name);
1563
+ }
1564
+ }
1565
+ return order;
1566
+ }
1567
+ function quadBezierPoint(x0, y0, cx, cy, x1, y1, t) {
1568
+ const mt = 1 - t;
1569
+ return {
1570
+ x: mt * mt * x0 + 2 * mt * t * cx + t * t * x1,
1571
+ y: mt * mt * y0 + 2 * mt * t * cy + t * t * y1
1572
+ };
1573
+ }
1574
+ function computeJazariLayout(input) {
1575
+ const { states, transitions, entityFields = [], direction = "ltr" } = input;
1576
+ if (states.length === 0) {
1577
+ return {
1578
+ width: 200,
1579
+ height: 200,
1580
+ gears: [],
1581
+ arms: [],
1582
+ axisY: 100,
1583
+ axisStartX: 0,
1584
+ axisEndX: 200,
1585
+ entityFields,
1586
+ direction
1587
+ };
1588
+ }
1589
+ const stateOrder = orderStates(states, transitions);
1590
+ const stateMap = new Map(states.map((s) => [s.name, s]));
1591
+ const stateIndex = new Map(stateOrder.map((name, i) => [name, i]));
1592
+ const totalWidth = PADDING_X * 2 + (stateOrder.length - 1) * GEAR_SPACING;
1593
+ const axisY = PADDING_Y + ARC_HEIGHT + SELF_LOOP_RADIUS + 10;
1594
+ const height = axisY + PADDING_Y + ARC_HEIGHT + SELF_LOOP_RADIUS + 10;
1595
+ const gears = stateOrder.map((name, i) => {
1596
+ const state = stateMap.get(name);
1597
+ const xPos = direction === "rtl" ? totalWidth - PADDING_X - i * GEAR_SPACING : PADDING_X + i * GEAR_SPACING;
1598
+ return {
1599
+ name,
1600
+ cx: xPos,
1601
+ cy: axisY,
1602
+ radius: GEAR_RADIUS,
1603
+ isInitial: state?.isInitial === true,
1604
+ isTerminal: state?.isTerminal === true || state?.isFinal === true
1605
+ };
1606
+ });
1607
+ const pairCounts = /* @__PURE__ */ new Map();
1608
+ const pairIndices = /* @__PURE__ */ new Map();
1609
+ for (const t of transitions) {
1610
+ const pairKey = `${t.from}|${t.to}`;
1611
+ pairCounts.set(pairKey, (pairCounts.get(pairKey) ?? 0) + 1);
1612
+ }
1613
+ const arms = transitions.map((t) => {
1614
+ const pairKey = `${t.from}|${t.to}`;
1615
+ const currentIdx = pairIndices.get(pairKey) ?? 0;
1616
+ pairIndices.set(pairKey, currentIdx + 1);
1617
+ const pairCount = pairCounts.get(pairKey) ?? 1;
1618
+ const parallelShift = (currentIdx - (pairCount - 1) / 2) * PARALLEL_OFFSET;
1619
+ const fromIdx = stateIndex.get(t.from) ?? 0;
1620
+ const toIdx = stateIndex.get(t.to) ?? 0;
1621
+ const fromGear = gears[fromIdx];
1622
+ const toGear = gears[toIdx];
1623
+ if (!fromGear || !toGear) {
1624
+ return {
1625
+ from: t.from,
1626
+ to: t.to,
1627
+ event: t.event,
1628
+ path: "",
1629
+ labelX: 0,
1630
+ labelY: 0,
1631
+ guard: null,
1632
+ effect: null,
1633
+ isSelfLoop: false
1634
+ };
1635
+ }
1636
+ const isSelfLoop = t.from === t.to;
1637
+ let path;
1638
+ let labelX;
1639
+ let labelY;
1640
+ let ctrlX;
1641
+ let ctrlY;
1642
+ if (isSelfLoop) {
1643
+ const loopY = fromGear.cy - GEAR_RADIUS - SELF_LOOP_RADIUS - 5;
1644
+ path = [
1645
+ `M ${fromGear.cx - 12} ${fromGear.cy - GEAR_RADIUS}`,
1646
+ `C ${fromGear.cx - 25} ${loopY - 15}, ${fromGear.cx + 25} ${loopY - 15}, ${fromGear.cx + 12} ${fromGear.cy - GEAR_RADIUS}`
1647
+ ].join(" ");
1648
+ labelX = fromGear.cx;
1649
+ labelY = loopY - 10;
1650
+ ctrlX = fromGear.cx;
1651
+ ctrlY = loopY;
1652
+ } else {
1653
+ const isForward = direction === "rtl" ? fromIdx > toIdx : fromIdx < toIdx;
1654
+ const arcSign = isForward ? -1 : 1;
1655
+ const midX = (fromGear.cx + toGear.cx) / 2;
1656
+ ctrlY = axisY + arcSign * (ARC_HEIGHT + Math.abs(parallelShift));
1657
+ ctrlX = midX;
1658
+ const perimeterR = GEAR_RADIUS + 7;
1659
+ const dx = toGear.cx - fromGear.cx;
1660
+ const dy = toGear.cy - fromGear.cy;
1661
+ const dist = Math.sqrt(dx * dx + dy * dy);
1662
+ const startX = dist > 0 ? fromGear.cx + dx / dist * perimeterR : fromGear.cx;
1663
+ const startY = dist > 0 ? fromGear.cy + dy / dist * perimeterR : fromGear.cy;
1664
+ const endX = dist > 0 ? toGear.cx - dx / dist * perimeterR : toGear.cx;
1665
+ const endY = dist > 0 ? toGear.cy - dy / dist * perimeterR : toGear.cy;
1666
+ path = `M ${startX} ${startY} Q ${ctrlX} ${ctrlY} ${endX} ${endY}`;
1667
+ const mid = quadBezierPoint(startX, startY, ctrlX, ctrlY, endX, endY, 0.5);
1668
+ labelX = mid.x;
1669
+ labelY = mid.y;
1670
+ }
1671
+ let guard = null;
1672
+ if (t.guard != null) {
1673
+ const isAI = Array.isArray(t.guard) && typeof t.guard[0] === "string" && t.guard[0] === "call-service";
1674
+ if (isSelfLoop) {
1675
+ guard = { x: fromGear.cx - 18, y: fromGear.cy - GEAR_RADIUS - SELF_LOOP_RADIUS, isAI };
1676
+ } else {
1677
+ const gp = quadBezierPoint(fromGear.cx, fromGear.cy, ctrlX, ctrlY, toGear.cx, toGear.cy, 0.3);
1678
+ guard = { x: gp.x, y: gp.y, isAI };
1679
+ }
1680
+ }
1681
+ let effect = null;
1682
+ if (t.effects && t.effects.length > 0) {
1683
+ const names = t.effects.map((e) => {
1684
+ if (Array.isArray(e)) return JSON.stringify(e);
1685
+ return String(e);
1686
+ });
1687
+ if (isSelfLoop) {
1688
+ effect = { x: fromGear.cx + 18, y: fromGear.cy - GEAR_RADIUS - SELF_LOOP_RADIUS, count: t.effects.length, names };
1689
+ } else {
1690
+ const ep = quadBezierPoint(fromGear.cx, fromGear.cy, ctrlX, ctrlY, toGear.cx, toGear.cy, 0.7);
1691
+ effect = { x: ep.x, y: ep.y, count: t.effects.length, names };
1692
+ }
1693
+ }
1694
+ return {
1695
+ from: t.from,
1696
+ to: t.to,
1697
+ event: t.event,
1698
+ path,
1699
+ labelX,
1700
+ labelY,
1701
+ guard,
1702
+ effect,
1703
+ isSelfLoop
1704
+ };
1705
+ });
1706
+ return {
1707
+ width: totalWidth,
1708
+ height,
1709
+ gears,
1710
+ arms,
1711
+ axisY,
1712
+ axisStartX: direction === "rtl" ? gears[gears.length - 1]?.cx ?? PADDING_X : gears[0]?.cx ?? PADDING_X,
1713
+ axisEndX: direction === "rtl" ? gears[0]?.cx ?? totalWidth - PADDING_X : gears[gears.length - 1]?.cx ?? totalWidth - PADDING_X,
1714
+ entityFields,
1715
+ direction
1716
+ };
1717
+ }
1718
+
1719
+ // lib/jazari/svg-paths.ts
1720
+ function gearTeethPath(cx, cy, innerRadius, outerRadius, numTeeth) {
1721
+ const parts = [];
1722
+ const angleStep = Math.PI * 2 / numTeeth;
1723
+ const halfTooth = angleStep * 0.25;
1724
+ for (let i = 0; i < numTeeth; i++) {
1725
+ const baseAngle = i * angleStep;
1726
+ const x0 = cx + innerRadius * Math.cos(baseAngle - halfTooth);
1727
+ const y0 = cy + innerRadius * Math.sin(baseAngle - halfTooth);
1728
+ const x1 = cx + outerRadius * Math.cos(baseAngle - halfTooth * 0.4);
1729
+ const y1 = cy + outerRadius * Math.sin(baseAngle - halfTooth * 0.4);
1730
+ const x2 = cx + outerRadius * Math.cos(baseAngle + halfTooth * 0.4);
1731
+ const y2 = cy + outerRadius * Math.sin(baseAngle + halfTooth * 0.4);
1732
+ const x3 = cx + innerRadius * Math.cos(baseAngle + halfTooth);
1733
+ const y3 = cy + innerRadius * Math.sin(baseAngle + halfTooth);
1734
+ if (i === 0) {
1735
+ parts.push(`M ${x0.toFixed(1)} ${y0.toFixed(1)}`);
1736
+ } else {
1737
+ parts.push(`L ${x0.toFixed(1)} ${y0.toFixed(1)}`);
1738
+ }
1739
+ parts.push(`L ${x1.toFixed(1)} ${y1.toFixed(1)}`);
1740
+ parts.push(`L ${x2.toFixed(1)} ${y2.toFixed(1)}`);
1741
+ parts.push(`L ${x3.toFixed(1)} ${y3.toFixed(1)}`);
1742
+ }
1743
+ parts.push("Z");
1744
+ return parts.join(" ");
1745
+ }
1746
+ function lockIconPath(cx, cy, size) {
1747
+ const bodyW = size * 0.7;
1748
+ const bodyH = size * 0.5;
1749
+ const bodyX = cx - bodyW / 2;
1750
+ const bodyY = cy - bodyH / 4;
1751
+ const body = `M ${bodyX.toFixed(1)} ${bodyY.toFixed(1)} h ${bodyW.toFixed(1)} v ${bodyH.toFixed(1)} h ${(-bodyW).toFixed(1)} Z`;
1752
+ const shR = size * 0.28;
1753
+ const shY = bodyY;
1754
+ const shackle = `M ${(cx - shR).toFixed(1)} ${shY.toFixed(1)} A ${shR.toFixed(1)} ${(shR * 1.2).toFixed(1)} 0 1 1 ${(cx + shR).toFixed(1)} ${shY.toFixed(1)}`;
1755
+ const kR = size * 0.08;
1756
+ const kY = bodyY + bodyH * 0.35;
1757
+ const keyhole = `M ${cx.toFixed(1)} ${(kY - kR).toFixed(1)} a ${kR.toFixed(1)} ${kR.toFixed(1)} 0 1 1 0 ${(kR * 2).toFixed(1)} a ${kR.toFixed(1)} ${kR.toFixed(1)} 0 1 1 0 ${(-kR * 2).toFixed(1)} Z`;
1758
+ return `${body} ${shackle} ${keyhole}`;
1759
+ }
1760
+ function brainIconPath(cx, cy, size) {
1761
+ const s = size / 2;
1762
+ return [
1763
+ `M ${cx.toFixed(1)} ${(cy - s).toFixed(1)}`,
1764
+ `C ${(cx - s * 1.2).toFixed(1)} ${(cy - s).toFixed(1)}, ${(cx - s * 1.3).toFixed(1)} ${(cy + s * 0.3).toFixed(1)}, ${cx.toFixed(1)} ${(cy + s).toFixed(1)}`,
1765
+ `C ${(cx + s * 1.3).toFixed(1)} ${(cy + s * 0.3).toFixed(1)}, ${(cx + s * 1.2).toFixed(1)} ${(cy - s).toFixed(1)}, ${cx.toFixed(1)} ${(cy - s).toFixed(1)}`,
1766
+ "Z",
1767
+ // Dividing line
1768
+ `M ${cx.toFixed(1)} ${(cy - s * 0.8).toFixed(1)}`,
1769
+ `C ${(cx - s * 0.2).toFixed(1)} ${(cy - s * 0.2).toFixed(1)}, ${(cx + s * 0.2).toFixed(1)} ${(cy + s * 0.2).toFixed(1)}, ${cx.toFixed(1)} ${(cy + s * 0.8).toFixed(1)}`
1770
+ ].join(" ");
1771
+ }
1772
+ function pipeIconPath(cx, cy, size) {
1773
+ const w = size * 0.6;
1774
+ const h = size * 0.3;
1775
+ const flangeW = size * 0.8;
1776
+ const flangeH = size * 0.1;
1777
+ const tube = `M ${(cx - w / 2).toFixed(1)} ${(cy - h / 2).toFixed(1)} h ${w.toFixed(1)} v ${h.toFixed(1)} h ${(-w).toFixed(1)} Z`;
1778
+ const lf = `M ${(cx - flangeW / 2).toFixed(1)} ${(cy - h / 2 - flangeH).toFixed(1)} h ${flangeH.toFixed(1)} v ${(h + flangeH * 2).toFixed(1)} h ${(-flangeH).toFixed(1)} Z`;
1779
+ const rf = `M ${(cx + flangeW / 2 - flangeH).toFixed(1)} ${(cy - h / 2 - flangeH).toFixed(1)} h ${flangeH.toFixed(1)} v ${(h + flangeH * 2).toFixed(1)} h ${(-flangeH).toFixed(1)} Z`;
1780
+ return `${tube} ${lf} ${rf}`;
1781
+ }
1782
+ function eightPointedStarPath(cx, cy, outerR, innerR) {
1783
+ const points = [];
1784
+ const numPoints = 8;
1785
+ const angleStep = Math.PI / numPoints;
1786
+ for (let i = 0; i < numPoints * 2; i++) {
1787
+ const angle = i * angleStep - Math.PI / 2;
1788
+ const r = i % 2 === 0 ? outerR : innerR;
1789
+ const x = cx + r * Math.cos(angle);
1790
+ const y = cy + r * Math.sin(angle);
1791
+ points.push(`${i === 0 ? "M" : "L"} ${x.toFixed(1)} ${y.toFixed(1)}`);
1792
+ }
1793
+ points.push("Z");
1794
+ return points.join(" ");
1795
+ }
1796
+ function arrowheadPath(size) {
1797
+ return `M 0 0 L ${size} ${size / 2} L 0 ${size} Z`;
1798
+ }
1799
+
1800
+ // lib/jazari/types.ts
1801
+ var JAZARI_COLORS = {
1802
+ brass: "#B87333",
1803
+ gold: "#C8A951",
1804
+ sky: "#0EA5E9",
1805
+ crimson: "#DC2626",
1806
+ lapis: "#1E40AF",
1807
+ ivory: "#FFFBEB",
1808
+ darkBg: "#1a1a2e"
1809
+ };
1810
+
1526
1811
  exports.ApiError = ApiError;
1527
1812
  exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
1813
+ exports.JAZARI_COLORS = JAZARI_COLORS;
1528
1814
  exports.apiClient = apiClient;
1815
+ exports.arrowheadPath = arrowheadPath;
1529
1816
  exports.bindCanvasCapture = bindCanvasCapture;
1530
1817
  exports.bindEventBus = bindEventBus;
1531
1818
  exports.bindTraitStateGetter = bindTraitStateGetter;
1819
+ exports.brainIconPath = brainIconPath;
1532
1820
  exports.clearDebugEvents = clearDebugEvents;
1533
1821
  exports.clearEntityProvider = clearEntityProvider;
1534
1822
  exports.clearGuardHistory = clearGuardHistory;
@@ -1536,6 +1824,7 @@ exports.clearTicks = clearTicks;
1536
1824
  exports.clearTraits = clearTraits;
1537
1825
  exports.clearVerification = clearVerification;
1538
1826
  exports.cn = cn;
1827
+ exports.computeJazariLayout = computeJazariLayout;
1539
1828
  exports.debug = debug;
1540
1829
  exports.debugCollision = debugCollision;
1541
1830
  exports.debugError = debugError;
@@ -1548,10 +1837,12 @@ exports.debugTable = debugTable;
1548
1837
  exports.debugTime = debugTime;
1549
1838
  exports.debugTimeEnd = debugTimeEnd;
1550
1839
  exports.debugWarn = debugWarn;
1840
+ exports.eightPointedStarPath = eightPointedStarPath;
1551
1841
  exports.extractOutputsFromTransitions = extractOutputsFromTransitions;
1552
1842
  exports.extractStateMachine = extractStateMachine;
1553
1843
  exports.formatGuard = formatGuard;
1554
1844
  exports.formatNestedFieldLabel = formatNestedFieldLabel;
1845
+ exports.gearTeethPath = gearTeethPath;
1555
1846
  exports.getAllChecks = getAllChecks;
1556
1847
  exports.getAllTicks = getAllTicks;
1557
1848
  exports.getAllTraits = getAllTraits;
@@ -1577,6 +1868,7 @@ exports.getTransitions = getTransitions;
1577
1868
  exports.getTransitionsForTrait = getTransitionsForTrait;
1578
1869
  exports.initDebugShortcut = initDebugShortcut;
1579
1870
  exports.isDebugEnabled = isDebugEnabled;
1871
+ exports.lockIconPath = lockIconPath;
1580
1872
  exports.logDebugEvent = logDebugEvent;
1581
1873
  exports.logEffectExecuted = logEffectExecuted;
1582
1874
  exports.logError = logError;
@@ -1587,6 +1879,7 @@ exports.logWarning = logWarning;
1587
1879
  exports.onDebugToggle = onDebugToggle;
1588
1880
  exports.parseContentSegments = parseContentSegments;
1589
1881
  exports.parseMarkdownWithCodeBlocks = parseMarkdownWithCodeBlocks;
1882
+ exports.pipeIconPath = pipeIconPath;
1590
1883
  exports.recordGuardEvaluation = recordGuardEvaluation;
1591
1884
  exports.recordServerResponse = recordServerResponse;
1592
1885
  exports.recordTransition = recordTransition;
@@ -16,3 +16,4 @@ export * from './verificationRegistry';
16
16
  export * from './getNestedValue';
17
17
  export * from './visualizer/index';
18
18
  export * from './parseContentSegments';
19
+ export * from './jazari/index';
package/dist/lib/index.js CHANGED
@@ -1521,4 +1521,289 @@ function parseContentSegments(content) {
1521
1521
  return segments;
1522
1522
  }
1523
1523
 
1524
- export { ApiError, DEFAULT_CONFIG, apiClient, bindCanvasCapture, bindEventBus, bindTraitStateGetter, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, extractOutputsFromTransitions, extractStateMachine, formatGuard, formatNestedFieldLabel, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTraitSnapshots, getTransitions, getTransitionsForTrait, initDebugShortcut, isDebugEnabled, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, registerTraitSnapshot, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
1524
+ // lib/jazari/layout.ts
1525
+ var GEAR_RADIUS = 35;
1526
+ var GEAR_SPACING = 130;
1527
+ var PADDING_X = 80;
1528
+ var PADDING_Y = 120;
1529
+ var ARC_HEIGHT = 70;
1530
+ var SELF_LOOP_RADIUS = 30;
1531
+ var PARALLEL_OFFSET = 24;
1532
+ function orderStates(states, transitions) {
1533
+ const initial = states.find((s) => s.isInitial);
1534
+ if (!initial) {
1535
+ return states.map((s) => s.name);
1536
+ }
1537
+ const adj = /* @__PURE__ */ new Map();
1538
+ for (const t of transitions) {
1539
+ const existing = adj.get(t.from) ?? [];
1540
+ existing.push(t.to);
1541
+ adj.set(t.from, existing);
1542
+ }
1543
+ const visited = /* @__PURE__ */ new Set();
1544
+ const order = [];
1545
+ const queue = [initial.name];
1546
+ visited.add(initial.name);
1547
+ while (queue.length > 0) {
1548
+ const current = queue.shift();
1549
+ order.push(current);
1550
+ const neighbors = adj.get(current) ?? [];
1551
+ for (const next of neighbors) {
1552
+ if (!visited.has(next)) {
1553
+ visited.add(next);
1554
+ queue.push(next);
1555
+ }
1556
+ }
1557
+ }
1558
+ for (const s of states) {
1559
+ if (!visited.has(s.name)) {
1560
+ order.push(s.name);
1561
+ }
1562
+ }
1563
+ return order;
1564
+ }
1565
+ function quadBezierPoint(x0, y0, cx, cy, x1, y1, t) {
1566
+ const mt = 1 - t;
1567
+ return {
1568
+ x: mt * mt * x0 + 2 * mt * t * cx + t * t * x1,
1569
+ y: mt * mt * y0 + 2 * mt * t * cy + t * t * y1
1570
+ };
1571
+ }
1572
+ function computeJazariLayout(input) {
1573
+ const { states, transitions, entityFields = [], direction = "ltr" } = input;
1574
+ if (states.length === 0) {
1575
+ return {
1576
+ width: 200,
1577
+ height: 200,
1578
+ gears: [],
1579
+ arms: [],
1580
+ axisY: 100,
1581
+ axisStartX: 0,
1582
+ axisEndX: 200,
1583
+ entityFields,
1584
+ direction
1585
+ };
1586
+ }
1587
+ const stateOrder = orderStates(states, transitions);
1588
+ const stateMap = new Map(states.map((s) => [s.name, s]));
1589
+ const stateIndex = new Map(stateOrder.map((name, i) => [name, i]));
1590
+ const totalWidth = PADDING_X * 2 + (stateOrder.length - 1) * GEAR_SPACING;
1591
+ const axisY = PADDING_Y + ARC_HEIGHT + SELF_LOOP_RADIUS + 10;
1592
+ const height = axisY + PADDING_Y + ARC_HEIGHT + SELF_LOOP_RADIUS + 10;
1593
+ const gears = stateOrder.map((name, i) => {
1594
+ const state = stateMap.get(name);
1595
+ const xPos = direction === "rtl" ? totalWidth - PADDING_X - i * GEAR_SPACING : PADDING_X + i * GEAR_SPACING;
1596
+ return {
1597
+ name,
1598
+ cx: xPos,
1599
+ cy: axisY,
1600
+ radius: GEAR_RADIUS,
1601
+ isInitial: state?.isInitial === true,
1602
+ isTerminal: state?.isTerminal === true || state?.isFinal === true
1603
+ };
1604
+ });
1605
+ const pairCounts = /* @__PURE__ */ new Map();
1606
+ const pairIndices = /* @__PURE__ */ new Map();
1607
+ for (const t of transitions) {
1608
+ const pairKey = `${t.from}|${t.to}`;
1609
+ pairCounts.set(pairKey, (pairCounts.get(pairKey) ?? 0) + 1);
1610
+ }
1611
+ const arms = transitions.map((t) => {
1612
+ const pairKey = `${t.from}|${t.to}`;
1613
+ const currentIdx = pairIndices.get(pairKey) ?? 0;
1614
+ pairIndices.set(pairKey, currentIdx + 1);
1615
+ const pairCount = pairCounts.get(pairKey) ?? 1;
1616
+ const parallelShift = (currentIdx - (pairCount - 1) / 2) * PARALLEL_OFFSET;
1617
+ const fromIdx = stateIndex.get(t.from) ?? 0;
1618
+ const toIdx = stateIndex.get(t.to) ?? 0;
1619
+ const fromGear = gears[fromIdx];
1620
+ const toGear = gears[toIdx];
1621
+ if (!fromGear || !toGear) {
1622
+ return {
1623
+ from: t.from,
1624
+ to: t.to,
1625
+ event: t.event,
1626
+ path: "",
1627
+ labelX: 0,
1628
+ labelY: 0,
1629
+ guard: null,
1630
+ effect: null,
1631
+ isSelfLoop: false
1632
+ };
1633
+ }
1634
+ const isSelfLoop = t.from === t.to;
1635
+ let path;
1636
+ let labelX;
1637
+ let labelY;
1638
+ let ctrlX;
1639
+ let ctrlY;
1640
+ if (isSelfLoop) {
1641
+ const loopY = fromGear.cy - GEAR_RADIUS - SELF_LOOP_RADIUS - 5;
1642
+ path = [
1643
+ `M ${fromGear.cx - 12} ${fromGear.cy - GEAR_RADIUS}`,
1644
+ `C ${fromGear.cx - 25} ${loopY - 15}, ${fromGear.cx + 25} ${loopY - 15}, ${fromGear.cx + 12} ${fromGear.cy - GEAR_RADIUS}`
1645
+ ].join(" ");
1646
+ labelX = fromGear.cx;
1647
+ labelY = loopY - 10;
1648
+ ctrlX = fromGear.cx;
1649
+ ctrlY = loopY;
1650
+ } else {
1651
+ const isForward = direction === "rtl" ? fromIdx > toIdx : fromIdx < toIdx;
1652
+ const arcSign = isForward ? -1 : 1;
1653
+ const midX = (fromGear.cx + toGear.cx) / 2;
1654
+ ctrlY = axisY + arcSign * (ARC_HEIGHT + Math.abs(parallelShift));
1655
+ ctrlX = midX;
1656
+ const perimeterR = GEAR_RADIUS + 7;
1657
+ const dx = toGear.cx - fromGear.cx;
1658
+ const dy = toGear.cy - fromGear.cy;
1659
+ const dist = Math.sqrt(dx * dx + dy * dy);
1660
+ const startX = dist > 0 ? fromGear.cx + dx / dist * perimeterR : fromGear.cx;
1661
+ const startY = dist > 0 ? fromGear.cy + dy / dist * perimeterR : fromGear.cy;
1662
+ const endX = dist > 0 ? toGear.cx - dx / dist * perimeterR : toGear.cx;
1663
+ const endY = dist > 0 ? toGear.cy - dy / dist * perimeterR : toGear.cy;
1664
+ path = `M ${startX} ${startY} Q ${ctrlX} ${ctrlY} ${endX} ${endY}`;
1665
+ const mid = quadBezierPoint(startX, startY, ctrlX, ctrlY, endX, endY, 0.5);
1666
+ labelX = mid.x;
1667
+ labelY = mid.y;
1668
+ }
1669
+ let guard = null;
1670
+ if (t.guard != null) {
1671
+ const isAI = Array.isArray(t.guard) && typeof t.guard[0] === "string" && t.guard[0] === "call-service";
1672
+ if (isSelfLoop) {
1673
+ guard = { x: fromGear.cx - 18, y: fromGear.cy - GEAR_RADIUS - SELF_LOOP_RADIUS, isAI };
1674
+ } else {
1675
+ const gp = quadBezierPoint(fromGear.cx, fromGear.cy, ctrlX, ctrlY, toGear.cx, toGear.cy, 0.3);
1676
+ guard = { x: gp.x, y: gp.y, isAI };
1677
+ }
1678
+ }
1679
+ let effect = null;
1680
+ if (t.effects && t.effects.length > 0) {
1681
+ const names = t.effects.map((e) => {
1682
+ if (Array.isArray(e)) return JSON.stringify(e);
1683
+ return String(e);
1684
+ });
1685
+ if (isSelfLoop) {
1686
+ effect = { x: fromGear.cx + 18, y: fromGear.cy - GEAR_RADIUS - SELF_LOOP_RADIUS, count: t.effects.length, names };
1687
+ } else {
1688
+ const ep = quadBezierPoint(fromGear.cx, fromGear.cy, ctrlX, ctrlY, toGear.cx, toGear.cy, 0.7);
1689
+ effect = { x: ep.x, y: ep.y, count: t.effects.length, names };
1690
+ }
1691
+ }
1692
+ return {
1693
+ from: t.from,
1694
+ to: t.to,
1695
+ event: t.event,
1696
+ path,
1697
+ labelX,
1698
+ labelY,
1699
+ guard,
1700
+ effect,
1701
+ isSelfLoop
1702
+ };
1703
+ });
1704
+ return {
1705
+ width: totalWidth,
1706
+ height,
1707
+ gears,
1708
+ arms,
1709
+ axisY,
1710
+ axisStartX: direction === "rtl" ? gears[gears.length - 1]?.cx ?? PADDING_X : gears[0]?.cx ?? PADDING_X,
1711
+ axisEndX: direction === "rtl" ? gears[0]?.cx ?? totalWidth - PADDING_X : gears[gears.length - 1]?.cx ?? totalWidth - PADDING_X,
1712
+ entityFields,
1713
+ direction
1714
+ };
1715
+ }
1716
+
1717
+ // lib/jazari/svg-paths.ts
1718
+ function gearTeethPath(cx, cy, innerRadius, outerRadius, numTeeth) {
1719
+ const parts = [];
1720
+ const angleStep = Math.PI * 2 / numTeeth;
1721
+ const halfTooth = angleStep * 0.25;
1722
+ for (let i = 0; i < numTeeth; i++) {
1723
+ const baseAngle = i * angleStep;
1724
+ const x0 = cx + innerRadius * Math.cos(baseAngle - halfTooth);
1725
+ const y0 = cy + innerRadius * Math.sin(baseAngle - halfTooth);
1726
+ const x1 = cx + outerRadius * Math.cos(baseAngle - halfTooth * 0.4);
1727
+ const y1 = cy + outerRadius * Math.sin(baseAngle - halfTooth * 0.4);
1728
+ const x2 = cx + outerRadius * Math.cos(baseAngle + halfTooth * 0.4);
1729
+ const y2 = cy + outerRadius * Math.sin(baseAngle + halfTooth * 0.4);
1730
+ const x3 = cx + innerRadius * Math.cos(baseAngle + halfTooth);
1731
+ const y3 = cy + innerRadius * Math.sin(baseAngle + halfTooth);
1732
+ if (i === 0) {
1733
+ parts.push(`M ${x0.toFixed(1)} ${y0.toFixed(1)}`);
1734
+ } else {
1735
+ parts.push(`L ${x0.toFixed(1)} ${y0.toFixed(1)}`);
1736
+ }
1737
+ parts.push(`L ${x1.toFixed(1)} ${y1.toFixed(1)}`);
1738
+ parts.push(`L ${x2.toFixed(1)} ${y2.toFixed(1)}`);
1739
+ parts.push(`L ${x3.toFixed(1)} ${y3.toFixed(1)}`);
1740
+ }
1741
+ parts.push("Z");
1742
+ return parts.join(" ");
1743
+ }
1744
+ function lockIconPath(cx, cy, size) {
1745
+ const bodyW = size * 0.7;
1746
+ const bodyH = size * 0.5;
1747
+ const bodyX = cx - bodyW / 2;
1748
+ const bodyY = cy - bodyH / 4;
1749
+ const body = `M ${bodyX.toFixed(1)} ${bodyY.toFixed(1)} h ${bodyW.toFixed(1)} v ${bodyH.toFixed(1)} h ${(-bodyW).toFixed(1)} Z`;
1750
+ const shR = size * 0.28;
1751
+ const shY = bodyY;
1752
+ const shackle = `M ${(cx - shR).toFixed(1)} ${shY.toFixed(1)} A ${shR.toFixed(1)} ${(shR * 1.2).toFixed(1)} 0 1 1 ${(cx + shR).toFixed(1)} ${shY.toFixed(1)}`;
1753
+ const kR = size * 0.08;
1754
+ const kY = bodyY + bodyH * 0.35;
1755
+ const keyhole = `M ${cx.toFixed(1)} ${(kY - kR).toFixed(1)} a ${kR.toFixed(1)} ${kR.toFixed(1)} 0 1 1 0 ${(kR * 2).toFixed(1)} a ${kR.toFixed(1)} ${kR.toFixed(1)} 0 1 1 0 ${(-kR * 2).toFixed(1)} Z`;
1756
+ return `${body} ${shackle} ${keyhole}`;
1757
+ }
1758
+ function brainIconPath(cx, cy, size) {
1759
+ const s = size / 2;
1760
+ return [
1761
+ `M ${cx.toFixed(1)} ${(cy - s).toFixed(1)}`,
1762
+ `C ${(cx - s * 1.2).toFixed(1)} ${(cy - s).toFixed(1)}, ${(cx - s * 1.3).toFixed(1)} ${(cy + s * 0.3).toFixed(1)}, ${cx.toFixed(1)} ${(cy + s).toFixed(1)}`,
1763
+ `C ${(cx + s * 1.3).toFixed(1)} ${(cy + s * 0.3).toFixed(1)}, ${(cx + s * 1.2).toFixed(1)} ${(cy - s).toFixed(1)}, ${cx.toFixed(1)} ${(cy - s).toFixed(1)}`,
1764
+ "Z",
1765
+ // Dividing line
1766
+ `M ${cx.toFixed(1)} ${(cy - s * 0.8).toFixed(1)}`,
1767
+ `C ${(cx - s * 0.2).toFixed(1)} ${(cy - s * 0.2).toFixed(1)}, ${(cx + s * 0.2).toFixed(1)} ${(cy + s * 0.2).toFixed(1)}, ${cx.toFixed(1)} ${(cy + s * 0.8).toFixed(1)}`
1768
+ ].join(" ");
1769
+ }
1770
+ function pipeIconPath(cx, cy, size) {
1771
+ const w = size * 0.6;
1772
+ const h = size * 0.3;
1773
+ const flangeW = size * 0.8;
1774
+ const flangeH = size * 0.1;
1775
+ const tube = `M ${(cx - w / 2).toFixed(1)} ${(cy - h / 2).toFixed(1)} h ${w.toFixed(1)} v ${h.toFixed(1)} h ${(-w).toFixed(1)} Z`;
1776
+ const lf = `M ${(cx - flangeW / 2).toFixed(1)} ${(cy - h / 2 - flangeH).toFixed(1)} h ${flangeH.toFixed(1)} v ${(h + flangeH * 2).toFixed(1)} h ${(-flangeH).toFixed(1)} Z`;
1777
+ const rf = `M ${(cx + flangeW / 2 - flangeH).toFixed(1)} ${(cy - h / 2 - flangeH).toFixed(1)} h ${flangeH.toFixed(1)} v ${(h + flangeH * 2).toFixed(1)} h ${(-flangeH).toFixed(1)} Z`;
1778
+ return `${tube} ${lf} ${rf}`;
1779
+ }
1780
+ function eightPointedStarPath(cx, cy, outerR, innerR) {
1781
+ const points = [];
1782
+ const numPoints = 8;
1783
+ const angleStep = Math.PI / numPoints;
1784
+ for (let i = 0; i < numPoints * 2; i++) {
1785
+ const angle = i * angleStep - Math.PI / 2;
1786
+ const r = i % 2 === 0 ? outerR : innerR;
1787
+ const x = cx + r * Math.cos(angle);
1788
+ const y = cy + r * Math.sin(angle);
1789
+ points.push(`${i === 0 ? "M" : "L"} ${x.toFixed(1)} ${y.toFixed(1)}`);
1790
+ }
1791
+ points.push("Z");
1792
+ return points.join(" ");
1793
+ }
1794
+ function arrowheadPath(size) {
1795
+ return `M 0 0 L ${size} ${size / 2} L 0 ${size} Z`;
1796
+ }
1797
+
1798
+ // lib/jazari/types.ts
1799
+ var JAZARI_COLORS = {
1800
+ brass: "#B87333",
1801
+ gold: "#C8A951",
1802
+ sky: "#0EA5E9",
1803
+ crimson: "#DC2626",
1804
+ lapis: "#1E40AF",
1805
+ ivory: "#FFFBEB",
1806
+ darkBg: "#1a1a2e"
1807
+ };
1808
+
1809
+ export { ApiError, DEFAULT_CONFIG, JAZARI_COLORS, apiClient, arrowheadPath, bindCanvasCapture, bindEventBus, bindTraitStateGetter, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, extractOutputsFromTransitions, extractStateMachine, formatGuard, formatNestedFieldLabel, gearTeethPath, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTraitSnapshots, getTransitions, getTransitionsForTrait, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, pipeIconPath, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, registerTraitSnapshot, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.93.0",
3
+ "version": "5.94.1",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [