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.cjs CHANGED
@@ -25,6 +25,7 @@ __export(index_exports, {
25
25
  ColorControl: () => ColorControl,
26
26
  DialRoot: () => DialRoot,
27
27
  DialStore: () => DialStore,
28
+ EasingVisualization: () => EasingVisualization,
28
29
  Folder: () => Folder,
29
30
  PresetManager: () => PresetManager,
30
31
  SelectControl: () => SelectControl,
@@ -33,6 +34,7 @@ __export(index_exports, {
33
34
  SpringVisualization: () => SpringVisualization,
34
35
  TextControl: () => TextControl,
35
36
  Toggle: () => Toggle,
37
+ TransitionControl: () => TransitionControl,
36
38
  useDialKit: () => useDialKit
37
39
  });
38
40
  module.exports = __toCommonJS(index_exports);
@@ -56,15 +58,67 @@ var DialStoreClass = class {
56
58
  registerPanel(id, name, config) {
57
59
  const controls = this.parseConfig(config, "");
58
60
  const values = this.flattenValues(config, "");
61
+ this.initTransitionModes(config, "", values);
59
62
  this.panels.set(id, { id, name, controls, values });
60
63
  this.snapshots.set(id, { ...values });
61
64
  this.baseValues.set(id, { ...values });
62
65
  this.notifyGlobal();
63
66
  }
67
+ updatePanel(id, name, config) {
68
+ const existing = this.panels.get(id);
69
+ if (!existing) {
70
+ this.registerPanel(id, name, config);
71
+ return;
72
+ }
73
+ const controls = this.parseConfig(config, "");
74
+ const controlsByPath = this.mapControlsByPath(controls);
75
+ const defaultValues = this.flattenValues(config, "");
76
+ const nextValues = {};
77
+ for (const [path, defaultValue] of Object.entries(defaultValues)) {
78
+ nextValues[path] = this.normalizePreservedValue(
79
+ existing.values[path],
80
+ defaultValue,
81
+ controlsByPath.get(path)
82
+ );
83
+ }
84
+ this.initTransitionModes(config, "", nextValues);
85
+ for (const [path, mode] of Object.entries(existing.values)) {
86
+ if (!path.endsWith(".__mode")) {
87
+ continue;
88
+ }
89
+ const transitionPath = path.slice(0, -"__mode".length - 1);
90
+ const transitionControl = controlsByPath.get(transitionPath);
91
+ if (transitionControl?.type === "transition") {
92
+ nextValues[path] = mode;
93
+ }
94
+ }
95
+ const nextPanel = { id, name, controls, values: nextValues };
96
+ this.panels.set(id, nextPanel);
97
+ this.snapshots.set(id, { ...nextValues });
98
+ const previousBaseValues = this.baseValues.get(id) ?? {};
99
+ const nextBaseValues = {};
100
+ for (const [path, defaultValue] of Object.entries(defaultValues)) {
101
+ nextBaseValues[path] = this.normalizePreservedValue(
102
+ previousBaseValues[path],
103
+ defaultValue,
104
+ controlsByPath.get(path)
105
+ );
106
+ }
107
+ for (const [path, value] of Object.entries(nextValues)) {
108
+ if (path.endsWith(".__mode")) {
109
+ nextBaseValues[path] = value;
110
+ }
111
+ }
112
+ this.baseValues.set(id, nextBaseValues);
113
+ this.notify(id);
114
+ this.notifyGlobal();
115
+ }
64
116
  unregisterPanel(id) {
65
117
  this.panels.delete(id);
66
118
  this.listeners.delete(id);
67
119
  this.snapshots.delete(id);
120
+ this.actionListeners.delete(id);
121
+ this.baseValues.delete(id);
68
122
  this.notifyGlobal();
69
123
  }
70
124
  updateValue(panelId, path, value) {
@@ -84,13 +138,21 @@ var DialStoreClass = class {
84
138
  this.notify(panelId);
85
139
  }
86
140
  updateSpringMode(panelId, path, mode) {
141
+ this.updateTransitionMode(panelId, path, mode);
142
+ }
143
+ getSpringMode(panelId, path) {
144
+ const mode = this.getTransitionMode(panelId, path);
145
+ if (mode === "easing") return "simple";
146
+ return mode;
147
+ }
148
+ updateTransitionMode(panelId, path, mode) {
87
149
  const panel = this.panels.get(panelId);
88
150
  if (!panel) return;
89
151
  panel.values[`${path}.__mode`] = mode;
90
152
  this.snapshots.set(panelId, { ...panel.values });
91
153
  this.notify(panelId);
92
154
  }
93
- getSpringMode(panelId, path) {
155
+ getTransitionMode(panelId, path) {
94
156
  const panel = this.panels.get(panelId);
95
157
  if (!panel) return "simple";
96
158
  return panel.values[`${path}.__mode`] || "simple";
@@ -194,6 +256,21 @@ var DialStoreClass = class {
194
256
  notifyGlobal() {
195
257
  this.globalListeners.forEach((fn) => fn());
196
258
  }
259
+ initTransitionModes(config, prefix, values) {
260
+ for (const [key, value] of Object.entries(config)) {
261
+ if (key === "_collapsed") continue;
262
+ const path = prefix ? `${prefix}.${key}` : key;
263
+ if (this.isEasingConfig(value)) {
264
+ values[`${path}.__mode`] = "easing";
265
+ } else if (this.isSpringConfig(value)) {
266
+ const hasPhysics = value.stiffness !== void 0 || value.damping !== void 0 || value.mass !== void 0;
267
+ const hasTime = value.visualDuration !== void 0 || value.bounce !== void 0;
268
+ values[`${path}.__mode`] = hasPhysics && !hasTime ? "advanced" : "simple";
269
+ } else if (typeof value === "object" && value !== null && !Array.isArray(value) && !this.isActionConfig(value) && !this.isSelectConfig(value) && !this.isColorConfig(value) && !this.isTextConfig(value)) {
270
+ this.initTransitionModes(value, path, values);
271
+ }
272
+ }
273
+ }
197
274
  parseConfig(config, prefix) {
198
275
  const controls = [];
199
276
  for (const [key, value] of Object.entries(config)) {
@@ -214,8 +291,8 @@ var DialStoreClass = class {
214
291
  controls.push({ type: "slider", path, label, min, max, step });
215
292
  } else if (typeof value === "boolean") {
216
293
  controls.push({ type: "toggle", path, label });
217
- } else if (this.isSpringConfig(value)) {
218
- controls.push({ type: "spring", path, label });
294
+ } else if (this.isSpringConfig(value) || this.isEasingConfig(value)) {
295
+ controls.push({ type: "transition", path, label });
219
296
  } else if (this.isActionConfig(value)) {
220
297
  controls.push({ type: "action", path, label: value.label || label });
221
298
  } else if (this.isSelectConfig(value)) {
@@ -253,7 +330,7 @@ var DialStoreClass = class {
253
330
  values[path] = value[0];
254
331
  } else if (typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
255
332
  values[path] = value;
256
- } else if (this.isSpringConfig(value)) {
333
+ } else if (this.isSpringConfig(value) || this.isEasingConfig(value)) {
257
334
  values[path] = value;
258
335
  } else if (this.isActionConfig(value)) {
259
336
  values[path] = value;
@@ -274,6 +351,9 @@ var DialStoreClass = class {
274
351
  isSpringConfig(value) {
275
352
  return typeof value === "object" && value !== null && "type" in value && value.type === "spring";
276
353
  }
354
+ isEasingConfig(value) {
355
+ return typeof value === "object" && value !== null && "type" in value && value.type === "easing";
356
+ }
277
357
  isActionConfig(value) {
278
358
  return typeof value === "object" && value !== null && "type" in value && value.type === "action";
279
359
  }
@@ -312,6 +392,75 @@ var DialStoreClass = class {
312
392
  if (range <= 100) return 1;
313
393
  return 10;
314
394
  }
395
+ normalizePreservedValue(existingValue, defaultValue, control) {
396
+ if (existingValue === void 0 || !control) {
397
+ return defaultValue;
398
+ }
399
+ switch (control.type) {
400
+ case "slider": {
401
+ if (typeof existingValue !== "number" || typeof defaultValue !== "number") {
402
+ return defaultValue;
403
+ }
404
+ const min = control.min ?? Number.NEGATIVE_INFINITY;
405
+ const max = control.max ?? Number.POSITIVE_INFINITY;
406
+ const clamped = Math.min(max, Math.max(min, existingValue));
407
+ if (typeof control.step !== "number" || control.step <= 0) {
408
+ return clamped;
409
+ }
410
+ return this.roundToStep(clamped, min, max, control.step);
411
+ }
412
+ case "toggle":
413
+ return typeof existingValue === "boolean" ? existingValue : defaultValue;
414
+ case "select": {
415
+ if (typeof existingValue !== "string") {
416
+ return defaultValue;
417
+ }
418
+ const options = control.options ?? [];
419
+ const validValues = new Set(options.map((option) => typeof option === "string" ? option : option.value));
420
+ return validValues.has(existingValue) ? existingValue : defaultValue;
421
+ }
422
+ case "color":
423
+ case "text":
424
+ return typeof existingValue === "string" ? existingValue : defaultValue;
425
+ case "transition":
426
+ if (this.isSpringConfig(defaultValue)) {
427
+ return this.isSpringConfig(existingValue) ? existingValue : defaultValue;
428
+ }
429
+ if (this.isEasingConfig(defaultValue)) {
430
+ return this.isEasingConfig(existingValue) ? existingValue : defaultValue;
431
+ }
432
+ return defaultValue;
433
+ case "action":
434
+ return defaultValue;
435
+ default:
436
+ return defaultValue;
437
+ }
438
+ }
439
+ roundToStep(value, min, max, step) {
440
+ const snapped = min + Math.round((value - min) / step) * step;
441
+ const clamped = Math.min(max, Math.max(min, snapped));
442
+ const precision = this.stepPrecision(step);
443
+ return Number(clamped.toFixed(precision));
444
+ }
445
+ stepPrecision(step) {
446
+ const text = String(step);
447
+ const decimalIndex = text.indexOf(".");
448
+ return decimalIndex === -1 ? 0 : text.length - decimalIndex - 1;
449
+ }
450
+ mapControlsByPath(controls) {
451
+ const map = /* @__PURE__ */ new Map();
452
+ const visit = (nodes) => {
453
+ for (const node of nodes) {
454
+ if (node.type === "folder" && node.children) {
455
+ visit(node.children);
456
+ continue;
457
+ }
458
+ map.set(node.path, node);
459
+ }
460
+ };
461
+ visit(controls);
462
+ return map;
463
+ }
315
464
  };
316
465
  var DialStore = new DialStoreClass();
317
466
 
@@ -320,12 +469,22 @@ function useDialKit(name, config, options) {
320
469
  const instanceId = (0, import_react.useId)();
321
470
  const panelId = `${name}-${instanceId}`;
322
471
  const configRef = (0, import_react.useRef)(config);
472
+ const serializedConfig = JSON.stringify(config);
473
+ configRef.current = config;
323
474
  const onActionRef = (0, import_react.useRef)(options?.onAction);
324
475
  onActionRef.current = options?.onAction;
325
476
  (0, import_react.useEffect)(() => {
326
477
  DialStore.registerPanel(panelId, name, configRef.current);
327
478
  return () => DialStore.unregisterPanel(panelId);
328
479
  }, [panelId, name]);
480
+ const mountedRef = (0, import_react.useRef)(false);
481
+ (0, import_react.useEffect)(() => {
482
+ if (!mountedRef.current) {
483
+ mountedRef.current = true;
484
+ return;
485
+ }
486
+ DialStore.updatePanel(panelId, name, configRef.current);
487
+ }, [panelId, name, serializedConfig]);
329
488
  (0, import_react.useEffect)(() => {
330
489
  return DialStore.subscribeActions(panelId, (action) => {
331
490
  onActionRef.current?.(action);
@@ -347,7 +506,7 @@ function buildResolvedValues(config, flatValues, prefix) {
347
506
  result[key] = flatValues[path] ?? configValue[0];
348
507
  } else if (typeof configValue === "number" || typeof configValue === "boolean" || typeof configValue === "string") {
349
508
  result[key] = flatValues[path] ?? configValue;
350
- } else if (isSpringConfig(configValue)) {
509
+ } else if (isSpringConfig(configValue) || isEasingConfig(configValue)) {
351
510
  result[key] = flatValues[path] ?? configValue;
352
511
  } else if (isActionConfig(configValue)) {
353
512
  result[key] = flatValues[path] ?? configValue;
@@ -370,6 +529,9 @@ function hasType(value, type) {
370
529
  function isSpringConfig(value) {
371
530
  return hasType(value, "spring");
372
531
  }
532
+ function isEasingConfig(value) {
533
+ return hasType(value, "easing");
534
+ }
373
535
  function isActionConfig(value) {
374
536
  return hasType(value, "action");
375
537
  }
@@ -388,12 +550,12 @@ function getFirstOptionValue(options) {
388
550
  }
389
551
 
390
552
  // src/components/DialRoot.tsx
391
- var import_react16 = require("react");
553
+ var import_react17 = require("react");
392
554
  var import_react_dom3 = require("react-dom");
393
555
 
394
556
  // src/components/Panel.tsx
395
- var import_react14 = require("react");
396
- var import_react15 = require("motion/react");
557
+ var import_react15 = require("react");
558
+ var import_react16 = require("motion/react");
397
559
 
398
560
  // src/components/Folder.tsx
399
561
  var import_react2 = require("react");
@@ -1156,12 +1318,180 @@ function SpringControl({ panelId, path, label, spring, onChange }) {
1156
1318
  ] }) });
1157
1319
  }
1158
1320
 
1159
- // src/components/TextControl.tsx
1321
+ // src/components/EasingVisualization.tsx
1160
1322
  var import_jsx_runtime7 = require("react/jsx-runtime");
1323
+ function EasingVisualization({ easing }) {
1324
+ const ease = easing.ease;
1325
+ const s = 200;
1326
+ const pad = 10;
1327
+ const inner = s - pad * 2;
1328
+ const unit = inner / 2;
1329
+ const toSvg = (nx, ny) => ({
1330
+ x: pad + (nx + 0.5) * unit,
1331
+ y: pad + (1.5 - ny) * unit
1332
+ });
1333
+ const start = toSvg(0, 0);
1334
+ const end = toSvg(1, 1);
1335
+ const p1 = toSvg(ease[0], ease[1]);
1336
+ const p2 = toSvg(ease[2], ease[3]);
1337
+ const curvePath = `M ${start.x} ${start.y} C ${p1.x} ${p1.y}, ${p2.x} ${p2.y}, ${end.x} ${end.y}`;
1338
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1339
+ "svg",
1340
+ {
1341
+ viewBox: `0 0 ${s} ${s}`,
1342
+ preserveAspectRatio: "xMidYMid slice",
1343
+ className: "dialkit-spring-viz dialkit-easing-viz",
1344
+ children: [
1345
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1346
+ "line",
1347
+ {
1348
+ x1: start.x,
1349
+ y1: start.y,
1350
+ x2: end.x,
1351
+ y2: end.y,
1352
+ stroke: "rgba(255, 255, 255, 0.15)",
1353
+ strokeWidth: "1",
1354
+ strokeDasharray: "4,4"
1355
+ }
1356
+ ),
1357
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: curvePath, fill: "none", stroke: "rgba(255, 255, 255, 0.6)", strokeWidth: "2", strokeLinecap: "round" })
1358
+ ]
1359
+ }
1360
+ );
1361
+ }
1362
+
1363
+ // src/components/TransitionControl.tsx
1364
+ var import_react9 = require("react");
1365
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1366
+ function TransitionControl({ panelId, path, label, value, onChange }) {
1367
+ const mode = (0, import_react9.useSyncExternalStore)(
1368
+ (cb) => DialStore.subscribe(panelId, cb),
1369
+ () => DialStore.getTransitionMode(panelId, path),
1370
+ () => DialStore.getTransitionMode(panelId, path)
1371
+ );
1372
+ const isEasing = mode === "easing";
1373
+ const isSimpleSpring = mode === "simple";
1374
+ const spring = value.type === "spring" ? value : { type: "spring", visualDuration: 0.3, bounce: 0.2 };
1375
+ const easing = value.type === "easing" ? value : { type: "easing", duration: 0.3, ease: [1, -0.4, 0.5, 1] };
1376
+ const handleModeChange = (newMode) => {
1377
+ DialStore.updateTransitionMode(panelId, path, newMode);
1378
+ if (newMode === "easing") {
1379
+ const duration = value.type === "spring" ? value.visualDuration ?? 0.3 : value.duration;
1380
+ onChange({ type: "easing", duration, ease: easing.ease });
1381
+ } 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
+ });
1387
+ } else {
1388
+ onChange({
1389
+ type: "spring",
1390
+ stiffness: spring.stiffness ?? 200,
1391
+ damping: spring.damping ?? 25,
1392
+ mass: spring.mass ?? 1
1393
+ });
1394
+ }
1395
+ };
1396
+ const handleSpringUpdate = (key, val) => {
1397
+ if (isSimpleSpring) {
1398
+ const { stiffness, damping, mass, ...rest } = spring;
1399
+ onChange({ ...rest, [key]: val });
1400
+ } else {
1401
+ const { visualDuration, bounce, ...rest } = spring;
1402
+ onChange({ ...rest, [key]: val });
1403
+ }
1404
+ };
1405
+ const updateEase = (index, val) => {
1406
+ const newEase = [...easing.ease];
1407
+ newEase[index] = val;
1408
+ onChange({ ...easing, ease: newEase });
1409
+ };
1410
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Folder, { title: label, defaultOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
1411
+ isEasing ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(EasingVisualization, { easing }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SpringVisualization, { spring, isSimpleMode: isSimpleSpring }),
1412
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dialkit-labeled-control", children: [
1413
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dialkit-labeled-control-label", children: "Type" }),
1414
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1415
+ SegmentedControl,
1416
+ {
1417
+ options: [
1418
+ { value: "easing", label: "Easing" },
1419
+ { value: "simple", label: "Time" },
1420
+ { value: "advanced", label: "Physics" }
1421
+ ],
1422
+ value: mode,
1423
+ onChange: handleModeChange
1424
+ }
1425
+ )
1426
+ ] }),
1427
+ isEasing ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1428
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Slider, { label: "x1", value: easing.ease[0], onChange: (v) => updateEase(0, v), min: 0, max: 1, step: 0.01 }),
1429
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Slider, { label: "y1", value: easing.ease[1], onChange: (v) => updateEase(1, v), min: -1, max: 2, step: 0.01 }),
1430
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Slider, { label: "x2", value: easing.ease[2], onChange: (v) => updateEase(2, v), min: 0, max: 1, step: 0.01 }),
1431
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Slider, { label: "y2", value: easing.ease[3], onChange: (v) => updateEase(3, v), min: -1, max: 2, step: 0.01 }),
1432
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Slider, { label: "Duration", value: easing.duration, onChange: (v) => onChange({ ...easing, duration: v }), min: 0.1, max: 2, step: 0.05, unit: "s" }),
1433
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(EaseTextInput, { ease: easing.ease, onChange: (newEase) => onChange({ ...easing, ease: newEase }) })
1434
+ ] }) : isSimpleSpring ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1435
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Slider, { label: "Duration", value: spring.visualDuration ?? 0.3, onChange: (v) => handleSpringUpdate("visualDuration", v), min: 0.1, max: 1, step: 0.05, unit: "s" }),
1436
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Slider, { label: "Bounce", value: spring.bounce ?? 0.2, onChange: (v) => handleSpringUpdate("bounce", v), min: 0, max: 1, step: 0.05 })
1437
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1438
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Slider, { label: "Stiffness", value: spring.stiffness ?? 400, onChange: (v) => handleSpringUpdate("stiffness", v), min: 1, max: 1e3, step: 10 }),
1439
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Slider, { label: "Damping", value: spring.damping ?? 17, onChange: (v) => handleSpringUpdate("damping", v), min: 1, max: 100, step: 1 }),
1440
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Slider, { label: "Mass", value: spring.mass ?? 1, onChange: (v) => handleSpringUpdate("mass", v), min: 0.1, max: 10, step: 0.1 })
1441
+ ] })
1442
+ ] }) });
1443
+ }
1444
+ function formatEase(ease) {
1445
+ return ease.map((v) => parseFloat(v.toFixed(2))).join(", ");
1446
+ }
1447
+ function parseEase(str) {
1448
+ const parts = str.split(",").map((s) => parseFloat(s.trim()));
1449
+ if (parts.length === 4 && parts.every((n) => !isNaN(n))) {
1450
+ return parts;
1451
+ }
1452
+ return null;
1453
+ }
1454
+ function EaseTextInput({ ease, onChange }) {
1455
+ const [editing, setEditing] = (0, import_react9.useState)(false);
1456
+ const [draft, setDraft] = (0, import_react9.useState)("");
1457
+ const handleFocus = () => {
1458
+ setDraft(formatEase(ease));
1459
+ setEditing(true);
1460
+ };
1461
+ const handleBlur = () => {
1462
+ const parsed = parseEase(draft);
1463
+ if (parsed) onChange(parsed);
1464
+ setEditing(false);
1465
+ };
1466
+ const handleKeyDown = (e) => {
1467
+ if (e.key === "Enter") {
1468
+ e.target.blur();
1469
+ }
1470
+ };
1471
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dialkit-labeled-control", children: [
1472
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dialkit-labeled-control-label", children: "Ease" }),
1473
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1474
+ "input",
1475
+ {
1476
+ type: "text",
1477
+ className: "dialkit-text-input",
1478
+ value: editing ? draft : formatEase(ease),
1479
+ onChange: (e) => setDraft(e.target.value),
1480
+ onFocus: handleFocus,
1481
+ onBlur: handleBlur,
1482
+ onKeyDown: handleKeyDown,
1483
+ spellCheck: false
1484
+ }
1485
+ )
1486
+ ] });
1487
+ }
1488
+
1489
+ // src/components/TextControl.tsx
1490
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1161
1491
  function TextControl({ label, value, onChange, placeholder }) {
1162
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dialkit-text-control", children: [
1163
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "dialkit-text-label", children: label }),
1164
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1492
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dialkit-text-control", children: [
1493
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "dialkit-text-label", children: label }),
1494
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1165
1495
  "input",
1166
1496
  {
1167
1497
  type: "text",
@@ -1175,10 +1505,10 @@ function TextControl({ label, value, onChange, placeholder }) {
1175
1505
  }
1176
1506
 
1177
1507
  // src/components/SelectControl.tsx
1178
- var import_react9 = require("react");
1508
+ var import_react10 = require("react");
1179
1509
  var import_react_dom = require("react-dom");
1180
- var import_react10 = require("motion/react");
1181
- var import_jsx_runtime8 = require("react/jsx-runtime");
1510
+ var import_react11 = require("motion/react");
1511
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1182
1512
  function toTitleCase(s) {
1183
1513
  return s.replace(/\b\w/g, (c) => c.toUpperCase());
1184
1514
  }
@@ -1188,14 +1518,14 @@ function normalizeOptions(options) {
1188
1518
  );
1189
1519
  }
1190
1520
  function SelectControl({ label, value, options, onChange }) {
1191
- const [isOpen, setIsOpen] = (0, import_react9.useState)(false);
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);
1521
+ const [isOpen, setIsOpen] = (0, import_react10.useState)(false);
1522
+ const triggerRef = (0, import_react10.useRef)(null);
1523
+ const dropdownRef = (0, import_react10.useRef)(null);
1524
+ const [portalTarget, setPortalTarget] = (0, import_react10.useState)(null);
1525
+ const [pos, setPos] = (0, import_react10.useState)(null);
1196
1526
  const normalized = normalizeOptions(options);
1197
1527
  const selectedOption = normalized.find((o) => o.value === value);
1198
- const updatePos = (0, import_react9.useCallback)(() => {
1528
+ const updatePos = (0, import_react10.useCallback)(() => {
1199
1529
  const el = triggerRef.current;
1200
1530
  if (!el) return;
1201
1531
  const rect = el.getBoundingClientRect();
@@ -1209,15 +1539,15 @@ function SelectControl({ label, value, options, onChange }) {
1209
1539
  above
1210
1540
  });
1211
1541
  }, [normalized.length]);
1212
- (0, import_react9.useEffect)(() => {
1542
+ (0, import_react10.useEffect)(() => {
1213
1543
  const root = triggerRef.current?.closest(".dialkit-root");
1214
1544
  setPortalTarget(root ?? document.body);
1215
1545
  }, []);
1216
- (0, import_react9.useEffect)(() => {
1546
+ (0, import_react10.useEffect)(() => {
1217
1547
  if (!isOpen) return;
1218
1548
  updatePos();
1219
1549
  }, [isOpen, updatePos]);
1220
- (0, import_react9.useEffect)(() => {
1550
+ (0, import_react10.useEffect)(() => {
1221
1551
  if (!isOpen) return;
1222
1552
  const handleClick = (e) => {
1223
1553
  const target = e.target;
@@ -1228,8 +1558,8 @@ function SelectControl({ label, value, options, onChange }) {
1228
1558
  document.addEventListener("mousedown", handleClick);
1229
1559
  return () => document.removeEventListener("mousedown", handleClick);
1230
1560
  }, [isOpen]);
1231
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dialkit-select-row", children: [
1232
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1561
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dialkit-select-row", children: [
1562
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1233
1563
  "button",
1234
1564
  {
1235
1565
  ref: triggerRef,
@@ -1237,11 +1567,11 @@ function SelectControl({ label, value, options, onChange }) {
1237
1567
  onClick: () => setIsOpen(!isOpen),
1238
1568
  "data-open": String(isOpen),
1239
1569
  children: [
1240
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dialkit-select-label", children: label }),
1241
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dialkit-select-right", children: [
1242
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dialkit-select-value", children: selectedOption?.label ?? value }),
1243
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1244
- import_react10.motion.svg,
1570
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "dialkit-select-label", children: label }),
1571
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dialkit-select-right", children: [
1572
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "dialkit-select-value", children: selectedOption?.label ?? value }),
1573
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1574
+ import_react11.motion.svg,
1245
1575
  {
1246
1576
  className: "dialkit-select-chevron",
1247
1577
  viewBox: "0 0 24 24",
@@ -1252,7 +1582,7 @@ function SelectControl({ label, value, options, onChange }) {
1252
1582
  strokeLinejoin: "round",
1253
1583
  animate: { rotate: isOpen ? 180 : 0 },
1254
1584
  transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
1255
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M6 9.5L12 15.5L18 9.5" })
1585
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M6 9.5L12 15.5L18 9.5" })
1256
1586
  }
1257
1587
  )
1258
1588
  ] })
@@ -1260,8 +1590,8 @@ function SelectControl({ label, value, options, onChange }) {
1260
1590
  }
1261
1591
  ),
1262
1592
  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,
1593
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react11.AnimatePresence, { children: isOpen && pos && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1594
+ import_react11.motion.div,
1265
1595
  {
1266
1596
  ref: dropdownRef,
1267
1597
  className: "dialkit-select-dropdown",
@@ -1275,7 +1605,7 @@ function SelectControl({ label, value, options, onChange }) {
1275
1605
  width: pos.width,
1276
1606
  ...pos.above ? { bottom: window.innerHeight - pos.top, transformOrigin: "bottom" } : { top: pos.top, transformOrigin: "top" }
1277
1607
  },
1278
- children: normalized.map((option) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1608
+ children: normalized.map((option) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1279
1609
  "button",
1280
1610
  {
1281
1611
  className: "dialkit-select-option",
@@ -1296,14 +1626,14 @@ function SelectControl({ label, value, options, onChange }) {
1296
1626
  }
1297
1627
 
1298
1628
  // src/components/ColorControl.tsx
1299
- var import_react11 = require("react");
1300
- var import_jsx_runtime9 = require("react/jsx-runtime");
1629
+ var import_react12 = require("react");
1630
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1301
1631
  var HEX_COLOR_REGEX = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;
1302
1632
  function ColorControl({ label, value, onChange }) {
1303
- const [isEditing, setIsEditing] = (0, import_react11.useState)(false);
1304
- const [editValue, setEditValue] = (0, import_react11.useState)(value);
1305
- const colorInputRef = (0, import_react11.useRef)(null);
1306
- (0, import_react11.useEffect)(() => {
1633
+ const [isEditing, setIsEditing] = (0, import_react12.useState)(false);
1634
+ const [editValue, setEditValue] = (0, import_react12.useState)(value);
1635
+ const colorInputRef = (0, import_react12.useRef)(null);
1636
+ (0, import_react12.useEffect)(() => {
1307
1637
  if (!isEditing) {
1308
1638
  setEditValue(value);
1309
1639
  }
@@ -1324,10 +1654,10 @@ function ColorControl({ label, value, onChange }) {
1324
1654
  setEditValue(value);
1325
1655
  }
1326
1656
  }
1327
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dialkit-color-control", children: [
1328
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dialkit-color-label", children: label }),
1329
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dialkit-color-inputs", children: [
1330
- isEditing ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1657
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dialkit-color-control", children: [
1658
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "dialkit-color-label", children: label }),
1659
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dialkit-color-inputs", children: [
1660
+ isEditing ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1331
1661
  "input",
1332
1662
  {
1333
1663
  type: "text",
@@ -1338,7 +1668,7 @@ function ColorControl({ label, value, onChange }) {
1338
1668
  onKeyDown: handleKeyDown,
1339
1669
  autoFocus: true
1340
1670
  }
1341
- ) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1671
+ ) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1342
1672
  "span",
1343
1673
  {
1344
1674
  className: "dialkit-color-hex",
@@ -1346,7 +1676,7 @@ function ColorControl({ label, value, onChange }) {
1346
1676
  children: (value ?? "").toUpperCase()
1347
1677
  }
1348
1678
  ),
1349
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1679
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1350
1680
  "button",
1351
1681
  {
1352
1682
  className: "dialkit-color-swatch",
@@ -1355,7 +1685,7 @@ function ColorControl({ label, value, onChange }) {
1355
1685
  title: "Pick color"
1356
1686
  }
1357
1687
  ),
1358
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1688
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1359
1689
  "input",
1360
1690
  {
1361
1691
  ref: colorInputRef,
@@ -1374,18 +1704,18 @@ function expandShorthandHex(hex) {
1374
1704
  }
1375
1705
 
1376
1706
  // src/components/PresetManager.tsx
1377
- var import_react12 = require("react");
1707
+ var import_react13 = require("react");
1378
1708
  var import_react_dom2 = require("react-dom");
1379
- var import_react13 = require("motion/react");
1380
- var import_jsx_runtime10 = require("react/jsx-runtime");
1709
+ var import_react14 = require("motion/react");
1710
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1381
1711
  function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1382
- const [isOpen, setIsOpen] = (0, import_react12.useState)(false);
1383
- const triggerRef = (0, import_react12.useRef)(null);
1384
- const dropdownRef = (0, import_react12.useRef)(null);
1385
- const [pos, setPos] = (0, import_react12.useState)({ top: 0, left: 0, width: 0 });
1712
+ const [isOpen, setIsOpen] = (0, import_react13.useState)(false);
1713
+ const triggerRef = (0, import_react13.useRef)(null);
1714
+ const dropdownRef = (0, import_react13.useRef)(null);
1715
+ const [pos, setPos] = (0, import_react13.useState)({ top: 0, left: 0, width: 0 });
1386
1716
  const hasPresets = presets.length > 0;
1387
1717
  const activePreset = presets.find((p) => p.id === activePresetId);
1388
- const open = (0, import_react12.useCallback)(() => {
1718
+ const open = (0, import_react13.useCallback)(() => {
1389
1719
  if (!hasPresets) return;
1390
1720
  const rect = triggerRef.current?.getBoundingClientRect();
1391
1721
  if (rect) {
@@ -1393,12 +1723,12 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1393
1723
  }
1394
1724
  setIsOpen(true);
1395
1725
  }, [hasPresets]);
1396
- const close = (0, import_react12.useCallback)(() => setIsOpen(false), []);
1397
- const toggle = (0, import_react12.useCallback)(() => {
1726
+ const close = (0, import_react13.useCallback)(() => setIsOpen(false), []);
1727
+ const toggle = (0, import_react13.useCallback)(() => {
1398
1728
  if (isOpen) close();
1399
1729
  else open();
1400
1730
  }, [isOpen, open, close]);
1401
- (0, import_react12.useEffect)(() => {
1731
+ (0, import_react13.useEffect)(() => {
1402
1732
  if (!isOpen) return;
1403
1733
  const handler = (e) => {
1404
1734
  const target = e.target;
@@ -1420,8 +1750,8 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1420
1750
  e.stopPropagation();
1421
1751
  DialStore.deletePreset(panelId, presetId);
1422
1752
  };
1423
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "dialkit-preset-manager", children: [
1424
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1753
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dialkit-preset-manager", children: [
1754
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1425
1755
  "button",
1426
1756
  {
1427
1757
  ref: triggerRef,
@@ -1431,9 +1761,9 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1431
1761
  "data-has-preset": String(!!activePreset),
1432
1762
  "data-disabled": String(!hasPresets),
1433
1763
  children: [
1434
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "dialkit-preset-label", children: activePreset ? activePreset.name : "Version 1" }),
1435
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1436
- import_react13.motion.svg,
1764
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dialkit-preset-label", children: activePreset ? activePreset.name : "Version 1" }),
1765
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1766
+ import_react14.motion.svg,
1437
1767
  {
1438
1768
  className: "dialkit-select-chevron",
1439
1769
  viewBox: "0 0 24 24",
@@ -1444,15 +1774,15 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1444
1774
  strokeLinejoin: "round",
1445
1775
  animate: { rotate: isOpen ? 180 : 0, opacity: hasPresets ? 0.6 : 0.25 },
1446
1776
  transition: { type: "spring", visualDuration: 0.2, bounce: 0.15 },
1447
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M6 9.5L12 15.5L18 9.5" })
1777
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M6 9.5L12 15.5L18 9.5" })
1448
1778
  }
1449
1779
  )
1450
1780
  ]
1451
1781
  }
1452
1782
  ),
1453
1783
  (0, import_react_dom2.createPortal)(
1454
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react13.AnimatePresence, { children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1455
- import_react13.motion.div,
1784
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react14.AnimatePresence, { children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1785
+ import_react14.motion.div,
1456
1786
  {
1457
1787
  ref: dropdownRef,
1458
1788
  className: "dialkit-root dialkit-preset-dropdown",
@@ -1462,35 +1792,35 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1462
1792
  exit: { opacity: 0, y: 4, scale: 0.97, pointerEvents: "none" },
1463
1793
  transition: { type: "spring", visualDuration: 0.15, bounce: 0 },
1464
1794
  children: [
1465
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1795
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1466
1796
  "div",
1467
1797
  {
1468
1798
  className: "dialkit-preset-item",
1469
1799
  "data-active": String(!activePresetId),
1470
1800
  onClick: () => handleSelect(null),
1471
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "dialkit-preset-name", children: "Version 1" })
1801
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dialkit-preset-name", children: "Version 1" })
1472
1802
  }
1473
1803
  ),
1474
- presets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1804
+ presets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1475
1805
  "div",
1476
1806
  {
1477
1807
  className: "dialkit-preset-item",
1478
1808
  "data-active": String(preset.id === activePresetId),
1479
1809
  onClick: () => handleSelect(preset.id),
1480
1810
  children: [
1481
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "dialkit-preset-name", children: preset.name }),
1482
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1811
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dialkit-preset-name", children: preset.name }),
1812
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1483
1813
  "button",
1484
1814
  {
1485
1815
  className: "dialkit-preset-delete",
1486
1816
  onClick: (e) => handleDelete(e, preset.id),
1487
1817
  title: "Delete preset",
1488
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1489
- /* @__PURE__ */ (0, import_jsx_runtime10.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" }),
1490
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M10 11V16" }),
1491
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M14 11V16" }),
1492
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M3.5 6H20.5" }),
1493
- /* @__PURE__ */ (0, import_jsx_runtime10.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" })
1818
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
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" })
1494
1824
  ] })
1495
1825
  }
1496
1826
  )
@@ -1507,11 +1837,11 @@ function PresetManager({ panelId, presets, activePresetId, onAdd }) {
1507
1837
  }
1508
1838
 
1509
1839
  // src/components/Panel.tsx
1510
- var import_jsx_runtime11 = require("react/jsx-runtime");
1511
- function Panel({ panel }) {
1512
- const [copied, setCopied] = (0, import_react14.useState)(false);
1513
- const [isPanelOpen, setIsPanelOpen] = (0, import_react14.useState)(true);
1514
- const values = (0, import_react14.useSyncExternalStore)(
1840
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1841
+ function Panel({ panel, defaultOpen = true }) {
1842
+ const [copied, setCopied] = (0, import_react15.useState)(false);
1843
+ const [isPanelOpen, setIsPanelOpen] = (0, import_react15.useState)(defaultOpen);
1844
+ const values = (0, import_react15.useSyncExternalStore)(
1515
1845
  (cb) => DialStore.subscribe(panel.id, cb),
1516
1846
  () => DialStore.getValues(panel.id),
1517
1847
  () => DialStore.getValues(panel.id)
@@ -1539,7 +1869,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1539
1869
  const value = values[control.path];
1540
1870
  switch (control.type) {
1541
1871
  case "slider":
1542
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1872
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1543
1873
  Slider,
1544
1874
  {
1545
1875
  label: control.label,
@@ -1552,7 +1882,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1552
1882
  control.path
1553
1883
  );
1554
1884
  case "toggle":
1555
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1885
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1556
1886
  Toggle,
1557
1887
  {
1558
1888
  label: control.label,
@@ -1562,7 +1892,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1562
1892
  control.path
1563
1893
  );
1564
1894
  case "spring":
1565
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1895
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1566
1896
  SpringControl,
1567
1897
  {
1568
1898
  panelId: panel.id,
@@ -1573,10 +1903,22 @@ Apply these values as the new defaults in the useDialKit call.`;
1573
1903
  },
1574
1904
  control.path
1575
1905
  );
1906
+ case "transition":
1907
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1908
+ TransitionControl,
1909
+ {
1910
+ panelId: panel.id,
1911
+ path: control.path,
1912
+ label: control.label,
1913
+ value,
1914
+ onChange: (v) => DialStore.updateValue(panel.id, control.path, v)
1915
+ },
1916
+ control.path
1917
+ );
1576
1918
  case "folder":
1577
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Folder, { title: control.label, defaultOpen: control.defaultOpen ?? true, children: control.children?.map(renderControl) }, control.path);
1919
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Folder, { title: control.label, defaultOpen: control.defaultOpen ?? true, children: control.children?.map(renderControl) }, control.path);
1578
1920
  case "text":
1579
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1921
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1580
1922
  TextControl,
1581
1923
  {
1582
1924
  label: control.label,
@@ -1587,7 +1929,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1587
1929
  control.path
1588
1930
  );
1589
1931
  case "select":
1590
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1932
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1591
1933
  SelectControl,
1592
1934
  {
1593
1935
  label: control.label,
@@ -1598,7 +1940,7 @@ Apply these values as the new defaults in the useDialKit call.`;
1598
1940
  control.path
1599
1941
  );
1600
1942
  case "color":
1601
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1943
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1602
1944
  ColorControl,
1603
1945
  {
1604
1946
  label: control.label,
@@ -1607,54 +1949,43 @@ Apply these values as the new defaults in the useDialKit call.`;
1607
1949
  },
1608
1950
  control.path
1609
1951
  );
1952
+ case "action":
1953
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1954
+ "button",
1955
+ {
1956
+ className: "dialkit-button",
1957
+ onClick: () => DialStore.triggerAction(panel.id, control.path),
1958
+ children: control.label
1959
+ },
1960
+ control.path
1961
+ );
1610
1962
  default:
1611
1963
  return null;
1612
1964
  }
1613
1965
  };
1614
1966
  const renderControls = () => {
1615
- const result = [];
1616
- let i = 0;
1617
- while (i < panel.controls.length) {
1618
- const control = panel.controls[i];
1619
- if (control.type === "action") {
1620
- result.push(
1621
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1622
- "button",
1623
- {
1624
- className: "dialkit-button",
1625
- onClick: () => DialStore.triggerAction(panel.id, control.path),
1626
- children: control.label
1627
- },
1628
- control.path
1629
- )
1630
- );
1631
- } else {
1632
- result.push(renderControl(control));
1633
- }
1634
- i++;
1635
- }
1636
- return result;
1967
+ return panel.controls.map(renderControl);
1637
1968
  };
1638
1969
  const iconTransition = { type: "spring", visualDuration: 0.4, bounce: 0.1 };
1639
- const toolbar = /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
1640
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1641
- import_react15.motion.button,
1970
+ const toolbar = /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1971
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1972
+ import_react16.motion.button,
1642
1973
  {
1643
1974
  className: "dialkit-toolbar-add",
1644
1975
  onClick: handleAddPreset,
1645
1976
  title: "Add preset",
1646
1977
  whileTap: { scale: 0.9 },
1647
1978
  transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
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: [
1649
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M4 6H20" }),
1650
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M4 12H10" }),
1651
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M15 15L21 15" }),
1652
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M18 12V18" }),
1653
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M4 18H10" })
1979
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
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" })
1654
1985
  ] })
1655
1986
  }
1656
1987
  ),
1657
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1988
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1658
1989
  PresetManager,
1659
1990
  {
1660
1991
  panelId: panel.id,
@@ -1663,8 +1994,8 @@ Apply these values as the new defaults in the useDialKit call.`;
1663
1994
  onAdd: handleAddPreset
1664
1995
  }
1665
1996
  ),
1666
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1667
- import_react15.motion.button,
1997
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1998
+ import_react16.motion.button,
1668
1999
  {
1669
2000
  className: "dialkit-toolbar-copy",
1670
2001
  onClick: handleCopy,
@@ -1672,8 +2003,8 @@ Apply these values as the new defaults in the useDialKit call.`;
1672
2003
  whileTap: { scale: 0.95 },
1673
2004
  transition: { type: "spring", visualDuration: 0.15, bounce: 0.3 },
1674
2005
  children: [
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)(
1676
- import_react15.motion.svg,
2006
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dialkit-toolbar-copy-icon-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react16.AnimatePresence, { initial: false, mode: "popLayout", children: copied ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2007
+ import_react16.motion.svg,
1677
2008
  {
1678
2009
  className: "dialkit-toolbar-copy-icon",
1679
2010
  viewBox: "0 0 24 24",
@@ -1686,11 +2017,11 @@ Apply these values as the new defaults in the useDialKit call.`;
1686
2017
  animate: { scale: 1, opacity: 1, filter: "blur(0px)" },
1687
2018
  exit: { scale: 0.5, opacity: 0, filter: "blur(4px)" },
1688
2019
  transition: { type: "spring", visualDuration: 0.3, bounce: 0.2 },
1689
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M5 12.75L10 19L19 5" })
2020
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M5 12.75L10 19L19 5" })
1690
2021
  },
1691
2022
  "check"
1692
- ) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1693
- import_react15.motion.svg,
2023
+ ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2024
+ import_react16.motion.svg,
1694
2025
  {
1695
2026
  className: "dialkit-toolbar-copy-icon",
1696
2027
  viewBox: "0 0 24 24",
@@ -1700,9 +2031,9 @@ Apply these values as the new defaults in the useDialKit call.`;
1700
2031
  exit: { scale: 0.5, opacity: 0, filter: "blur(4px)" },
1701
2032
  transition: { type: "spring", visualDuration: 0.3, bounce: 0.2 },
1702
2033
  children: [
1703
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M8 6C8 4.34315 9.34315 3 11 3H13C14.6569 3 16 4.34315 16 6V7H8V6Z", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }),
1704
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("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" }),
1705
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("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" })
2034
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M8 6C8 4.34315 9.34315 3 11 3H13C14.6569 3 16 4.34315 16 6V7H8V6Z", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }),
2035
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("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" }),
2036
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("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" })
1706
2037
  ]
1707
2038
  },
1708
2039
  "clipboard"
@@ -1712,15 +2043,15 @@ Apply these values as the new defaults in the useDialKit call.`;
1712
2043
  }
1713
2044
  )
1714
2045
  ] });
1715
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "dialkit-panel-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Folder, { title: panel.name, defaultOpen: true, isRoot: true, onOpenChange: setIsPanelOpen, toolbar, children: renderControls() }) });
2046
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dialkit-panel-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Folder, { title: panel.name, defaultOpen, isRoot: true, onOpenChange: setIsPanelOpen, toolbar, children: renderControls() }) });
1716
2047
  }
1717
2048
 
1718
2049
  // src/components/DialRoot.tsx
1719
- var import_jsx_runtime12 = require("react/jsx-runtime");
1720
- function DialRoot({ position = "top-right" }) {
1721
- const [panels, setPanels] = (0, import_react16.useState)([]);
1722
- const [mounted, setMounted] = (0, import_react16.useState)(false);
1723
- (0, import_react16.useEffect)(() => {
2050
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2051
+ function DialRoot({ position = "top-right", defaultOpen = true }) {
2052
+ const [panels, setPanels] = (0, import_react17.useState)([]);
2053
+ const [mounted, setMounted] = (0, import_react17.useState)(false);
2054
+ (0, import_react17.useEffect)(() => {
1724
2055
  setMounted(true);
1725
2056
  setPanels(DialStore.getPanels());
1726
2057
  const unsubscribe = DialStore.subscribeGlobal(() => {
@@ -1734,14 +2065,14 @@ function DialRoot({ position = "top-right" }) {
1734
2065
  if (panels.length === 0) {
1735
2066
  return null;
1736
2067
  }
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)) }) });
2068
+ const content = /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dialkit-root", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dialkit-panel", "data-position": position, children: panels.map((panel) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Panel, { panel, defaultOpen }, panel.id)) }) });
1738
2069
  return (0, import_react_dom3.createPortal)(content, document.body);
1739
2070
  }
1740
2071
 
1741
2072
  // src/components/ButtonGroup.tsx
1742
- var import_jsx_runtime13 = require("react/jsx-runtime");
2073
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1743
2074
  function ButtonGroup({ buttons }) {
1744
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dialkit-button-group", children: buttons.map((button, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2075
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "dialkit-button-group", children: buttons.map((button, index) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1745
2076
  "button",
1746
2077
  {
1747
2078
  className: "dialkit-button",
@@ -1757,6 +2088,7 @@ function ButtonGroup({ buttons }) {
1757
2088
  ColorControl,
1758
2089
  DialRoot,
1759
2090
  DialStore,
2091
+ EasingVisualization,
1760
2092
  Folder,
1761
2093
  PresetManager,
1762
2094
  SelectControl,
@@ -1765,6 +2097,7 @@ function ButtonGroup({ buttons }) {
1765
2097
  SpringVisualization,
1766
2098
  TextControl,
1767
2099
  Toggle,
2100
+ TransitionControl,
1768
2101
  useDialKit
1769
2102
  });
1770
2103
  //# sourceMappingURL=index.cjs.map