dialkit 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -6
- package/dist/index.cjs +138 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +143 -104
- package/dist/index.js.map +1 -1
- package/dist/styles.css +3 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,12 +72,24 @@ Returns a fully typed object matching your config shape with live values. Updati
|
|
|
72
72
|
|
|
73
73
|
### Slider
|
|
74
74
|
|
|
75
|
+
Numbers create sliders. There are three ways to define them:
|
|
76
|
+
|
|
77
|
+
**Explicit range** — `[default, min, max]`:
|
|
78
|
+
```tsx
|
|
79
|
+
blur: [24, 0, 100]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Explicit range + step** — `[default, min, max, step]`:
|
|
75
83
|
```tsx
|
|
76
|
-
blur: [24, 0, 100]
|
|
77
|
-
scale: 1.2 // auto-infers range from value
|
|
84
|
+
blur: [24, 0, 100, 5] // snaps in increments of 5
|
|
78
85
|
```
|
|
86
|
+
When `step` is omitted, it's inferred from the range (see table below).
|
|
79
87
|
|
|
80
|
-
|
|
88
|
+
**Auto-inferred** — bare number:
|
|
89
|
+
```tsx
|
|
90
|
+
scale: 1.2
|
|
91
|
+
```
|
|
92
|
+
A single number auto-infers a reasonable min, max, and step:
|
|
81
93
|
|
|
82
94
|
| Value range | Inferred min/max | Step |
|
|
83
95
|
|-------------|-----------------|------|
|
|
@@ -197,19 +209,28 @@ Action buttons trigger callbacks without storing any value. The `label` defaults
|
|
|
197
209
|
|
|
198
210
|
### Folder
|
|
199
211
|
|
|
212
|
+
Any nested plain object becomes a collapsible folder. Folders can nest arbitrarily deep.
|
|
213
|
+
|
|
200
214
|
```tsx
|
|
201
215
|
shadow: {
|
|
202
216
|
blur: [10, 0, 50],
|
|
203
217
|
opacity: [0.25, 0, 1],
|
|
204
218
|
color: '#000000',
|
|
205
219
|
}
|
|
220
|
+
|
|
221
|
+
// Access nested values:
|
|
222
|
+
params.shadow.blur // number
|
|
223
|
+
params.shadow.color // string
|
|
206
224
|
```
|
|
207
225
|
|
|
208
|
-
|
|
226
|
+
Folders are open by default. Add `_collapsed: true` to start a folder closed. This is a reserved metadata key — it controls the UI only and won't appear in your returned values.
|
|
209
227
|
|
|
210
228
|
```tsx
|
|
211
|
-
|
|
212
|
-
|
|
229
|
+
shadow: {
|
|
230
|
+
_collapsed: true, // folder starts closed
|
|
231
|
+
blur: [10, 0, 50],
|
|
232
|
+
opacity: [0.25, 0, 1],
|
|
233
|
+
}
|
|
213
234
|
```
|
|
214
235
|
|
|
215
236
|
---
|
package/dist/index.cjs
CHANGED
|
@@ -197,16 +197,17 @@ var DialStoreClass = class {
|
|
|
197
197
|
parseConfig(config, prefix) {
|
|
198
198
|
const controls = [];
|
|
199
199
|
for (const [key, value] of Object.entries(config)) {
|
|
200
|
+
if (key === "_collapsed") continue;
|
|
200
201
|
const path = prefix ? `${prefix}.${key}` : key;
|
|
201
202
|
const label = this.formatLabel(key);
|
|
202
|
-
if (Array.isArray(value) && value.length
|
|
203
|
+
if (Array.isArray(value) && value.length <= 4 && typeof value[0] === "number") {
|
|
203
204
|
controls.push({
|
|
204
205
|
type: "slider",
|
|
205
206
|
path,
|
|
206
207
|
label,
|
|
207
208
|
min: value[1],
|
|
208
209
|
max: value[2],
|
|
209
|
-
step: this.inferStep(value[1], value[2])
|
|
210
|
+
step: value[3] ?? this.inferStep(value[1], value[2])
|
|
210
211
|
});
|
|
211
212
|
} else if (typeof value === "number") {
|
|
212
213
|
const { min, max, step } = this.inferRange(value);
|
|
@@ -230,11 +231,14 @@ var DialStoreClass = class {
|
|
|
230
231
|
controls.push({ type: "text", path, label });
|
|
231
232
|
}
|
|
232
233
|
} else if (typeof value === "object" && value !== null) {
|
|
234
|
+
const folderConfig = value;
|
|
235
|
+
const defaultOpen = "_collapsed" in folderConfig ? !folderConfig._collapsed : true;
|
|
233
236
|
controls.push({
|
|
234
237
|
type: "folder",
|
|
235
238
|
path,
|
|
236
239
|
label,
|
|
237
|
-
|
|
240
|
+
defaultOpen,
|
|
241
|
+
children: this.parseConfig(folderConfig, path)
|
|
238
242
|
});
|
|
239
243
|
}
|
|
240
244
|
}
|
|
@@ -243,8 +247,9 @@ var DialStoreClass = class {
|
|
|
243
247
|
flattenValues(config, prefix) {
|
|
244
248
|
const values = {};
|
|
245
249
|
for (const [key, value] of Object.entries(config)) {
|
|
250
|
+
if (key === "_collapsed") continue;
|
|
246
251
|
const path = prefix ? `${prefix}.${key}` : key;
|
|
247
|
-
if (Array.isArray(value) && value.length
|
|
252
|
+
if (Array.isArray(value) && value.length <= 4 && typeof value[0] === "number") {
|
|
248
253
|
values[path] = value[0];
|
|
249
254
|
} else if (typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
|
|
250
255
|
values[path] = value;
|
|
@@ -336,8 +341,9 @@ function useDialKit(name, config, options) {
|
|
|
336
341
|
function buildResolvedValues(config, flatValues, prefix) {
|
|
337
342
|
const result = {};
|
|
338
343
|
for (const [key, configValue] of Object.entries(config)) {
|
|
344
|
+
if (key === "_collapsed") continue;
|
|
339
345
|
const path = prefix ? `${prefix}.${key}` : key;
|
|
340
|
-
if (Array.isArray(configValue) && configValue.length
|
|
346
|
+
if (Array.isArray(configValue) && configValue.length <= 4 && typeof configValue[0] === "number") {
|
|
341
347
|
result[key] = flatValues[path] ?? configValue[0];
|
|
342
348
|
} else if (typeof configValue === "number" || typeof configValue === "boolean" || typeof configValue === "string") {
|
|
343
349
|
result[key] = flatValues[path] ?? configValue;
|
|
@@ -383,7 +389,7 @@ function getFirstOptionValue(options) {
|
|
|
383
389
|
|
|
384
390
|
// src/components/DialRoot.tsx
|
|
385
391
|
var import_react16 = require("react");
|
|
386
|
-
var
|
|
392
|
+
var import_react_dom3 = require("react-dom");
|
|
387
393
|
|
|
388
394
|
// src/components/Panel.tsx
|
|
389
395
|
var import_react14 = require("react");
|
|
@@ -398,8 +404,6 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
398
404
|
const [isCollapsed, setIsCollapsed] = (0, import_react2.useState)(!defaultOpen);
|
|
399
405
|
const contentRef = (0, import_react2.useRef)(null);
|
|
400
406
|
const [contentHeight, setContentHeight] = (0, import_react2.useState)(void 0);
|
|
401
|
-
const iconTransition = { type: "spring", visualDuration: 0.4, bounce: 0.1 };
|
|
402
|
-
const panelTransition = { type: "spring", visualDuration: 0.4, bounce: 0.2 };
|
|
403
407
|
(0, import_react2.useEffect)(() => {
|
|
404
408
|
const el = contentRef.current;
|
|
405
409
|
if (!el) return;
|
|
@@ -412,25 +416,20 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
412
416
|
ro.observe(el);
|
|
413
417
|
return () => ro.disconnect();
|
|
414
418
|
}, [isOpen]);
|
|
419
|
+
const handleToggle = () => {
|
|
420
|
+
const next = !isOpen;
|
|
421
|
+
setIsOpen(next);
|
|
422
|
+
if (next) {
|
|
423
|
+
setIsCollapsed(false);
|
|
424
|
+
} else {
|
|
425
|
+
setIsCollapsed(true);
|
|
426
|
+
}
|
|
427
|
+
onOpenChange?.(next);
|
|
428
|
+
};
|
|
415
429
|
const folderContent = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: isRoot ? contentRef : void 0, className: `dialkit-folder ${isRoot ? "dialkit-folder-root" : ""}`, children: [
|
|
416
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `dialkit-folder-header ${isRoot ? "dialkit-panel-header" : ""}`, onClick:
|
|
417
|
-
const next = !isOpen;
|
|
418
|
-
setIsOpen(next);
|
|
419
|
-
if (next) setIsCollapsed(false);
|
|
420
|
-
onOpenChange?.(next);
|
|
421
|
-
}, children: [
|
|
430
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `dialkit-folder-header ${isRoot ? "dialkit-panel-header" : ""}`, onClick: handleToggle, children: [
|
|
422
431
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dialkit-folder-header-top", children: [
|
|
423
|
-
isRoot ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
424
|
-
import_react3.motion.div,
|
|
425
|
-
{
|
|
426
|
-
className: "dialkit-folder-title-row",
|
|
427
|
-
initial: { opacity: 1 },
|
|
428
|
-
animate: { opacity: 1 },
|
|
429
|
-
exit: { opacity: 0 },
|
|
430
|
-
transition: { duration: 0.15 },
|
|
431
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dialkit-folder-title dialkit-folder-title-root", children: title })
|
|
432
|
-
}
|
|
433
|
-
) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dialkit-folder-title-row", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dialkit-folder-title", children: title }) }),
|
|
432
|
+
isRoot ? isOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dialkit-folder-title-row", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dialkit-folder-title dialkit-folder-title-root", children: title }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dialkit-folder-title-row", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dialkit-folder-title", children: title }) }),
|
|
434
433
|
isRoot ? (
|
|
435
434
|
// Root panel icon — fixed position, container morphs around it
|
|
436
435
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
@@ -467,53 +466,32 @@ function Folder({ title, children, defaultOpen = true, isRoot = false, onOpenCha
|
|
|
467
466
|
)
|
|
468
467
|
)
|
|
469
468
|
] }),
|
|
470
|
-
isRoot && toolbar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
471
|
-
import_react3.motion.div,
|
|
472
|
-
{
|
|
473
|
-
initial: { opacity: 1 },
|
|
474
|
-
animate: { opacity: 1 },
|
|
475
|
-
exit: { opacity: 0 },
|
|
476
|
-
transition: { duration: 0.15 },
|
|
477
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dialkit-panel-toolbar", onClick: (e) => e.stopPropagation(), children: toolbar })
|
|
478
|
-
}
|
|
479
|
-
) })
|
|
469
|
+
isRoot && toolbar && isOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dialkit-panel-toolbar", onClick: (e) => e.stopPropagation(), children: toolbar })
|
|
480
470
|
] }),
|
|
481
471
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.AnimatePresence, { initial: false, children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
482
472
|
import_react3.motion.div,
|
|
483
473
|
{
|
|
484
474
|
className: "dialkit-folder-content",
|
|
485
|
-
initial: isRoot ?
|
|
486
|
-
animate: isRoot ?
|
|
487
|
-
exit: isRoot ?
|
|
488
|
-
transition: isRoot ?
|
|
489
|
-
style: isRoot ? void 0 : {
|
|
475
|
+
initial: isRoot ? void 0 : { height: 0, opacity: 0 },
|
|
476
|
+
animate: isRoot ? void 0 : { height: "auto", opacity: 1 },
|
|
477
|
+
exit: isRoot ? void 0 : { height: 0, opacity: 0 },
|
|
478
|
+
transition: isRoot ? void 0 : { type: "spring", visualDuration: 0.35, bounce: 0.1 },
|
|
479
|
+
style: isRoot ? void 0 : { clipPath: "inset(0 -20px)" },
|
|
490
480
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dialkit-folder-inner", children })
|
|
491
481
|
}
|
|
492
482
|
) })
|
|
493
483
|
] });
|
|
494
484
|
if (isRoot) {
|
|
485
|
+
const panelStyle = isOpen ? { width: 280, height: contentHeight !== void 0 ? contentHeight + 24 : "auto", borderRadius: 14, boxShadow: "0 8px 32px rgba(0, 0, 0, 0.5)", cursor: void 0 } : { width: 42, height: 42, borderRadius: 21, boxShadow: "0 4px 16px rgba(0, 0, 0, 0.25)", overflow: "hidden", cursor: "pointer" };
|
|
495
486
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
496
487
|
import_react3.motion.div,
|
|
497
488
|
{
|
|
498
489
|
className: "dialkit-panel-inner",
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
width: isOpen ? 280 : 42,
|
|
502
|
-
height: isOpen ? contentHeight !== void 0 ? contentHeight + 24 : "auto" : 42,
|
|
503
|
-
borderRadius: isOpen ? 14 : 21,
|
|
504
|
-
boxShadow: isOpen ? "0 8px 32px rgba(0, 0, 0, 0.5)" : "0 4px 16px rgba(0, 0, 0, 0.25)"
|
|
505
|
-
},
|
|
506
|
-
transition: panelTransition,
|
|
507
|
-
style: { overflow: isOpen ? void 0 : "hidden", cursor: isOpen ? void 0 : "pointer" },
|
|
508
|
-
onClick: !isOpen ? () => {
|
|
509
|
-
setIsOpen(true);
|
|
510
|
-
setIsCollapsed(false);
|
|
511
|
-
onOpenChange?.(true);
|
|
512
|
-
} : void 0,
|
|
513
|
-
onAnimationComplete: () => {
|
|
514
|
-
if (!isOpen) setIsCollapsed(true);
|
|
515
|
-
},
|
|
490
|
+
style: panelStyle,
|
|
491
|
+
onClick: !isOpen ? handleToggle : void 0,
|
|
516
492
|
"data-collapsed": isCollapsed,
|
|
493
|
+
whileTap: !isOpen ? { scale: 0.9 } : void 0,
|
|
494
|
+
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
517
495
|
children: folderContent
|
|
518
496
|
}
|
|
519
497
|
);
|
|
@@ -529,10 +507,14 @@ var CLICK_THRESHOLD = 3;
|
|
|
529
507
|
var DEAD_ZONE = 32;
|
|
530
508
|
var MAX_CURSOR_RANGE = 200;
|
|
531
509
|
var MAX_STRETCH = 8;
|
|
510
|
+
function decimalsForStep(step) {
|
|
511
|
+
const s = step.toString();
|
|
512
|
+
const dot = s.indexOf(".");
|
|
513
|
+
return dot === -1 ? 0 : s.length - dot - 1;
|
|
514
|
+
}
|
|
532
515
|
function roundValue(val, step) {
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
return Math.round(val * factor) / factor;
|
|
516
|
+
const raw = Math.round(val / step) * step;
|
|
517
|
+
return parseFloat(raw.toFixed(decimalsForStep(step)));
|
|
536
518
|
}
|
|
537
519
|
function snapToDecile(rawValue, min, max) {
|
|
538
520
|
const normalized = (rawValue - min) / (max - min);
|
|
@@ -680,7 +662,8 @@ function Slider({
|
|
|
680
662
|
if (!isInteracting) return;
|
|
681
663
|
if (isClickRef.current) {
|
|
682
664
|
const rawValue = positionToValue(e.clientX);
|
|
683
|
-
const
|
|
665
|
+
const discreteSteps2 = (max - min) / step;
|
|
666
|
+
const snappedValue = discreteSteps2 <= 10 ? Math.max(min, Math.min(max, min + Math.round((rawValue - min) / step) * step)) : snapToDecile(rawValue, min, max);
|
|
684
667
|
const newPct = percentFromValue(snappedValue);
|
|
685
668
|
if (animRef.current) {
|
|
686
669
|
animRef.current.stop();
|
|
@@ -760,7 +743,7 @@ function Slider({
|
|
|
760
743
|
e.stopPropagation();
|
|
761
744
|
e.preventDefault();
|
|
762
745
|
setShowInput(true);
|
|
763
|
-
setInputValue(
|
|
746
|
+
setInputValue(value.toFixed(decimalsForStep(step)));
|
|
764
747
|
}
|
|
765
748
|
};
|
|
766
749
|
const handleInputKeyDown = (e) => {
|
|
@@ -774,7 +757,7 @@ function Slider({
|
|
|
774
757
|
const handleInputBlur = () => {
|
|
775
758
|
handleInputSubmit();
|
|
776
759
|
};
|
|
777
|
-
const displayValue =
|
|
760
|
+
const displayValue = value.toFixed(decimalsForStep(step));
|
|
778
761
|
const HANDLE_BUFFER = 8;
|
|
779
762
|
const LABEL_CSS_LEFT = 10;
|
|
780
763
|
const VALUE_CSS_RIGHT = 10;
|
|
@@ -792,7 +775,18 @@ function Slider({
|
|
|
792
775
|
const valueDodge = percentage < leftThreshold || percentage > rightThreshold;
|
|
793
776
|
const handleOpacity = !isActive ? 0 : valueDodge ? 0.1 : isDragging ? 0.9 : 0.5;
|
|
794
777
|
const fillBackground = isActive ? "rgba(255, 255, 255, 0.15)" : "rgba(255, 255, 255, 0.11)";
|
|
795
|
-
const
|
|
778
|
+
const discreteSteps = (max - min) / step;
|
|
779
|
+
const hashMarks = discreteSteps <= 10 ? Array.from({ length: discreteSteps - 1 }, (_, i) => {
|
|
780
|
+
const pct = (i + 1) * step / (max - min) * 100;
|
|
781
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
782
|
+
"div",
|
|
783
|
+
{
|
|
784
|
+
className: "dialkit-slider-hashmark",
|
|
785
|
+
style: { left: `${pct}%` }
|
|
786
|
+
},
|
|
787
|
+
i
|
|
788
|
+
);
|
|
789
|
+
}) : Array.from({ length: 9 }, (_, i) => {
|
|
796
790
|
const pct = (i + 1) * 10;
|
|
797
791
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
798
792
|
"div",
|
|
@@ -1182,32 +1176,63 @@ function TextControl({ label, value, onChange, placeholder }) {
|
|
|
1182
1176
|
|
|
1183
1177
|
// src/components/SelectControl.tsx
|
|
1184
1178
|
var import_react9 = require("react");
|
|
1179
|
+
var import_react_dom = require("react-dom");
|
|
1185
1180
|
var import_react10 = require("motion/react");
|
|
1186
1181
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1182
|
+
function toTitleCase(s) {
|
|
1183
|
+
return s.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
1184
|
+
}
|
|
1187
1185
|
function normalizeOptions(options) {
|
|
1188
1186
|
return options.map(
|
|
1189
|
-
(opt) => typeof opt === "string" ? { value: opt, label: opt } : opt
|
|
1187
|
+
(opt) => typeof opt === "string" ? { value: opt, label: toTitleCase(opt) } : opt
|
|
1190
1188
|
);
|
|
1191
1189
|
}
|
|
1192
1190
|
function SelectControl({ label, value, options, onChange }) {
|
|
1193
1191
|
const [isOpen, setIsOpen] = (0, import_react9.useState)(false);
|
|
1194
|
-
const
|
|
1192
|
+
const triggerRef = (0, import_react9.useRef)(null);
|
|
1193
|
+
const dropdownRef = (0, import_react9.useRef)(null);
|
|
1194
|
+
const [portalTarget, setPortalTarget] = (0, import_react9.useState)(null);
|
|
1195
|
+
const [pos, setPos] = (0, import_react9.useState)(null);
|
|
1195
1196
|
const normalized = normalizeOptions(options);
|
|
1196
1197
|
const selectedOption = normalized.find((o) => o.value === value);
|
|
1198
|
+
const updatePos = (0, import_react9.useCallback)(() => {
|
|
1199
|
+
const el = triggerRef.current;
|
|
1200
|
+
if (!el) return;
|
|
1201
|
+
const rect = el.getBoundingClientRect();
|
|
1202
|
+
const dropdownHeight = 8 + normalized.length * 36;
|
|
1203
|
+
const spaceBelow = window.innerHeight - rect.bottom - 4;
|
|
1204
|
+
const above = spaceBelow < dropdownHeight && rect.top > spaceBelow;
|
|
1205
|
+
setPos({
|
|
1206
|
+
top: above ? rect.top - 4 : rect.bottom + 4,
|
|
1207
|
+
left: rect.left,
|
|
1208
|
+
width: rect.width,
|
|
1209
|
+
above
|
|
1210
|
+
});
|
|
1211
|
+
}, [normalized.length]);
|
|
1212
|
+
(0, import_react9.useEffect)(() => {
|
|
1213
|
+
const root = triggerRef.current?.closest(".dialkit-root");
|
|
1214
|
+
setPortalTarget(root ?? document.body);
|
|
1215
|
+
}, []);
|
|
1216
|
+
(0, import_react9.useEffect)(() => {
|
|
1217
|
+
if (!isOpen) return;
|
|
1218
|
+
updatePos();
|
|
1219
|
+
}, [isOpen, updatePos]);
|
|
1197
1220
|
(0, import_react9.useEffect)(() => {
|
|
1198
1221
|
if (!isOpen) return;
|
|
1199
1222
|
const handleClick = (e) => {
|
|
1200
|
-
|
|
1223
|
+
const target = e.target;
|
|
1224
|
+
if (triggerRef.current && !triggerRef.current.contains(target) && dropdownRef.current && !dropdownRef.current.contains(target)) {
|
|
1201
1225
|
setIsOpen(false);
|
|
1202
1226
|
}
|
|
1203
1227
|
};
|
|
1204
1228
|
document.addEventListener("mousedown", handleClick);
|
|
1205
1229
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
1206
1230
|
}, [isOpen]);
|
|
1207
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", {
|
|
1231
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dialkit-select-row", children: [
|
|
1208
1232
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1209
1233
|
"button",
|
|
1210
1234
|
{
|
|
1235
|
+
ref: triggerRef,
|
|
1211
1236
|
className: "dialkit-select-trigger",
|
|
1212
1237
|
onClick: () => setIsOpen(!isOpen),
|
|
1213
1238
|
"data-open": String(isOpen),
|
|
@@ -1234,29 +1259,39 @@ function SelectControl({ label, value, options, onChange }) {
|
|
|
1234
1259
|
]
|
|
1235
1260
|
}
|
|
1236
1261
|
),
|
|
1237
|
-
|
|
1238
|
-
import_react10.
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
"
|
|
1247
|
-
{
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
setIsOpen(false);
|
|
1253
|
-
},
|
|
1254
|
-
children: option.label
|
|
1262
|
+
portalTarget && (0, import_react_dom.createPortal)(
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react10.AnimatePresence, { children: isOpen && pos && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1264
|
+
import_react10.motion.div,
|
|
1265
|
+
{
|
|
1266
|
+
ref: dropdownRef,
|
|
1267
|
+
className: "dialkit-select-dropdown",
|
|
1268
|
+
initial: { opacity: 0, y: pos.above ? 8 : -8, scale: 0.95 },
|
|
1269
|
+
animate: { opacity: 1, y: 0, scale: 1 },
|
|
1270
|
+
exit: { opacity: 0, y: pos.above ? 8 : -8, scale: 0.95 },
|
|
1271
|
+
transition: { type: "spring", visualDuration: 0.15, bounce: 0 },
|
|
1272
|
+
style: {
|
|
1273
|
+
position: "fixed",
|
|
1274
|
+
left: pos.left,
|
|
1275
|
+
width: pos.width,
|
|
1276
|
+
...pos.above ? { bottom: window.innerHeight - pos.top, transformOrigin: "bottom" } : { top: pos.top, transformOrigin: "top" }
|
|
1255
1277
|
},
|
|
1256
|
-
option.
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1278
|
+
children: normalized.map((option) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1279
|
+
"button",
|
|
1280
|
+
{
|
|
1281
|
+
className: "dialkit-select-option",
|
|
1282
|
+
"data-selected": String(option.value === value),
|
|
1283
|
+
onClick: () => {
|
|
1284
|
+
onChange(option.value);
|
|
1285
|
+
setIsOpen(false);
|
|
1286
|
+
},
|
|
1287
|
+
children: option.label
|
|
1288
|
+
},
|
|
1289
|
+
option.value
|
|
1290
|
+
))
|
|
1291
|
+
}
|
|
1292
|
+
) }),
|
|
1293
|
+
portalTarget
|
|
1294
|
+
)
|
|
1260
1295
|
] });
|
|
1261
1296
|
}
|
|
1262
1297
|
|
|
@@ -1340,7 +1375,7 @@ function expandShorthandHex(hex) {
|
|
|
1340
1375
|
|
|
1341
1376
|
// src/components/PresetManager.tsx
|
|
1342
1377
|
var import_react12 = require("react");
|
|
1343
|
-
var
|
|
1378
|
+
var import_react_dom2 = require("react-dom");
|
|
1344
1379
|
var import_react13 = require("motion/react");
|
|
1345
1380
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1346
1381
|
function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
@@ -1407,7 +1442,7 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1407
1442
|
strokeWidth: "2.5",
|
|
1408
1443
|
strokeLinecap: "round",
|
|
1409
1444
|
strokeLinejoin: "round",
|
|
1410
|
-
animate: { rotate: isOpen ? 180 : 0 },
|
|
1445
|
+
animate: { rotate: isOpen ? 180 : 0, opacity: hasPresets ? 0.6 : 0.25 },
|
|
1411
1446
|
transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
|
|
1412
1447
|
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M6 9.5L12 15.5L18 9.5" })
|
|
1413
1448
|
}
|
|
@@ -1415,12 +1450,12 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
|
|
|
1415
1450
|
]
|
|
1416
1451
|
}
|
|
1417
1452
|
),
|
|
1418
|
-
(0,
|
|
1453
|
+
(0, import_react_dom2.createPortal)(
|
|
1419
1454
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react13.AnimatePresence, { children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1420
1455
|
import_react13.motion.div,
|
|
1421
1456
|
{
|
|
1422
1457
|
ref: dropdownRef,
|
|
1423
|
-
className: "dialkit-preset-dropdown",
|
|
1458
|
+
className: "dialkit-root dialkit-preset-dropdown",
|
|
1424
1459
|
style: { position: "fixed", top: pos.top, left: pos.left, minWidth: pos.width },
|
|
1425
1460
|
initial: { opacity: 0, y: 4, scale: 0.97 },
|
|
1426
1461
|
animate: { opacity: 1, y: 0, scale: 1 },
|
|
@@ -1539,7 +1574,7 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1539
1574
|
control.path
|
|
1540
1575
|
);
|
|
1541
1576
|
case "folder":
|
|
1542
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Folder, { title: control.label, children: control.children?.map(renderControl) }, control.path);
|
|
1577
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Folder, { title: control.label, defaultOpen: control.defaultOpen ?? true, children: control.children?.map(renderControl) }, control.path);
|
|
1543
1578
|
case "text":
|
|
1544
1579
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1545
1580
|
TextControl,
|
|
@@ -1603,11 +1638,13 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1603
1638
|
const iconTransition = { type: "spring", visualDuration: 0.4, bounce: 0.1 };
|
|
1604
1639
|
const toolbar = /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
1605
1640
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1606
|
-
|
|
1641
|
+
import_react15.motion.button,
|
|
1607
1642
|
{
|
|
1608
1643
|
className: "dialkit-toolbar-add",
|
|
1609
1644
|
onClick: handleAddPreset,
|
|
1610
1645
|
title: "Add preset",
|
|
1646
|
+
whileTap: { scale: 0.9 },
|
|
1647
|
+
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
1611
1648
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1612
1649
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M4 6H20" }),
|
|
1613
1650
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M4 12H10" }),
|
|
@@ -1627,13 +1664,15 @@ Apply these values as the new defaults in the useDialKit call.`;
|
|
|
1627
1664
|
}
|
|
1628
1665
|
),
|
|
1629
1666
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1630
|
-
|
|
1667
|
+
import_react15.motion.button,
|
|
1631
1668
|
{
|
|
1632
1669
|
className: "dialkit-toolbar-copy",
|
|
1633
1670
|
onClick: handleCopy,
|
|
1634
1671
|
title: "Copy parameters",
|
|
1672
|
+
whileTap: { scale: 0.95 },
|
|
1673
|
+
transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
|
|
1635
1674
|
children: [
|
|
1636
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dialkit-toolbar-copy-icon-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react15.AnimatePresence, { mode: "popLayout", children: copied ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1675
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dialkit-toolbar-copy-icon-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react15.AnimatePresence, { initial: false, mode: "popLayout", children: copied ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1637
1676
|
import_react15.motion.svg,
|
|
1638
1677
|
{
|
|
1639
1678
|
className: "dialkit-toolbar-copy-icon",
|
|
@@ -1696,7 +1735,7 @@ function DialRoot({ position = "top-right" }) {
|
|
|
1696
1735
|
return null;
|
|
1697
1736
|
}
|
|
1698
1737
|
const content = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dialkit-root", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dialkit-panel", "data-position": position, children: panels.map((panel) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Panel, { panel }, panel.id)) }) });
|
|
1699
|
-
return (0,
|
|
1738
|
+
return (0, import_react_dom3.createPortal)(content, document.body);
|
|
1700
1739
|
}
|
|
1701
1740
|
|
|
1702
1741
|
// src/components/ButtonGroup.tsx
|