dialkit 1.0.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.
- package/README.md +293 -2
- package/dist/index.cjs +905 -363
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -9
- package/dist/index.d.ts +46 -9
- package/dist/index.js +910 -370
- package/dist/index.js.map +1 -1
- package/dist/solid/index.cjs +1042 -532
- package/dist/solid/index.cjs.map +1 -1
- package/dist/solid/index.d.cts +36 -3
- package/dist/solid/index.d.ts +36 -3
- package/dist/solid/index.js +911 -402
- package/dist/solid/index.js.map +1 -1
- package/dist/store/index.cjs +490 -0
- package/dist/store/index.cjs.map +1 -0
- package/dist/store/index.d.cts +146 -0
- package/dist/store/index.d.ts +146 -0
- package/dist/store/index.js +465 -0
- package/dist/store/index.js.map +1 -0
- package/dist/styles.css +287 -25
- package/dist/svelte/Portal.svelte +30 -0
- package/dist/svelte/Portal.svelte.d.ts +9 -0
- package/dist/svelte/Portal.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ButtonGroup.svelte +16 -0
- package/dist/svelte/components/ButtonGroup.svelte.d.ts +11 -0
- package/dist/svelte/components/ButtonGroup.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ColorControl.svelte +81 -0
- package/dist/svelte/components/ColorControl.svelte.d.ts +9 -0
- package/dist/svelte/components/ColorControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ControlRenderer.svelte +96 -0
- package/dist/svelte/components/ControlRenderer.svelte.d.ts +11 -0
- package/dist/svelte/components/ControlRenderer.svelte.d.ts.map +1 -0
- package/dist/svelte/components/DialRoot.svelte +79 -0
- package/dist/svelte/components/DialRoot.svelte.d.ts +14 -0
- package/dist/svelte/components/DialRoot.svelte.d.ts.map +1 -0
- package/dist/svelte/components/EasingVisualization.svelte +50 -0
- package/dist/svelte/components/EasingVisualization.svelte.d.ts +10 -0
- package/dist/svelte/components/EasingVisualization.svelte.d.ts.map +1 -0
- package/dist/svelte/components/Folder.svelte +213 -0
- package/dist/svelte/components/Folder.svelte.d.ts +14 -0
- package/dist/svelte/components/Folder.svelte.d.ts.map +1 -0
- package/dist/svelte/components/Panel.svelte +149 -0
- package/dist/svelte/components/Panel.svelte.d.ts +10 -0
- package/dist/svelte/components/Panel.svelte.d.ts.map +1 -0
- package/dist/svelte/components/PresetManager.svelte +157 -0
- package/dist/svelte/components/PresetManager.svelte.d.ts +10 -0
- package/dist/svelte/components/PresetManager.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SegmentedControl.svelte +62 -0
- package/dist/svelte/components/SegmentedControl.svelte.d.ts +13 -0
- package/dist/svelte/components/SegmentedControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SelectControl.svelte +152 -0
- package/dist/svelte/components/SelectControl.svelte.d.ts +14 -0
- package/dist/svelte/components/SelectControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ShortcutListener.svelte +265 -0
- package/dist/svelte/components/ShortcutListener.svelte.d.ts +13 -0
- package/dist/svelte/components/ShortcutListener.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ShortcutsMenu.svelte +128 -0
- package/dist/svelte/components/ShortcutsMenu.svelte.d.ts +7 -0
- package/dist/svelte/components/ShortcutsMenu.svelte.d.ts.map +1 -0
- package/dist/svelte/components/Slider.svelte +332 -0
- package/dist/svelte/components/Slider.svelte.d.ts +16 -0
- package/dist/svelte/components/Slider.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SpringControl.svelte +126 -0
- package/dist/svelte/components/SpringControl.svelte.d.ts +12 -0
- package/dist/svelte/components/SpringControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SpringVisualization.svelte +115 -0
- package/dist/svelte/components/SpringVisualization.svelte.d.ts +9 -0
- package/dist/svelte/components/SpringVisualization.svelte.d.ts.map +1 -0
- package/dist/svelte/components/TextControl.svelte +19 -0
- package/dist/svelte/components/TextControl.svelte.d.ts +10 -0
- package/dist/svelte/components/TextControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/Toggle.svelte +32 -0
- package/dist/svelte/components/Toggle.svelte.d.ts +12 -0
- package/dist/svelte/components/Toggle.svelte.d.ts.map +1 -0
- package/dist/svelte/components/TransitionControl.svelte +203 -0
- package/dist/svelte/components/TransitionControl.svelte.d.ts +12 -0
- package/dist/svelte/components/TransitionControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/transitions.d.ts +6 -0
- package/dist/svelte/components/transitions.d.ts.map +1 -0
- package/dist/svelte/components/transitions.js +14 -0
- package/dist/svelte/createDialKit.svelte.d.ts +8 -0
- package/dist/svelte/createDialKit.svelte.d.ts.map +1 -0
- package/dist/svelte/createDialKit.svelte.js +82 -0
- package/dist/svelte/index.d.ts +23 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +23 -0
- package/dist/svelte/shims.d.ts +9 -0
- package/dist/svelte/theme-css.d.ts +2 -0
- package/dist/svelte/theme-css.d.ts.map +1 -0
- package/dist/svelte/theme-css.js +1328 -0
- package/dist/vue/index.cjs +3056 -0
- package/dist/vue/index.cjs.map +1 -0
- package/dist/vue/index.d.cts +675 -0
- package/dist/vue/index.d.ts +675 -0
- package/dist/vue/index.js +3014 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +50 -6
package/dist/index.js
CHANGED
|
@@ -16,22 +16,22 @@ var DialStoreClass = class {
|
|
|
16
16
|
this.activePreset = /* @__PURE__ */ new Map();
|
|
17
17
|
this.baseValues = /* @__PURE__ */ new Map();
|
|
18
18
|
}
|
|
19
|
-
registerPanel(id, name, config) {
|
|
20
|
-
const controls = this.parseConfig(config, "");
|
|
19
|
+
registerPanel(id, name, config, shortcuts) {
|
|
20
|
+
const controls = this.parseConfig(config, "", shortcuts);
|
|
21
21
|
const values = this.flattenValues(config, "");
|
|
22
22
|
this.initTransitionModes(config, "", values);
|
|
23
|
-
this.panels.set(id, { id, name, controls, values });
|
|
23
|
+
this.panels.set(id, { id, name, controls, values, shortcuts: shortcuts ?? {} });
|
|
24
24
|
this.snapshots.set(id, { ...values });
|
|
25
25
|
this.baseValues.set(id, { ...values });
|
|
26
26
|
this.notifyGlobal();
|
|
27
27
|
}
|
|
28
|
-
updatePanel(id, name, config) {
|
|
28
|
+
updatePanel(id, name, config, shortcuts) {
|
|
29
29
|
const existing = this.panels.get(id);
|
|
30
30
|
if (!existing) {
|
|
31
|
-
this.registerPanel(id, name, config);
|
|
31
|
+
this.registerPanel(id, name, config, shortcuts);
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
|
-
const controls = this.parseConfig(config, "");
|
|
34
|
+
const controls = this.parseConfig(config, "", shortcuts);
|
|
35
35
|
const controlsByPath = this.mapControlsByPath(controls);
|
|
36
36
|
const defaultValues = this.flattenValues(config, "");
|
|
37
37
|
const nextValues = {};
|
|
@@ -53,7 +53,7 @@ var DialStoreClass = class {
|
|
|
53
53
|
nextValues[path] = mode;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
const nextPanel = { id, name, controls, values: nextValues };
|
|
56
|
+
const nextPanel = { id, name, controls, values: nextValues, shortcuts: shortcuts ?? existing.shortcuts };
|
|
57
57
|
this.panels.set(id, nextPanel);
|
|
58
58
|
this.snapshots.set(id, { ...nextValues });
|
|
59
59
|
const previousBaseValues = this.baseValues.get(id) ?? {};
|
|
@@ -211,6 +211,44 @@ var DialStoreClass = class {
|
|
|
211
211
|
this.activePreset.set(panelId, null);
|
|
212
212
|
this.notify(panelId);
|
|
213
213
|
}
|
|
214
|
+
resolveShortcutTarget(key, modifier) {
|
|
215
|
+
for (const panel of this.panels.values()) {
|
|
216
|
+
for (const [path, shortcut] of Object.entries(panel.shortcuts)) {
|
|
217
|
+
if (!shortcut.key) continue;
|
|
218
|
+
if (shortcut.key.toLowerCase() !== key.toLowerCase()) continue;
|
|
219
|
+
const scMod = shortcut.modifier ?? void 0;
|
|
220
|
+
if (scMod !== modifier) continue;
|
|
221
|
+
const control = this.findControlByPath(panel.controls, path);
|
|
222
|
+
if (control) {
|
|
223
|
+
return { panelId: panel.id, path, control };
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
resolveScrollOnlyTargets() {
|
|
230
|
+
const results = [];
|
|
231
|
+
for (const panel of this.panels.values()) {
|
|
232
|
+
for (const [path, shortcut] of Object.entries(panel.shortcuts)) {
|
|
233
|
+
if ((shortcut.interaction ?? "scroll") !== "scroll-only") continue;
|
|
234
|
+
const control = this.findControlByPath(panel.controls, path);
|
|
235
|
+
if (control) {
|
|
236
|
+
results.push({ panelId: panel.id, path, control, shortcut });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return results;
|
|
241
|
+
}
|
|
242
|
+
findControlByPath(controls, path) {
|
|
243
|
+
for (const control of controls) {
|
|
244
|
+
if (control.path === path) return control;
|
|
245
|
+
if (control.type === "folder" && control.children) {
|
|
246
|
+
const found = this.findControlByPath(control.children, path);
|
|
247
|
+
if (found) return found;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
214
252
|
notify(panelId) {
|
|
215
253
|
this.listeners.get(panelId)?.forEach((fn) => fn());
|
|
216
254
|
}
|
|
@@ -232,12 +270,13 @@ var DialStoreClass = class {
|
|
|
232
270
|
}
|
|
233
271
|
}
|
|
234
272
|
}
|
|
235
|
-
parseConfig(config, prefix) {
|
|
273
|
+
parseConfig(config, prefix, shortcuts) {
|
|
236
274
|
const controls = [];
|
|
237
275
|
for (const [key, value] of Object.entries(config)) {
|
|
238
276
|
if (key === "_collapsed") continue;
|
|
239
277
|
const path = prefix ? `${prefix}.${key}` : key;
|
|
240
278
|
const label = this.formatLabel(key);
|
|
279
|
+
const shortcut = shortcuts?.[path];
|
|
241
280
|
if (Array.isArray(value) && value.length <= 4 && typeof value[0] === "number") {
|
|
242
281
|
controls.push({
|
|
243
282
|
type: "slider",
|
|
@@ -245,13 +284,14 @@ var DialStoreClass = class {
|
|
|
245
284
|
label,
|
|
246
285
|
min: value[1],
|
|
247
286
|
max: value[2],
|
|
248
|
-
step: value[3] ?? this.inferStep(value[1], value[2])
|
|
287
|
+
step: value[3] ?? this.inferStep(value[1], value[2]),
|
|
288
|
+
shortcut
|
|
249
289
|
});
|
|
250
290
|
} else if (typeof value === "number") {
|
|
251
291
|
const { min, max, step } = this.inferRange(value);
|
|
252
|
-
controls.push({ type: "slider", path, label, min, max, step });
|
|
292
|
+
controls.push({ type: "slider", path, label, min, max, step, shortcut });
|
|
253
293
|
} else if (typeof value === "boolean") {
|
|
254
|
-
controls.push({ type: "toggle", path, label });
|
|
294
|
+
controls.push({ type: "toggle", path, label, shortcut });
|
|
255
295
|
} else if (this.isSpringConfig(value) || this.isEasingConfig(value)) {
|
|
256
296
|
controls.push({ type: "transition", path, label });
|
|
257
297
|
} else if (this.isActionConfig(value)) {
|
|
@@ -276,7 +316,7 @@ var DialStoreClass = class {
|
|
|
276
316
|
path,
|
|
277
317
|
label,
|
|
278
318
|
defaultOpen,
|
|
279
|
-
children: this.parseConfig(folderConfig, path)
|
|
319
|
+
children: this.parseConfig(folderConfig, path, shortcuts)
|
|
280
320
|
});
|
|
281
321
|
}
|
|
282
322
|
}
|
|
@@ -434,8 +474,11 @@ function useDialKit(name, config, options) {
|
|
|
434
474
|
configRef.current = config;
|
|
435
475
|
const onActionRef = useRef(options?.onAction);
|
|
436
476
|
onActionRef.current = options?.onAction;
|
|
477
|
+
const shortcutsRef = useRef(options?.shortcuts);
|
|
478
|
+
shortcutsRef.current = options?.shortcuts;
|
|
479
|
+
const serializedShortcuts = JSON.stringify(options?.shortcuts);
|
|
437
480
|
useEffect(() => {
|
|
438
|
-
DialStore.registerPanel(panelId, name, configRef.current);
|
|
481
|
+
DialStore.registerPanel(panelId, name, configRef.current, shortcutsRef.current);
|
|
439
482
|
return () => DialStore.unregisterPanel(panelId);
|
|
440
483
|
}, [panelId, name]);
|
|
441
484
|
const mountedRef = useRef(false);
|
|
@@ -444,8 +487,8 @@ function useDialKit(name, config, options) {
|
|
|
444
487
|
mountedRef.current = true;
|
|
445
488
|
return;
|
|
446
489
|
}
|
|
447
|
-
DialStore.updatePanel(panelId, name, configRef.current);
|
|
448
|
-
}, [panelId, name, serializedConfig]);
|
|
490
|
+
DialStore.updatePanel(panelId, name, configRef.current, shortcutsRef.current);
|
|
491
|
+
}, [panelId, name, serializedConfig, serializedShortcuts]);
|
|
449
492
|
useEffect(() => {
|
|
450
493
|
return DialStore.subscribeActions(panelId, (action) => {
|
|
451
494
|
onActionRef.current?.(action);
|
|
@@ -511,23 +554,336 @@ function getFirstOptionValue(options) {
|
|
|
511
554
|
}
|
|
512
555
|
|
|
513
556
|
// src/components/DialRoot.tsx
|
|
514
|
-
import { useEffect as
|
|
557
|
+
import { useEffect as useEffect8, useState as useState10, useRef as useRef11, useCallback as useCallback6 } from "react";
|
|
515
558
|
import { createPortal as createPortal3 } from "react-dom";
|
|
516
559
|
|
|
517
560
|
// src/components/Panel.tsx
|
|
518
|
-
import { useState as
|
|
519
|
-
import { motion as
|
|
561
|
+
import { useState as useState9, useContext, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
562
|
+
import { motion as motion5, AnimatePresence as AnimatePresence4 } from "motion/react";
|
|
563
|
+
|
|
564
|
+
// src/components/ShortcutListener.tsx
|
|
565
|
+
import { createContext, useEffect as useEffect2, useRef as useRef2, useState, useCallback } from "react";
|
|
566
|
+
|
|
567
|
+
// src/shortcut-utils.ts
|
|
568
|
+
function decimalsForStep(step) {
|
|
569
|
+
const s = step.toString();
|
|
570
|
+
const dot = s.indexOf(".");
|
|
571
|
+
return dot === -1 ? 0 : s.length - dot - 1;
|
|
572
|
+
}
|
|
573
|
+
function roundValue(val, step) {
|
|
574
|
+
const raw = Math.round(val / step) * step;
|
|
575
|
+
return parseFloat(raw.toFixed(decimalsForStep(step)));
|
|
576
|
+
}
|
|
577
|
+
function getEffectiveStep(control, shortcut) {
|
|
578
|
+
const min = control.min ?? 0;
|
|
579
|
+
const max = control.max ?? 1;
|
|
580
|
+
const range = max - min;
|
|
581
|
+
const mode = shortcut.mode ?? "normal";
|
|
582
|
+
return mode === "fine" ? range * 0.01 : mode === "coarse" ? range * 0.1 : control.step ?? 1;
|
|
583
|
+
}
|
|
584
|
+
function applySliderDelta(panelId, path, control, effectiveStep, direction) {
|
|
585
|
+
const currentValue = DialStore.getValue(panelId, path);
|
|
586
|
+
const min = control.min ?? 0;
|
|
587
|
+
const max = control.max ?? 1;
|
|
588
|
+
const newValue = Math.max(min, Math.min(max, currentValue + direction * effectiveStep));
|
|
589
|
+
DialStore.updateValue(panelId, path, roundValue(newValue, effectiveStep));
|
|
590
|
+
}
|
|
591
|
+
function snapToDecile(rawValue, min, max) {
|
|
592
|
+
const normalized = (rawValue - min) / (max - min);
|
|
593
|
+
const nearest = Math.round(normalized * 10) / 10;
|
|
594
|
+
if (Math.abs(normalized - nearest) <= 0.03125) {
|
|
595
|
+
return min + nearest * (max - min);
|
|
596
|
+
}
|
|
597
|
+
return rawValue;
|
|
598
|
+
}
|
|
599
|
+
function isInputFocused() {
|
|
600
|
+
const el = document.activeElement;
|
|
601
|
+
if (!el) return false;
|
|
602
|
+
const tag = el.tagName;
|
|
603
|
+
if (tag === "INPUT" || tag === "TEXTAREA") return true;
|
|
604
|
+
if (el.contentEditable === "true") return true;
|
|
605
|
+
return false;
|
|
606
|
+
}
|
|
607
|
+
function getActiveModifier(e) {
|
|
608
|
+
if (e.altKey) return "alt";
|
|
609
|
+
if (e.shiftKey) return "shift";
|
|
610
|
+
if (e.metaKey) return "meta";
|
|
611
|
+
return void 0;
|
|
612
|
+
}
|
|
613
|
+
function findControl(controls, path) {
|
|
614
|
+
for (const control of controls) {
|
|
615
|
+
if (control.path === path) return control;
|
|
616
|
+
if (control.type === "folder" && control.children) {
|
|
617
|
+
const found = findControl(control.children, path);
|
|
618
|
+
if (found) return found;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
return null;
|
|
622
|
+
}
|
|
623
|
+
var DRAG_SENSITIVITY = 4;
|
|
624
|
+
function formatInteractionLabel(interaction) {
|
|
625
|
+
switch (interaction) {
|
|
626
|
+
case "drag":
|
|
627
|
+
return "Drag";
|
|
628
|
+
case "move":
|
|
629
|
+
return "Move";
|
|
630
|
+
case "scroll-only":
|
|
631
|
+
return "Scroll";
|
|
632
|
+
default:
|
|
633
|
+
return "Scroll";
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
function formatSliderShortcut(sc) {
|
|
637
|
+
const interaction = sc.interaction ?? "scroll";
|
|
638
|
+
const actionLabel = formatInteractionLabel(interaction);
|
|
639
|
+
if (!sc.key) return actionLabel;
|
|
640
|
+
const mod = formatModifier(sc.modifier);
|
|
641
|
+
return `${mod}${sc.key.toUpperCase()}+${actionLabel}`;
|
|
642
|
+
}
|
|
643
|
+
function formatToggleShortcut(sc) {
|
|
644
|
+
if (!sc.key) return "Press";
|
|
645
|
+
const mod = formatModifier(sc.modifier);
|
|
646
|
+
return `${mod}${sc.key.toUpperCase()}`;
|
|
647
|
+
}
|
|
648
|
+
function formatModifier(modifier) {
|
|
649
|
+
return modifier === "alt" ? "\u2325" : modifier === "shift" ? "\u21E7" : modifier === "meta" ? "\u2318" : "";
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// src/components/ShortcutListener.tsx
|
|
653
|
+
import { jsx } from "react/jsx-runtime";
|
|
654
|
+
var ShortcutContext = createContext({ activePanelId: null, activePath: null });
|
|
655
|
+
function ShortcutListener({ children }) {
|
|
656
|
+
const [activeShortcut, setActiveShortcut] = useState({ activePanelId: null, activePath: null });
|
|
657
|
+
const activeKeysRef = useRef2(/* @__PURE__ */ new Set());
|
|
658
|
+
const isDraggingRef = useRef2(false);
|
|
659
|
+
const lastMouseXRef = useRef2(null);
|
|
660
|
+
const dragAccumulatorRef = useRef2(0);
|
|
661
|
+
const resolveActiveTarget = useCallback((interaction) => {
|
|
662
|
+
for (const key of activeKeysRef.current) {
|
|
663
|
+
const panels = DialStore.getPanels();
|
|
664
|
+
for (const panel of panels) {
|
|
665
|
+
for (const [path, shortcut] of Object.entries(panel.shortcuts)) {
|
|
666
|
+
if (!shortcut.key) continue;
|
|
667
|
+
if (shortcut.key.toLowerCase() !== key) continue;
|
|
668
|
+
if ((shortcut.interaction ?? "scroll") !== interaction) continue;
|
|
669
|
+
const control = findControl(panel.controls, path);
|
|
670
|
+
if (control && control.type === "slider") {
|
|
671
|
+
return { panelId: panel.id, path, control, shortcut };
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
return null;
|
|
677
|
+
}, []);
|
|
678
|
+
useEffect2(() => {
|
|
679
|
+
const handleKeyDown = (e) => {
|
|
680
|
+
if (isInputFocused()) return;
|
|
681
|
+
const key = e.key.toLowerCase();
|
|
682
|
+
if (key === "arrowleft" || key === "arrowright" || key === "arrowup" || key === "arrowdown") {
|
|
683
|
+
if (activeKeysRef.current.size > 0) {
|
|
684
|
+
const target2 = resolveActiveTarget("scroll") || resolveActiveTarget("drag") || resolveActiveTarget("move");
|
|
685
|
+
if (target2 && target2.control.type === "slider") {
|
|
686
|
+
e.preventDefault();
|
|
687
|
+
const direction = key === "arrowright" || key === "arrowup" ? 1 : -1;
|
|
688
|
+
const effectiveStep = getEffectiveStep(target2.control, target2.shortcut);
|
|
689
|
+
applySliderDelta(target2.panelId, target2.path, target2.control, effectiveStep, direction);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
const wasAlreadyHeld = activeKeysRef.current.has(key);
|
|
695
|
+
activeKeysRef.current.add(key);
|
|
696
|
+
const modifier = getActiveModifier(e);
|
|
697
|
+
const target = DialStore.resolveShortcutTarget(key, modifier);
|
|
698
|
+
if (target) {
|
|
699
|
+
setActiveShortcut({ activePanelId: target.panelId, activePath: target.path });
|
|
700
|
+
if (!wasAlreadyHeld && target.control.type === "toggle") {
|
|
701
|
+
const currentValue = DialStore.getValue(target.panelId, target.path);
|
|
702
|
+
DialStore.updateValue(target.panelId, target.path, !currentValue);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
if (!wasAlreadyHeld) {
|
|
706
|
+
lastMouseXRef.current = null;
|
|
707
|
+
dragAccumulatorRef.current = 0;
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
const handleKeyUp = (e) => {
|
|
711
|
+
const key = e.key.toLowerCase();
|
|
712
|
+
activeKeysRef.current.delete(key);
|
|
713
|
+
isDraggingRef.current = false;
|
|
714
|
+
lastMouseXRef.current = null;
|
|
715
|
+
dragAccumulatorRef.current = 0;
|
|
716
|
+
if (activeKeysRef.current.size === 0) {
|
|
717
|
+
setActiveShortcut({ activePanelId: null, activePath: null });
|
|
718
|
+
} else {
|
|
719
|
+
let found = false;
|
|
720
|
+
for (const remainingKey of activeKeysRef.current) {
|
|
721
|
+
const modifier = getActiveModifier(e);
|
|
722
|
+
const target = DialStore.resolveShortcutTarget(remainingKey, modifier);
|
|
723
|
+
if (target) {
|
|
724
|
+
setActiveShortcut({ activePanelId: target.panelId, activePath: target.path });
|
|
725
|
+
found = true;
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
if (!found) {
|
|
730
|
+
setActiveShortcut({ activePanelId: null, activePath: null });
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
const handleWheel = (e) => {
|
|
735
|
+
if (isInputFocused()) return;
|
|
736
|
+
const modifier = getActiveModifier(e);
|
|
737
|
+
if (activeKeysRef.current.size > 0) {
|
|
738
|
+
for (const key of activeKeysRef.current) {
|
|
739
|
+
const target = DialStore.resolveShortcutTarget(key, modifier);
|
|
740
|
+
if (!target) continue;
|
|
741
|
+
const { panelId, path, control } = target;
|
|
742
|
+
const interaction = control.shortcut?.interaction ?? "scroll";
|
|
743
|
+
if (interaction !== "scroll" || control.type !== "slider") continue;
|
|
744
|
+
e.preventDefault();
|
|
745
|
+
const effectiveStep = getEffectiveStep(control, control.shortcut);
|
|
746
|
+
const direction = e.deltaY > 0 ? -1 : 1;
|
|
747
|
+
applySliderDelta(panelId, path, control, effectiveStep, direction);
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
const scrollOnlyTargets = DialStore.resolveScrollOnlyTargets();
|
|
752
|
+
for (const { panelId, path, control, shortcut } of scrollOnlyTargets) {
|
|
753
|
+
if (control.type !== "slider") continue;
|
|
754
|
+
e.preventDefault();
|
|
755
|
+
const effectiveStep = getEffectiveStep(control, shortcut);
|
|
756
|
+
const direction = e.deltaY > 0 ? -1 : 1;
|
|
757
|
+
applySliderDelta(panelId, path, control, effectiveStep, direction);
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
const handleMouseDown = (e) => {
|
|
762
|
+
if (isInputFocused()) return;
|
|
763
|
+
if (activeKeysRef.current.size === 0) return;
|
|
764
|
+
const target = resolveActiveTarget("drag");
|
|
765
|
+
if (target) {
|
|
766
|
+
isDraggingRef.current = true;
|
|
767
|
+
lastMouseXRef.current = e.clientX;
|
|
768
|
+
dragAccumulatorRef.current = 0;
|
|
769
|
+
e.preventDefault();
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
const handleMouseUp = () => {
|
|
773
|
+
isDraggingRef.current = false;
|
|
774
|
+
lastMouseXRef.current = null;
|
|
775
|
+
dragAccumulatorRef.current = 0;
|
|
776
|
+
};
|
|
777
|
+
const handleMouseMove = (e) => {
|
|
778
|
+
if (isInputFocused()) return;
|
|
779
|
+
if (activeKeysRef.current.size === 0) return;
|
|
780
|
+
if (isDraggingRef.current) {
|
|
781
|
+
const target = resolveActiveTarget("drag");
|
|
782
|
+
if (target && lastMouseXRef.current !== null) {
|
|
783
|
+
const deltaX = e.clientX - lastMouseXRef.current;
|
|
784
|
+
lastMouseXRef.current = e.clientX;
|
|
785
|
+
dragAccumulatorRef.current += deltaX;
|
|
786
|
+
const effectiveStep = getEffectiveStep(target.control, target.shortcut);
|
|
787
|
+
const steps = Math.trunc(dragAccumulatorRef.current / DRAG_SENSITIVITY);
|
|
788
|
+
if (steps !== 0) {
|
|
789
|
+
dragAccumulatorRef.current -= steps * DRAG_SENSITIVITY;
|
|
790
|
+
applySliderDelta(target.panelId, target.path, target.control, effectiveStep, steps);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
const moveTarget = resolveActiveTarget("move");
|
|
796
|
+
if (moveTarget) {
|
|
797
|
+
if (lastMouseXRef.current === null) {
|
|
798
|
+
lastMouseXRef.current = e.clientX;
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
const deltaX = e.clientX - lastMouseXRef.current;
|
|
802
|
+
lastMouseXRef.current = e.clientX;
|
|
803
|
+
dragAccumulatorRef.current += deltaX;
|
|
804
|
+
const effectiveStep = getEffectiveStep(moveTarget.control, moveTarget.shortcut);
|
|
805
|
+
const steps = Math.trunc(dragAccumulatorRef.current / DRAG_SENSITIVITY);
|
|
806
|
+
if (steps !== 0) {
|
|
807
|
+
dragAccumulatorRef.current -= steps * DRAG_SENSITIVITY;
|
|
808
|
+
applySliderDelta(moveTarget.panelId, moveTarget.path, moveTarget.control, effectiveStep, steps);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
const handleWindowBlur = () => {
|
|
813
|
+
activeKeysRef.current.clear();
|
|
814
|
+
isDraggingRef.current = false;
|
|
815
|
+
lastMouseXRef.current = null;
|
|
816
|
+
dragAccumulatorRef.current = 0;
|
|
817
|
+
setActiveShortcut({ activePanelId: null, activePath: null });
|
|
818
|
+
};
|
|
819
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
820
|
+
window.addEventListener("keyup", handleKeyUp);
|
|
821
|
+
window.addEventListener("wheel", handleWheel, { passive: false });
|
|
822
|
+
window.addEventListener("mousedown", handleMouseDown);
|
|
823
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
824
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
825
|
+
window.addEventListener("blur", handleWindowBlur);
|
|
826
|
+
return () => {
|
|
827
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
828
|
+
window.removeEventListener("keyup", handleKeyUp);
|
|
829
|
+
window.removeEventListener("wheel", handleWheel);
|
|
830
|
+
window.removeEventListener("mousedown", handleMouseDown);
|
|
831
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
832
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
833
|
+
window.removeEventListener("blur", handleWindowBlur);
|
|
834
|
+
};
|
|
835
|
+
}, [resolveActiveTarget]);
|
|
836
|
+
return /* @__PURE__ */ jsx(ShortcutContext.Provider, { value: activeShortcut, children });
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// src/icons.ts
|
|
840
|
+
var ICON_CHEVRON = "M6 9.5L12 15.5L18 9.5";
|
|
841
|
+
var ICON_CHECK = "M5 12.75L10 19L19 5";
|
|
842
|
+
var ICON_CLIPBOARD = {
|
|
843
|
+
board: "M8 6C8 4.34315 9.34315 3 11 3H13C14.6569 3 16 4.34315 16 6V7H8V6Z",
|
|
844
|
+
sparkle: "M19.2405 16.1852L18.5436 14.3733C18.4571 14.1484 18.241 14 18 14C17.759 14 17.5429 14.1484 17.4564 14.3733L16.7595 16.1852C16.658 16.4493 16.4493 16.658 16.1852 16.7595L14.3733 17.4564C14.1484 17.5429 14 17.759 14 18C14 18.241 14.1484 18.4571 14.3733 18.5436L16.1852 19.2405C16.4493 19.342 16.658 19.5507 16.7595 19.8148L17.4564 21.6267C17.5429 21.8516 17.759 22 18 22C18.241 22 18.4571 21.8516 18.5436 21.6267L19.2405 19.8148C19.342 19.5507 19.5507 19.342 19.8148 19.2405L21.6267 18.5436C21.8516 18.4571 22 18.241 22 18C22 17.759 21.8516 17.5429 21.6267 17.4564L19.8148 16.7595C19.5507 16.658 19.342 16.4493 19.2405 16.1852Z",
|
|
845
|
+
body: "M16 5H17C18.6569 5 20 6.34315 20 8V11M8 5H7C5.34315 5 4 6.34315 4 8V18C4 19.6569 5.34315 21 7 21H12"
|
|
846
|
+
};
|
|
847
|
+
var ICON_ADD_PRESET = [
|
|
848
|
+
"M4 6H20",
|
|
849
|
+
"M4 12H10",
|
|
850
|
+
"M15 15L21 15",
|
|
851
|
+
"M18 12V18",
|
|
852
|
+
"M4 18H10"
|
|
853
|
+
];
|
|
854
|
+
var ICON_TRASH = [
|
|
855
|
+
"M5 6.5L5.80734 18.2064C5.91582 19.7794 7.22348 21 8.80023 21H15.1998C16.7765 21 18.0842 19.7794 18.1927 18.2064L19 6.5",
|
|
856
|
+
"M10 11V16",
|
|
857
|
+
"M14 11V16",
|
|
858
|
+
"M3.5 6H20.5",
|
|
859
|
+
"M8.07092 5.74621C8.42348 3.89745 10.0485 2.5 12 2.5C13.9515 2.5 15.5765 3.89745 15.9291 5.74621"
|
|
860
|
+
];
|
|
861
|
+
var ICON_PANEL = {
|
|
862
|
+
path: "M6.84766 11.75C6.78583 11.9899 6.75 12.2408 6.75 12.5C6.75 12.7592 6.78583 13.0101 6.84766 13.25H2C1.58579 13.25 1.25 12.9142 1.25 12.5C1.25 12.0858 1.58579 11.75 2 11.75H6.84766ZM14 11.75C14.4142 11.75 14.75 12.0858 14.75 12.5C14.75 12.9142 14.4142 13.25 14 13.25H12.6523C12.7142 13.0101 12.75 12.7592 12.75 12.5C12.75 12.2408 12.7142 11.9899 12.6523 11.75H14ZM3.09766 7.25C3.03583 7.48994 3 7.74075 3 8C3 8.25925 3.03583 8.51006 3.09766 8.75H2C1.58579 8.75 1.25 8.41421 1.25 8C1.25 7.58579 1.58579 7.25 2 7.25H3.09766ZM14 7.25C14.4142 7.25 14.75 7.58579 14.75 8C14.75 8.41421 14.4142 8.75 14 8.75H8.90234C8.96417 8.51006 9 8.25925 9 8C9 7.74075 8.96417 7.48994 8.90234 7.25H14ZM7.59766 2.75C7.53583 2.98994 7.5 3.24075 7.5 3.5C7.5 3.75925 7.53583 4.01006 7.59766 4.25H2C1.58579 4.25 1.25 3.91421 1.25 3.5C1.25 3.08579 1.58579 2.75 2 2.75H7.59766ZM14 2.75C14.4142 2.75 14.75 3.08579 14.75 3.5C14.75 3.91421 14.4142 4.25 14 4.25H13.4023C13.4642 4.01006 13.5 3.75925 13.5 3.5C13.5 3.24075 13.4642 2.98994 13.4023 2.75H14Z",
|
|
863
|
+
circles: [
|
|
864
|
+
{ cx: "6", cy: "8", r: "0.998596" },
|
|
865
|
+
{ cx: "10.4999", cy: "3.5", r: "0.998657" },
|
|
866
|
+
{ cx: "9.75015", cy: "12.5", r: "0.997986" }
|
|
867
|
+
]
|
|
868
|
+
};
|
|
520
869
|
|
|
521
870
|
// src/components/Folder.tsx
|
|
522
|
-
import { useState, useRef as
|
|
871
|
+
import { useState as useState2, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
523
872
|
import { motion, AnimatePresence } from "motion/react";
|
|
524
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
525
|
-
function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenChange, toolbar }) {
|
|
526
|
-
const [isOpen, setIsOpen] =
|
|
527
|
-
const [isCollapsed, setIsCollapsed] =
|
|
528
|
-
const contentRef =
|
|
529
|
-
const [contentHeight, setContentHeight] =
|
|
530
|
-
|
|
873
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
874
|
+
function Folder({ title, children, defaultOpen = true, isRoot = false, inline = false, onOpenChange, toolbar }) {
|
|
875
|
+
const [isOpen, setIsOpen] = useState2(defaultOpen);
|
|
876
|
+
const [isCollapsed, setIsCollapsed] = useState2(!defaultOpen);
|
|
877
|
+
const contentRef = useRef3(null);
|
|
878
|
+
const [contentHeight, setContentHeight] = useState2(void 0);
|
|
879
|
+
const [windowHeight, setWindowHeight] = useState2(typeof window !== "undefined" ? window.innerHeight : 800);
|
|
880
|
+
useEffect3(() => {
|
|
881
|
+
if (!isRoot) return;
|
|
882
|
+
const onResize = () => setWindowHeight(window.innerHeight);
|
|
883
|
+
window.addEventListener("resize", onResize);
|
|
884
|
+
return () => window.removeEventListener("resize", onResize);
|
|
885
|
+
}, [isRoot]);
|
|
886
|
+
useEffect3(() => {
|
|
531
887
|
const el = contentRef.current;
|
|
532
888
|
if (!el) return;
|
|
533
889
|
const ro = new ResizeObserver(() => {
|
|
@@ -540,6 +896,7 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
540
896
|
return () => ro.disconnect();
|
|
541
897
|
}, [isOpen]);
|
|
542
898
|
const handleToggle = () => {
|
|
899
|
+
if (inline && isRoot) return;
|
|
543
900
|
const next = !isOpen;
|
|
544
901
|
setIsOpen(next);
|
|
545
902
|
if (next) {
|
|
@@ -552,46 +909,39 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
552
909
|
const folderContent = /* @__PURE__ */ jsxs("div", { ref: isRoot ? contentRef : void 0, className: `dialkit-folder ${isRoot ? "dialkit-folder-root" : ""}`, children: [
|
|
553
910
|
/* @__PURE__ */ jsxs("div", { className: `dialkit-folder-header ${isRoot ? "dialkit-panel-header" : ""}`, onClick: handleToggle, children: [
|
|
554
911
|
/* @__PURE__ */ jsxs("div", { className: "dialkit-folder-header-top", children: [
|
|
555
|
-
isRoot ? isOpen && /* @__PURE__ */
|
|
556
|
-
isRoot
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
"
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
fill: "
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
strokeLinejoin: "round",
|
|
584
|
-
initial: false,
|
|
585
|
-
animate: { rotate: isOpen ? 0 : 180 },
|
|
586
|
-
transition: { type: "spring", visualDuration: 0.35, bounce: 0.15 },
|
|
587
|
-
children: /* @__PURE__ */ jsx("path", { d: "M6 9.5L12 15.5L18 9.5" })
|
|
588
|
-
}
|
|
589
|
-
)
|
|
912
|
+
isRoot ? isOpen && /* @__PURE__ */ jsx2("div", { className: "dialkit-folder-title-row", children: /* @__PURE__ */ jsx2("span", { className: "dialkit-folder-title dialkit-folder-title-root", children: title }) }) : /* @__PURE__ */ jsx2("div", { className: "dialkit-folder-title-row", children: /* @__PURE__ */ jsx2("span", { className: "dialkit-folder-title", children: title }) }),
|
|
913
|
+
isRoot && !inline && /* @__PURE__ */ jsxs(
|
|
914
|
+
"svg",
|
|
915
|
+
{
|
|
916
|
+
className: "dialkit-panel-icon",
|
|
917
|
+
viewBox: "0 0 16 16",
|
|
918
|
+
fill: "none",
|
|
919
|
+
children: [
|
|
920
|
+
/* @__PURE__ */ jsx2("path", { opacity: "0.5", d: ICON_PANEL.path, fill: "currentColor" }),
|
|
921
|
+
ICON_PANEL.circles.map((c, i) => /* @__PURE__ */ jsx2("circle", { cx: c.cx, cy: c.cy, r: c.r, fill: "currentColor", stroke: "currentColor", strokeWidth: "1.25" }, i))
|
|
922
|
+
]
|
|
923
|
+
}
|
|
924
|
+
),
|
|
925
|
+
!isRoot && /* @__PURE__ */ jsx2(
|
|
926
|
+
motion.svg,
|
|
927
|
+
{
|
|
928
|
+
className: "dialkit-folder-icon",
|
|
929
|
+
viewBox: "0 0 24 24",
|
|
930
|
+
fill: "none",
|
|
931
|
+
stroke: "currentColor",
|
|
932
|
+
strokeWidth: "2.5",
|
|
933
|
+
strokeLinecap: "round",
|
|
934
|
+
strokeLinejoin: "round",
|
|
935
|
+
initial: false,
|
|
936
|
+
animate: { rotate: isOpen ? 0 : 180 },
|
|
937
|
+
transition: { type: "spring", visualDuration: 0.35, bounce: 0.15 },
|
|
938
|
+
children: /* @__PURE__ */ jsx2("path", { d: ICON_CHEVRON })
|
|
939
|
+
}
|
|
590
940
|
)
|
|
591
941
|
] }),
|
|
592
|
-
isRoot && toolbar && isOpen && /* @__PURE__ */
|
|
942
|
+
isRoot && toolbar && isOpen && /* @__PURE__ */ jsx2("div", { className: "dialkit-panel-toolbar", onClick: (e) => e.stopPropagation(), children: toolbar })
|
|
593
943
|
] }),
|
|
594
|
-
/* @__PURE__ */
|
|
944
|
+
/* @__PURE__ */ jsx2(AnimatePresence, { initial: false, children: isOpen && /* @__PURE__ */ jsx2(
|
|
595
945
|
motion.div,
|
|
596
946
|
{
|
|
597
947
|
className: "dialkit-folder-content",
|
|
@@ -600,13 +950,16 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
600
950
|
exit: isRoot ? void 0 : { height: 0, opacity: 0 },
|
|
601
951
|
transition: isRoot ? void 0 : { type: "spring", visualDuration: 0.35, bounce: 0.1 },
|
|
602
952
|
style: isRoot ? void 0 : { clipPath: "inset(0 -20px)" },
|
|
603
|
-
children: /* @__PURE__ */
|
|
953
|
+
children: /* @__PURE__ */ jsx2("div", { className: "dialkit-folder-inner", children })
|
|
604
954
|
}
|
|
605
955
|
) })
|
|
606
956
|
] });
|
|
607
957
|
if (isRoot) {
|
|
608
|
-
|
|
609
|
-
|
|
958
|
+
if (inline) {
|
|
959
|
+
return /* @__PURE__ */ jsx2("div", { className: "dialkit-panel-inner dialkit-panel-inline", children: folderContent });
|
|
960
|
+
}
|
|
961
|
+
const panelStyle = isOpen ? { width: 280, height: contentHeight !== void 0 ? Math.min(contentHeight + 10, windowHeight - 32) : "auto", borderRadius: 14, boxShadow: "var(--dial-shadow)", cursor: void 0, overflowY: "auto" } : { width: 42, height: 42, borderRadius: "50%", boxSizing: "border-box", boxShadow: "var(--dial-shadow-collapsed)", overflow: "hidden", cursor: "pointer" };
|
|
962
|
+
return /* @__PURE__ */ jsx2(
|
|
610
963
|
motion.div,
|
|
611
964
|
{
|
|
612
965
|
className: "dialkit-panel-inner",
|
|
@@ -623,30 +976,13 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
623
976
|
}
|
|
624
977
|
|
|
625
978
|
// src/components/Slider.tsx
|
|
626
|
-
import { useRef as
|
|
979
|
+
import { useRef as useRef4, useState as useState3, useCallback as useCallback2, useEffect as useEffect4 } from "react";
|
|
627
980
|
import { motion as motion2, useMotionValue, useTransform, animate } from "motion/react";
|
|
628
|
-
import { jsx as
|
|
981
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
629
982
|
var CLICK_THRESHOLD = 3;
|
|
630
983
|
var DEAD_ZONE = 32;
|
|
631
984
|
var MAX_CURSOR_RANGE = 200;
|
|
632
985
|
var MAX_STRETCH = 8;
|
|
633
|
-
function decimalsForStep(step) {
|
|
634
|
-
const s = step.toString();
|
|
635
|
-
const dot = s.indexOf(".");
|
|
636
|
-
return dot === -1 ? 0 : s.length - dot - 1;
|
|
637
|
-
}
|
|
638
|
-
function roundValue(val, step) {
|
|
639
|
-
const raw = Math.round(val / step) * step;
|
|
640
|
-
return parseFloat(raw.toFixed(decimalsForStep(step)));
|
|
641
|
-
}
|
|
642
|
-
function snapToDecile(rawValue, min, max) {
|
|
643
|
-
const normalized = (rawValue - min) / (max - min);
|
|
644
|
-
const nearest = Math.round(normalized * 10) / 10;
|
|
645
|
-
if (Math.abs(normalized - nearest) <= 0.03125) {
|
|
646
|
-
return min + nearest * (max - min);
|
|
647
|
-
}
|
|
648
|
-
return rawValue;
|
|
649
|
-
}
|
|
650
986
|
function Slider({
|
|
651
987
|
label,
|
|
652
988
|
value,
|
|
@@ -654,26 +990,28 @@ function Slider({
|
|
|
654
990
|
min = 0,
|
|
655
991
|
max = 1,
|
|
656
992
|
step = 0.01,
|
|
657
|
-
unit
|
|
993
|
+
unit,
|
|
994
|
+
shortcut,
|
|
995
|
+
shortcutActive
|
|
658
996
|
}) {
|
|
659
|
-
const wrapperRef =
|
|
660
|
-
const trackRef =
|
|
661
|
-
const inputRef =
|
|
662
|
-
const labelRef =
|
|
663
|
-
const valueSpanRef =
|
|
664
|
-
const [isInteracting, setIsInteracting] =
|
|
665
|
-
const [isDragging, setIsDragging] =
|
|
666
|
-
const [isHovered, setIsHovered] =
|
|
667
|
-
const [isValueHovered, setIsValueHovered] =
|
|
668
|
-
const [isValueEditable, setIsValueEditable] =
|
|
669
|
-
const [showInput, setShowInput] =
|
|
670
|
-
const [inputValue, setInputValue] =
|
|
671
|
-
const hoverTimeoutRef =
|
|
672
|
-
const pointerDownPos =
|
|
673
|
-
const isClickRef =
|
|
674
|
-
const animRef =
|
|
675
|
-
const wrapperRectRef =
|
|
676
|
-
const scaleRef =
|
|
997
|
+
const wrapperRef = useRef4(null);
|
|
998
|
+
const trackRef = useRef4(null);
|
|
999
|
+
const inputRef = useRef4(null);
|
|
1000
|
+
const labelRef = useRef4(null);
|
|
1001
|
+
const valueSpanRef = useRef4(null);
|
|
1002
|
+
const [isInteracting, setIsInteracting] = useState3(false);
|
|
1003
|
+
const [isDragging, setIsDragging] = useState3(false);
|
|
1004
|
+
const [isHovered, setIsHovered] = useState3(false);
|
|
1005
|
+
const [isValueHovered, setIsValueHovered] = useState3(false);
|
|
1006
|
+
const [isValueEditable, setIsValueEditable] = useState3(false);
|
|
1007
|
+
const [showInput, setShowInput] = useState3(false);
|
|
1008
|
+
const [inputValue, setInputValue] = useState3("");
|
|
1009
|
+
const hoverTimeoutRef = useRef4(null);
|
|
1010
|
+
const pointerDownPos = useRef4(null);
|
|
1011
|
+
const isClickRef = useRef4(true);
|
|
1012
|
+
const animRef = useRef4(null);
|
|
1013
|
+
const wrapperRectRef = useRef4(null);
|
|
1014
|
+
const scaleRef = useRef4(1);
|
|
677
1015
|
const percentage = (value - min) / (max - min) * 100;
|
|
678
1016
|
const isActive = isInteracting || isHovered;
|
|
679
1017
|
const fillPercent = useMotionValue(percentage);
|
|
@@ -691,12 +1029,12 @@ function Slider({
|
|
|
691
1029
|
rubberStretchPx,
|
|
692
1030
|
(stretch) => stretch < 0 ? stretch : 0
|
|
693
1031
|
);
|
|
694
|
-
|
|
1032
|
+
useEffect4(() => {
|
|
695
1033
|
if (!isInteracting && !animRef.current) {
|
|
696
1034
|
fillPercent.jump(percentage);
|
|
697
1035
|
}
|
|
698
1036
|
}, [percentage, isInteracting, fillPercent]);
|
|
699
|
-
const positionToValue =
|
|
1037
|
+
const positionToValue = useCallback2(
|
|
700
1038
|
(clientX) => {
|
|
701
1039
|
const rect = wrapperRectRef.current;
|
|
702
1040
|
if (!rect) return value;
|
|
@@ -709,11 +1047,11 @@ function Slider({
|
|
|
709
1047
|
},
|
|
710
1048
|
[min, max, value]
|
|
711
1049
|
);
|
|
712
|
-
const percentFromValue =
|
|
1050
|
+
const percentFromValue = useCallback2(
|
|
713
1051
|
(v) => (v - min) / (max - min) * 100,
|
|
714
1052
|
[min, max]
|
|
715
1053
|
);
|
|
716
|
-
const computeRubberStretch =
|
|
1054
|
+
const computeRubberStretch = useCallback2(
|
|
717
1055
|
(clientX, sign) => {
|
|
718
1056
|
const rect = wrapperRectRef.current;
|
|
719
1057
|
if (!rect) return 0;
|
|
@@ -723,7 +1061,7 @@ function Slider({
|
|
|
723
1061
|
},
|
|
724
1062
|
[]
|
|
725
1063
|
);
|
|
726
|
-
const handlePointerDown =
|
|
1064
|
+
const handlePointerDown = useCallback2(
|
|
727
1065
|
(e) => {
|
|
728
1066
|
if (showInput) return;
|
|
729
1067
|
e.preventDefault();
|
|
@@ -739,7 +1077,7 @@ function Slider({
|
|
|
739
1077
|
},
|
|
740
1078
|
[showInput]
|
|
741
1079
|
);
|
|
742
|
-
const handlePointerMove =
|
|
1080
|
+
const handlePointerMove = useCallback2(
|
|
743
1081
|
(e) => {
|
|
744
1082
|
if (!isInteracting || !pointerDownPos.current) return;
|
|
745
1083
|
const dx = e.clientX - pointerDownPos.current.x;
|
|
@@ -780,7 +1118,7 @@ function Slider({
|
|
|
780
1118
|
computeRubberStretch
|
|
781
1119
|
]
|
|
782
1120
|
);
|
|
783
|
-
const handlePointerUp =
|
|
1121
|
+
const handlePointerUp = useCallback2(
|
|
784
1122
|
(e) => {
|
|
785
1123
|
if (!isInteracting) return;
|
|
786
1124
|
if (isClickRef.current) {
|
|
@@ -824,7 +1162,7 @@ function Slider({
|
|
|
824
1162
|
rubberStretchPx
|
|
825
1163
|
]
|
|
826
1164
|
);
|
|
827
|
-
|
|
1165
|
+
useEffect4(() => {
|
|
828
1166
|
if (isValueHovered && !showInput && !isValueEditable) {
|
|
829
1167
|
hoverTimeoutRef.current = setTimeout(() => {
|
|
830
1168
|
setIsValueEditable(true);
|
|
@@ -842,7 +1180,7 @@ function Slider({
|
|
|
842
1180
|
}
|
|
843
1181
|
};
|
|
844
1182
|
}, [isValueHovered, showInput, isValueEditable]);
|
|
845
|
-
|
|
1183
|
+
useEffect4(() => {
|
|
846
1184
|
if (showInput && inputRef.current) {
|
|
847
1185
|
inputRef.current.focus();
|
|
848
1186
|
inputRef.current.select();
|
|
@@ -897,11 +1235,10 @@ function Slider({
|
|
|
897
1235
|
}
|
|
898
1236
|
const valueDodge = percentage < leftThreshold || percentage > rightThreshold;
|
|
899
1237
|
const handleOpacity = !isActive ? 0 : valueDodge ? 0.1 : isDragging ? 0.9 : 0.5;
|
|
900
|
-
const fillBackground = isActive ? "rgba(255, 255, 255, 0.15)" : "rgba(255, 255, 255, 0.11)";
|
|
901
1238
|
const discreteSteps = (max - min) / step;
|
|
902
1239
|
const hashMarks = discreteSteps <= 10 ? Array.from({ length: discreteSteps - 1 }, (_, i) => {
|
|
903
1240
|
const pct = (i + 1) * step / (max - min) * 100;
|
|
904
|
-
return /* @__PURE__ */
|
|
1241
|
+
return /* @__PURE__ */ jsx3(
|
|
905
1242
|
"div",
|
|
906
1243
|
{
|
|
907
1244
|
className: "dialkit-slider-hashmark",
|
|
@@ -911,7 +1248,7 @@ function Slider({
|
|
|
911
1248
|
);
|
|
912
1249
|
}) : Array.from({ length: 9 }, (_, i) => {
|
|
913
1250
|
const pct = (i + 1) * 10;
|
|
914
|
-
return /* @__PURE__ */
|
|
1251
|
+
return /* @__PURE__ */ jsx3(
|
|
915
1252
|
"div",
|
|
916
1253
|
{
|
|
917
1254
|
className: "dialkit-slider-hashmark",
|
|
@@ -920,7 +1257,7 @@ function Slider({
|
|
|
920
1257
|
i
|
|
921
1258
|
);
|
|
922
1259
|
});
|
|
923
|
-
return /* @__PURE__ */
|
|
1260
|
+
return /* @__PURE__ */ jsx3("div", { ref: wrapperRef, className: "dialkit-slider-wrapper", children: /* @__PURE__ */ jsxs2(
|
|
924
1261
|
motion2.div,
|
|
925
1262
|
{
|
|
926
1263
|
ref: trackRef,
|
|
@@ -932,26 +1269,23 @@ function Slider({
|
|
|
932
1269
|
onMouseLeave: () => setIsHovered(false),
|
|
933
1270
|
style: { width: rubberBandWidth, x: rubberBandX },
|
|
934
1271
|
children: [
|
|
935
|
-
/* @__PURE__ */
|
|
936
|
-
/* @__PURE__ */
|
|
1272
|
+
/* @__PURE__ */ jsx3("div", { className: "dialkit-slider-hashmarks", children: hashMarks }),
|
|
1273
|
+
/* @__PURE__ */ jsx3(
|
|
937
1274
|
motion2.div,
|
|
938
1275
|
{
|
|
939
1276
|
className: "dialkit-slider-fill",
|
|
940
1277
|
style: {
|
|
941
|
-
|
|
942
|
-
width: fillWidth,
|
|
943
|
-
transition: "background 0.15s"
|
|
1278
|
+
width: fillWidth
|
|
944
1279
|
}
|
|
945
1280
|
}
|
|
946
1281
|
),
|
|
947
|
-
/* @__PURE__ */
|
|
1282
|
+
/* @__PURE__ */ jsx3(
|
|
948
1283
|
motion2.div,
|
|
949
1284
|
{
|
|
950
1285
|
className: "dialkit-slider-handle",
|
|
951
1286
|
style: {
|
|
952
1287
|
left: handleLeft,
|
|
953
|
-
y: "-50%"
|
|
954
|
-
background: "rgba(255, 255, 255, 0.9)"
|
|
1288
|
+
y: "-50%"
|
|
955
1289
|
},
|
|
956
1290
|
animate: {
|
|
957
1291
|
opacity: handleOpacity,
|
|
@@ -965,8 +1299,11 @@ function Slider({
|
|
|
965
1299
|
}
|
|
966
1300
|
}
|
|
967
1301
|
),
|
|
968
|
-
/* @__PURE__ */
|
|
969
|
-
|
|
1302
|
+
/* @__PURE__ */ jsxs2("span", { ref: labelRef, className: "dialkit-slider-label", children: [
|
|
1303
|
+
label,
|
|
1304
|
+
shortcut && /* @__PURE__ */ jsx3("span", { className: `dialkit-shortcut-pill${shortcutActive ? " dialkit-shortcut-pill-active" : ""}`, children: formatSliderShortcut(shortcut) })
|
|
1305
|
+
] }),
|
|
1306
|
+
showInput ? /* @__PURE__ */ jsx3(
|
|
970
1307
|
"input",
|
|
971
1308
|
{
|
|
972
1309
|
ref: inputRef,
|
|
@@ -979,7 +1316,7 @@ function Slider({
|
|
|
979
1316
|
onClick: (e) => e.stopPropagation(),
|
|
980
1317
|
onMouseDown: (e) => e.stopPropagation()
|
|
981
1318
|
}
|
|
982
|
-
) : /* @__PURE__ */
|
|
1319
|
+
) : /* @__PURE__ */ jsx3(
|
|
983
1320
|
"span",
|
|
984
1321
|
{
|
|
985
1322
|
ref: valueSpanRef,
|
|
@@ -998,51 +1335,48 @@ function Slider({
|
|
|
998
1335
|
}
|
|
999
1336
|
|
|
1000
1337
|
// src/components/SegmentedControl.tsx
|
|
1001
|
-
import { useRef as
|
|
1002
|
-
import {
|
|
1003
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1338
|
+
import { useRef as useRef5, useState as useState4, useLayoutEffect, useCallback as useCallback3 } from "react";
|
|
1339
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1004
1340
|
function SegmentedControl({
|
|
1005
1341
|
options,
|
|
1006
1342
|
value,
|
|
1007
1343
|
onChange
|
|
1008
1344
|
}) {
|
|
1009
|
-
const containerRef =
|
|
1010
|
-
const
|
|
1011
|
-
const [pillStyle, setPillStyle] =
|
|
1012
|
-
const
|
|
1013
|
-
useLayoutEffect(() => {
|
|
1014
|
-
const button = buttonRefs.current.get(value);
|
|
1345
|
+
const containerRef = useRef5(null);
|
|
1346
|
+
const hasAnimated = useRef5(false);
|
|
1347
|
+
const [pillStyle, setPillStyle] = useState4(null);
|
|
1348
|
+
const measure = useCallback3(() => {
|
|
1015
1349
|
const container = containerRef.current;
|
|
1016
|
-
if (
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1350
|
+
if (!container) return;
|
|
1351
|
+
const activeButton = container.querySelector('[data-active="true"]');
|
|
1352
|
+
if (!activeButton) return;
|
|
1353
|
+
setPillStyle({
|
|
1354
|
+
left: activeButton.offsetLeft,
|
|
1355
|
+
width: activeButton.offsetWidth
|
|
1356
|
+
});
|
|
1357
|
+
}, []);
|
|
1358
|
+
useLayoutEffect(() => {
|
|
1359
|
+
measure();
|
|
1360
|
+
}, [value, options.length, measure]);
|
|
1361
|
+
const shouldAnimate = hasAnimated.current;
|
|
1362
|
+
hasAnimated.current = true;
|
|
1363
|
+
return /* @__PURE__ */ jsxs3("div", { className: "dialkit-segmented", ref: containerRef, children: [
|
|
1364
|
+
pillStyle && /* @__PURE__ */ jsx4(
|
|
1365
|
+
"div",
|
|
1028
1366
|
{
|
|
1029
1367
|
className: "dialkit-segmented-pill",
|
|
1030
|
-
style: {
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
hasAnimated.current = true;
|
|
1368
|
+
style: {
|
|
1369
|
+
left: pillStyle.left,
|
|
1370
|
+
width: pillStyle.width,
|
|
1371
|
+
transition: shouldAnimate ? "left 0.2s cubic-bezier(0.25, 1, 0.5, 1), width 0.2s cubic-bezier(0.25, 1, 0.5, 1)" : "none"
|
|
1035
1372
|
}
|
|
1036
1373
|
}
|
|
1037
1374
|
),
|
|
1038
1375
|
options.map((option) => {
|
|
1039
1376
|
const isActive = value === option.value;
|
|
1040
|
-
return /* @__PURE__ */
|
|
1377
|
+
return /* @__PURE__ */ jsx4(
|
|
1041
1378
|
"button",
|
|
1042
1379
|
{
|
|
1043
|
-
ref: (el) => {
|
|
1044
|
-
if (el) buttonRefs.current.set(option.value, el);
|
|
1045
|
-
},
|
|
1046
1380
|
onClick: () => onChange(option.value),
|
|
1047
1381
|
className: "dialkit-segmented-button",
|
|
1048
1382
|
"data-active": String(isActive),
|
|
@@ -1055,11 +1389,14 @@ function SegmentedControl({
|
|
|
1055
1389
|
}
|
|
1056
1390
|
|
|
1057
1391
|
// src/components/Toggle.tsx
|
|
1058
|
-
import { jsx as
|
|
1059
|
-
function Toggle({ label, checked, onChange }) {
|
|
1392
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1393
|
+
function Toggle({ label, checked, onChange, shortcut, shortcutActive }) {
|
|
1060
1394
|
return /* @__PURE__ */ jsxs4("div", { className: "dialkit-labeled-control", children: [
|
|
1061
|
-
/* @__PURE__ */
|
|
1062
|
-
|
|
1395
|
+
/* @__PURE__ */ jsxs4("span", { className: "dialkit-labeled-control-label", children: [
|
|
1396
|
+
label,
|
|
1397
|
+
shortcut && /* @__PURE__ */ jsx5("span", { className: `dialkit-shortcut-pill${shortcutActive ? " dialkit-shortcut-pill-active" : ""}`, children: formatToggleShortcut(shortcut) })
|
|
1398
|
+
] }),
|
|
1399
|
+
/* @__PURE__ */ jsx5(
|
|
1063
1400
|
SegmentedControl,
|
|
1064
1401
|
{
|
|
1065
1402
|
options: [
|
|
@@ -1074,7 +1411,7 @@ function Toggle({ label, checked, onChange }) {
|
|
|
1074
1411
|
}
|
|
1075
1412
|
|
|
1076
1413
|
// src/components/SpringVisualization.tsx
|
|
1077
|
-
import { jsx as
|
|
1414
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1078
1415
|
function generateSpringCurve(stiffness, damping, mass, duration) {
|
|
1079
1416
|
const points = [];
|
|
1080
1417
|
const steps = 100;
|
|
@@ -1129,13 +1466,13 @@ function SpringVisualization({ spring, isSimpleMode }) {
|
|
|
1129
1466
|
const x = width / 4 * i;
|
|
1130
1467
|
const y = height / 4 * i;
|
|
1131
1468
|
gridLines.push(
|
|
1132
|
-
/* @__PURE__ */
|
|
1133
|
-
/* @__PURE__ */
|
|
1469
|
+
/* @__PURE__ */ jsx6("line", { x1: x, y1: 0, x2: x, y2: height, stroke: "rgba(255, 255, 255, 0.08)", strokeWidth: "1" }, `v-${i}`),
|
|
1470
|
+
/* @__PURE__ */ jsx6("line", { x1: 0, y1: y, x2: width, y2: y, stroke: "rgba(255, 255, 255, 0.08)", strokeWidth: "1" }, `h-${i}`)
|
|
1134
1471
|
);
|
|
1135
1472
|
}
|
|
1136
1473
|
return /* @__PURE__ */ jsxs5("svg", { viewBox: `0 0 ${width} ${height}`, className: "dialkit-spring-viz", children: [
|
|
1137
1474
|
gridLines,
|
|
1138
|
-
/* @__PURE__ */
|
|
1475
|
+
/* @__PURE__ */ jsx6(
|
|
1139
1476
|
"line",
|
|
1140
1477
|
{
|
|
1141
1478
|
x1: 0,
|
|
@@ -1147,7 +1484,7 @@ function SpringVisualization({ spring, isSimpleMode }) {
|
|
|
1147
1484
|
strokeDasharray: "4,4"
|
|
1148
1485
|
}
|
|
1149
1486
|
),
|
|
1150
|
-
/* @__PURE__ */
|
|
1487
|
+
/* @__PURE__ */ jsx6(
|
|
1151
1488
|
"path",
|
|
1152
1489
|
{
|
|
1153
1490
|
d: pathData,
|
|
@@ -1162,8 +1499,8 @@ function SpringVisualization({ spring, isSimpleMode }) {
|
|
|
1162
1499
|
}
|
|
1163
1500
|
|
|
1164
1501
|
// src/components/SpringControl.tsx
|
|
1165
|
-
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
1166
|
-
import { Fragment, jsx as
|
|
1502
|
+
import { useSyncExternalStore as useSyncExternalStore2, useRef as useRef6 } from "react";
|
|
1503
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1167
1504
|
function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
1168
1505
|
const mode = useSyncExternalStore2(
|
|
1169
1506
|
(cb) => DialStore.subscribe(panelId, cb),
|
|
@@ -1171,25 +1508,21 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1171
1508
|
() => DialStore.getSpringMode(panelId, path)
|
|
1172
1509
|
);
|
|
1173
1510
|
const isSimpleMode = mode === "simple";
|
|
1511
|
+
const cache = useRef6({
|
|
1512
|
+
simple: spring.visualDuration !== void 0 ? spring : { type: "spring", visualDuration: 0.3, bounce: 0.2 },
|
|
1513
|
+
advanced: spring.stiffness !== void 0 ? spring : { type: "spring", stiffness: 200, damping: 25, mass: 1 }
|
|
1514
|
+
});
|
|
1515
|
+
if (isSimpleMode) {
|
|
1516
|
+
cache.current.simple = spring;
|
|
1517
|
+
} else {
|
|
1518
|
+
cache.current.advanced = spring;
|
|
1519
|
+
}
|
|
1174
1520
|
const handleModeChange = (newMode) => {
|
|
1175
1521
|
DialStore.updateSpringMode(panelId, path, newMode);
|
|
1176
1522
|
if (newMode === "simple") {
|
|
1177
|
-
|
|
1178
|
-
onChange({
|
|
1179
|
-
...rest,
|
|
1180
|
-
type: "spring",
|
|
1181
|
-
visualDuration: spring.visualDuration ?? 0.3,
|
|
1182
|
-
bounce: spring.bounce ?? 0.2
|
|
1183
|
-
});
|
|
1523
|
+
onChange(cache.current.simple);
|
|
1184
1524
|
} else {
|
|
1185
|
-
|
|
1186
|
-
onChange({
|
|
1187
|
-
...rest,
|
|
1188
|
-
type: "spring",
|
|
1189
|
-
stiffness: spring.stiffness ?? 200,
|
|
1190
|
-
damping: spring.damping ?? 25,
|
|
1191
|
-
mass: spring.mass ?? 1
|
|
1192
|
-
});
|
|
1525
|
+
onChange(cache.current.advanced);
|
|
1193
1526
|
}
|
|
1194
1527
|
};
|
|
1195
1528
|
const handleUpdate = (key, value) => {
|
|
@@ -1201,11 +1534,11 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1201
1534
|
onChange({ ...rest, [key]: value });
|
|
1202
1535
|
}
|
|
1203
1536
|
};
|
|
1204
|
-
return /* @__PURE__ */
|
|
1205
|
-
/* @__PURE__ */
|
|
1537
|
+
return /* @__PURE__ */ jsx7(Folder, { title: label, defaultOpen: true, children: /* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
1538
|
+
/* @__PURE__ */ jsx7(SpringVisualization, { spring, isSimpleMode }),
|
|
1206
1539
|
/* @__PURE__ */ jsxs6("div", { className: "dialkit-labeled-control", children: [
|
|
1207
|
-
/* @__PURE__ */
|
|
1208
|
-
/* @__PURE__ */
|
|
1540
|
+
/* @__PURE__ */ jsx7("span", { className: "dialkit-labeled-control-label", children: "Type" }),
|
|
1541
|
+
/* @__PURE__ */ jsx7(
|
|
1209
1542
|
SegmentedControl,
|
|
1210
1543
|
{
|
|
1211
1544
|
options: [
|
|
@@ -1218,7 +1551,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1218
1551
|
)
|
|
1219
1552
|
] }),
|
|
1220
1553
|
isSimpleMode ? /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
1221
|
-
/* @__PURE__ */
|
|
1554
|
+
/* @__PURE__ */ jsx7(
|
|
1222
1555
|
Slider,
|
|
1223
1556
|
{
|
|
1224
1557
|
label: "Duration",
|
|
@@ -1230,7 +1563,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1230
1563
|
unit: "s"
|
|
1231
1564
|
}
|
|
1232
1565
|
),
|
|
1233
|
-
/* @__PURE__ */
|
|
1566
|
+
/* @__PURE__ */ jsx7(
|
|
1234
1567
|
Slider,
|
|
1235
1568
|
{
|
|
1236
1569
|
label: "Bounce",
|
|
@@ -1242,7 +1575,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1242
1575
|
}
|
|
1243
1576
|
)
|
|
1244
1577
|
] }) : /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
1245
|
-
/* @__PURE__ */
|
|
1578
|
+
/* @__PURE__ */ jsx7(
|
|
1246
1579
|
Slider,
|
|
1247
1580
|
{
|
|
1248
1581
|
label: "Stiffness",
|
|
@@ -1253,7 +1586,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1253
1586
|
step: 10
|
|
1254
1587
|
}
|
|
1255
1588
|
),
|
|
1256
|
-
/* @__PURE__ */
|
|
1589
|
+
/* @__PURE__ */ jsx7(
|
|
1257
1590
|
Slider,
|
|
1258
1591
|
{
|
|
1259
1592
|
label: "Damping",
|
|
@@ -1264,7 +1597,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1264
1597
|
step: 1
|
|
1265
1598
|
}
|
|
1266
1599
|
),
|
|
1267
|
-
/* @__PURE__ */
|
|
1600
|
+
/* @__PURE__ */ jsx7(
|
|
1268
1601
|
Slider,
|
|
1269
1602
|
{
|
|
1270
1603
|
label: "Mass",
|
|
@@ -1280,7 +1613,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1280
1613
|
}
|
|
1281
1614
|
|
|
1282
1615
|
// src/components/EasingVisualization.tsx
|
|
1283
|
-
import { jsx as
|
|
1616
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1284
1617
|
function EasingVisualization({ easing }) {
|
|
1285
1618
|
const ease = easing.ease;
|
|
1286
1619
|
const s = 200;
|
|
@@ -1303,7 +1636,7 @@ function EasingVisualization({ easing }) {
|
|
|
1303
1636
|
preserveAspectRatio: "xMidYMid slice",
|
|
1304
1637
|
className: "dialkit-spring-viz dialkit-easing-viz",
|
|
1305
1638
|
children: [
|
|
1306
|
-
/* @__PURE__ */
|
|
1639
|
+
/* @__PURE__ */ jsx8(
|
|
1307
1640
|
"line",
|
|
1308
1641
|
{
|
|
1309
1642
|
x1: start.x,
|
|
@@ -1315,15 +1648,15 @@ function EasingVisualization({ easing }) {
|
|
|
1315
1648
|
strokeDasharray: "4,4"
|
|
1316
1649
|
}
|
|
1317
1650
|
),
|
|
1318
|
-
/* @__PURE__ */
|
|
1651
|
+
/* @__PURE__ */ jsx8("path", { d: curvePath, fill: "none", stroke: "rgba(255, 255, 255, 0.6)", strokeWidth: "2", strokeLinecap: "round" })
|
|
1319
1652
|
]
|
|
1320
1653
|
}
|
|
1321
1654
|
);
|
|
1322
1655
|
}
|
|
1323
1656
|
|
|
1324
1657
|
// src/components/TransitionControl.tsx
|
|
1325
|
-
import { useSyncExternalStore as useSyncExternalStore3, useState as
|
|
1326
|
-
import { Fragment as Fragment2, jsx as
|
|
1658
|
+
import { useSyncExternalStore as useSyncExternalStore3, useRef as useRef7, useState as useState5 } from "react";
|
|
1659
|
+
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1327
1660
|
function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
1328
1661
|
const mode = useSyncExternalStore3(
|
|
1329
1662
|
(cb) => DialStore.subscribe(panelId, cb),
|
|
@@ -1332,26 +1665,28 @@ function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
|
1332
1665
|
);
|
|
1333
1666
|
const isEasing = mode === "easing";
|
|
1334
1667
|
const isSimpleSpring = mode === "simple";
|
|
1335
|
-
const
|
|
1336
|
-
|
|
1668
|
+
const cache = useRef7({
|
|
1669
|
+
easing: value.type === "easing" ? value : { type: "easing", duration: 0.3, ease: [1, -0.4, 0.5, 1] },
|
|
1670
|
+
simple: value.type === "spring" && value.visualDuration !== void 0 ? value : { type: "spring", visualDuration: 0.3, bounce: 0.2 },
|
|
1671
|
+
advanced: value.type === "spring" && value.stiffness !== void 0 ? value : { type: "spring", stiffness: 200, damping: 25, mass: 1 }
|
|
1672
|
+
});
|
|
1673
|
+
if (isEasing && value.type === "easing") {
|
|
1674
|
+
cache.current.easing = value;
|
|
1675
|
+
} else if (isSimpleSpring && value.type === "spring") {
|
|
1676
|
+
cache.current.simple = value;
|
|
1677
|
+
} else if (mode === "advanced" && value.type === "spring") {
|
|
1678
|
+
cache.current.advanced = value;
|
|
1679
|
+
}
|
|
1680
|
+
const spring = value.type === "spring" ? value : cache.current.simple;
|
|
1681
|
+
const easing = value.type === "easing" ? value : cache.current.easing;
|
|
1337
1682
|
const handleModeChange = (newMode) => {
|
|
1338
1683
|
DialStore.updateTransitionMode(panelId, path, newMode);
|
|
1339
1684
|
if (newMode === "easing") {
|
|
1340
|
-
|
|
1341
|
-
onChange({ type: "easing", duration, ease: easing.ease });
|
|
1685
|
+
onChange(cache.current.easing);
|
|
1342
1686
|
} else if (newMode === "simple") {
|
|
1343
|
-
onChange(
|
|
1344
|
-
type: "spring",
|
|
1345
|
-
visualDuration: spring.visualDuration ?? (value.type === "easing" ? value.duration : 0.3),
|
|
1346
|
-
bounce: spring.bounce ?? 0.2
|
|
1347
|
-
});
|
|
1687
|
+
onChange(cache.current.simple);
|
|
1348
1688
|
} else {
|
|
1349
|
-
onChange(
|
|
1350
|
-
type: "spring",
|
|
1351
|
-
stiffness: spring.stiffness ?? 200,
|
|
1352
|
-
damping: spring.damping ?? 25,
|
|
1353
|
-
mass: spring.mass ?? 1
|
|
1354
|
-
});
|
|
1689
|
+
onChange(cache.current.advanced);
|
|
1355
1690
|
}
|
|
1356
1691
|
};
|
|
1357
1692
|
const handleSpringUpdate = (key, val) => {
|
|
@@ -1368,11 +1703,11 @@ function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
|
1368
1703
|
newEase[index] = val;
|
|
1369
1704
|
onChange({ ...easing, ease: newEase });
|
|
1370
1705
|
};
|
|
1371
|
-
return /* @__PURE__ */
|
|
1372
|
-
isEasing ? /* @__PURE__ */
|
|
1706
|
+
return /* @__PURE__ */ jsx9(Folder, { title: label, defaultOpen: true, children: /* @__PURE__ */ jsxs8("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
1707
|
+
isEasing ? /* @__PURE__ */ jsx9(EasingVisualization, { easing }) : /* @__PURE__ */ jsx9(SpringVisualization, { spring, isSimpleMode: isSimpleSpring }),
|
|
1373
1708
|
/* @__PURE__ */ jsxs8("div", { className: "dialkit-labeled-control", children: [
|
|
1374
|
-
/* @__PURE__ */
|
|
1375
|
-
/* @__PURE__ */
|
|
1709
|
+
/* @__PURE__ */ jsx9("span", { className: "dialkit-labeled-control-label", children: "Type" }),
|
|
1710
|
+
/* @__PURE__ */ jsx9(
|
|
1376
1711
|
SegmentedControl,
|
|
1377
1712
|
{
|
|
1378
1713
|
options: [
|
|
@@ -1386,19 +1721,19 @@ function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
|
1386
1721
|
)
|
|
1387
1722
|
] }),
|
|
1388
1723
|
isEasing ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
1389
|
-
/* @__PURE__ */
|
|
1390
|
-
/* @__PURE__ */
|
|
1391
|
-
/* @__PURE__ */
|
|
1392
|
-
/* @__PURE__ */
|
|
1393
|
-
/* @__PURE__ */
|
|
1394
|
-
/* @__PURE__ */
|
|
1724
|
+
/* @__PURE__ */ jsx9(Slider, { label: "x1", value: easing.ease[0], onChange: (v) => updateEase(0, v), min: 0, max: 1, step: 0.01 }),
|
|
1725
|
+
/* @__PURE__ */ jsx9(Slider, { label: "y1", value: easing.ease[1], onChange: (v) => updateEase(1, v), min: -1, max: 2, step: 0.01 }),
|
|
1726
|
+
/* @__PURE__ */ jsx9(Slider, { label: "x2", value: easing.ease[2], onChange: (v) => updateEase(2, v), min: 0, max: 1, step: 0.01 }),
|
|
1727
|
+
/* @__PURE__ */ jsx9(Slider, { label: "y2", value: easing.ease[3], onChange: (v) => updateEase(3, v), min: -1, max: 2, step: 0.01 }),
|
|
1728
|
+
/* @__PURE__ */ jsx9(Slider, { label: "Duration", value: easing.duration, onChange: (v) => onChange({ ...easing, duration: v }), min: 0.1, max: 2, step: 0.05, unit: "s" }),
|
|
1729
|
+
/* @__PURE__ */ jsx9(EaseTextInput, { ease: easing.ease, onChange: (newEase) => onChange({ ...easing, ease: newEase }) })
|
|
1395
1730
|
] }) : isSimpleSpring ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
1396
|
-
/* @__PURE__ */
|
|
1397
|
-
/* @__PURE__ */
|
|
1731
|
+
/* @__PURE__ */ jsx9(Slider, { label: "Duration", value: spring.visualDuration ?? 0.3, onChange: (v) => handleSpringUpdate("visualDuration", v), min: 0.1, max: 1, step: 0.05, unit: "s" }),
|
|
1732
|
+
/* @__PURE__ */ jsx9(Slider, { label: "Bounce", value: spring.bounce ?? 0.2, onChange: (v) => handleSpringUpdate("bounce", v), min: 0, max: 1, step: 0.05 })
|
|
1398
1733
|
] }) : /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
1399
|
-
/* @__PURE__ */
|
|
1400
|
-
/* @__PURE__ */
|
|
1401
|
-
/* @__PURE__ */
|
|
1734
|
+
/* @__PURE__ */ jsx9(Slider, { label: "Stiffness", value: spring.stiffness ?? 400, onChange: (v) => handleSpringUpdate("stiffness", v), min: 1, max: 1e3, step: 10 }),
|
|
1735
|
+
/* @__PURE__ */ jsx9(Slider, { label: "Damping", value: spring.damping ?? 17, onChange: (v) => handleSpringUpdate("damping", v), min: 1, max: 100, step: 1 }),
|
|
1736
|
+
/* @__PURE__ */ jsx9(Slider, { label: "Mass", value: spring.mass ?? 1, onChange: (v) => handleSpringUpdate("mass", v), min: 0.1, max: 10, step: 0.1 })
|
|
1402
1737
|
] })
|
|
1403
1738
|
] }) });
|
|
1404
1739
|
}
|
|
@@ -1413,8 +1748,8 @@ function parseEase(str) {
|
|
|
1413
1748
|
return null;
|
|
1414
1749
|
}
|
|
1415
1750
|
function EaseTextInput({ ease, onChange }) {
|
|
1416
|
-
const [editing, setEditing] =
|
|
1417
|
-
const [draft, setDraft] =
|
|
1751
|
+
const [editing, setEditing] = useState5(false);
|
|
1752
|
+
const [draft, setDraft] = useState5("");
|
|
1418
1753
|
const handleFocus = () => {
|
|
1419
1754
|
setDraft(formatEase(ease));
|
|
1420
1755
|
setEditing(true);
|
|
@@ -1430,8 +1765,8 @@ function EaseTextInput({ ease, onChange }) {
|
|
|
1430
1765
|
}
|
|
1431
1766
|
};
|
|
1432
1767
|
return /* @__PURE__ */ jsxs8("div", { className: "dialkit-labeled-control", children: [
|
|
1433
|
-
/* @__PURE__ */
|
|
1434
|
-
/* @__PURE__ */
|
|
1768
|
+
/* @__PURE__ */ jsx9("span", { className: "dialkit-labeled-control-label", children: "Ease" }),
|
|
1769
|
+
/* @__PURE__ */ jsx9(
|
|
1435
1770
|
"input",
|
|
1436
1771
|
{
|
|
1437
1772
|
type: "text",
|
|
@@ -1448,11 +1783,11 @@ function EaseTextInput({ ease, onChange }) {
|
|
|
1448
1783
|
}
|
|
1449
1784
|
|
|
1450
1785
|
// src/components/TextControl.tsx
|
|
1451
|
-
import { jsx as
|
|
1786
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1452
1787
|
function TextControl({ label, value, onChange, placeholder }) {
|
|
1453
1788
|
return /* @__PURE__ */ jsxs9("div", { className: "dialkit-text-control", children: [
|
|
1454
|
-
/* @__PURE__ */
|
|
1455
|
-
/* @__PURE__ */
|
|
1789
|
+
/* @__PURE__ */ jsx10("label", { className: "dialkit-text-label", children: label }),
|
|
1790
|
+
/* @__PURE__ */ jsx10(
|
|
1456
1791
|
"input",
|
|
1457
1792
|
{
|
|
1458
1793
|
type: "text",
|
|
@@ -1466,10 +1801,10 @@ function TextControl({ label, value, onChange, placeholder }) {
|
|
|
1466
1801
|
}
|
|
1467
1802
|
|
|
1468
1803
|
// src/components/SelectControl.tsx
|
|
1469
|
-
import { useState as
|
|
1804
|
+
import { useState as useState6, useRef as useRef8, useEffect as useEffect5, useCallback as useCallback4 } from "react";
|
|
1470
1805
|
import { createPortal } from "react-dom";
|
|
1471
|
-
import { motion as
|
|
1472
|
-
import { jsx as
|
|
1806
|
+
import { motion as motion3, AnimatePresence as AnimatePresence2 } from "motion/react";
|
|
1807
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1473
1808
|
function toTitleCase(s) {
|
|
1474
1809
|
return s.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
1475
1810
|
}
|
|
@@ -1479,14 +1814,14 @@ function normalizeOptions(options) {
|
|
|
1479
1814
|
);
|
|
1480
1815
|
}
|
|
1481
1816
|
function SelectControl({ label, value, options, onChange }) {
|
|
1482
|
-
const [isOpen, setIsOpen] =
|
|
1483
|
-
const triggerRef =
|
|
1484
|
-
const dropdownRef =
|
|
1485
|
-
const [portalTarget, setPortalTarget] =
|
|
1486
|
-
const [pos, setPos] =
|
|
1817
|
+
const [isOpen, setIsOpen] = useState6(false);
|
|
1818
|
+
const triggerRef = useRef8(null);
|
|
1819
|
+
const dropdownRef = useRef8(null);
|
|
1820
|
+
const [portalTarget, setPortalTarget] = useState6(null);
|
|
1821
|
+
const [pos, setPos] = useState6(null);
|
|
1487
1822
|
const normalized = normalizeOptions(options);
|
|
1488
1823
|
const selectedOption = normalized.find((o) => o.value === value);
|
|
1489
|
-
const updatePos =
|
|
1824
|
+
const updatePos = useCallback4(() => {
|
|
1490
1825
|
const el = triggerRef.current;
|
|
1491
1826
|
if (!el) return;
|
|
1492
1827
|
const rect = el.getBoundingClientRect();
|
|
@@ -1500,15 +1835,15 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1500
1835
|
above
|
|
1501
1836
|
});
|
|
1502
1837
|
}, [normalized.length]);
|
|
1503
|
-
|
|
1838
|
+
useEffect5(() => {
|
|
1504
1839
|
const root = triggerRef.current?.closest(".dialkit-root");
|
|
1505
1840
|
setPortalTarget(root ?? document.body);
|
|
1506
1841
|
}, []);
|
|
1507
|
-
|
|
1842
|
+
useEffect5(() => {
|
|
1508
1843
|
if (!isOpen) return;
|
|
1509
1844
|
updatePos();
|
|
1510
1845
|
}, [isOpen, updatePos]);
|
|
1511
|
-
|
|
1846
|
+
useEffect5(() => {
|
|
1512
1847
|
if (!isOpen) return;
|
|
1513
1848
|
const handleClick = (e) => {
|
|
1514
1849
|
const target = e.target;
|
|
@@ -1528,11 +1863,11 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1528
1863
|
onClick: () => setIsOpen(!isOpen),
|
|
1529
1864
|
"data-open": String(isOpen),
|
|
1530
1865
|
children: [
|
|
1531
|
-
/* @__PURE__ */
|
|
1866
|
+
/* @__PURE__ */ jsx11("span", { className: "dialkit-select-label", children: label }),
|
|
1532
1867
|
/* @__PURE__ */ jsxs10("div", { className: "dialkit-select-right", children: [
|
|
1533
|
-
/* @__PURE__ */
|
|
1534
|
-
/* @__PURE__ */
|
|
1535
|
-
|
|
1868
|
+
/* @__PURE__ */ jsx11("span", { className: "dialkit-select-value", children: selectedOption?.label ?? value }),
|
|
1869
|
+
/* @__PURE__ */ jsx11(
|
|
1870
|
+
motion3.svg,
|
|
1536
1871
|
{
|
|
1537
1872
|
className: "dialkit-select-chevron",
|
|
1538
1873
|
viewBox: "0 0 24 24",
|
|
@@ -1543,7 +1878,7 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1543
1878
|
strokeLinejoin: "round",
|
|
1544
1879
|
animate: { rotate: isOpen ? 180 : 0 },
|
|
1545
1880
|
transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
|
|
1546
|
-
children: /* @__PURE__ */
|
|
1881
|
+
children: /* @__PURE__ */ jsx11("path", { d: ICON_CHEVRON })
|
|
1547
1882
|
}
|
|
1548
1883
|
)
|
|
1549
1884
|
] })
|
|
@@ -1551,8 +1886,8 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1551
1886
|
}
|
|
1552
1887
|
),
|
|
1553
1888
|
portalTarget && createPortal(
|
|
1554
|
-
/* @__PURE__ */
|
|
1555
|
-
|
|
1889
|
+
/* @__PURE__ */ jsx11(AnimatePresence2, { children: isOpen && pos && /* @__PURE__ */ jsx11(
|
|
1890
|
+
motion3.div,
|
|
1556
1891
|
{
|
|
1557
1892
|
ref: dropdownRef,
|
|
1558
1893
|
className: "dialkit-select-dropdown",
|
|
@@ -1566,7 +1901,7 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1566
1901
|
width: pos.width,
|
|
1567
1902
|
...pos.above ? { bottom: window.innerHeight - pos.top, transformOrigin: "bottom" } : { top: pos.top, transformOrigin: "top" }
|
|
1568
1903
|
},
|
|
1569
|
-
children: normalized.map((option) => /* @__PURE__ */
|
|
1904
|
+
children: normalized.map((option) => /* @__PURE__ */ jsx11(
|
|
1570
1905
|
"button",
|
|
1571
1906
|
{
|
|
1572
1907
|
className: "dialkit-select-option",
|
|
@@ -1587,14 +1922,14 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1587
1922
|
}
|
|
1588
1923
|
|
|
1589
1924
|
// src/components/ColorControl.tsx
|
|
1590
|
-
import { useState as
|
|
1591
|
-
import { jsx as
|
|
1925
|
+
import { useState as useState7, useRef as useRef9, useEffect as useEffect6 } from "react";
|
|
1926
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1592
1927
|
var HEX_COLOR_REGEX = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;
|
|
1593
1928
|
function ColorControl({ label, value, onChange }) {
|
|
1594
|
-
const [isEditing, setIsEditing] =
|
|
1595
|
-
const [editValue, setEditValue] =
|
|
1596
|
-
const colorInputRef =
|
|
1597
|
-
|
|
1929
|
+
const [isEditing, setIsEditing] = useState7(false);
|
|
1930
|
+
const [editValue, setEditValue] = useState7(value);
|
|
1931
|
+
const colorInputRef = useRef9(null);
|
|
1932
|
+
useEffect6(() => {
|
|
1598
1933
|
if (!isEditing) {
|
|
1599
1934
|
setEditValue(value);
|
|
1600
1935
|
}
|
|
@@ -1616,9 +1951,9 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1616
1951
|
}
|
|
1617
1952
|
}
|
|
1618
1953
|
return /* @__PURE__ */ jsxs11("div", { className: "dialkit-color-control", children: [
|
|
1619
|
-
/* @__PURE__ */
|
|
1954
|
+
/* @__PURE__ */ jsx12("span", { className: "dialkit-color-label", children: label }),
|
|
1620
1955
|
/* @__PURE__ */ jsxs11("div", { className: "dialkit-color-inputs", children: [
|
|
1621
|
-
isEditing ? /* @__PURE__ */
|
|
1956
|
+
isEditing ? /* @__PURE__ */ jsx12(
|
|
1622
1957
|
"input",
|
|
1623
1958
|
{
|
|
1624
1959
|
type: "text",
|
|
@@ -1629,7 +1964,7 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1629
1964
|
onKeyDown: handleKeyDown,
|
|
1630
1965
|
autoFocus: true
|
|
1631
1966
|
}
|
|
1632
|
-
) : /* @__PURE__ */
|
|
1967
|
+
) : /* @__PURE__ */ jsx12(
|
|
1633
1968
|
"span",
|
|
1634
1969
|
{
|
|
1635
1970
|
className: "dialkit-color-hex",
|
|
@@ -1637,7 +1972,7 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1637
1972
|
children: (value ?? "").toUpperCase()
|
|
1638
1973
|
}
|
|
1639
1974
|
),
|
|
1640
|
-
/* @__PURE__ */
|
|
1975
|
+
/* @__PURE__ */ jsx12(
|
|
1641
1976
|
"button",
|
|
1642
1977
|
{
|
|
1643
1978
|
className: "dialkit-color-swatch",
|
|
@@ -1646,7 +1981,7 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1646
1981
|
title: "Pick color"
|
|
1647
1982
|
}
|
|
1648
1983
|
),
|
|
1649
|
-
/* @__PURE__ */
|
|
1984
|
+
/* @__PURE__ */ jsx12(
|
|
1650
1985
|
"input",
|
|
1651
1986
|
{
|
|
1652
1987
|
ref: colorInputRef,
|
|
@@ -1665,18 +2000,18 @@ function expandShorthandHex(hex) {
|
|
|
1665
2000
|
}
|
|
1666
2001
|
|
|
1667
2002
|
// src/components/PresetManager.tsx
|
|
1668
|
-
import { useState as
|
|
2003
|
+
import { useState as useState8, useRef as useRef10, useEffect as useEffect7, useCallback as useCallback5 } from "react";
|
|
1669
2004
|
import { createPortal as createPortal2 } from "react-dom";
|
|
1670
|
-
import { motion as
|
|
1671
|
-
import { jsx as
|
|
2005
|
+
import { motion as motion4, AnimatePresence as AnimatePresence3 } from "motion/react";
|
|
2006
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1672
2007
|
function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
1673
|
-
const [isOpen, setIsOpen] =
|
|
1674
|
-
const triggerRef =
|
|
1675
|
-
const dropdownRef =
|
|
1676
|
-
const [pos, setPos] =
|
|
2008
|
+
const [isOpen, setIsOpen] = useState8(false);
|
|
2009
|
+
const triggerRef = useRef10(null);
|
|
2010
|
+
const dropdownRef = useRef10(null);
|
|
2011
|
+
const [pos, setPos] = useState8({ top: 0, left: 0, width: 0 });
|
|
1677
2012
|
const hasPresets = presets.length > 0;
|
|
1678
2013
|
const activePreset = presets.find((p) => p.id === activePresetId);
|
|
1679
|
-
const open =
|
|
2014
|
+
const open = useCallback5(() => {
|
|
1680
2015
|
if (!hasPresets) return;
|
|
1681
2016
|
const rect = triggerRef.current?.getBoundingClientRect();
|
|
1682
2017
|
if (rect) {
|
|
@@ -1684,12 +2019,12 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1684
2019
|
}
|
|
1685
2020
|
setIsOpen(true);
|
|
1686
2021
|
}, [hasPresets]);
|
|
1687
|
-
const close =
|
|
1688
|
-
const toggle =
|
|
2022
|
+
const close = useCallback5(() => setIsOpen(false), []);
|
|
2023
|
+
const toggle = useCallback5(() => {
|
|
1689
2024
|
if (isOpen) close();
|
|
1690
2025
|
else open();
|
|
1691
2026
|
}, [isOpen, open, close]);
|
|
1692
|
-
|
|
2027
|
+
useEffect7(() => {
|
|
1693
2028
|
if (!isOpen) return;
|
|
1694
2029
|
const handler = (e) => {
|
|
1695
2030
|
const target = e.target;
|
|
@@ -1722,9 +2057,9 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1722
2057
|
"data-has-preset": String(!!activePreset),
|
|
1723
2058
|
"data-disabled": String(!hasPresets),
|
|
1724
2059
|
children: [
|
|
1725
|
-
/* @__PURE__ */
|
|
1726
|
-
/* @__PURE__ */
|
|
1727
|
-
|
|
2060
|
+
/* @__PURE__ */ jsx13("span", { className: "dialkit-preset-label", children: activePreset ? activePreset.name : "Version 1" }),
|
|
2061
|
+
/* @__PURE__ */ jsx13(
|
|
2062
|
+
motion4.svg,
|
|
1728
2063
|
{
|
|
1729
2064
|
className: "dialkit-select-chevron",
|
|
1730
2065
|
viewBox: "0 0 24 24",
|
|
@@ -1735,15 +2070,15 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1735
2070
|
strokeLinejoin: "round",
|
|
1736
2071
|
animate: { rotate: isOpen ? 180 : 0, opacity: hasPresets ? 0.6 : 0.25 },
|
|
1737
2072
|
transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
|
|
1738
|
-
children: /* @__PURE__ */
|
|
2073
|
+
children: /* @__PURE__ */ jsx13("path", { d: ICON_CHEVRON })
|
|
1739
2074
|
}
|
|
1740
2075
|
)
|
|
1741
2076
|
]
|
|
1742
2077
|
}
|
|
1743
2078
|
),
|
|
1744
2079
|
createPortal2(
|
|
1745
|
-
/* @__PURE__ */
|
|
1746
|
-
|
|
2080
|
+
/* @__PURE__ */ jsx13(AnimatePresence3, { children: isOpen && /* @__PURE__ */ jsxs12(
|
|
2081
|
+
motion4.div,
|
|
1747
2082
|
{
|
|
1748
2083
|
ref: dropdownRef,
|
|
1749
2084
|
className: "dialkit-root dialkit-preset-dropdown",
|
|
@@ -1753,13 +2088,13 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1753
2088
|
exit: { opacity: 0, y: 4, scale: 0.97, pointerEvents: "none" },
|
|
1754
2089
|
transition: { type: "spring", visualDuration: 0.15, bounce: 0 },
|
|
1755
2090
|
children: [
|
|
1756
|
-
/* @__PURE__ */
|
|
2091
|
+
/* @__PURE__ */ jsx13(
|
|
1757
2092
|
"div",
|
|
1758
2093
|
{
|
|
1759
2094
|
className: "dialkit-preset-item",
|
|
1760
2095
|
"data-active": String(!activePresetId),
|
|
1761
2096
|
onClick: () => handleSelect(null),
|
|
1762
|
-
children: /* @__PURE__ */
|
|
2097
|
+
children: /* @__PURE__ */ jsx13("span", { className: "dialkit-preset-name", children: "Version 1" })
|
|
1763
2098
|
}
|
|
1764
2099
|
),
|
|
1765
2100
|
presets.map((preset) => /* @__PURE__ */ jsxs12(
|
|
@@ -1769,20 +2104,14 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1769
2104
|
"data-active": String(preset.id === activePresetId),
|
|
1770
2105
|
onClick: () => handleSelect(preset.id),
|
|
1771
2106
|
children: [
|
|
1772
|
-
/* @__PURE__ */
|
|
1773
|
-
/* @__PURE__ */
|
|
2107
|
+
/* @__PURE__ */ jsx13("span", { className: "dialkit-preset-name", children: preset.name }),
|
|
2108
|
+
/* @__PURE__ */ jsx13(
|
|
1774
2109
|
"button",
|
|
1775
2110
|
{
|
|
1776
2111
|
className: "dialkit-preset-delete",
|
|
1777
2112
|
onClick: (e) => handleDelete(e, preset.id),
|
|
1778
2113
|
title: "Delete preset",
|
|
1779
|
-
children: /* @__PURE__ */
|
|
1780
|
-
/* @__PURE__ */ jsx12("path", { d: "M5 6.5L5.80734 18.2064C5.91582 19.7794 7.22348 21 8.80023 21H15.1998C16.7765 21 18.0842 19.7794 18.1927 18.2064L19 6.5" }),
|
|
1781
|
-
/* @__PURE__ */ jsx12("path", { d: "M10 11V16" }),
|
|
1782
|
-
/* @__PURE__ */ jsx12("path", { d: "M14 11V16" }),
|
|
1783
|
-
/* @__PURE__ */ jsx12("path", { d: "M3.5 6H20.5" }),
|
|
1784
|
-
/* @__PURE__ */ jsx12("path", { d: "M8.07092 5.74621C8.42348 3.89745 10.0485 2.5 12 2.5C13.9515 2.5 15.5765 3.89745 15.9291 5.74621" })
|
|
1785
|
-
] })
|
|
2114
|
+
children: /* @__PURE__ */ jsx13("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: ICON_TRASH.map((d, i) => /* @__PURE__ */ jsx13("path", { d }, i)) })
|
|
1786
2115
|
}
|
|
1787
2116
|
)
|
|
1788
2117
|
]
|
|
@@ -1798,10 +2127,12 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1798
2127
|
}
|
|
1799
2128
|
|
|
1800
2129
|
// src/components/Panel.tsx
|
|
1801
|
-
import { Fragment as Fragment3, jsx as
|
|
1802
|
-
function Panel({ panel, defaultOpen = true }) {
|
|
1803
|
-
const [copied, setCopied] =
|
|
1804
|
-
const [isPanelOpen, setIsPanelOpen] =
|
|
2130
|
+
import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2131
|
+
function Panel({ panel, defaultOpen = true, inline = false }) {
|
|
2132
|
+
const [copied, setCopied] = useState9(false);
|
|
2133
|
+
const [isPanelOpen, setIsPanelOpen] = useState9(defaultOpen);
|
|
2134
|
+
const shortcutCtx = useContext(ShortcutContext);
|
|
2135
|
+
const hasShortcuts = Object.keys(panel.shortcuts).length > 0;
|
|
1805
2136
|
const values = useSyncExternalStore4(
|
|
1806
2137
|
(cb) => DialStore.subscribe(panel.id, cb),
|
|
1807
2138
|
() => DialStore.getValues(panel.id),
|
|
@@ -1830,7 +2161,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1830
2161
|
const value = values[control.path];
|
|
1831
2162
|
switch (control.type) {
|
|
1832
2163
|
case "slider":
|
|
1833
|
-
return /* @__PURE__ */
|
|
2164
|
+
return /* @__PURE__ */ jsx14(
|
|
1834
2165
|
Slider,
|
|
1835
2166
|
{
|
|
1836
2167
|
label: control.label,
|
|
@@ -1838,22 +2169,26 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1838
2169
|
onChange: (v) => DialStore.updateValue(panel.id, control.path, v),
|
|
1839
2170
|
min: control.min,
|
|
1840
2171
|
max: control.max,
|
|
1841
|
-
step: control.step
|
|
2172
|
+
step: control.step,
|
|
2173
|
+
shortcut: control.shortcut,
|
|
2174
|
+
shortcutActive: shortcutCtx.activePanelId === panel.id && shortcutCtx.activePath === control.path
|
|
1842
2175
|
},
|
|
1843
2176
|
control.path
|
|
1844
2177
|
);
|
|
1845
2178
|
case "toggle":
|
|
1846
|
-
return /* @__PURE__ */
|
|
2179
|
+
return /* @__PURE__ */ jsx14(
|
|
1847
2180
|
Toggle,
|
|
1848
2181
|
{
|
|
1849
2182
|
label: control.label,
|
|
1850
2183
|
checked: value,
|
|
1851
|
-
onChange: (v) => DialStore.updateValue(panel.id, control.path, v)
|
|
2184
|
+
onChange: (v) => DialStore.updateValue(panel.id, control.path, v),
|
|
2185
|
+
shortcut: control.shortcut,
|
|
2186
|
+
shortcutActive: shortcutCtx.activePanelId === panel.id && shortcutCtx.activePath === control.path
|
|
1852
2187
|
},
|
|
1853
2188
|
control.path
|
|
1854
2189
|
);
|
|
1855
2190
|
case "spring":
|
|
1856
|
-
return /* @__PURE__ */
|
|
2191
|
+
return /* @__PURE__ */ jsx14(
|
|
1857
2192
|
SpringControl,
|
|
1858
2193
|
{
|
|
1859
2194
|
panelId: panel.id,
|
|
@@ -1865,7 +2200,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1865
2200
|
control.path
|
|
1866
2201
|
);
|
|
1867
2202
|
case "transition":
|
|
1868
|
-
return /* @__PURE__ */
|
|
2203
|
+
return /* @__PURE__ */ jsx14(
|
|
1869
2204
|
TransitionControl,
|
|
1870
2205
|
{
|
|
1871
2206
|
panelId: panel.id,
|
|
@@ -1877,9 +2212,9 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1877
2212
|
control.path
|
|
1878
2213
|
);
|
|
1879
2214
|
case "folder":
|
|
1880
|
-
return /* @__PURE__ */
|
|
2215
|
+
return /* @__PURE__ */ jsx14(Folder, { title: control.label, defaultOpen: control.defaultOpen ?? true, children: control.children?.map(renderControl) }, control.path);
|
|
1881
2216
|
case "text":
|
|
1882
|
-
return /* @__PURE__ */
|
|
2217
|
+
return /* @__PURE__ */ jsx14(
|
|
1883
2218
|
TextControl,
|
|
1884
2219
|
{
|
|
1885
2220
|
label: control.label,
|
|
@@ -1890,7 +2225,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1890
2225
|
control.path
|
|
1891
2226
|
);
|
|
1892
2227
|
case "select":
|
|
1893
|
-
return /* @__PURE__ */
|
|
2228
|
+
return /* @__PURE__ */ jsx14(
|
|
1894
2229
|
SelectControl,
|
|
1895
2230
|
{
|
|
1896
2231
|
label: control.label,
|
|
@@ -1901,7 +2236,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1901
2236
|
control.path
|
|
1902
2237
|
);
|
|
1903
2238
|
case "color":
|
|
1904
|
-
return /* @__PURE__ */
|
|
2239
|
+
return /* @__PURE__ */ jsx14(
|
|
1905
2240
|
ColorControl,
|
|
1906
2241
|
{
|
|
1907
2242
|
label: control.label,
|
|
@@ -1911,7 +2246,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1911
2246
|
control.path
|
|
1912
2247
|
);
|
|
1913
2248
|
case "action":
|
|
1914
|
-
return /* @__PURE__ */
|
|
2249
|
+
return /* @__PURE__ */ jsx14(
|
|
1915
2250
|
"button",
|
|
1916
2251
|
{
|
|
1917
2252
|
className: "dialkit-button",
|
|
@@ -1929,24 +2264,18 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1929
2264
|
};
|
|
1930
2265
|
const iconTransition = { type: "spring", visualDuration: 0.4, bounce: 0.1 };
|
|
1931
2266
|
const toolbar = /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
1932
|
-
/* @__PURE__ */
|
|
1933
|
-
|
|
2267
|
+
/* @__PURE__ */ jsx14(
|
|
2268
|
+
motion5.button,
|
|
1934
2269
|
{
|
|
1935
2270
|
className: "dialkit-toolbar-add",
|
|
1936
2271
|
onClick: handleAddPreset,
|
|
1937
2272
|
title: "Add preset",
|
|
1938
2273
|
whileTap: { scale: 0.9 },
|
|
1939
2274
|
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
1940
|
-
children: /* @__PURE__ */
|
|
1941
|
-
/* @__PURE__ */ jsx13("path", { d: "M4 6H20" }),
|
|
1942
|
-
/* @__PURE__ */ jsx13("path", { d: "M4 12H10" }),
|
|
1943
|
-
/* @__PURE__ */ jsx13("path", { d: "M15 15L21 15" }),
|
|
1944
|
-
/* @__PURE__ */ jsx13("path", { d: "M18 12V18" }),
|
|
1945
|
-
/* @__PURE__ */ jsx13("path", { d: "M4 18H10" })
|
|
1946
|
-
] })
|
|
2275
|
+
children: /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: ICON_ADD_PRESET.map((d, i) => /* @__PURE__ */ jsx14("path", { d }, i)) })
|
|
1947
2276
|
}
|
|
1948
2277
|
),
|
|
1949
|
-
/* @__PURE__ */
|
|
2278
|
+
/* @__PURE__ */ jsx14(
|
|
1950
2279
|
PresetManager,
|
|
1951
2280
|
{
|
|
1952
2281
|
panelId: panel.id,
|
|
@@ -1955,64 +2284,71 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1955
2284
|
onAdd: handleAddPreset
|
|
1956
2285
|
}
|
|
1957
2286
|
),
|
|
1958
|
-
/* @__PURE__ */
|
|
1959
|
-
|
|
2287
|
+
/* @__PURE__ */ jsx14(
|
|
2288
|
+
motion5.button,
|
|
1960
2289
|
{
|
|
1961
|
-
className: "dialkit-toolbar-
|
|
2290
|
+
className: "dialkit-toolbar-add",
|
|
1962
2291
|
onClick: handleCopy,
|
|
1963
2292
|
title: "Copy parameters",
|
|
1964
|
-
whileTap: { scale: 0.
|
|
2293
|
+
whileTap: { scale: 0.9 },
|
|
1965
2294
|
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
1966
|
-
children:
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
) }) }),
|
|
2002
|
-
"Copy"
|
|
2003
|
-
]
|
|
2295
|
+
children: /* @__PURE__ */ jsx14("span", { style: { position: "relative", width: 16, height: 16 }, children: /* @__PURE__ */ jsx14(AnimatePresence4, { initial: false, mode: "wait", children: copied ? /* @__PURE__ */ jsx14(
|
|
2296
|
+
motion5.svg,
|
|
2297
|
+
{
|
|
2298
|
+
viewBox: "0 0 24 24",
|
|
2299
|
+
fill: "none",
|
|
2300
|
+
stroke: "currentColor",
|
|
2301
|
+
strokeWidth: "2",
|
|
2302
|
+
strokeLinecap: "round",
|
|
2303
|
+
strokeLinejoin: "round",
|
|
2304
|
+
style: { position: "absolute", inset: 0, width: 16, height: 16, color: "var(--dial-text-label)" },
|
|
2305
|
+
initial: { scale: 0.8, opacity: 0 },
|
|
2306
|
+
animate: { scale: 1, opacity: 1 },
|
|
2307
|
+
exit: { scale: 0.8, opacity: 0 },
|
|
2308
|
+
transition: { duration: 0.08 },
|
|
2309
|
+
children: /* @__PURE__ */ jsx14("path", { d: ICON_CHECK })
|
|
2310
|
+
},
|
|
2311
|
+
"check"
|
|
2312
|
+
) : /* @__PURE__ */ jsxs13(
|
|
2313
|
+
motion5.svg,
|
|
2314
|
+
{
|
|
2315
|
+
viewBox: "0 0 24 24",
|
|
2316
|
+
fill: "none",
|
|
2317
|
+
style: { position: "absolute", inset: 0, width: 16, height: 16, color: "var(--dial-text-label)" },
|
|
2318
|
+
initial: { scale: 0.8, opacity: 0 },
|
|
2319
|
+
animate: { scale: 1, opacity: 1 },
|
|
2320
|
+
exit: { scale: 0.8, opacity: 0 },
|
|
2321
|
+
transition: { duration: 0.08 },
|
|
2322
|
+
children: [
|
|
2323
|
+
/* @__PURE__ */ jsx14("path", { d: ICON_CLIPBOARD.board, stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }),
|
|
2324
|
+
/* @__PURE__ */ jsx14("path", { d: ICON_CLIPBOARD.sparkle, fill: "currentColor" }),
|
|
2325
|
+
/* @__PURE__ */ jsx14("path", { d: ICON_CLIPBOARD.body, stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
2326
|
+
]
|
|
2327
|
+
},
|
|
2328
|
+
"clipboard"
|
|
2329
|
+
) }) })
|
|
2004
2330
|
}
|
|
2005
2331
|
)
|
|
2006
2332
|
] });
|
|
2007
|
-
return /* @__PURE__ */
|
|
2333
|
+
return /* @__PURE__ */ jsx14("div", { className: "dialkit-panel-wrapper", children: /* @__PURE__ */ jsx14(Folder, { title: panel.name, defaultOpen, isRoot: true, inline, onOpenChange: setIsPanelOpen, toolbar, children: renderControls() }) });
|
|
2008
2334
|
}
|
|
2009
2335
|
|
|
2010
2336
|
// src/components/DialRoot.tsx
|
|
2011
|
-
import { jsx as
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2337
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
2338
|
+
var isDevDefault = typeof process !== "undefined" && process?.env?.NODE_ENV ? process.env.NODE_ENV !== "production" : typeof import.meta !== "undefined" && import.meta.env?.MODE ? import.meta.env.MODE !== "production" : true;
|
|
2339
|
+
function DialRoot({ position = "top-right", defaultOpen = true, mode = "popover", theme = "system", productionEnabled = isDevDefault }) {
|
|
2340
|
+
if (!productionEnabled) return null;
|
|
2341
|
+
const [panels, setPanels] = useState10([]);
|
|
2342
|
+
const [mounted, setMounted] = useState10(false);
|
|
2343
|
+
const inline = mode === "inline";
|
|
2344
|
+
const panelRef = useRef11(null);
|
|
2345
|
+
const [dragOffset, setDragOffset] = useState10(null);
|
|
2346
|
+
const [activePosition, setActivePosition] = useState10(position);
|
|
2347
|
+
const lastDragOffset = useRef11(null);
|
|
2348
|
+
const draggingRef = useRef11(false);
|
|
2349
|
+
const dragStartRef = useRef11(null);
|
|
2350
|
+
const didDragRef = useRef11(false);
|
|
2351
|
+
useEffect8(() => {
|
|
2016
2352
|
setMounted(true);
|
|
2017
2353
|
setPanels(DialStore.getPanels());
|
|
2018
2354
|
const unsubscribe = DialStore.subscribeGlobal(() => {
|
|
@@ -2020,20 +2356,105 @@ function DialRoot({ position = "top-right", defaultOpen = true }) {
|
|
|
2020
2356
|
});
|
|
2021
2357
|
return unsubscribe;
|
|
2022
2358
|
}, []);
|
|
2359
|
+
useEffect8(() => {
|
|
2360
|
+
if (!panelRef.current || inline) return;
|
|
2361
|
+
const observer = new MutationObserver(() => {
|
|
2362
|
+
const inner = panelRef.current?.querySelector(".dialkit-panel-inner");
|
|
2363
|
+
if (!inner) return;
|
|
2364
|
+
const collapsed = inner.getAttribute("data-collapsed") === "true";
|
|
2365
|
+
if (!collapsed) {
|
|
2366
|
+
if (dragOffset) {
|
|
2367
|
+
lastDragOffset.current = dragOffset;
|
|
2368
|
+
const bubbleCenterX = dragOffset.x + 21;
|
|
2369
|
+
const midX = window.innerWidth / 2;
|
|
2370
|
+
setActivePosition(bubbleCenterX < midX ? "top-left" : "top-right");
|
|
2371
|
+
} else {
|
|
2372
|
+
setActivePosition(position);
|
|
2373
|
+
}
|
|
2374
|
+
setDragOffset(null);
|
|
2375
|
+
} else if (lastDragOffset.current) {
|
|
2376
|
+
setDragOffset(lastDragOffset.current);
|
|
2377
|
+
}
|
|
2378
|
+
});
|
|
2379
|
+
observer.observe(panelRef.current, { subtree: true, attributes: true, attributeFilter: ["data-collapsed"] });
|
|
2380
|
+
return () => observer.disconnect();
|
|
2381
|
+
}, [inline, dragOffset, position]);
|
|
2382
|
+
const handlePointerDown = useCallback6((e) => {
|
|
2383
|
+
const inner = panelRef.current?.querySelector(".dialkit-panel-inner");
|
|
2384
|
+
if (!inner || inner.getAttribute("data-collapsed") !== "true") return;
|
|
2385
|
+
const rect = panelRef.current.getBoundingClientRect();
|
|
2386
|
+
dragStartRef.current = {
|
|
2387
|
+
pointerX: e.clientX,
|
|
2388
|
+
pointerY: e.clientY,
|
|
2389
|
+
elX: rect.left,
|
|
2390
|
+
elY: rect.top
|
|
2391
|
+
};
|
|
2392
|
+
didDragRef.current = false;
|
|
2393
|
+
draggingRef.current = true;
|
|
2394
|
+
e.target.setPointerCapture(e.pointerId);
|
|
2395
|
+
}, []);
|
|
2396
|
+
const handlePointerMove = useCallback6((e) => {
|
|
2397
|
+
if (!draggingRef.current || !dragStartRef.current) return;
|
|
2398
|
+
const dx = e.clientX - dragStartRef.current.pointerX;
|
|
2399
|
+
const dy = e.clientY - dragStartRef.current.pointerY;
|
|
2400
|
+
if (!didDragRef.current && Math.abs(dx) + Math.abs(dy) < 4) return;
|
|
2401
|
+
didDragRef.current = true;
|
|
2402
|
+
setDragOffset({
|
|
2403
|
+
x: dragStartRef.current.elX + dx,
|
|
2404
|
+
y: dragStartRef.current.elY + dy
|
|
2405
|
+
});
|
|
2406
|
+
}, []);
|
|
2407
|
+
const handlePointerUp = useCallback6((e) => {
|
|
2408
|
+
if (!draggingRef.current) return;
|
|
2409
|
+
draggingRef.current = false;
|
|
2410
|
+
dragStartRef.current = null;
|
|
2411
|
+
if (didDragRef.current) {
|
|
2412
|
+
e.stopPropagation();
|
|
2413
|
+
const inner = panelRef.current?.querySelector(".dialkit-panel-inner");
|
|
2414
|
+
if (inner) {
|
|
2415
|
+
const blocker = (ev) => {
|
|
2416
|
+
ev.stopPropagation();
|
|
2417
|
+
};
|
|
2418
|
+
inner.addEventListener("click", blocker, { capture: true, once: true });
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
}, []);
|
|
2023
2422
|
if (!mounted || typeof window === "undefined") {
|
|
2024
2423
|
return null;
|
|
2025
2424
|
}
|
|
2026
2425
|
if (panels.length === 0) {
|
|
2027
2426
|
return null;
|
|
2028
2427
|
}
|
|
2029
|
-
const
|
|
2428
|
+
const dragStyle = dragOffset ? {
|
|
2429
|
+
top: dragOffset.y,
|
|
2430
|
+
left: dragOffset.x,
|
|
2431
|
+
right: "auto",
|
|
2432
|
+
bottom: "auto"
|
|
2433
|
+
} : void 0;
|
|
2434
|
+
const content = /* @__PURE__ */ jsx15(ShortcutListener, { children: /* @__PURE__ */ jsx15("div", { className: "dialkit-root", "data-mode": mode, "data-theme": theme, children: /* @__PURE__ */ jsx15(
|
|
2435
|
+
"div",
|
|
2436
|
+
{
|
|
2437
|
+
ref: panelRef,
|
|
2438
|
+
className: "dialkit-panel",
|
|
2439
|
+
"data-position": inline ? void 0 : dragOffset ? void 0 : activePosition,
|
|
2440
|
+
"data-mode": mode,
|
|
2441
|
+
style: dragStyle,
|
|
2442
|
+
onPointerDown: !inline ? handlePointerDown : void 0,
|
|
2443
|
+
onPointerMove: !inline ? handlePointerMove : void 0,
|
|
2444
|
+
onPointerUp: !inline ? handlePointerUp : void 0,
|
|
2445
|
+
children: panels.map((panel) => /* @__PURE__ */ jsx15(Panel, { panel, defaultOpen: inline || defaultOpen, inline }, panel.id))
|
|
2446
|
+
}
|
|
2447
|
+
) }) });
|
|
2448
|
+
if (inline) {
|
|
2449
|
+
return content;
|
|
2450
|
+
}
|
|
2030
2451
|
return createPortal3(content, document.body);
|
|
2031
2452
|
}
|
|
2032
2453
|
|
|
2033
2454
|
// src/components/ButtonGroup.tsx
|
|
2034
|
-
import { jsx as
|
|
2455
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
2035
2456
|
function ButtonGroup({ buttons }) {
|
|
2036
|
-
return /* @__PURE__ */
|
|
2457
|
+
return /* @__PURE__ */ jsx16("div", { className: "dialkit-button-group", children: buttons.map((button, index) => /* @__PURE__ */ jsx16(
|
|
2037
2458
|
"button",
|
|
2038
2459
|
{
|
|
2039
2460
|
className: "dialkit-button",
|
|
@@ -2043,6 +2464,124 @@ function ButtonGroup({ buttons }) {
|
|
|
2043
2464
|
index
|
|
2044
2465
|
)) });
|
|
2045
2466
|
}
|
|
2467
|
+
|
|
2468
|
+
// src/components/ShortcutsMenu.tsx
|
|
2469
|
+
import { useState as useState11, useRef as useRef12, useEffect as useEffect9, useCallback as useCallback7 } from "react";
|
|
2470
|
+
import { createPortal as createPortal4 } from "react-dom";
|
|
2471
|
+
import { motion as motion6, AnimatePresence as AnimatePresence5 } from "motion/react";
|
|
2472
|
+
import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2473
|
+
function formatShortcutKey(sc) {
|
|
2474
|
+
if (!sc.key) return "\u2014";
|
|
2475
|
+
const mod = sc.modifier === "alt" ? "\u2325" : sc.modifier === "shift" ? "\u21E7" : sc.modifier === "meta" ? "\u2318" : "";
|
|
2476
|
+
return `${mod}${sc.key.toUpperCase()}`;
|
|
2477
|
+
}
|
|
2478
|
+
function formatInteraction(sc) {
|
|
2479
|
+
const interaction = sc.interaction ?? "scroll";
|
|
2480
|
+
switch (interaction) {
|
|
2481
|
+
case "scroll":
|
|
2482
|
+
return sc.key ? "key+scroll" : "scroll";
|
|
2483
|
+
case "drag":
|
|
2484
|
+
return "key+drag";
|
|
2485
|
+
case "move":
|
|
2486
|
+
return "key+move";
|
|
2487
|
+
case "scroll-only":
|
|
2488
|
+
return "scroll";
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
function ShortcutsMenu({ panelId }) {
|
|
2492
|
+
const [isOpen, setIsOpen] = useState11(false);
|
|
2493
|
+
const triggerRef = useRef12(null);
|
|
2494
|
+
const dropdownRef = useRef12(null);
|
|
2495
|
+
const [pos, setPos] = useState11({ top: 0, right: 0 });
|
|
2496
|
+
const open = useCallback7(() => {
|
|
2497
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
2498
|
+
if (rect) {
|
|
2499
|
+
setPos({ top: rect.bottom + 4, right: window.innerWidth - rect.right });
|
|
2500
|
+
}
|
|
2501
|
+
setIsOpen(true);
|
|
2502
|
+
}, []);
|
|
2503
|
+
const close = useCallback7(() => setIsOpen(false), []);
|
|
2504
|
+
const toggle = useCallback7(() => {
|
|
2505
|
+
if (isOpen) close();
|
|
2506
|
+
else open();
|
|
2507
|
+
}, [isOpen, open, close]);
|
|
2508
|
+
useEffect9(() => {
|
|
2509
|
+
if (!isOpen) return;
|
|
2510
|
+
const handler = (e) => {
|
|
2511
|
+
const target = e.target;
|
|
2512
|
+
if (triggerRef.current?.contains(target) || dropdownRef.current?.contains(target)) return;
|
|
2513
|
+
close();
|
|
2514
|
+
};
|
|
2515
|
+
document.addEventListener("mousedown", handler);
|
|
2516
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
2517
|
+
}, [isOpen, close]);
|
|
2518
|
+
const panel = DialStore.getPanel(panelId);
|
|
2519
|
+
if (!panel) return null;
|
|
2520
|
+
const shortcuts = Object.entries(panel.shortcuts);
|
|
2521
|
+
if (shortcuts.length === 0) return null;
|
|
2522
|
+
const rows = shortcuts.map(([path, shortcut]) => {
|
|
2523
|
+
const findLabel = (controls) => {
|
|
2524
|
+
for (const c of controls) {
|
|
2525
|
+
if (c.path === path) return c.label;
|
|
2526
|
+
if (c.type === "folder" && c.children) {
|
|
2527
|
+
const found = findLabel(c.children);
|
|
2528
|
+
if (found) return found;
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
return path;
|
|
2532
|
+
};
|
|
2533
|
+
return {
|
|
2534
|
+
path,
|
|
2535
|
+
shortcut,
|
|
2536
|
+
label: findLabel(panel.controls)
|
|
2537
|
+
};
|
|
2538
|
+
});
|
|
2539
|
+
return /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
2540
|
+
/* @__PURE__ */ jsx17(
|
|
2541
|
+
motion6.button,
|
|
2542
|
+
{
|
|
2543
|
+
ref: triggerRef,
|
|
2544
|
+
className: "dialkit-shortcuts-trigger",
|
|
2545
|
+
onClick: toggle,
|
|
2546
|
+
title: "Keyboard shortcuts",
|
|
2547
|
+
whileTap: { scale: 0.9 },
|
|
2548
|
+
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
2549
|
+
children: /* @__PURE__ */ jsxs14("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2550
|
+
/* @__PURE__ */ jsx17("rect", { x: "2", y: "6", width: "20", height: "12", rx: "2" }),
|
|
2551
|
+
/* @__PURE__ */ jsx17("path", { d: "M6 10H6.01" }),
|
|
2552
|
+
/* @__PURE__ */ jsx17("path", { d: "M10 10H10.01" }),
|
|
2553
|
+
/* @__PURE__ */ jsx17("path", { d: "M14 10H14.01" }),
|
|
2554
|
+
/* @__PURE__ */ jsx17("path", { d: "M18 10H18.01" }),
|
|
2555
|
+
/* @__PURE__ */ jsx17("path", { d: "M8 14H16" })
|
|
2556
|
+
] })
|
|
2557
|
+
}
|
|
2558
|
+
),
|
|
2559
|
+
createPortal4(
|
|
2560
|
+
/* @__PURE__ */ jsx17(AnimatePresence5, { children: isOpen && /* @__PURE__ */ jsxs14(
|
|
2561
|
+
motion6.div,
|
|
2562
|
+
{
|
|
2563
|
+
ref: dropdownRef,
|
|
2564
|
+
className: "dialkit-root dialkit-shortcuts-dropdown",
|
|
2565
|
+
style: { position: "fixed", top: pos.top, right: pos.right },
|
|
2566
|
+
initial: { opacity: 0, y: 4, scale: 0.97 },
|
|
2567
|
+
animate: { opacity: 1, y: 0, scale: 1 },
|
|
2568
|
+
exit: { opacity: 0, y: 4, scale: 0.97, pointerEvents: "none" },
|
|
2569
|
+
transition: { type: "spring", visualDuration: 0.15, bounce: 0 },
|
|
2570
|
+
children: [
|
|
2571
|
+
/* @__PURE__ */ jsx17("div", { className: "dialkit-shortcuts-title", children: "Keyboard Shortcuts" }),
|
|
2572
|
+
/* @__PURE__ */ jsx17("div", { className: "dialkit-shortcuts-list", children: rows.map((row) => /* @__PURE__ */ jsxs14("div", { className: "dialkit-shortcuts-row", children: [
|
|
2573
|
+
/* @__PURE__ */ jsx17("span", { className: "dialkit-shortcuts-row-key", children: formatShortcutKey(row.shortcut) }),
|
|
2574
|
+
/* @__PURE__ */ jsx17("span", { className: "dialkit-shortcuts-row-label", children: row.label }),
|
|
2575
|
+
/* @__PURE__ */ jsx17("span", { className: "dialkit-shortcuts-row-mode", children: formatInteraction(row.shortcut) })
|
|
2576
|
+
] }, row.path)) }),
|
|
2577
|
+
/* @__PURE__ */ jsx17("div", { className: "dialkit-shortcuts-hint", children: "See pill badges on controls for keys" })
|
|
2578
|
+
]
|
|
2579
|
+
}
|
|
2580
|
+
) }),
|
|
2581
|
+
document.body
|
|
2582
|
+
)
|
|
2583
|
+
] });
|
|
2584
|
+
}
|
|
2046
2585
|
export {
|
|
2047
2586
|
ButtonGroup,
|
|
2048
2587
|
ColorControl,
|
|
@@ -2052,6 +2591,7 @@ export {
|
|
|
2052
2591
|
Folder,
|
|
2053
2592
|
PresetManager,
|
|
2054
2593
|
SelectControl,
|
|
2594
|
+
ShortcutsMenu,
|
|
2055
2595
|
Slider,
|
|
2056
2596
|
SpringControl,
|
|
2057
2597
|
SpringVisualization,
|