@stephen-netu/design-system 0.1.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/README.md +66 -0
- package/package.json +130 -0
- package/src/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte +221 -0
- package/src/b0-app-shell/clarification-overlay/index.ts +1 -0
- package/src/b0-app-shell/command-bar/CommandBar.svelte +565 -0
- package/src/b0-app-shell/index.ts +14 -0
- package/src/base.css +152 -0
- package/src/d0-data-viz/BarChart.svelte +236 -0
- package/src/d0-data-viz/CheckpointBar.svelte +574 -0
- package/src/d0-data-viz/CheckpointPill.svelte +297 -0
- package/src/d0-data-viz/MetricCard.svelte +159 -0
- package/src/d0-data-viz/SparkLine.svelte +66 -0
- package/src/d0-data-viz/StorageMap.svelte +182 -0
- package/src/d0-data-viz/Timeline.svelte +188 -0
- package/src/d0-data-viz/checkpoint-types.ts +162 -0
- package/src/d0-data-viz/d0-tokens.css +32 -0
- package/src/d0-data-viz/index.ts +58 -0
- package/src/d0-data-viz/storage-map-types.ts +142 -0
- package/src/d0-data-viz/theme-integration.ts +134 -0
- package/src/d0-data-viz/types.ts +53 -0
- package/src/demos/BspSizingInfographic.svelte +386 -0
- package/src/demos/BspZoneDemo.svelte +255 -0
- package/src/demos/ControlRoomDemo.svelte +570 -0
- package/src/demos/NodepadBlocksShowcase.svelte +189 -0
- package/src/demos/index.ts +7 -0
- package/src/editor/CodeEditor.svelte +188 -0
- package/src/editor/FindReplaceDialog.svelte +516 -0
- package/src/editor/MarkdownEditor.svelte +660 -0
- package/src/editor/index.ts +2 -0
- package/src/entity-graph-view/WorldView.svelte +171 -0
- package/src/entity-graph-view/index.ts +6 -0
- package/src/entity-graph-view/types.ts +364 -0
- package/src/epistemic/index.ts +2 -0
- package/src/epistemic/types.ts +134 -0
- package/src/epistemic/utils.ts +32 -0
- package/src/f0-forms/checkbox/Checkbox.svelte +158 -0
- package/src/f0-forms/field/FormField.svelte +91 -0
- package/src/f0-forms/index.ts +11 -0
- package/src/f0-forms/radio/RadioGroup.svelte +192 -0
- package/src/f0-forms/search/SearchBar.svelte +99 -0
- package/src/f0-forms/select/Select.svelte +198 -0
- package/src/f0-forms/textarea/TextArea.svelte +170 -0
- package/src/f0-forms/toggle/FormToggle.svelte +147 -0
- package/src/f0-forms/validation/validate.ts +47 -0
- package/src/fabric/ai/ChatPanel.svelte +648 -0
- package/src/fabric/ai/index.ts +11 -0
- package/src/fabric/data/index.ts +21 -0
- package/src/fabric/feedback/StatusBar.svelte +274 -0
- package/src/fabric/feedback/ToastContainer.svelte +122 -0
- package/src/fabric/feedback/index.ts +14 -0
- package/src/fabric/index.ts +37 -0
- package/src/fabric/input/CommandBar.svelte +79 -0
- package/src/fabric/input/KeyboardShortcuts.svelte +388 -0
- package/src/fabric/input/index.ts +12 -0
- package/src/fabric/layout/GlassBox.svelte +193 -0
- package/src/fabric/layout/KanbanBoard.svelte +158 -0
- package/src/fabric/layout/KanbanCard.svelte +226 -0
- package/src/fabric/layout/KanbanColumn.svelte +278 -0
- package/src/fabric/layout/index.ts +17 -0
- package/src/fabric/navigation/ActivityRail.svelte +271 -0
- package/src/fabric/navigation/index.ts +11 -0
- package/src/g0-geo/SovereignMap.svelte +149 -0
- package/src/g0-geo/index.ts +2 -0
- package/src/index.ts +68 -0
- package/src/l0-layout/block-writer/BlockConnectionLines.svelte +98 -0
- package/src/l0-layout/block-writer/BlockContent.svelte +213 -0
- package/src/l0-layout/block-writer/BlockHeader.svelte +230 -0
- package/src/l0-layout/block-writer/BlockItem.svelte +177 -0
- package/src/l0-layout/block-writer/BlockWriter.svelte +219 -0
- package/src/l0-layout/block-writer/block-writer-types.ts +63 -0
- package/src/l0-layout/block-writer/index.ts +24 -0
- package/src/l0-layout/block-writer/markdown.ts +110 -0
- package/src/l0-layout/chat-view/ChatViewLayout.svelte +61 -0
- package/src/l0-layout/epistemic/AllayDetailPanel.svelte +113 -0
- package/src/l0-layout/epistemic/AssayDetailPanel.svelte +164 -0
- package/src/l0-layout/epistemic/AvenueTrace.svelte +253 -0
- package/src/l0-layout/epistemic/KnowledgeDetailPanel.svelte +204 -0
- package/src/l0-layout/epistemic/ParadigmLens.svelte +170 -0
- package/src/l0-layout/epistemic/ProvenanceChain.svelte +164 -0
- package/src/l0-layout/epistemic/TrustView.svelte +195 -0
- package/src/l0-layout/epistemic/index.ts +7 -0
- package/src/l0-layout/grove/AccordCard.svelte +156 -0
- package/src/l0-layout/grove/GroveCard.svelte +197 -0
- package/src/l0-layout/grove/MemberBadge.svelte +96 -0
- package/src/l0-layout/grove/MemberList.svelte +59 -0
- package/src/l0-layout/grove/grove-types.ts +29 -0
- package/src/l0-layout/grove/index.ts +14 -0
- package/src/l0-layout/index.ts +45 -0
- package/src/l0-layout/kanban/KanbanBoard.svelte +71 -0
- package/src/l0-layout/kanban/KanbanCard.svelte +276 -0
- package/src/l0-layout/kanban/KanbanColumn.svelte +198 -0
- package/src/l0-layout/kanban/KanbanViewLayout.svelte +61 -0
- package/src/l0-layout/workspace/WorkspaceLayout.svelte +93 -0
- package/src/n0-node-graph/GraphEditor.svelte +342 -0
- package/src/n0-node-graph/GraphHistory.svelte +122 -0
- package/src/n0-node-graph/Node.svelte +269 -0
- package/src/n0-node-graph/NodeCanvas.svelte +187 -0
- package/src/n0-node-graph/NodeEdge.svelte +152 -0
- package/src/n0-node-graph/NodePalette.svelte +318 -0
- package/src/n0-node-graph/NodePort.svelte +128 -0
- package/src/n0-node-graph/index.ts +33 -0
- package/src/n0-node-graph/n0-tokens.css +29 -0
- package/src/n0-node-graph/node-port-types.ts +19 -0
- package/src/n0-node-graph/types.ts +96 -0
- package/src/n0-node-graph/validate.test.ts +722 -0
- package/src/n0-node-graph/validate.ts +371 -0
- package/src/n1-flow-canvas/FlowCanvas.svelte +202 -0
- package/src/n1-flow-canvas/graph-state.svelte.ts +95 -0
- package/src/n1-flow-canvas/index.ts +21 -0
- package/src/n1-flow-canvas/layout.ts +118 -0
- package/src/n1-flow-canvas/layout.worker.ts +128 -0
- package/src/n1-flow-canvas/types.ts +102 -0
- package/src/n1-flow-canvas/utils.ts +146 -0
- package/src/n2-manifold-disk/ManifoldDisk.svelte +314 -0
- package/src/n2-manifold-disk/index.ts +6 -0
- package/src/n2-manifold-disk/poincare.ts +184 -0
- package/src/n3-force-graph/ForceGraph.svelte +180 -0
- package/src/n3-force-graph/GraphTooltip.svelte +99 -0
- package/src/n3-force-graph/animated-edge.ts +107 -0
- package/src/n3-force-graph/health-node.ts +128 -0
- package/src/n3-force-graph/index.ts +31 -0
- package/src/n3-force-graph/types.ts +94 -0
- package/src/n4-adaptive-manifold/AdaptiveManifold.svelte +1165 -0
- package/src/n4-adaptive-manifold/DetailCard.svelte +212 -0
- package/src/n4-adaptive-manifold/SuggestionIndicator.svelte +91 -0
- package/src/n4-adaptive-manifold/classifier.ts +139 -0
- package/src/n4-adaptive-manifold/index.ts +45 -0
- package/src/n4-adaptive-manifold/n4-tokens.css +155 -0
- package/src/n4-adaptive-manifold/orchestrator.ts +301 -0
- package/src/n4-adaptive-manifold/phase-theme.ts +92 -0
- package/src/n4-adaptive-manifold/pinnacle-events.ts +135 -0
- package/src/n4-adaptive-manifold/providers/gravitational-provider.ts +191 -0
- package/src/n4-adaptive-manifold/providers/manifold-provider.ts +276 -0
- package/src/n4-adaptive-manifold/transition.ts +90 -0
- package/src/n4-adaptive-manifold/types.ts +313 -0
- package/src/p0-primitives/index.ts +6 -0
- package/src/p0-primitives/tokens/control-room.css +309 -0
- package/src/p0-primitives/tokens/index.ts +6 -0
- package/src/p0-primitives/tokens/tokens.css +140 -0
- package/src/p0-primitives/tokens/tokens.json +132 -0
- package/src/p0-primitives/types/index.ts +123 -0
- package/src/p0-primitives/types/plugin-types.ts +74 -0
- package/src/p0-primitives/utils/index.ts +39 -0
- package/src/platform/hud-protocol.ts +20 -0
- package/src/platform/index.ts +3 -0
- package/src/s0-state/create-store.ts +84 -0
- package/src/s0-state/derived.ts +41 -0
- package/src/s0-state/index.ts +6 -0
- package/src/showcase/Showcase.svelte +401 -0
- package/src/spatial/BspTilingCanvas.svelte +232 -0
- package/src/spatial/ForceCanvas.svelte +289 -0
- package/src/spatial/LodRenderer.svelte +334 -0
- package/src/spatial/SnapZoomCamera.svelte +185 -0
- package/src/spatial/ZoneTiler.svelte +311 -0
- package/src/spatial/camera-types.ts +45 -0
- package/src/spatial/content-proportional-bsp.ts +253 -0
- package/src/spatial/force-canvas-types.ts +102 -0
- package/src/spatial/index.ts +15 -0
- package/src/spatial/lod-types.ts +70 -0
- package/src/spatial/zone-tiler-types.ts +177 -0
- package/src/stores/vaultStore.svelte +14 -0
- package/src/t0-transport/connection.ts +34 -0
- package/src/t0-transport/error.ts +37 -0
- package/src/t0-transport/events.ts +50 -0
- package/src/t0-transport/index.ts +6 -0
- package/src/t0-transport/invoke.ts +30 -0
- package/src/tauri/index.ts +13 -0
- package/src/u0-primitives/allay-gauge/AllayGauge.svelte +90 -0
- package/src/u0-primitives/allay-gauge/index.ts +1 -0
- package/src/u0-primitives/animated-icon/AnimatedIcon.svelte +273 -0
- package/src/u0-primitives/animated-icon/README.md +53 -0
- package/src/u0-primitives/animated-icon/index.ts +31 -0
- package/src/u0-primitives/assay-badge/AssayBadge.svelte +121 -0
- package/src/u0-primitives/assay-badge/AssaySignalBar.svelte +83 -0
- package/src/u0-primitives/assay-badge/index.ts +2 -0
- package/src/u0-primitives/avatar/Avatar.svelte +177 -0
- package/src/u0-primitives/badge/Badge.svelte +149 -0
- package/src/u0-primitives/button/Button.svelte +304 -0
- package/src/u0-primitives/card/Card.svelte +182 -0
- package/src/u0-primitives/dropdown/Dropdown.svelte +305 -0
- package/src/u0-primitives/expert-badge/ExpertBadge.svelte +89 -0
- package/src/u0-primitives/expert-badge/index.ts +1 -0
- package/src/u0-primitives/index.ts +35 -0
- package/src/u0-primitives/input/Input.svelte +237 -0
- package/src/u0-primitives/modal/Modal.svelte +331 -0
- package/src/u0-primitives/modal/index.ts +1 -0
- package/src/u0-primitives/spinner/Spinner.svelte +129 -0
- package/src/u0-primitives/tabs/Tabs.svelte +225 -0
- package/src/u0-primitives/tabs/tabs-types.ts +11 -0
- package/src/u0-primitives/toggle/Toggle.svelte +161 -0
- package/src/u0-primitives/tooltip/Tooltip.svelte +234 -0
- package/src/v0-diagrams/DiagramPanel.svelte +68 -0
- package/src/v0-diagrams/MarkmapDiagram.svelte +56 -0
- package/src/v0-diagrams/MermaidDiagram.svelte +53 -0
- package/src/v0-diagrams/index.ts +4 -0
- package/src/v0-diagrams/types.ts +28 -0
- package/src/v0-diagrams/v0-tokens.css +6 -0
- package/src/vite-env.d.ts +7 -0
- package/src/x0-enchanted-blocks/ENCHANTED_BLOCKS_SPEC.md +457 -0
- package/src/x0-enchanted-blocks/components/EnchantedBlock.svelte +485 -0
- package/src/x0-enchanted-blocks/components/NodepadBlock.svelte +262 -0
- package/src/x0-enchanted-blocks/core/block-layout.ts +211 -0
- package/src/x0-enchanted-blocks/core/block-types.ts +227 -0
- package/src/x0-enchanted-blocks/index.ts +46 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* ActivityRail - Fabric Component
|
|
4
|
+
*
|
|
5
|
+
* Vertical navigation rail for app switching and view selection.
|
|
6
|
+
* Decoupled from shell stores - uses props/callbacks for all state.
|
|
7
|
+
*
|
|
8
|
+
* @package @kos/design-system/fabric/navigation
|
|
9
|
+
* @adr 2026-04-12-leap-substrate-refactor-001
|
|
10
|
+
*/
|
|
11
|
+
// Lucide icons are Svelte 4 class components - use permissive typing
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
type IconComponent = any;
|
|
14
|
+
import {
|
|
15
|
+
LayoutGrid, FileText, Network, Columns2, Globe,
|
|
16
|
+
FolderTree, MessageSquare, HelpCircle, Layers, Gauge, Wifi, Folder,
|
|
17
|
+
Compass, Cpu, MessageCircle, Inbox,
|
|
18
|
+
} from '@lucide/svelte';
|
|
19
|
+
|
|
20
|
+
export type RailItemType = 'app' | 'view' | 'panel';
|
|
21
|
+
|
|
22
|
+
export interface RailItem {
|
|
23
|
+
id: string;
|
|
24
|
+
type: RailItemType;
|
|
25
|
+
label: string;
|
|
26
|
+
iconName: string;
|
|
27
|
+
active?: boolean;
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
title?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface Props {
|
|
33
|
+
/** App-level items (top section) */
|
|
34
|
+
appItems: RailItem[];
|
|
35
|
+
/** View-level items (middle section) */
|
|
36
|
+
viewItems: RailItem[];
|
|
37
|
+
/** Panel toggle items (bottom section) */
|
|
38
|
+
panelItems: RailItem[];
|
|
39
|
+
/** Currently active app ID */
|
|
40
|
+
activeAppId?: string;
|
|
41
|
+
/** Callback when item is clicked */
|
|
42
|
+
onitemclick: (item: RailItem) => void;
|
|
43
|
+
/** Callback for help button */
|
|
44
|
+
onopenhelp?: () => void;
|
|
45
|
+
/** Enable drag-drop for stream cards (app items only) */
|
|
46
|
+
ondropstreamcard?: (item: RailItem, data: { content: string; contentType: string; source: string }) => void;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const props: Props = $props();
|
|
50
|
+
|
|
51
|
+
const ICON_MAP: Record<string, IconComponent> = {
|
|
52
|
+
'layout-grid': LayoutGrid,
|
|
53
|
+
'file-text': FileText,
|
|
54
|
+
'network': Network,
|
|
55
|
+
'columns': Columns2,
|
|
56
|
+
'globe': Globe,
|
|
57
|
+
'wifi': Wifi,
|
|
58
|
+
'folder-tree': FolderTree,
|
|
59
|
+
'message-square': MessageSquare,
|
|
60
|
+
'folder': Folder,
|
|
61
|
+
'compass': Compass,
|
|
62
|
+
'cpu': Cpu,
|
|
63
|
+
'message-circle': MessageCircle,
|
|
64
|
+
'inbox': Inbox,
|
|
65
|
+
'layers': Layers,
|
|
66
|
+
'gauge': Gauge,
|
|
67
|
+
'help-circle': HelpCircle,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
function getIcon(name: string): IconComponent {
|
|
71
|
+
return ICON_MAP[name.toLowerCase()] ?? FileText;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Drop target state
|
|
75
|
+
let dropTargetId = $state<string | null>(null);
|
|
76
|
+
|
|
77
|
+
function isStreamCardDrag(e: DragEvent): boolean {
|
|
78
|
+
return e.dataTransfer?.types.includes('application/json') ?? false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function handleDragOver(item: RailItem, e: DragEvent) {
|
|
82
|
+
if (!isStreamCardDrag(e) || item.type !== 'app') return;
|
|
83
|
+
e.preventDefault();
|
|
84
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';
|
|
85
|
+
dropTargetId = item.id;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function handleDragLeave(e: DragEvent) {
|
|
89
|
+
if (e.currentTarget instanceof HTMLElement && !e.currentTarget.contains(e.relatedTarget as Node)) {
|
|
90
|
+
dropTargetId = null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function handleDrop(item: RailItem, e: DragEvent) {
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
dropTargetId = null;
|
|
97
|
+
if (!props.ondropstreamcard || item.type !== 'app') return;
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const data = e.dataTransfer?.getData('application/json');
|
|
101
|
+
if (!data) return;
|
|
102
|
+
const payload = JSON.parse(data);
|
|
103
|
+
if (payload.type !== 'stream-card') return;
|
|
104
|
+
|
|
105
|
+
props.ondropstreamcard(
|
|
106
|
+
item,
|
|
107
|
+
{ content: payload.content, contentType: payload.contentType, source: payload.source }
|
|
108
|
+
);
|
|
109
|
+
} catch {
|
|
110
|
+
// Not a valid stream card payload
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
</script>
|
|
114
|
+
|
|
115
|
+
<nav class="activity-rail" aria-label="Activity navigation">
|
|
116
|
+
<div class="rail-brand">⬡</div>
|
|
117
|
+
|
|
118
|
+
<!-- App buttons -->
|
|
119
|
+
<div class="rail-section rail-apps">
|
|
120
|
+
{#each props.appItems as item (item.id)}
|
|
121
|
+
{@const Icon = getIcon(item.iconName)}
|
|
122
|
+
<button
|
|
123
|
+
class="rail-btn"
|
|
124
|
+
class:active={item.active}
|
|
125
|
+
class:drag-over={dropTargetId === item.id}
|
|
126
|
+
class:disabled={item.disabled}
|
|
127
|
+
title={item.title ?? item.label}
|
|
128
|
+
aria-label={item.label}
|
|
129
|
+
onclick={() => props.onitemclick(item)}
|
|
130
|
+
ondragover={(e) => handleDragOver(item, e)}
|
|
131
|
+
ondragleave={handleDragLeave}
|
|
132
|
+
ondrop={(e) => handleDrop(item, e)}
|
|
133
|
+
>
|
|
134
|
+
<Icon size={18} />
|
|
135
|
+
</button>
|
|
136
|
+
{/each}
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<div class="rail-divider"></div>
|
|
140
|
+
|
|
141
|
+
<!-- View buttons -->
|
|
142
|
+
<div class="rail-section">
|
|
143
|
+
{#each props.viewItems as item (item.id)}
|
|
144
|
+
{@const Icon = getIcon(item.iconName)}
|
|
145
|
+
<button
|
|
146
|
+
class="rail-btn"
|
|
147
|
+
class:active={item.active}
|
|
148
|
+
class:disabled={item.disabled}
|
|
149
|
+
title={item.label}
|
|
150
|
+
aria-label={item.label}
|
|
151
|
+
onclick={() => props.onitemclick(item)}
|
|
152
|
+
>
|
|
153
|
+
<Icon size={18} />
|
|
154
|
+
</button>
|
|
155
|
+
{/each}
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<!-- Panel toggles -->
|
|
159
|
+
<div class="rail-section rail-panels">
|
|
160
|
+
{#each props.panelItems as item (item.id)}
|
|
161
|
+
{@const Icon = getIcon(item.iconName)}
|
|
162
|
+
<button
|
|
163
|
+
class="rail-btn"
|
|
164
|
+
class:active={item.active}
|
|
165
|
+
class:disabled={item.disabled}
|
|
166
|
+
title={item.label}
|
|
167
|
+
aria-label={item.label}
|
|
168
|
+
onclick={() => props.onitemclick(item)}
|
|
169
|
+
>
|
|
170
|
+
<Icon size={18} />
|
|
171
|
+
</button>
|
|
172
|
+
{/each}
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
<div class="rail-spacer"></div>
|
|
176
|
+
|
|
177
|
+
<button
|
|
178
|
+
class="rail-btn"
|
|
179
|
+
title="Keyboard shortcuts (?)"
|
|
180
|
+
aria-label="Keyboard shortcuts"
|
|
181
|
+
onclick={() => props.onopenhelp?.()}
|
|
182
|
+
>
|
|
183
|
+
<HelpCircle size={18} />
|
|
184
|
+
</button>
|
|
185
|
+
</nav>
|
|
186
|
+
|
|
187
|
+
<style>
|
|
188
|
+
.activity-rail {
|
|
189
|
+
display: flex;
|
|
190
|
+
flex-direction: column;
|
|
191
|
+
align-items: center;
|
|
192
|
+
width: 48px;
|
|
193
|
+
height: 100%;
|
|
194
|
+
background: var(--color-bg-canvas, #1a1a1a);
|
|
195
|
+
border-right: 1px solid var(--border-subtle, rgba(255,255,255,0.06));
|
|
196
|
+
padding: 4px 0;
|
|
197
|
+
gap: 2px;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.rail-brand {
|
|
201
|
+
display: flex;
|
|
202
|
+
align-items: center;
|
|
203
|
+
justify-content: center;
|
|
204
|
+
height: 36px;
|
|
205
|
+
color: var(--color-accent, #b87333);
|
|
206
|
+
font-size: 16px;
|
|
207
|
+
flex-shrink: 0;
|
|
208
|
+
margin-bottom: 4px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.rail-section {
|
|
212
|
+
display: flex;
|
|
213
|
+
flex-direction: column;
|
|
214
|
+
align-items: center;
|
|
215
|
+
gap: 2px;
|
|
216
|
+
width: 100%;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.rail-divider {
|
|
220
|
+
width: 24px;
|
|
221
|
+
height: 1px;
|
|
222
|
+
background: var(--border-subtle, rgba(255,255,255,0.08));
|
|
223
|
+
margin: 4px 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.rail-panels {
|
|
227
|
+
border-top: 1px solid var(--border-subtle, rgba(255,255,255,0.06));
|
|
228
|
+
padding-top: 4px;
|
|
229
|
+
margin-top: 4px;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.rail-spacer {
|
|
233
|
+
flex: 1;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.rail-btn {
|
|
237
|
+
width: 36px;
|
|
238
|
+
height: 36px;
|
|
239
|
+
background: transparent;
|
|
240
|
+
border: none;
|
|
241
|
+
color: var(--color-text-tertiary, #706858);
|
|
242
|
+
cursor: pointer;
|
|
243
|
+
border-radius: var(--radius-lg, 0.5rem);
|
|
244
|
+
display: flex;
|
|
245
|
+
align-items: center;
|
|
246
|
+
justify-content: center;
|
|
247
|
+
transition: background 120ms, color 120ms, box-shadow 120ms;
|
|
248
|
+
flex-shrink: 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.rail-btn:hover {
|
|
252
|
+
background: rgba(255,255,255,0.05);
|
|
253
|
+
color: var(--color-text-secondary, #a09880);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.rail-btn.active {
|
|
257
|
+
background: var(--color-accent-subtle, rgba(184, 115, 51, 0.15));
|
|
258
|
+
color: var(--color-accent, #b87333);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.rail-btn.drag-over {
|
|
262
|
+
background: rgba(184, 115, 51, 0.25);
|
|
263
|
+
box-shadow: 0 0 8px rgba(184, 115, 51, 0.4);
|
|
264
|
+
color: var(--color-accent, #b87333);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.rail-btn.disabled {
|
|
268
|
+
opacity: 0.3;
|
|
269
|
+
pointer-events: none;
|
|
270
|
+
}
|
|
271
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fabric Navigation Components
|
|
3
|
+
*
|
|
4
|
+
* Navigation patterns for app switching and view selection.
|
|
5
|
+
*
|
|
6
|
+
* @package @kos/design-system/fabric/navigation
|
|
7
|
+
* @adr 2026-04-12-leap-substrate-refactor-001
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export { default as ActivityRail } from './ActivityRail.svelte';
|
|
11
|
+
export type { RailItem, RailItemType } from './ActivityRail.svelte';
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// SovereignMap — KOS-themed Leaflet map primitive.
|
|
3
|
+
//
|
|
4
|
+
// Design decisions (ADR: 2026-04-05-mir-civic-commons-adr.md):
|
|
5
|
+
// - Leaflet (BSD-2, 42KB gzipped) with CartoDB dark_all tiles — no API key required.
|
|
6
|
+
// - `visibility: hidden` persistence semantics: map is never destroyed when
|
|
7
|
+
// backgrounded (consistent with CodeMirror and canvas components in LEAP).
|
|
8
|
+
// - Long-term: regional PMTiles extract for offline sovereign operation.
|
|
9
|
+
|
|
10
|
+
import { onMount, onDestroy } from 'svelte';
|
|
11
|
+
import 'leaflet/dist/leaflet.css';
|
|
12
|
+
|
|
13
|
+
interface GeoPoint {
|
|
14
|
+
lat: number;
|
|
15
|
+
lon: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface MapMarker {
|
|
19
|
+
id: string;
|
|
20
|
+
lat: number;
|
|
21
|
+
lon: number;
|
|
22
|
+
label: string;
|
|
23
|
+
selected?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface Props {
|
|
27
|
+
center: GeoPoint;
|
|
28
|
+
zoom?: number;
|
|
29
|
+
markers?: MapMarker[];
|
|
30
|
+
onMarkerSelect?: (id: string) => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let { center, zoom = 12, markers = [], onMarkerSelect }: Props = $props();
|
|
34
|
+
|
|
35
|
+
let mapEl: HTMLDivElement;
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
|
+
let map: any = null;
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
+
let markerLayer: any = null;
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
|
+
let L: any = null;
|
|
42
|
+
|
|
43
|
+
onMount(async () => {
|
|
44
|
+
// Dynamic import keeps Leaflet out of the critical bundle path.
|
|
45
|
+
// CSS is statically imported at top of file — resolved from node_modules at build time (ADR: 2026-04-05-sovereign-map-css-delivery-adr.md).
|
|
46
|
+
const leafletModule = await import('leaflet');
|
|
47
|
+
L = leafletModule.default;
|
|
48
|
+
|
|
49
|
+
map = L.map(mapEl).setView([center.lat, center.lon], zoom);
|
|
50
|
+
|
|
51
|
+
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
|
|
52
|
+
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
|
53
|
+
subdomains: 'abcd',
|
|
54
|
+
maxZoom: 19,
|
|
55
|
+
}).addTo(map);
|
|
56
|
+
|
|
57
|
+
markerLayer = L.layerGroup().addTo(map);
|
|
58
|
+
syncMarkers();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
onDestroy(() => {
|
|
62
|
+
map?.remove();
|
|
63
|
+
map = null;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Reactively sync markers when prop changes.
|
|
67
|
+
$effect(() => {
|
|
68
|
+
if (map) syncMarkers();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Reactively re-centre when center prop changes.
|
|
72
|
+
$effect(() => {
|
|
73
|
+
map?.setView([center.lat, center.lon], zoom);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
function syncMarkers() {
|
|
77
|
+
if (!markerLayer || !L) return;
|
|
78
|
+
markerLayer.clearLayers();
|
|
79
|
+
|
|
80
|
+
for (const m of markers) {
|
|
81
|
+
const icon = L.divIcon({
|
|
82
|
+
className: '',
|
|
83
|
+
html: `<div class="sov-marker${m.selected ? ' sov-marker--selected' : ''}"></div>`,
|
|
84
|
+
iconSize: [12, 12],
|
|
85
|
+
iconAnchor: [6, 6],
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const leafletMarker = L.marker([m.lat, m.lon], { icon }).addTo(markerLayer);
|
|
89
|
+
leafletMarker.bindTooltip(m.label, { permanent: false, direction: 'top' });
|
|
90
|
+
|
|
91
|
+
if (onMarkerSelect) {
|
|
92
|
+
const id = m.id;
|
|
93
|
+
leafletMarker.on('click', () => onMarkerSelect(id));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
<div bind:this={mapEl} class="sovereign-map"></div>
|
|
100
|
+
|
|
101
|
+
<style>
|
|
102
|
+
.sovereign-map {
|
|
103
|
+
width: 100%;
|
|
104
|
+
height: 100%;
|
|
105
|
+
background: #1a1a1a;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Leaflet override: match KOS dark theme for controls */
|
|
109
|
+
:global(.leaflet-control-zoom a) {
|
|
110
|
+
background: #222;
|
|
111
|
+
border-color: #444;
|
|
112
|
+
color: #e8e0d0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
:global(.leaflet-control-zoom a:hover) {
|
|
116
|
+
background: #2a2a2a;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
:global(.leaflet-control-attribution) {
|
|
120
|
+
background: rgba(26, 26, 26, 0.8);
|
|
121
|
+
color: #a09880;
|
|
122
|
+
font-size: 10px;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
:global(.sov-marker) {
|
|
126
|
+
background: #b87333;
|
|
127
|
+
border: 2px solid #e8e0d0;
|
|
128
|
+
border-radius: 50%;
|
|
129
|
+
width: 10px;
|
|
130
|
+
height: 10px;
|
|
131
|
+
cursor: pointer;
|
|
132
|
+
transition: transform 0.1s;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
:global(.sov-marker--selected) {
|
|
136
|
+
background: #e8e0d0;
|
|
137
|
+
border-color: #b87333;
|
|
138
|
+
transform: scale(1.4);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
:global(.leaflet-tooltip) {
|
|
142
|
+
background: #222;
|
|
143
|
+
border: 1px solid #444;
|
|
144
|
+
color: #e8e0d0;
|
|
145
|
+
font-family: system-ui, sans-serif;
|
|
146
|
+
font-size: 12px;
|
|
147
|
+
padding: 4px 8px;
|
|
148
|
+
}
|
|
149
|
+
</style>
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// LEAP Design System — HDA-organized frontend primitives
|
|
2
|
+
// @kos/design-system
|
|
3
|
+
|
|
4
|
+
// CSS imports
|
|
5
|
+
import './base.css';
|
|
6
|
+
import './p0-primitives/tokens/tokens.css';
|
|
7
|
+
import './p0-primitives/tokens/control-room.css';
|
|
8
|
+
import './n0-node-graph/n0-tokens.css';
|
|
9
|
+
import './d0-data-viz/d0-tokens.css';
|
|
10
|
+
import './n4-adaptive-manifold/n4-tokens.css';
|
|
11
|
+
|
|
12
|
+
// B0 App Shell — Global LEAP chrome (CommandBar, intent dispatch, system state)
|
|
13
|
+
// B = Base shell layer — free in both SOVEREIGN HDA and existing DS prefixes
|
|
14
|
+
export * from './b0-app-shell';
|
|
15
|
+
|
|
16
|
+
// P0 Primitives — Shared types, utilities, design tokens
|
|
17
|
+
export * from './p0-primitives';
|
|
18
|
+
|
|
19
|
+
// U0 Primitives — Atomic UI components
|
|
20
|
+
export * from './u0-primitives';
|
|
21
|
+
|
|
22
|
+
// L0 Layout — Layout compositions
|
|
23
|
+
export * from './l0-layout';
|
|
24
|
+
|
|
25
|
+
// S0 State — Store primitives (Svelte 5 runes)
|
|
26
|
+
export * from './s0-state';
|
|
27
|
+
|
|
28
|
+
// T0 Transport — Tauri IPC
|
|
29
|
+
export * from './t0-transport';
|
|
30
|
+
|
|
31
|
+
// F0 Forms — Form primitives
|
|
32
|
+
export * from './f0-forms';
|
|
33
|
+
|
|
34
|
+
// D0 Data Viz — Charts, metrics, timelines
|
|
35
|
+
export * from './d0-data-viz';
|
|
36
|
+
|
|
37
|
+
// N0 Node Graph — Visual composition primitives (SVG DAG, <100 nodes)
|
|
38
|
+
export * from './n0-node-graph';
|
|
39
|
+
|
|
40
|
+
// N1 Flow Canvas — Canvas 2D + ELK layout + BFS edge reveal (PS2 aesthetic)
|
|
41
|
+
export * from './n1-flow-canvas';
|
|
42
|
+
|
|
43
|
+
// N2 Manifold Disk — Poincaré disk projection, wraps N1
|
|
44
|
+
export * from './n2-manifold-disk';
|
|
45
|
+
|
|
46
|
+
// N3 Force Graph — Force-directed graph with health-aware rendering (force-graph)
|
|
47
|
+
export * from './n3-force-graph';
|
|
48
|
+
|
|
49
|
+
// N4 Adaptive Manifold — Unified topology-aware graph layout with classifier
|
|
50
|
+
export * from './n4-adaptive-manifold';
|
|
51
|
+
|
|
52
|
+
// Entity Graph View — SOVEREIGN entity graph visualization
|
|
53
|
+
export * from './entity-graph-view';
|
|
54
|
+
|
|
55
|
+
// Epistemic types
|
|
56
|
+
export * from './epistemic';
|
|
57
|
+
|
|
58
|
+
// Platform — cross-boundary protocols (HUD, etc.)
|
|
59
|
+
export * from './platform';
|
|
60
|
+
|
|
61
|
+
// Spatial — BSP zone tiling, force-directed layout, LOD rendering, snap-zoom camera
|
|
62
|
+
export * from './spatial';
|
|
63
|
+
|
|
64
|
+
// G0 Geo — Geospatial map primitives (SovereignMap)
|
|
65
|
+
export * from './g0-geo';
|
|
66
|
+
|
|
67
|
+
// X0 Enchanted Blocks — Adaptive spatial content with Pretext measurement
|
|
68
|
+
export * from './x0-enchanted-blocks';
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { BlockConnection } from './block-writer-types.js';
|
|
3
|
+
import type { ZoneRect } from '../../spatial/zone-tiler-types.js';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
connections: BlockConnection[];
|
|
7
|
+
zones: ZoneRect[];
|
|
8
|
+
focusedBlockId?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { connections, zones, focusedBlockId = '' }: Props = $props();
|
|
12
|
+
|
|
13
|
+
interface LineSegment {
|
|
14
|
+
x1: number;
|
|
15
|
+
y1: number;
|
|
16
|
+
x2: number;
|
|
17
|
+
y2: number;
|
|
18
|
+
isActive: boolean;
|
|
19
|
+
label?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const lines = $derived.by((): LineSegment[] => {
|
|
23
|
+
const zoneMap = new Map(zones.map(z => [z.id, z]));
|
|
24
|
+
const result: LineSegment[] = [];
|
|
25
|
+
|
|
26
|
+
for (const conn of connections) {
|
|
27
|
+
const from = zoneMap.get(conn.fromId);
|
|
28
|
+
const to = zoneMap.get(conn.toId);
|
|
29
|
+
if (!from || !to) continue;
|
|
30
|
+
|
|
31
|
+
result.push({
|
|
32
|
+
x1: from.x + from.width / 2,
|
|
33
|
+
y1: from.y + from.height,
|
|
34
|
+
x2: to.x + to.width / 2,
|
|
35
|
+
y2: to.y,
|
|
36
|
+
isActive: conn.fromId === focusedBlockId || conn.toId === focusedBlockId,
|
|
37
|
+
label: conn.label,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return result;
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
{#if lines.length > 0}
|
|
46
|
+
<svg class="ds-block-connections" xmlns="http://www.w3.org/2000/svg">
|
|
47
|
+
{#each lines as line (`${line.x1},${line.y1}-${line.x2},${line.y2}`)}
|
|
48
|
+
<line
|
|
49
|
+
x1={line.x1}
|
|
50
|
+
y1={line.y1}
|
|
51
|
+
x2={line.x2}
|
|
52
|
+
y2={line.y2}
|
|
53
|
+
class:ds-block-conn-active={line.isActive}
|
|
54
|
+
class="ds-block-conn-line"
|
|
55
|
+
/>
|
|
56
|
+
{#if line.label}
|
|
57
|
+
<text
|
|
58
|
+
x={(line.x1 + line.x2) / 2}
|
|
59
|
+
y={(line.y1 + line.y2) / 2 - 4}
|
|
60
|
+
class="ds-block-conn-label"
|
|
61
|
+
>{line.label}</text>
|
|
62
|
+
{/if}
|
|
63
|
+
{/each}
|
|
64
|
+
</svg>
|
|
65
|
+
{/if}
|
|
66
|
+
|
|
67
|
+
<style>
|
|
68
|
+
.ds-block-connections {
|
|
69
|
+
position: absolute;
|
|
70
|
+
top: 0;
|
|
71
|
+
left: 0;
|
|
72
|
+
width: 100%;
|
|
73
|
+
height: 100%;
|
|
74
|
+
pointer-events: none;
|
|
75
|
+
z-index: 5;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.ds-block-conn-line {
|
|
79
|
+
stroke: var(--color-accent, #b87333);
|
|
80
|
+
stroke-opacity: 0.35;
|
|
81
|
+
stroke-width: 1.5;
|
|
82
|
+
stroke-dasharray: 4 3;
|
|
83
|
+
transition: stroke-opacity 0.15s ease, stroke-width 0.15s ease;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.ds-block-conn-active {
|
|
87
|
+
stroke-opacity: 0.7;
|
|
88
|
+
stroke-width: 2;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.ds-block-conn-label {
|
|
92
|
+
fill: var(--color-text-muted, #a09880);
|
|
93
|
+
font-size: 10px;
|
|
94
|
+
font-family: var(--font-mono, monospace);
|
|
95
|
+
text-anchor: middle;
|
|
96
|
+
pointer-events: none;
|
|
97
|
+
}
|
|
98
|
+
</style>
|