@visualli/core 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +263 -0
  2. package/dist/index.cjs +2325 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +1181 -0
  5. package/dist/index.d.ts +1181 -0
  6. package/dist/index.js +2119 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +80 -0
  9. package/src/animations/constants.ts +72 -0
  10. package/src/animations/easing.ts +70 -0
  11. package/src/animations/index.ts +2 -0
  12. package/src/config/blobShapes.ts +146 -0
  13. package/src/config/textScaling.ts +54 -0
  14. package/src/constants/design.ts +281 -0
  15. package/src/constants/index.ts +3 -0
  16. package/src/constants/performanceConstants.ts +157 -0
  17. package/src/constants/renderConfig.ts +134 -0
  18. package/src/index.ts +18 -0
  19. package/src/layout/circularLayout.ts +95 -0
  20. package/src/layout/index.ts +3 -0
  21. package/src/layout/layoutUtils.ts +132 -0
  22. package/src/layout/linearLayout.ts +84 -0
  23. package/src/parser/configUtils.ts +129 -0
  24. package/src/parser/index.ts +4 -0
  25. package/src/parser/middleware.ts +24 -0
  26. package/src/parser/mindmapUtils.ts +76 -0
  27. package/src/parser/visualliConverter.ts +328 -0
  28. package/src/parser/visualliParser.ts +191 -0
  29. package/src/performance/index.ts +1 -0
  30. package/src/performance/performanceMonitor.ts +145 -0
  31. package/src/rendering/culling.ts +71 -0
  32. package/src/spatial/index.ts +1 -0
  33. package/src/spatial/spatialIndex.ts +83 -0
  34. package/src/stores/index.ts +61 -0
  35. package/src/types/document.ts +15 -0
  36. package/src/types/index.ts +17 -0
  37. package/src/types/layer.ts +67 -0
  38. package/src/types/meta.ts +9 -0
  39. package/src/types/mindmap.ts +136 -0
  40. package/src/types/schema.ts +36 -0
  41. package/src/utils/navigation.ts +161 -0
  42. package/src/viewport/index.ts +1 -0
  43. package/src/viewport/viewportUtils.ts +195 -0
package/README.md ADDED
@@ -0,0 +1,263 @@
1
+ # @visualli/core
2
+
3
+ Framework-agnostic core logic, types, and algorithms for Visualli. Zero React / DOM dependencies.
4
+
5
+ ## Features
6
+
7
+ | Module | What it provides |
8
+ |--------|------------------|
9
+ | **Types** | Full TypeScript interfaces for `VisualliDocument`, `VisualliLayer`, `FlatNode`, `ViewportState`, `RenderConfig`, `Connection`, and more |
10
+ | **Parser** | Parse `.visualli` JSONL files, convert layers to flat nodes, resolve spatial overlaps |
11
+ | **Layout** | Circular and linear layout algorithms with automatic radius/spacing calculation |
12
+ | **Viewport** | Pure pan/zoom/bounds math — world↔screen coordinate transforms, fit-to-screen |
13
+ | **Spatial index** | RBush-backed O(log n) spatial index for viewport culling of large node graphs |
14
+ | **Animations** | Easing functions (cubic, quartic, sine, bezier LUT) and timing phase constants |
15
+ | **Performance** | rAF-based FPS monitor, memory monitor, profiler |
16
+ | **Constants** | Design tokens (colors, spacing, typography), zoom limits, FPS targets, render config |
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @visualli/core
22
+ ```
23
+
24
+ > **Only dependency:** [`rbush`](https://github.com/mourner/rbush) — no React, no Zod, no network code.
25
+
26
+ ## Quick Start
27
+
28
+ ### Parse a document
29
+
30
+ ```ts
31
+ import { parseVisualliFile, getNodesForLayer } from '@visualli/core';
32
+
33
+ // Parse from a raw JSONL string
34
+ const doc = parseVisualliFile(rawJsonlString);
35
+
36
+ // Get the root layer
37
+ const rootLayerId = [...doc.layers.keys()][0];
38
+ const nodes = getNodesForLayer(doc, rootLayerId); // FlatNode[]
39
+ ```
40
+
41
+ ### Apply layouts
42
+
43
+ ```ts
44
+ import { applyCircularLayout, applyLinearHorizontalLayout } from '@visualli/core';
45
+
46
+ applyCircularLayout(nodes); // mutates x/y in-place
47
+ applyLinearHorizontalLayout(nodes); // horizontal tree layout
48
+ ```
49
+
50
+ ### Viewport math
51
+
52
+ ```ts
53
+ import {
54
+ zoomViewport, panViewport, setViewportCenter,
55
+ calculateViewportBounds, worldToScreen, screenToWorld,
56
+ } from '@visualli/core';
57
+
58
+ const next = zoomViewport(delta, viewport, pivotX, pivotY, canvasW, canvasH);
59
+ const bounds = calculateViewportBounds(viewport, canvasW, canvasH);
60
+ const screenPt = worldToScreen(worldX, worldY, viewport, canvasW, canvasH);
61
+ ```
62
+
63
+ ### Spatial culling
64
+
65
+ ```ts
66
+ import { RBushSpatialIndex } from '@visualli/core';
67
+
68
+ const index = new RBushSpatialIndex();
69
+ index.bulkLoad(nodes.map(n => ({
70
+ nodeId: n.id,
71
+ bounds: { minX: n.x, minY: n.y, maxX: n.x + n.width, maxY: n.y + n.height },
72
+ })));
73
+
74
+ // Query visible nodes
75
+ const visible = index.query(viewportBounds); // string[] — node IDs
76
+ ```
77
+
78
+ ### Easing
79
+
80
+ ```ts
81
+ import { easeInOutCubic, easeOutCubic, createCubicBezier } from '@visualli/core';
82
+
83
+ const t = easeInOutCubic(progress); // 0..1 → 0..1
84
+ const custom = createCubicBezier(0.4, 0, 0.2, 1); // CSS timing function
85
+ ```
86
+
87
+ ### Colors & design tokens
88
+
89
+ ```ts
90
+ import {
91
+ getColorForLevel, getThemeBackground,
92
+ LEVEL_COLOR_ARRAY, DS_COLORS, BRAND_COLORS,
93
+ } from '@visualli/core';
94
+
95
+ const nodeColor = getColorForLevel(2); // '#...' for level 2
96
+ const bg = getThemeBackground(isDark); // canvas background
97
+ ```
98
+
99
+ ## Module Reference
100
+
101
+ ### `types/`
102
+
103
+ | Export | Description |
104
+ |--------|-------------|
105
+ | `VisualliDocument` | Top-level document (layers Map, extensions Map) |
106
+ | `VisualliLayer` | A single layer: level, nodes, connections, containers |
107
+ | `FlatNode` | Renderable node (position, size, title, color, level, parentId) |
108
+ | `NodeMap` | `Map<string, FlatNode>` |
109
+ | `ViewportState` | `centerX/Y`, `zoomLevel`, `rotation`, `visibleBounds` |
110
+ | `RenderConfig` | Quality level, FPS target, culling flag, render mode |
111
+ | `Connection` | Edge: `from`, `to`, `level`, optional `label` |
112
+
113
+ ### `parser/`
114
+
115
+ | Export | Description |
116
+ |--------|-------------|
117
+ | `parseVisualliFile(str)` | Parse JSONL → `VisualliDocument` |
118
+ | `loadVisualliFileFromFile(file)` | Parse a browser `File` object |
119
+ | `getNodesForLayer(doc, layerId)` | `FlatNode[]` for one layer |
120
+ | `convertVisualliToFlatNodes(doc)` | All layers → `NodeMap` |
121
+ | `getChildLayers(doc, layerId)` | Direct child layers |
122
+
123
+ ### `layout/`
124
+
125
+ | Export | Description |
126
+ |--------|-------------|
127
+ | `applyCircularLayout(nodes)` | Radial arrangement |
128
+ | `applyLinearHorizontalLayout(nodes)` | Left-to-right tree |
129
+ | `applyLinearVerticalLayout(nodes)` | Top-to-bottom tree |
130
+ | `resolveCollisions(nodes)` | Push apart overlapping nodes |
131
+
132
+ ### `viewport/`
133
+
134
+ | Export | Description |
135
+ |--------|-------------|
136
+ | `calculateViewportBounds(vp, w, h)` | Visible world rect |
137
+ | `zoomViewport(delta, vp, px, py, w, h)` | Zoom to cursor |
138
+ | `panViewport(dx, dy, vp)` | Translate camera |
139
+ | `setViewportCenter(x, y, vp)` | Teleport center |
140
+ | `clampZoom(level)` | Clamp to `[ZOOM_MIN, ZOOM_MAX]` |
141
+ | `worldToScreen(x, y, vp, w, h)` | World → screen px |
142
+ | `screenToWorld(x, y, vp, w, h)` | Screen px → world |
143
+
144
+ ### `constants/`
145
+
146
+ | Export | Description |
147
+ |--------|-------------|
148
+ | `ZOOM_MIN` / `ZOOM_MAX` | `0.3` / `5.0` |
149
+ | `ZOOM_NAV_IN_THRESHOLD` | `2.7` — zoom level that triggers drill-in |
150
+ | `ZOOM_NAV_OUT_THRESHOLD` | `0.4` — zoom level that triggers back navigation |
151
+ | `LEVEL_COLOR_ARRAY` | 10-color palette indexed by node level |
152
+ | `DEFAULT_RENDER_CONFIG` | Baseline quality settings |
153
+ | `ANIMATION_PHASES` | Duration constants for layer transitions |
154
+
155
+ ## TypeScript
156
+
157
+ The package ships `.d.ts` declarations alongside source maps. `moduleResolution: "bundler"` is recommended (compatible with Vite / esbuild).
158
+
159
+ ```jsonc
160
+ // tsconfig.json
161
+ {
162
+ "compilerOptions": {
163
+ "moduleResolution": "bundler",
164
+ "target": "ES2020"
165
+ }
166
+ }
167
+ ```
168
+
169
+ ## Build
170
+
171
+ ```bash
172
+ npm run build # tsc → dist/
173
+ npm run typecheck # tsc --noEmit (0 errors expected)
174
+ ```
175
+
176
+
177
+ ## Structure
178
+
179
+ ```
180
+ src/
181
+ ├── types/ TypeScript interfaces, enums, Zod schemas
182
+ │ ├── mindmap.ts MindMapNode, FlatNode, NodeMap, ViewportState, RenderConfig …
183
+ │ ├── meta.ts VisualliMeta
184
+ │ ├── layer.ts VisualliLayer, LayerNode, LayerConnection, LayerContainer …
185
+ │ ├── extension.ts VisualliExtension
186
+ │ ├── document.ts VisualliDocument
187
+ │ ├── schema.ts JSON-schema-aligned types + re-exports
188
+ │ ├── processing.ts ConnectionState, ProcessingState, type guards
189
+ │ └── sse.ts SSEEvent discriminated union + Zod validation + helpers
190
+ │
191
+ ├── layout/ Pure layout algorithms (no side-effects)
192
+ │ ├── circularLayout.ts applyCircularLayout, calculateOptimalRadiusPercentage
193
+ │ ├── linearLayout.ts applyLinearHorizontalLayout, applyLinearVerticalLayout
194
+ │ └── layoutUtils.ts getNodeBounds, resolveCollisions, optimizeLayout
195
+ │
196
+ ├── parser/ File parsing and data conversion
197
+ │ ├── visualliParser.ts parseVisualliFile, loadVisualliFile, getChildLayers …
198
+ │ ├── visualliConverter.ts convertVisualliToFlatNodes, resolveNodeOverlaps …
199
+ │ ├── mindmapUtils.ts flattenNodes, getVisibleNodes, calculateDistance …
200
+ │ └── configUtils.ts createMindMapConfig, generateSampleConfig
201
+ │
202
+ ├── services/ Network utilities (fetch, SSE, logging)
203
+ │ ├── api.ts initApi, apiRequest, ApiError, mindmapApi, correlationId helpers
204
+ │ ├── logger.ts Logger class (buffered remote + console)
205
+ │ └── sseClient.ts createSSEClient (fetch ReadableStream, reconnection)
206
+ │
207
+ ├── constants/ Design tokens, performance thresholds, render config
208
+ │ ├── performanceConstants.ts FPS targets, zoom limits, node dimensions …
209
+ │ ├── design.ts DS_COLORS, LEVEL_COLORS, BRAND_COLORS, helpers …
210
+ │ └── renderConfig.ts DEFAULT_RENDER_CONFIG, FEATURE_FLAGS, helpers …
211
+ │
212
+ ├── viewport/ Coordinate math and pan/zoom operations
213
+ │ └── viewportUtils.ts calculateViewportBounds, worldToScreen, zoomViewport …
214
+ │
215
+ ├── performance/ FPS / memory monitoring (browser APIs, no React)
216
+ │ └── performanceMonitor.ts FPSMonitor, MemoryMonitor, PerformanceProfiler
217
+ │
218
+ ├── animations/ Easing functions and timing constants
219
+ │ ├── easing.ts easeInOutCubic, createCubicBezier …
220
+ │ └── constants.ts ANIMATION_DURATION, ANIMATION_PHASES, COOLDOWN …
221
+ │
222
+ └── spatial/ RBush spatial index for O(log n) viewport culling
223
+ └── spatialIndex.ts RBushSpatialIndex, ISpatialIndex, BoundingBox
224
+ ```
225
+
226
+ ## Installation
227
+
228
+ ```bash
229
+ npm install @visualli/core
230
+ ```
231
+
232
+ > **Dependencies:** `zod` (schema validation) · `rbush` (spatial index)
233
+
234
+ ## Quick Start
235
+
236
+ ```ts
237
+ // Parse a .visualli document
238
+ import { parseVisualliFile, convertVisualliToFlatNodes } from '@visualli/core/parser';
239
+
240
+ const doc = parseVisualliFile(rawJsonlString);
241
+ const nodeMap = convertVisualliToFlatNodes(doc);
242
+
243
+ // Apply a circular layout
244
+ import { applyCircularLayout } from '@visualli/core/layout';
245
+ const nodes = [...nodeMap.values()];
246
+ applyCircularLayout(nodes);
247
+
248
+ // Viewport math
249
+ import { zoomViewport } from '@visualli/core/viewport';
250
+ const next = zoomViewport(0.1, currentViewport, pivotX, pivotY);
251
+
252
+ // API client
253
+ import { initApi, mindmapApi } from '@visualli/core/services';
254
+ initApi({ baseUrl: 'https://api.example.com/api' });
255
+ const list = await mindmapApi.getAllMindmaps();
256
+ ```
257
+
258
+ ## Design Principles
259
+
260
+ - **No React** — no hooks, no JSX, no Context
261
+ - **No DOM manipulation** — pure data transforms; browser APIs (`fetch`, `FileReader`) are used only at IO boundaries
262
+ - **No Vite env vars** — configure at runtime via `initApi()`
263
+ - **Tree-shakeable** — import from sub-paths to avoid bundling unused modules