@visualli/core 0.1.5 → 0.1.7

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 (85) hide show
  1. package/dist/animations/index.cjs +146 -0
  2. package/dist/animations/index.cjs.map +1 -0
  3. package/dist/animations/index.d.cts +81 -0
  4. package/dist/animations/index.d.ts +81 -0
  5. package/dist/animations/index.js +35 -0
  6. package/dist/animations/index.js.map +1 -0
  7. package/dist/chunk-6NXADJK2.js +562 -0
  8. package/dist/chunk-6NXADJK2.js.map +1 -0
  9. package/dist/chunk-F36SMC3K.js +106 -0
  10. package/dist/chunk-F36SMC3K.js.map +1 -0
  11. package/dist/chunk-G5H3P4YZ.js +273 -0
  12. package/dist/chunk-G5H3P4YZ.js.map +1 -0
  13. package/dist/chunk-GQMFBYLK.js +81 -0
  14. package/dist/chunk-GQMFBYLK.js.map +1 -0
  15. package/dist/chunk-I75TMOE4.js +108 -0
  16. package/dist/chunk-I75TMOE4.js.map +1 -0
  17. package/dist/chunk-LDJRGT2Q.js +163 -0
  18. package/dist/chunk-LDJRGT2Q.js.map +1 -0
  19. package/dist/chunk-LI3BVD6H.js +98 -0
  20. package/dist/chunk-LI3BVD6H.js.map +1 -0
  21. package/dist/chunk-LJYSKSCE.js +95 -0
  22. package/dist/chunk-LJYSKSCE.js.map +1 -0
  23. package/dist/chunk-LNTJTDB2.js +349 -0
  24. package/dist/chunk-LNTJTDB2.js.map +1 -0
  25. package/dist/chunk-PDP5CVUL.js +139 -0
  26. package/dist/chunk-PDP5CVUL.js.map +1 -0
  27. package/dist/chunk-VLGR5PZX.js +1 -0
  28. package/dist/chunk-VLGR5PZX.js.map +1 -0
  29. package/dist/config/index.cjs +391 -0
  30. package/dist/config/index.cjs.map +1 -0
  31. package/dist/config/index.d.cts +77 -0
  32. package/dist/config/index.d.ts +77 -0
  33. package/dist/config/index.js +38 -0
  34. package/dist/config/index.js.map +1 -0
  35. package/dist/constants/index.cjs +642 -0
  36. package/dist/constants/index.cjs.map +1 -0
  37. package/dist/constants/index.d.cts +448 -0
  38. package/dist/constants/index.d.ts +448 -0
  39. package/dist/constants/index.js +183 -0
  40. package/dist/constants/index.js.map +1 -0
  41. package/dist/document-B3hnNr-F.d.cts +73 -0
  42. package/dist/document-B3hnNr-F.d.ts +73 -0
  43. package/dist/index.cjs +32 -32
  44. package/dist/index.cjs.map +1 -1
  45. package/dist/index.d.cts +15 -1044
  46. package/dist/index.d.ts +15 -1044
  47. package/dist/index.js +179 -1747
  48. package/dist/index.js.map +1 -1
  49. package/dist/layout/index.cjs +210 -0
  50. package/dist/layout/index.cjs.map +1 -0
  51. package/dist/layout/index.d.cts +80 -0
  52. package/dist/layout/index.d.ts +80 -0
  53. package/dist/layout/index.js +25 -0
  54. package/dist/layout/index.js.map +1 -0
  55. package/dist/mindmap-DWS0WZT_.d.cts +118 -0
  56. package/dist/mindmap-DWS0WZT_.d.ts +118 -0
  57. package/dist/parser/index.cjs +739 -0
  58. package/dist/parser/index.cjs.map +1 -0
  59. package/dist/parser/index.d.cts +87 -0
  60. package/dist/parser/index.d.ts +87 -0
  61. package/dist/parser/index.js +43 -0
  62. package/dist/parser/index.js.map +1 -0
  63. package/dist/performance/index.cjs +167 -0
  64. package/dist/performance/index.cjs.map +1 -0
  65. package/dist/performance/index.d.cts +40 -0
  66. package/dist/performance/index.d.ts +40 -0
  67. package/dist/performance/index.js +12 -0
  68. package/dist/performance/index.js.map +1 -0
  69. package/dist/types/index.cjs +19 -0
  70. package/dist/types/index.cjs.map +1 -0
  71. package/dist/types/index.d.cts +8 -0
  72. package/dist/types/index.d.ts +8 -0
  73. package/dist/types/index.js +2 -0
  74. package/dist/types/index.js.map +1 -0
  75. package/dist/viewport/index.cjs +131 -0
  76. package/dist/viewport/index.cjs.map +1 -0
  77. package/dist/viewport/index.d.cts +56 -0
  78. package/dist/viewport/index.d.ts +56 -0
  79. package/dist/viewport/index.js +26 -0
  80. package/dist/viewport/index.js.map +1 -0
  81. package/package.json +7 -2
  82. package/src/config/README.md +59 -0
  83. package/src/config/USAGE_EXAMPLES.md +285 -0
  84. package/src/config/index.ts +7 -0
  85. package/src/index.ts +1 -2
@@ -0,0 +1,163 @@
1
+ // src/constants/performanceConstants.ts
2
+ var FPS_TARGET = 60;
3
+ var FPS_WARNING_THRESHOLD = 45;
4
+ var FPS_CRITICAL_THRESHOLD = 30;
5
+ var TARGET_FRAME_TIME = 1e3 / FPS_TARGET;
6
+ var MAX_FRAME_TIME = 18;
7
+ var FPS_TARGETS = {
8
+ PAN_MIN: 30,
9
+ ZOOM_TARGET: 60,
10
+ WARNING_THRESHOLD: 20
11
+ };
12
+ var TIMING_THRESHOLDS = {
13
+ VIEWPORT_QUERY_MAX: 5,
14
+ SPATIAL_UPDATE_MAX: 10,
15
+ DRAG_RESPONSE_MAX: 16,
16
+ LOAD_5K_TARGET: 2e3,
17
+ LOAD_10K_TARGET: 3e3,
18
+ VIEWPORT_DEBOUNCE: 100,
19
+ SPATIAL_INDEX_BUILD: 50
20
+ };
21
+ var MEMORY_TARGET_MB = 500;
22
+ var MEMORY_WARNING_MB = 600;
23
+ var MEMORY_CRITICAL_MB = 800;
24
+ var MEMORY_LIMITS = {
25
+ MAX_10K_NODES: 500,
26
+ MAX_GROWTH_PERCENT: 20,
27
+ WARNING_THRESHOLD: 400
28
+ };
29
+ var VIEWPORT_MARGIN = 0.1;
30
+ var MAX_VISIBLE_NODES = 800;
31
+ var CULLING_QUERY_TIME_BUDGET = 5;
32
+ var RBUSH_MAX_ENTRIES = 16;
33
+ var SPATIAL_INDEX_BUILD_BUDGET = 50;
34
+ var NODE_MIN_WIDTH = 200;
35
+ var NODE_HEIGHT = 80;
36
+ var NODE_PADDING = 40;
37
+ var CHAR_WIDTH = 8;
38
+ var TITLE_MAX_LENGTH = 150;
39
+ var CORNER_RADIUS = 8;
40
+ var BORDER_WIDTH_NORMAL = 2;
41
+ var BORDER_WIDTH_SELECTED = 3;
42
+ var COLOR_SELECTED = "#1B2D4F";
43
+ var COLOR_BORDER_LIGHT = "#4A3728";
44
+ var COLOR_BORDER_DARK = "#FAF6F1";
45
+ var COLOR_DEFAULT_NODE = "#FAF6F1";
46
+ var ZOOM_MIN = 0.05;
47
+ var ZOOM_MAX = 5;
48
+ var ZOOM_DEFAULT = 1;
49
+ var ZOOM_STEP = 0.1;
50
+ var ZOOM_WHEEL_SENSITIVITY = 1e-3;
51
+ var ZOOM_NAV_IN_THRESHOLD = 2.7;
52
+ var ZOOM_NAV_OUT_THRESHOLD = 0.4;
53
+ var TEXT_LABEL_HIDE_BELOW_ZOOM = 0.3;
54
+ var QUALITY_HIGH = {
55
+ shadows: true,
56
+ bezierCurves: true,
57
+ animations: true,
58
+ textQuality: "high",
59
+ antialiasing: true
60
+ };
61
+ var QUALITY_MEDIUM = {
62
+ shadows: false,
63
+ bezierCurves: true,
64
+ animations: true,
65
+ textQuality: "medium",
66
+ antialiasing: true
67
+ };
68
+ var QUALITY_LOW = {
69
+ shadows: false,
70
+ bezierCurves: false,
71
+ animations: false,
72
+ textQuality: "low",
73
+ antialiasing: false
74
+ };
75
+ var FPS_SAMPLE_WINDOW = 60;
76
+ var FPS_UPDATE_INTERVAL = 1e3;
77
+ var MEMORY_CHECK_INTERVAL = 5e3;
78
+ var PERFORMANCE_TOAST_COOLDOWN = 1e4;
79
+ var FPS_DOWNGRADE_THRESHOLD = 45;
80
+ var FPS_UPGRADE_THRESHOLD = 58;
81
+ var FPS_STABILIZATION_FRAMES = 180;
82
+ var DEFAULT_CANVAS_WIDTH = 1920;
83
+ var DEFAULT_CANVAS_HEIGHT = 1080;
84
+ var CLICK_THRESHOLD = 5;
85
+ var DOUBLE_CLICK_DELAY = 300;
86
+ var DRAG_START_DISTANCE = 10;
87
+ var MAX_NODES = 2e4;
88
+ var CIRCULAR_REFERENCE_MAX_DEPTH = 1e3;
89
+ var RESIZE_DEBOUNCE = 300;
90
+ var SCROLL_THROTTLE = 16;
91
+ var SEARCH_DEBOUNCE = 500;
92
+ var NODE_COUNT_THRESHOLDS = {
93
+ SPATIAL_INDEX_MIN: 100,
94
+ VIEWPORT_CULLING_MIN: 500,
95
+ CANVAS_RENDERING_MIN: 2e3,
96
+ DOM_RENDERING_MAX: 5e3
97
+ };
98
+ var VIEWPORT_CONFIG = {
99
+ BUFFER_PERCENT: 0.2,
100
+ MIN_VISIBLE_NODES: 10
101
+ };
102
+
103
+ export {
104
+ FPS_TARGET,
105
+ FPS_WARNING_THRESHOLD,
106
+ FPS_CRITICAL_THRESHOLD,
107
+ TARGET_FRAME_TIME,
108
+ MAX_FRAME_TIME,
109
+ FPS_TARGETS,
110
+ TIMING_THRESHOLDS,
111
+ MEMORY_TARGET_MB,
112
+ MEMORY_WARNING_MB,
113
+ MEMORY_CRITICAL_MB,
114
+ MEMORY_LIMITS,
115
+ VIEWPORT_MARGIN,
116
+ MAX_VISIBLE_NODES,
117
+ CULLING_QUERY_TIME_BUDGET,
118
+ RBUSH_MAX_ENTRIES,
119
+ SPATIAL_INDEX_BUILD_BUDGET,
120
+ NODE_MIN_WIDTH,
121
+ NODE_HEIGHT,
122
+ NODE_PADDING,
123
+ CHAR_WIDTH,
124
+ TITLE_MAX_LENGTH,
125
+ CORNER_RADIUS,
126
+ BORDER_WIDTH_NORMAL,
127
+ BORDER_WIDTH_SELECTED,
128
+ COLOR_SELECTED,
129
+ COLOR_BORDER_LIGHT,
130
+ COLOR_BORDER_DARK,
131
+ COLOR_DEFAULT_NODE,
132
+ ZOOM_MIN,
133
+ ZOOM_MAX,
134
+ ZOOM_DEFAULT,
135
+ ZOOM_STEP,
136
+ ZOOM_WHEEL_SENSITIVITY,
137
+ ZOOM_NAV_IN_THRESHOLD,
138
+ ZOOM_NAV_OUT_THRESHOLD,
139
+ TEXT_LABEL_HIDE_BELOW_ZOOM,
140
+ QUALITY_HIGH,
141
+ QUALITY_MEDIUM,
142
+ QUALITY_LOW,
143
+ FPS_SAMPLE_WINDOW,
144
+ FPS_UPDATE_INTERVAL,
145
+ MEMORY_CHECK_INTERVAL,
146
+ PERFORMANCE_TOAST_COOLDOWN,
147
+ FPS_DOWNGRADE_THRESHOLD,
148
+ FPS_UPGRADE_THRESHOLD,
149
+ FPS_STABILIZATION_FRAMES,
150
+ DEFAULT_CANVAS_WIDTH,
151
+ DEFAULT_CANVAS_HEIGHT,
152
+ CLICK_THRESHOLD,
153
+ DOUBLE_CLICK_DELAY,
154
+ DRAG_START_DISTANCE,
155
+ MAX_NODES,
156
+ CIRCULAR_REFERENCE_MAX_DEPTH,
157
+ RESIZE_DEBOUNCE,
158
+ SCROLL_THROTTLE,
159
+ SEARCH_DEBOUNCE,
160
+ NODE_COUNT_THRESHOLDS,
161
+ VIEWPORT_CONFIG
162
+ };
163
+ //# sourceMappingURL=chunk-LDJRGT2Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants/performanceConstants.ts"],"sourcesContent":["// ─── Performance & Rendering Constants ───────────────────────────────────────\n\n// ── FPS ───────────────────────────────────────────────────────────────────────\n\nexport const FPS_TARGET = 60;\nexport const FPS_WARNING_THRESHOLD = 45;\nexport const FPS_CRITICAL_THRESHOLD = 30;\nexport const TARGET_FRAME_TIME = 1000 / FPS_TARGET; // ~16.67 ms\nexport const MAX_FRAME_TIME = 18; // p95 threshold\n\n/** Legacy frame-rate targets kept for backward compatibility. */\nexport const FPS_TARGETS = {\n PAN_MIN: 30,\n ZOOM_TARGET: 60,\n WARNING_THRESHOLD: 20,\n} as const;\n\n// ── Timing Thresholds (ms) ────────────────────────────────────────────────────\n\nexport const TIMING_THRESHOLDS = {\n VIEWPORT_QUERY_MAX: 5,\n SPATIAL_UPDATE_MAX: 10,\n DRAG_RESPONSE_MAX: 16,\n LOAD_5K_TARGET: 2000,\n LOAD_10K_TARGET: 3000,\n VIEWPORT_DEBOUNCE: 100,\n SPATIAL_INDEX_BUILD: 50,\n} as const;\n\n// ── Memory Limits (MB) ────────────────────────────────────────────────────────\n\nexport const MEMORY_TARGET_MB = 500;\nexport const MEMORY_WARNING_MB = 600;\nexport const MEMORY_CRITICAL_MB = 800;\n\nexport const MEMORY_LIMITS = {\n MAX_10K_NODES: 500,\n MAX_GROWTH_PERCENT: 20,\n WARNING_THRESHOLD: 400,\n} as const;\n\n// ── Viewport Culling ──────────────────────────────────────────────────────────\n\nexport const VIEWPORT_MARGIN = 0.1;\nexport const MAX_VISIBLE_NODES = 800;\nexport const CULLING_QUERY_TIME_BUDGET = 5;\n\n// ── Spatial Index ─────────────────────────────────────────────────────────────\n\nexport const RBUSH_MAX_ENTRIES = 16;\nexport const SPATIAL_INDEX_BUILD_BUDGET = 50;\n\n// ── Node Dimensions ───────────────────────────────────────────────────────────\n\nexport const NODE_MIN_WIDTH = 200;\nexport const NODE_HEIGHT = 80;\nexport const NODE_PADDING = 40;\nexport const CHAR_WIDTH = 8;\nexport const TITLE_MAX_LENGTH = 150;\n\n// ── Visual Styling ────────────────────────────────────────────────────────────\n\nexport const CORNER_RADIUS = 8;\nexport const BORDER_WIDTH_NORMAL = 2;\nexport const BORDER_WIDTH_SELECTED = 3;\n\nexport const COLOR_SELECTED = '#1B2D4F';\nexport const COLOR_BORDER_LIGHT = '#4A3728';\nexport const COLOR_BORDER_DARK = '#FAF6F1';\nexport const COLOR_DEFAULT_NODE = '#FAF6F1';\n\n// ── Zoom Constraints ──────────────────────────────────────────────────────────\n\nexport const ZOOM_MIN = 0.05;\nexport const ZOOM_MAX = 5.0;\nexport const ZOOM_DEFAULT = 1.0;\nexport const ZOOM_STEP = 0.1;\nexport const ZOOM_WHEEL_SENSITIVITY = 0.001;\n\nexport const ZOOM_NAV_IN_THRESHOLD = 2.7;\nexport const ZOOM_NAV_OUT_THRESHOLD = 0.4;\nexport const TEXT_LABEL_HIDE_BELOW_ZOOM = 0.3;\n\n// ── Quality Level Presets ─────────────────────────────────────────────────────\n\nexport const QUALITY_HIGH = {\n shadows: true,\n bezierCurves: true,\n animations: true,\n textQuality: 'high' as const,\n antialiasing: true,\n};\n\nexport const QUALITY_MEDIUM = {\n shadows: false,\n bezierCurves: true,\n animations: true,\n textQuality: 'medium' as const,\n antialiasing: true,\n};\n\nexport const QUALITY_LOW = {\n shadows: false,\n bezierCurves: false,\n animations: false,\n textQuality: 'low' as const,\n antialiasing: false,\n};\n\n// ── Performance Monitoring ────────────────────────────────────────────────────\n\nexport const FPS_SAMPLE_WINDOW = 60;\nexport const FPS_UPDATE_INTERVAL = 1000;\nexport const MEMORY_CHECK_INTERVAL = 5000;\nexport const PERFORMANCE_TOAST_COOLDOWN = 10000;\n\n// ── Auto-Adjustment ───────────────────────────────────────────────────────────\n\nexport const FPS_DOWNGRADE_THRESHOLD = 45;\nexport const FPS_UPGRADE_THRESHOLD = 58;\nexport const FPS_STABILIZATION_FRAMES = 180;\n\n// ── Canvas Dimensions ─────────────────────────────────────────────────────────\n\nexport const DEFAULT_CANVAS_WIDTH = 1920;\nexport const DEFAULT_CANVAS_HEIGHT = 1080;\n\n// ── Interaction ───────────────────────────────────────────────────────────────\n\nexport const CLICK_THRESHOLD = 5;\nexport const DOUBLE_CLICK_DELAY = 300;\nexport const DRAG_START_DISTANCE = 10;\n\n// ── Data Validation ───────────────────────────────────────────────────────────\n\nexport const MAX_NODES = 20000;\nexport const CIRCULAR_REFERENCE_MAX_DEPTH = 1000;\n\n// ── Debounce / Throttle ───────────────────────────────────────────────────────\n\nexport const RESIZE_DEBOUNCE = 300;\nexport const SCROLL_THROTTLE = 16;\nexport const SEARCH_DEBOUNCE = 500;\n\n/** Node count thresholds that gate optimisation strategies. */\nexport const NODE_COUNT_THRESHOLDS = {\n SPATIAL_INDEX_MIN: 100,\n VIEWPORT_CULLING_MIN: 500,\n CANVAS_RENDERING_MIN: 2000,\n DOM_RENDERING_MAX: 5000,\n} as const;\n\n/** Viewport buffer configuration. */\nexport const VIEWPORT_CONFIG = {\n BUFFER_PERCENT: 0.2,\n MIN_VISIBLE_NODES: 10,\n} as const;\n"],"mappings":";AAIO,IAAM,aAA6B;AACnC,IAAM,wBAA6B;AACnC,IAAM,yBAA6B;AACnC,IAAM,oBAA6B,MAAO;AAC1C,IAAM,iBAA6B;AAGnC,IAAM,cAAc;AAAA,EACzB,SAAmB;AAAA,EACnB,aAAmB;AAAA,EACnB,mBAAmB;AACrB;AAIO,IAAM,oBAAoB;AAAA,EAC/B,oBAAuB;AAAA,EACvB,oBAAuB;AAAA,EACvB,mBAAuB;AAAA,EACvB,gBAAuB;AAAA,EACvB,iBAAuB;AAAA,EACvB,mBAAuB;AAAA,EACvB,qBAAuB;AACzB;AAIO,IAAM,mBAAqB;AAC3B,IAAM,oBAAqB;AAC3B,IAAM,qBAAqB;AAE3B,IAAM,gBAAgB;AAAA,EAC3B,eAAqB;AAAA,EACrB,oBAAqB;AAAA,EACrB,mBAAqB;AACvB;AAIO,IAAM,kBAA2B;AACjC,IAAM,oBAA2B;AACjC,IAAM,4BAA4B;AAIlC,IAAM,oBAA2B;AACjC,IAAM,6BAA6B;AAInC,IAAM,iBAAoB;AAC1B,IAAM,cAAoB;AAC1B,IAAM,eAAoB;AAC1B,IAAM,aAAoB;AAC1B,IAAM,mBAAoB;AAI1B,IAAM,gBAAwB;AAC9B,IAAM,sBAAwB;AAC9B,IAAM,wBAAwB;AAE9B,IAAM,iBAAsB;AAC5B,IAAM,qBAAsB;AAC5B,IAAM,oBAAsB;AAC5B,IAAM,qBAAsB;AAI5B,IAAM,WAAwB;AAC9B,IAAM,WAAwB;AAC9B,IAAM,eAAwB;AAC9B,IAAM,YAAwB;AAC9B,IAAM,yBAAyB;AAE/B,IAAM,wBAAyB;AAC/B,IAAM,yBAAyB;AAC/B,IAAM,6BAA6B;AAInC,IAAM,eAAe;AAAA,EAC1B,SAAc;AAAA,EACd,cAAc;AAAA,EACd,YAAc;AAAA,EACd,aAAc;AAAA,EACd,cAAc;AAChB;AAEO,IAAM,iBAAiB;AAAA,EAC5B,SAAc;AAAA,EACd,cAAc;AAAA,EACd,YAAc;AAAA,EACd,aAAc;AAAA,EACd,cAAc;AAChB;AAEO,IAAM,cAAc;AAAA,EACzB,SAAc;AAAA,EACd,cAAc;AAAA,EACd,YAAc;AAAA,EACd,aAAc;AAAA,EACd,cAAc;AAChB;AAIO,IAAM,oBAA6B;AACnC,IAAM,sBAA6B;AACnC,IAAM,wBAA6B;AACnC,IAAM,6BAA6B;AAInC,IAAM,0BAA6B;AACnC,IAAM,wBAA6B;AACnC,IAAM,2BAA6B;AAInC,IAAM,uBAAwB;AAC9B,IAAM,wBAAwB;AAI9B,IAAM,kBAAuB;AAC7B,IAAM,qBAAuB;AAC7B,IAAM,sBAAuB;AAI7B,IAAM,YAA+B;AACrC,IAAM,+BAA+B;AAIrC,IAAM,kBAAmB;AACzB,IAAM,kBAAmB;AACzB,IAAM,kBAAmB;AAGzB,IAAM,wBAAwB;AAAA,EACnC,mBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,mBAAsB;AACxB;AAGO,IAAM,kBAAkB;AAAA,EAC7B,gBAAkB;AAAA,EAClB,mBAAmB;AACrB;","names":[]}
@@ -0,0 +1,98 @@
1
+ // src/layout/layoutUtils.ts
2
+ function getNodeBounds(node) {
3
+ const baseWidth = Math.max(120, node.title.length * 8 + 40);
4
+ const baseHeight = Math.max(40, 32 + 16);
5
+ const padding = 20;
6
+ return {
7
+ x: node.x - baseWidth / 2 - padding,
8
+ y: node.y - baseHeight / 2 - padding,
9
+ width: baseWidth + padding * 2,
10
+ height: baseHeight + padding * 2
11
+ };
12
+ }
13
+ function checkCollision(box1, box2) {
14
+ return !(box1.x + box1.width < box2.x || box2.x + box2.width < box1.x || box1.y + box1.height < box2.y || box2.y + box2.height < box1.y);
15
+ }
16
+ function resolveCollisions(nodes, maxIterations = 10) {
17
+ const result = [...nodes];
18
+ for (let iter = 0; iter < maxIterations; iter++) {
19
+ let hasCollisions = false;
20
+ const byLevel = result.reduce((acc, n) => {
21
+ var _a;
22
+ (acc[_a = n.level] ?? (acc[_a] = [])).push(n);
23
+ return acc;
24
+ }, {});
25
+ for (const levelNodes of Object.values(byLevel)) {
26
+ for (let i = 0; i < levelNodes.length; i++) {
27
+ for (let j = i + 1; j < levelNodes.length; j++) {
28
+ const n1 = levelNodes[i];
29
+ const n2 = levelNodes[j];
30
+ if (!checkCollision(getNodeBounds(n1), getNodeBounds(n2))) continue;
31
+ hasCollisions = true;
32
+ const dx = n2.x - n1.x;
33
+ const dy = n2.y - n1.y;
34
+ const dist = Math.sqrt(dx * dx + dy * dy);
35
+ if (dist < 1) {
36
+ n2.x += 100;
37
+ } else {
38
+ const b1 = getNodeBounds(n1);
39
+ const b2 = getNodeBounds(n2);
40
+ const minSep = (b1.width + b2.width) / 2;
41
+ const overlap = minSep - dist + 20;
42
+ if (overlap > 0) {
43
+ const move = overlap / 2;
44
+ n1.x -= dx / dist * move;
45
+ n1.y -= dy / dist * move;
46
+ n2.x += dx / dist * move;
47
+ n2.y += dy / dist * move;
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ if (!hasCollisions) break;
54
+ }
55
+ return result;
56
+ }
57
+ function optimizeLayout(nodes) {
58
+ const result = [...nodes];
59
+ const iterations = 5;
60
+ const repulsion = 1e3;
61
+ const damp = 0.8;
62
+ for (let iter = 0; iter < iterations; iter++) {
63
+ const forces = /* @__PURE__ */ new Map();
64
+ result.forEach((n) => forces.set(n.id, { x: 0, y: 0 }));
65
+ for (let i = 0; i < result.length; i++) {
66
+ for (let j = i + 1; j < result.length; j++) {
67
+ const n1 = result[i];
68
+ const n2 = result[j];
69
+ if (n1.level !== n2.level) continue;
70
+ const dx = n2.x - n1.x;
71
+ const dy = n2.y - n1.y;
72
+ const dist = Math.sqrt(dx * dx + dy * dy);
73
+ if (dist <= 0 || dist >= 300) continue;
74
+ const force = repulsion / (dist * dist);
75
+ const f1 = forces.get(n1.id);
76
+ const f2 = forces.get(n2.id);
77
+ f1.x -= dx / dist * force;
78
+ f1.y -= dy / dist * force;
79
+ f2.x += dx / dist * force;
80
+ f2.y += dy / dist * force;
81
+ }
82
+ }
83
+ result.forEach((n) => {
84
+ const f = forces.get(n.id);
85
+ n.x += f.x * damp;
86
+ n.y += f.y * damp;
87
+ });
88
+ }
89
+ return resolveCollisions(result);
90
+ }
91
+
92
+ export {
93
+ getNodeBounds,
94
+ checkCollision,
95
+ resolveCollisions,
96
+ optimizeLayout
97
+ };
98
+ //# sourceMappingURL=chunk-LI3BVD6H.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/layout/layoutUtils.ts"],"sourcesContent":["// ─── Layout Utilities ─────────────────────────────────────────────────────────\n//\n// Collision detection and force-based positioning for MindMapNode trees.\n\nimport type { MindMapNode } from '../types/mindmap.js';\n\nexport interface CollisionBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Axis-aligned bounding box for a node, expanded by a fixed padding. */\nexport function getNodeBounds(node: MindMapNode): CollisionBox {\n const baseWidth = Math.max(120, node.title.length * 8 + 40);\n const baseHeight = Math.max(40, 32 + 16);\n const padding = 20;\n return {\n x: node.x - baseWidth / 2 - padding,\n y: node.y - baseHeight / 2 - padding,\n width: baseWidth + padding * 2,\n height: baseHeight + padding * 2,\n };\n}\n\nexport function checkCollision(box1: CollisionBox, box2: CollisionBox): boolean {\n return !(\n box1.x + box1.width < box2.x ||\n box2.x + box2.width < box1.x ||\n box1.y + box1.height < box2.y ||\n box2.y + box2.height < box1.y\n );\n}\n\n/**\n * Iteratively resolve bounding-box collisions within each level.\n * Nodes are pushed apart symmetrically until no overlaps remain\n * or `maxIterations` is reached.\n */\nexport function resolveCollisions(nodes: MindMapNode[], maxIterations = 10): MindMapNode[] {\n const result = [...nodes];\n\n for (let iter = 0; iter < maxIterations; iter++) {\n let hasCollisions = false;\n\n const byLevel = result.reduce<Record<number, MindMapNode[]>>((acc, n) => {\n (acc[n.level] ??= []).push(n);\n return acc;\n }, {});\n\n for (const levelNodes of Object.values(byLevel)) {\n for (let i = 0; i < levelNodes.length; i++) {\n for (let j = i + 1; j < levelNodes.length; j++) {\n const n1 = levelNodes[i];\n const n2 = levelNodes[j];\n if (!checkCollision(getNodeBounds(n1), getNodeBounds(n2))) continue;\n\n hasCollisions = true;\n const dx = n2.x - n1.x;\n const dy = n2.y - n1.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n if (dist < 1) {\n n2.x += 100;\n } else {\n const b1 = getNodeBounds(n1);\n const b2 = getNodeBounds(n2);\n const minSep = (b1.width + b2.width) / 2;\n const overlap = minSep - dist + 20;\n if (overlap > 0) {\n const move = overlap / 2;\n n1.x -= (dx / dist) * move;\n n1.y -= (dy / dist) * move;\n n2.x += (dx / dist) * move;\n n2.y += (dy / dist) * move;\n }\n }\n }\n }\n }\n\n if (!hasCollisions) break;\n }\n\n return result;\n}\n\n/**\n * Apply a lightweight repulsive force between same-level nodes that are\n * closer than 300 px, then resolve remaining collisions.\n */\nexport function optimizeLayout(nodes: MindMapNode[]): MindMapNode[] {\n const result = [...nodes];\n const iterations = 5;\n const repulsion = 1000;\n const damp = 0.8;\n\n for (let iter = 0; iter < iterations; iter++) {\n const forces = new Map<string, { x: number; y: number }>();\n result.forEach(n => forces.set(n.id, { x: 0, y: 0 }));\n\n for (let i = 0; i < result.length; i++) {\n for (let j = i + 1; j < result.length; j++) {\n const n1 = result[i];\n const n2 = result[j];\n if (n1.level !== n2.level) continue;\n\n const dx = n2.x - n1.x;\n const dy = n2.y - n1.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n if (dist <= 0 || dist >= 300) continue;\n\n const force = repulsion / (dist * dist);\n const f1 = forces.get(n1.id)!;\n const f2 = forces.get(n2.id)!;\n f1.x -= (dx / dist) * force;\n f1.y -= (dy / dist) * force;\n f2.x += (dx / dist) * force;\n f2.y += (dy / dist) * force;\n }\n }\n\n result.forEach(n => {\n const f = forces.get(n.id)!;\n n.x += f.x * damp;\n n.y += f.y * damp;\n });\n }\n\n return resolveCollisions(result);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,95 @@
1
+ import {
2
+ DEFAULT_CANVAS_HEIGHT,
3
+ DEFAULT_CANVAS_WIDTH,
4
+ VIEWPORT_MARGIN,
5
+ ZOOM_MAX,
6
+ ZOOM_MIN
7
+ } from "./chunk-LDJRGT2Q.js";
8
+
9
+ // src/viewport/viewportUtils.ts
10
+ function calculateViewportBounds(viewport, canvasWidth = DEFAULT_CANVAS_WIDTH, canvasHeight = DEFAULT_CANVAS_HEIGHT) {
11
+ const worldW = canvasWidth / viewport.zoomLevel;
12
+ const worldH = canvasHeight / viewport.zoomLevel;
13
+ const mx = worldW * VIEWPORT_MARGIN;
14
+ const my = worldH * VIEWPORT_MARGIN;
15
+ return {
16
+ minX: viewport.centerX - worldW / 2 - mx,
17
+ minY: viewport.centerY - worldH / 2 - my,
18
+ maxX: viewport.centerX + worldW / 2 + mx,
19
+ maxY: viewport.centerY + worldH / 2 + my
20
+ };
21
+ }
22
+ function recalculateViewportBounds(viewport, canvasWidth = DEFAULT_CANVAS_WIDTH, canvasHeight = DEFAULT_CANVAS_HEIGHT) {
23
+ return {
24
+ ...viewport,
25
+ visibleBounds: calculateViewportBounds(viewport, canvasWidth, canvasHeight)
26
+ };
27
+ }
28
+ function worldToScreen(worldX, worldY, viewport, canvasWidth = DEFAULT_CANVAS_WIDTH, canvasHeight = DEFAULT_CANVAS_HEIGHT) {
29
+ return {
30
+ x: (worldX - viewport.centerX) * viewport.zoomLevel + canvasWidth / 2,
31
+ y: (worldY - viewport.centerY) * viewport.zoomLevel + canvasHeight / 2
32
+ };
33
+ }
34
+ function screenToWorld(screenX, screenY, viewport, canvasWidth = DEFAULT_CANVAS_WIDTH, canvasHeight = DEFAULT_CANVAS_HEIGHT) {
35
+ return {
36
+ x: (screenX - canvasWidth / 2) / viewport.zoomLevel + viewport.centerX,
37
+ y: (screenY - canvasHeight / 2) / viewport.zoomLevel + viewport.centerY
38
+ };
39
+ }
40
+ function clampZoom(zoom) {
41
+ return Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, zoom));
42
+ }
43
+ function panViewport(deltaX, deltaY, viewport) {
44
+ return {
45
+ ...viewport,
46
+ centerX: viewport.centerX - deltaX / viewport.zoomLevel,
47
+ centerY: viewport.centerY - deltaY / viewport.zoomLevel
48
+ };
49
+ }
50
+ function setViewportCenter(x, y, viewport) {
51
+ return { ...viewport, centerX: x, centerY: y };
52
+ }
53
+ function zoomViewport(delta, viewport, pivotX, pivotY, canvasWidth = DEFAULT_CANVAS_WIDTH, canvasHeight = DEFAULT_CANVAS_HEIGHT) {
54
+ const newZoom = clampZoom(viewport.zoomLevel * (1 + delta));
55
+ let cx = viewport.centerX;
56
+ let cy = viewport.centerY;
57
+ if (pivotX !== void 0 && pivotY !== void 0) {
58
+ const worldPivot = screenToWorld(pivotX, pivotY, viewport, canvasWidth, canvasHeight);
59
+ cx = worldPivot.x - (pivotX - canvasWidth / 2) / newZoom;
60
+ cy = worldPivot.y - (pivotY - canvasHeight / 2) / newZoom;
61
+ }
62
+ return { ...viewport, centerX: cx, centerY: cy, zoomLevel: newZoom };
63
+ }
64
+ function focusOnNode(nodeX, nodeY, zoom) {
65
+ const clamped = clampZoom(zoom);
66
+ return {
67
+ centerX: nodeX,
68
+ centerY: nodeY,
69
+ zoomLevel: clamped,
70
+ rotation: 0,
71
+ visibleBounds: calculateViewportBounds(
72
+ { centerX: nodeX, centerY: nodeY, zoomLevel: clamped, rotation: 0, visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 } }
73
+ )
74
+ };
75
+ }
76
+ function isNodeInViewport(nodeX, nodeY, nodeWidth, nodeHeight, viewport, canvasWidth = DEFAULT_CANVAS_WIDTH, canvasHeight = DEFAULT_CANVAS_HEIGHT) {
77
+ const bounds = calculateViewportBounds(viewport, canvasWidth, canvasHeight);
78
+ const hw = nodeWidth / 2;
79
+ const hh = nodeHeight / 2;
80
+ return !(nodeX + hw < bounds.minX || nodeX - hw > bounds.maxX || nodeY + hh < bounds.minY || nodeY - hh > bounds.maxY);
81
+ }
82
+
83
+ export {
84
+ calculateViewportBounds,
85
+ recalculateViewportBounds,
86
+ worldToScreen,
87
+ screenToWorld,
88
+ clampZoom,
89
+ panViewport,
90
+ setViewportCenter,
91
+ zoomViewport,
92
+ focusOnNode,
93
+ isNodeInViewport
94
+ };
95
+ //# sourceMappingURL=chunk-LJYSKSCE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/viewport/viewportUtils.ts"],"sourcesContent":["// ─── Viewport Utilities ───────────────────────────────────────────────────────\n//\n// Pure functions for viewport bounds calculation, coordinate transforms,\n// pan/zoom operations, and node visibility queries.\n\nimport type { ViewportState } from '../types/mindmap.js';\nimport {\n VIEWPORT_MARGIN,\n DEFAULT_CANVAS_WIDTH,\n DEFAULT_CANVAS_HEIGHT,\n ZOOM_MIN,\n ZOOM_MAX,\n} from '../constants/performanceConstants.js';\n\n// ── Viewport Bounds ───────────────────────────────────────────────────────────\n\nexport interface WorldBounds {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\n/**\n * Calculate the visible world-space bounding box including a margin buffer.\n */\nexport function calculateViewportBounds(\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): WorldBounds {\n const worldW = canvasWidth / viewport.zoomLevel;\n const worldH = canvasHeight / viewport.zoomLevel;\n const mx = worldW * VIEWPORT_MARGIN;\n const my = worldH * VIEWPORT_MARGIN;\n return {\n minX: viewport.centerX - worldW / 2 - mx,\n minY: viewport.centerY - worldH / 2 - my,\n maxX: viewport.centerX + worldW / 2 + mx,\n maxY: viewport.centerY + worldH / 2 + my,\n };\n}\n\n/**\n * Return a new ViewportState with `visibleBounds` recalculated.\n */\nexport function recalculateViewportBounds(\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): ViewportState {\n return {\n ...viewport,\n visibleBounds: calculateViewportBounds(viewport, canvasWidth, canvasHeight),\n };\n}\n\n// ── Coordinate Transforms ─────────────────────────────────────────────────────\n\n/**\n * Convert world-space coordinates to screen-space pixel coordinates.\n */\nexport function worldToScreen(\n worldX: number,\n worldY: number,\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): { x: number; y: number } {\n return {\n x: (worldX - viewport.centerX) * viewport.zoomLevel + canvasWidth / 2,\n y: (worldY - viewport.centerY) * viewport.zoomLevel + canvasHeight / 2,\n };\n}\n\n/**\n * Convert screen-space pixel coordinates to world-space coordinates.\n */\nexport function screenToWorld(\n screenX: number,\n screenY: number,\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): { x: number; y: number } {\n return {\n x: (screenX - canvasWidth / 2) / viewport.zoomLevel + viewport.centerX,\n y: (screenY - canvasHeight / 2) / viewport.zoomLevel + viewport.centerY,\n };\n}\n\n// ── Pan / Zoom ────────────────────────────────────────────────────────────────\n\n/** Clamp zoom to [ZOOM_MIN, ZOOM_MAX]. */\nexport function clampZoom(zoom: number): number {\n return Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, zoom));\n}\n\n/**\n * Pan the viewport by a screen-space delta (positive = right/down).\n */\nexport function panViewport(\n deltaX: number,\n deltaY: number,\n viewport: ViewportState,\n): ViewportState {\n return {\n ...viewport,\n centerX: viewport.centerX - deltaX / viewport.zoomLevel,\n centerY: viewport.centerY - deltaY / viewport.zoomLevel,\n };\n}\n\n/** Teleport the viewport centre to the given world coordinates. */\nexport function setViewportCenter(\n x: number,\n y: number,\n viewport: ViewportState,\n): ViewportState {\n return { ...viewport, centerX: x, centerY: y };\n}\n\n/**\n * Zoom the viewport by a multiplicative delta, optionally around a pivot point.\n *\n * @param delta - Multiplier delta, e.g. 0.1 for +10% zoom\n * @param pivotX - Optional screen-space X pivot\n * @param pivotY - Optional screen-space Y pivot\n */\nexport function zoomViewport(\n delta: number,\n viewport: ViewportState,\n pivotX?: number,\n pivotY?: number,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): ViewportState {\n const newZoom = clampZoom(viewport.zoomLevel * (1 + delta));\n\n let cx = viewport.centerX;\n let cy = viewport.centerY;\n\n if (pivotX !== undefined && pivotY !== undefined) {\n const worldPivot = screenToWorld(pivotX, pivotY, viewport, canvasWidth, canvasHeight);\n cx = worldPivot.x - (pivotX - canvasWidth / 2) / newZoom;\n cy = worldPivot.y - (pivotY - canvasHeight / 2) / newZoom;\n }\n\n return { ...viewport, centerX: cx, centerY: cy, zoomLevel: newZoom };\n}\n\n/**\n * Create a viewport centred on a node (world coordinates) at the given zoom level.\n */\nexport function focusOnNode(\n nodeX: number,\n nodeY: number,\n zoom: number,\n): ViewportState {\n const clamped = clampZoom(zoom);\n return {\n centerX: nodeX,\n centerY: nodeY,\n zoomLevel: clamped,\n rotation: 0,\n visibleBounds: calculateViewportBounds(\n { centerX: nodeX, centerY: nodeY, zoomLevel: clamped, rotation: 0, visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 } },\n ),\n };\n}\n\n// ── Visibility ────────────────────────────────────────────────────────────────\n\n/**\n * Test whether a world-space AABB intersects the viewport's visible bounds.\n */\nexport function isNodeInViewport(\n nodeX: number,\n nodeY: number,\n nodeWidth: number,\n nodeHeight: number,\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): boolean {\n const bounds = calculateViewportBounds(viewport, canvasWidth, canvasHeight);\n const hw = nodeWidth / 2;\n const hh = nodeHeight / 2;\n return !(\n nodeX + hw < bounds.minX ||\n nodeX - hw > bounds.maxX ||\n nodeY + hh < bounds.minY ||\n nodeY - hh > bounds.maxY\n );\n}\n"],"mappings":";;;;;;;;;AA0BO,SAAS,wBACd,UACA,cAAe,sBACf,eAAe,uBACF;AACb,QAAM,SAAS,cAAe,SAAS;AACvC,QAAM,SAAS,eAAe,SAAS;AACvC,QAAM,KAAK,SAAS;AACpB,QAAM,KAAK,SAAS;AACpB,SAAO;AAAA,IACL,MAAM,SAAS,UAAU,SAAS,IAAI;AAAA,IACtC,MAAM,SAAS,UAAU,SAAS,IAAI;AAAA,IACtC,MAAM,SAAS,UAAU,SAAS,IAAI;AAAA,IACtC,MAAM,SAAS,UAAU,SAAS,IAAI;AAAA,EACxC;AACF;AAKO,SAAS,0BACd,UACA,cAAe,sBACf,eAAe,uBACA;AACf,SAAO;AAAA,IACL,GAAG;AAAA,IACH,eAAe,wBAAwB,UAAU,aAAa,YAAY;AAAA,EAC5E;AACF;AAOO,SAAS,cACd,QACA,QACA,UACA,cAAe,sBACf,eAAe,uBACW;AAC1B,SAAO;AAAA,IACL,IAAI,SAAS,SAAS,WAAW,SAAS,YAAY,cAAe;AAAA,IACrE,IAAI,SAAS,SAAS,WAAW,SAAS,YAAY,eAAe;AAAA,EACvE;AACF;AAKO,SAAS,cACd,SACA,SACA,UACA,cAAe,sBACf,eAAe,uBACW;AAC1B,SAAO;AAAA,IACL,IAAI,UAAU,cAAe,KAAK,SAAS,YAAY,SAAS;AAAA,IAChE,IAAI,UAAU,eAAe,KAAK,SAAS,YAAY,SAAS;AAAA,EAClE;AACF;AAKO,SAAS,UAAU,MAAsB;AAC9C,SAAO,KAAK,IAAI,UAAU,KAAK,IAAI,UAAU,IAAI,CAAC;AACpD;AAKO,SAAS,YACd,QACA,QACA,UACe;AACf,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,SAAS,UAAU,SAAS,SAAS;AAAA,IAC9C,SAAS,SAAS,UAAU,SAAS,SAAS;AAAA,EAChD;AACF;AAGO,SAAS,kBACd,GACA,GACA,UACe;AACf,SAAO,EAAE,GAAG,UAAU,SAAS,GAAG,SAAS,EAAE;AAC/C;AASO,SAAS,aACd,OACA,UACA,QACA,QACA,cAAe,sBACf,eAAe,uBACA;AACf,QAAM,UAAU,UAAU,SAAS,aAAa,IAAI,MAAM;AAE1D,MAAI,KAAK,SAAS;AAClB,MAAI,KAAK,SAAS;AAElB,MAAI,WAAW,UAAa,WAAW,QAAW;AAChD,UAAM,aAAa,cAAc,QAAQ,QAAQ,UAAU,aAAa,YAAY;AACpF,SAAK,WAAW,KAAK,SAAS,cAAe,KAAK;AAClD,SAAK,WAAW,KAAK,SAAS,eAAe,KAAK;AAAA,EACpD;AAEA,SAAO,EAAE,GAAG,UAAU,SAAS,IAAI,SAAS,IAAI,WAAW,QAAQ;AACrE;AAKO,SAAS,YACd,OACA,OACA,MACe;AACf,QAAM,UAAU,UAAU,IAAI;AAC9B,SAAO;AAAA,IACL,SAAU;AAAA,IACV,SAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,eAAe;AAAA,MACb,EAAE,SAAS,OAAO,SAAS,OAAO,WAAW,SAAS,UAAU,GAAG,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,EAAE;AAAA,IAC3H;AAAA,EACF;AACF;AAOO,SAAS,iBACd,OACA,OACA,WACA,YACA,UACA,cAAe,sBACf,eAAe,uBACN;AACT,QAAM,SAAS,wBAAwB,UAAU,aAAa,YAAY;AAC1E,QAAM,KAAK,YAAa;AACxB,QAAM,KAAK,aAAa;AACxB,SAAO,EACL,QAAQ,KAAK,OAAO,QACpB,QAAQ,KAAK,OAAO,QACpB,QAAQ,KAAK,OAAO,QACpB,QAAQ,KAAK,OAAO;AAExB;","names":[]}