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,32 +1,169 @@
|
|
|
1
1
|
import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates a `<div>` element.
|
|
5
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLDivElement}
|
|
6
|
+
*/
|
|
3
7
|
export const Div = HtmlElementWrapper('div');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a `<span>` element.
|
|
11
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLSpanElement}
|
|
12
|
+
*/
|
|
4
13
|
export const Span = HtmlElementWrapper('span');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a `<label>` element.
|
|
17
|
+
* @type {function(LabelAttributes=, NdChild|NdChild[]=): HTMLLabelElement}
|
|
18
|
+
*/
|
|
5
19
|
export const Label = HtmlElementWrapper('label');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates a `<p>` element.
|
|
23
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLParagraphElement}
|
|
24
|
+
*/
|
|
6
25
|
export const P = HtmlElementWrapper('p');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Alias for {@link P}.
|
|
29
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLParagraphElement}
|
|
30
|
+
*/
|
|
7
31
|
export const Paragraph = P;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates a `<strong>` element.
|
|
35
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
36
|
+
*/
|
|
8
37
|
export const Strong = HtmlElementWrapper('strong');
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Creates a `<h1>` element.
|
|
41
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLHeadingElement}
|
|
42
|
+
*/
|
|
9
43
|
export const H1 = HtmlElementWrapper('h1');
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Creates a `<h2>` element.
|
|
47
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLHeadingElement}
|
|
48
|
+
*/
|
|
10
49
|
export const H2 = HtmlElementWrapper('h2');
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates a `<h3>` element.
|
|
53
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLHeadingElement}
|
|
54
|
+
*/
|
|
11
55
|
export const H3 = HtmlElementWrapper('h3');
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Creates a `<h4>` element.
|
|
59
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLHeadingElement}
|
|
60
|
+
*/
|
|
12
61
|
export const H4 = HtmlElementWrapper('h4');
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Creates a `<h5>` element.
|
|
65
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLHeadingElement}
|
|
66
|
+
*/
|
|
13
67
|
export const H5 = HtmlElementWrapper('h5');
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Creates a `<h6>` element.
|
|
71
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLHeadingElement}
|
|
72
|
+
*/
|
|
14
73
|
export const H6 = HtmlElementWrapper('h6');
|
|
15
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Creates a `<br>` element.
|
|
77
|
+
* @type {function(GlobalAttributes=): HTMLBRElement}
|
|
78
|
+
*/
|
|
16
79
|
export const Br = HtmlElementWrapper('br');
|
|
17
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Creates an `<a>` element.
|
|
83
|
+
* @type {function(AnchorAttributes=, NdChild|NdChild[]=): HTMLAnchorElement}
|
|
84
|
+
*/
|
|
18
85
|
export const Link = HtmlElementWrapper('a');
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Creates a `<pre>` element.
|
|
89
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLPreElement}
|
|
90
|
+
*/
|
|
19
91
|
export const Pre = HtmlElementWrapper('pre');
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Creates a `<code>` element.
|
|
95
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
96
|
+
*/
|
|
20
97
|
export const Code = HtmlElementWrapper('code');
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Creates a `<blockquote>` element.
|
|
101
|
+
* @type {function(GlobalAttributes & { cite?: string }=, NdChild|NdChild[]=): HTMLQuoteElement}
|
|
102
|
+
*/
|
|
21
103
|
export const Blockquote = HtmlElementWrapper('blockquote');
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Creates an `<hr>` element.
|
|
107
|
+
* @type {function(GlobalAttributes=): HTMLHRElement}
|
|
108
|
+
*/
|
|
22
109
|
export const Hr = HtmlElementWrapper('hr');
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Creates an `<em>` element.
|
|
113
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
114
|
+
*/
|
|
23
115
|
export const Em = HtmlElementWrapper('em');
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Creates a `<small>` element.
|
|
119
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
120
|
+
*/
|
|
24
121
|
export const Small = HtmlElementWrapper('small');
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Creates a `<mark>` element.
|
|
125
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
126
|
+
*/
|
|
25
127
|
export const Mark = HtmlElementWrapper('mark');
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Creates a `<del>` element.
|
|
131
|
+
* @type {function(ModAttributes=, NdChild|NdChild[]=): HTMLModElement}
|
|
132
|
+
*/
|
|
26
133
|
export const Del = HtmlElementWrapper('del');
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Creates an `<ins>` element.
|
|
137
|
+
* @type {function(ModAttributes=, NdChild|NdChild[]=): HTMLModElement}
|
|
138
|
+
*/
|
|
27
139
|
export const Ins = HtmlElementWrapper('ins');
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Creates a `<sub>` element.
|
|
143
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
144
|
+
*/
|
|
28
145
|
export const Sub = HtmlElementWrapper('sub');
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Creates a `<sup>` element.
|
|
149
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
150
|
+
*/
|
|
29
151
|
export const Sup = HtmlElementWrapper('sup');
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Creates an `<abbr>` element.
|
|
155
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
156
|
+
*/
|
|
30
157
|
export const Abbr = HtmlElementWrapper('abbr');
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Creates a `<cite>` element.
|
|
161
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
162
|
+
*/
|
|
31
163
|
export const Cite = HtmlElementWrapper('cite');
|
|
32
|
-
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Creates a `<q>` element.
|
|
167
|
+
* @type {function(GlobalAttributes & { cite?: string }=, NdChild|NdChild[]=): HTMLQuoteElement}
|
|
168
|
+
*/
|
|
169
|
+
export const Quote = HtmlElementWrapper('q');
|
|
@@ -4,8 +4,26 @@ import Validator from "../../utils/validator";
|
|
|
4
4
|
import { ElementCreator } from "../../wrappers/ElementCreator";
|
|
5
5
|
import NativeDocumentError from "../../errors/NativeDocumentError";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Renders items from an ObservableArray with optimized array-specific updates.
|
|
9
|
+
* Provides index observables and handles array mutations efficiently.
|
|
10
|
+
*
|
|
11
|
+
* @param {ObservableArray} data - ObservableArray to iterate over
|
|
12
|
+
* @param {(item: *, index: null|ObservableItem) => NdChild} callback - Function that renders each item (item, indexObservable) => ValidChild
|
|
13
|
+
* @param {Object} [configs={}] - Configuration options
|
|
14
|
+
* @param {boolean} [configs.shouldKeepItemsInCache] - Whether to cache rendered items
|
|
15
|
+
* @param {boolean} [configs.isParentUniqueChild] - When it's the only child of the parent
|
|
16
|
+
* @returns {AnchorDocumentFragment} Fragment managing the list rendering
|
|
17
|
+
* @example
|
|
18
|
+
* const items = Observable.array([1, 2, 3]);
|
|
19
|
+
* ForEachArray(items, (item, index) =>
|
|
20
|
+
* Div({}, `Item ${item} at index ${index.val()}`)
|
|
21
|
+
* );
|
|
22
|
+
*
|
|
23
|
+
* items.push(4); // Automatically updates DOM
|
|
24
|
+
*/
|
|
7
25
|
export function ForEachArray(data, callback, configs = {}) {
|
|
8
|
-
const element = Anchor('ForEach Array');
|
|
26
|
+
const element = Anchor('ForEach Array', configs.isParentUniqueChild);
|
|
9
27
|
const blockEnd = element.endElement();
|
|
10
28
|
const blockStart = element.startElement();
|
|
11
29
|
|
|
@@ -180,7 +198,7 @@ export function ForEachArray(data, callback, configs = {}) {
|
|
|
180
198
|
elementBeforeFirst = firstChildRemoved?.previousSibling;
|
|
181
199
|
|
|
182
200
|
for(let i = 0; i < deleted.length; i++) {
|
|
183
|
-
|
|
201
|
+
removeByItem(deleted[i], garbageFragment);
|
|
184
202
|
}
|
|
185
203
|
}
|
|
186
204
|
} else {
|
|
@@ -7,12 +7,24 @@ import { ElementCreator } from "../../wrappers/ElementCreator";
|
|
|
7
7
|
import NativeDocumentError from "../../errors/NativeDocumentError";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
+
* Renders a list of items from an observable array or object, automatically updating when data changes.
|
|
11
|
+
* Efficiently manages DOM updates by tracking items with keys.
|
|
10
12
|
*
|
|
11
|
-
* @param {Array|Object
|
|
12
|
-
* @param {
|
|
13
|
-
* @param {
|
|
14
|
-
* @param {{
|
|
15
|
-
* @
|
|
13
|
+
* @param {ObservableItem<Array|Object>} data - Observable containing array or object to iterate over
|
|
14
|
+
* @param {(item: *, index: null|ObservableItem) => NdChild} callback - Function that renders each item (item, index) => ValidChild
|
|
15
|
+
* @param {string|Function} [key] - Property name or function to generate unique keys for items
|
|
16
|
+
* @param {Object} [options={}] - Configuration options
|
|
17
|
+
* @param {boolean} [options.shouldKeepItemsInCache=false] - Whether to cache rendered items
|
|
18
|
+
* @returns {AnchorDocumentFragment} Fragment managing the list rendering
|
|
19
|
+
* @example
|
|
20
|
+
* const users = Observable([
|
|
21
|
+
* { id: 1, name: 'John' },
|
|
22
|
+
* { id: 2, name: 'Jane' }
|
|
23
|
+
* ]);
|
|
24
|
+
* ForEach(users, (user) => Div({}, user.name), 'id');
|
|
25
|
+
*
|
|
26
|
+
* // With function key
|
|
27
|
+
* ForEach(items, (item) => Div({}, item), (item) => item.id);
|
|
16
28
|
*/
|
|
17
29
|
export function ForEach(data, callback, key, { shouldKeepItemsInCache = false } = {}) {
|
|
18
30
|
const element = Anchor('ForEach');
|
|
@@ -5,12 +5,18 @@ import Anchor from "../../elements/anchor";
|
|
|
5
5
|
import {ElementCreator} from "../../wrappers/ElementCreator";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Conditionally shows an element based on an observable condition.
|
|
9
|
+
* The element is mounted/unmounted from the DOM as the condition changes.
|
|
9
10
|
*
|
|
10
|
-
* @param {ObservableItem
|
|
11
|
-
* @param {
|
|
12
|
-
* @param {{
|
|
13
|
-
* @
|
|
11
|
+
* @param {ObservableItem<boolean>|ObservableChecker<boolean>|ObservableWhen} condition - Observable condition to watch
|
|
12
|
+
* @param {NdChild|(() => NdChild)} child - Element or content to show/hide
|
|
13
|
+
* @param {Object} [options={}] - Configuration options
|
|
14
|
+
* @param {string|null} [options.comment=null] - Comment for debugging
|
|
15
|
+
* @param {boolean} [options.shouldKeepInCache=true] - Whether to cache the element when hidden
|
|
16
|
+
* @returns {AnchorDocumentFragment} Anchor fragment managing the conditional content
|
|
17
|
+
* @example
|
|
18
|
+
* const isVisible = Observable(false);
|
|
19
|
+
* ShowIf(isVisible, Div({}, 'Hello World'));
|
|
14
20
|
*/
|
|
15
21
|
export const ShowIf = function(condition, child, { comment = null, shouldKeepInCache = true} = {}) {
|
|
16
22
|
if(!(Validator.isObservable(condition)) && !Validator.isObservableWhenResult(condition)) {
|
|
@@ -47,11 +53,18 @@ export const ShowIf = function(condition, child, { comment = null, shouldKeepInC
|
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* @param {
|
|
54
|
-
* @
|
|
56
|
+
* Conditionally hides an element when the observable condition is true.
|
|
57
|
+
* Inverse of ShowIf - element is shown when condition is false.
|
|
58
|
+
*
|
|
59
|
+
* @param {ObservableItem<boolean>|ObservableChecker<boolean>} condition - Observable condition to watch
|
|
60
|
+
* @param {NdChild|(() => NdChild)} child - Element or content to show/hide
|
|
61
|
+
* @param {Object} [configs] - Configuration options
|
|
62
|
+
* @param {string|null} [configs.comment] - Comment for debugging
|
|
63
|
+
* @param {boolean} [configs.shouldKeepInCache] - Whether to cache element when hidden
|
|
64
|
+
* @returns {AnchorDocumentFragment} Anchor fragment managing the conditional content
|
|
65
|
+
* @example
|
|
66
|
+
* const hasError = Observable(false);
|
|
67
|
+
* HideIf(hasError, Div({}, 'Content'));
|
|
55
68
|
*/
|
|
56
69
|
export const HideIf = function(condition, child, configs) {
|
|
57
70
|
const hideCondition = Observable(!condition.val());
|
|
@@ -61,12 +74,15 @@ export const HideIf = function(condition, child, configs) {
|
|
|
61
74
|
}
|
|
62
75
|
|
|
63
76
|
/**
|
|
64
|
-
*
|
|
77
|
+
* Conditionally hides an element when the observable condition is false.
|
|
78
|
+
* Same as ShowIf - element is shown when condition is true.
|
|
65
79
|
*
|
|
66
|
-
* @param {ObservableItem
|
|
67
|
-
* @param {
|
|
68
|
-
* @param {
|
|
69
|
-
* @
|
|
80
|
+
* @param {ObservableItem<boolean>|ObservableChecker<boolean>|ObservableWhen} condition - Observable condition to watch
|
|
81
|
+
* @param {NdChild|(() => NdChild)} child - Element or content to show/hide
|
|
82
|
+
* @param {Object} [configs] - Configuration options
|
|
83
|
+
* @param {string|null} [configs.comment] - Comment for debugging
|
|
84
|
+
* @param {boolean} [configs.shouldKeepInCache] - Whether to cache element when hidden
|
|
85
|
+
* @returns {AnchorDocumentFragment} Anchor fragment managing the conditional content
|
|
70
86
|
*/
|
|
71
87
|
export const HideIfNot = function(condition, child, configs) {
|
|
72
88
|
return ShowIf(condition, child, configs);
|
|
@@ -2,6 +2,29 @@ import Validator from "../../utils/validator.js";
|
|
|
2
2
|
import NativeDocumentError from "../../errors/NativeDocumentError.js";
|
|
3
3
|
import {ShowIf} from "./show-if.js";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Shows content when an observable equals a specific value.
|
|
7
|
+
* Can be called with 2 or 3 arguments.
|
|
8
|
+
*
|
|
9
|
+
* @overload
|
|
10
|
+
* @param {ObservableWhen} observerWhenResult - Result from observable.when(value)
|
|
11
|
+
* @param {NdChild|(() => NdChild)} view - Content to show when condition matches
|
|
12
|
+
* @returns {AnchorDocumentFragment}
|
|
13
|
+
*
|
|
14
|
+
* @overload
|
|
15
|
+
* @param {ObservableItem} observer - Observable to watch
|
|
16
|
+
* @param {*} target - Value to match
|
|
17
|
+
* @param {NdChild|(() => NdChild)} view - Content to show when observable equals target
|
|
18
|
+
* @returns {AnchorDocumentFragment}
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // 2 arguments
|
|
22
|
+
* const status = Observable('idle');
|
|
23
|
+
* ShowWhen(status.when('loading'), LoadingSpinner());
|
|
24
|
+
*
|
|
25
|
+
* // 3 arguments
|
|
26
|
+
* ShowWhen(status, 'loading', LoadingSpinner());
|
|
27
|
+
*/
|
|
5
28
|
export const ShowWhen = function() {
|
|
6
29
|
if(arguments.length === 2) {
|
|
7
30
|
const [observer, target] = arguments;
|
|
@@ -6,11 +6,24 @@ import {ElementCreator} from "../../wrappers/ElementCreator";
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
+
* Displays different content based on the current value of an observable.
|
|
10
|
+
* Like a switch statement for UI - shows the content corresponding to current value.
|
|
9
11
|
*
|
|
10
|
-
* @param {ObservableItem|ObservableChecker} $condition
|
|
11
|
-
* @param {
|
|
12
|
-
* @param {
|
|
13
|
-
* @returns {
|
|
12
|
+
* @param {ObservableItem|ObservableChecker} $condition - Observable to watch
|
|
13
|
+
* @param {Object<string|number, NdChild|(() => NdChild)>} values - Map of values to their corresponding content
|
|
14
|
+
* @param {boolean} [shouldKeepInCache=true] - Whether to cache rendered views
|
|
15
|
+
* @returns {AnchorDocumentFragment & {add: Function, remove: Function}} Fragment with dynamic methods
|
|
16
|
+
* @example
|
|
17
|
+
* const status = Observable('idle');
|
|
18
|
+
* const view = Match(status, {
|
|
19
|
+
* idle: Div({}, 'Ready'),
|
|
20
|
+
* loading: Div({}, 'Loading...'),
|
|
21
|
+
* error: Div({}, 'Error occurred')
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // Dynamic addition
|
|
25
|
+
* view.add('success', Div({}, 'Success!'));
|
|
26
|
+
* view.remove('idle');
|
|
14
27
|
*/
|
|
15
28
|
export const Match = function($condition, values, shouldKeepInCache = true) {
|
|
16
29
|
|
|
@@ -67,11 +80,19 @@ export const Match = function($condition, values, shouldKeepInCache = true) {
|
|
|
67
80
|
|
|
68
81
|
|
|
69
82
|
/**
|
|
83
|
+
* Displays one of two views based on a boolean observable condition.
|
|
84
|
+
* Simplified version of Match for true/false cases.
|
|
70
85
|
*
|
|
71
|
-
* @param {ObservableItem
|
|
72
|
-
* @param {
|
|
73
|
-
* @param {
|
|
74
|
-
* @returns {
|
|
86
|
+
* @param {ObservableItem<boolean>|ObservableChecker<boolean>} $condition - Boolean observable to watch
|
|
87
|
+
* @param {ValidChild} onTrue - Content to show when condition is true
|
|
88
|
+
* @param {ValidChild} onFalse - Content to show when condition is false
|
|
89
|
+
* @returns {AnchorDocumentFragment} Fragment managing the conditional content
|
|
90
|
+
* @example
|
|
91
|
+
* const isLoggedIn = Observable(false);
|
|
92
|
+
* Switch(isLoggedIn,
|
|
93
|
+
* Div({}, 'Welcome back!'),
|
|
94
|
+
* Div({}, 'Please login')
|
|
95
|
+
* );
|
|
75
96
|
*/
|
|
76
97
|
export const Switch = function ($condition, onTrue, onFalse) {
|
|
77
98
|
if(!Validator.isObservable($condition)) {
|
|
@@ -85,9 +106,15 @@ export const Switch = function ($condition, onTrue, onFalse) {
|
|
|
85
106
|
}
|
|
86
107
|
|
|
87
108
|
/**
|
|
109
|
+
* Provides a fluent API for conditional rendering with show/otherwise pattern.
|
|
88
110
|
*
|
|
89
|
-
* @param {ObservableItem
|
|
90
|
-
* @returns {{show: Function, otherwise:
|
|
111
|
+
* @param {ObservableItem<boolean>|ObservableChecker<boolean>} $condition - Boolean observable to watch
|
|
112
|
+
* @returns {{show: Function, otherwise: Function}} Object with fluent methods
|
|
113
|
+
* @example
|
|
114
|
+
* const isLoading = Observable(false);
|
|
115
|
+
* When(isLoading)
|
|
116
|
+
* .show(LoadingSpinner())
|
|
117
|
+
* .otherwise(Content());
|
|
91
118
|
*/
|
|
92
119
|
export const When = function($condition) {
|
|
93
120
|
if(!Validator.isObservable($condition)) {
|
|
@@ -105,6 +132,9 @@ export const When = function($condition) {
|
|
|
105
132
|
otherwise(onFalse) {
|
|
106
133
|
$onFalse = onFalse;
|
|
107
134
|
return Switch($condition, $onTrue, $onFalse);
|
|
135
|
+
},
|
|
136
|
+
toNdElement() {
|
|
137
|
+
return Switch($condition, $onTrue, $onFalse);
|
|
108
138
|
}
|
|
109
139
|
}
|
|
110
140
|
}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates a `<dl>` element.
|
|
5
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLDListElement}
|
|
6
|
+
*/
|
|
3
7
|
export const Dl = HtmlElementWrapper('dl');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a `<dt>` element.
|
|
11
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
12
|
+
*/
|
|
4
13
|
export const Dt = HtmlElementWrapper('dt');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a `<dd>` element.
|
|
17
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLElement}
|
|
18
|
+
*/
|
|
5
19
|
export const Dd = HtmlElementWrapper('dd');
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Creates a `<form>` element.
|
|
6
|
+
* Extended with fluent methods: `.submit()`, `.post()`, `.get()`, `.multipartFormData()`.
|
|
7
|
+
* @type {function(FormAttributes=, NdChild|NdChild[]=): HTMLFormElement & {
|
|
8
|
+
* submit: (actionOrFn: string | ((e: SubmitEvent) => void)) => HTMLFormElement,
|
|
9
|
+
* post: (action: string) => HTMLFormElement,
|
|
10
|
+
* get: (action: string) => HTMLFormElement,
|
|
11
|
+
* multipartFormData: () => HTMLFormElement,
|
|
12
|
+
* }}
|
|
13
|
+
*/
|
|
4
14
|
export const Form = HtmlElementWrapper('form', function(el) {
|
|
5
15
|
|
|
6
16
|
el.submit = function(action) {
|
|
@@ -30,42 +40,216 @@ export const Form = HtmlElementWrapper('form', function(el) {
|
|
|
30
40
|
return el;
|
|
31
41
|
});
|
|
32
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Creates an `<input>` element.
|
|
45
|
+
* @type {function(InputAttributes=): HTMLInputElement}
|
|
46
|
+
*/
|
|
33
47
|
export const Input = HtmlElementWrapper('input');
|
|
34
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Creates a `<textarea>` element.
|
|
51
|
+
* @type {function(TextAreaAttributes=, NdChild|NdChild[]=): HTMLTextAreaElement}
|
|
52
|
+
*/
|
|
35
53
|
export const TextArea = HtmlElementWrapper('textarea');
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Alias for {@link TextArea}.
|
|
57
|
+
* @type {function(TextAreaAttributes=, NdChild|NdChild[]=): HTMLTextAreaElement}
|
|
58
|
+
*/
|
|
36
59
|
export const TextInput = TextArea;
|
|
37
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Creates a `<select>` element.
|
|
63
|
+
* @type {function(SelectAttributes=, NdChild|NdChild[]=): HTMLSelectElement}
|
|
64
|
+
*/
|
|
38
65
|
export const Select = HtmlElementWrapper('select');
|
|
39
|
-
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Creates a `<fieldset>` element.
|
|
69
|
+
* @type {function(GlobalAttributes & { disabled?: Observable<boolean>|boolean }=, NdChild|NdChild[]=): HTMLFieldSetElement}
|
|
70
|
+
*/
|
|
71
|
+
export const FieldSet = HtmlElementWrapper('fieldset');
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Creates an `<option>` element.
|
|
75
|
+
* @type {function(OptionAttributes=, NdChild|NdChild[]=): HTMLOptionElement}
|
|
76
|
+
*/
|
|
40
77
|
export const Option = HtmlElementWrapper('option');
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Creates a `<legend>` element.
|
|
81
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLLegendElement}
|
|
82
|
+
*/
|
|
41
83
|
export const Legend = HtmlElementWrapper('legend');
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Creates a `<datalist>` element.
|
|
87
|
+
* @type {function(GlobalAttributes=, NdChild|NdChild[]=): HTMLDataListElement}
|
|
88
|
+
*/
|
|
42
89
|
export const Datalist = HtmlElementWrapper('datalist');
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Creates an `<output>` element.
|
|
93
|
+
* @type {function(OutputAttributes=, NdChild|NdChild[]=): HTMLOutputElement}
|
|
94
|
+
*/
|
|
43
95
|
export const Output = HtmlElementWrapper('output');
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Creates a `<progress>` element.
|
|
99
|
+
* @type {function(ProgressAttributes=, NdChild|NdChild[]=): HTMLProgressElement}
|
|
100
|
+
*/
|
|
44
101
|
export const Progress = HtmlElementWrapper('progress');
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Creates a `<meter>` element.
|
|
105
|
+
* @type {function(MeterAttributes=, NdChild|NdChild[]=): HTMLMeterElement}
|
|
106
|
+
*/
|
|
45
107
|
export const Meter = HtmlElementWrapper('meter');
|
|
46
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Creates an `<input readonly>` element.
|
|
111
|
+
* @param {Omit<InputAttributes, 'type'|'readonly'|'readOnly'>} [attributes]
|
|
112
|
+
* @returns {HTMLInputElement}
|
|
113
|
+
*/
|
|
47
114
|
export const ReadonlyInput = (attributes) => Input({ readonly: true, ...attributes });
|
|
48
|
-
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Creates an `<input type="hidden">` element.
|
|
118
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
119
|
+
* @returns {HTMLInputElement}
|
|
120
|
+
*/
|
|
121
|
+
export const HiddenInput = (attributes) => Input({ type: 'hidden', ...attributes });
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Creates an `<input type="file">` element.
|
|
125
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
126
|
+
* @returns {HTMLInputElement}
|
|
127
|
+
*/
|
|
49
128
|
export const FileInput = (attributes) => Input({ type: 'file', ...attributes });
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Creates an `<input type="password">` element.
|
|
132
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
133
|
+
* @returns {HTMLInputElement}
|
|
134
|
+
*/
|
|
50
135
|
export const PasswordInput = (attributes) => Input({ type: 'password', ...attributes });
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Creates an `<input type="checkbox">` element.
|
|
139
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
140
|
+
* @returns {HTMLInputElement}
|
|
141
|
+
*/
|
|
51
142
|
export const Checkbox = (attributes) => Input({ type: 'checkbox', ...attributes });
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Creates an `<input type="radio">` element.
|
|
146
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
147
|
+
* @returns {HTMLInputElement}
|
|
148
|
+
*/
|
|
52
149
|
export const Radio = (attributes) => Input({ type: 'radio', ...attributes });
|
|
53
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Creates an `<input type="range">` element.
|
|
153
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
154
|
+
* @returns {HTMLInputElement}
|
|
155
|
+
*/
|
|
54
156
|
export const RangeInput = (attributes) => Input({ type: 'range', ...attributes });
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Creates an `<input type="color">` element.
|
|
160
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
161
|
+
* @returns {HTMLInputElement}
|
|
162
|
+
*/
|
|
55
163
|
export const ColorInput = (attributes) => Input({ type: 'color', ...attributes });
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Creates an `<input type="date">` element.
|
|
167
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
168
|
+
* @returns {HTMLInputElement}
|
|
169
|
+
*/
|
|
56
170
|
export const DateInput = (attributes) => Input({ type: 'date', ...attributes });
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Creates an `<input type="time">` element.
|
|
174
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
175
|
+
* @returns {HTMLInputElement}
|
|
176
|
+
*/
|
|
57
177
|
export const TimeInput = (attributes) => Input({ type: 'time', ...attributes });
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Creates an `<input type="datetime-local">` element.
|
|
181
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
182
|
+
* @returns {HTMLInputElement}
|
|
183
|
+
*/
|
|
58
184
|
export const DateTimeInput = (attributes) => Input({ type: 'datetime-local', ...attributes });
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Creates an `<input type="week">` element.
|
|
188
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
189
|
+
* @returns {HTMLInputElement}
|
|
190
|
+
*/
|
|
59
191
|
export const WeekInput = (attributes) => Input({ type: 'week', ...attributes });
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Creates an `<input type="month">` element.
|
|
195
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
196
|
+
* @returns {HTMLInputElement}
|
|
197
|
+
*/
|
|
60
198
|
export const MonthInput = (attributes) => Input({ type: 'month', ...attributes });
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Creates an `<input type="search">` element.
|
|
202
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
203
|
+
* @returns {HTMLInputElement}
|
|
204
|
+
*/
|
|
61
205
|
export const SearchInput = (attributes) => Input({ type: 'search', ...attributes });
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Creates an `<input type="tel">` element.
|
|
209
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
210
|
+
* @returns {HTMLInputElement}
|
|
211
|
+
*/
|
|
62
212
|
export const TelInput = (attributes) => Input({ type: 'tel', ...attributes });
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Creates an `<input type="url">` element.
|
|
216
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
217
|
+
* @returns {HTMLInputElement}
|
|
218
|
+
*/
|
|
63
219
|
export const UrlInput = (attributes) => Input({ type: 'url', ...attributes });
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Creates an `<input type="email">` element.
|
|
223
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
224
|
+
* @returns {HTMLInputElement}
|
|
225
|
+
*/
|
|
64
226
|
export const EmailInput = (attributes) => Input({ type: 'email', ...attributes });
|
|
65
|
-
export const NumberInput = (attributes) => Input({ type: 'number', ...attributes });
|
|
66
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Creates an `<input type="number">` element.
|
|
230
|
+
* @param {Omit<InputAttributes, 'type'>} [attributes]
|
|
231
|
+
* @returns {HTMLInputElement}
|
|
232
|
+
*/
|
|
233
|
+
export const NumberInput = (attributes) => Input({ type: 'number', ...attributes });
|
|
67
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Creates a `<button>` element.
|
|
237
|
+
* @type {function(ButtonAttributes=, NdChild|NdChild[]=): HTMLButtonElement}
|
|
238
|
+
*/
|
|
68
239
|
export const Button = HtmlElementWrapper('button');
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Creates a `<button type="button">` element.
|
|
243
|
+
* @param {NdChild|NdChild[]} [child]
|
|
244
|
+
* @param {Omit<ButtonAttributes, 'type'>} [attributes]
|
|
245
|
+
* @returns {HTMLButtonElement}
|
|
246
|
+
*/
|
|
69
247
|
export const SimpleButton = (child, attributes) => Button(child, { type: 'button', ...attributes });
|
|
70
|
-
export const SubmitButton = (child, attributes) => Button(child, { type: 'submit', ...attributes });
|
|
71
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Creates a `<button type="submit">` element.
|
|
251
|
+
* @param {NdChild|NdChild[]} [child]
|
|
252
|
+
* @param {Omit<ButtonAttributes, 'type'>} [attributes]
|
|
253
|
+
* @returns {HTMLButtonElement}
|
|
254
|
+
*/
|
|
255
|
+
export const SubmitButton = (child, attributes) => Button(child, { type: 'submit', ...attributes });
|