@granularjs/core 1.0.0

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.
Files changed (70) hide show
  1. package/README.md +576 -0
  2. package/dist/granular.min.js +2 -0
  3. package/dist/granular.min.js.map +7 -0
  4. package/package.json +54 -0
  5. package/src/core/bootstrap.js +63 -0
  6. package/src/core/collections/observable-array.js +204 -0
  7. package/src/core/component/function-component.js +82 -0
  8. package/src/core/context.js +172 -0
  9. package/src/core/dom/dom.js +25 -0
  10. package/src/core/dom/element.js +725 -0
  11. package/src/core/dom/error-boundary.js +111 -0
  12. package/src/core/dom/input-format.js +82 -0
  13. package/src/core/dom/list.js +185 -0
  14. package/src/core/dom/portal.js +57 -0
  15. package/src/core/dom/tags.js +182 -0
  16. package/src/core/dom/virtual-list.js +242 -0
  17. package/src/core/dom/when.js +138 -0
  18. package/src/core/events/event-hub.js +97 -0
  19. package/src/core/forms/form.js +127 -0
  20. package/src/core/internal/symbols.js +5 -0
  21. package/src/core/network/websocket.js +165 -0
  22. package/src/core/query/query-client.js +529 -0
  23. package/src/core/reactivity/after-flush.js +20 -0
  24. package/src/core/reactivity/computed.js +51 -0
  25. package/src/core/reactivity/concat.js +89 -0
  26. package/src/core/reactivity/dirty-host.js +162 -0
  27. package/src/core/reactivity/observe.js +421 -0
  28. package/src/core/reactivity/persist.js +180 -0
  29. package/src/core/reactivity/resolve.js +8 -0
  30. package/src/core/reactivity/signal.js +97 -0
  31. package/src/core/reactivity/state.js +294 -0
  32. package/src/core/renderable/render-string.js +51 -0
  33. package/src/core/renderable/renderable.js +21 -0
  34. package/src/core/renderable/renderer.js +66 -0
  35. package/src/core/router/router.js +865 -0
  36. package/src/core/runtime.js +28 -0
  37. package/src/index.js +42 -0
  38. package/types/core/bootstrap.d.ts +11 -0
  39. package/types/core/collections/observable-array.d.ts +25 -0
  40. package/types/core/component/function-component.d.ts +14 -0
  41. package/types/core/context.d.ts +29 -0
  42. package/types/core/dom/dom.d.ts +13 -0
  43. package/types/core/dom/element.d.ts +10 -0
  44. package/types/core/dom/error-boundary.d.ts +8 -0
  45. package/types/core/dom/input-format.d.ts +6 -0
  46. package/types/core/dom/list.d.ts +8 -0
  47. package/types/core/dom/portal.d.ts +8 -0
  48. package/types/core/dom/tags.d.ts +114 -0
  49. package/types/core/dom/virtual-list.d.ts +8 -0
  50. package/types/core/dom/when.d.ts +13 -0
  51. package/types/core/events/event-hub.d.ts +48 -0
  52. package/types/core/forms/form.d.ts +9 -0
  53. package/types/core/internal/symbols.d.ts +4 -0
  54. package/types/core/network/websocket.d.ts +18 -0
  55. package/types/core/query/query-client.d.ts +73 -0
  56. package/types/core/reactivity/after-flush.d.ts +4 -0
  57. package/types/core/reactivity/computed.d.ts +1 -0
  58. package/types/core/reactivity/concat.d.ts +1 -0
  59. package/types/core/reactivity/dirty-host.d.ts +42 -0
  60. package/types/core/reactivity/observe.d.ts +10 -0
  61. package/types/core/reactivity/persist.d.ts +1 -0
  62. package/types/core/reactivity/resolve.d.ts +1 -0
  63. package/types/core/reactivity/signal.d.ts +11 -0
  64. package/types/core/reactivity/state.d.ts +14 -0
  65. package/types/core/renderable/render-string.d.ts +2 -0
  66. package/types/core/renderable/renderable.d.ts +15 -0
  67. package/types/core/renderable/renderer.d.ts +38 -0
  68. package/types/core/router/router.d.ts +57 -0
  69. package/types/core/runtime.d.ts +26 -0
  70. package/types/index.d.ts +2 -0
@@ -0,0 +1,111 @@
1
+ import { Renderable } from '../renderable/renderable.js';
2
+ import { Renderer } from '../renderable/renderer.js';
3
+ import { createComment, clearBetween } from './dom.js';
4
+
5
+ export class ErrorBoundaryNode extends Renderable {
6
+ #fallback;
7
+ #onError;
8
+ #child;
9
+ #start = null;
10
+ #end = null;
11
+ #mounted = false;
12
+ #mountedValues = [];
13
+
14
+ constructor(options, child) {
15
+ super();
16
+ this.#fallback = options?.fallback ?? null;
17
+ this.#onError = options?.onError ?? null;
18
+ this.#child = child;
19
+ }
20
+
21
+ mountInto(parent, beforeNode) {
22
+ if (this.#mounted) return;
23
+ this.#mounted = true;
24
+ this.#start = createComment('zb:error:start', 'error');
25
+ this.#end = createComment('zb:error:end', 'error');
26
+ parent.insertBefore(this.#start, beforeNode);
27
+ parent.insertBefore(this.#end, beforeNode);
28
+ this.#renderSafe();
29
+ }
30
+
31
+ unmount() {
32
+ if (!this.#mounted) return;
33
+ this.#mounted = false;
34
+ this.#cleanup();
35
+ if (this.#start && this.#end) {
36
+ clearBetween(this.#start, this.#end);
37
+ this.#start.remove();
38
+ this.#end.remove();
39
+ }
40
+ this.#start = null;
41
+ this.#end = null;
42
+ }
43
+
44
+ #cleanup() {
45
+ for (const r of this.#mountedValues) Renderer.unmount(r);
46
+ this.#mountedValues = [];
47
+ if (this.#start && this.#end) clearBetween(this.#start, this.#end);
48
+ }
49
+
50
+ #renderValue(value) {
51
+ const values = Renderer.normalize(value);
52
+ this.#mountedValues = values;
53
+ for (const r of values) {
54
+ if (Renderer.isRenderable(r)) {
55
+ r.mountInto(this.#end.parentNode, this.#end);
56
+ } else if (Renderer.isDomNode(r)) {
57
+ this.#end.parentNode.insertBefore(r, this.#end);
58
+ }
59
+ }
60
+ }
61
+
62
+ #renderSafe() {
63
+ this.#cleanup();
64
+ try {
65
+ const value = typeof this.#child === 'function' ? this.#child() : this.#child;
66
+ this.#renderValue(value);
67
+ } catch (error) {
68
+ this.#handleError(error);
69
+ }
70
+ }
71
+
72
+ #handleError(error) {
73
+ try {
74
+ if (typeof this.#onError === 'function') {
75
+ this.#onError(error, { phase: 'render' });
76
+ }
77
+ } catch {
78
+ // ignore errors from onError
79
+ }
80
+ try {
81
+ if (this.#fallback) {
82
+ const value = typeof this.#fallback === 'function' ? this.#fallback(error) : this.#fallback;
83
+ this.#renderValue(value);
84
+ }
85
+ } catch {
86
+ // ignore errors from fallback
87
+ }
88
+ }
89
+
90
+ renderToString(render) {
91
+ try {
92
+ const value = typeof this.#child === 'function' ? this.#child() : this.#child;
93
+ return render(value);
94
+ } catch (error) {
95
+ if (typeof this.#onError === 'function') {
96
+ try {
97
+ this.#onError(error, { phase: 'render' });
98
+ } catch {}
99
+ }
100
+ if (this.#fallback) {
101
+ const fallback = typeof this.#fallback === 'function' ? this.#fallback(error) : this.#fallback;
102
+ return render(fallback);
103
+ }
104
+ return '';
105
+ }
106
+ }
107
+ }
108
+
109
+ export function ErrorBoundary(options, child) {
110
+ return new ErrorBoundaryNode(options, child);
111
+ }
@@ -0,0 +1,82 @@
1
+ const tokenMatchers = {
2
+ d: (char) => /[0-9]/.test(char),
3
+ a: (char) => /[A-Za-z]/.test(char),
4
+ '*': (char) => /[A-Za-z0-9]/.test(char),
5
+ s: (char) => /[^A-Za-z0-9]/.test(char),
6
+ };
7
+
8
+ const isToken = (char) => Object.prototype.hasOwnProperty.call(tokenMatchers, char);
9
+
10
+ function collectPatternValues(input, pattern) {
11
+ const values = [];
12
+ let patternIndex = 0;
13
+ for (const char of input) {
14
+ while (patternIndex < pattern.length && !isToken(pattern[patternIndex])) {
15
+ patternIndex += 1;
16
+ }
17
+ if (patternIndex >= pattern.length) break;
18
+ const token = pattern[patternIndex];
19
+ if (tokenMatchers[token]?.(char)) {
20
+ values.push(char);
21
+ patternIndex += 1;
22
+ }
23
+ }
24
+ return values;
25
+ }
26
+
27
+ function applyPattern(input, pattern) {
28
+ const values = collectPatternValues(input, pattern);
29
+ let visual = '';
30
+ let valueIndex = 0;
31
+ for (let i = 0; i < pattern.length; i += 1) {
32
+ const char = pattern[i];
33
+ if (isToken(char)) {
34
+ if (valueIndex >= values.length) break;
35
+ visual += values[valueIndex];
36
+ valueIndex += 1;
37
+ continue;
38
+ }
39
+ if (valueIndex === 0) continue;
40
+ if (valueIndex < values.length) visual += char;
41
+ }
42
+ return { raw: values.join(''), visual };
43
+ }
44
+
45
+ export function normalizeInputFormat(format) {
46
+ if (format == null) return null;
47
+ if (typeof format === 'function') return { format, mode: 'both' };
48
+ if (typeof format === 'string') return { pattern: format, mode: 'both' };
49
+ if (typeof format === 'object') return { mode: 'both', ...format };
50
+ return null;
51
+ }
52
+
53
+ export function applyInputFormat(inputValue, format) {
54
+ const normalized = normalizeInputFormat(format);
55
+ const rawInput = String(inputValue ?? '');
56
+ if (!normalized) {
57
+ return { value: rawInput, visual: rawInput, raw: rawInput };
58
+ }
59
+ if (typeof normalized.format === 'function') {
60
+ let formatted = rawInput;
61
+ try {
62
+ formatted = normalized.format(rawInput);
63
+ } catch {}
64
+ if (formatted && typeof formatted === 'object') {
65
+ const value = formatted.value ?? formatted.visual ?? '';
66
+ const visual = formatted.visual ?? formatted.value ?? '';
67
+ const raw = formatted.raw ?? value ?? '';
68
+ return { value: String(value), visual: String(visual), raw: String(raw) };
69
+ }
70
+ return { value: String(formatted ?? ''), visual: String(formatted ?? ''), raw: String(formatted ?? '') };
71
+ }
72
+ if (normalized.pattern) {
73
+ const { raw, visual } = applyPattern(rawInput, String(normalized.pattern));
74
+ return { value: visual, visual, raw };
75
+ }
76
+ if (normalized.regex) {
77
+ const match = rawInput.match(normalized.regex);
78
+ const formatted = match ? match[0] : '';
79
+ return { value: formatted, visual: formatted, raw: formatted };
80
+ }
81
+ return { value: rawInput, visual: rawInput, raw: rawInput };
82
+ }
@@ -0,0 +1,185 @@
1
+ import { Renderable } from '../renderable/renderable.js';
2
+ import { Renderer } from '../renderable/renderer.js';
3
+ import { isObservableArray } from '../collections/observable-array.js';
4
+ import { createComment, clearBetween } from './dom.js';
5
+ import { signal, setSignal, isSignal, readSignal, subscribeSignal } from '../reactivity/signal.js';
6
+ import { state, isState, isStatePath, readState, subscribeState } from '../reactivity/state.js';
7
+
8
+ export class ListNode extends Renderable {
9
+ #items;
10
+ #renderItem;
11
+ #start = null;
12
+ #end = null;
13
+ #mounted = false;
14
+ #unsub = null;
15
+ #itemRefs = [];
16
+
17
+ constructor(items, renderItem) {
18
+ super();
19
+ this.#items = items;
20
+ this.#renderItem = renderItem;
21
+ }
22
+
23
+ mountInto(parent, beforeNode) {
24
+ if (this.#mounted) return;
25
+ this.#mounted = true;
26
+ this.#start = createComment('zb:list:start', 'list');
27
+ this.#end = createComment('zb:list:end', 'list');
28
+ parent.insertBefore(this.#start, beforeNode);
29
+ parent.insertBefore(this.#end, beforeNode);
30
+
31
+ const initial = this.#readItems();
32
+ this.#mountAll(initial);
33
+ this.#wire();
34
+ }
35
+
36
+ unmount() {
37
+ if (!this.#mounted) return;
38
+ this.#mounted = false;
39
+ if (this.#unsub) this.#unsub();
40
+ this.#unsub = null;
41
+ this.#cleanup();
42
+ if (this.#start && this.#end) {
43
+ clearBetween(this.#start, this.#end);
44
+ this.#start.remove();
45
+ this.#end.remove();
46
+ }
47
+ this.#start = null;
48
+ this.#end = null;
49
+ }
50
+
51
+ renderToString(render) {
52
+ const items = this.#readItems();
53
+ return items.map((item, index) => {
54
+ const itemState = state(item);
55
+ const indexSignal = signal(index);
56
+ return render(this.#renderItem(itemState, indexSignal));
57
+ }).join('');
58
+ }
59
+
60
+ #readItems() {
61
+ if (isObservableArray(this.#items)) return this.#items;
62
+ if (isSignal(this.#items)) return readSignal(this.#items) || [];
63
+ if (isState(this.#items) || isStatePath(this.#items)) return readState(this.#items) || [];
64
+ return Array.isArray(this.#items) ? this.#items : [];
65
+ }
66
+
67
+ #wire() {
68
+ if (isObservableArray(this.#items)) {
69
+ this.#unsub = this.#items.subscribe((patch) => {
70
+ if (!this.#mounted) return;
71
+ if (patch.type === 'reset') {
72
+ this.#reset(patch.items);
73
+ return;
74
+ }
75
+ if (patch.type === 'insert') {
76
+ for (let i = 0; i < patch.items.length; i++) {
77
+ this.#insert(patch.index + i, patch.items[i]);
78
+ }
79
+ this.#updateIndices(patch.index + patch.items.length);
80
+ return;
81
+ }
82
+ if (patch.type === 'remove') {
83
+ this.#remove(patch.index, patch.count);
84
+ this.#updateIndices(patch.index);
85
+ return;
86
+ }
87
+ if (patch.type === 'set') {
88
+ this.#set(patch.index, patch.value);
89
+ }
90
+ });
91
+ return;
92
+ }
93
+
94
+ if (isSignal(this.#items)) {
95
+ this.#unsub = subscribeSignal(this.#items, () => {
96
+ this.#reset(this.#readItems());
97
+ });
98
+ return;
99
+ }
100
+
101
+ if (isState(this.#items) || isStatePath(this.#items)) {
102
+ this.#unsub = subscribeState(this.#items, () => {
103
+ this.#reset(this.#readItems());
104
+ });
105
+ }
106
+ }
107
+
108
+ #mountAll(items) {
109
+ this.#itemRefs = [];
110
+ for (let i = 0; i < items.length; i++) {
111
+ this.#insert(i, items[i]);
112
+ }
113
+ }
114
+
115
+ #cleanup() {
116
+ for (const it of this.#itemRefs) {
117
+ for (const r of it.values) Renderer.unmount(r);
118
+ clearBetween(it.start, it.end);
119
+ it.start.remove();
120
+ it.end.remove();
121
+ }
122
+ this.#itemRefs = [];
123
+ }
124
+
125
+ #reset(items) {
126
+ this.#cleanup();
127
+ this.#mountAll(items);
128
+ }
129
+
130
+ #insert(index, item) {
131
+ const refNode = index < this.#itemRefs.length ? this.#itemRefs[index].start : this.#end;
132
+ const itemStart = createComment('zb:item:start', 'item');
133
+ const itemEnd = createComment('zb:item:end', 'item');
134
+ const parent = this.#end.parentNode;
135
+ parent.insertBefore(itemStart, refNode);
136
+ parent.insertBefore(itemEnd, refNode);
137
+ const itemState = state(item);
138
+ const indexSignal = signal(index);
139
+ const rendered = this.#renderItem ? this.#renderItem(itemState, indexSignal) : item;
140
+ const values = Renderer.normalize(rendered);
141
+ for (const r of values) this.#mountRenderable(parent, r, itemEnd);
142
+ this.#itemRefs.splice(index, 0, { start: itemStart, end: itemEnd, values, state: itemState, index: indexSignal });
143
+ }
144
+
145
+ #remove(index, count) {
146
+ const removed = this.#itemRefs.splice(index, count);
147
+ for (const it of removed) {
148
+ for (const r of it.values) Renderer.unmount(r);
149
+ clearBetween(it.start, it.end);
150
+ it.start.remove();
151
+ it.end.remove();
152
+ }
153
+ }
154
+
155
+ #set(index, item) {
156
+ const ref = this.#itemRefs[index];
157
+ if (ref && ref.state) {
158
+ ref.state.set(item);
159
+ return;
160
+ }
161
+ this.#remove(index, 1);
162
+ this.#insert(index, item);
163
+ }
164
+
165
+ #updateIndices(fromIndex) {
166
+ for (let i = fromIndex; i < this.#itemRefs.length; i++) {
167
+ const ref = this.#itemRefs[i];
168
+ if (ref.index) setSignal(ref.index, i);
169
+ }
170
+ }
171
+
172
+ #mountRenderable(parent, renderable, beforeNode) {
173
+ if (Renderer.isRenderable(renderable)) {
174
+ renderable.mountInto(parent, beforeNode);
175
+ return;
176
+ }
177
+ if (Renderer.isDomNode(renderable)) {
178
+ parent.insertBefore(renderable, beforeNode);
179
+ }
180
+ }
181
+ }
182
+
183
+ export function list(items, renderItem) {
184
+ return new ListNode(items, renderItem);
185
+ }
@@ -0,0 +1,57 @@
1
+ import { Renderable } from '../renderable/renderable.js';
2
+ import { Renderer } from '../renderable/renderer.js';
3
+
4
+ function resolveTarget(target) {
5
+ if (!target && typeof document !== 'undefined') return document.body;
6
+ if (typeof target === 'string') return document.querySelector(target);
7
+ return target;
8
+ }
9
+
10
+ export class PortalNode extends Renderable {
11
+ #target;
12
+ #content;
13
+ #mounted = false;
14
+ #mountedValues = [];
15
+
16
+ constructor(target, content) {
17
+ super();
18
+ this.#target = target;
19
+ this.#content = content;
20
+ }
21
+
22
+ mountInto(_parent, _beforeNode) {
23
+ if (this.#mounted) return;
24
+ this.#mounted = true;
25
+ const targetEl = resolveTarget(this.#target);
26
+ if (!targetEl) throw new Error('portal: target not found');
27
+ const value = typeof this.#content === 'function' ? this.#content() : this.#content;
28
+ const values = Renderer.normalize(value);
29
+ this.#mountedValues = values;
30
+ for (const r of values) {
31
+ if (Renderer.isRenderable(r)) {
32
+ r.mountInto(targetEl, null);
33
+ } else if (Renderer.isDomNode(r)) {
34
+ targetEl.appendChild(r);
35
+ }
36
+ }
37
+ }
38
+
39
+ unmount() {
40
+ if (!this.#mounted) return;
41
+ this.#mounted = false;
42
+ for (const r of this.#mountedValues) Renderer.unmount(r);
43
+ this.#mountedValues = [];
44
+ }
45
+
46
+ renderToString(render) {
47
+ const value = typeof this.#content === 'function' ? this.#content() : this.#content;
48
+ return render(value);
49
+ }
50
+ }
51
+
52
+ export function portal(target, content) {
53
+ if (content === undefined) {
54
+ return new PortalNode(null, target);
55
+ }
56
+ return new PortalNode(target, content);
57
+ }
@@ -0,0 +1,182 @@
1
+ import { ElementNode } from './element.js';
2
+ import { Renderer } from '../renderable/renderer.js';
3
+ import { isObservableArray } from '../collections/observable-array.js';
4
+ import { isSignal } from '../reactivity/signal.js';
5
+ import { isComputed, isState, isStatePath } from '../reactivity/state.js';
6
+
7
+ const tags = [
8
+ 'html', 'head', 'title', 'base', 'link', 'meta', 'style',
9
+ 'body', 'article', 'section', 'nav', 'aside', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
10
+ 'hgroup', 'header', 'footer', 'address', 'main', 'search',
11
+ 'p', 'hr', 'pre', 'blockquote', 'ol', 'ul', 'li', 'dl', 'dt', 'dd',
12
+ 'figure', 'figcaption', 'div', 'menu',
13
+ 'a', 'em', 'strong', 'small', 's', 'cite', 'q', 'dfn', 'abbr', 'ruby', 'rt', 'rp',
14
+ 'data', 'time', 'code', 'var', 'samp', 'kbd', 'sub', 'sup', 'i', 'b', 'u',
15
+ 'mark', 'bdi', 'bdo', 'span', 'br', 'wbr',
16
+ 'ins', 'del',
17
+ 'picture', 'source', 'img', 'iframe', 'embed', 'object', 'param', 'video', 'audio',
18
+ 'track', 'map', 'area',
19
+ 'table', 'caption', 'colgroup', 'col', 'tbody', 'thead', 'tfoot', 'tr', 'td', 'th',
20
+ 'form', 'label', 'input', 'button', 'select', 'datalist', 'optgroup', 'option',
21
+ 'textarea', 'output', 'progress', 'meter', 'fieldset', 'legend',
22
+ 'details', 'summary', 'dialog',
23
+ 'script', 'noscript', 'template', 'slot', 'canvas',
24
+ ];
25
+
26
+ function toFactoryName(tag) {
27
+ let name = tag.charAt(0).toUpperCase() + tag.slice(1);
28
+ if (name in globalThis) name = `Html${name}`;
29
+ return name;
30
+ }
31
+
32
+ function createTag(tagName) {
33
+ return (...args) => {
34
+ const nextProps = {};
35
+ const nextChildren = [];
36
+
37
+ const isPropsObject = (value) =>
38
+ !!value &&
39
+ typeof value === 'object' &&
40
+ !Array.isArray(value) &&
41
+ !Renderer.isRenderable(value) &&
42
+ !Renderer.isDomNode(value) &&
43
+ !isObservableArray(value) &&
44
+ !isSignal(value) &&
45
+ !isState(value) &&
46
+ !isStatePath(value) &&
47
+ !isComputed(value);
48
+
49
+ for (const arg of args) {
50
+ if (isPropsObject(arg)) {
51
+ Object.assign(nextProps, arg);
52
+ } else {
53
+ nextChildren.push(arg);
54
+ }
55
+ }
56
+
57
+ return new ElementNode(tagName, nextProps, nextChildren);
58
+ };
59
+ }
60
+
61
+ const exported = {};
62
+ for (const tag of tags) {
63
+ const name = toFactoryName(tag);
64
+ exported[name] = createTag(tag);
65
+ }
66
+
67
+ export const Elements = Object.freeze(exported);
68
+ export const {
69
+ Html,
70
+ Head,
71
+ Title,
72
+ Base,
73
+ Link,
74
+ Meta,
75
+ Style,
76
+ Body,
77
+ Article,
78
+ Section,
79
+ Nav,
80
+ Aside,
81
+ H1,
82
+ H2,
83
+ H3,
84
+ H4,
85
+ H5,
86
+ H6,
87
+ Hgroup,
88
+ Header,
89
+ Footer,
90
+ Address,
91
+ Main,
92
+ Search,
93
+ P,
94
+ Hr,
95
+ Pre,
96
+ Blockquote,
97
+ Ol,
98
+ Ul,
99
+ Li,
100
+ Dl,
101
+ Dt,
102
+ Dd,
103
+ Figure,
104
+ Figcaption,
105
+ Div,
106
+ Menu,
107
+ A,
108
+ Em,
109
+ Strong,
110
+ Small,
111
+ S,
112
+ Cite,
113
+ Q,
114
+ Dfn,
115
+ Abbr,
116
+ Ruby,
117
+ Rt,
118
+ Rp,
119
+ Data,
120
+ Time,
121
+ Code,
122
+ Var,
123
+ Samp,
124
+ Kbd,
125
+ Sub,
126
+ Sup,
127
+ I,
128
+ B,
129
+ U,
130
+ Mark,
131
+ Bdi,
132
+ Bdo,
133
+ Span,
134
+ Br,
135
+ Wbr,
136
+ Ins,
137
+ Del,
138
+ Picture,
139
+ Source,
140
+ Img,
141
+ Iframe,
142
+ Embed,
143
+ HtmlObject,
144
+ Param,
145
+ Video,
146
+ Audio,
147
+ Track,
148
+ Map,
149
+ Area,
150
+ Table,
151
+ Caption,
152
+ Colgroup,
153
+ Col,
154
+ Tbody,
155
+ Thead,
156
+ Tfoot,
157
+ Tr,
158
+ Td,
159
+ Th,
160
+ Form,
161
+ Label,
162
+ Input,
163
+ Button,
164
+ Select,
165
+ Datalist,
166
+ Optgroup,
167
+ Option,
168
+ Textarea,
169
+ Output,
170
+ Progress,
171
+ Meter,
172
+ Fieldset,
173
+ Legend,
174
+ Details,
175
+ Summary,
176
+ Dialog,
177
+ Script,
178
+ Noscript,
179
+ Template,
180
+ Slot,
181
+ Canvas,
182
+ } = exported;