dialkit 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -1
- package/dist/index.cjs +876 -337
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -6
- package/dist/index.d.ts +41 -6
- package/dist/index.js +878 -341
- package/dist/index.js.map +1 -1
- package/dist/solid/index.cjs +1011 -544
- package/dist/solid/index.cjs.map +1 -1
- package/dist/solid/index.d.cts +33 -3
- package/dist/solid/index.d.ts +33 -3
- package/dist/solid/index.js +864 -398
- package/dist/solid/index.js.map +1 -1
- package/dist/store/index.cjs +52 -12
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +25 -3
- package/dist/store/index.d.ts +25 -3
- package/dist/store/index.js +52 -12
- package/dist/store/index.js.map +1 -1
- package/dist/styles.css +256 -25
- package/dist/svelte/components/ControlRenderer.svelte +12 -0
- package/dist/svelte/components/ControlRenderer.svelte.d.ts.map +1 -1
- package/dist/svelte/components/DialRoot.svelte +22 -8
- package/dist/svelte/components/DialRoot.svelte.d.ts +3 -0
- package/dist/svelte/components/DialRoot.svelte.d.ts.map +1 -1
- package/dist/svelte/components/Folder.svelte +17 -8
- package/dist/svelte/components/Folder.svelte.d.ts.map +1 -1
- package/dist/svelte/components/Panel.svelte +14 -9
- package/dist/svelte/components/Panel.svelte.d.ts.map +1 -1
- package/dist/svelte/components/PresetManager.svelte +7 -6
- package/dist/svelte/components/PresetManager.svelte.d.ts.map +1 -1
- package/dist/svelte/components/SegmentedControl.svelte +30 -74
- package/dist/svelte/components/SegmentedControl.svelte.d.ts.map +1 -1
- package/dist/svelte/components/SelectControl.svelte +2 -1
- package/dist/svelte/components/SelectControl.svelte.d.ts.map +1 -1
- 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 +16 -29
- package/dist/svelte/components/Slider.svelte.d.ts +3 -0
- package/dist/svelte/components/Slider.svelte.d.ts.map +1 -1
- package/dist/svelte/components/SpringControl.svelte +17 -15
- package/dist/svelte/components/SpringControl.svelte.d.ts.map +1 -1
- package/dist/svelte/components/Toggle.svelte +13 -2
- package/dist/svelte/components/Toggle.svelte.d.ts +3 -0
- package/dist/svelte/components/Toggle.svelte.d.ts.map +1 -1
- package/dist/svelte/components/TransitionControl.svelte +28 -25
- package/dist/svelte/components/TransitionControl.svelte.d.ts.map +1 -1
- package/dist/svelte/createDialKit.svelte.d.ts +2 -1
- package/dist/svelte/createDialKit.svelte.d.ts.map +1 -1
- package/dist/svelte/createDialKit.svelte.js +1 -1
- package/dist/svelte/index.d.ts +6 -2
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +4 -0
- package/dist/svelte/theme-css.d.ts +1 -1
- package/dist/svelte/theme-css.d.ts.map +1 -1
- package/dist/svelte/theme-css.js +257 -26
- 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 +24 -4
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";
|
|
873
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
525
874
|
function Folder({ title, children, defaultOpen = true, isRoot = false, inline = false, onOpenChange, toolbar }) {
|
|
526
|
-
const [isOpen, setIsOpen] =
|
|
527
|
-
const [isCollapsed, setIsCollapsed] =
|
|
528
|
-
const contentRef =
|
|
529
|
-
const [contentHeight, setContentHeight] =
|
|
530
|
-
|
|
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(() => {
|
|
@@ -553,7 +909,7 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, inline =
|
|
|
553
909
|
const folderContent = /* @__PURE__ */ jsxs("div", { ref: isRoot ? contentRef : void 0, className: `dialkit-folder ${isRoot ? "dialkit-folder-root" : ""}`, children: [
|
|
554
910
|
/* @__PURE__ */ jsxs("div", { className: `dialkit-folder-header ${isRoot ? "dialkit-panel-header" : ""}`, onClick: handleToggle, children: [
|
|
555
911
|
/* @__PURE__ */ jsxs("div", { className: "dialkit-folder-header-top", children: [
|
|
556
|
-
isRoot ? isOpen && /* @__PURE__ */
|
|
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 }) }),
|
|
557
913
|
isRoot && !inline && /* @__PURE__ */ jsxs(
|
|
558
914
|
"svg",
|
|
559
915
|
{
|
|
@@ -561,14 +917,12 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, inline =
|
|
|
561
917
|
viewBox: "0 0 16 16",
|
|
562
918
|
fill: "none",
|
|
563
919
|
children: [
|
|
564
|
-
/* @__PURE__ */
|
|
565
|
-
/* @__PURE__ */
|
|
566
|
-
/* @__PURE__ */ jsx("circle", { cx: "10.4999", cy: "3.5", r: "0.998657", fill: "currentColor", stroke: "currentColor", strokeWidth: "1.25" }),
|
|
567
|
-
/* @__PURE__ */ jsx("circle", { cx: "9.75015", cy: "12.5", r: "0.997986", fill: "currentColor", stroke: "currentColor", strokeWidth: "1.25" })
|
|
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))
|
|
568
922
|
]
|
|
569
923
|
}
|
|
570
924
|
),
|
|
571
|
-
!isRoot && /* @__PURE__ */
|
|
925
|
+
!isRoot && /* @__PURE__ */ jsx2(
|
|
572
926
|
motion.svg,
|
|
573
927
|
{
|
|
574
928
|
className: "dialkit-folder-icon",
|
|
@@ -581,13 +935,13 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, inline =
|
|
|
581
935
|
initial: false,
|
|
582
936
|
animate: { rotate: isOpen ? 0 : 180 },
|
|
583
937
|
transition: { type: "spring", visualDuration: 0.35, bounce: 0.15 },
|
|
584
|
-
children: /* @__PURE__ */
|
|
938
|
+
children: /* @__PURE__ */ jsx2("path", { d: ICON_CHEVRON })
|
|
585
939
|
}
|
|
586
940
|
)
|
|
587
941
|
] }),
|
|
588
|
-
isRoot && toolbar && isOpen && /* @__PURE__ */
|
|
942
|
+
isRoot && toolbar && isOpen && /* @__PURE__ */ jsx2("div", { className: "dialkit-panel-toolbar", onClick: (e) => e.stopPropagation(), children: toolbar })
|
|
589
943
|
] }),
|
|
590
|
-
/* @__PURE__ */
|
|
944
|
+
/* @__PURE__ */ jsx2(AnimatePresence, { initial: false, children: isOpen && /* @__PURE__ */ jsx2(
|
|
591
945
|
motion.div,
|
|
592
946
|
{
|
|
593
947
|
className: "dialkit-folder-content",
|
|
@@ -596,16 +950,16 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, inline =
|
|
|
596
950
|
exit: isRoot ? void 0 : { height: 0, opacity: 0 },
|
|
597
951
|
transition: isRoot ? void 0 : { type: "spring", visualDuration: 0.35, bounce: 0.1 },
|
|
598
952
|
style: isRoot ? void 0 : { clipPath: "inset(0 -20px)" },
|
|
599
|
-
children: /* @__PURE__ */
|
|
953
|
+
children: /* @__PURE__ */ jsx2("div", { className: "dialkit-folder-inner", children })
|
|
600
954
|
}
|
|
601
955
|
) })
|
|
602
956
|
] });
|
|
603
957
|
if (isRoot) {
|
|
604
958
|
if (inline) {
|
|
605
|
-
return /* @__PURE__ */
|
|
959
|
+
return /* @__PURE__ */ jsx2("div", { className: "dialkit-panel-inner dialkit-panel-inline", children: folderContent });
|
|
606
960
|
}
|
|
607
|
-
const panelStyle = isOpen ? { width: 280, height: contentHeight !== void 0 ? contentHeight +
|
|
608
|
-
return /* @__PURE__ */
|
|
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(
|
|
609
963
|
motion.div,
|
|
610
964
|
{
|
|
611
965
|
className: "dialkit-panel-inner",
|
|
@@ -622,30 +976,13 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, inline =
|
|
|
622
976
|
}
|
|
623
977
|
|
|
624
978
|
// src/components/Slider.tsx
|
|
625
|
-
import { useRef as
|
|
979
|
+
import { useRef as useRef4, useState as useState3, useCallback as useCallback2, useEffect as useEffect4 } from "react";
|
|
626
980
|
import { motion as motion2, useMotionValue, useTransform, animate } from "motion/react";
|
|
627
|
-
import { jsx as
|
|
981
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
628
982
|
var CLICK_THRESHOLD = 3;
|
|
629
983
|
var DEAD_ZONE = 32;
|
|
630
984
|
var MAX_CURSOR_RANGE = 200;
|
|
631
985
|
var MAX_STRETCH = 8;
|
|
632
|
-
function decimalsForStep(step) {
|
|
633
|
-
const s = step.toString();
|
|
634
|
-
const dot = s.indexOf(".");
|
|
635
|
-
return dot === -1 ? 0 : s.length - dot - 1;
|
|
636
|
-
}
|
|
637
|
-
function roundValue(val, step) {
|
|
638
|
-
const raw = Math.round(val / step) * step;
|
|
639
|
-
return parseFloat(raw.toFixed(decimalsForStep(step)));
|
|
640
|
-
}
|
|
641
|
-
function snapToDecile(rawValue, min, max) {
|
|
642
|
-
const normalized = (rawValue - min) / (max - min);
|
|
643
|
-
const nearest = Math.round(normalized * 10) / 10;
|
|
644
|
-
if (Math.abs(normalized - nearest) <= 0.03125) {
|
|
645
|
-
return min + nearest * (max - min);
|
|
646
|
-
}
|
|
647
|
-
return rawValue;
|
|
648
|
-
}
|
|
649
986
|
function Slider({
|
|
650
987
|
label,
|
|
651
988
|
value,
|
|
@@ -653,26 +990,28 @@ function Slider({
|
|
|
653
990
|
min = 0,
|
|
654
991
|
max = 1,
|
|
655
992
|
step = 0.01,
|
|
656
|
-
unit
|
|
993
|
+
unit,
|
|
994
|
+
shortcut,
|
|
995
|
+
shortcutActive
|
|
657
996
|
}) {
|
|
658
|
-
const wrapperRef =
|
|
659
|
-
const trackRef =
|
|
660
|
-
const inputRef =
|
|
661
|
-
const labelRef =
|
|
662
|
-
const valueSpanRef =
|
|
663
|
-
const [isInteracting, setIsInteracting] =
|
|
664
|
-
const [isDragging, setIsDragging] =
|
|
665
|
-
const [isHovered, setIsHovered] =
|
|
666
|
-
const [isValueHovered, setIsValueHovered] =
|
|
667
|
-
const [isValueEditable, setIsValueEditable] =
|
|
668
|
-
const [showInput, setShowInput] =
|
|
669
|
-
const [inputValue, setInputValue] =
|
|
670
|
-
const hoverTimeoutRef =
|
|
671
|
-
const pointerDownPos =
|
|
672
|
-
const isClickRef =
|
|
673
|
-
const animRef =
|
|
674
|
-
const wrapperRectRef =
|
|
675
|
-
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);
|
|
676
1015
|
const percentage = (value - min) / (max - min) * 100;
|
|
677
1016
|
const isActive = isInteracting || isHovered;
|
|
678
1017
|
const fillPercent = useMotionValue(percentage);
|
|
@@ -690,12 +1029,12 @@ function Slider({
|
|
|
690
1029
|
rubberStretchPx,
|
|
691
1030
|
(stretch) => stretch < 0 ? stretch : 0
|
|
692
1031
|
);
|
|
693
|
-
|
|
1032
|
+
useEffect4(() => {
|
|
694
1033
|
if (!isInteracting && !animRef.current) {
|
|
695
1034
|
fillPercent.jump(percentage);
|
|
696
1035
|
}
|
|
697
1036
|
}, [percentage, isInteracting, fillPercent]);
|
|
698
|
-
const positionToValue =
|
|
1037
|
+
const positionToValue = useCallback2(
|
|
699
1038
|
(clientX) => {
|
|
700
1039
|
const rect = wrapperRectRef.current;
|
|
701
1040
|
if (!rect) return value;
|
|
@@ -708,11 +1047,11 @@ function Slider({
|
|
|
708
1047
|
},
|
|
709
1048
|
[min, max, value]
|
|
710
1049
|
);
|
|
711
|
-
const percentFromValue =
|
|
1050
|
+
const percentFromValue = useCallback2(
|
|
712
1051
|
(v) => (v - min) / (max - min) * 100,
|
|
713
1052
|
[min, max]
|
|
714
1053
|
);
|
|
715
|
-
const computeRubberStretch =
|
|
1054
|
+
const computeRubberStretch = useCallback2(
|
|
716
1055
|
(clientX, sign) => {
|
|
717
1056
|
const rect = wrapperRectRef.current;
|
|
718
1057
|
if (!rect) return 0;
|
|
@@ -722,7 +1061,7 @@ function Slider({
|
|
|
722
1061
|
},
|
|
723
1062
|
[]
|
|
724
1063
|
);
|
|
725
|
-
const handlePointerDown =
|
|
1064
|
+
const handlePointerDown = useCallback2(
|
|
726
1065
|
(e) => {
|
|
727
1066
|
if (showInput) return;
|
|
728
1067
|
e.preventDefault();
|
|
@@ -738,7 +1077,7 @@ function Slider({
|
|
|
738
1077
|
},
|
|
739
1078
|
[showInput]
|
|
740
1079
|
);
|
|
741
|
-
const handlePointerMove =
|
|
1080
|
+
const handlePointerMove = useCallback2(
|
|
742
1081
|
(e) => {
|
|
743
1082
|
if (!isInteracting || !pointerDownPos.current) return;
|
|
744
1083
|
const dx = e.clientX - pointerDownPos.current.x;
|
|
@@ -779,7 +1118,7 @@ function Slider({
|
|
|
779
1118
|
computeRubberStretch
|
|
780
1119
|
]
|
|
781
1120
|
);
|
|
782
|
-
const handlePointerUp =
|
|
1121
|
+
const handlePointerUp = useCallback2(
|
|
783
1122
|
(e) => {
|
|
784
1123
|
if (!isInteracting) return;
|
|
785
1124
|
if (isClickRef.current) {
|
|
@@ -823,7 +1162,7 @@ function Slider({
|
|
|
823
1162
|
rubberStretchPx
|
|
824
1163
|
]
|
|
825
1164
|
);
|
|
826
|
-
|
|
1165
|
+
useEffect4(() => {
|
|
827
1166
|
if (isValueHovered && !showInput && !isValueEditable) {
|
|
828
1167
|
hoverTimeoutRef.current = setTimeout(() => {
|
|
829
1168
|
setIsValueEditable(true);
|
|
@@ -841,7 +1180,7 @@ function Slider({
|
|
|
841
1180
|
}
|
|
842
1181
|
};
|
|
843
1182
|
}, [isValueHovered, showInput, isValueEditable]);
|
|
844
|
-
|
|
1183
|
+
useEffect4(() => {
|
|
845
1184
|
if (showInput && inputRef.current) {
|
|
846
1185
|
inputRef.current.focus();
|
|
847
1186
|
inputRef.current.select();
|
|
@@ -896,11 +1235,10 @@ function Slider({
|
|
|
896
1235
|
}
|
|
897
1236
|
const valueDodge = percentage < leftThreshold || percentage > rightThreshold;
|
|
898
1237
|
const handleOpacity = !isActive ? 0 : valueDodge ? 0.1 : isDragging ? 0.9 : 0.5;
|
|
899
|
-
const fillBackground = isActive ? "rgba(255, 255, 255, 0.15)" : "rgba(255, 255, 255, 0.11)";
|
|
900
1238
|
const discreteSteps = (max - min) / step;
|
|
901
1239
|
const hashMarks = discreteSteps <= 10 ? Array.from({ length: discreteSteps - 1 }, (_, i) => {
|
|
902
1240
|
const pct = (i + 1) * step / (max - min) * 100;
|
|
903
|
-
return /* @__PURE__ */
|
|
1241
|
+
return /* @__PURE__ */ jsx3(
|
|
904
1242
|
"div",
|
|
905
1243
|
{
|
|
906
1244
|
className: "dialkit-slider-hashmark",
|
|
@@ -910,7 +1248,7 @@ function Slider({
|
|
|
910
1248
|
);
|
|
911
1249
|
}) : Array.from({ length: 9 }, (_, i) => {
|
|
912
1250
|
const pct = (i + 1) * 10;
|
|
913
|
-
return /* @__PURE__ */
|
|
1251
|
+
return /* @__PURE__ */ jsx3(
|
|
914
1252
|
"div",
|
|
915
1253
|
{
|
|
916
1254
|
className: "dialkit-slider-hashmark",
|
|
@@ -919,7 +1257,7 @@ function Slider({
|
|
|
919
1257
|
i
|
|
920
1258
|
);
|
|
921
1259
|
});
|
|
922
|
-
return /* @__PURE__ */
|
|
1260
|
+
return /* @__PURE__ */ jsx3("div", { ref: wrapperRef, className: "dialkit-slider-wrapper", children: /* @__PURE__ */ jsxs2(
|
|
923
1261
|
motion2.div,
|
|
924
1262
|
{
|
|
925
1263
|
ref: trackRef,
|
|
@@ -931,26 +1269,23 @@ function Slider({
|
|
|
931
1269
|
onMouseLeave: () => setIsHovered(false),
|
|
932
1270
|
style: { width: rubberBandWidth, x: rubberBandX },
|
|
933
1271
|
children: [
|
|
934
|
-
/* @__PURE__ */
|
|
935
|
-
/* @__PURE__ */
|
|
1272
|
+
/* @__PURE__ */ jsx3("div", { className: "dialkit-slider-hashmarks", children: hashMarks }),
|
|
1273
|
+
/* @__PURE__ */ jsx3(
|
|
936
1274
|
motion2.div,
|
|
937
1275
|
{
|
|
938
1276
|
className: "dialkit-slider-fill",
|
|
939
1277
|
style: {
|
|
940
|
-
|
|
941
|
-
width: fillWidth,
|
|
942
|
-
transition: "background 0.15s"
|
|
1278
|
+
width: fillWidth
|
|
943
1279
|
}
|
|
944
1280
|
}
|
|
945
1281
|
),
|
|
946
|
-
/* @__PURE__ */
|
|
1282
|
+
/* @__PURE__ */ jsx3(
|
|
947
1283
|
motion2.div,
|
|
948
1284
|
{
|
|
949
1285
|
className: "dialkit-slider-handle",
|
|
950
1286
|
style: {
|
|
951
1287
|
left: handleLeft,
|
|
952
|
-
y: "-50%"
|
|
953
|
-
background: "rgba(255, 255, 255, 0.9)"
|
|
1288
|
+
y: "-50%"
|
|
954
1289
|
},
|
|
955
1290
|
animate: {
|
|
956
1291
|
opacity: handleOpacity,
|
|
@@ -964,8 +1299,11 @@ function Slider({
|
|
|
964
1299
|
}
|
|
965
1300
|
}
|
|
966
1301
|
),
|
|
967
|
-
/* @__PURE__ */
|
|
968
|
-
|
|
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(
|
|
969
1307
|
"input",
|
|
970
1308
|
{
|
|
971
1309
|
ref: inputRef,
|
|
@@ -978,7 +1316,7 @@ function Slider({
|
|
|
978
1316
|
onClick: (e) => e.stopPropagation(),
|
|
979
1317
|
onMouseDown: (e) => e.stopPropagation()
|
|
980
1318
|
}
|
|
981
|
-
) : /* @__PURE__ */
|
|
1319
|
+
) : /* @__PURE__ */ jsx3(
|
|
982
1320
|
"span",
|
|
983
1321
|
{
|
|
984
1322
|
ref: valueSpanRef,
|
|
@@ -997,51 +1335,48 @@ function Slider({
|
|
|
997
1335
|
}
|
|
998
1336
|
|
|
999
1337
|
// src/components/SegmentedControl.tsx
|
|
1000
|
-
import { useRef as
|
|
1001
|
-
import {
|
|
1002
|
-
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";
|
|
1003
1340
|
function SegmentedControl({
|
|
1004
1341
|
options,
|
|
1005
1342
|
value,
|
|
1006
1343
|
onChange
|
|
1007
1344
|
}) {
|
|
1008
|
-
const containerRef =
|
|
1009
|
-
const
|
|
1010
|
-
const [pillStyle, setPillStyle] =
|
|
1011
|
-
const
|
|
1012
|
-
useLayoutEffect(() => {
|
|
1013
|
-
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(() => {
|
|
1014
1349
|
const container = containerRef.current;
|
|
1015
|
-
if (
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
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",
|
|
1027
1366
|
{
|
|
1028
1367
|
className: "dialkit-segmented-pill",
|
|
1029
|
-
style: {
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
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"
|
|
1034
1372
|
}
|
|
1035
1373
|
}
|
|
1036
1374
|
),
|
|
1037
1375
|
options.map((option) => {
|
|
1038
1376
|
const isActive = value === option.value;
|
|
1039
|
-
return /* @__PURE__ */
|
|
1377
|
+
return /* @__PURE__ */ jsx4(
|
|
1040
1378
|
"button",
|
|
1041
1379
|
{
|
|
1042
|
-
ref: (el) => {
|
|
1043
|
-
if (el) buttonRefs.current.set(option.value, el);
|
|
1044
|
-
},
|
|
1045
1380
|
onClick: () => onChange(option.value),
|
|
1046
1381
|
className: "dialkit-segmented-button",
|
|
1047
1382
|
"data-active": String(isActive),
|
|
@@ -1054,11 +1389,14 @@ function SegmentedControl({
|
|
|
1054
1389
|
}
|
|
1055
1390
|
|
|
1056
1391
|
// src/components/Toggle.tsx
|
|
1057
|
-
import { jsx as
|
|
1058
|
-
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 }) {
|
|
1059
1394
|
return /* @__PURE__ */ jsxs4("div", { className: "dialkit-labeled-control", children: [
|
|
1060
|
-
/* @__PURE__ */
|
|
1061
|
-
|
|
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(
|
|
1062
1400
|
SegmentedControl,
|
|
1063
1401
|
{
|
|
1064
1402
|
options: [
|
|
@@ -1073,7 +1411,7 @@ function Toggle({ label, checked, onChange }) {
|
|
|
1073
1411
|
}
|
|
1074
1412
|
|
|
1075
1413
|
// src/components/SpringVisualization.tsx
|
|
1076
|
-
import { jsx as
|
|
1414
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1077
1415
|
function generateSpringCurve(stiffness, damping, mass, duration) {
|
|
1078
1416
|
const points = [];
|
|
1079
1417
|
const steps = 100;
|
|
@@ -1128,13 +1466,13 @@ function SpringVisualization({ spring, isSimpleMode }) {
|
|
|
1128
1466
|
const x = width / 4 * i;
|
|
1129
1467
|
const y = height / 4 * i;
|
|
1130
1468
|
gridLines.push(
|
|
1131
|
-
/* @__PURE__ */
|
|
1132
|
-
/* @__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}`)
|
|
1133
1471
|
);
|
|
1134
1472
|
}
|
|
1135
1473
|
return /* @__PURE__ */ jsxs5("svg", { viewBox: `0 0 ${width} ${height}`, className: "dialkit-spring-viz", children: [
|
|
1136
1474
|
gridLines,
|
|
1137
|
-
/* @__PURE__ */
|
|
1475
|
+
/* @__PURE__ */ jsx6(
|
|
1138
1476
|
"line",
|
|
1139
1477
|
{
|
|
1140
1478
|
x1: 0,
|
|
@@ -1146,7 +1484,7 @@ function SpringVisualization({ spring, isSimpleMode }) {
|
|
|
1146
1484
|
strokeDasharray: "4,4"
|
|
1147
1485
|
}
|
|
1148
1486
|
),
|
|
1149
|
-
/* @__PURE__ */
|
|
1487
|
+
/* @__PURE__ */ jsx6(
|
|
1150
1488
|
"path",
|
|
1151
1489
|
{
|
|
1152
1490
|
d: pathData,
|
|
@@ -1161,8 +1499,8 @@ function SpringVisualization({ spring, isSimpleMode }) {
|
|
|
1161
1499
|
}
|
|
1162
1500
|
|
|
1163
1501
|
// src/components/SpringControl.tsx
|
|
1164
|
-
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
1165
|
-
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";
|
|
1166
1504
|
function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
1167
1505
|
const mode = useSyncExternalStore2(
|
|
1168
1506
|
(cb) => DialStore.subscribe(panelId, cb),
|
|
@@ -1170,25 +1508,21 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1170
1508
|
() => DialStore.getSpringMode(panelId, path)
|
|
1171
1509
|
);
|
|
1172
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
|
+
}
|
|
1173
1520
|
const handleModeChange = (newMode) => {
|
|
1174
1521
|
DialStore.updateSpringMode(panelId, path, newMode);
|
|
1175
1522
|
if (newMode === "simple") {
|
|
1176
|
-
|
|
1177
|
-
onChange({
|
|
1178
|
-
...rest,
|
|
1179
|
-
type: "spring",
|
|
1180
|
-
visualDuration: spring.visualDuration ?? 0.3,
|
|
1181
|
-
bounce: spring.bounce ?? 0.2
|
|
1182
|
-
});
|
|
1523
|
+
onChange(cache.current.simple);
|
|
1183
1524
|
} else {
|
|
1184
|
-
|
|
1185
|
-
onChange({
|
|
1186
|
-
...rest,
|
|
1187
|
-
type: "spring",
|
|
1188
|
-
stiffness: spring.stiffness ?? 200,
|
|
1189
|
-
damping: spring.damping ?? 25,
|
|
1190
|
-
mass: spring.mass ?? 1
|
|
1191
|
-
});
|
|
1525
|
+
onChange(cache.current.advanced);
|
|
1192
1526
|
}
|
|
1193
1527
|
};
|
|
1194
1528
|
const handleUpdate = (key, value) => {
|
|
@@ -1200,11 +1534,11 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1200
1534
|
onChange({ ...rest, [key]: value });
|
|
1201
1535
|
}
|
|
1202
1536
|
};
|
|
1203
|
-
return /* @__PURE__ */
|
|
1204
|
-
/* @__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 }),
|
|
1205
1539
|
/* @__PURE__ */ jsxs6("div", { className: "dialkit-labeled-control", children: [
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
1540
|
+
/* @__PURE__ */ jsx7("span", { className: "dialkit-labeled-control-label", children: "Type" }),
|
|
1541
|
+
/* @__PURE__ */ jsx7(
|
|
1208
1542
|
SegmentedControl,
|
|
1209
1543
|
{
|
|
1210
1544
|
options: [
|
|
@@ -1217,7 +1551,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1217
1551
|
)
|
|
1218
1552
|
] }),
|
|
1219
1553
|
isSimpleMode ? /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
1220
|
-
/* @__PURE__ */
|
|
1554
|
+
/* @__PURE__ */ jsx7(
|
|
1221
1555
|
Slider,
|
|
1222
1556
|
{
|
|
1223
1557
|
label: "Duration",
|
|
@@ -1229,7 +1563,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1229
1563
|
unit: "s"
|
|
1230
1564
|
}
|
|
1231
1565
|
),
|
|
1232
|
-
/* @__PURE__ */
|
|
1566
|
+
/* @__PURE__ */ jsx7(
|
|
1233
1567
|
Slider,
|
|
1234
1568
|
{
|
|
1235
1569
|
label: "Bounce",
|
|
@@ -1241,7 +1575,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1241
1575
|
}
|
|
1242
1576
|
)
|
|
1243
1577
|
] }) : /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
1244
|
-
/* @__PURE__ */
|
|
1578
|
+
/* @__PURE__ */ jsx7(
|
|
1245
1579
|
Slider,
|
|
1246
1580
|
{
|
|
1247
1581
|
label: "Stiffness",
|
|
@@ -1252,7 +1586,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1252
1586
|
step: 10
|
|
1253
1587
|
}
|
|
1254
1588
|
),
|
|
1255
|
-
/* @__PURE__ */
|
|
1589
|
+
/* @__PURE__ */ jsx7(
|
|
1256
1590
|
Slider,
|
|
1257
1591
|
{
|
|
1258
1592
|
label: "Damping",
|
|
@@ -1263,7 +1597,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1263
1597
|
step: 1
|
|
1264
1598
|
}
|
|
1265
1599
|
),
|
|
1266
|
-
/* @__PURE__ */
|
|
1600
|
+
/* @__PURE__ */ jsx7(
|
|
1267
1601
|
Slider,
|
|
1268
1602
|
{
|
|
1269
1603
|
label: "Mass",
|
|
@@ -1279,7 +1613,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1279
1613
|
}
|
|
1280
1614
|
|
|
1281
1615
|
// src/components/EasingVisualization.tsx
|
|
1282
|
-
import { jsx as
|
|
1616
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1283
1617
|
function EasingVisualization({ easing }) {
|
|
1284
1618
|
const ease = easing.ease;
|
|
1285
1619
|
const s = 200;
|
|
@@ -1302,7 +1636,7 @@ function EasingVisualization({ easing }) {
|
|
|
1302
1636
|
preserveAspectRatio: "xMidYMid slice",
|
|
1303
1637
|
className: "dialkit-spring-viz dialkit-easing-viz",
|
|
1304
1638
|
children: [
|
|
1305
|
-
/* @__PURE__ */
|
|
1639
|
+
/* @__PURE__ */ jsx8(
|
|
1306
1640
|
"line",
|
|
1307
1641
|
{
|
|
1308
1642
|
x1: start.x,
|
|
@@ -1314,15 +1648,15 @@ function EasingVisualization({ easing }) {
|
|
|
1314
1648
|
strokeDasharray: "4,4"
|
|
1315
1649
|
}
|
|
1316
1650
|
),
|
|
1317
|
-
/* @__PURE__ */
|
|
1651
|
+
/* @__PURE__ */ jsx8("path", { d: curvePath, fill: "none", stroke: "rgba(255, 255, 255, 0.6)", strokeWidth: "2", strokeLinecap: "round" })
|
|
1318
1652
|
]
|
|
1319
1653
|
}
|
|
1320
1654
|
);
|
|
1321
1655
|
}
|
|
1322
1656
|
|
|
1323
1657
|
// src/components/TransitionControl.tsx
|
|
1324
|
-
import { useSyncExternalStore as useSyncExternalStore3, useState as
|
|
1325
|
-
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";
|
|
1326
1660
|
function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
1327
1661
|
const mode = useSyncExternalStore3(
|
|
1328
1662
|
(cb) => DialStore.subscribe(panelId, cb),
|
|
@@ -1331,26 +1665,28 @@ function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
|
1331
1665
|
);
|
|
1332
1666
|
const isEasing = mode === "easing";
|
|
1333
1667
|
const isSimpleSpring = mode === "simple";
|
|
1334
|
-
const
|
|
1335
|
-
|
|
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;
|
|
1336
1682
|
const handleModeChange = (newMode) => {
|
|
1337
1683
|
DialStore.updateTransitionMode(panelId, path, newMode);
|
|
1338
1684
|
if (newMode === "easing") {
|
|
1339
|
-
|
|
1340
|
-
onChange({ type: "easing", duration, ease: easing.ease });
|
|
1685
|
+
onChange(cache.current.easing);
|
|
1341
1686
|
} else if (newMode === "simple") {
|
|
1342
|
-
onChange(
|
|
1343
|
-
type: "spring",
|
|
1344
|
-
visualDuration: spring.visualDuration ?? (value.type === "easing" ? value.duration : 0.3),
|
|
1345
|
-
bounce: spring.bounce ?? 0.2
|
|
1346
|
-
});
|
|
1687
|
+
onChange(cache.current.simple);
|
|
1347
1688
|
} else {
|
|
1348
|
-
onChange(
|
|
1349
|
-
type: "spring",
|
|
1350
|
-
stiffness: spring.stiffness ?? 200,
|
|
1351
|
-
damping: spring.damping ?? 25,
|
|
1352
|
-
mass: spring.mass ?? 1
|
|
1353
|
-
});
|
|
1689
|
+
onChange(cache.current.advanced);
|
|
1354
1690
|
}
|
|
1355
1691
|
};
|
|
1356
1692
|
const handleSpringUpdate = (key, val) => {
|
|
@@ -1367,11 +1703,11 @@ function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
|
1367
1703
|
newEase[index] = val;
|
|
1368
1704
|
onChange({ ...easing, ease: newEase });
|
|
1369
1705
|
};
|
|
1370
|
-
return /* @__PURE__ */
|
|
1371
|
-
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 }),
|
|
1372
1708
|
/* @__PURE__ */ jsxs8("div", { className: "dialkit-labeled-control", children: [
|
|
1373
|
-
/* @__PURE__ */
|
|
1374
|
-
/* @__PURE__ */
|
|
1709
|
+
/* @__PURE__ */ jsx9("span", { className: "dialkit-labeled-control-label", children: "Type" }),
|
|
1710
|
+
/* @__PURE__ */ jsx9(
|
|
1375
1711
|
SegmentedControl,
|
|
1376
1712
|
{
|
|
1377
1713
|
options: [
|
|
@@ -1385,19 +1721,19 @@ function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
|
1385
1721
|
)
|
|
1386
1722
|
] }),
|
|
1387
1723
|
isEasing ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
1388
|
-
/* @__PURE__ */
|
|
1389
|
-
/* @__PURE__ */
|
|
1390
|
-
/* @__PURE__ */
|
|
1391
|
-
/* @__PURE__ */
|
|
1392
|
-
/* @__PURE__ */
|
|
1393
|
-
/* @__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 }) })
|
|
1394
1730
|
] }) : isSimpleSpring ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
1395
|
-
/* @__PURE__ */
|
|
1396
|
-
/* @__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 })
|
|
1397
1733
|
] }) : /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
1398
|
-
/* @__PURE__ */
|
|
1399
|
-
/* @__PURE__ */
|
|
1400
|
-
/* @__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 })
|
|
1401
1737
|
] })
|
|
1402
1738
|
] }) });
|
|
1403
1739
|
}
|
|
@@ -1412,8 +1748,8 @@ function parseEase(str) {
|
|
|
1412
1748
|
return null;
|
|
1413
1749
|
}
|
|
1414
1750
|
function EaseTextInput({ ease, onChange }) {
|
|
1415
|
-
const [editing, setEditing] =
|
|
1416
|
-
const [draft, setDraft] =
|
|
1751
|
+
const [editing, setEditing] = useState5(false);
|
|
1752
|
+
const [draft, setDraft] = useState5("");
|
|
1417
1753
|
const handleFocus = () => {
|
|
1418
1754
|
setDraft(formatEase(ease));
|
|
1419
1755
|
setEditing(true);
|
|
@@ -1429,8 +1765,8 @@ function EaseTextInput({ ease, onChange }) {
|
|
|
1429
1765
|
}
|
|
1430
1766
|
};
|
|
1431
1767
|
return /* @__PURE__ */ jsxs8("div", { className: "dialkit-labeled-control", children: [
|
|
1432
|
-
/* @__PURE__ */
|
|
1433
|
-
/* @__PURE__ */
|
|
1768
|
+
/* @__PURE__ */ jsx9("span", { className: "dialkit-labeled-control-label", children: "Ease" }),
|
|
1769
|
+
/* @__PURE__ */ jsx9(
|
|
1434
1770
|
"input",
|
|
1435
1771
|
{
|
|
1436
1772
|
type: "text",
|
|
@@ -1447,11 +1783,11 @@ function EaseTextInput({ ease, onChange }) {
|
|
|
1447
1783
|
}
|
|
1448
1784
|
|
|
1449
1785
|
// src/components/TextControl.tsx
|
|
1450
|
-
import { jsx as
|
|
1786
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1451
1787
|
function TextControl({ label, value, onChange, placeholder }) {
|
|
1452
1788
|
return /* @__PURE__ */ jsxs9("div", { className: "dialkit-text-control", children: [
|
|
1453
|
-
/* @__PURE__ */
|
|
1454
|
-
/* @__PURE__ */
|
|
1789
|
+
/* @__PURE__ */ jsx10("label", { className: "dialkit-text-label", children: label }),
|
|
1790
|
+
/* @__PURE__ */ jsx10(
|
|
1455
1791
|
"input",
|
|
1456
1792
|
{
|
|
1457
1793
|
type: "text",
|
|
@@ -1465,10 +1801,10 @@ function TextControl({ label, value, onChange, placeholder }) {
|
|
|
1465
1801
|
}
|
|
1466
1802
|
|
|
1467
1803
|
// src/components/SelectControl.tsx
|
|
1468
|
-
import { useState as
|
|
1804
|
+
import { useState as useState6, useRef as useRef8, useEffect as useEffect5, useCallback as useCallback4 } from "react";
|
|
1469
1805
|
import { createPortal } from "react-dom";
|
|
1470
|
-
import { motion as
|
|
1471
|
-
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";
|
|
1472
1808
|
function toTitleCase(s) {
|
|
1473
1809
|
return s.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
1474
1810
|
}
|
|
@@ -1478,14 +1814,14 @@ function normalizeOptions(options) {
|
|
|
1478
1814
|
);
|
|
1479
1815
|
}
|
|
1480
1816
|
function SelectControl({ label, value, options, onChange }) {
|
|
1481
|
-
const [isOpen, setIsOpen] =
|
|
1482
|
-
const triggerRef =
|
|
1483
|
-
const dropdownRef =
|
|
1484
|
-
const [portalTarget, setPortalTarget] =
|
|
1485
|
-
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);
|
|
1486
1822
|
const normalized = normalizeOptions(options);
|
|
1487
1823
|
const selectedOption = normalized.find((o) => o.value === value);
|
|
1488
|
-
const updatePos =
|
|
1824
|
+
const updatePos = useCallback4(() => {
|
|
1489
1825
|
const el = triggerRef.current;
|
|
1490
1826
|
if (!el) return;
|
|
1491
1827
|
const rect = el.getBoundingClientRect();
|
|
@@ -1499,15 +1835,15 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1499
1835
|
above
|
|
1500
1836
|
});
|
|
1501
1837
|
}, [normalized.length]);
|
|
1502
|
-
|
|
1838
|
+
useEffect5(() => {
|
|
1503
1839
|
const root = triggerRef.current?.closest(".dialkit-root");
|
|
1504
1840
|
setPortalTarget(root ?? document.body);
|
|
1505
1841
|
}, []);
|
|
1506
|
-
|
|
1842
|
+
useEffect5(() => {
|
|
1507
1843
|
if (!isOpen) return;
|
|
1508
1844
|
updatePos();
|
|
1509
1845
|
}, [isOpen, updatePos]);
|
|
1510
|
-
|
|
1846
|
+
useEffect5(() => {
|
|
1511
1847
|
if (!isOpen) return;
|
|
1512
1848
|
const handleClick = (e) => {
|
|
1513
1849
|
const target = e.target;
|
|
@@ -1527,11 +1863,11 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1527
1863
|
onClick: () => setIsOpen(!isOpen),
|
|
1528
1864
|
"data-open": String(isOpen),
|
|
1529
1865
|
children: [
|
|
1530
|
-
/* @__PURE__ */
|
|
1866
|
+
/* @__PURE__ */ jsx11("span", { className: "dialkit-select-label", children: label }),
|
|
1531
1867
|
/* @__PURE__ */ jsxs10("div", { className: "dialkit-select-right", children: [
|
|
1532
|
-
/* @__PURE__ */
|
|
1533
|
-
/* @__PURE__ */
|
|
1534
|
-
|
|
1868
|
+
/* @__PURE__ */ jsx11("span", { className: "dialkit-select-value", children: selectedOption?.label ?? value }),
|
|
1869
|
+
/* @__PURE__ */ jsx11(
|
|
1870
|
+
motion3.svg,
|
|
1535
1871
|
{
|
|
1536
1872
|
className: "dialkit-select-chevron",
|
|
1537
1873
|
viewBox: "0 0 24 24",
|
|
@@ -1542,7 +1878,7 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1542
1878
|
strokeLinejoin: "round",
|
|
1543
1879
|
animate: { rotate: isOpen ? 180 : 0 },
|
|
1544
1880
|
transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
|
|
1545
|
-
children: /* @__PURE__ */
|
|
1881
|
+
children: /* @__PURE__ */ jsx11("path", { d: ICON_CHEVRON })
|
|
1546
1882
|
}
|
|
1547
1883
|
)
|
|
1548
1884
|
] })
|
|
@@ -1550,8 +1886,8 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1550
1886
|
}
|
|
1551
1887
|
),
|
|
1552
1888
|
portalTarget && createPortal(
|
|
1553
|
-
/* @__PURE__ */
|
|
1554
|
-
|
|
1889
|
+
/* @__PURE__ */ jsx11(AnimatePresence2, { children: isOpen && pos && /* @__PURE__ */ jsx11(
|
|
1890
|
+
motion3.div,
|
|
1555
1891
|
{
|
|
1556
1892
|
ref: dropdownRef,
|
|
1557
1893
|
className: "dialkit-select-dropdown",
|
|
@@ -1565,7 +1901,7 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1565
1901
|
width: pos.width,
|
|
1566
1902
|
...pos.above ? { bottom: window.innerHeight - pos.top, transformOrigin: "bottom" } : { top: pos.top, transformOrigin: "top" }
|
|
1567
1903
|
},
|
|
1568
|
-
children: normalized.map((option) => /* @__PURE__ */
|
|
1904
|
+
children: normalized.map((option) => /* @__PURE__ */ jsx11(
|
|
1569
1905
|
"button",
|
|
1570
1906
|
{
|
|
1571
1907
|
className: "dialkit-select-option",
|
|
@@ -1586,14 +1922,14 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1586
1922
|
}
|
|
1587
1923
|
|
|
1588
1924
|
// src/components/ColorControl.tsx
|
|
1589
|
-
import { useState as
|
|
1590
|
-
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";
|
|
1591
1927
|
var HEX_COLOR_REGEX = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;
|
|
1592
1928
|
function ColorControl({ label, value, onChange }) {
|
|
1593
|
-
const [isEditing, setIsEditing] =
|
|
1594
|
-
const [editValue, setEditValue] =
|
|
1595
|
-
const colorInputRef =
|
|
1596
|
-
|
|
1929
|
+
const [isEditing, setIsEditing] = useState7(false);
|
|
1930
|
+
const [editValue, setEditValue] = useState7(value);
|
|
1931
|
+
const colorInputRef = useRef9(null);
|
|
1932
|
+
useEffect6(() => {
|
|
1597
1933
|
if (!isEditing) {
|
|
1598
1934
|
setEditValue(value);
|
|
1599
1935
|
}
|
|
@@ -1615,9 +1951,9 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1615
1951
|
}
|
|
1616
1952
|
}
|
|
1617
1953
|
return /* @__PURE__ */ jsxs11("div", { className: "dialkit-color-control", children: [
|
|
1618
|
-
/* @__PURE__ */
|
|
1954
|
+
/* @__PURE__ */ jsx12("span", { className: "dialkit-color-label", children: label }),
|
|
1619
1955
|
/* @__PURE__ */ jsxs11("div", { className: "dialkit-color-inputs", children: [
|
|
1620
|
-
isEditing ? /* @__PURE__ */
|
|
1956
|
+
isEditing ? /* @__PURE__ */ jsx12(
|
|
1621
1957
|
"input",
|
|
1622
1958
|
{
|
|
1623
1959
|
type: "text",
|
|
@@ -1628,7 +1964,7 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1628
1964
|
onKeyDown: handleKeyDown,
|
|
1629
1965
|
autoFocus: true
|
|
1630
1966
|
}
|
|
1631
|
-
) : /* @__PURE__ */
|
|
1967
|
+
) : /* @__PURE__ */ jsx12(
|
|
1632
1968
|
"span",
|
|
1633
1969
|
{
|
|
1634
1970
|
className: "dialkit-color-hex",
|
|
@@ -1636,7 +1972,7 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1636
1972
|
children: (value ?? "").toUpperCase()
|
|
1637
1973
|
}
|
|
1638
1974
|
),
|
|
1639
|
-
/* @__PURE__ */
|
|
1975
|
+
/* @__PURE__ */ jsx12(
|
|
1640
1976
|
"button",
|
|
1641
1977
|
{
|
|
1642
1978
|
className: "dialkit-color-swatch",
|
|
@@ -1645,7 +1981,7 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1645
1981
|
title: "Pick color"
|
|
1646
1982
|
}
|
|
1647
1983
|
),
|
|
1648
|
-
/* @__PURE__ */
|
|
1984
|
+
/* @__PURE__ */ jsx12(
|
|
1649
1985
|
"input",
|
|
1650
1986
|
{
|
|
1651
1987
|
ref: colorInputRef,
|
|
@@ -1664,18 +2000,18 @@ function expandShorthandHex(hex) {
|
|
|
1664
2000
|
}
|
|
1665
2001
|
|
|
1666
2002
|
// src/components/PresetManager.tsx
|
|
1667
|
-
import { useState as
|
|
2003
|
+
import { useState as useState8, useRef as useRef10, useEffect as useEffect7, useCallback as useCallback5 } from "react";
|
|
1668
2004
|
import { createPortal as createPortal2 } from "react-dom";
|
|
1669
|
-
import { motion as
|
|
1670
|
-
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";
|
|
1671
2007
|
function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
1672
|
-
const [isOpen, setIsOpen] =
|
|
1673
|
-
const triggerRef =
|
|
1674
|
-
const dropdownRef =
|
|
1675
|
-
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 });
|
|
1676
2012
|
const hasPresets = presets.length > 0;
|
|
1677
2013
|
const activePreset = presets.find((p) => p.id === activePresetId);
|
|
1678
|
-
const open =
|
|
2014
|
+
const open = useCallback5(() => {
|
|
1679
2015
|
if (!hasPresets) return;
|
|
1680
2016
|
const rect = triggerRef.current?.getBoundingClientRect();
|
|
1681
2017
|
if (rect) {
|
|
@@ -1683,12 +2019,12 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1683
2019
|
}
|
|
1684
2020
|
setIsOpen(true);
|
|
1685
2021
|
}, [hasPresets]);
|
|
1686
|
-
const close =
|
|
1687
|
-
const toggle =
|
|
2022
|
+
const close = useCallback5(() => setIsOpen(false), []);
|
|
2023
|
+
const toggle = useCallback5(() => {
|
|
1688
2024
|
if (isOpen) close();
|
|
1689
2025
|
else open();
|
|
1690
2026
|
}, [isOpen, open, close]);
|
|
1691
|
-
|
|
2027
|
+
useEffect7(() => {
|
|
1692
2028
|
if (!isOpen) return;
|
|
1693
2029
|
const handler = (e) => {
|
|
1694
2030
|
const target = e.target;
|
|
@@ -1721,9 +2057,9 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1721
2057
|
"data-has-preset": String(!!activePreset),
|
|
1722
2058
|
"data-disabled": String(!hasPresets),
|
|
1723
2059
|
children: [
|
|
1724
|
-
/* @__PURE__ */
|
|
1725
|
-
/* @__PURE__ */
|
|
1726
|
-
|
|
2060
|
+
/* @__PURE__ */ jsx13("span", { className: "dialkit-preset-label", children: activePreset ? activePreset.name : "Version 1" }),
|
|
2061
|
+
/* @__PURE__ */ jsx13(
|
|
2062
|
+
motion4.svg,
|
|
1727
2063
|
{
|
|
1728
2064
|
className: "dialkit-select-chevron",
|
|
1729
2065
|
viewBox: "0 0 24 24",
|
|
@@ -1734,15 +2070,15 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1734
2070
|
strokeLinejoin: "round",
|
|
1735
2071
|
animate: { rotate: isOpen ? 180 : 0, opacity: hasPresets ? 0.6 : 0.25 },
|
|
1736
2072
|
transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
|
|
1737
|
-
children: /* @__PURE__ */
|
|
2073
|
+
children: /* @__PURE__ */ jsx13("path", { d: ICON_CHEVRON })
|
|
1738
2074
|
}
|
|
1739
2075
|
)
|
|
1740
2076
|
]
|
|
1741
2077
|
}
|
|
1742
2078
|
),
|
|
1743
2079
|
createPortal2(
|
|
1744
|
-
/* @__PURE__ */
|
|
1745
|
-
|
|
2080
|
+
/* @__PURE__ */ jsx13(AnimatePresence3, { children: isOpen && /* @__PURE__ */ jsxs12(
|
|
2081
|
+
motion4.div,
|
|
1746
2082
|
{
|
|
1747
2083
|
ref: dropdownRef,
|
|
1748
2084
|
className: "dialkit-root dialkit-preset-dropdown",
|
|
@@ -1752,13 +2088,13 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1752
2088
|
exit: { opacity: 0, y: 4, scale: 0.97, pointerEvents: "none" },
|
|
1753
2089
|
transition: { type: "spring", visualDuration: 0.15, bounce: 0 },
|
|
1754
2090
|
children: [
|
|
1755
|
-
/* @__PURE__ */
|
|
2091
|
+
/* @__PURE__ */ jsx13(
|
|
1756
2092
|
"div",
|
|
1757
2093
|
{
|
|
1758
2094
|
className: "dialkit-preset-item",
|
|
1759
2095
|
"data-active": String(!activePresetId),
|
|
1760
2096
|
onClick: () => handleSelect(null),
|
|
1761
|
-
children: /* @__PURE__ */
|
|
2097
|
+
children: /* @__PURE__ */ jsx13("span", { className: "dialkit-preset-name", children: "Version 1" })
|
|
1762
2098
|
}
|
|
1763
2099
|
),
|
|
1764
2100
|
presets.map((preset) => /* @__PURE__ */ jsxs12(
|
|
@@ -1768,20 +2104,14 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1768
2104
|
"data-active": String(preset.id === activePresetId),
|
|
1769
2105
|
onClick: () => handleSelect(preset.id),
|
|
1770
2106
|
children: [
|
|
1771
|
-
/* @__PURE__ */
|
|
1772
|
-
/* @__PURE__ */
|
|
2107
|
+
/* @__PURE__ */ jsx13("span", { className: "dialkit-preset-name", children: preset.name }),
|
|
2108
|
+
/* @__PURE__ */ jsx13(
|
|
1773
2109
|
"button",
|
|
1774
2110
|
{
|
|
1775
2111
|
className: "dialkit-preset-delete",
|
|
1776
2112
|
onClick: (e) => handleDelete(e, preset.id),
|
|
1777
2113
|
title: "Delete preset",
|
|
1778
|
-
children: /* @__PURE__ */
|
|
1779
|
-
/* @__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" }),
|
|
1780
|
-
/* @__PURE__ */ jsx12("path", { d: "M10 11V16" }),
|
|
1781
|
-
/* @__PURE__ */ jsx12("path", { d: "M14 11V16" }),
|
|
1782
|
-
/* @__PURE__ */ jsx12("path", { d: "M3.5 6H20.5" }),
|
|
1783
|
-
/* @__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" })
|
|
1784
|
-
] })
|
|
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)) })
|
|
1785
2115
|
}
|
|
1786
2116
|
)
|
|
1787
2117
|
]
|
|
@@ -1797,10 +2127,12 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1797
2127
|
}
|
|
1798
2128
|
|
|
1799
2129
|
// src/components/Panel.tsx
|
|
1800
|
-
import { Fragment as Fragment3, jsx as
|
|
2130
|
+
import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1801
2131
|
function Panel({ panel, defaultOpen = true, inline = false }) {
|
|
1802
|
-
const [copied, setCopied] =
|
|
1803
|
-
const [isPanelOpen, setIsPanelOpen] =
|
|
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;
|
|
1804
2136
|
const values = useSyncExternalStore4(
|
|
1805
2137
|
(cb) => DialStore.subscribe(panel.id, cb),
|
|
1806
2138
|
() => DialStore.getValues(panel.id),
|
|
@@ -1829,7 +2161,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1829
2161
|
const value = values[control.path];
|
|
1830
2162
|
switch (control.type) {
|
|
1831
2163
|
case "slider":
|
|
1832
|
-
return /* @__PURE__ */
|
|
2164
|
+
return /* @__PURE__ */ jsx14(
|
|
1833
2165
|
Slider,
|
|
1834
2166
|
{
|
|
1835
2167
|
label: control.label,
|
|
@@ -1837,22 +2169,26 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1837
2169
|
onChange: (v) => DialStore.updateValue(panel.id, control.path, v),
|
|
1838
2170
|
min: control.min,
|
|
1839
2171
|
max: control.max,
|
|
1840
|
-
step: control.step
|
|
2172
|
+
step: control.step,
|
|
2173
|
+
shortcut: control.shortcut,
|
|
2174
|
+
shortcutActive: shortcutCtx.activePanelId === panel.id && shortcutCtx.activePath === control.path
|
|
1841
2175
|
},
|
|
1842
2176
|
control.path
|
|
1843
2177
|
);
|
|
1844
2178
|
case "toggle":
|
|
1845
|
-
return /* @__PURE__ */
|
|
2179
|
+
return /* @__PURE__ */ jsx14(
|
|
1846
2180
|
Toggle,
|
|
1847
2181
|
{
|
|
1848
2182
|
label: control.label,
|
|
1849
2183
|
checked: value,
|
|
1850
|
-
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
|
|
1851
2187
|
},
|
|
1852
2188
|
control.path
|
|
1853
2189
|
);
|
|
1854
2190
|
case "spring":
|
|
1855
|
-
return /* @__PURE__ */
|
|
2191
|
+
return /* @__PURE__ */ jsx14(
|
|
1856
2192
|
SpringControl,
|
|
1857
2193
|
{
|
|
1858
2194
|
panelId: panel.id,
|
|
@@ -1864,7 +2200,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1864
2200
|
control.path
|
|
1865
2201
|
);
|
|
1866
2202
|
case "transition":
|
|
1867
|
-
return /* @__PURE__ */
|
|
2203
|
+
return /* @__PURE__ */ jsx14(
|
|
1868
2204
|
TransitionControl,
|
|
1869
2205
|
{
|
|
1870
2206
|
panelId: panel.id,
|
|
@@ -1876,9 +2212,9 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1876
2212
|
control.path
|
|
1877
2213
|
);
|
|
1878
2214
|
case "folder":
|
|
1879
|
-
return /* @__PURE__ */
|
|
2215
|
+
return /* @__PURE__ */ jsx14(Folder, { title: control.label, defaultOpen: control.defaultOpen ?? true, children: control.children?.map(renderControl) }, control.path);
|
|
1880
2216
|
case "text":
|
|
1881
|
-
return /* @__PURE__ */
|
|
2217
|
+
return /* @__PURE__ */ jsx14(
|
|
1882
2218
|
TextControl,
|
|
1883
2219
|
{
|
|
1884
2220
|
label: control.label,
|
|
@@ -1889,7 +2225,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1889
2225
|
control.path
|
|
1890
2226
|
);
|
|
1891
2227
|
case "select":
|
|
1892
|
-
return /* @__PURE__ */
|
|
2228
|
+
return /* @__PURE__ */ jsx14(
|
|
1893
2229
|
SelectControl,
|
|
1894
2230
|
{
|
|
1895
2231
|
label: control.label,
|
|
@@ -1900,7 +2236,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1900
2236
|
control.path
|
|
1901
2237
|
);
|
|
1902
2238
|
case "color":
|
|
1903
|
-
return /* @__PURE__ */
|
|
2239
|
+
return /* @__PURE__ */ jsx14(
|
|
1904
2240
|
ColorControl,
|
|
1905
2241
|
{
|
|
1906
2242
|
label: control.label,
|
|
@@ -1910,7 +2246,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1910
2246
|
control.path
|
|
1911
2247
|
);
|
|
1912
2248
|
case "action":
|
|
1913
|
-
return /* @__PURE__ */
|
|
2249
|
+
return /* @__PURE__ */ jsx14(
|
|
1914
2250
|
"button",
|
|
1915
2251
|
{
|
|
1916
2252
|
className: "dialkit-button",
|
|
@@ -1928,24 +2264,18 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1928
2264
|
};
|
|
1929
2265
|
const iconTransition = { type: "spring", visualDuration: 0.4, bounce: 0.1 };
|
|
1930
2266
|
const toolbar = /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
1931
|
-
/* @__PURE__ */
|
|
1932
|
-
|
|
2267
|
+
/* @__PURE__ */ jsx14(
|
|
2268
|
+
motion5.button,
|
|
1933
2269
|
{
|
|
1934
2270
|
className: "dialkit-toolbar-add",
|
|
1935
2271
|
onClick: handleAddPreset,
|
|
1936
2272
|
title: "Add preset",
|
|
1937
2273
|
whileTap: { scale: 0.9 },
|
|
1938
2274
|
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
1939
|
-
children: /* @__PURE__ */
|
|
1940
|
-
/* @__PURE__ */ jsx13("path", { d: "M4 6H20" }),
|
|
1941
|
-
/* @__PURE__ */ jsx13("path", { d: "M4 12H10" }),
|
|
1942
|
-
/* @__PURE__ */ jsx13("path", { d: "M15 15L21 15" }),
|
|
1943
|
-
/* @__PURE__ */ jsx13("path", { d: "M18 12V18" }),
|
|
1944
|
-
/* @__PURE__ */ jsx13("path", { d: "M4 18H10" })
|
|
1945
|
-
] })
|
|
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)) })
|
|
1946
2276
|
}
|
|
1947
2277
|
),
|
|
1948
|
-
/* @__PURE__ */
|
|
2278
|
+
/* @__PURE__ */ jsx14(
|
|
1949
2279
|
PresetManager,
|
|
1950
2280
|
{
|
|
1951
2281
|
panelId: panel.id,
|
|
@@ -1954,65 +2284,71 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1954
2284
|
onAdd: handleAddPreset
|
|
1955
2285
|
}
|
|
1956
2286
|
),
|
|
1957
|
-
/* @__PURE__ */
|
|
1958
|
-
|
|
2287
|
+
/* @__PURE__ */ jsx14(
|
|
2288
|
+
motion5.button,
|
|
1959
2289
|
{
|
|
1960
|
-
className: "dialkit-toolbar-
|
|
2290
|
+
className: "dialkit-toolbar-add",
|
|
1961
2291
|
onClick: handleCopy,
|
|
1962
2292
|
title: "Copy parameters",
|
|
1963
|
-
whileTap: { scale: 0.
|
|
2293
|
+
whileTap: { scale: 0.9 },
|
|
1964
2294
|
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
1965
|
-
children:
|
|
1966
|
-
|
|
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
|
-
"Copy"
|
|
2002
|
-
]
|
|
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
|
+
) }) })
|
|
2003
2330
|
}
|
|
2004
2331
|
)
|
|
2005
2332
|
] });
|
|
2006
|
-
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() }) });
|
|
2007
2334
|
}
|
|
2008
2335
|
|
|
2009
2336
|
// src/components/DialRoot.tsx
|
|
2010
|
-
import { jsx as
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
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);
|
|
2014
2343
|
const inline = mode === "inline";
|
|
2015
|
-
|
|
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,13 +2356,95 @@ function DialRoot({ position = "top-right", defaultOpen = true, mode = "popover"
|
|
|
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
|
+
) }) });
|
|
2030
2448
|
if (inline) {
|
|
2031
2449
|
return content;
|
|
2032
2450
|
}
|
|
@@ -2034,9 +2452,9 @@ function DialRoot({ position = "top-right", defaultOpen = true, mode = "popover"
|
|
|
2034
2452
|
}
|
|
2035
2453
|
|
|
2036
2454
|
// src/components/ButtonGroup.tsx
|
|
2037
|
-
import { jsx as
|
|
2455
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
2038
2456
|
function ButtonGroup({ buttons }) {
|
|
2039
|
-
return /* @__PURE__ */
|
|
2457
|
+
return /* @__PURE__ */ jsx16("div", { className: "dialkit-button-group", children: buttons.map((button, index) => /* @__PURE__ */ jsx16(
|
|
2040
2458
|
"button",
|
|
2041
2459
|
{
|
|
2042
2460
|
className: "dialkit-button",
|
|
@@ -2046,6 +2464,124 @@ function ButtonGroup({ buttons }) {
|
|
|
2046
2464
|
index
|
|
2047
2465
|
)) });
|
|
2048
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
|
+
}
|
|
2049
2585
|
export {
|
|
2050
2586
|
ButtonGroup,
|
|
2051
2587
|
ColorControl,
|
|
@@ -2055,6 +2591,7 @@ export {
|
|
|
2055
2591
|
Folder,
|
|
2056
2592
|
PresetManager,
|
|
2057
2593
|
SelectControl,
|
|
2594
|
+
ShortcutsMenu,
|
|
2058
2595
|
Slider,
|
|
2059
2596
|
SpringControl,
|
|
2060
2597
|
SpringVisualization,
|