native-document 1.0.93 → 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/elements.js +1 -0
- package/index.def.js +1086 -0
- package/package.json +1 -1
- package/src/core/elements/anchor.js +28 -20
- package/src/core/elements/content-formatter.js +138 -1
- package/src/core/elements/control/for-each-array.js +1 -1
- package/src/core/elements/control/for-each.js +2 -2
- package/src/core/elements/control/show-if.js +3 -3
- package/src/core/elements/control/show-when.js +2 -2
- package/src/core/elements/control/switch.js +1 -1
- package/src/core/elements/description-list.js +14 -0
- package/src/core/elements/form.js +188 -4
- package/src/core/elements/html5-semantics.js +44 -1
- package/src/core/elements/img.js +22 -10
- package/src/core/elements/index.js +5 -0
- package/src/core/elements/interactive.js +19 -1
- package/src/core/elements/list.js +28 -1
- package/src/core/elements/medias.js +29 -0
- package/src/core/elements/meta-data.js +34 -0
- package/src/core/elements/table.js +59 -0
- package/src/core/utils/helpers.js +7 -2
- package/src/core/utils/memoize.js +1 -1
- package/src/core/wrappers/DocumentObserver.js +102 -31
- package/src/core/wrappers/ElementCreator.js +5 -0
- package/src/core/wrappers/HtmlElementWrapper.js +2 -2
- package/src/core/wrappers/NDElement.js +33 -2
- package/src/core/wrappers/TemplateCloner.js +1 -1
- package/src/core/wrappers/prototypes/nd-element.transition.extensions.js +83 -0
- package/types/elements.d.ts +1073 -113
- package/types/forms.d.ts +85 -48
- package/types/images.d.ts +16 -9
- package/types/nd-element.d.ts +6 -0
package/src/core/elements/img.js
CHANGED
|
@@ -2,18 +2,30 @@ import HtmlElementWrapper from "../wrappers/HtmlElementWrapper"
|
|
|
2
2
|
import Validator from "../utils/validator";
|
|
3
3
|
import NativeDocumentError from "../errors/NativeDocumentError";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Creates an `<img>` element.
|
|
7
|
+
* @type {function(ImgAttributes=): HTMLImageElement}
|
|
8
|
+
*/
|
|
5
9
|
export const BaseImage = HtmlElementWrapper('img');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates an `<img>` element.
|
|
13
|
+
* @param {Observable<string>|string} src
|
|
14
|
+
* @param {Omit<ImgAttributes, 'src'>} [attributes]
|
|
15
|
+
* @returns {HTMLImageElement}
|
|
16
|
+
*/
|
|
6
17
|
export const Img = function(src, attributes) {
|
|
7
18
|
return BaseImage({ src, ...attributes });
|
|
8
19
|
};
|
|
9
20
|
|
|
10
21
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* @param {string
|
|
14
|
-
* @param {
|
|
15
|
-
* @param {
|
|
16
|
-
* @
|
|
22
|
+
* Creates an `<img>` that loads asynchronously, showing a placeholder until the image is ready.
|
|
23
|
+
* Supports reactive `src` — automatically updates when the observable changes.
|
|
24
|
+
* @param {Observable<string>|string} src - Final image URL
|
|
25
|
+
* @param {string|null} defaultImage - Placeholder shown while loading
|
|
26
|
+
* @param {Omit<ImgAttributes, 'src'>} attributes
|
|
27
|
+
* @param {(error: NativeDocumentError|null, img: HTMLImageElement) => void} [callback]
|
|
28
|
+
* @returns {HTMLImageElement}
|
|
17
29
|
*/
|
|
18
30
|
export const AsyncImg = function(src, defaultImage, attributes, callback) {
|
|
19
31
|
const defaultSrc = Validator.isObservable(src) ? src.val() : src;
|
|
@@ -37,10 +49,10 @@ export const AsyncImg = function(src, defaultImage, attributes, callback) {
|
|
|
37
49
|
};
|
|
38
50
|
|
|
39
51
|
/**
|
|
40
|
-
*
|
|
41
|
-
* @param {string}
|
|
42
|
-
* @param {
|
|
43
|
-
* @returns {
|
|
52
|
+
* Creates an `<img loading="lazy">` element.
|
|
53
|
+
* @param {Observable<string>|string} src
|
|
54
|
+
* @param {Omit<ImgAttributes, 'src'|'loading'>} [attributes]
|
|
55
|
+
* @returns {HTMLImageElement}
|
|
44
56
|
*/
|
|
45
57
|
export const LazyImg = function(src, attributes) {
|
|
46
58
|
return Img(src, { ...attributes, loading: 'lazy' });
|
|
@@ -16,6 +16,11 @@ export * from './medias';
|
|
|
16
16
|
export * from './meta-data';
|
|
17
17
|
export * from './table';
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Creates an empty `DocumentFragment` wrapper.
|
|
21
|
+
* Useful for grouping elements without adding a DOM node.
|
|
22
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): DocumentFragment}
|
|
23
|
+
*/
|
|
19
24
|
export const Fragment = HtmlElementWrapper('');
|
|
20
25
|
|
|
21
26
|
|
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Creates a `<details>` element.
|
|
5
|
+
* @type {function(DetailsAttributes=, NdChild|NdChild[]=): HTMLDetailsElement}
|
|
6
|
+
*/
|
|
4
7
|
export const Details = HtmlElementWrapper('details');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a `<summary>` element.
|
|
11
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
12
|
+
*/
|
|
5
13
|
export const Summary = HtmlElementWrapper('summary');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a `<dialog>` element.
|
|
17
|
+
* @type {function(DialogAttributes=, NdChild|NdChild[]=): HTMLDialogElement}
|
|
18
|
+
*/
|
|
6
19
|
export const Dialog = HtmlElementWrapper('dialog');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates a `<menu>` element.
|
|
23
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLMenuElement}
|
|
24
|
+
*/
|
|
7
25
|
export const Menu = HtmlElementWrapper('menu');
|
|
@@ -1,10 +1,37 @@
|
|
|
1
1
|
import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates an `<ol>` element.
|
|
5
|
+
* @type {function(OlAttributes=, NdChild|NdChild[]=): HTMLOListElement}
|
|
6
|
+
*/
|
|
3
7
|
export const OrderedList = HtmlElementWrapper('ol');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a `<ul>` element.
|
|
11
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLUListElement}
|
|
12
|
+
*/
|
|
4
13
|
export const UnorderedList = HtmlElementWrapper('ul');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a `<li>` element.
|
|
17
|
+
* @type {function(GlobalAttributes & { value?: number }=, NdChild|NdChild[]=): HTMLLIElement}
|
|
18
|
+
*/
|
|
5
19
|
export const ListItem = HtmlElementWrapper('li');
|
|
6
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Alias for {@link ListItem}.
|
|
23
|
+
* @type {typeof ListItem}
|
|
24
|
+
*/
|
|
7
25
|
export const Li = ListItem;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Alias for {@link OrderedList}.
|
|
29
|
+
* @type {typeof OrderedList}
|
|
30
|
+
*/
|
|
8
31
|
export const Ol = OrderedList;
|
|
9
|
-
export const Ul = UnorderedList;
|
|
10
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Alias for {@link UnorderedList}.
|
|
35
|
+
* @type {typeof UnorderedList}
|
|
36
|
+
*/
|
|
37
|
+
export const Ul = UnorderedList;
|
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates an `<audio>` element.
|
|
5
|
+
* @type {function(AudioAttributes=, NdChild|NdChild[]=): HTMLAudioElement}
|
|
6
|
+
*/
|
|
3
7
|
export const Audio = HtmlElementWrapper('audio');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a `<video>` element.
|
|
11
|
+
* @type {function(VideoAttributes=, NdChild|NdChild[]=): HTMLVideoElement}
|
|
12
|
+
*/
|
|
4
13
|
export const Video = HtmlElementWrapper('video');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a `<source>` element.
|
|
17
|
+
* @type {function(SourceAttributes=): HTMLSourceElement}
|
|
18
|
+
*/
|
|
5
19
|
export const Source = HtmlElementWrapper('source');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates a `<track>` element.
|
|
23
|
+
* @type {function(TrackAttributes=): HTMLTrackElement}
|
|
24
|
+
*/
|
|
6
25
|
export const Track = HtmlElementWrapper('track');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a `<canvas>` element.
|
|
29
|
+
* @type {function(CanvasAttributes=, NdChild|NdChild[]=): HTMLCanvasElement}
|
|
30
|
+
*/
|
|
7
31
|
export const Canvas = HtmlElementWrapper('canvas');
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates an `<svg>` element.
|
|
35
|
+
* @type {function(SvgAttributes=, NdChild|NdChild[]=): SVGSVGElement}
|
|
36
|
+
*/
|
|
8
37
|
export const Svg = HtmlElementWrapper('svg');
|
|
@@ -1,9 +1,43 @@
|
|
|
1
1
|
import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates a `<time>` element.
|
|
5
|
+
* @type {function(TimeAttributes=, NdChild|NdChild[]=): HTMLTimeElement}
|
|
6
|
+
*/
|
|
3
7
|
export const Time = HtmlElementWrapper('time');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a `<data>` element.
|
|
11
|
+
* @type {function(GlobalAttributes & { value?: Observable<string>|string }=, NdChild|NdChild[]=): HTMLDataElement}
|
|
12
|
+
*/
|
|
4
13
|
export const Data = HtmlElementWrapper('data');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates an `<address>` element.
|
|
17
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
18
|
+
*/
|
|
5
19
|
export const Address = HtmlElementWrapper('address');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates a `<kbd>` element.
|
|
23
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
24
|
+
*/
|
|
6
25
|
export const Kbd = HtmlElementWrapper('kbd');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a `<samp>` element.
|
|
29
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
30
|
+
*/
|
|
7
31
|
export const Samp = HtmlElementWrapper('samp');
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates a `<var>` element.
|
|
35
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
36
|
+
*/
|
|
8
37
|
export const Var = HtmlElementWrapper('var');
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Creates a `<wbr>` element.
|
|
41
|
+
* @type {function(GlobalAttributes=): HTMLElement}
|
|
42
|
+
*/
|
|
9
43
|
export const Wbr = HtmlElementWrapper('wbr');
|
|
@@ -1,14 +1,73 @@
|
|
|
1
1
|
import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates a `<caption>` element.
|
|
5
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLTableCaptionElement}
|
|
6
|
+
*/
|
|
3
7
|
export const Caption = HtmlElementWrapper('caption');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a `<table>` element.
|
|
11
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLTableElement}
|
|
12
|
+
*/
|
|
4
13
|
export const Table = HtmlElementWrapper('table');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a `<thead>` element.
|
|
17
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLTableSectionElement}
|
|
18
|
+
*/
|
|
5
19
|
export const THead = HtmlElementWrapper('thead');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates a `<tfoot>` element.
|
|
23
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLTableSectionElement}
|
|
24
|
+
*/
|
|
6
25
|
export const TFoot = HtmlElementWrapper('tfoot');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a `<tbody>` element.
|
|
29
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLTableSectionElement}
|
|
30
|
+
*/
|
|
7
31
|
export const TBody = HtmlElementWrapper('tbody');
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates a `<tr>` element.
|
|
35
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLTableRowElement}
|
|
36
|
+
*/
|
|
8
37
|
export const Tr = HtmlElementWrapper('tr');
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Alias for {@link Tr}.
|
|
41
|
+
* @type {typeof Tr}
|
|
42
|
+
*/
|
|
9
43
|
export const TRow = Tr;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Creates a `<th>` element.
|
|
47
|
+
* @type {function(ThAttributes=, NdChild|NdChild[]=): HTMLTableCellElement}
|
|
48
|
+
*/
|
|
10
49
|
export const Th = HtmlElementWrapper('th');
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Alias for {@link Th}.
|
|
53
|
+
* @type {typeof Th}
|
|
54
|
+
*/
|
|
11
55
|
export const THeadCell = Th;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Alias for {@link Th}.
|
|
59
|
+
* @type {typeof Th}
|
|
60
|
+
*/
|
|
12
61
|
export const TFootCell = Th;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Creates a `<td>` element.
|
|
65
|
+
* @type {function(TdAttributes=, NdChild|NdChild[]=): HTMLTableCellElement}
|
|
66
|
+
*/
|
|
13
67
|
export const Td = HtmlElementWrapper('td');
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Alias for {@link Td}.
|
|
71
|
+
* @type {typeof Td}
|
|
72
|
+
*/
|
|
14
73
|
export const TBodyCell = Td;
|
|
@@ -75,7 +75,12 @@ export const trim = function(str, char) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
export const deepClone = (value, onObservableFound) => {
|
|
78
|
-
|
|
78
|
+
try {
|
|
79
|
+
if(window.structuredClone !== undefined) {
|
|
80
|
+
return window.structuredClone(value);
|
|
81
|
+
}
|
|
82
|
+
} catch (e){}
|
|
83
|
+
|
|
79
84
|
if (value === null || typeof value !== 'object') {
|
|
80
85
|
return value;
|
|
81
86
|
}
|
|
@@ -99,7 +104,7 @@ export const deepClone = (value, onObservableFound) => {
|
|
|
99
104
|
// Objects
|
|
100
105
|
const cloned = {};
|
|
101
106
|
for (const key in value) {
|
|
102
|
-
if (
|
|
107
|
+
if (Object.hasOwn(value, key)) {
|
|
103
108
|
cloned[key] = deepClone(value[key]);
|
|
104
109
|
}
|
|
105
110
|
}
|
|
@@ -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;
|
|
@@ -28,10 +28,10 @@ function createHtmlElement($tagName, customWrapper, _attributes, _children = nul
|
|
|
28
28
|
/**
|
|
29
29
|
*
|
|
30
30
|
* @param {string} name
|
|
31
|
-
* @param {?Function} customWrapper
|
|
31
|
+
* @param {?Function=} customWrapper
|
|
32
32
|
* @returns {Function}
|
|
33
33
|
*/
|
|
34
|
-
export default function HtmlElementWrapper(name, customWrapper) {
|
|
34
|
+
export default function HtmlElementWrapper(name, customWrapper = null) {
|
|
35
35
|
return createHtmlElement.bind(null, name, customWrapper);
|
|
36
36
|
};
|
|
37
37
|
|
|
@@ -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.
|
|
@@ -195,7 +226,7 @@ NDElement.extend = function(methods) {
|
|
|
195
226
|
]);
|
|
196
227
|
|
|
197
228
|
for (const name in methods) {
|
|
198
|
-
if (!
|
|
229
|
+
if (!Object.hasOwn(methods, name)) {
|
|
199
230
|
continue;
|
|
200
231
|
}
|
|
201
232
|
|
|
@@ -51,7 +51,7 @@ const $hydrateFn = function(hydrateFunction, targetType, element, property) {
|
|
|
51
51
|
hydrationState[targetType][property] = hydrateFunction;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
const bindAttachMethods =
|
|
54
|
+
const bindAttachMethods = (node, bindDingData, data) => {
|
|
55
55
|
if(!bindDingData.attach) {
|
|
56
56
|
return null;
|
|
57
57
|
}
|