native-document 1.0.92 → 1.0.94
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 +1088 -65
- package/dist/native-document.dev.js +695 -142
- 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/docs/advanced-components.md +814 -0
- package/docs/anchor.md +71 -11
- package/docs/cache.md +888 -0
- package/docs/conditional-rendering.md +91 -1
- package/docs/core-concepts.md +9 -2
- package/docs/elements.md +127 -2
- package/docs/extending-native-document-element.md +7 -1
- package/docs/filters.md +1216 -0
- package/docs/getting-started.md +12 -3
- package/docs/lifecycle-events.md +10 -2
- package/docs/list-rendering.md +453 -54
- package/docs/memory-management.md +9 -7
- package/docs/native-document-element.md +30 -9
- package/docs/native-fetch.md +744 -0
- package/docs/observables.md +135 -6
- package/docs/routing.md +7 -1
- package/docs/state-management.md +7 -1
- package/docs/validation.md +8 -1
- package/elements.js +1 -0
- package/eslint.config.js +3 -3
- package/index.def.js +350 -0
- package/package.json +3 -2
- package/readme.md +53 -14
- package/src/components/$traits/HasItems.js +42 -1
- package/src/components/BaseComponent.js +4 -1
- package/src/components/accordion/Accordion.js +112 -8
- package/src/components/accordion/AccordionItem.js +93 -4
- package/src/components/alert/Alert.js +164 -4
- package/src/components/avatar/Avatar.js +236 -22
- package/src/components/menu/index.js +1 -2
- package/src/core/data/ObservableArray.js +120 -2
- package/src/core/data/ObservableChecker.js +50 -0
- package/src/core/data/ObservableItem.js +124 -4
- package/src/core/data/ObservableWhen.js +36 -6
- package/src/core/data/observable-helpers/array.js +12 -3
- package/src/core/data/observable-helpers/computed.js +17 -4
- package/src/core/data/observable-helpers/object.js +19 -3
- package/src/core/elements/content-formatter.js +138 -1
- package/src/core/elements/control/for-each-array.js +20 -2
- package/src/core/elements/control/for-each.js +17 -5
- package/src/core/elements/control/show-if.js +31 -15
- package/src/core/elements/control/show-when.js +23 -0
- package/src/core/elements/control/switch.js +40 -10
- 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/cache.js +5 -0
- package/src/core/utils/helpers.js +7 -2
- package/src/core/utils/memoize.js +25 -16
- package/src/core/utils/prototypes.js +3 -2
- package/src/core/wrappers/AttributesWrapper.js +1 -1
- package/src/core/wrappers/HtmlElementWrapper.js +2 -2
- package/src/core/wrappers/NDElement.js +42 -2
- package/src/core/wrappers/NdPrototype.js +4 -0
- package/src/core/wrappers/TemplateCloner.js +14 -11
- package/src/core/wrappers/prototypes/bind-class-extensions.js +1 -1
- package/src/core/wrappers/prototypes/nd-element-extensions.js +3 -0
- package/src/router/Route.js +9 -4
- package/src/router/Router.js +28 -9
- package/src/router/errors/RouterError.js +0 -1
- package/types/control-flow.d.ts +9 -6
- package/types/elements.d.ts +496 -111
- package/types/filters/index.d.ts +4 -0
- package/types/forms.d.ts +85 -48
- package/types/images.d.ts +16 -9
- package/types/nd-element.d.ts +5 -238
- package/types/observable.d.ts +9 -3
- package/types/router.d.ts +5 -1
- package/types/template-cloner.ts +1 -0
- package/types/validator.ts +11 -1
- package/utils.d.ts +2 -1
- package/utils.js +4 -4
- package/src/core/utils/service.js +0 -6
|
@@ -1,12 +1,55 @@
|
|
|
1
1
|
import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates a `<main>` element.
|
|
5
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
6
|
+
*/
|
|
3
7
|
export const Main = HtmlElementWrapper('main');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a `<section>` element.
|
|
11
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
12
|
+
*/
|
|
4
13
|
export const Section = HtmlElementWrapper('section');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates an `<article>` element.
|
|
17
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
18
|
+
*/
|
|
5
19
|
export const Article = HtmlElementWrapper('article');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates an `<aside>` element.
|
|
23
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
24
|
+
*/
|
|
6
25
|
export const Aside = HtmlElementWrapper('aside');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a `<nav>` element.
|
|
29
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
30
|
+
*/
|
|
7
31
|
export const Nav = HtmlElementWrapper('nav');
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates a `<figure>` element.
|
|
35
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
36
|
+
*/
|
|
8
37
|
export const Figure = HtmlElementWrapper('figure');
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Creates a `<figcaption>` element.
|
|
41
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
42
|
+
*/
|
|
9
43
|
export const FigCaption = HtmlElementWrapper('figcaption');
|
|
10
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Creates a `<header>` element.
|
|
47
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
48
|
+
*/
|
|
11
49
|
export const Header = HtmlElementWrapper('header');
|
|
12
|
-
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates a `<footer>` element.
|
|
53
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
54
|
+
*/
|
|
55
|
+
export const Footer = HtmlElementWrapper('footer');
|
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
|
}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
export const once = (fn) => {
|
|
4
4
|
let result = null;
|
|
5
5
|
return (...args) => {
|
|
6
|
-
if(result
|
|
7
|
-
result
|
|
6
|
+
if(result != null) {
|
|
7
|
+
return result;
|
|
8
8
|
}
|
|
9
|
+
result = fn(...args);
|
|
9
10
|
return result;
|
|
10
11
|
};
|
|
11
12
|
};
|
|
@@ -14,9 +15,10 @@ export const autoOnce = (fn) => {
|
|
|
14
15
|
let target = null;
|
|
15
16
|
return new Proxy({}, {
|
|
16
17
|
get: (_, key) => {
|
|
17
|
-
if(target
|
|
18
|
-
target
|
|
18
|
+
if(target) {
|
|
19
|
+
return target[key];
|
|
19
20
|
}
|
|
21
|
+
target = fn();
|
|
20
22
|
return target[key];
|
|
21
23
|
}
|
|
22
24
|
});
|
|
@@ -26,10 +28,13 @@ export const memoize = (fn) => {
|
|
|
26
28
|
const cache = new Map();
|
|
27
29
|
return (...args) => {
|
|
28
30
|
const [key, ...rest] = args;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
const cached = cache.get(key);
|
|
32
|
+
if(cached) {
|
|
33
|
+
return cached;
|
|
31
34
|
}
|
|
32
|
-
|
|
35
|
+
const result = fn(...rest);
|
|
36
|
+
cache.set(key, result);
|
|
37
|
+
return result;
|
|
33
38
|
};
|
|
34
39
|
};
|
|
35
40
|
|
|
@@ -37,17 +42,21 @@ export const autoMemoize = (fn) => {
|
|
|
37
42
|
const cache = new Map();
|
|
38
43
|
return new Proxy({}, {
|
|
39
44
|
get: (_, key) => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
const cached = cache.get(key);
|
|
46
|
+
if(cached) {
|
|
47
|
+
return cached;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if(fn.length > 0) {
|
|
51
|
+
return (...args) => {
|
|
52
|
+
const result = fn(...args, key);
|
|
53
|
+
cache.set(key, result);
|
|
54
|
+
return result;
|
|
47
55
|
}
|
|
48
|
-
cache.set(key, fn());
|
|
49
56
|
}
|
|
50
|
-
|
|
57
|
+
const result = fn(key);
|
|
58
|
+
cache.set(key, result);
|
|
59
|
+
return result;
|
|
51
60
|
}
|
|
52
61
|
});
|
|
53
62
|
};
|
|
@@ -27,13 +27,14 @@ Function.prototype.cached = function(...args) {
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
Function.prototype.errorBoundary = function(callback) {
|
|
30
|
-
|
|
30
|
+
const handler = (...args) => {
|
|
31
31
|
try {
|
|
32
32
|
return this.apply(this, args);
|
|
33
33
|
} catch(e) {
|
|
34
|
-
return callback(e);
|
|
34
|
+
return callback(e, {caller: handler, args: args });
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
+
return handler;
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
String.prototype.use = function(args) {
|
|
@@ -17,7 +17,7 @@ export function bindClassAttribute(element, data) {
|
|
|
17
17
|
continue;
|
|
18
18
|
}
|
|
19
19
|
if(value.__$isObservableWhen) {
|
|
20
|
-
element.classes.toggle(className, value.
|
|
20
|
+
element.classes.toggle(className, value.isActive());
|
|
21
21
|
value.subscribe((shouldAdd) => element.classes.toggle(className, shouldAdd));
|
|
22
22
|
continue;
|
|
23
23
|
}
|
|
@@ -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
|
|
|
@@ -103,12 +103,35 @@ NDElement.prototype.closedShadow = function(style = null) {
|
|
|
103
103
|
return this.shadow('closed', style);
|
|
104
104
|
};
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Attaches a template binding to the element by hydrating it with the specified method.
|
|
108
|
+
*
|
|
109
|
+
* @param {string} methodName - Name of the hydration method to call
|
|
110
|
+
* @param {BindingHydrator} bindingHydrator - Template binding with $hydrate method
|
|
111
|
+
* @returns {HTMLElement} The underlying HTML element
|
|
112
|
+
* @example
|
|
113
|
+
* const onClick = $binder.attach((event, data) => console.log(data));
|
|
114
|
+
* element.nd.attach('onClick', onClick);
|
|
115
|
+
*/
|
|
106
116
|
NDElement.prototype.attach = function(methodName, bindingHydrator) {
|
|
107
117
|
bindingHydrator.$hydrate(this.$element, methodName);
|
|
108
118
|
return this.$element;
|
|
109
119
|
};
|
|
110
120
|
|
|
111
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Extends the current NDElement instance with custom methods.
|
|
123
|
+
* Methods are bound to the instance and available for chaining.
|
|
124
|
+
*
|
|
125
|
+
* @param {Object} methods - Object containing method definitions
|
|
126
|
+
* @returns {this} The NDElement instance with added methods for chaining
|
|
127
|
+
* @example
|
|
128
|
+
* element.nd.with({
|
|
129
|
+
* highlight() {
|
|
130
|
+
* this.$element.style.background = 'yellow';
|
|
131
|
+
* return this;
|
|
132
|
+
* }
|
|
133
|
+
* }).highlight().onClick(() => console.log('Clicked'));
|
|
134
|
+
*/
|
|
112
135
|
NDElement.prototype.with = function(methods) {
|
|
113
136
|
if (!methods || typeof methods !== 'object') {
|
|
114
137
|
throw new NativeDocumentError('extend() requires an object of methods');
|
|
@@ -139,6 +162,23 @@ NDElement.prototype.with = function(methods) {
|
|
|
139
162
|
return this;
|
|
140
163
|
}
|
|
141
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Extends the NDElement prototype with new methods available to all NDElement instances.
|
|
167
|
+
* Use this to add global methods to all NDElements.
|
|
168
|
+
*
|
|
169
|
+
* @param {Object} methods - Object containing method definitions to add to prototype
|
|
170
|
+
* @returns {typeof NDElement} The NDElement constructor
|
|
171
|
+
* @throws {NativeDocumentError} If methods is not an object or contains non-function values
|
|
172
|
+
* @example
|
|
173
|
+
* NDElement.extend({
|
|
174
|
+
* fadeIn() {
|
|
175
|
+
* this.$element.style.opacity = '1';
|
|
176
|
+
* return this;
|
|
177
|
+
* }
|
|
178
|
+
* });
|
|
179
|
+
* // Now all NDElements have .fadeIn() method
|
|
180
|
+
* Div().nd.fadeIn();
|
|
181
|
+
*/
|
|
142
182
|
NDElement.extend = function(methods) {
|
|
143
183
|
if (!methods || typeof methods !== 'object') {
|
|
144
184
|
throw new NativeDocumentError('NDElement.extend() requires an object of methods');
|
|
@@ -155,7 +195,7 @@ NDElement.extend = function(methods) {
|
|
|
155
195
|
]);
|
|
156
196
|
|
|
157
197
|
for (const name in methods) {
|
|
158
|
-
if (!
|
|
198
|
+
if (!Object.hasOwn(methods, name)) {
|
|
159
199
|
continue;
|
|
160
200
|
}
|
|
161
201
|
|
|
@@ -38,6 +38,10 @@ EVENTS_WITH_STOP.forEach(eventSourceName => {
|
|
|
38
38
|
_stop(this.$element, eventName, callback);
|
|
39
39
|
return this;
|
|
40
40
|
};
|
|
41
|
+
NDElement.prototype['onPreventStop'+eventSourceName] = function(callback = null) {
|
|
42
|
+
_preventStop(this.$element, eventName, callback);
|
|
43
|
+
return this;
|
|
44
|
+
};
|
|
41
45
|
});
|
|
42
46
|
|
|
43
47
|
EVENTS_WITH_PREVENT.forEach(eventSourceName => {
|
|
@@ -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
|
}
|
|
@@ -65,7 +65,12 @@ const bindAttachMethods = function(node, bindDingData, data) {
|
|
|
65
65
|
|
|
66
66
|
const applyBindingTreePath = (root, target, data, path) => {
|
|
67
67
|
if(path.fn) {
|
|
68
|
-
path.fn
|
|
68
|
+
if(typeof path.fn === 'string') {
|
|
69
|
+
ElementCreator.bindTextNode(target, data[0][path.fn]);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
path.fn(data, target, root);
|
|
73
|
+
}
|
|
69
74
|
}
|
|
70
75
|
if(path.children) {
|
|
71
76
|
for(let i = 0, length = path.children.length; i < length; i++) {
|
|
@@ -91,15 +96,16 @@ export function TemplateCloner($fn) {
|
|
|
91
96
|
if(bindDingData && bindDingData.value) {
|
|
92
97
|
currentPath.fn = bindDingData.value;
|
|
93
98
|
const textNode = node.cloneNode();
|
|
99
|
+
if(typeof bindDingData.value === 'string') {
|
|
100
|
+
ElementCreator.bindTextNode(textNode, data[0][bindDingData.value]);
|
|
101
|
+
return textNode;
|
|
102
|
+
}
|
|
94
103
|
bindDingData.value(data, textNode);
|
|
95
104
|
return textNode;
|
|
96
105
|
}
|
|
97
106
|
return node.cloneNode(true);
|
|
98
107
|
}
|
|
99
|
-
const nodeCloned = node.cloneNode(
|
|
100
|
-
if(node.fullCloneNode) {
|
|
101
|
-
return nodeCloned;
|
|
102
|
-
}
|
|
108
|
+
const nodeCloned = node.cloneNode();
|
|
103
109
|
if(bindDingData) {
|
|
104
110
|
bindAttributes(nodeCloned, bindDingData, data);
|
|
105
111
|
bindAttachMethods(nodeCloned, bindDingData, data);
|
|
@@ -164,12 +170,9 @@ export function TemplateCloner($fn) {
|
|
|
164
170
|
}
|
|
165
171
|
this.value = (callbackOrProperty) => {
|
|
166
172
|
if(typeof callbackOrProperty !== 'function') {
|
|
167
|
-
return createBinding(
|
|
168
|
-
const firstArgument = data[0];
|
|
169
|
-
ElementCreator.bindTextNode(textNode, firstArgument[callbackOrProperty]);
|
|
170
|
-
}, 'value');
|
|
173
|
+
return createBinding(callbackOrProperty, 'value');
|
|
171
174
|
}
|
|
172
|
-
return createBinding(
|
|
175
|
+
return createBinding((data, textNode) => {
|
|
173
176
|
ElementCreator.bindTextNode(textNode, callbackOrProperty(...data));
|
|
174
177
|
}, 'value');
|
|
175
178
|
};
|
|
@@ -9,7 +9,7 @@ ObservableItem.prototype.bindNdClass = function(element, className) {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
ObservableWhen.prototype.bindNdClass = function(element, className) {
|
|
12
|
-
element.classes.toggle(className, this.
|
|
12
|
+
element.classes.toggle(className, this.isMatch());
|
|
13
13
|
this.subscribe((shouldAdd) => element.classes.toggle(className, shouldAdd));
|
|
14
14
|
};
|
|
15
15
|
|
|
@@ -4,6 +4,7 @@ import TemplateBinding from "../TemplateBinding";
|
|
|
4
4
|
import {ElementCreator} from "../ElementCreator";
|
|
5
5
|
import PluginsManager from "../../utils/plugins-manager";
|
|
6
6
|
import Validator from "../../utils/validator";
|
|
7
|
+
import ObservableChecker from "../../data/ObservableChecker";
|
|
7
8
|
|
|
8
9
|
String.prototype.toNdElement = function () {
|
|
9
10
|
const formattedChild = this.resolveObservableTemplate ? this.resolveObservableTemplate() : this;
|
|
@@ -33,6 +34,8 @@ ObservableItem.prototype.toNdElement = function () {
|
|
|
33
34
|
return ElementCreator.createObservableNode(null, this);
|
|
34
35
|
};
|
|
35
36
|
|
|
37
|
+
ObservableChecker.prototype.toNdElement = ObservableItem.prototype.toNdElement;
|
|
38
|
+
|
|
36
39
|
NDElement.prototype.toNdElement = function () {
|
|
37
40
|
return this.$element ?? this.$build?.() ?? this.build?.() ?? null;
|
|
38
41
|
};
|