native-document 1.0.137 → 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;
36
+ ObservableChecker.prototype.__$Observable = true;
37
+ ObservableChecker.prototype.__$isObservableChecker = true;
164
38
 
39
+ /**
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
48
+ */
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;
55
+ };
165
56
 
166
57
  /**
167
- * Sets the default template for all Accordion instances
168
- * @param {{accordion: (accordion: Accordion) => ValidChildren}} template - Template object containing accordion factory function
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
169
67
  */
170
- Accordion.use = function(template) {
171
- Accordion.defaultTemplate = template.accordion;
68
+ ObservableChecker.prototype.check = function(callback) {
69
+ return this.observable.check(() => callback(this.val()));
172
70
  };
173
71
 
174
72
  /**
175
- * Adds an accordion item to the collection
176
- * @param {AccordionItem} accordionItem - The accordion item to add
177
- * @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
178
80
  */
179
- Accordion.prototype.item = function(accordionItem) {
180
- this.$description.items.push(accordionItem);
181
- return this;
81
+ ObservableChecker.prototype.val = function() {
82
+ return this.checker && this.checker(this.observable.val());
182
83
  };
183
84
 
184
85
  /**
185
- * Sets the accordion items collection
186
- * @param {Array<AccordionItem>} items - Array of accordion items
187
- * @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
188
93
  */
189
- Accordion.prototype.items = function(items) {
190
- this.$description.items = items;
191
- return this;
94
+ ObservableChecker.prototype.set = function(value) {
95
+ return this.observable.set(value);
192
96
  };
193
97
 
194
98
  /**
195
- * Alias for item method
196
- * @param {AccordionItem} accordionItem - The accordion item to add
197
- * @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
198
105
  */
199
- Accordion.prototype.addItem = Accordion.prototype.item;
106
+ ObservableChecker.prototype.trigger = function() {
107
+ return this.observable.trigger();
108
+ };
200
109
 
201
110
  /**
202
- * Removes an item by its id
203
- * @param {string} id - The id of the item to remove
204
- * @returns {Accordion}
111
+ * Cleans up the underlying observable and all its subscriptions.
205
112
  */
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;
113
+ ObservableChecker.prototype.cleanup = function() {
114
+ return this.observable.cleanup();
211
115
  };
212
116
 
213
- /**
214
- * Removes items matching the filter function
215
- * @param {Function} filter - Filter function to determine which items to keep
216
- * @returns {Accordion}
217
- */
218
- Accordion.prototype.remove = function(filter) {
219
- if (this.$description.items) {
220
- this.$description.items = this.$description.items.filter(filter);
221
- }
222
- return this;
223
- };
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
+ },
224
134
 
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
- };
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
+ },
234
152
 
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
- };
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
+ }
244
162
 
245
- /**
246
- * Sets the accordion variant to 'bordered'
247
- * @returns {Accordion}
248
- */
249
- Accordion.prototype.bordered = function() {
250
- return this.variant('bordered');
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$2 = {};
371
- {
372
- DebugManager$2 = {
373
- log() {},
374
- warn() {},
375
- error() {},
376
- disable() {}
377
- };
378
- }
379
- var DebugManager$1 = DebugManager$2;
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
- }
416
+ $element.append = shadowRoot.append.bind(shadowRoot);
417
+ $element.appendChild = shadowRoot.appendChild.bind(shadowRoot);
418
+ shadowRoot.append(...children);
401
419
 
402
- ObservableChecker.prototype.__$Observable = true;
403
- ObservableChecker.prototype.__$isObservableChecker = true;
420
+ return this;
421
+ };
404
422
 
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;
423
+ NDElement.prototype.openShadow = function(style = null) {
424
+ return this.shadow('open', style);
421
425
  };
422
426
 
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()));
427
+ NDElement.prototype.closedShadow = function(style = null) {
428
+ return this.shadow('closed', style);
436
429
  };
437
430
 
438
431
  /**
439
- * Gets the current transformed/checked value.
432
+ * Extends the current NDElement instance with custom methods.
433
+ * Methods are bound to the instance and available for chaining.
440
434
  *
441
- * @returns {*} The result of applying the checker function to the observable's current value
435
+ * @param {Object} methods - Object containing method definitions
436
+ * @returns {this} The NDElement instance with added methods for chaining
442
437
  * @example
443
- * const count = Observable(5);
444
- * const doubled = count.check(n => n * 2);
445
- * doubled.val(); // 10
438
+ * element.nd.with({
439
+ * highlight() {
440
+ * this.$element.style.background = 'yellow';
441
+ * return this;
442
+ * }
443
+ * }).highlight().onClick(() => console.log('Clicked'));
446
444
  */
447
- ObservableChecker.prototype.val = function() {
448
- return this.checker && this.checker(this.observable.val());
449
- };
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
+ }
450
460
 
451
- /**
452
- * Sets the value of the underlying observable (not the transformed value).
453
- *
454
- * @param {*} value - New value for the underlying observable
455
- * @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
459
- */
460
- ObservableChecker.prototype.set = function(value) {
461
- return this.observable.set(value);
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;
696
837
  };
697
838
 
698
- NDElement.prototype.remove = function() {
699
- let element = this.$element;
700
- element.nd.unmountChildren();
701
- element.$ndProx = null;
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
+ };
702
852
 
703
- $lifeCycleObservers.delete(element);
853
+ function HasEventEmitter() {
704
854
 
705
- element = null;
706
- return this;
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);
873
+ };
874
+
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$1.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$1.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$1.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([
@@ -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
 
@@ -4608,22 +4678,17 @@ var NativeComponents = (function (exports) {
4608
4678
  }
4609
4679
 
4610
4680
  Alert.defaultTemplate = null;
4611
- Alert.defaultTitleTemplate = null;
4612
- Alert.defaultButtonsTemplate = null;
4613
- Alert.defaultContentTemplate = null;
4614
4681
 
4615
4682
  /**
4616
4683
  * Sets the default template for all Alert instances
4617
- * @param {{alert: (alert: Alert) => ValidChildren, alertContent: (alert: Alert) => ValidChildren, alertButtons: (alert: Alert) => ValidChildren, alertTitle: (alert: Alert) => ValidChildren}} template - Template object containing alert factory function
4684
+ * @param {ValidChildren} template - Template object containing alert factory function
4618
4685
  */
4619
4686
  Alert.use = function(template) {
4620
- Alert.defaultTemplate = template.alert;
4621
- Alert.defaultTitleTemplate = template.alertTitle;
4622
- Alert.defaultButtonsTemplate = template.alertButtons;
4623
- Alert.defaultContentTemplate = template.alertContent;
4687
+ Alert.defaultTemplate = template;
4624
4688
  };
4625
4689
 
4626
- BaseComponent.extends(Alert, HasEventEmitter);
4690
+ BaseComponent.extends(Alert);
4691
+ BaseComponent.use(Alert, HasEventEmitter);
4627
4692
 
4628
4693
  /**
4629
4694
  * Sets the variant style for the alert
@@ -5105,10 +5170,10 @@ var NativeComponents = (function (exports) {
5105
5170
 
5106
5171
  /**
5107
5172
  * Sets the default template for all Avatar instances
5108
- * @param {{avatar: (avatar: Avatar) => ValidChildren}} template - Template object containing avatar factory function
5173
+ * @param {ValidChildren} template - Template object containing avatar factory function
5109
5174
  */
5110
5175
  Avatar.use = function(template) {
5111
- Avatar.defaultTemplate = template.avatar;
5176
+ Avatar.defaultTemplate = template;
5112
5177
  };
5113
5178
 
5114
5179
  Avatar.preset = function(name, callback) {
@@ -5476,6 +5541,11 @@ var NativeComponents = (function (exports) {
5476
5541
  }
5477
5542
  BaseComponent.extends(AvatarGroup);
5478
5543
 
5544
+ AvatarGroup.defaultTemplate = null;
5545
+ AvatarGroup.use = function(template) {
5546
+ AvatarGroup.defaultTemplate = template;
5547
+ };
5548
+
5479
5549
  AvatarGroup.prototype.items = function() {
5480
5550
  this.$description.items = Array.from(arguments);
5481
5551
  return this;
@@ -5518,7 +5588,9 @@ var NativeComponents = (function (exports) {
5518
5588
 
5519
5589
  Badge.defaultTemplate = null;
5520
5590
 
5521
- Badge.use = function(template) {};
5591
+ Badge.use = function(template) {
5592
+ Badge.defaultTemplate = template;
5593
+ };
5522
5594
 
5523
5595
  Badge.preset = function(name, callback) {
5524
5596
  if (Badge.prototype[name] || Badge[name]) {
@@ -5630,10 +5702,13 @@ var NativeComponents = (function (exports) {
5630
5702
  };
5631
5703
  }
5632
5704
 
5633
- BaseComponent.extends(Breadcrumb, HasEventEmitter);
5705
+ BaseComponent.extends(Breadcrumb);
5706
+ BaseComponent.use(Breadcrumb, HasEventEmitter);
5634
5707
 
5635
- Breadcrumb.use = function(template) {};
5636
5708
  Breadcrumb.defaultTemplate = null;
5709
+ Breadcrumb.use = function(template) {
5710
+ Breadcrumb.defaultTemplate = template;
5711
+ };
5637
5712
 
5638
5713
  Breadcrumb.prototype.item = function(label, href) {
5639
5714
  this.$description.items.push({ label, href });
@@ -5880,7 +5955,7 @@ var NativeComponents = (function (exports) {
5880
5955
  MenuDivider.defaultTemplate = null;
5881
5956
 
5882
5957
  MenuDivider.use = function(template) {
5883
- MenuDivider.defaultTemplate = template.menuDivider;
5958
+ MenuDivider.defaultTemplate = template;
5884
5959
  };
5885
5960
 
5886
5961
  function MenuGroup(label, props) {
@@ -6282,9 +6357,8 @@ var NativeComponents = (function (exports) {
6282
6357
  BaseComponent.extends(Divider);
6283
6358
 
6284
6359
  Divider.defaultTemplate = null;
6285
-
6286
6360
  Divider.use = function(template) {
6287
- Divider.defaultTemplate = template.divider;
6361
+ Divider.defaultTemplate = template;
6288
6362
  };
6289
6363
 
6290
6364
  Divider.preset = function(name, callback) {
@@ -9460,7 +9534,7 @@ var NativeComponents = (function (exports) {
9460
9534
  ListItem.defaultTemplate = null;
9461
9535
 
9462
9536
  ListItem.use = function(template) {
9463
- ListItem.defaultTemplate = template.listItem;
9537
+ ListItem.defaultTemplate = template;
9464
9538
  };
9465
9539
 
9466
9540
  ListItem.prototype.content = function(content) {
@@ -9560,7 +9634,7 @@ var NativeComponents = (function (exports) {
9560
9634
  ListGroup.defaultTemplate = null;
9561
9635
 
9562
9636
  ListGroup.use = function(template) {
9563
- ListGroup.defaultTemplate = template.listGroup;
9637
+ ListGroup.defaultTemplate = template;
9564
9638
  };
9565
9639
 
9566
9640
  ListGroup.prototype.header = function(header) {
@@ -10272,7 +10346,7 @@ var NativeComponents = (function (exports) {
10272
10346
  Progress.defaultTemplate = null;
10273
10347
 
10274
10348
  Progress.use = function(template) {
10275
- Progress.defaultTemplate = template.progress;
10349
+ Progress.defaultTemplate = template;
10276
10350
  };
10277
10351
 
10278
10352
  Progress.preset = function(name, callback) {
@@ -10818,7 +10892,7 @@ var NativeComponents = (function (exports) {
10818
10892
 
10819
10893
  Spinner.defaultTemplate = null;
10820
10894
  Spinner.use = function(template) {
10821
- Spinner.defaultTemplate = template.spinner;
10895
+ Spinner.defaultTemplate = template;
10822
10896
  };
10823
10897
 
10824
10898
  BaseComponent.extends(Spinner);
@@ -10991,7 +11065,7 @@ var NativeComponents = (function (exports) {
10991
11065
  Splitter.defaultTemplate = null;
10992
11066
 
10993
11067
  Splitter.use = function(template) {
10994
- Splitter.defaultTemplate = template.splitter;
11068
+ Splitter.defaultTemplate = template;
10995
11069
  };
10996
11070
 
10997
11071
  Splitter.prototype.dynamic = function(){
@@ -11090,7 +11164,7 @@ var NativeComponents = (function (exports) {
11090
11164
  SplitterPanel.defaultTemplate = null;
11091
11165
 
11092
11166
  SplitterPanel.use = function(template) {
11093
- SplitterPanel.defaultTemplate = template.splitterPanel;
11167
+ SplitterPanel.defaultTemplate = template;
11094
11168
  };
11095
11169
 
11096
11170
  SplitterPanel.prototype.content = function(content) {