dialkit 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +293 -2
- package/dist/index.cjs +905 -363
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -9
- package/dist/index.d.ts +46 -9
- package/dist/index.js +910 -370
- package/dist/index.js.map +1 -1
- package/dist/solid/index.cjs +1042 -532
- package/dist/solid/index.cjs.map +1 -1
- package/dist/solid/index.d.cts +36 -3
- package/dist/solid/index.d.ts +36 -3
- package/dist/solid/index.js +911 -402
- package/dist/solid/index.js.map +1 -1
- package/dist/store/index.cjs +490 -0
- package/dist/store/index.cjs.map +1 -0
- package/dist/store/index.d.cts +146 -0
- package/dist/store/index.d.ts +146 -0
- package/dist/store/index.js +465 -0
- package/dist/store/index.js.map +1 -0
- package/dist/styles.css +287 -25
- package/dist/svelte/Portal.svelte +30 -0
- package/dist/svelte/Portal.svelte.d.ts +9 -0
- package/dist/svelte/Portal.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ButtonGroup.svelte +16 -0
- package/dist/svelte/components/ButtonGroup.svelte.d.ts +11 -0
- package/dist/svelte/components/ButtonGroup.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ColorControl.svelte +81 -0
- package/dist/svelte/components/ColorControl.svelte.d.ts +9 -0
- package/dist/svelte/components/ColorControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ControlRenderer.svelte +96 -0
- package/dist/svelte/components/ControlRenderer.svelte.d.ts +11 -0
- package/dist/svelte/components/ControlRenderer.svelte.d.ts.map +1 -0
- package/dist/svelte/components/DialRoot.svelte +79 -0
- package/dist/svelte/components/DialRoot.svelte.d.ts +14 -0
- package/dist/svelte/components/DialRoot.svelte.d.ts.map +1 -0
- package/dist/svelte/components/EasingVisualization.svelte +50 -0
- package/dist/svelte/components/EasingVisualization.svelte.d.ts +10 -0
- package/dist/svelte/components/EasingVisualization.svelte.d.ts.map +1 -0
- package/dist/svelte/components/Folder.svelte +213 -0
- package/dist/svelte/components/Folder.svelte.d.ts +14 -0
- package/dist/svelte/components/Folder.svelte.d.ts.map +1 -0
- package/dist/svelte/components/Panel.svelte +149 -0
- package/dist/svelte/components/Panel.svelte.d.ts +10 -0
- package/dist/svelte/components/Panel.svelte.d.ts.map +1 -0
- package/dist/svelte/components/PresetManager.svelte +157 -0
- package/dist/svelte/components/PresetManager.svelte.d.ts +10 -0
- package/dist/svelte/components/PresetManager.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SegmentedControl.svelte +62 -0
- package/dist/svelte/components/SegmentedControl.svelte.d.ts +13 -0
- package/dist/svelte/components/SegmentedControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SelectControl.svelte +152 -0
- package/dist/svelte/components/SelectControl.svelte.d.ts +14 -0
- package/dist/svelte/components/SelectControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ShortcutListener.svelte +265 -0
- package/dist/svelte/components/ShortcutListener.svelte.d.ts +13 -0
- package/dist/svelte/components/ShortcutListener.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ShortcutsMenu.svelte +128 -0
- package/dist/svelte/components/ShortcutsMenu.svelte.d.ts +7 -0
- package/dist/svelte/components/ShortcutsMenu.svelte.d.ts.map +1 -0
- package/dist/svelte/components/Slider.svelte +332 -0
- package/dist/svelte/components/Slider.svelte.d.ts +16 -0
- package/dist/svelte/components/Slider.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SpringControl.svelte +126 -0
- package/dist/svelte/components/SpringControl.svelte.d.ts +12 -0
- package/dist/svelte/components/SpringControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SpringVisualization.svelte +115 -0
- package/dist/svelte/components/SpringVisualization.svelte.d.ts +9 -0
- package/dist/svelte/components/SpringVisualization.svelte.d.ts.map +1 -0
- package/dist/svelte/components/TextControl.svelte +19 -0
- package/dist/svelte/components/TextControl.svelte.d.ts +10 -0
- package/dist/svelte/components/TextControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/Toggle.svelte +32 -0
- package/dist/svelte/components/Toggle.svelte.d.ts +12 -0
- package/dist/svelte/components/Toggle.svelte.d.ts.map +1 -0
- package/dist/svelte/components/TransitionControl.svelte +203 -0
- package/dist/svelte/components/TransitionControl.svelte.d.ts +12 -0
- package/dist/svelte/components/TransitionControl.svelte.d.ts.map +1 -0
- package/dist/svelte/components/transitions.d.ts +6 -0
- package/dist/svelte/components/transitions.d.ts.map +1 -0
- package/dist/svelte/components/transitions.js +14 -0
- package/dist/svelte/createDialKit.svelte.d.ts +8 -0
- package/dist/svelte/createDialKit.svelte.d.ts.map +1 -0
- package/dist/svelte/createDialKit.svelte.js +82 -0
- package/dist/svelte/index.d.ts +23 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +23 -0
- package/dist/svelte/shims.d.ts +9 -0
- package/dist/svelte/theme-css.d.ts +2 -0
- package/dist/svelte/theme-css.d.ts.map +1 -0
- package/dist/svelte/theme-css.js +1328 -0
- package/dist/vue/index.cjs +3056 -0
- package/dist/vue/index.cjs.map +1 -0
- package/dist/vue/index.d.cts +675 -0
- package/dist/vue/index.d.ts +675 -0
- package/dist/vue/index.js +3014 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +50 -6
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,7 @@ __export(index_exports, {
|
|
|
29
29
|
Folder: () => Folder,
|
|
30
30
|
PresetManager: () => PresetManager,
|
|
31
31
|
SelectControl: () => SelectControl,
|
|
32
|
+
ShortcutsMenu: () => ShortcutsMenu,
|
|
32
33
|
Slider: () => Slider,
|
|
33
34
|
SpringControl: () => SpringControl,
|
|
34
35
|
SpringVisualization: () => SpringVisualization,
|
|
@@ -55,22 +56,22 @@ var DialStoreClass = class {
|
|
|
55
56
|
this.activePreset = /* @__PURE__ */ new Map();
|
|
56
57
|
this.baseValues = /* @__PURE__ */ new Map();
|
|
57
58
|
}
|
|
58
|
-
registerPanel(id, name, config) {
|
|
59
|
-
const controls = this.parseConfig(config, "");
|
|
59
|
+
registerPanel(id, name, config, shortcuts) {
|
|
60
|
+
const controls = this.parseConfig(config, "", shortcuts);
|
|
60
61
|
const values = this.flattenValues(config, "");
|
|
61
62
|
this.initTransitionModes(config, "", values);
|
|
62
|
-
this.panels.set(id, { id, name, controls, values });
|
|
63
|
+
this.panels.set(id, { id, name, controls, values, shortcuts: shortcuts ?? {} });
|
|
63
64
|
this.snapshots.set(id, { ...values });
|
|
64
65
|
this.baseValues.set(id, { ...values });
|
|
65
66
|
this.notifyGlobal();
|
|
66
67
|
}
|
|
67
|
-
updatePanel(id, name, config) {
|
|
68
|
+
updatePanel(id, name, config, shortcuts) {
|
|
68
69
|
const existing = this.panels.get(id);
|
|
69
70
|
if (!existing) {
|
|
70
|
-
this.registerPanel(id, name, config);
|
|
71
|
+
this.registerPanel(id, name, config, shortcuts);
|
|
71
72
|
return;
|
|
72
73
|
}
|
|
73
|
-
const controls = this.parseConfig(config, "");
|
|
74
|
+
const controls = this.parseConfig(config, "", shortcuts);
|
|
74
75
|
const controlsByPath = this.mapControlsByPath(controls);
|
|
75
76
|
const defaultValues = this.flattenValues(config, "");
|
|
76
77
|
const nextValues = {};
|
|
@@ -92,7 +93,7 @@ var DialStoreClass = class {
|
|
|
92
93
|
nextValues[path] = mode;
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
|
-
const nextPanel = { id, name, controls, values: nextValues };
|
|
96
|
+
const nextPanel = { id, name, controls, values: nextValues, shortcuts: shortcuts ?? existing.shortcuts };
|
|
96
97
|
this.panels.set(id, nextPanel);
|
|
97
98
|
this.snapshots.set(id, { ...nextValues });
|
|
98
99
|
const previousBaseValues = this.baseValues.get(id) ?? {};
|
|
@@ -250,6 +251,44 @@ var DialStoreClass = class {
|
|
|
250
251
|
this.activePreset.set(panelId, null);
|
|
251
252
|
this.notify(panelId);
|
|
252
253
|
}
|
|
254
|
+
resolveShortcutTarget(key, modifier) {
|
|
255
|
+
for (const panel of this.panels.values()) {
|
|
256
|
+
for (const [path, shortcut] of Object.entries(panel.shortcuts)) {
|
|
257
|
+
if (!shortcut.key) continue;
|
|
258
|
+
if (shortcut.key.toLowerCase() !== key.toLowerCase()) continue;
|
|
259
|
+
const scMod = shortcut.modifier ?? void 0;
|
|
260
|
+
if (scMod !== modifier) continue;
|
|
261
|
+
const control = this.findControlByPath(panel.controls, path);
|
|
262
|
+
if (control) {
|
|
263
|
+
return { panelId: panel.id, path, control };
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
resolveScrollOnlyTargets() {
|
|
270
|
+
const results = [];
|
|
271
|
+
for (const panel of this.panels.values()) {
|
|
272
|
+
for (const [path, shortcut] of Object.entries(panel.shortcuts)) {
|
|
273
|
+
if ((shortcut.interaction ?? "scroll") !== "scroll-only") continue;
|
|
274
|
+
const control = this.findControlByPath(panel.controls, path);
|
|
275
|
+
if (control) {
|
|
276
|
+
results.push({ panelId: panel.id, path, control, shortcut });
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return results;
|
|
281
|
+
}
|
|
282
|
+
findControlByPath(controls, path) {
|
|
283
|
+
for (const control of controls) {
|
|
284
|
+
if (control.path === path) return control;
|
|
285
|
+
if (control.type === "folder" && control.children) {
|
|
286
|
+
const found = this.findControlByPath(control.children, path);
|
|
287
|
+
if (found) return found;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
253
292
|
notify(panelId) {
|
|
254
293
|
this.listeners.get(panelId)?.forEach((fn) => fn());
|
|
255
294
|
}
|
|
@@ -271,12 +310,13 @@ var DialStoreClass = class {
|
|
|
271
310
|
}
|
|
272
311
|
}
|
|
273
312
|
}
|
|
274
|
-
parseConfig(config, prefix) {
|
|
313
|
+
parseConfig(config, prefix, shortcuts) {
|
|
275
314
|
const controls = [];
|
|
276
315
|
for (const [key, value] of Object.entries(config)) {
|
|
277
316
|
if (key === "_collapsed") continue;
|
|
278
317
|
const path = prefix ? `${prefix}.${key}` : key;
|
|
279
318
|
const label = this.formatLabel(key);
|
|
319
|
+
const shortcut = shortcuts?.[path];
|
|
280
320
|
if (Array.isArray(value) && value.length <= 4 && typeof value[0] === "number") {
|
|
281
321
|
controls.push({
|
|
282
322
|
type: "slider",
|
|
@@ -284,13 +324,14 @@ var DialStoreClass = class {
|
|
|
284
324
|
label,
|
|
285
325
|
min: value[1],
|
|
286
326
|
max: value[2],
|
|
287
|
-
step: value[3] ?? this.inferStep(value[1], value[2])
|
|
327
|
+
step: value[3] ?? this.inferStep(value[1], value[2]),
|
|
328
|
+
shortcut
|
|
288
329
|
});
|
|
289
330
|
} else if (typeof value === "number") {
|
|
290
331
|
const { min, max, step } = this.inferRange(value);
|
|
291
|
-
controls.push({ type: "slider", path, label, min, max, step });
|
|
332
|
+
controls.push({ type: "slider", path, label, min, max, step, shortcut });
|
|
292
333
|
} else if (typeof value === "boolean") {
|
|
293
|
-
controls.push({ type: "toggle", path, label });
|
|
334
|
+
controls.push({ type: "toggle", path, label, shortcut });
|
|
294
335
|
} else if (this.isSpringConfig(value) || this.isEasingConfig(value)) {
|
|
295
336
|
controls.push({ type: "transition", path, label });
|
|
296
337
|
} else if (this.isActionConfig(value)) {
|
|
@@ -315,7 +356,7 @@ var DialStoreClass = class {
|
|
|
315
356
|
path,
|
|
316
357
|
label,
|
|
317
358
|
defaultOpen,
|
|
318
|
-
children: this.parseConfig(folderConfig, path)
|
|
359
|
+
children: this.parseConfig(folderConfig, path, shortcuts)
|
|
319
360
|
});
|
|
320
361
|
}
|
|
321
362
|
}
|
|
@@ -473,8 +514,11 @@ function useDialKit(name, config, options) {
|
|
|
473
514
|
configRef.current = config;
|
|
474
515
|
const onActionRef = (0, import_react.useRef)(options?.onAction);
|
|
475
516
|
onActionRef.current = options?.onAction;
|
|
517
|
+
const shortcutsRef = (0, import_react.useRef)(options?.shortcuts);
|
|
518
|
+
shortcutsRef.current = options?.shortcuts;
|
|
519
|
+
const serializedShortcuts = JSON.stringify(options?.shortcuts);
|
|
476
520
|
(0, import_react.useEffect)(() => {
|
|
477
|
-
DialStore.registerPanel(panelId, name, configRef.current);
|
|
521
|
+
DialStore.registerPanel(panelId, name, configRef.current, shortcutsRef.current);
|
|
478
522
|
return () => DialStore.unregisterPanel(panelId);
|
|
479
523
|
}, [panelId, name]);
|
|
480
524
|
const mountedRef = (0, import_react.useRef)(false);
|
|
@@ -483,8 +527,8 @@ function useDialKit(name, config, options) {
|
|
|
483
527
|
mountedRef.current = true;
|
|
484
528
|
return;
|
|
485
529
|
}
|
|
486
|
-
DialStore.updatePanel(panelId, name, configRef.current);
|
|
487
|
-
}, [panelId, name, serializedConfig]);
|
|
530
|
+
DialStore.updatePanel(panelId, name, configRef.current, shortcutsRef.current);
|
|
531
|
+
}, [panelId, name, serializedConfig, serializedShortcuts]);
|
|
488
532
|
(0, import_react.useEffect)(() => {
|
|
489
533
|
return DialStore.subscribeActions(panelId, (action) => {
|
|
490
534
|
onActionRef.current?.(action);
|
|
@@ -557,16 +601,329 @@ var import_react_dom3 = require("react-dom");
|
|
|
557
601
|
var import_react15 = require("react");
|
|
558
602
|
var import_react16 = require("motion/react");
|
|
559
603
|
|
|
560
|
-
// src/components/
|
|
604
|
+
// src/components/ShortcutListener.tsx
|
|
561
605
|
var import_react2 = require("react");
|
|
562
|
-
|
|
606
|
+
|
|
607
|
+
// src/shortcut-utils.ts
|
|
608
|
+
function decimalsForStep(step) {
|
|
609
|
+
const s = step.toString();
|
|
610
|
+
const dot = s.indexOf(".");
|
|
611
|
+
return dot === -1 ? 0 : s.length - dot - 1;
|
|
612
|
+
}
|
|
613
|
+
function roundValue(val, step) {
|
|
614
|
+
const raw = Math.round(val / step) * step;
|
|
615
|
+
return parseFloat(raw.toFixed(decimalsForStep(step)));
|
|
616
|
+
}
|
|
617
|
+
function getEffectiveStep(control, shortcut) {
|
|
618
|
+
const min = control.min ?? 0;
|
|
619
|
+
const max = control.max ?? 1;
|
|
620
|
+
const range = max - min;
|
|
621
|
+
const mode = shortcut.mode ?? "normal";
|
|
622
|
+
return mode === "fine" ? range * 0.01 : mode === "coarse" ? range * 0.1 : control.step ?? 1;
|
|
623
|
+
}
|
|
624
|
+
function applySliderDelta(panelId, path, control, effectiveStep, direction) {
|
|
625
|
+
const currentValue = DialStore.getValue(panelId, path);
|
|
626
|
+
const min = control.min ?? 0;
|
|
627
|
+
const max = control.max ?? 1;
|
|
628
|
+
const newValue = Math.max(min, Math.min(max, currentValue + direction * effectiveStep));
|
|
629
|
+
DialStore.updateValue(panelId, path, roundValue(newValue, effectiveStep));
|
|
630
|
+
}
|
|
631
|
+
function snapToDecile(rawValue, min, max) {
|
|
632
|
+
const normalized = (rawValue - min) / (max - min);
|
|
633
|
+
const nearest = Math.round(normalized * 10) / 10;
|
|
634
|
+
if (Math.abs(normalized - nearest) <= 0.03125) {
|
|
635
|
+
return min + nearest * (max - min);
|
|
636
|
+
}
|
|
637
|
+
return rawValue;
|
|
638
|
+
}
|
|
639
|
+
function isInputFocused() {
|
|
640
|
+
const el = document.activeElement;
|
|
641
|
+
if (!el) return false;
|
|
642
|
+
const tag = el.tagName;
|
|
643
|
+
if (tag === "INPUT" || tag === "TEXTAREA") return true;
|
|
644
|
+
if (el.contentEditable === "true") return true;
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
function getActiveModifier(e) {
|
|
648
|
+
if (e.altKey) return "alt";
|
|
649
|
+
if (e.shiftKey) return "shift";
|
|
650
|
+
if (e.metaKey) return "meta";
|
|
651
|
+
return void 0;
|
|
652
|
+
}
|
|
653
|
+
function findControl(controls, path) {
|
|
654
|
+
for (const control of controls) {
|
|
655
|
+
if (control.path === path) return control;
|
|
656
|
+
if (control.type === "folder" && control.children) {
|
|
657
|
+
const found = findControl(control.children, path);
|
|
658
|
+
if (found) return found;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return null;
|
|
662
|
+
}
|
|
663
|
+
var DRAG_SENSITIVITY = 4;
|
|
664
|
+
function formatInteractionLabel(interaction) {
|
|
665
|
+
switch (interaction) {
|
|
666
|
+
case "drag":
|
|
667
|
+
return "Drag";
|
|
668
|
+
case "move":
|
|
669
|
+
return "Move";
|
|
670
|
+
case "scroll-only":
|
|
671
|
+
return "Scroll";
|
|
672
|
+
default:
|
|
673
|
+
return "Scroll";
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
function formatSliderShortcut(sc) {
|
|
677
|
+
const interaction = sc.interaction ?? "scroll";
|
|
678
|
+
const actionLabel = formatInteractionLabel(interaction);
|
|
679
|
+
if (!sc.key) return actionLabel;
|
|
680
|
+
const mod = formatModifier(sc.modifier);
|
|
681
|
+
return `${mod}${sc.key.toUpperCase()}+${actionLabel}`;
|
|
682
|
+
}
|
|
683
|
+
function formatToggleShortcut(sc) {
|
|
684
|
+
if (!sc.key) return "Press";
|
|
685
|
+
const mod = formatModifier(sc.modifier);
|
|
686
|
+
return `${mod}${sc.key.toUpperCase()}`;
|
|
687
|
+
}
|
|
688
|
+
function formatModifier(modifier) {
|
|
689
|
+
return modifier === "alt" ? "\u2325" : modifier === "shift" ? "\u21E7" : modifier === "meta" ? "\u2318" : "";
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// src/components/ShortcutListener.tsx
|
|
563
693
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
const [
|
|
567
|
-
const
|
|
568
|
-
const
|
|
694
|
+
var ShortcutContext = (0, import_react2.createContext)({ activePanelId: null, activePath: null });
|
|
695
|
+
function ShortcutListener({ children }) {
|
|
696
|
+
const [activeShortcut, setActiveShortcut] = (0, import_react2.useState)({ activePanelId: null, activePath: null });
|
|
697
|
+
const activeKeysRef = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
698
|
+
const isDraggingRef = (0, import_react2.useRef)(false);
|
|
699
|
+
const lastMouseXRef = (0, import_react2.useRef)(null);
|
|
700
|
+
const dragAccumulatorRef = (0, import_react2.useRef)(0);
|
|
701
|
+
const resolveActiveTarget = (0, import_react2.useCallback)((interaction) => {
|
|
702
|
+
for (const key of activeKeysRef.current) {
|
|
703
|
+
const panels = DialStore.getPanels();
|
|
704
|
+
for (const panel of panels) {
|
|
705
|
+
for (const [path, shortcut] of Object.entries(panel.shortcuts)) {
|
|
706
|
+
if (!shortcut.key) continue;
|
|
707
|
+
if (shortcut.key.toLowerCase() !== key) continue;
|
|
708
|
+
if ((shortcut.interaction ?? "scroll") !== interaction) continue;
|
|
709
|
+
const control = findControl(panel.controls, path);
|
|
710
|
+
if (control && control.type === "slider") {
|
|
711
|
+
return { panelId: panel.id, path, control, shortcut };
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
return null;
|
|
717
|
+
}, []);
|
|
569
718
|
(0, import_react2.useEffect)(() => {
|
|
719
|
+
const handleKeyDown = (e) => {
|
|
720
|
+
if (isInputFocused()) return;
|
|
721
|
+
const key = e.key.toLowerCase();
|
|
722
|
+
if (key === "arrowleft" || key === "arrowright" || key === "arrowup" || key === "arrowdown") {
|
|
723
|
+
if (activeKeysRef.current.size > 0) {
|
|
724
|
+
const target2 = resolveActiveTarget("scroll") || resolveActiveTarget("drag") || resolveActiveTarget("move");
|
|
725
|
+
if (target2 && target2.control.type === "slider") {
|
|
726
|
+
e.preventDefault();
|
|
727
|
+
const direction = key === "arrowright" || key === "arrowup" ? 1 : -1;
|
|
728
|
+
const effectiveStep = getEffectiveStep(target2.control, target2.shortcut);
|
|
729
|
+
applySliderDelta(target2.panelId, target2.path, target2.control, effectiveStep, direction);
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
const wasAlreadyHeld = activeKeysRef.current.has(key);
|
|
735
|
+
activeKeysRef.current.add(key);
|
|
736
|
+
const modifier = getActiveModifier(e);
|
|
737
|
+
const target = DialStore.resolveShortcutTarget(key, modifier);
|
|
738
|
+
if (target) {
|
|
739
|
+
setActiveShortcut({ activePanelId: target.panelId, activePath: target.path });
|
|
740
|
+
if (!wasAlreadyHeld && target.control.type === "toggle") {
|
|
741
|
+
const currentValue = DialStore.getValue(target.panelId, target.path);
|
|
742
|
+
DialStore.updateValue(target.panelId, target.path, !currentValue);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
if (!wasAlreadyHeld) {
|
|
746
|
+
lastMouseXRef.current = null;
|
|
747
|
+
dragAccumulatorRef.current = 0;
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
const handleKeyUp = (e) => {
|
|
751
|
+
const key = e.key.toLowerCase();
|
|
752
|
+
activeKeysRef.current.delete(key);
|
|
753
|
+
isDraggingRef.current = false;
|
|
754
|
+
lastMouseXRef.current = null;
|
|
755
|
+
dragAccumulatorRef.current = 0;
|
|
756
|
+
if (activeKeysRef.current.size === 0) {
|
|
757
|
+
setActiveShortcut({ activePanelId: null, activePath: null });
|
|
758
|
+
} else {
|
|
759
|
+
let found = false;
|
|
760
|
+
for (const remainingKey of activeKeysRef.current) {
|
|
761
|
+
const modifier = getActiveModifier(e);
|
|
762
|
+
const target = DialStore.resolveShortcutTarget(remainingKey, modifier);
|
|
763
|
+
if (target) {
|
|
764
|
+
setActiveShortcut({ activePanelId: target.panelId, activePath: target.path });
|
|
765
|
+
found = true;
|
|
766
|
+
break;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
if (!found) {
|
|
770
|
+
setActiveShortcut({ activePanelId: null, activePath: null });
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
const handleWheel = (e) => {
|
|
775
|
+
if (isInputFocused()) return;
|
|
776
|
+
const modifier = getActiveModifier(e);
|
|
777
|
+
if (activeKeysRef.current.size > 0) {
|
|
778
|
+
for (const key of activeKeysRef.current) {
|
|
779
|
+
const target = DialStore.resolveShortcutTarget(key, modifier);
|
|
780
|
+
if (!target) continue;
|
|
781
|
+
const { panelId, path, control } = target;
|
|
782
|
+
const interaction = control.shortcut?.interaction ?? "scroll";
|
|
783
|
+
if (interaction !== "scroll" || control.type !== "slider") continue;
|
|
784
|
+
e.preventDefault();
|
|
785
|
+
const effectiveStep = getEffectiveStep(control, control.shortcut);
|
|
786
|
+
const direction = e.deltaY > 0 ? -1 : 1;
|
|
787
|
+
applySliderDelta(panelId, path, control, effectiveStep, direction);
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
const scrollOnlyTargets = DialStore.resolveScrollOnlyTargets();
|
|
792
|
+
for (const { panelId, path, control, shortcut } of scrollOnlyTargets) {
|
|
793
|
+
if (control.type !== "slider") continue;
|
|
794
|
+
e.preventDefault();
|
|
795
|
+
const effectiveStep = getEffectiveStep(control, shortcut);
|
|
796
|
+
const direction = e.deltaY > 0 ? -1 : 1;
|
|
797
|
+
applySliderDelta(panelId, path, control, effectiveStep, direction);
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
const handleMouseDown = (e) => {
|
|
802
|
+
if (isInputFocused()) return;
|
|
803
|
+
if (activeKeysRef.current.size === 0) return;
|
|
804
|
+
const target = resolveActiveTarget("drag");
|
|
805
|
+
if (target) {
|
|
806
|
+
isDraggingRef.current = true;
|
|
807
|
+
lastMouseXRef.current = e.clientX;
|
|
808
|
+
dragAccumulatorRef.current = 0;
|
|
809
|
+
e.preventDefault();
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
const handleMouseUp = () => {
|
|
813
|
+
isDraggingRef.current = false;
|
|
814
|
+
lastMouseXRef.current = null;
|
|
815
|
+
dragAccumulatorRef.current = 0;
|
|
816
|
+
};
|
|
817
|
+
const handleMouseMove = (e) => {
|
|
818
|
+
if (isInputFocused()) return;
|
|
819
|
+
if (activeKeysRef.current.size === 0) return;
|
|
820
|
+
if (isDraggingRef.current) {
|
|
821
|
+
const target = resolveActiveTarget("drag");
|
|
822
|
+
if (target && lastMouseXRef.current !== null) {
|
|
823
|
+
const deltaX = e.clientX - lastMouseXRef.current;
|
|
824
|
+
lastMouseXRef.current = e.clientX;
|
|
825
|
+
dragAccumulatorRef.current += deltaX;
|
|
826
|
+
const effectiveStep = getEffectiveStep(target.control, target.shortcut);
|
|
827
|
+
const steps = Math.trunc(dragAccumulatorRef.current / DRAG_SENSITIVITY);
|
|
828
|
+
if (steps !== 0) {
|
|
829
|
+
dragAccumulatorRef.current -= steps * DRAG_SENSITIVITY;
|
|
830
|
+
applySliderDelta(target.panelId, target.path, target.control, effectiveStep, steps);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
const moveTarget = resolveActiveTarget("move");
|
|
836
|
+
if (moveTarget) {
|
|
837
|
+
if (lastMouseXRef.current === null) {
|
|
838
|
+
lastMouseXRef.current = e.clientX;
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
const deltaX = e.clientX - lastMouseXRef.current;
|
|
842
|
+
lastMouseXRef.current = e.clientX;
|
|
843
|
+
dragAccumulatorRef.current += deltaX;
|
|
844
|
+
const effectiveStep = getEffectiveStep(moveTarget.control, moveTarget.shortcut);
|
|
845
|
+
const steps = Math.trunc(dragAccumulatorRef.current / DRAG_SENSITIVITY);
|
|
846
|
+
if (steps !== 0) {
|
|
847
|
+
dragAccumulatorRef.current -= steps * DRAG_SENSITIVITY;
|
|
848
|
+
applySliderDelta(moveTarget.panelId, moveTarget.path, moveTarget.control, effectiveStep, steps);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
const handleWindowBlur = () => {
|
|
853
|
+
activeKeysRef.current.clear();
|
|
854
|
+
isDraggingRef.current = false;
|
|
855
|
+
lastMouseXRef.current = null;
|
|
856
|
+
dragAccumulatorRef.current = 0;
|
|
857
|
+
setActiveShortcut({ activePanelId: null, activePath: null });
|
|
858
|
+
};
|
|
859
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
860
|
+
window.addEventListener("keyup", handleKeyUp);
|
|
861
|
+
window.addEventListener("wheel", handleWheel, { passive: false });
|
|
862
|
+
window.addEventListener("mousedown", handleMouseDown);
|
|
863
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
864
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
865
|
+
window.addEventListener("blur", handleWindowBlur);
|
|
866
|
+
return () => {
|
|
867
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
868
|
+
window.removeEventListener("keyup", handleKeyUp);
|
|
869
|
+
window.removeEventListener("wheel", handleWheel);
|
|
870
|
+
window.removeEventListener("mousedown", handleMouseDown);
|
|
871
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
872
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
873
|
+
window.removeEventListener("blur", handleWindowBlur);
|
|
874
|
+
};
|
|
875
|
+
}, [resolveActiveTarget]);
|
|
876
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShortcutContext.Provider, { value: activeShortcut, children });
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// src/icons.ts
|
|
880
|
+
var ICON_CHEVRON = "M6 9.5L12 15.5L18 9.5";
|
|
881
|
+
var ICON_CHECK = "M5 12.75L10 19L19 5";
|
|
882
|
+
var ICON_CLIPBOARD = {
|
|
883
|
+
board: "M8 6C8 4.34315 9.34315 3 11 3H13C14.6569 3 16 4.34315 16 6V7H8V6Z",
|
|
884
|
+
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",
|
|
885
|
+
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"
|
|
886
|
+
};
|
|
887
|
+
var ICON_ADD_PRESET = [
|
|
888
|
+
"M4 6H20",
|
|
889
|
+
"M4 12H10",
|
|
890
|
+
"M15 15L21 15",
|
|
891
|
+
"M18 12V18",
|
|
892
|
+
"M4 18H10"
|
|
893
|
+
];
|
|
894
|
+
var ICON_TRASH = [
|
|
895
|
+
"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",
|
|
896
|
+
"M10 11V16",
|
|
897
|
+
"M14 11V16",
|
|
898
|
+
"M3.5 6H20.5",
|
|
899
|
+
"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"
|
|
900
|
+
];
|
|
901
|
+
var ICON_PANEL = {
|
|
902
|
+
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",
|
|
903
|
+
circles: [
|
|
904
|
+
{ cx: "6", cy: "8", r: "0.998596" },
|
|
905
|
+
{ cx: "10.4999", cy: "3.5", r: "0.998657" },
|
|
906
|
+
{ cx: "9.75015", cy: "12.5", r: "0.997986" }
|
|
907
|
+
]
|
|
908
|
+
};
|
|
909
|
+
|
|
910
|
+
// src/components/Folder.tsx
|
|
911
|
+
var import_react3 = require("react");
|
|
912
|
+
var import_react4 = require("motion/react");
|
|
913
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
914
|
+
function Folder({ title, children, defaultOpen = true, isRoot = false, inline = false, onOpenChange, toolbar }) {
|
|
915
|
+
const [isOpen, setIsOpen] = (0, import_react3.useState)(defaultOpen);
|
|
916
|
+
const [isCollapsed, setIsCollapsed] = (0, import_react3.useState)(!defaultOpen);
|
|
917
|
+
const contentRef = (0, import_react3.useRef)(null);
|
|
918
|
+
const [contentHeight, setContentHeight] = (0, import_react3.useState)(void 0);
|
|
919
|
+
const [windowHeight, setWindowHeight] = (0, import_react3.useState)(typeof window !== "undefined" ? window.innerHeight : 800);
|
|
920
|
+
(0, import_react3.useEffect)(() => {
|
|
921
|
+
if (!isRoot) return;
|
|
922
|
+
const onResize = () => setWindowHeight(window.innerHeight);
|
|
923
|
+
window.addEventListener("resize", onResize);
|
|
924
|
+
return () => window.removeEventListener("resize", onResize);
|
|
925
|
+
}, [isRoot]);
|
|
926
|
+
(0, import_react3.useEffect)(() => {
|
|
570
927
|
const el = contentRef.current;
|
|
571
928
|
if (!el) return;
|
|
572
929
|
const ro = new ResizeObserver(() => {
|
|
@@ -579,6 +936,7 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
579
936
|
return () => ro.disconnect();
|
|
580
937
|
}, [isOpen]);
|
|
581
938
|
const handleToggle = () => {
|
|
939
|
+
if (inline && isRoot) return;
|
|
582
940
|
const next = !isOpen;
|
|
583
941
|
setIsOpen(next);
|
|
584
942
|
if (next) {
|
|
@@ -588,50 +946,43 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
588
946
|
}
|
|
589
947
|
onOpenChange?.(next);
|
|
590
948
|
};
|
|
591
|
-
const folderContent = /* @__PURE__ */ (0,
|
|
592
|
-
/* @__PURE__ */ (0,
|
|
593
|
-
/* @__PURE__ */ (0,
|
|
594
|
-
isRoot ? isOpen && /* @__PURE__ */ (0,
|
|
595
|
-
isRoot
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
"
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
fill: "
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
strokeLinejoin: "round",
|
|
623
|
-
initial: false,
|
|
624
|
-
animate: { rotate: isOpen ? 0 : 180 },
|
|
625
|
-
transition: { type: "spring", visualDuration: 0.35, bounce: 0.15 },
|
|
626
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 9.5L12 15.5L18 9.5" })
|
|
627
|
-
}
|
|
628
|
-
)
|
|
949
|
+
const folderContent = /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { ref: isRoot ? contentRef : void 0, className: `dialkit-folder ${isRoot ? "dialkit-folder-root" : ""}`, children: [
|
|
950
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `dialkit-folder-header ${isRoot ? "dialkit-panel-header" : ""}`, onClick: handleToggle, children: [
|
|
951
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dialkit-folder-header-top", children: [
|
|
952
|
+
isRoot ? isOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dialkit-folder-title-row", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dialkit-folder-title dialkit-folder-title-root", children: title }) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dialkit-folder-title-row", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dialkit-folder-title", children: title }) }),
|
|
953
|
+
isRoot && !inline && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
954
|
+
"svg",
|
|
955
|
+
{
|
|
956
|
+
className: "dialkit-panel-icon",
|
|
957
|
+
viewBox: "0 0 16 16",
|
|
958
|
+
fill: "none",
|
|
959
|
+
children: [
|
|
960
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { opacity: "0.5", d: ICON_PANEL.path, fill: "currentColor" }),
|
|
961
|
+
ICON_PANEL.circles.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: c.cx, cy: c.cy, r: c.r, fill: "currentColor", stroke: "currentColor", strokeWidth: "1.25" }, i))
|
|
962
|
+
]
|
|
963
|
+
}
|
|
964
|
+
),
|
|
965
|
+
!isRoot && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
966
|
+
import_react4.motion.svg,
|
|
967
|
+
{
|
|
968
|
+
className: "dialkit-folder-icon",
|
|
969
|
+
viewBox: "0 0 24 24",
|
|
970
|
+
fill: "none",
|
|
971
|
+
stroke: "currentColor",
|
|
972
|
+
strokeWidth: "2.5",
|
|
973
|
+
strokeLinecap: "round",
|
|
974
|
+
strokeLinejoin: "round",
|
|
975
|
+
initial: false,
|
|
976
|
+
animate: { rotate: isOpen ? 0 : 180 },
|
|
977
|
+
transition: { type: "spring", visualDuration: 0.35, bounce: 0.15 },
|
|
978
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: ICON_CHEVRON })
|
|
979
|
+
}
|
|
629
980
|
)
|
|
630
981
|
] }),
|
|
631
|
-
isRoot && toolbar && isOpen && /* @__PURE__ */ (0,
|
|
982
|
+
isRoot && toolbar && isOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dialkit-panel-toolbar", onClick: (e) => e.stopPropagation(), children: toolbar })
|
|
632
983
|
] }),
|
|
633
|
-
/* @__PURE__ */ (0,
|
|
634
|
-
|
|
984
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react4.AnimatePresence, { initial: false, children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
985
|
+
import_react4.motion.div,
|
|
635
986
|
{
|
|
636
987
|
className: "dialkit-folder-content",
|
|
637
988
|
initial: isRoot ? void 0 : { height: 0, opacity: 0 },
|
|
@@ -639,14 +990,17 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
639
990
|
exit: isRoot ? void 0 : { height: 0, opacity: 0 },
|
|
640
991
|
transition: isRoot ? void 0 : { type: "spring", visualDuration: 0.35, bounce: 0.1 },
|
|
641
992
|
style: isRoot ? void 0 : { clipPath: "inset(0 -20px)" },
|
|
642
|
-
children: /* @__PURE__ */ (0,
|
|
993
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dialkit-folder-inner", children })
|
|
643
994
|
}
|
|
644
995
|
) })
|
|
645
996
|
] });
|
|
646
997
|
if (isRoot) {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
998
|
+
if (inline) {
|
|
999
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dialkit-panel-inner dialkit-panel-inline", children: folderContent });
|
|
1000
|
+
}
|
|
1001
|
+
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" };
|
|
1002
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1003
|
+
import_react4.motion.div,
|
|
650
1004
|
{
|
|
651
1005
|
className: "dialkit-panel-inner",
|
|
652
1006
|
style: panelStyle,
|
|
@@ -662,30 +1016,13 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
662
1016
|
}
|
|
663
1017
|
|
|
664
1018
|
// src/components/Slider.tsx
|
|
665
|
-
var
|
|
666
|
-
var
|
|
667
|
-
var
|
|
1019
|
+
var import_react5 = require("react");
|
|
1020
|
+
var import_react6 = require("motion/react");
|
|
1021
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
668
1022
|
var CLICK_THRESHOLD = 3;
|
|
669
1023
|
var DEAD_ZONE = 32;
|
|
670
1024
|
var MAX_CURSOR_RANGE = 200;
|
|
671
1025
|
var MAX_STRETCH = 8;
|
|
672
|
-
function decimalsForStep(step) {
|
|
673
|
-
const s = step.toString();
|
|
674
|
-
const dot = s.indexOf(".");
|
|
675
|
-
return dot === -1 ? 0 : s.length - dot - 1;
|
|
676
|
-
}
|
|
677
|
-
function roundValue(val, step) {
|
|
678
|
-
const raw = Math.round(val / step) * step;
|
|
679
|
-
return parseFloat(raw.toFixed(decimalsForStep(step)));
|
|
680
|
-
}
|
|
681
|
-
function snapToDecile(rawValue, min, max) {
|
|
682
|
-
const normalized = (rawValue - min) / (max - min);
|
|
683
|
-
const nearest = Math.round(normalized * 10) / 10;
|
|
684
|
-
if (Math.abs(normalized - nearest) <= 0.03125) {
|
|
685
|
-
return min + nearest * (max - min);
|
|
686
|
-
}
|
|
687
|
-
return rawValue;
|
|
688
|
-
}
|
|
689
1026
|
function Slider({
|
|
690
1027
|
label,
|
|
691
1028
|
value,
|
|
@@ -693,49 +1030,51 @@ function Slider({
|
|
|
693
1030
|
min = 0,
|
|
694
1031
|
max = 1,
|
|
695
1032
|
step = 0.01,
|
|
696
|
-
unit
|
|
1033
|
+
unit,
|
|
1034
|
+
shortcut,
|
|
1035
|
+
shortcutActive
|
|
697
1036
|
}) {
|
|
698
|
-
const wrapperRef = (0,
|
|
699
|
-
const trackRef = (0,
|
|
700
|
-
const inputRef = (0,
|
|
701
|
-
const labelRef = (0,
|
|
702
|
-
const valueSpanRef = (0,
|
|
703
|
-
const [isInteracting, setIsInteracting] = (0,
|
|
704
|
-
const [isDragging, setIsDragging] = (0,
|
|
705
|
-
const [isHovered, setIsHovered] = (0,
|
|
706
|
-
const [isValueHovered, setIsValueHovered] = (0,
|
|
707
|
-
const [isValueEditable, setIsValueEditable] = (0,
|
|
708
|
-
const [showInput, setShowInput] = (0,
|
|
709
|
-
const [inputValue, setInputValue] = (0,
|
|
710
|
-
const hoverTimeoutRef = (0,
|
|
711
|
-
const pointerDownPos = (0,
|
|
712
|
-
const isClickRef = (0,
|
|
713
|
-
const animRef = (0,
|
|
714
|
-
const wrapperRectRef = (0,
|
|
715
|
-
const scaleRef = (0,
|
|
1037
|
+
const wrapperRef = (0, import_react5.useRef)(null);
|
|
1038
|
+
const trackRef = (0, import_react5.useRef)(null);
|
|
1039
|
+
const inputRef = (0, import_react5.useRef)(null);
|
|
1040
|
+
const labelRef = (0, import_react5.useRef)(null);
|
|
1041
|
+
const valueSpanRef = (0, import_react5.useRef)(null);
|
|
1042
|
+
const [isInteracting, setIsInteracting] = (0, import_react5.useState)(false);
|
|
1043
|
+
const [isDragging, setIsDragging] = (0, import_react5.useState)(false);
|
|
1044
|
+
const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
|
|
1045
|
+
const [isValueHovered, setIsValueHovered] = (0, import_react5.useState)(false);
|
|
1046
|
+
const [isValueEditable, setIsValueEditable] = (0, import_react5.useState)(false);
|
|
1047
|
+
const [showInput, setShowInput] = (0, import_react5.useState)(false);
|
|
1048
|
+
const [inputValue, setInputValue] = (0, import_react5.useState)("");
|
|
1049
|
+
const hoverTimeoutRef = (0, import_react5.useRef)(null);
|
|
1050
|
+
const pointerDownPos = (0, import_react5.useRef)(null);
|
|
1051
|
+
const isClickRef = (0, import_react5.useRef)(true);
|
|
1052
|
+
const animRef = (0, import_react5.useRef)(null);
|
|
1053
|
+
const wrapperRectRef = (0, import_react5.useRef)(null);
|
|
1054
|
+
const scaleRef = (0, import_react5.useRef)(1);
|
|
716
1055
|
const percentage = (value - min) / (max - min) * 100;
|
|
717
1056
|
const isActive = isInteracting || isHovered;
|
|
718
|
-
const fillPercent = (0,
|
|
719
|
-
const fillWidth = (0,
|
|
720
|
-
const handleLeft = (0,
|
|
1057
|
+
const fillPercent = (0, import_react6.useMotionValue)(percentage);
|
|
1058
|
+
const fillWidth = (0, import_react6.useTransform)(fillPercent, (pct) => `${pct}%`);
|
|
1059
|
+
const handleLeft = (0, import_react6.useTransform)(
|
|
721
1060
|
fillPercent,
|
|
722
1061
|
(pct) => `max(5px, calc(${pct}% - 9px))`
|
|
723
1062
|
);
|
|
724
|
-
const rubberStretchPx = (0,
|
|
725
|
-
const rubberBandWidth = (0,
|
|
1063
|
+
const rubberStretchPx = (0, import_react6.useMotionValue)(0);
|
|
1064
|
+
const rubberBandWidth = (0, import_react6.useTransform)(
|
|
726
1065
|
rubberStretchPx,
|
|
727
1066
|
(stretch) => `calc(100% + ${Math.abs(stretch)}px)`
|
|
728
1067
|
);
|
|
729
|
-
const rubberBandX = (0,
|
|
1068
|
+
const rubberBandX = (0, import_react6.useTransform)(
|
|
730
1069
|
rubberStretchPx,
|
|
731
1070
|
(stretch) => stretch < 0 ? stretch : 0
|
|
732
1071
|
);
|
|
733
|
-
(0,
|
|
1072
|
+
(0, import_react5.useEffect)(() => {
|
|
734
1073
|
if (!isInteracting && !animRef.current) {
|
|
735
1074
|
fillPercent.jump(percentage);
|
|
736
1075
|
}
|
|
737
1076
|
}, [percentage, isInteracting, fillPercent]);
|
|
738
|
-
const positionToValue = (0,
|
|
1077
|
+
const positionToValue = (0, import_react5.useCallback)(
|
|
739
1078
|
(clientX) => {
|
|
740
1079
|
const rect = wrapperRectRef.current;
|
|
741
1080
|
if (!rect) return value;
|
|
@@ -748,11 +1087,11 @@ function Slider({
|
|
|
748
1087
|
},
|
|
749
1088
|
[min, max, value]
|
|
750
1089
|
);
|
|
751
|
-
const percentFromValue = (0,
|
|
1090
|
+
const percentFromValue = (0, import_react5.useCallback)(
|
|
752
1091
|
(v) => (v - min) / (max - min) * 100,
|
|
753
1092
|
[min, max]
|
|
754
1093
|
);
|
|
755
|
-
const computeRubberStretch = (0,
|
|
1094
|
+
const computeRubberStretch = (0, import_react5.useCallback)(
|
|
756
1095
|
(clientX, sign) => {
|
|
757
1096
|
const rect = wrapperRectRef.current;
|
|
758
1097
|
if (!rect) return 0;
|
|
@@ -762,7 +1101,7 @@ function Slider({
|
|
|
762
1101
|
},
|
|
763
1102
|
[]
|
|
764
1103
|
);
|
|
765
|
-
const handlePointerDown = (0,
|
|
1104
|
+
const handlePointerDown = (0, import_react5.useCallback)(
|
|
766
1105
|
(e) => {
|
|
767
1106
|
if (showInput) return;
|
|
768
1107
|
e.preventDefault();
|
|
@@ -778,7 +1117,7 @@ function Slider({
|
|
|
778
1117
|
},
|
|
779
1118
|
[showInput]
|
|
780
1119
|
);
|
|
781
|
-
const handlePointerMove = (0,
|
|
1120
|
+
const handlePointerMove = (0, import_react5.useCallback)(
|
|
782
1121
|
(e) => {
|
|
783
1122
|
if (!isInteracting || !pointerDownPos.current) return;
|
|
784
1123
|
const dx = e.clientX - pointerDownPos.current.x;
|
|
@@ -819,7 +1158,7 @@ function Slider({
|
|
|
819
1158
|
computeRubberStretch
|
|
820
1159
|
]
|
|
821
1160
|
);
|
|
822
|
-
const handlePointerUp = (0,
|
|
1161
|
+
const handlePointerUp = (0, import_react5.useCallback)(
|
|
823
1162
|
(e) => {
|
|
824
1163
|
if (!isInteracting) return;
|
|
825
1164
|
if (isClickRef.current) {
|
|
@@ -830,7 +1169,7 @@ function Slider({
|
|
|
830
1169
|
if (animRef.current) {
|
|
831
1170
|
animRef.current.stop();
|
|
832
1171
|
}
|
|
833
|
-
animRef.current = (0,
|
|
1172
|
+
animRef.current = (0, import_react6.animate)(fillPercent, newPct, {
|
|
834
1173
|
type: "spring",
|
|
835
1174
|
stiffness: 300,
|
|
836
1175
|
damping: 25,
|
|
@@ -842,7 +1181,7 @@ function Slider({
|
|
|
842
1181
|
onChange(roundValue(snappedValue, step));
|
|
843
1182
|
}
|
|
844
1183
|
if (rubberStretchPx.get() !== 0) {
|
|
845
|
-
(0,
|
|
1184
|
+
(0, import_react6.animate)(rubberStretchPx, 0, {
|
|
846
1185
|
type: "spring",
|
|
847
1186
|
visualDuration: 0.35,
|
|
848
1187
|
bounce: 0.15
|
|
@@ -863,7 +1202,7 @@ function Slider({
|
|
|
863
1202
|
rubberStretchPx
|
|
864
1203
|
]
|
|
865
1204
|
);
|
|
866
|
-
(0,
|
|
1205
|
+
(0, import_react5.useEffect)(() => {
|
|
867
1206
|
if (isValueHovered && !showInput && !isValueEditable) {
|
|
868
1207
|
hoverTimeoutRef.current = setTimeout(() => {
|
|
869
1208
|
setIsValueEditable(true);
|
|
@@ -881,7 +1220,7 @@ function Slider({
|
|
|
881
1220
|
}
|
|
882
1221
|
};
|
|
883
1222
|
}, [isValueHovered, showInput, isValueEditable]);
|
|
884
|
-
(0,
|
|
1223
|
+
(0, import_react5.useEffect)(() => {
|
|
885
1224
|
if (showInput && inputRef.current) {
|
|
886
1225
|
inputRef.current.focus();
|
|
887
1226
|
inputRef.current.select();
|
|
@@ -936,11 +1275,10 @@ function Slider({
|
|
|
936
1275
|
}
|
|
937
1276
|
const valueDodge = percentage < leftThreshold || percentage > rightThreshold;
|
|
938
1277
|
const handleOpacity = !isActive ? 0 : valueDodge ? 0.1 : isDragging ? 0.9 : 0.5;
|
|
939
|
-
const fillBackground = isActive ? "rgba(255, 255, 255, 0.15)" : "rgba(255, 255, 255, 0.11)";
|
|
940
1278
|
const discreteSteps = (max - min) / step;
|
|
941
1279
|
const hashMarks = discreteSteps <= 10 ? Array.from({ length: discreteSteps - 1 }, (_, i) => {
|
|
942
1280
|
const pct = (i + 1) * step / (max - min) * 100;
|
|
943
|
-
return /* @__PURE__ */ (0,
|
|
1281
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
944
1282
|
"div",
|
|
945
1283
|
{
|
|
946
1284
|
className: "dialkit-slider-hashmark",
|
|
@@ -950,7 +1288,7 @@ function Slider({
|
|
|
950
1288
|
);
|
|
951
1289
|
}) : Array.from({ length: 9 }, (_, i) => {
|
|
952
1290
|
const pct = (i + 1) * 10;
|
|
953
|
-
return /* @__PURE__ */ (0,
|
|
1291
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
954
1292
|
"div",
|
|
955
1293
|
{
|
|
956
1294
|
className: "dialkit-slider-hashmark",
|
|
@@ -959,8 +1297,8 @@ function Slider({
|
|
|
959
1297
|
i
|
|
960
1298
|
);
|
|
961
1299
|
});
|
|
962
|
-
return /* @__PURE__ */ (0,
|
|
963
|
-
|
|
1300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: wrapperRef, className: "dialkit-slider-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1301
|
+
import_react6.motion.div,
|
|
964
1302
|
{
|
|
965
1303
|
ref: trackRef,
|
|
966
1304
|
className: `dialkit-slider ${isActive ? "dialkit-slider-active" : ""}`,
|
|
@@ -971,26 +1309,23 @@ function Slider({
|
|
|
971
1309
|
onMouseLeave: () => setIsHovered(false),
|
|
972
1310
|
style: { width: rubberBandWidth, x: rubberBandX },
|
|
973
1311
|
children: [
|
|
974
|
-
/* @__PURE__ */ (0,
|
|
975
|
-
/* @__PURE__ */ (0,
|
|
976
|
-
|
|
1312
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dialkit-slider-hashmarks", children: hashMarks }),
|
|
1313
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1314
|
+
import_react6.motion.div,
|
|
977
1315
|
{
|
|
978
1316
|
className: "dialkit-slider-fill",
|
|
979
1317
|
style: {
|
|
980
|
-
|
|
981
|
-
width: fillWidth,
|
|
982
|
-
transition: "background 0.15s"
|
|
1318
|
+
width: fillWidth
|
|
983
1319
|
}
|
|
984
1320
|
}
|
|
985
1321
|
),
|
|
986
|
-
/* @__PURE__ */ (0,
|
|
987
|
-
|
|
1322
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1323
|
+
import_react6.motion.div,
|
|
988
1324
|
{
|
|
989
1325
|
className: "dialkit-slider-handle",
|
|
990
1326
|
style: {
|
|
991
1327
|
left: handleLeft,
|
|
992
|
-
y: "-50%"
|
|
993
|
-
background: "rgba(255, 255, 255, 0.9)"
|
|
1328
|
+
y: "-50%"
|
|
994
1329
|
},
|
|
995
1330
|
animate: {
|
|
996
1331
|
opacity: handleOpacity,
|
|
@@ -1004,8 +1339,11 @@ function Slider({
|
|
|
1004
1339
|
}
|
|
1005
1340
|
}
|
|
1006
1341
|
),
|
|
1007
|
-
/* @__PURE__ */ (0,
|
|
1008
|
-
|
|
1342
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { ref: labelRef, className: "dialkit-slider-label", children: [
|
|
1343
|
+
label,
|
|
1344
|
+
shortcut && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `dialkit-shortcut-pill${shortcutActive ? " dialkit-shortcut-pill-active" : ""}`, children: formatSliderShortcut(shortcut) })
|
|
1345
|
+
] }),
|
|
1346
|
+
showInput ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1009
1347
|
"input",
|
|
1010
1348
|
{
|
|
1011
1349
|
ref: inputRef,
|
|
@@ -1018,7 +1356,7 @@ function Slider({
|
|
|
1018
1356
|
onClick: (e) => e.stopPropagation(),
|
|
1019
1357
|
onMouseDown: (e) => e.stopPropagation()
|
|
1020
1358
|
}
|
|
1021
|
-
) : /* @__PURE__ */ (0,
|
|
1359
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1022
1360
|
"span",
|
|
1023
1361
|
{
|
|
1024
1362
|
ref: valueSpanRef,
|
|
@@ -1037,51 +1375,48 @@ function Slider({
|
|
|
1037
1375
|
}
|
|
1038
1376
|
|
|
1039
1377
|
// src/components/SegmentedControl.tsx
|
|
1040
|
-
var
|
|
1041
|
-
var
|
|
1042
|
-
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1378
|
+
var import_react7 = require("react");
|
|
1379
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1043
1380
|
function SegmentedControl({
|
|
1044
1381
|
options,
|
|
1045
1382
|
value,
|
|
1046
1383
|
onChange
|
|
1047
1384
|
}) {
|
|
1048
|
-
const containerRef = (0,
|
|
1049
|
-
const
|
|
1050
|
-
const [pillStyle, setPillStyle] = (0,
|
|
1051
|
-
const
|
|
1052
|
-
(0, import_react6.useLayoutEffect)(() => {
|
|
1053
|
-
const button = buttonRefs.current.get(value);
|
|
1385
|
+
const containerRef = (0, import_react7.useRef)(null);
|
|
1386
|
+
const hasAnimated = (0, import_react7.useRef)(false);
|
|
1387
|
+
const [pillStyle, setPillStyle] = (0, import_react7.useState)(null);
|
|
1388
|
+
const measure = (0, import_react7.useCallback)(() => {
|
|
1054
1389
|
const container = containerRef.current;
|
|
1055
|
-
if (
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1390
|
+
if (!container) return;
|
|
1391
|
+
const activeButton = container.querySelector('[data-active="true"]');
|
|
1392
|
+
if (!activeButton) return;
|
|
1393
|
+
setPillStyle({
|
|
1394
|
+
left: activeButton.offsetLeft,
|
|
1395
|
+
width: activeButton.offsetWidth
|
|
1396
|
+
});
|
|
1397
|
+
}, []);
|
|
1398
|
+
(0, import_react7.useLayoutEffect)(() => {
|
|
1399
|
+
measure();
|
|
1400
|
+
}, [value, options.length, measure]);
|
|
1401
|
+
const shouldAnimate = hasAnimated.current;
|
|
1402
|
+
hasAnimated.current = true;
|
|
1403
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dialkit-segmented", ref: containerRef, children: [
|
|
1404
|
+
pillStyle && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1405
|
+
"div",
|
|
1067
1406
|
{
|
|
1068
1407
|
className: "dialkit-segmented-pill",
|
|
1069
|
-
style: {
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
hasAnimated.current = true;
|
|
1408
|
+
style: {
|
|
1409
|
+
left: pillStyle.left,
|
|
1410
|
+
width: pillStyle.width,
|
|
1411
|
+
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"
|
|
1074
1412
|
}
|
|
1075
1413
|
}
|
|
1076
1414
|
),
|
|
1077
1415
|
options.map((option) => {
|
|
1078
1416
|
const isActive = value === option.value;
|
|
1079
|
-
return /* @__PURE__ */ (0,
|
|
1417
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1080
1418
|
"button",
|
|
1081
1419
|
{
|
|
1082
|
-
ref: (el) => {
|
|
1083
|
-
if (el) buttonRefs.current.set(option.value, el);
|
|
1084
|
-
},
|
|
1085
1420
|
onClick: () => onChange(option.value),
|
|
1086
1421
|
className: "dialkit-segmented-button",
|
|
1087
1422
|
"data-active": String(isActive),
|
|
@@ -1094,11 +1429,14 @@ function SegmentedControl({
|
|
|
1094
1429
|
}
|
|
1095
1430
|
|
|
1096
1431
|
// src/components/Toggle.tsx
|
|
1097
|
-
var
|
|
1098
|
-
function Toggle({ label, checked, onChange }) {
|
|
1099
|
-
return /* @__PURE__ */ (0,
|
|
1100
|
-
/* @__PURE__ */ (0,
|
|
1101
|
-
|
|
1432
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1433
|
+
function Toggle({ label, checked, onChange, shortcut, shortcutActive }) {
|
|
1434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dialkit-labeled-control", children: [
|
|
1435
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "dialkit-labeled-control-label", children: [
|
|
1436
|
+
label,
|
|
1437
|
+
shortcut && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `dialkit-shortcut-pill${shortcutActive ? " dialkit-shortcut-pill-active" : ""}`, children: formatToggleShortcut(shortcut) })
|
|
1438
|
+
] }),
|
|
1439
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1102
1440
|
SegmentedControl,
|
|
1103
1441
|
{
|
|
1104
1442
|
options: [
|
|
@@ -1113,7 +1451,7 @@ function Toggle({ label, checked, onChange }) {
|
|
|
1113
1451
|
}
|
|
1114
1452
|
|
|
1115
1453
|
// src/components/SpringVisualization.tsx
|
|
1116
|
-
var
|
|
1454
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1117
1455
|
function generateSpringCurve(stiffness, damping, mass, duration) {
|
|
1118
1456
|
const points = [];
|
|
1119
1457
|
const steps = 100;
|
|
@@ -1168,13 +1506,13 @@ function SpringVisualization({ spring, isSimpleMode }) {
|
|
|
1168
1506
|
const x = width / 4 * i;
|
|
1169
1507
|
const y = height / 4 * i;
|
|
1170
1508
|
gridLines.push(
|
|
1171
|
-
/* @__PURE__ */ (0,
|
|
1172
|
-
/* @__PURE__ */ (0,
|
|
1509
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: x, y1: 0, x2: x, y2: height, stroke: "rgba(255, 255, 255, 0.08)", strokeWidth: "1" }, `v-${i}`),
|
|
1510
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: 0, y1: y, x2: width, y2: y, stroke: "rgba(255, 255, 255, 0.08)", strokeWidth: "1" }, `h-${i}`)
|
|
1173
1511
|
);
|
|
1174
1512
|
}
|
|
1175
|
-
return /* @__PURE__ */ (0,
|
|
1513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { viewBox: `0 0 ${width} ${height}`, className: "dialkit-spring-viz", children: [
|
|
1176
1514
|
gridLines,
|
|
1177
|
-
/* @__PURE__ */ (0,
|
|
1515
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1178
1516
|
"line",
|
|
1179
1517
|
{
|
|
1180
1518
|
x1: 0,
|
|
@@ -1186,7 +1524,7 @@ function SpringVisualization({ spring, isSimpleMode }) {
|
|
|
1186
1524
|
strokeDasharray: "4,4"
|
|
1187
1525
|
}
|
|
1188
1526
|
),
|
|
1189
|
-
/* @__PURE__ */ (0,
|
|
1527
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1190
1528
|
"path",
|
|
1191
1529
|
{
|
|
1192
1530
|
d: pathData,
|
|
@@ -1202,7 +1540,7 @@ function SpringVisualization({ spring, isSimpleMode }) {
|
|
|
1202
1540
|
|
|
1203
1541
|
// src/components/SpringControl.tsx
|
|
1204
1542
|
var import_react8 = require("react");
|
|
1205
|
-
var
|
|
1543
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1206
1544
|
function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
1207
1545
|
const mode = (0, import_react8.useSyncExternalStore)(
|
|
1208
1546
|
(cb) => DialStore.subscribe(panelId, cb),
|
|
@@ -1210,25 +1548,21 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1210
1548
|
() => DialStore.getSpringMode(panelId, path)
|
|
1211
1549
|
);
|
|
1212
1550
|
const isSimpleMode = mode === "simple";
|
|
1551
|
+
const cache = (0, import_react8.useRef)({
|
|
1552
|
+
simple: spring.visualDuration !== void 0 ? spring : { type: "spring", visualDuration: 0.3, bounce: 0.2 },
|
|
1553
|
+
advanced: spring.stiffness !== void 0 ? spring : { type: "spring", stiffness: 200, damping: 25, mass: 1 }
|
|
1554
|
+
});
|
|
1555
|
+
if (isSimpleMode) {
|
|
1556
|
+
cache.current.simple = spring;
|
|
1557
|
+
} else {
|
|
1558
|
+
cache.current.advanced = spring;
|
|
1559
|
+
}
|
|
1213
1560
|
const handleModeChange = (newMode) => {
|
|
1214
1561
|
DialStore.updateSpringMode(panelId, path, newMode);
|
|
1215
1562
|
if (newMode === "simple") {
|
|
1216
|
-
|
|
1217
|
-
onChange({
|
|
1218
|
-
...rest,
|
|
1219
|
-
type: "spring",
|
|
1220
|
-
visualDuration: spring.visualDuration ?? 0.3,
|
|
1221
|
-
bounce: spring.bounce ?? 0.2
|
|
1222
|
-
});
|
|
1563
|
+
onChange(cache.current.simple);
|
|
1223
1564
|
} else {
|
|
1224
|
-
|
|
1225
|
-
onChange({
|
|
1226
|
-
...rest,
|
|
1227
|
-
type: "spring",
|
|
1228
|
-
stiffness: spring.stiffness ?? 200,
|
|
1229
|
-
damping: spring.damping ?? 25,
|
|
1230
|
-
mass: spring.mass ?? 1
|
|
1231
|
-
});
|
|
1565
|
+
onChange(cache.current.advanced);
|
|
1232
1566
|
}
|
|
1233
1567
|
};
|
|
1234
1568
|
const handleUpdate = (key, value) => {
|
|
@@ -1240,11 +1574,11 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1240
1574
|
onChange({ ...rest, [key]: value });
|
|
1241
1575
|
}
|
|
1242
1576
|
};
|
|
1243
|
-
return /* @__PURE__ */ (0,
|
|
1244
|
-
/* @__PURE__ */ (0,
|
|
1245
|
-
/* @__PURE__ */ (0,
|
|
1246
|
-
/* @__PURE__ */ (0,
|
|
1247
|
-
/* @__PURE__ */ (0,
|
|
1577
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Folder, { title: label, defaultOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
1578
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpringVisualization, { spring, isSimpleMode }),
|
|
1579
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dialkit-labeled-control", children: [
|
|
1580
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dialkit-labeled-control-label", children: "Type" }),
|
|
1581
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1248
1582
|
SegmentedControl,
|
|
1249
1583
|
{
|
|
1250
1584
|
options: [
|
|
@@ -1256,8 +1590,8 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1256
1590
|
}
|
|
1257
1591
|
)
|
|
1258
1592
|
] }),
|
|
1259
|
-
isSimpleMode ? /* @__PURE__ */ (0,
|
|
1260
|
-
/* @__PURE__ */ (0,
|
|
1593
|
+
isSimpleMode ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1594
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1261
1595
|
Slider,
|
|
1262
1596
|
{
|
|
1263
1597
|
label: "Duration",
|
|
@@ -1269,7 +1603,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1269
1603
|
unit: "s"
|
|
1270
1604
|
}
|
|
1271
1605
|
),
|
|
1272
|
-
/* @__PURE__ */ (0,
|
|
1606
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1273
1607
|
Slider,
|
|
1274
1608
|
{
|
|
1275
1609
|
label: "Bounce",
|
|
@@ -1280,8 +1614,8 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1280
1614
|
step: 0.05
|
|
1281
1615
|
}
|
|
1282
1616
|
)
|
|
1283
|
-
] }) : /* @__PURE__ */ (0,
|
|
1284
|
-
/* @__PURE__ */ (0,
|
|
1617
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1618
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1285
1619
|
Slider,
|
|
1286
1620
|
{
|
|
1287
1621
|
label: "Stiffness",
|
|
@@ -1292,7 +1626,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1292
1626
|
step: 10
|
|
1293
1627
|
}
|
|
1294
1628
|
),
|
|
1295
|
-
/* @__PURE__ */ (0,
|
|
1629
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1296
1630
|
Slider,
|
|
1297
1631
|
{
|
|
1298
1632
|
label: "Damping",
|
|
@@ -1303,7 +1637,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1303
1637
|
step: 1
|
|
1304
1638
|
}
|
|
1305
1639
|
),
|
|
1306
|
-
/* @__PURE__ */ (0,
|
|
1640
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1307
1641
|
Slider,
|
|
1308
1642
|
{
|
|
1309
1643
|
label: "Mass",
|
|
@@ -1319,7 +1653,7 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
|
|
|
1319
1653
|
}
|
|
1320
1654
|
|
|
1321
1655
|
// src/components/EasingVisualization.tsx
|
|
1322
|
-
var
|
|
1656
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1323
1657
|
function EasingVisualization({ easing }) {
|
|
1324
1658
|
const ease = easing.ease;
|
|
1325
1659
|
const s = 200;
|
|
@@ -1335,14 +1669,14 @@ function EasingVisualization({ easing }) {
|
|
|
1335
1669
|
const p1 = toSvg(ease[0], ease[1]);
|
|
1336
1670
|
const p2 = toSvg(ease[2], ease[3]);
|
|
1337
1671
|
const curvePath = `M ${start.x} ${start.y} C ${p1.x} ${p1.y}, ${p2.x} ${p2.y}, ${end.x} ${end.y}`;
|
|
1338
|
-
return /* @__PURE__ */ (0,
|
|
1672
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1339
1673
|
"svg",
|
|
1340
1674
|
{
|
|
1341
1675
|
viewBox: `0 0 ${s} ${s}`,
|
|
1342
1676
|
preserveAspectRatio: "xMidYMid slice",
|
|
1343
1677
|
className: "dialkit-spring-viz dialkit-easing-viz",
|
|
1344
1678
|
children: [
|
|
1345
|
-
/* @__PURE__ */ (0,
|
|
1679
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1346
1680
|
"line",
|
|
1347
1681
|
{
|
|
1348
1682
|
x1: start.x,
|
|
@@ -1354,7 +1688,7 @@ function EasingVisualization({ easing }) {
|
|
|
1354
1688
|
strokeDasharray: "4,4"
|
|
1355
1689
|
}
|
|
1356
1690
|
),
|
|
1357
|
-
/* @__PURE__ */ (0,
|
|
1691
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: curvePath, fill: "none", stroke: "rgba(255, 255, 255, 0.6)", strokeWidth: "2", strokeLinecap: "round" })
|
|
1358
1692
|
]
|
|
1359
1693
|
}
|
|
1360
1694
|
);
|
|
@@ -1362,7 +1696,7 @@ function EasingVisualization({ easing }) {
|
|
|
1362
1696
|
|
|
1363
1697
|
// src/components/TransitionControl.tsx
|
|
1364
1698
|
var import_react9 = require("react");
|
|
1365
|
-
var
|
|
1699
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1366
1700
|
function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
1367
1701
|
const mode = (0, import_react9.useSyncExternalStore)(
|
|
1368
1702
|
(cb) => DialStore.subscribe(panelId, cb),
|
|
@@ -1371,26 +1705,28 @@ function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
|
1371
1705
|
);
|
|
1372
1706
|
const isEasing = mode === "easing";
|
|
1373
1707
|
const isSimpleSpring = mode === "simple";
|
|
1374
|
-
const
|
|
1375
|
-
|
|
1708
|
+
const cache = (0, import_react9.useRef)({
|
|
1709
|
+
easing: value.type === "easing" ? value : { type: "easing", duration: 0.3, ease: [1, -0.4, 0.5, 1] },
|
|
1710
|
+
simple: value.type === "spring" && value.visualDuration !== void 0 ? value : { type: "spring", visualDuration: 0.3, bounce: 0.2 },
|
|
1711
|
+
advanced: value.type === "spring" && value.stiffness !== void 0 ? value : { type: "spring", stiffness: 200, damping: 25, mass: 1 }
|
|
1712
|
+
});
|
|
1713
|
+
if (isEasing && value.type === "easing") {
|
|
1714
|
+
cache.current.easing = value;
|
|
1715
|
+
} else if (isSimpleSpring && value.type === "spring") {
|
|
1716
|
+
cache.current.simple = value;
|
|
1717
|
+
} else if (mode === "advanced" && value.type === "spring") {
|
|
1718
|
+
cache.current.advanced = value;
|
|
1719
|
+
}
|
|
1720
|
+
const spring = value.type === "spring" ? value : cache.current.simple;
|
|
1721
|
+
const easing = value.type === "easing" ? value : cache.current.easing;
|
|
1376
1722
|
const handleModeChange = (newMode) => {
|
|
1377
1723
|
DialStore.updateTransitionMode(panelId, path, newMode);
|
|
1378
1724
|
if (newMode === "easing") {
|
|
1379
|
-
|
|
1380
|
-
onChange({ type: "easing", duration, ease: easing.ease });
|
|
1725
|
+
onChange(cache.current.easing);
|
|
1381
1726
|
} else if (newMode === "simple") {
|
|
1382
|
-
onChange(
|
|
1383
|
-
type: "spring",
|
|
1384
|
-
visualDuration: spring.visualDuration ?? (value.type === "easing" ? value.duration : 0.3),
|
|
1385
|
-
bounce: spring.bounce ?? 0.2
|
|
1386
|
-
});
|
|
1727
|
+
onChange(cache.current.simple);
|
|
1387
1728
|
} else {
|
|
1388
|
-
onChange(
|
|
1389
|
-
type: "spring",
|
|
1390
|
-
stiffness: spring.stiffness ?? 200,
|
|
1391
|
-
damping: spring.damping ?? 25,
|
|
1392
|
-
mass: spring.mass ?? 1
|
|
1393
|
-
});
|
|
1729
|
+
onChange(cache.current.advanced);
|
|
1394
1730
|
}
|
|
1395
1731
|
};
|
|
1396
1732
|
const handleSpringUpdate = (key, val) => {
|
|
@@ -1407,11 +1743,11 @@ function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
|
1407
1743
|
newEase[index] = val;
|
|
1408
1744
|
onChange({ ...easing, ease: newEase });
|
|
1409
1745
|
};
|
|
1410
|
-
return /* @__PURE__ */ (0,
|
|
1411
|
-
isEasing ? /* @__PURE__ */ (0,
|
|
1412
|
-
/* @__PURE__ */ (0,
|
|
1413
|
-
/* @__PURE__ */ (0,
|
|
1414
|
-
/* @__PURE__ */ (0,
|
|
1746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Folder, { title: label, defaultOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
1747
|
+
isEasing ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EasingVisualization, { easing }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SpringVisualization, { spring, isSimpleMode: isSimpleSpring }),
|
|
1748
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dialkit-labeled-control", children: [
|
|
1749
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dialkit-labeled-control-label", children: "Type" }),
|
|
1750
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1415
1751
|
SegmentedControl,
|
|
1416
1752
|
{
|
|
1417
1753
|
options: [
|
|
@@ -1424,20 +1760,20 @@ function TransitionControl({ panelId, path, label, value, onChange }) {
|
|
|
1424
1760
|
}
|
|
1425
1761
|
)
|
|
1426
1762
|
] }),
|
|
1427
|
-
isEasing ? /* @__PURE__ */ (0,
|
|
1428
|
-
/* @__PURE__ */ (0,
|
|
1429
|
-
/* @__PURE__ */ (0,
|
|
1430
|
-
/* @__PURE__ */ (0,
|
|
1431
|
-
/* @__PURE__ */ (0,
|
|
1432
|
-
/* @__PURE__ */ (0,
|
|
1433
|
-
/* @__PURE__ */ (0,
|
|
1434
|
-
] }) : isSimpleSpring ? /* @__PURE__ */ (0,
|
|
1435
|
-
/* @__PURE__ */ (0,
|
|
1436
|
-
/* @__PURE__ */ (0,
|
|
1437
|
-
] }) : /* @__PURE__ */ (0,
|
|
1438
|
-
/* @__PURE__ */ (0,
|
|
1439
|
-
/* @__PURE__ */ (0,
|
|
1440
|
-
/* @__PURE__ */ (0,
|
|
1763
|
+
isEasing ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1764
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Slider, { label: "x1", value: easing.ease[0], onChange: (v) => updateEase(0, v), min: 0, max: 1, step: 0.01 }),
|
|
1765
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Slider, { label: "y1", value: easing.ease[1], onChange: (v) => updateEase(1, v), min: -1, max: 2, step: 0.01 }),
|
|
1766
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Slider, { label: "x2", value: easing.ease[2], onChange: (v) => updateEase(2, v), min: 0, max: 1, step: 0.01 }),
|
|
1767
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Slider, { label: "y2", value: easing.ease[3], onChange: (v) => updateEase(3, v), min: -1, max: 2, step: 0.01 }),
|
|
1768
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Slider, { label: "Duration", value: easing.duration, onChange: (v) => onChange({ ...easing, duration: v }), min: 0.1, max: 2, step: 0.05, unit: "s" }),
|
|
1769
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EaseTextInput, { ease: easing.ease, onChange: (newEase) => onChange({ ...easing, ease: newEase }) })
|
|
1770
|
+
] }) : isSimpleSpring ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1771
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Slider, { label: "Duration", value: spring.visualDuration ?? 0.3, onChange: (v) => handleSpringUpdate("visualDuration", v), min: 0.1, max: 1, step: 0.05, unit: "s" }),
|
|
1772
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Slider, { label: "Bounce", value: spring.bounce ?? 0.2, onChange: (v) => handleSpringUpdate("bounce", v), min: 0, max: 1, step: 0.05 })
|
|
1773
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1774
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Slider, { label: "Stiffness", value: spring.stiffness ?? 400, onChange: (v) => handleSpringUpdate("stiffness", v), min: 1, max: 1e3, step: 10 }),
|
|
1775
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Slider, { label: "Damping", value: spring.damping ?? 17, onChange: (v) => handleSpringUpdate("damping", v), min: 1, max: 100, step: 1 }),
|
|
1776
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Slider, { label: "Mass", value: spring.mass ?? 1, onChange: (v) => handleSpringUpdate("mass", v), min: 0.1, max: 10, step: 0.1 })
|
|
1441
1777
|
] })
|
|
1442
1778
|
] }) });
|
|
1443
1779
|
}
|
|
@@ -1468,9 +1804,9 @@ function EaseTextInput({ ease, onChange }) {
|
|
|
1468
1804
|
e.target.blur();
|
|
1469
1805
|
}
|
|
1470
1806
|
};
|
|
1471
|
-
return /* @__PURE__ */ (0,
|
|
1472
|
-
/* @__PURE__ */ (0,
|
|
1473
|
-
/* @__PURE__ */ (0,
|
|
1807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dialkit-labeled-control", children: [
|
|
1808
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dialkit-labeled-control-label", children: "Ease" }),
|
|
1809
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1474
1810
|
"input",
|
|
1475
1811
|
{
|
|
1476
1812
|
type: "text",
|
|
@@ -1487,11 +1823,11 @@ function EaseTextInput({ ease, onChange }) {
|
|
|
1487
1823
|
}
|
|
1488
1824
|
|
|
1489
1825
|
// src/components/TextControl.tsx
|
|
1490
|
-
var
|
|
1826
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1491
1827
|
function TextControl({ label, value, onChange, placeholder }) {
|
|
1492
|
-
return /* @__PURE__ */ (0,
|
|
1493
|
-
/* @__PURE__ */ (0,
|
|
1494
|
-
/* @__PURE__ */ (0,
|
|
1828
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dialkit-text-control", children: [
|
|
1829
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "dialkit-text-label", children: label }),
|
|
1830
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1495
1831
|
"input",
|
|
1496
1832
|
{
|
|
1497
1833
|
type: "text",
|
|
@@ -1508,7 +1844,7 @@ function TextControl({ label, value, onChange, placeholder }) {
|
|
|
1508
1844
|
var import_react10 = require("react");
|
|
1509
1845
|
var import_react_dom = require("react-dom");
|
|
1510
1846
|
var import_react11 = require("motion/react");
|
|
1511
|
-
var
|
|
1847
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1512
1848
|
function toTitleCase(s) {
|
|
1513
1849
|
return s.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
1514
1850
|
}
|
|
@@ -1558,8 +1894,8 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1558
1894
|
document.addEventListener("mousedown", handleClick);
|
|
1559
1895
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
1560
1896
|
}, [isOpen]);
|
|
1561
|
-
return /* @__PURE__ */ (0,
|
|
1562
|
-
/* @__PURE__ */ (0,
|
|
1897
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dialkit-select-row", children: [
|
|
1898
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1563
1899
|
"button",
|
|
1564
1900
|
{
|
|
1565
1901
|
ref: triggerRef,
|
|
@@ -1567,10 +1903,10 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1567
1903
|
onClick: () => setIsOpen(!isOpen),
|
|
1568
1904
|
"data-open": String(isOpen),
|
|
1569
1905
|
children: [
|
|
1570
|
-
/* @__PURE__ */ (0,
|
|
1571
|
-
/* @__PURE__ */ (0,
|
|
1572
|
-
/* @__PURE__ */ (0,
|
|
1573
|
-
/* @__PURE__ */ (0,
|
|
1906
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dialkit-select-label", children: label }),
|
|
1907
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dialkit-select-right", children: [
|
|
1908
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dialkit-select-value", children: selectedOption?.label ?? value }),
|
|
1909
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1574
1910
|
import_react11.motion.svg,
|
|
1575
1911
|
{
|
|
1576
1912
|
className: "dialkit-select-chevron",
|
|
@@ -1582,7 +1918,7 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1582
1918
|
strokeLinejoin: "round",
|
|
1583
1919
|
animate: { rotate: isOpen ? 180 : 0 },
|
|
1584
1920
|
transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
|
|
1585
|
-
children: /* @__PURE__ */ (0,
|
|
1921
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: ICON_CHEVRON })
|
|
1586
1922
|
}
|
|
1587
1923
|
)
|
|
1588
1924
|
] })
|
|
@@ -1590,7 +1926,7 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1590
1926
|
}
|
|
1591
1927
|
),
|
|
1592
1928
|
portalTarget && (0, import_react_dom.createPortal)(
|
|
1593
|
-
/* @__PURE__ */ (0,
|
|
1929
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react11.AnimatePresence, { children: isOpen && pos && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1594
1930
|
import_react11.motion.div,
|
|
1595
1931
|
{
|
|
1596
1932
|
ref: dropdownRef,
|
|
@@ -1605,7 +1941,7 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1605
1941
|
width: pos.width,
|
|
1606
1942
|
...pos.above ? { bottom: window.innerHeight - pos.top, transformOrigin: "bottom" } : { top: pos.top, transformOrigin: "top" }
|
|
1607
1943
|
},
|
|
1608
|
-
children: normalized.map((option) => /* @__PURE__ */ (0,
|
|
1944
|
+
children: normalized.map((option) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1609
1945
|
"button",
|
|
1610
1946
|
{
|
|
1611
1947
|
className: "dialkit-select-option",
|
|
@@ -1627,7 +1963,7 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1627
1963
|
|
|
1628
1964
|
// src/components/ColorControl.tsx
|
|
1629
1965
|
var import_react12 = require("react");
|
|
1630
|
-
var
|
|
1966
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1631
1967
|
var HEX_COLOR_REGEX = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;
|
|
1632
1968
|
function ColorControl({ label, value, onChange }) {
|
|
1633
1969
|
const [isEditing, setIsEditing] = (0, import_react12.useState)(false);
|
|
@@ -1654,10 +1990,10 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1654
1990
|
setEditValue(value);
|
|
1655
1991
|
}
|
|
1656
1992
|
}
|
|
1657
|
-
return /* @__PURE__ */ (0,
|
|
1658
|
-
/* @__PURE__ */ (0,
|
|
1659
|
-
/* @__PURE__ */ (0,
|
|
1660
|
-
isEditing ? /* @__PURE__ */ (0,
|
|
1993
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dialkit-color-control", children: [
|
|
1994
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dialkit-color-label", children: label }),
|
|
1995
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dialkit-color-inputs", children: [
|
|
1996
|
+
isEditing ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1661
1997
|
"input",
|
|
1662
1998
|
{
|
|
1663
1999
|
type: "text",
|
|
@@ -1668,7 +2004,7 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1668
2004
|
onKeyDown: handleKeyDown,
|
|
1669
2005
|
autoFocus: true
|
|
1670
2006
|
}
|
|
1671
|
-
) : /* @__PURE__ */ (0,
|
|
2007
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1672
2008
|
"span",
|
|
1673
2009
|
{
|
|
1674
2010
|
className: "dialkit-color-hex",
|
|
@@ -1676,7 +2012,7 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1676
2012
|
children: (value ?? "").toUpperCase()
|
|
1677
2013
|
}
|
|
1678
2014
|
),
|
|
1679
|
-
/* @__PURE__ */ (0,
|
|
2015
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1680
2016
|
"button",
|
|
1681
2017
|
{
|
|
1682
2018
|
className: "dialkit-color-swatch",
|
|
@@ -1685,7 +2021,7 @@ function ColorControl({ label, value, onChange }) {
|
|
|
1685
2021
|
title: "Pick color"
|
|
1686
2022
|
}
|
|
1687
2023
|
),
|
|
1688
|
-
/* @__PURE__ */ (0,
|
|
2024
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1689
2025
|
"input",
|
|
1690
2026
|
{
|
|
1691
2027
|
ref: colorInputRef,
|
|
@@ -1707,7 +2043,7 @@ function expandShorthandHex(hex) {
|
|
|
1707
2043
|
var import_react13 = require("react");
|
|
1708
2044
|
var import_react_dom2 = require("react-dom");
|
|
1709
2045
|
var import_react14 = require("motion/react");
|
|
1710
|
-
var
|
|
2046
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1711
2047
|
function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
1712
2048
|
const [isOpen, setIsOpen] = (0, import_react13.useState)(false);
|
|
1713
2049
|
const triggerRef = (0, import_react13.useRef)(null);
|
|
@@ -1750,8 +2086,8 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1750
2086
|
e.stopPropagation();
|
|
1751
2087
|
DialStore.deletePreset(panelId, presetId);
|
|
1752
2088
|
};
|
|
1753
|
-
return /* @__PURE__ */ (0,
|
|
1754
|
-
/* @__PURE__ */ (0,
|
|
2089
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dialkit-preset-manager", children: [
|
|
2090
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1755
2091
|
"button",
|
|
1756
2092
|
{
|
|
1757
2093
|
ref: triggerRef,
|
|
@@ -1761,8 +2097,8 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1761
2097
|
"data-has-preset": String(!!activePreset),
|
|
1762
2098
|
"data-disabled": String(!hasPresets),
|
|
1763
2099
|
children: [
|
|
1764
|
-
/* @__PURE__ */ (0,
|
|
1765
|
-
/* @__PURE__ */ (0,
|
|
2100
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dialkit-preset-label", children: activePreset ? activePreset.name : "Version 1" }),
|
|
2101
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1766
2102
|
import_react14.motion.svg,
|
|
1767
2103
|
{
|
|
1768
2104
|
className: "dialkit-select-chevron",
|
|
@@ -1774,14 +2110,14 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1774
2110
|
strokeLinejoin: "round",
|
|
1775
2111
|
animate: { rotate: isOpen ? 180 : 0, opacity: hasPresets ? 0.6 : 0.25 },
|
|
1776
2112
|
transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
|
|
1777
|
-
children: /* @__PURE__ */ (0,
|
|
2113
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: ICON_CHEVRON })
|
|
1778
2114
|
}
|
|
1779
2115
|
)
|
|
1780
2116
|
]
|
|
1781
2117
|
}
|
|
1782
2118
|
),
|
|
1783
2119
|
(0, import_react_dom2.createPortal)(
|
|
1784
|
-
/* @__PURE__ */ (0,
|
|
2120
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react14.AnimatePresence, { children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1785
2121
|
import_react14.motion.div,
|
|
1786
2122
|
{
|
|
1787
2123
|
ref: dropdownRef,
|
|
@@ -1792,36 +2128,30 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1792
2128
|
exit: { opacity: 0, y: 4, scale: 0.97, pointerEvents: "none" },
|
|
1793
2129
|
transition: { type: "spring", visualDuration: 0.15, bounce: 0 },
|
|
1794
2130
|
children: [
|
|
1795
|
-
/* @__PURE__ */ (0,
|
|
2131
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1796
2132
|
"div",
|
|
1797
2133
|
{
|
|
1798
2134
|
className: "dialkit-preset-item",
|
|
1799
2135
|
"data-active": String(!activePresetId),
|
|
1800
2136
|
onClick: () => handleSelect(null),
|
|
1801
|
-
children: /* @__PURE__ */ (0,
|
|
2137
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dialkit-preset-name", children: "Version 1" })
|
|
1802
2138
|
}
|
|
1803
2139
|
),
|
|
1804
|
-
presets.map((preset) => /* @__PURE__ */ (0,
|
|
2140
|
+
presets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1805
2141
|
"div",
|
|
1806
2142
|
{
|
|
1807
2143
|
className: "dialkit-preset-item",
|
|
1808
2144
|
"data-active": String(preset.id === activePresetId),
|
|
1809
2145
|
onClick: () => handleSelect(preset.id),
|
|
1810
2146
|
children: [
|
|
1811
|
-
/* @__PURE__ */ (0,
|
|
1812
|
-
/* @__PURE__ */ (0,
|
|
2147
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dialkit-preset-name", children: preset.name }),
|
|
2148
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1813
2149
|
"button",
|
|
1814
2150
|
{
|
|
1815
2151
|
className: "dialkit-preset-delete",
|
|
1816
2152
|
onClick: (e) => handleDelete(e, preset.id),
|
|
1817
2153
|
title: "Delete preset",
|
|
1818
|
-
children: /* @__PURE__ */ (0,
|
|
1819
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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" }),
|
|
1820
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M10 11V16" }),
|
|
1821
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M14 11V16" }),
|
|
1822
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M3.5 6H20.5" }),
|
|
1823
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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" })
|
|
1824
|
-
] })
|
|
2154
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: ICON_TRASH.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d }, i)) })
|
|
1825
2155
|
}
|
|
1826
2156
|
)
|
|
1827
2157
|
]
|
|
@@ -1837,10 +2167,12 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1837
2167
|
}
|
|
1838
2168
|
|
|
1839
2169
|
// src/components/Panel.tsx
|
|
1840
|
-
var
|
|
1841
|
-
function Panel({ panel, defaultOpen = true }) {
|
|
2170
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2171
|
+
function Panel({ panel, defaultOpen = true, inline = false }) {
|
|
1842
2172
|
const [copied, setCopied] = (0, import_react15.useState)(false);
|
|
1843
2173
|
const [isPanelOpen, setIsPanelOpen] = (0, import_react15.useState)(defaultOpen);
|
|
2174
|
+
const shortcutCtx = (0, import_react15.useContext)(ShortcutContext);
|
|
2175
|
+
const hasShortcuts = Object.keys(panel.shortcuts).length > 0;
|
|
1844
2176
|
const values = (0, import_react15.useSyncExternalStore)(
|
|
1845
2177
|
(cb) => DialStore.subscribe(panel.id, cb),
|
|
1846
2178
|
() => DialStore.getValues(panel.id),
|
|
@@ -1869,7 +2201,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1869
2201
|
const value = values[control.path];
|
|
1870
2202
|
switch (control.type) {
|
|
1871
2203
|
case "slider":
|
|
1872
|
-
return /* @__PURE__ */ (0,
|
|
2204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1873
2205
|
Slider,
|
|
1874
2206
|
{
|
|
1875
2207
|
label: control.label,
|
|
@@ -1877,22 +2209,26 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1877
2209
|
onChange: (v) => DialStore.updateValue(panel.id, control.path, v),
|
|
1878
2210
|
min: control.min,
|
|
1879
2211
|
max: control.max,
|
|
1880
|
-
step: control.step
|
|
2212
|
+
step: control.step,
|
|
2213
|
+
shortcut: control.shortcut,
|
|
2214
|
+
shortcutActive: shortcutCtx.activePanelId === panel.id && shortcutCtx.activePath === control.path
|
|
1881
2215
|
},
|
|
1882
2216
|
control.path
|
|
1883
2217
|
);
|
|
1884
2218
|
case "toggle":
|
|
1885
|
-
return /* @__PURE__ */ (0,
|
|
2219
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1886
2220
|
Toggle,
|
|
1887
2221
|
{
|
|
1888
2222
|
label: control.label,
|
|
1889
2223
|
checked: value,
|
|
1890
|
-
onChange: (v) => DialStore.updateValue(panel.id, control.path, v)
|
|
2224
|
+
onChange: (v) => DialStore.updateValue(panel.id, control.path, v),
|
|
2225
|
+
shortcut: control.shortcut,
|
|
2226
|
+
shortcutActive: shortcutCtx.activePanelId === panel.id && shortcutCtx.activePath === control.path
|
|
1891
2227
|
},
|
|
1892
2228
|
control.path
|
|
1893
2229
|
);
|
|
1894
2230
|
case "spring":
|
|
1895
|
-
return /* @__PURE__ */ (0,
|
|
2231
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1896
2232
|
SpringControl,
|
|
1897
2233
|
{
|
|
1898
2234
|
panelId: panel.id,
|
|
@@ -1904,7 +2240,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1904
2240
|
control.path
|
|
1905
2241
|
);
|
|
1906
2242
|
case "transition":
|
|
1907
|
-
return /* @__PURE__ */ (0,
|
|
2243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1908
2244
|
TransitionControl,
|
|
1909
2245
|
{
|
|
1910
2246
|
panelId: panel.id,
|
|
@@ -1916,9 +2252,9 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1916
2252
|
control.path
|
|
1917
2253
|
);
|
|
1918
2254
|
case "folder":
|
|
1919
|
-
return /* @__PURE__ */ (0,
|
|
2255
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Folder, { title: control.label, defaultOpen: control.defaultOpen ?? true, children: control.children?.map(renderControl) }, control.path);
|
|
1920
2256
|
case "text":
|
|
1921
|
-
return /* @__PURE__ */ (0,
|
|
2257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1922
2258
|
TextControl,
|
|
1923
2259
|
{
|
|
1924
2260
|
label: control.label,
|
|
@@ -1929,7 +2265,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1929
2265
|
control.path
|
|
1930
2266
|
);
|
|
1931
2267
|
case "select":
|
|
1932
|
-
return /* @__PURE__ */ (0,
|
|
2268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1933
2269
|
SelectControl,
|
|
1934
2270
|
{
|
|
1935
2271
|
label: control.label,
|
|
@@ -1940,7 +2276,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1940
2276
|
control.path
|
|
1941
2277
|
);
|
|
1942
2278
|
case "color":
|
|
1943
|
-
return /* @__PURE__ */ (0,
|
|
2279
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1944
2280
|
ColorControl,
|
|
1945
2281
|
{
|
|
1946
2282
|
label: control.label,
|
|
@@ -1950,7 +2286,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1950
2286
|
control.path
|
|
1951
2287
|
);
|
|
1952
2288
|
case "action":
|
|
1953
|
-
return /* @__PURE__ */ (0,
|
|
2289
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1954
2290
|
"button",
|
|
1955
2291
|
{
|
|
1956
2292
|
className: "dialkit-button",
|
|
@@ -1967,8 +2303,8 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1967
2303
|
return panel.controls.map(renderControl);
|
|
1968
2304
|
};
|
|
1969
2305
|
const iconTransition = { type: "spring", visualDuration: 0.4, bounce: 0.1 };
|
|
1970
|
-
const toolbar = /* @__PURE__ */ (0,
|
|
1971
|
-
/* @__PURE__ */ (0,
|
|
2306
|
+
const toolbar = /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
2307
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1972
2308
|
import_react16.motion.button,
|
|
1973
2309
|
{
|
|
1974
2310
|
className: "dialkit-toolbar-add",
|
|
@@ -1976,16 +2312,10 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1976
2312
|
title: "Add preset",
|
|
1977
2313
|
whileTap: { scale: 0.9 },
|
|
1978
2314
|
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
1979
|
-
children: /* @__PURE__ */ (0,
|
|
1980
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M4 6H20" }),
|
|
1981
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M4 12H10" }),
|
|
1982
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M15 15L21 15" }),
|
|
1983
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M18 12V18" }),
|
|
1984
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M4 18H10" })
|
|
1985
|
-
] })
|
|
2315
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("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__ */ (0, import_jsx_runtime14.jsx)("path", { d }, i)) })
|
|
1986
2316
|
}
|
|
1987
2317
|
),
|
|
1988
|
-
/* @__PURE__ */ (0,
|
|
2318
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1989
2319
|
PresetManager,
|
|
1990
2320
|
{
|
|
1991
2321
|
panelId: panel.id,
|
|
@@ -1994,63 +2324,71 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1994
2324
|
onAdd: handleAddPreset
|
|
1995
2325
|
}
|
|
1996
2326
|
),
|
|
1997
|
-
/* @__PURE__ */ (0,
|
|
2327
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1998
2328
|
import_react16.motion.button,
|
|
1999
2329
|
{
|
|
2000
|
-
className: "dialkit-toolbar-
|
|
2330
|
+
className: "dialkit-toolbar-add",
|
|
2001
2331
|
onClick: handleCopy,
|
|
2002
2332
|
title: "Copy parameters",
|
|
2003
|
-
whileTap: { scale: 0.
|
|
2333
|
+
whileTap: { scale: 0.9 },
|
|
2004
2334
|
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
2005
|
-
children:
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
) }) }),
|
|
2041
|
-
"Copy"
|
|
2042
|
-
]
|
|
2335
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: { position: "relative", width: 16, height: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react16.AnimatePresence, { initial: false, mode: "wait", children: copied ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2336
|
+
import_react16.motion.svg,
|
|
2337
|
+
{
|
|
2338
|
+
viewBox: "0 0 24 24",
|
|
2339
|
+
fill: "none",
|
|
2340
|
+
stroke: "currentColor",
|
|
2341
|
+
strokeWidth: "2",
|
|
2342
|
+
strokeLinecap: "round",
|
|
2343
|
+
strokeLinejoin: "round",
|
|
2344
|
+
style: { position: "absolute", inset: 0, width: 16, height: 16, color: "var(--dial-text-label)" },
|
|
2345
|
+
initial: { scale: 0.8, opacity: 0 },
|
|
2346
|
+
animate: { scale: 1, opacity: 1 },
|
|
2347
|
+
exit: { scale: 0.8, opacity: 0 },
|
|
2348
|
+
transition: { duration: 0.08 },
|
|
2349
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("path", { d: ICON_CHECK })
|
|
2350
|
+
},
|
|
2351
|
+
"check"
|
|
2352
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2353
|
+
import_react16.motion.svg,
|
|
2354
|
+
{
|
|
2355
|
+
viewBox: "0 0 24 24",
|
|
2356
|
+
fill: "none",
|
|
2357
|
+
style: { position: "absolute", inset: 0, width: 16, height: 16, color: "var(--dial-text-label)" },
|
|
2358
|
+
initial: { scale: 0.8, opacity: 0 },
|
|
2359
|
+
animate: { scale: 1, opacity: 1 },
|
|
2360
|
+
exit: { scale: 0.8, opacity: 0 },
|
|
2361
|
+
transition: { duration: 0.08 },
|
|
2362
|
+
children: [
|
|
2363
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("path", { d: ICON_CLIPBOARD.board, stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }),
|
|
2364
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("path", { d: ICON_CLIPBOARD.sparkle, fill: "currentColor" }),
|
|
2365
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("path", { d: ICON_CLIPBOARD.body, stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
2366
|
+
]
|
|
2367
|
+
},
|
|
2368
|
+
"clipboard"
|
|
2369
|
+
) }) })
|
|
2043
2370
|
}
|
|
2044
2371
|
)
|
|
2045
2372
|
] });
|
|
2046
|
-
return /* @__PURE__ */ (0,
|
|
2373
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dialkit-panel-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Folder, { title: panel.name, defaultOpen, isRoot: true, inline, onOpenChange: setIsPanelOpen, toolbar, children: renderControls() }) });
|
|
2047
2374
|
}
|
|
2048
2375
|
|
|
2049
2376
|
// src/components/DialRoot.tsx
|
|
2050
|
-
var
|
|
2051
|
-
|
|
2377
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2378
|
+
var import_meta = {};
|
|
2379
|
+
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;
|
|
2380
|
+
function DialRoot({ position = "top-right", defaultOpen = true, mode = "popover", theme = "system", productionEnabled = isDevDefault }) {
|
|
2381
|
+
if (!productionEnabled) return null;
|
|
2052
2382
|
const [panels, setPanels] = (0, import_react17.useState)([]);
|
|
2053
2383
|
const [mounted, setMounted] = (0, import_react17.useState)(false);
|
|
2384
|
+
const inline = mode === "inline";
|
|
2385
|
+
const panelRef = (0, import_react17.useRef)(null);
|
|
2386
|
+
const [dragOffset, setDragOffset] = (0, import_react17.useState)(null);
|
|
2387
|
+
const [activePosition, setActivePosition] = (0, import_react17.useState)(position);
|
|
2388
|
+
const lastDragOffset = (0, import_react17.useRef)(null);
|
|
2389
|
+
const draggingRef = (0, import_react17.useRef)(false);
|
|
2390
|
+
const dragStartRef = (0, import_react17.useRef)(null);
|
|
2391
|
+
const didDragRef = (0, import_react17.useRef)(false);
|
|
2054
2392
|
(0, import_react17.useEffect)(() => {
|
|
2055
2393
|
setMounted(true);
|
|
2056
2394
|
setPanels(DialStore.getPanels());
|
|
@@ -2059,20 +2397,105 @@ function DialRoot({ position = "top-right", defaultOpen = true }) {
|
|
|
2059
2397
|
});
|
|
2060
2398
|
return unsubscribe;
|
|
2061
2399
|
}, []);
|
|
2400
|
+
(0, import_react17.useEffect)(() => {
|
|
2401
|
+
if (!panelRef.current || inline) return;
|
|
2402
|
+
const observer = new MutationObserver(() => {
|
|
2403
|
+
const inner = panelRef.current?.querySelector(".dialkit-panel-inner");
|
|
2404
|
+
if (!inner) return;
|
|
2405
|
+
const collapsed = inner.getAttribute("data-collapsed") === "true";
|
|
2406
|
+
if (!collapsed) {
|
|
2407
|
+
if (dragOffset) {
|
|
2408
|
+
lastDragOffset.current = dragOffset;
|
|
2409
|
+
const bubbleCenterX = dragOffset.x + 21;
|
|
2410
|
+
const midX = window.innerWidth / 2;
|
|
2411
|
+
setActivePosition(bubbleCenterX < midX ? "top-left" : "top-right");
|
|
2412
|
+
} else {
|
|
2413
|
+
setActivePosition(position);
|
|
2414
|
+
}
|
|
2415
|
+
setDragOffset(null);
|
|
2416
|
+
} else if (lastDragOffset.current) {
|
|
2417
|
+
setDragOffset(lastDragOffset.current);
|
|
2418
|
+
}
|
|
2419
|
+
});
|
|
2420
|
+
observer.observe(panelRef.current, { subtree: true, attributes: true, attributeFilter: ["data-collapsed"] });
|
|
2421
|
+
return () => observer.disconnect();
|
|
2422
|
+
}, [inline, dragOffset, position]);
|
|
2423
|
+
const handlePointerDown = (0, import_react17.useCallback)((e) => {
|
|
2424
|
+
const inner = panelRef.current?.querySelector(".dialkit-panel-inner");
|
|
2425
|
+
if (!inner || inner.getAttribute("data-collapsed") !== "true") return;
|
|
2426
|
+
const rect = panelRef.current.getBoundingClientRect();
|
|
2427
|
+
dragStartRef.current = {
|
|
2428
|
+
pointerX: e.clientX,
|
|
2429
|
+
pointerY: e.clientY,
|
|
2430
|
+
elX: rect.left,
|
|
2431
|
+
elY: rect.top
|
|
2432
|
+
};
|
|
2433
|
+
didDragRef.current = false;
|
|
2434
|
+
draggingRef.current = true;
|
|
2435
|
+
e.target.setPointerCapture(e.pointerId);
|
|
2436
|
+
}, []);
|
|
2437
|
+
const handlePointerMove = (0, import_react17.useCallback)((e) => {
|
|
2438
|
+
if (!draggingRef.current || !dragStartRef.current) return;
|
|
2439
|
+
const dx = e.clientX - dragStartRef.current.pointerX;
|
|
2440
|
+
const dy = e.clientY - dragStartRef.current.pointerY;
|
|
2441
|
+
if (!didDragRef.current && Math.abs(dx) + Math.abs(dy) < 4) return;
|
|
2442
|
+
didDragRef.current = true;
|
|
2443
|
+
setDragOffset({
|
|
2444
|
+
x: dragStartRef.current.elX + dx,
|
|
2445
|
+
y: dragStartRef.current.elY + dy
|
|
2446
|
+
});
|
|
2447
|
+
}, []);
|
|
2448
|
+
const handlePointerUp = (0, import_react17.useCallback)((e) => {
|
|
2449
|
+
if (!draggingRef.current) return;
|
|
2450
|
+
draggingRef.current = false;
|
|
2451
|
+
dragStartRef.current = null;
|
|
2452
|
+
if (didDragRef.current) {
|
|
2453
|
+
e.stopPropagation();
|
|
2454
|
+
const inner = panelRef.current?.querySelector(".dialkit-panel-inner");
|
|
2455
|
+
if (inner) {
|
|
2456
|
+
const blocker = (ev) => {
|
|
2457
|
+
ev.stopPropagation();
|
|
2458
|
+
};
|
|
2459
|
+
inner.addEventListener("click", blocker, { capture: true, once: true });
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
}, []);
|
|
2062
2463
|
if (!mounted || typeof window === "undefined") {
|
|
2063
2464
|
return null;
|
|
2064
2465
|
}
|
|
2065
2466
|
if (panels.length === 0) {
|
|
2066
2467
|
return null;
|
|
2067
2468
|
}
|
|
2068
|
-
const
|
|
2469
|
+
const dragStyle = dragOffset ? {
|
|
2470
|
+
top: dragOffset.y,
|
|
2471
|
+
left: dragOffset.x,
|
|
2472
|
+
right: "auto",
|
|
2473
|
+
bottom: "auto"
|
|
2474
|
+
} : void 0;
|
|
2475
|
+
const content = /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ShortcutListener, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "dialkit-root", "data-mode": mode, "data-theme": theme, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2476
|
+
"div",
|
|
2477
|
+
{
|
|
2478
|
+
ref: panelRef,
|
|
2479
|
+
className: "dialkit-panel",
|
|
2480
|
+
"data-position": inline ? void 0 : dragOffset ? void 0 : activePosition,
|
|
2481
|
+
"data-mode": mode,
|
|
2482
|
+
style: dragStyle,
|
|
2483
|
+
onPointerDown: !inline ? handlePointerDown : void 0,
|
|
2484
|
+
onPointerMove: !inline ? handlePointerMove : void 0,
|
|
2485
|
+
onPointerUp: !inline ? handlePointerUp : void 0,
|
|
2486
|
+
children: panels.map((panel) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Panel, { panel, defaultOpen: inline || defaultOpen, inline }, panel.id))
|
|
2487
|
+
}
|
|
2488
|
+
) }) });
|
|
2489
|
+
if (inline) {
|
|
2490
|
+
return content;
|
|
2491
|
+
}
|
|
2069
2492
|
return (0, import_react_dom3.createPortal)(content, document.body);
|
|
2070
2493
|
}
|
|
2071
2494
|
|
|
2072
2495
|
// src/components/ButtonGroup.tsx
|
|
2073
|
-
var
|
|
2496
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
2074
2497
|
function ButtonGroup({ buttons }) {
|
|
2075
|
-
return /* @__PURE__ */ (0,
|
|
2498
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "dialkit-button-group", children: buttons.map((button, index) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2076
2499
|
"button",
|
|
2077
2500
|
{
|
|
2078
2501
|
className: "dialkit-button",
|
|
@@ -2082,6 +2505,124 @@ function ButtonGroup({ buttons }) {
|
|
|
2082
2505
|
index
|
|
2083
2506
|
)) });
|
|
2084
2507
|
}
|
|
2508
|
+
|
|
2509
|
+
// src/components/ShortcutsMenu.tsx
|
|
2510
|
+
var import_react18 = require("react");
|
|
2511
|
+
var import_react_dom4 = require("react-dom");
|
|
2512
|
+
var import_react19 = require("motion/react");
|
|
2513
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
2514
|
+
function formatShortcutKey(sc) {
|
|
2515
|
+
if (!sc.key) return "\u2014";
|
|
2516
|
+
const mod = sc.modifier === "alt" ? "\u2325" : sc.modifier === "shift" ? "\u21E7" : sc.modifier === "meta" ? "\u2318" : "";
|
|
2517
|
+
return `${mod}${sc.key.toUpperCase()}`;
|
|
2518
|
+
}
|
|
2519
|
+
function formatInteraction(sc) {
|
|
2520
|
+
const interaction = sc.interaction ?? "scroll";
|
|
2521
|
+
switch (interaction) {
|
|
2522
|
+
case "scroll":
|
|
2523
|
+
return sc.key ? "key+scroll" : "scroll";
|
|
2524
|
+
case "drag":
|
|
2525
|
+
return "key+drag";
|
|
2526
|
+
case "move":
|
|
2527
|
+
return "key+move";
|
|
2528
|
+
case "scroll-only":
|
|
2529
|
+
return "scroll";
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
function ShortcutsMenu({ panelId }) {
|
|
2533
|
+
const [isOpen, setIsOpen] = (0, import_react18.useState)(false);
|
|
2534
|
+
const triggerRef = (0, import_react18.useRef)(null);
|
|
2535
|
+
const dropdownRef = (0, import_react18.useRef)(null);
|
|
2536
|
+
const [pos, setPos] = (0, import_react18.useState)({ top: 0, right: 0 });
|
|
2537
|
+
const open = (0, import_react18.useCallback)(() => {
|
|
2538
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
2539
|
+
if (rect) {
|
|
2540
|
+
setPos({ top: rect.bottom + 4, right: window.innerWidth - rect.right });
|
|
2541
|
+
}
|
|
2542
|
+
setIsOpen(true);
|
|
2543
|
+
}, []);
|
|
2544
|
+
const close = (0, import_react18.useCallback)(() => setIsOpen(false), []);
|
|
2545
|
+
const toggle = (0, import_react18.useCallback)(() => {
|
|
2546
|
+
if (isOpen) close();
|
|
2547
|
+
else open();
|
|
2548
|
+
}, [isOpen, open, close]);
|
|
2549
|
+
(0, import_react18.useEffect)(() => {
|
|
2550
|
+
if (!isOpen) return;
|
|
2551
|
+
const handler = (e) => {
|
|
2552
|
+
const target = e.target;
|
|
2553
|
+
if (triggerRef.current?.contains(target) || dropdownRef.current?.contains(target)) return;
|
|
2554
|
+
close();
|
|
2555
|
+
};
|
|
2556
|
+
document.addEventListener("mousedown", handler);
|
|
2557
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
2558
|
+
}, [isOpen, close]);
|
|
2559
|
+
const panel = DialStore.getPanel(panelId);
|
|
2560
|
+
if (!panel) return null;
|
|
2561
|
+
const shortcuts = Object.entries(panel.shortcuts);
|
|
2562
|
+
if (shortcuts.length === 0) return null;
|
|
2563
|
+
const rows = shortcuts.map(([path, shortcut]) => {
|
|
2564
|
+
const findLabel = (controls) => {
|
|
2565
|
+
for (const c of controls) {
|
|
2566
|
+
if (c.path === path) return c.label;
|
|
2567
|
+
if (c.type === "folder" && c.children) {
|
|
2568
|
+
const found = findLabel(c.children);
|
|
2569
|
+
if (found) return found;
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
return path;
|
|
2573
|
+
};
|
|
2574
|
+
return {
|
|
2575
|
+
path,
|
|
2576
|
+
shortcut,
|
|
2577
|
+
label: findLabel(panel.controls)
|
|
2578
|
+
};
|
|
2579
|
+
});
|
|
2580
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
2581
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2582
|
+
import_react19.motion.button,
|
|
2583
|
+
{
|
|
2584
|
+
ref: triggerRef,
|
|
2585
|
+
className: "dialkit-shortcuts-trigger",
|
|
2586
|
+
onClick: toggle,
|
|
2587
|
+
title: "Keyboard shortcuts",
|
|
2588
|
+
whileTap: { scale: 0.9 },
|
|
2589
|
+
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
2590
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2591
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("rect", { x: "2", y: "6", width: "20", height: "12", rx: "2" }),
|
|
2592
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M6 10H6.01" }),
|
|
2593
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M10 10H10.01" }),
|
|
2594
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M14 10H14.01" }),
|
|
2595
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M18 10H18.01" }),
|
|
2596
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M8 14H16" })
|
|
2597
|
+
] })
|
|
2598
|
+
}
|
|
2599
|
+
),
|
|
2600
|
+
(0, import_react_dom4.createPortal)(
|
|
2601
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react19.AnimatePresence, { children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2602
|
+
import_react19.motion.div,
|
|
2603
|
+
{
|
|
2604
|
+
ref: dropdownRef,
|
|
2605
|
+
className: "dialkit-root dialkit-shortcuts-dropdown",
|
|
2606
|
+
style: { position: "fixed", top: pos.top, right: pos.right },
|
|
2607
|
+
initial: { opacity: 0, y: 4, scale: 0.97 },
|
|
2608
|
+
animate: { opacity: 1, y: 0, scale: 1 },
|
|
2609
|
+
exit: { opacity: 0, y: 4, scale: 0.97, pointerEvents: "none" },
|
|
2610
|
+
transition: { type: "spring", visualDuration: 0.15, bounce: 0 },
|
|
2611
|
+
children: [
|
|
2612
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "dialkit-shortcuts-title", children: "Keyboard Shortcuts" }),
|
|
2613
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "dialkit-shortcuts-list", children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "dialkit-shortcuts-row", children: [
|
|
2614
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dialkit-shortcuts-row-key", children: formatShortcutKey(row.shortcut) }),
|
|
2615
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dialkit-shortcuts-row-label", children: row.label }),
|
|
2616
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dialkit-shortcuts-row-mode", children: formatInteraction(row.shortcut) })
|
|
2617
|
+
] }, row.path)) }),
|
|
2618
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "dialkit-shortcuts-hint", children: "See pill badges on controls for keys" })
|
|
2619
|
+
]
|
|
2620
|
+
}
|
|
2621
|
+
) }),
|
|
2622
|
+
document.body
|
|
2623
|
+
)
|
|
2624
|
+
] });
|
|
2625
|
+
}
|
|
2085
2626
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2086
2627
|
0 && (module.exports = {
|
|
2087
2628
|
ButtonGroup,
|
|
@@ -2092,6 +2633,7 @@ function ButtonGroup({ buttons }) {
|
|
|
2092
2633
|
Folder,
|
|
2093
2634
|
PresetManager,
|
|
2094
2635
|
SelectControl,
|
|
2636
|
+
ShortcutsMenu,
|
|
2095
2637
|
Slider,
|
|
2096
2638
|
SpringControl,
|
|
2097
2639
|
SpringVisualization,
|