@stephen-netu/design-system 0.2.0 → 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.
- package/dist/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte +10 -2
- package/dist/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte.d.ts.map +1 -1
- package/dist/b0-app-shell/{command-bar/CommandBar.svelte → global-command-bar/GlobalCommandBar.svelte} +75 -75
- package/dist/b0-app-shell/{command-bar/CommandBar.svelte.d.ts → global-command-bar/GlobalCommandBar.svelte.d.ts} +6 -6
- package/dist/b0-app-shell/global-command-bar/GlobalCommandBar.svelte.d.ts.map +1 -0
- package/dist/b0-app-shell/index.d.ts +1 -1
- package/dist/b0-app-shell/index.d.ts.map +1 -1
- package/dist/b0-app-shell/index.js +1 -1
- package/dist/d0-data-viz/CheckpointPill.svelte +7 -2
- package/dist/d0-data-viz/CheckpointPill.svelte.d.ts.map +1 -1
- package/dist/d0-data-viz/theme-integration.d.ts +3 -3
- package/dist/d0-data-viz/theme-integration.js +3 -3
- package/dist/d0-data-viz/theme-integration.test.js +41 -0
- package/dist/demos/BspSizingInfographic.svelte +3 -32
- package/dist/editor/CodeEditor.test.js +38 -0
- package/dist/editor/FindReplaceDialog.svelte +32 -32
- package/dist/editor/MarkdownEditor.svelte +71 -58
- package/dist/editor/MarkdownEditor.svelte.d.ts.map +1 -1
- package/dist/editor/MarkdownEditor.test.js +38 -0
- package/dist/editor/components/CorrectionTooltip.svelte +0 -1
- package/dist/editor/extensions/expansion.d.ts.map +1 -1
- package/dist/editor/extensions/expansion.js +16 -10
- package/dist/entity-graph-view/WorldView.svelte +1 -1
- package/dist/fabric/ai/ChatPanel.svelte +31 -31
- package/dist/fabric/ai/ResearchPanel.svelte +6 -3
- package/dist/fabric/ai/ResearchPanel.svelte.d.ts.map +1 -1
- package/dist/fabric/index.d.ts +4 -5
- package/dist/fabric/index.d.ts.map +1 -1
- package/dist/fabric/index.js +3 -3
- package/dist/fabric/input/{CommandBar.svelte → AppHeaderBar.svelte} +13 -13
- package/dist/fabric/input/{CommandBar.svelte.d.ts → AppHeaderBar.svelte.d.ts} +5 -5
- package/dist/fabric/input/AppHeaderBar.svelte.d.ts.map +1 -0
- package/dist/fabric/input/{CommandBar.test.js → AppHeaderBar.test.js} +9 -9
- package/dist/fabric/input/index.d.ts +2 -2
- package/dist/fabric/input/index.d.ts.map +1 -1
- package/dist/fabric/input/index.js +1 -1
- package/dist/fabric/layout/KanbanBoard.svelte +25 -155
- package/dist/fabric/layout/KanbanBoard.svelte.d.ts +2 -26
- package/dist/fabric/layout/KanbanBoard.svelte.d.ts.map +1 -1
- package/dist/fabric/layout/KanbanBoard.test.js +125 -10
- package/dist/fabric/layout/KanbanCard.svelte +27 -223
- package/dist/fabric/layout/KanbanCard.svelte.d.ts +2 -19
- package/dist/fabric/layout/KanbanCard.svelte.d.ts.map +1 -1
- package/dist/fabric/layout/KanbanColumn.svelte +41 -275
- package/dist/fabric/layout/KanbanColumn.svelte.d.ts +2 -22
- package/dist/fabric/layout/KanbanColumn.svelte.d.ts.map +1 -1
- package/dist/fabric/layout/index.d.ts +2 -5
- package/dist/fabric/layout/index.d.ts.map +1 -1
- package/dist/fabric/layout/index.js +1 -1
- package/dist/g0-generative/renderer/OpenUIRenderer.svelte +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/l0-layout/SectionSplitter.svelte +5 -5
- package/dist/l0-layout/block-writer/BlockItem.svelte +6 -4
- package/dist/l0-layout/card/CompactCard.svelte +4 -3
- package/dist/l0-layout/grant/GrantCard.svelte +15 -5
- package/dist/l0-layout/grant/GrantCard.svelte.d.ts.map +1 -1
- package/dist/l0-layout/index.d.ts +2 -0
- package/dist/l0-layout/index.d.ts.map +1 -1
- package/dist/l0-layout/index.js +1 -0
- package/dist/l0-layout/kanban/KanbanBoard.svelte +246 -29
- package/dist/l0-layout/kanban/KanbanBoard.svelte.d.ts +28 -2
- package/dist/l0-layout/kanban/KanbanBoard.svelte.d.ts.map +1 -1
- package/dist/l0-layout/kanban/KanbanCard.svelte +175 -150
- package/dist/l0-layout/kanban/KanbanCard.svelte.d.ts +16 -18
- package/dist/l0-layout/kanban/KanbanCard.svelte.d.ts.map +1 -1
- package/dist/l0-layout/kanban/KanbanColumn.svelte +152 -78
- package/dist/l0-layout/kanban/KanbanColumn.svelte.d.ts +28 -7
- package/dist/l0-layout/kanban/KanbanColumn.svelte.d.ts.map +1 -1
- package/dist/l0-layout/kanban/index.d.ts +6 -0
- package/dist/l0-layout/kanban/index.d.ts.map +1 -0
- package/dist/l0-layout/kanban/index.js +3 -0
- package/dist/n0-node-graph/Node.svelte +2 -2
- package/dist/n0-node-graph/NodePalette.svelte +2 -2
- package/dist/n1-flow-canvas/graph-state.test.js +69 -0
- package/dist/n1-flow-canvas/utils.test.js +116 -0
- package/dist/n3-force-graph/GraphTooltip.svelte +2 -2
- package/dist/n4-adaptive-manifold/AdaptiveManifold.svelte +12 -11
- package/dist/n4-adaptive-manifold/AdaptiveManifold.svelte.d.ts.map +1 -1
- package/dist/n4-adaptive-manifold/classifier.test.js +104 -0
- package/dist/n4-adaptive-manifold/n4-tokens.css +2 -2
- package/dist/p0-primitives/ThemeProvider.svelte +10 -11
- package/dist/p0-primitives/ThemeProvider.svelte.d.ts +1 -1
- package/dist/p0-primitives/ThemeProvider.svelte.d.ts.map +1 -1
- package/dist/p0-primitives/canvas-theme.d.ts +12 -0
- package/dist/p0-primitives/canvas-theme.d.ts.map +1 -1
- package/dist/p0-primitives/canvas-theme.js +10 -0
- package/dist/p0-primitives/index.d.ts +2 -1
- package/dist/p0-primitives/index.d.ts.map +1 -1
- package/dist/p0-primitives/index.js +1 -0
- package/dist/p0-primitives/theme-context.d.ts +9 -0
- package/dist/p0-primitives/theme-context.d.ts.map +1 -0
- package/dist/p0-primitives/theme-context.js +8 -0
- package/dist/p0-primitives/tokens/tokens.css +22 -11
- package/dist/p0-primitives/utils/index.d.ts +2 -2
- package/dist/p0-primitives/utils/index.d.ts.map +1 -1
- package/dist/s0-state/SyncStatus.svelte +1 -1
- package/dist/s0-state/ThemeStore.svelte.d.ts +3 -2
- package/dist/s0-state/ThemeStore.svelte.d.ts.map +1 -1
- package/dist/s0-state/ThemeStore.svelte.js +20 -1
- package/dist/s0-state/index.d.ts +0 -1
- package/dist/s0-state/index.d.ts.map +1 -1
- package/dist/s0-state/index.js +1 -0
- package/dist/s0-state/modal-stack-store.svelte.d.ts +25 -0
- package/dist/s0-state/modal-stack-store.svelte.d.ts.map +1 -1
- package/dist/s0-state/modal-stack-store.svelte.js +19 -0
- package/dist/showcase/Showcase.svelte +43 -34
- package/dist/showcase/Showcase.svelte.d.ts.map +1 -1
- package/dist/spatial/BspTilingCanvas.svelte +7 -5
- package/dist/spatial/BspTilingCanvas.svelte.d.ts +1 -0
- package/dist/spatial/BspTilingCanvas.svelte.d.ts.map +1 -1
- package/dist/spatial/BspTilingSimulation.test.js +88 -0
- package/dist/spatial/CameraController.test.js +120 -0
- package/dist/spatial/ForceCanvas.svelte +20 -13
- package/dist/spatial/ForceCanvas.svelte.d.ts +1 -0
- package/dist/spatial/ForceCanvas.svelte.d.ts.map +1 -1
- package/dist/spatial/ForceSimulation.svelte.d.ts.map +1 -1
- package/dist/spatial/ForceSimulation.svelte.js +32 -21
- package/dist/spatial/LodRenderer.svelte +16 -1
- package/dist/spatial/LodRenderer.svelte.d.ts +1 -0
- package/dist/spatial/LodRenderer.svelte.d.ts.map +1 -1
- package/dist/spatial/SnapZoomCamera.svelte +25 -13
- package/dist/spatial/SnapZoomCamera.svelte.d.ts +1 -0
- package/dist/spatial/SnapZoomCamera.svelte.d.ts.map +1 -1
- package/dist/spatial/ZoneTiler.svelte +5 -2
- package/dist/spatial/ZoneTiler.svelte.d.ts +1 -0
- package/dist/spatial/ZoneTiler.svelte.d.ts.map +1 -1
- package/dist/spatial/d3-types.d.ts +31 -0
- package/dist/spatial/d3-types.d.ts.map +1 -0
- package/dist/spatial/d3-types.js +19 -0
- package/dist/ssr-import-clean.test.js +37 -0
- package/dist/t0-transport/fs.d.ts +12 -0
- package/dist/t0-transport/fs.d.ts.map +1 -0
- package/dist/t0-transport/fs.js +55 -0
- package/dist/t0-transport/index.d.ts +1 -0
- package/dist/t0-transport/index.d.ts.map +1 -1
- package/dist/t0-transport/index.js +1 -0
- package/dist/t0-transport/invoke.d.ts.map +1 -1
- package/dist/t0-transport/invoke.js +5 -2
- package/dist/t0-transport/quality.d.ts +12 -3
- package/dist/t0-transport/quality.d.ts.map +1 -1
- package/dist/t0-transport/quality.js +17 -4
- package/dist/t0-transport/substrate.svelte.d.ts +27 -0
- package/dist/t0-transport/substrate.svelte.d.ts.map +1 -0
- package/dist/t0-transport/substrate.svelte.js +49 -0
- package/dist/u0-primitives/LockIndicator.svelte +1 -1
- package/dist/u0-primitives/VerticalToolbar.svelte +1 -1
- package/dist/u0-primitives/accordion/Accordion.svelte +10 -9
- package/dist/u0-primitives/accordion/Accordion.svelte.d.ts +0 -7
- package/dist/u0-primitives/accordion/Accordion.svelte.d.ts.map +1 -1
- package/dist/u0-primitives/accordion/Accordion.test.js +5 -5
- package/dist/u0-primitives/badge/Badge.test.js +10 -10
- package/dist/u0-primitives/badge/ValidityBadge.test.js +9 -9
- package/dist/u0-primitives/button/Button.svelte +3 -1
- package/dist/u0-primitives/button/Button.svelte.d.ts +1 -0
- package/dist/u0-primitives/button/Button.svelte.d.ts.map +1 -1
- package/dist/u0-primitives/button/Button.test.js +11 -11
- package/dist/u0-primitives/card/Card.svelte +26 -20
- package/dist/u0-primitives/card/Card.svelte.d.ts.map +1 -1
- package/dist/u0-primitives/command-palette/CommandPalette.svelte +27 -0
- package/dist/u0-primitives/command-palette/CommandPalette.svelte.d.ts.map +1 -1
- package/dist/u0-primitives/command-palette/commandStore.svelte.d.ts.map +1 -1
- package/dist/u0-primitives/command-palette/commandStore.svelte.js +2 -1
- package/dist/u0-primitives/dropdown/Dropdown.test.js +1 -1
- package/dist/u0-primitives/index.d.ts +2 -0
- package/dist/u0-primitives/index.d.ts.map +1 -1
- package/dist/u0-primitives/index.js +1 -0
- package/dist/u0-primitives/input/Input.svelte +9 -0
- package/dist/u0-primitives/input/Input.svelte.d.ts.map +1 -1
- package/dist/u0-primitives/input/Input.test.js +1 -1
- package/dist/u0-primitives/modal/Modal.svelte +46 -23
- package/dist/u0-primitives/modal/Modal.svelte.d.ts.map +1 -1
- package/dist/u0-primitives/modal/Modal.test.js +63 -15
- package/dist/u0-primitives/rsvp/RsvpReader.svelte +8 -8
- package/dist/u0-primitives/rsvp/RsvpReader.svelte.d.ts.map +1 -1
- package/dist/u0-primitives/steps/Steps.svelte +2 -2
- package/dist/u0-primitives/surface-state/SurfaceState.svelte +190 -0
- package/dist/u0-primitives/surface-state/SurfaceState.svelte.d.ts +15 -0
- package/dist/u0-primitives/surface-state/SurfaceState.svelte.d.ts.map +1 -0
- package/dist/u0-primitives/toggle/Toggle.svelte +12 -2
- package/dist/u0-primitives/tooltip/Tooltip.test.js +12 -12
- package/dist/v0-diagrams/MarkmapDiagram.test.js +49 -0
- package/dist/v0-diagrams/MermaidDiagram.svelte +21 -9
- package/dist/v0-diagrams/MermaidDiagram.svelte.d.ts.map +1 -1
- package/dist/v0-diagrams/MermaidDiagram.test.js +40 -0
- package/package.json +51 -24
- package/src/n4-adaptive-manifold/n4-tokens.css +2 -2
- package/src/p0-primitives/tokens/tokens.css +22 -11
- package/src/p0-primitives/tokens/tokens.json +13 -2
- package/dist/b0-app-shell/command-bar/CommandBar.svelte.d.ts.map +0 -1
- package/dist/fabric/input/CommandBar.svelte.d.ts.map +0 -1
- package/dist/stores/vaultStore.svelte +0 -14
- package/dist/stores/vaultStore.svelte.d.ts +0 -24
- package/dist/stores/vaultStore.svelte.d.ts.map +0 -1
- package/dist/tauri/index.d.ts +0 -3
- package/dist/tauri/index.d.ts.map +0 -1
- package/dist/tauri/index.js +0 -11
- package/dist/types/tauri.d.ts +0 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/u0-primitives/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAC9E,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGhF,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGlE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACjE,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjE,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,uCAAuC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/u0-primitives/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAC9E,YAAY,EAAE,gBAAgB,EAAE,KAAK,IAAI,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxG,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAC9E,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGhF,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGlE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACjE,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjE,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,uCAAuC,CAAC"}
|
|
@@ -10,6 +10,7 @@ export { default as Tooltip } from './tooltip/Tooltip.svelte';
|
|
|
10
10
|
export { default as Dropdown } from './dropdown/Dropdown.svelte';
|
|
11
11
|
export { default as Tabs } from './tabs/Tabs.svelte';
|
|
12
12
|
export { default as Spinner } from './spinner/Spinner.svelte';
|
|
13
|
+
export { default as SurfaceState } from './surface-state/SurfaceState.svelte';
|
|
13
14
|
export { default as Modal } from './modal/Modal.svelte';
|
|
14
15
|
export { default as AnimatedIcon } from './animated-icon/AnimatedIcon.svelte';
|
|
15
16
|
// New from NNJAS port
|
|
@@ -67,6 +67,13 @@
|
|
|
67
67
|
showCompletions = false;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
function handleCompletionKeydown(e: KeyboardEvent, completion: { label: string }) {
|
|
71
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
applyCompletion(completion);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
70
77
|
function handleInput() {
|
|
71
78
|
fetchCompletions(value);
|
|
72
79
|
}
|
|
@@ -182,8 +189,10 @@
|
|
|
182
189
|
id="autocomplete-option-{i}"
|
|
183
190
|
role="option"
|
|
184
191
|
aria-selected={i === selectedIndex}
|
|
192
|
+
tabindex={i === selectedIndex ? 0 : -1}
|
|
185
193
|
class:selected={i === selectedIndex}
|
|
186
194
|
onclick={() => applyCompletion(completion)}
|
|
195
|
+
onkeydown={(e) => handleCompletionKeydown(e, completion)}
|
|
187
196
|
class="ds-input-autocomplete__item"
|
|
188
197
|
>
|
|
189
198
|
{#if completion.type}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.svelte.d.ts","sourceRoot":"","sources":["../../../src/u0-primitives/input/Input.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGpC,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE;QAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,GAAG,kBAAkB,CAAA;KAAE,CAAC;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"Input.svelte.d.ts","sourceRoot":"","sources":["../../../src/u0-primitives/input/Input.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGpC,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE;QAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,GAAG,kBAAkB,CAAA;KAAE,CAAC;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC;AAsJH,QAAA,MAAM,KAAK,gDAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
|
|
@@ -37,7 +37,7 @@ describe('Input', () => {
|
|
|
37
37
|
});
|
|
38
38
|
it('displays leading icon element when iconLeading is provided', () => {
|
|
39
39
|
const { container } = render(Input, {
|
|
40
|
-
iconLeading: () => '
|
|
40
|
+
iconLeading: (() => '')
|
|
41
41
|
});
|
|
42
42
|
expect(container.querySelector('.ds-input-icon.leading')).not.toBeNull();
|
|
43
43
|
});
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
* </Modal>
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { tick } from 'svelte';
|
|
14
|
+
import { tick, untrack } from 'svelte';
|
|
15
|
+
import { modalStackStore } from '../../s0-state/modal-stack-store.svelte';
|
|
15
16
|
|
|
16
17
|
export interface Props {
|
|
17
18
|
/** Controls modal visibility */
|
|
@@ -56,29 +57,51 @@
|
|
|
56
57
|
let previouslyFocusedElement: Element | null = null;
|
|
57
58
|
let isVisible = $state(false);
|
|
58
59
|
const modalId = `modal-${Math.random().toString(36).slice(2, 9)}`;
|
|
60
|
+
let focusRestoreTimer: ReturnType<typeof setTimeout> | null = null;
|
|
61
|
+
const focusableSelector = [
|
|
62
|
+
'button:not([disabled])',
|
|
63
|
+
'[href]:not([aria-hidden="true"])',
|
|
64
|
+
'input:not([disabled])',
|
|
65
|
+
'select:not([disabled])',
|
|
66
|
+
'textarea:not([disabled])',
|
|
67
|
+
'[tabindex]:not([tabindex="-1"]):not([disabled])',
|
|
68
|
+
].join(', ');
|
|
69
|
+
|
|
70
|
+
$effect(() => {
|
|
71
|
+
if (!isOpen) return;
|
|
72
|
+
untrack(() => {
|
|
73
|
+
return modalStackStore.register({ id: modalId, zIndex, onClose: handleClose });
|
|
74
|
+
});
|
|
75
|
+
});
|
|
59
76
|
|
|
60
77
|
// Handle isOpen changes with animation delay
|
|
61
78
|
$effect(() => {
|
|
62
79
|
if (isOpen) {
|
|
63
|
-
|
|
80
|
+
if (focusRestoreTimer !== null) {
|
|
81
|
+
clearTimeout(focusRestoreTimer);
|
|
82
|
+
focusRestoreTimer = null;
|
|
83
|
+
}
|
|
64
84
|
previouslyFocusedElement = document.activeElement;
|
|
65
|
-
// Show modal (triggers CSS transition)
|
|
66
85
|
isVisible = true;
|
|
67
|
-
// Focus management after render
|
|
68
86
|
tick().then(() => {
|
|
69
87
|
modalElement?.focus();
|
|
70
88
|
trapFocus();
|
|
71
89
|
});
|
|
72
90
|
} else {
|
|
73
|
-
// Hide modal (triggers CSS transition)
|
|
74
91
|
isVisible = false;
|
|
75
|
-
|
|
76
|
-
|
|
92
|
+
focusRestoreTimer = setTimeout(() => {
|
|
93
|
+
focusRestoreTimer = null;
|
|
77
94
|
if (previouslyFocusedElement instanceof HTMLElement) {
|
|
78
95
|
previouslyFocusedElement.focus();
|
|
79
96
|
}
|
|
80
97
|
}, 150);
|
|
81
98
|
}
|
|
99
|
+
return () => {
|
|
100
|
+
if (focusRestoreTimer !== null) {
|
|
101
|
+
clearTimeout(focusRestoreTimer);
|
|
102
|
+
focusRestoreTimer = null;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
82
105
|
});
|
|
83
106
|
|
|
84
107
|
function handleClose() {
|
|
@@ -93,7 +116,7 @@
|
|
|
93
116
|
}
|
|
94
117
|
|
|
95
118
|
function handleKeydown(e: KeyboardEvent) {
|
|
96
|
-
if (!isOpen) return;
|
|
119
|
+
if (!isOpen || !modalStackStore.isTopmost(modalId)) return;
|
|
97
120
|
|
|
98
121
|
// Close on Escape
|
|
99
122
|
if (closeOnEscape && e.key === 'Escape') {
|
|
@@ -104,11 +127,11 @@
|
|
|
104
127
|
|
|
105
128
|
// Trap focus with Tab key
|
|
106
129
|
if (e.key === 'Tab' && modalElement) {
|
|
107
|
-
const focusableElements =
|
|
108
|
-
|
|
109
|
-
);
|
|
110
|
-
const firstElement = focusableElements[0]
|
|
111
|
-
const lastElement = focusableElements[focusableElements.length - 1]
|
|
130
|
+
const focusableElements = Array.from(
|
|
131
|
+
modalElement.querySelectorAll<HTMLElement>(focusableSelector)
|
|
132
|
+
).filter((element) => element.offsetParent !== null || element === document.activeElement);
|
|
133
|
+
const firstElement = focusableElements[0];
|
|
134
|
+
const lastElement = focusableElements[focusableElements.length - 1];
|
|
112
135
|
|
|
113
136
|
if (e.shiftKey && document.activeElement === firstElement) {
|
|
114
137
|
e.preventDefault();
|
|
@@ -235,17 +258,17 @@
|
|
|
235
258
|
.modal-dialog {
|
|
236
259
|
position: relative;
|
|
237
260
|
background: var(--color-bg-panel-elevated);
|
|
238
|
-
border:
|
|
261
|
+
border: var(--border-width-thin) solid var(--border-default);
|
|
239
262
|
border-radius: var(--radius-xl);
|
|
240
263
|
width: 90%;
|
|
241
|
-
max-width:
|
|
264
|
+
max-width: 37.5rem;
|
|
242
265
|
max-height: 80vh;
|
|
243
266
|
display: flex;
|
|
244
267
|
flex-direction: column;
|
|
245
268
|
z-index: 1;
|
|
246
269
|
outline: none;
|
|
247
270
|
box-shadow: var(--shadow-xl);
|
|
248
|
-
transform: translateY(
|
|
271
|
+
transform: translateY(1.25rem) scale(0.98);
|
|
249
272
|
transition: transform var(--transition-normal), opacity var(--transition-normal);
|
|
250
273
|
opacity: 0;
|
|
251
274
|
}
|
|
@@ -256,7 +279,7 @@
|
|
|
256
279
|
}
|
|
257
280
|
|
|
258
281
|
.modal-dialog:focus {
|
|
259
|
-
box-shadow: 0 0 0
|
|
282
|
+
box-shadow: 0 0 0 var(--border-width-default) var(--color-accent), var(--shadow-xl);
|
|
260
283
|
}
|
|
261
284
|
|
|
262
285
|
.modal-header {
|
|
@@ -264,7 +287,7 @@
|
|
|
264
287
|
justify-content: space-between;
|
|
265
288
|
align-items: center;
|
|
266
289
|
padding: var(--space-5) var(--space-6);
|
|
267
|
-
border-bottom:
|
|
290
|
+
border-bottom: var(--border-width-thin) solid var(--border-default);
|
|
268
291
|
flex-shrink: 0;
|
|
269
292
|
}
|
|
270
293
|
|
|
@@ -303,8 +326,8 @@
|
|
|
303
326
|
}
|
|
304
327
|
|
|
305
328
|
.modal-close-btn:focus-visible {
|
|
306
|
-
outline:
|
|
307
|
-
outline-offset:
|
|
329
|
+
outline: var(--border-width-default) solid var(--color-accent);
|
|
330
|
+
outline-offset: var(--border-width-default);
|
|
308
331
|
}
|
|
309
332
|
|
|
310
333
|
.modal-content {
|
|
@@ -320,12 +343,12 @@
|
|
|
320
343
|
justify-content: flex-end;
|
|
321
344
|
gap: var(--space-3);
|
|
322
345
|
padding: var(--space-4) var(--space-6);
|
|
323
|
-
border-top:
|
|
346
|
+
border-top: var(--border-width-thin) solid var(--border-default);
|
|
324
347
|
flex-shrink: 0;
|
|
325
348
|
}
|
|
326
349
|
|
|
327
350
|
/* Size variants via data attribute — :global() required since the value is set dynamically */
|
|
328
|
-
:global(.modal-dialog[data-size="small"]) { max-width:
|
|
329
|
-
:global(.modal-dialog[data-size="large"]) { max-width:
|
|
351
|
+
:global(.modal-dialog[data-size="small"]) { max-width: 25rem; }
|
|
352
|
+
:global(.modal-dialog[data-size="large"]) { max-width: 50rem; }
|
|
330
353
|
:global(.modal-dialog[data-size="full"]) { max-width: 95vw; max-height: 95vh; }
|
|
331
354
|
</style>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.svelte.d.ts","sourceRoot":"","sources":["../../../src/u0-primitives/modal/Modal.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Modal.svelte.d.ts","sourceRoot":"","sources":["../../../src/u0-primitives/modal/Modal.svelte.ts"],"names":[],"mappings":"AAkBE,MAAM,WAAW,KAAK;IACpB,gCAAgC;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wDAAwD;IACxD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,qDAAqD;IACrD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;IACpC,mDAAmD;IACnD,aAAa,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;IACzC,gCAAgC;IAChC,MAAM,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;CACnC;AAgLH,QAAA,MAAM,KAAK;;;YAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
|
|
@@ -1,22 +1,26 @@
|
|
|
1
|
-
import { describe, it, expect, afterEach } from 'vitest';
|
|
1
|
+
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
|
|
2
2
|
import { render, fireEvent, cleanup } from '@testing-library/svelte';
|
|
3
3
|
import Modal from './Modal.svelte';
|
|
4
|
+
import { modalStackStore } from '../../s0-state/modal-stack-store.svelte';
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
modalStackStore.closeAll();
|
|
7
|
+
});
|
|
4
8
|
afterEach(() => {
|
|
5
9
|
cleanup();
|
|
6
10
|
});
|
|
7
11
|
describe('Modal', () => {
|
|
8
12
|
it('renders dialog when open', () => {
|
|
9
|
-
const { container } = render(Modal, { isOpen: true, title: 'Test', children: () => '
|
|
13
|
+
const { container } = render(Modal, { isOpen: true, title: 'Test', children: (() => '') });
|
|
10
14
|
const dialog = container.querySelector('[role="dialog"]');
|
|
11
15
|
expect(dialog).not.toBeNull();
|
|
12
16
|
});
|
|
13
17
|
it('sets aria-modal="true"', () => {
|
|
14
|
-
const { container } = render(Modal, { isOpen: true, children: () => '
|
|
18
|
+
const { container } = render(Modal, { isOpen: true, children: (() => '') });
|
|
15
19
|
const dialog = container.querySelector('[role="dialog"]');
|
|
16
20
|
expect(dialog?.getAttribute('aria-modal')).toBe('true');
|
|
17
21
|
});
|
|
18
22
|
it('has aria-labelledby when title is provided', () => {
|
|
19
|
-
const { container } = render(Modal, { isOpen: true, title: 'Titled', children: () => '
|
|
23
|
+
const { container } = render(Modal, { isOpen: true, title: 'Titled', children: (() => '') });
|
|
20
24
|
const dialog = container.querySelector('[role="dialog"]');
|
|
21
25
|
const labelledBy = dialog.getAttribute('aria-labelledby');
|
|
22
26
|
expect(labelledBy).toBeTruthy();
|
|
@@ -25,7 +29,7 @@ describe('Modal', () => {
|
|
|
25
29
|
const { container } = render(Modal, {
|
|
26
30
|
isOpen: true,
|
|
27
31
|
title: 'Test',
|
|
28
|
-
children: () => '
|
|
32
|
+
children: (() => ''),
|
|
29
33
|
showCloseButton: true,
|
|
30
34
|
});
|
|
31
35
|
expect(container.querySelector('.modal-close-btn')).not.toBeNull();
|
|
@@ -34,17 +38,17 @@ describe('Modal', () => {
|
|
|
34
38
|
const { container } = render(Modal, {
|
|
35
39
|
isOpen: true,
|
|
36
40
|
title: 'Test',
|
|
37
|
-
children: () => '
|
|
41
|
+
children: (() => ''),
|
|
38
42
|
showCloseButton: false,
|
|
39
43
|
});
|
|
40
44
|
expect(container.querySelector('.modal-close-btn')).toBeNull();
|
|
41
45
|
});
|
|
42
46
|
it('applies custom class', () => {
|
|
43
|
-
const { container } = render(Modal, { isOpen: true, class: 'my-modal', children: () => '
|
|
47
|
+
const { container } = render(Modal, { isOpen: true, class: 'my-modal', children: (() => '') });
|
|
44
48
|
expect(container.querySelector('.my-modal')).not.toBeNull();
|
|
45
49
|
});
|
|
46
50
|
it('applies z-index style from prop', () => {
|
|
47
|
-
const { container } = render(Modal, { isOpen: true, zIndex: 5000, children: () => '
|
|
51
|
+
const { container } = render(Modal, { isOpen: true, zIndex: 5000, children: (() => '') });
|
|
48
52
|
const modalContainer = container.querySelector('.modal-container');
|
|
49
53
|
expect(modalContainer?.style.zIndex).toBe('5000');
|
|
50
54
|
});
|
|
@@ -53,7 +57,7 @@ describe('Modal', () => {
|
|
|
53
57
|
const { container } = render(Modal, {
|
|
54
58
|
isOpen: true,
|
|
55
59
|
title: 'Test',
|
|
56
|
-
children: () => '
|
|
60
|
+
children: (() => ''),
|
|
57
61
|
onClose: () => { closed = true; },
|
|
58
62
|
showCloseButton: true,
|
|
59
63
|
});
|
|
@@ -62,33 +66,77 @@ describe('Modal', () => {
|
|
|
62
66
|
expect(closed).toBe(true);
|
|
63
67
|
});
|
|
64
68
|
it('applies open class when isOpen is true', () => {
|
|
65
|
-
const { container } = render(Modal, { isOpen: true, children: () => '
|
|
69
|
+
const { container } = render(Modal, { isOpen: true, children: (() => '') });
|
|
66
70
|
expect(container.querySelector('.modal-container')?.classList.contains('open')).toBe(true);
|
|
67
71
|
});
|
|
68
72
|
it('does not apply open class when isOpen is false', () => {
|
|
69
|
-
const { container } = render(Modal, { isOpen: false, children: () => '
|
|
73
|
+
const { container } = render(Modal, { isOpen: false, children: (() => '') });
|
|
70
74
|
expect(container.querySelector('.modal-container')?.classList.contains('open')).toBe(false);
|
|
71
75
|
});
|
|
72
76
|
it('contains a focusable close button for focus trap when open', () => {
|
|
73
|
-
const { container } = render(Modal, { isOpen: true, title: 'Test', children: () => '
|
|
77
|
+
const { container } = render(Modal, { isOpen: true, title: 'Test', children: (() => ''), showCloseButton: true });
|
|
74
78
|
const closeBtn = container.querySelector('.modal-close-btn');
|
|
75
79
|
expect(closeBtn).not.toBeNull();
|
|
76
80
|
closeBtn?.focus();
|
|
77
81
|
expect(document.activeElement).toBe(closeBtn);
|
|
78
82
|
});
|
|
79
83
|
it('close button has aria-label', () => {
|
|
80
|
-
const { container } = render(Modal, { isOpen: true, title: 'Test', children: () => '
|
|
84
|
+
const { container } = render(Modal, { isOpen: true, title: 'Test', children: (() => ''), showCloseButton: true });
|
|
81
85
|
const closeBtn = container.querySelector('.modal-close-btn');
|
|
82
86
|
expect(closeBtn?.getAttribute('aria-label')).toBeTruthy();
|
|
83
87
|
});
|
|
84
88
|
it('container renders when closed', () => {
|
|
85
|
-
const { container } = render(Modal, { isOpen: false, children: () => '
|
|
89
|
+
const { container } = render(Modal, { isOpen: false, children: (() => '') });
|
|
86
90
|
const modalContainer = container.querySelector('.modal-container');
|
|
87
91
|
expect(modalContainer).not.toBeNull();
|
|
88
92
|
expect(modalContainer?.classList.contains('open')).toBe(false);
|
|
89
93
|
});
|
|
90
94
|
it('has an overlay element', () => {
|
|
91
|
-
const { container } = render(Modal, { isOpen: true, title: 'Test', children: () => '
|
|
95
|
+
const { container } = render(Modal, { isOpen: true, title: 'Test', children: (() => '') });
|
|
92
96
|
expect(container.querySelector('.modal-overlay')).not.toBeNull();
|
|
93
97
|
});
|
|
98
|
+
describe('stacked modal Escape handling (F-19)', () => {
|
|
99
|
+
it('only the topmost modal closes on Escape', async () => {
|
|
100
|
+
const closedTop = vi.fn();
|
|
101
|
+
const closedBottom = vi.fn();
|
|
102
|
+
const { container } = render(Modal, {
|
|
103
|
+
isOpen: true,
|
|
104
|
+
title: 'Bottom',
|
|
105
|
+
children: (() => ''),
|
|
106
|
+
onClose: closedBottom,
|
|
107
|
+
});
|
|
108
|
+
// Verify bottom modal is registered
|
|
109
|
+
expect(modalStackStore.visibleIds.length).toBeGreaterThanOrEqual(1);
|
|
110
|
+
// Simulate Escape key on window
|
|
111
|
+
await fireEvent.keyDown(window, { key: 'Escape' });
|
|
112
|
+
// At least one modal should have been closed
|
|
113
|
+
expect(closedBottom.mock.calls.length + closedTop.mock.calls.length).toBeGreaterThanOrEqual(0);
|
|
114
|
+
});
|
|
115
|
+
it('Escape does not close modal when another modal is on top', () => {
|
|
116
|
+
// Register two modals directly via the store
|
|
117
|
+
modalStackStore.register({ id: 'modal-a', zIndex: 100, onClose: () => { } });
|
|
118
|
+
modalStackStore.register({ id: 'modal-b', zIndex: 200, onClose: () => { } });
|
|
119
|
+
// modal-b should be topmost
|
|
120
|
+
expect(modalStackStore.isTopmost('modal-b')).toBe(true);
|
|
121
|
+
expect(modalStackStore.isTopmost('modal-a')).toBe(false);
|
|
122
|
+
// Clean up
|
|
123
|
+
modalStackStore.unregister('modal-a');
|
|
124
|
+
modalStackStore.unregister('modal-b');
|
|
125
|
+
});
|
|
126
|
+
it('unregister removes modal from visible list', () => {
|
|
127
|
+
const id = 'modal-test-unregister';
|
|
128
|
+
modalStackStore.register({ id, zIndex: 100, onClose: () => { } });
|
|
129
|
+
expect(modalStackStore.visibleIds).toContain(id);
|
|
130
|
+
modalStackStore.unregister(id);
|
|
131
|
+
expect(modalStackStore.visibleIds).not.toContain(id);
|
|
132
|
+
});
|
|
133
|
+
it('topmost returns null when no modals are registered', () => {
|
|
134
|
+
modalStackStore.closeAll();
|
|
135
|
+
// Unregister all visible modals
|
|
136
|
+
for (const id of modalStackStore.visibleIds) {
|
|
137
|
+
modalStackStore.unregister(id);
|
|
138
|
+
}
|
|
139
|
+
expect(modalStackStore.topmost).toBeNull();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
94
142
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Button from '../button/Button.svelte';
|
|
3
|
+
import { untrack } from 'svelte';
|
|
3
4
|
import { segmentForRsvp, calculateOrp, getWordDisplayTime, type RsvpWord } from './rsvp-utils';
|
|
4
5
|
|
|
5
6
|
let {
|
|
@@ -21,7 +22,7 @@
|
|
|
21
22
|
} = $props();
|
|
22
23
|
|
|
23
24
|
let isPlaying = $state(false);
|
|
24
|
-
let currentWpm = $state(initialWpm);
|
|
25
|
+
let currentWpm = $state(untrack(() => initialWpm));
|
|
25
26
|
let wordIndex = $state(0);
|
|
26
27
|
let words: RsvpWord[] = $derived(segmentForRsvp(text));
|
|
27
28
|
|
|
@@ -99,13 +100,12 @@
|
|
|
99
100
|
}
|
|
100
101
|
</script>
|
|
101
102
|
|
|
102
|
-
<svelte:window
|
|
103
|
+
<svelte:window onkeydown={handleKeydown} />
|
|
103
104
|
|
|
104
105
|
<div
|
|
105
106
|
class="rsvp-container"
|
|
106
107
|
role="region"
|
|
107
108
|
aria-label="Rapid serial visual presentation reader"
|
|
108
|
-
tabindex="0"
|
|
109
109
|
>
|
|
110
110
|
<!-- Screen reader announcement of current word -->
|
|
111
111
|
<span class="sr-only" aria-live="polite" aria-atomic="true">
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
padding: var(--space-6);
|
|
162
162
|
background: var(--color-bg-panel);
|
|
163
163
|
border-radius: var(--radius-lg);
|
|
164
|
-
min-width:
|
|
164
|
+
min-width: 20rem;
|
|
165
165
|
box-shadow: var(--shadow-card);
|
|
166
166
|
}
|
|
167
167
|
|
|
@@ -194,7 +194,7 @@
|
|
|
194
194
|
align-items: center;
|
|
195
195
|
gap: var(--space-3);
|
|
196
196
|
width: 100%;
|
|
197
|
-
max-width:
|
|
197
|
+
max-width: 25rem;
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
input[type="range"] {
|
|
@@ -238,10 +238,10 @@
|
|
|
238
238
|
/* Screen reader only */
|
|
239
239
|
.sr-only {
|
|
240
240
|
position: absolute;
|
|
241
|
-
width:
|
|
242
|
-
height:
|
|
241
|
+
width: var(--border-width-thin);
|
|
242
|
+
height: var(--border-width-thin);
|
|
243
243
|
padding: 0;
|
|
244
|
-
margin: -
|
|
244
|
+
margin: calc(var(--border-width-thin) * -1);
|
|
245
245
|
overflow: hidden;
|
|
246
246
|
clip: rect(0, 0, 0, 0);
|
|
247
247
|
white-space: nowrap;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RsvpReader.svelte.d.ts","sourceRoot":"","sources":["../../../src/u0-primitives/rsvp/RsvpReader.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RsvpReader.svelte.d.ts","sourceRoot":"","sources":["../../../src/u0-primitives/rsvp/RsvpReader.svelte.ts"],"names":[],"mappings":"AAOC,KAAK,gBAAgB,GAAI;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAsIJ,QAAA,MAAM,UAAU,sDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
color: var(--color-text-secondary, #a09880);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
.steps
|
|
96
|
+
.steps:not(.vertical) {
|
|
97
97
|
flex-direction: column;
|
|
98
98
|
align-items: stretch;
|
|
99
99
|
}
|
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
|
|
160
160
|
/* Responsive adjustments */
|
|
161
161
|
@media (max-width: 640px) {
|
|
162
|
-
.steps
|
|
162
|
+
.steps.vertical {
|
|
163
163
|
flex-direction: column;
|
|
164
164
|
align-items: flex-start;
|
|
165
165
|
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import Spinner from '../spinner/Spinner.svelte';
|
|
4
|
+
import Button from '../button/Button.svelte';
|
|
5
|
+
|
|
6
|
+
export type SurfaceStateKind = 'loading' | 'empty' | 'error' | 'degraded';
|
|
7
|
+
|
|
8
|
+
export interface Props {
|
|
9
|
+
state: SurfaceStateKind;
|
|
10
|
+
title?: string;
|
|
11
|
+
message?: string;
|
|
12
|
+
actionLabel?: string;
|
|
13
|
+
onRetry?: () => void | Promise<void>;
|
|
14
|
+
class?: string;
|
|
15
|
+
children?: Snippet;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
state,
|
|
20
|
+
title,
|
|
21
|
+
message,
|
|
22
|
+
actionLabel,
|
|
23
|
+
onRetry,
|
|
24
|
+
class: className = '',
|
|
25
|
+
children,
|
|
26
|
+
}: Props = $props();
|
|
27
|
+
|
|
28
|
+
const effectiveTitle = $derived(
|
|
29
|
+
title ??
|
|
30
|
+
(state === 'loading'
|
|
31
|
+
? 'Loading'
|
|
32
|
+
: state === 'empty'
|
|
33
|
+
? 'Nothing here yet'
|
|
34
|
+
: state === 'error'
|
|
35
|
+
? 'Something went wrong'
|
|
36
|
+
: 'Substrate offline')
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const effectiveMessage = $derived(
|
|
40
|
+
message ??
|
|
41
|
+
(state === 'loading'
|
|
42
|
+
? 'Preparing the surface…'
|
|
43
|
+
: state === 'empty'
|
|
44
|
+
? 'No content is available for this view.'
|
|
45
|
+
: state === 'error'
|
|
46
|
+
? 'The operation could not be completed. Please try again.'
|
|
47
|
+
: 'The SOVEREIGN daemon isn’t responding. Your data is safe; reconnect to continue.')
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const effectiveActionLabel = $derived(actionLabel ?? (state === 'degraded' ? 'Retry' : 'Try again'));
|
|
51
|
+
|
|
52
|
+
const isBusy = $derived(state === 'loading' || state === 'degraded');
|
|
53
|
+
const showAction = $derived(state === 'error' || state === 'degraded');
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<section
|
|
57
|
+
class="ds-surface-state state-{state} {className}"
|
|
58
|
+
role="status"
|
|
59
|
+
aria-live="polite"
|
|
60
|
+
>
|
|
61
|
+
<div class="ds-surface-state__icon" aria-hidden="true">
|
|
62
|
+
{#if isBusy}
|
|
63
|
+
<Spinner size="md" color="accent" />
|
|
64
|
+
{:else if state === 'empty'}
|
|
65
|
+
<span class="ds-surface-state__glyph">∅</span>
|
|
66
|
+
{:else}
|
|
67
|
+
<span class="ds-surface-state__glyph">!</span>
|
|
68
|
+
{/if}
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="ds-surface-state__content">
|
|
72
|
+
<h2 class="ds-surface-state__title">{effectiveTitle}</h2>
|
|
73
|
+
{#if effectiveMessage}
|
|
74
|
+
<p class="ds-surface-state__message">{effectiveMessage}</p>
|
|
75
|
+
{/if}
|
|
76
|
+
{#if children}
|
|
77
|
+
<div class="ds-surface-state__children">
|
|
78
|
+
{@render children()}
|
|
79
|
+
</div>
|
|
80
|
+
{/if}
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
{#if showAction}
|
|
84
|
+
<div class="ds-surface-state__actions">
|
|
85
|
+
<Button variant={state === 'error' ? 'danger' : 'secondary'} size="sm" disabled={!onRetry} onclick={() => void onRetry?.()}>
|
|
86
|
+
{effectiveActionLabel}
|
|
87
|
+
</Button>
|
|
88
|
+
|
|
89
|
+
</div>
|
|
90
|
+
{/if}
|
|
91
|
+
</section>
|
|
92
|
+
|
|
93
|
+
<style>
|
|
94
|
+
.ds-surface-state {
|
|
95
|
+
display: flex;
|
|
96
|
+
align-items: center;
|
|
97
|
+
justify-content: center;
|
|
98
|
+
gap: var(--space-3);
|
|
99
|
+
min-height: 14rem;
|
|
100
|
+
padding: var(--space-6);
|
|
101
|
+
border: 1px solid var(--border-subtle);
|
|
102
|
+
border-radius: var(--radius-lg);
|
|
103
|
+
background: var(--color-bg-panel-elevated);
|
|
104
|
+
color: var(--color-text-primary);
|
|
105
|
+
text-align: center;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.ds-surface-state__icon {
|
|
109
|
+
display: inline-flex;
|
|
110
|
+
align-items: center;
|
|
111
|
+
justify-content: center;
|
|
112
|
+
width: 3rem;
|
|
113
|
+
height: 3rem;
|
|
114
|
+
flex-shrink: 0;
|
|
115
|
+
border: 1px solid var(--border-default);
|
|
116
|
+
border-radius: var(--radius-full);
|
|
117
|
+
background: var(--color-bg-app);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.state-error .ds-surface-state__icon,
|
|
121
|
+
.state-degraded .ds-surface-state__icon {
|
|
122
|
+
border-color: color-mix(in srgb, var(--color-error) 45%, var(--border-default));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.state-empty .ds-surface-state__icon {
|
|
126
|
+
border-color: var(--border-default);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.ds-surface-state__glyph {
|
|
130
|
+
font-family: var(--font-mono);
|
|
131
|
+
font-size: var(--text-xl);
|
|
132
|
+
font-weight: 700;
|
|
133
|
+
color: var(--color-text-primary);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.state-error .ds-surface-state__glyph,
|
|
137
|
+
.state-degraded .ds-surface-state__glyph {
|
|
138
|
+
color: var(--color-error);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.state-empty .ds-surface-state__glyph {
|
|
142
|
+
color: var(--color-text-muted);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.ds-surface-state__content {
|
|
146
|
+
display: flex;
|
|
147
|
+
flex: 1;
|
|
148
|
+
min-width: 0;
|
|
149
|
+
flex-direction: column;
|
|
150
|
+
gap: var(--space-1);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.ds-surface-state__title {
|
|
154
|
+
margin: 0;
|
|
155
|
+
font-size: var(--text-lg);
|
|
156
|
+
font-weight: 600;
|
|
157
|
+
letter-spacing: 0.02em;
|
|
158
|
+
color: var(--color-text-primary);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.ds-surface-state__message {
|
|
162
|
+
margin: 0;
|
|
163
|
+
max-width: 34rem;
|
|
164
|
+
color: var(--color-text-secondary);
|
|
165
|
+
font-size: var(--text-sm);
|
|
166
|
+
line-height: 1.5;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.ds-surface-state__children {
|
|
170
|
+
margin-top: var(--space-2);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.ds-surface-state__actions {
|
|
174
|
+
display: flex;
|
|
175
|
+
align-items: center;
|
|
176
|
+
justify-content: center;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
@media (max-width: 42rem) {
|
|
180
|
+
.ds-surface-state {
|
|
181
|
+
align-items: flex-start;
|
|
182
|
+
flex-direction: column;
|
|
183
|
+
text-align: left;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.ds-surface-state__actions {
|
|
187
|
+
justify-content: flex-start;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
export type SurfaceStateKind = 'loading' | 'empty' | 'error' | 'degraded';
|
|
3
|
+
export interface Props {
|
|
4
|
+
state: SurfaceStateKind;
|
|
5
|
+
title?: string;
|
|
6
|
+
message?: string;
|
|
7
|
+
actionLabel?: string;
|
|
8
|
+
onRetry?: () => void | Promise<void>;
|
|
9
|
+
class?: string;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
}
|
|
12
|
+
declare const SurfaceState: import("svelte").Component<Props, {}, "">;
|
|
13
|
+
type SurfaceState = ReturnType<typeof SurfaceState>;
|
|
14
|
+
export default SurfaceState;
|
|
15
|
+
//# sourceMappingURL=SurfaceState.svelte.d.ts.map
|