@vib3code/sdk 2.0.1 → 2.0.3-canary.0a63e71

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 (192) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +245 -0
  3. package/DOCS/ANDROID_DEPLOYMENT.md +59 -0
  4. package/DOCS/ARCHITECTURE.md +1 -0
  5. package/DOCS/CI_TESTING.md +2 -0
  6. package/DOCS/CLI_ONBOARDING.md +3 -1
  7. package/DOCS/CONTROL_REFERENCE.md +2 -0
  8. package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +119 -0
  9. package/DOCS/ENV_SETUP.md +2 -0
  10. package/DOCS/EPIC_SCROLL_EVENTS.md +775 -0
  11. package/DOCS/EXPANSION_DESIGN.md +979 -0
  12. package/DOCS/EXPANSION_DESIGN_ULTRA.md +389 -0
  13. package/DOCS/EXPORT_FORMATS.md +2 -0
  14. package/DOCS/GPU_DISPOSAL_GUIDE.md +2 -0
  15. package/DOCS/HANDOFF_LANDING_PAGE.md +156 -0
  16. package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +495 -0
  17. package/DOCS/LICENSING_TIERS.md +2 -0
  18. package/DOCS/MASTER_PLAN_2026-01-31.md +4 -2
  19. package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +939 -0
  20. package/DOCS/OBS_SETUP_GUIDE.md +2 -0
  21. package/DOCS/OPTIMIZATION_PLAN_MATH.md +119 -0
  22. package/DOCS/PRODUCT_STRATEGY.md +65 -0
  23. package/DOCS/PROJECT_SETUP.md +2 -0
  24. package/DOCS/README.md +105 -0
  25. package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +99 -0
  26. package/DOCS/RENDERER_LIFECYCLE.md +2 -0
  27. package/DOCS/REPO_MANIFEST.md +2 -0
  28. package/DOCS/ROADMAP.md +113 -0
  29. package/DOCS/SCROLL_TIMELINE_v3.md +271 -0
  30. package/DOCS/SITE_REFACTOR_PLAN.md +102 -0
  31. package/DOCS/STATUS.md +26 -0
  32. package/DOCS/SYSTEM_INVENTORY.md +37 -32
  33. package/DOCS/TELEMETRY_EXPORTS.md +2 -0
  34. package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +87 -0
  35. package/DOCS/VISUAL_ANALYSIS_FACETAD.md +135 -0
  36. package/DOCS/VISUAL_ANALYSIS_SIMONE.md +97 -0
  37. package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +88 -0
  38. package/DOCS/WEBGPU_STATUS.md +121 -38
  39. package/DOCS/XR_BENCHMARKS.md +2 -0
  40. package/DOCS/archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +1 -0
  41. package/DOCS/archive/DEV_TRACK_ANALYSIS.md +1 -0
  42. package/DOCS/archive/DEV_TRACK_PLAN_2026-01-07.md +1 -0
  43. package/DOCS/archive/SESSION_014_PLAN.md +1 -0
  44. package/DOCS/archive/SESSION_LOG_2026-01-07.md +1 -0
  45. package/DOCS/archive/STRATEGIC_BLUEPRINT_2026-01-07.md +1 -0
  46. package/DOCS/archive/SYSTEM_AUDIT_2026-01-30.md +1 -0
  47. package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +1 -0
  48. package/DOCS/{DEV_TRACK_SESSION_2026-01-31.md → dev-tracks/DEV_TRACK_SESSION_2026-01-31.md} +3 -1
  49. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +233 -0
  50. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +129 -0
  51. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +144 -0
  52. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +110 -0
  53. package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +310 -0
  54. package/DOCS/dev-tracks/README.md +12 -0
  55. package/README.md +26 -13
  56. package/cpp/CMakeLists.txt +236 -0
  57. package/cpp/bindings/embind.cpp +269 -0
  58. package/cpp/build.sh +129 -0
  59. package/cpp/geometry/Crystal.cpp +103 -0
  60. package/cpp/geometry/Fractal.cpp +136 -0
  61. package/cpp/geometry/GeometryGenerator.cpp +262 -0
  62. package/cpp/geometry/KleinBottle.cpp +71 -0
  63. package/cpp/geometry/Sphere.cpp +134 -0
  64. package/cpp/geometry/Tesseract.cpp +94 -0
  65. package/cpp/geometry/Tetrahedron.cpp +83 -0
  66. package/cpp/geometry/Torus.cpp +65 -0
  67. package/cpp/geometry/WarpFunctions.cpp +238 -0
  68. package/cpp/geometry/Wave.cpp +85 -0
  69. package/cpp/include/vib3_ffi.h +238 -0
  70. package/cpp/math/Mat4x4.cpp +409 -0
  71. package/cpp/math/Mat4x4.hpp +209 -0
  72. package/cpp/math/Projection.cpp +142 -0
  73. package/cpp/math/Projection.hpp +148 -0
  74. package/cpp/math/Rotor4D.cpp +322 -0
  75. package/cpp/math/Rotor4D.hpp +204 -0
  76. package/cpp/math/Vec4.cpp +303 -0
  77. package/cpp/math/Vec4.hpp +225 -0
  78. package/cpp/src/vib3_ffi.cpp +607 -0
  79. package/cpp/tests/Geometry_test.cpp +213 -0
  80. package/cpp/tests/Mat4x4_test.cpp +494 -0
  81. package/cpp/tests/Projection_test.cpp +298 -0
  82. package/cpp/tests/Rotor4D_test.cpp +423 -0
  83. package/cpp/tests/Vec4_test.cpp +489 -0
  84. package/docs/webgpu-live.html +1 -1
  85. package/package.json +41 -30
  86. package/src/agent/index.js +1 -3
  87. package/src/agent/mcp/MCPServer.js +1220 -144
  88. package/src/agent/mcp/index.js +1 -1
  89. package/src/agent/mcp/stdio-server.js +264 -0
  90. package/src/agent/mcp/tools.js +498 -31
  91. package/src/cli/index.js +431 -47
  92. package/src/core/CanvasManager.js +97 -204
  93. package/src/core/ErrorReporter.js +1 -1
  94. package/src/core/Parameters.js +1 -1
  95. package/src/core/VIB3Engine.js +93 -4
  96. package/src/core/VitalitySystem.js +53 -0
  97. package/src/core/index.js +18 -0
  98. package/src/core/renderers/FacetedRendererAdapter.js +10 -9
  99. package/src/core/renderers/HolographicRendererAdapter.js +13 -9
  100. package/src/core/renderers/QuantumRendererAdapter.js +11 -7
  101. package/src/creative/AestheticMapper.js +628 -0
  102. package/src/creative/ChoreographyPlayer.js +481 -0
  103. package/src/creative/index.js +11 -0
  104. package/src/experimental/GameLoop.js +72 -0
  105. package/src/experimental/LatticePhysics.js +100 -0
  106. package/src/experimental/LiveDirector.js +143 -0
  107. package/src/experimental/PlayerController4D.js +154 -0
  108. package/src/experimental/VIB3Actor.js +138 -0
  109. package/src/experimental/VIB3Compositor.js +117 -0
  110. package/src/experimental/VIB3Link.js +122 -0
  111. package/src/experimental/VIB3Orchestrator.js +146 -0
  112. package/src/experimental/VIB3Universe.js +109 -0
  113. package/src/experimental/demos/CrystalLabyrinth.js +202 -0
  114. package/src/export/TradingCardManager.js +3 -4
  115. package/src/export/index.js +11 -1
  116. package/src/faceted/FacetedSystem.js +260 -394
  117. package/src/games/glyph-war/GlyphWarVisualizer.js +641 -0
  118. package/src/geometry/generators/Crystal.js +2 -2
  119. package/src/geometry/warp/HypersphereCore.js +53 -24
  120. package/src/holograms/HolographicVisualizer.js +84 -98
  121. package/src/holograms/RealHolographicSystem.js +194 -43
  122. package/src/math/Mat4x4.js +308 -105
  123. package/src/math/Rotor4D.js +124 -40
  124. package/src/math/Vec4.js +200 -103
  125. package/src/math/index.js +7 -7
  126. package/src/polychora/PolychoraSystem.js +77 -0
  127. package/src/quantum/QuantumEngine.js +103 -66
  128. package/src/quantum/QuantumVisualizer.js +31 -22
  129. package/src/reactivity/index.js +3 -5
  130. package/src/render/LayerPresetManager.js +372 -0
  131. package/src/render/LayerReactivityBridge.js +344 -0
  132. package/src/render/LayerRelationshipGraph.js +610 -0
  133. package/src/render/MultiCanvasBridge.js +148 -25
  134. package/src/render/ShaderLoader.js +38 -0
  135. package/src/render/ShaderProgram.js +4 -4
  136. package/src/render/UnifiedRenderBridge.js +4 -1
  137. package/src/render/backends/WebGPUBackend.js +8 -4
  138. package/src/render/index.js +27 -2
  139. package/src/scene/Node4D.js +74 -24
  140. package/src/scene/index.js +4 -4
  141. package/src/shaders/common/geometry24.glsl +65 -0
  142. package/src/shaders/common/geometry24.wgsl +54 -0
  143. package/src/shaders/common/rotation4d.glsl +4 -4
  144. package/src/shaders/common/rotation4d.wgsl +2 -2
  145. package/src/shaders/common/uniforms.wgsl +15 -8
  146. package/src/shaders/faceted/faceted.frag.glsl +220 -80
  147. package/src/shaders/faceted/faceted.frag.wgsl +144 -90
  148. package/src/shaders/holographic/holographic.frag.glsl +28 -9
  149. package/src/shaders/holographic/holographic.frag.wgsl +112 -41
  150. package/src/shaders/quantum/quantum.frag.glsl +1 -0
  151. package/src/shaders/quantum/quantum.frag.wgsl +6 -4
  152. package/src/testing/ParallelTestFramework.js +2 -2
  153. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +2 -2
  154. package/src/viewer/GalleryUI.js +17 -0
  155. package/src/viewer/ViewerPortal.js +2 -2
  156. package/src/viewer/index.js +1 -1
  157. package/tools/headless-renderer.js +258 -0
  158. package/tools/shader-sync-verify.js +14 -8
  159. package/tools/site-analysis/all-reports.json +32 -0
  160. package/tools/site-analysis/combined-analysis.md +50 -0
  161. package/tools/site-analyzer.mjs +779 -0
  162. package/tools/visual-catalog/capture.js +276 -0
  163. package/tools/visual-catalog/composite.js +138 -0
  164. package/types/adaptive-sdk.d.ts +204 -5
  165. package/types/agent/cli.d.ts +78 -0
  166. package/types/agent/index.d.ts +18 -0
  167. package/types/agent/mcp.d.ts +87 -0
  168. package/types/agent/telemetry.d.ts +190 -0
  169. package/types/core/VIB3Engine.d.ts +26 -0
  170. package/types/core/index.d.ts +261 -0
  171. package/types/creative/AestheticMapper.d.ts +72 -0
  172. package/types/creative/ChoreographyPlayer.d.ts +96 -0
  173. package/types/creative/index.d.ts +17 -0
  174. package/types/export/index.d.ts +243 -0
  175. package/types/geometry/index.d.ts +164 -0
  176. package/types/math/index.d.ts +214 -0
  177. package/types/render/LayerPresetManager.d.ts +78 -0
  178. package/types/render/LayerReactivityBridge.d.ts +85 -0
  179. package/types/render/LayerRelationshipGraph.d.ts +174 -0
  180. package/types/render/index.d.ts +3 -0
  181. package/types/scene/index.d.ts +204 -0
  182. package/types/systems/index.d.ts +244 -0
  183. package/types/variations/index.d.ts +62 -0
  184. package/types/viewer/index.d.ts +225 -0
  185. package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +0 -34
  186. package/DOCS/DEV_TRACK_ANALYSIS.md +0 -77
  187. package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +0 -42
  188. package/DOCS/SESSION_014_PLAN.md +0 -195
  189. package/DOCS/SESSION_LOG_2026-01-07.md +0 -56
  190. package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +0 -72
  191. package/DOCS/SYSTEM_AUDIT_2026-01-30.md +0 -738
  192. /package/src/viewer/{ReactivityManager.js → ViewerInputHandler.js} +0 -0
@@ -0,0 +1,372 @@
1
+ /**
2
+ * LayerPresetManager — Save, load, tune, and share layer relationship presets
3
+ *
4
+ * Works with LayerRelationshipGraph to persist custom layer configurations.
5
+ * Users and agents can:
6
+ * - Save the current graph state as a named preset
7
+ * - Load presets by name
8
+ * - Tune individual relationship parameters at runtime
9
+ * - Import/export preset libraries as JSON
10
+ * - List available presets (built-in + user)
11
+ *
12
+ * Storage: localStorage by default, configurable via constructor.
13
+ *
14
+ * Usage:
15
+ * const presets = new LayerPresetManager(graph);
16
+ * presets.save('my-look'); // save current graph
17
+ * presets.load('my-look'); // restore to graph
18
+ * presets.tune('shadow', { opacity: 0.6, gain: 3 }); // tweak a layer
19
+ * const lib = presets.exportLibrary(); // full JSON export
20
+ * presets.importLibrary(lib); // bulk import
21
+ */
22
+
23
+ import { LayerRelationshipGraph, PROFILES, PRESET_REGISTRY } from './LayerRelationshipGraph.js';
24
+
25
+ const STORAGE_KEY = 'vib3_layer_presets';
26
+
27
+ export class LayerPresetManager {
28
+ /**
29
+ * @param {LayerRelationshipGraph} graph - The live graph to save from / load into
30
+ * @param {object} [options]
31
+ * @param {Storage} [options.storage] - Storage backend (default: localStorage)
32
+ * @param {string} [options.storageKey] - Key prefix for storage
33
+ */
34
+ constructor(graph, options = {}) {
35
+ if (!(graph instanceof LayerRelationshipGraph)) {
36
+ throw new Error('LayerPresetManager requires a LayerRelationshipGraph instance');
37
+ }
38
+
39
+ /** @type {LayerRelationshipGraph} */
40
+ this._graph = graph;
41
+
42
+ /** @type {Storage|null} */
43
+ this._storage = options.storage !== undefined ? options.storage : this._getStorage();
44
+
45
+ /** @type {string} */
46
+ this._storageKey = options.storageKey || STORAGE_KEY;
47
+
48
+ /** @type {Map<string, object>} In-memory preset cache */
49
+ this._presets = new Map();
50
+
51
+ // Load persisted presets into memory
52
+ this._loadFromStorage();
53
+ }
54
+
55
+ /**
56
+ * Get localStorage safely (returns null in non-browser / restricted environments).
57
+ * @private
58
+ * @returns {Storage|null}
59
+ */
60
+ _getStorage() {
61
+ try {
62
+ if (typeof localStorage !== 'undefined') {
63
+ // Verify it works
64
+ localStorage.setItem('__vib3_test', '1');
65
+ localStorage.removeItem('__vib3_test');
66
+ return localStorage;
67
+ }
68
+ } catch (_e) { /* restricted */ }
69
+ return null;
70
+ }
71
+
72
+ /**
73
+ * Load all presets from storage into the in-memory cache.
74
+ * @private
75
+ */
76
+ _loadFromStorage() {
77
+ if (!this._storage) return;
78
+
79
+ try {
80
+ const raw = this._storage.getItem(this._storageKey);
81
+ if (raw) {
82
+ const data = JSON.parse(raw);
83
+ if (data && typeof data === 'object') {
84
+ for (const [name, preset] of Object.entries(data)) {
85
+ this._presets.set(name, preset);
86
+ }
87
+ }
88
+ }
89
+ } catch (e) {
90
+ console.warn('LayerPresetManager: failed to load presets from storage:', e.message);
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Persist the in-memory preset cache to storage.
96
+ * @private
97
+ */
98
+ _saveToStorage() {
99
+ if (!this._storage) return;
100
+
101
+ try {
102
+ const data = {};
103
+ for (const [name, preset] of this._presets) {
104
+ data[name] = preset;
105
+ }
106
+ this._storage.setItem(this._storageKey, JSON.stringify(data));
107
+ } catch (e) {
108
+ console.warn('LayerPresetManager: failed to save presets to storage:', e.message);
109
+ }
110
+ }
111
+
112
+ // ========================================================================
113
+ // Save / Load
114
+ // ========================================================================
115
+
116
+ /**
117
+ * Save the current graph state as a named preset.
118
+ *
119
+ * @param {string} name - Preset name (must not collide with built-in profile names)
120
+ * @param {object} [metadata] - Optional metadata (description, author, tags)
121
+ * @returns {object} The saved preset data
122
+ */
123
+ save(name, metadata = {}) {
124
+ if (!name || typeof name !== 'string') {
125
+ throw new Error('Preset name must be a non-empty string');
126
+ }
127
+
128
+ if (PROFILES[name]) {
129
+ throw new Error(`Cannot overwrite built-in profile "${name}". Choose a different name.`);
130
+ }
131
+
132
+ const config = this._graph.exportConfig();
133
+ const preset = {
134
+ name,
135
+ config,
136
+ metadata: {
137
+ ...metadata,
138
+ createdAt: new Date().toISOString(),
139
+ updatedAt: new Date().toISOString()
140
+ }
141
+ };
142
+
143
+ this._presets.set(name, preset);
144
+ this._saveToStorage();
145
+
146
+ return preset;
147
+ }
148
+
149
+ /**
150
+ * Load a preset by name into the live graph.
151
+ * Checks user presets first, then built-in profiles.
152
+ *
153
+ * @param {string} name - Preset or profile name
154
+ * @returns {boolean} True if loaded successfully
155
+ */
156
+ load(name) {
157
+ // User preset
158
+ const preset = this._presets.get(name);
159
+ if (preset && preset.config) {
160
+ this._graph.importConfig(preset.config);
161
+ return true;
162
+ }
163
+
164
+ // Built-in profile
165
+ if (PROFILES[name]) {
166
+ this._graph.loadProfile(name);
167
+ return true;
168
+ }
169
+
170
+ return false;
171
+ }
172
+
173
+ /**
174
+ * Delete a user preset.
175
+ *
176
+ * @param {string} name
177
+ * @returns {boolean} True if deleted
178
+ */
179
+ delete(name) {
180
+ if (PROFILES[name]) {
181
+ throw new Error(`Cannot delete built-in profile "${name}".`);
182
+ }
183
+
184
+ const existed = this._presets.delete(name);
185
+ if (existed) {
186
+ this._saveToStorage();
187
+ }
188
+ return existed;
189
+ }
190
+
191
+ /**
192
+ * Check if a preset exists (user or built-in).
193
+ *
194
+ * @param {string} name
195
+ * @returns {boolean}
196
+ */
197
+ has(name) {
198
+ return this._presets.has(name) || !!PROFILES[name];
199
+ }
200
+
201
+ /**
202
+ * Get a preset's data without loading it.
203
+ *
204
+ * @param {string} name
205
+ * @returns {object|null}
206
+ */
207
+ get(name) {
208
+ return this._presets.get(name) || null;
209
+ }
210
+
211
+ // ========================================================================
212
+ // List / Browse
213
+ // ========================================================================
214
+
215
+ /**
216
+ * List all available presets (user + built-in).
217
+ *
218
+ * @returns {{ user: string[], builtIn: string[] }}
219
+ */
220
+ list() {
221
+ return {
222
+ user: Array.from(this._presets.keys()),
223
+ builtIn: Object.keys(PROFILES)
224
+ };
225
+ }
226
+
227
+ /**
228
+ * List all preset names (user + built-in) as a flat array.
229
+ *
230
+ * @returns {string[]}
231
+ */
232
+ listAll() {
233
+ return [
234
+ ...Object.keys(PROFILES),
235
+ ...Array.from(this._presets.keys())
236
+ ];
237
+ }
238
+
239
+ /**
240
+ * Get the count of user presets.
241
+ *
242
+ * @returns {number}
243
+ */
244
+ get count() {
245
+ return this._presets.size;
246
+ }
247
+
248
+ // ========================================================================
249
+ // Tune
250
+ // ========================================================================
251
+
252
+ /**
253
+ * Tune (hot-patch) a layer's relationship config without replacing the full graph.
254
+ * Re-instantiates the relationship function with updated config.
255
+ *
256
+ * @param {string} layerName - Layer to tune
257
+ * @param {object} configOverrides - Config values to merge (e.g., { opacity: 0.6, gain: 3 })
258
+ * @returns {boolean} True if tuned successfully
259
+ */
260
+ tune(layerName, configOverrides) {
261
+ if (!configOverrides || typeof configOverrides !== 'object') return false;
262
+
263
+ // Read current config for this layer from the graph
264
+ const graphConfig = this._graph.exportConfig();
265
+ const currentRel = graphConfig.relationships[layerName];
266
+
267
+ if (!currentRel || !currentRel.preset) {
268
+ // Can't tune a custom function or missing relationship
269
+ return false;
270
+ }
271
+
272
+ const factory = PRESET_REGISTRY[currentRel.preset];
273
+ if (!factory) return false;
274
+
275
+ // Merge overrides into existing config
276
+ const newConfig = { ...(currentRel.config || {}), ...configOverrides };
277
+
278
+ // Re-set the relationship with updated config
279
+ this._graph.setRelationship(layerName, {
280
+ preset: currentRel.preset,
281
+ config: newConfig
282
+ });
283
+
284
+ return true;
285
+ }
286
+
287
+ /**
288
+ * Get the current tunable config for a layer.
289
+ *
290
+ * @param {string} layerName
291
+ * @returns {object|null} The current { preset, config } or null
292
+ */
293
+ getLayerConfig(layerName) {
294
+ const graphConfig = this._graph.exportConfig();
295
+ return graphConfig.relationships[layerName] || null;
296
+ }
297
+
298
+ // ========================================================================
299
+ // Import / Export
300
+ // ========================================================================
301
+
302
+ /**
303
+ * Export all user presets as a JSON-serializable library.
304
+ *
305
+ * @returns {object} Library object with version and presets
306
+ */
307
+ exportLibrary() {
308
+ const presets = {};
309
+ for (const [name, preset] of this._presets) {
310
+ presets[name] = preset;
311
+ }
312
+
313
+ return {
314
+ version: '1.0',
315
+ type: 'vib3_layer_presets',
316
+ exportedAt: new Date().toISOString(),
317
+ count: this._presets.size,
318
+ presets
319
+ };
320
+ }
321
+
322
+ /**
323
+ * Import presets from a library object.
324
+ * Does not overwrite existing presets unless `overwrite` is true.
325
+ *
326
+ * @param {object} library - Library object from exportLibrary()
327
+ * @param {object} [options]
328
+ * @param {boolean} [options.overwrite=false] - Overwrite existing presets
329
+ * @returns {{ imported: number, skipped: number }}
330
+ */
331
+ importLibrary(library, options = {}) {
332
+ const { overwrite = false } = options;
333
+
334
+ if (!library || !library.presets || typeof library.presets !== 'object') {
335
+ throw new Error('Invalid library format: missing presets object');
336
+ }
337
+
338
+ let imported = 0;
339
+ let skipped = 0;
340
+
341
+ for (const [name, preset] of Object.entries(library.presets)) {
342
+ if (PROFILES[name]) {
343
+ skipped++;
344
+ continue; // Never overwrite built-in profiles
345
+ }
346
+
347
+ if (!overwrite && this._presets.has(name)) {
348
+ skipped++;
349
+ continue;
350
+ }
351
+
352
+ this._presets.set(name, preset);
353
+ imported++;
354
+ }
355
+
356
+ if (imported > 0) {
357
+ this._saveToStorage();
358
+ }
359
+
360
+ return { imported, skipped };
361
+ }
362
+
363
+ /**
364
+ * Clear all user presets.
365
+ */
366
+ clear() {
367
+ this._presets.clear();
368
+ this._saveToStorage();
369
+ }
370
+ }
371
+
372
+ export default LayerPresetManager;