@almadar/ui 2.20.0 → 2.20.6

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.
Files changed (41) hide show
  1. package/LICENSE +72 -21
  2. package/dist/avl/index.cjs +1437 -1328
  3. package/dist/avl/index.d.cts +51 -47
  4. package/dist/avl/index.js +1408 -1299
  5. package/dist/components/atoms/avl/Avl3DLabel.d.ts +23 -0
  6. package/dist/components/atoms/avl/Avl3DTooltip.d.ts +25 -0
  7. package/dist/components/atoms/avl/index.d.ts +2 -0
  8. package/dist/components/index.cjs +3 -1
  9. package/dist/components/index.js +3 -1
  10. package/dist/components/molecules/avl/Avl3DCrossWire.d.ts +22 -0
  11. package/dist/components/molecules/avl/Avl3DEntityCore.d.ts +26 -0
  12. package/dist/components/molecules/avl/Avl3DExprTree.d.ts +21 -0
  13. package/dist/components/molecules/avl/Avl3DOrbitalNode.d.ts +29 -0
  14. package/dist/components/molecules/avl/Avl3DStateNode.d.ts +34 -0
  15. package/dist/components/molecules/avl/Avl3DTransitionArc.d.ts +38 -0
  16. package/dist/components/molecules/avl/index.d.ts +6 -0
  17. package/dist/components/organisms/avl/Avl3DApplicationScene.d.ts +19 -0
  18. package/dist/components/organisms/avl/Avl3DEffects.d.ts +18 -0
  19. package/dist/components/organisms/avl/Avl3DOrbitalScene.d.ts +23 -0
  20. package/dist/components/organisms/avl/Avl3DTraitScene.d.ts +19 -0
  21. package/dist/components/organisms/avl/Avl3DTransitionScene.d.ts +17 -0
  22. package/dist/components/organisms/avl/Avl3DViewer.d.ts +40 -0
  23. package/dist/components/organisms/avl/AvlOrbitalScene.d.ts +4 -0
  24. package/dist/components/organisms/avl/avl-3d-context.d.ts +32 -0
  25. package/dist/components/organisms/avl/avl-3d-layout.d.ts +116 -0
  26. package/dist/components/organisms/avl/avl-zoom-state.d.ts +3 -0
  27. package/dist/components/organisms/game/three/index.cjs +2549 -120
  28. package/dist/components/organisms/game/three/index.d.ts +8 -0
  29. package/dist/components/organisms/game/three/index.js +2419 -5
  30. package/dist/illustrations/index.cjs +2880 -109
  31. package/dist/illustrations/index.js +2879 -108
  32. package/dist/providers/OrbitalProvider.d.ts +4 -2
  33. package/dist/providers/index.cjs +263 -284
  34. package/dist/providers/index.js +189 -210
  35. package/dist/runtime/OrbPreview.d.ts +9 -6
  36. package/dist/runtime/ServerBridge.d.ts +23 -0
  37. package/dist/runtime/enrichFromResponse.d.ts +21 -0
  38. package/dist/runtime/index.cjs +31754 -2587
  39. package/dist/runtime/index.d.ts +2 -0
  40. package/dist/runtime/index.js +31735 -2571
  41. package/package.json +5 -2
package/dist/avl/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import React6, { createContext, useCallback, useContext, useState, useMemo, useEffect, useReducer, useRef } from 'react';
2
+ import React8, { createContext, useCallback, useContext, useState, useMemo, useEffect, useReducer, useRef } from 'react';
3
+ import '@react-three/drei';
4
+ import '@react-three/fiber';
5
+ import 'three';
3
6
  import ELK from 'elkjs/lib/elk.bundled.js';
4
7
 
5
8
  // components/atoms/avl/types.ts
@@ -374,7 +377,7 @@ var AvlTransition = ({
374
377
  opacity = 1,
375
378
  className
376
379
  }) => {
377
- const ids = React6.useMemo(() => {
380
+ const ids = React8.useMemo(() => {
378
381
  avlTransitionId += 1;
379
382
  return { arrow: `avl-tr-${avlTransitionId}-arrow` };
380
383
  }, []);
@@ -1048,1024 +1051,183 @@ var AvlBindingRef = ({
1048
1051
  };
1049
1052
  AvlBindingRef.displayName = "AvlBindingRef";
1050
1053
 
1051
- // components/molecules/avl/avl-layout.ts
1052
- function ringPositions(cx, cy, r2, count, startAngle = -Math.PI / 2) {
1053
- if (count === 0) return [];
1054
- if (count === 1) {
1055
- return [{ x: cx, y: cy, angle: 0 }];
1054
+ // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
1055
+ function r(e) {
1056
+ var t, f, n = "";
1057
+ if ("string" == typeof e || "number" == typeof e) n += e;
1058
+ else if ("object" == typeof e) if (Array.isArray(e)) {
1059
+ var o = e.length;
1060
+ for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
1061
+ } else for (f in e) e[f] && (n && (n += " "), n += f);
1062
+ return n;
1063
+ }
1064
+ function clsx() {
1065
+ for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
1066
+ return n;
1067
+ }
1068
+
1069
+ // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
1070
+ var CLASS_PART_SEPARATOR = "-";
1071
+ var createClassGroupUtils = (config) => {
1072
+ const classMap = createClassMap(config);
1073
+ const {
1074
+ conflictingClassGroups,
1075
+ conflictingClassGroupModifiers
1076
+ } = config;
1077
+ const getClassGroupId = (className) => {
1078
+ const classParts = className.split(CLASS_PART_SEPARATOR);
1079
+ if (classParts[0] === "" && classParts.length !== 1) {
1080
+ classParts.shift();
1081
+ }
1082
+ return getGroupRecursive(classParts, classMap) || getGroupIdForArbitraryProperty(className);
1083
+ };
1084
+ const getConflictingClassGroupIds = (classGroupId, hasPostfixModifier) => {
1085
+ const conflicts = conflictingClassGroups[classGroupId] || [];
1086
+ if (hasPostfixModifier && conflictingClassGroupModifiers[classGroupId]) {
1087
+ return [...conflicts, ...conflictingClassGroupModifiers[classGroupId]];
1088
+ }
1089
+ return conflicts;
1090
+ };
1091
+ return {
1092
+ getClassGroupId,
1093
+ getConflictingClassGroupIds
1094
+ };
1095
+ };
1096
+ var getGroupRecursive = (classParts, classPartObject) => {
1097
+ if (classParts.length === 0) {
1098
+ return classPartObject.classGroupId;
1056
1099
  }
1057
- if (count === 2) {
1058
- return [
1059
- { x: cx - r2 * 0.7, y: cy, angle: Math.PI },
1060
- { x: cx + r2 * 0.7, y: cy, angle: 0 }
1061
- ];
1100
+ const currentClassPart = classParts[0];
1101
+ const nextClassPartObject = classPartObject.nextPart.get(currentClassPart);
1102
+ const classGroupFromNextClassPart = nextClassPartObject ? getGroupRecursive(classParts.slice(1), nextClassPartObject) : void 0;
1103
+ if (classGroupFromNextClassPart) {
1104
+ return classGroupFromNextClassPart;
1062
1105
  }
1063
- return Array.from({ length: count }, (_, i) => {
1064
- const angle = startAngle + Math.PI * 2 * i / count;
1065
- return {
1066
- x: cx + r2 * Math.cos(angle),
1067
- y: cy + r2 * Math.sin(angle),
1068
- angle
1069
- };
1106
+ if (classPartObject.validators.length === 0) {
1107
+ return void 0;
1108
+ }
1109
+ const classRest = classParts.join(CLASS_PART_SEPARATOR);
1110
+ return classPartObject.validators.find(({
1111
+ validator
1112
+ }) => validator(classRest))?.classGroupId;
1113
+ };
1114
+ var arbitraryPropertyRegex = /^\[(.+)\]$/;
1115
+ var getGroupIdForArbitraryProperty = (className) => {
1116
+ if (arbitraryPropertyRegex.test(className)) {
1117
+ const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)[1];
1118
+ const property = arbitraryPropertyClassName?.substring(0, arbitraryPropertyClassName.indexOf(":"));
1119
+ if (property) {
1120
+ return "arbitrary.." + property;
1121
+ }
1122
+ }
1123
+ };
1124
+ var createClassMap = (config) => {
1125
+ const {
1126
+ theme,
1127
+ prefix
1128
+ } = config;
1129
+ const classMap = {
1130
+ nextPart: /* @__PURE__ */ new Map(),
1131
+ validators: []
1132
+ };
1133
+ const prefixedClassGroupEntries = getPrefixedClassGroupEntries(Object.entries(config.classGroups), prefix);
1134
+ prefixedClassGroupEntries.forEach(([classGroupId, classGroup]) => {
1135
+ processClassesRecursively(classGroup, classMap, classGroupId, theme);
1070
1136
  });
1071
- }
1072
- function arcPath(cx, cy, r2, startAngle, endAngle) {
1073
- const x1 = cx + r2 * Math.cos(startAngle);
1074
- const y1 = cy + r2 * Math.sin(startAngle);
1075
- const x2 = cx + r2 * Math.cos(endAngle);
1076
- const y2 = cy + r2 * Math.sin(endAngle);
1077
- const largeArc = endAngle - startAngle > Math.PI ? 1 : 0;
1078
- return `M${x1},${y1} A${r2},${r2} 0 ${largeArc},1 ${x2},${y2}`;
1079
- }
1080
- function radialPositions(cx, cy, innerR, outerR, count, startAngle = -Math.PI / 2) {
1081
- return Array.from({ length: count }, (_, i) => {
1082
- const angle = startAngle + Math.PI * 2 * i / count;
1083
- return {
1084
- x1: cx + innerR * Math.cos(angle),
1085
- y1: cy + innerR * Math.sin(angle),
1086
- x2: cx + outerR * Math.cos(angle),
1087
- y2: cy + outerR * Math.sin(angle),
1088
- angle
1089
- };
1137
+ return classMap;
1138
+ };
1139
+ var processClassesRecursively = (classGroup, classPartObject, classGroupId, theme) => {
1140
+ classGroup.forEach((classDefinition) => {
1141
+ if (typeof classDefinition === "string") {
1142
+ const classPartObjectToEdit = classDefinition === "" ? classPartObject : getPart(classPartObject, classDefinition);
1143
+ classPartObjectToEdit.classGroupId = classGroupId;
1144
+ return;
1145
+ }
1146
+ if (typeof classDefinition === "function") {
1147
+ if (isThemeGetter(classDefinition)) {
1148
+ processClassesRecursively(classDefinition(theme), classPartObject, classGroupId, theme);
1149
+ return;
1150
+ }
1151
+ classPartObject.validators.push({
1152
+ validator: classDefinition,
1153
+ classGroupId
1154
+ });
1155
+ return;
1156
+ }
1157
+ Object.entries(classDefinition).forEach(([key, classGroup2]) => {
1158
+ processClassesRecursively(classGroup2, getPart(classPartObject, key), classGroupId, theme);
1159
+ });
1090
1160
  });
1091
- }
1092
- function gridPositions(startX, startY, cols, cellWidth, cellHeight, count) {
1093
- return Array.from({ length: count }, (_, i) => {
1094
- const col = i % cols;
1095
- const row = Math.floor(i / cols);
1161
+ };
1162
+ var getPart = (classPartObject, path) => {
1163
+ let currentClassPartObject = classPartObject;
1164
+ path.split(CLASS_PART_SEPARATOR).forEach((pathPart) => {
1165
+ if (!currentClassPartObject.nextPart.has(pathPart)) {
1166
+ currentClassPartObject.nextPart.set(pathPart, {
1167
+ nextPart: /* @__PURE__ */ new Map(),
1168
+ validators: []
1169
+ });
1170
+ }
1171
+ currentClassPartObject = currentClassPartObject.nextPart.get(pathPart);
1172
+ });
1173
+ return currentClassPartObject;
1174
+ };
1175
+ var isThemeGetter = (func) => func.isThemeGetter;
1176
+ var getPrefixedClassGroupEntries = (classGroupEntries, prefix) => {
1177
+ if (!prefix) {
1178
+ return classGroupEntries;
1179
+ }
1180
+ return classGroupEntries.map(([classGroupId, classGroup]) => {
1181
+ const prefixedClassGroup = classGroup.map((classDefinition) => {
1182
+ if (typeof classDefinition === "string") {
1183
+ return prefix + classDefinition;
1184
+ }
1185
+ if (typeof classDefinition === "object") {
1186
+ return Object.fromEntries(Object.entries(classDefinition).map(([key, value]) => [prefix + key, value]));
1187
+ }
1188
+ return classDefinition;
1189
+ });
1190
+ return [classGroupId, prefixedClassGroup];
1191
+ });
1192
+ };
1193
+ var createLruCache = (maxCacheSize) => {
1194
+ if (maxCacheSize < 1) {
1096
1195
  return {
1097
- x: startX + col * cellWidth,
1098
- y: startY + row * cellHeight,
1099
- col,
1100
- row
1196
+ get: () => void 0,
1197
+ set: () => {
1198
+ }
1101
1199
  };
1102
- });
1103
- }
1104
- function curveControlPoint(x1, y1, x2, y2, offset) {
1105
- const mx = (x1 + x2) / 2;
1106
- const my = (y1 + y2) / 2;
1107
- const dx = x2 - x1;
1108
- const dy = y2 - y1;
1109
- const len = Math.sqrt(dx * dx + dy * dy) || 1;
1200
+ }
1201
+ let cacheSize = 0;
1202
+ let cache = /* @__PURE__ */ new Map();
1203
+ let previousCache = /* @__PURE__ */ new Map();
1204
+ const update = (key, value) => {
1205
+ cache.set(key, value);
1206
+ cacheSize++;
1207
+ if (cacheSize > maxCacheSize) {
1208
+ cacheSize = 0;
1209
+ previousCache = cache;
1210
+ cache = /* @__PURE__ */ new Map();
1211
+ }
1212
+ };
1110
1213
  return {
1111
- cpx: mx + -dy / len * offset,
1112
- cpy: my + dx / len * offset
1113
- };
1114
- }
1115
- var avlSmId = 0;
1116
- var AvlStateMachine = ({
1117
- states,
1118
- transitions,
1119
- className,
1120
- color = "var(--color-primary)",
1121
- animated = false
1122
- }) => {
1123
- const ids = React6.useMemo(() => {
1124
- avlSmId += 1;
1125
- const base = `avl-sm-${avlSmId}`;
1126
- return { glow: `${base}-glow`, grad: `${base}-grad` };
1127
- }, []);
1128
- const cx = 300;
1129
- const cy = 200;
1130
- const r2 = 150;
1131
- const stateWidth = 90;
1132
- const stateHeight = 36;
1133
- const positions = ringPositions(cx, cy, r2, states.length);
1134
- const stateIndex = new Map(states.map((s, i) => [s.name, i]));
1135
- const pairCount = /* @__PURE__ */ new Map();
1136
- const pairSeen = /* @__PURE__ */ new Map();
1137
- for (const tr of transitions) {
1138
- const key = [tr.from, tr.to].sort().join("|");
1139
- pairCount.set(key, (pairCount.get(key) ?? 0) + 1);
1140
- }
1141
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
1142
- /* @__PURE__ */ jsxs("defs", { children: [
1143
- /* @__PURE__ */ jsxs("filter", { id: ids.glow, x: "-50%", y: "-50%", width: "200%", height: "200%", children: [
1144
- /* @__PURE__ */ jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "3", result: "blur" }),
1145
- /* @__PURE__ */ jsxs("feMerge", { children: [
1146
- /* @__PURE__ */ jsx("feMergeNode", { in: "blur" }),
1147
- /* @__PURE__ */ jsx("feMergeNode", { in: "SourceGraphic" })
1148
- ] })
1149
- ] }),
1150
- /* @__PURE__ */ jsxs("linearGradient", { id: ids.grad, x1: "0%", y1: "0%", x2: "100%", y2: "100%", children: [
1151
- /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.1 }),
1152
- /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0.05 })
1153
- ] })
1154
- ] }),
1155
- animated && /* @__PURE__ */ jsx("style", { children: `
1156
- @keyframes avl-sm-dash { from { stroke-dashoffset: 20; } to { stroke-dashoffset: 0; } }
1157
- ` }),
1158
- /* @__PURE__ */ jsx("circle", { cx, cy, r: r2 + 30, fill: `url(#${ids.grad})` }),
1159
- transitions.map((tr, i) => {
1160
- if (tr.from !== tr.to) return null;
1161
- const idx = stateIndex.get(tr.from);
1162
- if (idx === void 0) return null;
1163
- const pos = positions[idx];
1164
- const loopR = 20;
1165
- const loopY = pos.y - stateHeight / 2 - 4;
1166
- const d = `M${pos.x - 14},${loopY} C${pos.x - 14},${loopY - loopR * 2} ${pos.x + 14},${loopY - loopR * 2} ${pos.x + 14},${loopY}`;
1167
- return /* @__PURE__ */ jsxs("g", { children: [
1168
- /* @__PURE__ */ jsx(
1169
- "path",
1170
- {
1171
- d,
1172
- fill: "none",
1173
- stroke: color,
1174
- strokeWidth: 1.5,
1175
- opacity: 0.7,
1176
- markerEnd: `url(#${ids.grad})`
1177
- }
1178
- ),
1179
- tr.event && /* @__PURE__ */ jsx(
1180
- "text",
1181
- {
1182
- x: pos.x,
1183
- y: loopY - loopR * 2 + 4,
1184
- textAnchor: "middle",
1185
- fill: color,
1186
- fontSize: 9,
1187
- fontFamily: "inherit",
1188
- fontWeight: "bold",
1189
- opacity: 0.8,
1190
- children: tr.event
1191
- }
1192
- )
1193
- ] }, `self-${i}`);
1194
- }),
1195
- transitions.map((tr, i) => {
1196
- if (tr.from === tr.to) return null;
1197
- const fromIdx = stateIndex.get(tr.from);
1198
- const toIdx = stateIndex.get(tr.to);
1199
- if (fromIdx === void 0 || toIdx === void 0) return null;
1200
- const fp = positions[fromIdx];
1201
- const tp = positions[toIdx];
1202
- const dx = tp.x - fp.x;
1203
- const dy = tp.y - fp.y;
1204
- const dist = Math.sqrt(dx * dx + dy * dy) || 1;
1205
- const nx = dx / dist;
1206
- const ny = dy / dist;
1207
- const pairKey = [tr.from, tr.to].sort().join("|");
1208
- const totalForPair = pairCount.get(pairKey) ?? 1;
1209
- const seenIdx = pairSeen.get(pairKey) ?? 0;
1210
- pairSeen.set(pairKey, seenIdx + 1);
1211
- const pairOffset = totalForPair > 1 ? (seenIdx - (totalForPair - 1) / 2) * 24 : 0;
1212
- const x1 = fp.x + nx * (stateWidth / 2 + 4);
1213
- const y1 = fp.y + ny * (stateHeight / 2 + 4);
1214
- const x2 = tp.x - nx * (stateWidth / 2 + 8);
1215
- const y2 = tp.y - ny * (stateHeight / 2 + 8);
1216
- const t = 0.3;
1217
- const labelX = x1 * (1 - t) + x2 * t;
1218
- const labelY = y1 * (1 - t) + y2 * t;
1219
- const perpX = -ny * (20 + Math.abs(pairOffset));
1220
- const perpY = nx * (20 + Math.abs(pairOffset));
1221
- const midToCenter = Math.sqrt((labelX - cx) ** 2 + (labelY - cy) ** 2);
1222
- const testX = labelX + perpX;
1223
- const testY = labelY + perpY;
1224
- const testToCenter = Math.sqrt((testX - cx) ** 2 + (testY - cy) ** 2);
1225
- const outSign = testToCenter > midToCenter ? 1 : -1;
1226
- const lx = labelX + perpX * outSign + -ny * pairOffset;
1227
- const ly = labelY + perpY * outSign + nx * pairOffset;
1228
- return /* @__PURE__ */ jsxs("g", { children: [
1229
- /* @__PURE__ */ jsx(
1230
- AvlTransition,
1231
- {
1232
- x1: x1 + -ny * pairOffset,
1233
- y1: y1 + nx * pairOffset,
1234
- x2: x2 + -ny * pairOffset,
1235
- y2: y2 + nx * pairOffset,
1236
- curved: states.length > 2,
1237
- curveAwayFrom: { x: cx, y: cy },
1238
- color,
1239
- opacity: 0.7
1240
- }
1241
- ),
1242
- tr.event && /* @__PURE__ */ jsx(
1243
- "text",
1244
- {
1245
- x: lx,
1246
- y: ly,
1247
- textAnchor: "middle",
1248
- fill: color,
1249
- fontSize: 9,
1250
- fontFamily: "inherit",
1251
- fontWeight: "bold",
1252
- opacity: 0.8,
1253
- children: tr.event
1254
- }
1255
- ),
1256
- tr.guard && /* @__PURE__ */ jsxs(
1257
- "text",
1258
- {
1259
- x: lx,
1260
- y: ly + 12,
1261
- textAnchor: "middle",
1262
- fill: color,
1263
- fontSize: 8,
1264
- fontFamily: "inherit",
1265
- opacity: 0.6,
1266
- children: [
1267
- "[",
1268
- tr.guard,
1269
- "]"
1270
- ]
1271
- }
1272
- ),
1273
- tr.effects?.map((eff, j) => /* @__PURE__ */ jsx(
1274
- AvlEffect,
1275
- {
1276
- x: lx + (j - ((tr.effects?.length ?? 1) - 1) / 2) * 14,
1277
- y: ly + (tr.guard ? 22 : 12),
1278
- effectType: eff,
1279
- size: 5,
1280
- color,
1281
- opacity: 0.7
1282
- },
1283
- j
1284
- ))
1285
- ] }, `tr-${i}`);
1286
- }),
1287
- states.map((state, i) => {
1288
- const pos = positions[i];
1289
- return /* @__PURE__ */ jsx(
1290
- AvlState,
1291
- {
1292
- x: pos.x - stateWidth / 2,
1293
- y: pos.y - stateHeight / 2,
1294
- width: stateWidth,
1295
- height: stateHeight,
1296
- name: state.name,
1297
- isInitial: state.isInitial,
1298
- isTerminal: state.isTerminal,
1299
- color
1300
- },
1301
- state.name
1302
- );
1303
- })
1304
- ] });
1305
- };
1306
- AvlStateMachine.displayName = "AvlStateMachine";
1307
- var avlOuId = 0;
1308
- var AvlOrbitalUnit = ({
1309
- entityName,
1310
- fields = 4,
1311
- persistence = "persistent",
1312
- traits,
1313
- pages,
1314
- className,
1315
- color = "var(--color-primary)",
1316
- animated = false
1317
- }) => {
1318
- const ids = React6.useMemo(() => {
1319
- avlOuId += 1;
1320
- const base = `avl-ou-${avlOuId}`;
1321
- return { glow: `${base}-glow`, grad: `${base}-grad` };
1322
- }, []);
1323
- const cx = 300;
1324
- const cy = 200;
1325
- const entityR = 24;
1326
- const orbitalR = 130;
1327
- const traitBaseRx = 55;
1328
- const traitBaseRy = 24;
1329
- const traitRxStep = 20;
1330
- const traitRyStep = 8;
1331
- const traitAngleStep = traits.length > 1 ? 120 / (traits.length - 1) : 0;
1332
- const traitAngleStart = traits.length > 1 ? -60 : 0;
1333
- const pageAngleStart = -Math.PI / 3;
1334
- const pageAngleStep = pages.length > 1 ? Math.PI * 0.8 / (pages.length - 1) : 0;
1335
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
1336
- /* @__PURE__ */ jsxs("defs", { children: [
1337
- /* @__PURE__ */ jsxs("filter", { id: ids.glow, x: "-50%", y: "-50%", width: "200%", height: "200%", children: [
1338
- /* @__PURE__ */ jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "3", result: "blur" }),
1339
- /* @__PURE__ */ jsxs("feMerge", { children: [
1340
- /* @__PURE__ */ jsx("feMergeNode", { in: "blur" }),
1341
- /* @__PURE__ */ jsx("feMergeNode", { in: "SourceGraphic" })
1342
- ] })
1343
- ] }),
1344
- /* @__PURE__ */ jsxs("radialGradient", { id: ids.grad, cx: "50%", cy: "50%", r: "50%", children: [
1345
- /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.08 }),
1346
- /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0 })
1347
- ] })
1348
- ] }),
1349
- animated && /* @__PURE__ */ jsx("style", { children: `
1350
- @keyframes avl-ou-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
1351
- ` }),
1352
- /* @__PURE__ */ jsx("circle", { cx, cy, r: orbitalR + 20, fill: `url(#${ids.grad})` }),
1353
- /* @__PURE__ */ jsx(AvlOrbital, { cx, cy, r: orbitalR, label: entityName, color }),
1354
- traits.map((trait, i) => {
1355
- const rotation = traitAngleStart + i * traitAngleStep;
1356
- const traitColor = trait.color ?? color;
1357
- return /* @__PURE__ */ jsx(
1358
- AvlTrait,
1359
- {
1360
- cx,
1361
- cy,
1362
- rx: traitBaseRx + i * traitRxStep,
1363
- ry: traitBaseRy + i * traitRyStep,
1364
- rotation,
1365
- label: trait.name,
1366
- color: traitColor,
1367
- opacity: 0.7
1368
- },
1369
- trait.name
1370
- );
1371
- }),
1372
- /* @__PURE__ */ jsx(
1373
- AvlEntity,
1374
- {
1375
- x: cx,
1376
- y: cy,
1377
- r: entityR,
1378
- fieldCount: fields,
1379
- persistence,
1380
- color
1381
- }
1382
- ),
1383
- pages.map((page, i) => {
1384
- const angle = pageAngleStart + i * pageAngleStep;
1385
- const px = cx + orbitalR * Math.cos(angle);
1386
- const py = cy + orbitalR * Math.sin(angle);
1387
- return /* @__PURE__ */ jsx(
1388
- AvlPage,
1389
- {
1390
- x: px,
1391
- y: py,
1392
- size: 10,
1393
- label: page.name,
1394
- color
1395
- },
1396
- page.name
1397
- );
1398
- })
1399
- ] });
1400
- };
1401
- AvlOrbitalUnit.displayName = "AvlOrbitalUnit";
1402
- var avlCcId = 0;
1403
- var AvlClosedCircuit = ({
1404
- states,
1405
- transitions,
1406
- className,
1407
- color = "var(--color-primary)",
1408
- animated = false
1409
- }) => {
1410
- const ids = React6.useMemo(() => {
1411
- avlCcId += 1;
1412
- const base = `avl-cc-${avlCcId}`;
1413
- return { glow: `${base}-glow`, grad: `${base}-grad`, arrow: `${base}-arrow` };
1414
- }, []);
1415
- const cx = 300;
1416
- const cy = 200;
1417
- const r2 = 120;
1418
- const stateW = 80;
1419
- const stateH = 32;
1420
- const positions = ringPositions(cx, cy, r2, states.length);
1421
- const stateIndex = new Map(states.map((s, i) => [s.name, i]));
1422
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
1423
- /* @__PURE__ */ jsxs("defs", { children: [
1424
- /* @__PURE__ */ jsxs("filter", { id: ids.glow, x: "-50%", y: "-50%", width: "200%", height: "200%", children: [
1425
- /* @__PURE__ */ jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "4", result: "blur" }),
1426
- /* @__PURE__ */ jsxs("feMerge", { children: [
1427
- /* @__PURE__ */ jsx("feMergeNode", { in: "blur" }),
1428
- /* @__PURE__ */ jsx("feMergeNode", { in: "SourceGraphic" })
1429
- ] })
1430
- ] }),
1431
- /* @__PURE__ */ jsxs("linearGradient", { id: ids.grad, x1: "0%", y1: "0%", x2: "100%", y2: "100%", children: [
1432
- /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.15 }),
1433
- /* @__PURE__ */ jsx("stop", { offset: "50%", stopColor: color, stopOpacity: 0.4 }),
1434
- /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0.15 })
1435
- ] }),
1436
- /* @__PURE__ */ jsx(
1437
- "marker",
1438
- {
1439
- id: ids.arrow,
1440
- markerWidth: "8",
1441
- markerHeight: "6",
1442
- refX: "7",
1443
- refY: "3",
1444
- orient: "auto",
1445
- markerUnits: "strokeWidth",
1446
- children: /* @__PURE__ */ jsx("path", { d: "M0,0 L8,3 L0,6 Z", fill: color, opacity: 0.6 })
1447
- }
1448
- )
1449
- ] }),
1450
- animated && /* @__PURE__ */ jsx("style", { children: `
1451
- @keyframes avl-cc-flow { from { stroke-dashoffset: 24; } to { stroke-dashoffset: 0; } }
1452
- ` }),
1453
- /* @__PURE__ */ jsx("circle", { cx, cy, r: r2 + 30, fill: "none", stroke: color, strokeWidth: 0.3, opacity: 0.06 }),
1454
- /* @__PURE__ */ jsx("circle", { cx, cy, r: 50, fill: "none", stroke: color, strokeWidth: 0.5, opacity: 0.08 }),
1455
- transitions.map((tr, i) => {
1456
- const fromIdx = stateIndex.get(tr.from);
1457
- const toIdx = stateIndex.get(tr.to);
1458
- if (fromIdx === void 0 || toIdx === void 0) return null;
1459
- const fp = positions[fromIdx];
1460
- const tp = positions[toIdx];
1461
- const dx = tp.x - fp.x;
1462
- const dy = tp.y - fp.y;
1463
- const dist = Math.sqrt(dx * dx + dy * dy) || 1;
1464
- const nx = dx / dist;
1465
- const ny = dy / dist;
1466
- const x1 = fp.x + nx * (stateW / 2 + 4);
1467
- const y1 = fp.y + ny * (stateH / 2 + 4);
1468
- const x2 = tp.x - nx * (stateW / 2 + 8);
1469
- const y2 = tp.y - ny * (stateH / 2 + 8);
1470
- const mx = (x1 + x2) / 2;
1471
- const my = (y1 + y2) / 2;
1472
- const curvature = dist * 0.25;
1473
- let perpX = -ny;
1474
- let perpY = nx;
1475
- const testX = mx + perpX * curvature;
1476
- const testY = my + perpY * curvature;
1477
- const distTest = Math.sqrt((testX - cx) ** 2 + (testY - cy) ** 2);
1478
- const distMid = Math.sqrt((mx - cx) ** 2 + (my - cy) ** 2);
1479
- if (distTest < distMid) {
1480
- perpX = -perpX;
1481
- perpY = -perpY;
1482
- }
1483
- const cpx = mx + perpX * curvature;
1484
- const cpy = my + perpY * curvature;
1485
- const d = `M${x1},${y1} Q${cpx},${cpy} ${x2},${y2}`;
1486
- return /* @__PURE__ */ jsxs("g", { children: [
1487
- /* @__PURE__ */ jsx(
1488
- "path",
1489
- {
1490
- d,
1491
- fill: "none",
1492
- stroke: `url(#${ids.grad})`,
1493
- strokeWidth: 1.5,
1494
- strokeDasharray: animated ? "8 6" : void 0,
1495
- markerEnd: `url(#${ids.arrow})`,
1496
- style: animated ? { animation: "avl-cc-flow 1.5s linear infinite" } : void 0
1497
- }
1498
- ),
1499
- tr.event && /* @__PURE__ */ jsx(
1500
- AvlEvent,
1501
- {
1502
- x: cpx,
1503
- y: cpy - 14,
1504
- size: 8,
1505
- label: tr.event,
1506
- color,
1507
- opacity: 0.8
1508
- }
1509
- ),
1510
- tr.guard && /* @__PURE__ */ jsx(
1511
- AvlGuard,
1512
- {
1513
- x: mx,
1514
- y: my - 8,
1515
- size: 10,
1516
- label: tr.guard,
1517
- color,
1518
- opacity: 0.6
1519
- }
1520
- ),
1521
- tr.effects?.map((eff, j) => /* @__PURE__ */ jsx(
1522
- AvlEffect,
1523
- {
1524
- x: mx + (j - ((tr.effects?.length ?? 1) - 1) / 2) * 14,
1525
- y: my + 14,
1526
- effectType: eff,
1527
- size: 5,
1528
- color,
1529
- opacity: 0.7
1530
- },
1531
- j
1532
- ))
1533
- ] }, `cc-tr-${i}`);
1534
- }),
1535
- states.map((state, i) => {
1536
- const pos = positions[i];
1537
- return /* @__PURE__ */ jsx(
1538
- AvlState,
1539
- {
1540
- x: pos.x - stateW / 2,
1541
- y: pos.y - stateH / 2,
1542
- width: stateW,
1543
- height: stateH,
1544
- name: state.name,
1545
- color
1546
- },
1547
- state.name
1548
- );
1549
- }),
1550
- /* @__PURE__ */ jsx("circle", { cx, cy, r: 3, fill: color, opacity: 0.4 })
1551
- ] });
1552
- };
1553
- AvlClosedCircuit.displayName = "AvlClosedCircuit";
1554
- var avlElId = 0;
1555
- var AvlEmitListen = ({
1556
- emitter,
1557
- listener,
1558
- eventName,
1559
- className,
1560
- color = "var(--color-primary)",
1561
- animated = false
1562
- }) => {
1563
- const ids = React6.useMemo(() => {
1564
- avlElId += 1;
1565
- const base = `avl-el-${avlElId}`;
1566
- return { arrow: `${base}-arrow`, grad: `${base}-grad` };
1567
- }, []);
1568
- const leftCx = 180;
1569
- const rightCx = 420;
1570
- const cy = 200;
1571
- const orbR = 80;
1572
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
1573
- /* @__PURE__ */ jsxs("defs", { children: [
1574
- /* @__PURE__ */ jsx(
1575
- "marker",
1576
- {
1577
- id: ids.arrow,
1578
- markerWidth: "8",
1579
- markerHeight: "6",
1580
- refX: "7",
1581
- refY: "3",
1582
- orient: "auto",
1583
- markerUnits: "strokeWidth",
1584
- children: /* @__PURE__ */ jsx("path", { d: "M0,0 L8,3 L0,6 Z", fill: color, opacity: 0.6 })
1585
- }
1586
- ),
1587
- /* @__PURE__ */ jsxs("linearGradient", { id: ids.grad, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [
1588
- /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.5 }),
1589
- /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0.2 })
1590
- ] })
1591
- ] }),
1592
- animated && /* @__PURE__ */ jsx("style", { children: `
1593
- @keyframes avl-el-dash { from { stroke-dashoffset: 16; } to { stroke-dashoffset: 0; } }
1594
- ` }),
1595
- /* @__PURE__ */ jsx(AvlOrbital, { cx: leftCx, cy, r: orbR, label: emitter.name, color }),
1596
- /* @__PURE__ */ jsx(AvlEntity, { x: leftCx, y: cy, r: 18, fieldCount: emitter.fields ?? 3, color }),
1597
- /* @__PURE__ */ jsx(AvlOrbital, { cx: rightCx, cy, r: orbR, label: listener.name, color }),
1598
- /* @__PURE__ */ jsx(AvlEntity, { x: rightCx, y: cy, r: 18, fieldCount: listener.fields ?? 3, color }),
1599
- /* @__PURE__ */ jsx(
1600
- "path",
1601
- {
1602
- d: `M${leftCx + orbR + 4},${cy} L${rightCx - orbR - 8},${cy}`,
1603
- fill: "none",
1604
- stroke: `url(#${ids.grad})`,
1605
- strokeWidth: 2,
1606
- strokeDasharray: "6 4",
1607
- markerEnd: `url(#${ids.arrow})`,
1608
- style: animated ? { animation: "avl-el-dash 1s linear infinite" } : void 0
1609
- }
1610
- ),
1611
- /* @__PURE__ */ jsx(
1612
- AvlEffect,
1613
- {
1614
- x: leftCx + orbR + 20,
1615
- y: cy - 20,
1616
- effectType: "emit",
1617
- size: 6,
1618
- color,
1619
- opacity: 0.8
1620
- }
1621
- ),
1622
- eventName && /* @__PURE__ */ jsxs(
1623
- "text",
1624
- {
1625
- x: 300,
1626
- y: cy - 18,
1627
- textAnchor: "middle",
1628
- fill: color,
1629
- fontSize: 11,
1630
- fontFamily: "inherit",
1631
- fontWeight: "bold",
1632
- opacity: 0.8,
1633
- children: [
1634
- "~",
1635
- eventName
1636
- ]
1637
- }
1638
- ),
1639
- /* @__PURE__ */ jsx(
1640
- "text",
1641
- {
1642
- x: 300,
1643
- y: cy + 18,
1644
- textAnchor: "middle",
1645
- fill: color,
1646
- fontSize: 12,
1647
- fontFamily: "inherit",
1648
- opacity: 0.3,
1649
- letterSpacing: 4,
1650
- children: "~ ~ ~"
1651
- }
1652
- )
1653
- ] });
1654
- };
1655
- AvlEmitListen.displayName = "AvlEmitListen";
1656
- var SLOT_PRESETS = {
1657
- header: { x: 10, y: 5, width: 340, height: 35 },
1658
- main: { x: 120, y: 50, width: 230, height: 195 },
1659
- sidebar: { x: 10, y: 50, width: 100, height: 195 },
1660
- modal: { x: 80, y: 60, width: 200, height: 140 },
1661
- drawer: { x: 220, y: 50, width: 130, height: 195 },
1662
- toast: { x: 220, y: 210, width: 130, height: 35 },
1663
- footer: { x: 10, y: 220, width: 340, height: 30 },
1664
- center: { x: 60, y: 50, width: 240, height: 195 },
1665
- "hud-top": { x: 10, y: 5, width: 340, height: 30 },
1666
- "hud-bottom": { x: 10, y: 220, width: 340, height: 30 }
1667
- };
1668
- function resolveSlot(slot, fallbackIdx) {
1669
- if (slot.x !== void 0 && slot.y !== void 0 && slot.width !== void 0 && slot.height !== void 0) {
1670
- return slot;
1671
- }
1672
- const preset = SLOT_PRESETS[slot.name];
1673
- if (preset) {
1674
- return {
1675
- name: slot.name,
1676
- x: slot.x ?? preset.x,
1677
- y: slot.y ?? preset.y,
1678
- width: slot.width ?? preset.width,
1679
- height: slot.height ?? preset.height
1680
- };
1681
- }
1682
- const col = fallbackIdx % 2;
1683
- const row = Math.floor(fallbackIdx / 2);
1684
- return {
1685
- name: slot.name,
1686
- x: 10 + col * 175,
1687
- y: 50 + row * 100,
1688
- width: 165,
1689
- height: 90
1690
- };
1691
- }
1692
- var AvlSlotMap = ({
1693
- slots,
1694
- pageWidth = 360,
1695
- pageHeight = 280,
1696
- className,
1697
- color = "var(--color-primary)",
1698
- animated = false
1699
- }) => {
1700
- const ox = (600 - pageWidth) / 2;
1701
- const oy = (400 - pageHeight) / 2;
1702
- let unknownIdx = 0;
1703
- const resolvedSlots = slots.map((slot) => {
1704
- const isUnknown = !SLOT_PRESETS[slot.name] && (slot.x === void 0 || slot.y === void 0);
1705
- const resolved = resolveSlot(slot, isUnknown ? unknownIdx : 0);
1706
- if (isUnknown) unknownIdx++;
1707
- return resolved;
1708
- });
1709
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
1710
- animated && /* @__PURE__ */ jsx("style", { children: `
1711
- @keyframes avl-slot-pulse { 0%, 100% { opacity: 0.15; } 50% { opacity: 0.25; } }
1712
- ` }),
1713
- /* @__PURE__ */ jsx(
1714
- "rect",
1715
- {
1716
- x: ox,
1717
- y: oy,
1718
- width: pageWidth,
1719
- height: pageHeight,
1720
- rx: 4,
1721
- ry: 4,
1722
- fill: "none",
1723
- stroke: color,
1724
- strokeWidth: 2
1725
- }
1726
- ),
1727
- /* @__PURE__ */ jsx(
1728
- "rect",
1729
- {
1730
- x: ox,
1731
- y: oy,
1732
- width: pageWidth,
1733
- height: 24,
1734
- rx: 4,
1735
- ry: 4,
1736
- fill: color,
1737
- opacity: 0.1
1738
- }
1739
- ),
1740
- /* @__PURE__ */ jsx(
1741
- "text",
1742
- {
1743
- x: ox + pageWidth / 2,
1744
- y: oy + 16,
1745
- textAnchor: "middle",
1746
- fill: color,
1747
- fontSize: 10,
1748
- fontFamily: "inherit",
1749
- fontWeight: "bold",
1750
- children: "Page Layout"
1751
- }
1752
- ),
1753
- resolvedSlots.map((slot) => /* @__PURE__ */ jsxs("g", { children: [
1754
- /* @__PURE__ */ jsx(
1755
- "rect",
1756
- {
1757
- x: ox + slot.x,
1758
- y: oy + 24 + slot.y,
1759
- width: slot.width,
1760
- height: slot.height,
1761
- rx: 3,
1762
- ry: 3,
1763
- fill: color,
1764
- opacity: 0.08,
1765
- stroke: color,
1766
- strokeWidth: 1,
1767
- strokeDasharray: "4 2",
1768
- style: animated ? { animation: "avl-slot-pulse 2s ease-in-out infinite" } : void 0
1769
- }
1770
- ),
1771
- /* @__PURE__ */ jsx(
1772
- "text",
1773
- {
1774
- x: ox + slot.x + slot.width / 2,
1775
- y: oy + 24 + slot.y + slot.height / 2,
1776
- textAnchor: "middle",
1777
- dominantBaseline: "central",
1778
- fill: color,
1779
- fontSize: 9,
1780
- fontFamily: "inherit",
1781
- opacity: 0.6,
1782
- children: slot.name
1783
- }
1784
- )
1785
- ] }, slot.name))
1786
- ] });
1787
- };
1788
- AvlSlotMap.displayName = "AvlSlotMap";
1789
- var avlEtId = 0;
1790
- function layoutTree(node, x, y, hSpacing, vSpacing) {
1791
- const children = node.children ?? [];
1792
- if (children.length === 0) {
1793
- return { label: node.label, type: node.type, x, y, children: [] };
1794
- }
1795
- const totalWidth = (children.length - 1) * hSpacing;
1796
- const startX = x - totalWidth / 2;
1797
- const layoutChildren = children.map(
1798
- (child, i) => layoutTree(child, startX + i * hSpacing, y + vSpacing, hSpacing * 0.65, vSpacing)
1799
- );
1800
- return { label: node.label, type: node.type, x, y, children: layoutChildren };
1801
- }
1802
- function nodeColor(type, baseColor) {
1803
- switch (type) {
1804
- case "operator":
1805
- return baseColor;
1806
- case "literal":
1807
- return baseColor;
1808
- case "binding":
1809
- return baseColor;
1810
- }
1811
- }
1812
- function renderNode(node, color, glowId) {
1813
- const labelLen = node.label.length;
1814
- const baseR = node.type === "operator" ? 20 : 16;
1815
- const r2 = Math.max(baseR, labelLen * 3.5 + 6);
1816
- const nc = nodeColor(node.type, color);
1817
- return /* @__PURE__ */ jsxs(React6.Fragment, { children: [
1818
- node.children.map((child, i) => {
1819
- const childR = Math.max(
1820
- child.type === "operator" ? 20 : 16,
1821
- child.label.length * 3.5 + 6
1822
- );
1823
- return /* @__PURE__ */ jsx(
1824
- "line",
1825
- {
1826
- x1: node.x,
1827
- y1: node.y + (node.type === "operator" ? r2 * 0.7 : r2),
1828
- x2: child.x,
1829
- y2: child.y - (child.type === "operator" ? childR * 0.7 : childR),
1830
- stroke: color,
1831
- strokeWidth: 1,
1832
- opacity: 0.3
1833
- },
1834
- `line-${i}`
1835
- );
1836
- }),
1837
- node.type === "operator" ? /* @__PURE__ */ jsx(
1838
- "rect",
1839
- {
1840
- x: node.x - r2,
1841
- y: node.y - r2 * 0.6,
1842
- width: r2 * 2,
1843
- height: r2 * 1.2,
1844
- rx: 4,
1845
- ry: 4,
1846
- fill: color,
1847
- fillOpacity: 0.15,
1848
- stroke: nc,
1849
- strokeWidth: 1.5
1850
- }
1851
- ) : node.type === "binding" ? /* @__PURE__ */ jsx("circle", { cx: node.x, cy: node.y, r: r2, fill: "none", stroke: nc, strokeWidth: 1.5, strokeDasharray: "3 2" }) : /* @__PURE__ */ jsx("circle", { cx: node.x, cy: node.y, r: r2, fill: "none", stroke: nc, strokeWidth: 1, opacity: 0.5 }),
1852
- /* @__PURE__ */ jsx(
1853
- "text",
1854
- {
1855
- x: node.x,
1856
- y: node.y + 1,
1857
- textAnchor: "middle",
1858
- dominantBaseline: "central",
1859
- fill: nc,
1860
- fontSize: node.type === "operator" ? 11 : 10,
1861
- fontFamily: "inherit",
1862
- fontWeight: node.type === "operator" ? "bold" : "normal",
1863
- children: node.type === "binding" ? `@${node.label}` : node.label
1864
- }
1865
- ),
1866
- node.children.map((child) => renderNode(child, color))
1867
- ] }, `${node.label}-${node.x}-${node.y}`);
1868
- }
1869
- var AvlExprTree = ({
1870
- expression,
1871
- className,
1872
- color = "var(--color-primary)"
1873
- }) => {
1874
- const ids = React6.useMemo(() => {
1875
- avlEtId += 1;
1876
- return { glow: `avl-et-${avlEtId}-glow` };
1877
- }, []);
1878
- const layout = layoutTree(expression, 300, 70, 150, 85);
1879
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
1880
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("filter", { id: ids.glow, x: "-50%", y: "-50%", width: "200%", height: "200%", children: [
1881
- /* @__PURE__ */ jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "2", result: "blur" }),
1882
- /* @__PURE__ */ jsxs("feMerge", { children: [
1883
- /* @__PURE__ */ jsx("feMergeNode", { in: "blur" }),
1884
- /* @__PURE__ */ jsx("feMergeNode", { in: "SourceGraphic" })
1885
- ] })
1886
- ] }) }),
1887
- renderNode(layout, color, ids.glow)
1888
- ] });
1889
- };
1890
- AvlExprTree.displayName = "AvlExprTree";
1891
-
1892
- // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
1893
- function r(e) {
1894
- var t, f, n = "";
1895
- if ("string" == typeof e || "number" == typeof e) n += e;
1896
- else if ("object" == typeof e) if (Array.isArray(e)) {
1897
- var o = e.length;
1898
- for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
1899
- } else for (f in e) e[f] && (n && (n += " "), n += f);
1900
- return n;
1901
- }
1902
- function clsx() {
1903
- for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
1904
- return n;
1905
- }
1906
-
1907
- // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
1908
- var CLASS_PART_SEPARATOR = "-";
1909
- var createClassGroupUtils = (config) => {
1910
- const classMap = createClassMap(config);
1911
- const {
1912
- conflictingClassGroups,
1913
- conflictingClassGroupModifiers
1914
- } = config;
1915
- const getClassGroupId = (className) => {
1916
- const classParts = className.split(CLASS_PART_SEPARATOR);
1917
- if (classParts[0] === "" && classParts.length !== 1) {
1918
- classParts.shift();
1919
- }
1920
- return getGroupRecursive(classParts, classMap) || getGroupIdForArbitraryProperty(className);
1921
- };
1922
- const getConflictingClassGroupIds = (classGroupId, hasPostfixModifier) => {
1923
- const conflicts = conflictingClassGroups[classGroupId] || [];
1924
- if (hasPostfixModifier && conflictingClassGroupModifiers[classGroupId]) {
1925
- return [...conflicts, ...conflictingClassGroupModifiers[classGroupId]];
1926
- }
1927
- return conflicts;
1928
- };
1929
- return {
1930
- getClassGroupId,
1931
- getConflictingClassGroupIds
1932
- };
1933
- };
1934
- var getGroupRecursive = (classParts, classPartObject) => {
1935
- if (classParts.length === 0) {
1936
- return classPartObject.classGroupId;
1937
- }
1938
- const currentClassPart = classParts[0];
1939
- const nextClassPartObject = classPartObject.nextPart.get(currentClassPart);
1940
- const classGroupFromNextClassPart = nextClassPartObject ? getGroupRecursive(classParts.slice(1), nextClassPartObject) : void 0;
1941
- if (classGroupFromNextClassPart) {
1942
- return classGroupFromNextClassPart;
1943
- }
1944
- if (classPartObject.validators.length === 0) {
1945
- return void 0;
1946
- }
1947
- const classRest = classParts.join(CLASS_PART_SEPARATOR);
1948
- return classPartObject.validators.find(({
1949
- validator
1950
- }) => validator(classRest))?.classGroupId;
1951
- };
1952
- var arbitraryPropertyRegex = /^\[(.+)\]$/;
1953
- var getGroupIdForArbitraryProperty = (className) => {
1954
- if (arbitraryPropertyRegex.test(className)) {
1955
- const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)[1];
1956
- const property = arbitraryPropertyClassName?.substring(0, arbitraryPropertyClassName.indexOf(":"));
1957
- if (property) {
1958
- return "arbitrary.." + property;
1959
- }
1960
- }
1961
- };
1962
- var createClassMap = (config) => {
1963
- const {
1964
- theme,
1965
- prefix
1966
- } = config;
1967
- const classMap = {
1968
- nextPart: /* @__PURE__ */ new Map(),
1969
- validators: []
1970
- };
1971
- const prefixedClassGroupEntries = getPrefixedClassGroupEntries(Object.entries(config.classGroups), prefix);
1972
- prefixedClassGroupEntries.forEach(([classGroupId, classGroup]) => {
1973
- processClassesRecursively(classGroup, classMap, classGroupId, theme);
1974
- });
1975
- return classMap;
1976
- };
1977
- var processClassesRecursively = (classGroup, classPartObject, classGroupId, theme) => {
1978
- classGroup.forEach((classDefinition) => {
1979
- if (typeof classDefinition === "string") {
1980
- const classPartObjectToEdit = classDefinition === "" ? classPartObject : getPart(classPartObject, classDefinition);
1981
- classPartObjectToEdit.classGroupId = classGroupId;
1982
- return;
1983
- }
1984
- if (typeof classDefinition === "function") {
1985
- if (isThemeGetter(classDefinition)) {
1986
- processClassesRecursively(classDefinition(theme), classPartObject, classGroupId, theme);
1987
- return;
1988
- }
1989
- classPartObject.validators.push({
1990
- validator: classDefinition,
1991
- classGroupId
1992
- });
1993
- return;
1994
- }
1995
- Object.entries(classDefinition).forEach(([key, classGroup2]) => {
1996
- processClassesRecursively(classGroup2, getPart(classPartObject, key), classGroupId, theme);
1997
- });
1998
- });
1999
- };
2000
- var getPart = (classPartObject, path) => {
2001
- let currentClassPartObject = classPartObject;
2002
- path.split(CLASS_PART_SEPARATOR).forEach((pathPart) => {
2003
- if (!currentClassPartObject.nextPart.has(pathPart)) {
2004
- currentClassPartObject.nextPart.set(pathPart, {
2005
- nextPart: /* @__PURE__ */ new Map(),
2006
- validators: []
2007
- });
2008
- }
2009
- currentClassPartObject = currentClassPartObject.nextPart.get(pathPart);
2010
- });
2011
- return currentClassPartObject;
2012
- };
2013
- var isThemeGetter = (func) => func.isThemeGetter;
2014
- var getPrefixedClassGroupEntries = (classGroupEntries, prefix) => {
2015
- if (!prefix) {
2016
- return classGroupEntries;
2017
- }
2018
- return classGroupEntries.map(([classGroupId, classGroup]) => {
2019
- const prefixedClassGroup = classGroup.map((classDefinition) => {
2020
- if (typeof classDefinition === "string") {
2021
- return prefix + classDefinition;
2022
- }
2023
- if (typeof classDefinition === "object") {
2024
- return Object.fromEntries(Object.entries(classDefinition).map(([key, value]) => [prefix + key, value]));
2025
- }
2026
- return classDefinition;
2027
- });
2028
- return [classGroupId, prefixedClassGroup];
2029
- });
2030
- };
2031
- var createLruCache = (maxCacheSize) => {
2032
- if (maxCacheSize < 1) {
2033
- return {
2034
- get: () => void 0,
2035
- set: () => {
2036
- }
2037
- };
2038
- }
2039
- let cacheSize = 0;
2040
- let cache = /* @__PURE__ */ new Map();
2041
- let previousCache = /* @__PURE__ */ new Map();
2042
- const update = (key, value) => {
2043
- cache.set(key, value);
2044
- cacheSize++;
2045
- if (cacheSize > maxCacheSize) {
2046
- cacheSize = 0;
2047
- previousCache = cache;
2048
- cache = /* @__PURE__ */ new Map();
2049
- }
2050
- };
2051
- return {
2052
- get(key) {
2053
- let value = cache.get(key);
2054
- if (value !== void 0) {
2055
- return value;
2056
- }
2057
- if ((value = previousCache.get(key)) !== void 0) {
2058
- update(key, value);
2059
- return value;
2060
- }
2061
- },
2062
- set(key, value) {
2063
- if (cache.has(key)) {
2064
- cache.set(key, value);
2065
- } else {
2066
- update(key, value);
2067
- }
2068
- }
1214
+ get(key) {
1215
+ let value = cache.get(key);
1216
+ if (value !== void 0) {
1217
+ return value;
1218
+ }
1219
+ if ((value = previousCache.get(key)) !== void 0) {
1220
+ update(key, value);
1221
+ return value;
1222
+ }
1223
+ },
1224
+ set(key, value) {
1225
+ if (cache.has(key)) {
1226
+ cache.set(key, value);
1227
+ } else {
1228
+ update(key, value);
1229
+ }
1230
+ }
2069
1231
  };
2070
1232
  };
2071
1233
  var IMPORTANT_MODIFIER = "!";
@@ -4368,6 +3530,113 @@ var twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
4368
3530
  function cn(...inputs) {
4369
3531
  return twMerge(clsx(inputs));
4370
3532
  }
3533
+ var variantStyles = {
3534
+ h1: "text-4xl font-bold tracking-tight text-[var(--color-foreground)]",
3535
+ h2: "text-3xl font-bold tracking-tight text-[var(--color-foreground)]",
3536
+ h3: "text-2xl font-bold text-[var(--color-foreground)]",
3537
+ h4: "text-xl font-bold text-[var(--color-foreground)]",
3538
+ h5: "text-lg font-bold text-[var(--color-foreground)]",
3539
+ h6: "text-base font-bold text-[var(--color-foreground)]",
3540
+ heading: "text-2xl font-bold text-[var(--color-foreground)]",
3541
+ subheading: "text-lg font-semibold text-[var(--color-foreground)]",
3542
+ body1: "text-base font-normal text-[var(--color-foreground)]",
3543
+ body2: "text-sm font-normal text-[var(--color-foreground)]",
3544
+ body: "text-base font-normal text-[var(--color-foreground)]",
3545
+ caption: "text-xs font-normal text-[var(--color-muted-foreground)]",
3546
+ overline: "text-xs uppercase tracking-wide font-bold text-[var(--color-muted-foreground)]",
3547
+ small: "text-sm font-normal text-[var(--color-foreground)]",
3548
+ large: "text-lg font-medium text-[var(--color-foreground)]",
3549
+ label: "text-sm font-medium text-[var(--color-foreground)]"
3550
+ };
3551
+ var colorStyles = {
3552
+ primary: "text-[var(--color-foreground)]",
3553
+ secondary: "text-[var(--color-muted-foreground)]",
3554
+ muted: "text-[var(--color-muted-foreground)]",
3555
+ error: "text-[var(--color-error)]",
3556
+ success: "text-[var(--color-success)]",
3557
+ warning: "text-[var(--color-warning)]",
3558
+ inherit: "text-inherit"
3559
+ };
3560
+ var weightStyles = {
3561
+ light: "font-light",
3562
+ normal: "font-normal",
3563
+ medium: "font-medium",
3564
+ semibold: "font-semibold",
3565
+ bold: "font-bold"
3566
+ };
3567
+ var defaultElements = {
3568
+ h1: "h1",
3569
+ h2: "h2",
3570
+ h3: "h3",
3571
+ h4: "h4",
3572
+ h5: "h5",
3573
+ h6: "h6",
3574
+ heading: "h2",
3575
+ subheading: "h3",
3576
+ body1: "p",
3577
+ body2: "p",
3578
+ body: "p",
3579
+ caption: "span",
3580
+ overline: "span",
3581
+ small: "span",
3582
+ large: "p",
3583
+ label: "span"
3584
+ };
3585
+ var typographySizeStyles = {
3586
+ xs: "text-xs",
3587
+ sm: "text-sm",
3588
+ md: "text-base",
3589
+ lg: "text-lg",
3590
+ xl: "text-xl",
3591
+ "2xl": "text-2xl",
3592
+ "3xl": "text-3xl"
3593
+ };
3594
+ var overflowStyles = {
3595
+ visible: "overflow-visible",
3596
+ hidden: "overflow-hidden",
3597
+ wrap: "break-words overflow-hidden",
3598
+ "clamp-2": "overflow-hidden line-clamp-2",
3599
+ "clamp-3": "overflow-hidden line-clamp-3"
3600
+ };
3601
+ var Typography = ({
3602
+ variant: variantProp,
3603
+ level,
3604
+ color = "primary",
3605
+ align,
3606
+ weight,
3607
+ size,
3608
+ truncate = false,
3609
+ overflow,
3610
+ as,
3611
+ id,
3612
+ className,
3613
+ style,
3614
+ content,
3615
+ children
3616
+ }) => {
3617
+ const variant = variantProp ?? (level ? `h${level}` : "body1");
3618
+ const Component = as || defaultElements[variant];
3619
+ const Comp = Component;
3620
+ return /* @__PURE__ */ jsx(
3621
+ Comp,
3622
+ {
3623
+ id,
3624
+ className: cn(
3625
+ variantStyles[variant],
3626
+ colorStyles[color],
3627
+ weight && weightStyles[weight],
3628
+ size && typographySizeStyles[size],
3629
+ align && `text-${align}`,
3630
+ truncate && "truncate overflow-hidden text-ellipsis",
3631
+ overflow && overflowStyles[overflow],
3632
+ className
3633
+ ),
3634
+ style,
3635
+ children: children ?? content
3636
+ }
3637
+ );
3638
+ };
3639
+ Typography.displayName = "Typography";
4371
3640
  var EventBusContext = createContext(null);
4372
3641
 
4373
3642
  // hooks/useEventBus.ts
@@ -4531,296 +3800,1049 @@ var displayStyles = {
4531
3800
  "inline-flex": "inline-flex",
4532
3801
  grid: "grid"
4533
3802
  };
4534
- var overflowStyles = {
4535
- auto: "overflow-auto",
4536
- hidden: "overflow-hidden",
4537
- visible: "overflow-visible",
4538
- scroll: "overflow-scroll"
3803
+ var overflowStyles2 = {
3804
+ auto: "overflow-auto",
3805
+ hidden: "overflow-hidden",
3806
+ visible: "overflow-visible",
3807
+ scroll: "overflow-scroll"
3808
+ };
3809
+ var positionStyles = {
3810
+ relative: "relative",
3811
+ absolute: "absolute",
3812
+ fixed: "fixed",
3813
+ sticky: "sticky"
3814
+ };
3815
+ var Box = React8.forwardRef(
3816
+ ({
3817
+ padding,
3818
+ paddingX,
3819
+ paddingY,
3820
+ margin,
3821
+ marginX,
3822
+ marginY,
3823
+ bg = "transparent",
3824
+ border = false,
3825
+ rounded = "none",
3826
+ shadow = "none",
3827
+ display,
3828
+ fullWidth = false,
3829
+ fullHeight = false,
3830
+ overflow,
3831
+ position,
3832
+ className,
3833
+ children,
3834
+ as: Component = "div",
3835
+ action,
3836
+ actionPayload,
3837
+ hoverEvent,
3838
+ onClick,
3839
+ onMouseEnter,
3840
+ onMouseLeave,
3841
+ ...rest
3842
+ }, ref) => {
3843
+ const eventBus = useEventBus();
3844
+ const handleClick = useCallback((e) => {
3845
+ if (action) {
3846
+ e.stopPropagation();
3847
+ eventBus.emit(`UI:${action}`, actionPayload ?? {});
3848
+ }
3849
+ onClick?.(e);
3850
+ }, [action, actionPayload, eventBus, onClick]);
3851
+ const handleMouseEnter = useCallback((e) => {
3852
+ if (hoverEvent) {
3853
+ eventBus.emit(`UI:${hoverEvent}`, { hovered: true });
3854
+ }
3855
+ onMouseEnter?.(e);
3856
+ }, [hoverEvent, eventBus, onMouseEnter]);
3857
+ const handleMouseLeave = useCallback((e) => {
3858
+ if (hoverEvent) {
3859
+ eventBus.emit(`UI:${hoverEvent}`, { hovered: false });
3860
+ }
3861
+ onMouseLeave?.(e);
3862
+ }, [hoverEvent, eventBus, onMouseLeave]);
3863
+ const isClickable = action || onClick;
3864
+ const Comp = Component;
3865
+ return /* @__PURE__ */ jsx(
3866
+ Comp,
3867
+ {
3868
+ ref,
3869
+ className: cn(
3870
+ // Padding
3871
+ padding && paddingStyles[padding],
3872
+ paddingX && paddingXStyles[paddingX],
3873
+ paddingY && paddingYStyles[paddingY],
3874
+ // Margin
3875
+ margin && marginStyles[margin],
3876
+ marginX && marginXStyles[marginX],
3877
+ marginY && marginYStyles[marginY],
3878
+ // Background
3879
+ bgStyles[bg],
3880
+ // Border - uses theme variables
3881
+ border && "border-[length:var(--border-width)] border-[var(--color-border)]",
3882
+ // Rounded
3883
+ roundedStyles[rounded],
3884
+ // Shadow
3885
+ shadowStyles[shadow],
3886
+ // Display
3887
+ display && displayStyles[display],
3888
+ // Dimensions
3889
+ fullWidth && "w-full",
3890
+ fullHeight && "h-full",
3891
+ // Overflow
3892
+ overflow && overflowStyles2[overflow],
3893
+ // Position
3894
+ position && positionStyles[position],
3895
+ // Cursor for clickable
3896
+ isClickable && "cursor-pointer",
3897
+ className
3898
+ ),
3899
+ onClick: isClickable ? handleClick : void 0,
3900
+ onMouseEnter: hoverEvent || onMouseEnter ? handleMouseEnter : void 0,
3901
+ onMouseLeave: hoverEvent || onMouseLeave ? handleMouseLeave : void 0,
3902
+ ...rest,
3903
+ children
3904
+ }
3905
+ );
3906
+ }
3907
+ );
3908
+ Box.displayName = "Box";
3909
+ var gapStyles = {
3910
+ none: "gap-0",
3911
+ xs: "gap-1",
3912
+ sm: "gap-2",
3913
+ md: "gap-4",
3914
+ lg: "gap-6",
3915
+ xl: "gap-8",
3916
+ "2xl": "gap-12"
3917
+ };
3918
+ var alignStyles = {
3919
+ start: "items-start",
3920
+ center: "items-center",
3921
+ end: "items-end",
3922
+ stretch: "items-stretch",
3923
+ baseline: "items-baseline"
3924
+ };
3925
+ var justifyStyles = {
3926
+ start: "justify-start",
3927
+ center: "justify-center",
3928
+ end: "justify-end",
3929
+ between: "justify-between",
3930
+ around: "justify-around",
3931
+ evenly: "justify-evenly"
3932
+ };
3933
+ var Stack = ({
3934
+ direction = "vertical",
3935
+ gap = "md",
3936
+ align = "stretch",
3937
+ justify = "start",
3938
+ wrap = false,
3939
+ reverse = false,
3940
+ flex = false,
3941
+ className,
3942
+ style,
3943
+ children,
3944
+ as: Component = "div",
3945
+ onClick,
3946
+ onKeyDown,
3947
+ role,
3948
+ tabIndex,
3949
+ action,
3950
+ actionPayload,
3951
+ responsive = false
3952
+ }) => {
3953
+ const eventBus = useEventBus();
3954
+ const handleClick = (e) => {
3955
+ if (action) {
3956
+ eventBus.emit(`UI:${action}`, actionPayload ?? {});
3957
+ }
3958
+ onClick?.(e);
3959
+ };
3960
+ const isHorizontal = direction === "horizontal";
3961
+ const directionClass = responsive && isHorizontal ? reverse ? "flex-col-reverse md:flex-row-reverse" : "flex-col md:flex-row" : isHorizontal ? reverse ? "flex-row-reverse" : "flex-row" : reverse ? "flex-col-reverse" : "flex-col";
3962
+ const Comp = Component;
3963
+ return /* @__PURE__ */ jsx(
3964
+ Comp,
3965
+ {
3966
+ className: cn(
3967
+ "flex",
3968
+ directionClass,
3969
+ gapStyles[gap],
3970
+ alignStyles[align],
3971
+ justifyStyles[justify],
3972
+ wrap && "flex-wrap",
3973
+ flex && "flex-1",
3974
+ className
3975
+ ),
3976
+ style,
3977
+ onClick: action || onClick ? handleClick : void 0,
3978
+ onKeyDown,
3979
+ role,
3980
+ tabIndex,
3981
+ children
3982
+ }
3983
+ );
3984
+ };
3985
+ var HStack = (props) => /* @__PURE__ */ jsx(Stack, { direction: "horizontal", ...props });
3986
+
3987
+ // components/molecules/avl/avl-layout.ts
3988
+ function ringPositions(cx, cy, r2, count, startAngle = -Math.PI / 2) {
3989
+ if (count === 0) return [];
3990
+ if (count === 1) {
3991
+ return [{ x: cx, y: cy, angle: 0 }];
3992
+ }
3993
+ if (count === 2) {
3994
+ return [
3995
+ { x: cx - r2 * 0.7, y: cy, angle: Math.PI },
3996
+ { x: cx + r2 * 0.7, y: cy, angle: 0 }
3997
+ ];
3998
+ }
3999
+ return Array.from({ length: count }, (_, i) => {
4000
+ const angle = startAngle + Math.PI * 2 * i / count;
4001
+ return {
4002
+ x: cx + r2 * Math.cos(angle),
4003
+ y: cy + r2 * Math.sin(angle),
4004
+ angle
4005
+ };
4006
+ });
4007
+ }
4008
+ function arcPath(cx, cy, r2, startAngle, endAngle) {
4009
+ const x1 = cx + r2 * Math.cos(startAngle);
4010
+ const y1 = cy + r2 * Math.sin(startAngle);
4011
+ const x2 = cx + r2 * Math.cos(endAngle);
4012
+ const y2 = cy + r2 * Math.sin(endAngle);
4013
+ const largeArc = endAngle - startAngle > Math.PI ? 1 : 0;
4014
+ return `M${x1},${y1} A${r2},${r2} 0 ${largeArc},1 ${x2},${y2}`;
4015
+ }
4016
+ function radialPositions(cx, cy, innerR, outerR, count, startAngle = -Math.PI / 2) {
4017
+ return Array.from({ length: count }, (_, i) => {
4018
+ const angle = startAngle + Math.PI * 2 * i / count;
4019
+ return {
4020
+ x1: cx + innerR * Math.cos(angle),
4021
+ y1: cy + innerR * Math.sin(angle),
4022
+ x2: cx + outerR * Math.cos(angle),
4023
+ y2: cy + outerR * Math.sin(angle),
4024
+ angle
4025
+ };
4026
+ });
4027
+ }
4028
+ function gridPositions(startX, startY, cols, cellWidth, cellHeight, count) {
4029
+ return Array.from({ length: count }, (_, i) => {
4030
+ const col = i % cols;
4031
+ const row = Math.floor(i / cols);
4032
+ return {
4033
+ x: startX + col * cellWidth,
4034
+ y: startY + row * cellHeight,
4035
+ col,
4036
+ row
4037
+ };
4038
+ });
4039
+ }
4040
+ function curveControlPoint(x1, y1, x2, y2, offset) {
4041
+ const mx = (x1 + x2) / 2;
4042
+ const my = (y1 + y2) / 2;
4043
+ const dx = x2 - x1;
4044
+ const dy = y2 - y1;
4045
+ const len = Math.sqrt(dx * dx + dy * dy) || 1;
4046
+ return {
4047
+ cpx: mx + -dy / len * offset,
4048
+ cpy: my + dx / len * offset
4049
+ };
4050
+ }
4051
+ var avlSmId = 0;
4052
+ var AvlStateMachine = ({
4053
+ states,
4054
+ transitions,
4055
+ className,
4056
+ color = "var(--color-primary)",
4057
+ animated = false
4058
+ }) => {
4059
+ const ids = React8.useMemo(() => {
4060
+ avlSmId += 1;
4061
+ const base = `avl-sm-${avlSmId}`;
4062
+ return { glow: `${base}-glow`, grad: `${base}-grad` };
4063
+ }, []);
4064
+ const cx = 300;
4065
+ const cy = 200;
4066
+ const r2 = 150;
4067
+ const stateWidth = 90;
4068
+ const stateHeight = 36;
4069
+ const positions = ringPositions(cx, cy, r2, states.length);
4070
+ const stateIndex = new Map(states.map((s, i) => [s.name, i]));
4071
+ const pairCount = /* @__PURE__ */ new Map();
4072
+ const pairSeen = /* @__PURE__ */ new Map();
4073
+ for (const tr of transitions) {
4074
+ const key = [tr.from, tr.to].sort().join("|");
4075
+ pairCount.set(key, (pairCount.get(key) ?? 0) + 1);
4076
+ }
4077
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
4078
+ /* @__PURE__ */ jsxs("defs", { children: [
4079
+ /* @__PURE__ */ jsxs("filter", { id: ids.glow, x: "-50%", y: "-50%", width: "200%", height: "200%", children: [
4080
+ /* @__PURE__ */ jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "3", result: "blur" }),
4081
+ /* @__PURE__ */ jsxs("feMerge", { children: [
4082
+ /* @__PURE__ */ jsx("feMergeNode", { in: "blur" }),
4083
+ /* @__PURE__ */ jsx("feMergeNode", { in: "SourceGraphic" })
4084
+ ] })
4085
+ ] }),
4086
+ /* @__PURE__ */ jsxs("linearGradient", { id: ids.grad, x1: "0%", y1: "0%", x2: "100%", y2: "100%", children: [
4087
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.1 }),
4088
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0.05 })
4089
+ ] })
4090
+ ] }),
4091
+ animated && /* @__PURE__ */ jsx("style", { children: `
4092
+ @keyframes avl-sm-dash { from { stroke-dashoffset: 20; } to { stroke-dashoffset: 0; } }
4093
+ ` }),
4094
+ /* @__PURE__ */ jsx("circle", { cx, cy, r: r2 + 30, fill: `url(#${ids.grad})` }),
4095
+ transitions.map((tr, i) => {
4096
+ if (tr.from !== tr.to) return null;
4097
+ const idx = stateIndex.get(tr.from);
4098
+ if (idx === void 0) return null;
4099
+ const pos = positions[idx];
4100
+ const loopR = 20;
4101
+ const loopY = pos.y - stateHeight / 2 - 4;
4102
+ const d = `M${pos.x - 14},${loopY} C${pos.x - 14},${loopY - loopR * 2} ${pos.x + 14},${loopY - loopR * 2} ${pos.x + 14},${loopY}`;
4103
+ return /* @__PURE__ */ jsxs("g", { children: [
4104
+ /* @__PURE__ */ jsx(
4105
+ "path",
4106
+ {
4107
+ d,
4108
+ fill: "none",
4109
+ stroke: color,
4110
+ strokeWidth: 1.5,
4111
+ opacity: 0.7,
4112
+ markerEnd: `url(#${ids.grad})`
4113
+ }
4114
+ ),
4115
+ tr.event && /* @__PURE__ */ jsx(
4116
+ "text",
4117
+ {
4118
+ x: pos.x,
4119
+ y: loopY - loopR * 2 + 4,
4120
+ textAnchor: "middle",
4121
+ fill: color,
4122
+ fontSize: 9,
4123
+ fontFamily: "inherit",
4124
+ fontWeight: "bold",
4125
+ opacity: 0.8,
4126
+ children: tr.event
4127
+ }
4128
+ )
4129
+ ] }, `self-${i}`);
4130
+ }),
4131
+ transitions.map((tr, i) => {
4132
+ if (tr.from === tr.to) return null;
4133
+ const fromIdx = stateIndex.get(tr.from);
4134
+ const toIdx = stateIndex.get(tr.to);
4135
+ if (fromIdx === void 0 || toIdx === void 0) return null;
4136
+ const fp = positions[fromIdx];
4137
+ const tp = positions[toIdx];
4138
+ const dx = tp.x - fp.x;
4139
+ const dy = tp.y - fp.y;
4140
+ const dist = Math.sqrt(dx * dx + dy * dy) || 1;
4141
+ const nx = dx / dist;
4142
+ const ny = dy / dist;
4143
+ const pairKey = [tr.from, tr.to].sort().join("|");
4144
+ const totalForPair = pairCount.get(pairKey) ?? 1;
4145
+ const seenIdx = pairSeen.get(pairKey) ?? 0;
4146
+ pairSeen.set(pairKey, seenIdx + 1);
4147
+ const pairOffset = totalForPair > 1 ? (seenIdx - (totalForPair - 1) / 2) * 24 : 0;
4148
+ const x1 = fp.x + nx * (stateWidth / 2 + 4);
4149
+ const y1 = fp.y + ny * (stateHeight / 2 + 4);
4150
+ const x2 = tp.x - nx * (stateWidth / 2 + 8);
4151
+ const y2 = tp.y - ny * (stateHeight / 2 + 8);
4152
+ const t = 0.3;
4153
+ const labelX = x1 * (1 - t) + x2 * t;
4154
+ const labelY = y1 * (1 - t) + y2 * t;
4155
+ const perpX = -ny * (20 + Math.abs(pairOffset));
4156
+ const perpY = nx * (20 + Math.abs(pairOffset));
4157
+ const midToCenter = Math.sqrt((labelX - cx) ** 2 + (labelY - cy) ** 2);
4158
+ const testX = labelX + perpX;
4159
+ const testY = labelY + perpY;
4160
+ const testToCenter = Math.sqrt((testX - cx) ** 2 + (testY - cy) ** 2);
4161
+ const outSign = testToCenter > midToCenter ? 1 : -1;
4162
+ const lx = labelX + perpX * outSign + -ny * pairOffset;
4163
+ const ly = labelY + perpY * outSign + nx * pairOffset;
4164
+ return /* @__PURE__ */ jsxs("g", { children: [
4165
+ /* @__PURE__ */ jsx(
4166
+ AvlTransition,
4167
+ {
4168
+ x1: x1 + -ny * pairOffset,
4169
+ y1: y1 + nx * pairOffset,
4170
+ x2: x2 + -ny * pairOffset,
4171
+ y2: y2 + nx * pairOffset,
4172
+ curved: states.length > 2,
4173
+ curveAwayFrom: { x: cx, y: cy },
4174
+ color,
4175
+ opacity: 0.7
4176
+ }
4177
+ ),
4178
+ tr.event && /* @__PURE__ */ jsx(
4179
+ "text",
4180
+ {
4181
+ x: lx,
4182
+ y: ly,
4183
+ textAnchor: "middle",
4184
+ fill: color,
4185
+ fontSize: 9,
4186
+ fontFamily: "inherit",
4187
+ fontWeight: "bold",
4188
+ opacity: 0.8,
4189
+ children: tr.event
4190
+ }
4191
+ ),
4192
+ tr.guard && /* @__PURE__ */ jsxs(
4193
+ "text",
4194
+ {
4195
+ x: lx,
4196
+ y: ly + 12,
4197
+ textAnchor: "middle",
4198
+ fill: color,
4199
+ fontSize: 8,
4200
+ fontFamily: "inherit",
4201
+ opacity: 0.6,
4202
+ children: [
4203
+ "[",
4204
+ tr.guard,
4205
+ "]"
4206
+ ]
4207
+ }
4208
+ ),
4209
+ tr.effects?.map((eff, j) => /* @__PURE__ */ jsx(
4210
+ AvlEffect,
4211
+ {
4212
+ x: lx + (j - ((tr.effects?.length ?? 1) - 1) / 2) * 14,
4213
+ y: ly + (tr.guard ? 22 : 12),
4214
+ effectType: eff,
4215
+ size: 5,
4216
+ color,
4217
+ opacity: 0.7
4218
+ },
4219
+ j
4220
+ ))
4221
+ ] }, `tr-${i}`);
4222
+ }),
4223
+ states.map((state, i) => {
4224
+ const pos = positions[i];
4225
+ return /* @__PURE__ */ jsx(
4226
+ AvlState,
4227
+ {
4228
+ x: pos.x - stateWidth / 2,
4229
+ y: pos.y - stateHeight / 2,
4230
+ width: stateWidth,
4231
+ height: stateHeight,
4232
+ name: state.name,
4233
+ isInitial: state.isInitial,
4234
+ isTerminal: state.isTerminal,
4235
+ color
4236
+ },
4237
+ state.name
4238
+ );
4239
+ })
4240
+ ] });
4241
+ };
4242
+ AvlStateMachine.displayName = "AvlStateMachine";
4243
+ var avlOuId = 0;
4244
+ var AvlOrbitalUnit = ({
4245
+ entityName,
4246
+ fields = 4,
4247
+ persistence = "persistent",
4248
+ traits,
4249
+ pages,
4250
+ className,
4251
+ color = "var(--color-primary)",
4252
+ animated = false
4253
+ }) => {
4254
+ const ids = React8.useMemo(() => {
4255
+ avlOuId += 1;
4256
+ const base = `avl-ou-${avlOuId}`;
4257
+ return { glow: `${base}-glow`, grad: `${base}-grad` };
4258
+ }, []);
4259
+ const cx = 300;
4260
+ const cy = 200;
4261
+ const entityR = 24;
4262
+ const orbitalR = 130;
4263
+ const traitBaseRx = 55;
4264
+ const traitBaseRy = 24;
4265
+ const traitRxStep = 20;
4266
+ const traitRyStep = 8;
4267
+ const traitAngleStep = traits.length > 1 ? 120 / (traits.length - 1) : 0;
4268
+ const traitAngleStart = traits.length > 1 ? -60 : 0;
4269
+ const pageAngleStart = -Math.PI / 3;
4270
+ const pageAngleStep = pages.length > 1 ? Math.PI * 0.8 / (pages.length - 1) : 0;
4271
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
4272
+ /* @__PURE__ */ jsxs("defs", { children: [
4273
+ /* @__PURE__ */ jsxs("filter", { id: ids.glow, x: "-50%", y: "-50%", width: "200%", height: "200%", children: [
4274
+ /* @__PURE__ */ jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "3", result: "blur" }),
4275
+ /* @__PURE__ */ jsxs("feMerge", { children: [
4276
+ /* @__PURE__ */ jsx("feMergeNode", { in: "blur" }),
4277
+ /* @__PURE__ */ jsx("feMergeNode", { in: "SourceGraphic" })
4278
+ ] })
4279
+ ] }),
4280
+ /* @__PURE__ */ jsxs("radialGradient", { id: ids.grad, cx: "50%", cy: "50%", r: "50%", children: [
4281
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.08 }),
4282
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0 })
4283
+ ] })
4284
+ ] }),
4285
+ animated && /* @__PURE__ */ jsx("style", { children: `
4286
+ @keyframes avl-ou-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
4287
+ ` }),
4288
+ /* @__PURE__ */ jsx("circle", { cx, cy, r: orbitalR + 20, fill: `url(#${ids.grad})` }),
4289
+ /* @__PURE__ */ jsx(AvlOrbital, { cx, cy, r: orbitalR, label: entityName, color }),
4290
+ traits.map((trait, i) => {
4291
+ const rotation = traitAngleStart + i * traitAngleStep;
4292
+ const traitColor = trait.color ?? color;
4293
+ return /* @__PURE__ */ jsx(
4294
+ AvlTrait,
4295
+ {
4296
+ cx,
4297
+ cy,
4298
+ rx: traitBaseRx + i * traitRxStep,
4299
+ ry: traitBaseRy + i * traitRyStep,
4300
+ rotation,
4301
+ label: trait.name,
4302
+ color: traitColor,
4303
+ opacity: 0.7
4304
+ },
4305
+ trait.name
4306
+ );
4307
+ }),
4308
+ /* @__PURE__ */ jsx(
4309
+ AvlEntity,
4310
+ {
4311
+ x: cx,
4312
+ y: cy,
4313
+ r: entityR,
4314
+ fieldCount: fields,
4315
+ persistence,
4316
+ color
4317
+ }
4318
+ ),
4319
+ pages.map((page, i) => {
4320
+ const angle = pageAngleStart + i * pageAngleStep;
4321
+ const px = cx + orbitalR * Math.cos(angle);
4322
+ const py = cy + orbitalR * Math.sin(angle);
4323
+ return /* @__PURE__ */ jsx(
4324
+ AvlPage,
4325
+ {
4326
+ x: px,
4327
+ y: py,
4328
+ size: 10,
4329
+ label: page.name,
4330
+ color
4331
+ },
4332
+ page.name
4333
+ );
4334
+ })
4335
+ ] });
4539
4336
  };
4540
- var positionStyles = {
4541
- relative: "relative",
4542
- absolute: "absolute",
4543
- fixed: "fixed",
4544
- sticky: "sticky"
4337
+ AvlOrbitalUnit.displayName = "AvlOrbitalUnit";
4338
+ var avlCcId = 0;
4339
+ var AvlClosedCircuit = ({
4340
+ states,
4341
+ transitions,
4342
+ className,
4343
+ color = "var(--color-primary)",
4344
+ animated = false
4345
+ }) => {
4346
+ const ids = React8.useMemo(() => {
4347
+ avlCcId += 1;
4348
+ const base = `avl-cc-${avlCcId}`;
4349
+ return { glow: `${base}-glow`, grad: `${base}-grad`, arrow: `${base}-arrow` };
4350
+ }, []);
4351
+ const cx = 300;
4352
+ const cy = 200;
4353
+ const r2 = 120;
4354
+ const stateW = 80;
4355
+ const stateH = 32;
4356
+ const positions = ringPositions(cx, cy, r2, states.length);
4357
+ const stateIndex = new Map(states.map((s, i) => [s.name, i]));
4358
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
4359
+ /* @__PURE__ */ jsxs("defs", { children: [
4360
+ /* @__PURE__ */ jsxs("filter", { id: ids.glow, x: "-50%", y: "-50%", width: "200%", height: "200%", children: [
4361
+ /* @__PURE__ */ jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "4", result: "blur" }),
4362
+ /* @__PURE__ */ jsxs("feMerge", { children: [
4363
+ /* @__PURE__ */ jsx("feMergeNode", { in: "blur" }),
4364
+ /* @__PURE__ */ jsx("feMergeNode", { in: "SourceGraphic" })
4365
+ ] })
4366
+ ] }),
4367
+ /* @__PURE__ */ jsxs("linearGradient", { id: ids.grad, x1: "0%", y1: "0%", x2: "100%", y2: "100%", children: [
4368
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.15 }),
4369
+ /* @__PURE__ */ jsx("stop", { offset: "50%", stopColor: color, stopOpacity: 0.4 }),
4370
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0.15 })
4371
+ ] }),
4372
+ /* @__PURE__ */ jsx(
4373
+ "marker",
4374
+ {
4375
+ id: ids.arrow,
4376
+ markerWidth: "8",
4377
+ markerHeight: "6",
4378
+ refX: "7",
4379
+ refY: "3",
4380
+ orient: "auto",
4381
+ markerUnits: "strokeWidth",
4382
+ children: /* @__PURE__ */ jsx("path", { d: "M0,0 L8,3 L0,6 Z", fill: color, opacity: 0.6 })
4383
+ }
4384
+ )
4385
+ ] }),
4386
+ animated && /* @__PURE__ */ jsx("style", { children: `
4387
+ @keyframes avl-cc-flow { from { stroke-dashoffset: 24; } to { stroke-dashoffset: 0; } }
4388
+ ` }),
4389
+ /* @__PURE__ */ jsx("circle", { cx, cy, r: r2 + 30, fill: "none", stroke: color, strokeWidth: 0.3, opacity: 0.06 }),
4390
+ /* @__PURE__ */ jsx("circle", { cx, cy, r: 50, fill: "none", stroke: color, strokeWidth: 0.5, opacity: 0.08 }),
4391
+ transitions.map((tr, i) => {
4392
+ const fromIdx = stateIndex.get(tr.from);
4393
+ const toIdx = stateIndex.get(tr.to);
4394
+ if (fromIdx === void 0 || toIdx === void 0) return null;
4395
+ const fp = positions[fromIdx];
4396
+ const tp = positions[toIdx];
4397
+ const dx = tp.x - fp.x;
4398
+ const dy = tp.y - fp.y;
4399
+ const dist = Math.sqrt(dx * dx + dy * dy) || 1;
4400
+ const nx = dx / dist;
4401
+ const ny = dy / dist;
4402
+ const x1 = fp.x + nx * (stateW / 2 + 4);
4403
+ const y1 = fp.y + ny * (stateH / 2 + 4);
4404
+ const x2 = tp.x - nx * (stateW / 2 + 8);
4405
+ const y2 = tp.y - ny * (stateH / 2 + 8);
4406
+ const mx = (x1 + x2) / 2;
4407
+ const my = (y1 + y2) / 2;
4408
+ const curvature = dist * 0.25;
4409
+ let perpX = -ny;
4410
+ let perpY = nx;
4411
+ const testX = mx + perpX * curvature;
4412
+ const testY = my + perpY * curvature;
4413
+ const distTest = Math.sqrt((testX - cx) ** 2 + (testY - cy) ** 2);
4414
+ const distMid = Math.sqrt((mx - cx) ** 2 + (my - cy) ** 2);
4415
+ if (distTest < distMid) {
4416
+ perpX = -perpX;
4417
+ perpY = -perpY;
4418
+ }
4419
+ const cpx = mx + perpX * curvature;
4420
+ const cpy = my + perpY * curvature;
4421
+ const d = `M${x1},${y1} Q${cpx},${cpy} ${x2},${y2}`;
4422
+ return /* @__PURE__ */ jsxs("g", { children: [
4423
+ /* @__PURE__ */ jsx(
4424
+ "path",
4425
+ {
4426
+ d,
4427
+ fill: "none",
4428
+ stroke: `url(#${ids.grad})`,
4429
+ strokeWidth: 1.5,
4430
+ strokeDasharray: animated ? "8 6" : void 0,
4431
+ markerEnd: `url(#${ids.arrow})`,
4432
+ style: animated ? { animation: "avl-cc-flow 1.5s linear infinite" } : void 0
4433
+ }
4434
+ ),
4435
+ tr.event && /* @__PURE__ */ jsx(
4436
+ AvlEvent,
4437
+ {
4438
+ x: cpx,
4439
+ y: cpy - 14,
4440
+ size: 8,
4441
+ label: tr.event,
4442
+ color,
4443
+ opacity: 0.8
4444
+ }
4445
+ ),
4446
+ tr.guard && /* @__PURE__ */ jsx(
4447
+ AvlGuard,
4448
+ {
4449
+ x: mx,
4450
+ y: my - 8,
4451
+ size: 10,
4452
+ label: tr.guard,
4453
+ color,
4454
+ opacity: 0.6
4455
+ }
4456
+ ),
4457
+ tr.effects?.map((eff, j) => /* @__PURE__ */ jsx(
4458
+ AvlEffect,
4459
+ {
4460
+ x: mx + (j - ((tr.effects?.length ?? 1) - 1) / 2) * 14,
4461
+ y: my + 14,
4462
+ effectType: eff,
4463
+ size: 5,
4464
+ color,
4465
+ opacity: 0.7
4466
+ },
4467
+ j
4468
+ ))
4469
+ ] }, `cc-tr-${i}`);
4470
+ }),
4471
+ states.map((state, i) => {
4472
+ const pos = positions[i];
4473
+ return /* @__PURE__ */ jsx(
4474
+ AvlState,
4475
+ {
4476
+ x: pos.x - stateW / 2,
4477
+ y: pos.y - stateH / 2,
4478
+ width: stateW,
4479
+ height: stateH,
4480
+ name: state.name,
4481
+ color
4482
+ },
4483
+ state.name
4484
+ );
4485
+ }),
4486
+ /* @__PURE__ */ jsx("circle", { cx, cy, r: 3, fill: color, opacity: 0.4 })
4487
+ ] });
4545
4488
  };
4546
- var Box = React6.forwardRef(
4547
- ({
4548
- padding,
4549
- paddingX,
4550
- paddingY,
4551
- margin,
4552
- marginX,
4553
- marginY,
4554
- bg = "transparent",
4555
- border = false,
4556
- rounded = "none",
4557
- shadow = "none",
4558
- display,
4559
- fullWidth = false,
4560
- fullHeight = false,
4561
- overflow,
4562
- position,
4563
- className,
4564
- children,
4565
- as: Component = "div",
4566
- action,
4567
- actionPayload,
4568
- hoverEvent,
4569
- onClick,
4570
- onMouseEnter,
4571
- onMouseLeave,
4572
- ...rest
4573
- }, ref) => {
4574
- const eventBus = useEventBus();
4575
- const handleClick = useCallback((e) => {
4576
- if (action) {
4577
- e.stopPropagation();
4578
- eventBus.emit(`UI:${action}`, actionPayload ?? {});
4489
+ AvlClosedCircuit.displayName = "AvlClosedCircuit";
4490
+ var avlElId = 0;
4491
+ var AvlEmitListen = ({
4492
+ emitter,
4493
+ listener,
4494
+ eventName,
4495
+ className,
4496
+ color = "var(--color-primary)",
4497
+ animated = false
4498
+ }) => {
4499
+ const ids = React8.useMemo(() => {
4500
+ avlElId += 1;
4501
+ const base = `avl-el-${avlElId}`;
4502
+ return { arrow: `${base}-arrow`, grad: `${base}-grad` };
4503
+ }, []);
4504
+ const leftCx = 180;
4505
+ const rightCx = 420;
4506
+ const cy = 200;
4507
+ const orbR = 80;
4508
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
4509
+ /* @__PURE__ */ jsxs("defs", { children: [
4510
+ /* @__PURE__ */ jsx(
4511
+ "marker",
4512
+ {
4513
+ id: ids.arrow,
4514
+ markerWidth: "8",
4515
+ markerHeight: "6",
4516
+ refX: "7",
4517
+ refY: "3",
4518
+ orient: "auto",
4519
+ markerUnits: "strokeWidth",
4520
+ children: /* @__PURE__ */ jsx("path", { d: "M0,0 L8,3 L0,6 Z", fill: color, opacity: 0.6 })
4521
+ }
4522
+ ),
4523
+ /* @__PURE__ */ jsxs("linearGradient", { id: ids.grad, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [
4524
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.5 }),
4525
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0.2 })
4526
+ ] })
4527
+ ] }),
4528
+ animated && /* @__PURE__ */ jsx("style", { children: `
4529
+ @keyframes avl-el-dash { from { stroke-dashoffset: 16; } to { stroke-dashoffset: 0; } }
4530
+ ` }),
4531
+ /* @__PURE__ */ jsx(AvlOrbital, { cx: leftCx, cy, r: orbR, label: emitter.name, color }),
4532
+ /* @__PURE__ */ jsx(AvlEntity, { x: leftCx, y: cy, r: 18, fieldCount: emitter.fields ?? 3, color }),
4533
+ /* @__PURE__ */ jsx(AvlOrbital, { cx: rightCx, cy, r: orbR, label: listener.name, color }),
4534
+ /* @__PURE__ */ jsx(AvlEntity, { x: rightCx, y: cy, r: 18, fieldCount: listener.fields ?? 3, color }),
4535
+ /* @__PURE__ */ jsx(
4536
+ "path",
4537
+ {
4538
+ d: `M${leftCx + orbR + 4},${cy} L${rightCx - orbR - 8},${cy}`,
4539
+ fill: "none",
4540
+ stroke: `url(#${ids.grad})`,
4541
+ strokeWidth: 2,
4542
+ strokeDasharray: "6 4",
4543
+ markerEnd: `url(#${ids.arrow})`,
4544
+ style: animated ? { animation: "avl-el-dash 1s linear infinite" } : void 0
4579
4545
  }
4580
- onClick?.(e);
4581
- }, [action, actionPayload, eventBus, onClick]);
4582
- const handleMouseEnter = useCallback((e) => {
4583
- if (hoverEvent) {
4584
- eventBus.emit(`UI:${hoverEvent}`, { hovered: true });
4546
+ ),
4547
+ /* @__PURE__ */ jsx(
4548
+ AvlEffect,
4549
+ {
4550
+ x: leftCx + orbR + 20,
4551
+ y: cy - 20,
4552
+ effectType: "emit",
4553
+ size: 6,
4554
+ color,
4555
+ opacity: 0.8
4585
4556
  }
4586
- onMouseEnter?.(e);
4587
- }, [hoverEvent, eventBus, onMouseEnter]);
4588
- const handleMouseLeave = useCallback((e) => {
4589
- if (hoverEvent) {
4590
- eventBus.emit(`UI:${hoverEvent}`, { hovered: false });
4557
+ ),
4558
+ eventName && /* @__PURE__ */ jsxs(
4559
+ "text",
4560
+ {
4561
+ x: 300,
4562
+ y: cy - 18,
4563
+ textAnchor: "middle",
4564
+ fill: color,
4565
+ fontSize: 11,
4566
+ fontFamily: "inherit",
4567
+ fontWeight: "bold",
4568
+ opacity: 0.8,
4569
+ children: [
4570
+ "~",
4571
+ eventName
4572
+ ]
4591
4573
  }
4592
- onMouseLeave?.(e);
4593
- }, [hoverEvent, eventBus, onMouseLeave]);
4594
- const isClickable = action || onClick;
4595
- const Comp = Component;
4596
- return /* @__PURE__ */ jsx(
4597
- Comp,
4574
+ ),
4575
+ /* @__PURE__ */ jsx(
4576
+ "text",
4598
4577
  {
4599
- ref,
4600
- className: cn(
4601
- // Padding
4602
- padding && paddingStyles[padding],
4603
- paddingX && paddingXStyles[paddingX],
4604
- paddingY && paddingYStyles[paddingY],
4605
- // Margin
4606
- margin && marginStyles[margin],
4607
- marginX && marginXStyles[marginX],
4608
- marginY && marginYStyles[marginY],
4609
- // Background
4610
- bgStyles[bg],
4611
- // Border - uses theme variables
4612
- border && "border-[length:var(--border-width)] border-[var(--color-border)]",
4613
- // Rounded
4614
- roundedStyles[rounded],
4615
- // Shadow
4616
- shadowStyles[shadow],
4617
- // Display
4618
- display && displayStyles[display],
4619
- // Dimensions
4620
- fullWidth && "w-full",
4621
- fullHeight && "h-full",
4622
- // Overflow
4623
- overflow && overflowStyles[overflow],
4624
- // Position
4625
- position && positionStyles[position],
4626
- // Cursor for clickable
4627
- isClickable && "cursor-pointer",
4628
- className
4629
- ),
4630
- onClick: isClickable ? handleClick : void 0,
4631
- onMouseEnter: hoverEvent || onMouseEnter ? handleMouseEnter : void 0,
4632
- onMouseLeave: hoverEvent || onMouseLeave ? handleMouseLeave : void 0,
4633
- ...rest,
4634
- children
4578
+ x: 300,
4579
+ y: cy + 18,
4580
+ textAnchor: "middle",
4581
+ fill: color,
4582
+ fontSize: 12,
4583
+ fontFamily: "inherit",
4584
+ opacity: 0.3,
4585
+ letterSpacing: 4,
4586
+ children: "~ ~ ~"
4635
4587
  }
4636
- );
4637
- }
4638
- );
4639
- Box.displayName = "Box";
4640
- var variantStyles = {
4641
- h1: "text-4xl font-bold tracking-tight text-[var(--color-foreground)]",
4642
- h2: "text-3xl font-bold tracking-tight text-[var(--color-foreground)]",
4643
- h3: "text-2xl font-bold text-[var(--color-foreground)]",
4644
- h4: "text-xl font-bold text-[var(--color-foreground)]",
4645
- h5: "text-lg font-bold text-[var(--color-foreground)]",
4646
- h6: "text-base font-bold text-[var(--color-foreground)]",
4647
- heading: "text-2xl font-bold text-[var(--color-foreground)]",
4648
- subheading: "text-lg font-semibold text-[var(--color-foreground)]",
4649
- body1: "text-base font-normal text-[var(--color-foreground)]",
4650
- body2: "text-sm font-normal text-[var(--color-foreground)]",
4651
- body: "text-base font-normal text-[var(--color-foreground)]",
4652
- caption: "text-xs font-normal text-[var(--color-muted-foreground)]",
4653
- overline: "text-xs uppercase tracking-wide font-bold text-[var(--color-muted-foreground)]",
4654
- small: "text-sm font-normal text-[var(--color-foreground)]",
4655
- large: "text-lg font-medium text-[var(--color-foreground)]",
4656
- label: "text-sm font-medium text-[var(--color-foreground)]"
4657
- };
4658
- var colorStyles = {
4659
- primary: "text-[var(--color-foreground)]",
4660
- secondary: "text-[var(--color-muted-foreground)]",
4661
- muted: "text-[var(--color-muted-foreground)]",
4662
- error: "text-[var(--color-error)]",
4663
- success: "text-[var(--color-success)]",
4664
- warning: "text-[var(--color-warning)]",
4665
- inherit: "text-inherit"
4666
- };
4667
- var weightStyles = {
4668
- light: "font-light",
4669
- normal: "font-normal",
4670
- medium: "font-medium",
4671
- semibold: "font-semibold",
4672
- bold: "font-bold"
4673
- };
4674
- var defaultElements = {
4675
- h1: "h1",
4676
- h2: "h2",
4677
- h3: "h3",
4678
- h4: "h4",
4679
- h5: "h5",
4680
- h6: "h6",
4681
- heading: "h2",
4682
- subheading: "h3",
4683
- body1: "p",
4684
- body2: "p",
4685
- body: "p",
4686
- caption: "span",
4687
- overline: "span",
4688
- small: "span",
4689
- large: "p",
4690
- label: "span"
4588
+ )
4589
+ ] });
4691
4590
  };
4692
- var typographySizeStyles = {
4693
- xs: "text-xs",
4694
- sm: "text-sm",
4695
- md: "text-base",
4696
- lg: "text-lg",
4697
- xl: "text-xl",
4698
- "2xl": "text-2xl",
4699
- "3xl": "text-3xl"
4591
+ AvlEmitListen.displayName = "AvlEmitListen";
4592
+ var SLOT_PRESETS = {
4593
+ header: { x: 10, y: 5, width: 340, height: 35 },
4594
+ main: { x: 120, y: 50, width: 230, height: 195 },
4595
+ sidebar: { x: 10, y: 50, width: 100, height: 195 },
4596
+ modal: { x: 80, y: 60, width: 200, height: 140 },
4597
+ drawer: { x: 220, y: 50, width: 130, height: 195 },
4598
+ toast: { x: 220, y: 210, width: 130, height: 35 },
4599
+ footer: { x: 10, y: 220, width: 340, height: 30 },
4600
+ center: { x: 60, y: 50, width: 240, height: 195 },
4601
+ "hud-top": { x: 10, y: 5, width: 340, height: 30 },
4602
+ "hud-bottom": { x: 10, y: 220, width: 340, height: 30 }
4700
4603
  };
4701
- var overflowStyles2 = {
4702
- visible: "overflow-visible",
4703
- hidden: "overflow-hidden",
4704
- wrap: "break-words overflow-hidden",
4705
- "clamp-2": "overflow-hidden line-clamp-2",
4706
- "clamp-3": "overflow-hidden line-clamp-3"
4604
+ function resolveSlot(slot, fallbackIdx) {
4605
+ if (slot.x !== void 0 && slot.y !== void 0 && slot.width !== void 0 && slot.height !== void 0) {
4606
+ return slot;
4607
+ }
4608
+ const preset = SLOT_PRESETS[slot.name];
4609
+ if (preset) {
4610
+ return {
4611
+ name: slot.name,
4612
+ x: slot.x ?? preset.x,
4613
+ y: slot.y ?? preset.y,
4614
+ width: slot.width ?? preset.width,
4615
+ height: slot.height ?? preset.height
4616
+ };
4617
+ }
4618
+ const col = fallbackIdx % 2;
4619
+ const row = Math.floor(fallbackIdx / 2);
4620
+ return {
4621
+ name: slot.name,
4622
+ x: 10 + col * 175,
4623
+ y: 50 + row * 100,
4624
+ width: 165,
4625
+ height: 90
4626
+ };
4627
+ }
4628
+ var AvlSlotMap = ({
4629
+ slots,
4630
+ pageWidth = 360,
4631
+ pageHeight = 280,
4632
+ className,
4633
+ color = "var(--color-primary)",
4634
+ animated = false
4635
+ }) => {
4636
+ const ox = (600 - pageWidth) / 2;
4637
+ const oy = (400 - pageHeight) / 2;
4638
+ let unknownIdx = 0;
4639
+ const resolvedSlots = slots.map((slot) => {
4640
+ const isUnknown = !SLOT_PRESETS[slot.name] && (slot.x === void 0 || slot.y === void 0);
4641
+ const resolved = resolveSlot(slot, isUnknown ? unknownIdx : 0);
4642
+ if (isUnknown) unknownIdx++;
4643
+ return resolved;
4644
+ });
4645
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
4646
+ animated && /* @__PURE__ */ jsx("style", { children: `
4647
+ @keyframes avl-slot-pulse { 0%, 100% { opacity: 0.15; } 50% { opacity: 0.25; } }
4648
+ ` }),
4649
+ /* @__PURE__ */ jsx(
4650
+ "rect",
4651
+ {
4652
+ x: ox,
4653
+ y: oy,
4654
+ width: pageWidth,
4655
+ height: pageHeight,
4656
+ rx: 4,
4657
+ ry: 4,
4658
+ fill: "none",
4659
+ stroke: color,
4660
+ strokeWidth: 2
4661
+ }
4662
+ ),
4663
+ /* @__PURE__ */ jsx(
4664
+ "rect",
4665
+ {
4666
+ x: ox,
4667
+ y: oy,
4668
+ width: pageWidth,
4669
+ height: 24,
4670
+ rx: 4,
4671
+ ry: 4,
4672
+ fill: color,
4673
+ opacity: 0.1
4674
+ }
4675
+ ),
4676
+ /* @__PURE__ */ jsx(
4677
+ "text",
4678
+ {
4679
+ x: ox + pageWidth / 2,
4680
+ y: oy + 16,
4681
+ textAnchor: "middle",
4682
+ fill: color,
4683
+ fontSize: 10,
4684
+ fontFamily: "inherit",
4685
+ fontWeight: "bold",
4686
+ children: "Page Layout"
4687
+ }
4688
+ ),
4689
+ resolvedSlots.map((slot) => {
4690
+ const isOverlay = ["modal", "drawer", "toast"].includes(slot.name);
4691
+ return /* @__PURE__ */ jsxs("g", { children: [
4692
+ isOverlay && /* @__PURE__ */ jsx(
4693
+ "rect",
4694
+ {
4695
+ x: ox + slot.x + 3,
4696
+ y: oy + 24 + slot.y + 3,
4697
+ width: slot.width,
4698
+ height: slot.height,
4699
+ rx: 3,
4700
+ ry: 3,
4701
+ fill: "black",
4702
+ opacity: 0.06
4703
+ }
4704
+ ),
4705
+ /* @__PURE__ */ jsx(
4706
+ "rect",
4707
+ {
4708
+ x: ox + slot.x,
4709
+ y: oy + 24 + slot.y,
4710
+ width: slot.width,
4711
+ height: slot.height,
4712
+ rx: 3,
4713
+ ry: 3,
4714
+ fill: isOverlay ? "var(--color-surface, #fff)" : color,
4715
+ opacity: isOverlay ? 0.9 : 0.08,
4716
+ stroke: color,
4717
+ strokeWidth: isOverlay ? 1.5 : 1,
4718
+ strokeDasharray: isOverlay ? "6 3" : "4 2",
4719
+ style: animated ? { animation: "avl-slot-pulse 2s ease-in-out infinite" } : void 0
4720
+ }
4721
+ ),
4722
+ /* @__PURE__ */ jsxs(
4723
+ "text",
4724
+ {
4725
+ x: ox + slot.x + slot.width / 2,
4726
+ y: oy + 24 + slot.y + slot.height / 2,
4727
+ textAnchor: "middle",
4728
+ dominantBaseline: "central",
4729
+ fill: color,
4730
+ fontSize: 9,
4731
+ fontFamily: "inherit",
4732
+ opacity: 0.6,
4733
+ children: [
4734
+ slot.name,
4735
+ isOverlay ? " (overlay)" : ""
4736
+ ]
4737
+ }
4738
+ )
4739
+ ] }, slot.name);
4740
+ })
4741
+ ] });
4707
4742
  };
4708
- var Typography = ({
4709
- variant: variantProp,
4710
- level,
4711
- color = "primary",
4712
- align,
4713
- weight,
4714
- size,
4715
- truncate = false,
4716
- overflow,
4717
- as,
4718
- id,
4719
- className,
4720
- style,
4721
- content,
4722
- children
4723
- }) => {
4724
- const variant = variantProp ?? (level ? `h${level}` : "body1");
4725
- const Component = as || defaultElements[variant];
4726
- const Comp = Component;
4727
- return /* @__PURE__ */ jsx(
4728
- Comp,
4729
- {
4730
- id,
4731
- className: cn(
4732
- variantStyles[variant],
4733
- colorStyles[color],
4734
- weight && weightStyles[weight],
4735
- size && typographySizeStyles[size],
4736
- align && `text-${align}`,
4737
- truncate && "truncate overflow-hidden text-ellipsis",
4738
- overflow && overflowStyles2[overflow],
4739
- className
4740
- ),
4741
- style,
4742
- children: children ?? content
4743
- }
4743
+ AvlSlotMap.displayName = "AvlSlotMap";
4744
+ var avlEtId = 0;
4745
+ function layoutTree(node, x, y, hSpacing, vSpacing) {
4746
+ const children = node.children ?? [];
4747
+ if (children.length === 0) {
4748
+ return { label: node.label, type: node.type, x, y, children: [] };
4749
+ }
4750
+ const totalWidth = (children.length - 1) * hSpacing;
4751
+ const startX = x - totalWidth / 2;
4752
+ const layoutChildren = children.map(
4753
+ (child, i) => layoutTree(child, startX + i * hSpacing, y + vSpacing, hSpacing * 0.75, vSpacing)
4744
4754
  );
4745
- };
4746
- Typography.displayName = "Typography";
4747
- var gapStyles = {
4748
- none: "gap-0",
4749
- xs: "gap-1",
4750
- sm: "gap-2",
4751
- md: "gap-4",
4752
- lg: "gap-6",
4753
- xl: "gap-8",
4754
- "2xl": "gap-12"
4755
- };
4756
- var alignStyles = {
4757
- start: "items-start",
4758
- center: "items-center",
4759
- end: "items-end",
4760
- stretch: "items-stretch",
4761
- baseline: "items-baseline"
4762
- };
4763
- var justifyStyles = {
4764
- start: "justify-start",
4765
- center: "justify-center",
4766
- end: "justify-end",
4767
- between: "justify-between",
4768
- around: "justify-around",
4769
- evenly: "justify-evenly"
4770
- };
4771
- var Stack = ({
4772
- direction = "vertical",
4773
- gap = "md",
4774
- align = "stretch",
4775
- justify = "start",
4776
- wrap = false,
4777
- reverse = false,
4778
- flex = false,
4755
+ return { label: node.label, type: node.type, x, y, children: layoutChildren };
4756
+ }
4757
+ function nodeColor(type, baseColor) {
4758
+ switch (type) {
4759
+ case "operator":
4760
+ return baseColor;
4761
+ case "literal":
4762
+ return baseColor;
4763
+ case "binding":
4764
+ return baseColor;
4765
+ }
4766
+ }
4767
+ function renderNode(node, color, glowId) {
4768
+ const labelLen = node.label.length;
4769
+ const baseR = node.type === "operator" ? 20 : 16;
4770
+ const r2 = Math.max(baseR, labelLen * 3.5 + 6);
4771
+ const nc = nodeColor(node.type, color);
4772
+ return /* @__PURE__ */ jsxs(React8.Fragment, { children: [
4773
+ node.children.map((child, i) => {
4774
+ const childR = Math.max(
4775
+ child.type === "operator" ? 20 : 16,
4776
+ child.label.length * 3.5 + 6
4777
+ );
4778
+ return /* @__PURE__ */ jsx(
4779
+ "line",
4780
+ {
4781
+ x1: node.x,
4782
+ y1: node.y + (node.type === "operator" ? r2 * 0.7 : r2),
4783
+ x2: child.x,
4784
+ y2: child.y - (child.type === "operator" ? childR * 0.7 : childR),
4785
+ stroke: color,
4786
+ strokeWidth: 1,
4787
+ opacity: 0.3
4788
+ },
4789
+ `line-${i}`
4790
+ );
4791
+ }),
4792
+ node.type === "operator" ? /* @__PURE__ */ jsx(
4793
+ "rect",
4794
+ {
4795
+ x: node.x - r2,
4796
+ y: node.y - r2 * 0.6,
4797
+ width: r2 * 2,
4798
+ height: r2 * 1.2,
4799
+ rx: 4,
4800
+ ry: 4,
4801
+ fill: color,
4802
+ fillOpacity: 0.15,
4803
+ stroke: nc,
4804
+ strokeWidth: 1.5
4805
+ }
4806
+ ) : node.type === "binding" ? /* @__PURE__ */ jsx("circle", { cx: node.x, cy: node.y, r: r2, fill: "none", stroke: nc, strokeWidth: 1.5, strokeDasharray: "3 2" }) : /* @__PURE__ */ jsx("circle", { cx: node.x, cy: node.y, r: r2, fill: "none", stroke: nc, strokeWidth: 1, opacity: 0.5 }),
4807
+ /* @__PURE__ */ jsx(
4808
+ "text",
4809
+ {
4810
+ x: node.x,
4811
+ y: node.y + 1,
4812
+ textAnchor: "middle",
4813
+ dominantBaseline: "central",
4814
+ fill: nc,
4815
+ fontSize: node.type === "operator" ? 11 : 10,
4816
+ fontFamily: "inherit",
4817
+ fontWeight: node.type === "operator" ? "bold" : "normal",
4818
+ children: node.type === "binding" ? `@${node.label}` : node.label
4819
+ }
4820
+ ),
4821
+ node.children.map((child) => renderNode(child, color))
4822
+ ] }, `${node.label}-${node.x}-${node.y}`);
4823
+ }
4824
+ var AvlExprTree = ({
4825
+ expression,
4779
4826
  className,
4780
- style,
4781
- children,
4782
- as: Component = "div",
4783
- onClick,
4784
- onKeyDown,
4785
- role,
4786
- tabIndex,
4787
- action,
4788
- actionPayload,
4789
- responsive = false
4827
+ color = "var(--color-primary)"
4790
4828
  }) => {
4791
- const eventBus = useEventBus();
4792
- const handleClick = (e) => {
4793
- if (action) {
4794
- eventBus.emit(`UI:${action}`, actionPayload ?? {});
4795
- }
4796
- onClick?.(e);
4797
- };
4798
- const isHorizontal = direction === "horizontal";
4799
- const directionClass = responsive && isHorizontal ? reverse ? "flex-col-reverse md:flex-row-reverse" : "flex-col md:flex-row" : isHorizontal ? reverse ? "flex-row-reverse" : "flex-row" : reverse ? "flex-col-reverse" : "flex-col";
4800
- const Comp = Component;
4801
- return /* @__PURE__ */ jsx(
4802
- Comp,
4803
- {
4804
- className: cn(
4805
- "flex",
4806
- directionClass,
4807
- gapStyles[gap],
4808
- alignStyles[align],
4809
- justifyStyles[justify],
4810
- wrap && "flex-wrap",
4811
- flex && "flex-1",
4812
- className
4813
- ),
4814
- style,
4815
- onClick: action || onClick ? handleClick : void 0,
4816
- onKeyDown,
4817
- role,
4818
- tabIndex,
4819
- children
4820
- }
4821
- );
4829
+ const ids = React8.useMemo(() => {
4830
+ avlEtId += 1;
4831
+ return { glow: `avl-et-${avlEtId}-glow` };
4832
+ }, []);
4833
+ const layout = layoutTree(expression, 300, 60, 200, 90);
4834
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 600 400", xmlns: "http://www.w3.org/2000/svg", className, children: [
4835
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("filter", { id: ids.glow, x: "-50%", y: "-50%", width: "200%", height: "200%", children: [
4836
+ /* @__PURE__ */ jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "2", result: "blur" }),
4837
+ /* @__PURE__ */ jsxs("feMerge", { children: [
4838
+ /* @__PURE__ */ jsx("feMergeNode", { in: "blur" }),
4839
+ /* @__PURE__ */ jsx("feMergeNode", { in: "SourceGraphic" })
4840
+ ] })
4841
+ ] }) }),
4842
+ renderNode(layout, color, ids.glow)
4843
+ ] });
4822
4844
  };
4823
- var HStack = (props) => /* @__PURE__ */ jsx(Stack, { direction: "horizontal", ...props });
4845
+ AvlExprTree.displayName = "AvlExprTree";
4824
4846
 
4825
4847
  // components/organisms/avl/avl-schema-parser.ts
4826
4848
  function getEntity(orbital) {
@@ -5164,6 +5186,14 @@ function zoomReducer(state, action) {
5164
5186
  }
5165
5187
  return state;
5166
5188
  }
5189
+ case "SWITCH_TRAIT": {
5190
+ if (state.level !== "trait" || state.animating) return state;
5191
+ return {
5192
+ ...state,
5193
+ selectedTrait: action.trait,
5194
+ selectedTransition: null
5195
+ };
5196
+ }
5167
5197
  case "RESET": {
5168
5198
  return initialZoomState;
5169
5199
  }
@@ -5371,12 +5401,15 @@ var AvlApplicationScene = ({
5371
5401
  AvlApplicationScene.displayName = "AvlApplicationScene";
5372
5402
  var CX = 300;
5373
5403
  var CY = 200;
5404
+ var VIEWBOX_H = 400;
5374
5405
  var ORBITAL_R2 = 130;
5375
5406
  var ENTITY_R2 = 24;
5376
5407
  var AvlOrbitalScene = ({
5377
5408
  data,
5378
5409
  color = "var(--color-primary)",
5379
- onTraitClick
5410
+ highlightedTrait,
5411
+ onTraitClick,
5412
+ onTraitHighlight
5380
5413
  }) => {
5381
5414
  const traitAngleStart = -Math.PI / 3;
5382
5415
  const traitAngleStep = data.traits.length > 1 ? Math.PI * 1.2 / (data.traits.length - 1) : 0;
@@ -5402,7 +5435,7 @@ var AvlOrbitalScene = ({
5402
5435
  rotation: rotationDeg,
5403
5436
  label: trait.name,
5404
5437
  color,
5405
- opacity: 0.7
5438
+ opacity: highlightedTrait ? highlightedTrait === trait.name ? 1 : 0.25 : 0.7
5406
5439
  }
5407
5440
  ),
5408
5441
  onTraitClick && /* @__PURE__ */ jsx(
@@ -5475,6 +5508,54 @@ var AvlOrbitalScene = ({
5475
5508
  const py = CY + (ORBITAL_R2 + 15) * Math.sin(angle);
5476
5509
  return /* @__PURE__ */ jsx(AvlPage, { x: px, y: py, label: page.route, color }, page.name);
5477
5510
  }),
5511
+ data.traits.length > 1 && /* @__PURE__ */ jsx("g", { children: data.traits.map((trait, i) => {
5512
+ const pillW = 70;
5513
+ const gap = 8;
5514
+ const totalW = data.traits.length * pillW + (data.traits.length - 1) * gap;
5515
+ const startX = CX - totalW / 2;
5516
+ const px = startX + i * (pillW + gap);
5517
+ const py = VIEWBOX_H - 30;
5518
+ const isHighlighted = highlightedTrait === trait.name;
5519
+ return /* @__PURE__ */ jsxs(
5520
+ "g",
5521
+ {
5522
+ style: { cursor: "pointer" },
5523
+ onClick: () => onTraitClick?.(trait.name, { x: CX, y: CY }),
5524
+ onMouseEnter: () => onTraitHighlight?.(trait.name),
5525
+ onMouseLeave: () => onTraitHighlight?.(null),
5526
+ children: [
5527
+ /* @__PURE__ */ jsx(
5528
+ "rect",
5529
+ {
5530
+ x: px,
5531
+ y: py,
5532
+ width: pillW,
5533
+ height: 22,
5534
+ rx: 11,
5535
+ fill: isHighlighted ? color : "transparent",
5536
+ stroke: color,
5537
+ strokeWidth: isHighlighted ? 1.5 : 0.8,
5538
+ opacity: isHighlighted ? 0.15 : 0.3
5539
+ }
5540
+ ),
5541
+ /* @__PURE__ */ jsx(
5542
+ "text",
5543
+ {
5544
+ x: px + pillW / 2,
5545
+ y: py + 14,
5546
+ textAnchor: "middle",
5547
+ fill: color,
5548
+ fontSize: 8,
5549
+ fontWeight: isHighlighted ? "bold" : "normal",
5550
+ opacity: isHighlighted ? 1 : 0.6,
5551
+ children: trait.name.length > 10 ? trait.name.slice(0, 9) + "\u2026" : trait.name
5552
+ }
5553
+ )
5554
+ ]
5555
+ },
5556
+ `tab-${trait.name}`
5557
+ );
5558
+ }) }),
5478
5559
  data.externalLinks.map((link, i) => {
5479
5560
  const isOut = link.direction === "out";
5480
5561
  const edgeX = isOut ? 580 : 20;
@@ -6140,7 +6221,7 @@ var AvlLegend = ({
6140
6221
  };
6141
6222
  AvlLegend.displayName = "AvlLegend";
6142
6223
  var VIEWBOX_W = 600;
6143
- var VIEWBOX_H = 400;
6224
+ var VIEWBOX_H2 = 400;
6144
6225
  var ANIMATION_DURATION = 600;
6145
6226
  var AvlCosmicZoom = ({
6146
6227
  schema: schemaProp,
@@ -6169,11 +6250,11 @@ var AvlCosmicZoom = ({
6169
6250
  const [transitionStyle, setTransitionStyle] = useState({});
6170
6251
  useEffect(() => {
6171
6252
  if (initialOrbital) {
6172
- dispatch({ type: "ZOOM_INTO_ORBITAL", orbital: initialOrbital, targetPosition: { x: VIEWBOX_W / 2, y: VIEWBOX_H / 2 } });
6253
+ dispatch({ type: "ZOOM_INTO_ORBITAL", orbital: initialOrbital, targetPosition: { x: VIEWBOX_W / 2, y: VIEWBOX_H2 / 2 } });
6173
6254
  setTimeout(() => dispatch({ type: "ANIMATION_COMPLETE" }), 0);
6174
6255
  if (initialTrait) {
6175
6256
  setTimeout(() => {
6176
- dispatch({ type: "ZOOM_INTO_TRAIT", trait: initialTrait, targetPosition: { x: VIEWBOX_W / 2, y: VIEWBOX_H / 2 } });
6257
+ dispatch({ type: "ZOOM_INTO_TRAIT", trait: initialTrait, targetPosition: { x: VIEWBOX_W / 2, y: VIEWBOX_H2 / 2 } });
6177
6258
  setTimeout(() => dispatch({ type: "ANIMATION_COMPLETE" }), 0);
6178
6259
  }, 10);
6179
6260
  }
@@ -6197,7 +6278,7 @@ var AvlCosmicZoom = ({
6197
6278
  if (!target) return;
6198
6279
  if (state.animationDirection === "in") {
6199
6280
  setTransitionStyle({
6200
- transform: `scale(${target.scale}) translate(${-(target.x - VIEWBOX_W / 2)}px, ${-(target.y - VIEWBOX_H / 2)}px)`,
6281
+ transform: `scale(${target.scale}) translate(${-(target.x - VIEWBOX_W / 2)}px, ${-(target.y - VIEWBOX_H2 / 2)}px)`,
6201
6282
  transformOrigin: `${target.x}px ${target.y}px`,
6202
6283
  transition: `transform ${ANIMATION_DURATION}ms cubic-bezier(0.4, 0, 0.2, 1), opacity ${ANIMATION_DURATION}ms ease`,
6203
6284
  opacity: 0.3
@@ -6227,6 +6308,10 @@ var AvlCosmicZoom = ({
6227
6308
  const handleTraitClick = useCallback((name, pos) => {
6228
6309
  dispatch({ type: "ZOOM_INTO_TRAIT", trait: name, targetPosition: pos });
6229
6310
  }, []);
6311
+ const handleTraitSwitch = useCallback((name) => {
6312
+ dispatch({ type: "SWITCH_TRAIT", trait: name });
6313
+ }, []);
6314
+ const [highlightedTrait, setHighlightedTrait] = React8.useState(null);
6230
6315
  const handleTransitionClick = useCallback((index, pos) => {
6231
6316
  dispatch({ type: "ZOOM_INTO_TRANSITION", transitionIndex: index, targetPosition: pos });
6232
6317
  }, []);
@@ -6260,7 +6345,9 @@ var AvlCosmicZoom = ({
6260
6345
  {
6261
6346
  data,
6262
6347
  color,
6263
- onTraitClick: handleTraitClick
6348
+ highlightedTrait,
6349
+ onTraitClick: handleTraitClick,
6350
+ onTraitHighlight: setHighlightedTrait
6264
6351
  }
6265
6352
  );
6266
6353
  }
@@ -6292,7 +6379,7 @@ var AvlCosmicZoom = ({
6292
6379
  default:
6293
6380
  return null;
6294
6381
  }
6295
- }, [state.level, state.selectedOrbital, state.selectedTrait, state.selectedTransition, schema, color, handleOrbitalClick, handleTraitClick, handleTransitionClick]);
6382
+ }, [state.level, state.selectedOrbital, state.selectedTrait, state.selectedTransition, schema, color, handleOrbitalClick, handleTraitClick, handleTransitionClick, highlightedTrait, setHighlightedTrait]);
6296
6383
  const breadcrumbs = getBreadcrumbs(state);
6297
6384
  return /* @__PURE__ */ jsxs(
6298
6385
  Box,
@@ -6308,7 +6395,7 @@ var AvlCosmicZoom = ({
6308
6395
  gap: "xs",
6309
6396
  align: "center",
6310
6397
  className: "absolute top-2 left-2 z-10 bg-[var(--color-surface)]/80 backdrop-blur rounded-md px-3 py-1.5",
6311
- children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxs(React6.Fragment, { children: [
6398
+ children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxs(React8.Fragment, { children: [
6312
6399
  i > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", className: "mx-1", children: "/" }),
6313
6400
  i < breadcrumbs.length - 1 ? /* @__PURE__ */ jsx(
6314
6401
  Box,
@@ -6322,6 +6409,28 @@ var AvlCosmicZoom = ({
6322
6409
  ] }, crumb.level))
6323
6410
  }
6324
6411
  ),
6412
+ state.level === "trait" && state.selectedOrbital && (() => {
6413
+ const orbData = parseOrbitalLevel(schema, state.selectedOrbital);
6414
+ if (!orbData || orbData.traits.length <= 1) return null;
6415
+ return /* @__PURE__ */ jsx(
6416
+ HStack,
6417
+ {
6418
+ gap: "xs",
6419
+ align: "center",
6420
+ className: "absolute top-2 right-2 z-10 bg-[var(--color-surface)]/80 backdrop-blur rounded-md px-1.5 py-1",
6421
+ children: orbData.traits.map((t) => /* @__PURE__ */ jsx(
6422
+ Box,
6423
+ {
6424
+ as: "button",
6425
+ className: `px-2.5 py-1 rounded-md text-xs font-medium transition-all cursor-pointer border-none ${t.name === state.selectedTrait ? "bg-[var(--color-primary)] text-[var(--color-primary-foreground)]" : "bg-transparent text-[var(--color-muted-foreground)] hover:text-[var(--color-foreground)] hover:bg-[var(--color-surface)]"}`,
6426
+ onClick: () => handleTraitSwitch(t.name),
6427
+ children: t.name
6428
+ },
6429
+ t.name
6430
+ ))
6431
+ }
6432
+ );
6433
+ })(),
6325
6434
  state.level !== "application" && /* @__PURE__ */ jsx(
6326
6435
  Typography,
6327
6436
  {
@@ -6334,7 +6443,7 @@ var AvlCosmicZoom = ({
6334
6443
  /* @__PURE__ */ jsxs(
6335
6444
  "svg",
6336
6445
  {
6337
- viewBox: `0 0 ${VIEWBOX_W} ${VIEWBOX_H}`,
6446
+ viewBox: `0 0 ${VIEWBOX_W} ${VIEWBOX_H2}`,
6338
6447
  xmlns: "http://www.w3.org/2000/svg",
6339
6448
  className: "w-full h-full",
6340
6449
  role: "img",