native-document 1.0.138 → 1.0.139

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.
@@ -1,1025 +1,1132 @@
1
1
  var NativeComponents = (function (exports) {
2
2
  'use strict';
3
3
 
4
- /**
5
- *
6
- * @class
7
- */
8
- function BaseComponent() {
9
- this.$description = {};
4
+ let DebugManager$2 = {};
5
+ {
6
+ DebugManager$2 = {
7
+ log() {},
8
+ warn() {},
9
+ error() {},
10
+ disable() {}
11
+ };
10
12
  }
13
+ var DebugManager$1 = DebugManager$2;
11
14
 
12
- Object.defineProperty( BaseComponent.prototype, 'nd', {
13
- get: function() {
14
- if(this.$element) {
15
- return this.$element.nd;
16
- }
17
- this.$storeElement(this.toNdElement());
18
- return this.$element?.nd;
19
- }
20
- });
21
-
22
-
23
- BaseComponent.extends = function(Component, ...parents) {
24
- const MainParent = parents[0] || BaseComponent;
25
- Component.prototype = Object.create(MainParent.prototype);
26
-
27
- if(parents.length > 0) {
28
- for(const parent of parents) {
29
- Object.assign(Component.prototype, parent.prototype);
30
- }
31
- }
32
- Component.prototype.constructor = Component;
33
- };
34
-
35
- BaseComponent.use = function(Component, ...traits) {
36
- if(traits.length > 0) {
37
- for(const trait of traits) {
38
- Object.assign(Component.prototype, trait.prototype);
39
- }
40
- }
41
- };
42
-
43
- BaseComponent.obs = (value) => {
44
- return value.__$Observable ? value : Observable(value);
45
- };
46
-
47
- BaseComponent.prototype.$storeElement = function(element) {
48
- this.$element = element;
49
- return this;
50
- };
51
-
52
- BaseComponent.prototype.refSelf = function(target, name) {
53
- target[name] = this;
54
- return this;
55
- };
56
-
57
- BaseComponent.prototype.$build = function() {
58
- const ComponentClass = this.constructor;
59
- const renderer = this.$description.render || ComponentClass.defaultTemplate;
60
-
61
- if (!renderer) {
62
- throw new Error(`No renderer for ${ComponentClass.name}`);
63
- }
64
-
65
- return renderer(this.$description, this);
66
- };
67
-
68
- BaseComponent.prototype.toNdElement = function() {
69
- if (this.$element) {
70
- return this.$element;
71
- }
72
- this.$element = this.$build();
73
- return this.$element;
74
- };
75
-
76
- BaseComponent.prototype.toJSON = function() {
77
- if(!this.$description) {
78
- return {};
79
- }
80
- return { ...this.$description };
81
- };
82
-
83
- BaseComponent.prototype.render = function(renderFn) {
84
- if (typeof renderFn !== 'function') {
85
- throw new Error('Custom renderer must be a function');
15
+ class NativeDocumentError extends Error {
16
+ constructor(message, context = {}) {
17
+ super(message);
18
+ this.name = 'NativeDocumentError';
19
+ this.context = context;
20
+ this.timestamp = new Date().toISOString();
86
21
  }
87
- this.$description.render = renderFn;
88
- return this;
89
- };
90
-
91
- function HasEventEmitter() {
92
-
93
- this.__$events = null;
94
-
95
22
  }
96
23
 
97
- HasEventEmitter.prototype.on = function(eventName, callback) {
98
- if(!this.__$events) {
99
- this.__$events = new Map();
100
- }
101
- if(!this.__$events.has(eventName)) {
102
- this.__$events.set(eventName, callback);
103
- return;
104
- }
105
- const existingCallback = this.__$events.get(eventName);
106
- if(!Array.isArray(existingCallback)) {
107
- this.__$events.set(eventName, [existingCallback, callback]);
108
- return;
109
- }
110
- existingCallback.push(callback);
111
- };
112
-
113
- HasEventEmitter.prototype.hasListeners = function(eventName) {
114
- return !!this.__$events.get(eventName);
115
- };
116
-
117
- HasEventEmitter.prototype.trigger = async function(eventName, ...args) {
118
- const callbacks = this.__$events.get(eventName);
119
- if(!callbacks) {
120
- // throw new NativeDocumentError(this.constructor.name, 'Event '+eventName+' not found');
121
- return;
122
- }
123
-
124
- if(typeof callbacks === 'function') {
125
- return await Promise.resolve(callbacks.apply(this, args))
126
- }
127
-
128
- let result = null;
129
- for(let i = 0, length = callbacks.length; i < length; i++) {
130
- result = await Promise.resolve(await callbacks[i].apply(this, args));
131
- }
132
- return result;
133
- };
134
- HasEventEmitter.prototype.emit = HasEventEmitter.prototype.trigger;
135
-
136
- /**
137
- * Valid children types that can be rendered in the DOM
138
- * @typedef {HTMLElement|Text|DocumentFragment|string|Array<ValidChildren>} ValidChildren
139
- */
140
-
141
24
  /**
142
- * Component for creating accordion interfaces with expandable/collapsible items
143
- * @param {{ items?: Array<AccordionItem>, multiple?: boolean, variant?: string, renderContent?: (field: Accordion) => HTMLElement }} config
144
- * @returns {Accordion}
145
- * @class
25
+ *
26
+ * @param {ObservableItem} $observable
27
+ * @param {Function} $checker
28
+ * @class ObservableChecker
146
29
  */
147
- function Accordion(config = {}) {
148
- if (!(this instanceof Accordion)) {
149
- return new Accordion(config);
150
- }
151
-
152
- this.$description = {
153
- items: [],
154
- multiple: null,
155
- variant: null,
156
- renderContent: null,
157
- ...config
158
- };
30
+ function ObservableChecker($observable, $checker) {
31
+ this.observable = $observable;
32
+ this.checker = $checker;
33
+ this.unSubscriptions = [];
159
34
  }
160
35
 
161
- BaseComponent.extends(Accordion, HasEventEmitter);
162
-
163
- Accordion.defaultTemplate = null;
164
-
36
+ ObservableChecker.prototype.__$Observable = true;
37
+ ObservableChecker.prototype.__$isObservableChecker = true;
165
38
 
166
39
  /**
167
- * Sets the default template for all Accordion instances
168
- * @param {{accordion: (accordion: Accordion) => ValidChildren}} template - Template object containing accordion factory function
40
+ * Subscribes to changes in the checked/transformed value.
41
+ *
42
+ * @param {Function} callback - Function called with the transformed value when observable changes
43
+ * @returns {Function} Unsubscribe function
44
+ * @example
45
+ * const count = Observable(5);
46
+ * const doubled = count.check(n => n * 2);
47
+ * doubled.subscribe(value => console.log(value)); // Logs: 10
169
48
  */
170
- Accordion.use = function(template) {
171
- Accordion.defaultTemplate = template.accordion;
49
+ ObservableChecker.prototype.subscribe = function(callback) {
50
+ const unSubscribe = this.observable.subscribe((value) => {
51
+ callback && callback(this.checker(value));
52
+ });
53
+ this.unSubscriptions.push(unSubscribe);
54
+ return unSubscribe;
172
55
  };
173
56
 
174
57
  /**
175
- * Adds an accordion item to the collection
176
- * @param {AccordionItem} accordionItem - The accordion item to add
177
- * @returns {Accordion}
58
+ * Creates a new ObservableChecker by applying another transformation.
59
+ * Allows chaining transformations.
60
+ *
61
+ * @param {(value: *) => *} callback - Transformation function to apply to the current checked value
62
+ * @returns {ObservableChecker} New ObservableChecker with chained transformation
63
+ * @example
64
+ * const count = Observable(5);
65
+ * const result = count.check(n => n * 2).check(n => n + 1);
66
+ * result.val(); // 11
178
67
  */
179
- Accordion.prototype.item = function(accordionItem) {
180
- this.$description.items.push(accordionItem);
181
- return this;
68
+ ObservableChecker.prototype.check = function(callback) {
69
+ return this.observable.check(() => callback(this.val()));
182
70
  };
183
71
 
184
72
  /**
185
- * Sets the accordion items collection
186
- * @param {Array<AccordionItem>} items - Array of accordion items
187
- * @returns {Accordion}
73
+ * Gets the current transformed/checked value.
74
+ *
75
+ * @returns {*} The result of applying the checker function to the observable's current value
76
+ * @example
77
+ * const count = Observable(5);
78
+ * const doubled = count.check(n => n * 2);
79
+ * doubled.val(); // 10
188
80
  */
189
- Accordion.prototype.items = function(items) {
190
- this.$description.items = items;
191
- return this;
81
+ ObservableChecker.prototype.val = function() {
82
+ return this.checker && this.checker(this.observable.val());
192
83
  };
193
84
 
194
85
  /**
195
- * Alias for item method
196
- * @param {AccordionItem} accordionItem - The accordion item to add
197
- * @returns {Accordion}
86
+ * Sets the value of the underlying observable (not the transformed value).
87
+ *
88
+ * @param {*} value - New value for the underlying observable
89
+ * @example
90
+ * const count = Observable(5);
91
+ * const doubled = count.check(n => n * 2);
92
+ * doubled.set(10); // Sets count to 10, doubled.val() returns 20
198
93
  */
199
- Accordion.prototype.addItem = Accordion.prototype.item;
94
+ ObservableChecker.prototype.set = function(value) {
95
+ return this.observable.set(value);
96
+ };
200
97
 
201
98
  /**
202
- * Removes an item by its id
203
- * @param {string} id - The id of the item to remove
204
- * @returns {Accordion}
99
+ * Manually triggers the underlying observable to notify subscribers.
100
+ *
101
+ * @example
102
+ * const count = Observable(5);
103
+ * const doubled = count.check(n => n * 2);
104
+ * doubled.trigger(); // Notifies all subscribers
205
105
  */
206
- Accordion.prototype.removeItemById = function(id) {
207
- if (this.$description.items) {
208
- this.$description.items = this.$description.items.filter(item => item.id !== id);
209
- }
210
- return this;
106
+ ObservableChecker.prototype.trigger = function() {
107
+ return this.observable.trigger();
211
108
  };
212
109
 
213
110
  /**
214
- * Removes items matching the filter function
215
- * @param {Function} filter - Filter function to determine which items to keep
216
- * @returns {Accordion}
111
+ * Cleans up the underlying observable and all its subscriptions.
217
112
  */
218
- Accordion.prototype.remove = function(filter) {
219
- if (this.$description.items) {
220
- this.$description.items = this.$description.items.filter(filter);
221
- }
222
- return this;
113
+ ObservableChecker.prototype.cleanup = function() {
114
+ return this.observable.cleanup();
223
115
  };
224
116
 
225
- /**
226
- * Enables or disables multiple items expansion
227
- * @param {boolean} [enabled=true] - Whether multiple items can be expanded simultaneously
228
- * @returns {Accordion}
229
- */
230
- Accordion.prototype.multiple = function(enabled = true) {
231
- this.$description.multiple = enabled;
232
- return this;
233
- };
117
+ const DocumentObserver = {
118
+ mounted: new WeakMap(),
119
+ beforeUnmount: new WeakMap(),
120
+ mountedSupposedSize: 0,
121
+ unmounted: new WeakMap(),
122
+ unmountedSupposedSize: 0,
123
+ observer: null,
124
+ initObserver: () => {
125
+ if(DocumentObserver.observer) {
126
+ return;
127
+ }
128
+ DocumentObserver.observer = new MutationObserver(DocumentObserver.checkMutation);
129
+ DocumentObserver.observer.observe(document.body, {
130
+ childList: true,
131
+ subtree: true,
132
+ });
133
+ },
234
134
 
235
- /**
236
- * Sets the variant style for the accordion
237
- * @param {string} name - The variant name
238
- * @returns {Accordion}
239
- */
240
- Accordion.prototype.variant = function(name) {
241
- this.$description.variant = name;
242
- return this;
243
- };
135
+ executeMountedCallback(node) {
136
+ const data = DocumentObserver.mounted.get(node);
137
+ if(!data) {
138
+ return;
139
+ }
140
+ data.inDom = true;
141
+ if(!data.mounted) {
142
+ return;
143
+ }
144
+ if(Array.isArray(data.mounted)) {
145
+ for(const cb of data.mounted) {
146
+ cb(node);
147
+ }
148
+ return;
149
+ }
150
+ data.mounted(node);
151
+ },
244
152
 
245
- /**
246
- * Sets the accordion variant to 'bordered'
247
- * @returns {Accordion}
248
- */
249
- Accordion.prototype.bordered = function() {
250
- return this.variant('bordered');
153
+ executeUnmountedCallback(node) {
154
+ const data = DocumentObserver.unmounted.get(node);
155
+ if(!data) {
156
+ return;
157
+ }
158
+ data.inDom = false;
159
+ if(!data.unmounted) {
160
+ return;
161
+ }
162
+
163
+ let shouldRemove = false;
164
+ if(Array.isArray(data.unmounted)) {
165
+ for(const cb of data.unmounted) {
166
+ if(cb(node) === true) {
167
+ shouldRemove = true;
168
+ }
169
+ }
170
+ } else {
171
+ shouldRemove = data.unmounted(node) === true;
172
+ }
173
+
174
+ if(shouldRemove) {
175
+ data.disconnect();
176
+ node.nd?.remove();
177
+ }
178
+ },
179
+
180
+ checkMutation: function(mutationsList) {
181
+ console.log('mutationsList', mutationsList);
182
+ for(const mutation of mutationsList) {
183
+ if(DocumentObserver.mountedSupposedSize > 0) {
184
+ for(const node of mutation.addedNodes) {
185
+ DocumentObserver.executeMountedCallback(node);
186
+ if(!node.querySelectorAll) {
187
+ continue;
188
+ }
189
+ const children = node.querySelectorAll('[data--nd-mounted]');
190
+ for(const child of children) {
191
+ DocumentObserver.executeMountedCallback(child);
192
+ }
193
+ }
194
+ }
195
+
196
+ if (DocumentObserver.unmountedSupposedSize > 0) {
197
+ for (const node of mutation.removedNodes) {
198
+ DocumentObserver.executeUnmountedCallback(node);
199
+ if(!node.querySelectorAll) {
200
+ continue;
201
+ }
202
+ const children = node.querySelectorAll('[data--nd-unmounted]');
203
+ for(const child of children) {
204
+ DocumentObserver.executeUnmountedCallback(child);
205
+ }
206
+ }
207
+ }
208
+ }
209
+ },
210
+
211
+ /**
212
+ * @param {HTMLElement} element
213
+ * @param {boolean} inDom
214
+ * @returns {{ disconnect: Function, mounted: Function, unmounted: Function, off: Function }}
215
+ */
216
+ watch: function(element, inDom = false) {
217
+ let mountedRegistered = false;
218
+ let unmountedRegistered = false;
219
+
220
+ DocumentObserver.initObserver();
221
+
222
+ let data = {
223
+ inDom,
224
+ mounted: null,
225
+ unmounted: null,
226
+ disconnect: () => {
227
+ if (mountedRegistered) {
228
+ DocumentObserver.mounted.delete(element);
229
+ DocumentObserver.mountedSupposedSize--;
230
+ }
231
+ if (unmountedRegistered) {
232
+ DocumentObserver.unmounted.delete(element);
233
+ DocumentObserver.unmountedSupposedSize--;
234
+ }
235
+ data = null;
236
+ }
237
+ };
238
+
239
+ const addListener = (type, callback) => {
240
+ if (!data[type]) {
241
+ data[type] = callback;
242
+ return;
243
+ }
244
+ if (!Array.isArray(data[type])) {
245
+ data[type] = [data[type], callback];
246
+ return;
247
+ }
248
+ data[type].push(callback);
249
+ };
250
+
251
+ const removeListener = (type, callback) => {
252
+ if(!data?.[type]) {
253
+ return;
254
+ }
255
+ if(Array.isArray(data[type])) {
256
+ const index = data[type].indexOf(callback);
257
+ if(index > -1) {
258
+ data[type].splice(index, 1);
259
+ }
260
+ if(data[type].length === 1) {
261
+ data[type] = data[type][0];
262
+ }
263
+ if(data[type].length === 0) {
264
+ data[type] = null;
265
+ }
266
+ return;
267
+ }
268
+ data[type] = null;
269
+ };
270
+
271
+ return {
272
+ disconnect: () => data?.disconnect(),
273
+
274
+ mounted: (callback) => {
275
+ addListener('mounted', callback);
276
+ DocumentObserver.mounted.set(element, data);
277
+ if (!mountedRegistered) {
278
+ DocumentObserver.mountedSupposedSize++;
279
+ mountedRegistered = true;
280
+ }
281
+ },
282
+
283
+ unmounted: (callback) => {
284
+ addListener('unmounted', callback);
285
+ DocumentObserver.unmounted.set(element, data);
286
+ if (!unmountedRegistered) {
287
+ DocumentObserver.unmountedSupposedSize++;
288
+ unmountedRegistered = true;
289
+ }
290
+ },
291
+
292
+ off: (type, callback) => {
293
+ removeListener(type, callback);
294
+ }
295
+ };
296
+ }
251
297
  };
252
298
 
253
- /**
254
- * Sets the accordion variant to 'separated'
255
- * @returns {Accordion}
256
- */
257
- Accordion.prototype.separated = function() {
258
- return this.variant('separated');
299
+ function NDElement(element) {
300
+ this.$element = element;
301
+ }
302
+
303
+ NDElement.prototype.__$isNDElement = true;
304
+
305
+ NDElement.prototype.valueOf = function() {
306
+ return this.$element;
259
307
  };
260
308
 
261
- /**
262
- * Sets the accordion variant to 'flush'
263
- * @returns {Accordion}
264
- */
265
- Accordion.prototype.flush = function() {
266
- return this.variant('flush');
309
+ NDElement.prototype.ref = function(target, name) {
310
+ target[name] = this.$element;
311
+ return this;
267
312
  };
268
313
 
269
- /**
270
- * Retrieves an accordion item by its key
271
- * @param {string} key - The key of the item to retrieve
272
- * @returns {AccordionItem|undefined}
273
- */
274
- Accordion.prototype.getByKey = function(key) {
275
- return this.$description.items.find(item => item.key === key);
314
+ NDElement.prototype.refSelf = function(target, name) {
315
+ target[name] = new NDElement(this.$element);
316
+ return this;
276
317
  };
277
318
 
278
- /**
279
- * Expands or collapses an accordion item by key
280
- * @param {string} key - The key of the item
281
- * @param {boolean} [state=true] - Whether to expand (true) or collapse (false)
282
- * @returns {Accordion}
283
- */
284
- Accordion.prototype.expanded = function(key, state = true) {
285
- const item = this.getByKey(key);
286
- if(item) {
287
- if (state && !this.$description.multiple) {
288
- this.collapseAll();
319
+ NDElement.prototype.unmountChildren = function() {
320
+ let element = this.$element;
321
+ for(let i = 0, length = element.children.length; i < length; i++) {
322
+ let elementChildren = element.children[i];
323
+ if(!elementChildren.$ndProx) {
324
+ elementChildren.nd?.remove();
289
325
  }
290
- item.expanded(state);
291
- this.emit(state ? 'expand' : 'collapse', key, state);
326
+ elementChildren = null;
292
327
  }
328
+ element = null;
293
329
  return this;
294
330
  };
295
331
 
296
- /**
297
- * Expands all accordion items
298
- * @returns {Accordion}
299
- */
300
- Accordion.prototype.expandAll = function() {
301
- this.$description.items.forEach(item => item.expanded(true));
332
+ NDElement.prototype.remove = function() {
333
+ let element = this.$element;
334
+ element.nd.unmountChildren();
335
+ element.$ndProx = null;
336
+
337
+ $lifeCycleObservers.delete(element);
338
+
339
+ element = null;
302
340
  return this;
303
341
  };
304
342
 
305
- /**
306
- * Collapses all accordion items
307
- * @returns {Accordion}
308
- */
309
- Accordion.prototype.collapseAll = function() {
310
- this.$description.items.forEach(item => item.expanded(false));
343
+ const $lifeCycleObservers = new WeakMap();
344
+ NDElement.prototype.lifecycle = function(states) {
345
+ const el = this.$element;
346
+ if (!$lifeCycleObservers.has(el)) {
347
+ $lifeCycleObservers.set(el, DocumentObserver.watch(el));
348
+ }
349
+ const observer = $lifeCycleObservers.get(el);
350
+
351
+ if(states.mounted) {
352
+ this.$element.setAttribute('data--nd-mounted', '1');
353
+ observer.mounted(states.mounted);
354
+ }
355
+ if(states.unmounted) {
356
+ this.$element.setAttribute('data--nd-unmounted', '1');
357
+ observer.unmounted(states.unmounted);
358
+ }
311
359
  return this;
312
360
  };
313
361
 
314
- /**
315
- * Checks if an accordion item is expanded
316
- * @param {string} key - The key of the item to check
317
- * @returns {boolean|undefined}
318
- */
319
- Accordion.prototype.isExpanded = function(key) {
320
- return this.getByKey(key)?.isExpanded?.();
362
+ NDElement.prototype.mounted = function(callback) {
363
+ return this.lifecycle({ mounted: callback });
321
364
  };
322
365
 
323
- /**
324
- * Registers a handler for the expand event
325
- * @param {Function} handler - The event handler
326
- * @returns {Accordion}
327
- */
328
- Accordion.prototype.onExpand = function(handler) {
329
- this.on('expand', handler);
330
- return this;
366
+ NDElement.prototype.unmounted = function(callback) {
367
+ return this.lifecycle({ unmounted: callback });
331
368
  };
332
369
 
333
- /**
334
- * Registers a handler for the collapse event
335
- * @param {Function} handler - The event handler
336
- * @returns {Accordion}
337
- */
338
- Accordion.prototype.onCollapse = function(handler) {
339
- this.on('collapse', handler);
340
- return this;
341
- };
370
+ NDElement.prototype.beforeUnmount = function(id, callback) {
371
+ const el = this.$element;
342
372
 
343
- /**
344
- * Sets the content render function
345
- * @param {Function} renderFn - Function to render content
346
- * @returns {Accordion}
347
- */
348
- Accordion.prototype.renderContent = function(renderFn) {
349
- this.$description.renderContent = renderFn;
373
+ if(!DocumentObserver.beforeUnmount.has(el)) {
374
+ DocumentObserver.beforeUnmount.set(el, new Map());
375
+ const originalRemove = el.remove.bind(el);
376
+
377
+ let $isUnmounting = false;
378
+
379
+ el.remove = async () => {
380
+ if($isUnmounting) {
381
+ return;
382
+ }
383
+ $isUnmounting = true;
384
+
385
+ try {
386
+ const callbacks = DocumentObserver.beforeUnmount.get(el);
387
+ for (const cb of callbacks.values()) {
388
+ await cb.call(this, el);
389
+ }
390
+ } finally {
391
+ originalRemove();
392
+ $isUnmounting = false;
393
+ }
394
+ };
395
+ }
396
+
397
+ DocumentObserver.beforeUnmount.get(el).set(id, callback);
350
398
  return this;
351
399
  };
352
400
 
353
- /**
354
- * Builds the accordion component
355
- * @private
356
- */
357
- Accordion.prototype.$build = function() {
358
- // TODO: Implementation
359
- // this.$description.items.forEach(item => {
360
- // item.onExpand(() => {
361
- // if (!this.$description.multiple) {
362
- // this.$description.items
363
- // .filter(i => i !== item)
364
- // .forEach(i => i.expanded(false));
365
- // }
366
- // });
367
- // });
401
+ NDElement.prototype.htmlElement = function() {
402
+ return this.$element;
368
403
  };
369
404
 
370
- let DebugManager$1 = {};
371
- {
372
- DebugManager$1 = {
373
- log() {},
374
- warn() {},
375
- error() {},
376
- disable() {}
377
- };
378
- }
379
- var DebugManager$2 = DebugManager$1;
405
+ NDElement.prototype.node = NDElement.prototype.htmlElement;
380
406
 
381
- class NativeDocumentError extends Error {
382
- constructor(message, context = {}) {
383
- super(message);
384
- this.name = 'NativeDocumentError';
385
- this.context = context;
386
- this.timestamp = new Date().toISOString();
407
+ NDElement.prototype.shadow = function(mode, style = null) {
408
+ const $element = this.$element;
409
+ const children = Array.from($element.childNodes);
410
+ const shadowRoot = $element.attachShadow({ mode });
411
+ if(style) {
412
+ const styleNode = document.createElement("style");
413
+ styleNode.textContent = style;
414
+ shadowRoot.appendChild(styleNode);
387
415
  }
388
- }
389
-
390
- /**
391
- *
392
- * @param {ObservableItem} $observable
393
- * @param {Function} $checker
394
- * @class ObservableChecker
395
- */
396
- function ObservableChecker($observable, $checker) {
397
- this.observable = $observable;
398
- this.checker = $checker;
399
- this.unSubscriptions = [];
400
- }
401
-
402
- ObservableChecker.prototype.__$Observable = true;
403
- ObservableChecker.prototype.__$isObservableChecker = true;
416
+ $element.append = shadowRoot.append.bind(shadowRoot);
417
+ $element.appendChild = shadowRoot.appendChild.bind(shadowRoot);
418
+ shadowRoot.append(...children);
404
419
 
405
- /**
406
- * Subscribes to changes in the checked/transformed value.
407
- *
408
- * @param {Function} callback - Function called with the transformed value when observable changes
409
- * @returns {Function} Unsubscribe function
410
- * @example
411
- * const count = Observable(5);
412
- * const doubled = count.check(n => n * 2);
413
- * doubled.subscribe(value => console.log(value)); // Logs: 10
414
- */
415
- ObservableChecker.prototype.subscribe = function(callback) {
416
- const unSubscribe = this.observable.subscribe((value) => {
417
- callback && callback(this.checker(value));
418
- });
419
- this.unSubscriptions.push(unSubscribe);
420
- return unSubscribe;
420
+ return this;
421
421
  };
422
422
 
423
- /**
424
- * Creates a new ObservableChecker by applying another transformation.
425
- * Allows chaining transformations.
426
- *
427
- * @param {(value: *) => *} callback - Transformation function to apply to the current checked value
428
- * @returns {ObservableChecker} New ObservableChecker with chained transformation
429
- * @example
430
- * const count = Observable(5);
431
- * const result = count.check(n => n * 2).check(n => n + 1);
432
- * result.val(); // 11
433
- */
434
- ObservableChecker.prototype.check = function(callback) {
435
- return this.observable.check(() => callback(this.val()));
423
+ NDElement.prototype.openShadow = function(style = null) {
424
+ return this.shadow('open', style);
436
425
  };
437
426
 
438
- /**
439
- * Gets the current transformed/checked value.
440
- *
441
- * @returns {*} The result of applying the checker function to the observable's current value
442
- * @example
443
- * const count = Observable(5);
444
- * const doubled = count.check(n => n * 2);
445
- * doubled.val(); // 10
446
- */
447
- ObservableChecker.prototype.val = function() {
448
- return this.checker && this.checker(this.observable.val());
427
+ NDElement.prototype.closedShadow = function(style = null) {
428
+ return this.shadow('closed', style);
449
429
  };
450
430
 
451
431
  /**
452
- * Sets the value of the underlying observable (not the transformed value).
432
+ * Extends the current NDElement instance with custom methods.
433
+ * Methods are bound to the instance and available for chaining.
453
434
  *
454
- * @param {*} value - New value for the underlying observable
435
+ * @param {Object} methods - Object containing method definitions
436
+ * @returns {this} The NDElement instance with added methods for chaining
455
437
  * @example
456
- * const count = Observable(5);
457
- * const doubled = count.check(n => n * 2);
458
- * doubled.set(10); // Sets count to 10, doubled.val() returns 20
438
+ * element.nd.with({
439
+ * highlight() {
440
+ * this.$element.style.background = 'yellow';
441
+ * return this;
442
+ * }
443
+ * }).highlight().onClick(() => console.log('Clicked'));
459
444
  */
460
- ObservableChecker.prototype.set = function(value) {
461
- return this.observable.set(value);
445
+ NDElement.prototype.with = function(methods) {
446
+ if (!methods || typeof methods !== 'object') {
447
+ throw new NativeDocumentError('extend() requires an object of methods');
448
+ }
449
+
450
+ for (const name in methods) {
451
+ const method = methods[name];
452
+
453
+ if (typeof method !== 'function') {
454
+ console.warn(`⚠️ extends(): "${name}" is not a function, skipping`);
455
+ continue;
456
+ }
457
+
458
+ this[name] = method.bind(this);
459
+ }
460
+
461
+ return this;
462
462
  };
463
463
 
464
464
  /**
465
- * Manually triggers the underlying observable to notify subscribers.
465
+ * Extends the NDElement prototype with new methods available to all NDElement instances.
466
+ * Use this to add global methods to all NDElements.
466
467
  *
468
+ * @param {Object} methods - Object containing method definitions to add to prototype
469
+ * @returns {typeof NDElement} The NDElement constructor
470
+ * @throws {NativeDocumentError} If methods is not an object or contains non-function values
467
471
  * @example
468
- * const count = Observable(5);
469
- * const doubled = count.check(n => n * 2);
470
- * doubled.trigger(); // Notifies all subscribers
472
+ * NDElement.extend({
473
+ * fadeIn() {
474
+ * this.$element.style.opacity = '1';
475
+ * return this;
476
+ * }
477
+ * });
478
+ * // Now all NDElements have .fadeIn() method
479
+ * Div().nd.fadeIn();
471
480
  */
472
- ObservableChecker.prototype.trigger = function() {
473
- return this.observable.trigger();
474
- };
481
+ NDElement.extend = function(methods) {
482
+ if (!methods || typeof methods !== 'object') {
483
+ throw new NativeDocumentError('NDElement.extend() requires an object of methods');
484
+ }
475
485
 
476
- /**
477
- * Cleans up the underlying observable and all its subscriptions.
478
- */
479
- ObservableChecker.prototype.cleanup = function() {
480
- return this.observable.cleanup();
481
- };
486
+ if (Array.isArray(methods)) {
487
+ throw new NativeDocumentError('NDElement.extend() requires an object, not an array');
488
+ }
482
489
 
483
- const DocumentObserver = {
484
- mounted: new WeakMap(),
485
- beforeUnmount: new WeakMap(),
486
- mountedSupposedSize: 0,
487
- unmounted: new WeakMap(),
488
- unmountedSupposedSize: 0,
489
- observer: null,
490
- initObserver: () => {
491
- if(DocumentObserver.observer) {
492
- return;
493
- }
494
- DocumentObserver.observer = new MutationObserver(DocumentObserver.checkMutation);
495
- DocumentObserver.observer.observe(document.body, {
496
- childList: true,
497
- subtree: true,
498
- });
499
- },
490
+ const protectedMethods = new Set([
491
+ 'constructor', 'valueOf', '$element', '$observer',
492
+ 'ref', 'remove', 'cleanup', 'with', 'extend', 'attach',
493
+ 'lifecycle', 'mounted', 'unmounted', 'unmountChildren'
494
+ ]);
500
495
 
501
- executeMountedCallback(node) {
502
- const data = DocumentObserver.mounted.get(node);
503
- if(!data) {
504
- return;
505
- }
506
- data.inDom = true;
507
- if(!data.mounted) {
508
- return;
509
- }
510
- if(Array.isArray(data.mounted)) {
511
- for(const cb of data.mounted) {
512
- cb(node);
513
- }
514
- return;
496
+ for (const name in methods) {
497
+ if (!Object.hasOwn(methods, name)) {
498
+ continue;
515
499
  }
516
- data.mounted(node);
517
- },
518
500
 
519
- executeUnmountedCallback(node) {
520
- const data = DocumentObserver.unmounted.get(node);
521
- if(!data) {
522
- return;
501
+ const method = methods[name];
502
+
503
+ if (typeof method !== 'function') {
504
+ DebugManager$1.warn('NDElement.extend', `"${name}" is not a function, skipping`);
505
+ continue;
523
506
  }
524
- data.inDom = false;
525
- if(!data.unmounted) {
526
- return;
507
+
508
+ if (protectedMethods.has(name)) {
509
+ DebugManager$1.error('NDElement.extend', `Cannot override protected method "${name}"`);
510
+ throw new NativeDocumentError(`Cannot override protected method "${name}"`);
527
511
  }
528
512
 
529
- let shouldRemove = false;
530
- if(Array.isArray(data.unmounted)) {
531
- for(const cb of data.unmounted) {
532
- if(cb(node) === true) {
533
- shouldRemove = true;
534
- }
535
- }
536
- } else {
537
- shouldRemove = data.unmounted(node) === true;
513
+ if (NDElement.prototype[name]) {
514
+ DebugManager$1.warn('NDElement.extend', `Overwriting existing prototype method "${name}"`);
538
515
  }
539
516
 
540
- if(shouldRemove) {
541
- data.disconnect();
542
- node.nd?.remove();
517
+ NDElement.prototype[name] = method;
518
+ }
519
+
520
+ return NDElement;
521
+ };
522
+
523
+ const COMMON_NODE_TYPES = {
524
+ ELEMENT: 1,
525
+ TEXT: 3,
526
+ COMMENT: 8,
527
+ DOCUMENT_FRAGMENT: 11
528
+ };
529
+
530
+ const VALID_TYPES = [];
531
+ VALID_TYPES[COMMON_NODE_TYPES.ELEMENT] = true;
532
+ VALID_TYPES[COMMON_NODE_TYPES.TEXT] = true;
533
+ VALID_TYPES[COMMON_NODE_TYPES.DOCUMENT_FRAGMENT] = true;
534
+ VALID_TYPES[COMMON_NODE_TYPES.COMMENT] = true;
535
+
536
+ const Validator = {
537
+ isObservable(value) {
538
+ return value?.__$isObservable;
539
+ },
540
+ isTemplateBinding(value) {
541
+ return value?.__$isTemplateBinding;
542
+ },
543
+ isObservableWhenResult(value) {
544
+ return value && (value.__$isObservableWhen || (typeof value === 'object' && '$target' in value && '$observer' in value));
545
+ },
546
+ isArrayObservable(value) {
547
+ return value?.__$isObservableArray;
548
+ },
549
+ isProxy(value) {
550
+ return value?.__isProxy__
551
+ },
552
+ isObservableOrProxy(value) {
553
+ return Validator.isObservable(value) || Validator.isProxy(value);
554
+ },
555
+ isAnchor(value) {
556
+ return value?.__Anchor__
557
+ },
558
+ isObservableChecker(value) {
559
+ return value?.__$isObservableChecker || value instanceof ObservableChecker;
560
+ },
561
+ isArray(value) {
562
+ return Array.isArray(value);
563
+ },
564
+ isString(value) {
565
+ return typeof value === 'string';
566
+ },
567
+ isNumber(value) {
568
+ return typeof value === 'number';
569
+ },
570
+ isBoolean(value) {
571
+ return typeof value === 'boolean';
572
+ },
573
+ isFunction(value) {
574
+ return typeof value === 'function';
575
+ },
576
+ isAsyncFunction(value) {
577
+ return typeof value === 'function' && value.constructor.name === 'AsyncFunction';
578
+ },
579
+ isObject(value) {
580
+ return typeof value === 'object' && value !== null;
581
+ },
582
+ isJson(value) {
583
+ return !(typeof value !== 'object' || value === null || Array.isArray(value) || value.constructor.name !== 'Object')
584
+ },
585
+ isElement(value) {
586
+ return value && VALID_TYPES[value.nodeType];
587
+ },
588
+ isDOMNode(value) {
589
+ return VALID_TYPES[value.nodeType];
590
+ },
591
+ isFragment(value) {
592
+ return value?.nodeType === COMMON_NODE_TYPES.DOCUMENT_FRAGMENT;
593
+ },
594
+ isStringOrObservable(value) {
595
+ return this.isString(value) || this.isObservable(value);
596
+ },
597
+ isValidChild(child) {
598
+ return child === null ||
599
+ this.isElement(child) ||
600
+ this.isObservable(child) ||
601
+ this.isNDElement(child) ||
602
+ ['string', 'number', 'boolean'].includes(typeof child);
603
+ },
604
+ isNDElement(child) {
605
+ return child?.__$isNDElement || child instanceof NDElement;
606
+ },
607
+ isValidChildren(children) {
608
+ if (!Array.isArray(children)) {
609
+ children = [children];
543
610
  }
611
+
612
+ const invalid = children.filter(child => !this.isValidChild(child));
613
+ return invalid.length === 0;
544
614
  },
615
+ validateChildren(children) {
616
+ if (!Array.isArray(children)) {
617
+ children = [children];
618
+ }
545
619
 
546
- checkMutation: function(mutationsList) {
547
- console.log('mutationsList', mutationsList);
548
- for(const mutation of mutationsList) {
549
- if(DocumentObserver.mountedSupposedSize > 0) {
550
- for(const node of mutation.addedNodes) {
551
- DocumentObserver.executeMountedCallback(node);
552
- if(!node.querySelectorAll) {
553
- continue;
554
- }
555
- const children = node.querySelectorAll('[data--nd-mounted]');
556
- for(const child of children) {
557
- DocumentObserver.executeMountedCallback(child);
558
- }
559
- }
560
- }
620
+ const invalid = children.filter(child => !this.isValidChild(child));
621
+ if (invalid.length > 0) {
622
+ throw new NativeDocumentError(`Invalid children detected: ${invalid.map(i => typeof i).join(', ')}`);
623
+ }
561
624
 
562
- if (DocumentObserver.unmountedSupposedSize > 0) {
563
- for (const node of mutation.removedNodes) {
564
- DocumentObserver.executeUnmountedCallback(node);
565
- if(!node.querySelectorAll) {
566
- continue;
567
- }
568
- const children = node.querySelectorAll('[data--nd-unmounted]');
569
- for(const child of children) {
570
- DocumentObserver.executeUnmountedCallback(child);
571
- }
572
- }
573
- }
625
+ return children;
626
+ },
627
+ /**
628
+ * Check if the data contains observables.
629
+ * @param {Array|Object} data
630
+ * @returns {boolean}
631
+ */
632
+ containsObservables(data) {
633
+ if(!data) {
634
+ return false;
574
635
  }
636
+ return Validator.isObject(data)
637
+ && Object.values(data).some(value => Validator.isObservable(value));
575
638
  },
576
-
577
639
  /**
578
- * @param {HTMLElement} element
579
- * @param {boolean} inDom
580
- * @returns {{ disconnect: Function, mounted: Function, unmounted: Function, off: Function }}
640
+ * Check if the data contains an observable reference.
641
+ * @param {string} data
642
+ * @returns {boolean}
581
643
  */
582
- watch: function(element, inDom = false) {
583
- let mountedRegistered = false;
584
- let unmountedRegistered = false;
644
+ containsObservableReference(data) {
645
+ if(!data || typeof data !== 'string') {
646
+ return false;
647
+ }
648
+ return /\{\{#ObItem::\([0-9]+\)\}\}/.test(data);
649
+ },
650
+ validateAttributes(attributes) {},
585
651
 
586
- DocumentObserver.initObserver();
652
+ validateEventCallback(callback) {
653
+ if (typeof callback !== 'function') {
654
+ throw new NativeDocumentError('Event callback must be a function');
655
+ }
656
+ }
657
+ };
587
658
 
588
- let data = {
589
- inDom,
590
- mounted: null,
591
- unmounted: null,
592
- disconnect: () => {
593
- if (mountedRegistered) {
594
- DocumentObserver.mounted.delete(element);
595
- DocumentObserver.mountedSupposedSize--;
596
- }
597
- if (unmountedRegistered) {
598
- DocumentObserver.unmounted.delete(element);
599
- DocumentObserver.unmountedSupposedSize--;
659
+ function createMultiSourceFilter(sources, callbackFn){
660
+ const observables = sources.filter(Validator.isObservable);
661
+
662
+ const getValues = () => sources.map(src =>
663
+ Validator.isObservable(src) ? src.val() : src
664
+ );
665
+
666
+ return {
667
+ dependencies: observables.length > 0 ? observables : null,
668
+ callback: (value) => callbackFn(value, getValues())
669
+ };
670
+ }
671
+
672
+ function match(patternObservableOrValue, asRegexObservableOrValue = true, flagsObservableOrValue = ''){
673
+ return createMultiSourceFilter(
674
+ [patternObservableOrValue, asRegexObservableOrValue, flagsObservableOrValue],
675
+ (value, [pattern, asRegex, flags]) => {
676
+ if (!pattern) return true;
677
+
678
+ if (asRegex){
679
+ try {
680
+ const regex = new RegExp(pattern, flags);
681
+ return regex.test(String(value));
682
+ } catch (error){
683
+ console.warn('Invalid regex pattern:', pattern, error);
684
+ return false;
600
685
  }
601
- data = null;
602
686
  }
603
- };
604
687
 
605
- const addListener = (type, callback) => {
606
- if (!data[type]) {
607
- data[type] = callback;
608
- return;
688
+ if (!flags || flags === ''){
689
+ return String(value).toLowerCase().includes(String(pattern).toLowerCase());
609
690
  }
610
- if (!Array.isArray(data[type])) {
611
- data[type] = [data[type], callback];
691
+ return String(value).includes(String(pattern));
692
+ }
693
+ );
694
+ }
695
+
696
+ const cssPropertyAccumulator = function(initialValue = {}) {
697
+ let data = Validator.isString(initialValue) ? initialValue.split(';').filter(Boolean) : initialValue;
698
+ const isArray = Validator.isArray(data);
699
+
700
+ return {
701
+ add(key, value) {
702
+ if(isArray) {
703
+ data.push(key+': '+value);
612
704
  return;
613
705
  }
614
- data[type].push(callback);
615
- };
706
+ data[key] = value;
707
+ },
708
+ value() {
709
+ if(isArray) {
710
+ return data.join(';').concat(';');
711
+ }
712
+ return { ...data };
713
+ },
714
+ };
715
+ };
616
716
 
617
- const removeListener = (type, callback) => {
618
- if(!data?.[type]) {
717
+ const classPropertyAccumulator = function(initialValue = []) {
718
+ let data = Validator.isString(initialValue) ? initialValue.split(" ").filter(Boolean) : initialValue;
719
+ const isArray = Validator.isArray(data);
720
+
721
+ return {
722
+ add(key, value = true) {
723
+ if(isArray) {
724
+ data.push(key);
619
725
  return;
620
726
  }
621
- if(Array.isArray(data[type])) {
622
- const index = data[type].indexOf(callback);
623
- if(index > -1) {
624
- data[type].splice(index, 1);
625
- }
626
- if(data[type].length === 1) {
627
- data[type] = data[type][0];
628
- }
629
- if(data[type].length === 0) {
630
- data[type] = null;
631
- }
632
- return;
727
+ data[key] = value;
728
+ },
729
+ value() {
730
+ if(isArray) {
731
+ return data.join(' ');
633
732
  }
634
- data[type] = null;
635
- };
733
+ return { ...data };
734
+ },
735
+ };
736
+ };
636
737
 
637
- return {
638
- disconnect: () => data?.disconnect(),
738
+ /**
739
+ *
740
+ * @class
741
+ */
742
+ function BaseComponent() {
743
+ this.$description = {};
744
+ this.$editableProps = null;
745
+ }
639
746
 
640
- mounted: (callback) => {
641
- addListener('mounted', callback);
642
- DocumentObserver.mounted.set(element, data);
643
- if (!mountedRegistered) {
644
- DocumentObserver.mountedSupposedSize++;
645
- mountedRegistered = true;
646
- }
647
- },
747
+ Object.defineProperty( BaseComponent.prototype, 'nd', {
748
+ get: function() {
749
+ if(this.$element) {
750
+ return this.$element.nd;
751
+ }
752
+ this.$storeElement(this.toNdElement());
753
+ return this.$element?.nd;
754
+ }
755
+ });
648
756
 
649
- unmounted: (callback) => {
650
- addListener('unmounted', callback);
651
- DocumentObserver.unmounted.set(element, data);
652
- if (!unmountedRegistered) {
653
- DocumentObserver.unmountedSupposedSize++;
654
- unmountedRegistered = true;
655
- }
656
- },
657
757
 
658
- off: (type, callback) => {
659
- removeListener(type, callback);
660
- }
661
- };
758
+ BaseComponent.extends = function(Component, ...parents) {
759
+ const MainParent = parents[0] || BaseComponent;
760
+ Component.prototype = Object.create(MainParent.prototype);
761
+
762
+ if(parents.length > 0) {
763
+ for(const parent of parents) {
764
+ Object.assign(Component.prototype, parent.prototype);
765
+ }
662
766
  }
767
+ Component.prototype.constructor = Component;
663
768
  };
664
769
 
665
- function NDElement(element) {
770
+ BaseComponent.use = function(Component, ...traits) {
771
+ if(traits.length > 0) {
772
+ for(const trait of traits) {
773
+ Object.assign(Component.prototype, trait.prototype);
774
+ }
775
+ }
776
+ };
777
+
778
+ BaseComponent.obs = (value) => {
779
+ return value.__$Observable ? value : Observable(value);
780
+ };
781
+
782
+ BaseComponent.prototype.$storeElement = function(element) {
666
783
  this.$element = element;
667
- }
784
+ return this;
785
+ };
668
786
 
669
- NDElement.prototype.__$isNDElement = true;
787
+ BaseComponent.prototype.refSelf = function(target, name) {
788
+ target[name] = this;
789
+ return this;
790
+ };
670
791
 
671
- NDElement.prototype.valueOf = function() {
792
+ BaseComponent.prototype.$build = function() {
793
+ const ComponentClass = this.constructor;
794
+ const renderer = this.$description.render || ComponentClass.defaultTemplate;
795
+
796
+ if (!renderer) {
797
+ throw new Error(`No renderer for ${ComponentClass.name}`);
798
+ }
799
+
800
+ return renderer(this.$description, this);
801
+ };
802
+
803
+ BaseComponent.prototype.toNdElement = function() {
804
+ if (this.$element) {
805
+ return this.$element;
806
+ }
807
+ this.$element = this.$build();
672
808
  return this.$element;
673
809
  };
674
810
 
675
- NDElement.prototype.ref = function(target, name) {
676
- target[name] = this.$element;
677
- return this;
811
+ BaseComponent.prototype.toJSON = function() {
812
+ if(!this.$description) {
813
+ return {};
814
+ }
815
+ return { ...this.$description };
678
816
  };
679
817
 
680
- NDElement.prototype.refSelf = function(target, name) {
681
- target[name] = new NDElement(this.$element);
818
+ BaseComponent.prototype.render = function(renderFn) {
819
+ if (typeof renderFn !== 'function') {
820
+ throw new Error('Custom renderer must be a function');
821
+ }
822
+ this.$description.render = renderFn;
682
823
  return this;
683
824
  };
684
825
 
685
- NDElement.prototype.unmountChildren = function() {
686
- let element = this.$element;
687
- for(let i = 0, length = element.children.length; i < length; i++) {
688
- let elementChildren = element.children[i];
689
- if(!elementChildren.$ndProx) {
690
- elementChildren.nd?.remove();
691
- }
692
- elementChildren = null;
826
+ BaseComponent.prototype.getEditableProps = function() {
827
+ if(!this.$editableProps) {
828
+ const rawProps = this.$description.props || {};
829
+ this.$editableProps = {
830
+ ...rawProps,
831
+ class: classPropertyAccumulator(this.$description.props.class),
832
+ style: cssPropertyAccumulator(this.$description.props.style)
833
+ };
693
834
  }
694
- element = null;
695
- return this;
835
+
836
+ return this.$editableProps;
837
+ };
838
+
839
+ BaseComponent.prototype.resolveProps = function() {
840
+ if(!this.$editableProps) {
841
+ return { ...this.$description.props };
842
+ }
843
+ const props = { ...this.$editableProps };
844
+ if(props.class) {
845
+ props.class = props.class.value();
846
+ }
847
+ if(props.style) {
848
+ props.style = props.style.value();
849
+ }
850
+ return props;
851
+ };
852
+
853
+ function HasEventEmitter() {
854
+
855
+ this.__$events = null;
856
+
857
+ }
858
+
859
+ HasEventEmitter.prototype.on = function(eventName, callback) {
860
+ if(!this.__$events) {
861
+ this.__$events = new Map();
862
+ }
863
+ if(!this.__$events.has(eventName)) {
864
+ this.__$events.set(eventName, callback);
865
+ return;
866
+ }
867
+ const existingCallback = this.__$events.get(eventName);
868
+ if(!Array.isArray(existingCallback)) {
869
+ this.__$events.set(eventName, [existingCallback, callback]);
870
+ return;
871
+ }
872
+ existingCallback.push(callback);
696
873
  };
697
874
 
698
- NDElement.prototype.remove = function() {
699
- let element = this.$element;
700
- element.nd.unmountChildren();
701
- element.$ndProx = null;
702
-
703
- $lifeCycleObservers.delete(element);
704
-
705
- element = null;
706
- return this;
875
+ HasEventEmitter.prototype.hasListeners = function(eventName) {
876
+ return !!this.__$events.get(eventName);
707
877
  };
708
878
 
709
- const $lifeCycleObservers = new WeakMap();
710
- NDElement.prototype.lifecycle = function(states) {
711
- const el = this.$element;
712
- if (!$lifeCycleObservers.has(el)) {
713
- $lifeCycleObservers.set(el, DocumentObserver.watch(el));
879
+ HasEventEmitter.prototype.trigger = async function(eventName, ...args) {
880
+ const callbacks = this.__$events.get(eventName);
881
+ if(!callbacks) {
882
+ // throw new NativeDocumentError(this.constructor.name, 'Event '+eventName+' not found');
883
+ return;
714
884
  }
715
- const observer = $lifeCycleObservers.get(el);
716
885
 
717
- if(states.mounted) {
718
- this.$element.setAttribute('data--nd-mounted', '1');
719
- observer.mounted(states.mounted);
886
+ if(typeof callbacks === 'function') {
887
+ return await Promise.resolve(callbacks.apply(this, args))
720
888
  }
721
- if(states.unmounted) {
722
- this.$element.setAttribute('data--nd-unmounted', '1');
723
- observer.unmounted(states.unmounted);
889
+
890
+ let result = null;
891
+ for(let i = 0, length = callbacks.length; i < length; i++) {
892
+ result = await Promise.resolve(await callbacks[i].apply(this, args));
724
893
  }
725
- return this;
894
+ return result;
726
895
  };
896
+ HasEventEmitter.prototype.emit = HasEventEmitter.prototype.trigger;
727
897
 
728
- NDElement.prototype.mounted = function(callback) {
729
- return this.lifecycle({ mounted: callback });
730
- };
898
+ /**
899
+ * Valid children types that can be rendered in the DOM
900
+ * @typedef {HTMLElement|Text|DocumentFragment|string|Array<ValidChildren>} ValidChildren
901
+ */
731
902
 
732
- NDElement.prototype.unmounted = function(callback) {
733
- return this.lifecycle({ unmounted: callback });
734
- };
903
+ /**
904
+ * Component for creating accordion interfaces with expandable/collapsible items
905
+ * @param {{ items?: Array<AccordionItem>, multiple?: boolean, variant?: string, renderContent?: (field: Accordion) => HTMLElement }} config
906
+ * @returns {Accordion}
907
+ * @class
908
+ */
909
+ function Accordion(config = {}) {
910
+ if (!(this instanceof Accordion)) {
911
+ return new Accordion(config);
912
+ }
735
913
 
736
- NDElement.prototype.beforeUnmount = function(id, callback) {
737
- const el = this.$element;
914
+ this.$description = {
915
+ items: [],
916
+ multiple: null,
917
+ variant: null,
918
+ renderContent: null,
919
+ ...config
920
+ };
921
+ }
738
922
 
739
- if(!DocumentObserver.beforeUnmount.has(el)) {
740
- DocumentObserver.beforeUnmount.set(el, new Map());
741
- const originalRemove = el.remove.bind(el);
923
+ BaseComponent.extends(Accordion, HasEventEmitter);
742
924
 
743
- let $isUnmounting = false;
925
+ Accordion.defaultTemplate = null;
744
926
 
745
- el.remove = async () => {
746
- if($isUnmounting) {
747
- return;
748
- }
749
- $isUnmounting = true;
750
927
 
751
- try {
752
- const callbacks = DocumentObserver.beforeUnmount.get(el);
753
- for (const cb of callbacks.values()) {
754
- await cb.call(this, el);
755
- }
756
- } finally {
757
- originalRemove();
758
- $isUnmounting = false;
759
- }
760
- };
761
- }
928
+ /**
929
+ * Sets the default template for all Accordion instances
930
+ * @param {{accordion: (accordion: Accordion) => ValidChildren}} template - Template object containing accordion factory function
931
+ */
932
+ Accordion.use = function(template) {
933
+ Accordion.defaultTemplate = template.accordion;
934
+ };
762
935
 
763
- DocumentObserver.beforeUnmount.get(el).set(id, callback);
936
+ /**
937
+ * Adds an accordion item to the collection
938
+ * @param {AccordionItem} accordionItem - The accordion item to add
939
+ * @returns {Accordion}
940
+ */
941
+ Accordion.prototype.item = function(accordionItem) {
942
+ this.$description.items.push(accordionItem);
764
943
  return this;
765
944
  };
766
945
 
767
- NDElement.prototype.htmlElement = function() {
768
- return this.$element;
946
+ /**
947
+ * Sets the accordion items collection
948
+ * @param {Array<AccordionItem>} items - Array of accordion items
949
+ * @returns {Accordion}
950
+ */
951
+ Accordion.prototype.items = function(items) {
952
+ this.$description.items = items;
953
+ return this;
769
954
  };
770
955
 
771
- NDElement.prototype.node = NDElement.prototype.htmlElement;
956
+ /**
957
+ * Alias for item method
958
+ * @param {AccordionItem} accordionItem - The accordion item to add
959
+ * @returns {Accordion}
960
+ */
961
+ Accordion.prototype.addItem = Accordion.prototype.item;
772
962
 
773
- NDElement.prototype.shadow = function(mode, style = null) {
774
- const $element = this.$element;
775
- const children = Array.from($element.childNodes);
776
- const shadowRoot = $element.attachShadow({ mode });
777
- if(style) {
778
- const styleNode = document.createElement("style");
779
- styleNode.textContent = style;
780
- shadowRoot.appendChild(styleNode);
963
+ /**
964
+ * Removes an item by its id
965
+ * @param {string} id - The id of the item to remove
966
+ * @returns {Accordion}
967
+ */
968
+ Accordion.prototype.removeItemById = function(id) {
969
+ if (this.$description.items) {
970
+ this.$description.items = this.$description.items.filter(item => item.id !== id);
781
971
  }
782
- $element.append = shadowRoot.append.bind(shadowRoot);
783
- $element.appendChild = shadowRoot.appendChild.bind(shadowRoot);
784
- shadowRoot.append(...children);
785
-
786
972
  return this;
787
973
  };
788
974
 
789
- NDElement.prototype.openShadow = function(style = null) {
790
- return this.shadow('open', style);
975
+ /**
976
+ * Removes items matching the filter function
977
+ * @param {Function} filter - Filter function to determine which items to keep
978
+ * @returns {Accordion}
979
+ */
980
+ Accordion.prototype.remove = function(filter) {
981
+ if (this.$description.items) {
982
+ this.$description.items = this.$description.items.filter(filter);
983
+ }
984
+ return this;
791
985
  };
792
986
 
793
- NDElement.prototype.closedShadow = function(style = null) {
794
- return this.shadow('closed', style);
987
+ /**
988
+ * Enables or disables multiple items expansion
989
+ * @param {boolean} [enabled=true] - Whether multiple items can be expanded simultaneously
990
+ * @returns {Accordion}
991
+ */
992
+ Accordion.prototype.multiple = function(enabled = true) {
993
+ this.$description.multiple = enabled;
994
+ return this;
795
995
  };
796
996
 
797
997
  /**
798
- * Extends the current NDElement instance with custom methods.
799
- * Methods are bound to the instance and available for chaining.
800
- *
801
- * @param {Object} methods - Object containing method definitions
802
- * @returns {this} The NDElement instance with added methods for chaining
803
- * @example
804
- * element.nd.with({
805
- * highlight() {
806
- * this.$element.style.background = 'yellow';
807
- * return this;
808
- * }
809
- * }).highlight().onClick(() => console.log('Clicked'));
998
+ * Sets the variant style for the accordion
999
+ * @param {string} name - The variant name
1000
+ * @returns {Accordion}
810
1001
  */
811
- NDElement.prototype.with = function(methods) {
812
- if (!methods || typeof methods !== 'object') {
813
- throw new NativeDocumentError('extend() requires an object of methods');
814
- }
815
-
816
- for (const name in methods) {
817
- const method = methods[name];
818
-
819
- if (typeof method !== 'function') {
820
- console.warn(`⚠️ extends(): "${name}" is not a function, skipping`);
821
- continue;
822
- }
823
-
824
- this[name] = method.bind(this);
825
- }
826
-
1002
+ Accordion.prototype.variant = function(name) {
1003
+ this.$description.variant = name;
827
1004
  return this;
828
1005
  };
829
1006
 
830
1007
  /**
831
- * Extends the NDElement prototype with new methods available to all NDElement instances.
832
- * Use this to add global methods to all NDElements.
833
- *
834
- * @param {Object} methods - Object containing method definitions to add to prototype
835
- * @returns {typeof NDElement} The NDElement constructor
836
- * @throws {NativeDocumentError} If methods is not an object or contains non-function values
837
- * @example
838
- * NDElement.extend({
839
- * fadeIn() {
840
- * this.$element.style.opacity = '1';
841
- * return this;
842
- * }
843
- * });
844
- * // Now all NDElements have .fadeIn() method
845
- * Div().nd.fadeIn();
1008
+ * Sets the accordion variant to 'bordered'
1009
+ * @returns {Accordion}
846
1010
  */
847
- NDElement.extend = function(methods) {
848
- if (!methods || typeof methods !== 'object') {
849
- throw new NativeDocumentError('NDElement.extend() requires an object of methods');
850
- }
851
-
852
- if (Array.isArray(methods)) {
853
- throw new NativeDocumentError('NDElement.extend() requires an object, not an array');
854
- }
855
-
856
- const protectedMethods = new Set([
857
- 'constructor', 'valueOf', '$element', '$observer',
858
- 'ref', 'remove', 'cleanup', 'with', 'extend', 'attach',
859
- 'lifecycle', 'mounted', 'unmounted', 'unmountChildren'
860
- ]);
861
-
862
- for (const name in methods) {
863
- if (!Object.hasOwn(methods, name)) {
864
- continue;
865
- }
1011
+ Accordion.prototype.bordered = function() {
1012
+ return this.variant('bordered');
1013
+ };
866
1014
 
867
- const method = methods[name];
1015
+ /**
1016
+ * Sets the accordion variant to 'separated'
1017
+ * @returns {Accordion}
1018
+ */
1019
+ Accordion.prototype.separated = function() {
1020
+ return this.variant('separated');
1021
+ };
868
1022
 
869
- if (typeof method !== 'function') {
870
- DebugManager$2.warn('NDElement.extend', `"${name}" is not a function, skipping`);
871
- continue;
872
- }
1023
+ /**
1024
+ * Sets the accordion variant to 'flush'
1025
+ * @returns {Accordion}
1026
+ */
1027
+ Accordion.prototype.flush = function() {
1028
+ return this.variant('flush');
1029
+ };
873
1030
 
874
- if (protectedMethods.has(name)) {
875
- DebugManager$2.error('NDElement.extend', `Cannot override protected method "${name}"`);
876
- throw new NativeDocumentError(`Cannot override protected method "${name}"`);
877
- }
1031
+ /**
1032
+ * Retrieves an accordion item by its key
1033
+ * @param {string} key - The key of the item to retrieve
1034
+ * @returns {AccordionItem|undefined}
1035
+ */
1036
+ Accordion.prototype.getByKey = function(key) {
1037
+ return this.$description.items.find(item => item.key === key);
1038
+ };
878
1039
 
879
- if (NDElement.prototype[name]) {
880
- DebugManager$2.warn('NDElement.extend', `Overwriting existing prototype method "${name}"`);
1040
+ /**
1041
+ * Expands or collapses an accordion item by key
1042
+ * @param {string} key - The key of the item
1043
+ * @param {boolean} [state=true] - Whether to expand (true) or collapse (false)
1044
+ * @returns {Accordion}
1045
+ */
1046
+ Accordion.prototype.expanded = function(key, state = true) {
1047
+ const item = this.getByKey(key);
1048
+ if(item) {
1049
+ if (state && !this.$description.multiple) {
1050
+ this.collapseAll();
881
1051
  }
882
-
883
- NDElement.prototype[name] = method;
1052
+ item.expanded(state);
1053
+ this.emit(state ? 'expand' : 'collapse', key, state);
884
1054
  }
885
-
886
- return NDElement;
1055
+ return this;
887
1056
  };
888
1057
 
889
- const COMMON_NODE_TYPES = {
890
- ELEMENT: 1,
891
- TEXT: 3,
892
- COMMENT: 8,
893
- DOCUMENT_FRAGMENT: 11
1058
+ /**
1059
+ * Expands all accordion items
1060
+ * @returns {Accordion}
1061
+ */
1062
+ Accordion.prototype.expandAll = function() {
1063
+ this.$description.items.forEach(item => item.expanded(true));
1064
+ return this;
894
1065
  };
895
1066
 
896
- const VALID_TYPES = [];
897
- VALID_TYPES[COMMON_NODE_TYPES.ELEMENT] = true;
898
- VALID_TYPES[COMMON_NODE_TYPES.TEXT] = true;
899
- VALID_TYPES[COMMON_NODE_TYPES.DOCUMENT_FRAGMENT] = true;
900
- VALID_TYPES[COMMON_NODE_TYPES.COMMENT] = true;
1067
+ /**
1068
+ * Collapses all accordion items
1069
+ * @returns {Accordion}
1070
+ */
1071
+ Accordion.prototype.collapseAll = function() {
1072
+ this.$description.items.forEach(item => item.expanded(false));
1073
+ return this;
1074
+ };
901
1075
 
902
- const Validator = {
903
- isObservable(value) {
904
- return value?.__$isObservable;
905
- },
906
- isTemplateBinding(value) {
907
- return value?.__$isTemplateBinding;
908
- },
909
- isObservableWhenResult(value) {
910
- return value && (value.__$isObservableWhen || (typeof value === 'object' && '$target' in value && '$observer' in value));
911
- },
912
- isArrayObservable(value) {
913
- return value?.__$isObservableArray;
914
- },
915
- isProxy(value) {
916
- return value?.__isProxy__
917
- },
918
- isObservableOrProxy(value) {
919
- return Validator.isObservable(value) || Validator.isProxy(value);
920
- },
921
- isAnchor(value) {
922
- return value?.__Anchor__
923
- },
924
- isObservableChecker(value) {
925
- return value?.__$isObservableChecker || value instanceof ObservableChecker;
926
- },
927
- isArray(value) {
928
- return Array.isArray(value);
929
- },
930
- isString(value) {
931
- return typeof value === 'string';
932
- },
933
- isNumber(value) {
934
- return typeof value === 'number';
935
- },
936
- isBoolean(value) {
937
- return typeof value === 'boolean';
938
- },
939
- isFunction(value) {
940
- return typeof value === 'function';
941
- },
942
- isAsyncFunction(value) {
943
- return typeof value === 'function' && value.constructor.name === 'AsyncFunction';
944
- },
945
- isObject(value) {
946
- return typeof value === 'object' && value !== null;
947
- },
948
- isJson(value) {
949
- return !(typeof value !== 'object' || value === null || Array.isArray(value) || value.constructor.name !== 'Object')
950
- },
951
- isElement(value) {
952
- return value && VALID_TYPES[value.nodeType];
953
- },
954
- isDOMNode(value) {
955
- return VALID_TYPES[value.nodeType];
956
- },
957
- isFragment(value) {
958
- return value?.nodeType === COMMON_NODE_TYPES.DOCUMENT_FRAGMENT;
959
- },
960
- isStringOrObservable(value) {
961
- return this.isString(value) || this.isObservable(value);
962
- },
963
- isValidChild(child) {
964
- return child === null ||
965
- this.isElement(child) ||
966
- this.isObservable(child) ||
967
- this.isNDElement(child) ||
968
- ['string', 'number', 'boolean'].includes(typeof child);
969
- },
970
- isNDElement(child) {
971
- return child?.__$isNDElement || child instanceof NDElement;
972
- },
973
- isValidChildren(children) {
974
- if (!Array.isArray(children)) {
975
- children = [children];
976
- }
1076
+ /**
1077
+ * Checks if an accordion item is expanded
1078
+ * @param {string} key - The key of the item to check
1079
+ * @returns {boolean|undefined}
1080
+ */
1081
+ Accordion.prototype.isExpanded = function(key) {
1082
+ return this.getByKey(key)?.isExpanded?.();
1083
+ };
977
1084
 
978
- const invalid = children.filter(child => !this.isValidChild(child));
979
- return invalid.length === 0;
980
- },
981
- validateChildren(children) {
982
- if (!Array.isArray(children)) {
983
- children = [children];
984
- }
1085
+ /**
1086
+ * Registers a handler for the expand event
1087
+ * @param {Function} handler - The event handler
1088
+ * @returns {Accordion}
1089
+ */
1090
+ Accordion.prototype.onExpand = function(handler) {
1091
+ this.on('expand', handler);
1092
+ return this;
1093
+ };
985
1094
 
986
- const invalid = children.filter(child => !this.isValidChild(child));
987
- if (invalid.length > 0) {
988
- throw new NativeDocumentError(`Invalid children detected: ${invalid.map(i => typeof i).join(', ')}`);
989
- }
1095
+ /**
1096
+ * Registers a handler for the collapse event
1097
+ * @param {Function} handler - The event handler
1098
+ * @returns {Accordion}
1099
+ */
1100
+ Accordion.prototype.onCollapse = function(handler) {
1101
+ this.on('collapse', handler);
1102
+ return this;
1103
+ };
990
1104
 
991
- return children;
992
- },
993
- /**
994
- * Check if the data contains observables.
995
- * @param {Array|Object} data
996
- * @returns {boolean}
997
- */
998
- containsObservables(data) {
999
- if(!data) {
1000
- return false;
1001
- }
1002
- return Validator.isObject(data)
1003
- && Object.values(data).some(value => Validator.isObservable(value));
1004
- },
1005
- /**
1006
- * Check if the data contains an observable reference.
1007
- * @param {string} data
1008
- * @returns {boolean}
1009
- */
1010
- containsObservableReference(data) {
1011
- if(!data || typeof data !== 'string') {
1012
- return false;
1013
- }
1014
- return /\{\{#ObItem::\([0-9]+\)\}\}/.test(data);
1015
- },
1016
- validateAttributes(attributes) {},
1105
+ /**
1106
+ * Sets the content render function
1107
+ * @param {Function} renderFn - Function to render content
1108
+ * @returns {Accordion}
1109
+ */
1110
+ Accordion.prototype.renderContent = function(renderFn) {
1111
+ this.$description.renderContent = renderFn;
1112
+ return this;
1113
+ };
1017
1114
 
1018
- validateEventCallback(callback) {
1019
- if (typeof callback !== 'function') {
1020
- throw new NativeDocumentError('Event callback must be a function');
1021
- }
1022
- }
1115
+ /**
1116
+ * Builds the accordion component
1117
+ * @private
1118
+ */
1119
+ Accordion.prototype.$build = function() {
1120
+ // TODO: Implementation
1121
+ // this.$description.items.forEach(item => {
1122
+ // item.onExpand(() => {
1123
+ // if (!this.$description.multiple) {
1124
+ // this.$description.items
1125
+ // .filter(i => i !== item)
1126
+ // .forEach(i => i.expanded(false));
1127
+ // }
1128
+ // });
1129
+ // });
1023
1130
  };
1024
1131
 
1025
1132
  const BOOLEAN_ATTRIBUTES = new Set([
@@ -1102,7 +1209,7 @@ var NativeComponents = (function (exports) {
1102
1209
  }
1103
1210
  }
1104
1211
  if (cleanedCount > 0) {
1105
- DebugManager$2.log('Memory Auto Clean', `🧹 Cleaned ${cleanedCount} orphaned observables`);
1212
+ DebugManager$1.log('Memory Auto Clean', `🧹 Cleaned ${cleanedCount} orphaned observables`);
1106
1213
  }
1107
1214
  }
1108
1215
  };
@@ -3241,43 +3348,6 @@ var NativeComponents = (function (exports) {
3241
3348
  });
3242
3349
  };
3243
3350
 
3244
- function createMultiSourceFilter(sources, callbackFn){
3245
- const observables = sources.filter(Validator.isObservable);
3246
-
3247
- const getValues = () => sources.map(src =>
3248
- Validator.isObservable(src) ? src.val() : src
3249
- );
3250
-
3251
- return {
3252
- dependencies: observables.length > 0 ? observables : null,
3253
- callback: (value) => callbackFn(value, getValues())
3254
- };
3255
- }
3256
-
3257
- function match(patternObservableOrValue, asRegexObservableOrValue = true, flagsObservableOrValue = ''){
3258
- return createMultiSourceFilter(
3259
- [patternObservableOrValue, asRegexObservableOrValue, flagsObservableOrValue],
3260
- (value, [pattern, asRegex, flags]) => {
3261
- if (!pattern) return true;
3262
-
3263
- if (asRegex){
3264
- try {
3265
- const regex = new RegExp(pattern, flags);
3266
- return regex.test(String(value));
3267
- } catch (error){
3268
- console.warn('Invalid regex pattern:', pattern, error);
3269
- return false;
3270
- }
3271
- }
3272
-
3273
- if (!flags || flags === ''){
3274
- return String(value).toLowerCase().includes(String(pattern).toLowerCase());
3275
- }
3276
- return String(value).includes(String(pattern));
3277
- }
3278
- );
3279
- }
3280
-
3281
3351
  const mutationMethods = ['push', 'pop', 'shift', 'unshift', 'reverse', 'sort', 'splice'];
3282
3352
  const noMutationMethods = ['map', 'forEach', 'filter', 'reduce', 'some', 'every', 'find', 'findIndex', 'concat', 'includes', 'indexOf'];
3283
3353
 
@@ -3958,7 +4028,7 @@ var NativeComponents = (function (exports) {
3958
4028
  const $getStoreOrThrow = (method, name) => {
3959
4029
  const item = $stores.get(name);
3960
4030
  if (!item) {
3961
- DebugManager$2.error('Store', `Store.${method}('${name}') : store not found. Did you call Store.create('${name}') first?`);
4031
+ DebugManager$1.error('Store', `Store.${method}('${name}') : store not found. Did you call Store.create('${name}') first?`);
3962
4032
  throw new NativeDocumentError(
3963
4033
  `Store.${method}('${name}') : store not found.`
3964
4034
  );
@@ -3971,7 +4041,7 @@ var NativeComponents = (function (exports) {
3971
4041
  */
3972
4042
  const $applyReadOnly = (observer, name, context) => {
3973
4043
  const readOnlyError = (method) => () => {
3974
- DebugManager$2.error('Store', `Store.${context}('${name}') is read-only. '${method}()' is not allowed.`);
4044
+ DebugManager$1.error('Store', `Store.${context}('${name}') is read-only. '${method}()' is not allowed.`);
3975
4045
  throw new NativeDocumentError(
3976
4046
  `Store.${context}('${name}') is read-only.`
3977
4047
  );
@@ -4002,7 +4072,7 @@ var NativeComponents = (function (exports) {
4002
4072
  */
4003
4073
  create(name, value) {
4004
4074
  if ($stores.has(name)) {
4005
- DebugManager$2.warn('Store', `Store.create('${name}') : a store with this name already exists. Use Store.get('${name}') to retrieve it.`);
4075
+ DebugManager$1.warn('Store', `Store.create('${name}') : a store with this name already exists. Use Store.get('${name}') to retrieve it.`);
4006
4076
  throw new NativeDocumentError(
4007
4077
  `Store.create('${name}') : a store with this name already exists.`
4008
4078
  );
@@ -4023,7 +4093,7 @@ var NativeComponents = (function (exports) {
4023
4093
  */
4024
4094
  createResettable(name, value) {
4025
4095
  if ($stores.has(name)) {
4026
- DebugManager$2.warn('Store', `Store.createResettable('${name}') : a store with this name already exists.`);
4096
+ DebugManager$1.warn('Store', `Store.createResettable('${name}') : a store with this name already exists.`);
4027
4097
  throw new NativeDocumentError(
4028
4098
  `Store.createResettable('${name}') : a store with this name already exists.`
4029
4099
  );
@@ -4059,7 +4129,7 @@ var NativeComponents = (function (exports) {
4059
4129
  */
4060
4130
  createComposed(name, computation, dependencies) {
4061
4131
  if ($stores.has(name)) {
4062
- DebugManager$2.warn('Store', `Store.createComposed('${name}') : a store with this name already exists.`);
4132
+ DebugManager$1.warn('Store', `Store.createComposed('${name}') : a store with this name already exists.`);
4063
4133
  throw new NativeDocumentError(
4064
4134
  `Store.createComposed('${name}') : a store with this name already exists.`
4065
4135
  );
@@ -4082,7 +4152,7 @@ var NativeComponents = (function (exports) {
4082
4152
  }
4083
4153
  const depItem = $stores.get(depName);
4084
4154
  if (!depItem) {
4085
- DebugManager$2.error('Store', `Store.createComposed('${name}') : dependency '${depName}' not found. Create it first.`);
4155
+ DebugManager$1.error('Store', `Store.createComposed('${name}') : dependency '${depName}' not found. Create it first.`);
4086
4156
  throw new NativeDocumentError(
4087
4157
  `Store.createComposed('${name}') : dependency store '${depName}' not found.`
4088
4158
  );
@@ -4116,13 +4186,13 @@ var NativeComponents = (function (exports) {
4116
4186
  reset(name) {
4117
4187
  const item = $getStoreOrThrow('reset', name);
4118
4188
  if (item.composed) {
4119
- DebugManager$2.error('Store', `Store.reset('${name}') : composed stores cannot be reset. Their value is derived from dependencies.`);
4189
+ DebugManager$1.error('Store', `Store.reset('${name}') : composed stores cannot be reset. Their value is derived from dependencies.`);
4120
4190
  throw new NativeDocumentError(
4121
4191
  `Store.reset('${name}') : composed stores cannot be reset.`
4122
4192
  );
4123
4193
  }
4124
4194
  if (!item.resettable) {
4125
- DebugManager$2.error('Store', `Store.reset('${name}') : this store is not resettable. Use Store.createResettable('${name}', value) instead of Store.create().`);
4195
+ DebugManager$1.error('Store', `Store.reset('${name}') : this store is not resettable. Use Store.createResettable('${name}', value) instead of Store.create().`);
4126
4196
  throw new NativeDocumentError(
4127
4197
  `Store.reset('${name}') : this store is not resettable. Use Store.createResettable('${name}', value) instead of Store.create().`
4128
4198
  );
@@ -4143,7 +4213,7 @@ var NativeComponents = (function (exports) {
4143
4213
  const item = $getStoreOrThrow('use', name);
4144
4214
 
4145
4215
  if (item.composed) {
4146
- DebugManager$2.error('Store', `Store.use('${name}') : composed stores are read-only. Use Store.follow('${name}') instead.`);
4216
+ DebugManager$1.error('Store', `Store.use('${name}') : composed stores are read-only. Use Store.follow('${name}') instead.`);
4147
4217
  throw new NativeDocumentError(
4148
4218
  `Store.use('${name}') : composed stores are read-only. Use Store.follow('${name}') instead.`
4149
4219
  );
@@ -4210,7 +4280,7 @@ var NativeComponents = (function (exports) {
4210
4280
  get(name) {
4211
4281
  const item = $stores.get(name);
4212
4282
  if (!item) {
4213
- DebugManager$2.warn('Store', `Store.get('${name}') : store not found.`);
4283
+ DebugManager$1.warn('Store', `Store.get('${name}') : store not found.`);
4214
4284
  return null;
4215
4285
  }
4216
4286
  return item.observer;
@@ -4232,7 +4302,7 @@ var NativeComponents = (function (exports) {
4232
4302
  delete(name) {
4233
4303
  const item = $stores.get(name);
4234
4304
  if (!item) {
4235
- DebugManager$2.warn('Store', `Store.delete('${name}') : store not found, nothing to delete.`);
4305
+ DebugManager$1.warn('Store', `Store.delete('${name}') : store not found, nothing to delete.`);
4236
4306
  return;
4237
4307
  }
4238
4308
  item.subscribers.forEach(follower => follower.destroy());
@@ -4334,7 +4404,7 @@ var NativeComponents = (function (exports) {
4334
4404
  return undefined;
4335
4405
  },
4336
4406
  set(target, prop, value) {
4337
- DebugManager$2.error('Store', `Forbidden: You cannot overwrite the store key '${String(prop)}'. Use .use('${String(prop)}').set(value) instead.`);
4407
+ DebugManager$1.error('Store', `Forbidden: You cannot overwrite the store key '${String(prop)}'. Use .use('${String(prop)}').set(value) instead.`);
4338
4408
  throw new NativeDocumentError(`Store structure is immutable. Use .set() on the observable.`);
4339
4409
  },
4340
4410
  deleteProperty(target, prop) {
@@ -5524,7 +5594,7 @@ var NativeComponents = (function (exports) {
5524
5594
 
5525
5595
  Badge.preset = function(name, callback) {
5526
5596
  if (Badge.prototype[name] || Badge[name]) {
5527
- DebugManager$2.warn(`Warning: the ${name} method already exists in Badge.`);
5597
+ DebugManager$1.warn(`Warning: the ${name} method already exists in Badge.`);
5528
5598
  return;
5529
5599
  }
5530
5600
  Badge[name] = (content, props) => callback(new Badge(content, props));
@@ -6293,7 +6363,7 @@ var NativeComponents = (function (exports) {
6293
6363
 
6294
6364
  Divider.preset = function(name, callback) {
6295
6365
  if (Divider.prototype[name] || Divider[name]) {
6296
- DebugManager$2.warn(`Warning: the ${name} method already exists in Divider.`);
6366
+ DebugManager$1.warn(`Warning: the ${name} method already exists in Divider.`);
6297
6367
  return;
6298
6368
  }
6299
6369
  Divider[name] = (label, props) => callback(new Divider(label, props));
@@ -10281,7 +10351,7 @@ var NativeComponents = (function (exports) {
10281
10351
 
10282
10352
  Progress.preset = function(name, callback) {
10283
10353
  if (Progress.prototype[name] || Progress[name]) {
10284
- DebugManager$2.warn(`Warning: the ${name} method already exists in Progress.`);
10354
+ DebugManager$1.warn(`Warning: the ${name} method already exists in Progress.`);
10285
10355
  return;
10286
10356
  }
10287
10357
  Progress[name] = (props) => callback(new Progress(props));
@@ -10513,7 +10583,7 @@ var NativeComponents = (function (exports) {
10513
10583
 
10514
10584
  Skeleton.preset = function(name, callback) {
10515
10585
  if (Skeleton.prototype[name] || Skeleton[name]) {
10516
- DebugManager$2.warn(`Warning: the ${name} method already exists in Skeleton.`);
10586
+ DebugManager$1.warn(`Warning: the ${name} method already exists in Skeleton.`);
10517
10587
  return;
10518
10588
  }
10519
10589
  Skeleton[name] = (props) => callback(new Skeleton(props));
@@ -10829,7 +10899,7 @@ var NativeComponents = (function (exports) {
10829
10899
 
10830
10900
  Spinner.preset = function(name, callback) {
10831
10901
  if (Spinner.prototype[name] || Spinner[name]) {
10832
- DebugManager$2.warn(`Warning: the ${name} method already exists in Spinner.`);
10902
+ DebugManager$1.warn(`Warning: the ${name} method already exists in Spinner.`);
10833
10903
  return;
10834
10904
  }
10835
10905
  Spinner[name] = (props) => callback(new Spinner(props));
@@ -12427,7 +12497,7 @@ var NativeComponents = (function (exports) {
12427
12497
 
12428
12498
  VStack.preset = function(name, callback) {
12429
12499
  if (VStack.prototype[name] || VStack[name]) {
12430
- DebugManager$2.warn(`Warning: the ${name} method already exists in VStack.`);
12500
+ DebugManager$1.warn(`Warning: the ${name} method already exists in VStack.`);
12431
12501
  return;
12432
12502
  }
12433
12503
  VStack[name] = (content, props) => callback(new VStack(content, props));
@@ -12461,7 +12531,7 @@ var NativeComponents = (function (exports) {
12461
12531
 
12462
12532
  ZStack.preset = function(name, callback) {
12463
12533
  if (ZStack.prototype[name] || ZStack[name]) {
12464
- DebugManager$2.warn(`Warning: the ${name} method already exists in ZStack.`);
12534
+ DebugManager$1.warn(`Warning: the ${name} method already exists in ZStack.`);
12465
12535
  return;
12466
12536
  }
12467
12537
  ZStack[name] = (content, props) => callback(new ZStack(content, props));
@@ -12496,7 +12566,7 @@ var NativeComponents = (function (exports) {
12496
12566
 
12497
12567
  HStack.preset = function(name, callback) {
12498
12568
  if (HStack.prototype[name] || HStack[name]) {
12499
- DebugManager$2.warn(`Warning: the ${name} method already exists in HStack.`);
12569
+ DebugManager$1.warn(`Warning: the ${name} method already exists in HStack.`);
12500
12570
  return;
12501
12571
  }
12502
12572
  HStack[name] = (content, props) => callback(new HStack(content, props));