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
@@ -20,13 +20,119 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/store/DialStore.ts
21
21
  var DialStore_exports = {};
22
22
  __export(DialStore_exports, {
23
- DialStore: () => DialStore
23
+ DialStore: () => DialStore,
24
+ flattenDialValueUpdates: () => flattenDialValueUpdates,
25
+ formatLabel: () => formatLabel,
26
+ inferStep: () => inferStep,
27
+ isEasingConfigValue: () => isEasingConfigValue,
28
+ isHexColor: () => isHexColor,
29
+ isSpringConfigValue: () => isSpringConfigValue,
30
+ resolveDialValues: () => resolveDialValues
24
31
  });
25
32
  module.exports = __toCommonJS(DialStore_exports);
26
33
  var EMPTY_VALUES = Object.freeze({});
34
+ function resolveDialValues(config, flatValues) {
35
+ return resolveConfigValues(config, flatValues, "");
36
+ }
37
+ function flattenDialValueUpdates(config, updates) {
38
+ const values = {};
39
+ if (typeof updates === "object" && updates !== null) {
40
+ flattenConfigUpdates(config, updates, "", values);
41
+ }
42
+ return values;
43
+ }
44
+ function resolveConfigValues(config, flatValues, prefix) {
45
+ const result = {};
46
+ for (const [key, configValue] of Object.entries(config)) {
47
+ if (key === "_collapsed") continue;
48
+ const path = prefix ? `${prefix}.${key}` : key;
49
+ if (Array.isArray(configValue) && configValue.length <= 4 && typeof configValue[0] === "number") {
50
+ result[key] = flatValues[path] ?? configValue[0];
51
+ } else if (typeof configValue === "number" || typeof configValue === "boolean" || typeof configValue === "string") {
52
+ result[key] = flatValues[path] ?? configValue;
53
+ } else if (isSpringConfigValue(configValue) || isEasingConfigValue(configValue)) {
54
+ result[key] = flatValues[path] ?? configValue;
55
+ } else if (isActionConfigValue(configValue)) {
56
+ result[key] = flatValues[path] ?? configValue;
57
+ } else if (isSelectConfigValue(configValue)) {
58
+ const defaultValue = configValue.default ?? getFirstOptionValue(configValue.options);
59
+ result[key] = flatValues[path] ?? defaultValue;
60
+ } else if (isColorConfigValue(configValue)) {
61
+ result[key] = flatValues[path] ?? configValue.default ?? "#000000";
62
+ } else if (isTextConfigValue(configValue)) {
63
+ result[key] = flatValues[path] ?? configValue.default ?? "";
64
+ } else if (typeof configValue === "object" && configValue !== null) {
65
+ result[key] = resolveConfigValues(configValue, flatValues, path);
66
+ }
67
+ }
68
+ return result;
69
+ }
70
+ function flattenConfigUpdates(config, updates, prefix, values) {
71
+ for (const [key, configValue] of Object.entries(config)) {
72
+ if (key === "_collapsed" || !(key in updates)) continue;
73
+ const nextValue = updates[key];
74
+ if (nextValue === void 0) continue;
75
+ const path = prefix ? `${prefix}.${key}` : key;
76
+ if (isActionConfigValue(configValue)) {
77
+ continue;
78
+ }
79
+ if (isLeafConfigValue(configValue)) {
80
+ values[path] = nextValue;
81
+ continue;
82
+ }
83
+ if (typeof configValue === "object" && configValue !== null && typeof nextValue === "object" && nextValue !== null && !Array.isArray(nextValue)) {
84
+ flattenConfigUpdates(configValue, nextValue, path, values);
85
+ }
86
+ }
87
+ }
88
+ function isLeafConfigValue(value) {
89
+ 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);
90
+ }
91
+ function hasType(value, type) {
92
+ return typeof value === "object" && value !== null && "type" in value && value.type === type;
93
+ }
94
+ function isSpringConfigValue(value) {
95
+ return hasType(value, "spring");
96
+ }
97
+ function isEasingConfigValue(value) {
98
+ return hasType(value, "easing");
99
+ }
100
+ function isHexColor(value) {
101
+ return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(value);
102
+ }
103
+ function formatLabel(key) {
104
+ return key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()).trim();
105
+ }
106
+ function inferStep(min, max) {
107
+ const range = max - min;
108
+ if (range <= 1) return 0.01;
109
+ if (range <= 10) return 0.1;
110
+ if (range <= 100) return 1;
111
+ return 10;
112
+ }
113
+ function isActionConfigValue(value) {
114
+ return hasType(value, "action");
115
+ }
116
+ function isSelectConfigValue(value) {
117
+ return hasType(value, "select") && "options" in value && Array.isArray(value.options);
118
+ }
119
+ function isColorConfigValue(value) {
120
+ return hasType(value, "color");
121
+ }
122
+ function isTextConfigValue(value) {
123
+ return hasType(value, "text");
124
+ }
125
+ function getFirstOptionValue(options) {
126
+ const first = options[0];
127
+ if (first === void 0) return "";
128
+ return typeof first === "string" ? first : first.value;
129
+ }
27
130
  var DialStoreClass = class {
28
131
  constructor() {
29
132
  this.panels = /* @__PURE__ */ new Map();
133
+ this.panelsSnapshot = [];
134
+ this.standardPanelsSnapshot = [];
135
+ this.timelinePanelsSnapshot = [];
30
136
  this.listeners = /* @__PURE__ */ new Map();
31
137
  this.globalListeners = /* @__PURE__ */ new Set();
32
138
  this.snapshots = /* @__PURE__ */ new Map();
@@ -34,87 +140,144 @@ var DialStoreClass = class {
34
140
  this.presets = /* @__PURE__ */ new Map();
35
141
  this.activePreset = /* @__PURE__ */ new Map();
36
142
  this.baseValues = /* @__PURE__ */ new Map();
37
- }
38
- registerPanel(id, name, config, shortcuts) {
143
+ this.defaultValues = /* @__PURE__ */ new Map();
144
+ this.registrationCounts = /* @__PURE__ */ new Map();
145
+ this.retainedPanels = /* @__PURE__ */ new Set();
146
+ this.persistConfigs = /* @__PURE__ */ new Map();
147
+ }
148
+ registerPanel(id, name, config, shortcuts, options = {}) {
149
+ const existingPanel = this.panels.get(id);
150
+ if (existingPanel && existingPanel.kind !== options.kind) {
151
+ console.warn(
152
+ `[dialkit] Panel id "${id}" cannot be shared by a timeline and a standard panel; the most recent registration controls where it renders.`
153
+ );
154
+ }
155
+ this.configurePanelRetention(id, options);
156
+ this.registrationCounts.set(id, (this.registrationCounts.get(id) ?? 0) + 1);
39
157
  const controls = this.parseConfig(config, "", shortcuts);
40
- const values = this.flattenValues(config, "");
41
- this.initTransitionModes(config, "", values);
42
- this.panels.set(id, { id, name, controls, values, shortcuts: shortcuts ?? {} });
158
+ const controlsByPath = this.mapControlsByPath(controls);
159
+ const defaultValues = this.flattenValues(config, "");
160
+ this.initTransitionModes(config, "", defaultValues);
161
+ const persisted = this.loadPersistedPanel(id);
162
+ const previousValues = this.panels.get(id)?.values ?? this.snapshots.get(id) ?? persisted?.values ?? {};
163
+ const values = this.reconcileValues(defaultValues, previousValues, controlsByPath);
164
+ const previousBaseValues = this.baseValues.get(id) ?? persisted?.baseValues ?? persisted?.values ?? {};
165
+ const baseValues = this.reconcileValues(defaultValues, previousBaseValues, controlsByPath);
166
+ this.panels.set(id, { id, name, controls, values, shortcuts: shortcuts ?? {}, kind: options.kind });
43
167
  this.snapshots.set(id, { ...values });
44
- this.baseValues.set(id, { ...values });
168
+ this.baseValues.set(id, baseValues);
169
+ this.defaultValues.set(id, { ...defaultValues });
170
+ const existingPresets = this.presets.get(id) ?? persisted?.presets;
171
+ if (existingPresets) {
172
+ this.presets.set(id, this.reconcilePresets(existingPresets, defaultValues, controlsByPath));
173
+ }
174
+ if (!this.activePreset.has(id) && persisted?.activePresetId !== void 0) {
175
+ this.activePreset.set(id, persisted.activePresetId);
176
+ }
177
+ this.persistPanel(id);
178
+ this.notify(id);
45
179
  this.notifyGlobal();
46
180
  }
47
- updatePanel(id, name, config, shortcuts) {
181
+ updatePanel(id, name, config, shortcuts, options = {}) {
182
+ this.configurePanelRetention(id, options);
48
183
  const existing = this.panels.get(id);
49
184
  if (!existing) {
50
- this.registerPanel(id, name, config, shortcuts);
185
+ this.registerPanel(id, name, config, shortcuts, options);
51
186
  return;
52
187
  }
53
188
  const controls = this.parseConfig(config, "", shortcuts);
54
189
  const controlsByPath = this.mapControlsByPath(controls);
55
190
  const defaultValues = this.flattenValues(config, "");
56
- const nextValues = {};
57
- for (const [path, defaultValue] of Object.entries(defaultValues)) {
58
- nextValues[path] = this.normalizePreservedValue(
59
- existing.values[path],
60
- defaultValue,
61
- controlsByPath.get(path)
62
- );
63
- }
64
- this.initTransitionModes(config, "", nextValues);
65
- for (const [path, mode] of Object.entries(existing.values)) {
66
- if (!path.endsWith(".__mode")) {
67
- continue;
68
- }
69
- const transitionPath = path.slice(0, -"__mode".length - 1);
70
- const transitionControl = controlsByPath.get(transitionPath);
71
- if (transitionControl?.type === "transition") {
72
- nextValues[path] = mode;
73
- }
74
- }
75
- const nextPanel = { id, name, controls, values: nextValues, shortcuts: shortcuts ?? existing.shortcuts };
191
+ this.initTransitionModes(config, "", defaultValues);
192
+ const nextValues = this.reconcileValues(defaultValues, existing.values, controlsByPath);
193
+ const nextPanel = { id, name, controls, values: nextValues, shortcuts: shortcuts ?? existing.shortcuts, kind: options.kind ?? existing.kind };
76
194
  this.panels.set(id, nextPanel);
77
195
  this.snapshots.set(id, { ...nextValues });
78
196
  const previousBaseValues = this.baseValues.get(id) ?? {};
79
- const nextBaseValues = {};
80
- for (const [path, defaultValue] of Object.entries(defaultValues)) {
81
- nextBaseValues[path] = this.normalizePreservedValue(
82
- previousBaseValues[path],
83
- defaultValue,
84
- controlsByPath.get(path)
85
- );
86
- }
197
+ const nextBaseValues = this.reconcileValues(defaultValues, previousBaseValues, controlsByPath);
87
198
  for (const [path, value] of Object.entries(nextValues)) {
88
199
  if (path.endsWith(".__mode")) {
89
200
  nextBaseValues[path] = value;
90
201
  }
91
202
  }
92
203
  this.baseValues.set(id, nextBaseValues);
204
+ this.defaultValues.set(id, { ...defaultValues });
205
+ this.presets.set(id, this.reconcilePresets(this.presets.get(id) ?? [], defaultValues, controlsByPath));
206
+ this.persistPanel(id);
93
207
  this.notify(id);
94
208
  this.notifyGlobal();
95
209
  }
96
210
  unregisterPanel(id) {
211
+ const nextCount = (this.registrationCounts.get(id) ?? 1) - 1;
212
+ if (nextCount > 0) {
213
+ this.registrationCounts.set(id, nextCount);
214
+ return;
215
+ }
216
+ this.registrationCounts.delete(id);
97
217
  this.panels.delete(id);
98
- this.listeners.delete(id);
99
- this.snapshots.delete(id);
100
- this.actionListeners.delete(id);
101
- this.baseValues.delete(id);
218
+ if (this.listeners.get(id)?.size === 0) this.listeners.delete(id);
219
+ if (this.actionListeners.get(id)?.size === 0) this.actionListeners.delete(id);
220
+ if (!this.retainedPanels.has(id)) {
221
+ this.snapshots.delete(id);
222
+ this.baseValues.delete(id);
223
+ this.defaultValues.delete(id);
224
+ this.presets.delete(id);
225
+ this.activePreset.delete(id);
226
+ this.persistConfigs.delete(id);
227
+ }
102
228
  this.notifyGlobal();
103
229
  }
104
230
  updateValue(panelId, path, value) {
231
+ this.updateValues(panelId, { [path]: value });
232
+ }
233
+ updateValues(panelId, updates) {
105
234
  const panel = this.panels.get(panelId);
106
235
  if (!panel) return;
107
- panel.values[path] = value;
236
+ const validUpdates = {};
237
+ for (const [path, value] of Object.entries(updates)) {
238
+ if (!Object.prototype.hasOwnProperty.call(panel.values, path)) {
239
+ continue;
240
+ }
241
+ const control = this.findControlByPath(panel.controls, path);
242
+ if (control?.type === "action") {
243
+ continue;
244
+ }
245
+ panel.values[path] = value;
246
+ validUpdates[path] = value;
247
+ }
248
+ if (Object.keys(validUpdates).length === 0) {
249
+ return;
250
+ }
108
251
  const activeId = this.activePreset.get(panelId);
109
252
  if (activeId) {
110
253
  const presets = this.presets.get(panelId) ?? [];
111
254
  const preset = presets.find((p) => p.id === activeId);
112
- if (preset) preset.values[path] = value;
255
+ if (preset) {
256
+ for (const [path, value] of Object.entries(validUpdates)) {
257
+ preset.values[path] = value;
258
+ }
259
+ }
113
260
  } else {
114
261
  const base = this.baseValues.get(panelId);
115
- if (base) base[path] = value;
262
+ if (base) {
263
+ for (const [path, value] of Object.entries(validUpdates)) {
264
+ base[path] = value;
265
+ }
266
+ }
116
267
  }
117
268
  this.snapshots.set(panelId, { ...panel.values });
269
+ this.persistPanel(panelId);
270
+ this.notify(panelId);
271
+ }
272
+ resetValues(panelId) {
273
+ const panel = this.panels.get(panelId);
274
+ const defaults = this.defaultValues.get(panelId);
275
+ if (!panel || !defaults) return;
276
+ panel.values = { ...defaults };
277
+ this.snapshots.set(panelId, { ...panel.values });
278
+ this.baseValues.set(panelId, { ...defaults });
279
+ this.activePreset.set(panelId, null);
280
+ this.persistPanel(panelId);
118
281
  this.notify(panelId);
119
282
  }
120
283
  updateSpringMode(panelId, path, mode) {
@@ -130,6 +293,7 @@ var DialStoreClass = class {
130
293
  if (!panel) return;
131
294
  panel.values[`${path}.__mode`] = mode;
132
295
  this.snapshots.set(panelId, { ...panel.values });
296
+ this.persistPanel(panelId);
133
297
  this.notify(panelId);
134
298
  }
135
299
  getTransitionMode(panelId, path) {
@@ -144,8 +308,10 @@ var DialStoreClass = class {
144
308
  getValues(panelId) {
145
309
  return this.snapshots.get(panelId) ?? EMPTY_VALUES;
146
310
  }
147
- getPanels() {
148
- return Array.from(this.panels.values());
311
+ getPanels(kind) {
312
+ if (kind === "panel") return this.standardPanelsSnapshot;
313
+ if (kind === "timeline") return this.timelinePanelsSnapshot;
314
+ return this.panelsSnapshot;
149
315
  }
150
316
  getPanel(id) {
151
317
  return this.panels.get(id);
@@ -156,7 +322,11 @@ var DialStoreClass = class {
156
322
  }
157
323
  this.listeners.get(panelId).add(listener);
158
324
  return () => {
159
- this.listeners.get(panelId)?.delete(listener);
325
+ const listeners = this.listeners.get(panelId);
326
+ listeners?.delete(listener);
327
+ if (listeners?.size === 0 && !this.panels.has(panelId)) {
328
+ this.listeners.delete(panelId);
329
+ }
160
330
  };
161
331
  }
162
332
  subscribeGlobal(listener) {
@@ -169,7 +339,11 @@ var DialStoreClass = class {
169
339
  }
170
340
  this.actionListeners.get(panelId).add(listener);
171
341
  return () => {
172
- this.actionListeners.get(panelId)?.delete(listener);
342
+ const listeners = this.actionListeners.get(panelId);
343
+ listeners?.delete(listener);
344
+ if (listeners?.size === 0 && !this.panels.has(panelId)) {
345
+ this.actionListeners.delete(panelId);
346
+ }
173
347
  };
174
348
  }
175
349
  triggerAction(panelId, path) {
@@ -188,6 +362,7 @@ var DialStoreClass = class {
188
362
  this.presets.set(panelId, [...existing, preset]);
189
363
  this.activePreset.set(panelId, id);
190
364
  this.snapshots.set(panelId, { ...panel.values });
365
+ this.persistPanel(panelId);
191
366
  this.notify(panelId);
192
367
  return id;
193
368
  }
@@ -200,6 +375,7 @@ var DialStoreClass = class {
200
375
  panel.values = { ...preset.values };
201
376
  this.snapshots.set(panelId, { ...panel.values });
202
377
  this.activePreset.set(panelId, presetId);
378
+ this.persistPanel(panelId);
203
379
  this.notify(panelId);
204
380
  }
205
381
  deletePreset(panelId, presetId) {
@@ -212,6 +388,7 @@ var DialStoreClass = class {
212
388
  if (panel) {
213
389
  this.snapshots.set(panelId, { ...panel.values });
214
390
  }
391
+ this.persistPanel(panelId);
215
392
  this.notify(panelId);
216
393
  }
217
394
  getPresets(panelId) {
@@ -228,6 +405,7 @@ var DialStoreClass = class {
228
405
  this.snapshots.set(panelId, { ...panel.values });
229
406
  }
230
407
  this.activePreset.set(panelId, null);
408
+ this.persistPanel(panelId);
231
409
  this.notify(panelId);
232
410
  }
233
411
  resolveShortcutTarget(key, modifier) {
@@ -258,6 +436,94 @@ var DialStoreClass = class {
258
436
  }
259
437
  return results;
260
438
  }
439
+ configurePanelRetention(id, options) {
440
+ if (options.retainOnUnmount) {
441
+ this.retainedPanels.add(id);
442
+ }
443
+ const persistConfig = this.normalizePersistConfig(id, options.persist);
444
+ if (persistConfig) {
445
+ this.persistConfigs.set(id, persistConfig);
446
+ this.retainedPanels.add(id);
447
+ }
448
+ }
449
+ reconcileValues(defaultValues, previousValues, controlsByPath) {
450
+ const nextValues = {};
451
+ for (const [path, defaultValue] of Object.entries(defaultValues)) {
452
+ if (path.endsWith(".__mode")) {
453
+ const transitionPath = path.slice(0, -".__mode".length);
454
+ const transitionControl = controlsByPath.get(transitionPath);
455
+ nextValues[path] = transitionControl?.type === "transition" && previousValues[path] !== void 0 ? previousValues[path] : defaultValue;
456
+ continue;
457
+ }
458
+ nextValues[path] = this.normalizePreservedValue(
459
+ previousValues[path],
460
+ defaultValue,
461
+ controlsByPath.get(path)
462
+ );
463
+ }
464
+ return nextValues;
465
+ }
466
+ reconcilePresets(presets, defaultValues, controlsByPath) {
467
+ return presets.map((preset) => ({
468
+ ...preset,
469
+ values: this.reconcileValues(defaultValues, preset.values, controlsByPath)
470
+ }));
471
+ }
472
+ normalizePersistConfig(id, persist) {
473
+ if (!persist) return null;
474
+ const options = typeof persist === "object" ? persist : {};
475
+ return {
476
+ key: options.key ?? `dialkit:${id}`,
477
+ storage: options.storage ?? "localStorage",
478
+ presets: options.presets ?? true
479
+ };
480
+ }
481
+ loadPersistedPanel(id) {
482
+ const config = this.persistConfigs.get(id);
483
+ if (!config) return null;
484
+ const storage = this.getStorage(config.storage);
485
+ if (!storage) return null;
486
+ try {
487
+ const raw = storage.getItem(config.key);
488
+ if (!raw) return null;
489
+ const parsed = JSON.parse(raw);
490
+ if (parsed?.version !== 1 || typeof parsed !== "object") return null;
491
+ return parsed;
492
+ } catch {
493
+ return null;
494
+ }
495
+ }
496
+ persistPanel(id) {
497
+ const config = this.persistConfigs.get(id);
498
+ if (!config) return;
499
+ const storage = this.getStorage(config.storage);
500
+ if (!storage) return;
501
+ const values = this.snapshots.get(id) ?? this.panels.get(id)?.values;
502
+ if (!values) return;
503
+ const state = {
504
+ version: 1,
505
+ values,
506
+ baseValues: this.baseValues.get(id) ?? values,
507
+ activePresetId: this.activePreset.get(id) ?? null
508
+ };
509
+ if (config.presets) {
510
+ state.presets = this.presets.get(id) ?? [];
511
+ }
512
+ try {
513
+ storage.setItem(config.key, JSON.stringify(state));
514
+ } catch {
515
+ }
516
+ }
517
+ getStorage(kind) {
518
+ if (typeof globalThis === "undefined" || !("window" in globalThis)) {
519
+ return null;
520
+ }
521
+ try {
522
+ return kind === "sessionStorage" ? globalThis.window?.sessionStorage ?? null : globalThis.window?.localStorage ?? null;
523
+ } catch {
524
+ return null;
525
+ }
526
+ }
261
527
  findControlByPath(controls, path) {
262
528
  for (const control of controls) {
263
529
  if (control.path === path) return control;
@@ -272,6 +538,9 @@ var DialStoreClass = class {
272
538
  this.listeners.get(panelId)?.forEach((fn) => fn());
273
539
  }
274
540
  notifyGlobal() {
541
+ this.panelsSnapshot = Array.from(this.panels.values());
542
+ this.standardPanelsSnapshot = this.panelsSnapshot.filter((panel) => panel.kind !== "timeline");
543
+ this.timelinePanelsSnapshot = this.panelsSnapshot.filter((panel) => panel.kind === "timeline");
275
544
  this.globalListeners.forEach((fn) => fn());
276
545
  }
277
546
  initTransitionModes(config, prefix, values) {
@@ -387,10 +656,10 @@ var DialStoreClass = class {
387
656
  return typeof value === "object" && value !== null && "type" in value && value.type === "text";
388
657
  }
389
658
  isHexColor(value) {
390
- return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(value);
659
+ return isHexColor(value);
391
660
  }
392
661
  formatLabel(key) {
393
- return key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()).trim();
662
+ return formatLabel(key);
394
663
  }
395
664
  inferRange(value) {
396
665
  if (value >= 0 && value <= 1) {
@@ -406,11 +675,7 @@ var DialStoreClass = class {
406
675
  }
407
676
  }
408
677
  inferStep(min, max) {
409
- const range = max - min;
410
- if (range <= 1) return 0.01;
411
- if (range <= 10) return 0.1;
412
- if (range <= 100) return 1;
413
- return 10;
678
+ return inferStep(min, max);
414
679
  }
415
680
  normalizePreservedValue(existingValue, defaultValue, control) {
416
681
  if (existingValue === void 0 || !control) {
@@ -482,9 +747,16 @@ var DialStoreClass = class {
482
747
  return map;
483
748
  }
484
749
  };
485
- var DialStore = new DialStoreClass();
750
+ var DialStore = /* @__PURE__ */ new DialStoreClass();
486
751
  // Annotate the CommonJS export names for ESM import in node:
487
752
  0 && (module.exports = {
488
- DialStore
753
+ DialStore,
754
+ flattenDialValueUpdates,
755
+ formatLabel,
756
+ inferStep,
757
+ isEasingConfigValue,
758
+ isHexColor,
759
+ isSpringConfigValue,
760
+ resolveDialValues
489
761
  });
490
762
  //# sourceMappingURL=index.cjs.map