dialkit 1.2.1 → 1.4.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.
Files changed (88) hide show
  1. package/README.md +653 -6
  2. package/dist/dropdown-position.d.ts +15 -0
  3. package/dist/dropdown-position.js +22 -0
  4. package/dist/dropdown-position.js.map +1 -0
  5. package/dist/icons.d.ts +4 -1
  6. package/dist/icons.js +13 -0
  7. package/dist/icons.js.map +1 -1
  8. package/dist/index.cjs +3796 -768
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +315 -10
  11. package/dist/index.d.ts +315 -10
  12. package/dist/index.js +3733 -711
  13. package/dist/index.js.map +1 -1
  14. package/dist/panel-drag.d.ts +19 -0
  15. package/dist/panel-drag.js +72 -0
  16. package/dist/panel-drag.js.map +1 -0
  17. package/dist/solid/index.d.ts +264 -5
  18. package/dist/solid/index.js +5277 -1632
  19. package/dist/solid/index.js.map +1 -1
  20. package/dist/store/index.cjs +329 -57
  21. package/dist/store/index.cjs.map +1 -1
  22. package/dist/store/index.d.cts +43 -4
  23. package/dist/store/index.d.ts +43 -4
  24. package/dist/store/index.js +321 -56
  25. package/dist/store/index.js.map +1 -1
  26. package/dist/styles.css +809 -7
  27. package/dist/svelte/components/ControlRenderer.svelte +5 -2
  28. package/dist/svelte/components/ControlRenderer.svelte.d.ts +2 -0
  29. package/dist/svelte/components/ControlRenderer.svelte.d.ts.map +1 -1
  30. package/dist/svelte/components/DialRoot.svelte +218 -16
  31. package/dist/svelte/components/DialRoot.svelte.d.ts +1 -0
  32. package/dist/svelte/components/DialRoot.svelte.d.ts.map +1 -1
  33. package/dist/svelte/components/Folder.svelte +24 -13
  34. package/dist/svelte/components/Folder.svelte.d.ts +1 -0
  35. package/dist/svelte/components/Folder.svelte.d.ts.map +1 -1
  36. package/dist/svelte/components/Panel.svelte +104 -71
  37. package/dist/svelte/components/Panel.svelte.d.ts +4 -0
  38. package/dist/svelte/components/Panel.svelte.d.ts.map +1 -1
  39. package/dist/svelte/components/PresetManager.svelte +5 -5
  40. package/dist/svelte/components/PresetManager.svelte.d.ts.map +1 -1
  41. package/dist/svelte/components/SelectControl.svelte +6 -14
  42. package/dist/svelte/components/SelectControl.svelte.d.ts.map +1 -1
  43. package/dist/svelte/components/Timeline/ClipPopover.svelte +206 -0
  44. package/dist/svelte/components/Timeline/ClipPopover.svelte.d.ts +26 -0
  45. package/dist/svelte/components/Timeline/ClipPopover.svelte.d.ts.map +1 -0
  46. package/dist/svelte/components/Timeline/DialTimeline.svelte +76 -0
  47. package/dist/svelte/components/Timeline/DialTimeline.svelte.d.ts +13 -0
  48. package/dist/svelte/components/Timeline/DialTimeline.svelte.d.ts.map +1 -0
  49. package/dist/svelte/components/Timeline/TimelineClip.svelte +233 -0
  50. package/dist/svelte/components/Timeline/TimelineClip.svelte.d.ts +24 -0
  51. package/dist/svelte/components/Timeline/TimelineClip.svelte.d.ts.map +1 -0
  52. package/dist/svelte/components/Timeline/TimelineSection.svelte +756 -0
  53. package/dist/svelte/components/Timeline/TimelineSection.svelte.d.ts +12 -0
  54. package/dist/svelte/components/Timeline/TimelineSection.svelte.d.ts.map +1 -0
  55. package/dist/svelte/components/Timeline/TimelineToggleButton.svelte +25 -0
  56. package/dist/svelte/components/Timeline/TimelineToggleButton.svelte.d.ts +4 -0
  57. package/dist/svelte/components/Timeline/TimelineToggleButton.svelte.d.ts.map +1 -0
  58. package/dist/svelte/components/TransitionControl.svelte +26 -11
  59. package/dist/svelte/components/TransitionControl.svelte.d.ts +9 -0
  60. package/dist/svelte/components/TransitionControl.svelte.d.ts.map +1 -1
  61. package/dist/svelte/createDialKit.svelte.d.ts +11 -1
  62. package/dist/svelte/createDialKit.svelte.d.ts.map +1 -1
  63. package/dist/svelte/createDialKit.svelte.js +61 -34
  64. package/dist/svelte/createDialTimeline.svelte.d.ts +4 -0
  65. package/dist/svelte/createDialTimeline.svelte.d.ts.map +1 -0
  66. package/dist/svelte/createDialTimeline.svelte.js +73 -0
  67. package/dist/svelte/index.d.ts +7 -3
  68. package/dist/svelte/index.d.ts.map +1 -1
  69. package/dist/svelte/index.js +4 -1
  70. package/dist/svelte/theme-css.d.ts +1 -1
  71. package/dist/svelte/theme-css.d.ts.map +1 -1
  72. package/dist/svelte/theme-css.js +809 -7
  73. package/dist/timeline/index.cjs +1288 -0
  74. package/dist/timeline/index.cjs.map +1 -0
  75. package/dist/timeline/index.d.cts +443 -0
  76. package/dist/timeline/index.d.ts +443 -0
  77. package/dist/timeline/index.js +1233 -0
  78. package/dist/timeline/index.js.map +1 -0
  79. package/dist/vue/index.d.ts +325 -12
  80. package/dist/vue/index.js +3226 -280
  81. package/dist/vue/index.js.map +1 -1
  82. package/package.json +23 -13
  83. package/dist/solid/index.cjs +0 -3079
  84. package/dist/solid/index.cjs.map +0 -1
  85. package/dist/solid/index.d.cts +0 -258
  86. package/dist/vue/index.cjs +0 -3056
  87. package/dist/vue/index.cjs.map +0 -1
  88. package/dist/vue/index.d.cts +0 -675
@@ -1,8 +1,107 @@
1
1
  // src/store/DialStore.ts
2
2
  var EMPTY_VALUES = Object.freeze({});
3
+ function resolveDialValues(config, flatValues) {
4
+ return resolveConfigValues(config, flatValues, "");
5
+ }
6
+ function flattenDialValueUpdates(config, updates) {
7
+ const values = {};
8
+ if (typeof updates === "object" && updates !== null) {
9
+ flattenConfigUpdates(config, updates, "", values);
10
+ }
11
+ return values;
12
+ }
13
+ function resolveConfigValues(config, flatValues, prefix) {
14
+ const result = {};
15
+ for (const [key, configValue] of Object.entries(config)) {
16
+ if (key === "_collapsed") continue;
17
+ const path = prefix ? `${prefix}.${key}` : key;
18
+ if (Array.isArray(configValue) && configValue.length <= 4 && typeof configValue[0] === "number") {
19
+ result[key] = flatValues[path] ?? configValue[0];
20
+ } else if (typeof configValue === "number" || typeof configValue === "boolean" || typeof configValue === "string") {
21
+ result[key] = flatValues[path] ?? configValue;
22
+ } else if (isSpringConfigValue(configValue) || isEasingConfigValue(configValue)) {
23
+ result[key] = flatValues[path] ?? configValue;
24
+ } else if (isActionConfigValue(configValue)) {
25
+ result[key] = flatValues[path] ?? configValue;
26
+ } else if (isSelectConfigValue(configValue)) {
27
+ const defaultValue = configValue.default ?? getFirstOptionValue(configValue.options);
28
+ result[key] = flatValues[path] ?? defaultValue;
29
+ } else if (isColorConfigValue(configValue)) {
30
+ result[key] = flatValues[path] ?? configValue.default ?? "#000000";
31
+ } else if (isTextConfigValue(configValue)) {
32
+ result[key] = flatValues[path] ?? configValue.default ?? "";
33
+ } else if (typeof configValue === "object" && configValue !== null) {
34
+ result[key] = resolveConfigValues(configValue, flatValues, path);
35
+ }
36
+ }
37
+ return result;
38
+ }
39
+ function flattenConfigUpdates(config, updates, prefix, values) {
40
+ for (const [key, configValue] of Object.entries(config)) {
41
+ if (key === "_collapsed" || !(key in updates)) continue;
42
+ const nextValue = updates[key];
43
+ if (nextValue === void 0) continue;
44
+ const path = prefix ? `${prefix}.${key}` : key;
45
+ if (isActionConfigValue(configValue)) {
46
+ continue;
47
+ }
48
+ if (isLeafConfigValue(configValue)) {
49
+ values[path] = nextValue;
50
+ continue;
51
+ }
52
+ if (typeof configValue === "object" && configValue !== null && typeof nextValue === "object" && nextValue !== null && !Array.isArray(nextValue)) {
53
+ flattenConfigUpdates(configValue, nextValue, path, values);
54
+ }
55
+ }
56
+ }
57
+ function isLeafConfigValue(value) {
58
+ return Array.isArray(value) && value.length <= 4 && typeof value[0] === "number" || typeof value === "number" || typeof value === "boolean" || typeof value === "string" || isSpringConfigValue(value) || isEasingConfigValue(value) || isActionConfigValue(value) || isSelectConfigValue(value) || isColorConfigValue(value) || isTextConfigValue(value);
59
+ }
60
+ function hasType(value, type) {
61
+ return typeof value === "object" && value !== null && "type" in value && value.type === type;
62
+ }
63
+ function isSpringConfigValue(value) {
64
+ return hasType(value, "spring");
65
+ }
66
+ function isEasingConfigValue(value) {
67
+ return hasType(value, "easing");
68
+ }
69
+ function isHexColor(value) {
70
+ return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(value);
71
+ }
72
+ function formatLabel(key) {
73
+ return key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()).trim();
74
+ }
75
+ function inferStep(min, max) {
76
+ const range = max - min;
77
+ if (range <= 1) return 0.01;
78
+ if (range <= 10) return 0.1;
79
+ if (range <= 100) return 1;
80
+ return 10;
81
+ }
82
+ function isActionConfigValue(value) {
83
+ return hasType(value, "action");
84
+ }
85
+ function isSelectConfigValue(value) {
86
+ return hasType(value, "select") && "options" in value && Array.isArray(value.options);
87
+ }
88
+ function isColorConfigValue(value) {
89
+ return hasType(value, "color");
90
+ }
91
+ function isTextConfigValue(value) {
92
+ return hasType(value, "text");
93
+ }
94
+ function getFirstOptionValue(options) {
95
+ const first = options[0];
96
+ if (first === void 0) return "";
97
+ return typeof first === "string" ? first : first.value;
98
+ }
3
99
  var DialStoreClass = class {
4
100
  constructor() {
5
101
  this.panels = /* @__PURE__ */ new Map();
102
+ this.panelsSnapshot = [];
103
+ this.standardPanelsSnapshot = [];
104
+ this.timelinePanelsSnapshot = [];
6
105
  this.listeners = /* @__PURE__ */ new Map();
7
106
  this.globalListeners = /* @__PURE__ */ new Set();
8
107
  this.snapshots = /* @__PURE__ */ new Map();
@@ -10,87 +109,144 @@ var DialStoreClass = class {
10
109
  this.presets = /* @__PURE__ */ new Map();
11
110
  this.activePreset = /* @__PURE__ */ new Map();
12
111
  this.baseValues = /* @__PURE__ */ new Map();
13
- }
14
- registerPanel(id, name, config, shortcuts) {
112
+ this.defaultValues = /* @__PURE__ */ new Map();
113
+ this.registrationCounts = /* @__PURE__ */ new Map();
114
+ this.retainedPanels = /* @__PURE__ */ new Set();
115
+ this.persistConfigs = /* @__PURE__ */ new Map();
116
+ }
117
+ registerPanel(id, name, config, shortcuts, options = {}) {
118
+ const existingPanel = this.panels.get(id);
119
+ if (existingPanel && existingPanel.kind !== options.kind) {
120
+ console.warn(
121
+ `[dialkit] Panel id "${id}" cannot be shared by a timeline and a standard panel; the most recent registration controls where it renders.`
122
+ );
123
+ }
124
+ this.configurePanelRetention(id, options);
125
+ this.registrationCounts.set(id, (this.registrationCounts.get(id) ?? 0) + 1);
15
126
  const controls = this.parseConfig(config, "", shortcuts);
16
- const values = this.flattenValues(config, "");
17
- this.initTransitionModes(config, "", values);
18
- this.panels.set(id, { id, name, controls, values, shortcuts: shortcuts ?? {} });
127
+ const controlsByPath = this.mapControlsByPath(controls);
128
+ const defaultValues = this.flattenValues(config, "");
129
+ this.initTransitionModes(config, "", defaultValues);
130
+ const persisted = this.loadPersistedPanel(id);
131
+ const previousValues = this.panels.get(id)?.values ?? this.snapshots.get(id) ?? persisted?.values ?? {};
132
+ const values = this.reconcileValues(defaultValues, previousValues, controlsByPath);
133
+ const previousBaseValues = this.baseValues.get(id) ?? persisted?.baseValues ?? persisted?.values ?? {};
134
+ const baseValues = this.reconcileValues(defaultValues, previousBaseValues, controlsByPath);
135
+ this.panels.set(id, { id, name, controls, values, shortcuts: shortcuts ?? {}, kind: options.kind });
19
136
  this.snapshots.set(id, { ...values });
20
- this.baseValues.set(id, { ...values });
137
+ this.baseValues.set(id, baseValues);
138
+ this.defaultValues.set(id, { ...defaultValues });
139
+ const existingPresets = this.presets.get(id) ?? persisted?.presets;
140
+ if (existingPresets) {
141
+ this.presets.set(id, this.reconcilePresets(existingPresets, defaultValues, controlsByPath));
142
+ }
143
+ if (!this.activePreset.has(id) && persisted?.activePresetId !== void 0) {
144
+ this.activePreset.set(id, persisted.activePresetId);
145
+ }
146
+ this.persistPanel(id);
147
+ this.notify(id);
21
148
  this.notifyGlobal();
22
149
  }
23
- updatePanel(id, name, config, shortcuts) {
150
+ updatePanel(id, name, config, shortcuts, options = {}) {
151
+ this.configurePanelRetention(id, options);
24
152
  const existing = this.panels.get(id);
25
153
  if (!existing) {
26
- this.registerPanel(id, name, config, shortcuts);
154
+ this.registerPanel(id, name, config, shortcuts, options);
27
155
  return;
28
156
  }
29
157
  const controls = this.parseConfig(config, "", shortcuts);
30
158
  const controlsByPath = this.mapControlsByPath(controls);
31
159
  const defaultValues = this.flattenValues(config, "");
32
- const nextValues = {};
33
- for (const [path, defaultValue] of Object.entries(defaultValues)) {
34
- nextValues[path] = this.normalizePreservedValue(
35
- existing.values[path],
36
- defaultValue,
37
- controlsByPath.get(path)
38
- );
39
- }
40
- this.initTransitionModes(config, "", nextValues);
41
- for (const [path, mode] of Object.entries(existing.values)) {
42
- if (!path.endsWith(".__mode")) {
43
- continue;
44
- }
45
- const transitionPath = path.slice(0, -"__mode".length - 1);
46
- const transitionControl = controlsByPath.get(transitionPath);
47
- if (transitionControl?.type === "transition") {
48
- nextValues[path] = mode;
49
- }
50
- }
51
- const nextPanel = { id, name, controls, values: nextValues, shortcuts: shortcuts ?? existing.shortcuts };
160
+ this.initTransitionModes(config, "", defaultValues);
161
+ const nextValues = this.reconcileValues(defaultValues, existing.values, controlsByPath);
162
+ const nextPanel = { id, name, controls, values: nextValues, shortcuts: shortcuts ?? existing.shortcuts, kind: options.kind ?? existing.kind };
52
163
  this.panels.set(id, nextPanel);
53
164
  this.snapshots.set(id, { ...nextValues });
54
165
  const previousBaseValues = this.baseValues.get(id) ?? {};
55
- const nextBaseValues = {};
56
- for (const [path, defaultValue] of Object.entries(defaultValues)) {
57
- nextBaseValues[path] = this.normalizePreservedValue(
58
- previousBaseValues[path],
59
- defaultValue,
60
- controlsByPath.get(path)
61
- );
62
- }
166
+ const nextBaseValues = this.reconcileValues(defaultValues, previousBaseValues, controlsByPath);
63
167
  for (const [path, value] of Object.entries(nextValues)) {
64
168
  if (path.endsWith(".__mode")) {
65
169
  nextBaseValues[path] = value;
66
170
  }
67
171
  }
68
172
  this.baseValues.set(id, nextBaseValues);
173
+ this.defaultValues.set(id, { ...defaultValues });
174
+ this.presets.set(id, this.reconcilePresets(this.presets.get(id) ?? [], defaultValues, controlsByPath));
175
+ this.persistPanel(id);
69
176
  this.notify(id);
70
177
  this.notifyGlobal();
71
178
  }
72
179
  unregisterPanel(id) {
180
+ const nextCount = (this.registrationCounts.get(id) ?? 1) - 1;
181
+ if (nextCount > 0) {
182
+ this.registrationCounts.set(id, nextCount);
183
+ return;
184
+ }
185
+ this.registrationCounts.delete(id);
73
186
  this.panels.delete(id);
74
- this.listeners.delete(id);
75
- this.snapshots.delete(id);
76
- this.actionListeners.delete(id);
77
- this.baseValues.delete(id);
187
+ if (this.listeners.get(id)?.size === 0) this.listeners.delete(id);
188
+ if (this.actionListeners.get(id)?.size === 0) this.actionListeners.delete(id);
189
+ if (!this.retainedPanels.has(id)) {
190
+ this.snapshots.delete(id);
191
+ this.baseValues.delete(id);
192
+ this.defaultValues.delete(id);
193
+ this.presets.delete(id);
194
+ this.activePreset.delete(id);
195
+ this.persistConfigs.delete(id);
196
+ }
78
197
  this.notifyGlobal();
79
198
  }
80
199
  updateValue(panelId, path, value) {
200
+ this.updateValues(panelId, { [path]: value });
201
+ }
202
+ updateValues(panelId, updates) {
81
203
  const panel = this.panels.get(panelId);
82
204
  if (!panel) return;
83
- panel.values[path] = value;
205
+ const validUpdates = {};
206
+ for (const [path, value] of Object.entries(updates)) {
207
+ if (!Object.prototype.hasOwnProperty.call(panel.values, path)) {
208
+ continue;
209
+ }
210
+ const control = this.findControlByPath(panel.controls, path);
211
+ if (control?.type === "action") {
212
+ continue;
213
+ }
214
+ panel.values[path] = value;
215
+ validUpdates[path] = value;
216
+ }
217
+ if (Object.keys(validUpdates).length === 0) {
218
+ return;
219
+ }
84
220
  const activeId = this.activePreset.get(panelId);
85
221
  if (activeId) {
86
222
  const presets = this.presets.get(panelId) ?? [];
87
223
  const preset = presets.find((p) => p.id === activeId);
88
- if (preset) preset.values[path] = value;
224
+ if (preset) {
225
+ for (const [path, value] of Object.entries(validUpdates)) {
226
+ preset.values[path] = value;
227
+ }
228
+ }
89
229
  } else {
90
230
  const base = this.baseValues.get(panelId);
91
- if (base) base[path] = value;
231
+ if (base) {
232
+ for (const [path, value] of Object.entries(validUpdates)) {
233
+ base[path] = value;
234
+ }
235
+ }
92
236
  }
93
237
  this.snapshots.set(panelId, { ...panel.values });
238
+ this.persistPanel(panelId);
239
+ this.notify(panelId);
240
+ }
241
+ resetValues(panelId) {
242
+ const panel = this.panels.get(panelId);
243
+ const defaults = this.defaultValues.get(panelId);
244
+ if (!panel || !defaults) return;
245
+ panel.values = { ...defaults };
246
+ this.snapshots.set(panelId, { ...panel.values });
247
+ this.baseValues.set(panelId, { ...defaults });
248
+ this.activePreset.set(panelId, null);
249
+ this.persistPanel(panelId);
94
250
  this.notify(panelId);
95
251
  }
96
252
  updateSpringMode(panelId, path, mode) {
@@ -106,6 +262,7 @@ var DialStoreClass = class {
106
262
  if (!panel) return;
107
263
  panel.values[`${path}.__mode`] = mode;
108
264
  this.snapshots.set(panelId, { ...panel.values });
265
+ this.persistPanel(panelId);
109
266
  this.notify(panelId);
110
267
  }
111
268
  getTransitionMode(panelId, path) {
@@ -120,8 +277,10 @@ var DialStoreClass = class {
120
277
  getValues(panelId) {
121
278
  return this.snapshots.get(panelId) ?? EMPTY_VALUES;
122
279
  }
123
- getPanels() {
124
- return Array.from(this.panels.values());
280
+ getPanels(kind) {
281
+ if (kind === "panel") return this.standardPanelsSnapshot;
282
+ if (kind === "timeline") return this.timelinePanelsSnapshot;
283
+ return this.panelsSnapshot;
125
284
  }
126
285
  getPanel(id) {
127
286
  return this.panels.get(id);
@@ -132,7 +291,11 @@ var DialStoreClass = class {
132
291
  }
133
292
  this.listeners.get(panelId).add(listener);
134
293
  return () => {
135
- this.listeners.get(panelId)?.delete(listener);
294
+ const listeners = this.listeners.get(panelId);
295
+ listeners?.delete(listener);
296
+ if (listeners?.size === 0 && !this.panels.has(panelId)) {
297
+ this.listeners.delete(panelId);
298
+ }
136
299
  };
137
300
  }
138
301
  subscribeGlobal(listener) {
@@ -145,7 +308,11 @@ var DialStoreClass = class {
145
308
  }
146
309
  this.actionListeners.get(panelId).add(listener);
147
310
  return () => {
148
- this.actionListeners.get(panelId)?.delete(listener);
311
+ const listeners = this.actionListeners.get(panelId);
312
+ listeners?.delete(listener);
313
+ if (listeners?.size === 0 && !this.panels.has(panelId)) {
314
+ this.actionListeners.delete(panelId);
315
+ }
149
316
  };
150
317
  }
151
318
  triggerAction(panelId, path) {
@@ -164,6 +331,7 @@ var DialStoreClass = class {
164
331
  this.presets.set(panelId, [...existing, preset]);
165
332
  this.activePreset.set(panelId, id);
166
333
  this.snapshots.set(panelId, { ...panel.values });
334
+ this.persistPanel(panelId);
167
335
  this.notify(panelId);
168
336
  return id;
169
337
  }
@@ -176,6 +344,7 @@ var DialStoreClass = class {
176
344
  panel.values = { ...preset.values };
177
345
  this.snapshots.set(panelId, { ...panel.values });
178
346
  this.activePreset.set(panelId, presetId);
347
+ this.persistPanel(panelId);
179
348
  this.notify(panelId);
180
349
  }
181
350
  deletePreset(panelId, presetId) {
@@ -188,6 +357,7 @@ var DialStoreClass = class {
188
357
  if (panel) {
189
358
  this.snapshots.set(panelId, { ...panel.values });
190
359
  }
360
+ this.persistPanel(panelId);
191
361
  this.notify(panelId);
192
362
  }
193
363
  getPresets(panelId) {
@@ -204,6 +374,7 @@ var DialStoreClass = class {
204
374
  this.snapshots.set(panelId, { ...panel.values });
205
375
  }
206
376
  this.activePreset.set(panelId, null);
377
+ this.persistPanel(panelId);
207
378
  this.notify(panelId);
208
379
  }
209
380
  resolveShortcutTarget(key, modifier) {
@@ -234,6 +405,94 @@ var DialStoreClass = class {
234
405
  }
235
406
  return results;
236
407
  }
408
+ configurePanelRetention(id, options) {
409
+ if (options.retainOnUnmount) {
410
+ this.retainedPanels.add(id);
411
+ }
412
+ const persistConfig = this.normalizePersistConfig(id, options.persist);
413
+ if (persistConfig) {
414
+ this.persistConfigs.set(id, persistConfig);
415
+ this.retainedPanels.add(id);
416
+ }
417
+ }
418
+ reconcileValues(defaultValues, previousValues, controlsByPath) {
419
+ const nextValues = {};
420
+ for (const [path, defaultValue] of Object.entries(defaultValues)) {
421
+ if (path.endsWith(".__mode")) {
422
+ const transitionPath = path.slice(0, -".__mode".length);
423
+ const transitionControl = controlsByPath.get(transitionPath);
424
+ nextValues[path] = transitionControl?.type === "transition" && previousValues[path] !== void 0 ? previousValues[path] : defaultValue;
425
+ continue;
426
+ }
427
+ nextValues[path] = this.normalizePreservedValue(
428
+ previousValues[path],
429
+ defaultValue,
430
+ controlsByPath.get(path)
431
+ );
432
+ }
433
+ return nextValues;
434
+ }
435
+ reconcilePresets(presets, defaultValues, controlsByPath) {
436
+ return presets.map((preset) => ({
437
+ ...preset,
438
+ values: this.reconcileValues(defaultValues, preset.values, controlsByPath)
439
+ }));
440
+ }
441
+ normalizePersistConfig(id, persist) {
442
+ if (!persist) return null;
443
+ const options = typeof persist === "object" ? persist : {};
444
+ return {
445
+ key: options.key ?? `dialkit:${id}`,
446
+ storage: options.storage ?? "localStorage",
447
+ presets: options.presets ?? true
448
+ };
449
+ }
450
+ loadPersistedPanel(id) {
451
+ const config = this.persistConfigs.get(id);
452
+ if (!config) return null;
453
+ const storage = this.getStorage(config.storage);
454
+ if (!storage) return null;
455
+ try {
456
+ const raw = storage.getItem(config.key);
457
+ if (!raw) return null;
458
+ const parsed = JSON.parse(raw);
459
+ if (parsed?.version !== 1 || typeof parsed !== "object") return null;
460
+ return parsed;
461
+ } catch {
462
+ return null;
463
+ }
464
+ }
465
+ persistPanel(id) {
466
+ const config = this.persistConfigs.get(id);
467
+ if (!config) return;
468
+ const storage = this.getStorage(config.storage);
469
+ if (!storage) return;
470
+ const values = this.snapshots.get(id) ?? this.panels.get(id)?.values;
471
+ if (!values) return;
472
+ const state = {
473
+ version: 1,
474
+ values,
475
+ baseValues: this.baseValues.get(id) ?? values,
476
+ activePresetId: this.activePreset.get(id) ?? null
477
+ };
478
+ if (config.presets) {
479
+ state.presets = this.presets.get(id) ?? [];
480
+ }
481
+ try {
482
+ storage.setItem(config.key, JSON.stringify(state));
483
+ } catch {
484
+ }
485
+ }
486
+ getStorage(kind) {
487
+ if (typeof globalThis === "undefined" || !("window" in globalThis)) {
488
+ return null;
489
+ }
490
+ try {
491
+ return kind === "sessionStorage" ? globalThis.window?.sessionStorage ?? null : globalThis.window?.localStorage ?? null;
492
+ } catch {
493
+ return null;
494
+ }
495
+ }
237
496
  findControlByPath(controls, path) {
238
497
  for (const control of controls) {
239
498
  if (control.path === path) return control;
@@ -248,6 +507,9 @@ var DialStoreClass = class {
248
507
  this.listeners.get(panelId)?.forEach((fn) => fn());
249
508
  }
250
509
  notifyGlobal() {
510
+ this.panelsSnapshot = Array.from(this.panels.values());
511
+ this.standardPanelsSnapshot = this.panelsSnapshot.filter((panel) => panel.kind !== "timeline");
512
+ this.timelinePanelsSnapshot = this.panelsSnapshot.filter((panel) => panel.kind === "timeline");
251
513
  this.globalListeners.forEach((fn) => fn());
252
514
  }
253
515
  initTransitionModes(config, prefix, values) {
@@ -363,10 +625,10 @@ var DialStoreClass = class {
363
625
  return typeof value === "object" && value !== null && "type" in value && value.type === "text";
364
626
  }
365
627
  isHexColor(value) {
366
- return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(value);
628
+ return isHexColor(value);
367
629
  }
368
630
  formatLabel(key) {
369
- return key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()).trim();
631
+ return formatLabel(key);
370
632
  }
371
633
  inferRange(value) {
372
634
  if (value >= 0 && value <= 1) {
@@ -382,11 +644,7 @@ var DialStoreClass = class {
382
644
  }
383
645
  }
384
646
  inferStep(min, max) {
385
- const range = max - min;
386
- if (range <= 1) return 0.01;
387
- if (range <= 10) return 0.1;
388
- if (range <= 100) return 1;
389
- return 10;
647
+ return inferStep(min, max);
390
648
  }
391
649
  normalizePreservedValue(existingValue, defaultValue, control) {
392
650
  if (existingValue === void 0 || !control) {
@@ -458,8 +716,15 @@ var DialStoreClass = class {
458
716
  return map;
459
717
  }
460
718
  };
461
- var DialStore = new DialStoreClass();
719
+ var DialStore = /* @__PURE__ */ new DialStoreClass();
462
720
  export {
463
- DialStore
721
+ DialStore,
722
+ flattenDialValueUpdates,
723
+ formatLabel,
724
+ inferStep,
725
+ isEasingConfigValue,
726
+ isHexColor,
727
+ isSpringConfigValue,
728
+ resolveDialValues
464
729
  };
465
730
  //# sourceMappingURL=index.js.map