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.
- package/README.md +220 -3
- package/dist/dropdown-position.d.ts +15 -0
- package/dist/dropdown-position.js +22 -0
- package/dist/dropdown-position.js.map +1 -0
- package/dist/index.cjs +697 -307
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -5
- package/dist/index.d.ts +42 -5
- package/dist/index.js +720 -331
- package/dist/index.js.map +1 -1
- package/dist/panel-drag.d.ts +19 -0
- package/dist/panel-drag.js +72 -0
- package/dist/panel-drag.js.map +1 -0
- package/dist/solid/index.cjs +661 -204
- package/dist/solid/index.cjs.map +1 -1
- package/dist/solid/index.d.cts +40 -3
- package/dist/solid/index.d.ts +40 -3
- package/dist/solid/index.js +646 -190
- package/dist/solid/index.js.map +1 -1
- package/dist/store/index.cjs +272 -41
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +30 -3
- package/dist/store/index.d.ts +30 -3
- package/dist/store/index.js +269 -40
- package/dist/store/index.js.map +1 -1
- package/dist/styles.css +105 -7
- package/dist/svelte/components/DialRoot.svelte +176 -11
- package/dist/svelte/components/DialRoot.svelte.d.ts +1 -0
- package/dist/svelte/components/DialRoot.svelte.d.ts.map +1 -1
- package/dist/svelte/components/Folder.svelte +24 -13
- package/dist/svelte/components/Folder.svelte.d.ts +1 -0
- package/dist/svelte/components/Folder.svelte.d.ts.map +1 -1
- package/dist/svelte/components/Panel.svelte +98 -71
- package/dist/svelte/components/Panel.svelte.d.ts +2 -0
- package/dist/svelte/components/Panel.svelte.d.ts.map +1 -1
- package/dist/svelte/components/PresetManager.svelte +5 -5
- package/dist/svelte/components/PresetManager.svelte.d.ts.map +1 -1
- package/dist/svelte/components/SelectControl.svelte +6 -14
- package/dist/svelte/components/SelectControl.svelte.d.ts.map +1 -1
- package/dist/svelte/createDialKit.svelte.d.ts +11 -1
- package/dist/svelte/createDialKit.svelte.d.ts.map +1 -1
- package/dist/svelte/createDialKit.svelte.js +61 -34
- package/dist/svelte/index.d.ts +3 -3
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +1 -1
- package/dist/svelte/theme-css.d.ts +1 -1
- package/dist/svelte/theme-css.d.ts.map +1 -1
- package/dist/svelte/theme-css.js +105 -7
- package/dist/vue/index.cjs +573 -132
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.d.cts +53 -6
- package/dist/vue/index.d.ts +53 -6
- package/dist/vue/index.js +573 -133
- package/dist/vue/index.js.map +1 -1
- package/package.json +2 -2
package/dist/store/index.cjs
CHANGED
|
@@ -20,10 +20,95 @@ 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
|
+
resolveDialValues: () => resolveDialValues
|
|
24
26
|
});
|
|
25
27
|
module.exports = __toCommonJS(DialStore_exports);
|
|
26
28
|
var EMPTY_VALUES = Object.freeze({});
|
|
29
|
+
function resolveDialValues(config, flatValues) {
|
|
30
|
+
return resolveConfigValues(config, flatValues, "");
|
|
31
|
+
}
|
|
32
|
+
function flattenDialValueUpdates(config, updates) {
|
|
33
|
+
const values = {};
|
|
34
|
+
if (typeof updates === "object" && updates !== null) {
|
|
35
|
+
flattenConfigUpdates(config, updates, "", values);
|
|
36
|
+
}
|
|
37
|
+
return values;
|
|
38
|
+
}
|
|
39
|
+
function resolveConfigValues(config, flatValues, prefix) {
|
|
40
|
+
const result = {};
|
|
41
|
+
for (const [key, configValue] of Object.entries(config)) {
|
|
42
|
+
if (key === "_collapsed") continue;
|
|
43
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
44
|
+
if (Array.isArray(configValue) && configValue.length <= 4 && typeof configValue[0] === "number") {
|
|
45
|
+
result[key] = flatValues[path] ?? configValue[0];
|
|
46
|
+
} else if (typeof configValue === "number" || typeof configValue === "boolean" || typeof configValue === "string") {
|
|
47
|
+
result[key] = flatValues[path] ?? configValue;
|
|
48
|
+
} else if (isSpringConfigValue(configValue) || isEasingConfigValue(configValue)) {
|
|
49
|
+
result[key] = flatValues[path] ?? configValue;
|
|
50
|
+
} else if (isActionConfigValue(configValue)) {
|
|
51
|
+
result[key] = flatValues[path] ?? configValue;
|
|
52
|
+
} else if (isSelectConfigValue(configValue)) {
|
|
53
|
+
const defaultValue = configValue.default ?? getFirstOptionValue(configValue.options);
|
|
54
|
+
result[key] = flatValues[path] ?? defaultValue;
|
|
55
|
+
} else if (isColorConfigValue(configValue)) {
|
|
56
|
+
result[key] = flatValues[path] ?? configValue.default ?? "#000000";
|
|
57
|
+
} else if (isTextConfigValue(configValue)) {
|
|
58
|
+
result[key] = flatValues[path] ?? configValue.default ?? "";
|
|
59
|
+
} else if (typeof configValue === "object" && configValue !== null) {
|
|
60
|
+
result[key] = resolveConfigValues(configValue, flatValues, path);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
function flattenConfigUpdates(config, updates, prefix, values) {
|
|
66
|
+
for (const [key, configValue] of Object.entries(config)) {
|
|
67
|
+
if (key === "_collapsed" || !(key in updates)) continue;
|
|
68
|
+
const nextValue = updates[key];
|
|
69
|
+
if (nextValue === void 0) continue;
|
|
70
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
71
|
+
if (isActionConfigValue(configValue)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (isLeafConfigValue(configValue)) {
|
|
75
|
+
values[path] = nextValue;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (typeof configValue === "object" && configValue !== null && typeof nextValue === "object" && nextValue !== null && !Array.isArray(nextValue)) {
|
|
79
|
+
flattenConfigUpdates(configValue, nextValue, path, values);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function isLeafConfigValue(value) {
|
|
84
|
+
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);
|
|
85
|
+
}
|
|
86
|
+
function hasType(value, type) {
|
|
87
|
+
return typeof value === "object" && value !== null && "type" in value && value.type === type;
|
|
88
|
+
}
|
|
89
|
+
function isSpringConfigValue(value) {
|
|
90
|
+
return hasType(value, "spring");
|
|
91
|
+
}
|
|
92
|
+
function isEasingConfigValue(value) {
|
|
93
|
+
return hasType(value, "easing");
|
|
94
|
+
}
|
|
95
|
+
function isActionConfigValue(value) {
|
|
96
|
+
return hasType(value, "action");
|
|
97
|
+
}
|
|
98
|
+
function isSelectConfigValue(value) {
|
|
99
|
+
return hasType(value, "select") && "options" in value && Array.isArray(value.options);
|
|
100
|
+
}
|
|
101
|
+
function isColorConfigValue(value) {
|
|
102
|
+
return hasType(value, "color");
|
|
103
|
+
}
|
|
104
|
+
function isTextConfigValue(value) {
|
|
105
|
+
return hasType(value, "text");
|
|
106
|
+
}
|
|
107
|
+
function getFirstOptionValue(options) {
|
|
108
|
+
const first = options[0];
|
|
109
|
+
if (first === void 0) return "";
|
|
110
|
+
return typeof first === "string" ? first : first.value;
|
|
111
|
+
}
|
|
27
112
|
var DialStoreClass = class {
|
|
28
113
|
constructor() {
|
|
29
114
|
this.panels = /* @__PURE__ */ new Map();
|
|
@@ -34,87 +119,138 @@ var DialStoreClass = class {
|
|
|
34
119
|
this.presets = /* @__PURE__ */ new Map();
|
|
35
120
|
this.activePreset = /* @__PURE__ */ new Map();
|
|
36
121
|
this.baseValues = /* @__PURE__ */ new Map();
|
|
37
|
-
|
|
38
|
-
|
|
122
|
+
this.defaultValues = /* @__PURE__ */ new Map();
|
|
123
|
+
this.registrationCounts = /* @__PURE__ */ new Map();
|
|
124
|
+
this.retainedPanels = /* @__PURE__ */ new Set();
|
|
125
|
+
this.persistConfigs = /* @__PURE__ */ new Map();
|
|
126
|
+
}
|
|
127
|
+
registerPanel(id, name, config, shortcuts, options = {}) {
|
|
128
|
+
this.configurePanelRetention(id, options);
|
|
129
|
+
this.registrationCounts.set(id, (this.registrationCounts.get(id) ?? 0) + 1);
|
|
39
130
|
const controls = this.parseConfig(config, "", shortcuts);
|
|
40
|
-
const
|
|
41
|
-
this.
|
|
131
|
+
const controlsByPath = this.mapControlsByPath(controls);
|
|
132
|
+
const defaultValues = this.flattenValues(config, "");
|
|
133
|
+
this.initTransitionModes(config, "", defaultValues);
|
|
134
|
+
const persisted = this.loadPersistedPanel(id);
|
|
135
|
+
const previousValues = this.panels.get(id)?.values ?? this.snapshots.get(id) ?? persisted?.values ?? {};
|
|
136
|
+
const values = this.reconcileValues(defaultValues, previousValues, controlsByPath);
|
|
137
|
+
const previousBaseValues = this.baseValues.get(id) ?? persisted?.baseValues ?? persisted?.values ?? {};
|
|
138
|
+
const baseValues = this.reconcileValues(defaultValues, previousBaseValues, controlsByPath);
|
|
42
139
|
this.panels.set(id, { id, name, controls, values, shortcuts: shortcuts ?? {} });
|
|
43
140
|
this.snapshots.set(id, { ...values });
|
|
44
|
-
this.baseValues.set(id,
|
|
141
|
+
this.baseValues.set(id, baseValues);
|
|
142
|
+
this.defaultValues.set(id, { ...defaultValues });
|
|
143
|
+
const existingPresets = this.presets.get(id) ?? persisted?.presets;
|
|
144
|
+
if (existingPresets) {
|
|
145
|
+
this.presets.set(id, this.reconcilePresets(existingPresets, defaultValues, controlsByPath));
|
|
146
|
+
}
|
|
147
|
+
if (!this.activePreset.has(id) && persisted?.activePresetId !== void 0) {
|
|
148
|
+
this.activePreset.set(id, persisted.activePresetId);
|
|
149
|
+
}
|
|
150
|
+
this.persistPanel(id);
|
|
151
|
+
this.notify(id);
|
|
45
152
|
this.notifyGlobal();
|
|
46
153
|
}
|
|
47
|
-
updatePanel(id, name, config, shortcuts) {
|
|
154
|
+
updatePanel(id, name, config, shortcuts, options = {}) {
|
|
155
|
+
this.configurePanelRetention(id, options);
|
|
48
156
|
const existing = this.panels.get(id);
|
|
49
157
|
if (!existing) {
|
|
50
|
-
this.registerPanel(id, name, config, shortcuts);
|
|
158
|
+
this.registerPanel(id, name, config, shortcuts, options);
|
|
51
159
|
return;
|
|
52
160
|
}
|
|
53
161
|
const controls = this.parseConfig(config, "", shortcuts);
|
|
54
162
|
const controlsByPath = this.mapControlsByPath(controls);
|
|
55
163
|
const defaultValues = this.flattenValues(config, "");
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
}
|
|
164
|
+
this.initTransitionModes(config, "", defaultValues);
|
|
165
|
+
const nextValues = this.reconcileValues(defaultValues, existing.values, controlsByPath);
|
|
75
166
|
const nextPanel = { id, name, controls, values: nextValues, shortcuts: shortcuts ?? existing.shortcuts };
|
|
76
167
|
this.panels.set(id, nextPanel);
|
|
77
168
|
this.snapshots.set(id, { ...nextValues });
|
|
78
169
|
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
|
-
}
|
|
170
|
+
const nextBaseValues = this.reconcileValues(defaultValues, previousBaseValues, controlsByPath);
|
|
87
171
|
for (const [path, value] of Object.entries(nextValues)) {
|
|
88
172
|
if (path.endsWith(".__mode")) {
|
|
89
173
|
nextBaseValues[path] = value;
|
|
90
174
|
}
|
|
91
175
|
}
|
|
92
176
|
this.baseValues.set(id, nextBaseValues);
|
|
177
|
+
this.defaultValues.set(id, { ...defaultValues });
|
|
178
|
+
this.presets.set(id, this.reconcilePresets(this.presets.get(id) ?? [], defaultValues, controlsByPath));
|
|
179
|
+
this.persistPanel(id);
|
|
93
180
|
this.notify(id);
|
|
94
181
|
this.notifyGlobal();
|
|
95
182
|
}
|
|
96
183
|
unregisterPanel(id) {
|
|
184
|
+
const nextCount = (this.registrationCounts.get(id) ?? 1) - 1;
|
|
185
|
+
if (nextCount > 0) {
|
|
186
|
+
this.registrationCounts.set(id, nextCount);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
this.registrationCounts.delete(id);
|
|
97
190
|
this.panels.delete(id);
|
|
98
191
|
this.listeners.delete(id);
|
|
99
|
-
this.snapshots.delete(id);
|
|
100
192
|
this.actionListeners.delete(id);
|
|
101
|
-
this.
|
|
193
|
+
if (!this.retainedPanels.has(id)) {
|
|
194
|
+
this.snapshots.delete(id);
|
|
195
|
+
this.baseValues.delete(id);
|
|
196
|
+
this.defaultValues.delete(id);
|
|
197
|
+
this.presets.delete(id);
|
|
198
|
+
this.activePreset.delete(id);
|
|
199
|
+
this.persistConfigs.delete(id);
|
|
200
|
+
}
|
|
102
201
|
this.notifyGlobal();
|
|
103
202
|
}
|
|
104
203
|
updateValue(panelId, path, value) {
|
|
204
|
+
this.updateValues(panelId, { [path]: value });
|
|
205
|
+
}
|
|
206
|
+
updateValues(panelId, updates) {
|
|
105
207
|
const panel = this.panels.get(panelId);
|
|
106
208
|
if (!panel) return;
|
|
107
|
-
|
|
209
|
+
const validUpdates = {};
|
|
210
|
+
for (const [path, value] of Object.entries(updates)) {
|
|
211
|
+
if (!Object.prototype.hasOwnProperty.call(panel.values, path)) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const control = this.findControlByPath(panel.controls, path);
|
|
215
|
+
if (control?.type === "action") {
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
panel.values[path] = value;
|
|
219
|
+
validUpdates[path] = value;
|
|
220
|
+
}
|
|
221
|
+
if (Object.keys(validUpdates).length === 0) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
108
224
|
const activeId = this.activePreset.get(panelId);
|
|
109
225
|
if (activeId) {
|
|
110
226
|
const presets = this.presets.get(panelId) ?? [];
|
|
111
227
|
const preset = presets.find((p) => p.id === activeId);
|
|
112
|
-
if (preset)
|
|
228
|
+
if (preset) {
|
|
229
|
+
for (const [path, value] of Object.entries(validUpdates)) {
|
|
230
|
+
preset.values[path] = value;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
113
233
|
} else {
|
|
114
234
|
const base = this.baseValues.get(panelId);
|
|
115
|
-
if (base)
|
|
235
|
+
if (base) {
|
|
236
|
+
for (const [path, value] of Object.entries(validUpdates)) {
|
|
237
|
+
base[path] = value;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
116
240
|
}
|
|
117
241
|
this.snapshots.set(panelId, { ...panel.values });
|
|
242
|
+
this.persistPanel(panelId);
|
|
243
|
+
this.notify(panelId);
|
|
244
|
+
}
|
|
245
|
+
resetValues(panelId) {
|
|
246
|
+
const panel = this.panels.get(panelId);
|
|
247
|
+
const defaults = this.defaultValues.get(panelId);
|
|
248
|
+
if (!panel || !defaults) return;
|
|
249
|
+
panel.values = { ...defaults };
|
|
250
|
+
this.snapshots.set(panelId, { ...panel.values });
|
|
251
|
+
this.baseValues.set(panelId, { ...defaults });
|
|
252
|
+
this.activePreset.set(panelId, null);
|
|
253
|
+
this.persistPanel(panelId);
|
|
118
254
|
this.notify(panelId);
|
|
119
255
|
}
|
|
120
256
|
updateSpringMode(panelId, path, mode) {
|
|
@@ -130,6 +266,7 @@ var DialStoreClass = class {
|
|
|
130
266
|
if (!panel) return;
|
|
131
267
|
panel.values[`${path}.__mode`] = mode;
|
|
132
268
|
this.snapshots.set(panelId, { ...panel.values });
|
|
269
|
+
this.persistPanel(panelId);
|
|
133
270
|
this.notify(panelId);
|
|
134
271
|
}
|
|
135
272
|
getTransitionMode(panelId, path) {
|
|
@@ -188,6 +325,7 @@ var DialStoreClass = class {
|
|
|
188
325
|
this.presets.set(panelId, [...existing, preset]);
|
|
189
326
|
this.activePreset.set(panelId, id);
|
|
190
327
|
this.snapshots.set(panelId, { ...panel.values });
|
|
328
|
+
this.persistPanel(panelId);
|
|
191
329
|
this.notify(panelId);
|
|
192
330
|
return id;
|
|
193
331
|
}
|
|
@@ -200,6 +338,7 @@ var DialStoreClass = class {
|
|
|
200
338
|
panel.values = { ...preset.values };
|
|
201
339
|
this.snapshots.set(panelId, { ...panel.values });
|
|
202
340
|
this.activePreset.set(panelId, presetId);
|
|
341
|
+
this.persistPanel(panelId);
|
|
203
342
|
this.notify(panelId);
|
|
204
343
|
}
|
|
205
344
|
deletePreset(panelId, presetId) {
|
|
@@ -212,6 +351,7 @@ var DialStoreClass = class {
|
|
|
212
351
|
if (panel) {
|
|
213
352
|
this.snapshots.set(panelId, { ...panel.values });
|
|
214
353
|
}
|
|
354
|
+
this.persistPanel(panelId);
|
|
215
355
|
this.notify(panelId);
|
|
216
356
|
}
|
|
217
357
|
getPresets(panelId) {
|
|
@@ -228,6 +368,7 @@ var DialStoreClass = class {
|
|
|
228
368
|
this.snapshots.set(panelId, { ...panel.values });
|
|
229
369
|
}
|
|
230
370
|
this.activePreset.set(panelId, null);
|
|
371
|
+
this.persistPanel(panelId);
|
|
231
372
|
this.notify(panelId);
|
|
232
373
|
}
|
|
233
374
|
resolveShortcutTarget(key, modifier) {
|
|
@@ -258,6 +399,94 @@ var DialStoreClass = class {
|
|
|
258
399
|
}
|
|
259
400
|
return results;
|
|
260
401
|
}
|
|
402
|
+
configurePanelRetention(id, options) {
|
|
403
|
+
if (options.retainOnUnmount) {
|
|
404
|
+
this.retainedPanels.add(id);
|
|
405
|
+
}
|
|
406
|
+
const persistConfig = this.normalizePersistConfig(id, options.persist);
|
|
407
|
+
if (persistConfig) {
|
|
408
|
+
this.persistConfigs.set(id, persistConfig);
|
|
409
|
+
this.retainedPanels.add(id);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
reconcileValues(defaultValues, previousValues, controlsByPath) {
|
|
413
|
+
const nextValues = {};
|
|
414
|
+
for (const [path, defaultValue] of Object.entries(defaultValues)) {
|
|
415
|
+
if (path.endsWith(".__mode")) {
|
|
416
|
+
const transitionPath = path.slice(0, -".__mode".length);
|
|
417
|
+
const transitionControl = controlsByPath.get(transitionPath);
|
|
418
|
+
nextValues[path] = transitionControl?.type === "transition" && previousValues[path] !== void 0 ? previousValues[path] : defaultValue;
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
nextValues[path] = this.normalizePreservedValue(
|
|
422
|
+
previousValues[path],
|
|
423
|
+
defaultValue,
|
|
424
|
+
controlsByPath.get(path)
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
return nextValues;
|
|
428
|
+
}
|
|
429
|
+
reconcilePresets(presets, defaultValues, controlsByPath) {
|
|
430
|
+
return presets.map((preset) => ({
|
|
431
|
+
...preset,
|
|
432
|
+
values: this.reconcileValues(defaultValues, preset.values, controlsByPath)
|
|
433
|
+
}));
|
|
434
|
+
}
|
|
435
|
+
normalizePersistConfig(id, persist) {
|
|
436
|
+
if (!persist) return null;
|
|
437
|
+
const options = typeof persist === "object" ? persist : {};
|
|
438
|
+
return {
|
|
439
|
+
key: options.key ?? `dialkit:${id}`,
|
|
440
|
+
storage: options.storage ?? "localStorage",
|
|
441
|
+
presets: options.presets ?? true
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
loadPersistedPanel(id) {
|
|
445
|
+
const config = this.persistConfigs.get(id);
|
|
446
|
+
if (!config) return null;
|
|
447
|
+
const storage = this.getStorage(config.storage);
|
|
448
|
+
if (!storage) return null;
|
|
449
|
+
try {
|
|
450
|
+
const raw = storage.getItem(config.key);
|
|
451
|
+
if (!raw) return null;
|
|
452
|
+
const parsed = JSON.parse(raw);
|
|
453
|
+
if (parsed?.version !== 1 || typeof parsed !== "object") return null;
|
|
454
|
+
return parsed;
|
|
455
|
+
} catch {
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
persistPanel(id) {
|
|
460
|
+
const config = this.persistConfigs.get(id);
|
|
461
|
+
if (!config) return;
|
|
462
|
+
const storage = this.getStorage(config.storage);
|
|
463
|
+
if (!storage) return;
|
|
464
|
+
const values = this.snapshots.get(id) ?? this.panels.get(id)?.values;
|
|
465
|
+
if (!values) return;
|
|
466
|
+
const state = {
|
|
467
|
+
version: 1,
|
|
468
|
+
values,
|
|
469
|
+
baseValues: this.baseValues.get(id) ?? values,
|
|
470
|
+
activePresetId: this.activePreset.get(id) ?? null
|
|
471
|
+
};
|
|
472
|
+
if (config.presets) {
|
|
473
|
+
state.presets = this.presets.get(id) ?? [];
|
|
474
|
+
}
|
|
475
|
+
try {
|
|
476
|
+
storage.setItem(config.key, JSON.stringify(state));
|
|
477
|
+
} catch {
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
getStorage(kind) {
|
|
481
|
+
if (typeof globalThis === "undefined" || !("window" in globalThis)) {
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
try {
|
|
485
|
+
return kind === "sessionStorage" ? globalThis.window?.sessionStorage ?? null : globalThis.window?.localStorage ?? null;
|
|
486
|
+
} catch {
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
261
490
|
findControlByPath(controls, path) {
|
|
262
491
|
for (const control of controls) {
|
|
263
492
|
if (control.path === path) return control;
|
|
@@ -485,6 +714,8 @@ var DialStoreClass = class {
|
|
|
485
714
|
var DialStore = new DialStoreClass();
|
|
486
715
|
// Annotate the CommonJS export names for ESM import in node:
|
|
487
716
|
0 && (module.exports = {
|
|
488
|
-
DialStore
|
|
717
|
+
DialStore,
|
|
718
|
+
flattenDialValueUpdates,
|
|
719
|
+
resolveDialValues
|
|
489
720
|
});
|
|
490
721
|
//# sourceMappingURL=index.cjs.map
|
package/dist/store/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/store/DialStore.ts"],"sourcesContent":["// Lightweight state store with subscriptions for dialkit\n\nexport type SpringConfig = {\n type: 'spring';\n stiffness?: number;\n damping?: number;\n mass?: number;\n visualDuration?: number;\n bounce?: number;\n};\n\nexport type EasingConfig = {\n type: 'easing';\n duration: number;\n ease: [number, number, number, number];\n};\n\nexport type TransitionConfig = SpringConfig | EasingConfig;\n\nexport type ActionConfig = {\n type: 'action';\n label?: string;\n};\n\nexport type SelectConfig = {\n type: 'select';\n options: (string | { value: string; label: string })[];\n default?: string;\n};\n\nexport type ColorConfig = {\n type: 'color';\n default?: string;\n};\n\nexport type TextConfig = {\n type: 'text';\n default?: string;\n placeholder?: string;\n};\n\nexport type DialValue = number | boolean | string | SpringConfig | EasingConfig | ActionConfig | SelectConfig | ColorConfig | TextConfig;\n\nexport type DialConfig = {\n [key: string]: DialValue | [number, number, number, number?] | DialConfig;\n};\n\nexport type ResolvedValues<T extends DialConfig> = {\n [K in keyof T]: T[K] extends [number, number, number, number?]\n ? number\n : T[K] extends SpringConfig\n ? TransitionConfig\n : T[K] extends EasingConfig\n ? TransitionConfig\n : T[K] extends SelectConfig\n ? string\n : T[K] extends ColorConfig\n ? string\n : T[K] extends TextConfig\n ? string\n : T[K] extends DialConfig\n ? ResolvedValues<T[K]>\n : T[K];\n};\n\nexport type ShortcutMode = 'fine' | 'normal' | 'coarse';\nexport type ShortcutInteraction = 'scroll' | 'drag' | 'move' | 'scroll-only';\n\nexport type ShortcutConfig = {\n key?: string;\n modifier?: 'alt' | 'shift' | 'meta';\n mode?: ShortcutMode;\n interaction?: ShortcutInteraction;\n};\n\nexport type ControlMeta = {\n type: 'slider' | 'toggle' | 'spring' | 'transition' | 'folder' | 'action' | 'select' | 'color' | 'text';\n path: string;\n label: string;\n min?: number;\n max?: number;\n step?: number;\n children?: ControlMeta[];\n defaultOpen?: boolean;\n options?: (string | { value: string; label: string })[];\n placeholder?: string;\n shortcut?: ShortcutConfig;\n};\n\nexport type PanelConfig = {\n id: string;\n name: string;\n controls: ControlMeta[];\n values: Record<string, DialValue>;\n shortcuts: Record<string, ShortcutConfig>;\n};\n\ntype Listener = () => void;\ntype ActionListener = (action: string) => void;\n\nexport type Preset = {\n id: string;\n name: string;\n values: Record<string, DialValue>;\n};\n\n// Stable empty object for unregistered panels (React 19 useSyncExternalStore requirement)\nconst EMPTY_VALUES: Record<string, DialValue> = Object.freeze({});\n\nclass DialStoreClass {\n private panels: Map<string, PanelConfig> = new Map();\n private listeners: Map<string, Set<Listener>> = new Map();\n private globalListeners: Set<Listener> = new Set();\n private snapshots: Map<string, Record<string, DialValue>> = new Map();\n private actionListeners: Map<string, Set<ActionListener>> = new Map();\n private presets: Map<string, Preset[]> = new Map();\n private activePreset: Map<string, string | null> = new Map();\n private baseValues: Map<string, Record<string, DialValue>> = new Map();\n\n registerPanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>): void {\n const controls = this.parseConfig(config, '', shortcuts);\n const values = this.flattenValues(config, '');\n\n // Set initial transition modes based on config types\n this.initTransitionModes(config, '', values);\n\n this.panels.set(id, { id, name, controls, values, shortcuts: shortcuts ?? {} });\n this.snapshots.set(id, { ...values });\n this.baseValues.set(id, { ...values });\n this.notifyGlobal();\n }\n\n updatePanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>): void {\n const existing = this.panels.get(id);\n if (!existing) {\n this.registerPanel(id, name, config, shortcuts);\n return;\n }\n\n const controls = this.parseConfig(config, '', shortcuts);\n const controlsByPath = this.mapControlsByPath(controls);\n const defaultValues = this.flattenValues(config, '');\n const nextValues: Record<string, DialValue> = {};\n\n for (const [path, defaultValue] of Object.entries(defaultValues)) {\n nextValues[path] = this.normalizePreservedValue(\n existing.values[path],\n defaultValue,\n controlsByPath.get(path)\n );\n }\n\n // Set mode defaults for new transition controls first.\n this.initTransitionModes(config, '', nextValues);\n\n for (const [path, mode] of Object.entries(existing.values)) {\n if (!path.endsWith('.__mode')) {\n continue;\n }\n\n const transitionPath = path.slice(0, -'__mode'.length - 1);\n const transitionControl = controlsByPath.get(transitionPath);\n if (transitionControl?.type === 'transition') {\n nextValues[path] = mode;\n }\n }\n\n const nextPanel: PanelConfig = { id, name, controls, values: nextValues, shortcuts: shortcuts ?? existing.shortcuts };\n this.panels.set(id, nextPanel);\n this.snapshots.set(id, { ...nextValues });\n\n const previousBaseValues = this.baseValues.get(id) ?? {};\n const nextBaseValues: Record<string, DialValue> = {};\n for (const [path, defaultValue] of Object.entries(defaultValues)) {\n nextBaseValues[path] = this.normalizePreservedValue(\n previousBaseValues[path],\n defaultValue,\n controlsByPath.get(path)\n );\n }\n\n for (const [path, value] of Object.entries(nextValues)) {\n if (path.endsWith('.__mode')) {\n nextBaseValues[path] = value;\n }\n }\n\n this.baseValues.set(id, nextBaseValues);\n\n this.notify(id);\n this.notifyGlobal();\n }\n\n unregisterPanel(id: string): void {\n this.panels.delete(id);\n this.listeners.delete(id);\n this.snapshots.delete(id);\n this.actionListeners.delete(id);\n this.baseValues.delete(id);\n this.notifyGlobal();\n }\n\n updateValue(panelId: string, path: string, value: DialValue): void {\n const panel = this.panels.get(panelId);\n if (!panel) return;\n\n panel.values[path] = value;\n\n // Auto-save to active preset or base values\n const activeId = this.activePreset.get(panelId);\n if (activeId) {\n const presets = this.presets.get(panelId) ?? [];\n const preset = presets.find(p => p.id === activeId);\n if (preset) preset.values[path] = value;\n } else {\n const base = this.baseValues.get(panelId);\n if (base) base[path] = value;\n }\n\n // Create a new snapshot reference so useSyncExternalStore detects the change\n this.snapshots.set(panelId, { ...panel.values });\n this.notify(panelId);\n }\n\n updateSpringMode(panelId: string, path: string, mode: 'simple' | 'advanced'): void {\n this.updateTransitionMode(panelId, path, mode);\n }\n\n getSpringMode(panelId: string, path: string): 'simple' | 'advanced' {\n const mode = this.getTransitionMode(panelId, path);\n if (mode === 'easing') return 'simple';\n return mode;\n }\n\n updateTransitionMode(panelId: string, path: string, mode: 'easing' | 'simple' | 'advanced'): void {\n const panel = this.panels.get(panelId);\n if (!panel) return;\n\n panel.values[`${path}.__mode`] = mode;\n this.snapshots.set(panelId, { ...panel.values });\n this.notify(panelId);\n }\n\n getTransitionMode(panelId: string, path: string): 'easing' | 'simple' | 'advanced' {\n const panel = this.panels.get(panelId);\n if (!panel) return 'simple';\n return (panel.values[`${path}.__mode`] as 'easing' | 'simple' | 'advanced') || 'simple';\n }\n\n getValue(panelId: string, path: string): DialValue | undefined {\n const panel = this.panels.get(panelId);\n return panel?.values[path];\n }\n\n getValues(panelId: string): Record<string, DialValue> {\n // Return the snapshot for useSyncExternalStore compatibility\n // Use stable EMPTY_VALUES to avoid infinite loop in React 19\n return this.snapshots.get(panelId) ?? EMPTY_VALUES;\n }\n\n getPanels(): PanelConfig[] {\n return Array.from(this.panels.values());\n }\n\n getPanel(id: string): PanelConfig | undefined {\n return this.panels.get(id);\n }\n\n subscribe(panelId: string, listener: Listener): () => void {\n if (!this.listeners.has(panelId)) {\n this.listeners.set(panelId, new Set());\n }\n this.listeners.get(panelId)!.add(listener);\n\n return () => {\n this.listeners.get(panelId)?.delete(listener);\n };\n }\n\n subscribeGlobal(listener: Listener): () => void {\n this.globalListeners.add(listener);\n return () => this.globalListeners.delete(listener);\n }\n\n subscribeActions(panelId: string, listener: ActionListener): () => void {\n if (!this.actionListeners.has(panelId)) {\n this.actionListeners.set(panelId, new Set());\n }\n this.actionListeners.get(panelId)!.add(listener);\n\n return () => {\n this.actionListeners.get(panelId)?.delete(listener);\n };\n }\n\n triggerAction(panelId: string, path: string): void {\n this.actionListeners.get(panelId)?.forEach(fn => fn(path));\n }\n\n savePreset(panelId: string, name: string): string {\n const panel = this.panels.get(panelId);\n if (!panel) throw new Error(`Panel ${panelId} not found`);\n\n const id = `preset-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n const preset: Preset = {\n id,\n name,\n values: { ...panel.values },\n };\n\n const existing = this.presets.get(panelId) ?? [];\n this.presets.set(panelId, [...existing, preset]);\n this.activePreset.set(panelId, id);\n\n // Force re-render by creating new snapshot reference\n this.snapshots.set(panelId, { ...panel.values });\n this.notify(panelId);\n\n return id;\n }\n\n loadPreset(panelId: string, presetId: string): void {\n const panel = this.panels.get(panelId);\n if (!panel) return;\n\n const presets = this.presets.get(panelId) ?? [];\n const preset = presets.find(p => p.id === presetId);\n if (!preset) return;\n\n // Apply preset values\n panel.values = { ...preset.values };\n this.snapshots.set(panelId, { ...panel.values });\n this.activePreset.set(panelId, presetId);\n this.notify(panelId);\n }\n\n deletePreset(panelId: string, presetId: string): void {\n const presets = this.presets.get(panelId) ?? [];\n this.presets.set(panelId, presets.filter(p => p.id !== presetId));\n\n // Clear active if deleted\n if (this.activePreset.get(panelId) === presetId) {\n this.activePreset.set(panelId, null);\n }\n\n // Force re-render by creating new snapshot reference\n const panel = this.panels.get(panelId);\n if (panel) {\n this.snapshots.set(panelId, { ...panel.values });\n }\n this.notify(panelId);\n }\n\n getPresets(panelId: string): Preset[] {\n return this.presets.get(panelId) ?? [];\n }\n\n getActivePresetId(panelId: string): string | null {\n return this.activePreset.get(panelId) ?? null;\n }\n\n clearActivePreset(panelId: string): void {\n const panel = this.panels.get(panelId);\n const base = this.baseValues.get(panelId);\n if (panel && base) {\n panel.values = { ...base };\n this.snapshots.set(panelId, { ...panel.values });\n }\n this.activePreset.set(panelId, null);\n this.notify(panelId);\n }\n\n resolveShortcutTarget(key: string, modifier?: 'alt' | 'shift' | 'meta'): {\n panelId: string;\n path: string;\n control: ControlMeta;\n } | null {\n for (const panel of this.panels.values()) {\n for (const [path, shortcut] of Object.entries(panel.shortcuts)) {\n if (!shortcut.key) continue; // skip keyless shortcuts\n if (shortcut.key.toLowerCase() !== key.toLowerCase()) continue;\n const scMod = shortcut.modifier ?? undefined;\n if (scMod !== modifier) continue;\n\n const control = this.findControlByPath(panel.controls, path);\n if (control) {\n return { panelId: panel.id, path, control };\n }\n }\n }\n return null;\n }\n\n resolveScrollOnlyTargets(): Array<{\n panelId: string;\n path: string;\n control: ControlMeta;\n shortcut: ShortcutConfig;\n }> {\n const results: Array<{ panelId: string; path: string; control: ControlMeta; shortcut: ShortcutConfig }> = [];\n for (const panel of this.panels.values()) {\n for (const [path, shortcut] of Object.entries(panel.shortcuts)) {\n if ((shortcut.interaction ?? 'scroll') !== 'scroll-only') continue;\n const control = this.findControlByPath(panel.controls, path);\n if (control) {\n results.push({ panelId: panel.id, path, control, shortcut });\n }\n }\n }\n return results;\n }\n\n private findControlByPath(controls: ControlMeta[], path: string): ControlMeta | null {\n for (const control of controls) {\n if (control.path === path) return control;\n if (control.type === 'folder' && control.children) {\n const found = this.findControlByPath(control.children, path);\n if (found) return found;\n }\n }\n return null;\n }\n\n private notify(panelId: string): void {\n this.listeners.get(panelId)?.forEach(fn => fn());\n }\n\n private notifyGlobal(): void {\n this.globalListeners.forEach(fn => fn());\n }\n\n private initTransitionModes(config: DialConfig, prefix: string, values: Record<string, DialValue>): void {\n for (const [key, value] of Object.entries(config)) {\n if (key === '_collapsed') continue;\n const path = prefix ? `${prefix}.${key}` : key;\n\n if (this.isEasingConfig(value)) {\n values[`${path}.__mode`] = 'easing';\n } else if (this.isSpringConfig(value)) {\n // Detect physics mode from config\n const hasPhysics = value.stiffness !== undefined || value.damping !== undefined || value.mass !== undefined;\n const hasTime = value.visualDuration !== undefined || value.bounce !== undefined;\n values[`${path}.__mode`] = hasPhysics && !hasTime ? 'advanced' : 'simple';\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value) && !this.isActionConfig(value) && !this.isSelectConfig(value) && !this.isColorConfig(value) && !this.isTextConfig(value)) {\n this.initTransitionModes(value as DialConfig, path, values);\n }\n }\n }\n\n private parseConfig(config: DialConfig, prefix: string, shortcuts?: Record<string, ShortcutConfig>): ControlMeta[] {\n const controls: ControlMeta[] = [];\n\n for (const [key, value] of Object.entries(config)) {\n if (key === '_collapsed') continue;\n const path = prefix ? `${prefix}.${key}` : key;\n const label = this.formatLabel(key);\n const shortcut = shortcuts?.[path];\n\n if (Array.isArray(value) && value.length <= 4 && typeof value[0] === 'number') {\n // Range tuple: [default, min, max]\n controls.push({\n type: 'slider',\n path,\n label,\n min: value[1],\n max: value[2],\n step: value[3] ?? this.inferStep(value[1], value[2]),\n shortcut,\n });\n } else if (typeof value === 'number') {\n // Single number - auto-infer range\n const { min, max, step } = this.inferRange(value);\n controls.push({ type: 'slider', path, label, min, max, step, shortcut });\n } else if (typeof value === 'boolean') {\n controls.push({ type: 'toggle', path, label, shortcut });\n } else if (this.isSpringConfig(value) || this.isEasingConfig(value)) {\n controls.push({ type: 'transition', path, label });\n } else if (this.isActionConfig(value)) {\n controls.push({ type: 'action', path, label: (value as ActionConfig).label || label });\n } else if (this.isSelectConfig(value)) {\n controls.push({ type: 'select', path, label, options: value.options });\n } else if (this.isColorConfig(value)) {\n controls.push({ type: 'color', path, label });\n } else if (this.isTextConfig(value)) {\n controls.push({ type: 'text', path, label, placeholder: value.placeholder });\n } else if (typeof value === 'string') {\n // Auto-detect: hex color vs text\n if (this.isHexColor(value)) {\n controls.push({ type: 'color', path, label });\n } else {\n controls.push({ type: 'text', path, label });\n }\n } else if (typeof value === 'object' && value !== null) {\n // Nested object becomes a folder\n const folderConfig = value as DialConfig;\n const defaultOpen = '_collapsed' in folderConfig ? !(folderConfig._collapsed as boolean) : true;\n controls.push({\n type: 'folder',\n path,\n label,\n defaultOpen,\n children: this.parseConfig(folderConfig, path, shortcuts),\n });\n }\n }\n\n return controls;\n }\n\n private flattenValues(config: DialConfig, prefix: string): Record<string, DialValue> {\n const values: Record<string, DialValue> = {};\n\n for (const [key, value] of Object.entries(config)) {\n if (key === '_collapsed') continue;\n const path = prefix ? `${prefix}.${key}` : key;\n\n if (Array.isArray(value) && value.length <= 4 && typeof value[0] === 'number') {\n values[path] = value[0]; // Default value\n } else if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'string') {\n values[path] = value;\n } else if (this.isSpringConfig(value) || this.isEasingConfig(value)) {\n values[path] = value;\n } else if (this.isActionConfig(value)) {\n // Actions don't need stored values - they're just triggers\n values[path] = value;\n } else if (this.isSelectConfig(value)) {\n // Use default or first option's value\n const firstOption = value.options[0];\n const firstValue = typeof firstOption === 'string' ? firstOption : firstOption.value;\n values[path] = value.default ?? firstValue;\n } else if (this.isColorConfig(value)) {\n values[path] = value.default ?? '#000000';\n } else if (this.isTextConfig(value)) {\n values[path] = value.default ?? '';\n } else if (typeof value === 'object' && value !== null) {\n Object.assign(values, this.flattenValues(value as DialConfig, path));\n }\n }\n\n return values;\n }\n\n private isSpringConfig(value: unknown): value is SpringConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as SpringConfig).type === 'spring'\n );\n }\n\n private isEasingConfig(value: unknown): value is EasingConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as EasingConfig).type === 'easing'\n );\n }\n\n private isActionConfig(value: unknown): value is ActionConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as ActionConfig).type === 'action'\n );\n }\n\n private isSelectConfig(value: unknown): value is SelectConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as SelectConfig).type === 'select' &&\n 'options' in value &&\n Array.isArray((value as SelectConfig).options)\n );\n }\n\n private isColorConfig(value: unknown): value is ColorConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as ColorConfig).type === 'color'\n );\n }\n\n private isTextConfig(value: unknown): value is TextConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as TextConfig).type === 'text'\n );\n }\n\n private isHexColor(value: string): boolean {\n return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(value);\n }\n\n private formatLabel(key: string): string {\n // Convert camelCase to Title Case\n return key\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, str => str.toUpperCase())\n .trim();\n }\n\n private inferRange(value: number): { min: number; max: number; step: number } {\n // Infer reasonable range based on value\n if (value >= 0 && value <= 1) {\n return { min: 0, max: 1, step: 0.01 };\n } else if (value >= 0 && value <= 10) {\n return { min: 0, max: value * 3 || 10, step: 0.1 };\n } else if (value >= 0 && value <= 100) {\n return { min: 0, max: value * 3 || 100, step: 1 };\n } else if (value >= 0) {\n return { min: 0, max: value * 3 || 1000, step: 10 };\n } else {\n return { min: value * 3, max: -value * 3, step: 1 };\n }\n }\n\n private inferStep(min: number, max: number): number {\n const range = max - min;\n if (range <= 1) return 0.01;\n if (range <= 10) return 0.1;\n if (range <= 100) return 1;\n return 10;\n }\n\n private normalizePreservedValue(\n existingValue: DialValue | undefined,\n defaultValue: DialValue,\n control: ControlMeta | undefined\n ): DialValue {\n if (existingValue === undefined || !control) {\n return defaultValue;\n }\n\n switch (control.type) {\n case 'slider': {\n if (typeof existingValue !== 'number' || typeof defaultValue !== 'number') {\n return defaultValue;\n }\n\n const min = control.min ?? Number.NEGATIVE_INFINITY;\n const max = control.max ?? Number.POSITIVE_INFINITY;\n const clamped = Math.min(max, Math.max(min, existingValue));\n\n if (typeof control.step !== 'number' || control.step <= 0) {\n return clamped;\n }\n\n return this.roundToStep(clamped, min, max, control.step);\n }\n case 'toggle':\n return typeof existingValue === 'boolean' ? existingValue : defaultValue;\n case 'select': {\n if (typeof existingValue !== 'string') {\n return defaultValue;\n }\n\n const options = control.options ?? [];\n const validValues = new Set(options.map((option) => (typeof option === 'string' ? option : option.value)));\n return validValues.has(existingValue) ? existingValue : defaultValue;\n }\n case 'color':\n case 'text':\n return typeof existingValue === 'string' ? existingValue : defaultValue;\n case 'transition':\n if (this.isSpringConfig(defaultValue)) {\n return this.isSpringConfig(existingValue) ? existingValue : defaultValue;\n }\n if (this.isEasingConfig(defaultValue)) {\n return this.isEasingConfig(existingValue) ? existingValue : defaultValue;\n }\n return defaultValue;\n case 'action':\n return defaultValue;\n default:\n return defaultValue;\n }\n }\n\n private roundToStep(value: number, min: number, max: number, step: number): number {\n const snapped = min + Math.round((value - min) / step) * step;\n const clamped = Math.min(max, Math.max(min, snapped));\n const precision = this.stepPrecision(step);\n return Number(clamped.toFixed(precision));\n }\n\n private stepPrecision(step: number): number {\n const text = String(step);\n const decimalIndex = text.indexOf('.');\n return decimalIndex === -1 ? 0 : text.length - decimalIndex - 1;\n }\n\n private mapControlsByPath(controls: ControlMeta[]): Map<string, ControlMeta> {\n const map = new Map<string, ControlMeta>();\n\n const visit = (nodes: ControlMeta[]) => {\n for (const node of nodes) {\n if (node.type === 'folder' && node.children) {\n visit(node.children);\n continue;\n }\n\n map.set(node.path, node);\n }\n };\n\n visit(controls);\n return map;\n }\n\n}\n\n// Singleton instance\nexport const DialStore = new DialStoreClass();\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/store/DialStore.ts"],"sourcesContent":["// Lightweight state store with subscriptions for dialkit\n\nexport type SpringConfig = {\n type: 'spring';\n stiffness?: number;\n damping?: number;\n mass?: number;\n visualDuration?: number;\n bounce?: number;\n};\n\nexport type EasingConfig = {\n type: 'easing';\n duration: number;\n ease: [number, number, number, number];\n};\n\nexport type TransitionConfig = SpringConfig | EasingConfig;\n\nexport type ActionConfig = {\n type: 'action';\n label?: string;\n};\n\nexport type SelectConfig = {\n type: 'select';\n options: (string | { value: string; label: string })[];\n default?: string;\n};\n\nexport type ColorConfig = {\n type: 'color';\n default?: string;\n};\n\nexport type TextConfig = {\n type: 'text';\n default?: string;\n placeholder?: string;\n};\n\nexport type DialValue = number | boolean | string | SpringConfig | EasingConfig | ActionConfig | SelectConfig | ColorConfig | TextConfig;\n\nexport type DialConfig = {\n [key: string]: DialValue | [number, number, number, number?] | DialConfig;\n};\n\nexport type ResolvedValues<T extends DialConfig> = {\n [K in keyof T]: T[K] extends [number, number, number, number?]\n ? number\n : T[K] extends SpringConfig\n ? TransitionConfig\n : T[K] extends EasingConfig\n ? TransitionConfig\n : T[K] extends SelectConfig\n ? string\n : T[K] extends ColorConfig\n ? string\n : T[K] extends TextConfig\n ? string\n : T[K] extends DialConfig\n ? ResolvedValues<T[K]>\n : T[K];\n};\n\nexport type DialKitValueUpdates<T extends DialConfig> = {\n [K in keyof T as K extends '_collapsed' ? never : K]?: T[K] extends [number, number, number, number?]\n ? number\n : T[K] extends SpringConfig | EasingConfig\n ? TransitionConfig\n : T[K] extends ActionConfig\n ? never\n : T[K] extends SelectConfig | ColorConfig | TextConfig\n ? string\n : T[K] extends DialConfig\n ? DialKitValueUpdates<T[K]>\n : T[K];\n};\n\nexport type ShortcutMode = 'fine' | 'normal' | 'coarse';\nexport type ShortcutInteraction = 'scroll' | 'drag' | 'move' | 'scroll-only';\n\nexport type ShortcutConfig = {\n key?: string;\n modifier?: 'alt' | 'shift' | 'meta';\n mode?: ShortcutMode;\n interaction?: ShortcutInteraction;\n};\n\nexport type ControlMeta = {\n type: 'slider' | 'toggle' | 'spring' | 'transition' | 'folder' | 'action' | 'select' | 'color' | 'text';\n path: string;\n label: string;\n min?: number;\n max?: number;\n step?: number;\n children?: ControlMeta[];\n defaultOpen?: boolean;\n options?: (string | { value: string; label: string })[];\n placeholder?: string;\n shortcut?: ShortcutConfig;\n};\n\nexport type PanelConfig = {\n id: string;\n name: string;\n controls: ControlMeta[];\n values: Record<string, DialValue>;\n shortcuts: Record<string, ShortcutConfig>;\n};\n\ntype Listener = () => void;\ntype ActionListener = (action: string) => void;\n\nexport type Preset = {\n id: string;\n name: string;\n values: Record<string, DialValue>;\n};\n\nexport type DialKitPersistOptions = boolean | {\n key?: string;\n storage?: 'localStorage' | 'sessionStorage';\n presets?: boolean;\n};\n\nexport type DialStorePanelOptions = {\n retainOnUnmount?: boolean;\n persist?: DialKitPersistOptions;\n};\n\ntype PersistConfig = {\n key: string;\n storage: 'localStorage' | 'sessionStorage';\n presets: boolean;\n};\n\ntype PersistedPanelState = {\n version: 1;\n values?: Record<string, DialValue>;\n baseValues?: Record<string, DialValue>;\n presets?: Preset[];\n activePresetId?: string | null;\n};\n\n// Stable empty object for unregistered panels (React 19 useSyncExternalStore requirement)\nconst EMPTY_VALUES: Record<string, DialValue> = Object.freeze({});\n\nexport function resolveDialValues<T extends DialConfig>(\n config: T,\n flatValues: Record<string, DialValue>\n): ResolvedValues<T> {\n return resolveConfigValues(config, flatValues, '') as ResolvedValues<T>;\n}\n\nexport function flattenDialValueUpdates<T extends DialConfig>(\n config: T,\n updates: DialKitValueUpdates<T>\n): Record<string, DialValue> {\n const values: Record<string, DialValue> = {};\n if (typeof updates === 'object' && updates !== null) {\n flattenConfigUpdates(config, updates as Record<string, unknown>, '', values);\n }\n return values;\n}\n\nfunction resolveConfigValues(\n config: DialConfig,\n flatValues: Record<string, DialValue>,\n prefix: string\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, configValue] of Object.entries(config)) {\n if (key === '_collapsed') continue;\n const path = prefix ? `${prefix}.${key}` : key;\n\n if (Array.isArray(configValue) && configValue.length <= 4 && typeof configValue[0] === 'number') {\n result[key] = flatValues[path] ?? configValue[0];\n } else if (typeof configValue === 'number' || typeof configValue === 'boolean' || typeof configValue === 'string') {\n result[key] = flatValues[path] ?? configValue;\n } else if (isSpringConfigValue(configValue) || isEasingConfigValue(configValue)) {\n result[key] = flatValues[path] ?? configValue;\n } else if (isActionConfigValue(configValue)) {\n result[key] = flatValues[path] ?? configValue;\n } else if (isSelectConfigValue(configValue)) {\n const defaultValue = configValue.default ?? getFirstOptionValue(configValue.options);\n result[key] = flatValues[path] ?? defaultValue;\n } else if (isColorConfigValue(configValue)) {\n result[key] = flatValues[path] ?? configValue.default ?? '#000000';\n } else if (isTextConfigValue(configValue)) {\n result[key] = flatValues[path] ?? configValue.default ?? '';\n } else if (typeof configValue === 'object' && configValue !== null) {\n result[key] = resolveConfigValues(configValue as DialConfig, flatValues, path);\n }\n }\n\n return result;\n}\n\nfunction flattenConfigUpdates(\n config: DialConfig,\n updates: Record<string, unknown>,\n prefix: string,\n values: Record<string, DialValue>\n): void {\n for (const [key, configValue] of Object.entries(config)) {\n if (key === '_collapsed' || !(key in updates)) continue;\n\n const nextValue = updates[key];\n if (nextValue === undefined) continue;\n\n const path = prefix ? `${prefix}.${key}` : key;\n\n if (isActionConfigValue(configValue)) {\n continue;\n }\n\n if (isLeafConfigValue(configValue)) {\n values[path] = nextValue as DialValue;\n continue;\n }\n\n if (\n typeof configValue === 'object' &&\n configValue !== null &&\n typeof nextValue === 'object' &&\n nextValue !== null &&\n !Array.isArray(nextValue)\n ) {\n flattenConfigUpdates(configValue as DialConfig, nextValue as Record<string, unknown>, path, values);\n }\n }\n}\n\nfunction isLeafConfigValue(value: unknown): boolean {\n return (\n (Array.isArray(value) && value.length <= 4 && typeof value[0] === 'number') ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n typeof value === 'string' ||\n isSpringConfigValue(value) ||\n isEasingConfigValue(value) ||\n isActionConfigValue(value) ||\n isSelectConfigValue(value) ||\n isColorConfigValue(value) ||\n isTextConfigValue(value)\n );\n}\n\nfunction hasType(value: unknown, type: string): boolean {\n return typeof value === 'object' && value !== null && 'type' in value && (value as { type: string }).type === type;\n}\n\nfunction isSpringConfigValue(value: unknown): value is SpringConfig {\n return hasType(value, 'spring');\n}\n\nfunction isEasingConfigValue(value: unknown): value is EasingConfig {\n return hasType(value, 'easing');\n}\n\nfunction isActionConfigValue(value: unknown): value is ActionConfig {\n return hasType(value, 'action');\n}\n\nfunction isSelectConfigValue(value: unknown): value is SelectConfig {\n return hasType(value, 'select') && 'options' in (value as object) && Array.isArray((value as SelectConfig).options);\n}\n\nfunction isColorConfigValue(value: unknown): value is ColorConfig {\n return hasType(value, 'color');\n}\n\nfunction isTextConfigValue(value: unknown): value is TextConfig {\n return hasType(value, 'text');\n}\n\nfunction getFirstOptionValue(options: (string | { value: string; label: string })[]): string {\n const first = options[0];\n if (first === undefined) return '';\n return typeof first === 'string' ? first : first.value;\n}\n\nclass DialStoreClass {\n private panels: Map<string, PanelConfig> = new Map();\n private listeners: Map<string, Set<Listener>> = new Map();\n private globalListeners: Set<Listener> = new Set();\n private snapshots: Map<string, Record<string, DialValue>> = new Map();\n private actionListeners: Map<string, Set<ActionListener>> = new Map();\n private presets: Map<string, Preset[]> = new Map();\n private activePreset: Map<string, string | null> = new Map();\n private baseValues: Map<string, Record<string, DialValue>> = new Map();\n private defaultValues: Map<string, Record<string, DialValue>> = new Map();\n private registrationCounts: Map<string, number> = new Map();\n private retainedPanels: Set<string> = new Set();\n private persistConfigs: Map<string, PersistConfig> = new Map();\n\n registerPanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>, options: DialStorePanelOptions = {}): void {\n this.configurePanelRetention(id, options);\n this.registrationCounts.set(id, (this.registrationCounts.get(id) ?? 0) + 1);\n\n const controls = this.parseConfig(config, '', shortcuts);\n const controlsByPath = this.mapControlsByPath(controls);\n const defaultValues = this.flattenValues(config, '');\n\n // Set initial transition modes based on config types\n this.initTransitionModes(config, '', defaultValues);\n\n const persisted = this.loadPersistedPanel(id);\n const previousValues = this.panels.get(id)?.values ?? this.snapshots.get(id) ?? persisted?.values ?? {};\n const values = this.reconcileValues(defaultValues, previousValues, controlsByPath);\n\n const previousBaseValues = this.baseValues.get(id) ?? persisted?.baseValues ?? persisted?.values ?? {};\n const baseValues = this.reconcileValues(defaultValues, previousBaseValues, controlsByPath);\n\n this.panels.set(id, { id, name, controls, values, shortcuts: shortcuts ?? {} });\n this.snapshots.set(id, { ...values });\n this.baseValues.set(id, baseValues);\n this.defaultValues.set(id, { ...defaultValues });\n\n const existingPresets = this.presets.get(id) ?? persisted?.presets;\n if (existingPresets) {\n this.presets.set(id, this.reconcilePresets(existingPresets, defaultValues, controlsByPath));\n }\n if (!this.activePreset.has(id) && persisted?.activePresetId !== undefined) {\n this.activePreset.set(id, persisted.activePresetId);\n }\n\n this.persistPanel(id);\n this.notify(id);\n this.notifyGlobal();\n }\n\n updatePanel(id: string, name: string, config: DialConfig, shortcuts?: Record<string, ShortcutConfig>, options: DialStorePanelOptions = {}): void {\n this.configurePanelRetention(id, options);\n const existing = this.panels.get(id);\n if (!existing) {\n this.registerPanel(id, name, config, shortcuts, options);\n return;\n }\n\n const controls = this.parseConfig(config, '', shortcuts);\n const controlsByPath = this.mapControlsByPath(controls);\n const defaultValues = this.flattenValues(config, '');\n this.initTransitionModes(config, '', defaultValues);\n const nextValues = this.reconcileValues(defaultValues, existing.values, controlsByPath);\n\n const nextPanel: PanelConfig = { id, name, controls, values: nextValues, shortcuts: shortcuts ?? existing.shortcuts };\n this.panels.set(id, nextPanel);\n this.snapshots.set(id, { ...nextValues });\n\n const previousBaseValues = this.baseValues.get(id) ?? {};\n const nextBaseValues = this.reconcileValues(defaultValues, previousBaseValues, controlsByPath);\n\n for (const [path, value] of Object.entries(nextValues)) {\n if (path.endsWith('.__mode')) {\n nextBaseValues[path] = value;\n }\n }\n\n this.baseValues.set(id, nextBaseValues);\n this.defaultValues.set(id, { ...defaultValues });\n this.presets.set(id, this.reconcilePresets(this.presets.get(id) ?? [], defaultValues, controlsByPath));\n\n this.persistPanel(id);\n this.notify(id);\n this.notifyGlobal();\n }\n\n unregisterPanel(id: string): void {\n const nextCount = (this.registrationCounts.get(id) ?? 1) - 1;\n if (nextCount > 0) {\n this.registrationCounts.set(id, nextCount);\n return;\n }\n\n this.registrationCounts.delete(id);\n this.panels.delete(id);\n this.listeners.delete(id);\n this.actionListeners.delete(id);\n\n if (!this.retainedPanels.has(id)) {\n this.snapshots.delete(id);\n this.baseValues.delete(id);\n this.defaultValues.delete(id);\n this.presets.delete(id);\n this.activePreset.delete(id);\n this.persistConfigs.delete(id);\n }\n\n this.notifyGlobal();\n }\n\n updateValue(panelId: string, path: string, value: DialValue): void {\n this.updateValues(panelId, { [path]: value });\n }\n\n updateValues(panelId: string, updates: Record<string, DialValue>): void {\n const panel = this.panels.get(panelId);\n if (!panel) return;\n\n const validUpdates: Record<string, DialValue> = {};\n\n for (const [path, value] of Object.entries(updates)) {\n if (!Object.prototype.hasOwnProperty.call(panel.values, path)) {\n continue;\n }\n\n const control = this.findControlByPath(panel.controls, path);\n if (control?.type === 'action') {\n continue;\n }\n\n panel.values[path] = value;\n validUpdates[path] = value;\n }\n\n if (Object.keys(validUpdates).length === 0) {\n return;\n }\n\n // Auto-save to active preset or base values\n const activeId = this.activePreset.get(panelId);\n if (activeId) {\n const presets = this.presets.get(panelId) ?? [];\n const preset = presets.find(p => p.id === activeId);\n if (preset) {\n for (const [path, value] of Object.entries(validUpdates)) {\n preset.values[path] = value;\n }\n }\n } else {\n const base = this.baseValues.get(panelId);\n if (base) {\n for (const [path, value] of Object.entries(validUpdates)) {\n base[path] = value;\n }\n }\n }\n\n // Create a new snapshot reference so useSyncExternalStore detects the change\n this.snapshots.set(panelId, { ...panel.values });\n this.persistPanel(panelId);\n this.notify(panelId);\n }\n\n resetValues(panelId: string): void {\n const panel = this.panels.get(panelId);\n const defaults = this.defaultValues.get(panelId);\n if (!panel || !defaults) return;\n\n panel.values = { ...defaults };\n this.snapshots.set(panelId, { ...panel.values });\n this.baseValues.set(panelId, { ...defaults });\n this.activePreset.set(panelId, null);\n this.persistPanel(panelId);\n this.notify(panelId);\n }\n\n updateSpringMode(panelId: string, path: string, mode: 'simple' | 'advanced'): void {\n this.updateTransitionMode(panelId, path, mode);\n }\n\n getSpringMode(panelId: string, path: string): 'simple' | 'advanced' {\n const mode = this.getTransitionMode(panelId, path);\n if (mode === 'easing') return 'simple';\n return mode;\n }\n\n updateTransitionMode(panelId: string, path: string, mode: 'easing' | 'simple' | 'advanced'): void {\n const panel = this.panels.get(panelId);\n if (!panel) return;\n\n panel.values[`${path}.__mode`] = mode;\n this.snapshots.set(panelId, { ...panel.values });\n this.persistPanel(panelId);\n this.notify(panelId);\n }\n\n getTransitionMode(panelId: string, path: string): 'easing' | 'simple' | 'advanced' {\n const panel = this.panels.get(panelId);\n if (!panel) return 'simple';\n return (panel.values[`${path}.__mode`] as 'easing' | 'simple' | 'advanced') || 'simple';\n }\n\n getValue(panelId: string, path: string): DialValue | undefined {\n const panel = this.panels.get(panelId);\n return panel?.values[path];\n }\n\n getValues(panelId: string): Record<string, DialValue> {\n // Return the snapshot for useSyncExternalStore compatibility\n // Use stable EMPTY_VALUES to avoid infinite loop in React 19\n return this.snapshots.get(panelId) ?? EMPTY_VALUES;\n }\n\n getPanels(): PanelConfig[] {\n return Array.from(this.panels.values());\n }\n\n getPanel(id: string): PanelConfig | undefined {\n return this.panels.get(id);\n }\n\n subscribe(panelId: string, listener: Listener): () => void {\n if (!this.listeners.has(panelId)) {\n this.listeners.set(panelId, new Set());\n }\n this.listeners.get(panelId)!.add(listener);\n\n return () => {\n this.listeners.get(panelId)?.delete(listener);\n };\n }\n\n subscribeGlobal(listener: Listener): () => void {\n this.globalListeners.add(listener);\n return () => this.globalListeners.delete(listener);\n }\n\n subscribeActions(panelId: string, listener: ActionListener): () => void {\n if (!this.actionListeners.has(panelId)) {\n this.actionListeners.set(panelId, new Set());\n }\n this.actionListeners.get(panelId)!.add(listener);\n\n return () => {\n this.actionListeners.get(panelId)?.delete(listener);\n };\n }\n\n triggerAction(panelId: string, path: string): void {\n this.actionListeners.get(panelId)?.forEach(fn => fn(path));\n }\n\n savePreset(panelId: string, name: string): string {\n const panel = this.panels.get(panelId);\n if (!panel) throw new Error(`Panel ${panelId} not found`);\n\n const id = `preset-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n const preset: Preset = {\n id,\n name,\n values: { ...panel.values },\n };\n\n const existing = this.presets.get(panelId) ?? [];\n this.presets.set(panelId, [...existing, preset]);\n this.activePreset.set(panelId, id);\n\n // Force re-render by creating new snapshot reference\n this.snapshots.set(panelId, { ...panel.values });\n this.persistPanel(panelId);\n this.notify(panelId);\n\n return id;\n }\n\n loadPreset(panelId: string, presetId: string): void {\n const panel = this.panels.get(panelId);\n if (!panel) return;\n\n const presets = this.presets.get(panelId) ?? [];\n const preset = presets.find(p => p.id === presetId);\n if (!preset) return;\n\n // Apply preset values\n panel.values = { ...preset.values };\n this.snapshots.set(panelId, { ...panel.values });\n this.activePreset.set(panelId, presetId);\n this.persistPanel(panelId);\n this.notify(panelId);\n }\n\n deletePreset(panelId: string, presetId: string): void {\n const presets = this.presets.get(panelId) ?? [];\n this.presets.set(panelId, presets.filter(p => p.id !== presetId));\n\n // Clear active if deleted\n if (this.activePreset.get(panelId) === presetId) {\n this.activePreset.set(panelId, null);\n }\n\n // Force re-render by creating new snapshot reference\n const panel = this.panels.get(panelId);\n if (panel) {\n this.snapshots.set(panelId, { ...panel.values });\n }\n this.persistPanel(panelId);\n this.notify(panelId);\n }\n\n getPresets(panelId: string): Preset[] {\n return this.presets.get(panelId) ?? [];\n }\n\n getActivePresetId(panelId: string): string | null {\n return this.activePreset.get(panelId) ?? null;\n }\n\n clearActivePreset(panelId: string): void {\n const panel = this.panels.get(panelId);\n const base = this.baseValues.get(panelId);\n if (panel && base) {\n panel.values = { ...base };\n this.snapshots.set(panelId, { ...panel.values });\n }\n this.activePreset.set(panelId, null);\n this.persistPanel(panelId);\n this.notify(panelId);\n }\n\n resolveShortcutTarget(key: string, modifier?: 'alt' | 'shift' | 'meta'): {\n panelId: string;\n path: string;\n control: ControlMeta;\n } | null {\n for (const panel of this.panels.values()) {\n for (const [path, shortcut] of Object.entries(panel.shortcuts)) {\n if (!shortcut.key) continue; // skip keyless shortcuts\n if (shortcut.key.toLowerCase() !== key.toLowerCase()) continue;\n const scMod = shortcut.modifier ?? undefined;\n if (scMod !== modifier) continue;\n\n const control = this.findControlByPath(panel.controls, path);\n if (control) {\n return { panelId: panel.id, path, control };\n }\n }\n }\n return null;\n }\n\n resolveScrollOnlyTargets(): Array<{\n panelId: string;\n path: string;\n control: ControlMeta;\n shortcut: ShortcutConfig;\n }> {\n const results: Array<{ panelId: string; path: string; control: ControlMeta; shortcut: ShortcutConfig }> = [];\n for (const panel of this.panels.values()) {\n for (const [path, shortcut] of Object.entries(panel.shortcuts)) {\n if ((shortcut.interaction ?? 'scroll') !== 'scroll-only') continue;\n const control = this.findControlByPath(panel.controls, path);\n if (control) {\n results.push({ panelId: panel.id, path, control, shortcut });\n }\n }\n }\n return results;\n }\n\n private configurePanelRetention(id: string, options: DialStorePanelOptions): void {\n if (options.retainOnUnmount) {\n this.retainedPanels.add(id);\n }\n\n const persistConfig = this.normalizePersistConfig(id, options.persist);\n if (persistConfig) {\n this.persistConfigs.set(id, persistConfig);\n this.retainedPanels.add(id);\n }\n }\n\n private reconcileValues(\n defaultValues: Record<string, DialValue>,\n previousValues: Record<string, DialValue>,\n controlsByPath: Map<string, ControlMeta>\n ): Record<string, DialValue> {\n const nextValues: Record<string, DialValue> = {};\n\n for (const [path, defaultValue] of Object.entries(defaultValues)) {\n if (path.endsWith('.__mode')) {\n const transitionPath = path.slice(0, -'.__mode'.length);\n const transitionControl = controlsByPath.get(transitionPath);\n nextValues[path] = transitionControl?.type === 'transition' && previousValues[path] !== undefined\n ? previousValues[path]\n : defaultValue;\n continue;\n }\n\n nextValues[path] = this.normalizePreservedValue(\n previousValues[path],\n defaultValue,\n controlsByPath.get(path)\n );\n }\n\n return nextValues;\n }\n\n private reconcilePresets(\n presets: Preset[],\n defaultValues: Record<string, DialValue>,\n controlsByPath: Map<string, ControlMeta>\n ): Preset[] {\n return presets.map((preset) => ({\n ...preset,\n values: this.reconcileValues(defaultValues, preset.values, controlsByPath),\n }));\n }\n\n private normalizePersistConfig(id: string, persist: DialKitPersistOptions | undefined): PersistConfig | null {\n if (!persist) return null;\n const options = typeof persist === 'object' ? persist : {};\n return {\n key: options.key ?? `dialkit:${id}`,\n storage: options.storage ?? 'localStorage',\n presets: options.presets ?? true,\n };\n }\n\n private loadPersistedPanel(id: string): PersistedPanelState | null {\n const config = this.persistConfigs.get(id);\n if (!config) return null;\n\n const storage = this.getStorage(config.storage);\n if (!storage) return null;\n\n try {\n const raw = storage.getItem(config.key);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as PersistedPanelState;\n if (parsed?.version !== 1 || typeof parsed !== 'object') return null;\n return parsed;\n } catch {\n return null;\n }\n }\n\n private persistPanel(id: string): void {\n const config = this.persistConfigs.get(id);\n if (!config) return;\n\n const storage = this.getStorage(config.storage);\n if (!storage) return;\n\n const values = this.snapshots.get(id) ?? this.panels.get(id)?.values;\n if (!values) return;\n\n const state: PersistedPanelState = {\n version: 1,\n values,\n baseValues: this.baseValues.get(id) ?? values,\n activePresetId: this.activePreset.get(id) ?? null,\n };\n\n if (config.presets) {\n state.presets = this.presets.get(id) ?? [];\n }\n\n try {\n storage.setItem(config.key, JSON.stringify(state));\n } catch {\n // Ignore storage quota/security errors; DialKit should still work in-memory.\n }\n }\n\n private getStorage(kind: 'localStorage' | 'sessionStorage'): Storage | null {\n if (typeof globalThis === 'undefined' || !('window' in globalThis)) {\n return null;\n }\n\n try {\n return kind === 'sessionStorage'\n ? globalThis.window?.sessionStorage ?? null\n : globalThis.window?.localStorage ?? null;\n } catch {\n return null;\n }\n }\n\n private findControlByPath(controls: ControlMeta[], path: string): ControlMeta | null {\n for (const control of controls) {\n if (control.path === path) return control;\n if (control.type === 'folder' && control.children) {\n const found = this.findControlByPath(control.children, path);\n if (found) return found;\n }\n }\n return null;\n }\n\n private notify(panelId: string): void {\n this.listeners.get(panelId)?.forEach(fn => fn());\n }\n\n private notifyGlobal(): void {\n this.globalListeners.forEach(fn => fn());\n }\n\n private initTransitionModes(config: DialConfig, prefix: string, values: Record<string, DialValue>): void {\n for (const [key, value] of Object.entries(config)) {\n if (key === '_collapsed') continue;\n const path = prefix ? `${prefix}.${key}` : key;\n\n if (this.isEasingConfig(value)) {\n values[`${path}.__mode`] = 'easing';\n } else if (this.isSpringConfig(value)) {\n // Detect physics mode from config\n const hasPhysics = value.stiffness !== undefined || value.damping !== undefined || value.mass !== undefined;\n const hasTime = value.visualDuration !== undefined || value.bounce !== undefined;\n values[`${path}.__mode`] = hasPhysics && !hasTime ? 'advanced' : 'simple';\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value) && !this.isActionConfig(value) && !this.isSelectConfig(value) && !this.isColorConfig(value) && !this.isTextConfig(value)) {\n this.initTransitionModes(value as DialConfig, path, values);\n }\n }\n }\n\n private parseConfig(config: DialConfig, prefix: string, shortcuts?: Record<string, ShortcutConfig>): ControlMeta[] {\n const controls: ControlMeta[] = [];\n\n for (const [key, value] of Object.entries(config)) {\n if (key === '_collapsed') continue;\n const path = prefix ? `${prefix}.${key}` : key;\n const label = this.formatLabel(key);\n const shortcut = shortcuts?.[path];\n\n if (Array.isArray(value) && value.length <= 4 && typeof value[0] === 'number') {\n // Range tuple: [default, min, max]\n controls.push({\n type: 'slider',\n path,\n label,\n min: value[1],\n max: value[2],\n step: value[3] ?? this.inferStep(value[1], value[2]),\n shortcut,\n });\n } else if (typeof value === 'number') {\n // Single number - auto-infer range\n const { min, max, step } = this.inferRange(value);\n controls.push({ type: 'slider', path, label, min, max, step, shortcut });\n } else if (typeof value === 'boolean') {\n controls.push({ type: 'toggle', path, label, shortcut });\n } else if (this.isSpringConfig(value) || this.isEasingConfig(value)) {\n controls.push({ type: 'transition', path, label });\n } else if (this.isActionConfig(value)) {\n controls.push({ type: 'action', path, label: (value as ActionConfig).label || label });\n } else if (this.isSelectConfig(value)) {\n controls.push({ type: 'select', path, label, options: value.options });\n } else if (this.isColorConfig(value)) {\n controls.push({ type: 'color', path, label });\n } else if (this.isTextConfig(value)) {\n controls.push({ type: 'text', path, label, placeholder: value.placeholder });\n } else if (typeof value === 'string') {\n // Auto-detect: hex color vs text\n if (this.isHexColor(value)) {\n controls.push({ type: 'color', path, label });\n } else {\n controls.push({ type: 'text', path, label });\n }\n } else if (typeof value === 'object' && value !== null) {\n // Nested object becomes a folder\n const folderConfig = value as DialConfig;\n const defaultOpen = '_collapsed' in folderConfig ? !(folderConfig._collapsed as boolean) : true;\n controls.push({\n type: 'folder',\n path,\n label,\n defaultOpen,\n children: this.parseConfig(folderConfig, path, shortcuts),\n });\n }\n }\n\n return controls;\n }\n\n private flattenValues(config: DialConfig, prefix: string): Record<string, DialValue> {\n const values: Record<string, DialValue> = {};\n\n for (const [key, value] of Object.entries(config)) {\n if (key === '_collapsed') continue;\n const path = prefix ? `${prefix}.${key}` : key;\n\n if (Array.isArray(value) && value.length <= 4 && typeof value[0] === 'number') {\n values[path] = value[0]; // Default value\n } else if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'string') {\n values[path] = value;\n } else if (this.isSpringConfig(value) || this.isEasingConfig(value)) {\n values[path] = value;\n } else if (this.isActionConfig(value)) {\n // Actions don't need stored values - they're just triggers\n values[path] = value;\n } else if (this.isSelectConfig(value)) {\n // Use default or first option's value\n const firstOption = value.options[0];\n const firstValue = typeof firstOption === 'string' ? firstOption : firstOption.value;\n values[path] = value.default ?? firstValue;\n } else if (this.isColorConfig(value)) {\n values[path] = value.default ?? '#000000';\n } else if (this.isTextConfig(value)) {\n values[path] = value.default ?? '';\n } else if (typeof value === 'object' && value !== null) {\n Object.assign(values, this.flattenValues(value as DialConfig, path));\n }\n }\n\n return values;\n }\n\n private isSpringConfig(value: unknown): value is SpringConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as SpringConfig).type === 'spring'\n );\n }\n\n private isEasingConfig(value: unknown): value is EasingConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as EasingConfig).type === 'easing'\n );\n }\n\n private isActionConfig(value: unknown): value is ActionConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as ActionConfig).type === 'action'\n );\n }\n\n private isSelectConfig(value: unknown): value is SelectConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as SelectConfig).type === 'select' &&\n 'options' in value &&\n Array.isArray((value as SelectConfig).options)\n );\n }\n\n private isColorConfig(value: unknown): value is ColorConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as ColorConfig).type === 'color'\n );\n }\n\n private isTextConfig(value: unknown): value is TextConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n (value as TextConfig).type === 'text'\n );\n }\n\n private isHexColor(value: string): boolean {\n return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(value);\n }\n\n private formatLabel(key: string): string {\n // Convert camelCase to Title Case\n return key\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, str => str.toUpperCase())\n .trim();\n }\n\n private inferRange(value: number): { min: number; max: number; step: number } {\n // Infer reasonable range based on value\n if (value >= 0 && value <= 1) {\n return { min: 0, max: 1, step: 0.01 };\n } else if (value >= 0 && value <= 10) {\n return { min: 0, max: value * 3 || 10, step: 0.1 };\n } else if (value >= 0 && value <= 100) {\n return { min: 0, max: value * 3 || 100, step: 1 };\n } else if (value >= 0) {\n return { min: 0, max: value * 3 || 1000, step: 10 };\n } else {\n return { min: value * 3, max: -value * 3, step: 1 };\n }\n }\n\n private inferStep(min: number, max: number): number {\n const range = max - min;\n if (range <= 1) return 0.01;\n if (range <= 10) return 0.1;\n if (range <= 100) return 1;\n return 10;\n }\n\n private normalizePreservedValue(\n existingValue: DialValue | undefined,\n defaultValue: DialValue,\n control: ControlMeta | undefined\n ): DialValue {\n if (existingValue === undefined || !control) {\n return defaultValue;\n }\n\n switch (control.type) {\n case 'slider': {\n if (typeof existingValue !== 'number' || typeof defaultValue !== 'number') {\n return defaultValue;\n }\n\n const min = control.min ?? Number.NEGATIVE_INFINITY;\n const max = control.max ?? Number.POSITIVE_INFINITY;\n const clamped = Math.min(max, Math.max(min, existingValue));\n\n if (typeof control.step !== 'number' || control.step <= 0) {\n return clamped;\n }\n\n return this.roundToStep(clamped, min, max, control.step);\n }\n case 'toggle':\n return typeof existingValue === 'boolean' ? existingValue : defaultValue;\n case 'select': {\n if (typeof existingValue !== 'string') {\n return defaultValue;\n }\n\n const options = control.options ?? [];\n const validValues = new Set(options.map((option) => (typeof option === 'string' ? option : option.value)));\n return validValues.has(existingValue) ? existingValue : defaultValue;\n }\n case 'color':\n case 'text':\n return typeof existingValue === 'string' ? existingValue : defaultValue;\n case 'transition':\n if (this.isSpringConfig(defaultValue)) {\n return this.isSpringConfig(existingValue) ? existingValue : defaultValue;\n }\n if (this.isEasingConfig(defaultValue)) {\n return this.isEasingConfig(existingValue) ? existingValue : defaultValue;\n }\n return defaultValue;\n case 'action':\n return defaultValue;\n default:\n return defaultValue;\n }\n }\n\n private roundToStep(value: number, min: number, max: number, step: number): number {\n const snapped = min + Math.round((value - min) / step) * step;\n const clamped = Math.min(max, Math.max(min, snapped));\n const precision = this.stepPrecision(step);\n return Number(clamped.toFixed(precision));\n }\n\n private stepPrecision(step: number): number {\n const text = String(step);\n const decimalIndex = text.indexOf('.');\n return decimalIndex === -1 ? 0 : text.length - decimalIndex - 1;\n }\n\n private mapControlsByPath(controls: ControlMeta[]): Map<string, ControlMeta> {\n const map = new Map<string, ControlMeta>();\n\n const visit = (nodes: ControlMeta[]) => {\n for (const node of nodes) {\n if (node.type === 'folder' && node.children) {\n visit(node.children);\n continue;\n }\n\n map.set(node.path, node);\n }\n };\n\n visit(controls);\n return map;\n }\n\n}\n\n// Singleton instance\nexport const DialStore = new DialStoreClass();\n"],"mappings":"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","names":[]}
|