dialkit 0.2.2 → 1.0.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/dist/index.js CHANGED
@@ -19,15 +19,67 @@ var DialStoreClass = class {
19
19
  registerPanel(id, name, config) {
20
20
  const controls = this.parseConfig(config, "");
21
21
  const values = this.flattenValues(config, "");
22
+ this.initTransitionModes(config, "", values);
22
23
  this.panels.set(id, { id, name, controls, values });
23
24
  this.snapshots.set(id, { ...values });
24
25
  this.baseValues.set(id, { ...values });
25
26
  this.notifyGlobal();
26
27
  }
28
+ updatePanel(id, name, config) {
29
+ const existing = this.panels.get(id);
30
+ if (!existing) {
31
+ this.registerPanel(id, name, config);
32
+ return;
33
+ }
34
+ const controls = this.parseConfig(config, "");
35
+ const controlsByPath = this.mapControlsByPath(controls);
36
+ const defaultValues = this.flattenValues(config, "");
37
+ const nextValues = {};
38
+ for (const [path, defaultValue] of Object.entries(defaultValues)) {
39
+ nextValues[path] = this.normalizePreservedValue(
40
+ existing.values[path],
41
+ defaultValue,
42
+ controlsByPath.get(path)
43
+ );
44
+ }
45
+ this.initTransitionModes(config, "", nextValues);
46
+ for (const [path, mode] of Object.entries(existing.values)) {
47
+ if (!path.endsWith(".__mode")) {
48
+ continue;
49
+ }
50
+ const transitionPath = path.slice(0, -"__mode".length - 1);
51
+ const transitionControl = controlsByPath.get(transitionPath);
52
+ if (transitionControl?.type === "transition") {
53
+ nextValues[path] = mode;
54
+ }
55
+ }
56
+ const nextPanel = { id, name, controls, values: nextValues };
57
+ this.panels.set(id, nextPanel);
58
+ this.snapshots.set(id, { ...nextValues });
59
+ const previousBaseValues = this.baseValues.get(id) ?? {};
60
+ const nextBaseValues = {};
61
+ for (const [path, defaultValue] of Object.entries(defaultValues)) {
62
+ nextBaseValues[path] = this.normalizePreservedValue(
63
+ previousBaseValues[path],
64
+ defaultValue,
65
+ controlsByPath.get(path)
66
+ );
67
+ }
68
+ for (const [path, value] of Object.entries(nextValues)) {
69
+ if (path.endsWith(".__mode")) {
70
+ nextBaseValues[path] = value;
71
+ }
72
+ }
73
+ this.baseValues.set(id, nextBaseValues);
74
+ this.notify(id);
75
+ this.notifyGlobal();
76
+ }
27
77
  unregisterPanel(id) {
28
78
  this.panels.delete(id);
29
79
  this.listeners.delete(id);
30
80
  this.snapshots.delete(id);
81
+ this.actionListeners.delete(id);
82
+ this.baseValues.delete(id);
31
83
  this.notifyGlobal();
32
84
  }
33
85
  updateValue(panelId, path, value) {
@@ -47,13 +99,21 @@ var DialStoreClass = class {
47
99
  this.notify(panelId);
48
100
  }
49
101
  updateSpringMode(panelId, path, mode) {
102
+ this.updateTransitionMode(panelId, path, mode);
103
+ }
104
+ getSpringMode(panelId, path) {
105
+ const mode = this.getTransitionMode(panelId, path);
106
+ if (mode === "easing") return "simple";
107
+ return mode;
108
+ }
109
+ updateTransitionMode(panelId, path, mode) {
50
110
  const panel = this.panels.get(panelId);
51
111
  if (!panel) return;
52
112
  panel.values[`${path}.__mode`] = mode;
53
113
  this.snapshots.set(panelId, { ...panel.values });
54
114
  this.notify(panelId);
55
115
  }
56
- getSpringMode(panelId, path) {
116
+ getTransitionMode(panelId, path) {
57
117
  const panel = this.panels.get(panelId);
58
118
  if (!panel) return "simple";
59
119
  return panel.values[`${path}.__mode`] || "simple";
@@ -157,6 +217,21 @@ var DialStoreClass = class {
157
217
  notifyGlobal() {
158
218
  this.globalListeners.forEach((fn) => fn());
159
219
  }
220
+ initTransitionModes(config, prefix, values) {
221
+ for (const [key, value] of Object.entries(config)) {
222
+ if (key === "_collapsed") continue;
223
+ const path = prefix ? `${prefix}.${key}` : key;
224
+ if (this.isEasingConfig(value)) {
225
+ values[`${path}.__mode`] = "easing";
226
+ } else if (this.isSpringConfig(value)) {
227
+ const hasPhysics = value.stiffness !== void 0 || value.damping !== void 0 || value.mass !== void 0;
228
+ const hasTime = value.visualDuration !== void 0 || value.bounce !== void 0;
229
+ values[`${path}.__mode`] = hasPhysics && !hasTime ? "advanced" : "simple";
230
+ } else if (typeof value === "object" && value !== null && !Array.isArray(value) && !this.isActionConfig(value) && !this.isSelectConfig(value) && !this.isColorConfig(value) && !this.isTextConfig(value)) {
231
+ this.initTransitionModes(value, path, values);
232
+ }
233
+ }
234
+ }
160
235
  parseConfig(config, prefix) {
161
236
  const controls = [];
162
237
  for (const [key, value] of Object.entries(config)) {
@@ -177,8 +252,8 @@ var DialStoreClass = class {
177
252
  controls.push({ type: "slider", path, label, min, max, step });
178
253
  } else if (typeof value === "boolean") {
179
254
  controls.push({ type: "toggle", path, label });
180
- } else if (this.isSpringConfig(value)) {
181
- controls.push({ type: "spring", path, label });
255
+ } else if (this.isSpringConfig(value) || this.isEasingConfig(value)) {
256
+ controls.push({ type: "transition", path, label });
182
257
  } else if (this.isActionConfig(value)) {
183
258
  controls.push({ type: "action", path, label: value.label || label });
184
259
  } else if (this.isSelectConfig(value)) {
@@ -216,7 +291,7 @@ var DialStoreClass = class {
216
291
  values[path] = value[0];
217
292
  } else if (typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
218
293
  values[path] = value;
219
- } else if (this.isSpringConfig(value)) {
294
+ } else if (this.isSpringConfig(value) || this.isEasingConfig(value)) {
220
295
  values[path] = value;
221
296
  } else if (this.isActionConfig(value)) {
222
297
  values[path] = value;
@@ -237,6 +312,9 @@ var DialStoreClass = class {
237
312
  isSpringConfig(value) {
238
313
  return typeof value === "object" && value !== null && "type" in value && value.type === "spring";
239
314
  }
315
+ isEasingConfig(value) {
316
+ return typeof value === "object" && value !== null && "type" in value && value.type === "easing";
317
+ }
240
318
  isActionConfig(value) {
241
319
  return typeof value === "object" && value !== null && "type" in value && value.type === "action";
242
320
  }
@@ -275,6 +353,75 @@ var DialStoreClass = class {
275
353
  if (range <= 100) return 1;
276
354
  return 10;
277
355
  }
356
+ normalizePreservedValue(existingValue, defaultValue, control) {
357
+ if (existingValue === void 0 || !control) {
358
+ return defaultValue;
359
+ }
360
+ switch (control.type) {
361
+ case "slider": {
362
+ if (typeof existingValue !== "number" || typeof defaultValue !== "number") {
363
+ return defaultValue;
364
+ }
365
+ const min = control.min ?? Number.NEGATIVE_INFINITY;
366
+ const max = control.max ?? Number.POSITIVE_INFINITY;
367
+ const clamped = Math.min(max, Math.max(min, existingValue));
368
+ if (typeof control.step !== "number" || control.step <= 0) {
369
+ return clamped;
370
+ }
371
+ return this.roundToStep(clamped, min, max, control.step);
372
+ }
373
+ case "toggle":
374
+ return typeof existingValue === "boolean" ? existingValue : defaultValue;
375
+ case "select": {
376
+ if (typeof existingValue !== "string") {
377
+ return defaultValue;
378
+ }
379
+ const options = control.options ?? [];
380
+ const validValues = new Set(options.map((option) => typeof option === "string" ? option : option.value));
381
+ return validValues.has(existingValue) ? existingValue : defaultValue;
382
+ }
383
+ case "color":
384
+ case "text":
385
+ return typeof existingValue === "string" ? existingValue : defaultValue;
386
+ case "transition":
387
+ if (this.isSpringConfig(defaultValue)) {
388
+ return this.isSpringConfig(existingValue) ? existingValue : defaultValue;
389
+ }
390
+ if (this.isEasingConfig(defaultValue)) {
391
+ return this.isEasingConfig(existingValue) ? existingValue : defaultValue;
392
+ }
393
+ return defaultValue;
394
+ case "action":
395
+ return defaultValue;
396
+ default:
397
+ return defaultValue;
398
+ }
399
+ }
400
+ roundToStep(value, min, max, step) {
401
+ const snapped = min + Math.round((value - min) / step) * step;
402
+ const clamped = Math.min(max, Math.max(min, snapped));
403
+ const precision = this.stepPrecision(step);
404
+ return Number(clamped.toFixed(precision));
405
+ }
406
+ stepPrecision(step) {
407
+ const text = String(step);
408
+ const decimalIndex = text.indexOf(".");
409
+ return decimalIndex === -1 ? 0 : text.length - decimalIndex - 1;
410
+ }
411
+ mapControlsByPath(controls) {
412
+ const map = /* @__PURE__ */ new Map();
413
+ const visit = (nodes) => {
414
+ for (const node of nodes) {
415
+ if (node.type === "folder" && node.children) {
416
+ visit(node.children);
417
+ continue;
418
+ }
419
+ map.set(node.path, node);
420
+ }
421
+ };
422
+ visit(controls);
423
+ return map;
424
+ }
278
425
  };
279
426
  var DialStore = new DialStoreClass();
280
427
 
@@ -283,12 +430,22 @@ function useDialKit(name, config, options) {
283
430
  const instanceId = useId();
284
431
  const panelId = `${name}-${instanceId}`;
285
432
  const configRef = useRef(config);
433
+ const serializedConfig = JSON.stringify(config);
434
+ configRef.current = config;
286
435
  const onActionRef = useRef(options?.onAction);
287
436
  onActionRef.current = options?.onAction;
288
437
  useEffect(() => {
289
438
  DialStore.registerPanel(panelId, name, configRef.current);
290
439
  return () => DialStore.unregisterPanel(panelId);
291
440
  }, [panelId, name]);
441
+ const mountedRef = useRef(false);
442
+ useEffect(() => {
443
+ if (!mountedRef.current) {
444
+ mountedRef.current = true;
445
+ return;
446
+ }
447
+ DialStore.updatePanel(panelId, name, configRef.current);
448
+ }, [panelId, name, serializedConfig]);
292
449
  useEffect(() => {
293
450
  return DialStore.subscribeActions(panelId, (action) => {
294
451
  onActionRef.current?.(action);
@@ -310,7 +467,7 @@ function buildResolvedValues(config, flatValues, prefix) {
310
467
  result[key] = flatValues[path] ?? configValue[0];
311
468
  } else if (typeof configValue === "number" || typeof configValue === "boolean" || typeof configValue === "string") {
312
469
  result[key] = flatValues[path] ?? configValue;
313
- } else if (isSpringConfig(configValue)) {
470
+ } else if (isSpringConfig(configValue) || isEasingConfig(configValue)) {
314
471
  result[key] = flatValues[path] ?? configValue;
315
472
  } else if (isActionConfig(configValue)) {
316
473
  result[key] = flatValues[path] ?? configValue;
@@ -333,6 +490,9 @@ function hasType(value, type) {
333
490
  function isSpringConfig(value) {
334
491
  return hasType(value, "spring");
335
492
  }
493
+ function isEasingConfig(value) {
494
+ return hasType(value, "easing");
495
+ }
336
496
  function isActionConfig(value) {
337
497
  return hasType(value, "action");
338
498
  }
@@ -351,11 +511,11 @@ function getFirstOptionValue(options) {
351
511
  }
352
512
 
353
513
  // src/components/DialRoot.tsx
354
- import { useEffect as useEffect7, useState as useState8 } from "react";
514
+ import { useEffect as useEffect7, useState as useState9 } from "react";
355
515
  import { createPortal as createPortal3 } from "react-dom";
356
516
 
357
517
  // src/components/Panel.tsx
358
- import { useState as useState7, useSyncExternalStore as useSyncExternalStore3 } from "react";
518
+ import { useState as useState8, useSyncExternalStore as useSyncExternalStore4 } from "react";
359
519
  import { motion as motion6, AnimatePresence as AnimatePresence4 } from "motion/react";
360
520
 
361
521
  // src/components/Folder.tsx
@@ -1119,12 +1279,180 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
1119
1279
  ] }) });
1120
1280
  }
1121
1281
 
1122
- // src/components/TextControl.tsx
1282
+ // src/components/EasingVisualization.tsx
1123
1283
  import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1284
+ function EasingVisualization({ easing }) {
1285
+ const ease = easing.ease;
1286
+ const s = 200;
1287
+ const pad = 10;
1288
+ const inner = s - pad * 2;
1289
+ const unit = inner / 2;
1290
+ const toSvg = (nx, ny) => ({
1291
+ x: pad + (nx + 0.5) * unit,
1292
+ y: pad + (1.5 - ny) * unit
1293
+ });
1294
+ const start = toSvg(0, 0);
1295
+ const end = toSvg(1, 1);
1296
+ const p1 = toSvg(ease[0], ease[1]);
1297
+ const p2 = toSvg(ease[2], ease[3]);
1298
+ const curvePath = `M ${start.x} ${start.y} C ${p1.x} ${p1.y}, ${p2.x} ${p2.y}, ${end.x} ${end.y}`;
1299
+ return /* @__PURE__ */ jsxs7(
1300
+ "svg",
1301
+ {
1302
+ viewBox: `0 0 ${s} ${s}`,
1303
+ preserveAspectRatio: "xMidYMid slice",
1304
+ className: "dialkit-spring-viz dialkit-easing-viz",
1305
+ children: [
1306
+ /* @__PURE__ */ jsx7(
1307
+ "line",
1308
+ {
1309
+ x1: start.x,
1310
+ y1: start.y,
1311
+ x2: end.x,
1312
+ y2: end.y,
1313
+ stroke: "rgba(255, 255, 255, 0.15)",
1314
+ strokeWidth: "1",
1315
+ strokeDasharray: "4,4"
1316
+ }
1317
+ ),
1318
+ /* @__PURE__ */ jsx7("path", { d: curvePath, fill: "none", stroke: "rgba(255, 255, 255, 0.6)", strokeWidth: "2", strokeLinecap: "round" })
1319
+ ]
1320
+ }
1321
+ );
1322
+ }
1323
+
1324
+ // src/components/TransitionControl.tsx
1325
+ import { useSyncExternalStore as useSyncExternalStore3, useState as useState4 } from "react";
1326
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1327
+ function TransitionControl({ panelId, path, label, value, onChange }) {
1328
+ const mode = useSyncExternalStore3(
1329
+ (cb) => DialStore.subscribe(panelId, cb),
1330
+ () => DialStore.getTransitionMode(panelId, path),
1331
+ () => DialStore.getTransitionMode(panelId, path)
1332
+ );
1333
+ const isEasing = mode === "easing";
1334
+ const isSimpleSpring = mode === "simple";
1335
+ const spring = value.type === "spring" ? value : { type: "spring", visualDuration: 0.3, bounce: 0.2 };
1336
+ const easing = value.type === "easing" ? value : { type: "easing", duration: 0.3, ease: [1, -0.4, 0.5, 1] };
1337
+ const handleModeChange = (newMode) => {
1338
+ DialStore.updateTransitionMode(panelId, path, newMode);
1339
+ if (newMode === "easing") {
1340
+ const duration = value.type === "spring" ? value.visualDuration ?? 0.3 : value.duration;
1341
+ onChange({ type: "easing", duration, ease: easing.ease });
1342
+ } else if (newMode === "simple") {
1343
+ onChange({
1344
+ type: "spring",
1345
+ visualDuration: spring.visualDuration ?? (value.type === "easing" ? value.duration : 0.3),
1346
+ bounce: spring.bounce ?? 0.2
1347
+ });
1348
+ } else {
1349
+ onChange({
1350
+ type: "spring",
1351
+ stiffness: spring.stiffness ?? 200,
1352
+ damping: spring.damping ?? 25,
1353
+ mass: spring.mass ?? 1
1354
+ });
1355
+ }
1356
+ };
1357
+ const handleSpringUpdate = (key, val) => {
1358
+ if (isSimpleSpring) {
1359
+ const { stiffness, damping, mass, ...rest } = spring;
1360
+ onChange({ ...rest, [key]: val });
1361
+ } else {
1362
+ const { visualDuration, bounce, ...rest } = spring;
1363
+ onChange({ ...rest, [key]: val });
1364
+ }
1365
+ };
1366
+ const updateEase = (index, val) => {
1367
+ const newEase = [...easing.ease];
1368
+ newEase[index] = val;
1369
+ onChange({ ...easing, ease: newEase });
1370
+ };
1371
+ return /* @__PURE__ */ jsx8(Folder, { title: label, defaultOpen: true, children: /* @__PURE__ */ jsxs8("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
1372
+ isEasing ? /* @__PURE__ */ jsx8(EasingVisualization, { easing }) : /* @__PURE__ */ jsx8(SpringVisualization, { spring, isSimpleMode: isSimpleSpring }),
1373
+ /* @__PURE__ */ jsxs8("div", { className: "dialkit-labeled-control", children: [
1374
+ /* @__PURE__ */ jsx8("span", { className: "dialkit-labeled-control-label", children: "Type" }),
1375
+ /* @__PURE__ */ jsx8(
1376
+ SegmentedControl,
1377
+ {
1378
+ options: [
1379
+ { value: "easing", label: "Easing" },
1380
+ { value: "simple", label: "Time" },
1381
+ { value: "advanced", label: "Physics" }
1382
+ ],
1383
+ value: mode,
1384
+ onChange: handleModeChange
1385
+ }
1386
+ )
1387
+ ] }),
1388
+ isEasing ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
1389
+ /* @__PURE__ */ jsx8(Slider, { label: "x1", value: easing.ease[0], onChange: (v) => updateEase(0, v), min: 0, max: 1, step: 0.01 }),
1390
+ /* @__PURE__ */ jsx8(Slider, { label: "y1", value: easing.ease[1], onChange: (v) => updateEase(1, v), min: -1, max: 2, step: 0.01 }),
1391
+ /* @__PURE__ */ jsx8(Slider, { label: "x2", value: easing.ease[2], onChange: (v) => updateEase(2, v), min: 0, max: 1, step: 0.01 }),
1392
+ /* @__PURE__ */ jsx8(Slider, { label: "y2", value: easing.ease[3], onChange: (v) => updateEase(3, v), min: -1, max: 2, step: 0.01 }),
1393
+ /* @__PURE__ */ jsx8(Slider, { label: "Duration", value: easing.duration, onChange: (v) => onChange({ ...easing, duration: v }), min: 0.1, max: 2, step: 0.05, unit: "s" }),
1394
+ /* @__PURE__ */ jsx8(EaseTextInput, { ease: easing.ease, onChange: (newEase) => onChange({ ...easing, ease: newEase }) })
1395
+ ] }) : isSimpleSpring ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
1396
+ /* @__PURE__ */ jsx8(Slider, { label: "Duration", value: spring.visualDuration ?? 0.3, onChange: (v) => handleSpringUpdate("visualDuration", v), min: 0.1, max: 1, step: 0.05, unit: "s" }),
1397
+ /* @__PURE__ */ jsx8(Slider, { label: "Bounce", value: spring.bounce ?? 0.2, onChange: (v) => handleSpringUpdate("bounce", v), min: 0, max: 1, step: 0.05 })
1398
+ ] }) : /* @__PURE__ */ jsxs8(Fragment2, { children: [
1399
+ /* @__PURE__ */ jsx8(Slider, { label: "Stiffness", value: spring.stiffness ?? 400, onChange: (v) => handleSpringUpdate("stiffness", v), min: 1, max: 1e3, step: 10 }),
1400
+ /* @__PURE__ */ jsx8(Slider, { label: "Damping", value: spring.damping ?? 17, onChange: (v) => handleSpringUpdate("damping", v), min: 1, max: 100, step: 1 }),
1401
+ /* @__PURE__ */ jsx8(Slider, { label: "Mass", value: spring.mass ?? 1, onChange: (v) => handleSpringUpdate("mass", v), min: 0.1, max: 10, step: 0.1 })
1402
+ ] })
1403
+ ] }) });
1404
+ }
1405
+ function formatEase(ease) {
1406
+ return ease.map((v) => parseFloat(v.toFixed(2))).join(", ");
1407
+ }
1408
+ function parseEase(str) {
1409
+ const parts = str.split(",").map((s) => parseFloat(s.trim()));
1410
+ if (parts.length === 4 && parts.every((n) => !isNaN(n))) {
1411
+ return parts;
1412
+ }
1413
+ return null;
1414
+ }
1415
+ function EaseTextInput({ ease, onChange }) {
1416
+ const [editing, setEditing] = useState4(false);
1417
+ const [draft, setDraft] = useState4("");
1418
+ const handleFocus = () => {
1419
+ setDraft(formatEase(ease));
1420
+ setEditing(true);
1421
+ };
1422
+ const handleBlur = () => {
1423
+ const parsed = parseEase(draft);
1424
+ if (parsed) onChange(parsed);
1425
+ setEditing(false);
1426
+ };
1427
+ const handleKeyDown = (e) => {
1428
+ if (e.key === "Enter") {
1429
+ e.target.blur();
1430
+ }
1431
+ };
1432
+ return /* @__PURE__ */ jsxs8("div", { className: "dialkit-labeled-control", children: [
1433
+ /* @__PURE__ */ jsx8("span", { className: "dialkit-labeled-control-label", children: "Ease" }),
1434
+ /* @__PURE__ */ jsx8(
1435
+ "input",
1436
+ {
1437
+ type: "text",
1438
+ className: "dialkit-text-input",
1439
+ value: editing ? draft : formatEase(ease),
1440
+ onChange: (e) => setDraft(e.target.value),
1441
+ onFocus: handleFocus,
1442
+ onBlur: handleBlur,
1443
+ onKeyDown: handleKeyDown,
1444
+ spellCheck: false
1445
+ }
1446
+ )
1447
+ ] });
1448
+ }
1449
+
1450
+ // src/components/TextControl.tsx
1451
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1124
1452
  function TextControl({ label, value, onChange, placeholder }) {
1125
- return /* @__PURE__ */ jsxs7("div", { className: "dialkit-text-control", children: [
1126
- /* @__PURE__ */ jsx7("label", { className: "dialkit-text-label", children: label }),
1127
- /* @__PURE__ */ jsx7(
1453
+ return /* @__PURE__ */ jsxs9("div", { className: "dialkit-text-control", children: [
1454
+ /* @__PURE__ */ jsx9("label", { className: "dialkit-text-label", children: label }),
1455
+ /* @__PURE__ */ jsx9(
1128
1456
  "input",
1129
1457
  {
1130
1458
  type: "text",
@@ -1138,10 +1466,10 @@ function TextControl({ label, value, onChange, placeholder }) {
1138
1466
  }
1139
1467
 
1140
1468
  // src/components/SelectControl.tsx
1141
- import { useState as useState4, useRef as useRef5, useEffect as useEffect4, useCallback as useCallback2 } from "react";
1469
+ import { useState as useState5, useRef as useRef5, useEffect as useEffect4, useCallback as useCallback2 } from "react";
1142
1470
  import { createPortal } from "react-dom";
1143
1471
  import { motion as motion4, AnimatePresence as AnimatePresence2 } from "motion/react";
1144
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1472
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1145
1473
  function toTitleCase(s) {
1146
1474
  return s.replace(/\b\w/g, (c) => c.toUpperCase());
1147
1475
  }
@@ -1151,11 +1479,11 @@ function normalizeOptions(options) {
1151
1479
  );
1152
1480
  }
1153
1481
  function SelectControl({ label, value, options, onChange }) {
1154
- const [isOpen, setIsOpen] = useState4(false);
1482
+ const [isOpen, setIsOpen] = useState5(false);
1155
1483
  const triggerRef = useRef5(null);
1156
1484
  const dropdownRef = useRef5(null);
1157
- const [portalTarget, setPortalTarget] = useState4(null);
1158
- const [pos, setPos] = useState4(null);
1485
+ const [portalTarget, setPortalTarget] = useState5(null);
1486
+ const [pos, setPos] = useState5(null);
1159
1487
  const normalized = normalizeOptions(options);
1160
1488
  const selectedOption = normalized.find((o) => o.value === value);
1161
1489
  const updatePos = useCallback2(() => {
@@ -1191,8 +1519,8 @@ function SelectControl({ label, value, options, onChange }) {
1191
1519
  document.addEventListener("mousedown", handleClick);
1192
1520
  return () => document.removeEventListener("mousedown", handleClick);
1193
1521
  }, [isOpen]);
1194
- return /* @__PURE__ */ jsxs8("div", { className: "dialkit-select-row", children: [
1195
- /* @__PURE__ */ jsxs8(
1522
+ return /* @__PURE__ */ jsxs10("div", { className: "dialkit-select-row", children: [
1523
+ /* @__PURE__ */ jsxs10(
1196
1524
  "button",
1197
1525
  {
1198
1526
  ref: triggerRef,
@@ -1200,10 +1528,10 @@ function SelectControl({ label, value, options, onChange }) {
1200
1528
  onClick: () => setIsOpen(!isOpen),
1201
1529
  "data-open": String(isOpen),
1202
1530
  children: [
1203
- /* @__PURE__ */ jsx8("span", { className: "dialkit-select-label", children: label }),
1204
- /* @__PURE__ */ jsxs8("div", { className: "dialkit-select-right", children: [
1205
- /* @__PURE__ */ jsx8("span", { className: "dialkit-select-value", children: selectedOption?.label ?? value }),
1206
- /* @__PURE__ */ jsx8(
1531
+ /* @__PURE__ */ jsx10("span", { className: "dialkit-select-label", children: label }),
1532
+ /* @__PURE__ */ jsxs10("div", { className: "dialkit-select-right", children: [
1533
+ /* @__PURE__ */ jsx10("span", { className: "dialkit-select-value", children: selectedOption?.label ?? value }),
1534
+ /* @__PURE__ */ jsx10(
1207
1535
  motion4.svg,
1208
1536
  {
1209
1537
  className: "dialkit-select-chevron",
@@ -1215,7 +1543,7 @@ function SelectControl({ label, value, options, onChange }) {
1215
1543
  strokeLinejoin: "round",
1216
1544
  animate: { rotate: isOpen ? 180 : 0 },
1217
1545
  transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
1218
- children: /* @__PURE__ */ jsx8("path", { d: "M6 9.5L12 15.5L18 9.5" })
1546
+ children: /* @__PURE__ */ jsx10("path", { d: "M6 9.5L12 15.5L18 9.5" })
1219
1547
  }
1220
1548
  )
1221
1549
  ] })
@@ -1223,7 +1551,7 @@ function SelectControl({ label, value, options, onChange }) {
1223
1551
  }
1224
1552
  ),
1225
1553
  portalTarget && createPortal(
1226
- /* @__PURE__ */ jsx8(AnimatePresence2, { children: isOpen && pos && /* @__PURE__ */ jsx8(
1554
+ /* @__PURE__ */ jsx10(AnimatePresence2, { children: isOpen && pos && /* @__PURE__ */ jsx10(
1227
1555
  motion4.div,
1228
1556
  {
1229
1557
  ref: dropdownRef,
@@ -1238,7 +1566,7 @@ function SelectControl({ label, value, options, onChange }) {
1238
1566
  width: pos.width,
1239
1567
  ...pos.above ? { bottom: window.innerHeight - pos.top, transformOrigin: "bottom" } : { top: pos.top, transformOrigin: "top" }
1240
1568
  },
1241
- children: normalized.map((option) => /* @__PURE__ */ jsx8(
1569
+ children: normalized.map((option) => /* @__PURE__ */ jsx10(
1242
1570
  "button",
1243
1571
  {
1244
1572
  className: "dialkit-select-option",
@@ -1259,12 +1587,12 @@ function SelectControl({ label, value, options, onChange }) {
1259
1587
  }
1260
1588
 
1261
1589
  // src/components/ColorControl.tsx
1262
- import { useState as useState5, useRef as useRef6, useEffect as useEffect5 } from "react";
1263
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1590
+ import { useState as useState6, useRef as useRef6, useEffect as useEffect5 } from "react";
1591
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1264
1592
  var HEX_COLOR_REGEX = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;
1265
1593
  function ColorControl({ label, value, onChange }) {
1266
- const [isEditing, setIsEditing] = useState5(false);
1267
- const [editValue, setEditValue] = useState5(value);
1594
+ const [isEditing, setIsEditing] = useState6(false);
1595
+ const [editValue, setEditValue] = useState6(value);
1268
1596
  const colorInputRef = useRef6(null);
1269
1597
  useEffect5(() => {
1270
1598
  if (!isEditing) {
@@ -1287,10 +1615,10 @@ function ColorControl({ label, value, onChange }) {
1287
1615
  setEditValue(value);
1288
1616
  }
1289
1617
  }
1290
- return /* @__PURE__ */ jsxs9("div", { className: "dialkit-color-control", children: [
1291
- /* @__PURE__ */ jsx9("span", { className: "dialkit-color-label", children: label }),
1292
- /* @__PURE__ */ jsxs9("div", { className: "dialkit-color-inputs", children: [
1293
- isEditing ? /* @__PURE__ */ jsx9(
1618
+ return /* @__PURE__ */ jsxs11("div", { className: "dialkit-color-control", children: [
1619
+ /* @__PURE__ */ jsx11("span", { className: "dialkit-color-label", children: label }),
1620
+ /* @__PURE__ */ jsxs11("div", { className: "dialkit-color-inputs", children: [
1621
+ isEditing ? /* @__PURE__ */ jsx11(
1294
1622
  "input",
1295
1623
  {
1296
1624
  type: "text",
@@ -1301,7 +1629,7 @@ function ColorControl({ label, value, onChange }) {
1301
1629
  onKeyDown: handleKeyDown,
1302
1630
  autoFocus: true
1303
1631
  }
1304
- ) : /* @__PURE__ */ jsx9(
1632
+ ) : /* @__PURE__ */ jsx11(
1305
1633
  "span",
1306
1634
  {
1307
1635
  className: "dialkit-color-hex",
@@ -1309,7 +1637,7 @@ function ColorControl({ label, value, onChange }) {
1309
1637
  children: (value ?? "").toUpperCase()
1310
1638
  }
1311
1639
  ),
1312
- /* @__PURE__ */ jsx9(
1640
+ /* @__PURE__ */ jsx11(
1313
1641
  "button",
1314
1642
  {
1315
1643
  className: "dialkit-color-swatch",
@@ -1318,7 +1646,7 @@ function ColorControl({ label, value, onChange }) {
1318
1646
  title: "Pick color"
1319
1647
  }
1320
1648
  ),
1321
- /* @__PURE__ */ jsx9(
1649
+ /* @__PURE__ */ jsx11(
1322
1650
  "input",
1323
1651
  {
1324
1652
  ref: colorInputRef,
@@ -1337,15 +1665,15 @@ function expandShorthandHex(hex) {
1337
1665
  }
1338
1666
 
1339
1667
  // src/components/PresetManager.tsx
1340
- import { useState as useState6, useRef as useRef7, useEffect as useEffect6, useCallback as useCallback3 } from "react";
1668
+ import { useState as useState7, useRef as useRef7, useEffect as useEffect6, useCallback as useCallback3 } from "react";
1341
1669
  import { createPortal as createPortal2 } from "react-dom";
1342
1670
  import { motion as motion5, AnimatePresence as AnimatePresence3 } from "motion/react";
1343
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1671
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1344
1672
  function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1345
- const [isOpen, setIsOpen] = useState6(false);
1673
+ const [isOpen, setIsOpen] = useState7(false);
1346
1674
  const triggerRef = useRef7(null);
1347
1675
  const dropdownRef = useRef7(null);
1348
- const [pos, setPos] = useState6({ top: 0, left: 0, width: 0 });
1676
+ const [pos, setPos] = useState7({ top: 0, left: 0, width: 0 });
1349
1677
  const hasPresets = presets.length > 0;
1350
1678
  const activePreset = presets.find((p) => p.id === activePresetId);
1351
1679
  const open = useCallback3(() => {
@@ -1383,8 +1711,8 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1383
1711
  e.stopPropagation();
1384
1712
  DialStore.deletePreset(panelId, presetId);
1385
1713
  };
1386
- return /* @__PURE__ */ jsxs10("div", { className: "dialkit-preset-manager", children: [
1387
- /* @__PURE__ */ jsxs10(
1714
+ return /* @__PURE__ */ jsxs12("div", { className: "dialkit-preset-manager", children: [
1715
+ /* @__PURE__ */ jsxs12(
1388
1716
  "button",
1389
1717
  {
1390
1718
  ref: triggerRef,
@@ -1394,8 +1722,8 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1394
1722
  "data-has-preset": String(!!activePreset),
1395
1723
  "data-disabled": String(!hasPresets),
1396
1724
  children: [
1397
- /* @__PURE__ */ jsx10("span", { className: "dialkit-preset-label", children: activePreset ? activePreset.name : "Version 1" }),
1398
- /* @__PURE__ */ jsx10(
1725
+ /* @__PURE__ */ jsx12("span", { className: "dialkit-preset-label", children: activePreset ? activePreset.name : "Version 1" }),
1726
+ /* @__PURE__ */ jsx12(
1399
1727
  motion5.svg,
1400
1728
  {
1401
1729
  className: "dialkit-select-chevron",
@@ -1407,14 +1735,14 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1407
1735
  strokeLinejoin: "round",
1408
1736
  animate: { rotate: isOpen ? 180 : 0, opacity: hasPresets ? 0.6 : 0.25 },
1409
1737
  transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
1410
- children: /* @__PURE__ */ jsx10("path", { d: "M6 9.5L12 15.5L18 9.5" })
1738
+ children: /* @__PURE__ */ jsx12("path", { d: "M6 9.5L12 15.5L18 9.5" })
1411
1739
  }
1412
1740
  )
1413
1741
  ]
1414
1742
  }
1415
1743
  ),
1416
1744
  createPortal2(
1417
- /* @__PURE__ */ jsx10(AnimatePresence3, { children: isOpen && /* @__PURE__ */ jsxs10(
1745
+ /* @__PURE__ */ jsx12(AnimatePresence3, { children: isOpen && /* @__PURE__ */ jsxs12(
1418
1746
  motion5.div,
1419
1747
  {
1420
1748
  ref: dropdownRef,
@@ -1425,35 +1753,35 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1425
1753
  exit: { opacity: 0, y: 4, scale: 0.97, pointerEvents: "none" },
1426
1754
  transition: { type: "spring", visualDuration: 0.15, bounce: 0 },
1427
1755
  children: [
1428
- /* @__PURE__ */ jsx10(
1756
+ /* @__PURE__ */ jsx12(
1429
1757
  "div",
1430
1758
  {
1431
1759
  className: "dialkit-preset-item",
1432
1760
  "data-active": String(!activePresetId),
1433
1761
  onClick: () => handleSelect(null),
1434
- children: /* @__PURE__ */ jsx10("span", { className: "dialkit-preset-name", children: "Version 1" })
1762
+ children: /* @__PURE__ */ jsx12("span", { className: "dialkit-preset-name", children: "Version 1" })
1435
1763
  }
1436
1764
  ),
1437
- presets.map((preset) => /* @__PURE__ */ jsxs10(
1765
+ presets.map((preset) => /* @__PURE__ */ jsxs12(
1438
1766
  "div",
1439
1767
  {
1440
1768
  className: "dialkit-preset-item",
1441
1769
  "data-active": String(preset.id === activePresetId),
1442
1770
  onClick: () => handleSelect(preset.id),
1443
1771
  children: [
1444
- /* @__PURE__ */ jsx10("span", { className: "dialkit-preset-name", children: preset.name }),
1445
- /* @__PURE__ */ jsx10(
1772
+ /* @__PURE__ */ jsx12("span", { className: "dialkit-preset-name", children: preset.name }),
1773
+ /* @__PURE__ */ jsx12(
1446
1774
  "button",
1447
1775
  {
1448
1776
  className: "dialkit-preset-delete",
1449
1777
  onClick: (e) => handleDelete(e, preset.id),
1450
1778
  title: "Delete preset",
1451
- children: /* @__PURE__ */ jsxs10("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1452
- /* @__PURE__ */ jsx10("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" }),
1453
- /* @__PURE__ */ jsx10("path", { d: "M10 11V16" }),
1454
- /* @__PURE__ */ jsx10("path", { d: "M14 11V16" }),
1455
- /* @__PURE__ */ jsx10("path", { d: "M3.5 6H20.5" }),
1456
- /* @__PURE__ */ jsx10("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" })
1779
+ children: /* @__PURE__ */ jsxs12("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1780
+ /* @__PURE__ */ jsx12("path", { d: "M5 6.5L5.80734 18.2064C5.91582 19.7794 7.22348 21 8.80023 21H15.1998C16.7765 21 18.0842 19.7794 18.1927 18.2064L19 6.5" }),
1781
+ /* @__PURE__ */ jsx12("path", { d: "M10 11V16" }),
1782
+ /* @__PURE__ */ jsx12("path", { d: "M14 11V16" }),
1783
+ /* @__PURE__ */ jsx12("path", { d: "M3.5 6H20.5" }),
1784
+ /* @__PURE__ */ jsx12("path", { d: "M8.07092 5.74621C8.42348 3.89745 10.0485 2.5 12 2.5C13.9515 2.5 15.5765 3.89745 15.9291 5.74621" })
1457
1785
  ] })
1458
1786
  }
1459
1787
  )
@@ -1470,11 +1798,11 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1470
1798
  }
1471
1799
 
1472
1800
  // src/components/Panel.tsx
1473
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1474
- function Panel({ panel }) {
1475
- const [copied, setCopied] = useState7(false);
1476
- const [isPanelOpen, setIsPanelOpen] = useState7(true);
1477
- const values = useSyncExternalStore3(
1801
+ import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1802
+ function Panel({ panel, defaultOpen = true }) {
1803
+ const [copied, setCopied] = useState8(false);
1804
+ const [isPanelOpen, setIsPanelOpen] = useState8(defaultOpen);
1805
+ const values = useSyncExternalStore4(
1478
1806
  (cb) => DialStore.subscribe(panel.id, cb),
1479
1807
  () => DialStore.getValues(panel.id),
1480
1808
  () => DialStore.getValues(panel.id)
@@ -1502,7 +1830,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1502
1830
  const value = values[control.path];
1503
1831
  switch (control.type) {
1504
1832
  case "slider":
1505
- return /* @__PURE__ */ jsx11(
1833
+ return /* @__PURE__ */ jsx13(
1506
1834
  Slider,
1507
1835
  {
1508
1836
  label: control.label,
@@ -1515,7 +1843,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1515
1843
  control.path
1516
1844
  );
1517
1845
  case "toggle":
1518
- return /* @__PURE__ */ jsx11(
1846
+ return /* @__PURE__ */ jsx13(
1519
1847
  Toggle,
1520
1848
  {
1521
1849
  label: control.label,
@@ -1525,7 +1853,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1525
1853
  control.path
1526
1854
  );
1527
1855
  case "spring":
1528
- return /* @__PURE__ */ jsx11(
1856
+ return /* @__PURE__ */ jsx13(
1529
1857
  SpringControl,
1530
1858
  {
1531
1859
  panelId: panel.id,
@@ -1536,10 +1864,22 @@ Apply these values as the new defaults in the useDialKit call.`;
1536
1864
  },
1537
1865
  control.path
1538
1866
  );
1867
+ case "transition":
1868
+ return /* @__PURE__ */ jsx13(
1869
+ TransitionControl,
1870
+ {
1871
+ panelId: panel.id,
1872
+ path: control.path,
1873
+ label: control.label,
1874
+ value,
1875
+ onChange: (v) => DialStore.updateValue(panel.id, control.path, v)
1876
+ },
1877
+ control.path
1878
+ );
1539
1879
  case "folder":
1540
- return /* @__PURE__ */ jsx11(Folder, { title: control.label, defaultOpen: control.defaultOpen ?? true, children: control.children?.map(renderControl) }, control.path);
1880
+ return /* @__PURE__ */ jsx13(Folder, { title: control.label, defaultOpen: control.defaultOpen ?? true, children: control.children?.map(renderControl) }, control.path);
1541
1881
  case "text":
1542
- return /* @__PURE__ */ jsx11(
1882
+ return /* @__PURE__ */ jsx13(
1543
1883
  TextControl,
1544
1884
  {
1545
1885
  label: control.label,
@@ -1550,7 +1890,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1550
1890
  control.path
1551
1891
  );
1552
1892
  case "select":
1553
- return /* @__PURE__ */ jsx11(
1893
+ return /* @__PURE__ */ jsx13(
1554
1894
  SelectControl,
1555
1895
  {
1556
1896
  label: control.label,
@@ -1561,7 +1901,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1561
1901
  control.path
1562
1902
  );
1563
1903
  case "color":
1564
- return /* @__PURE__ */ jsx11(
1904
+ return /* @__PURE__ */ jsx13(
1565
1905
  ColorControl,
1566
1906
  {
1567
1907
  label: control.label,
@@ -1570,37 +1910,26 @@ Apply these values as the new defaults in the useDialKit call.`;
1570
1910
  },
1571
1911
  control.path
1572
1912
  );
1913
+ case "action":
1914
+ return /* @__PURE__ */ jsx13(
1915
+ "button",
1916
+ {
1917
+ className: "dialkit-button",
1918
+ onClick: () => DialStore.triggerAction(panel.id, control.path),
1919
+ children: control.label
1920
+ },
1921
+ control.path
1922
+ );
1573
1923
  default:
1574
1924
  return null;
1575
1925
  }
1576
1926
  };
1577
1927
  const renderControls = () => {
1578
- const result = [];
1579
- let i = 0;
1580
- while (i < panel.controls.length) {
1581
- const control = panel.controls[i];
1582
- if (control.type === "action") {
1583
- result.push(
1584
- /* @__PURE__ */ jsx11(
1585
- "button",
1586
- {
1587
- className: "dialkit-button",
1588
- onClick: () => DialStore.triggerAction(panel.id, control.path),
1589
- children: control.label
1590
- },
1591
- control.path
1592
- )
1593
- );
1594
- } else {
1595
- result.push(renderControl(control));
1596
- }
1597
- i++;
1598
- }
1599
- return result;
1928
+ return panel.controls.map(renderControl);
1600
1929
  };
1601
1930
  const iconTransition = { type: "spring", visualDuration: 0.4, bounce: 0.1 };
1602
- const toolbar = /* @__PURE__ */ jsxs11(Fragment2, { children: [
1603
- /* @__PURE__ */ jsx11(
1931
+ const toolbar = /* @__PURE__ */ jsxs13(Fragment3, { children: [
1932
+ /* @__PURE__ */ jsx13(
1604
1933
  motion6.button,
1605
1934
  {
1606
1935
  className: "dialkit-toolbar-add",
@@ -1608,16 +1937,16 @@ Apply these values as the new defaults in the useDialKit call.`;
1608
1937
  title: "Add preset",
1609
1938
  whileTap: { scale: 0.9 },
1610
1939
  transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
1611
- children: /* @__PURE__ */ jsxs11("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
1612
- /* @__PURE__ */ jsx11("path", { d: "M4 6H20" }),
1613
- /* @__PURE__ */ jsx11("path", { d: "M4 12H10" }),
1614
- /* @__PURE__ */ jsx11("path", { d: "M15 15L21 15" }),
1615
- /* @__PURE__ */ jsx11("path", { d: "M18 12V18" }),
1616
- /* @__PURE__ */ jsx11("path", { d: "M4 18H10" })
1940
+ children: /* @__PURE__ */ jsxs13("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
1941
+ /* @__PURE__ */ jsx13("path", { d: "M4 6H20" }),
1942
+ /* @__PURE__ */ jsx13("path", { d: "M4 12H10" }),
1943
+ /* @__PURE__ */ jsx13("path", { d: "M15 15L21 15" }),
1944
+ /* @__PURE__ */ jsx13("path", { d: "M18 12V18" }),
1945
+ /* @__PURE__ */ jsx13("path", { d: "M4 18H10" })
1617
1946
  ] })
1618
1947
  }
1619
1948
  ),
1620
- /* @__PURE__ */ jsx11(
1949
+ /* @__PURE__ */ jsx13(
1621
1950
  PresetManager,
1622
1951
  {
1623
1952
  panelId: panel.id,
@@ -1626,7 +1955,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1626
1955
  onAdd: handleAddPreset
1627
1956
  }
1628
1957
  ),
1629
- /* @__PURE__ */ jsxs11(
1958
+ /* @__PURE__ */ jsxs13(
1630
1959
  motion6.button,
1631
1960
  {
1632
1961
  className: "dialkit-toolbar-copy",
@@ -1635,7 +1964,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1635
1964
  whileTap: { scale: 0.95 },
1636
1965
  transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
1637
1966
  children: [
1638
- /* @__PURE__ */ jsx11("span", { className: "dialkit-toolbar-copy-icon-wrap", children: /* @__PURE__ */ jsx11(AnimatePresence4, { initial: false, mode: "popLayout", children: copied ? /* @__PURE__ */ jsx11(
1967
+ /* @__PURE__ */ jsx13("span", { className: "dialkit-toolbar-copy-icon-wrap", children: /* @__PURE__ */ jsx13(AnimatePresence4, { initial: false, mode: "popLayout", children: copied ? /* @__PURE__ */ jsx13(
1639
1968
  motion6.svg,
1640
1969
  {
1641
1970
  className: "dialkit-toolbar-copy-icon",
@@ -1649,10 +1978,10 @@ Apply these values as the new defaults in the useDialKit call.`;
1649
1978
  animate: { scale: 1, opacity: 1, filter: "blur(0px)" },
1650
1979
  exit: { scale: 0.5, opacity: 0, filter: "blur(4px)" },
1651
1980
  transition: { type: "spring", visualDuration: 0.3, bounce: 0.2 },
1652
- children: /* @__PURE__ */ jsx11("path", { d: "M5 12.75L10 19L19 5" })
1981
+ children: /* @__PURE__ */ jsx13("path", { d: "M5 12.75L10 19L19 5" })
1653
1982
  },
1654
1983
  "check"
1655
- ) : /* @__PURE__ */ jsxs11(
1984
+ ) : /* @__PURE__ */ jsxs13(
1656
1985
  motion6.svg,
1657
1986
  {
1658
1987
  className: "dialkit-toolbar-copy-icon",
@@ -1663,9 +1992,9 @@ Apply these values as the new defaults in the useDialKit call.`;
1663
1992
  exit: { scale: 0.5, opacity: 0, filter: "blur(4px)" },
1664
1993
  transition: { type: "spring", visualDuration: 0.3, bounce: 0.2 },
1665
1994
  children: [
1666
- /* @__PURE__ */ jsx11("path", { d: "M8 6C8 4.34315 9.34315 3 11 3H13C14.6569 3 16 4.34315 16 6V7H8V6Z", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }),
1667
- /* @__PURE__ */ jsx11("path", { d: "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", fill: "currentColor" }),
1668
- /* @__PURE__ */ jsx11("path", { d: "M16 5H17C18.6569 5 20 6.34315 20 8V11M8 5H7C5.34315 5 4 6.34315 4 8V18C4 19.6569 5.34315 21 7 21H12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
1995
+ /* @__PURE__ */ jsx13("path", { d: "M8 6C8 4.34315 9.34315 3 11 3H13C14.6569 3 16 4.34315 16 6V7H8V6Z", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }),
1996
+ /* @__PURE__ */ jsx13("path", { d: "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", fill: "currentColor" }),
1997
+ /* @__PURE__ */ jsx13("path", { d: "M16 5H17C18.6569 5 20 6.34315 20 8V11M8 5H7C5.34315 5 4 6.34315 4 8V18C4 19.6569 5.34315 21 7 21H12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
1669
1998
  ]
1670
1999
  },
1671
2000
  "clipboard"
@@ -1675,14 +2004,14 @@ Apply these values as the new defaults in the useDialKit call.`;
1675
2004
  }
1676
2005
  )
1677
2006
  ] });
1678
- return /* @__PURE__ */ jsx11("div", { className: "dialkit-panel-wrapper", children: /* @__PURE__ */ jsx11(Folder, { title: panel.name, defaultOpen: true, isRoot: true, onOpenChange: setIsPanelOpen, toolbar, children: renderControls() }) });
2007
+ return /* @__PURE__ */ jsx13("div", { className: "dialkit-panel-wrapper", children: /* @__PURE__ */ jsx13(Folder, { title: panel.name, defaultOpen, isRoot: true, onOpenChange: setIsPanelOpen, toolbar, children: renderControls() }) });
1679
2008
  }
1680
2009
 
1681
2010
  // src/components/DialRoot.tsx
1682
- import { jsx as jsx12 } from "react/jsx-runtime";
1683
- function DialRoot({ position = "top-right" }) {
1684
- const [panels, setPanels] = useState8([]);
1685
- const [mounted, setMounted] = useState8(false);
2011
+ import { jsx as jsx14 } from "react/jsx-runtime";
2012
+ function DialRoot({ position = "top-right", defaultOpen = true }) {
2013
+ const [panels, setPanels] = useState9([]);
2014
+ const [mounted, setMounted] = useState9(false);
1686
2015
  useEffect7(() => {
1687
2016
  setMounted(true);
1688
2017
  setPanels(DialStore.getPanels());
@@ -1697,14 +2026,14 @@ function DialRoot({ position = "top-right" }) {
1697
2026
  if (panels.length === 0) {
1698
2027
  return null;
1699
2028
  }
1700
- const content = /* @__PURE__ */ jsx12("div", { className: "dialkit-root", children: /* @__PURE__ */ jsx12("div", { className: "dialkit-panel", "data-position": position, children: panels.map((panel) => /* @__PURE__ */ jsx12(Panel, { panel }, panel.id)) }) });
2029
+ const content = /* @__PURE__ */ jsx14("div", { className: "dialkit-root", children: /* @__PURE__ */ jsx14("div", { className: "dialkit-panel", "data-position": position, children: panels.map((panel) => /* @__PURE__ */ jsx14(Panel, { panel, defaultOpen }, panel.id)) }) });
1701
2030
  return createPortal3(content, document.body);
1702
2031
  }
1703
2032
 
1704
2033
  // src/components/ButtonGroup.tsx
1705
- import { jsx as jsx13 } from "react/jsx-runtime";
2034
+ import { jsx as jsx15 } from "react/jsx-runtime";
1706
2035
  function ButtonGroup({ buttons }) {
1707
- return /* @__PURE__ */ jsx13("div", { className: "dialkit-button-group", children: buttons.map((button, index) => /* @__PURE__ */ jsx13(
2036
+ return /* @__PURE__ */ jsx15("div", { className: "dialkit-button-group", children: buttons.map((button, index) => /* @__PURE__ */ jsx15(
1708
2037
  "button",
1709
2038
  {
1710
2039
  className: "dialkit-button",
@@ -1719,6 +2048,7 @@ export {
1719
2048
  ColorControl,
1720
2049
  DialRoot,
1721
2050
  DialStore,
2051
+ EasingVisualization,
1722
2052
  Folder,
1723
2053
  PresetManager,
1724
2054
  SelectControl,
@@ -1727,6 +2057,7 @@ export {
1727
2057
  SpringVisualization,
1728
2058
  TextControl,
1729
2059
  Toggle,
2060
+ TransitionControl,
1730
2061
  useDialKit
1731
2062
  };
1732
2063
  //# sourceMappingURL=index.js.map