stellavault 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/core/dist/api/dashboard.d.ts +3 -0
- package/packages/core/{src/api/dashboard.ts → dist/api/dashboard.js} +8 -11
- package/packages/core/dist/api/graph-data.d.ts +11 -0
- package/packages/core/dist/api/graph-data.js +255 -0
- package/packages/core/dist/api/pwa.d.ts +3 -0
- package/packages/core/{src/api/pwa.ts → dist/api/pwa.js} +27 -32
- package/packages/core/dist/api/server.d.ts +16 -0
- package/packages/core/dist/api/server.js +718 -0
- package/packages/core/dist/capture/voice.d.ts +24 -0
- package/packages/core/dist/capture/voice.js +135 -0
- package/packages/core/{src/cloud/index.ts → dist/cloud/index.d.ts} +1 -0
- package/packages/core/dist/cloud/index.js +2 -0
- package/packages/core/dist/cloud/sync.d.ts +29 -0
- package/packages/core/dist/cloud/sync.js +137 -0
- package/packages/core/dist/config.d.ts +27 -0
- package/packages/core/dist/config.js +55 -0
- package/packages/core/dist/federation/credits.d.ts +26 -0
- package/packages/core/dist/federation/credits.js +56 -0
- package/packages/core/dist/federation/identity.d.ts +14 -0
- package/packages/core/dist/federation/identity.js +74 -0
- package/packages/core/{src/federation/index.ts → dist/federation/index.d.ts} +1 -2
- package/packages/core/dist/federation/index.js +5 -0
- package/packages/core/dist/federation/node.d.ts +31 -0
- package/packages/core/dist/federation/node.js +216 -0
- package/packages/core/dist/federation/privacy.d.ts +8 -0
- package/packages/core/dist/federation/privacy.js +40 -0
- package/packages/core/dist/federation/reputation.d.ts +37 -0
- package/packages/core/dist/federation/reputation.js +139 -0
- package/packages/core/dist/federation/search.d.ts +19 -0
- package/packages/core/dist/federation/search.js +101 -0
- package/packages/core/dist/federation/sharing.d.ts +72 -0
- package/packages/core/dist/federation/sharing.js +246 -0
- package/packages/core/dist/federation/trust.d.ts +15 -0
- package/packages/core/dist/federation/trust.js +60 -0
- package/packages/core/dist/federation/types.d.ts +40 -0
- package/packages/core/dist/federation/types.js +3 -0
- package/packages/core/dist/i18n/index.d.ts +6 -0
- package/packages/core/dist/i18n/index.js +81 -0
- package/packages/core/{src/index.ts → dist/index.d.ts} +46 -65
- package/packages/core/dist/index.js +69 -0
- package/packages/core/dist/indexer/chunker.d.ts +14 -0
- package/packages/core/dist/indexer/chunker.js +148 -0
- package/packages/core/dist/indexer/embedder.d.ts +8 -0
- package/packages/core/dist/indexer/embedder.js +3 -0
- package/packages/core/dist/indexer/index.d.ts +28 -0
- package/packages/core/dist/indexer/index.js +74 -0
- package/packages/core/dist/indexer/local-embedder.d.ts +3 -0
- package/packages/core/dist/indexer/local-embedder.js +29 -0
- package/packages/core/dist/indexer/scanner.d.ts +11 -0
- package/packages/core/dist/indexer/scanner.js +137 -0
- package/packages/core/dist/indexer/watcher.d.ts +19 -0
- package/packages/core/dist/indexer/watcher.js +49 -0
- package/packages/core/dist/intelligence/code-linker.d.ts +20 -0
- package/packages/core/dist/intelligence/code-linker.js +88 -0
- package/packages/core/dist/intelligence/contradiction-detector.d.ts +20 -0
- package/packages/core/dist/intelligence/contradiction-detector.js +115 -0
- package/packages/core/dist/intelligence/decay-engine.d.ts +27 -0
- package/packages/core/dist/intelligence/decay-engine.js +190 -0
- package/packages/core/dist/intelligence/duplicate-detector.d.ts +20 -0
- package/packages/core/dist/intelligence/duplicate-detector.js +55 -0
- package/packages/core/dist/intelligence/fsrs.d.ts +43 -0
- package/packages/core/dist/intelligence/fsrs.js +70 -0
- package/packages/core/dist/intelligence/gap-detector.d.ts +25 -0
- package/packages/core/dist/intelligence/gap-detector.js +78 -0
- package/packages/core/dist/intelligence/learning-path.d.ts +31 -0
- package/packages/core/dist/intelligence/learning-path.js +53 -0
- package/packages/core/dist/intelligence/notifications.d.ts +31 -0
- package/packages/core/dist/intelligence/notifications.js +65 -0
- package/packages/core/dist/intelligence/predictive-gaps.d.ts +14 -0
- package/packages/core/dist/intelligence/predictive-gaps.js +74 -0
- package/packages/core/dist/intelligence/semantic-versioning.d.ts +37 -0
- package/packages/core/dist/intelligence/semantic-versioning.js +68 -0
- package/packages/core/dist/intelligence/types.d.ts +28 -0
- package/packages/core/dist/intelligence/types.js +3 -0
- package/packages/core/dist/mcp/custom-tools.d.ts +29 -0
- package/packages/core/dist/mcp/custom-tools.js +70 -0
- package/packages/core/{src/mcp/index.ts → dist/mcp/index.d.ts} +1 -0
- package/packages/core/dist/mcp/index.js +2 -0
- package/packages/core/dist/mcp/server.d.ts +49 -0
- package/packages/core/dist/mcp/server.js +151 -0
- package/packages/core/dist/mcp/tools/agentic-graph.d.ts +87 -0
- package/packages/core/dist/mcp/tools/agentic-graph.js +88 -0
- package/packages/core/dist/mcp/tools/brief.d.ts +31 -0
- package/packages/core/dist/mcp/tools/brief.js +39 -0
- package/packages/core/dist/mcp/tools/decay.d.ts +33 -0
- package/packages/core/dist/mcp/tools/decay.js +32 -0
- package/packages/core/dist/mcp/tools/decision-journal.d.ts +78 -0
- package/packages/core/dist/mcp/tools/decision-journal.js +79 -0
- package/packages/core/dist/mcp/tools/detect-gaps.d.ts +24 -0
- package/packages/core/dist/mcp/tools/detect-gaps.js +47 -0
- package/packages/core/dist/mcp/tools/export.d.ts +29 -0
- package/packages/core/dist/mcp/tools/export.js +60 -0
- package/packages/core/dist/mcp/tools/federated-search.d.ts +29 -0
- package/packages/core/dist/mcp/tools/federated-search.js +36 -0
- package/packages/core/dist/mcp/tools/generate-claude-md.d.ts +35 -0
- package/packages/core/dist/mcp/tools/generate-claude-md.js +107 -0
- package/packages/core/dist/mcp/tools/get-document.d.ts +35 -0
- package/packages/core/dist/mcp/tools/get-document.js +25 -0
- package/packages/core/dist/mcp/tools/get-evolution.d.ts +28 -0
- package/packages/core/dist/mcp/tools/get-evolution.js +70 -0
- package/packages/core/dist/mcp/tools/get-related.d.ts +32 -0
- package/packages/core/dist/mcp/tools/get-related.js +33 -0
- package/packages/core/dist/mcp/tools/learning-path.d.ts +23 -0
- package/packages/core/dist/mcp/tools/learning-path.js +45 -0
- package/packages/core/dist/mcp/tools/link-code.d.ts +34 -0
- package/packages/core/dist/mcp/tools/link-code.js +44 -0
- package/packages/core/dist/mcp/tools/list-topics.d.ts +15 -0
- package/packages/core/dist/mcp/tools/list-topics.js +18 -0
- package/packages/core/dist/mcp/tools/search.d.ts +39 -0
- package/packages/core/dist/mcp/tools/search.js +29 -0
- package/packages/core/dist/mcp/tools/snapshot.d.ts +47 -0
- package/packages/core/dist/mcp/tools/snapshot.js +84 -0
- package/packages/core/dist/multi-vault/index.d.ts +26 -0
- package/packages/core/dist/multi-vault/index.js +80 -0
- package/packages/core/dist/pack/creator.d.ts +21 -0
- package/packages/core/dist/pack/creator.js +105 -0
- package/packages/core/dist/pack/exporter.d.ts +4 -0
- package/packages/core/dist/pack/exporter.js +18 -0
- package/packages/core/dist/pack/importer.d.ts +10 -0
- package/packages/core/dist/pack/importer.js +55 -0
- package/packages/core/{src/pack/index.ts → dist/pack/index.d.ts} +1 -0
- package/packages/core/dist/pack/index.js +5 -0
- package/packages/core/dist/pack/marketplace.d.ts +14 -0
- package/packages/core/dist/pack/marketplace.js +90 -0
- package/packages/core/dist/pack/pii-masker.d.ts +7 -0
- package/packages/core/dist/pack/pii-masker.js +29 -0
- package/packages/core/dist/pack/types.d.ts +36 -0
- package/packages/core/dist/pack/types.js +3 -0
- package/packages/core/dist/plugins/index.d.ts +35 -0
- package/packages/core/dist/plugins/index.js +57 -0
- package/packages/core/dist/plugins/webhooks.d.ts +30 -0
- package/packages/core/dist/plugins/webhooks.js +79 -0
- package/packages/core/dist/search/adaptive.d.ts +16 -0
- package/packages/core/dist/search/adaptive.js +67 -0
- package/packages/core/dist/search/bm25.d.ts +4 -0
- package/packages/core/dist/search/bm25.js +10 -0
- package/packages/core/dist/search/index.d.ts +15 -0
- package/packages/core/dist/search/index.js +64 -0
- package/packages/core/dist/search/rrf.d.ts +7 -0
- package/packages/core/dist/search/rrf.js +21 -0
- package/packages/core/dist/search/semantic.d.ts +5 -0
- package/packages/core/dist/search/semantic.js +6 -0
- package/packages/core/{src/store/index.ts → dist/store/index.d.ts} +1 -0
- package/packages/core/dist/store/index.js +2 -0
- package/packages/core/dist/store/sqlite-vec.d.ts +6 -0
- package/packages/core/dist/store/sqlite-vec.js +251 -0
- package/packages/core/dist/store/types.d.ts +20 -0
- package/packages/core/dist/store/types.js +3 -0
- package/packages/core/dist/team/index.d.ts +25 -0
- package/packages/core/dist/team/index.js +97 -0
- package/packages/core/dist/types/chunk.d.ts +23 -0
- package/packages/core/dist/types/chunk.js +3 -0
- package/packages/core/dist/types/document.d.ts +23 -0
- package/packages/core/dist/types/document.js +3 -0
- package/packages/core/dist/types/graph.d.ts +39 -0
- package/packages/core/dist/types/graph.js +3 -0
- package/packages/core/dist/types/index.d.ts +5 -0
- package/packages/core/dist/types/index.js +2 -0
- package/packages/core/dist/types/search.d.ts +39 -0
- package/packages/core/dist/types/search.js +3 -0
- package/packages/core/dist/utils/retry.d.ts +25 -0
- package/packages/core/dist/utils/retry.js +59 -0
- package/.github/workflows/pages.yml +0 -37
- package/memory/MEMORY.md +0 -25
- package/packages/cli/dist/commands/brief-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/brief-cmd.js.map +0 -1
- package/packages/cli/dist/commands/capture-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/capture-cmd.js.map +0 -1
- package/packages/cli/dist/commands/card-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/card-cmd.js.map +0 -1
- package/packages/cli/dist/commands/clip-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/clip-cmd.js.map +0 -1
- package/packages/cli/dist/commands/cloud-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/cloud-cmd.js.map +0 -1
- package/packages/cli/dist/commands/contradictions-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/contradictions-cmd.js.map +0 -1
- package/packages/cli/dist/commands/decay-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/decay-cmd.js.map +0 -1
- package/packages/cli/dist/commands/digest-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/digest-cmd.js.map +0 -1
- package/packages/cli/dist/commands/duplicates-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/duplicates-cmd.js.map +0 -1
- package/packages/cli/dist/commands/federate-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/federate-cmd.js.map +0 -1
- package/packages/cli/dist/commands/gaps-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/gaps-cmd.js.map +0 -1
- package/packages/cli/dist/commands/graph-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/graph-cmd.js.map +0 -1
- package/packages/cli/dist/commands/index-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/index-cmd.js.map +0 -1
- package/packages/cli/dist/commands/init-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/init-cmd.js.map +0 -1
- package/packages/cli/dist/commands/learn-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/learn-cmd.js.map +0 -1
- package/packages/cli/dist/commands/pack-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/pack-cmd.js.map +0 -1
- package/packages/cli/dist/commands/review-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/review-cmd.js.map +0 -1
- package/packages/cli/dist/commands/search-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/search-cmd.js.map +0 -1
- package/packages/cli/dist/commands/serve-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/serve-cmd.js.map +0 -1
- package/packages/cli/dist/commands/status-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/status-cmd.js.map +0 -1
- package/packages/cli/dist/commands/sync-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/sync-cmd.js.map +0 -1
- package/packages/cli/dist/commands/vault-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/vault-cmd.js.map +0 -1
- package/packages/cli/dist/index.d.ts.map +0 -1
- package/packages/cli/dist/index.js.map +0 -1
- package/packages/cli/src/commands/brief-cmd.ts +0 -87
- package/packages/cli/src/commands/capture-cmd.ts +0 -34
- package/packages/cli/src/commands/card-cmd.ts +0 -29
- package/packages/cli/src/commands/clip-cmd.ts +0 -172
- package/packages/cli/src/commands/cloud-cmd.ts +0 -75
- package/packages/cli/src/commands/contradictions-cmd.ts +0 -41
- package/packages/cli/src/commands/decay-cmd.ts +0 -57
- package/packages/cli/src/commands/digest-cmd.ts +0 -89
- package/packages/cli/src/commands/duplicates-cmd.ts +0 -38
- package/packages/cli/src/commands/federate-cmd.ts +0 -256
- package/packages/cli/src/commands/gaps-cmd.ts +0 -40
- package/packages/cli/src/commands/graph-cmd.ts +0 -88
- package/packages/cli/src/commands/index-cmd.ts +0 -65
- package/packages/cli/src/commands/init-cmd.ts +0 -145
- package/packages/cli/src/commands/learn-cmd.ts +0 -56
- package/packages/cli/src/commands/pack-cmd.ts +0 -121
- package/packages/cli/src/commands/review-cmd.ts +0 -125
- package/packages/cli/src/commands/search-cmd.ts +0 -45
- package/packages/cli/src/commands/serve-cmd.ts +0 -17
- package/packages/cli/src/commands/status-cmd.ts +0 -37
- package/packages/cli/src/commands/sync-cmd.ts +0 -68
- package/packages/cli/src/commands/vault-cmd.ts +0 -64
- package/packages/cli/src/index.ts +0 -187
- package/packages/core/src/api/graph-data.ts +0 -286
- package/packages/core/src/api/server.ts +0 -660
- package/packages/core/src/capture/voice.ts +0 -168
- package/packages/core/src/cloud/sync.ts +0 -167
- package/packages/core/src/config.ts +0 -82
- package/packages/core/src/federation/credits.ts +0 -80
- package/packages/core/src/federation/hyperswarm.d.ts +0 -19
- package/packages/core/src/federation/identity.ts +0 -90
- package/packages/core/src/federation/node.ts +0 -235
- package/packages/core/src/federation/privacy.ts +0 -52
- package/packages/core/src/federation/reputation.ts +0 -202
- package/packages/core/src/federation/search.ts +0 -129
- package/packages/core/src/federation/sharing.ts +0 -315
- package/packages/core/src/federation/trust.ts +0 -76
- package/packages/core/src/federation/types.ts +0 -25
- package/packages/core/src/i18n/index.ts +0 -85
- package/packages/core/src/indexer/chunker.ts +0 -180
- package/packages/core/src/indexer/embedder.ts +0 -9
- package/packages/core/src/indexer/index.ts +0 -113
- package/packages/core/src/indexer/local-embedder.ts +0 -35
- package/packages/core/src/indexer/scanner.ts +0 -142
- package/packages/core/src/indexer/watcher.ts +0 -62
- package/packages/core/src/intelligence/contradiction-detector.ts +0 -134
- package/packages/core/src/intelligence/decay-engine.ts +0 -229
- package/packages/core/src/intelligence/duplicate-detector.ts +0 -71
- package/packages/core/src/intelligence/fsrs.ts +0 -79
- package/packages/core/src/intelligence/gap-detector.ts +0 -109
- package/packages/core/src/intelligence/learning-path.ts +0 -86
- package/packages/core/src/intelligence/notifications.ts +0 -106
- package/packages/core/src/intelligence/predictive-gaps.ts +0 -94
- package/packages/core/src/intelligence/semantic-versioning.ts +0 -97
- package/packages/core/src/intelligence/types.ts +0 -28
- package/packages/core/src/mcp/custom-tools.ts +0 -97
- package/packages/core/src/mcp/server.ts +0 -142
- package/packages/core/src/mcp/tools/agentic-graph.ts +0 -96
- package/packages/core/src/mcp/tools/brief.ts +0 -49
- package/packages/core/src/mcp/tools/decay.ts +0 -40
- package/packages/core/src/mcp/tools/decision-journal.ts +0 -95
- package/packages/core/src/mcp/tools/export.ts +0 -72
- package/packages/core/src/mcp/tools/federated-search.ts +0 -43
- package/packages/core/src/mcp/tools/generate-claude-md.ts +0 -130
- package/packages/core/src/mcp/tools/get-document.ts +0 -26
- package/packages/core/src/mcp/tools/get-related.ts +0 -41
- package/packages/core/src/mcp/tools/learning-path.ts +0 -52
- package/packages/core/src/mcp/tools/list-topics.ts +0 -20
- package/packages/core/src/mcp/tools/search.ts +0 -35
- package/packages/core/src/mcp/tools/snapshot.ts +0 -98
- package/packages/core/src/multi-vault/index.ts +0 -118
- package/packages/core/src/pack/creator.ts +0 -127
- package/packages/core/src/pack/exporter.ts +0 -21
- package/packages/core/src/pack/importer.ts +0 -82
- package/packages/core/src/pack/marketplace.ts +0 -103
- package/packages/core/src/pack/pii-masker.ts +0 -38
- package/packages/core/src/pack/types.ts +0 -39
- package/packages/core/src/plugins/index.ts +0 -100
- package/packages/core/src/plugins/webhooks.ts +0 -110
- package/packages/core/src/search/bm25.ts +0 -16
- package/packages/core/src/search/index.ts +0 -83
- package/packages/core/src/search/rrf.ts +0 -31
- package/packages/core/src/search/semantic.ts +0 -15
- package/packages/core/src/store/sqlite-vec.ts +0 -290
- package/packages/core/src/store/types.ts +0 -22
- package/packages/core/src/team/index.ts +0 -126
- package/packages/core/src/types/chunk.ts +0 -25
- package/packages/core/src/types/document.ts +0 -24
- package/packages/core/src/types/graph.ts +0 -44
- package/packages/core/src/types/index.ts +0 -15
- package/packages/core/src/types/search.ts +0 -38
- package/packages/core/src/utils/retry.ts +0 -85
- package/packages/core/tests/api-card.test.ts +0 -60
- package/packages/core/tests/api-routes.test.ts +0 -98
- package/packages/core/tests/bm25.test.ts +0 -87
- package/packages/core/tests/chunker.test.ts +0 -48
- package/packages/core/tests/cluster.test.ts +0 -75
- package/packages/core/tests/constellation.test.ts +0 -77
- package/packages/core/tests/export-utils.test.ts +0 -97
- package/packages/core/tests/fsrs.test.ts +0 -96
- package/packages/core/tests/gesture-detector.test.ts +0 -45
- package/packages/core/tests/graph-data.test.ts +0 -87
- package/packages/core/tests/layout.test.ts +0 -83
- package/packages/core/tests/mcp.test.ts +0 -148
- package/packages/core/tests/pack.test.ts +0 -127
- package/packages/core/tests/pii-masker.test.ts +0 -42
- package/packages/core/tests/profile-card.test.ts +0 -62
- package/packages/core/tests/rrf.test.ts +0 -29
- package/packages/core/tests/search-integration.test.ts +0 -139
- package/packages/core/tests/store.test.ts +0 -80
- package/packages/graph/click-result.png +0 -0
- package/packages/graph/dist/assets/camera_utils-BMxqtvoZ.js +0 -1
- package/packages/graph/dist/assets/hands-DXA01_mx.js +0 -18
- package/packages/graph/dist/assets/index-DMEe2diW.js +0 -4192
- package/packages/graph/dist/assets/layout.worker-DbKCEFTz.js +0 -1
- package/packages/graph/dist/index.html +0 -17
- package/packages/graph/index.html +0 -17
- package/packages/graph/package.json +0 -32
- package/packages/graph/src/App.tsx +0 -7
- package/packages/graph/src/api/client.ts +0 -39
- package/packages/graph/src/components/ClusterFilter.tsx +0 -73
- package/packages/graph/src/components/ConstellationView.tsx +0 -232
- package/packages/graph/src/components/ExportPanel.tsx +0 -177
- package/packages/graph/src/components/Graph3D.tsx +0 -230
- package/packages/graph/src/components/GraphEdges.tsx +0 -100
- package/packages/graph/src/components/GraphNodes.tsx +0 -386
- package/packages/graph/src/components/HealthDashboard.tsx +0 -173
- package/packages/graph/src/components/Layout.tsx +0 -214
- package/packages/graph/src/components/MotionOverlay.tsx +0 -81
- package/packages/graph/src/components/MotionToggle.tsx +0 -33
- package/packages/graph/src/components/MultiverseView.tsx +0 -286
- package/packages/graph/src/components/NodeDetail.tsx +0 -232
- package/packages/graph/src/components/PulseParticle.tsx +0 -232
- package/packages/graph/src/components/SearchBar.tsx +0 -107
- package/packages/graph/src/components/StarField.tsx +0 -197
- package/packages/graph/src/components/StatusBar.tsx +0 -53
- package/packages/graph/src/components/Timeline.tsx +0 -148
- package/packages/graph/src/components/ToolsPanel.tsx +0 -512
- package/packages/graph/src/components/Tooltip.tsx +0 -100
- package/packages/graph/src/components/TypeFilter.tsx +0 -131
- package/packages/graph/src/embed/EmbedGraph.tsx +0 -144
- package/packages/graph/src/hooks/useConstellationLOD.ts +0 -76
- package/packages/graph/src/hooks/useDecay.ts +0 -37
- package/packages/graph/src/hooks/useExport.ts +0 -165
- package/packages/graph/src/hooks/useGraph.ts +0 -69
- package/packages/graph/src/hooks/useKeyboardNav.ts +0 -122
- package/packages/graph/src/hooks/useLayout.ts +0 -45
- package/packages/graph/src/hooks/useMotion.ts +0 -120
- package/packages/graph/src/hooks/usePulse.ts +0 -58
- package/packages/graph/src/hooks/useSearch.ts +0 -71
- package/packages/graph/src/lib/constellation.ts +0 -107
- package/packages/graph/src/lib/export-utils.ts +0 -48
- package/packages/graph/src/lib/gesture-detector.ts +0 -123
- package/packages/graph/src/lib/layout.worker.ts +0 -153
- package/packages/graph/src/lib/motion-controller.ts +0 -83
- package/packages/graph/src/lib/profile-card.ts +0 -122
- package/packages/graph/src/main.tsx +0 -4
- package/packages/graph/src/stores/graph-store.ts +0 -155
- package/packages/graph/success.png +0 -0
- package/packages/graph/test-click.mjs +0 -49
- package/packages/graph/test-explore.mjs +0 -102
- package/packages/graph/test-final.mjs +0 -61
- package/packages/graph/test-graph.mjs +0 -139
- package/packages/graph/test-hover.mjs +0 -48
- package/packages/graph/test-pulse.mjs +0 -68
- package/packages/graph/test-screenshot.mjs +0 -56
- package/packages/graph/test-v2.mjs +0 -97
- package/packages/graph/tsconfig.tsbuildinfo +0 -1
- package/packages/graph/vite.config.ts +0 -15
- package/packages/sync/.env.example +0 -11
- package/packages/sync/.sync-state.json +0 -317
- package/packages/sync/.upload-state.json +0 -1009
- package/packages/sync/create-stella-network-notion.mjs +0 -151
- package/packages/sync/create-stellavault-project-notion.mjs +0 -322
- package/packages/sync/logs/sync-2026-03-28.log +0 -6
- package/packages/sync/logs/sync-2026-03-29.log +0 -12
- package/packages/sync/logs/sync-2026-03-30.log +0 -6
- package/packages/sync/logs/sync-2026-03-31.log +0 -6
- package/packages/sync/logs/sync-2026-04-01.log +0 -6
- package/packages/sync/logs/sync-2026-04-02.log +0 -6
- package/packages/sync/package-lock.json +0 -373
- package/packages/sync/package.json +0 -16
- package/packages/sync/run-sync.bat +0 -18
- package/packages/sync/run-sync.mjs +0 -46
- package/packages/sync/setup-scheduler.mjs +0 -119
- package/packages/sync/structured-sync.mjs +0 -187
- package/packages/sync/sync-to-obsidian.mjs +0 -264
- package/packages/sync/upload-pdca-to-notion.mjs +0 -495
- package/tsconfig.base.json +0 -18
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(){"use strict";const q={iterations:200,repulsion:800,attraction:.005,damping:.92,brainScale:[250,180,200]};self.onmessage=m=>{if(m.data.type!=="init")return;const{nodes:u,edges:A,options:F}=m.data,i={...q,...F},d=u.length;if(d===0){self.postMessage({type:"done",positions:[]});return}const y=new Map;u.forEach((o,f)=>y.set(o.id,f));const I=A.map(o=>({s:y.get(o.source)??-1,t:y.get(o.target)??-1,w:o.weight})).filter(o=>o.s>=0&&o.t>=0),s=new Float64Array(d*3),e=new Float64Array(d*3),[x,w,z]=i.brainScale;for(let o=0;o<d;o++){const f=Math.acos(2*Math.random()-1),p=Math.random()*2*Math.PI,t=.5+.5*Math.random(),n=1+.1*Math.sin(5*f)*Math.cos(3*p);s[o*3]=x*t*Math.sin(f)*Math.cos(p)*n,s[o*3+1]=w*t*Math.cos(f)*n,s[o*3+2]=z*t*Math.sin(f)*Math.sin(p)*n;const a=u[o].clusterId/10*2*Math.PI;s[o*3]+=30*Math.cos(a),s[o*3+2]+=30*Math.sin(a)}for(let o=0;o<i.iterations;o++){const f=1-o/i.iterations,p=i.repulsion*f;for(let t=0;t<d;t++)for(let n=t+1;n<d;n++){const r=s[n*3]-s[t*3],a=s[n*3+1]-s[t*3+1],l=s[n*3+2]-s[t*3+2],c=r*r+a*a+l*l+.01,h=p/c,M=r*h/Math.sqrt(c),g=a*h/Math.sqrt(c),b=l*h/Math.sqrt(c);e[t*3]-=M,e[t*3+1]-=g,e[t*3+2]-=b,e[n*3]+=M,e[n*3+1]+=g,e[n*3+2]+=b}for(const t of I){const n=s[t.t*3]-s[t.s*3],r=s[t.t*3+1]-s[t.s*3+1],a=s[t.t*3+2]-s[t.s*3+2],l=Math.sqrt(n*n+r*r+a*a)+.01,c=i.attraction*l*t.w,h=n/l*c,M=r/l*c,g=a/l*c;e[t.s*3]+=h,e[t.s*3+1]+=M,e[t.s*3+2]+=g,e[t.t*3]-=h,e[t.t*3+1]-=M,e[t.t*3+2]-=g}for(let t=0;t<d;t++){const n=s[t*3],r=s[t*3+1],a=s[t*3+2],l=(n/x)**2+(r/w)**2+(a/z)**2;if(l>1){const c=.3*(l-1);e[t*3]-=n*c*.01,e[t*3+1]-=r*c*.01,e[t*3+2]-=a*c*.01}s[t*3]+=e[t*3],s[t*3+1]+=e[t*3+1],s[t*3+2]+=e[t*3+2],e[t*3]*=i.damping,e[t*3+1]*=i.damping,e[t*3+2]*=i.damping}if(o%20===0||o===i.iterations-1){const t=[];for(let n=0;n<d;n++)t.push([s[n*3],s[n*3+1],s[n*3+2]]);self.postMessage({type:o===i.iterations-1?"done":"progress",positions:t,iteration:o,total:i.iterations})}}}})();
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="ko">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Evan Knowledge Hub — 3D Knowledge Graph</title>
|
|
7
|
-
<style>
|
|
8
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
9
|
-
html, body, #root { width: 100%; height: 100%; overflow: hidden; }
|
|
10
|
-
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0a0a0f; color: #e0e0e0; }
|
|
11
|
-
</style>
|
|
12
|
-
<script type="module" crossorigin src="/assets/index-DMEe2diW.js"></script>
|
|
13
|
-
</head>
|
|
14
|
-
<body>
|
|
15
|
-
<div id="root"></div>
|
|
16
|
-
</body>
|
|
17
|
-
</html>
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="ko">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Evan Knowledge Hub — 3D Knowledge Graph</title>
|
|
7
|
-
<style>
|
|
8
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
9
|
-
html, body, #root { width: 100%; height: 100%; overflow: hidden; }
|
|
10
|
-
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0a0a0f; color: #e0e0e0; }
|
|
11
|
-
</style>
|
|
12
|
-
</head>
|
|
13
|
-
<body>
|
|
14
|
-
<div id="root"></div>
|
|
15
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
16
|
-
</body>
|
|
17
|
-
</html>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@stellavault/graph",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"description": "Stellavault — 3D Neural Knowledge Graph Visualization",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"private": true,
|
|
7
|
-
"scripts": {
|
|
8
|
-
"dev": "vite",
|
|
9
|
-
"build": "tsc -b && vite build",
|
|
10
|
-
"preview": "vite preview"
|
|
11
|
-
},
|
|
12
|
-
"dependencies": {
|
|
13
|
-
"@mediapipe/camera_utils": "^0.3.1675466862",
|
|
14
|
-
"@mediapipe/drawing_utils": "^0.3.1675466124",
|
|
15
|
-
"@mediapipe/hands": "^0.4.1675469240",
|
|
16
|
-
"@react-three/drei": "^10.0.0",
|
|
17
|
-
"@react-three/fiber": "^9.0.0",
|
|
18
|
-
"react": "^19.0.0",
|
|
19
|
-
"react-dom": "^19.0.0",
|
|
20
|
-
"react-markdown": "^10.0.0",
|
|
21
|
-
"three": "^0.170.0",
|
|
22
|
-
"zustand": "^5.0.0"
|
|
23
|
-
},
|
|
24
|
-
"devDependencies": {
|
|
25
|
-
"@types/react": "^19.0.0",
|
|
26
|
-
"@types/react-dom": "^19.0.0",
|
|
27
|
-
"@types/three": "^0.170.0",
|
|
28
|
-
"@vitejs/plugin-react": "^4.0.0",
|
|
29
|
-
"typescript": "^5.7.0",
|
|
30
|
-
"vite": "^6.0.0"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// Design Ref: §2.2 — API-UI 통신 (REST HTTP)
|
|
2
|
-
|
|
3
|
-
const BASE = '/api';
|
|
4
|
-
|
|
5
|
-
export async function fetchGraph() {
|
|
6
|
-
const res = await fetch(`${BASE}/graph`);
|
|
7
|
-
if (!res.ok) throw new Error(`Graph API error: ${res.status}`);
|
|
8
|
-
return res.json();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export async function fetchSearch(query: string, limit = 10) {
|
|
12
|
-
const res = await fetch(`${BASE}/search?q=${encodeURIComponent(query)}&limit=${limit}`);
|
|
13
|
-
if (!res.ok) throw new Error(`Search API error: ${res.status}`);
|
|
14
|
-
return res.json();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function fetchDocument(id: string) {
|
|
18
|
-
const res = await fetch(`${BASE}/document/${encodeURIComponent(id)}`);
|
|
19
|
-
if (!res.ok) throw new Error(`Document API error: ${res.status}`);
|
|
20
|
-
return res.json();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export async function fetchStats() {
|
|
24
|
-
const res = await fetch(`${BASE}/stats`);
|
|
25
|
-
if (!res.ok) throw new Error(`Stats API error: ${res.status}`);
|
|
26
|
-
return res.json();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export async function fetchHealth() {
|
|
30
|
-
const res = await fetch(`${BASE}/health`);
|
|
31
|
-
if (!res.ok) throw new Error(`Health API error: ${res.status}`);
|
|
32
|
-
return res.json();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function fetchEmbed(apiUrl: string, max = 200) {
|
|
36
|
-
const res = await fetch(`${apiUrl}/api/embed?max=${max}`);
|
|
37
|
-
if (!res.ok) throw new Error(`Embed API error: ${res.status}`);
|
|
38
|
-
return res.json();
|
|
39
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// 클러스터 필터 — zustand store 기반
|
|
2
|
-
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import { useGraphStore } from '../stores/graph-store.js';
|
|
5
|
-
|
|
6
|
-
export function ClusterFilter() {
|
|
7
|
-
const clusters = useGraphStore((s) => s.clusters);
|
|
8
|
-
const hiddenClusters = useGraphStore((s) => s.hiddenClusters);
|
|
9
|
-
const toggleHiddenCluster = useGraphStore((s) => s.toggleHiddenCluster);
|
|
10
|
-
const theme = useGraphStore((s) => s.theme);
|
|
11
|
-
const isDark = theme === 'dark';
|
|
12
|
-
const [open, setOpen] = useState(false);
|
|
13
|
-
|
|
14
|
-
if (clusters.length === 0) return null;
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<div style={{ position: 'relative' }}>
|
|
18
|
-
<button
|
|
19
|
-
onClick={() => setOpen(!open)}
|
|
20
|
-
style={{
|
|
21
|
-
padding: '4px 10px', fontSize: '11px',
|
|
22
|
-
border: `1px solid ${isDark ? 'rgba(100,120,255,0.15)' : 'rgba(0,0,0,0.12)'}`,
|
|
23
|
-
borderRadius: '4px', cursor: 'pointer',
|
|
24
|
-
background: open
|
|
25
|
-
? (isDark ? 'rgba(100,120,255,0.2)' : 'rgba(0,0,0,0.08)')
|
|
26
|
-
: (isDark ? 'rgba(100,120,255,0.06)' : 'rgba(0,0,0,0.03)'),
|
|
27
|
-
color: isDark ? '#aab' : '#555',
|
|
28
|
-
}}
|
|
29
|
-
>
|
|
30
|
-
Clusters {hiddenClusters.size > 0 ? `(${clusters.length - hiddenClusters.size}/${clusters.length})` : ''}
|
|
31
|
-
</button>
|
|
32
|
-
|
|
33
|
-
{open && (
|
|
34
|
-
<div style={{
|
|
35
|
-
position: 'absolute', top: '100%', right: 0, marginTop: '6px',
|
|
36
|
-
background: isDark ? 'rgba(10,10,20,0.95)' : 'rgba(255,255,255,0.97)',
|
|
37
|
-
border: `1px solid ${isDark ? 'rgba(100,120,255,0.15)' : 'rgba(0,0,0,0.1)'}`,
|
|
38
|
-
borderRadius: '8px', padding: '8px', minWidth: '200px',
|
|
39
|
-
backdropFilter: 'blur(8px)', zIndex: 100,
|
|
40
|
-
boxShadow: isDark ? 'none' : '0 4px 16px rgba(0,0,0,0.08)',
|
|
41
|
-
}}>
|
|
42
|
-
{[...clusters]
|
|
43
|
-
.sort((a, b) => b.nodeCount - a.nodeCount)
|
|
44
|
-
.map((c) => (
|
|
45
|
-
<label
|
|
46
|
-
key={c.id}
|
|
47
|
-
style={{
|
|
48
|
-
display: 'flex', alignItems: 'center', gap: '8px',
|
|
49
|
-
padding: '4px 6px', borderRadius: '4px', cursor: 'pointer',
|
|
50
|
-
opacity: hiddenClusters.has(c.id) ? 0.3 : 1,
|
|
51
|
-
fontSize: '11px', color: isDark ? '#aab' : '#444',
|
|
52
|
-
}}
|
|
53
|
-
>
|
|
54
|
-
<div style={{
|
|
55
|
-
width: '10px', height: '10px', borderRadius: '50%',
|
|
56
|
-
background: hiddenClusters.has(c.id) ? '#333' : c.color,
|
|
57
|
-
flexShrink: 0,
|
|
58
|
-
}} />
|
|
59
|
-
<span style={{ flex: 1 }}>{c.label}</span>
|
|
60
|
-
<span style={{ color: '#556', fontSize: '10px' }}>{c.nodeCount}</span>
|
|
61
|
-
<input
|
|
62
|
-
type="checkbox"
|
|
63
|
-
checked={!hiddenClusters.has(c.id)}
|
|
64
|
-
onChange={() => toggleHiddenCluster(c.id)}
|
|
65
|
-
style={{ accentColor: c.color }}
|
|
66
|
-
/>
|
|
67
|
-
</label>
|
|
68
|
-
))}
|
|
69
|
-
</div>
|
|
70
|
-
)}
|
|
71
|
-
</div>
|
|
72
|
-
);
|
|
73
|
-
}
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
// Design Ref: §3 — 별자리 뷰
|
|
2
|
-
// Design Ref: §8 — LOD 확장 (universe/constellation/note 3단계)
|
|
3
|
-
// 줌아웃(>800) → universe: 별자리 강조, 줌인(<300) → note: 개별 노드
|
|
4
|
-
|
|
5
|
-
import { useMemo, useRef } from 'react';
|
|
6
|
-
import { useFrame, useThree } from '@react-three/fiber';
|
|
7
|
-
import { Html } from '@react-three/drei';
|
|
8
|
-
import * as THREE from 'three';
|
|
9
|
-
import { useGraphStore } from '../stores/graph-store.js';
|
|
10
|
-
import { buildConstellations, type ConstellationData } from '../lib/constellation.js';
|
|
11
|
-
import { useConstellationLOD } from '../hooks/useConstellationLOD.js';
|
|
12
|
-
|
|
13
|
-
function darkenHex(hex: string, factor: number): string {
|
|
14
|
-
const c = hex.replace('#', '');
|
|
15
|
-
const r = Math.round(parseInt(c.slice(0, 2), 16) * factor);
|
|
16
|
-
const g = Math.round(parseInt(c.slice(2, 4), 16) * factor);
|
|
17
|
-
const b = Math.round(parseInt(c.slice(4, 6), 16) * factor);
|
|
18
|
-
return `rgb(${r},${g},${b})`;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function ConstellationView() {
|
|
22
|
-
const nodes = useGraphStore((s) => s.nodes);
|
|
23
|
-
const clusters = useGraphStore((s) => s.clusters);
|
|
24
|
-
const theme = useGraphStore((s) => s.theme);
|
|
25
|
-
const isLight = theme === 'light';
|
|
26
|
-
const showConstellation = useGraphStore((s) => s.showConstellation);
|
|
27
|
-
|
|
28
|
-
if (!showConstellation) return null;
|
|
29
|
-
const groupRef = useRef<THREE.Group>(null);
|
|
30
|
-
const { constellationOpacity } = useConstellationLOD();
|
|
31
|
-
const opacityRef = useRef(0);
|
|
32
|
-
|
|
33
|
-
// 별자리 데이터 계산 (노드/클러스터 변경 시에만)
|
|
34
|
-
const data: ConstellationData = useMemo(() => {
|
|
35
|
-
if (nodes.length === 0 || clusters.length === 0) return { lines: [], labels: [] };
|
|
36
|
-
return buildConstellations(nodes, clusters);
|
|
37
|
-
}, [nodes, clusters]);
|
|
38
|
-
|
|
39
|
-
// 별자리 라인 geometry
|
|
40
|
-
const lineGeometries = useMemo(() => {
|
|
41
|
-
const geoMap = new Map<number, THREE.BufferGeometry>();
|
|
42
|
-
|
|
43
|
-
// 클러스터별로 라인 그룹화
|
|
44
|
-
const byCluster = new Map<number, number[]>();
|
|
45
|
-
for (const line of data.lines) {
|
|
46
|
-
if (!byCluster.has(line.clusterId)) byCluster.set(line.clusterId, []);
|
|
47
|
-
const arr = byCluster.get(line.clusterId)!;
|
|
48
|
-
arr.push(line.from[0], line.from[1], line.from[2]);
|
|
49
|
-
arr.push(line.to[0], line.to[1], line.to[2]);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
for (const [cId, positions] of byCluster) {
|
|
53
|
-
const geo = new THREE.BufferGeometry();
|
|
54
|
-
geo.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
|
|
55
|
-
geoMap.set(cId, geo);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return geoMap;
|
|
59
|
-
}, [data]);
|
|
60
|
-
|
|
61
|
-
const highlightedNodeIds = useGraphStore((s) => s.highlightedNodeIds);
|
|
62
|
-
const hoveredNodeId = useGraphStore((s) => s.hoveredNodeId);
|
|
63
|
-
const selectedNodeId = useGraphStore((s) => s.selectedNodeId);
|
|
64
|
-
const hasInteraction = highlightedNodeIds.size > 0 || !!hoveredNodeId || !!selectedNodeId;
|
|
65
|
-
|
|
66
|
-
// LOD + 상호작용 상태에 따라 별자리 표시
|
|
67
|
-
useFrame(() => {
|
|
68
|
-
const group = groupRef.current;
|
|
69
|
-
if (!group) return;
|
|
70
|
-
|
|
71
|
-
// 상호작용 중이면 별자리를 대폭 페이드 (활성 노드에 집중)
|
|
72
|
-
let targetOpacity = constellationOpacity;
|
|
73
|
-
if (hasInteraction) {
|
|
74
|
-
targetOpacity = isLight ? 0.03 : constellationOpacity * 0.15;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
opacityRef.current += (targetOpacity - opacityRef.current) * 0.08;
|
|
78
|
-
const opacity = opacityRef.current;
|
|
79
|
-
|
|
80
|
-
group.visible = opacity > 0.01;
|
|
81
|
-
|
|
82
|
-
group.traverse((child) => {
|
|
83
|
-
if ((child as THREE.LineSegments).isLineSegments) {
|
|
84
|
-
const mat = (child as THREE.LineSegments).material as THREE.LineBasicMaterial;
|
|
85
|
-
mat.opacity = isLight ? opacity * 0.6 : opacity * 0.4;
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
if (data.lines.length === 0) return null;
|
|
91
|
-
|
|
92
|
-
// 클러스터 컬러 맵
|
|
93
|
-
const colorMap = new Map(clusters.map(c => [c.id, c.color]));
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<group ref={groupRef}>
|
|
97
|
-
{/* 별자리 라인 — 은은한 클러스터 컬러 */}
|
|
98
|
-
{[...lineGeometries.entries()].map(([cId, geo]) => (
|
|
99
|
-
<lineSegments key={cId} geometry={geo}>
|
|
100
|
-
<lineBasicMaterial
|
|
101
|
-
color={isLight ? '#b0b8c8' : (colorMap.get(cId) ?? '#6688ff')}
|
|
102
|
-
transparent
|
|
103
|
-
opacity={isLight ? 0.35 : 0.12}
|
|
104
|
-
depthWrite={false}
|
|
105
|
-
blending={isLight ? THREE.NormalBlending : THREE.AdditiveBlending}
|
|
106
|
-
/>
|
|
107
|
-
</lineSegments>
|
|
108
|
-
))}
|
|
109
|
-
|
|
110
|
-
{/* 별자리 라벨 */}
|
|
111
|
-
{data.labels.map((label) => (
|
|
112
|
-
<ConstellationLabel
|
|
113
|
-
key={label.clusterId}
|
|
114
|
-
position={label.position}
|
|
115
|
-
text={label.text}
|
|
116
|
-
color={label.color}
|
|
117
|
-
clusterId={label.clusterId}
|
|
118
|
-
opacityRef={opacityRef}
|
|
119
|
-
/>
|
|
120
|
-
))}
|
|
121
|
-
</group>
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function ConstellationLabel({ position, text, color, clusterId, opacityRef }: {
|
|
126
|
-
position: [number, number, number];
|
|
127
|
-
text: string;
|
|
128
|
-
color: string;
|
|
129
|
-
clusterId: number;
|
|
130
|
-
opacityRef: React.RefObject<number>;
|
|
131
|
-
}) {
|
|
132
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
133
|
-
const { camera } = useThree();
|
|
134
|
-
const highlightedNodeIds = useGraphStore((s) => s.highlightedNodeIds);
|
|
135
|
-
const nodes = useGraphStore((s) => s.nodes);
|
|
136
|
-
const themeVal = useGraphStore((s) => s.theme);
|
|
137
|
-
const isLightLabel = themeVal === 'light';
|
|
138
|
-
|
|
139
|
-
const selectedNodeId = useGraphStore((s) => s.selectedNodeId);
|
|
140
|
-
|
|
141
|
-
// 이 클러스터가 활성 상태인지: 하이라이트 중이거나, 선택된 노드가 이 클러스터에 속함
|
|
142
|
-
const isActiveCluster =
|
|
143
|
-
(highlightedNodeIds.size > 0 && nodes.some(n => n.clusterId === clusterId && highlightedNodeIds.has(n.id))) ||
|
|
144
|
-
(selectedNodeId && nodes.some(n => n.id === selectedNodeId && n.clusterId === clusterId));
|
|
145
|
-
|
|
146
|
-
useFrame(() => {
|
|
147
|
-
if (ref.current) {
|
|
148
|
-
// 활성 클러스터 라벨은 줌인해도 항상 보임
|
|
149
|
-
const opacity = isActiveCluster ? 1 : (opacityRef.current ?? 0);
|
|
150
|
-
ref.current.style.opacity = String(opacity);
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
const handleClick = () => {
|
|
155
|
-
const state = useGraphStore.getState();
|
|
156
|
-
const clusterNodeIds = state.nodes
|
|
157
|
-
.filter(n => n.clusterId === clusterId)
|
|
158
|
-
.map(n => n.id);
|
|
159
|
-
|
|
160
|
-
// 이미 이 클러스터가 하이라이트 중이면 해제 (토글)
|
|
161
|
-
const alreadyActive = clusterNodeIds.length > 0 &&
|
|
162
|
-
clusterNodeIds.every(id => state.highlightedNodeIds.has(id));
|
|
163
|
-
|
|
164
|
-
if (alreadyActive) {
|
|
165
|
-
state.setHighlightedNodes([]);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
state.setHighlightedNodes(clusterNodeIds);
|
|
170
|
-
|
|
171
|
-
// OrbitControls target을 별자리 중심으로 이동
|
|
172
|
-
const controls = (window as any).__sv_controls?.current;
|
|
173
|
-
if (controls) {
|
|
174
|
-
const target = new THREE.Vector3(...position);
|
|
175
|
-
const startTarget = controls.target.clone();
|
|
176
|
-
const startPos = controls.object.position.clone();
|
|
177
|
-
const dir = startPos.clone().sub(target).normalize();
|
|
178
|
-
const endPos = target.clone().add(dir.multiplyScalar(350));
|
|
179
|
-
|
|
180
|
-
let t = 0;
|
|
181
|
-
function animate() {
|
|
182
|
-
t += 0.025;
|
|
183
|
-
if (t > 1) t = 1;
|
|
184
|
-
const ease = t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
|
|
185
|
-
|
|
186
|
-
controls.target.lerpVectors(startTarget, target, ease);
|
|
187
|
-
controls.object.position.lerpVectors(startPos, endPos, ease);
|
|
188
|
-
controls.update();
|
|
189
|
-
|
|
190
|
-
if (t < 1) requestAnimationFrame(animate);
|
|
191
|
-
}
|
|
192
|
-
requestAnimationFrame(animate);
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
return (
|
|
197
|
-
<Html position={position} center>
|
|
198
|
-
<div
|
|
199
|
-
ref={ref}
|
|
200
|
-
onClick={handleClick}
|
|
201
|
-
style={{
|
|
202
|
-
fontSize: isLightLabel ? '13px' : '14px',
|
|
203
|
-
fontWeight: isLightLabel ? 800 : 700,
|
|
204
|
-
color: isLightLabel ? darkenHex(color, 0.5) : color,
|
|
205
|
-
textShadow: isLightLabel
|
|
206
|
-
? '1px 1px 0 rgba(255,255,255,0.9), -1px -1px 0 rgba(255,255,255,0.9), 1px -1px 0 rgba(255,255,255,0.9), -1px 1px 0 rgba(255,255,255,0.9)'
|
|
207
|
-
: `0 0 12px ${color}, 0 0 24px ${color}40`,
|
|
208
|
-
letterSpacing: '1.5px',
|
|
209
|
-
textTransform: 'uppercase',
|
|
210
|
-
whiteSpace: 'nowrap',
|
|
211
|
-
opacity: 0,
|
|
212
|
-
transition: 'none',
|
|
213
|
-
cursor: 'pointer',
|
|
214
|
-
userSelect: 'none',
|
|
215
|
-
}}
|
|
216
|
-
onMouseEnter={(e) => {
|
|
217
|
-
const darkColor = isLightLabel ? darkenHex(color, 0.3) : color;
|
|
218
|
-
(e.target as HTMLElement).style.textShadow = isLightLabel
|
|
219
|
-
? `0 0 4px ${darkColor}, 1px 1px 0 rgba(255,255,255,0.9), -1px -1px 0 rgba(255,255,255,0.9)`
|
|
220
|
-
: `0 0 20px ${color}, 0 0 40px ${color}`;
|
|
221
|
-
}}
|
|
222
|
-
onMouseLeave={(e) => {
|
|
223
|
-
(e.target as HTMLElement).style.textShadow = isLightLabel
|
|
224
|
-
? '1px 1px 0 rgba(255,255,255,0.9), -1px -1px 0 rgba(255,255,255,0.9), 1px -1px 0 rgba(255,255,255,0.9), -1px 1px 0 rgba(255,255,255,0.9)'
|
|
225
|
-
: `0 0 12px ${color}, 0 0 24px ${color}40`;
|
|
226
|
-
}}
|
|
227
|
-
>
|
|
228
|
-
{text}
|
|
229
|
-
</div>
|
|
230
|
-
</Html>
|
|
231
|
-
);
|
|
232
|
-
}
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
// Design Ref: §4.1 — 내보내기 UI 패널
|
|
2
|
-
// Plan SC: SC-01 (스크린샷), SC-02 (WebM 녹화)
|
|
3
|
-
|
|
4
|
-
import { useState } from 'react';
|
|
5
|
-
import { useGraphStore } from '../stores/graph-store.js';
|
|
6
|
-
import { useExport } from '../hooks/useExport.js';
|
|
7
|
-
|
|
8
|
-
export function ExportPanel() {
|
|
9
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
10
|
-
const [watermark, setWatermark] = useState(true);
|
|
11
|
-
const [duration, setDuration] = useState(5);
|
|
12
|
-
|
|
13
|
-
const isRecording = useGraphStore((s) => s.isRecording);
|
|
14
|
-
const isExporting = useGraphStore((s) => s.isExporting);
|
|
15
|
-
const theme = useGraphStore((s) => s.theme);
|
|
16
|
-
const isDark = theme === 'dark';
|
|
17
|
-
const {
|
|
18
|
-
takeScreenshot,
|
|
19
|
-
startRecording,
|
|
20
|
-
stopRecording,
|
|
21
|
-
recordingDuration,
|
|
22
|
-
isMediaRecorderSupported,
|
|
23
|
-
} = useExport();
|
|
24
|
-
|
|
25
|
-
if (!isOpen) {
|
|
26
|
-
return (
|
|
27
|
-
<button
|
|
28
|
-
onClick={() => setIsOpen(true)}
|
|
29
|
-
title="Export"
|
|
30
|
-
style={{
|
|
31
|
-
background: isDark ? 'rgba(100,120,255,0.08)' : 'rgba(0,0,0,0.03)',
|
|
32
|
-
border: `1px solid ${isDark ? 'rgba(100,120,255,0.15)' : 'rgba(0,0,0,0.12)'}`,
|
|
33
|
-
borderRadius: '4px',
|
|
34
|
-
padding: '2px 8px',
|
|
35
|
-
color: isDark ? '#667' : '#555',
|
|
36
|
-
fontSize: '10px',
|
|
37
|
-
cursor: 'pointer',
|
|
38
|
-
}}
|
|
39
|
-
>
|
|
40
|
-
Export
|
|
41
|
-
</button>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<div style={{
|
|
47
|
-
position: 'fixed',
|
|
48
|
-
bottom: '40px',
|
|
49
|
-
right: '16px',
|
|
50
|
-
background: isDark ? 'rgba(10, 12, 28, 0.95)' : 'rgba(255, 255, 255, 0.97)',
|
|
51
|
-
border: `1px solid ${isDark ? 'rgba(100, 120, 255, 0.2)' : 'rgba(0, 0, 0, 0.1)'}`,
|
|
52
|
-
borderRadius: '8px',
|
|
53
|
-
padding: '12px 16px',
|
|
54
|
-
width: '240px',
|
|
55
|
-
backdropFilter: 'blur(12px)',
|
|
56
|
-
boxShadow: isDark ? 'none' : '0 4px 16px rgba(0,0,0,0.08)',
|
|
57
|
-
zIndex: 100,
|
|
58
|
-
}}>
|
|
59
|
-
<div style={{
|
|
60
|
-
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
|
|
61
|
-
marginBottom: '10px',
|
|
62
|
-
}}>
|
|
63
|
-
<span style={{ fontSize: '12px', fontWeight: 600, color: isDark ? '#c0c0f0' : '#2a2a4a' }}>
|
|
64
|
-
Export
|
|
65
|
-
</span>
|
|
66
|
-
<button
|
|
67
|
-
onClick={() => setIsOpen(false)}
|
|
68
|
-
style={{
|
|
69
|
-
background: 'none', border: 'none', color: isDark ? '#556' : '#999',
|
|
70
|
-
cursor: 'pointer', fontSize: '14px',
|
|
71
|
-
}}
|
|
72
|
-
>
|
|
73
|
-
x
|
|
74
|
-
</button>
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
{/* Options */}
|
|
78
|
-
<div style={{ marginBottom: '10px' }}>
|
|
79
|
-
<label style={{
|
|
80
|
-
display: 'flex', alignItems: 'center', gap: '6px',
|
|
81
|
-
fontSize: '11px', color: '#889', cursor: 'pointer',
|
|
82
|
-
}}>
|
|
83
|
-
<input
|
|
84
|
-
type="checkbox"
|
|
85
|
-
checked={watermark}
|
|
86
|
-
onChange={(e) => setWatermark(e.target.checked)}
|
|
87
|
-
style={{ accentColor: '#6366f1' }}
|
|
88
|
-
/>
|
|
89
|
-
Watermark
|
|
90
|
-
</label>
|
|
91
|
-
</div>
|
|
92
|
-
|
|
93
|
-
{/* Screenshot Button */}
|
|
94
|
-
<button
|
|
95
|
-
onClick={() => takeScreenshot({ watermark })}
|
|
96
|
-
disabled={isExporting || isRecording}
|
|
97
|
-
style={{
|
|
98
|
-
width: '100%',
|
|
99
|
-
padding: '6px',
|
|
100
|
-
marginBottom: '6px',
|
|
101
|
-
background: isExporting ? 'rgba(100,120,255,0.2)' : 'rgba(100,120,255,0.12)',
|
|
102
|
-
border: '1px solid rgba(100,120,255,0.2)',
|
|
103
|
-
borderRadius: '4px',
|
|
104
|
-
color: '#c0d0ff',
|
|
105
|
-
fontSize: '11px',
|
|
106
|
-
cursor: isExporting ? 'wait' : 'pointer',
|
|
107
|
-
}}
|
|
108
|
-
>
|
|
109
|
-
{isExporting ? 'Capturing...' : 'Screenshot (PNG)'}
|
|
110
|
-
</button>
|
|
111
|
-
|
|
112
|
-
{/* Recording */}
|
|
113
|
-
{isMediaRecorderSupported ? (
|
|
114
|
-
<>
|
|
115
|
-
{!isRecording ? (
|
|
116
|
-
<div style={{ display: 'flex', gap: '6px' }}>
|
|
117
|
-
<select
|
|
118
|
-
value={duration}
|
|
119
|
-
onChange={(e) => setDuration(Number(e.target.value))}
|
|
120
|
-
style={{
|
|
121
|
-
flex: '0 0 60px',
|
|
122
|
-
background: 'rgba(100,120,255,0.08)',
|
|
123
|
-
border: '1px solid rgba(100,120,255,0.15)',
|
|
124
|
-
borderRadius: '4px',
|
|
125
|
-
color: '#889',
|
|
126
|
-
fontSize: '11px',
|
|
127
|
-
padding: '4px',
|
|
128
|
-
}}
|
|
129
|
-
>
|
|
130
|
-
<option value={3}>3s</option>
|
|
131
|
-
<option value={5}>5s</option>
|
|
132
|
-
<option value={10}>10s</option>
|
|
133
|
-
</select>
|
|
134
|
-
<button
|
|
135
|
-
onClick={() => startRecording({ duration, rotation: true })}
|
|
136
|
-
disabled={isExporting}
|
|
137
|
-
style={{
|
|
138
|
-
flex: 1,
|
|
139
|
-
padding: '6px',
|
|
140
|
-
background: 'rgba(255,80,80,0.12)',
|
|
141
|
-
border: '1px solid rgba(255,80,80,0.2)',
|
|
142
|
-
borderRadius: '4px',
|
|
143
|
-
color: '#ff8888',
|
|
144
|
-
fontSize: '11px',
|
|
145
|
-
cursor: 'pointer',
|
|
146
|
-
}}
|
|
147
|
-
>
|
|
148
|
-
Record (WebM)
|
|
149
|
-
</button>
|
|
150
|
-
</div>
|
|
151
|
-
) : (
|
|
152
|
-
<button
|
|
153
|
-
onClick={stopRecording}
|
|
154
|
-
style={{
|
|
155
|
-
width: '100%',
|
|
156
|
-
padding: '6px',
|
|
157
|
-
background: 'rgba(255,80,80,0.2)',
|
|
158
|
-
border: '1px solid rgba(255,80,80,0.3)',
|
|
159
|
-
borderRadius: '4px',
|
|
160
|
-
color: '#ff6666',
|
|
161
|
-
fontSize: '11px',
|
|
162
|
-
cursor: 'pointer',
|
|
163
|
-
animation: 'pulse 1s infinite',
|
|
164
|
-
}}
|
|
165
|
-
>
|
|
166
|
-
Recording {recordingDuration.toFixed(1)}s — Stop
|
|
167
|
-
</button>
|
|
168
|
-
)}
|
|
169
|
-
</>
|
|
170
|
-
) : (
|
|
171
|
-
<div style={{ fontSize: '10px', color: '#556', marginTop: '4px' }}>
|
|
172
|
-
WebM recording requires Chrome or Firefox
|
|
173
|
-
</div>
|
|
174
|
-
)}
|
|
175
|
-
</div>
|
|
176
|
-
);
|
|
177
|
-
}
|