dialkit 1.2.1 → 1.3.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 (55) hide show
  1. package/README.md +220 -3
  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/index.cjs +697 -307
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +42 -5
  8. package/dist/index.d.ts +42 -5
  9. package/dist/index.js +720 -331
  10. package/dist/index.js.map +1 -1
  11. package/dist/panel-drag.d.ts +19 -0
  12. package/dist/panel-drag.js +72 -0
  13. package/dist/panel-drag.js.map +1 -0
  14. package/dist/solid/index.cjs +661 -204
  15. package/dist/solid/index.cjs.map +1 -1
  16. package/dist/solid/index.d.cts +40 -3
  17. package/dist/solid/index.d.ts +40 -3
  18. package/dist/solid/index.js +646 -190
  19. package/dist/solid/index.js.map +1 -1
  20. package/dist/store/index.cjs +272 -41
  21. package/dist/store/index.cjs.map +1 -1
  22. package/dist/store/index.d.cts +30 -3
  23. package/dist/store/index.d.ts +30 -3
  24. package/dist/store/index.js +269 -40
  25. package/dist/store/index.js.map +1 -1
  26. package/dist/styles.css +105 -7
  27. package/dist/svelte/components/DialRoot.svelte +176 -11
  28. package/dist/svelte/components/DialRoot.svelte.d.ts +1 -0
  29. package/dist/svelte/components/DialRoot.svelte.d.ts.map +1 -1
  30. package/dist/svelte/components/Folder.svelte +24 -13
  31. package/dist/svelte/components/Folder.svelte.d.ts +1 -0
  32. package/dist/svelte/components/Folder.svelte.d.ts.map +1 -1
  33. package/dist/svelte/components/Panel.svelte +98 -71
  34. package/dist/svelte/components/Panel.svelte.d.ts +2 -0
  35. package/dist/svelte/components/Panel.svelte.d.ts.map +1 -1
  36. package/dist/svelte/components/PresetManager.svelte +5 -5
  37. package/dist/svelte/components/PresetManager.svelte.d.ts.map +1 -1
  38. package/dist/svelte/components/SelectControl.svelte +6 -14
  39. package/dist/svelte/components/SelectControl.svelte.d.ts.map +1 -1
  40. package/dist/svelte/createDialKit.svelte.d.ts +11 -1
  41. package/dist/svelte/createDialKit.svelte.d.ts.map +1 -1
  42. package/dist/svelte/createDialKit.svelte.js +61 -34
  43. package/dist/svelte/index.d.ts +3 -3
  44. package/dist/svelte/index.d.ts.map +1 -1
  45. package/dist/svelte/index.js +1 -1
  46. package/dist/svelte/theme-css.d.ts +1 -1
  47. package/dist/svelte/theme-css.d.ts.map +1 -1
  48. package/dist/svelte/theme-css.js +105 -7
  49. package/dist/vue/index.cjs +573 -132
  50. package/dist/vue/index.cjs.map +1 -1
  51. package/dist/vue/index.d.cts +53 -6
  52. package/dist/vue/index.d.ts +53 -6
  53. package/dist/vue/index.js +573 -133
  54. package/dist/vue/index.js.map +1 -1
  55. package/package.json +2 -2
@@ -40,6 +40,9 @@ type DialConfig = {
40
40
  type ResolvedValues<T extends DialConfig> = {
41
41
  [K in keyof T]: T[K] extends [number, number, number, number?] ? number : T[K] extends SpringConfig ? TransitionConfig : T[K] extends EasingConfig ? TransitionConfig : T[K] extends SelectConfig ? string : T[K] extends ColorConfig ? string : T[K] extends TextConfig ? string : T[K] extends DialConfig ? ResolvedValues<T[K]> : T[K];
42
42
  };
43
+ type DialKitValueUpdates<T extends DialConfig> = {
44
+ [K in keyof T as K extends '_collapsed' ? never : K]?: T[K] extends [number, number, number, number?] ? number : T[K] extends SpringConfig | EasingConfig ? TransitionConfig : T[K] extends ActionConfig ? never : T[K] extends SelectConfig | ColorConfig | TextConfig ? string : T[K] extends DialConfig ? DialKitValueUpdates<T[K]> : T[K];
45
+ };
43
46
  type ShortcutMode = 'fine' | 'normal' | 'coarse';
44
47
  type ShortcutInteraction = 'scroll' | 'drag' | 'move' | 'scroll-only';
45
48
  type ShortcutConfig = {
@@ -78,6 +81,17 @@ type Preset = {
78
81
  name: string;
79
82
  values: Record<string, DialValue>;
80
83
  };
84
+ type DialKitPersistOptions = boolean | {
85
+ key?: string;
86
+ storage?: 'localStorage' | 'sessionStorage';
87
+ presets?: boolean;
88
+ };
89
+ type DialStorePanelOptions = {
90
+ retainOnUnmount?: boolean;
91
+ persist?: DialKitPersistOptions;
92
+ };
93
+ declare function resolveDialValues<T extends DialConfig>(config: T, flatValues: Record<string, DialValue>): ResolvedValues<T>;
94
+ declare function flattenDialValueUpdates<T extends DialConfig>(config: T, updates: DialKitValueUpdates<T>): Record<string, DialValue>;
81
95
  declare class DialStoreClass {
82
96
  private panels;
83
97
  private listeners;
@@ -87,10 +101,16 @@ declare class DialStoreClass {
87
101
  private presets;
88
102
  private activePreset;
89
103
  private baseValues;
90
- registerPanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>): void;
91
- updatePanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>): void;
104
+ private defaultValues;
105
+ private registrationCounts;
106
+ private retainedPanels;
107
+ private persistConfigs;
108
+ registerPanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>, options?: DialStorePanelOptions): void;
109
+ updatePanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>, options?: DialStorePanelOptions): void;
92
110
  unregisterPanel(id: string): void;
93
111
  updateValue(panelId: string, path: string, value: DialValue): void;
112
+ updateValues(panelId: string, updates: Record<string, DialValue>): void;
113
+ resetValues(panelId: string): void;
94
114
  updateSpringMode(panelId: string, path: string, mode: 'simple' | 'advanced'): void;
95
115
  getSpringMode(panelId: string, path: string): 'simple' | 'advanced';
96
116
  updateTransitionMode(panelId: string, path: string, mode: 'easing' | 'simple' | 'advanced'): void;
@@ -120,6 +140,13 @@ declare class DialStoreClass {
120
140
  control: ControlMeta;
121
141
  shortcut: ShortcutConfig;
122
142
  }>;
143
+ private configurePanelRetention;
144
+ private reconcileValues;
145
+ private reconcilePresets;
146
+ private normalizePersistConfig;
147
+ private loadPersistedPanel;
148
+ private persistPanel;
149
+ private getStorage;
123
150
  private findControlByPath;
124
151
  private notify;
125
152
  private notifyGlobal;
@@ -143,4 +170,4 @@ declare class DialStoreClass {
143
170
  }
144
171
  declare const DialStore: DialStoreClass;
145
172
 
146
- export { type ActionConfig, type ColorConfig, type ControlMeta, type DialConfig, DialStore, type DialValue, type EasingConfig, type PanelConfig, type Preset, type ResolvedValues, type SelectConfig, type ShortcutConfig, type ShortcutInteraction, type ShortcutMode, type SpringConfig, type TextConfig, type TransitionConfig };
173
+ export { type ActionConfig, type ColorConfig, type ControlMeta, type DialConfig, type DialKitPersistOptions, type DialKitValueUpdates, DialStore, type DialStorePanelOptions, type DialValue, type EasingConfig, type PanelConfig, type Preset, type ResolvedValues, type SelectConfig, type ShortcutConfig, type ShortcutInteraction, type ShortcutMode, type SpringConfig, type TextConfig, type TransitionConfig, flattenDialValueUpdates, resolveDialValues };
@@ -40,6 +40,9 @@ type DialConfig = {
40
40
  type ResolvedValues<T extends DialConfig> = {
41
41
  [K in keyof T]: T[K] extends [number, number, number, number?] ? number : T[K] extends SpringConfig ? TransitionConfig : T[K] extends EasingConfig ? TransitionConfig : T[K] extends SelectConfig ? string : T[K] extends ColorConfig ? string : T[K] extends TextConfig ? string : T[K] extends DialConfig ? ResolvedValues<T[K]> : T[K];
42
42
  };
43
+ type DialKitValueUpdates<T extends DialConfig> = {
44
+ [K in keyof T as K extends '_collapsed' ? never : K]?: T[K] extends [number, number, number, number?] ? number : T[K] extends SpringConfig | EasingConfig ? TransitionConfig : T[K] extends ActionConfig ? never : T[K] extends SelectConfig | ColorConfig | TextConfig ? string : T[K] extends DialConfig ? DialKitValueUpdates<T[K]> : T[K];
45
+ };
43
46
  type ShortcutMode = 'fine' | 'normal' | 'coarse';
44
47
  type ShortcutInteraction = 'scroll' | 'drag' | 'move' | 'scroll-only';
45
48
  type ShortcutConfig = {
@@ -78,6 +81,17 @@ type Preset = {
78
81
  name: string;
79
82
  values: Record<string, DialValue>;
80
83
  };
84
+ type DialKitPersistOptions = boolean | {
85
+ key?: string;
86
+ storage?: 'localStorage' | 'sessionStorage';
87
+ presets?: boolean;
88
+ };
89
+ type DialStorePanelOptions = {
90
+ retainOnUnmount?: boolean;
91
+ persist?: DialKitPersistOptions;
92
+ };
93
+ declare function resolveDialValues<T extends DialConfig>(config: T, flatValues: Record<string, DialValue>): ResolvedValues<T>;
94
+ declare function flattenDialValueUpdates<T extends DialConfig>(config: T, updates: DialKitValueUpdates<T>): Record<string, DialValue>;
81
95
  declare class DialStoreClass {
82
96
  private panels;
83
97
  private listeners;
@@ -87,10 +101,16 @@ declare class DialStoreClass {
87
101
  private presets;
88
102
  private activePreset;
89
103
  private baseValues;
90
- registerPanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>): void;
91
- updatePanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>): void;
104
+ private defaultValues;
105
+ private registrationCounts;
106
+ private retainedPanels;
107
+ private persistConfigs;
108
+ registerPanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>, options?: DialStorePanelOptions): void;
109
+ updatePanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>, options?: DialStorePanelOptions): void;
92
110
  unregisterPanel(id: string): void;
93
111
  updateValue(panelId: string, path: string, value: DialValue): void;
112
+ updateValues(panelId: string, updates: Record<string, DialValue>): void;
113
+ resetValues(panelId: string): void;
94
114
  updateSpringMode(panelId: string, path: string, mode: 'simple' | 'advanced'): void;
95
115
  getSpringMode(panelId: string, path: string): 'simple' | 'advanced';
96
116
  updateTransitionMode(panelId: string, path: string, mode: 'easing' | 'simple' | 'advanced'): void;
@@ -120,6 +140,13 @@ declare class DialStoreClass {
120
140
  control: ControlMeta;
121
141
  shortcut: ShortcutConfig;
122
142
  }>;
143
+ private configurePanelRetention;
144
+ private reconcileValues;
145
+ private reconcilePresets;
146
+ private normalizePersistConfig;
147
+ private loadPersistedPanel;
148
+ private persistPanel;
149
+ private getStorage;
123
150
  private findControlByPath;
124
151
  private notify;
125
152
  private notifyGlobal;
@@ -143,4 +170,4 @@ declare class DialStoreClass {
143
170
  }
144
171
  declare const DialStore: DialStoreClass;
145
172
 
146
- export { type ActionConfig, type ColorConfig, type ControlMeta, type DialConfig, DialStore, type DialValue, type EasingConfig, type PanelConfig, type Preset, type ResolvedValues, type SelectConfig, type ShortcutConfig, type ShortcutInteraction, type ShortcutMode, type SpringConfig, type TextConfig, type TransitionConfig };
173
+ export { type ActionConfig, type ColorConfig, type ControlMeta, type DialConfig, type DialKitPersistOptions, type DialKitValueUpdates, DialStore, type DialStorePanelOptions, type DialValue, type EasingConfig, type PanelConfig, type Preset, type ResolvedValues, type SelectConfig, type ShortcutConfig, type ShortcutInteraction, type ShortcutMode, type SpringConfig, type TextConfig, type TransitionConfig, flattenDialValueUpdates, resolveDialValues };
@@ -1,5 +1,88 @@
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 isActionConfigValue(value) {
70
+ return hasType(value, "action");
71
+ }
72
+ function isSelectConfigValue(value) {
73
+ return hasType(value, "select") && "options" in value && Array.isArray(value.options);
74
+ }
75
+ function isColorConfigValue(value) {
76
+ return hasType(value, "color");
77
+ }
78
+ function isTextConfigValue(value) {
79
+ return hasType(value, "text");
80
+ }
81
+ function getFirstOptionValue(options) {
82
+ const first = options[0];
83
+ if (first === void 0) return "";
84
+ return typeof first === "string" ? first : first.value;
85
+ }
3
86
  var DialStoreClass = class {
4
87
  constructor() {
5
88
  this.panels = /* @__PURE__ */ new Map();
@@ -10,87 +93,138 @@ var DialStoreClass = class {
10
93
  this.presets = /* @__PURE__ */ new Map();
11
94
  this.activePreset = /* @__PURE__ */ new Map();
12
95
  this.baseValues = /* @__PURE__ */ new Map();
13
- }
14
- registerPanel(id, name, config, shortcuts) {
96
+ this.defaultValues = /* @__PURE__ */ new Map();
97
+ this.registrationCounts = /* @__PURE__ */ new Map();
98
+ this.retainedPanels = /* @__PURE__ */ new Set();
99
+ this.persistConfigs = /* @__PURE__ */ new Map();
100
+ }
101
+ registerPanel(id, name, config, shortcuts, options = {}) {
102
+ this.configurePanelRetention(id, options);
103
+ this.registrationCounts.set(id, (this.registrationCounts.get(id) ?? 0) + 1);
15
104
  const controls = this.parseConfig(config, "", shortcuts);
16
- const values = this.flattenValues(config, "");
17
- this.initTransitionModes(config, "", values);
105
+ const controlsByPath = this.mapControlsByPath(controls);
106
+ const defaultValues = this.flattenValues(config, "");
107
+ this.initTransitionModes(config, "", defaultValues);
108
+ const persisted = this.loadPersistedPanel(id);
109
+ const previousValues = this.panels.get(id)?.values ?? this.snapshots.get(id) ?? persisted?.values ?? {};
110
+ const values = this.reconcileValues(defaultValues, previousValues, controlsByPath);
111
+ const previousBaseValues = this.baseValues.get(id) ?? persisted?.baseValues ?? persisted?.values ?? {};
112
+ const baseValues = this.reconcileValues(defaultValues, previousBaseValues, controlsByPath);
18
113
  this.panels.set(id, { id, name, controls, values, shortcuts: shortcuts ?? {} });
19
114
  this.snapshots.set(id, { ...values });
20
- this.baseValues.set(id, { ...values });
115
+ this.baseValues.set(id, baseValues);
116
+ this.defaultValues.set(id, { ...defaultValues });
117
+ const existingPresets = this.presets.get(id) ?? persisted?.presets;
118
+ if (existingPresets) {
119
+ this.presets.set(id, this.reconcilePresets(existingPresets, defaultValues, controlsByPath));
120
+ }
121
+ if (!this.activePreset.has(id) && persisted?.activePresetId !== void 0) {
122
+ this.activePreset.set(id, persisted.activePresetId);
123
+ }
124
+ this.persistPanel(id);
125
+ this.notify(id);
21
126
  this.notifyGlobal();
22
127
  }
23
- updatePanel(id, name, config, shortcuts) {
128
+ updatePanel(id, name, config, shortcuts, options = {}) {
129
+ this.configurePanelRetention(id, options);
24
130
  const existing = this.panels.get(id);
25
131
  if (!existing) {
26
- this.registerPanel(id, name, config, shortcuts);
132
+ this.registerPanel(id, name, config, shortcuts, options);
27
133
  return;
28
134
  }
29
135
  const controls = this.parseConfig(config, "", shortcuts);
30
136
  const controlsByPath = this.mapControlsByPath(controls);
31
137
  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
- }
138
+ this.initTransitionModes(config, "", defaultValues);
139
+ const nextValues = this.reconcileValues(defaultValues, existing.values, controlsByPath);
51
140
  const nextPanel = { id, name, controls, values: nextValues, shortcuts: shortcuts ?? existing.shortcuts };
52
141
  this.panels.set(id, nextPanel);
53
142
  this.snapshots.set(id, { ...nextValues });
54
143
  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
- }
144
+ const nextBaseValues = this.reconcileValues(defaultValues, previousBaseValues, controlsByPath);
63
145
  for (const [path, value] of Object.entries(nextValues)) {
64
146
  if (path.endsWith(".__mode")) {
65
147
  nextBaseValues[path] = value;
66
148
  }
67
149
  }
68
150
  this.baseValues.set(id, nextBaseValues);
151
+ this.defaultValues.set(id, { ...defaultValues });
152
+ this.presets.set(id, this.reconcilePresets(this.presets.get(id) ?? [], defaultValues, controlsByPath));
153
+ this.persistPanel(id);
69
154
  this.notify(id);
70
155
  this.notifyGlobal();
71
156
  }
72
157
  unregisterPanel(id) {
158
+ const nextCount = (this.registrationCounts.get(id) ?? 1) - 1;
159
+ if (nextCount > 0) {
160
+ this.registrationCounts.set(id, nextCount);
161
+ return;
162
+ }
163
+ this.registrationCounts.delete(id);
73
164
  this.panels.delete(id);
74
165
  this.listeners.delete(id);
75
- this.snapshots.delete(id);
76
166
  this.actionListeners.delete(id);
77
- this.baseValues.delete(id);
167
+ if (!this.retainedPanels.has(id)) {
168
+ this.snapshots.delete(id);
169
+ this.baseValues.delete(id);
170
+ this.defaultValues.delete(id);
171
+ this.presets.delete(id);
172
+ this.activePreset.delete(id);
173
+ this.persistConfigs.delete(id);
174
+ }
78
175
  this.notifyGlobal();
79
176
  }
80
177
  updateValue(panelId, path, value) {
178
+ this.updateValues(panelId, { [path]: value });
179
+ }
180
+ updateValues(panelId, updates) {
81
181
  const panel = this.panels.get(panelId);
82
182
  if (!panel) return;
83
- panel.values[path] = value;
183
+ const validUpdates = {};
184
+ for (const [path, value] of Object.entries(updates)) {
185
+ if (!Object.prototype.hasOwnProperty.call(panel.values, path)) {
186
+ continue;
187
+ }
188
+ const control = this.findControlByPath(panel.controls, path);
189
+ if (control?.type === "action") {
190
+ continue;
191
+ }
192
+ panel.values[path] = value;
193
+ validUpdates[path] = value;
194
+ }
195
+ if (Object.keys(validUpdates).length === 0) {
196
+ return;
197
+ }
84
198
  const activeId = this.activePreset.get(panelId);
85
199
  if (activeId) {
86
200
  const presets = this.presets.get(panelId) ?? [];
87
201
  const preset = presets.find((p) => p.id === activeId);
88
- if (preset) preset.values[path] = value;
202
+ if (preset) {
203
+ for (const [path, value] of Object.entries(validUpdates)) {
204
+ preset.values[path] = value;
205
+ }
206
+ }
89
207
  } else {
90
208
  const base = this.baseValues.get(panelId);
91
- if (base) base[path] = value;
209
+ if (base) {
210
+ for (const [path, value] of Object.entries(validUpdates)) {
211
+ base[path] = value;
212
+ }
213
+ }
92
214
  }
93
215
  this.snapshots.set(panelId, { ...panel.values });
216
+ this.persistPanel(panelId);
217
+ this.notify(panelId);
218
+ }
219
+ resetValues(panelId) {
220
+ const panel = this.panels.get(panelId);
221
+ const defaults = this.defaultValues.get(panelId);
222
+ if (!panel || !defaults) return;
223
+ panel.values = { ...defaults };
224
+ this.snapshots.set(panelId, { ...panel.values });
225
+ this.baseValues.set(panelId, { ...defaults });
226
+ this.activePreset.set(panelId, null);
227
+ this.persistPanel(panelId);
94
228
  this.notify(panelId);
95
229
  }
96
230
  updateSpringMode(panelId, path, mode) {
@@ -106,6 +240,7 @@ var DialStoreClass = class {
106
240
  if (!panel) return;
107
241
  panel.values[`${path}.__mode`] = mode;
108
242
  this.snapshots.set(panelId, { ...panel.values });
243
+ this.persistPanel(panelId);
109
244
  this.notify(panelId);
110
245
  }
111
246
  getTransitionMode(panelId, path) {
@@ -164,6 +299,7 @@ var DialStoreClass = class {
164
299
  this.presets.set(panelId, [...existing, preset]);
165
300
  this.activePreset.set(panelId, id);
166
301
  this.snapshots.set(panelId, { ...panel.values });
302
+ this.persistPanel(panelId);
167
303
  this.notify(panelId);
168
304
  return id;
169
305
  }
@@ -176,6 +312,7 @@ var DialStoreClass = class {
176
312
  panel.values = { ...preset.values };
177
313
  this.snapshots.set(panelId, { ...panel.values });
178
314
  this.activePreset.set(panelId, presetId);
315
+ this.persistPanel(panelId);
179
316
  this.notify(panelId);
180
317
  }
181
318
  deletePreset(panelId, presetId) {
@@ -188,6 +325,7 @@ var DialStoreClass = class {
188
325
  if (panel) {
189
326
  this.snapshots.set(panelId, { ...panel.values });
190
327
  }
328
+ this.persistPanel(panelId);
191
329
  this.notify(panelId);
192
330
  }
193
331
  getPresets(panelId) {
@@ -204,6 +342,7 @@ var DialStoreClass = class {
204
342
  this.snapshots.set(panelId, { ...panel.values });
205
343
  }
206
344
  this.activePreset.set(panelId, null);
345
+ this.persistPanel(panelId);
207
346
  this.notify(panelId);
208
347
  }
209
348
  resolveShortcutTarget(key, modifier) {
@@ -234,6 +373,94 @@ var DialStoreClass = class {
234
373
  }
235
374
  return results;
236
375
  }
376
+ configurePanelRetention(id, options) {
377
+ if (options.retainOnUnmount) {
378
+ this.retainedPanels.add(id);
379
+ }
380
+ const persistConfig = this.normalizePersistConfig(id, options.persist);
381
+ if (persistConfig) {
382
+ this.persistConfigs.set(id, persistConfig);
383
+ this.retainedPanels.add(id);
384
+ }
385
+ }
386
+ reconcileValues(defaultValues, previousValues, controlsByPath) {
387
+ const nextValues = {};
388
+ for (const [path, defaultValue] of Object.entries(defaultValues)) {
389
+ if (path.endsWith(".__mode")) {
390
+ const transitionPath = path.slice(0, -".__mode".length);
391
+ const transitionControl = controlsByPath.get(transitionPath);
392
+ nextValues[path] = transitionControl?.type === "transition" && previousValues[path] !== void 0 ? previousValues[path] : defaultValue;
393
+ continue;
394
+ }
395
+ nextValues[path] = this.normalizePreservedValue(
396
+ previousValues[path],
397
+ defaultValue,
398
+ controlsByPath.get(path)
399
+ );
400
+ }
401
+ return nextValues;
402
+ }
403
+ reconcilePresets(presets, defaultValues, controlsByPath) {
404
+ return presets.map((preset) => ({
405
+ ...preset,
406
+ values: this.reconcileValues(defaultValues, preset.values, controlsByPath)
407
+ }));
408
+ }
409
+ normalizePersistConfig(id, persist) {
410
+ if (!persist) return null;
411
+ const options = typeof persist === "object" ? persist : {};
412
+ return {
413
+ key: options.key ?? `dialkit:${id}`,
414
+ storage: options.storage ?? "localStorage",
415
+ presets: options.presets ?? true
416
+ };
417
+ }
418
+ loadPersistedPanel(id) {
419
+ const config = this.persistConfigs.get(id);
420
+ if (!config) return null;
421
+ const storage = this.getStorage(config.storage);
422
+ if (!storage) return null;
423
+ try {
424
+ const raw = storage.getItem(config.key);
425
+ if (!raw) return null;
426
+ const parsed = JSON.parse(raw);
427
+ if (parsed?.version !== 1 || typeof parsed !== "object") return null;
428
+ return parsed;
429
+ } catch {
430
+ return null;
431
+ }
432
+ }
433
+ persistPanel(id) {
434
+ const config = this.persistConfigs.get(id);
435
+ if (!config) return;
436
+ const storage = this.getStorage(config.storage);
437
+ if (!storage) return;
438
+ const values = this.snapshots.get(id) ?? this.panels.get(id)?.values;
439
+ if (!values) return;
440
+ const state = {
441
+ version: 1,
442
+ values,
443
+ baseValues: this.baseValues.get(id) ?? values,
444
+ activePresetId: this.activePreset.get(id) ?? null
445
+ };
446
+ if (config.presets) {
447
+ state.presets = this.presets.get(id) ?? [];
448
+ }
449
+ try {
450
+ storage.setItem(config.key, JSON.stringify(state));
451
+ } catch {
452
+ }
453
+ }
454
+ getStorage(kind) {
455
+ if (typeof globalThis === "undefined" || !("window" in globalThis)) {
456
+ return null;
457
+ }
458
+ try {
459
+ return kind === "sessionStorage" ? globalThis.window?.sessionStorage ?? null : globalThis.window?.localStorage ?? null;
460
+ } catch {
461
+ return null;
462
+ }
463
+ }
237
464
  findControlByPath(controls, path) {
238
465
  for (const control of controls) {
239
466
  if (control.path === path) return control;
@@ -460,6 +687,8 @@ var DialStoreClass = class {
460
687
  };
461
688
  var DialStore = new DialStoreClass();
462
689
  export {
463
- DialStore
690
+ DialStore,
691
+ flattenDialValueUpdates,
692
+ resolveDialValues
464
693
  };
465
694
  //# sourceMappingURL=index.js.map