native-document 1.0.94 → 1.0.95
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 +667 -62
- package/dist/native-document.dev.js +878 -111
- 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.def.js +762 -26
- package/package.json +1 -1
- package/src/core/elements/anchor.js +28 -20
- package/src/core/elements/control/for-each.js +1 -1
- package/src/core/wrappers/DocumentObserver.js +102 -31
- package/src/core/wrappers/ElementCreator.js +5 -0
- package/src/core/wrappers/NDElement.js +32 -1
- package/src/core/wrappers/prototypes/nd-element.transition.extensions.js +83 -0
- package/types/elements.d.ts +580 -2
- package/types/nd-element.d.ts +6 -0
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@ export default function Anchor(name, isUniqueChild = false) {
|
|
|
15
15
|
|
|
16
16
|
anchorFragment.nativeInsertBefore = anchorFragment.insertBefore;
|
|
17
17
|
anchorFragment.nativeAppendChild = anchorFragment.appendChild;
|
|
18
|
+
anchorFragment.nativeAppend = anchorFragment.append;
|
|
18
19
|
|
|
19
20
|
const isParentUniqueChild = (parent) => (isUniqueChild || (parent.firstChild === anchorStart && parent.lastChild === anchorEnd))
|
|
20
21
|
|
|
@@ -50,59 +51,66 @@ export default function Anchor(name, isUniqueChild = false) {
|
|
|
50
51
|
before = before ?? anchorEnd;
|
|
51
52
|
insertBefore(parent, child, before);
|
|
52
53
|
};
|
|
54
|
+
|
|
53
55
|
anchorFragment.append = function(...args ) {
|
|
54
56
|
return anchorFragment.appendChild(args);
|
|
55
|
-
}
|
|
57
|
+
};
|
|
56
58
|
|
|
57
|
-
anchorFragment.removeChildren = function() {
|
|
59
|
+
anchorFragment.removeChildren = async function() {
|
|
58
60
|
const parent = anchorEnd.parentNode;
|
|
59
61
|
if(parent === anchorFragment) {
|
|
60
62
|
return;
|
|
61
63
|
}
|
|
62
|
-
if(isParentUniqueChild(parent)) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
64
|
+
// if(isParentUniqueChild(parent)) {
|
|
65
|
+
// parent.replaceChildren(anchorStart, anchorEnd);
|
|
66
|
+
// return;
|
|
67
|
+
// }
|
|
66
68
|
|
|
67
69
|
let itemToRemove = anchorStart.nextSibling, tempItem;
|
|
68
|
-
const
|
|
70
|
+
const removes = [];
|
|
69
71
|
while(itemToRemove && itemToRemove !== anchorEnd) {
|
|
70
72
|
tempItem = itemToRemove.nextSibling;
|
|
71
|
-
|
|
73
|
+
removes.push(itemToRemove.remove());
|
|
72
74
|
itemToRemove = tempItem;
|
|
73
75
|
}
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
76
|
+
await Promise.all(removes);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
anchorFragment.remove = async function() {
|
|
77
80
|
const parent = anchorEnd.parentNode;
|
|
78
81
|
if(parent === anchorFragment) {
|
|
79
82
|
return;
|
|
80
83
|
}
|
|
81
84
|
let itemToRemove = anchorStart.nextSibling, tempItem;
|
|
85
|
+
const allItemToRemove = [];
|
|
86
|
+
const removes = [];
|
|
82
87
|
while(itemToRemove && itemToRemove !== anchorEnd) {
|
|
83
88
|
tempItem = itemToRemove.nextSibling;
|
|
84
|
-
|
|
89
|
+
allItemToRemove.push(itemToRemove);
|
|
90
|
+
removes.push(itemToRemove.remove());
|
|
85
91
|
itemToRemove = tempItem;
|
|
86
92
|
}
|
|
93
|
+
await Promise.all(removes);
|
|
94
|
+
anchorFragment.nativeAppend(...allItemToRemove);
|
|
87
95
|
};
|
|
88
96
|
|
|
89
|
-
anchorFragment.removeWithAnchors = function() {
|
|
90
|
-
anchorFragment.removeChildren();
|
|
97
|
+
anchorFragment.removeWithAnchors = async function() {
|
|
98
|
+
await anchorFragment.removeChildren();
|
|
91
99
|
anchorStart.remove();
|
|
92
100
|
anchorEnd.remove();
|
|
93
101
|
};
|
|
94
102
|
|
|
95
|
-
anchorFragment.replaceContent = function(child) {
|
|
103
|
+
anchorFragment.replaceContent = async function(child) {
|
|
96
104
|
const childElement = Validator.isElement(child) ? child : ElementCreator.getChild(child);
|
|
97
105
|
const parent = anchorEnd.parentNode;
|
|
98
106
|
if(!parent) {
|
|
99
107
|
return;
|
|
100
108
|
}
|
|
101
|
-
if(isParentUniqueChild(parent)) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
anchorFragment.removeChildren();
|
|
109
|
+
// if(isParentUniqueChild(parent)) {
|
|
110
|
+
// parent.replaceChildren(anchorStart, childElement, anchorEnd);
|
|
111
|
+
// return;
|
|
112
|
+
// }
|
|
113
|
+
await anchorFragment.removeChildren();
|
|
106
114
|
parent.insertBefore(childElement, anchorEnd);
|
|
107
115
|
};
|
|
108
116
|
|
|
@@ -50,7 +50,7 @@ export function ForEach(data, callback, key, { shouldKeepItemsInCache = false }
|
|
|
50
50
|
}
|
|
51
51
|
const child = cacheItem.child?.deref();
|
|
52
52
|
if(parent && child) {
|
|
53
|
-
|
|
53
|
+
child.remove();
|
|
54
54
|
}
|
|
55
55
|
cacheItem.indexObserver?.cleanup();
|
|
56
56
|
cacheItem.child = null;
|
|
@@ -1,97 +1,167 @@
|
|
|
1
|
-
|
|
2
1
|
const DocumentObserver = {
|
|
3
2
|
mounted: new WeakMap(),
|
|
3
|
+
beforeUnmount: new WeakMap(),
|
|
4
4
|
mountedSupposedSize: 0,
|
|
5
5
|
unmounted: new WeakMap(),
|
|
6
6
|
unmountedSupposedSize: 0,
|
|
7
7
|
observer: null,
|
|
8
|
+
|
|
8
9
|
executeMountedCallback(node) {
|
|
9
10
|
const data = DocumentObserver.mounted.get(node);
|
|
10
11
|
if(!data) {
|
|
11
12
|
return;
|
|
12
13
|
}
|
|
13
14
|
data.inDom = true;
|
|
14
|
-
data.mounted
|
|
15
|
+
if(!data.mounted) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if(Array.isArray(data.mounted)) {
|
|
19
|
+
for(const cb of data.mounted) {
|
|
20
|
+
cb(node);
|
|
21
|
+
}
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
data.mounted(node);
|
|
15
25
|
},
|
|
26
|
+
|
|
16
27
|
executeUnmountedCallback(node) {
|
|
17
28
|
const data = DocumentObserver.unmounted.get(node);
|
|
18
29
|
if(!data) {
|
|
19
30
|
return;
|
|
20
31
|
}
|
|
21
|
-
|
|
22
32
|
data.inDom = false;
|
|
23
|
-
if(data.unmounted
|
|
33
|
+
if(!data.unmounted) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let shouldRemove = false;
|
|
38
|
+
if(Array.isArray(data.unmounted)) {
|
|
39
|
+
for(const cb of data.unmounted) {
|
|
40
|
+
if(cb(node) === true) {
|
|
41
|
+
shouldRemove = true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
shouldRemove = data.unmounted(node) === true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if(shouldRemove) {
|
|
24
49
|
data.disconnect();
|
|
25
50
|
node.nd?.remove();
|
|
26
51
|
}
|
|
27
52
|
},
|
|
53
|
+
|
|
28
54
|
checkMutation: function(mutationsList) {
|
|
29
|
-
let i = 0;
|
|
30
55
|
for(const mutation of mutationsList) {
|
|
31
|
-
if(DocumentObserver.mountedSupposedSize > 0
|
|
56
|
+
if(DocumentObserver.mountedSupposedSize > 0) {
|
|
32
57
|
for(const node of mutation.addedNodes) {
|
|
33
58
|
DocumentObserver.executeMountedCallback(node);
|
|
34
59
|
if(!node.querySelectorAll) {
|
|
35
|
-
|
|
60
|
+
continue;
|
|
36
61
|
}
|
|
37
62
|
const children = node.querySelectorAll('[data--nd-mounted]');
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
for(const node of children) {
|
|
42
|
-
DocumentObserver.executeMountedCallback(node);
|
|
63
|
+
for(const child of children) {
|
|
64
|
+
DocumentObserver.executeMountedCallback(child);
|
|
43
65
|
}
|
|
44
66
|
}
|
|
45
67
|
}
|
|
46
68
|
|
|
47
|
-
if(DocumentObserver.unmountedSupposedSize > 0
|
|
48
|
-
for(const node of mutation.removedNodes) {
|
|
69
|
+
if (DocumentObserver.unmountedSupposedSize > 0) {
|
|
70
|
+
for (const node of mutation.removedNodes) {
|
|
49
71
|
DocumentObserver.executeUnmountedCallback(node);
|
|
50
72
|
if(!node.querySelectorAll) {
|
|
51
|
-
|
|
73
|
+
continue;
|
|
52
74
|
}
|
|
53
75
|
const children = node.querySelectorAll('[data--nd-unmounted]');
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
for(const node of children) {
|
|
58
|
-
DocumentObserver.executeUnmountedCallback(node);
|
|
76
|
+
for(const child of children) {
|
|
77
|
+
DocumentObserver.executeUnmountedCallback(child);
|
|
59
78
|
}
|
|
60
79
|
}
|
|
61
80
|
}
|
|
62
81
|
}
|
|
63
82
|
},
|
|
83
|
+
|
|
64
84
|
/**
|
|
65
|
-
*
|
|
66
85
|
* @param {HTMLElement} element
|
|
67
86
|
* @param {boolean} inDom
|
|
68
|
-
* @returns {{
|
|
87
|
+
* @returns {{ disconnect: Function, mounted: Function, unmounted: Function, off: Function }}
|
|
69
88
|
*/
|
|
70
89
|
watch: function(element, inDom = false) {
|
|
90
|
+
let mountedRegistered = false;
|
|
91
|
+
let unmountedRegistered = false;
|
|
92
|
+
|
|
71
93
|
let data = {
|
|
72
94
|
inDom,
|
|
73
95
|
mounted: null,
|
|
74
96
|
unmounted: null,
|
|
75
97
|
disconnect: () => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
98
|
+
if (mountedRegistered) {
|
|
99
|
+
DocumentObserver.mounted.delete(element);
|
|
100
|
+
DocumentObserver.mountedSupposedSize--;
|
|
101
|
+
}
|
|
102
|
+
if (unmountedRegistered) {
|
|
103
|
+
DocumentObserver.unmounted.delete(element);
|
|
104
|
+
DocumentObserver.unmountedSupposedSize--;
|
|
105
|
+
}
|
|
80
106
|
data = null;
|
|
81
107
|
}
|
|
82
108
|
};
|
|
83
109
|
|
|
110
|
+
const addListener = (type, callback) => {
|
|
111
|
+
if (!data[type]) {
|
|
112
|
+
data[type] = callback;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (!Array.isArray(data[type])) {
|
|
116
|
+
data[type] = [data[type], callback];
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
data[type].push(callback);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const removeListener = (type, callback) => {
|
|
123
|
+
if(!data?.[type]) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if(Array.isArray(data[type])) {
|
|
127
|
+
const index = data[type].indexOf(callback);
|
|
128
|
+
if(index > -1) {
|
|
129
|
+
data[type].splice(index, 1);
|
|
130
|
+
}
|
|
131
|
+
if(data[type].length === 1) {
|
|
132
|
+
data[type] = data[type][0];
|
|
133
|
+
}
|
|
134
|
+
if(data[type].length === 0) {
|
|
135
|
+
data[type] = null;
|
|
136
|
+
}
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
data[type] = null;
|
|
140
|
+
};
|
|
141
|
+
|
|
84
142
|
return {
|
|
85
|
-
disconnect: data
|
|
143
|
+
disconnect: () => data?.disconnect(),
|
|
144
|
+
|
|
86
145
|
mounted: (callback) => {
|
|
87
|
-
|
|
146
|
+
addListener('mounted', callback);
|
|
88
147
|
DocumentObserver.mounted.set(element, data);
|
|
89
|
-
|
|
148
|
+
if (!mountedRegistered) {
|
|
149
|
+
DocumentObserver.mountedSupposedSize++;
|
|
150
|
+
mountedRegistered = true;
|
|
151
|
+
}
|
|
90
152
|
},
|
|
153
|
+
|
|
91
154
|
unmounted: (callback) => {
|
|
92
|
-
|
|
155
|
+
addListener('unmounted', callback);
|
|
93
156
|
DocumentObserver.unmounted.set(element, data);
|
|
94
|
-
|
|
157
|
+
if (!unmountedRegistered) {
|
|
158
|
+
DocumentObserver.unmountedSupposedSize++;
|
|
159
|
+
unmountedRegistered = true;
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
off: (type, callback) => {
|
|
164
|
+
removeListener(type, callback);
|
|
95
165
|
}
|
|
96
166
|
};
|
|
97
167
|
}
|
|
@@ -102,4 +172,5 @@ DocumentObserver.observer.observe(document.body, {
|
|
|
102
172
|
childList: true,
|
|
103
173
|
subtree: true,
|
|
104
174
|
});
|
|
175
|
+
|
|
105
176
|
export default DocumentObserver;
|
|
@@ -3,6 +3,7 @@ import Validator from "../utils/validator";
|
|
|
3
3
|
import AttributesWrapper from "./AttributesWrapper";
|
|
4
4
|
import PluginsManager from "../utils/plugins-manager";
|
|
5
5
|
import './prototypes/nd-element-extensions';
|
|
6
|
+
import './prototypes/nd-element.transition.extensions';
|
|
6
7
|
import './prototypes/attributes-extensions';
|
|
7
8
|
|
|
8
9
|
const $nodeCache = new Map();
|
|
@@ -95,6 +96,10 @@ export const ElementCreator = {
|
|
|
95
96
|
PluginsManager.emit('AfterProcessChildren', parent);
|
|
96
97
|
}
|
|
97
98
|
},
|
|
99
|
+
async safeRemove(element) {
|
|
100
|
+
await element.remove();
|
|
101
|
+
|
|
102
|
+
},
|
|
98
103
|
getChild(child) {
|
|
99
104
|
if(child == null) {
|
|
100
105
|
return null;
|
|
@@ -73,6 +73,37 @@ NDElement.prototype.unmounted = function(callback) {
|
|
|
73
73
|
return this.lifecycle({ unmounted: callback });
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
+
NDElement.prototype.beforeUnmount = function(id, callback) {
|
|
77
|
+
const el = this.$element;
|
|
78
|
+
|
|
79
|
+
if(!DocumentObserver.beforeUnmount.has(el)) {
|
|
80
|
+
DocumentObserver.beforeUnmount.set(el, new Map());
|
|
81
|
+
const originalRemove = el.remove.bind(el);
|
|
82
|
+
|
|
83
|
+
let $isUnmounting = false
|
|
84
|
+
|
|
85
|
+
el.remove = async () => {
|
|
86
|
+
if($isUnmounting) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
$isUnmounting = true;
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
const callbacks = DocumentObserver.beforeUnmount.get(el);
|
|
93
|
+
for (const cb of callbacks.values()) {
|
|
94
|
+
await cb.call(this, el);
|
|
95
|
+
}
|
|
96
|
+
} finally {
|
|
97
|
+
originalRemove();
|
|
98
|
+
$isUnmounting = false;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
DocumentObserver.beforeUnmount.get(el).set(id, callback);
|
|
104
|
+
return this;
|
|
105
|
+
};
|
|
106
|
+
|
|
76
107
|
NDElement.prototype.htmlElement = function() {
|
|
77
108
|
return this.$element;
|
|
78
109
|
};
|
|
@@ -160,7 +191,7 @@ NDElement.prototype.with = function(methods) {
|
|
|
160
191
|
}
|
|
161
192
|
|
|
162
193
|
return this;
|
|
163
|
-
}
|
|
194
|
+
};
|
|
164
195
|
|
|
165
196
|
/**
|
|
166
197
|
* Extends the NDElement prototype with new methods available to all NDElement instances.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {NDElement} from "../NDElement";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {HTMLElement} el
|
|
5
|
+
* @param {number} timeout
|
|
6
|
+
*/
|
|
7
|
+
const waitForVisualEnd = (el, timeout = 1000) => {
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
let isResolved = false;
|
|
10
|
+
|
|
11
|
+
const cleanupAndResolve = (e) => {
|
|
12
|
+
if (e && e.target !== el) return;
|
|
13
|
+
if (isResolved) return;
|
|
14
|
+
|
|
15
|
+
isResolved = true;
|
|
16
|
+
el.removeEventListener('transitionend', cleanupAndResolve);
|
|
17
|
+
el.removeEventListener('animationend', cleanupAndResolve);
|
|
18
|
+
clearTimeout(timer);
|
|
19
|
+
resolve();
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
el.addEventListener('transitionend', cleanupAndResolve);
|
|
23
|
+
el.addEventListener('animationend', cleanupAndResolve);
|
|
24
|
+
|
|
25
|
+
const timer = setTimeout(cleanupAndResolve, timeout);
|
|
26
|
+
|
|
27
|
+
const style = window.getComputedStyle(el);
|
|
28
|
+
const hasTransition = style.transitionDuration !== '0s';
|
|
29
|
+
const hasAnimation = style.animationDuration !== '0s';
|
|
30
|
+
|
|
31
|
+
if (!hasTransition && !hasAnimation) {
|
|
32
|
+
cleanupAndResolve();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
NDElement.prototype.transitionOut = function(transitionName) {
|
|
38
|
+
const exitClass = transitionName + '-exit';
|
|
39
|
+
this.beforeUnmount('transition-exit', async function() {
|
|
40
|
+
this.$element.classes.add(exitClass);
|
|
41
|
+
await waitForVisualEnd(this.$element);
|
|
42
|
+
this.$element.classes.remove(exitClass);
|
|
43
|
+
});
|
|
44
|
+
return this;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
NDElement.prototype.transitionIn = function(transitionName) {
|
|
48
|
+
const startClass = transitionName + '-enter-from';
|
|
49
|
+
const endClass = transitionName + '-enter-to';
|
|
50
|
+
|
|
51
|
+
this.$element.classes.add(startClass);
|
|
52
|
+
|
|
53
|
+
this.mounted(() => {
|
|
54
|
+
requestAnimationFrame(() => {
|
|
55
|
+
requestAnimationFrame(() => {
|
|
56
|
+
this.$element.classes.remove(startClass);
|
|
57
|
+
this.$element.classes.add(endClass);
|
|
58
|
+
|
|
59
|
+
waitForVisualEnd(this.$element).then(() => {
|
|
60
|
+
this.$element.classes.remove(endClass);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
return this;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
NDElement.prototype.transition = function (transitionName) {
|
|
70
|
+
this.transitionIn(transitionName);
|
|
71
|
+
this.transitionOut(transitionName);
|
|
72
|
+
return this;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
NDElement.prototype.animate = function(animationName) {
|
|
76
|
+
this.$element.classes.add(animationName);
|
|
77
|
+
|
|
78
|
+
waitForVisualEnd(this.$element).then(() => {
|
|
79
|
+
this.$element.classes.remove(animationName);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return this;
|
|
83
|
+
};
|