native-document 1.0.151 → 1.0.153
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/cdn.js +4 -0
- package/components.js +1 -0
- package/dist/native-document.components.min.js +1422 -1667
- package/dist/native-document.dev.js +839 -1092
- package/dist/native-document.dev.js.map +1 -1
- package/dist/native-document.min.js +1 -1
- package/elements.js +5 -0
- package/index.js +3 -2
- package/package.json +2 -1
- package/src/components/BaseComponent.js +2 -6
- package/src/components/dropdown/helpers.js +2 -1
- package/src/core/data/ObservableItem.js +0 -113
- package/src/core/data/observable-helpers/observable.prototypes.js +119 -0
- package/src/core/utils/validator.js +4 -6
- package/src/core/wrappers/ElementCreator.js +0 -9
- package/src/core/wrappers/NDElement.js +3 -3
- package/src/core/wrappers/prototypes/nd-element-extensions.js +3 -0
|
@@ -43,6 +43,191 @@ var NativeDocument = (function (exports) {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
const COMMON_NODE_TYPES = {
|
|
47
|
+
ELEMENT: 1,
|
|
48
|
+
TEXT: 3,
|
|
49
|
+
COMMENT: 8,
|
|
50
|
+
DOCUMENT_FRAGMENT: 11
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const VALID_TYPES = [];
|
|
54
|
+
VALID_TYPES[COMMON_NODE_TYPES.ELEMENT] = true;
|
|
55
|
+
VALID_TYPES[COMMON_NODE_TYPES.TEXT] = true;
|
|
56
|
+
VALID_TYPES[COMMON_NODE_TYPES.DOCUMENT_FRAGMENT] = true;
|
|
57
|
+
VALID_TYPES[COMMON_NODE_TYPES.COMMENT] = true;
|
|
58
|
+
|
|
59
|
+
const Validator = {
|
|
60
|
+
isObservable(value) {
|
|
61
|
+
return value && (value.__$isObservable || value.__$Observable);
|
|
62
|
+
},
|
|
63
|
+
isTemplateBinding(value) {
|
|
64
|
+
return value?.__$isTemplateBinding;
|
|
65
|
+
},
|
|
66
|
+
isObservableWhenResult(value) {
|
|
67
|
+
return value && (value.__$isObservableWhen || (typeof value === 'object' && '$target' in value && '$observer' in value));
|
|
68
|
+
},
|
|
69
|
+
isArrayObservable(value) {
|
|
70
|
+
return value?.__$isObservableArray;
|
|
71
|
+
},
|
|
72
|
+
isProxy(value) {
|
|
73
|
+
return value?.__isProxy__
|
|
74
|
+
},
|
|
75
|
+
isObservableOrProxy(value) {
|
|
76
|
+
return Validator.isObservable(value) || Validator.isProxy(value);
|
|
77
|
+
},
|
|
78
|
+
isAnchor(value) {
|
|
79
|
+
return value?.__Anchor__
|
|
80
|
+
},
|
|
81
|
+
isObservableChecker(value) {
|
|
82
|
+
return value?.__$isObservableChecker;
|
|
83
|
+
},
|
|
84
|
+
isArray(value) {
|
|
85
|
+
return Array.isArray(value);
|
|
86
|
+
},
|
|
87
|
+
isString(value) {
|
|
88
|
+
return typeof value === 'string';
|
|
89
|
+
},
|
|
90
|
+
isNumber(value) {
|
|
91
|
+
return typeof value === 'number';
|
|
92
|
+
},
|
|
93
|
+
isBoolean(value) {
|
|
94
|
+
return typeof value === 'boolean';
|
|
95
|
+
},
|
|
96
|
+
isFunction(value) {
|
|
97
|
+
return typeof value === 'function';
|
|
98
|
+
},
|
|
99
|
+
isAsyncFunction(value) {
|
|
100
|
+
return typeof value === 'function' && value.constructor.name === 'AsyncFunction';
|
|
101
|
+
},
|
|
102
|
+
isObject(value) {
|
|
103
|
+
return typeof value === 'object' && value !== null;
|
|
104
|
+
},
|
|
105
|
+
isJson(value) {
|
|
106
|
+
return !(typeof value !== 'object' || value === null || Array.isArray(value) || value.constructor.name !== 'Object')
|
|
107
|
+
},
|
|
108
|
+
isElement(value) {
|
|
109
|
+
return value && VALID_TYPES[value.nodeType];
|
|
110
|
+
},
|
|
111
|
+
isDOMNode(value) {
|
|
112
|
+
return VALID_TYPES[value.nodeType];
|
|
113
|
+
},
|
|
114
|
+
isFragment(value) {
|
|
115
|
+
return value?.nodeType === COMMON_NODE_TYPES.DOCUMENT_FRAGMENT;
|
|
116
|
+
},
|
|
117
|
+
isStringOrObservable(value) {
|
|
118
|
+
return this.isString(value) || this.isObservable(value);
|
|
119
|
+
},
|
|
120
|
+
isValidChild(child) {
|
|
121
|
+
return child === null ||
|
|
122
|
+
this.isElement(child) ||
|
|
123
|
+
child.__$Observable ||
|
|
124
|
+
child?.__$isNDElement ||
|
|
125
|
+
['string', 'number', 'boolean'].includes(typeof child);
|
|
126
|
+
},
|
|
127
|
+
isNDElement(child) {
|
|
128
|
+
return child?.__$isNDElement;
|
|
129
|
+
},
|
|
130
|
+
isValidChildren(children) {
|
|
131
|
+
if (!Array.isArray(children)) {
|
|
132
|
+
children = [children];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const invalid = children.filter(child => !this.isValidChild(child));
|
|
136
|
+
return invalid.length === 0;
|
|
137
|
+
},
|
|
138
|
+
validateChildren(children) {
|
|
139
|
+
if (!Array.isArray(children)) {
|
|
140
|
+
children = [children];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const invalid = children.filter(child => !this.isValidChild(child));
|
|
144
|
+
if (invalid.length > 0) {
|
|
145
|
+
throw new NativeDocumentError(`Invalid children detected: ${invalid.map(i => typeof i).join(', ')}`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return children;
|
|
149
|
+
},
|
|
150
|
+
/**
|
|
151
|
+
* Check if the data contains observables.
|
|
152
|
+
* @param {Array|Object} data
|
|
153
|
+
* @returns {boolean}
|
|
154
|
+
*/
|
|
155
|
+
containsObservables(data) {
|
|
156
|
+
if(!data) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return Validator.isObject(data)
|
|
160
|
+
&& Object.values(data).some(value => Validator.isObservable(value));
|
|
161
|
+
},
|
|
162
|
+
/**
|
|
163
|
+
* Check if the data contains an observable reference.
|
|
164
|
+
* @param {string} data
|
|
165
|
+
* @returns {boolean}
|
|
166
|
+
*/
|
|
167
|
+
containsObservableReference(data) {
|
|
168
|
+
if(!data || typeof data !== 'string') {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
return /\{\{#ObItem::\([0-9]+\)\}\}/.test(data);
|
|
172
|
+
},
|
|
173
|
+
validateAttributes(attributes) {},
|
|
174
|
+
|
|
175
|
+
validateEventCallback(callback) {
|
|
176
|
+
if (typeof callback !== 'function') {
|
|
177
|
+
throw new NativeDocumentError('Event callback must be a function');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
{
|
|
182
|
+
Validator.validateAttributes = function(attributes) {
|
|
183
|
+
if (!attributes || typeof attributes !== 'object') {
|
|
184
|
+
return attributes;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const reserved = [];
|
|
188
|
+
const foundReserved = Object.keys(attributes).filter(key => reserved.includes(key));
|
|
189
|
+
|
|
190
|
+
if (foundReserved.length > 0) {
|
|
191
|
+
DebugManager$2.warn('Validator', `Reserved attributes found: ${foundReserved.join(', ')}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return attributes;
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const BOOLEAN_ATTRIBUTES = new Set([
|
|
199
|
+
'checked',
|
|
200
|
+
'selected',
|
|
201
|
+
'disabled',
|
|
202
|
+
'readonly',
|
|
203
|
+
'required',
|
|
204
|
+
'autofocus',
|
|
205
|
+
'multiple',
|
|
206
|
+
'autocomplete',
|
|
207
|
+
'hidden',
|
|
208
|
+
'contenteditable',
|
|
209
|
+
'spellcheck',
|
|
210
|
+
'translate',
|
|
211
|
+
'draggable',
|
|
212
|
+
'async',
|
|
213
|
+
'defer',
|
|
214
|
+
'autoplay',
|
|
215
|
+
'controls',
|
|
216
|
+
'loop',
|
|
217
|
+
'muted',
|
|
218
|
+
'download',
|
|
219
|
+
'reversed',
|
|
220
|
+
'open',
|
|
221
|
+
'default',
|
|
222
|
+
'formnovalidate',
|
|
223
|
+
'novalidate',
|
|
224
|
+
'scoped',
|
|
225
|
+
'itemscope',
|
|
226
|
+
'allowfullscreen',
|
|
227
|
+
'allowpaymentrequest',
|
|
228
|
+
'playsinline'
|
|
229
|
+
]);
|
|
230
|
+
|
|
46
231
|
const MemoryManager = (function() {
|
|
47
232
|
|
|
48
233
|
let $nextObserverId = 0;
|
|
@@ -176,60 +361,6 @@ var NativeDocument = (function (exports) {
|
|
|
176
361
|
|
|
177
362
|
var PluginsManager$1 = PluginsManager;
|
|
178
363
|
|
|
179
|
-
/**
|
|
180
|
-
* Creates an ObservableWhen that tracks whether an observable equals a specific value.
|
|
181
|
-
*
|
|
182
|
-
* @param {ObservableItem} observer - The observable to watch
|
|
183
|
-
* @param {*} value - The value to compare against
|
|
184
|
-
* @class ObservableWhen
|
|
185
|
-
*/
|
|
186
|
-
const ObservableWhen = function(observer, value) {
|
|
187
|
-
this.$target = value;
|
|
188
|
-
this.$observer = observer;
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
ObservableWhen.prototype.__$Observable = true;
|
|
192
|
-
ObservableWhen.prototype.__$isObservableWhen = true;
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Subscribes to changes in the match status (true when observable equals target value).
|
|
196
|
-
*
|
|
197
|
-
* @param {Function} callback - Function called with boolean indicating if values match
|
|
198
|
-
* @returns {Function} Unsubscribe function
|
|
199
|
-
* @example
|
|
200
|
-
* const status = Observable('idle');
|
|
201
|
-
* const isLoading = status.when('loading');
|
|
202
|
-
* isLoading.subscribe(active => console.log('Loading:', active));
|
|
203
|
-
*/
|
|
204
|
-
ObservableWhen.prototype.subscribe = function(callback) {
|
|
205
|
-
return this.$observer.on(this.$target, callback);
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Returns true if the observable's current value equals the target value.
|
|
210
|
-
*
|
|
211
|
-
* @returns {boolean} True if observable value matches target value
|
|
212
|
-
*/
|
|
213
|
-
ObservableWhen.prototype.val = function() {
|
|
214
|
-
return this.$observer.$currentValue === this.$target;
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Returns true if the observable's current value equals the target value.
|
|
219
|
-
* Alias for val().
|
|
220
|
-
*
|
|
221
|
-
* @returns {boolean} True if observable value matches target value
|
|
222
|
-
*/
|
|
223
|
-
ObservableWhen.prototype.isMatch = ObservableWhen.prototype.val;
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Returns true if the observable's current value equals the target value.
|
|
227
|
-
* Alias for val().
|
|
228
|
-
*
|
|
229
|
-
* @returns {boolean} True if observable value matches target value
|
|
230
|
-
*/
|
|
231
|
-
ObservableWhen.prototype.isActive = ObservableWhen.prototype.val;
|
|
232
|
-
|
|
233
364
|
const nextTick = function(fn) {
|
|
234
365
|
let pending = false;
|
|
235
366
|
return function(...args) {
|
|
@@ -306,201 +437,40 @@ var NativeDocument = (function (exports) {
|
|
|
306
437
|
return cloned;
|
|
307
438
|
};
|
|
308
439
|
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
day: '2-digit',
|
|
317
|
-
hour: '2-digit',
|
|
318
|
-
minute: '2-digit',
|
|
319
|
-
second: '2-digit',
|
|
320
|
-
}).formatToParts(d).reduce((acc, { type, value }) => {
|
|
321
|
-
acc[type] = value;
|
|
322
|
-
return acc;
|
|
323
|
-
}, {})
|
|
324
|
-
};
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
const $applyDatePattern = (pattern, d, parts) => {
|
|
328
|
-
const pad = n => String(n).padStart(2, '0');
|
|
329
|
-
return pattern
|
|
330
|
-
.replace('YYYY', parts.year)
|
|
331
|
-
.replace('YY', parts.year.slice(-2))
|
|
332
|
-
.replace('MMMM', parts.month)
|
|
333
|
-
.replace('MMM', parts.month.slice(0, 3))
|
|
334
|
-
.replace('MM', pad(d.getMonth() + 1))
|
|
335
|
-
.replace('DD', pad(d.getDate()))
|
|
336
|
-
.replace('D', d.getDate())
|
|
337
|
-
.replace('HH', parts.hour)
|
|
338
|
-
.replace('mm', parts.minute)
|
|
339
|
-
.replace('ss', parts.second);
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
const Formatters = {
|
|
343
|
-
currency: (value, locale, { currency = 'XOF', notation, minimumFractionDigits, maximumFractionDigits } = {}) =>
|
|
344
|
-
new Intl.NumberFormat(locale, {
|
|
345
|
-
style: 'currency',
|
|
346
|
-
currency,
|
|
347
|
-
notation,
|
|
348
|
-
minimumFractionDigits,
|
|
349
|
-
maximumFractionDigits
|
|
350
|
-
}).format(value),
|
|
351
|
-
|
|
352
|
-
number: (value, locale, { notation, minimumFractionDigits, maximumFractionDigits } = {}) =>
|
|
353
|
-
new Intl.NumberFormat(locale, {
|
|
354
|
-
notation,
|
|
355
|
-
minimumFractionDigits,
|
|
356
|
-
maximumFractionDigits
|
|
357
|
-
}).format(value),
|
|
358
|
-
|
|
359
|
-
percent: (value, locale, { decimals = 1 } = {}) =>
|
|
360
|
-
new Intl.NumberFormat(locale, {
|
|
361
|
-
style: 'percent',
|
|
362
|
-
maximumFractionDigits: decimals
|
|
363
|
-
}).format(value),
|
|
364
|
-
|
|
365
|
-
date: (value, locale, { format, dateStyle = 'long' } = {}) => {
|
|
366
|
-
if (format) {
|
|
367
|
-
const { d, parts } = $parseDateParts(value, locale);
|
|
368
|
-
return $applyDatePattern(format, d, parts);
|
|
369
|
-
}
|
|
370
|
-
return new Intl.DateTimeFormat(locale, { dateStyle }).format(new Date(value));
|
|
371
|
-
},
|
|
372
|
-
|
|
373
|
-
time: (value, locale, { format, hour = '2-digit', minute = '2-digit', second } = {}) => {
|
|
374
|
-
if (format) {
|
|
375
|
-
const { d, parts } = $parseDateParts(value, locale);
|
|
376
|
-
return $applyDatePattern(format, d, parts);
|
|
440
|
+
const LocalStorage = {
|
|
441
|
+
getJson(key) {
|
|
442
|
+
let value = localStorage.getItem(key);
|
|
443
|
+
try {
|
|
444
|
+
return JSON.parse(value);
|
|
445
|
+
} catch (e) {
|
|
446
|
+
throw new NativeDocumentError('invalid_json:'+key);
|
|
377
447
|
}
|
|
378
|
-
return new Intl.DateTimeFormat(locale, { hour, minute, second }).format(new Date(value));
|
|
379
448
|
},
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
if (format) {
|
|
383
|
-
const { d, parts } = $parseDateParts(value, locale);
|
|
384
|
-
return $applyDatePattern(format, d, parts);
|
|
385
|
-
}
|
|
386
|
-
return new Intl.DateTimeFormat(locale, { dateStyle, hour, minute, second }).format(new Date(value));
|
|
449
|
+
getNumber(key) {
|
|
450
|
+
return Number(this.get(key));
|
|
387
451
|
},
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
return new Intl.RelativeTimeFormat(locale, { numeric }).format(diff, unit);
|
|
452
|
+
getBool(key) {
|
|
453
|
+
const value = this.get(key);
|
|
454
|
+
return value === 'true' || value === '1';
|
|
392
455
|
},
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
456
|
+
setJson(key, value) {
|
|
457
|
+
localStorage.setItem(key, JSON.stringify(value));
|
|
458
|
+
},
|
|
459
|
+
setBool(key, value) {
|
|
460
|
+
localStorage.setItem(key, value ? 'true' : 'false');
|
|
461
|
+
},
|
|
462
|
+
get(key, defaultValue = null) {
|
|
463
|
+
return localStorage.getItem(key) || defaultValue;
|
|
464
|
+
},
|
|
465
|
+
set(key, value) {
|
|
466
|
+
return localStorage.setItem(key, value);
|
|
467
|
+
},
|
|
468
|
+
remove(key) {
|
|
469
|
+
localStorage.removeItem(key);
|
|
397
470
|
},
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
*
|
|
402
|
-
* @param {*} value
|
|
403
|
-
* @param {{ propagation: boolean, reset: boolean} | null} configs
|
|
404
|
-
* @returns {ObservableItem}
|
|
405
|
-
* @constructor
|
|
406
|
-
*/
|
|
407
|
-
function Observable(value, configs = null) {
|
|
408
|
-
return new ObservableItem(value, configs);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
const $ = Observable;
|
|
412
|
-
const obs = Observable;
|
|
413
|
-
|
|
414
|
-
/**
|
|
415
|
-
*
|
|
416
|
-
* @param {string} propertyName
|
|
417
|
-
*/
|
|
418
|
-
Observable.useValueProperty = function(propertyName = 'value') {
|
|
419
|
-
Object.defineProperty(ObservableItem.prototype, propertyName, {
|
|
420
|
-
get() {
|
|
421
|
-
return this.$currentValue;
|
|
422
|
-
},
|
|
423
|
-
set(value) {
|
|
424
|
-
this.set(value);
|
|
425
|
-
},
|
|
426
|
-
configurable: true,
|
|
427
|
-
});
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
*
|
|
433
|
-
* @param id
|
|
434
|
-
* @returns {ObservableItem|null}
|
|
435
|
-
*/
|
|
436
|
-
Observable.getById = function(id) {
|
|
437
|
-
const item = MemoryManager.getObservableById(parseInt(id));
|
|
438
|
-
if(!item) {
|
|
439
|
-
throw new NativeDocumentError('Observable.getById : No observable found with id ' + id);
|
|
440
|
-
}
|
|
441
|
-
return item;
|
|
442
|
-
};
|
|
443
|
-
|
|
444
|
-
/**
|
|
445
|
-
*
|
|
446
|
-
* @param {ObservableItem} observable
|
|
447
|
-
*/
|
|
448
|
-
Observable.cleanup = function(observable) {
|
|
449
|
-
observable.cleanup();
|
|
450
|
-
};
|
|
451
|
-
|
|
452
|
-
/**
|
|
453
|
-
* Enable auto cleanup of observables.
|
|
454
|
-
* @param {Boolean} enable
|
|
455
|
-
* @param {{interval:Boolean, threshold:number}} options
|
|
456
|
-
*/
|
|
457
|
-
Observable.autoCleanup = function(enable = false, options = {}) {
|
|
458
|
-
if(!enable) {
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
const { interval = 60000, threshold = 100 } = options;
|
|
462
|
-
|
|
463
|
-
window.addEventListener('beforeunload', () => {
|
|
464
|
-
MemoryManager.cleanup();
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
setInterval(() => MemoryManager.cleanObservables(threshold), interval);
|
|
468
|
-
};
|
|
469
|
-
|
|
470
|
-
const LocalStorage = {
|
|
471
|
-
getJson(key) {
|
|
472
|
-
let value = localStorage.getItem(key);
|
|
473
|
-
try {
|
|
474
|
-
return JSON.parse(value);
|
|
475
|
-
} catch (e) {
|
|
476
|
-
throw new NativeDocumentError('invalid_json:'+key);
|
|
477
|
-
}
|
|
478
|
-
},
|
|
479
|
-
getNumber(key) {
|
|
480
|
-
return Number(this.get(key));
|
|
481
|
-
},
|
|
482
|
-
getBool(key) {
|
|
483
|
-
const value = this.get(key);
|
|
484
|
-
return value === 'true' || value === '1';
|
|
485
|
-
},
|
|
486
|
-
setJson(key, value) {
|
|
487
|
-
localStorage.setItem(key, JSON.stringify(value));
|
|
488
|
-
},
|
|
489
|
-
setBool(key, value) {
|
|
490
|
-
localStorage.setItem(key, value ? 'true' : 'false');
|
|
491
|
-
},
|
|
492
|
-
get(key, defaultValue = null) {
|
|
493
|
-
return localStorage.getItem(key) || defaultValue;
|
|
494
|
-
},
|
|
495
|
-
set(key, value) {
|
|
496
|
-
return localStorage.setItem(key, value);
|
|
497
|
-
},
|
|
498
|
-
remove(key) {
|
|
499
|
-
localStorage.removeItem(key);
|
|
500
|
-
},
|
|
501
|
-
has(key) {
|
|
502
|
-
return localStorage.getItem(key) != null;
|
|
503
|
-
}
|
|
471
|
+
has(key) {
|
|
472
|
+
return localStorage.getItem(key) != null;
|
|
473
|
+
}
|
|
504
474
|
};
|
|
505
475
|
|
|
506
476
|
const $getFromStorage = (key, value) => {
|
|
@@ -876,27 +846,6 @@ var NativeDocument = (function (exports) {
|
|
|
876
846
|
}
|
|
877
847
|
};
|
|
878
848
|
|
|
879
|
-
/**
|
|
880
|
-
* Create an Observable checker instance
|
|
881
|
-
* @param callback
|
|
882
|
-
* @returns {ObservableChecker}
|
|
883
|
-
*/
|
|
884
|
-
ObservableItem.prototype.check = function(callback) {
|
|
885
|
-
return new ObservableChecker(this, callback)
|
|
886
|
-
};
|
|
887
|
-
|
|
888
|
-
ObservableItem.prototype.transform = ObservableItem.prototype.check;
|
|
889
|
-
ObservableItem.prototype.pluck = function(property) {
|
|
890
|
-
return new ObservableChecker(this, (value) => value[property]);
|
|
891
|
-
};
|
|
892
|
-
ObservableItem.prototype.is = function(callbackOrValue) {
|
|
893
|
-
if(typeof callbackOrValue === 'function') {
|
|
894
|
-
return new ObservableChecker(this, callbackOrValue);
|
|
895
|
-
}
|
|
896
|
-
return new ObservableChecker(this, (value) => value === callbackOrValue);
|
|
897
|
-
};
|
|
898
|
-
ObservableItem.prototype.select = ObservableItem.prototype.check;
|
|
899
|
-
|
|
900
849
|
|
|
901
850
|
|
|
902
851
|
|
|
@@ -916,21 +865,6 @@ var NativeDocument = (function (exports) {
|
|
|
916
865
|
return Validator.isObservable(item) ? item.val() : item;
|
|
917
866
|
};
|
|
918
867
|
|
|
919
|
-
/**
|
|
920
|
-
* Creates an ObservableWhen that represents whether the observable equals a specific value.
|
|
921
|
-
* Returns an object that can be subscribed to and will emit true/false.
|
|
922
|
-
*
|
|
923
|
-
* @param {*} value - The value to compare against
|
|
924
|
-
* @returns {ObservableWhen} An ObservableWhen instance that tracks when the observable equals the value
|
|
925
|
-
* @example
|
|
926
|
-
* const status = Observable('idle');
|
|
927
|
-
* const isLoading = status.when('loading');
|
|
928
|
-
* isLoading.subscribe(active => console.log('Loading:', active));
|
|
929
|
-
* status.set('loading'); // Logs: "Loading: true"
|
|
930
|
-
*/
|
|
931
|
-
ObservableItem.prototype.when = function(value) {
|
|
932
|
-
return new ObservableWhen(this, value);
|
|
933
|
-
};
|
|
934
868
|
|
|
935
869
|
/**
|
|
936
870
|
* Compares the observable's current value with another value or observable.
|
|
@@ -1018,79 +952,6 @@ var NativeDocument = (function (exports) {
|
|
|
1018
952
|
};
|
|
1019
953
|
|
|
1020
954
|
|
|
1021
|
-
/**
|
|
1022
|
-
* Creates a derived observable that formats the current value using Intl.
|
|
1023
|
-
* Automatically reacts to both value changes and locale changes (Store.__nd.locale).
|
|
1024
|
-
*
|
|
1025
|
-
* @param {string | Function} type - Format type or custom formatter function
|
|
1026
|
-
* @param {Object} [options={}] - Options passed to the formatter
|
|
1027
|
-
* @returns {ObservableItem<string>}
|
|
1028
|
-
*
|
|
1029
|
-
* @example
|
|
1030
|
-
* // Currency
|
|
1031
|
-
* price.format('currency') // "15 000 FCFA"
|
|
1032
|
-
* price.format('currency', { currency: 'EUR' }) // "15 000,00 €"
|
|
1033
|
-
* price.format('currency', { notation: 'compact' }) // "15 K FCFA"
|
|
1034
|
-
*
|
|
1035
|
-
* // Number
|
|
1036
|
-
* count.format('number') // "15 000"
|
|
1037
|
-
*
|
|
1038
|
-
* // Percent
|
|
1039
|
-
* rate.format('percent') // "15,0 %"
|
|
1040
|
-
* rate.format('percent', { decimals: 2 }) // "15,00 %"
|
|
1041
|
-
*
|
|
1042
|
-
* // Date
|
|
1043
|
-
* date.format('date') // "3 mars 2026"
|
|
1044
|
-
* date.format('date', { dateStyle: 'full' }) // "mardi 3 mars 2026"
|
|
1045
|
-
* date.format('date', { format: 'DD/MM/YYYY' }) // "03/03/2026"
|
|
1046
|
-
* date.format('date', { format: 'DD MMM YYYY' }) // "03 mar 2026"
|
|
1047
|
-
* date.format('date', { format: 'DD MMMM YYYY' }) // "03 mars 2026"
|
|
1048
|
-
*
|
|
1049
|
-
* // Time
|
|
1050
|
-
* date.format('time') // "20:30"
|
|
1051
|
-
* date.format('time', { second: '2-digit' }) // "20:30:00"
|
|
1052
|
-
* date.format('time', { format: 'HH:mm:ss' }) // "20:30:00"
|
|
1053
|
-
*
|
|
1054
|
-
* // Datetime
|
|
1055
|
-
* date.format('datetime') // "3 mars 2026, 20:30"
|
|
1056
|
-
* date.format('datetime', { dateStyle: 'full' }) // "mardi 3 mars 2026, 20:30"
|
|
1057
|
-
* date.format('datetime', { format: 'DD/MM/YYYY HH:mm' }) // "03/03/2026 20:30"
|
|
1058
|
-
*
|
|
1059
|
-
* // Relative
|
|
1060
|
-
* date.format('relative') // "dans 11 jours"
|
|
1061
|
-
* date.format('relative', { unit: 'month' }) // "dans 1 mois"
|
|
1062
|
-
*
|
|
1063
|
-
* // Plural
|
|
1064
|
-
* count.format('plural', { singular: 'billet', plural: 'billets' }) // "3 billets"
|
|
1065
|
-
*
|
|
1066
|
-
* // Custom formatter
|
|
1067
|
-
* price.format(value => `${value.toLocaleString()} FCFA`)
|
|
1068
|
-
*
|
|
1069
|
-
* // Reacts to locale changes automatically
|
|
1070
|
-
* Store.setLocale('en-US');
|
|
1071
|
-
*/
|
|
1072
|
-
ObservableItem.prototype.format = function(type, options = {}) {
|
|
1073
|
-
const self = this;
|
|
1074
|
-
|
|
1075
|
-
if (typeof type === 'function') {
|
|
1076
|
-
return new ObservableChecker(self, type);
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
{
|
|
1080
|
-
if (!Formatters[type]) {
|
|
1081
|
-
throw new NativeDocumentError(
|
|
1082
|
-
`Observable.format : unknown type '${type}'. Available : ${Object.keys(Formatters).join(', ')}.`
|
|
1083
|
-
);
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
const formatter = Formatters[type];
|
|
1088
|
-
const localeObservable = Formatters.locale;
|
|
1089
|
-
|
|
1090
|
-
return Observable.computed(() => formatter(self.val(), localeObservable.val(), options),
|
|
1091
|
-
[self, localeObservable]
|
|
1092
|
-
);
|
|
1093
|
-
};
|
|
1094
955
|
|
|
1095
956
|
ObservableItem.prototype.persist = function(key, options = {}) {
|
|
1096
957
|
let value = $getFromStorage(key, this.$currentValue);
|
|
@@ -1121,279 +982,98 @@ var NativeDocument = (function (exports) {
|
|
|
1121
982
|
|
|
1122
983
|
/**
|
|
1123
984
|
*
|
|
1124
|
-
* @param {
|
|
1125
|
-
* @param {
|
|
1126
|
-
* @
|
|
985
|
+
* @param {*} value
|
|
986
|
+
* @param {{ propagation: boolean, reset: boolean} | null} configs
|
|
987
|
+
* @returns {ObservableItem}
|
|
988
|
+
* @constructor
|
|
1127
989
|
*/
|
|
1128
|
-
function
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
ObservableItem.call(this);
|
|
1132
|
-
{
|
|
1133
|
-
PluginsManager$1.emit('CreateObservableChecker', this);
|
|
1134
|
-
}
|
|
990
|
+
function Observable(value, configs = null) {
|
|
991
|
+
return new ObservableItem(value, configs);
|
|
992
|
+
}
|
|
1135
993
|
|
|
1136
|
-
|
|
994
|
+
const $ = Observable;
|
|
995
|
+
const obs = Observable;
|
|
1137
996
|
|
|
1138
|
-
|
|
1139
|
-
|
|
997
|
+
/**
|
|
998
|
+
*
|
|
999
|
+
* @param {string} propertyName
|
|
1000
|
+
*/
|
|
1001
|
+
Observable.useValueProperty = function(propertyName = 'value') {
|
|
1002
|
+
Object.defineProperty(ObservableItem.prototype, propertyName, {
|
|
1003
|
+
get() {
|
|
1004
|
+
return this.$currentValue;
|
|
1005
|
+
},
|
|
1006
|
+
set(value) {
|
|
1007
|
+
this.set(value);
|
|
1008
|
+
},
|
|
1009
|
+
configurable: true,
|
|
1140
1010
|
});
|
|
1011
|
+
};
|
|
1141
1012
|
|
|
1142
|
-
this.$updateWithMutation($observable.val());
|
|
1143
|
-
}
|
|
1144
1013
|
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1014
|
+
/**
|
|
1015
|
+
*
|
|
1016
|
+
* @param id
|
|
1017
|
+
* @returns {ObservableItem|null}
|
|
1018
|
+
*/
|
|
1019
|
+
Observable.getById = function(id) {
|
|
1020
|
+
const item = MemoryManager.getObservableById(parseInt(id));
|
|
1021
|
+
if(!item) {
|
|
1022
|
+
throw new NativeDocumentError('Observable.getById : No observable found with id ' + id);
|
|
1023
|
+
}
|
|
1024
|
+
return item;
|
|
1025
|
+
};
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
*
|
|
1029
|
+
* @param {ObservableItem} observable
|
|
1030
|
+
*/
|
|
1031
|
+
Observable.cleanup = function(observable) {
|
|
1032
|
+
observable.cleanup();
|
|
1033
|
+
};
|
|
1149
1034
|
|
|
1035
|
+
/**
|
|
1036
|
+
* Enable auto cleanup of observables.
|
|
1037
|
+
* @param {Boolean} enable
|
|
1038
|
+
* @param {{interval:Boolean, threshold:number}} options
|
|
1039
|
+
*/
|
|
1040
|
+
Observable.autoCleanup = function(enable = false, options = {}) {
|
|
1041
|
+
if(!enable) {
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
const { interval = 60000, threshold = 100 } = options;
|
|
1150
1045
|
|
|
1151
|
-
|
|
1152
|
-
|
|
1046
|
+
window.addEventListener('beforeunload', () => {
|
|
1047
|
+
MemoryManager.cleanup();
|
|
1048
|
+
});
|
|
1153
1049
|
|
|
1154
|
-
|
|
1155
|
-
newValue = this.$mutation(newValue);
|
|
1156
|
-
return this.set(newValue);
|
|
1050
|
+
setInterval(() => MemoryManager.cleanObservables(threshold), interval);
|
|
1157
1051
|
};
|
|
1158
1052
|
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
if(
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
if(!data.mounted) {
|
|
1184
|
-
return;
|
|
1185
|
-
}
|
|
1186
|
-
if(Array.isArray(data.mounted)) {
|
|
1187
|
-
for(const cb of data.mounted) {
|
|
1188
|
-
cb(node);
|
|
1189
|
-
}
|
|
1190
|
-
return;
|
|
1191
|
-
}
|
|
1192
|
-
data.mounted(node);
|
|
1193
|
-
},
|
|
1194
|
-
|
|
1195
|
-
executeUnmountedCallback(node) {
|
|
1196
|
-
const data = DocumentObserver.unmounted.get(node);
|
|
1197
|
-
if(!data) {
|
|
1198
|
-
return;
|
|
1199
|
-
}
|
|
1200
|
-
data.inDom = false;
|
|
1201
|
-
if(!data.unmounted) {
|
|
1202
|
-
return;
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
let shouldRemove = false;
|
|
1206
|
-
if(Array.isArray(data.unmounted)) {
|
|
1207
|
-
for(const cb of data.unmounted) {
|
|
1208
|
-
if(cb(node) === true) {
|
|
1209
|
-
shouldRemove = true;
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
} else {
|
|
1213
|
-
shouldRemove = data.unmounted(node) === true;
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
if(shouldRemove) {
|
|
1217
|
-
data.disconnect();
|
|
1218
|
-
node.nd?.remove();
|
|
1219
|
-
}
|
|
1220
|
-
},
|
|
1221
|
-
|
|
1222
|
-
checkMutation: function(mutationsList) {
|
|
1223
|
-
for(const mutation of mutationsList) {
|
|
1224
|
-
if(DocumentObserver.mountedSupposedSize > 0) {
|
|
1225
|
-
for(const node of mutation.addedNodes) {
|
|
1226
|
-
DocumentObserver.executeMountedCallback(node);
|
|
1227
|
-
if(!node.querySelectorAll) {
|
|
1228
|
-
continue;
|
|
1229
|
-
}
|
|
1230
|
-
const children = node.querySelectorAll('[data--nd-mounted]');
|
|
1231
|
-
for(const child of children) {
|
|
1232
|
-
DocumentObserver.executeMountedCallback(child);
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
if (DocumentObserver.unmountedSupposedSize > 0) {
|
|
1238
|
-
for (const node of mutation.removedNodes) {
|
|
1239
|
-
DocumentObserver.executeUnmountedCallback(node);
|
|
1240
|
-
if(!node.querySelectorAll) {
|
|
1241
|
-
continue;
|
|
1242
|
-
}
|
|
1243
|
-
const children = node.querySelectorAll('[data--nd-unmounted]');
|
|
1244
|
-
for(const child of children) {
|
|
1245
|
-
DocumentObserver.executeUnmountedCallback(child);
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
}
|
|
1250
|
-
},
|
|
1251
|
-
|
|
1252
|
-
/**
|
|
1253
|
-
* @param {HTMLElement} element
|
|
1254
|
-
* @param {boolean} inDom
|
|
1255
|
-
* @returns {{ disconnect: Function, mounted: Function, unmounted: Function, off: Function }}
|
|
1256
|
-
*/
|
|
1257
|
-
watch: function(element, inDom = false) {
|
|
1258
|
-
let mountedRegistered = false;
|
|
1259
|
-
let unmountedRegistered = false;
|
|
1260
|
-
|
|
1261
|
-
DocumentObserver.initObserver();
|
|
1262
|
-
|
|
1263
|
-
let data = {
|
|
1264
|
-
inDom,
|
|
1265
|
-
mounted: null,
|
|
1266
|
-
unmounted: null,
|
|
1267
|
-
disconnect: () => {
|
|
1268
|
-
if (mountedRegistered) {
|
|
1269
|
-
DocumentObserver.mounted.delete(element);
|
|
1270
|
-
DocumentObserver.mountedSupposedSize--;
|
|
1271
|
-
}
|
|
1272
|
-
if (unmountedRegistered) {
|
|
1273
|
-
DocumentObserver.unmounted.delete(element);
|
|
1274
|
-
DocumentObserver.unmountedSupposedSize--;
|
|
1275
|
-
}
|
|
1276
|
-
data = null;
|
|
1277
|
-
}
|
|
1278
|
-
};
|
|
1279
|
-
|
|
1280
|
-
const addListener = (type, callback) => {
|
|
1281
|
-
if (!data[type]) {
|
|
1282
|
-
data[type] = callback;
|
|
1283
|
-
return;
|
|
1284
|
-
}
|
|
1285
|
-
if (!Array.isArray(data[type])) {
|
|
1286
|
-
data[type] = [data[type], callback];
|
|
1287
|
-
return;
|
|
1288
|
-
}
|
|
1289
|
-
data[type].push(callback);
|
|
1290
|
-
};
|
|
1291
|
-
|
|
1292
|
-
const removeListener = (type, callback) => {
|
|
1293
|
-
if(!data?.[type]) {
|
|
1294
|
-
return;
|
|
1295
|
-
}
|
|
1296
|
-
if(Array.isArray(data[type])) {
|
|
1297
|
-
const index = data[type].indexOf(callback);
|
|
1298
|
-
if(index > -1) {
|
|
1299
|
-
data[type].splice(index, 1);
|
|
1300
|
-
}
|
|
1301
|
-
if(data[type].length === 1) {
|
|
1302
|
-
data[type] = data[type][0];
|
|
1303
|
-
}
|
|
1304
|
-
if(data[type].length === 0) {
|
|
1305
|
-
data[type] = null;
|
|
1306
|
-
}
|
|
1307
|
-
return;
|
|
1308
|
-
}
|
|
1309
|
-
data[type] = null;
|
|
1310
|
-
};
|
|
1311
|
-
|
|
1312
|
-
return {
|
|
1313
|
-
disconnect: () => data?.disconnect(),
|
|
1314
|
-
|
|
1315
|
-
mounted: (callback) => {
|
|
1316
|
-
addListener('mounted', callback);
|
|
1317
|
-
DocumentObserver.mounted.set(element, data);
|
|
1318
|
-
if (!mountedRegistered) {
|
|
1319
|
-
DocumentObserver.mountedSupposedSize++;
|
|
1320
|
-
mountedRegistered = true;
|
|
1321
|
-
}
|
|
1322
|
-
},
|
|
1323
|
-
|
|
1324
|
-
unmounted: (callback) => {
|
|
1325
|
-
addListener('unmounted', callback);
|
|
1326
|
-
DocumentObserver.unmounted.set(element, data);
|
|
1327
|
-
if (!unmountedRegistered) {
|
|
1328
|
-
DocumentObserver.unmountedSupposedSize++;
|
|
1329
|
-
unmountedRegistered = true;
|
|
1330
|
-
}
|
|
1331
|
-
},
|
|
1332
|
-
|
|
1333
|
-
off: (type, callback) => {
|
|
1334
|
-
removeListener(type, callback);
|
|
1335
|
-
}
|
|
1336
|
-
};
|
|
1337
|
-
}
|
|
1338
|
-
};
|
|
1339
|
-
|
|
1340
|
-
const BOOLEAN_ATTRIBUTES = new Set([
|
|
1341
|
-
'checked',
|
|
1342
|
-
'selected',
|
|
1343
|
-
'disabled',
|
|
1344
|
-
'readonly',
|
|
1345
|
-
'required',
|
|
1346
|
-
'autofocus',
|
|
1347
|
-
'multiple',
|
|
1348
|
-
'autocomplete',
|
|
1349
|
-
'hidden',
|
|
1350
|
-
'contenteditable',
|
|
1351
|
-
'spellcheck',
|
|
1352
|
-
'translate',
|
|
1353
|
-
'draggable',
|
|
1354
|
-
'async',
|
|
1355
|
-
'defer',
|
|
1356
|
-
'autoplay',
|
|
1357
|
-
'controls',
|
|
1358
|
-
'loop',
|
|
1359
|
-
'muted',
|
|
1360
|
-
'download',
|
|
1361
|
-
'reversed',
|
|
1362
|
-
'open',
|
|
1363
|
-
'default',
|
|
1364
|
-
'formnovalidate',
|
|
1365
|
-
'novalidate',
|
|
1366
|
-
'scoped',
|
|
1367
|
-
'itemscope',
|
|
1368
|
-
'allowfullscreen',
|
|
1369
|
-
'allowpaymentrequest',
|
|
1370
|
-
'playsinline'
|
|
1371
|
-
]);
|
|
1372
|
-
|
|
1373
|
-
/**
|
|
1374
|
-
*
|
|
1375
|
-
* @param {HTMLElement} element
|
|
1376
|
-
* @param {Object} data
|
|
1377
|
-
*/
|
|
1378
|
-
const bindClassAttribute = (element, data) => {
|
|
1379
|
-
for(const className in data) {
|
|
1380
|
-
const value = data[className];
|
|
1381
|
-
if(value.__$Observable) {
|
|
1382
|
-
if(value.__$isObservableChecker) {
|
|
1383
|
-
let lastClass = value.val();
|
|
1384
|
-
if(typeof lastClass === "string") {
|
|
1385
|
-
element.classes.toggle(lastClass, true);
|
|
1386
|
-
value.subscribe((currentValue) => {
|
|
1387
|
-
element.classes.remove(lastClass);
|
|
1388
|
-
element.classes.toggle(currentValue, true);
|
|
1389
|
-
lastClass = currentValue;
|
|
1390
|
-
});
|
|
1391
|
-
continue;
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
element.classes.toggle(className, value.val());
|
|
1395
|
-
value.subscribe((shouldAdd) => element.classes.toggle(className, shouldAdd));
|
|
1396
|
-
continue;
|
|
1053
|
+
/**
|
|
1054
|
+
*
|
|
1055
|
+
* @param {HTMLElement} element
|
|
1056
|
+
* @param {Object} data
|
|
1057
|
+
*/
|
|
1058
|
+
const bindClassAttribute = (element, data) => {
|
|
1059
|
+
for(const className in data) {
|
|
1060
|
+
const value = data[className];
|
|
1061
|
+
if(value.__$Observable) {
|
|
1062
|
+
if(value.__$isObservableChecker) {
|
|
1063
|
+
let lastClass = value.val();
|
|
1064
|
+
if(typeof lastClass === "string") {
|
|
1065
|
+
element.classes.toggle(lastClass, true);
|
|
1066
|
+
value.subscribe((currentValue) => {
|
|
1067
|
+
element.classes.remove(lastClass);
|
|
1068
|
+
element.classes.toggle(currentValue, true);
|
|
1069
|
+
lastClass = currentValue;
|
|
1070
|
+
});
|
|
1071
|
+
continue;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
element.classes.toggle(className, value.val());
|
|
1075
|
+
value.subscribe((shouldAdd) => element.classes.toggle(className, shouldAdd));
|
|
1076
|
+
continue;
|
|
1397
1077
|
}
|
|
1398
1078
|
if(value.$hydrate) {
|
|
1399
1079
|
value.$hydrate(element, className);
|
|
@@ -1428,281 +1108,111 @@ var NativeDocument = (function (exports) {
|
|
|
1428
1108
|
value.subscribe((newValue) => {
|
|
1429
1109
|
if(newValue === false) {
|
|
1430
1110
|
element.style.removeProperty(styleName);
|
|
1431
|
-
return;
|
|
1432
|
-
}
|
|
1433
|
-
element.style[styleName] = newValue;
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
continue;
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
|
-
if(isCustomProperty) {
|
|
1440
|
-
element.style.setProperty(styleName, value);
|
|
1441
|
-
continue;
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
element.style[styleName] = value;
|
|
1445
|
-
}
|
|
1446
|
-
};
|
|
1447
|
-
|
|
1448
|
-
/**
|
|
1449
|
-
*
|
|
1450
|
-
* @param {HTMLElement} element
|
|
1451
|
-
* @param {string} attributeName
|
|
1452
|
-
* @param {boolean|number|Observable} value
|
|
1453
|
-
*/
|
|
1454
|
-
const bindBooleanAttribute = (element, attributeName, value) => {
|
|
1455
|
-
const isObservable = value.__$isObservable;
|
|
1456
|
-
const defaultValue = isObservable? value.val() : value;
|
|
1457
|
-
if(Validator.isBoolean(defaultValue)) {
|
|
1458
|
-
element[attributeName] = defaultValue;
|
|
1459
|
-
}
|
|
1460
|
-
else {
|
|
1461
|
-
element[attributeName] = defaultValue === element.value;
|
|
1462
|
-
}
|
|
1463
|
-
if(isObservable) {
|
|
1464
|
-
if(attributeName === 'checked') {
|
|
1465
|
-
if(typeof defaultValue === 'boolean') {
|
|
1466
|
-
element.addEventListener('input', () => value.set(element[attributeName]));
|
|
1467
|
-
}
|
|
1468
|
-
else {
|
|
1469
|
-
element.addEventListener('input', () => value.set(element.value));
|
|
1470
|
-
}
|
|
1471
|
-
value.subscribe((newValue) => element[attributeName] = newValue);
|
|
1472
|
-
return;
|
|
1473
|
-
}
|
|
1474
|
-
value.subscribe((newValue) => element[attributeName] = (newValue === element.value));
|
|
1475
|
-
}
|
|
1476
|
-
};
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
/**
|
|
1480
|
-
*
|
|
1481
|
-
* @param {HTMLElement} element
|
|
1482
|
-
* @param {string} attributeName
|
|
1483
|
-
* @param {Observable} value
|
|
1484
|
-
*/
|
|
1485
|
-
const bindAttributeWithObservable = (element, attributeName, value) => {
|
|
1486
|
-
const applyValue = attributeName === 'value' ? (newValue) => element.value = newValue : (newValue) => element.setAttribute(attributeName, newValue);
|
|
1487
|
-
value.subscribe(applyValue);
|
|
1488
|
-
|
|
1489
|
-
if(attributeName === 'value') {
|
|
1490
|
-
element.value = value.val();
|
|
1491
|
-
element.addEventListener('input', () => value.set(element.value));
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1494
|
-
element.setAttribute(attributeName, value.val());
|
|
1495
|
-
};
|
|
1496
|
-
|
|
1497
|
-
/**
|
|
1498
|
-
*
|
|
1499
|
-
* @param {HTMLElement} element
|
|
1500
|
-
* @param {Object} attributes
|
|
1501
|
-
*/
|
|
1502
|
-
const AttributesWrapper = (element, attributes) => {
|
|
1503
|
-
|
|
1504
|
-
{
|
|
1505
|
-
Validator.validateAttributes(attributes);
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
for(const originalAttributeName in attributes) {
|
|
1509
|
-
const attributeName = originalAttributeName.toLowerCase();
|
|
1510
|
-
let value = attributes[originalAttributeName];
|
|
1511
|
-
if(value == null) {
|
|
1512
|
-
continue;
|
|
1513
|
-
}
|
|
1514
|
-
if(value.handleNdAttribute) {
|
|
1515
|
-
value.handleNdAttribute(element, attributeName, value);
|
|
1516
|
-
continue;
|
|
1517
|
-
}
|
|
1518
|
-
if(typeof value === 'object') {
|
|
1519
|
-
if(attributeName === 'class') {
|
|
1520
|
-
bindClassAttribute(element, value);
|
|
1521
|
-
continue;
|
|
1522
|
-
}
|
|
1523
|
-
if(attributeName === 'style') {
|
|
1524
|
-
bindStyleAttribute(element, value);
|
|
1525
|
-
continue;
|
|
1526
|
-
}
|
|
1527
|
-
}
|
|
1528
|
-
if(BOOLEAN_ATTRIBUTES.has(attributeName)) {
|
|
1529
|
-
bindBooleanAttribute(element, attributeName, value);
|
|
1530
|
-
continue;
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1533
|
-
element.setAttribute(attributeName, value);
|
|
1534
|
-
}
|
|
1535
|
-
return element;
|
|
1536
|
-
};
|
|
1537
|
-
|
|
1538
|
-
function TemplateBinding(hydrate) {
|
|
1539
|
-
this.$hydrate = hydrate;
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
TemplateBinding.prototype.__$isTemplateBinding = true;
|
|
1543
|
-
|
|
1544
|
-
String.prototype.toNdElement = function () {
|
|
1545
|
-
return ElementCreator.createStaticTextNode(null, this);
|
|
1546
|
-
};
|
|
1547
|
-
|
|
1548
|
-
Number.prototype.toNdElement = function () {
|
|
1549
|
-
return ElementCreator.createStaticTextNode(null, this.toString());
|
|
1550
|
-
};
|
|
1551
|
-
|
|
1552
|
-
Element.prototype.toNdElement = function () {
|
|
1553
|
-
return this;
|
|
1554
|
-
};
|
|
1555
|
-
Text.prototype.toNdElement = function () {
|
|
1556
|
-
return this;
|
|
1557
|
-
};
|
|
1558
|
-
Comment.prototype.toNdElement = function () {
|
|
1559
|
-
return this;
|
|
1560
|
-
};
|
|
1561
|
-
Document.prototype.toNdElement = function () {
|
|
1562
|
-
return this;
|
|
1563
|
-
};
|
|
1564
|
-
DocumentFragment.prototype.toNdElement = function () {
|
|
1565
|
-
return this;
|
|
1566
|
-
};
|
|
1567
|
-
|
|
1568
|
-
ObservableItem.prototype.toNdElement = function () {
|
|
1569
|
-
return ElementCreator.createObservableNode(null, this);
|
|
1570
|
-
};
|
|
1571
|
-
|
|
1572
|
-
ObservableChecker.prototype.toNdElement = ObservableItem.prototype.toNdElement;
|
|
1573
|
-
|
|
1574
|
-
NDElement.prototype.toNdElement = function () {
|
|
1575
|
-
const element = this.$element ?? this.$build?.() ?? this.build?.() ?? null;
|
|
1576
|
-
if(this.$attachements) {
|
|
1577
|
-
if(!this.$attachements.contains(this.$element)) {
|
|
1578
|
-
this.$attachements.append(this.$element);
|
|
1579
|
-
}
|
|
1580
|
-
return this.$attachements;
|
|
1581
|
-
}
|
|
1582
|
-
return element;
|
|
1583
|
-
};
|
|
1584
|
-
|
|
1585
|
-
Array.prototype.toNdElement = function () {
|
|
1586
|
-
const fragment = document.createDocumentFragment();
|
|
1587
|
-
for(let i = 0, length = this.length; i < length; i++) {
|
|
1588
|
-
const child = ElementCreator.getChild(this[i]);
|
|
1589
|
-
if(child === null) continue;
|
|
1590
|
-
fragment.appendChild(child);
|
|
1591
|
-
}
|
|
1592
|
-
return fragment;
|
|
1593
|
-
};
|
|
1594
|
-
|
|
1595
|
-
Function.prototype.toNdElement = function () {
|
|
1596
|
-
const child = this;
|
|
1597
|
-
{
|
|
1598
|
-
PluginsManager$1.emit('BeforeProcessComponent', child);
|
|
1599
|
-
}
|
|
1600
|
-
return ElementCreator.getChild(child());
|
|
1601
|
-
};
|
|
1602
|
-
|
|
1603
|
-
TemplateBinding.prototype.toNdElement = function () {
|
|
1604
|
-
return ElementCreator.createHydratableNode(null, this);
|
|
1605
|
-
};
|
|
1606
|
-
|
|
1607
|
-
/**
|
|
1608
|
-
* @param {HTMLElement} el
|
|
1609
|
-
* @param {number} timeout
|
|
1610
|
-
*/
|
|
1611
|
-
const waitForVisualEnd = (el, timeout = 1000) => {
|
|
1612
|
-
return new Promise((resolve) => {
|
|
1613
|
-
let isResolved = false;
|
|
1614
|
-
|
|
1615
|
-
const cleanupAndResolve = (e) => {
|
|
1616
|
-
if (e && e.target !== el) return;
|
|
1617
|
-
if (isResolved) return;
|
|
1618
|
-
|
|
1619
|
-
isResolved = true;
|
|
1620
|
-
el.removeEventListener('transitionend', cleanupAndResolve);
|
|
1621
|
-
el.removeEventListener('animationend', cleanupAndResolve);
|
|
1622
|
-
clearTimeout(timer);
|
|
1623
|
-
resolve();
|
|
1624
|
-
};
|
|
1625
|
-
|
|
1626
|
-
el.addEventListener('transitionend', cleanupAndResolve);
|
|
1627
|
-
el.addEventListener('animationend', cleanupAndResolve);
|
|
1628
|
-
|
|
1629
|
-
const timer = setTimeout(cleanupAndResolve, timeout);
|
|
1630
|
-
|
|
1631
|
-
const style = window.getComputedStyle(el);
|
|
1632
|
-
const hasTransition = style.transitionDuration !== '0s';
|
|
1633
|
-
const hasAnimation = style.animationDuration !== '0s';
|
|
1634
|
-
|
|
1635
|
-
if (!hasTransition && !hasAnimation) {
|
|
1636
|
-
cleanupAndResolve();
|
|
1637
|
-
}
|
|
1638
|
-
});
|
|
1639
|
-
};
|
|
1640
|
-
|
|
1641
|
-
NDElement.prototype.transitionOut = function(transitionName) {
|
|
1642
|
-
const exitClass = transitionName + '-exit';
|
|
1643
|
-
const el = this.$element;
|
|
1644
|
-
this.beforeUnmount('transition-exit', async function() {
|
|
1645
|
-
el.classes.add(exitClass);
|
|
1646
|
-
await waitForVisualEnd(el);
|
|
1647
|
-
el.classes.remove(exitClass);
|
|
1648
|
-
});
|
|
1649
|
-
return this;
|
|
1650
|
-
};
|
|
1651
|
-
|
|
1652
|
-
NDElement.prototype.transitionIn = function(transitionName) {
|
|
1653
|
-
const startClass = transitionName + '-enter-from';
|
|
1654
|
-
const endClass = transitionName + '-enter-to';
|
|
1655
|
-
|
|
1656
|
-
const el = this.$element;
|
|
1657
|
-
|
|
1658
|
-
el.classes.add(startClass);
|
|
1659
|
-
|
|
1660
|
-
this.mounted(() => {
|
|
1661
|
-
requestAnimationFrame(() => {
|
|
1662
|
-
requestAnimationFrame(() => {
|
|
1663
|
-
el.classes.remove(startClass);
|
|
1664
|
-
el.classes.add(endClass);
|
|
1665
|
-
|
|
1666
|
-
waitForVisualEnd(el).then(() => {
|
|
1667
|
-
el.classes.remove(endClass);
|
|
1668
|
-
});
|
|
1669
|
-
});
|
|
1670
|
-
});
|
|
1671
|
-
});
|
|
1672
|
-
return this;
|
|
1673
|
-
};
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
element.style[styleName] = newValue;
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
continue;
|
|
1117
|
+
}
|
|
1674
1118
|
|
|
1119
|
+
if(isCustomProperty) {
|
|
1120
|
+
element.style.setProperty(styleName, value);
|
|
1121
|
+
continue;
|
|
1122
|
+
}
|
|
1675
1123
|
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
this.transitionOut(transitionName);
|
|
1679
|
-
return this;
|
|
1124
|
+
element.style[styleName] = value;
|
|
1125
|
+
}
|
|
1680
1126
|
};
|
|
1681
1127
|
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1128
|
+
/**
|
|
1129
|
+
*
|
|
1130
|
+
* @param {HTMLElement} element
|
|
1131
|
+
* @param {string} attributeName
|
|
1132
|
+
* @param {boolean|number|Observable} value
|
|
1133
|
+
*/
|
|
1134
|
+
const bindBooleanAttribute = (element, attributeName, value) => {
|
|
1135
|
+
const isObservable = value.__$isObservable;
|
|
1136
|
+
const defaultValue = isObservable? value.val() : value;
|
|
1137
|
+
if(Validator.isBoolean(defaultValue)) {
|
|
1138
|
+
element[attributeName] = defaultValue;
|
|
1139
|
+
}
|
|
1140
|
+
else {
|
|
1141
|
+
element[attributeName] = defaultValue === element.value;
|
|
1142
|
+
}
|
|
1143
|
+
if(isObservable) {
|
|
1144
|
+
if(attributeName === 'checked') {
|
|
1145
|
+
if(typeof defaultValue === 'boolean') {
|
|
1146
|
+
element.addEventListener('input', () => value.set(element[attributeName]));
|
|
1147
|
+
}
|
|
1148
|
+
else {
|
|
1149
|
+
element.addEventListener('input', () => value.set(element.value));
|
|
1150
|
+
}
|
|
1151
|
+
value.subscribe((newValue) => element[attributeName] = newValue);
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
value.subscribe((newValue) => element[attributeName] = (newValue === element.value));
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1685
1157
|
|
|
1686
|
-
waitForVisualEnd(el).then(() => {
|
|
1687
|
-
el.classes.remove(animationName);
|
|
1688
|
-
});
|
|
1689
1158
|
|
|
1690
|
-
|
|
1691
|
-
|
|
1159
|
+
/**
|
|
1160
|
+
*
|
|
1161
|
+
* @param {HTMLElement} element
|
|
1162
|
+
* @param {string} attributeName
|
|
1163
|
+
* @param {Observable} value
|
|
1164
|
+
*/
|
|
1165
|
+
const bindAttributeWithObservable = (element, attributeName, value) => {
|
|
1166
|
+
const applyValue = attributeName === 'value' ? (newValue) => element.value = newValue : (newValue) => element.setAttribute(attributeName, newValue);
|
|
1167
|
+
value.subscribe(applyValue);
|
|
1692
1168
|
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1169
|
+
if(attributeName === 'value') {
|
|
1170
|
+
element.value = value.val();
|
|
1171
|
+
element.addEventListener('input', () => value.set(element.value));
|
|
1696
1172
|
return;
|
|
1697
1173
|
}
|
|
1698
|
-
|
|
1699
|
-
bindAttributeWithObservable(element, attributeName, this);
|
|
1174
|
+
element.setAttribute(attributeName, value.val());
|
|
1700
1175
|
};
|
|
1701
1176
|
|
|
1702
|
-
|
|
1177
|
+
/**
|
|
1178
|
+
*
|
|
1179
|
+
* @param {HTMLElement} element
|
|
1180
|
+
* @param {Object} attributes
|
|
1181
|
+
*/
|
|
1182
|
+
const AttributesWrapper = (element, attributes) => {
|
|
1703
1183
|
|
|
1704
|
-
|
|
1705
|
-
|
|
1184
|
+
{
|
|
1185
|
+
Validator.validateAttributes(attributes);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
for(const originalAttributeName in attributes) {
|
|
1189
|
+
const attributeName = originalAttributeName.toLowerCase();
|
|
1190
|
+
let value = attributes[originalAttributeName];
|
|
1191
|
+
if(value == null) {
|
|
1192
|
+
continue;
|
|
1193
|
+
}
|
|
1194
|
+
if(value.handleNdAttribute) {
|
|
1195
|
+
value.handleNdAttribute(element, attributeName, value);
|
|
1196
|
+
continue;
|
|
1197
|
+
}
|
|
1198
|
+
if(typeof value === 'object') {
|
|
1199
|
+
if(attributeName === 'class') {
|
|
1200
|
+
bindClassAttribute(element, value);
|
|
1201
|
+
continue;
|
|
1202
|
+
}
|
|
1203
|
+
if(attributeName === 'style') {
|
|
1204
|
+
bindStyleAttribute(element, value);
|
|
1205
|
+
continue;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
if(BOOLEAN_ATTRIBUTES.has(attributeName)) {
|
|
1209
|
+
bindBooleanAttribute(element, attributeName, value);
|
|
1210
|
+
continue;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
element.setAttribute(attributeName, value);
|
|
1214
|
+
}
|
|
1215
|
+
return element;
|
|
1706
1216
|
};
|
|
1707
1217
|
|
|
1708
1218
|
let $textNodeCache = null;
|
|
@@ -1761,9 +1271,6 @@ var NativeDocument = (function (exports) {
|
|
|
1761
1271
|
const node = document.createElement(name);
|
|
1762
1272
|
return node.cloneNode();
|
|
1763
1273
|
},
|
|
1764
|
-
createFragment: (name) => {
|
|
1765
|
-
return Anchor('Fragment');
|
|
1766
|
-
},
|
|
1767
1274
|
bindTextNode: (textNode, value) => {
|
|
1768
1275
|
if(value?.__$isObservable) {
|
|
1769
1276
|
value.subscribe(newValue => textNode.nodeValue = newValue);
|
|
@@ -2099,37 +1606,218 @@ var NativeDocument = (function (exports) {
|
|
|
2099
1606
|
anchorFragment.appendChild(anchorFragment);
|
|
2100
1607
|
};
|
|
2101
1608
|
|
|
2102
|
-
anchorFragment.clear = anchorFragment.remove;
|
|
2103
|
-
anchorFragment.detach = anchorFragment.remove;
|
|
1609
|
+
anchorFragment.clear = anchorFragment.remove;
|
|
1610
|
+
anchorFragment.detach = anchorFragment.remove;
|
|
1611
|
+
|
|
1612
|
+
anchorFragment.getByIndex = function(index) {
|
|
1613
|
+
let currentNode = anchorStart;
|
|
1614
|
+
for(let i = 0; i <= index; i++) {
|
|
1615
|
+
if(!currentNode.nextSibling) {
|
|
1616
|
+
return null;
|
|
1617
|
+
}
|
|
1618
|
+
currentNode = currentNode.nextSibling;
|
|
1619
|
+
}
|
|
1620
|
+
return currentNode !== anchorStart ? currentNode : null;
|
|
1621
|
+
};
|
|
1622
|
+
|
|
1623
|
+
return anchorFragment;
|
|
1624
|
+
}
|
|
1625
|
+
/**
|
|
1626
|
+
*
|
|
1627
|
+
* @param {HTMLElement|DocumentFragment|Text|String|Array} children
|
|
1628
|
+
* @param {{ parent?: HTMLElement, name?: String}} configs
|
|
1629
|
+
* @returns {DocumentFragment}
|
|
1630
|
+
*/
|
|
1631
|
+
function createPortal(children, { parent, name = 'unnamed' } = {}) {
|
|
1632
|
+
const anchor = Anchor('Portal '+name);
|
|
1633
|
+
anchor.appendChild(ElementCreator.getChild(children));
|
|
1634
|
+
|
|
1635
|
+
(parent || document.body).appendChild(anchor);
|
|
1636
|
+
return anchor;
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
DocumentFragment.prototype.setAttribute = () => {};
|
|
1640
|
+
|
|
1641
|
+
const DocumentObserver = {
|
|
1642
|
+
mounted: new WeakMap(),
|
|
1643
|
+
beforeUnmount: new WeakMap(),
|
|
1644
|
+
mountedSupposedSize: 0,
|
|
1645
|
+
unmounted: new WeakMap(),
|
|
1646
|
+
unmountedSupposedSize: 0,
|
|
1647
|
+
observer: null,
|
|
1648
|
+
initObserver: () => {
|
|
1649
|
+
if(DocumentObserver.observer) {
|
|
1650
|
+
return;
|
|
1651
|
+
}
|
|
1652
|
+
DocumentObserver.observer = new MutationObserver(DocumentObserver.checkMutation);
|
|
1653
|
+
DocumentObserver.observer.observe(document.body, {
|
|
1654
|
+
childList: true,
|
|
1655
|
+
subtree: true,
|
|
1656
|
+
});
|
|
1657
|
+
},
|
|
1658
|
+
|
|
1659
|
+
executeMountedCallback(node) {
|
|
1660
|
+
const data = DocumentObserver.mounted.get(node);
|
|
1661
|
+
if(!data) {
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1664
|
+
data.inDom = true;
|
|
1665
|
+
if(!data.mounted) {
|
|
1666
|
+
return;
|
|
1667
|
+
}
|
|
1668
|
+
if(Array.isArray(data.mounted)) {
|
|
1669
|
+
for(const cb of data.mounted) {
|
|
1670
|
+
cb(node);
|
|
1671
|
+
}
|
|
1672
|
+
return;
|
|
1673
|
+
}
|
|
1674
|
+
data.mounted(node);
|
|
1675
|
+
},
|
|
1676
|
+
|
|
1677
|
+
executeUnmountedCallback(node) {
|
|
1678
|
+
const data = DocumentObserver.unmounted.get(node);
|
|
1679
|
+
if(!data) {
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
data.inDom = false;
|
|
1683
|
+
if(!data.unmounted) {
|
|
1684
|
+
return;
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
let shouldRemove = false;
|
|
1688
|
+
if(Array.isArray(data.unmounted)) {
|
|
1689
|
+
for(const cb of data.unmounted) {
|
|
1690
|
+
if(cb(node) === true) {
|
|
1691
|
+
shouldRemove = true;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
} else {
|
|
1695
|
+
shouldRemove = data.unmounted(node) === true;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
if(shouldRemove) {
|
|
1699
|
+
data.disconnect();
|
|
1700
|
+
node.nd?.remove();
|
|
1701
|
+
}
|
|
1702
|
+
},
|
|
1703
|
+
|
|
1704
|
+
checkMutation: function(mutationsList) {
|
|
1705
|
+
for(const mutation of mutationsList) {
|
|
1706
|
+
if(DocumentObserver.mountedSupposedSize > 0) {
|
|
1707
|
+
for(const node of mutation.addedNodes) {
|
|
1708
|
+
DocumentObserver.executeMountedCallback(node);
|
|
1709
|
+
if(!node.querySelectorAll) {
|
|
1710
|
+
continue;
|
|
1711
|
+
}
|
|
1712
|
+
const children = node.querySelectorAll('[data--nd-mounted]');
|
|
1713
|
+
for(const child of children) {
|
|
1714
|
+
DocumentObserver.executeMountedCallback(child);
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
if (DocumentObserver.unmountedSupposedSize > 0) {
|
|
1720
|
+
for (const node of mutation.removedNodes) {
|
|
1721
|
+
DocumentObserver.executeUnmountedCallback(node);
|
|
1722
|
+
if(!node.querySelectorAll) {
|
|
1723
|
+
continue;
|
|
1724
|
+
}
|
|
1725
|
+
const children = node.querySelectorAll('[data--nd-unmounted]');
|
|
1726
|
+
for(const child of children) {
|
|
1727
|
+
DocumentObserver.executeUnmountedCallback(child);
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
},
|
|
1733
|
+
|
|
1734
|
+
/**
|
|
1735
|
+
* @param {HTMLElement} element
|
|
1736
|
+
* @param {boolean} inDom
|
|
1737
|
+
* @returns {{ disconnect: Function, mounted: Function, unmounted: Function, off: Function }}
|
|
1738
|
+
*/
|
|
1739
|
+
watch: function(element, inDom = false) {
|
|
1740
|
+
let mountedRegistered = false;
|
|
1741
|
+
let unmountedRegistered = false;
|
|
1742
|
+
|
|
1743
|
+
DocumentObserver.initObserver();
|
|
1744
|
+
|
|
1745
|
+
let data = {
|
|
1746
|
+
inDom,
|
|
1747
|
+
mounted: null,
|
|
1748
|
+
unmounted: null,
|
|
1749
|
+
disconnect: () => {
|
|
1750
|
+
if (mountedRegistered) {
|
|
1751
|
+
DocumentObserver.mounted.delete(element);
|
|
1752
|
+
DocumentObserver.mountedSupposedSize--;
|
|
1753
|
+
}
|
|
1754
|
+
if (unmountedRegistered) {
|
|
1755
|
+
DocumentObserver.unmounted.delete(element);
|
|
1756
|
+
DocumentObserver.unmountedSupposedSize--;
|
|
1757
|
+
}
|
|
1758
|
+
data = null;
|
|
1759
|
+
}
|
|
1760
|
+
};
|
|
1761
|
+
|
|
1762
|
+
const addListener = (type, callback) => {
|
|
1763
|
+
if (!data[type]) {
|
|
1764
|
+
data[type] = callback;
|
|
1765
|
+
return;
|
|
1766
|
+
}
|
|
1767
|
+
if (!Array.isArray(data[type])) {
|
|
1768
|
+
data[type] = [data[type], callback];
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
data[type].push(callback);
|
|
1772
|
+
};
|
|
2104
1773
|
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
if(!currentNode.nextSibling) {
|
|
2109
|
-
return null;
|
|
1774
|
+
const removeListener = (type, callback) => {
|
|
1775
|
+
if(!data?.[type]) {
|
|
1776
|
+
return;
|
|
2110
1777
|
}
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
1778
|
+
if(Array.isArray(data[type])) {
|
|
1779
|
+
const index = data[type].indexOf(callback);
|
|
1780
|
+
if(index > -1) {
|
|
1781
|
+
data[type].splice(index, 1);
|
|
1782
|
+
}
|
|
1783
|
+
if(data[type].length === 1) {
|
|
1784
|
+
data[type] = data[type][0];
|
|
1785
|
+
}
|
|
1786
|
+
if(data[type].length === 0) {
|
|
1787
|
+
data[type] = null;
|
|
1788
|
+
}
|
|
1789
|
+
return;
|
|
1790
|
+
}
|
|
1791
|
+
data[type] = null;
|
|
1792
|
+
};
|
|
2115
1793
|
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
/**
|
|
2119
|
-
*
|
|
2120
|
-
* @param {HTMLElement|DocumentFragment|Text|String|Array} children
|
|
2121
|
-
* @param {{ parent?: HTMLElement, name?: String}} configs
|
|
2122
|
-
* @returns {DocumentFragment}
|
|
2123
|
-
*/
|
|
2124
|
-
function createPortal(children, { parent, name = 'unnamed' } = {}) {
|
|
2125
|
-
const anchor = Anchor('Portal '+name);
|
|
2126
|
-
anchor.appendChild(ElementCreator.getChild(children));
|
|
1794
|
+
return {
|
|
1795
|
+
disconnect: () => data?.disconnect(),
|
|
2127
1796
|
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
1797
|
+
mounted: (callback) => {
|
|
1798
|
+
addListener('mounted', callback);
|
|
1799
|
+
DocumentObserver.mounted.set(element, data);
|
|
1800
|
+
if (!mountedRegistered) {
|
|
1801
|
+
DocumentObserver.mountedSupposedSize++;
|
|
1802
|
+
mountedRegistered = true;
|
|
1803
|
+
}
|
|
1804
|
+
},
|
|
2131
1805
|
|
|
2132
|
-
|
|
1806
|
+
unmounted: (callback) => {
|
|
1807
|
+
addListener('unmounted', callback);
|
|
1808
|
+
DocumentObserver.unmounted.set(element, data);
|
|
1809
|
+
if (!unmountedRegistered) {
|
|
1810
|
+
DocumentObserver.unmountedSupposedSize++;
|
|
1811
|
+
unmountedRegistered = true;
|
|
1812
|
+
}
|
|
1813
|
+
},
|
|
1814
|
+
|
|
1815
|
+
off: (type, callback) => {
|
|
1816
|
+
removeListener(type, callback);
|
|
1817
|
+
}
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
};
|
|
2133
1821
|
|
|
2134
1822
|
function NDElement(element) {
|
|
2135
1823
|
this.$element = element;
|
|
@@ -2141,11 +1829,13 @@ var NativeDocument = (function (exports) {
|
|
|
2141
1829
|
|
|
2142
1830
|
NDElement.prototype.__$isNDElement = true;
|
|
2143
1831
|
|
|
1832
|
+
NDElement.$getChild = (el) => el;
|
|
1833
|
+
|
|
2144
1834
|
NDElement.prototype.ghostDom = function(element) {
|
|
2145
1835
|
if(!this.$attachements) {
|
|
2146
1836
|
this.$attachements = document.createDocumentFragment();
|
|
2147
1837
|
}
|
|
2148
|
-
this.$attachements.appendChild(
|
|
1838
|
+
this.$attachements.appendChild(NDElement.$getChild(element));
|
|
2149
1839
|
return this;
|
|
2150
1840
|
};
|
|
2151
1841
|
|
|
@@ -2343,197 +2033,45 @@ var NativeDocument = (function (exports) {
|
|
|
2343
2033
|
throw new NativeDocumentError('NDElement.extend() requires an object of methods');
|
|
2344
2034
|
}
|
|
2345
2035
|
|
|
2346
|
-
if (Array.isArray(methods)) {
|
|
2347
|
-
throw new NativeDocumentError('NDElement.extend() requires an object, not an array');
|
|
2348
|
-
}
|
|
2349
|
-
|
|
2350
|
-
const protectedMethods = new Set([
|
|
2351
|
-
'constructor', 'valueOf', '$element', '$observer',
|
|
2352
|
-
'ref', 'remove', 'cleanup', 'with', 'extend', 'attach',
|
|
2353
|
-
'lifecycle', 'mounted', 'unmounted', 'unmountChildren'
|
|
2354
|
-
]);
|
|
2355
|
-
|
|
2356
|
-
for (const name in methods) {
|
|
2357
|
-
if (!Object.hasOwn(methods, name)) {
|
|
2358
|
-
continue;
|
|
2359
|
-
}
|
|
2360
|
-
|
|
2361
|
-
const method = methods[name];
|
|
2362
|
-
|
|
2363
|
-
if (typeof method !== 'function') {
|
|
2364
|
-
DebugManager$2.warn('NDElement.extend', `"${name}" is not a function, skipping`);
|
|
2365
|
-
continue;
|
|
2366
|
-
}
|
|
2367
|
-
|
|
2368
|
-
if (protectedMethods.has(name)) {
|
|
2369
|
-
DebugManager$2.error('NDElement.extend', `Cannot override protected method "${name}"`);
|
|
2370
|
-
throw new NativeDocumentError(`Cannot override protected method "${name}"`);
|
|
2371
|
-
}
|
|
2372
|
-
|
|
2373
|
-
if (NDElement.prototype[name]) {
|
|
2374
|
-
DebugManager$2.warn('NDElement.extend', `Overwriting existing prototype method "${name}"`);
|
|
2375
|
-
}
|
|
2376
|
-
|
|
2377
|
-
NDElement.prototype[name] = method;
|
|
2378
|
-
}
|
|
2379
|
-
{
|
|
2380
|
-
PluginsManager$1.emit('NDElementExtended', methods);
|
|
2381
|
-
}
|
|
2382
|
-
|
|
2383
|
-
return NDElement;
|
|
2384
|
-
};
|
|
2385
|
-
|
|
2386
|
-
const COMMON_NODE_TYPES = {
|
|
2387
|
-
ELEMENT: 1,
|
|
2388
|
-
TEXT: 3,
|
|
2389
|
-
COMMENT: 8,
|
|
2390
|
-
DOCUMENT_FRAGMENT: 11
|
|
2391
|
-
};
|
|
2392
|
-
|
|
2393
|
-
const VALID_TYPES = [];
|
|
2394
|
-
VALID_TYPES[COMMON_NODE_TYPES.ELEMENT] = true;
|
|
2395
|
-
VALID_TYPES[COMMON_NODE_TYPES.TEXT] = true;
|
|
2396
|
-
VALID_TYPES[COMMON_NODE_TYPES.DOCUMENT_FRAGMENT] = true;
|
|
2397
|
-
VALID_TYPES[COMMON_NODE_TYPES.COMMENT] = true;
|
|
2398
|
-
|
|
2399
|
-
const Validator = {
|
|
2400
|
-
isObservable(value) {
|
|
2401
|
-
return value && (value.__$isObservable || value.__$Observable);
|
|
2402
|
-
},
|
|
2403
|
-
isTemplateBinding(value) {
|
|
2404
|
-
return value?.__$isTemplateBinding;
|
|
2405
|
-
},
|
|
2406
|
-
isObservableWhenResult(value) {
|
|
2407
|
-
return value && (value.__$isObservableWhen || (typeof value === 'object' && '$target' in value && '$observer' in value));
|
|
2408
|
-
},
|
|
2409
|
-
isArrayObservable(value) {
|
|
2410
|
-
return value?.__$isObservableArray;
|
|
2411
|
-
},
|
|
2412
|
-
isProxy(value) {
|
|
2413
|
-
return value?.__isProxy__
|
|
2414
|
-
},
|
|
2415
|
-
isObservableOrProxy(value) {
|
|
2416
|
-
return Validator.isObservable(value) || Validator.isProxy(value);
|
|
2417
|
-
},
|
|
2418
|
-
isAnchor(value) {
|
|
2419
|
-
return value?.__Anchor__
|
|
2420
|
-
},
|
|
2421
|
-
isObservableChecker(value) {
|
|
2422
|
-
return value?.__$isObservableChecker || value instanceof ObservableChecker;
|
|
2423
|
-
},
|
|
2424
|
-
isArray(value) {
|
|
2425
|
-
return Array.isArray(value);
|
|
2426
|
-
},
|
|
2427
|
-
isString(value) {
|
|
2428
|
-
return typeof value === 'string';
|
|
2429
|
-
},
|
|
2430
|
-
isNumber(value) {
|
|
2431
|
-
return typeof value === 'number';
|
|
2432
|
-
},
|
|
2433
|
-
isBoolean(value) {
|
|
2434
|
-
return typeof value === 'boolean';
|
|
2435
|
-
},
|
|
2436
|
-
isFunction(value) {
|
|
2437
|
-
return typeof value === 'function';
|
|
2438
|
-
},
|
|
2439
|
-
isAsyncFunction(value) {
|
|
2440
|
-
return typeof value === 'function' && value.constructor.name === 'AsyncFunction';
|
|
2441
|
-
},
|
|
2442
|
-
isObject(value) {
|
|
2443
|
-
return typeof value === 'object' && value !== null;
|
|
2444
|
-
},
|
|
2445
|
-
isJson(value) {
|
|
2446
|
-
return !(typeof value !== 'object' || value === null || Array.isArray(value) || value.constructor.name !== 'Object')
|
|
2447
|
-
},
|
|
2448
|
-
isElement(value) {
|
|
2449
|
-
return value && VALID_TYPES[value.nodeType];
|
|
2450
|
-
},
|
|
2451
|
-
isDOMNode(value) {
|
|
2452
|
-
return VALID_TYPES[value.nodeType];
|
|
2453
|
-
},
|
|
2454
|
-
isFragment(value) {
|
|
2455
|
-
return value?.nodeType === COMMON_NODE_TYPES.DOCUMENT_FRAGMENT;
|
|
2456
|
-
},
|
|
2457
|
-
isStringOrObservable(value) {
|
|
2458
|
-
return this.isString(value) || this.isObservable(value);
|
|
2459
|
-
},
|
|
2460
|
-
isValidChild(child) {
|
|
2461
|
-
return child === null ||
|
|
2462
|
-
this.isElement(child) ||
|
|
2463
|
-
this.isObservable(child) ||
|
|
2464
|
-
this.isNDElement(child) ||
|
|
2465
|
-
['string', 'number', 'boolean'].includes(typeof child);
|
|
2466
|
-
},
|
|
2467
|
-
isNDElement(child) {
|
|
2468
|
-
return child?.__$isNDElement || child instanceof NDElement;
|
|
2469
|
-
},
|
|
2470
|
-
isValidChildren(children) {
|
|
2471
|
-
if (!Array.isArray(children)) {
|
|
2472
|
-
children = [children];
|
|
2473
|
-
}
|
|
2474
|
-
|
|
2475
|
-
const invalid = children.filter(child => !this.isValidChild(child));
|
|
2476
|
-
return invalid.length === 0;
|
|
2477
|
-
},
|
|
2478
|
-
validateChildren(children) {
|
|
2479
|
-
if (!Array.isArray(children)) {
|
|
2480
|
-
children = [children];
|
|
2481
|
-
}
|
|
2482
|
-
|
|
2483
|
-
const invalid = children.filter(child => !this.isValidChild(child));
|
|
2484
|
-
if (invalid.length > 0) {
|
|
2485
|
-
throw new NativeDocumentError(`Invalid children detected: ${invalid.map(i => typeof i).join(', ')}`);
|
|
2486
|
-
}
|
|
2487
|
-
|
|
2488
|
-
return children;
|
|
2489
|
-
},
|
|
2490
|
-
/**
|
|
2491
|
-
* Check if the data contains observables.
|
|
2492
|
-
* @param {Array|Object} data
|
|
2493
|
-
* @returns {boolean}
|
|
2494
|
-
*/
|
|
2495
|
-
containsObservables(data) {
|
|
2496
|
-
if(!data) {
|
|
2497
|
-
return false;
|
|
2498
|
-
}
|
|
2499
|
-
return Validator.isObject(data)
|
|
2500
|
-
&& Object.values(data).some(value => Validator.isObservable(value));
|
|
2501
|
-
},
|
|
2502
|
-
/**
|
|
2503
|
-
* Check if the data contains an observable reference.
|
|
2504
|
-
* @param {string} data
|
|
2505
|
-
* @returns {boolean}
|
|
2506
|
-
*/
|
|
2507
|
-
containsObservableReference(data) {
|
|
2508
|
-
if(!data || typeof data !== 'string') {
|
|
2509
|
-
return false;
|
|
2510
|
-
}
|
|
2511
|
-
return /\{\{#ObItem::\([0-9]+\)\}\}/.test(data);
|
|
2512
|
-
},
|
|
2513
|
-
validateAttributes(attributes) {},
|
|
2036
|
+
if (Array.isArray(methods)) {
|
|
2037
|
+
throw new NativeDocumentError('NDElement.extend() requires an object, not an array');
|
|
2038
|
+
}
|
|
2514
2039
|
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2040
|
+
const protectedMethods = new Set([
|
|
2041
|
+
'constructor', 'valueOf', '$element', '$observer',
|
|
2042
|
+
'ref', 'remove', 'cleanup', 'with', 'extend', 'attach',
|
|
2043
|
+
'lifecycle', 'mounted', 'unmounted', 'unmountChildren'
|
|
2044
|
+
]);
|
|
2045
|
+
|
|
2046
|
+
for (const name in methods) {
|
|
2047
|
+
if (!Object.hasOwn(methods, name)) {
|
|
2048
|
+
continue;
|
|
2518
2049
|
}
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2050
|
+
|
|
2051
|
+
const method = methods[name];
|
|
2052
|
+
|
|
2053
|
+
if (typeof method !== 'function') {
|
|
2054
|
+
DebugManager$2.warn('NDElement.extend', `"${name}" is not a function, skipping`);
|
|
2055
|
+
continue;
|
|
2525
2056
|
}
|
|
2526
2057
|
|
|
2527
|
-
|
|
2528
|
-
|
|
2058
|
+
if (protectedMethods.has(name)) {
|
|
2059
|
+
DebugManager$2.error('NDElement.extend', `Cannot override protected method "${name}"`);
|
|
2060
|
+
throw new NativeDocumentError(`Cannot override protected method "${name}"`);
|
|
2061
|
+
}
|
|
2529
2062
|
|
|
2530
|
-
if (
|
|
2531
|
-
DebugManager$2.warn('
|
|
2063
|
+
if (NDElement.prototype[name]) {
|
|
2064
|
+
DebugManager$2.warn('NDElement.extend', `Overwriting existing prototype method "${name}"`);
|
|
2532
2065
|
}
|
|
2533
2066
|
|
|
2534
|
-
|
|
2535
|
-
}
|
|
2536
|
-
|
|
2067
|
+
NDElement.prototype[name] = method;
|
|
2068
|
+
}
|
|
2069
|
+
{
|
|
2070
|
+
PluginsManager$1.emit('NDElementExtended', methods);
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
return NDElement;
|
|
2074
|
+
};
|
|
2537
2075
|
|
|
2538
2076
|
const EVENTS = [
|
|
2539
2077
|
"Click",
|
|
@@ -3006,6 +2544,12 @@ var NativeDocument = (function (exports) {
|
|
|
3006
2544
|
};
|
|
3007
2545
|
}
|
|
3008
2546
|
|
|
2547
|
+
function TemplateBinding(hydrate) {
|
|
2548
|
+
this.$hydrate = hydrate;
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
TemplateBinding.prototype.__$isTemplateBinding = true;
|
|
2552
|
+
|
|
3009
2553
|
function NodeCloner($element) {
|
|
3010
2554
|
this.$element = $element;
|
|
3011
2555
|
this.$classes = null;
|
|
@@ -3361,6 +2905,209 @@ var NativeDocument = (function (exports) {
|
|
|
3361
2905
|
return handler;
|
|
3362
2906
|
};
|
|
3363
2907
|
|
|
2908
|
+
/**
|
|
2909
|
+
*
|
|
2910
|
+
* @param {ObservableItem} $observable
|
|
2911
|
+
* @param {Function} $checker
|
|
2912
|
+
* @class ObservableChecker
|
|
2913
|
+
*/
|
|
2914
|
+
function ObservableChecker($observable, $checker) {
|
|
2915
|
+
this.observable = $observable;
|
|
2916
|
+
|
|
2917
|
+
ObservableItem.call(this);
|
|
2918
|
+
{
|
|
2919
|
+
PluginsManager$1.emit('CreateObservableChecker', this);
|
|
2920
|
+
}
|
|
2921
|
+
|
|
2922
|
+
this.$mutation = $checker;
|
|
2923
|
+
|
|
2924
|
+
$observable.subscribe((newValue) => {
|
|
2925
|
+
this.$updateWithMutation(newValue);
|
|
2926
|
+
});
|
|
2927
|
+
|
|
2928
|
+
this.$updateWithMutation($observable.val());
|
|
2929
|
+
}
|
|
2930
|
+
|
|
2931
|
+
ObservableChecker.prototype = Object.create(ObservableItem.prototype);
|
|
2932
|
+
ObservableChecker.prototype.constructor = ObservableChecker;
|
|
2933
|
+
ObservableChecker.prototype.__$Observable = true;
|
|
2934
|
+
ObservableChecker.prototype.__$isObservableChecker = true;
|
|
2935
|
+
|
|
2936
|
+
|
|
2937
|
+
const ObservablePipe = ObservableChecker;
|
|
2938
|
+
ObservablePipe.prototype.constructor = ObservablePipe;
|
|
2939
|
+
|
|
2940
|
+
ObservableChecker.prototype.$updateWithMutation = function(newValue) {
|
|
2941
|
+
newValue = this.$mutation(newValue);
|
|
2942
|
+
return this.set(newValue);
|
|
2943
|
+
};
|
|
2944
|
+
|
|
2945
|
+
NDElement.$getChild = ElementCreator.getChild;
|
|
2946
|
+
|
|
2947
|
+
String.prototype.toNdElement = function () {
|
|
2948
|
+
return ElementCreator.createStaticTextNode(null, this);
|
|
2949
|
+
};
|
|
2950
|
+
|
|
2951
|
+
Number.prototype.toNdElement = function () {
|
|
2952
|
+
return ElementCreator.createStaticTextNode(null, this.toString());
|
|
2953
|
+
};
|
|
2954
|
+
|
|
2955
|
+
Element.prototype.toNdElement = function () {
|
|
2956
|
+
return this;
|
|
2957
|
+
};
|
|
2958
|
+
Text.prototype.toNdElement = function () {
|
|
2959
|
+
return this;
|
|
2960
|
+
};
|
|
2961
|
+
Comment.prototype.toNdElement = function () {
|
|
2962
|
+
return this;
|
|
2963
|
+
};
|
|
2964
|
+
Document.prototype.toNdElement = function () {
|
|
2965
|
+
return this;
|
|
2966
|
+
};
|
|
2967
|
+
DocumentFragment.prototype.toNdElement = function () {
|
|
2968
|
+
return this;
|
|
2969
|
+
};
|
|
2970
|
+
|
|
2971
|
+
ObservableItem.prototype.toNdElement = function () {
|
|
2972
|
+
return ElementCreator.createObservableNode(null, this);
|
|
2973
|
+
};
|
|
2974
|
+
|
|
2975
|
+
ObservableChecker.prototype.toNdElement = ObservableItem.prototype.toNdElement;
|
|
2976
|
+
|
|
2977
|
+
NDElement.prototype.toNdElement = function () {
|
|
2978
|
+
const element = this.$element ?? this.$build?.() ?? this.build?.() ?? null;
|
|
2979
|
+
if(this.$attachements) {
|
|
2980
|
+
if(!this.$attachements.contains(this.$element)) {
|
|
2981
|
+
this.$attachements.append(this.$element);
|
|
2982
|
+
}
|
|
2983
|
+
return this.$attachements;
|
|
2984
|
+
}
|
|
2985
|
+
return element;
|
|
2986
|
+
};
|
|
2987
|
+
|
|
2988
|
+
Array.prototype.toNdElement = function () {
|
|
2989
|
+
const fragment = document.createDocumentFragment();
|
|
2990
|
+
for(let i = 0, length = this.length; i < length; i++) {
|
|
2991
|
+
const child = ElementCreator.getChild(this[i]);
|
|
2992
|
+
if(child === null) continue;
|
|
2993
|
+
fragment.appendChild(child);
|
|
2994
|
+
}
|
|
2995
|
+
return fragment;
|
|
2996
|
+
};
|
|
2997
|
+
|
|
2998
|
+
Function.prototype.toNdElement = function () {
|
|
2999
|
+
const child = this;
|
|
3000
|
+
{
|
|
3001
|
+
PluginsManager$1.emit('BeforeProcessComponent', child);
|
|
3002
|
+
}
|
|
3003
|
+
return ElementCreator.getChild(child());
|
|
3004
|
+
};
|
|
3005
|
+
|
|
3006
|
+
TemplateBinding.prototype.toNdElement = function () {
|
|
3007
|
+
return ElementCreator.createHydratableNode(null, this);
|
|
3008
|
+
};
|
|
3009
|
+
|
|
3010
|
+
/**
|
|
3011
|
+
* @param {HTMLElement} el
|
|
3012
|
+
* @param {number} timeout
|
|
3013
|
+
*/
|
|
3014
|
+
const waitForVisualEnd = (el, timeout = 1000) => {
|
|
3015
|
+
return new Promise((resolve) => {
|
|
3016
|
+
let isResolved = false;
|
|
3017
|
+
|
|
3018
|
+
const cleanupAndResolve = (e) => {
|
|
3019
|
+
if (e && e.target !== el) return;
|
|
3020
|
+
if (isResolved) return;
|
|
3021
|
+
|
|
3022
|
+
isResolved = true;
|
|
3023
|
+
el.removeEventListener('transitionend', cleanupAndResolve);
|
|
3024
|
+
el.removeEventListener('animationend', cleanupAndResolve);
|
|
3025
|
+
clearTimeout(timer);
|
|
3026
|
+
resolve();
|
|
3027
|
+
};
|
|
3028
|
+
|
|
3029
|
+
el.addEventListener('transitionend', cleanupAndResolve);
|
|
3030
|
+
el.addEventListener('animationend', cleanupAndResolve);
|
|
3031
|
+
|
|
3032
|
+
const timer = setTimeout(cleanupAndResolve, timeout);
|
|
3033
|
+
|
|
3034
|
+
const style = window.getComputedStyle(el);
|
|
3035
|
+
const hasTransition = style.transitionDuration !== '0s';
|
|
3036
|
+
const hasAnimation = style.animationDuration !== '0s';
|
|
3037
|
+
|
|
3038
|
+
if (!hasTransition && !hasAnimation) {
|
|
3039
|
+
cleanupAndResolve();
|
|
3040
|
+
}
|
|
3041
|
+
});
|
|
3042
|
+
};
|
|
3043
|
+
|
|
3044
|
+
NDElement.prototype.transitionOut = function(transitionName) {
|
|
3045
|
+
const exitClass = transitionName + '-exit';
|
|
3046
|
+
const el = this.$element;
|
|
3047
|
+
this.beforeUnmount('transition-exit', async function() {
|
|
3048
|
+
el.classes.add(exitClass);
|
|
3049
|
+
await waitForVisualEnd(el);
|
|
3050
|
+
el.classes.remove(exitClass);
|
|
3051
|
+
});
|
|
3052
|
+
return this;
|
|
3053
|
+
};
|
|
3054
|
+
|
|
3055
|
+
NDElement.prototype.transitionIn = function(transitionName) {
|
|
3056
|
+
const startClass = transitionName + '-enter-from';
|
|
3057
|
+
const endClass = transitionName + '-enter-to';
|
|
3058
|
+
|
|
3059
|
+
const el = this.$element;
|
|
3060
|
+
|
|
3061
|
+
el.classes.add(startClass);
|
|
3062
|
+
|
|
3063
|
+
this.mounted(() => {
|
|
3064
|
+
requestAnimationFrame(() => {
|
|
3065
|
+
requestAnimationFrame(() => {
|
|
3066
|
+
el.classes.remove(startClass);
|
|
3067
|
+
el.classes.add(endClass);
|
|
3068
|
+
|
|
3069
|
+
waitForVisualEnd(el).then(() => {
|
|
3070
|
+
el.classes.remove(endClass);
|
|
3071
|
+
});
|
|
3072
|
+
});
|
|
3073
|
+
});
|
|
3074
|
+
});
|
|
3075
|
+
return this;
|
|
3076
|
+
};
|
|
3077
|
+
|
|
3078
|
+
|
|
3079
|
+
NDElement.prototype.transition = function (transitionName) {
|
|
3080
|
+
this.transitionIn(transitionName);
|
|
3081
|
+
this.transitionOut(transitionName);
|
|
3082
|
+
return this;
|
|
3083
|
+
};
|
|
3084
|
+
|
|
3085
|
+
NDElement.prototype.animate = function(animationName) {
|
|
3086
|
+
const el = this.$element;
|
|
3087
|
+
el.classes.add(animationName);
|
|
3088
|
+
|
|
3089
|
+
waitForVisualEnd(el).then(() => {
|
|
3090
|
+
el.classes.remove(animationName);
|
|
3091
|
+
});
|
|
3092
|
+
|
|
3093
|
+
return this;
|
|
3094
|
+
};
|
|
3095
|
+
|
|
3096
|
+
ObservableItem.prototype.handleNdAttribute = function(element, attributeName) {
|
|
3097
|
+
if(BOOLEAN_ATTRIBUTES.has(attributeName)) {
|
|
3098
|
+
bindBooleanAttribute(element, attributeName, this);
|
|
3099
|
+
return;
|
|
3100
|
+
}
|
|
3101
|
+
|
|
3102
|
+
bindAttributeWithObservable(element, attributeName, this);
|
|
3103
|
+
};
|
|
3104
|
+
|
|
3105
|
+
ObservableChecker.prototype.handleNdAttribute = ObservableItem.prototype.handleNdAttribute;
|
|
3106
|
+
|
|
3107
|
+
TemplateBinding.prototype.handleNdAttribute = function(element, attributeName) {
|
|
3108
|
+
this.$hydrate(element, attributeName);
|
|
3109
|
+
};
|
|
3110
|
+
|
|
3364
3111
|
const cssPropertyAccumulator = function(initialValue = {}) {
|
|
3365
3112
|
let data = Validator.isString(initialValue) ? initialValue.split(';').filter(Boolean) : initialValue;
|
|
3366
3113
|
|