@almadar/ui 2.20.1 → 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 (39) hide show
  1. package/LICENSE +72 -21
  2. package/dist/avl/index.cjs +1345 -1323
  3. package/dist/avl/index.d.cts +47 -47
  4. package/dist/avl/index.js +1321 -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/avl-3d-context.d.ts +32 -0
  24. package/dist/components/organisms/avl/avl-3d-layout.d.ts +116 -0
  25. package/dist/components/organisms/game/three/index.cjs +2549 -120
  26. package/dist/components/organisms/game/three/index.d.ts +8 -0
  27. package/dist/components/organisms/game/three/index.js +2419 -5
  28. package/dist/illustrations/index.cjs +2880 -109
  29. package/dist/illustrations/index.js +2879 -108
  30. package/dist/providers/OrbitalProvider.d.ts +4 -2
  31. package/dist/providers/index.cjs +263 -284
  32. package/dist/providers/index.js +189 -210
  33. package/dist/runtime/OrbPreview.d.ts +9 -6
  34. package/dist/runtime/ServerBridge.d.ts +23 -0
  35. package/dist/runtime/enrichFromResponse.d.ts +21 -0
  36. package/dist/runtime/index.cjs +31754 -2587
  37. package/dist/runtime/index.d.ts +2 -0
  38. package/dist/runtime/index.js +31735 -2571
  39. package/package.json +5 -2
@@ -1,8 +1,9 @@
1
- import React7, { forwardRef, useRef, useEffect, useImperativeHandle, useState, useMemo, useCallback, Component, useContext } from 'react';
1
+ import React21, { forwardRef, useRef, useEffect, useImperativeHandle, useState, useMemo, useCallback, createContext, Component, useContext, useReducer } from 'react';
2
2
  import { useThree, useFrame, Canvas } from '@react-three/fiber';
3
3
  import * as THREE6 from 'three';
4
+ import { Vector3, QuadraticBezierCurve3, MathUtils, Quaternion } from 'three';
4
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
- import { OrbitControls, Grid } from '@react-three/drei';
6
+ import { OrbitControls, Grid, Stars, Sparkles, Html, RoundedBox } from '@react-three/drei';
6
7
  import { GLTFLoader as GLTFLoader$1 } from 'three/examples/jsm/loaders/GLTFLoader';
7
8
  import { OrbitControls as OrbitControls$1 } from 'three/examples/jsm/controls/OrbitControls.js';
8
9
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
@@ -10,6 +11,7 @@ import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
10
11
  import { EventBusContext } from '@almadar/ui/providers';
11
12
  import { clsx } from 'clsx';
12
13
  import { twMerge } from 'tailwind-merge';
14
+ import { EffectComposer, Bloom, DepthOfField, Vignette } from '@react-three/postprocessing';
13
15
 
14
16
  var __defProp = Object.defineProperty;
15
17
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -1816,7 +1818,7 @@ function UnitRenderer({
1816
1818
  onAnimationStateChange,
1817
1819
  animationSpeed = 1
1818
1820
  }) {
1819
- const handleUnitClick = React7.useCallback(
1821
+ const handleUnitClick = React21.useCallback(
1820
1822
  (unit) => {
1821
1823
  onUnitClick?.(unit);
1822
1824
  },
@@ -2795,7 +2797,7 @@ var positionStyles = {
2795
2797
  fixed: "fixed",
2796
2798
  sticky: "sticky"
2797
2799
  };
2798
- var Box = React7.forwardRef(
2800
+ var Box = React21.forwardRef(
2799
2801
  ({
2800
2802
  padding,
2801
2803
  paddingX,
@@ -3339,6 +3341,2418 @@ function normalizeMouseCoordinates(clientX, clientY, element) {
3339
3341
  y: -((clientY - rect.top) / rect.height) * 2 + 1
3340
3342
  };
3341
3343
  }
3344
+
3345
+ // components/organisms/avl/avl-schema-parser.ts
3346
+ function getEntity(orbital) {
3347
+ const entity = orbital.entity;
3348
+ if (typeof entity === "string") {
3349
+ return { name: entity, fields: [], persistence: "runtime" };
3350
+ }
3351
+ const e = entity;
3352
+ return {
3353
+ name: e.name ?? orbital.name,
3354
+ fields: e.fields ?? [],
3355
+ persistence: e.persistence ?? "runtime"
3356
+ };
3357
+ }
3358
+ function getTraits(orbital) {
3359
+ if (!orbital.traits) return [];
3360
+ return orbital.traits.map((t) => {
3361
+ if (typeof t === "string") return { name: t };
3362
+ return t;
3363
+ });
3364
+ }
3365
+ function getPages(orbital) {
3366
+ if (!orbital.pages) return [];
3367
+ return orbital.pages.map((p) => {
3368
+ if (typeof p === "string") return { name: p, path: `/${p.toLowerCase()}` };
3369
+ return p;
3370
+ });
3371
+ }
3372
+ function getStateMachine(trait) {
3373
+ return trait.stateMachine ?? null;
3374
+ }
3375
+ function getStates(sm) {
3376
+ return sm.states ?? [];
3377
+ }
3378
+ function getTransitions(sm) {
3379
+ return sm.transitions ?? [];
3380
+ }
3381
+ function getEvents(sm) {
3382
+ return sm.events ?? [];
3383
+ }
3384
+ function getEmits(trait) {
3385
+ const emits = trait.emits;
3386
+ if (!emits) return [];
3387
+ return emits.map((e) => typeof e === "string" ? e : e.event ?? e.name ?? "");
3388
+ }
3389
+ function getListens(trait) {
3390
+ const listens = trait.listens;
3391
+ if (!listens) return [];
3392
+ return listens.map((l) => typeof l === "string" ? l : l.event ?? "");
3393
+ }
3394
+ function parseEffectType(effect) {
3395
+ if (Array.isArray(effect)) {
3396
+ const [type, ...args] = effect;
3397
+ return { type: String(type), args };
3398
+ }
3399
+ return { type: "unknown", args: [] };
3400
+ }
3401
+ function exprToTree(expr) {
3402
+ if (Array.isArray(expr)) {
3403
+ const [op, ...args] = expr;
3404
+ return {
3405
+ label: String(op),
3406
+ type: "operator",
3407
+ children: args.map((a) => exprToTree(a))
3408
+ };
3409
+ }
3410
+ if (typeof expr === "string") {
3411
+ if (expr.startsWith("@")) {
3412
+ return { label: expr, type: "binding" };
3413
+ }
3414
+ return { label: expr, type: "literal" };
3415
+ }
3416
+ return { label: String(expr), type: "literal" };
3417
+ }
3418
+ function parseApplicationLevel(schema) {
3419
+ const orbitals = [];
3420
+ const crossLinks = [];
3421
+ const count = schema.orbitals.length;
3422
+ const cols = Math.ceil(Math.sqrt(count));
3423
+ const rows = Math.ceil(count / cols);
3424
+ const spacing = 200;
3425
+ const gridW = cols * spacing;
3426
+ const gridH = rows * spacing;
3427
+ const originX = (600 - gridW) / 2 + spacing / 2;
3428
+ const originY = (400 - gridH) / 2 + spacing / 2;
3429
+ schema.orbitals.forEach((orbital, i) => {
3430
+ const entity = getEntity(orbital);
3431
+ const traits = getTraits(orbital);
3432
+ const pages = getPages(orbital);
3433
+ orbitals.push({
3434
+ name: orbital.name,
3435
+ entityName: entity.name,
3436
+ fieldCount: entity.fields.length,
3437
+ persistence: entity.persistence,
3438
+ traitNames: traits.map((t) => t.name ?? ""),
3439
+ pageNames: pages.map((p) => p.name ?? ""),
3440
+ position: {
3441
+ x: originX + i % cols * spacing,
3442
+ y: originY + Math.floor(i / cols) * spacing
3443
+ }
3444
+ });
3445
+ });
3446
+ const emitMap = [];
3447
+ const listenMap = [];
3448
+ for (const orbital of schema.orbitals) {
3449
+ for (const traitRef of getTraits(orbital)) {
3450
+ const traitName = traitRef.name ?? "";
3451
+ for (const event of getEmits(traitRef)) {
3452
+ emitMap.push({ orbital: orbital.name, trait: traitName, event });
3453
+ }
3454
+ for (const event of getListens(traitRef)) {
3455
+ listenMap.push({ orbital: orbital.name, trait: traitName, event });
3456
+ }
3457
+ }
3458
+ }
3459
+ for (const emit of emitMap) {
3460
+ for (const listen of listenMap) {
3461
+ if (emit.event === listen.event && emit.orbital !== listen.orbital) {
3462
+ crossLinks.push({
3463
+ emitterOrbital: emit.orbital,
3464
+ listenerOrbital: listen.orbital,
3465
+ eventName: emit.event,
3466
+ emitterTrait: emit.trait,
3467
+ listenerTrait: listen.trait
3468
+ });
3469
+ }
3470
+ }
3471
+ }
3472
+ return { orbitals, crossLinks };
3473
+ }
3474
+ function parseOrbitalLevel(schema, orbitalName) {
3475
+ const orbital = schema.orbitals.find((o) => o.name === orbitalName);
3476
+ if (!orbital) return null;
3477
+ const entity = getEntity(orbital);
3478
+ const traits = getTraits(orbital);
3479
+ const pages = getPages(orbital);
3480
+ const fields = entity.fields.map((f) => ({
3481
+ name: f.name ?? "",
3482
+ type: f.type ?? "string",
3483
+ required: f.required ?? false,
3484
+ hasDefault: f.default !== void 0
3485
+ }));
3486
+ const traitInfos = traits.map((t) => {
3487
+ const sm = getStateMachine(t);
3488
+ return {
3489
+ name: t.name ?? "",
3490
+ stateCount: sm ? getStates(sm).length : 0,
3491
+ eventCount: sm ? getEvents(sm).length : 0,
3492
+ transitionCount: sm ? getTransitions(sm).length : 0,
3493
+ emits: getEmits(t),
3494
+ listens: getListens(t)
3495
+ };
3496
+ });
3497
+ const pageInfos = pages.map((p) => ({
3498
+ name: p.name ?? "",
3499
+ route: p.path ?? `/${(p.name ?? "").toLowerCase()}`
3500
+ }));
3501
+ const externalLinks = [];
3502
+ const thisTraitEmits = traits.flatMap((t) => getEmits(t).map((e) => ({ trait: t.name ?? "", event: e })));
3503
+ const thisTraitListens = traits.flatMap((t) => getListens(t).map((e) => ({ trait: t.name ?? "", event: e })));
3504
+ for (const other of schema.orbitals) {
3505
+ if (other.name === orbitalName) continue;
3506
+ const otherTraits = getTraits(other);
3507
+ const otherListens = otherTraits.flatMap((t) => getListens(t));
3508
+ const otherEmits = otherTraits.flatMap((t) => getEmits(t));
3509
+ for (const emit of thisTraitEmits) {
3510
+ if (otherListens.includes(emit.event)) {
3511
+ externalLinks.push({
3512
+ targetOrbital: other.name,
3513
+ eventName: emit.event,
3514
+ direction: "out",
3515
+ traitName: emit.trait
3516
+ });
3517
+ }
3518
+ }
3519
+ for (const listen of thisTraitListens) {
3520
+ if (otherEmits.includes(listen.event)) {
3521
+ externalLinks.push({
3522
+ targetOrbital: other.name,
3523
+ eventName: listen.event,
3524
+ direction: "in",
3525
+ traitName: listen.trait
3526
+ });
3527
+ }
3528
+ }
3529
+ }
3530
+ return {
3531
+ name: orbital.name,
3532
+ entity: {
3533
+ name: entity.name,
3534
+ fields,
3535
+ persistence: entity.persistence
3536
+ },
3537
+ traits: traitInfos,
3538
+ pages: pageInfos,
3539
+ externalLinks
3540
+ };
3541
+ }
3542
+ function parseTraitLevel(schema, orbitalName, traitName) {
3543
+ const orbital = schema.orbitals.find((o) => o.name === orbitalName);
3544
+ if (!orbital) return null;
3545
+ const traits = getTraits(orbital);
3546
+ const trait = traits.find((t) => t.name === traitName);
3547
+ if (!trait) return null;
3548
+ const sm = getStateMachine(trait);
3549
+ if (!sm) return null;
3550
+ const states = getStates(sm).map((s) => ({
3551
+ name: s.name ?? "",
3552
+ isInitial: s.isInitial ?? false,
3553
+ isTerminal: s.isTerminal ?? false
3554
+ }));
3555
+ const transitions = getTransitions(sm).map((t, i) => ({
3556
+ from: t.from ?? "",
3557
+ to: t.to ?? "",
3558
+ event: t.event ?? "",
3559
+ guard: t.guard,
3560
+ effects: (t.effects ?? []).map(parseEffectType),
3561
+ index: i
3562
+ }));
3563
+ const entity = getEntity(orbital);
3564
+ return {
3565
+ name: traitName,
3566
+ linkedEntity: entity.name,
3567
+ states,
3568
+ transitions,
3569
+ emittedEvents: getEmits(trait),
3570
+ listenedEvents: getListens(trait)
3571
+ };
3572
+ }
3573
+ function parseTransitionLevel(schema, orbitalName, traitName, transitionIndex) {
3574
+ const traitData = parseTraitLevel(schema, orbitalName, traitName);
3575
+ if (!traitData) return null;
3576
+ const transition = traitData.transitions[transitionIndex];
3577
+ if (!transition) return null;
3578
+ const guard = transition.guard ? exprToTree(transition.guard) : null;
3579
+ const effects = transition.effects.map(
3580
+ (e) => exprToTree([e.type, ...e.args])
3581
+ );
3582
+ const slotTargets = transition.effects.filter((e) => e.type === "render-ui").map((e) => ({
3583
+ name: String(e.args[0] ?? "main"),
3584
+ pattern: typeof e.args[1] === "object" && e.args[1] !== null ? e.args[1].type ?? "unknown" : String(e.args[1] ?? "unknown")
3585
+ }));
3586
+ return {
3587
+ from: transition.from,
3588
+ to: transition.to,
3589
+ event: transition.event,
3590
+ guard,
3591
+ effects,
3592
+ slotTargets
3593
+ };
3594
+ }
3595
+
3596
+ // components/organisms/avl/avl-zoom-state.ts
3597
+ var initialZoomState = {
3598
+ level: "application",
3599
+ selectedOrbital: null,
3600
+ selectedTrait: null,
3601
+ selectedTransition: null,
3602
+ animating: false,
3603
+ animationDirection: "in",
3604
+ animationTarget: null
3605
+ };
3606
+ function zoomReducer(state, action) {
3607
+ switch (action.type) {
3608
+ case "ZOOM_INTO_ORBITAL": {
3609
+ if (state.level !== "application" || state.animating) return state;
3610
+ return {
3611
+ ...state,
3612
+ animating: true,
3613
+ animationDirection: "in",
3614
+ animationTarget: { x: action.targetPosition.x, y: action.targetPosition.y, scale: 3 },
3615
+ selectedOrbital: action.orbital
3616
+ };
3617
+ }
3618
+ case "ZOOM_INTO_TRAIT": {
3619
+ if (state.level !== "orbital" || state.animating) return state;
3620
+ return {
3621
+ ...state,
3622
+ animating: true,
3623
+ animationDirection: "in",
3624
+ animationTarget: { x: action.targetPosition.x, y: action.targetPosition.y, scale: 3 },
3625
+ selectedTrait: action.trait
3626
+ };
3627
+ }
3628
+ case "ZOOM_INTO_TRANSITION": {
3629
+ if (state.level !== "trait" || state.animating) return state;
3630
+ return {
3631
+ ...state,
3632
+ animating: true,
3633
+ animationDirection: "in",
3634
+ animationTarget: { x: action.targetPosition.x, y: action.targetPosition.y, scale: 3 },
3635
+ selectedTransition: action.transitionIndex
3636
+ };
3637
+ }
3638
+ case "ZOOM_OUT": {
3639
+ if (state.level === "application" || state.animating) return state;
3640
+ return {
3641
+ ...state,
3642
+ animating: true,
3643
+ animationDirection: "out",
3644
+ animationTarget: { x: 300, y: 200, scale: 0.3 }
3645
+ };
3646
+ }
3647
+ case "ANIMATION_COMPLETE": {
3648
+ if (!state.animating) return state;
3649
+ if (state.animationDirection === "in") {
3650
+ const nextLevel = state.level === "application" ? "orbital" : state.level === "orbital" ? "trait" : "transition";
3651
+ return {
3652
+ ...state,
3653
+ level: nextLevel,
3654
+ animating: false,
3655
+ animationTarget: null
3656
+ };
3657
+ }
3658
+ if (state.level === "transition") {
3659
+ return {
3660
+ ...state,
3661
+ level: "trait",
3662
+ selectedTransition: null,
3663
+ animating: false,
3664
+ animationTarget: null
3665
+ };
3666
+ }
3667
+ if (state.level === "trait") {
3668
+ return {
3669
+ ...state,
3670
+ level: "orbital",
3671
+ selectedTrait: null,
3672
+ animating: false,
3673
+ animationTarget: null
3674
+ };
3675
+ }
3676
+ if (state.level === "orbital") {
3677
+ return {
3678
+ ...state,
3679
+ level: "application",
3680
+ selectedOrbital: null,
3681
+ animating: false,
3682
+ animationTarget: null
3683
+ };
3684
+ }
3685
+ return state;
3686
+ }
3687
+ case "SWITCH_TRAIT": {
3688
+ if (state.level !== "trait" || state.animating) return state;
3689
+ return {
3690
+ ...state,
3691
+ selectedTrait: action.trait,
3692
+ selectedTransition: null
3693
+ };
3694
+ }
3695
+ case "RESET": {
3696
+ return initialZoomState;
3697
+ }
3698
+ default:
3699
+ return state;
3700
+ }
3701
+ }
3702
+ function getBreadcrumbs(state) {
3703
+ const crumbs = [{ label: "Application", level: "application" }];
3704
+ if (state.selectedOrbital) {
3705
+ crumbs.push({ label: state.selectedOrbital, level: "orbital" });
3706
+ }
3707
+ if (state.selectedTrait) {
3708
+ crumbs.push({ label: state.selectedTrait, level: "trait" });
3709
+ }
3710
+ if (state.selectedTransition !== null) {
3711
+ crumbs.push({ label: `Transition #${state.selectedTransition}`, level: "transition" });
3712
+ }
3713
+ return crumbs;
3714
+ }
3715
+ var AVL_3D_COLORS = {
3716
+ // Orbital node: deep indigo body with soft cyan-blue rim glow
3717
+ orbitalSphere: "#161b2e",
3718
+ orbitalRim: "#5b9bd5",
3719
+ // Entity core: warm amber-gold (slightly desaturated for dark bg)
3720
+ entityCore: "#f0c040",
3721
+ entityCoreGlow: "#ffd866",
3722
+ // Trait orbit ring
3723
+ traitOrbit: "#5b9bd5",
3724
+ traitOrbitHighlight: "#7ab8f5",
3725
+ // State nodes
3726
+ stateIdle: "#1e2a3a",
3727
+ stateEdge: "#5b9bd5",
3728
+ stateActive: "#4ecb71",
3729
+ // Transitions: warm copper-orange
3730
+ transitionArc: "#e0944a",
3731
+ transitionArcHover: "#f0a860",
3732
+ // Guards
3733
+ guardPass: "#4ecb71",
3734
+ guardFail: "#f06060",
3735
+ // Cross-orbital wires: soft lavender
3736
+ crossWire: "#a78bda",
3737
+ crossWireGlow: "#c4a8f0",
3738
+ // Page portals: soft teal
3739
+ pagePortal: "#40c8aa",
3740
+ // Background: deep navy with blue undertone (not pure black)
3741
+ background: "#0c1222",
3742
+ backgroundSurface: "#111a2e",
3743
+ // Fog: matches background for seamless fade
3744
+ fog: "#0c1222",
3745
+ // Sparkle/particle accent
3746
+ sparkle: "#7ab8f5",
3747
+ sparkleWarm: "#f0c040"
3748
+ };
3749
+ var GOLDEN_ANGLE = Math.PI * (3 - Math.sqrt(5));
3750
+ function goldenSpiralPositions(count, baseRadius) {
3751
+ if (count === 0) return [];
3752
+ if (count === 1) return [{ x: 0, y: 0, z: 0 }];
3753
+ const positions = [];
3754
+ for (let i = 0; i < count; i++) {
3755
+ const angle = i * GOLDEN_ANGLE;
3756
+ const r = baseRadius * Math.sqrt(i / count);
3757
+ positions.push({
3758
+ x: r * Math.cos(angle),
3759
+ y: 0,
3760
+ z: r * Math.sin(angle)
3761
+ });
3762
+ }
3763
+ return positions;
3764
+ }
3765
+ function forceDirectedPositions(count, edges, baseRadius, iterations = 80) {
3766
+ if (count === 0) return [];
3767
+ if (count === 1) return [{ x: 0, y: 0, z: 0 }];
3768
+ const positions = goldenSpiralPositions(count, baseRadius);
3769
+ const repulsionStrength = baseRadius * baseRadius * 0.5;
3770
+ const attractionStrength = 0.15;
3771
+ const damping = 0.85;
3772
+ const velocities = positions.map(() => ({ x: 0, y: 0, z: 0 }));
3773
+ for (let iter = 0; iter < iterations; iter++) {
3774
+ for (let i = 0; i < count; i++) {
3775
+ for (let j = i + 1; j < count; j++) {
3776
+ const dx = positions[i].x - positions[j].x;
3777
+ const dz = positions[i].z - positions[j].z;
3778
+ const distSq = dx * dx + dz * dz + 0.01;
3779
+ const force = repulsionStrength / distSq;
3780
+ const dist = Math.sqrt(distSq);
3781
+ const fx = dx / dist * force;
3782
+ const fz = dz / dist * force;
3783
+ velocities[i].x += fx;
3784
+ velocities[i].z += fz;
3785
+ velocities[j].x -= fx;
3786
+ velocities[j].z -= fz;
3787
+ }
3788
+ }
3789
+ for (const edge of edges) {
3790
+ const dx = positions[edge.to].x - positions[edge.from].x;
3791
+ const dz = positions[edge.to].z - positions[edge.from].z;
3792
+ const dist = Math.sqrt(dx * dx + dz * dz + 0.01);
3793
+ const force = dist * attractionStrength;
3794
+ const fx = dx / dist * force;
3795
+ const fz = dz / dist * force;
3796
+ velocities[edge.from].x += fx;
3797
+ velocities[edge.from].z += fz;
3798
+ velocities[edge.to].x -= fx;
3799
+ velocities[edge.to].z -= fz;
3800
+ }
3801
+ for (let i = 0; i < count; i++) {
3802
+ positions[i].x += velocities[i].x * 0.1;
3803
+ positions[i].z += velocities[i].z * 0.1;
3804
+ velocities[i].x *= damping;
3805
+ velocities[i].z *= damping;
3806
+ }
3807
+ }
3808
+ let cx = 0, cz = 0;
3809
+ for (const p of positions) {
3810
+ cx += p.x;
3811
+ cz += p.z;
3812
+ }
3813
+ cx /= count;
3814
+ cz /= count;
3815
+ for (const p of positions) {
3816
+ p.x -= cx;
3817
+ p.z -= cz;
3818
+ }
3819
+ return positions;
3820
+ }
3821
+ function fibonacciSpherePositions(count, radius) {
3822
+ if (count === 0) return [];
3823
+ if (count === 1) return [{ x: 0, y: 0, z: 0 }];
3824
+ const positions = [];
3825
+ for (let i = 0; i < count; i++) {
3826
+ const y = 1 - 2 * i / (count - 1);
3827
+ const radiusAtY = Math.sqrt(1 - y * y);
3828
+ const theta = GOLDEN_ANGLE * i;
3829
+ positions.push({
3830
+ x: radius * radiusAtY * Math.cos(theta),
3831
+ y: radius * y,
3832
+ z: radius * radiusAtY * Math.sin(theta)
3833
+ });
3834
+ }
3835
+ return positions;
3836
+ }
3837
+ function orbitRingPositions(count, radius, tilt) {
3838
+ if (count === 0) return [];
3839
+ const positions = [];
3840
+ const step = 2 * Math.PI / count;
3841
+ for (let i = 0; i < count; i++) {
3842
+ const angle = i * step;
3843
+ const x = radius * Math.cos(angle);
3844
+ const flatZ = radius * Math.sin(angle);
3845
+ const y = flatZ * Math.sin(tilt);
3846
+ const z = flatZ * Math.cos(tilt);
3847
+ positions.push({ x, y, z });
3848
+ }
3849
+ return positions;
3850
+ }
3851
+ function arcCurve3D(from, to, offset) {
3852
+ const start = new Vector3(...from);
3853
+ const end = new Vector3(...to);
3854
+ const mid = new Vector3().addVectors(start, end).multiplyScalar(0.5);
3855
+ const dir = new Vector3().subVectors(end, start).normalize();
3856
+ const up = new Vector3(0, 1, 0);
3857
+ const perp = new Vector3().crossVectors(dir, up).normalize();
3858
+ if (perp.length() < 1e-3) {
3859
+ perp.crossVectors(dir, new Vector3(1, 0, 0)).normalize();
3860
+ }
3861
+ const control = mid.clone().add(perp.multiplyScalar(offset));
3862
+ control.y += Math.abs(offset) * 0.3;
3863
+ return new QuadraticBezierCurve3(start, control, end);
3864
+ }
3865
+ function selfLoopCurve3D(position, loopRadius) {
3866
+ const base = new Vector3(...position);
3867
+ const start = base.clone().add(new Vector3(-loopRadius * 0.3, 0, 0));
3868
+ const end = base.clone().add(new Vector3(loopRadius * 0.3, 0, 0));
3869
+ const control = base.clone().add(new Vector3(0, loopRadius, 0));
3870
+ return new QuadraticBezierCurve3(start, control, end);
3871
+ }
3872
+ function treeLayout3D(node, origin, horizontalSpacing, verticalSpacing = 2) {
3873
+ const results = [];
3874
+ function layoutNode(n, pos, depth) {
3875
+ results.push({ node: n, position: pos });
3876
+ if (!n.children || n.children.length === 0) return;
3877
+ const childCount = n.children.length;
3878
+ const totalWidth = (childCount - 1) * horizontalSpacing / (depth + 1);
3879
+ const startX = pos.x - totalWidth / 2;
3880
+ for (let i = 0; i < childCount; i++) {
3881
+ const childPos = {
3882
+ x: startX + i * totalWidth / Math.max(childCount - 1, 1),
3883
+ y: pos.y - verticalSpacing,
3884
+ z: pos.z
3885
+ };
3886
+ layoutNode(n.children[i], childPos, depth + 1);
3887
+ }
3888
+ }
3889
+ layoutNode(node, origin, 0);
3890
+ return results;
3891
+ }
3892
+ var CAMERA_POSITIONS = {
3893
+ application: { position: [0, 20, 30], target: [0, 0, 0] },
3894
+ orbital: { position: [0, 8, 12], target: [0, 0, 0] },
3895
+ trait: { position: [0, 6, 10], target: [0, 0, 0] },
3896
+ transition: { position: [0, 4, 8], target: [0, 0, 0] }
3897
+ };
3898
+ var Avl3DLabel = ({
3899
+ position,
3900
+ text,
3901
+ color = "#ffffff",
3902
+ fontSize = 12,
3903
+ className,
3904
+ occlude = false
3905
+ }) => {
3906
+ return /* @__PURE__ */ jsx(
3907
+ Html,
3908
+ {
3909
+ position,
3910
+ center: true,
3911
+ distanceFactor: 10,
3912
+ occlude: occlude ? "blending" : void 0,
3913
+ className,
3914
+ style: { pointerEvents: "none" },
3915
+ children: /* @__PURE__ */ jsx(
3916
+ Typography,
3917
+ {
3918
+ variant: "small",
3919
+ style: {
3920
+ color,
3921
+ fontSize: `${fontSize}px`,
3922
+ whiteSpace: "nowrap",
3923
+ textShadow: "0 0 4px rgba(0,0,0,0.8)",
3924
+ userSelect: "none"
3925
+ },
3926
+ children: text
3927
+ }
3928
+ )
3929
+ }
3930
+ );
3931
+ };
3932
+ Avl3DLabel.displayName = "Avl3DLabel";
3933
+ var Avl3DTooltip = ({
3934
+ position,
3935
+ title,
3936
+ rows,
3937
+ accentColor = "#5b9bd5"
3938
+ }) => {
3939
+ return /* @__PURE__ */ jsx(
3940
+ Html,
3941
+ {
3942
+ position,
3943
+ center: true,
3944
+ distanceFactor: 8,
3945
+ style: { pointerEvents: "none" },
3946
+ zIndexRange: [100, 0],
3947
+ children: /* @__PURE__ */ jsx(
3948
+ Box,
3949
+ {
3950
+ style: {
3951
+ background: "rgba(12, 18, 34, 0.92)",
3952
+ backdropFilter: "blur(8px)",
3953
+ borderLeft: `3px solid ${accentColor}`,
3954
+ borderRadius: "6px",
3955
+ padding: "8px 12px",
3956
+ minWidth: "140px",
3957
+ maxWidth: "220px",
3958
+ boxShadow: "0 4px 20px rgba(0,0,0,0.4)"
3959
+ },
3960
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
3961
+ /* @__PURE__ */ jsx(
3962
+ Typography,
3963
+ {
3964
+ variant: "small",
3965
+ style: {
3966
+ color: "#ffffff",
3967
+ fontWeight: 600,
3968
+ fontSize: "12px",
3969
+ lineHeight: 1.3
3970
+ },
3971
+ children: title
3972
+ }
3973
+ ),
3974
+ rows.map((row) => /* @__PURE__ */ jsxs(
3975
+ Box,
3976
+ {
3977
+ style: {
3978
+ display: "flex",
3979
+ justifyContent: "space-between",
3980
+ gap: "12px"
3981
+ },
3982
+ children: [
3983
+ /* @__PURE__ */ jsx(
3984
+ Typography,
3985
+ {
3986
+ variant: "small",
3987
+ style: {
3988
+ color: "#8899bb",
3989
+ fontSize: "10px",
3990
+ whiteSpace: "nowrap"
3991
+ },
3992
+ children: row.label
3993
+ }
3994
+ ),
3995
+ /* @__PURE__ */ jsx(
3996
+ Typography,
3997
+ {
3998
+ variant: "small",
3999
+ style: {
4000
+ color: "#ccddf0",
4001
+ fontSize: "10px",
4002
+ fontWeight: 500,
4003
+ textAlign: "right"
4004
+ },
4005
+ children: row.value
4006
+ }
4007
+ )
4008
+ ]
4009
+ },
4010
+ row.label
4011
+ ))
4012
+ ] })
4013
+ }
4014
+ )
4015
+ }
4016
+ );
4017
+ };
4018
+ Avl3DTooltip.displayName = "Avl3DTooltip";
4019
+ var Avl3DOrbitalNode = ({
4020
+ name,
4021
+ entityName,
4022
+ traitCount,
4023
+ pageCount = 0,
4024
+ persistence = "persistent",
4025
+ position,
4026
+ onClick
4027
+ }) => {
4028
+ const groupRef = useRef(null);
4029
+ const [hovered, setHovered] = useState(false);
4030
+ const scale = useMemo(() => 0.6 + Math.min(traitCount, 8) * 0.3, [traitCount]);
4031
+ const currentScale = useRef(scale);
4032
+ const targetScale = hovered ? scale * 1.06 : scale;
4033
+ useFrame((_, delta) => {
4034
+ if (!groupRef.current) return;
4035
+ groupRef.current.rotation.y += delta * (hovered ? 0.4 : 0.2);
4036
+ groupRef.current.rotation.x += delta * 0.05;
4037
+ currentScale.current = MathUtils.damp(currentScale.current, targetScale, 6, delta);
4038
+ });
4039
+ const baseBrightness = 0.3 + Math.min(pageCount, 5) * 0.05;
4040
+ const emissiveIntensity = hovered ? 0.8 : baseBrightness;
4041
+ return /* @__PURE__ */ jsxs("group", { position, children: [
4042
+ /* @__PURE__ */ jsxs("mesh", { scale: scale * 1.3, children: [
4043
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [1, 16, 16] }),
4044
+ /* @__PURE__ */ jsx(
4045
+ "meshStandardMaterial",
4046
+ {
4047
+ color: AVL_3D_COLORS.orbitalRim,
4048
+ emissive: AVL_3D_COLORS.orbitalRim,
4049
+ emissiveIntensity: hovered ? 0.2 : 0.06,
4050
+ transparent: true,
4051
+ opacity: hovered ? 0.08 : 0.03,
4052
+ depthWrite: false
4053
+ }
4054
+ )
4055
+ ] }),
4056
+ /* @__PURE__ */ jsxs("group", { ref: groupRef, children: [
4057
+ /* @__PURE__ */ jsxs(
4058
+ "mesh",
4059
+ {
4060
+ onClick: (e) => {
4061
+ e.stopPropagation();
4062
+ onClick?.();
4063
+ },
4064
+ onPointerOver: (e) => {
4065
+ e.stopPropagation();
4066
+ setHovered(true);
4067
+ document.body.style.cursor = "pointer";
4068
+ },
4069
+ onPointerOut: () => {
4070
+ setHovered(false);
4071
+ document.body.style.cursor = "auto";
4072
+ },
4073
+ scale: currentScale.current,
4074
+ rotation: [Math.PI / 4, 0, 0],
4075
+ children: [
4076
+ /* @__PURE__ */ jsx("torusGeometry", { args: [1, 0.18, 24, 64] }),
4077
+ /* @__PURE__ */ jsx(
4078
+ "meshStandardMaterial",
4079
+ {
4080
+ color: AVL_3D_COLORS.orbitalSphere,
4081
+ emissive: AVL_3D_COLORS.orbitalRim,
4082
+ emissiveIntensity,
4083
+ roughness: 0.2,
4084
+ metalness: 0.7
4085
+ }
4086
+ )
4087
+ ]
4088
+ }
4089
+ ),
4090
+ /* @__PURE__ */ jsxs(
4091
+ "mesh",
4092
+ {
4093
+ scale: scale * 0.9,
4094
+ rotation: [Math.PI / 2 + 0.3, Math.PI / 5, 0],
4095
+ children: [
4096
+ /* @__PURE__ */ jsx("torusGeometry", { args: [1, 0.06, 12, 64] }),
4097
+ /* @__PURE__ */ jsx(
4098
+ "meshStandardMaterial",
4099
+ {
4100
+ color: AVL_3D_COLORS.traitOrbit,
4101
+ emissive: AVL_3D_COLORS.traitOrbit,
4102
+ emissiveIntensity: 0.25,
4103
+ transparent: true,
4104
+ opacity: 0.4
4105
+ }
4106
+ )
4107
+ ]
4108
+ }
4109
+ )
4110
+ ] }),
4111
+ /* @__PURE__ */ jsxs("mesh", { scale: scale * 0.25, children: [
4112
+ /* @__PURE__ */ jsx("icosahedronGeometry", { args: [1, 1] }),
4113
+ /* @__PURE__ */ jsx(
4114
+ "meshStandardMaterial",
4115
+ {
4116
+ color: AVL_3D_COLORS.entityCore,
4117
+ emissive: AVL_3D_COLORS.entityCoreGlow,
4118
+ emissiveIntensity: 2,
4119
+ roughness: 0.1
4120
+ }
4121
+ )
4122
+ ] }),
4123
+ /* @__PURE__ */ jsx(
4124
+ "pointLight",
4125
+ {
4126
+ color: AVL_3D_COLORS.entityCoreGlow,
4127
+ intensity: 0.5,
4128
+ distance: 3,
4129
+ decay: 2
4130
+ }
4131
+ ),
4132
+ /* @__PURE__ */ jsx(
4133
+ Avl3DLabel,
4134
+ {
4135
+ position: [0, scale + 0.6, 0],
4136
+ text: name,
4137
+ color: "#ffffff",
4138
+ fontSize: hovered ? 14 : 12
4139
+ }
4140
+ ),
4141
+ /* @__PURE__ */ jsx(
4142
+ Avl3DLabel,
4143
+ {
4144
+ position: [0, -(scale + 0.4), 0],
4145
+ text: entityName,
4146
+ color: "#999999",
4147
+ fontSize: 10
4148
+ }
4149
+ ),
4150
+ hovered && /* @__PURE__ */ jsx(
4151
+ Avl3DTooltip,
4152
+ {
4153
+ position: [scale + 1.2, 0.3, 0],
4154
+ title: name,
4155
+ accentColor: AVL_3D_COLORS.orbitalRim,
4156
+ rows: [
4157
+ { label: "Entity", value: entityName },
4158
+ { label: "Persistence", value: persistence },
4159
+ { label: "Traits", value: String(traitCount) },
4160
+ { label: "Pages", value: String(pageCount) }
4161
+ ]
4162
+ }
4163
+ )
4164
+ ] });
4165
+ };
4166
+ Avl3DOrbitalNode.displayName = "Avl3DOrbitalNode";
4167
+ var Avl3DCrossWire = ({
4168
+ from,
4169
+ to,
4170
+ eventName,
4171
+ color = AVL_3D_COLORS.crossWire
4172
+ }) => {
4173
+ const { tubeArgs, midpoint } = useMemo(() => {
4174
+ const curve = arcCurve3D(from, to, 2);
4175
+ const mid = curve.getPoint(0.5);
4176
+ return {
4177
+ tubeArgs: [curve, 32, 0.03, 8, false],
4178
+ midpoint: [mid.x, mid.y, mid.z]
4179
+ };
4180
+ }, [from, to]);
4181
+ return /* @__PURE__ */ jsxs("group", { children: [
4182
+ /* @__PURE__ */ jsxs("mesh", { children: [
4183
+ /* @__PURE__ */ jsx("tubeGeometry", { args: [...tubeArgs] }),
4184
+ /* @__PURE__ */ jsx(
4185
+ "meshStandardMaterial",
4186
+ {
4187
+ color,
4188
+ emissive: color,
4189
+ emissiveIntensity: 0.4,
4190
+ transparent: true,
4191
+ opacity: 0.6,
4192
+ roughness: 0.5
4193
+ }
4194
+ )
4195
+ ] }),
4196
+ /* @__PURE__ */ jsx(
4197
+ Avl3DLabel,
4198
+ {
4199
+ position: midpoint,
4200
+ text: eventName,
4201
+ color,
4202
+ fontSize: 9
4203
+ }
4204
+ )
4205
+ ] });
4206
+ };
4207
+ Avl3DCrossWire.displayName = "Avl3DCrossWire";
4208
+ var Avl3DApplicationScene = ({
4209
+ data,
4210
+ onOrbitalClick
4211
+ }) => {
4212
+ const groupRef = useRef(null);
4213
+ const [, setHoverTrigger] = useState(0);
4214
+ const orbitalPositions = useMemo(() => {
4215
+ const baseRadius = Math.max(4, data.orbitals.length * 1.5);
4216
+ if (data.crossLinks.length === 0) {
4217
+ return goldenSpiralPositions(data.orbitals.length, baseRadius);
4218
+ }
4219
+ const nameToIdx = /* @__PURE__ */ new Map();
4220
+ data.orbitals.forEach((o, i) => nameToIdx.set(o.name, i));
4221
+ const edges = data.crossLinks.map((link) => ({
4222
+ from: nameToIdx.get(link.emitterOrbital) ?? -1,
4223
+ to: nameToIdx.get(link.listenerOrbital) ?? -1
4224
+ })).filter((e) => e.from >= 0 && e.to >= 0);
4225
+ return forceDirectedPositions(data.orbitals.length, edges, baseRadius);
4226
+ }, [data.orbitals, data.crossLinks]);
4227
+ const positionByName = useMemo(() => {
4228
+ const map = /* @__PURE__ */ new Map();
4229
+ data.orbitals.forEach((orb, i) => {
4230
+ const pos = orbitalPositions[i];
4231
+ map.set(orb.name, [pos.x, pos.y, pos.z]);
4232
+ });
4233
+ return map;
4234
+ }, [data.orbitals, orbitalPositions]);
4235
+ useFrame((_, delta) => {
4236
+ if (!groupRef.current) return;
4237
+ groupRef.current.rotation.y += delta * 0.03;
4238
+ });
4239
+ return /* @__PURE__ */ jsxs("group", { ref: groupRef, children: [
4240
+ data.orbitals.map((orbital, i) => {
4241
+ const pos = orbitalPositions[i];
4242
+ return /* @__PURE__ */ jsx(
4243
+ Avl3DOrbitalNode,
4244
+ {
4245
+ name: orbital.name,
4246
+ entityName: orbital.entityName,
4247
+ traitCount: orbital.traitNames.length,
4248
+ pageCount: orbital.pageNames.length,
4249
+ persistence: orbital.persistence,
4250
+ position: [pos.x, pos.y, pos.z],
4251
+ onClick: () => {
4252
+ onOrbitalClick?.(orbital.name);
4253
+ setHoverTrigger((v) => v + 1);
4254
+ }
4255
+ },
4256
+ orbital.name
4257
+ );
4258
+ }),
4259
+ data.crossLinks.map((link, i) => {
4260
+ const fromPos = positionByName.get(link.emitterOrbital);
4261
+ const toPos = positionByName.get(link.listenerOrbital);
4262
+ if (!fromPos || !toPos) return null;
4263
+ return /* @__PURE__ */ jsx(
4264
+ Avl3DCrossWire,
4265
+ {
4266
+ from: fromPos,
4267
+ to: toPos,
4268
+ eventName: link.eventName
4269
+ },
4270
+ `${link.emitterOrbital}-${link.eventName}-${link.listenerOrbital}-${i}`
4271
+ );
4272
+ })
4273
+ ] });
4274
+ };
4275
+ Avl3DApplicationScene.displayName = "Avl3DApplicationScene";
4276
+ function fieldPositions(count, radius) {
4277
+ const positions = [];
4278
+ const goldenAngle = Math.PI * (3 - Math.sqrt(5));
4279
+ for (let i = 0; i < Math.min(count, 12); i++) {
4280
+ const y = 1 - 2 * i / Math.max(count - 1, 1);
4281
+ const r = Math.sqrt(1 - y * y);
4282
+ const theta = goldenAngle * i;
4283
+ positions.push([
4284
+ radius * r * Math.cos(theta),
4285
+ radius * y,
4286
+ radius * r * Math.sin(theta)
4287
+ ]);
4288
+ }
4289
+ return positions;
4290
+ }
4291
+ function persistenceColor(persistence) {
4292
+ switch (persistence) {
4293
+ case "persistent":
4294
+ return "#4A90D9";
4295
+ case "runtime":
4296
+ return "#27AE60";
4297
+ case "singleton":
4298
+ return "#E8913A";
4299
+ default:
4300
+ return "#999999";
4301
+ }
4302
+ }
4303
+ var Avl3DEntityCore = ({
4304
+ name,
4305
+ fieldCount,
4306
+ persistence,
4307
+ position,
4308
+ fields
4309
+ }) => {
4310
+ const coreRef = useRef(null);
4311
+ useFrame((_, delta) => {
4312
+ if (!coreRef.current) return;
4313
+ coreRef.current.rotation.y += delta * 0.3;
4314
+ coreRef.current.rotation.x += delta * 0.1;
4315
+ });
4316
+ const fieldPos = fieldPositions(fieldCount, 1.4);
4317
+ const pColor = persistenceColor(persistence);
4318
+ return /* @__PURE__ */ jsxs("group", { position, children: [
4319
+ /* @__PURE__ */ jsxs("mesh", { ref: coreRef, children: [
4320
+ /* @__PURE__ */ jsx("icosahedronGeometry", { args: [1, 2] }),
4321
+ /* @__PURE__ */ jsx(
4322
+ "meshStandardMaterial",
4323
+ {
4324
+ color: AVL_3D_COLORS.entityCore,
4325
+ emissive: AVL_3D_COLORS.entityCoreGlow,
4326
+ emissiveIntensity: 2,
4327
+ roughness: 0.15,
4328
+ metalness: 0.85
4329
+ }
4330
+ )
4331
+ ] }),
4332
+ /* @__PURE__ */ jsxs("mesh", { scale: 1.2, children: [
4333
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [1, 24, 24] }),
4334
+ /* @__PURE__ */ jsx(
4335
+ "meshStandardMaterial",
4336
+ {
4337
+ color: AVL_3D_COLORS.entityCoreGlow,
4338
+ emissive: AVL_3D_COLORS.entityCoreGlow,
4339
+ emissiveIntensity: 0.6,
4340
+ transparent: true,
4341
+ opacity: 0.1,
4342
+ depthWrite: false
4343
+ }
4344
+ )
4345
+ ] }),
4346
+ /* @__PURE__ */ jsxs("mesh", { scale: 1.6, children: [
4347
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [1, 16, 16] }),
4348
+ /* @__PURE__ */ jsx(
4349
+ "meshStandardMaterial",
4350
+ {
4351
+ color: AVL_3D_COLORS.entityCore,
4352
+ emissive: AVL_3D_COLORS.entityCore,
4353
+ emissiveIntensity: 0.2,
4354
+ transparent: true,
4355
+ opacity: 0.04,
4356
+ depthWrite: false
4357
+ }
4358
+ )
4359
+ ] }),
4360
+ /* @__PURE__ */ jsx(
4361
+ "pointLight",
4362
+ {
4363
+ color: AVL_3D_COLORS.entityCoreGlow,
4364
+ intensity: 2.5,
4365
+ distance: 10,
4366
+ decay: 2
4367
+ }
4368
+ ),
4369
+ fieldPos.map((pos, i) => {
4370
+ const fieldType = fields?.[i];
4371
+ return /* @__PURE__ */ jsxs("mesh", { position: pos, scale: 0.08, rotation: [Math.PI / 6, Math.PI / 4, 0], children: [
4372
+ fieldType === "number" ? /* @__PURE__ */ jsx("tetrahedronGeometry", { args: [1, 0] }) : fieldType === "boolean" ? /* @__PURE__ */ jsx("boxGeometry", { args: [1.2, 1.2, 1.2] }) : fieldType === "date" ? /* @__PURE__ */ jsx("octahedronGeometry", { args: [1, 0] }) : fieldType === "enum" ? /* @__PURE__ */ jsx("torusGeometry", { args: [0.8, 0.3, 6, 12] }) : fieldType === "object" ? /* @__PURE__ */ jsx("dodecahedronGeometry", { args: [1, 0] }) : fieldType === "array" ? /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.8, 0.8, 1.5, 6] }) : (
4373
+ // string (default): sphere
4374
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [1, 8, 8] })
4375
+ ),
4376
+ /* @__PURE__ */ jsx(
4377
+ "meshStandardMaterial",
4378
+ {
4379
+ color: "#ffffff",
4380
+ emissive: "#ffffff",
4381
+ emissiveIntensity: 0.8,
4382
+ transparent: true,
4383
+ opacity: 0.7
4384
+ }
4385
+ )
4386
+ ] }, i);
4387
+ }),
4388
+ persistence === "singleton" ? (
4389
+ // Singleton: double concentric rings (thick outer + thin inner)
4390
+ /* @__PURE__ */ jsxs(Fragment, { children: [
4391
+ /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
4392
+ /* @__PURE__ */ jsx("torusGeometry", { args: [1.6, 0.04, 8, 64] }),
4393
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: pColor, emissive: pColor, emissiveIntensity: 0.6, transparent: true, opacity: 0.6 })
4394
+ ] }),
4395
+ /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
4396
+ /* @__PURE__ */ jsx("torusGeometry", { args: [1.4, 0.02, 8, 64] }),
4397
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: pColor, emissive: pColor, emissiveIntensity: 0.4, transparent: true, opacity: 0.4 })
4398
+ ] })
4399
+ ] })
4400
+ ) : persistence === "runtime" ? (
4401
+ // Runtime: segmented ring (8 arc segments with gaps)
4402
+ /* @__PURE__ */ jsx(Fragment, { children: Array.from({ length: 8 }).map((_, i) => {
4403
+ const angle = i / 8 * Math.PI * 2;
4404
+ const x = 1.6 * Math.cos(angle);
4405
+ const z = 1.6 * Math.sin(angle);
4406
+ return /* @__PURE__ */ jsxs("mesh", { position: [x, 0, z], rotation: [Math.PI / 2, 0, angle], children: [
4407
+ /* @__PURE__ */ jsx("torusGeometry", { args: [0.25, 0.025, 6, 12, Math.PI * 0.7] }),
4408
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: pColor, emissive: pColor, emissiveIntensity: 0.6, transparent: true, opacity: 0.6 })
4409
+ ] }, i);
4410
+ }) })
4411
+ ) : persistence === "instance" ? (
4412
+ // Instance: dotted ring (small spheres in a circle)
4413
+ /* @__PURE__ */ jsx(Fragment, { children: Array.from({ length: 16 }).map((_, i) => {
4414
+ const angle = i / 16 * Math.PI * 2;
4415
+ const x = 1.6 * Math.cos(angle);
4416
+ const z = 1.6 * Math.sin(angle);
4417
+ return /* @__PURE__ */ jsxs("mesh", { position: [x, 0, z], scale: 0.04, children: [
4418
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [1, 6, 6] }),
4419
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: pColor, emissive: pColor, emissiveIntensity: 0.8 })
4420
+ ] }, i);
4421
+ }) })
4422
+ ) : (
4423
+ // Persistent (default): solid torus ring
4424
+ /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
4425
+ /* @__PURE__ */ jsx("torusGeometry", { args: [1.6, 0.03, 8, 64] }),
4426
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: pColor, emissive: pColor, emissiveIntensity: 0.6, transparent: true, opacity: 0.6 })
4427
+ ] })
4428
+ ),
4429
+ /* @__PURE__ */ jsx(
4430
+ Avl3DLabel,
4431
+ {
4432
+ position: [0, -1.8, 0],
4433
+ text: name,
4434
+ color: AVL_3D_COLORS.entityCore,
4435
+ fontSize: 14
4436
+ }
4437
+ ),
4438
+ /* @__PURE__ */ jsx(
4439
+ Avl3DLabel,
4440
+ {
4441
+ position: [0, -2.3, 0],
4442
+ text: `${fieldCount} fields`,
4443
+ color: "#999999",
4444
+ fontSize: 10
4445
+ }
4446
+ )
4447
+ ] });
4448
+ };
4449
+ Avl3DEntityCore.displayName = "Avl3DEntityCore";
4450
+ function TraitOrbit({
4451
+ name,
4452
+ radius,
4453
+ tilt,
4454
+ speed,
4455
+ highlighted,
4456
+ dimmed,
4457
+ stateCount = 0,
4458
+ eventCount = 0,
4459
+ transitionCount = 0,
4460
+ onClick,
4461
+ onHover
4462
+ }) {
4463
+ const groupRef = useRef(null);
4464
+ const angleRef = useRef(Math.random() * Math.PI * 2);
4465
+ useFrame((_, delta) => {
4466
+ angleRef.current += delta * speed;
4467
+ if (!groupRef.current) return;
4468
+ const x = radius * Math.cos(angleRef.current);
4469
+ const flatZ = radius * Math.sin(angleRef.current);
4470
+ const y = flatZ * Math.sin(tilt);
4471
+ const z = flatZ * Math.cos(tilt);
4472
+ groupRef.current.position.set(x, y, z);
4473
+ });
4474
+ const opacity = dimmed ? 0.2 : 0.5;
4475
+ const emissiveIntensity = highlighted ? 0.8 : 0.4;
4476
+ return /* @__PURE__ */ jsxs("group", { children: [
4477
+ /* @__PURE__ */ jsxs("mesh", { rotation: [tilt, 0, 0], children: [
4478
+ /* @__PURE__ */ jsx("torusGeometry", { args: [radius, 0.015, 8, 64] }),
4479
+ /* @__PURE__ */ jsx(
4480
+ "meshStandardMaterial",
4481
+ {
4482
+ color: AVL_3D_COLORS.traitOrbit,
4483
+ emissive: AVL_3D_COLORS.traitOrbit,
4484
+ emissiveIntensity,
4485
+ transparent: true,
4486
+ opacity
4487
+ }
4488
+ )
4489
+ ] }),
4490
+ /* @__PURE__ */ jsxs("group", { ref: groupRef, children: [
4491
+ /* @__PURE__ */ jsxs(
4492
+ "mesh",
4493
+ {
4494
+ onClick: (e) => {
4495
+ e.stopPropagation();
4496
+ onClick?.();
4497
+ },
4498
+ onPointerOver: (e) => {
4499
+ e.stopPropagation();
4500
+ onHover?.(true);
4501
+ document.body.style.cursor = "pointer";
4502
+ },
4503
+ onPointerOut: () => {
4504
+ onHover?.(false);
4505
+ document.body.style.cursor = "auto";
4506
+ },
4507
+ scale: highlighted ? 1.3 : 1,
4508
+ children: [
4509
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [0.25, 16, 16] }),
4510
+ /* @__PURE__ */ jsx(
4511
+ "meshStandardMaterial",
4512
+ {
4513
+ color: AVL_3D_COLORS.traitOrbit,
4514
+ emissive: AVL_3D_COLORS.traitOrbit,
4515
+ emissiveIntensity: highlighted ? 1.2 : 0.6,
4516
+ transparent: true,
4517
+ opacity: dimmed ? 0.3 : 0.9
4518
+ }
4519
+ )
4520
+ ]
4521
+ }
4522
+ ),
4523
+ /* @__PURE__ */ jsx(
4524
+ Avl3DLabel,
4525
+ {
4526
+ position: [0, 0.5, 0],
4527
+ text: name,
4528
+ color: dimmed ? "#666666" : "#ffffff",
4529
+ fontSize: highlighted ? 13 : 11
4530
+ }
4531
+ ),
4532
+ highlighted && /* @__PURE__ */ jsx(
4533
+ Avl3DTooltip,
4534
+ {
4535
+ position: [0.8, 0.8, 0],
4536
+ title: name,
4537
+ accentColor: AVL_3D_COLORS.traitOrbitHighlight,
4538
+ rows: [
4539
+ { label: "States", value: String(stateCount) },
4540
+ { label: "Events", value: String(eventCount) },
4541
+ { label: "Transitions", value: String(transitionCount) }
4542
+ ]
4543
+ }
4544
+ )
4545
+ ] })
4546
+ ] });
4547
+ }
4548
+ function PagePortal({ name, position }) {
4549
+ return /* @__PURE__ */ jsxs("group", { position, children: [
4550
+ /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
4551
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.35, 0.35, 0.12, 6] }),
4552
+ /* @__PURE__ */ jsx(
4553
+ "meshStandardMaterial",
4554
+ {
4555
+ color: AVL_3D_COLORS.pagePortal,
4556
+ emissive: AVL_3D_COLORS.pagePortal,
4557
+ emissiveIntensity: 0.5,
4558
+ transparent: true,
4559
+ opacity: 0.7,
4560
+ roughness: 0.3
4561
+ }
4562
+ )
4563
+ ] }),
4564
+ /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
4565
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.25, 0.25, 0.14, 6] }),
4566
+ /* @__PURE__ */ jsx(
4567
+ "meshStandardMaterial",
4568
+ {
4569
+ color: AVL_3D_COLORS.pagePortal,
4570
+ emissive: AVL_3D_COLORS.pagePortal,
4571
+ emissiveIntensity: 0.8,
4572
+ transparent: true,
4573
+ opacity: 0.2,
4574
+ depthWrite: false
4575
+ }
4576
+ )
4577
+ ] }),
4578
+ /* @__PURE__ */ jsx(
4579
+ Avl3DLabel,
4580
+ {
4581
+ position: [0, -0.5, 0],
4582
+ text: name,
4583
+ color: AVL_3D_COLORS.pagePortal,
4584
+ fontSize: 9
4585
+ }
4586
+ )
4587
+ ] });
4588
+ }
4589
+ var Avl3DOrbitalScene = ({
4590
+ data,
4591
+ onTraitClick,
4592
+ highlightedTrait,
4593
+ onTraitHighlight
4594
+ }) => {
4595
+ const [localHighlight, setLocalHighlight] = useState(null);
4596
+ const activeHighlight = highlightedTrait ?? localHighlight;
4597
+ const traitOrbits = useMemo(() => {
4598
+ return data.traits.map((trait, i) => ({
4599
+ name: trait.name,
4600
+ radius: 3 + i * 1.2,
4601
+ tilt: i * Math.PI / (data.traits.length + 1) - Math.PI / 4,
4602
+ speed: 0.3 - i * 0.04,
4603
+ stateCount: trait.stateCount,
4604
+ eventCount: trait.eventCount,
4605
+ transitionCount: trait.transitionCount
4606
+ }));
4607
+ }, [data.traits]);
4608
+ const pagePositions = useMemo(() => {
4609
+ const outerRadius = 3 + data.traits.length * 1.2 + 1.5;
4610
+ return data.pages.map((_, i) => {
4611
+ const angle = 2 * Math.PI * i / data.pages.length - Math.PI / 2;
4612
+ return [
4613
+ outerRadius * Math.cos(angle),
4614
+ 0,
4615
+ outerRadius * Math.sin(angle)
4616
+ ];
4617
+ });
4618
+ }, [data.pages, data.traits.length]);
4619
+ return /* @__PURE__ */ jsxs("group", { children: [
4620
+ /* @__PURE__ */ jsx(
4621
+ Avl3DEntityCore,
4622
+ {
4623
+ name: data.entity.name,
4624
+ fieldCount: data.entity.fields.length,
4625
+ persistence: data.entity.persistence,
4626
+ position: [0, 0, 0],
4627
+ fields: data.entity.fields.map((f) => f.type)
4628
+ }
4629
+ ),
4630
+ traitOrbits.map((orbit) => /* @__PURE__ */ jsx(
4631
+ TraitOrbit,
4632
+ {
4633
+ name: orbit.name,
4634
+ radius: orbit.radius,
4635
+ tilt: orbit.tilt,
4636
+ speed: orbit.speed,
4637
+ highlighted: activeHighlight === orbit.name,
4638
+ dimmed: activeHighlight !== null && activeHighlight !== orbit.name,
4639
+ stateCount: orbit.stateCount,
4640
+ eventCount: orbit.eventCount,
4641
+ transitionCount: orbit.transitionCount,
4642
+ onClick: () => onTraitClick?.(orbit.name),
4643
+ onHover: (h) => {
4644
+ const value = h ? orbit.name : null;
4645
+ onTraitHighlight?.(value);
4646
+ setLocalHighlight(value);
4647
+ }
4648
+ },
4649
+ orbit.name
4650
+ )),
4651
+ data.pages.map((page, i) => /* @__PURE__ */ jsx(
4652
+ PagePortal,
4653
+ {
4654
+ name: page.name,
4655
+ position: pagePositions[i]
4656
+ },
4657
+ page.name
4658
+ ))
4659
+ ] });
4660
+ };
4661
+ Avl3DOrbitalScene.displayName = "Avl3DOrbitalScene";
4662
+ var Avl3DStateNode = ({
4663
+ name,
4664
+ isInitial = false,
4665
+ isTerminal = false,
4666
+ position,
4667
+ active = false,
4668
+ incomingCount = 0,
4669
+ outgoingCount = 0,
4670
+ onClick
4671
+ }) => {
4672
+ const [hovered, setHovered] = useState(false);
4673
+ const baseColor = active ? AVL_3D_COLORS.stateActive : AVL_3D_COLORS.stateIdle;
4674
+ const emissiveColor = active ? AVL_3D_COLORS.stateActive : AVL_3D_COLORS.stateEdge;
4675
+ const emissiveIntensity = active ? 2 : hovered ? 0.8 : 0.3;
4676
+ const targetScale = hovered ? 1.08 : 1;
4677
+ const currentScale = useRef(1);
4678
+ useFrame((_, delta) => {
4679
+ currentScale.current = MathUtils.damp(currentScale.current, targetScale, 6, delta);
4680
+ });
4681
+ const scale = currentScale.current;
4682
+ return /* @__PURE__ */ jsxs("group", { position, children: [
4683
+ /* @__PURE__ */ jsxs("mesh", { scale: scale * 1.4, children: [
4684
+ /* @__PURE__ */ jsx("boxGeometry", { args: [1.2, 0.7, 0.5] }),
4685
+ /* @__PURE__ */ jsx(
4686
+ "meshStandardMaterial",
4687
+ {
4688
+ color: emissiveColor,
4689
+ emissive: emissiveColor,
4690
+ emissiveIntensity: active ? 0.3 : hovered ? 0.1 : 0.03,
4691
+ transparent: true,
4692
+ opacity: active ? 0.08 : 0.03,
4693
+ depthWrite: false
4694
+ }
4695
+ )
4696
+ ] }),
4697
+ /* @__PURE__ */ jsx(
4698
+ RoundedBox,
4699
+ {
4700
+ args: [1, 0.55, 0.35],
4701
+ radius: 0.12,
4702
+ smoothness: 4,
4703
+ scale,
4704
+ onClick: (e) => {
4705
+ e.stopPropagation();
4706
+ onClick?.();
4707
+ },
4708
+ onPointerOver: (e) => {
4709
+ e.stopPropagation();
4710
+ setHovered(true);
4711
+ document.body.style.cursor = "pointer";
4712
+ },
4713
+ onPointerOut: () => {
4714
+ setHovered(false);
4715
+ document.body.style.cursor = "auto";
4716
+ },
4717
+ children: /* @__PURE__ */ jsx(
4718
+ "meshStandardMaterial",
4719
+ {
4720
+ color: baseColor,
4721
+ emissive: emissiveColor,
4722
+ emissiveIntensity,
4723
+ roughness: 0.35,
4724
+ metalness: 0.5
4725
+ }
4726
+ )
4727
+ }
4728
+ ),
4729
+ isInitial && /* @__PURE__ */ jsxs("group", { position: [-0.75, 0, 0], children: [
4730
+ /* @__PURE__ */ jsxs("mesh", { rotation: [0, 0, -Math.PI / 2], children: [
4731
+ /* @__PURE__ */ jsx("coneGeometry", { args: [0.12, 0.25, 8] }),
4732
+ /* @__PURE__ */ jsx(
4733
+ "meshStandardMaterial",
4734
+ {
4735
+ color: AVL_3D_COLORS.stateActive,
4736
+ emissive: AVL_3D_COLORS.stateActive,
4737
+ emissiveIntensity: 1
4738
+ }
4739
+ )
4740
+ ] }),
4741
+ /* @__PURE__ */ jsxs("mesh", { position: [-0.2, 0, 0], rotation: [0, 0, Math.PI / 2], children: [
4742
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.02, 0.02, 0.25, 6] }),
4743
+ /* @__PURE__ */ jsx(
4744
+ "meshStandardMaterial",
4745
+ {
4746
+ color: AVL_3D_COLORS.stateActive,
4747
+ emissive: AVL_3D_COLORS.stateActive,
4748
+ emissiveIntensity: 0.6
4749
+ }
4750
+ )
4751
+ ] })
4752
+ ] }),
4753
+ isTerminal && /* @__PURE__ */ jsxs("group", { position: [0.75, 0, 0], children: [
4754
+ /* @__PURE__ */ jsxs("mesh", { scale: 0.15, children: [
4755
+ /* @__PURE__ */ jsx("octahedronGeometry", { args: [1, 0] }),
4756
+ /* @__PURE__ */ jsx(
4757
+ "meshStandardMaterial",
4758
+ {
4759
+ color: AVL_3D_COLORS.guardFail,
4760
+ emissive: AVL_3D_COLORS.guardFail,
4761
+ emissiveIntensity: 1
4762
+ }
4763
+ )
4764
+ ] }),
4765
+ /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
4766
+ /* @__PURE__ */ jsx("torusGeometry", { args: [0.2, 0.015, 8, 24] }),
4767
+ /* @__PURE__ */ jsx(
4768
+ "meshStandardMaterial",
4769
+ {
4770
+ color: AVL_3D_COLORS.guardFail,
4771
+ emissive: AVL_3D_COLORS.guardFail,
4772
+ emissiveIntensity: 0.5
4773
+ }
4774
+ )
4775
+ ] })
4776
+ ] }),
4777
+ active && /* @__PURE__ */ jsx(
4778
+ "pointLight",
4779
+ {
4780
+ color: AVL_3D_COLORS.stateActive,
4781
+ intensity: 1.5,
4782
+ distance: 4,
4783
+ decay: 2
4784
+ }
4785
+ ),
4786
+ /* @__PURE__ */ jsx(
4787
+ Avl3DLabel,
4788
+ {
4789
+ position: [0, -0.55, 0],
4790
+ text: name,
4791
+ color: active ? AVL_3D_COLORS.stateActive : "#ffffff",
4792
+ fontSize: 11
4793
+ }
4794
+ ),
4795
+ hovered && /* @__PURE__ */ jsx(
4796
+ Avl3DTooltip,
4797
+ {
4798
+ position: [0.9, 0.3, 0],
4799
+ title: name,
4800
+ accentColor: active ? AVL_3D_COLORS.stateActive : AVL_3D_COLORS.stateEdge,
4801
+ rows: [
4802
+ { label: "Type", value: isInitial ? "Initial" : isTerminal ? "Terminal" : "Standard" },
4803
+ { label: "Incoming", value: String(incomingCount) },
4804
+ { label: "Outgoing", value: String(outgoingCount) },
4805
+ ...active ? [{ label: "Status", value: "Active" }] : []
4806
+ ]
4807
+ }
4808
+ )
4809
+ ] });
4810
+ };
4811
+ Avl3DStateNode.displayName = "Avl3DStateNode";
4812
+ function effectTypeColor(type) {
4813
+ switch (type) {
4814
+ case "render-ui":
4815
+ return "#5b9bd5";
4816
+ case "set":
4817
+ return "#e0944a";
4818
+ case "persist":
4819
+ return "#4ecb71";
4820
+ case "fetch":
4821
+ return "#5b9bd5";
4822
+ case "emit":
4823
+ return "#a78bda";
4824
+ case "navigate":
4825
+ return "#40c8aa";
4826
+ case "notify":
4827
+ return "#f0c040";
4828
+ case "call-service":
4829
+ return "#a78bda";
4830
+ case "spawn":
4831
+ return "#4ecb71";
4832
+ case "despawn":
4833
+ return "#f06060";
4834
+ default:
4835
+ return "#888888";
4836
+ }
4837
+ }
4838
+ var Avl3DTransitionArc = ({
4839
+ from,
4840
+ to,
4841
+ event,
4842
+ hasGuard = false,
4843
+ effectTypes,
4844
+ index,
4845
+ isSelf = false,
4846
+ fromState,
4847
+ toState,
4848
+ onClick,
4849
+ color = AVL_3D_COLORS.transitionArc
4850
+ }) => {
4851
+ const [hovered, setHovered] = useState(false);
4852
+ const { tubeArgs, labelPos, guardPos, arrowPos, arrowQuat, effectPositions } = useMemo(() => {
4853
+ const offset = 1.5 + index * 0.8;
4854
+ const curve = isSelf ? selfLoopCurve3D(from, 1.2) : arcCurve3D(from, to, offset);
4855
+ const mid = curve.getPoint(0.5);
4856
+ const guardPt = curve.getPoint(0.3);
4857
+ const arrowPt = curve.getPoint(0.9);
4858
+ const arrowTangent = curve.getTangent(0.9);
4859
+ const upVec = new Vector3(0, 1, 0);
4860
+ const tangentVec = new Vector3(arrowTangent.x, arrowTangent.y, arrowTangent.z).normalize();
4861
+ const quat = new Quaternion().setFromUnitVectors(upVec, tangentVec);
4862
+ const effectPositions2 = [];
4863
+ for (let ei = 0; ei < 4; ei++) {
4864
+ const t = 0.7 + ei * 0.05;
4865
+ const ep = curve.getPoint(t);
4866
+ effectPositions2.push([ep.x, ep.y + 0.2, ep.z]);
4867
+ }
4868
+ return {
4869
+ tubeArgs: [curve, 48, 0.02, 8, false],
4870
+ labelPos: [mid.x, mid.y + 0.3, mid.z],
4871
+ guardPos: [guardPt.x, guardPt.y, guardPt.z],
4872
+ arrowPos: [arrowPt.x, arrowPt.y, arrowPt.z],
4873
+ arrowQuat: [quat.x, quat.y, quat.z, quat.w],
4874
+ effectPositions: effectPositions2
4875
+ };
4876
+ }, [from, to, index, isSelf]);
4877
+ const emissiveIntensity = hovered ? 0.8 : 0.4;
4878
+ return /* @__PURE__ */ jsxs("group", { children: [
4879
+ /* @__PURE__ */ jsxs(
4880
+ "mesh",
4881
+ {
4882
+ onClick: (e) => {
4883
+ e.stopPropagation();
4884
+ onClick?.();
4885
+ },
4886
+ onPointerOver: (e) => {
4887
+ e.stopPropagation();
4888
+ setHovered(true);
4889
+ document.body.style.cursor = "pointer";
4890
+ },
4891
+ onPointerOut: () => {
4892
+ setHovered(false);
4893
+ document.body.style.cursor = "auto";
4894
+ },
4895
+ children: [
4896
+ /* @__PURE__ */ jsx("tubeGeometry", { args: [...tubeArgs] }),
4897
+ /* @__PURE__ */ jsx(
4898
+ "meshStandardMaterial",
4899
+ {
4900
+ color,
4901
+ emissive: color,
4902
+ emissiveIntensity,
4903
+ transparent: true,
4904
+ opacity: hovered ? 0.9 : 0.7
4905
+ }
4906
+ )
4907
+ ]
4908
+ }
4909
+ ),
4910
+ hasGuard && /* @__PURE__ */ jsxs("mesh", { position: guardPos, scale: 0.15, children: [
4911
+ /* @__PURE__ */ jsx("octahedronGeometry", { args: [1, 0] }),
4912
+ /* @__PURE__ */ jsx(
4913
+ "meshStandardMaterial",
4914
+ {
4915
+ color: AVL_3D_COLORS.guardPass,
4916
+ emissive: AVL_3D_COLORS.guardPass,
4917
+ emissiveIntensity: 0.8
4918
+ }
4919
+ )
4920
+ ] }),
4921
+ /* @__PURE__ */ jsxs(
4922
+ "mesh",
4923
+ {
4924
+ position: arrowPos,
4925
+ quaternion: arrowQuat,
4926
+ scale: 0.08,
4927
+ children: [
4928
+ /* @__PURE__ */ jsx("coneGeometry", { args: [1, 2, 8] }),
4929
+ /* @__PURE__ */ jsx(
4930
+ "meshStandardMaterial",
4931
+ {
4932
+ color,
4933
+ emissive: color,
4934
+ emissiveIntensity: 0.6
4935
+ }
4936
+ )
4937
+ ]
4938
+ }
4939
+ ),
4940
+ /* @__PURE__ */ jsx(
4941
+ Avl3DLabel,
4942
+ {
4943
+ position: labelPos,
4944
+ text: event,
4945
+ color: hovered ? "#ffffff" : color,
4946
+ fontSize: hovered ? 11 : 9
4947
+ }
4948
+ ),
4949
+ hovered && /* @__PURE__ */ jsx(
4950
+ Avl3DTooltip,
4951
+ {
4952
+ position: [labelPos[0], labelPos[1] + 0.6, labelPos[2]],
4953
+ title: event,
4954
+ accentColor: AVL_3D_COLORS.transitionArc,
4955
+ rows: [
4956
+ ...fromState && toState ? [{ label: "Transition", value: `${fromState} \u2192 ${toState}` }] : [],
4957
+ ...hasGuard ? [{ label: "Guard", value: "Yes" }] : [],
4958
+ ...effectTypes && effectTypes.length > 0 ? [{ label: "Effects", value: effectTypes.slice(0, 3).join(", ") + (effectTypes.length > 3 ? ` +${effectTypes.length - 3}` : "") }] : []
4959
+ ]
4960
+ }
4961
+ ),
4962
+ effectTypes && effectTypes.length > 0 && effectTypes.slice(0, 4).map((effectType, ei) => {
4963
+ const pt = effectPositions[ei];
4964
+ if (!pt) return null;
4965
+ const eColor = effectTypeColor(effectType);
4966
+ return /* @__PURE__ */ jsx("group", { position: pt, children: /* @__PURE__ */ jsxs("mesh", { scale: 0.06, children: [
4967
+ effectType === "render-ui" ? /* @__PURE__ */ jsx("boxGeometry", { args: [1.5, 1.5, 0.3] }) : effectType === "persist" ? /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.6, 0.6, 1.5, 8] }) : effectType === "emit" ? /* @__PURE__ */ jsx("sphereGeometry", { args: [1, 8, 8] }) : effectType === "navigate" ? /* @__PURE__ */ jsx("coneGeometry", { args: [0.8, 1.5, 6] }) : effectType === "set" ? /* @__PURE__ */ jsx("tetrahedronGeometry", { args: [1, 0] }) : effectType === "notify" ? /* @__PURE__ */ jsx("dodecahedronGeometry", { args: [0.8, 0] }) : effectType === "call-service" ? /* @__PURE__ */ jsx("torusGeometry", { args: [0.8, 0.3, 6, 12] }) : /* @__PURE__ */ jsx("octahedronGeometry", { args: [0.8, 0] }),
4968
+ /* @__PURE__ */ jsx(
4969
+ "meshStandardMaterial",
4970
+ {
4971
+ color: eColor,
4972
+ emissive: eColor,
4973
+ emissiveIntensity: 0.8
4974
+ }
4975
+ )
4976
+ ] }) }, ei);
4977
+ })
4978
+ ] });
4979
+ };
4980
+ Avl3DTransitionArc.displayName = "Avl3DTransitionArc";
4981
+ var Avl3DTraitScene = ({
4982
+ data,
4983
+ onTransitionClick
4984
+ }) => {
4985
+ const statePositions = useMemo(() => {
4986
+ const radius = Math.max(3, data.states.length * 0.8);
4987
+ const positions = fibonacciSpherePositions(data.states.length, radius);
4988
+ const posMap = /* @__PURE__ */ new Map();
4989
+ data.states.forEach((state, i) => {
4990
+ const pos = positions[i];
4991
+ posMap.set(state.name, [pos.x, pos.y, pos.z]);
4992
+ });
4993
+ return posMap;
4994
+ }, [data.states]);
4995
+ const transitionIndices = useMemo(() => {
4996
+ const pairCount = /* @__PURE__ */ new Map();
4997
+ return data.transitions.map((t) => {
4998
+ const key = `${t.from}->${t.to}`;
4999
+ const idx = pairCount.get(key) ?? 0;
5000
+ pairCount.set(key, idx + 1);
5001
+ return idx;
5002
+ });
5003
+ }, [data.transitions]);
5004
+ const transitionCounts = useMemo(() => {
5005
+ const incoming = /* @__PURE__ */ new Map();
5006
+ const outgoing = /* @__PURE__ */ new Map();
5007
+ for (const t of data.transitions) {
5008
+ outgoing.set(t.from, (outgoing.get(t.from) ?? 0) + 1);
5009
+ incoming.set(t.to, (incoming.get(t.to) ?? 0) + 1);
5010
+ }
5011
+ return { incoming, outgoing };
5012
+ }, [data.transitions]);
5013
+ return /* @__PURE__ */ jsxs("group", { children: [
5014
+ /* @__PURE__ */ jsx(
5015
+ Avl3DLabel,
5016
+ {
5017
+ position: [0, 5, 0],
5018
+ text: `${data.name} (${data.linkedEntity})`,
5019
+ color: "#ffffff",
5020
+ fontSize: 14
5021
+ }
5022
+ ),
5023
+ data.states.map((state) => {
5024
+ const pos = statePositions.get(state.name);
5025
+ if (!pos) return null;
5026
+ return /* @__PURE__ */ jsx(
5027
+ Avl3DStateNode,
5028
+ {
5029
+ name: state.name,
5030
+ isInitial: state.isInitial,
5031
+ isTerminal: state.isTerminal,
5032
+ position: pos,
5033
+ incomingCount: transitionCounts.incoming.get(state.name) ?? 0,
5034
+ outgoingCount: transitionCounts.outgoing.get(state.name) ?? 0
5035
+ },
5036
+ state.name
5037
+ );
5038
+ }),
5039
+ data.transitions.map((transition, i) => {
5040
+ const fromPos = statePositions.get(transition.from);
5041
+ const toPos = statePositions.get(transition.to);
5042
+ if (!fromPos || !toPos) return null;
5043
+ const isSelf = transition.from === transition.to;
5044
+ return /* @__PURE__ */ jsx(
5045
+ Avl3DTransitionArc,
5046
+ {
5047
+ from: fromPos,
5048
+ to: toPos,
5049
+ event: transition.event,
5050
+ hasGuard: !!transition.guard,
5051
+ effectCount: transition.effects?.length ?? 0,
5052
+ effectTypes: transition.effects?.map((e) => {
5053
+ if (Array.isArray(e)) return String(e[0]);
5054
+ return typeof e === "string" ? e : "unknown";
5055
+ }),
5056
+ index: transitionIndices[i],
5057
+ isSelf,
5058
+ fromState: transition.from,
5059
+ toState: transition.to,
5060
+ onClick: () => onTransitionClick?.(i)
5061
+ },
5062
+ `${transition.from}-${transition.event}-${transition.to}-${i}`
5063
+ );
5064
+ })
5065
+ ] });
5066
+ };
5067
+ Avl3DTraitScene.displayName = "Avl3DTraitScene";
5068
+
5069
+ // components/atoms/avl/types.ts
5070
+ var AVL_OPERATOR_COLORS = {
5071
+ arithmetic: "#4A90D9",
5072
+ comparison: "#E8913A",
5073
+ logic: "#9B59B6",
5074
+ string: "#27AE60",
5075
+ collection: "#1ABC9C"};
5076
+ function operatorColor(label) {
5077
+ if (["+", "-", "*", "/", "%", "mod"].includes(label)) return AVL_OPERATOR_COLORS.arithmetic;
5078
+ if (["=", "!=", "<", ">", "<=", ">=", "eq", "neq", "lt", "gt"].includes(label)) return AVL_OPERATOR_COLORS.comparison;
5079
+ if (["and", "or", "not", "if", "cond"].includes(label)) return AVL_OPERATOR_COLORS.logic;
5080
+ if (["concat", "upper", "lower", "trim", "substr"].includes(label)) return AVL_OPERATOR_COLORS.string;
5081
+ if (["map", "filter", "reduce", "find", "count", "sum"].includes(label)) return AVL_OPERATOR_COLORS.collection;
5082
+ return "#4A90D9";
5083
+ }
5084
+ function edgeGeometry(parent, child) {
5085
+ const p = new Vector3(parent.x, parent.y, parent.z);
5086
+ const c = new Vector3(child.x, child.y, child.z);
5087
+ const mid = new Vector3().addVectors(p, c).multiplyScalar(0.5);
5088
+ const dir = new Vector3().subVectors(c, p);
5089
+ const length = dir.length();
5090
+ const yAxis = new Vector3(0, 1, 0);
5091
+ const angle = yAxis.angleTo(dir.normalize());
5092
+ const axis = new Vector3().crossVectors(yAxis, dir).normalize();
5093
+ if (axis.length() < 1e-3) {
5094
+ return {
5095
+ position: [mid.x, mid.y, mid.z],
5096
+ rotation: [0, 0, 0],
5097
+ length
5098
+ };
5099
+ }
5100
+ return {
5101
+ position: [mid.x, mid.y, mid.z],
5102
+ rotation: [
5103
+ axis.x * angle,
5104
+ axis.y * angle,
5105
+ axis.z * angle
5106
+ ],
5107
+ length
5108
+ };
5109
+ }
5110
+ var Avl3DExprTree = ({
5111
+ expression,
5112
+ position
5113
+ }) => {
5114
+ const layoutResults = useMemo(() => {
5115
+ const origin = { x: position[0], y: position[1], z: position[2] };
5116
+ return treeLayout3D(expression, origin, 2.5, 1.5);
5117
+ }, [expression, position]);
5118
+ const edges = useMemo(() => {
5119
+ const result = [];
5120
+ function collectEdges(node, parentPos) {
5121
+ const entry = layoutResults.find((r) => r.node === node);
5122
+ if (!entry) return;
5123
+ if (parentPos) {
5124
+ result.push({
5125
+ parent: parentPos,
5126
+ child: entry.position,
5127
+ key: `${parentPos.x}-${parentPos.y}-${entry.position.x}-${entry.position.y}`
5128
+ });
5129
+ }
5130
+ if (node.children) {
5131
+ for (const child of node.children) {
5132
+ collectEdges(child, entry.position);
5133
+ }
5134
+ }
5135
+ }
5136
+ collectEdges(expression, null);
5137
+ return result;
5138
+ }, [expression, layoutResults]);
5139
+ return /* @__PURE__ */ jsxs("group", { children: [
5140
+ edges.map((edge) => {
5141
+ const geo = edgeGeometry(edge.parent, edge.child);
5142
+ return /* @__PURE__ */ jsxs(
5143
+ "mesh",
5144
+ {
5145
+ position: geo.position,
5146
+ rotation: geo.rotation,
5147
+ children: [
5148
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.015, 0.015, geo.length, 6] }),
5149
+ /* @__PURE__ */ jsx(
5150
+ "meshStandardMaterial",
5151
+ {
5152
+ color: "#555555",
5153
+ transparent: true,
5154
+ opacity: 0.5
5155
+ }
5156
+ )
5157
+ ]
5158
+ },
5159
+ edge.key
5160
+ );
5161
+ }),
5162
+ layoutResults.map((entry, i) => {
5163
+ const pos = [
5164
+ entry.position.x,
5165
+ entry.position.y,
5166
+ entry.position.z
5167
+ ];
5168
+ if (entry.node.type === "operator") {
5169
+ const opColor = operatorColor(entry.node.label);
5170
+ return /* @__PURE__ */ jsxs("group", { position: pos, children: [
5171
+ /* @__PURE__ */ jsxs("mesh", { children: [
5172
+ /* @__PURE__ */ jsx("boxGeometry", { args: [0.6, 0.4, 0.3] }),
5173
+ /* @__PURE__ */ jsx(
5174
+ "meshStandardMaterial",
5175
+ {
5176
+ color: opColor,
5177
+ emissive: opColor,
5178
+ emissiveIntensity: 0.4,
5179
+ roughness: 0.3
5180
+ }
5181
+ )
5182
+ ] }),
5183
+ /* @__PURE__ */ jsx(
5184
+ Avl3DLabel,
5185
+ {
5186
+ position: [0, -0.4, 0],
5187
+ text: entry.node.label,
5188
+ color: opColor,
5189
+ fontSize: 10
5190
+ }
5191
+ )
5192
+ ] }, i);
5193
+ }
5194
+ if (entry.node.type === "binding") {
5195
+ return /* @__PURE__ */ jsxs("group", { position: pos, children: [
5196
+ /* @__PURE__ */ jsxs("mesh", { scale: 0.08, children: [
5197
+ /* @__PURE__ */ jsx("torusKnotGeometry", { args: [2, 0.6, 48, 8, 2, 3] }),
5198
+ /* @__PURE__ */ jsx(
5199
+ "meshStandardMaterial",
5200
+ {
5201
+ color: "#4A90D9",
5202
+ emissive: "#4A90D9",
5203
+ emissiveIntensity: 0.4,
5204
+ transparent: true,
5205
+ opacity: 0.85,
5206
+ roughness: 0.3
5207
+ }
5208
+ )
5209
+ ] }),
5210
+ /* @__PURE__ */ jsx(
5211
+ Avl3DLabel,
5212
+ {
5213
+ position: [0, -0.35, 0],
5214
+ text: entry.node.label,
5215
+ color: "#4A90D9",
5216
+ fontSize: 9
5217
+ }
5218
+ )
5219
+ ] }, i);
5220
+ }
5221
+ return /* @__PURE__ */ jsxs("group", { position: pos, children: [
5222
+ /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 6, Math.PI / 4, 0], children: [
5223
+ /* @__PURE__ */ jsx("boxGeometry", { args: [0.2, 0.2, 0.2] }),
5224
+ /* @__PURE__ */ jsx(
5225
+ "meshStandardMaterial",
5226
+ {
5227
+ color: "#888888",
5228
+ emissive: "#666666",
5229
+ emissiveIntensity: 0.2,
5230
+ roughness: 0.5
5231
+ }
5232
+ )
5233
+ ] }),
5234
+ /* @__PURE__ */ jsx(
5235
+ Avl3DLabel,
5236
+ {
5237
+ position: [0, -0.3, 0],
5238
+ text: entry.node.label,
5239
+ color: "#999999",
5240
+ fontSize: 8
5241
+ }
5242
+ )
5243
+ ] }, i);
5244
+ })
5245
+ ] });
5246
+ };
5247
+ Avl3DExprTree.displayName = "Avl3DExprTree";
5248
+ var Avl3DTransitionScene = ({
5249
+ data
5250
+ }) => {
5251
+ return /* @__PURE__ */ jsxs("group", { children: [
5252
+ /* @__PURE__ */ jsx(
5253
+ Avl3DStateNode,
5254
+ {
5255
+ name: data.from,
5256
+ position: [0, 4, 0]
5257
+ }
5258
+ ),
5259
+ /* @__PURE__ */ jsxs("group", { position: [0, 2.2, 0], children: [
5260
+ /* @__PURE__ */ jsxs("mesh", { children: [
5261
+ /* @__PURE__ */ jsx("boxGeometry", { args: [2, 0.6, 0.4] }),
5262
+ /* @__PURE__ */ jsx(
5263
+ "meshStandardMaterial",
5264
+ {
5265
+ color: AVL_3D_COLORS.transitionArc,
5266
+ emissive: AVL_3D_COLORS.transitionArc,
5267
+ emissiveIntensity: 0.5,
5268
+ roughness: 0.3
5269
+ }
5270
+ )
5271
+ ] }),
5272
+ /* @__PURE__ */ jsx(
5273
+ Avl3DLabel,
5274
+ {
5275
+ position: [0, 0, 0.3],
5276
+ text: data.event,
5277
+ color: "#ffffff",
5278
+ fontSize: 13
5279
+ }
5280
+ )
5281
+ ] }),
5282
+ /* @__PURE__ */ jsxs("mesh", { position: [0, 3.1, 0], children: [
5283
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.02, 0.02, 1.2, 6] }),
5284
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: "#555555", transparent: true, opacity: 0.5 })
5285
+ ] }),
5286
+ data.guard && /* @__PURE__ */ jsxs("group", { position: [0, 1, 0], children: [
5287
+ /* @__PURE__ */ jsxs("mesh", { rotation: [0, 0, Math.PI / 4], children: [
5288
+ /* @__PURE__ */ jsx("boxGeometry", { args: [0.5, 0.5, 0.3] }),
5289
+ /* @__PURE__ */ jsx(
5290
+ "meshStandardMaterial",
5291
+ {
5292
+ color: AVL_3D_COLORS.guardPass,
5293
+ emissive: AVL_3D_COLORS.guardPass,
5294
+ emissiveIntensity: 0.6
5295
+ }
5296
+ )
5297
+ ] }),
5298
+ /* @__PURE__ */ jsxs("mesh", { position: [0, 0.7, 0], children: [
5299
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.02, 0.02, 0.8, 6] }),
5300
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: "#555555", transparent: true, opacity: 0.5 })
5301
+ ] }),
5302
+ /* @__PURE__ */ jsx(
5303
+ Avl3DExprTree,
5304
+ {
5305
+ expression: data.guard,
5306
+ position: [3, 0, 0]
5307
+ }
5308
+ ),
5309
+ /* @__PURE__ */ jsx(
5310
+ Avl3DLabel,
5311
+ {
5312
+ position: [1.5, 0.3, 0],
5313
+ text: "guard",
5314
+ color: AVL_3D_COLORS.guardPass,
5315
+ fontSize: 9
5316
+ }
5317
+ )
5318
+ ] }),
5319
+ data.effects.length > 0 && /* @__PURE__ */ jsxs("group", { position: [0, data.guard ? -0.5 : 0.5, 0], children: [
5320
+ /* @__PURE__ */ jsx(
5321
+ Avl3DLabel,
5322
+ {
5323
+ position: [0, 0.4, 0],
5324
+ text: `${data.effects.length} effect${data.effects.length > 1 ? "s" : ""}`,
5325
+ color: "#E8913A",
5326
+ fontSize: 10
5327
+ }
5328
+ ),
5329
+ data.effects.map((effect, i) => {
5330
+ const xOffset = (i - (data.effects.length - 1) / 2) * 3;
5331
+ return /* @__PURE__ */ jsx(
5332
+ Avl3DExprTree,
5333
+ {
5334
+ expression: effect,
5335
+ position: [xOffset, -1, 0]
5336
+ },
5337
+ i
5338
+ );
5339
+ })
5340
+ ] }),
5341
+ /* @__PURE__ */ jsxs("mesh", { position: [0, data.guard ? -2.5 : -1.5, 0], children: [
5342
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.02, 0.02, 1.2, 6] }),
5343
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: "#555555", transparent: true, opacity: 0.5 })
5344
+ ] }),
5345
+ /* @__PURE__ */ jsx(
5346
+ Avl3DStateNode,
5347
+ {
5348
+ name: data.to,
5349
+ position: [0, data.guard ? -3.5 : -2.5, 0]
5350
+ }
5351
+ )
5352
+ ] });
5353
+ };
5354
+ Avl3DTransitionScene.displayName = "Avl3DTransitionScene";
5355
+ var BLOOM_CONFIG = {
5356
+ application: { intensity: 0.4, luminanceThreshold: 0.88, luminanceSmoothing: 0.95 },
5357
+ orbital: { intensity: 0.5, luminanceThreshold: 0.85, luminanceSmoothing: 0.9 },
5358
+ trait: { intensity: 0.3, luminanceThreshold: 0.92, luminanceSmoothing: 0.9 },
5359
+ transition: { intensity: 0.35, luminanceThreshold: 0.9, luminanceSmoothing: 0.9 }
5360
+ };
5361
+ var DOF_CONFIG = {
5362
+ application: null,
5363
+ orbital: { focusDistance: 0.02, focalLength: 0.02, bokehScale: 1.5 },
5364
+ trait: null,
5365
+ transition: null
5366
+ };
5367
+ var SPARKLE_CONFIGS = {
5368
+ application: [
5369
+ { count: 60, size: 1.2, speed: 0.2, opacity: 0.35, scale: 35, color: AVL_3D_COLORS.sparkle },
5370
+ { count: 15, size: 1.8, speed: 0.1, opacity: 0.2, scale: 25, color: AVL_3D_COLORS.sparkleWarm }
5371
+ ],
5372
+ orbital: [
5373
+ { count: 30, size: 0.8, speed: 0.15, opacity: 0.25, scale: 18, color: AVL_3D_COLORS.sparkle },
5374
+ { count: 8, size: 1.2, speed: 0.08, opacity: 0.15, scale: 12, color: AVL_3D_COLORS.sparkleWarm }
5375
+ ],
5376
+ trait: [
5377
+ { count: 15, size: 0.6, speed: 0.1, opacity: 0.2, scale: 12, color: AVL_3D_COLORS.sparkle }
5378
+ ],
5379
+ transition: [
5380
+ { count: 8, size: 0.4, speed: 0.08, opacity: 0.15, scale: 8, color: AVL_3D_COLORS.sparkle }
5381
+ ]
5382
+ };
5383
+ var STARS_CONFIG = {
5384
+ application: { radius: 80, count: 3e3, factor: 5, fade: true },
5385
+ orbital: { radius: 60, count: 1500, factor: 4, fade: true },
5386
+ trait: { radius: 40, count: 800, factor: 3, fade: true },
5387
+ transition: { radius: 30, count: 400, factor: 2, fade: true }
5388
+ };
5389
+ var Avl3DEffects = ({
5390
+ level,
5391
+ enabled = true
5392
+ }) => {
5393
+ if (!enabled) return null;
5394
+ const bloom = BLOOM_CONFIG[level];
5395
+ const dof = DOF_CONFIG[level];
5396
+ const sparkles = SPARKLE_CONFIGS[level];
5397
+ const stars = STARS_CONFIG[level];
5398
+ const starsKey = useMemo(() => `stars-${level}`, [level]);
5399
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
5400
+ /* @__PURE__ */ jsx(
5401
+ Stars,
5402
+ {
5403
+ radius: stars.radius,
5404
+ count: stars.count,
5405
+ factor: stars.factor,
5406
+ saturation: 0.1,
5407
+ fade: stars.fade,
5408
+ speed: 0.3
5409
+ },
5410
+ starsKey
5411
+ ),
5412
+ sparkles.map((cfg, i) => /* @__PURE__ */ jsx(
5413
+ Sparkles,
5414
+ {
5415
+ count: cfg.count,
5416
+ size: cfg.size,
5417
+ speed: cfg.speed,
5418
+ opacity: cfg.opacity,
5419
+ scale: cfg.scale,
5420
+ color: cfg.color
5421
+ },
5422
+ `sparkle-${level}-${i}`
5423
+ )),
5424
+ dof ? /* @__PURE__ */ jsxs(EffectComposer, { children: [
5425
+ /* @__PURE__ */ jsx(
5426
+ Bloom,
5427
+ {
5428
+ intensity: bloom.intensity,
5429
+ luminanceThreshold: bloom.luminanceThreshold,
5430
+ luminanceSmoothing: bloom.luminanceSmoothing,
5431
+ mipmapBlur: true
5432
+ }
5433
+ ),
5434
+ /* @__PURE__ */ jsx(
5435
+ DepthOfField,
5436
+ {
5437
+ focusDistance: dof.focusDistance,
5438
+ focalLength: dof.focalLength,
5439
+ bokehScale: dof.bokehScale
5440
+ }
5441
+ ),
5442
+ /* @__PURE__ */ jsx(Vignette, { eskil: false, offset: 0.2, darkness: 0.35 })
5443
+ ] }) : /* @__PURE__ */ jsxs(EffectComposer, { children: [
5444
+ /* @__PURE__ */ jsx(
5445
+ Bloom,
5446
+ {
5447
+ intensity: bloom.intensity,
5448
+ luminanceThreshold: bloom.luminanceThreshold,
5449
+ luminanceSmoothing: bloom.luminanceSmoothing,
5450
+ mipmapBlur: true
5451
+ }
5452
+ ),
5453
+ /* @__PURE__ */ jsx(Vignette, { eskil: false, offset: 0.2, darkness: 0.35 })
5454
+ ] })
5455
+ ] });
5456
+ };
5457
+ Avl3DEffects.displayName = "Avl3DEffects";
5458
+ var DEFAULT_CONFIG2 = {
5459
+ modelOverrides: {},
5460
+ effectsEnabled: true
5461
+ };
5462
+ var Avl3DContext = createContext(DEFAULT_CONFIG2);
5463
+ function useAvl3DConfig() {
5464
+ return useContext(Avl3DContext);
5465
+ }
5466
+ function CameraController2({ targetPosition, targetLookAt, animated }) {
5467
+ const { camera } = useThree();
5468
+ const targetPosVec = useRef(new THREE6.Vector3(...targetPosition));
5469
+ const targetLookVec = useRef(new THREE6.Vector3(...targetLookAt));
5470
+ const isAnimating = useRef(false);
5471
+ useEffect(() => {
5472
+ const newTarget = new THREE6.Vector3(...targetPosition);
5473
+ const newLookAt = new THREE6.Vector3(...targetLookAt);
5474
+ if (!newTarget.equals(targetPosVec.current) || !newLookAt.equals(targetLookVec.current)) {
5475
+ targetPosVec.current.copy(newTarget);
5476
+ targetLookVec.current.copy(newLookAt);
5477
+ if (animated) {
5478
+ isAnimating.current = true;
5479
+ } else {
5480
+ camera.position.copy(targetPosVec.current);
5481
+ camera.lookAt(targetLookVec.current);
5482
+ }
5483
+ }
5484
+ }, [targetPosition, targetLookAt, animated, camera]);
5485
+ useFrame((_, delta) => {
5486
+ if (!isAnimating.current) return;
5487
+ const speed = 3;
5488
+ camera.position.x = THREE6.MathUtils.damp(camera.position.x, targetPosVec.current.x, speed, delta);
5489
+ camera.position.y = THREE6.MathUtils.damp(camera.position.y, targetPosVec.current.y, speed, delta);
5490
+ camera.position.z = THREE6.MathUtils.damp(camera.position.z, targetPosVec.current.z, speed, delta);
5491
+ camera.lookAt(targetLookVec.current);
5492
+ const dist = camera.position.distanceTo(targetPosVec.current);
5493
+ if (dist < 0.05) {
5494
+ isAnimating.current = false;
5495
+ }
5496
+ });
5497
+ return null;
5498
+ }
5499
+ function SceneFade({ animating, children }) {
5500
+ const groupRef = useRef(null);
5501
+ const opacityRef = useRef(1);
5502
+ useFrame((_, delta) => {
5503
+ if (!groupRef.current) return;
5504
+ const target = animating ? 0 : 1;
5505
+ opacityRef.current = THREE6.MathUtils.damp(opacityRef.current, target, 5, delta);
5506
+ groupRef.current.visible = opacityRef.current > 0.05;
5507
+ const s = 0.9 + opacityRef.current * 0.1;
5508
+ groupRef.current.scale.setScalar(s);
5509
+ });
5510
+ return /* @__PURE__ */ jsx("group", { ref: groupRef, children });
5511
+ }
5512
+ var Avl3DViewer = ({
5513
+ schema: schemaProp,
5514
+ className,
5515
+ animated = true,
5516
+ initialOrbital,
5517
+ initialTrait,
5518
+ onZoomChange,
5519
+ width = "100%",
5520
+ height = 500,
5521
+ effects = true,
5522
+ modelOverrides = {}
5523
+ }) => {
5524
+ const schema = useMemo(() => {
5525
+ if (typeof schemaProp === "string") {
5526
+ try {
5527
+ return JSON.parse(schemaProp);
5528
+ } catch {
5529
+ return { name: "Error", orbitals: [] };
5530
+ }
5531
+ }
5532
+ return schemaProp;
5533
+ }, [schemaProp]);
5534
+ const configValue = useMemo(() => ({
5535
+ modelOverrides,
5536
+ effectsEnabled: effects
5537
+ }), [modelOverrides, effects]);
5538
+ const [state, dispatch] = useReducer(zoomReducer, initialZoomState);
5539
+ useEffect(() => {
5540
+ if (initialOrbital) {
5541
+ dispatch({ type: "ZOOM_INTO_ORBITAL", orbital: initialOrbital, targetPosition: { x: 0, y: 0 } });
5542
+ setTimeout(() => dispatch({ type: "ANIMATION_COMPLETE" }), 0);
5543
+ if (initialTrait) {
5544
+ setTimeout(() => {
5545
+ dispatch({ type: "ZOOM_INTO_TRAIT", trait: initialTrait, targetPosition: { x: 0, y: 0 } });
5546
+ setTimeout(() => dispatch({ type: "ANIMATION_COMPLETE" }), 0);
5547
+ }, 10);
5548
+ }
5549
+ }
5550
+ }, [initialOrbital, initialTrait]);
5551
+ useEffect(() => {
5552
+ onZoomChange?.(state.level, {
5553
+ orbital: state.selectedOrbital ?? void 0,
5554
+ trait: state.selectedTrait ?? void 0
5555
+ });
5556
+ }, [state.level, state.selectedOrbital, state.selectedTrait, onZoomChange]);
5557
+ useEffect(() => {
5558
+ if (!state.animating) return;
5559
+ const timer = setTimeout(() => {
5560
+ dispatch({ type: "ANIMATION_COMPLETE" });
5561
+ }, 800);
5562
+ return () => clearTimeout(timer);
5563
+ }, [state.animating]);
5564
+ const handleKeyDown = useCallback((e) => {
5565
+ if (e.key === "Escape") {
5566
+ dispatch({ type: "ZOOM_OUT" });
5567
+ }
5568
+ }, []);
5569
+ const handleOrbitalClick = useCallback((name) => {
5570
+ dispatch({ type: "ZOOM_INTO_ORBITAL", orbital: name, targetPosition: { x: 0, y: 0 } });
5571
+ }, []);
5572
+ const handleTraitClick = useCallback((name) => {
5573
+ dispatch({ type: "ZOOM_INTO_TRAIT", trait: name, targetPosition: { x: 0, y: 0 } });
5574
+ }, []);
5575
+ const [highlightedTrait, setHighlightedTrait] = React21.useState(null);
5576
+ const handleTransitionClick = useCallback((index) => {
5577
+ dispatch({ type: "ZOOM_INTO_TRANSITION", transitionIndex: index, targetPosition: { x: 0, y: 0 } });
5578
+ }, []);
5579
+ const handleBreadcrumbClick = useCallback((targetLevel) => {
5580
+ const levelOrder = ["application", "orbital", "trait", "transition"];
5581
+ const currentIdx = levelOrder.indexOf(state.level);
5582
+ const targetIdx = levelOrder.indexOf(targetLevel);
5583
+ if (targetIdx < currentIdx) {
5584
+ dispatch({ type: "ZOOM_OUT" });
5585
+ }
5586
+ }, [state.level]);
5587
+ const cameraConfig = CAMERA_POSITIONS[state.level];
5588
+ const sceneContent = useMemo(() => {
5589
+ switch (state.level) {
5590
+ case "application": {
5591
+ const data = parseApplicationLevel(schema);
5592
+ return /* @__PURE__ */ jsx(
5593
+ Avl3DApplicationScene,
5594
+ {
5595
+ data,
5596
+ onOrbitalClick: handleOrbitalClick
5597
+ }
5598
+ );
5599
+ }
5600
+ case "orbital": {
5601
+ if (!state.selectedOrbital) return null;
5602
+ const orbData = parseOrbitalLevel(schema, state.selectedOrbital);
5603
+ if (!orbData) return null;
5604
+ return /* @__PURE__ */ jsx(
5605
+ Avl3DOrbitalScene,
5606
+ {
5607
+ data: orbData,
5608
+ onTraitClick: handleTraitClick,
5609
+ highlightedTrait,
5610
+ onTraitHighlight: setHighlightedTrait
5611
+ }
5612
+ );
5613
+ }
5614
+ case "trait": {
5615
+ if (!state.selectedOrbital || !state.selectedTrait) return null;
5616
+ const traitData = parseTraitLevel(schema, state.selectedOrbital, state.selectedTrait);
5617
+ if (!traitData) return null;
5618
+ return /* @__PURE__ */ jsx(
5619
+ Avl3DTraitScene,
5620
+ {
5621
+ data: traitData,
5622
+ onTransitionClick: handleTransitionClick
5623
+ }
5624
+ );
5625
+ }
5626
+ case "transition": {
5627
+ if (!state.selectedOrbital || !state.selectedTrait || state.selectedTransition === null) return null;
5628
+ const transData = parseTransitionLevel(schema, state.selectedOrbital, state.selectedTrait, state.selectedTransition);
5629
+ if (!transData) return null;
5630
+ return /* @__PURE__ */ jsx(
5631
+ Avl3DTransitionScene,
5632
+ {
5633
+ data: transData
5634
+ }
5635
+ );
5636
+ }
5637
+ default:
5638
+ return null;
5639
+ }
5640
+ }, [state.level, state.selectedOrbital, state.selectedTrait, state.selectedTransition, schema, handleOrbitalClick, handleTraitClick, handleTransitionClick, highlightedTrait, setHighlightedTrait]);
5641
+ const breadcrumbs = getBreadcrumbs(state);
5642
+ return /* @__PURE__ */ jsxs(
5643
+ Box,
5644
+ {
5645
+ className: `relative ${className ?? ""}`,
5646
+ style: {
5647
+ width,
5648
+ height: typeof height === "number" ? `${height}px` : height,
5649
+ backgroundColor: AVL_3D_COLORS.background,
5650
+ borderRadius: "8px",
5651
+ overflow: "hidden"
5652
+ },
5653
+ onKeyDown: handleKeyDown,
5654
+ tabIndex: 0,
5655
+ children: [
5656
+ /* @__PURE__ */ jsx(
5657
+ HStack,
5658
+ {
5659
+ gap: "xs",
5660
+ align: "center",
5661
+ className: "absolute top-2 left-2 z-10 bg-[var(--color-surface)]/80 backdrop-blur rounded-md px-3 py-1.5",
5662
+ children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxs(React21.Fragment, { children: [
5663
+ i > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", className: "mx-1", children: "/" }),
5664
+ i < breadcrumbs.length - 1 ? /* @__PURE__ */ jsx(
5665
+ Box,
5666
+ {
5667
+ as: "span",
5668
+ className: "cursor-pointer hover:underline",
5669
+ onClick: () => handleBreadcrumbClick(crumb.level),
5670
+ children: /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: crumb.label })
5671
+ }
5672
+ ) : /* @__PURE__ */ jsx(Typography, { variant: "small", color: "primary", className: "font-bold", children: crumb.label })
5673
+ ] }, crumb.level))
5674
+ }
5675
+ ),
5676
+ state.level !== "application" && /* @__PURE__ */ jsx(
5677
+ Typography,
5678
+ {
5679
+ variant: "small",
5680
+ color: "muted",
5681
+ className: "absolute bottom-2 right-2 z-10 bg-[var(--color-surface)]/60 backdrop-blur rounded px-2 py-1",
5682
+ children: "Press Esc to zoom out"
5683
+ }
5684
+ ),
5685
+ /* @__PURE__ */ jsx(
5686
+ Canvas,
5687
+ {
5688
+ style: { width: "100%", height: "100%" },
5689
+ camera: {
5690
+ position: cameraConfig.position,
5691
+ fov: 60,
5692
+ near: 0.1,
5693
+ far: 200
5694
+ },
5695
+ onCreated: ({ gl }) => {
5696
+ gl.setClearColor(AVL_3D_COLORS.background);
5697
+ },
5698
+ children: /* @__PURE__ */ jsx(Avl3DContext.Provider, { value: configValue, children: /* @__PURE__ */ jsxs(
5699
+ Scene3D,
5700
+ {
5701
+ background: AVL_3D_COLORS.background,
5702
+ fog: { color: AVL_3D_COLORS.fog, near: 30, far: 80 },
5703
+ children: [
5704
+ /* @__PURE__ */ jsx(
5705
+ Camera3D,
5706
+ {
5707
+ mode: "perspective",
5708
+ position: cameraConfig.position,
5709
+ target: cameraConfig.target,
5710
+ enableOrbit: true,
5711
+ minDistance: 3,
5712
+ maxDistance: 80
5713
+ }
5714
+ ),
5715
+ /* @__PURE__ */ jsx(
5716
+ Lighting3D,
5717
+ {
5718
+ ambientIntensity: 0.35,
5719
+ ambientColor: "#8090c0",
5720
+ directionalIntensity: 0.5,
5721
+ directionalColor: "#c0d0f0",
5722
+ directionalPosition: [8, 15, 12],
5723
+ shadows: false
5724
+ }
5725
+ ),
5726
+ /* @__PURE__ */ jsx(
5727
+ "pointLight",
5728
+ {
5729
+ position: [0, -10, 0],
5730
+ color: "#2040a0",
5731
+ intensity: 0.15,
5732
+ distance: 50,
5733
+ decay: 2
5734
+ }
5735
+ ),
5736
+ /* @__PURE__ */ jsx(
5737
+ CameraController2,
5738
+ {
5739
+ targetPosition: cameraConfig.position,
5740
+ targetLookAt: cameraConfig.target,
5741
+ animated
5742
+ }
5743
+ ),
5744
+ /* @__PURE__ */ jsx(SceneFade, { animating: state.animating, children: sceneContent }),
5745
+ /* @__PURE__ */ jsx(Avl3DEffects, { level: state.level, enabled: effects })
5746
+ ]
5747
+ }
5748
+ ) })
5749
+ }
5750
+ )
5751
+ ]
5752
+ }
5753
+ );
5754
+ };
5755
+ Avl3DViewer.displayName = "Avl3DViewer";
3342
5756
  function isInFrustum(position, camera, padding = 0) {
3343
5757
  const frustum = new THREE6.Frustum();
3344
5758
  const projScreenMatrix = new THREE6.Matrix4();
@@ -3521,4 +5935,4 @@ var SpatialHashGrid = class {
3521
5935
  }
3522
5936
  };
3523
5937
 
3524
- export { AssetLoader, Camera3D, Canvas3DErrorBoundary, Canvas3DLoadingState, FeatureRenderer, FeatureRenderer3D, GameCanvas3D, GameCanvas3DBattleTemplate, GameCanvas3DCastleTemplate, GameCanvas3DWorldMapTemplate, Lighting3D, ModelLoader, PhysicsObject3D, Scene3D, SpatialHashGrid, TileRenderer, UnitRenderer, assetLoader, calculateLODLevel, createGridHighlight, cullInstancedMesh, filterByFrustum, getCellsInRadius, getNeighbors, getVisibleIndices, gridDistance, gridManhattanDistance, gridToWorld, isInBounds, isInFrustum, normalizeMouseCoordinates, preloadFeatures, raycastToObjects, raycastToPlane, updateInstanceLOD, useAssetLoader, useGameCanvas3DEvents, usePhysics3DController, useRaycaster, useSceneGraph, useThree3 as useThree, worldToGrid };
5938
+ export { AVL_3D_COLORS, AssetLoader, Avl3DApplicationScene, Avl3DContext, Avl3DEffects, Avl3DOrbitalScene, Avl3DTraitScene, Avl3DTransitionScene, Avl3DViewer, CAMERA_POSITIONS, Camera3D, Canvas3DErrorBoundary, Canvas3DLoadingState, FeatureRenderer, FeatureRenderer3D, GameCanvas3D, GameCanvas3DBattleTemplate, GameCanvas3DCastleTemplate, GameCanvas3DWorldMapTemplate, Lighting3D, ModelLoader, PhysicsObject3D, Scene3D, SpatialHashGrid, TileRenderer, UnitRenderer, arcCurve3D, assetLoader, calculateLODLevel, createGridHighlight, cullInstancedMesh, fibonacciSpherePositions, filterByFrustum, getCellsInRadius, getNeighbors, getVisibleIndices, goldenSpiralPositions, gridDistance, gridManhattanDistance, gridToWorld, isInBounds, isInFrustum, normalizeMouseCoordinates, orbitRingPositions, preloadFeatures, raycastToObjects, raycastToPlane, selfLoopCurve3D, treeLayout3D, updateInstanceLOD, useAssetLoader, useAvl3DConfig, useGameCanvas3DEvents, usePhysics3DController, useRaycaster, useSceneGraph, useThree3 as useThree, worldToGrid };