@stephen-netu/design-system 0.2.1 → 0.2.2

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 (187) hide show
  1. package/dist/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte +10 -2
  2. package/dist/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte.d.ts.map +1 -1
  3. package/dist/b0-app-shell/{command-bar/CommandBar.svelte → global-command-bar/GlobalCommandBar.svelte} +75 -75
  4. package/dist/b0-app-shell/{command-bar/CommandBar.svelte.d.ts → global-command-bar/GlobalCommandBar.svelte.d.ts} +6 -6
  5. package/dist/b0-app-shell/global-command-bar/GlobalCommandBar.svelte.d.ts.map +1 -0
  6. package/dist/b0-app-shell/index.d.ts +1 -1
  7. package/dist/b0-app-shell/index.d.ts.map +1 -1
  8. package/dist/b0-app-shell/index.js +1 -1
  9. package/dist/d0-data-viz/CheckpointPill.svelte +7 -2
  10. package/dist/d0-data-viz/CheckpointPill.svelte.d.ts.map +1 -1
  11. package/dist/d0-data-viz/theme-integration.d.ts +3 -3
  12. package/dist/d0-data-viz/theme-integration.js +3 -3
  13. package/dist/d0-data-viz/theme-integration.test.js +41 -0
  14. package/dist/demos/BspSizingInfographic.svelte +3 -32
  15. package/dist/editor/CodeEditor.test.js +38 -0
  16. package/dist/editor/FindReplaceDialog.svelte +32 -32
  17. package/dist/editor/MarkdownEditor.svelte +71 -58
  18. package/dist/editor/MarkdownEditor.svelte.d.ts.map +1 -1
  19. package/dist/editor/MarkdownEditor.test.js +38 -0
  20. package/dist/editor/components/CorrectionTooltip.svelte +0 -1
  21. package/dist/entity-graph-view/WorldView.svelte +1 -1
  22. package/dist/fabric/ai/ChatPanel.svelte +31 -31
  23. package/dist/fabric/ai/ResearchPanel.svelte +6 -3
  24. package/dist/fabric/ai/ResearchPanel.svelte.d.ts.map +1 -1
  25. package/dist/fabric/index.d.ts +4 -5
  26. package/dist/fabric/index.d.ts.map +1 -1
  27. package/dist/fabric/index.js +3 -3
  28. package/dist/fabric/input/{CommandBar.svelte → AppHeaderBar.svelte} +13 -13
  29. package/dist/fabric/input/{CommandBar.svelte.d.ts → AppHeaderBar.svelte.d.ts} +5 -5
  30. package/dist/fabric/input/AppHeaderBar.svelte.d.ts.map +1 -0
  31. package/dist/fabric/input/{CommandBar.test.js → AppHeaderBar.test.js} +9 -9
  32. package/dist/fabric/input/index.d.ts +2 -2
  33. package/dist/fabric/input/index.d.ts.map +1 -1
  34. package/dist/fabric/input/index.js +1 -1
  35. package/dist/fabric/layout/KanbanBoard.svelte +25 -155
  36. package/dist/fabric/layout/KanbanBoard.svelte.d.ts +2 -26
  37. package/dist/fabric/layout/KanbanBoard.svelte.d.ts.map +1 -1
  38. package/dist/fabric/layout/KanbanBoard.test.js +125 -10
  39. package/dist/fabric/layout/KanbanCard.svelte +27 -223
  40. package/dist/fabric/layout/KanbanCard.svelte.d.ts +2 -19
  41. package/dist/fabric/layout/KanbanCard.svelte.d.ts.map +1 -1
  42. package/dist/fabric/layout/KanbanColumn.svelte +41 -275
  43. package/dist/fabric/layout/KanbanColumn.svelte.d.ts +2 -22
  44. package/dist/fabric/layout/KanbanColumn.svelte.d.ts.map +1 -1
  45. package/dist/fabric/layout/index.d.ts +2 -5
  46. package/dist/fabric/layout/index.d.ts.map +1 -1
  47. package/dist/fabric/layout/index.js +1 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +4 -2
  50. package/dist/l0-layout/SectionSplitter.svelte +5 -5
  51. package/dist/l0-layout/block-writer/BlockItem.svelte +6 -4
  52. package/dist/l0-layout/card/CompactCard.svelte +4 -3
  53. package/dist/l0-layout/grant/GrantCard.svelte +15 -5
  54. package/dist/l0-layout/grant/GrantCard.svelte.d.ts.map +1 -1
  55. package/dist/l0-layout/index.d.ts +2 -0
  56. package/dist/l0-layout/index.d.ts.map +1 -1
  57. package/dist/l0-layout/index.js +1 -0
  58. package/dist/l0-layout/kanban/KanbanBoard.svelte +246 -29
  59. package/dist/l0-layout/kanban/KanbanBoard.svelte.d.ts +28 -2
  60. package/dist/l0-layout/kanban/KanbanBoard.svelte.d.ts.map +1 -1
  61. package/dist/l0-layout/kanban/KanbanCard.svelte +175 -150
  62. package/dist/l0-layout/kanban/KanbanCard.svelte.d.ts +16 -18
  63. package/dist/l0-layout/kanban/KanbanCard.svelte.d.ts.map +1 -1
  64. package/dist/l0-layout/kanban/KanbanColumn.svelte +152 -78
  65. package/dist/l0-layout/kanban/KanbanColumn.svelte.d.ts +28 -7
  66. package/dist/l0-layout/kanban/KanbanColumn.svelte.d.ts.map +1 -1
  67. package/dist/l0-layout/kanban/index.d.ts +6 -0
  68. package/dist/l0-layout/kanban/index.d.ts.map +1 -0
  69. package/dist/l0-layout/kanban/index.js +3 -0
  70. package/dist/n0-node-graph/Node.svelte +2 -2
  71. package/dist/n0-node-graph/NodePalette.svelte +2 -2
  72. package/dist/n1-flow-canvas/graph-state.test.js +69 -0
  73. package/dist/n1-flow-canvas/utils.test.js +116 -0
  74. package/dist/n3-force-graph/GraphTooltip.svelte +2 -2
  75. package/dist/n4-adaptive-manifold/AdaptiveManifold.svelte +12 -11
  76. package/dist/n4-adaptive-manifold/AdaptiveManifold.svelte.d.ts.map +1 -1
  77. package/dist/n4-adaptive-manifold/classifier.test.js +104 -0
  78. package/dist/n4-adaptive-manifold/n4-tokens.css +2 -2
  79. package/dist/p0-primitives/ThemeProvider.svelte +10 -11
  80. package/dist/p0-primitives/ThemeProvider.svelte.d.ts +1 -1
  81. package/dist/p0-primitives/ThemeProvider.svelte.d.ts.map +1 -1
  82. package/dist/p0-primitives/canvas-theme.d.ts +12 -0
  83. package/dist/p0-primitives/canvas-theme.d.ts.map +1 -1
  84. package/dist/p0-primitives/canvas-theme.js +10 -0
  85. package/dist/p0-primitives/index.d.ts +2 -1
  86. package/dist/p0-primitives/index.d.ts.map +1 -1
  87. package/dist/p0-primitives/index.js +1 -0
  88. package/dist/p0-primitives/theme-context.d.ts +9 -0
  89. package/dist/p0-primitives/theme-context.d.ts.map +1 -0
  90. package/dist/p0-primitives/theme-context.js +8 -0
  91. package/dist/p0-primitives/tokens/tokens.css +22 -11
  92. package/dist/p0-primitives/utils/index.d.ts +2 -2
  93. package/dist/p0-primitives/utils/index.d.ts.map +1 -1
  94. package/dist/s0-state/SyncStatus.svelte +1 -1
  95. package/dist/s0-state/ThemeStore.svelte.d.ts +3 -2
  96. package/dist/s0-state/ThemeStore.svelte.d.ts.map +1 -1
  97. package/dist/s0-state/ThemeStore.svelte.js +20 -1
  98. package/dist/s0-state/index.d.ts +0 -1
  99. package/dist/s0-state/index.d.ts.map +1 -1
  100. package/dist/s0-state/index.js +1 -0
  101. package/dist/s0-state/modal-stack-store.svelte.d.ts +25 -0
  102. package/dist/s0-state/modal-stack-store.svelte.d.ts.map +1 -1
  103. package/dist/s0-state/modal-stack-store.svelte.js +19 -0
  104. package/dist/showcase/Showcase.svelte +43 -34
  105. package/dist/showcase/Showcase.svelte.d.ts.map +1 -1
  106. package/dist/spatial/BspTilingCanvas.svelte +5 -5
  107. package/dist/spatial/BspTilingSimulation.test.js +88 -0
  108. package/dist/spatial/CameraController.test.js +120 -0
  109. package/dist/spatial/ForceCanvas.svelte +18 -13
  110. package/dist/spatial/ForceCanvas.svelte.d.ts.map +1 -1
  111. package/dist/spatial/ForceSimulation.svelte.d.ts.map +1 -1
  112. package/dist/spatial/ForceSimulation.svelte.js +32 -21
  113. package/dist/spatial/LodRenderer.svelte +14 -1
  114. package/dist/spatial/LodRenderer.svelte.d.ts.map +1 -1
  115. package/dist/spatial/SnapZoomCamera.svelte +23 -13
  116. package/dist/spatial/SnapZoomCamera.svelte.d.ts.map +1 -1
  117. package/dist/spatial/ZoneTiler.svelte +3 -2
  118. package/dist/spatial/d3-types.d.ts +31 -0
  119. package/dist/spatial/d3-types.d.ts.map +1 -0
  120. package/dist/spatial/d3-types.js +19 -0
  121. package/dist/ssr-import-clean.test.js +37 -0
  122. package/dist/t0-transport/fs.d.ts +12 -0
  123. package/dist/t0-transport/fs.d.ts.map +1 -0
  124. package/dist/t0-transport/fs.js +55 -0
  125. package/dist/t0-transport/index.d.ts +1 -0
  126. package/dist/t0-transport/index.d.ts.map +1 -1
  127. package/dist/t0-transport/index.js +1 -0
  128. package/dist/t0-transport/invoke.d.ts.map +1 -1
  129. package/dist/t0-transport/invoke.js +5 -2
  130. package/dist/t0-transport/quality.d.ts +12 -3
  131. package/dist/t0-transport/quality.d.ts.map +1 -1
  132. package/dist/t0-transport/quality.js +17 -4
  133. package/dist/t0-transport/substrate.svelte.d.ts +27 -0
  134. package/dist/t0-transport/substrate.svelte.d.ts.map +1 -0
  135. package/dist/t0-transport/substrate.svelte.js +49 -0
  136. package/dist/u0-primitives/LockIndicator.svelte +1 -1
  137. package/dist/u0-primitives/VerticalToolbar.svelte +1 -1
  138. package/dist/u0-primitives/accordion/Accordion.svelte +10 -9
  139. package/dist/u0-primitives/accordion/Accordion.svelte.d.ts +0 -7
  140. package/dist/u0-primitives/accordion/Accordion.svelte.d.ts.map +1 -1
  141. package/dist/u0-primitives/accordion/Accordion.test.js +5 -5
  142. package/dist/u0-primitives/badge/Badge.test.js +10 -10
  143. package/dist/u0-primitives/badge/ValidityBadge.test.js +9 -9
  144. package/dist/u0-primitives/button/Button.svelte +3 -1
  145. package/dist/u0-primitives/button/Button.svelte.d.ts +1 -0
  146. package/dist/u0-primitives/button/Button.svelte.d.ts.map +1 -1
  147. package/dist/u0-primitives/button/Button.test.js +11 -11
  148. package/dist/u0-primitives/card/Card.svelte +26 -20
  149. package/dist/u0-primitives/card/Card.svelte.d.ts.map +1 -1
  150. package/dist/u0-primitives/command-palette/CommandPalette.svelte +27 -0
  151. package/dist/u0-primitives/command-palette/CommandPalette.svelte.d.ts.map +1 -1
  152. package/dist/u0-primitives/command-palette/commandStore.svelte.d.ts.map +1 -1
  153. package/dist/u0-primitives/command-palette/commandStore.svelte.js +2 -1
  154. package/dist/u0-primitives/dropdown/Dropdown.test.js +1 -1
  155. package/dist/u0-primitives/index.d.ts +2 -0
  156. package/dist/u0-primitives/index.d.ts.map +1 -1
  157. package/dist/u0-primitives/index.js +1 -0
  158. package/dist/u0-primitives/input/Input.svelte +9 -0
  159. package/dist/u0-primitives/input/Input.svelte.d.ts.map +1 -1
  160. package/dist/u0-primitives/input/Input.test.js +1 -1
  161. package/dist/u0-primitives/modal/Modal.svelte +46 -23
  162. package/dist/u0-primitives/modal/Modal.svelte.d.ts.map +1 -1
  163. package/dist/u0-primitives/modal/Modal.test.js +63 -15
  164. package/dist/u0-primitives/rsvp/RsvpReader.svelte +8 -8
  165. package/dist/u0-primitives/rsvp/RsvpReader.svelte.d.ts.map +1 -1
  166. package/dist/u0-primitives/steps/Steps.svelte +2 -2
  167. package/dist/u0-primitives/surface-state/SurfaceState.svelte +190 -0
  168. package/dist/u0-primitives/surface-state/SurfaceState.svelte.d.ts +15 -0
  169. package/dist/u0-primitives/surface-state/SurfaceState.svelte.d.ts.map +1 -0
  170. package/dist/u0-primitives/toggle/Toggle.svelte +12 -2
  171. package/dist/u0-primitives/tooltip/Tooltip.test.js +12 -12
  172. package/dist/v0-diagrams/MarkmapDiagram.test.js +49 -0
  173. package/dist/v0-diagrams/MermaidDiagram.svelte +21 -9
  174. package/dist/v0-diagrams/MermaidDiagram.svelte.d.ts.map +1 -1
  175. package/dist/v0-diagrams/MermaidDiagram.test.js +40 -0
  176. package/package.json +50 -24
  177. package/src/n4-adaptive-manifold/n4-tokens.css +2 -2
  178. package/src/p0-primitives/tokens/tokens.css +22 -11
  179. package/src/p0-primitives/tokens/tokens.json +13 -2
  180. package/dist/b0-app-shell/command-bar/CommandBar.svelte.d.ts.map +0 -1
  181. package/dist/fabric/input/CommandBar.svelte.d.ts.map +0 -1
  182. package/dist/stores/vaultStore.svelte +0 -14
  183. package/dist/stores/vaultStore.svelte.d.ts +0 -24
  184. package/dist/stores/vaultStore.svelte.d.ts.map +0 -1
  185. package/dist/tauri/index.d.ts +0 -3
  186. package/dist/tauri/index.d.ts.map +0 -1
  187. package/dist/tauri/index.js +0 -11
@@ -1 +1 @@
1
- {"version":3,"file":"LodRenderer.svelte.d.ts","sourceRoot":"","sources":["../../src/spatial/LodRenderer.svelte.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAgB,MAAM,gBAAgB,CAAC;AAQ9E,UAAU,KAAK;IACb,sCAAsC;IACtC,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAI3B,gCAAgC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC7C,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC7C,wBAAwB;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC7C;8DAC0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IAE7C,sDAAsD;IACtD,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;CACzD;AAED,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAsNvC,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"LodRenderer.svelte.d.ts","sourceRoot":"","sources":["../../src/spatial/LodRenderer.svelte.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAgB,MAAM,gBAAgB,CAAC;AAQ9E,UAAU,KAAK;IACb,sCAAsC;IACtC,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAI3B,gCAAgC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC7C,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC7C,wBAAwB;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC7C;8DAC0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IAE7C,sDAAsD;IACtD,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;CACzD;AAED,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAmOvC,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -4,7 +4,7 @@
4
4
  // Renders via CSS transforms on a wrapper div
5
5
 
6
6
  import type { Snippet } from 'svelte';
7
- import { onMount, onDestroy } from 'svelte';
7
+ import { onMount, onDestroy, untrack } from 'svelte';
8
8
  import { CameraController } from './CameraController.svelte.js';
9
9
  import type { CameraState, SnapZoomTarget, CameraConfig } from './camera-types.js';
10
10
  import type { InteractionContext } from '../s0-lifecycle/InteractionContext.js';
@@ -27,8 +27,21 @@
27
27
  onCameraChange,
28
28
  }: Props = $props();
29
29
 
30
- const controller = $state(new CameraController(width, height, config));
31
- const cameraState: CameraState = $derived(controller.getCameraState());
30
+ let controller = $state<CameraController | null>(null);
31
+ const cameraState: CameraState = $derived(controller?.getCameraState() ?? { zoom: 1, panX: 0, panY: 0 });
32
+ const panX = $derived(controller?.panX ?? 0);
33
+ const panY = $derived(controller?.panY ?? 0);
34
+ const zoom = $derived(controller?.zoom ?? 1);
35
+
36
+ $effect(() => {
37
+ void width;
38
+ void height;
39
+ void config;
40
+ untrack(() => {
41
+ controller = new CameraController(width, height, config);
42
+ runPhases();
43
+ });
44
+ });
32
45
 
33
46
  $effect(() => {
34
47
  onCameraChange?.(cameraState);
@@ -37,6 +50,7 @@
37
50
  // ── Contexts for lifecycle phases ─────────────────────────────────────────
38
51
 
39
52
  function runPhases(): void {
53
+ if (!controller) return;
40
54
  controller.constrain({
41
55
  available: {
42
56
  width: { min: width, preferred: width, max: width },
@@ -61,17 +75,13 @@
61
75
  });
62
76
  }
63
77
 
64
- onMount(() => {
65
- runPhases();
66
- });
67
-
68
78
  // ── Interaction forwarding ────────────────────────────────────────────────
69
79
 
70
80
  let wheelRafId: number | null = null;
71
81
  let pendingWheelEvent: WheelEvent | null = null;
72
82
 
73
83
  onDestroy(() => {
74
- controller.stop();
84
+ controller?.stop();
75
85
  if (wheelRafId !== null) cancelAnimationFrame(wheelRafId);
76
86
  });
77
87
 
@@ -120,14 +130,14 @@
120
130
  pendingWheelEvent = null;
121
131
  if (evt) {
122
132
  const ctx = makeInteractionContext(evt);
123
- controller.interact(ctx);
133
+ controller?.interact(ctx);
124
134
  }
125
135
  });
126
136
  }
127
137
 
128
138
  function handlePointerDown(e: PointerEvent) {
129
139
  const ctx = makeInteractionContext(e);
130
- const outcome = controller.interact(ctx);
140
+ const outcome = controller?.interact(ctx);
131
141
  if (outcome === 'consumed') {
132
142
  (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
133
143
  }
@@ -135,12 +145,12 @@
135
145
 
136
146
  function handlePointerMove(e: PointerEvent) {
137
147
  const ctx = makeInteractionContext(e);
138
- controller.interact(ctx);
148
+ controller?.interact(ctx);
139
149
  }
140
150
 
141
151
  function handlePointerUp(e: PointerEvent) {
142
152
  const ctx = makeInteractionContext(e);
143
- controller.interact(ctx);
153
+ controller?.interact(ctx);
144
154
  }
145
155
  </script>
146
156
 
@@ -157,7 +167,7 @@
157
167
  >
158
168
  <div
159
169
  class="camera-viewport"
160
- style:transform="translate({controller.panX}px, {controller.panY}px) scale({controller.zoom})"
170
+ style:transform="translate({panX}px, {panY}px) scale({zoom})"
161
171
  style:transform-origin="0 0"
162
172
  >
163
173
  {@render children(cameraState)}
@@ -1 +1 @@
1
- {"version":3,"file":"SnapZoomCamera.svelte.d.ts","sourceRoot":"","sources":["../../src/spatial/SnapZoomCamera.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,KAAK,EAAE,WAAW,EAAkB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIjF,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CAC/C;AAED,MAAM,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAsJ1C,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"SnapZoomCamera.svelte.d.ts","sourceRoot":"","sources":["../../src/spatial/SnapZoomCamera.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,KAAK,EAAE,WAAW,EAAkB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIjF,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CAC/C;AAED,MAAM,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAgK1C,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -204,7 +204,7 @@
204
204
  style:height="{height}px"
205
205
  onkeydown={handleKeydown}
206
206
  tabindex="0"
207
- role="application"
207
+ role="grid"
208
208
  aria-label="Zone tiler — use h/j/k/l to navigate zones"
209
209
  >
210
210
  <!-- Zone panes -->
@@ -219,7 +219,8 @@
219
219
  style:width="{zone.width}px"
220
220
  style:height="{zone.height}px"
221
221
  tabindex="0"
222
- role="region"
222
+ role="button"
223
+ aria-pressed={zone.id === focusedZoneId}
223
224
  aria-label={zone.zone.label}
224
225
  data-zone-id={zone.id}
225
226
  onclick={() => handleZoneClick(zone.id)}
@@ -0,0 +1,31 @@
1
+ import type { ForceCell, ForceLink } from './force-canvas-types';
2
+ export interface D3SimulationNode {
3
+ id: string;
4
+ index?: number;
5
+ x?: number;
6
+ y?: number;
7
+ vx?: number;
8
+ vy?: number;
9
+ fx?: number | null;
10
+ fy?: number | null;
11
+ }
12
+ export interface D3ForceLink<T extends D3SimulationNode = D3SimulationNode> {
13
+ source: T | string;
14
+ target: T | string;
15
+ distance?: number;
16
+ }
17
+ export interface D3Simulation<T extends D3SimulationNode = D3SimulationNode> {
18
+ force(name: string): unknown;
19
+ force(name: string, force: unknown): this;
20
+ nodes(): T[];
21
+ nodes(nodes: T[]): this;
22
+ alphaDecay(): number;
23
+ alphaDecay(decay: number): this;
24
+ velocityDecay(): number;
25
+ velocityDecay(decay: number): this;
26
+ on(event: string, listener: (() => void) | null): this;
27
+ stop(): void;
28
+ }
29
+ export declare function toD3Node(cell: ForceCell): D3SimulationNode;
30
+ export declare function toD3Link(link: ForceLink): D3ForceLink;
31
+ //# sourceMappingURL=d3-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"d3-types.d.ts","sourceRoot":"","sources":["../../src/spatial/d3-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB;IACxE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC;IACnB,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB;IACzE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1C,KAAK,IAAI,CAAC,EAAE,CAAC;IACb,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC;IACxB,UAAU,IAAI,MAAM,CAAC;IACrB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,IAAI,MAAM,CAAC;IACxB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;IACvD,IAAI,IAAI,IAAI,CAAC;CACd;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,gBAAgB,CAW1D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW,CAMrD"}
@@ -0,0 +1,19 @@
1
+ export function toD3Node(cell) {
2
+ return {
3
+ id: cell.id,
4
+ index: cell.index,
5
+ x: cell.x,
6
+ y: cell.y,
7
+ vx: cell.vx,
8
+ vy: cell.vy,
9
+ fx: cell.fx,
10
+ fy: cell.fy,
11
+ };
12
+ }
13
+ export function toD3Link(link) {
14
+ return {
15
+ source: link.source,
16
+ target: link.target,
17
+ distance: link.distance,
18
+ };
19
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * F-30a: Verify that key modules import cleanly without browser-API violations.
3
+ *
4
+ * vitest-setup.ts injects a localStorage mock and jsdom provides window/document,
5
+ * which can mask SSR violations. This test verifies that pure logic modules
6
+ * (no DOM, no browser-only APIs) import and execute without errors.
7
+ */
8
+ import { describe, it, expect } from 'vitest';
9
+ describe('F-30a import-clean (pure modules)', () => {
10
+ it('quality module imports cleanly (module-scope singletons)', async () => {
11
+ const mod = await import('./t0-transport/quality');
12
+ expect(mod.startQualityMonitoring).toBeDefined();
13
+ expect(mod.subscribeQuality).toBeDefined();
14
+ expect(mod.getCurrentMetrics).toBeDefined();
15
+ });
16
+ it('n1-flow-canvas utils are pure and import cleanly', async () => {
17
+ const mod = await import('./n1-flow-canvas/utils');
18
+ expect(mod.nodeHitTest).toBeDefined();
19
+ expect(mod.domEventToCanvasCoords).toBeDefined();
20
+ expect(mod.parseMentionEdges).toBeDefined();
21
+ expect(mod.parseGroupedSequenceEdges).toBeDefined();
22
+ });
23
+ it('n4 classifier is pure and import cleanly', async () => {
24
+ const mod = await import('./n4-adaptive-manifold/classifier');
25
+ expect(mod.classifyTopology).toBeDefined();
26
+ expect(mod.computeMetrics).toBeDefined();
27
+ });
28
+ it('n4 transition is pure and import cleanly', async () => {
29
+ const mod = await import('./n4-adaptive-manifold/transition');
30
+ expect(mod.EASING_FUNCTIONS).toBeDefined();
31
+ expect(mod.TransitionAnimator).toBeDefined();
32
+ });
33
+ it('n4 graph-state is pure and import cleanly', async () => {
34
+ const mod = await import('./n1-flow-canvas/graph-state.svelte');
35
+ expect(mod.GraphState).toBeDefined();
36
+ });
37
+ });
@@ -0,0 +1,12 @@
1
+ export { isTauri } from './invoke';
2
+ /** Thrown when no Tauri runtime (or no fs plugin) is available. */
3
+ export declare class FsUnavailableError extends Error {
4
+ constructor(operation: string, cause?: unknown);
5
+ }
6
+ /** Read a text file. Rejects with FsUnavailableError outside a Tauri host. */
7
+ export declare function readTextFile(path: string): Promise<string>;
8
+ /** Write a text file. Rejects with FsUnavailableError outside a Tauri host — never a silent no-op. */
9
+ export declare function writeTextFile(path: string, contents: string): Promise<void>;
10
+ /** Last-modified time in epoch ms, or null when the backend can't provide one. */
11
+ export declare function getMtimeMs(path: string): Promise<number | null>;
12
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/t0-transport/fs.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,mEAAmE;AACnE,qBAAa,kBAAmB,SAAQ,KAAK;gBAChC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAQ9C;AAsBD,8EAA8E;AAC9E,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhE;AAED,sGAAsG;AACtG,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjF;AAED,kFAAkF;AAClF,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIrE"}
@@ -0,0 +1,55 @@
1
+ // T0 Transport — file persistence over the optional Tauri FS plugin.
2
+ //
3
+ // Follows the same optional-peer pattern as invoke.ts: a literal dynamic
4
+ // import of the Tauri module, guarded at runtime by isTauri(). In a non-Tauri
5
+ // environment every operation rejects with FsUnavailableError — callers must
6
+ // surface that state instead of pretending the operation succeeded.
7
+ //
8
+ // NOTE: deliberately NOT re-exported from the t0-transport barrel. The barrel
9
+ // is reachable from the root package export; keeping fs.ts subpath-only means
10
+ // consumers who never import the editor never make their bundler resolve
11
+ // '@tauri-apps/plugin-fs' (an optional peer). Import it directly:
12
+ // import { readTextFile, writeTextFile } from '<pkg>/t0-transport/fs' (internal: '../t0-transport/fs')
13
+ import { isTauri } from './invoke';
14
+ export { isTauri } from './invoke';
15
+ /** Thrown when no Tauri runtime (or no fs plugin) is available. */
16
+ export class FsUnavailableError extends Error {
17
+ constructor(operation, cause) {
18
+ super(`File ${operation} unavailable: no Tauri runtime detected. ` +
19
+ 'Persistence requires a Tauri host with @tauri-apps/plugin-fs installed.');
20
+ this.name = 'FsUnavailableError';
21
+ if (cause !== undefined)
22
+ this.cause = cause;
23
+ }
24
+ }
25
+ async function loadFs(operation) {
26
+ if (!isTauri())
27
+ throw new FsUnavailableError(operation);
28
+ try {
29
+ // @tauri-apps/plugin-fs is an optional peer. Using an indirect specifier
30
+ // so TypeScript and bundlers treat this as a fully dynamic import — no
31
+ // static module resolution, no build-time error on missing package.
32
+ const spec = '@tauri-apps/plugin-fs';
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ return await import(/* @vite-ignore */ spec);
35
+ }
36
+ catch (cause) {
37
+ throw new FsUnavailableError(operation, cause);
38
+ }
39
+ }
40
+ /** Read a text file. Rejects with FsUnavailableError outside a Tauri host. */
41
+ export async function readTextFile(path) {
42
+ const fs = await loadFs('read');
43
+ return fs.readTextFile(path);
44
+ }
45
+ /** Write a text file. Rejects with FsUnavailableError outside a Tauri host — never a silent no-op. */
46
+ export async function writeTextFile(path, contents) {
47
+ const fs = await loadFs('write');
48
+ await fs.writeTextFile(path, contents);
49
+ }
50
+ /** Last-modified time in epoch ms, or null when the backend can't provide one. */
51
+ export async function getMtimeMs(path) {
52
+ const fs = await loadFs('stat');
53
+ const info = await fs.stat(path);
54
+ return info?.mtime ? new Date(info.mtime).getTime() : null;
55
+ }
@@ -2,5 +2,6 @@ export { invoke, isTauri, isTauriReady, awaitTauriReady } from './invoke';
2
2
  export { createEventBus, type EventBus } from './events';
3
3
  export { TransportError, TransportErrorCode } from './error';
4
4
  export { createConnectionTracker, type ConnectionState } from './connection';
5
+ export { createSubstrateConnection, type CreateSubstrateConnectionOptions, type SubstrateConnection, type SubstrateState, } from './substrate.svelte';
5
6
  export { startQualityMonitoring, stopQualityMonitoring, recordPingStart, recordPingEnd, subscribeQuality, getCurrentMetrics, createQualityMonitor, getQualityColor, getQualityLabel, type QualityMetrics, type QualitySample, type QualityLevel, type QualityMonitor, } from './quality';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/t0-transport/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAG7E,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/t0-transport/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EACL,yBAAyB,EACzB,KAAK,gCAAgC,EACrC,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACpB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,WAAW,CAAC"}
@@ -3,5 +3,6 @@ export { invoke, isTauri, isTauriReady, awaitTauriReady } from './invoke';
3
3
  export { createEventBus } from './events';
4
4
  export { TransportError, TransportErrorCode } from './error';
5
5
  export { createConnectionTracker } from './connection';
6
+ export { createSubstrateConnection, } from './substrate.svelte';
6
7
  // New from NNJAS port - Connection quality monitoring
7
8
  export { startQualityMonitoring, stopQualityMonitoring, recordPingStart, recordPingEnd, subscribeQuality, getCurrentMetrics, createQualityMonitor, getQualityColor, getQualityLabel, } from './quality';
@@ -1 +1 @@
1
- {"version":3,"file":"invoke.d.ts","sourceRoot":"","sources":["../../src/t0-transport/invoke.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,QAAQ,CAAC,EAAE,CAAC,CAAC;CACd;AAOD;;GAEG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzF,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,CAAC,GACV,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;GAEG;AACH,wBAAgB,OAAO,IAAI,OAAO,CAEjC;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAUxD"}
1
+ {"version":3,"file":"invoke.d.ts","sourceRoot":"","sources":["../../src/t0-transport/invoke.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,QAAQ,CAAC,EAAE,CAAC,CAAC;CACd;AAYD;;GAEG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzF,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,CAAC,GACV,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;GAEG;AACH,wBAAgB,OAAO,IAAI,OAAO,CAEjC;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAGtC;AAED;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAUxD"}
@@ -1,6 +1,7 @@
1
1
  // Type-safe invoke wrapper for Tauri commands
2
2
  async function getTauriInvoke() {
3
- const mod = await import('@tauri-apps/api/core');
3
+ const spec = '@tauri-apps/api/core';
4
+ const mod = await import(/* @vite-ignore */ spec);
4
5
  return mod.invoke;
5
6
  }
6
7
  /**
@@ -26,7 +27,9 @@ export function isTauri() {
26
27
  * Use for conditional rendering. Use awaitTauriReady() for init paths.
27
28
  */
28
29
  export function isTauriReady() {
29
- return typeof window !== 'undefined' && window.__TAURI_INTERNALS__ != null;
30
+ if (typeof window === 'undefined')
31
+ return false;
32
+ return window.__TAURI_INTERNALS__ != null;
30
33
  }
31
34
  /**
32
35
  * Polls until window.__TAURI_INTERNALS__ is available (up to 5 seconds).
@@ -1,8 +1,17 @@
1
1
  /**
2
- * Connection Quality Monitoring
2
+ * Connection Quality Monitoring (F-29 — module-scope singleton).
3
3
  *
4
- * A generalized version of NNJAS quality.ts for the LEAP design system.
5
- * Monitors WebSocket/connection quality with latency tracking.
4
+ * Holds module-scope mutable state (metrics, pingId, interval, subscribers).
5
+ * startQualityMonitoring() uses setInterval; consume via subscribeQuality()
6
+ * for reactive updates in components.
7
+ *
8
+ * @module t0-transport/quality
9
+ * @example
10
+ * ```ts
11
+ * import { startQualityMonitoring, subscribeQuality } from '@kos/design-system/t0-transport';
12
+ * startQualityMonitoring();
13
+ * const unsub = subscribeQuality(m => console.log(m.quality));
14
+ * ```
6
15
  */
7
16
  export type QualityLevel = 'excellent' | 'good' | 'fair' | 'poor' | 'disconnected';
8
17
  export interface QualitySample {
@@ -1 +1 @@
1
- {"version":3,"file":"quality.d.ts","sourceRoot":"","sources":["../../src/t0-transport/quality.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,cAAc,CAAC;AAEnF,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;IACb,IAAI,IAAI,IAAI,CAAC;IACb,UAAU,IAAI,cAAc,CAAC;IAC7B,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACpE;AA2DD,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAQ7D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAQ7D;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAkB7C;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAM5C;AAED,wBAAgB,eAAe,IAAI,MAAM,CAGtC;AAEH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAmBlE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI,CASxF;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAElD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAoHrD"}
1
+ {"version":3,"file":"quality.d.ts","sourceRoot":"","sources":["../../src/t0-transport/quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,cAAc,CAAC;AAEnF,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;IACb,IAAI,IAAI,IAAI,CAAC;IACb,UAAU,IAAI,cAAc,CAAC;IAC7B,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACpE;AA2DD,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAQ7D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAQ7D;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAsB7C;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAM5C;AAED,wBAAgB,eAAe,IAAI,MAAM,CAGtC;AAEH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAmBlE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI,CASxF;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAElD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAoHrD"}
@@ -1,12 +1,21 @@
1
1
  /**
2
- * Connection Quality Monitoring
2
+ * Connection Quality Monitoring (F-29 — module-scope singleton).
3
3
  *
4
- * A generalized version of NNJAS quality.ts for the LEAP design system.
5
- * Monitors WebSocket/connection quality with latency tracking.
4
+ * Holds module-scope mutable state (metrics, pingId, interval, subscribers).
5
+ * startQualityMonitoring() uses setInterval; consume via subscribeQuality()
6
+ * for reactive updates in components.
7
+ *
8
+ * @module t0-transport/quality
9
+ * @example
10
+ * ```ts
11
+ * import { startQualityMonitoring, subscribeQuality } from '@kos/design-system/t0-transport';
12
+ * startQualityMonitoring();
13
+ * const unsub = subscribeQuality(m => console.log(m.quality));
14
+ * ```
6
15
  */
7
16
  const SAMPLE_WINDOW = 60; // 60 seconds of history
8
17
  const PING_INTERVAL = 5000; // Ping every 5 seconds
9
- const MAX_HISTORY = 12; // Keep last 12 samples
18
+ const MAX_HISTORY = Math.max(12, Math.ceil(SAMPLE_WINDOW * 1000 / PING_INTERVAL)); // 60s window 12 samples at 5s interval
10
19
  let metrics = {
11
20
  latency: null,
12
21
  jitter: null,
@@ -88,6 +97,10 @@ export function startQualityMonitoring() {
88
97
  lost: true
89
98
  });
90
99
  pingStartTime = null;
100
+ // Trim to bounded size — interval runs every 1s so history can grow fast
101
+ if (metrics.history.length > MAX_HISTORY) {
102
+ metrics.history = metrics.history.slice(-MAX_HISTORY);
103
+ }
91
104
  updateMetrics();
92
105
  }
93
106
  }
@@ -0,0 +1,27 @@
1
+ export type SubstrateState = {
2
+ status: 'starting';
3
+ } | {
4
+ status: 'connected';
5
+ seqno: number;
6
+ } | {
7
+ status: 'reconnecting';
8
+ attempt: number;
9
+ } | {
10
+ status: 'failed';
11
+ reason: string;
12
+ };
13
+ export interface SubstrateConnection {
14
+ state: SubstrateState;
15
+ init(): Promise<void>;
16
+ retry(): Promise<void>;
17
+ destroy(): void;
18
+ isDegraded: boolean;
19
+ retryLabel: string;
20
+ }
21
+ export interface CreateSubstrateConnectionOptions {
22
+ getStateCommand?: string;
23
+ stateEvent?: string;
24
+ retryCommand?: string;
25
+ }
26
+ export declare function createSubstrateConnection(options?: CreateSubstrateConnectionOptions): SubstrateConnection;
27
+ //# sourceMappingURL=substrate.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"substrate.svelte.d.ts","sourceRoot":"","sources":["../../src/t0-transport/substrate.svelte.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,cAAc,GACtB;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gCAAgC;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAkDD,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,gCAAqC,GAC7C,mBAAmB,CAErB"}
@@ -0,0 +1,49 @@
1
+ import { listen } from '@tauri-apps/api/event';
2
+ import { awaitTauriReady, invoke } from './invoke';
3
+ class SubstrateConnectionImpl {
4
+ options;
5
+ state = $state({ status: 'starting' });
6
+ unlisten = null;
7
+ constructor(options = {}) {
8
+ this.options = options;
9
+ }
10
+ get isDegraded() {
11
+ return this.state.status === 'reconnecting' || this.state.status === 'failed';
12
+ }
13
+ get retryLabel() {
14
+ return this.state.status === 'failed' ? 'Retry' : 'Reconnecting';
15
+ }
16
+ async init() {
17
+ this.destroy();
18
+ const ready = await awaitTauriReady();
19
+ if (!ready) {
20
+ console.warn('[SubstrateConnection] Tauri bridge not available — skipping listeners');
21
+ return;
22
+ }
23
+ try {
24
+ this.state = await invoke(this.options.getStateCommand ?? 'substrate_get_state');
25
+ }
26
+ catch (error) {
27
+ this.state = { status: 'failed', reason: error instanceof Error ? error.message : 'Unable to read substrate state' };
28
+ }
29
+ this.unlisten = await listen(this.options.stateEvent ?? 'substrate:state', (event) => {
30
+ this.state = event.payload;
31
+ });
32
+ }
33
+ async retry() {
34
+ this.state = { status: 'reconnecting', attempt: 0 };
35
+ try {
36
+ await invoke(this.options.retryCommand ?? 'substrate_retry');
37
+ }
38
+ catch (error) {
39
+ this.state = { status: 'failed', reason: error instanceof Error ? error.message : 'Unable to retry substrate connection' };
40
+ }
41
+ }
42
+ destroy() {
43
+ this.unlisten?.();
44
+ this.unlisten = null;
45
+ }
46
+ }
47
+ export function createSubstrateConnection(options = {}) {
48
+ return new SubstrateConnectionImpl(options);
49
+ }
@@ -121,7 +121,7 @@
121
121
  <style>
122
122
  .lock-indicator {
123
123
  position: relative;
124
- background: var(--color-bg-panel, var(--color-bg-panel-token, #181c20));
124
+ background: var(--color-bg-panel, #181c20);
125
125
  border-radius: var(--radius-md, 4px);
126
126
  overflow: hidden;
127
127
  }
@@ -117,7 +117,7 @@
117
117
  background: transparent;
118
118
  border: 1px solid transparent;
119
119
  border-radius: var(--radius-md, 4px);
120
- color: var(--color-text-muted, var(--color-text-muted-token, #6b6558));
120
+ color: var(--color-text-muted, #6b6558);
121
121
  cursor: pointer;
122
122
  transition: all 0.15s ease;
123
123
  }
@@ -6,6 +6,7 @@
6
6
  *
7
7
  * @package @kos/design-system/u0-primitives
8
8
  */
9
+ import { untrack } from 'svelte';
9
10
  import type { Snippet } from 'svelte';
10
11
 
11
12
  interface Panel {
@@ -40,7 +41,7 @@
40
41
  onOpenChange,
41
42
  }: Props = $props();
42
43
 
43
- let internalOpenIds = $state<string[]>([...defaultOpen]);
44
+ let internalOpenIds = $state<string[]>(untrack(() => [...defaultOpen]));
44
45
 
45
46
  function setInternalOpenIds(fn: (prev: string[]) => string[]) {
46
47
  internalOpenIds = fn(internalOpenIds);
@@ -125,14 +126,14 @@
125
126
 
126
127
  <style>
127
128
  .accordion {
128
- border-radius: var(--radius-md, 0.25rem);
129
+ border-radius: var(--radius-md);
129
130
  overflow: hidden;
130
- border: 1px solid var(--color-border, var(--border-default, #3a3630));
131
- background: var(--color-bg-app, #0b0d0f);
131
+ border: var(--border-width-thin) solid var(--color-border);
132
+ background: var(--color-bg-app);
132
133
  }
133
134
 
134
135
  .accordion-item {
135
- border-bottom: 1px solid var(--color-border, var(--border-default, #3a3630));
136
+ border-bottom: var(--border-width-thin) solid var(--color-border);
136
137
  }
137
138
 
138
139
  .accordion-item:last-child {
@@ -148,21 +149,21 @@
148
149
  display: flex;
149
150
  align-items: center;
150
151
  justify-content: space-between;
151
- padding: var(--space-4, 1rem);
152
+ padding: var(--space-4);
152
153
  cursor: pointer;
153
154
  user-select: none;
154
- transition: background-color var(--duration-normal, 200ms) ease-in-out;
155
+ transition: background-color var(--duration-normal) ease-in-out;
155
156
  }
156
157
 
157
158
  .accordion-header:hover:not(.disabled) {
158
- background: var(--color-bg-secondary, var(--color-bg-canvas, #121518));
159
+ background: var(--color-bg-secondary);
159
160
  }
160
161
 
161
162
  /* Removed duplicate focus-visible — the box-shadow variant below supersedes. */
162
163
 
163
164
  /* Focus styles for keyboard navigation */
164
165
  .accordion-header:focus-visible {
165
- box-shadow: 0 0 0 2px var(--color-accent, var(--color-accent));
166
+ box-shadow: 0 0 0 var(--border-width-default) var(--color-accent);
166
167
  }
167
168
 
168
169
  /* Disabled states */
@@ -1,10 +1,3 @@
1
- /**
2
- * Accordion Component
3
- *
4
- * A vertically stacked set of interactive headings that each reveal a panel of associated content.
5
- *
6
- * @package @kos/design-system/u0-primitives
7
- */
8
1
  import type { Snippet } from 'svelte';
9
2
  interface Panel {
10
3
  /** Unique identifier for the panel */
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.svelte.d.ts","sourceRoot":"","sources":["../../../src/u0-primitives/accordion/Accordion.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;KAMK;AACL,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGpC,UAAU,KAAK;IACb,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,KAAK;IACpB,iCAAiC;IACjC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,mDAAmD;IACnD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,uCAAuC;IACvC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC5C;AAyFH,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"Accordion.svelte.d.ts","sourceRoot":"","sources":["../../../src/u0-primitives/accordion/Accordion.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGpC,UAAU,KAAK;IACb,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,KAAK;IACpB,iCAAiC;IACjC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,mDAAmD;IACnD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,uCAAuC;IACvC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC5C;AA0FH,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -2,9 +2,9 @@ import { afterEach, describe, it, expect, vi } from 'vitest';
2
2
  import { cleanup, render, fireEvent } from '@testing-library/svelte';
3
3
  import Accordion from './Accordion.svelte';
4
4
  const samplePanels = [
5
- { id: 'p1', title: 'First', content: () => 'Content 1' },
6
- { id: 'p2', title: 'Second', content: () => 'Content 2' },
7
- { id: 'p3', title: 'Third', content: () => 'Content 3' },
5
+ { id: 'p1', title: 'First', content: (() => '') },
6
+ { id: 'p2', title: 'Second', content: (() => '') },
7
+ { id: 'p3', title: 'Third', content: (() => '') },
8
8
  ];
9
9
  describe('Accordion', () => {
10
10
  afterEach(() => cleanup());
@@ -54,8 +54,8 @@ describe('Accordion', () => {
54
54
  });
55
55
  it('does not open disabled panels', async () => {
56
56
  const panels = [
57
- { id: 'p1', title: 'Enabled', content: () => 'E' },
58
- { id: 'p2', title: 'Disabled', content: () => 'D', disabled: true },
57
+ { id: 'p1', title: 'Enabled', content: (() => '') },
58
+ { id: 'p2', title: 'Disabled', content: (() => ''), disabled: true },
59
59
  ];
60
60
  const { container } = render(Accordion, { panels });
61
61
  const buttons = container.querySelectorAll('[role="button"]');