@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.
- 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/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/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 +5 -5
- package/dist/spatial/BspTilingSimulation.test.js +88 -0
- package/dist/spatial/CameraController.test.js +120 -0
- package/dist/spatial/ForceCanvas.svelte +18 -13
- 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 +14 -1
- package/dist/spatial/LodRenderer.svelte.d.ts.map +1 -1
- package/dist/spatial/SnapZoomCamera.svelte +23 -13
- package/dist/spatial/SnapZoomCamera.svelte.d.ts.map +1 -1
- package/dist/spatial/ZoneTiler.svelte +3 -2
- 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 +50 -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
|
@@ -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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SurfaceState.svelte.d.ts","sourceRoot":"","sources":["../../../src/u0-primitives/surface-state/SurfaceState.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAKpC,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;AAE1E,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAmFH,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
</div>
|
|
49
49
|
|
|
50
50
|
{#if label}
|
|
51
|
-
<
|
|
51
|
+
<button type="button" class="ds-toggle-label" onclick={toggle} disabled={disabled}>
|
|
52
52
|
{@render label()}
|
|
53
|
-
</
|
|
53
|
+
</button>
|
|
54
54
|
{/if}
|
|
55
55
|
</label>
|
|
56
56
|
|
|
@@ -105,11 +105,21 @@
|
|
|
105
105
|
|
|
106
106
|
/* Label */
|
|
107
107
|
.ds-toggle-label {
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
padding: 0;
|
|
111
|
+
border: 0;
|
|
112
|
+
background: transparent;
|
|
113
|
+
font: inherit;
|
|
108
114
|
font-family: var(--font-sans);
|
|
109
115
|
color: var(--color-text-primary);
|
|
110
116
|
cursor: pointer;
|
|
111
117
|
}
|
|
112
118
|
|
|
119
|
+
.ds-toggle-label:disabled {
|
|
120
|
+
cursor: not-allowed;
|
|
121
|
+
}
|
|
122
|
+
|
|
113
123
|
/* --- Sizes --- */
|
|
114
124
|
|
|
115
125
|
.size-sm .ds-toggle-track {
|