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.
- package/dist/native-document.components.min.js +968 -894
- package/package.json +1 -1
- package/src/components/BaseComponent.js +30 -0
- package/src/components/alert/Alert.js +4 -9
- package/src/components/avatar/Avatar.js +2 -2
- package/src/components/avatar/AvatarGroup.js +5 -0
- package/src/components/badge/Badge.js +3 -1
- package/src/components/breadcrumb/BreadCrumb.js +5 -2
- package/src/components/divider/Divider.js +1 -2
- package/src/components/list/ListGroup.js +1 -1
- package/src/components/list/ListItem.js +1 -1
- package/src/components/menu/MenuDivider.js +1 -1
- package/src/components/progress/Progress.js +1 -1
- package/src/components/spacer/Spacer.js +6 -1
- package/src/components/spinner/Spinner.js +1 -1
- package/src/components/splitter/Splitter.js +1 -1
- package/src/components/splitter/SplitterGutter.js +1 -1
- package/src/components/splitter/SplitterPanel.js +1 -1
|
@@ -1,1025 +1,1132 @@
|
|
|
1
1
|
var NativeComponents = (function (exports) {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
this
|
|
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
|
-
*
|
|
143
|
-
* @param {
|
|
144
|
-
* @
|
|
145
|
-
* @class
|
|
25
|
+
*
|
|
26
|
+
* @param {ObservableItem} $observable
|
|
27
|
+
* @param {Function} $checker
|
|
28
|
+
* @class ObservableChecker
|
|
146
29
|
*/
|
|
147
|
-
function
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
168
|
-
*
|
|
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
|
-
|
|
171
|
-
|
|
68
|
+
ObservableChecker.prototype.check = function(callback) {
|
|
69
|
+
return this.observable.check(() => callback(this.val()));
|
|
172
70
|
};
|
|
173
71
|
|
|
174
72
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* @returns {
|
|
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
|
-
|
|
180
|
-
this
|
|
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
|
|
186
|
-
*
|
|
187
|
-
* @
|
|
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
|
-
|
|
190
|
-
this
|
|
191
|
-
return this;
|
|
94
|
+
ObservableChecker.prototype.set = function(value) {
|
|
95
|
+
return this.observable.set(value);
|
|
192
96
|
};
|
|
193
97
|
|
|
194
98
|
/**
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* @
|
|
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
|
-
|
|
106
|
+
ObservableChecker.prototype.trigger = function() {
|
|
107
|
+
return this.observable.trigger();
|
|
108
|
+
};
|
|
200
109
|
|
|
201
110
|
/**
|
|
202
|
-
*
|
|
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
|
-
|
|
207
|
-
|
|
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
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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
|
-
|
|
263
|
-
|
|
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
|
-
|
|
271
|
-
|
|
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
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
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
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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
|
-
|
|
403
|
-
|
|
420
|
+
return this;
|
|
421
|
+
};
|
|
404
422
|
|
|
405
|
-
|
|
406
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
432
|
+
* Extends the current NDElement instance with custom methods.
|
|
433
|
+
* Methods are bound to the instance and available for chaining.
|
|
440
434
|
*
|
|
441
|
-
* @
|
|
435
|
+
* @param {Object} methods - Object containing method definitions
|
|
436
|
+
* @returns {this} The NDElement instance with added methods for chaining
|
|
442
437
|
* @example
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
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
|
-
|
|
448
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
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
|
-
|
|
473
|
-
|
|
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
|
-
|
|
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
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
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
|
-
|
|
502
|
-
|
|
503
|
-
|
|
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
|
-
|
|
520
|
-
|
|
521
|
-
if(
|
|
522
|
-
|
|
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
|
-
|
|
525
|
-
if(
|
|
526
|
-
|
|
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
|
-
|
|
530
|
-
|
|
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
|
-
|
|
541
|
-
|
|
542
|
-
|
|
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
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
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
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
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
|
-
*
|
|
579
|
-
* @param {
|
|
580
|
-
* @returns {
|
|
640
|
+
* Check if the data contains an observable reference.
|
|
641
|
+
* @param {string} data
|
|
642
|
+
* @returns {boolean}
|
|
581
643
|
*/
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
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
|
-
|
|
652
|
+
validateEventCallback(callback) {
|
|
653
|
+
if (typeof callback !== 'function') {
|
|
654
|
+
throw new NativeDocumentError('Event callback must be a function');
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
};
|
|
587
658
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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
|
-
|
|
606
|
-
|
|
607
|
-
data[type] = callback;
|
|
608
|
-
return;
|
|
688
|
+
if (!flags || flags === ''){
|
|
689
|
+
return String(value).toLowerCase().includes(String(pattern).toLowerCase());
|
|
609
690
|
}
|
|
610
|
-
|
|
611
|
-
|
|
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[
|
|
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
|
-
|
|
618
|
-
|
|
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
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
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
|
|
635
|
-
}
|
|
733
|
+
return { ...data };
|
|
734
|
+
},
|
|
735
|
+
};
|
|
736
|
+
};
|
|
636
737
|
|
|
637
|
-
|
|
638
|
-
|
|
738
|
+
/**
|
|
739
|
+
*
|
|
740
|
+
* @class
|
|
741
|
+
*/
|
|
742
|
+
function BaseComponent() {
|
|
743
|
+
this.$description = {};
|
|
744
|
+
this.$editableProps = null;
|
|
745
|
+
}
|
|
639
746
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
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
|
-
|
|
659
|
-
|
|
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
|
|
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
|
-
|
|
787
|
+
BaseComponent.prototype.refSelf = function(target, name) {
|
|
788
|
+
target[name] = this;
|
|
789
|
+
return this;
|
|
790
|
+
};
|
|
670
791
|
|
|
671
|
-
|
|
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
|
-
|
|
676
|
-
|
|
677
|
-
|
|
811
|
+
BaseComponent.prototype.toJSON = function() {
|
|
812
|
+
if(!this.$description) {
|
|
813
|
+
return {};
|
|
814
|
+
}
|
|
815
|
+
return { ...this.$description };
|
|
678
816
|
};
|
|
679
817
|
|
|
680
|
-
|
|
681
|
-
|
|
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
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
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
|
-
|
|
695
|
-
return this;
|
|
835
|
+
|
|
836
|
+
return this.$editableProps;
|
|
696
837
|
};
|
|
697
838
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
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
|
-
|
|
853
|
+
function HasEventEmitter() {
|
|
704
854
|
|
|
705
|
-
|
|
706
|
-
|
|
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
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
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(
|
|
718
|
-
|
|
719
|
-
observer.mounted(states.mounted);
|
|
886
|
+
if(typeof callbacks === 'function') {
|
|
887
|
+
return await Promise.resolve(callbacks.apply(this, args))
|
|
720
888
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
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
|
|
894
|
+
return result;
|
|
726
895
|
};
|
|
896
|
+
HasEventEmitter.prototype.emit = HasEventEmitter.prototype.trigger;
|
|
727
897
|
|
|
728
|
-
|
|
729
|
-
|
|
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
|
-
|
|
733
|
-
|
|
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
|
-
|
|
737
|
-
|
|
914
|
+
this.$description = {
|
|
915
|
+
items: [],
|
|
916
|
+
multiple: null,
|
|
917
|
+
variant: null,
|
|
918
|
+
renderContent: null,
|
|
919
|
+
...config
|
|
920
|
+
};
|
|
921
|
+
}
|
|
738
922
|
|
|
739
|
-
|
|
740
|
-
DocumentObserver.beforeUnmount.set(el, new Map());
|
|
741
|
-
const originalRemove = el.remove.bind(el);
|
|
923
|
+
BaseComponent.extends(Accordion, HasEventEmitter);
|
|
742
924
|
|
|
743
|
-
|
|
925
|
+
Accordion.defaultTemplate = null;
|
|
744
926
|
|
|
745
|
-
el.remove = async () => {
|
|
746
|
-
if($isUnmounting) {
|
|
747
|
-
return;
|
|
748
|
-
}
|
|
749
|
-
$isUnmounting = true;
|
|
750
927
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
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
|
-
|
|
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
|
-
|
|
768
|
-
|
|
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
|
-
|
|
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
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
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
|
-
|
|
790
|
-
|
|
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
|
-
|
|
794
|
-
|
|
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
|
-
*
|
|
799
|
-
*
|
|
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
|
-
|
|
812
|
-
|
|
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
|
-
*
|
|
832
|
-
*
|
|
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
|
-
|
|
848
|
-
|
|
849
|
-
|
|
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
|
-
|
|
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
|
-
|
|
870
|
-
|
|
871
|
-
|
|
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
|
-
|
|
875
|
-
|
|
876
|
-
|
|
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
|
-
|
|
880
|
-
|
|
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
|
-
|
|
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
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
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
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
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
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
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
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
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
|
-
|
|
987
|
-
|
|
988
|
-
|
|
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
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
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
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
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 {
|
|
4684
|
+
* @param {ValidChildren} template - Template object containing alert factory function
|
|
4618
4685
|
*/
|
|
4619
4686
|
Alert.use = function(template) {
|
|
4620
|
-
Alert.defaultTemplate = template
|
|
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
|
|
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 {
|
|
5173
|
+
* @param {ValidChildren} template - Template object containing avatar factory function
|
|
5109
5174
|
*/
|
|
5110
5175
|
Avatar.use = function(template) {
|
|
5111
|
-
Avatar.defaultTemplate = template
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
11167
|
+
SplitterPanel.defaultTemplate = template;
|
|
11094
11168
|
};
|
|
11095
11169
|
|
|
11096
11170
|
SplitterPanel.prototype.content = function(content) {
|