@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.
- package/dist/lib/index.cjs +293 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +286 -1
- package/package.json +1 -1
package/dist/lib/index.cjs
CHANGED
|
@@ -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;
|
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.js
CHANGED
|
@@ -1521,4 +1521,289 @@ function parseContentSegments(content) {
|
|
|
1521
1521
|
return segments;
|
|
1522
1522
|
}
|
|
1523
1523
|
|
|
1524
|
-
|
|
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 };
|