dialkit 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +171 -1
  2. package/dist/index.cjs +876 -337
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +41 -6
  5. package/dist/index.d.ts +41 -6
  6. package/dist/index.js +878 -341
  7. package/dist/index.js.map +1 -1
  8. package/dist/solid/index.cjs +1011 -544
  9. package/dist/solid/index.cjs.map +1 -1
  10. package/dist/solid/index.d.cts +33 -3
  11. package/dist/solid/index.d.ts +33 -3
  12. package/dist/solid/index.js +864 -398
  13. package/dist/solid/index.js.map +1 -1
  14. package/dist/store/index.cjs +52 -12
  15. package/dist/store/index.cjs.map +1 -1
  16. package/dist/store/index.d.cts +25 -3
  17. package/dist/store/index.d.ts +25 -3
  18. package/dist/store/index.js +52 -12
  19. package/dist/store/index.js.map +1 -1
  20. package/dist/styles.css +256 -25
  21. package/dist/svelte/components/ControlRenderer.svelte +12 -0
  22. package/dist/svelte/components/ControlRenderer.svelte.d.ts.map +1 -1
  23. package/dist/svelte/components/DialRoot.svelte +22 -8
  24. package/dist/svelte/components/DialRoot.svelte.d.ts +3 -0
  25. package/dist/svelte/components/DialRoot.svelte.d.ts.map +1 -1
  26. package/dist/svelte/components/Folder.svelte +17 -8
  27. package/dist/svelte/components/Folder.svelte.d.ts.map +1 -1
  28. package/dist/svelte/components/Panel.svelte +14 -9
  29. package/dist/svelte/components/Panel.svelte.d.ts.map +1 -1
  30. package/dist/svelte/components/PresetManager.svelte +7 -6
  31. package/dist/svelte/components/PresetManager.svelte.d.ts.map +1 -1
  32. package/dist/svelte/components/SegmentedControl.svelte +30 -74
  33. package/dist/svelte/components/SegmentedControl.svelte.d.ts.map +1 -1
  34. package/dist/svelte/components/SelectControl.svelte +2 -1
  35. package/dist/svelte/components/SelectControl.svelte.d.ts.map +1 -1
  36. package/dist/svelte/components/ShortcutListener.svelte +265 -0
  37. package/dist/svelte/components/ShortcutListener.svelte.d.ts +13 -0
  38. package/dist/svelte/components/ShortcutListener.svelte.d.ts.map +1 -0
  39. package/dist/svelte/components/ShortcutsMenu.svelte +128 -0
  40. package/dist/svelte/components/ShortcutsMenu.svelte.d.ts +7 -0
  41. package/dist/svelte/components/ShortcutsMenu.svelte.d.ts.map +1 -0
  42. package/dist/svelte/components/Slider.svelte +16 -29
  43. package/dist/svelte/components/Slider.svelte.d.ts +3 -0
  44. package/dist/svelte/components/Slider.svelte.d.ts.map +1 -1
  45. package/dist/svelte/components/SpringControl.svelte +17 -15
  46. package/dist/svelte/components/SpringControl.svelte.d.ts.map +1 -1
  47. package/dist/svelte/components/Toggle.svelte +13 -2
  48. package/dist/svelte/components/Toggle.svelte.d.ts +3 -0
  49. package/dist/svelte/components/Toggle.svelte.d.ts.map +1 -1
  50. package/dist/svelte/components/TransitionControl.svelte +28 -25
  51. package/dist/svelte/components/TransitionControl.svelte.d.ts.map +1 -1
  52. package/dist/svelte/createDialKit.svelte.d.ts +2 -1
  53. package/dist/svelte/createDialKit.svelte.d.ts.map +1 -1
  54. package/dist/svelte/createDialKit.svelte.js +1 -1
  55. package/dist/svelte/index.d.ts +6 -2
  56. package/dist/svelte/index.d.ts.map +1 -1
  57. package/dist/svelte/index.js +4 -0
  58. package/dist/svelte/theme-css.d.ts +1 -1
  59. package/dist/svelte/theme-css.d.ts.map +1 -1
  60. package/dist/svelte/theme-css.js +257 -26
  61. package/dist/vue/index.cjs +3056 -0
  62. package/dist/vue/index.cjs.map +1 -0
  63. package/dist/vue/index.d.cts +675 -0
  64. package/dist/vue/index.d.ts +675 -0
  65. package/dist/vue/index.js +3014 -0
  66. package/dist/vue/index.js.map +1 -0
  67. package/package.json +24 -4
@@ -0,0 +1,265 @@
1
+ <script lang="ts" module>
2
+ export const SHORTCUT_CTX = Symbol('dialkit-shortcut');
3
+
4
+ export interface ShortcutContextValue {
5
+ activePanelId: string | null;
6
+ activePath: string | null;
7
+ }
8
+ </script>
9
+
10
+ <script lang="ts">
11
+ import { setContext } from 'svelte';
12
+ import { DialStore } from 'dialkit/store';
13
+ import type { Snippet } from 'svelte';
14
+ import {
15
+ getEffectiveStep,
16
+ applySliderDelta,
17
+ findControl,
18
+ DRAG_SENSITIVITY,
19
+ isInputFocused,
20
+ getActiveModifier,
21
+ } from '../../shortcut-utils';
22
+
23
+ let { children } = $props<{ children?: Snippet }>();
24
+
25
+ let activePanelId = $state<string | null>(null);
26
+ let activePath = $state<string | null>(null);
27
+
28
+ const ctx: ShortcutContextValue = {
29
+ get activePanelId() { return activePanelId; },
30
+ get activePath() { return activePath; },
31
+ };
32
+
33
+ setContext(SHORTCUT_CTX, ctx);
34
+
35
+ // --- mutable refs ---
36
+
37
+ let activeKeys = new Set<string>();
38
+ let isDragging = false;
39
+ let lastMouseX: number | null = null;
40
+ let dragAccumulator = 0;
41
+
42
+ function resolveActiveTarget(interaction: string) {
43
+ for (const key of activeKeys) {
44
+ const panels = DialStore.getPanels();
45
+ for (const panel of panels) {
46
+ for (const [path, shortcut] of Object.entries(panel.shortcuts)) {
47
+ if (!shortcut.key) continue;
48
+ if (shortcut.key.toLowerCase() !== key) continue;
49
+ if ((shortcut.interaction ?? 'scroll') !== interaction) continue;
50
+ const control = DialStore.getPanel(panel.id)?.controls
51
+ ? findControl(panel.controls, path)
52
+ : null;
53
+ if (control && control.type === 'slider') {
54
+ return { panelId: panel.id, path, control, shortcut };
55
+ }
56
+ }
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+
62
+ // --- event handlers ---
63
+
64
+ function handleKeyDown(e: KeyboardEvent) {
65
+ if (isInputFocused()) return;
66
+
67
+ const key = e.key.toLowerCase();
68
+
69
+ // Arrow keys adjust the active shortcut's slider
70
+ if (key === 'arrowleft' || key === 'arrowright' || key === 'arrowup' || key === 'arrowdown') {
71
+ if (activeKeys.size > 0) {
72
+ const target = resolveActiveTarget('scroll') || resolveActiveTarget('drag') || resolveActiveTarget('move');
73
+ if (target && target.control.type === 'slider') {
74
+ e.preventDefault();
75
+ const direction = (key === 'arrowright' || key === 'arrowup') ? 1 : -1;
76
+ const effectiveStep = getEffectiveStep(target.control, target.shortcut);
77
+ applySliderDelta(target.panelId, target.path, target.control, effectiveStep, direction);
78
+ return;
79
+ }
80
+ }
81
+ }
82
+
83
+ const wasAlreadyHeld = activeKeys.has(key);
84
+ activeKeys.add(key);
85
+
86
+ const modifier = getActiveModifier(e);
87
+ const target = DialStore.resolveShortcutTarget(key, modifier);
88
+ if (target) {
89
+ activePanelId = target.panelId;
90
+ activePath = target.path;
91
+
92
+ // Toggle: flip on first keydown only (not on key repeat)
93
+ if (!wasAlreadyHeld && target.control.type === 'toggle') {
94
+ const currentValue = DialStore.getValue(target.panelId, target.path) as boolean;
95
+ DialStore.updateValue(target.panelId, target.path, !currentValue);
96
+ }
97
+ }
98
+
99
+ // Reset mouse tracking when a new key is pressed (for move/drag)
100
+ if (!wasAlreadyHeld) {
101
+ lastMouseX = null;
102
+ dragAccumulator = 0;
103
+ }
104
+ }
105
+
106
+ function handleKeyUp(e: KeyboardEvent) {
107
+ const key = e.key.toLowerCase();
108
+ activeKeys.delete(key);
109
+
110
+ // Reset drag state when key is released
111
+ isDragging = false;
112
+ lastMouseX = null;
113
+ dragAccumulator = 0;
114
+
115
+ if (activeKeys.size === 0) {
116
+ activePanelId = null;
117
+ activePath = null;
118
+ } else {
119
+ let found = false;
120
+ for (const remainingKey of activeKeys) {
121
+ const modifier = getActiveModifier(e);
122
+ const target = DialStore.resolveShortcutTarget(remainingKey, modifier);
123
+ if (target) {
124
+ activePanelId = target.panelId;
125
+ activePath = target.path;
126
+ found = true;
127
+ break;
128
+ }
129
+ }
130
+ if (!found) {
131
+ activePanelId = null;
132
+ activePath = null;
133
+ }
134
+ }
135
+ }
136
+
137
+ function handleWheel(e: WheelEvent) {
138
+ if (isInputFocused()) return;
139
+
140
+ const modifier = getActiveModifier(e);
141
+
142
+ // Key+scroll shortcuts
143
+ if (activeKeys.size > 0) {
144
+ for (const key of activeKeys) {
145
+ const target = DialStore.resolveShortcutTarget(key, modifier);
146
+ if (!target) continue;
147
+
148
+ const { panelId, path, control } = target;
149
+ const interaction = control.shortcut?.interaction ?? 'scroll';
150
+ if (interaction !== 'scroll' || control.type !== 'slider') continue;
151
+
152
+ e.preventDefault();
153
+ const effectiveStep = getEffectiveStep(control, control.shortcut!);
154
+ const direction = e.deltaY > 0 ? -1 : 1;
155
+ applySliderDelta(panelId, path, control, effectiveStep, direction);
156
+ return;
157
+ }
158
+ }
159
+
160
+ // Scroll-only shortcuts (no key needed)
161
+ const scrollOnlyTargets = DialStore.resolveScrollOnlyTargets();
162
+ for (const { panelId, path, control, shortcut } of scrollOnlyTargets) {
163
+ if (control.type !== 'slider') continue;
164
+
165
+ e.preventDefault();
166
+ const effectiveStep = getEffectiveStep(control, shortcut);
167
+ const direction = e.deltaY > 0 ? -1 : 1;
168
+ applySliderDelta(panelId, path, control, effectiveStep, direction);
169
+ return;
170
+ }
171
+ }
172
+
173
+ function handleMouseDown(e: MouseEvent) {
174
+ if (isInputFocused()) return;
175
+ if (activeKeys.size === 0) return;
176
+
177
+ const target = resolveActiveTarget('drag');
178
+ if (target) {
179
+ isDragging = true;
180
+ lastMouseX = e.clientX;
181
+ dragAccumulator = 0;
182
+ e.preventDefault();
183
+ }
184
+ }
185
+
186
+ function handleMouseUp() {
187
+ isDragging = false;
188
+ lastMouseX = null;
189
+ dragAccumulator = 0;
190
+ }
191
+
192
+ function handleMouseMove(e: MouseEvent) {
193
+ if (isInputFocused()) return;
194
+ if (activeKeys.size === 0) return;
195
+
196
+ // Drag interaction (requires mousedown)
197
+ if (isDragging) {
198
+ const target = resolveActiveTarget('drag');
199
+ if (target && lastMouseX !== null) {
200
+ const deltaX = e.clientX - lastMouseX;
201
+ lastMouseX = e.clientX;
202
+ dragAccumulator += deltaX;
203
+
204
+ const effectiveStep = getEffectiveStep(target.control, target.shortcut);
205
+ const steps = Math.trunc(dragAccumulator / DRAG_SENSITIVITY);
206
+ if (steps !== 0) {
207
+ dragAccumulator -= steps * DRAG_SENSITIVITY;
208
+ applySliderDelta(target.panelId, target.path, target.control, effectiveStep, steps);
209
+ }
210
+ }
211
+ return;
212
+ }
213
+
214
+ // Move interaction (no click needed, just key held + mouse movement)
215
+ const moveTarget = resolveActiveTarget('move');
216
+ if (moveTarget) {
217
+ if (lastMouseX === null) {
218
+ lastMouseX = e.clientX;
219
+ return;
220
+ }
221
+
222
+ const deltaX = e.clientX - lastMouseX;
223
+ lastMouseX = e.clientX;
224
+ dragAccumulator += deltaX;
225
+
226
+ const effectiveStep = getEffectiveStep(moveTarget.control, moveTarget.shortcut);
227
+ const steps = Math.trunc(dragAccumulator / DRAG_SENSITIVITY);
228
+ if (steps !== 0) {
229
+ dragAccumulator -= steps * DRAG_SENSITIVITY;
230
+ applySliderDelta(moveTarget.panelId, moveTarget.path, moveTarget.control, effectiveStep, steps);
231
+ }
232
+ }
233
+ }
234
+
235
+ function handleWindowBlur() {
236
+ activeKeys.clear();
237
+ isDragging = false;
238
+ lastMouseX = null;
239
+ dragAccumulator = 0;
240
+ activePanelId = null;
241
+ activePath = null;
242
+ }
243
+
244
+ $effect(() => {
245
+ window.addEventListener('keydown', handleKeyDown);
246
+ window.addEventListener('keyup', handleKeyUp);
247
+ window.addEventListener('wheel', handleWheel, { passive: false });
248
+ window.addEventListener('mousedown', handleMouseDown);
249
+ window.addEventListener('mouseup', handleMouseUp);
250
+ window.addEventListener('mousemove', handleMouseMove);
251
+ window.addEventListener('blur', handleWindowBlur);
252
+
253
+ return () => {
254
+ window.removeEventListener('keydown', handleKeyDown);
255
+ window.removeEventListener('keyup', handleKeyUp);
256
+ window.removeEventListener('wheel', handleWheel);
257
+ window.removeEventListener('mousedown', handleMouseDown);
258
+ window.removeEventListener('mouseup', handleMouseUp);
259
+ window.removeEventListener('mousemove', handleMouseMove);
260
+ window.removeEventListener('blur', handleWindowBlur);
261
+ };
262
+ });
263
+ </script>
264
+
265
+ {#if children}{@render children()}{/if}
@@ -0,0 +1,13 @@
1
+ export declare const SHORTCUT_CTX: unique symbol;
2
+ export interface ShortcutContextValue {
3
+ activePanelId: string | null;
4
+ activePath: string | null;
5
+ }
6
+ import type { Snippet } from 'svelte';
7
+ type $$ComponentProps = {
8
+ children?: Snippet;
9
+ };
10
+ declare const ShortcutListener: import("svelte").Component<$$ComponentProps, {}, "">;
11
+ type ShortcutListener = ReturnType<typeof ShortcutListener>;
12
+ export default ShortcutListener;
13
+ //# sourceMappingURL=ShortcutListener.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShortcutListener.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ShortcutListener.svelte.ts"],"names":[],"mappings":"AAGE,eAAO,MAAM,YAAY,eAA6B,CAAC;AAEvD,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAUrC,KAAK,gBAAgB,GAAG;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AA+PhD,QAAA,MAAM,gBAAgB,sDAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,128 @@
1
+ <script lang="ts">
2
+ import { DialStore } from 'dialkit/store';
3
+ import type { ShortcutConfig } from 'dialkit/store';
4
+ import Portal from '../Portal.svelte';
5
+
6
+ let { panelId } = $props<{ panelId: string }>();
7
+
8
+ let isOpen = $state(false);
9
+ let triggerEl: HTMLButtonElement | undefined;
10
+ let dropdownEl: HTMLDivElement | undefined;
11
+ let pos = $state({ top: 0, right: 0 });
12
+
13
+ function formatShortcutKey(sc: ShortcutConfig): string {
14
+ if (!sc.key) return '\u2014';
15
+ const mod = sc.modifier === 'alt' ? '\u2325'
16
+ : sc.modifier === 'shift' ? '\u21E7'
17
+ : sc.modifier === 'meta' ? '\u2318'
18
+ : '';
19
+ return `${mod}${sc.key.toUpperCase()}`;
20
+ }
21
+
22
+ function formatInteraction(sc: ShortcutConfig): string {
23
+ const interaction = sc.interaction ?? 'scroll';
24
+ switch (interaction) {
25
+ case 'scroll': return sc.key ? 'key+scroll' : 'scroll';
26
+ case 'drag': return 'key+drag';
27
+ case 'move': return 'key+move';
28
+ case 'scroll-only': return 'scroll';
29
+ }
30
+ }
31
+
32
+ function open() {
33
+ const rect = triggerEl?.getBoundingClientRect();
34
+ if (rect) {
35
+ pos = { top: rect.bottom + 4, right: window.innerWidth - rect.right };
36
+ }
37
+ isOpen = true;
38
+ }
39
+
40
+ function close() {
41
+ isOpen = false;
42
+ }
43
+
44
+ function toggle() {
45
+ if (isOpen) close();
46
+ else open();
47
+ }
48
+
49
+ // Close on mousedown outside
50
+ $effect(() => {
51
+ if (!isOpen) return;
52
+
53
+ const handler = (e: MouseEvent) => {
54
+ const target = e.target as Node;
55
+ if (triggerEl?.contains(target) || dropdownEl?.contains(target)) return;
56
+ close();
57
+ };
58
+
59
+ document.addEventListener('mousedown', handler);
60
+ return () => document.removeEventListener('mousedown', handler);
61
+ });
62
+
63
+ const panel = $derived(DialStore.getPanel(panelId));
64
+
65
+ const rows = $derived.by(() => {
66
+ if (!panel) return [];
67
+ const shortcuts = Object.entries(panel.shortcuts);
68
+ if (shortcuts.length === 0) return [];
69
+
70
+ return shortcuts.map(([path, shortcut]) => {
71
+ const findLabel = (controls: typeof panel.controls): string => {
72
+ for (const c of controls) {
73
+ if (c.path === path) return c.label;
74
+ if (c.type === 'folder' && c.children) {
75
+ const found = findLabel(c.children);
76
+ if (found) return found;
77
+ }
78
+ }
79
+ return path;
80
+ };
81
+ return { path, shortcut, label: findLabel(panel.controls) };
82
+ });
83
+ });
84
+ </script>
85
+
86
+ {#if panel && rows.length > 0}
87
+ <button
88
+ bind:this={triggerEl}
89
+ class="dialkit-shortcuts-trigger"
90
+ onclick={toggle}
91
+ title="Keyboard shortcuts"
92
+ >
93
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
94
+ <rect x="2" y="6" width="20" height="12" rx="2" />
95
+ <path d="M6 10H6.01" />
96
+ <path d="M10 10H10.01" />
97
+ <path d="M14 10H14.01" />
98
+ <path d="M18 10H18.01" />
99
+ <path d="M8 14H16" />
100
+ </svg>
101
+ </button>
102
+
103
+ <Portal target="body">
104
+ {#if isOpen}
105
+ <div
106
+ bind:this={dropdownEl}
107
+ class="dialkit-root dialkit-shortcuts-dropdown"
108
+ style:position="fixed"
109
+ style:top="{pos.top}px"
110
+ style:right="{pos.right}px"
111
+ >
112
+ <div class="dialkit-shortcuts-title">Keyboard Shortcuts</div>
113
+ <div class="dialkit-shortcuts-list">
114
+ {#each rows as row (row.path)}
115
+ <div class="dialkit-shortcuts-row">
116
+ <span class="dialkit-shortcuts-row-key">
117
+ {formatShortcutKey(row.shortcut)}
118
+ </span>
119
+ <span class="dialkit-shortcuts-row-label">{row.label}</span>
120
+ <span class="dialkit-shortcuts-row-mode">{formatInteraction(row.shortcut)}</span>
121
+ </div>
122
+ {/each}
123
+ </div>
124
+ <div class="dialkit-shortcuts-hint">See pill badges on controls for keys</div>
125
+ </div>
126
+ {/if}
127
+ </Portal>
128
+ {/if}
@@ -0,0 +1,7 @@
1
+ type $$ComponentProps = {
2
+ panelId: string;
3
+ };
4
+ declare const ShortcutsMenu: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type ShortcutsMenu = ReturnType<typeof ShortcutsMenu>;
6
+ export default ShortcutsMenu;
7
+ //# sourceMappingURL=ShortcutsMenu.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShortcutsMenu.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ShortcutsMenu.svelte.ts"],"names":[],"mappings":"AAOC,KAAK,gBAAgB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAyH7C,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -1,6 +1,8 @@
1
1
  <script lang="ts">
2
2
  import { tick } from 'svelte';
3
3
  import { Spring } from 'svelte/motion';
4
+ import type { ShortcutConfig } from 'dialkit/store';
5
+ import { decimalsForStep, roundValue, snapToDecile, formatSliderShortcut } from '../../shortcut-utils';
4
6
 
5
7
  let {
6
8
  label,
@@ -9,6 +11,8 @@
9
11
  min = 0,
10
12
  max = 1,
11
13
  step = 0.01,
14
+ shortcut,
15
+ shortcutActive = false,
12
16
  } = $props<{
13
17
  label: string;
14
18
  value: number;
@@ -17,6 +21,8 @@
17
21
  max?: number;
18
22
  step?: number;
19
23
  unit?: string;
24
+ shortcut?: ShortcutConfig;
25
+ shortcutActive?: boolean;
20
26
  }>();
21
27
 
22
28
  const CLICK_THRESHOLD = 3;
@@ -52,28 +58,6 @@
52
58
  let scaleVal = 1;
53
59
  let hoverTimeout: ReturnType<typeof setTimeout> | null = null;
54
60
 
55
- const decimalsForStep = (s: number) => {
56
- const text = s.toString();
57
- const dot = text.indexOf('.');
58
- return dot === -1 ? 0 : text.length - dot - 1;
59
- };
60
-
61
- const roundValue = (val: number, s: number) => {
62
- const raw = Math.round(val / s) * s;
63
- return Number.parseFloat(raw.toFixed(decimalsForStep(s)));
64
- };
65
-
66
- const snapToDecile = (rawValue: number, minValue: number, maxValue: number) => {
67
- const normalized = (rawValue - minValue) / (maxValue - minValue);
68
- const nearest = Math.round(normalized * 10) / 10;
69
-
70
- if (Math.abs(normalized - nearest) <= 0.03125) {
71
- return minValue + nearest * (maxValue - minValue);
72
- }
73
-
74
- return rawValue;
75
- };
76
-
77
61
  const percentFromValue = (nextValue: number) => ((nextValue - min) / (max - min)) * 100;
78
62
 
79
63
  const positionToValue = (clientX: number) => {
@@ -165,10 +149,6 @@
165
149
  handleScaleYMv.set(isActive && valueDodge ? 0.75 : 1);
166
150
  });
167
151
 
168
- const fillBackground = $derived(
169
- isActive ? 'rgba(255, 255, 255, 0.15)' : 'rgba(255, 255, 255, 0.11)'
170
- );
171
-
172
152
  const discreteSteps = $derived((max - min) / step);
173
153
 
174
154
  const hashMarks = $derived.by(() => {
@@ -283,8 +263,8 @@
283
263
  const displayValue = $derived(value.toFixed(decimalsForStep(step)));
284
264
 
285
265
  const trackStyle = $derived(`width:calc(100% + ${Math.abs(rubberStretchPx.current)}px);transform:translateX(${rubberStretchPx.current < 0 ? rubberStretchPx.current : 0}px);`);
286
- const fillStyle = $derived(`background:${fillBackground};width:${fillPercent.current}%;transition:background 0.15s;`);
287
- const handleStyle = $derived(`left:max(5px, calc(${fillPercent.current}% - 9px));opacity:${handleOpacityMv.current};transform:translateY(-50%) scaleX(${handleScaleXMv.current}) scaleY(${handleScaleYMv.current});background:rgba(255, 255, 255, 0.9);`);
266
+ const fillStyle = $derived(`width:${fillPercent.current}%;`);
267
+ const handleStyle = $derived(`left:max(5px, calc(${fillPercent.current}% - 9px));opacity:${handleOpacityMv.current};transform:translateY(-50%) scaleX(${handleScaleXMv.current}) scaleY(${handleScaleYMv.current});`);
288
268
  </script>
289
269
 
290
270
  <div bind:this={wrapperRef} class="dialkit-slider-wrapper">
@@ -308,7 +288,14 @@
308
288
 
309
289
  <div class="dialkit-slider-handle" style={handleStyle} />
310
290
 
311
- <span bind:this={labelRef} class="dialkit-slider-label">{label}</span>
291
+ <span bind:this={labelRef} class="dialkit-slider-label">
292
+ {label}
293
+ {#if shortcut}
294
+ <span class={`dialkit-shortcut-pill${shortcutActive ? ' dialkit-shortcut-pill-active' : ''}`}>
295
+ {formatSliderShortcut(shortcut)}
296
+ </span>
297
+ {/if}
298
+ </span>
312
299
 
313
300
  {#if showInput}
314
301
  <input
@@ -1,3 +1,4 @@
1
+ import type { ShortcutConfig } from 'dialkit/store';
1
2
  type $$ComponentProps = {
2
3
  label: string;
3
4
  value: number;
@@ -6,6 +7,8 @@ type $$ComponentProps = {
6
7
  max?: number;
7
8
  step?: number;
8
9
  unit?: string;
10
+ shortcut?: ShortcutConfig;
11
+ shortcutActive?: boolean;
9
12
  };
10
13
  declare const Slider: import("svelte").Component<$$ComponentProps, {}, "">;
11
14
  type Slider = ReturnType<typeof Slider>;
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/Slider.svelte.ts"],"names":[],"mappings":"AAMC,KAAK,gBAAgB,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AA0TJ,QAAA,MAAM,MAAM,sDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"Slider.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/Slider.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGnD,KAAK,gBAAgB,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AA2SJ,QAAA,MAAM,MAAM,sDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}
@@ -25,27 +25,29 @@
25
25
 
26
26
  const isSimpleMode = $derived(mode === 'simple');
27
27
 
28
+ const cache: {
29
+ simple: SpringConfig;
30
+ advanced: SpringConfig;
31
+ } = {
32
+ simple: spring.visualDuration !== undefined ? spring : { type: 'spring', visualDuration: 0.3, bounce: 0.2 },
33
+ advanced: spring.stiffness !== undefined ? spring : { type: 'spring', stiffness: 200, damping: 25, mass: 1 },
34
+ };
35
+
28
36
  const handleModeChange = (newMode: string) => {
29
37
  const typedMode = newMode as 'simple' | 'advanced';
38
+
39
+ if (isSimpleMode) {
40
+ cache.simple = spring;
41
+ } else {
42
+ cache.advanced = spring;
43
+ }
44
+
30
45
  DialStore.updateSpringMode(panelId, path, typedMode);
31
46
 
32
47
  if (typedMode === 'simple') {
33
- const { stiffness, damping, mass, ...rest } = spring;
34
- onChange({
35
- ...rest,
36
- type: 'spring',
37
- visualDuration: spring.visualDuration ?? 0.3,
38
- bounce: spring.bounce ?? 0.2,
39
- });
48
+ onChange(cache.simple);
40
49
  } else {
41
- const { visualDuration, bounce, ...rest } = spring;
42
- onChange({
43
- ...rest,
44
- type: 'spring',
45
- stiffness: spring.stiffness ?? 200,
46
- damping: spring.damping ?? 25,
47
- mass: spring.mass ?? 1,
48
- });
50
+ onChange(cache.advanced);
49
51
  }
50
52
  };
51
53
 
@@ -1 +1 @@
1
- {"version":3,"file":"SpringControl.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/SpringControl.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAMjD,KAAK,gBAAgB,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;CAC1C,CAAC;AAkFJ,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"SpringControl.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/SpringControl.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAMjD,KAAK,gBAAgB,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;CAC1C,CAAC;AAoFJ,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -1,15 +1,26 @@
1
1
  <script lang="ts">
2
2
  import SegmentedControl from './SegmentedControl.svelte';
3
+ import type { ShortcutConfig } from 'dialkit/store';
4
+ import { formatToggleShortcut } from '../../shortcut-utils';
3
5
 
4
- let { label, checked, onChange } = $props<{
6
+ let { label, checked, onChange, shortcut, shortcutActive = false } = $props<{
5
7
  label: string;
6
8
  checked: boolean;
7
9
  onChange: (checked: boolean) => void;
10
+ shortcut?: ShortcutConfig;
11
+ shortcutActive?: boolean;
8
12
  }>();
9
13
  </script>
10
14
 
11
15
  <div class="dialkit-labeled-control">
12
- <span class="dialkit-labeled-control-label">{label}</span>
16
+ <span class="dialkit-labeled-control-label">
17
+ {label}
18
+ {#if shortcut}
19
+ <span class={`dialkit-shortcut-pill${shortcutActive ? ' dialkit-shortcut-pill-active' : ''}`}>
20
+ {formatToggleShortcut(shortcut)}
21
+ </span>
22
+ {/if}
23
+ </span>
13
24
  <SegmentedControl
14
25
  options={[
15
26
  { value: 'off', label: 'Off' },
@@ -1,7 +1,10 @@
1
+ import type { ShortcutConfig } from 'dialkit/store';
1
2
  type $$ComponentProps = {
2
3
  label: string;
3
4
  checked: boolean;
4
5
  onChange: (checked: boolean) => void;
6
+ shortcut?: ShortcutConfig;
7
+ shortcutActive?: boolean;
5
8
  };
6
9
  declare const Toggle: import("svelte").Component<$$ComponentProps, {}, "">;
7
10
  type Toggle = ReturnType<typeof Toggle>;
@@ -1 +1 @@
1
- {"version":3,"file":"Toggle.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/Toggle.svelte.ts"],"names":[],"mappings":"AAKC,KAAK,gBAAgB,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACtC,CAAC;AAiBJ,QAAA,MAAM,MAAM,sDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"Toggle.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/Toggle.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGnD,KAAK,gBAAgB,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AA0BJ,QAAA,MAAM,MAAM,sDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}