native-document 1.0.53 → 1.0.54
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.dev.js +337 -86
- package/dist/native-document.dev.js.map +1 -1
- package/dist/native-document.devtools.min.js +1 -1
- package/dist/native-document.min.js +1 -1
- package/index.js +2 -1
- package/package.json +1 -1
- package/src/data/Observable.js +3 -2
- package/src/data/ObservableArray.js +8 -2
- package/src/data/ObservableItem.js +23 -1
- package/src/data/observable-helpers/array.js +3 -2
- package/src/data/observable-helpers/object.js +31 -43
- package/src/elements/control/switch.js +13 -2
- package/src/utils/helpers.js +33 -1
- package/src/utils/validator.js +1 -1
- package/src/wrappers/NDElement.js +83 -1
- package/src/wrappers/NdPrototype.js +12 -2
- package/types/memoize.d.ts +16 -6
- package/types/nd-element.d.ts +245 -231
- package/types/observable.d.ts +24 -5
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import Validator from "../../utils/validator";
|
|
2
2
|
import {Observable} from "../Observable";
|
|
3
|
-
import ObservableItem from "../ObservableItem";
|
|
4
|
-
|
|
5
|
-
|
|
6
3
|
|
|
7
4
|
const ObservableObjectValue = function(data) {
|
|
8
5
|
const result = {};
|
|
@@ -45,40 +42,47 @@ const ObservableGet = function(target, property) {
|
|
|
45
42
|
/**
|
|
46
43
|
*
|
|
47
44
|
* @param {Object} initialValue
|
|
48
|
-
* @param {{propagation: boolean, deep: boolean}} configs
|
|
45
|
+
* @param {{propagation: boolean, deep: boolean, reset: boolean}|null} configs
|
|
49
46
|
* @returns {Proxy}
|
|
50
47
|
*/
|
|
51
|
-
Observable.init = function(initialValue,
|
|
48
|
+
Observable.init = function(initialValue, configs = null) {
|
|
52
49
|
const data = {};
|
|
53
50
|
for(const key in initialValue) {
|
|
54
51
|
const itemValue = initialValue[key];
|
|
55
52
|
if(Array.isArray(itemValue)) {
|
|
56
|
-
if(deep) {
|
|
53
|
+
if(configs?.deep !== false) {
|
|
57
54
|
const mappedItemValue = itemValue.map(item => {
|
|
58
55
|
if(Validator.isJson(item)) {
|
|
59
|
-
return Observable.json(item,
|
|
56
|
+
return Observable.json(item, configs);
|
|
60
57
|
}
|
|
61
58
|
if(Validator.isArray(item)) {
|
|
62
|
-
return Observable.array(item,
|
|
59
|
+
return Observable.array(item, configs);
|
|
63
60
|
}
|
|
64
|
-
return Observable(item);
|
|
61
|
+
return Observable(item, configs);
|
|
65
62
|
});
|
|
66
|
-
data[key] = Observable.array(mappedItemValue,
|
|
63
|
+
data[key] = Observable.array(mappedItemValue, configs);
|
|
67
64
|
continue;
|
|
68
65
|
}
|
|
69
|
-
data[key] = Observable.array(itemValue,
|
|
66
|
+
data[key] = Observable.array(itemValue, configs);
|
|
70
67
|
continue;
|
|
71
68
|
}
|
|
72
69
|
if(Validator.isObservable(itemValue) || Validator.isProxy(itemValue)) {
|
|
73
70
|
data[key] = itemValue;
|
|
74
71
|
continue;
|
|
75
72
|
}
|
|
76
|
-
data[key] = Observable(itemValue);
|
|
73
|
+
data[key] = Observable(itemValue, configs);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const $reset = () => {
|
|
77
|
+
for(const key in data) {
|
|
78
|
+
const item = data[key];
|
|
79
|
+
item.reset();
|
|
80
|
+
}
|
|
77
81
|
}
|
|
78
82
|
|
|
79
83
|
const $val = () => ObservableObjectValue(data);
|
|
80
84
|
|
|
81
|
-
const $clone = () => Observable.init($val(),
|
|
85
|
+
const $clone = () => Observable.init($val(), configs);
|
|
82
86
|
|
|
83
87
|
const $updateWith = (values) => {
|
|
84
88
|
Observable.update(proxy, values);
|
|
@@ -88,34 +92,17 @@ Observable.init = function(initialValue, { propagation= false, deep = true } = {
|
|
|
88
92
|
|
|
89
93
|
const proxy = new Proxy(data, {
|
|
90
94
|
get(target, property) {
|
|
91
|
-
if(property === '__isProxy__') {
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
if(property === '$
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
if(property === '$
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
if(property === '
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
if(property === '$observables') {
|
|
104
|
-
return Object.values(target);
|
|
105
|
-
}
|
|
106
|
-
if(property === '$set' || property === '$updateWith') {
|
|
107
|
-
return $updateWith;
|
|
108
|
-
}
|
|
109
|
-
if(property === '$get') {
|
|
110
|
-
return $get;
|
|
111
|
-
}
|
|
112
|
-
if(property === '$val') {
|
|
113
|
-
return $val;
|
|
114
|
-
}
|
|
115
|
-
if(target[property] !== undefined) {
|
|
116
|
-
return target[property];
|
|
117
|
-
}
|
|
118
|
-
return undefined;
|
|
95
|
+
if(property === '__isProxy__') { return true; }
|
|
96
|
+
if(property === '$value') { return $val() }
|
|
97
|
+
if(property === 'get' || property === '$get') { return $get; }
|
|
98
|
+
if(property === 'val' || property === '$val') { return $val; }
|
|
99
|
+
if(property === 'set' || property === '$set' || property === '$updateWith') { return $updateWith; }
|
|
100
|
+
if(property === 'observables' || property === '$observables') { return Object.values(target); }
|
|
101
|
+
if(property === 'keys'|| property === '$keys') { return Object.keys(initialValue); }
|
|
102
|
+
if(property === 'clone' || property === '$clone') { return $clone; }
|
|
103
|
+
if(property === 'reset') { return $reset; }
|
|
104
|
+
if(property === 'configs') { return configs; }
|
|
105
|
+
return target[property];
|
|
119
106
|
},
|
|
120
107
|
set(target, prop, newValue) {
|
|
121
108
|
if(target[prop] !== undefined) {
|
|
@@ -166,6 +153,7 @@ Observable.value = function(data) {
|
|
|
166
153
|
|
|
167
154
|
Observable.update = function($target, newData) {
|
|
168
155
|
const data = Validator.isProxy(newData) ? newData.$value : newData;
|
|
156
|
+
const configs = $target.configs;
|
|
169
157
|
|
|
170
158
|
for(const key in data) {
|
|
171
159
|
const targetItem = $target[key];
|
|
@@ -178,9 +166,9 @@ Observable.update = function($target, newData) {
|
|
|
178
166
|
if(Validator.isObservable(firstElementFromOriginalValue) || Validator.isProxy(firstElementFromOriginalValue)) {
|
|
179
167
|
const newValues = newValue.map(item => {
|
|
180
168
|
if(Validator.isProxy(firstElementFromOriginalValue)) {
|
|
181
|
-
return Observable.init(item);
|
|
169
|
+
return Observable.init(item, configs);
|
|
182
170
|
}
|
|
183
|
-
return Observable(item);
|
|
171
|
+
return Observable(item, configs);
|
|
184
172
|
});
|
|
185
173
|
targetItem.set(newValues);
|
|
186
174
|
continue;
|
|
@@ -49,9 +49,20 @@ export const Match = function($condition, values, shouldKeepInCache = true) {
|
|
|
49
49
|
if(content) {
|
|
50
50
|
anchor.appendChild(content);
|
|
51
51
|
}
|
|
52
|
-
})
|
|
52
|
+
});
|
|
53
53
|
|
|
54
|
-
return anchor
|
|
54
|
+
return anchor.nd.with({
|
|
55
|
+
add(key, view, shouldFocusOn = false) {
|
|
56
|
+
values[key] = view;
|
|
57
|
+
if(shouldFocusOn) {
|
|
58
|
+
$condition.set(key);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
remove(key) {
|
|
62
|
+
shouldKeepInCache && cache.delete(key);
|
|
63
|
+
delete values[key];
|
|
64
|
+
}
|
|
65
|
+
});
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
|
package/src/utils/helpers.js
CHANGED
|
@@ -57,4 +57,36 @@ export const getKey = (item, defaultKey, key) => {
|
|
|
57
57
|
|
|
58
58
|
export const trim = function(str, char) {
|
|
59
59
|
return str.replace(new RegExp(`^[${char}]+|[${char}]+$`, 'g'), '');
|
|
60
|
-
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const deepClone = (value, onObservableFound) => {
|
|
63
|
+
// Primitives
|
|
64
|
+
if (value === null || typeof value !== 'object') {
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Dates
|
|
69
|
+
if (value instanceof Date) {
|
|
70
|
+
return new Date(value.getTime());
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Arrays
|
|
74
|
+
if (Array.isArray(value)) {
|
|
75
|
+
return value.map(item => deepClone(item));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Observables - keep the référence
|
|
79
|
+
if (Validator.isObservable(value)) {
|
|
80
|
+
onObservableFound && onObservableFound(value);
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Objects
|
|
85
|
+
const cloned = {};
|
|
86
|
+
for (const key in value) {
|
|
87
|
+
if (value.hasOwnProperty(key)) {
|
|
88
|
+
cloned[key] = deepClone(value[key]);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return cloned;
|
|
92
|
+
};
|
package/src/utils/validator.js
CHANGED
|
@@ -50,7 +50,7 @@ const Validator = {
|
|
|
50
50
|
return typeof value === 'function' && value.constructor.name === 'AsyncFunction';
|
|
51
51
|
},
|
|
52
52
|
isObject(value) {
|
|
53
|
-
return typeof value === 'object';
|
|
53
|
+
return typeof value === 'object' && value !== null;
|
|
54
54
|
},
|
|
55
55
|
isJson(value) {
|
|
56
56
|
return typeof value === 'object' && value !== null && !Array.isArray(value) && value.constructor.name === 'Object';
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import DocumentObserver from "./DocumentObserver";
|
|
2
2
|
import PluginsManager from "../utils/plugins-manager";
|
|
3
3
|
import Validator from "../utils/validator";
|
|
4
|
+
import NativeDocumentError from "../errors/NativeDocumentError.js";
|
|
5
|
+
import DebugManager from "../utils/debug-manager.js";
|
|
6
|
+
|
|
4
7
|
import {EVENTS} from "../utils/events";
|
|
5
8
|
|
|
6
9
|
export function NDElement(element) {
|
|
@@ -19,6 +22,11 @@ NDElement.prototype.ref = function(target, name) {
|
|
|
19
22
|
return this;
|
|
20
23
|
};
|
|
21
24
|
|
|
25
|
+
NDElement.prototype.refSelf = function(target, name) {
|
|
26
|
+
target[name] = this;
|
|
27
|
+
return this;
|
|
28
|
+
};
|
|
29
|
+
|
|
22
30
|
NDElement.prototype.unmountChildren = function() {
|
|
23
31
|
let element = this.$element;
|
|
24
32
|
for(let i = 0, length = element.children.length; i < length; i++) {
|
|
@@ -209,4 +217,78 @@ for(const event of EVENTS) {
|
|
|
209
217
|
captureEventWrapper(this.$element, eventName, directHandler);
|
|
210
218
|
return this;
|
|
211
219
|
};
|
|
212
|
-
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
NDElement.prototype.with = function(methods) {
|
|
223
|
+
if (!methods || typeof methods !== 'object') {
|
|
224
|
+
throw new NativeDocumentError('extend() requires an object of methods');
|
|
225
|
+
}
|
|
226
|
+
if(process.env.NODE_ENV === 'development') {
|
|
227
|
+
if (!this.$localExtensions) {
|
|
228
|
+
this.$localExtensions = new Map();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
for (const name in methods) {
|
|
233
|
+
const method = methods[name];
|
|
234
|
+
|
|
235
|
+
if (typeof method !== 'function') {
|
|
236
|
+
console.warn(`⚠️ extends(): "${name}" is not a function, skipping`);
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if(process.env.NODE_ENV === 'development') {
|
|
240
|
+
if (this[name] && !this.$localExtensions.has(name)) {
|
|
241
|
+
DebugManager.warn('NDElement.extend', `Method "${name}" already exists and will be overwritten`);
|
|
242
|
+
}
|
|
243
|
+
this.$localExtensions.set(name, method);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
this[name] = method.bind(this);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return this;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
NDElement.extend = function(methods) {
|
|
253
|
+
if (!methods || typeof methods !== 'object') {
|
|
254
|
+
throw new NativeDocumentError('NDElement.extend() requires an object of methods');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (Array.isArray(methods)) {
|
|
258
|
+
throw new NativeDocumentError('NDElement.extend() requires an object, not an array');
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const protectedMethods = new Set([
|
|
262
|
+
'constructor', 'valueOf', '$element', '$observer',
|
|
263
|
+
'ref', 'remove', 'cleanup', 'with', 'extend', 'attach',
|
|
264
|
+
'lifecycle', 'mounted', 'unmounted', 'unmountChildren'
|
|
265
|
+
]);
|
|
266
|
+
|
|
267
|
+
for (const name in methods) {
|
|
268
|
+
if (!methods.hasOwnProperty(name)) {
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const method = methods[name];
|
|
273
|
+
|
|
274
|
+
if (typeof method !== 'function') {
|
|
275
|
+
DebugManager.warn('NDElement.extend', `"${name}" is not a function, skipping`);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (protectedMethods.has(name)) {
|
|
280
|
+
DebugManager.error('NDElement.extend', `Cannot override protected method "${name}"`);
|
|
281
|
+
throw new NativeDocumentError(`Cannot override protected method "${name}"`);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (NDElement.prototype[name]) {
|
|
285
|
+
DebugManager.warn('NDElement.extend', `Overwriting existing prototype method "${name}"`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
NDElement.prototype[name] = method;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
PluginsManager.emit('NDElementExtended', methods);
|
|
292
|
+
|
|
293
|
+
return NDElement;
|
|
294
|
+
};
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { NDElement } from "./NDElement";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const property = {
|
|
4
4
|
configurable: true,
|
|
5
5
|
get() {
|
|
6
|
-
return
|
|
6
|
+
return new NDElement(this);
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
Object.defineProperty(HTMLElement.prototype, 'nd', property);
|
|
11
|
+
|
|
12
|
+
Object.defineProperty(DocumentFragment.prototype, 'nd', property);
|
|
13
|
+
Object.defineProperty(NDElement.prototype, 'nd', {
|
|
14
|
+
configurable: true,
|
|
15
|
+
get: function() {
|
|
16
|
+
return this;
|
|
7
17
|
}
|
|
8
18
|
});
|
|
9
19
|
|
package/types/memoize.d.ts
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
|
|
2
|
+
type OnceProxy<T> = {
|
|
3
|
+
[K in keyof T]: T[K];
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type MemoizeProxy<T> = {
|
|
7
|
+
[key: string]: T;
|
|
8
|
+
[key: symbol]: T;
|
|
9
|
+
};
|
|
10
|
+
|
|
2
11
|
export function once<T extends (...args: any[]) => any>(
|
|
3
12
|
fn: T
|
|
4
13
|
): (...args: Parameters<T>) => ReturnType<T>;
|
|
5
14
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
): T;
|
|
15
|
+
|
|
16
|
+
export function autoOnce<T extends object>(fn: () => T): OnceProxy<T>;
|
|
9
17
|
|
|
10
18
|
export function memoize<T extends (...args: any[]) => any>(
|
|
11
19
|
fn: T
|
|
12
20
|
): (key: any, ...args: Parameters<T>) => ReturnType<T>;
|
|
13
21
|
|
|
14
|
-
export function autoMemoize<T
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
export function autoMemoize<T>(fn: () => T): MemoizeProxy<T>;
|
|
23
|
+
|
|
24
|
+
export function autoMemoize<T, Args extends any[]>(
|
|
25
|
+
fn: (...args: Args) => T
|
|
26
|
+
): MemoizeProxy<(...args: Args) => T>;
|