solarite 0.5.2 → 0.7.1

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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/dist/Solarite-debug.js +4847 -3878
  3. package/dist/Solarite.js +4583 -3626
  4. package/dist/Solarite.min.js +2 -4
  5. package/package.json +19 -6
  6. package/readme.md +58 -11
  7. package/src/Globals.js +54 -72
  8. package/src/HtmlParser.js +90 -90
  9. package/src/MultiValueMap.js +57 -105
  10. package/src/NodeGroup.js +624 -470
  11. package/src/Path.js +224 -211
  12. package/src/PathToAttribValue.js +401 -261
  13. package/src/PathToAttribs.js +113 -80
  14. package/src/PathToComment.js +7 -7
  15. package/src/PathToComponent.js +183 -188
  16. package/src/PathToEvent.js +76 -64
  17. package/src/PathToKey.js +19 -0
  18. package/src/PathToNodes.js +1053 -566
  19. package/src/RootNodeGroup.js +120 -8
  20. package/src/Shell.js +570 -348
  21. package/src/Solarite.d.ts +134 -113
  22. package/src/Solarite.js +243 -286
  23. package/src/Template.js +195 -274
  24. package/src/Util.js +353 -351
  25. package/src/assert.js +10 -10
  26. package/src/assignAttributes.js +63 -0
  27. package/src/delve.js +55 -43
  28. package/src/h.js +220 -138
  29. package/src/jsx-dev-runtime.d.ts +1 -0
  30. package/src/jsx-dev-runtime.js +5 -0
  31. package/src/jsx-runtime.d.ts +21 -0
  32. package/src/jsx-runtime.js +84 -0
  33. package/src/jsx.js +194 -0
  34. package/src/toEl.js +77 -82
  35. package/dist/udomdiff-license.txt +0 -18
  36. package/src/getArg.js +0 -137
  37. package/src/hash.js +0 -89
  38. package/src/udomdiff.js +0 -176
  39. package/src/unused/FastLookupArray.js +0 -54
  40. package/src/unused/Hashes.js +0 -339
  41. package/src/unused/InUse.test.js +0 -92
  42. package/src/unused/InUseMap.js +0 -98
  43. package/src/unused/LinkedList.js +0 -117
  44. package/src/unused/LinkedList.test.js +0 -115
  45. package/src/unused/Misc.js +0 -13
  46. package/src/unused/Perf.js +0 -47
  47. package/src/unused/TrackedArray.js +0 -54
  48. package/src/unused/WeakArray.js +0 -33
  49. package/src/watch.js +0 -543
package/src/assert.js CHANGED
@@ -1,10 +1,10 @@
1
-
2
- /*@__NO_SIDE_EFFECTS__*/
3
- export default function assert(val) {
4
- //#IFDEV
5
- if (!val) {
6
- //debugger;
7
- throw new Error('Assertion failed: ' + val);
8
- }
9
- //#ENDIF
10
- }
1
+
2
+ /*@__NO_SIDE_EFFECTS__*/
3
+ export default function assert(val) {
4
+ //#IFDEV
5
+ if (!val) {
6
+ //debugger;
7
+ throw new Error('Assertion failed: ' + val);
8
+ }
9
+ //#ENDIF
10
+ }
@@ -0,0 +1,63 @@
1
+ /*
2
+ ┏┓ ┓ •
3
+ ┗┓┏┓┃┏┓┏┓┓╋▗▖
4
+ ┗┛┗┛┗┗┻╹ ╹╹┗
5
+ JavaScript UI library
6
+ @license MIT
7
+ @copyright Vorticode LLC
8
+ https://vorticode.github.io/solarite/ */
9
+
10
+ import Util from "./Util.js";
11
+
12
+ /**
13
+ * Read an element's html attributes onto fields that already exist on the element.
14
+ * Typically called from a web component constructor to support plain-html instantiation
15
+ * like `<my-timer duration="7" auto-start>`. Tagged-template values are already typed and
16
+ * arrive in the constructor's argument instead, so assign those directly.
17
+ *
18
+ * Attribute names convert from kebab-case to camelCase, so `auto-start` becomes `autoStart`.
19
+ * An attribute written like `${...}` is JSON-parsed back to its original type and assigned
20
+ * as-is. Every other attribute value is a string: if its field is named in `types`, the
21
+ * string is cast with that converter, otherwise it's assigned as a string.
22
+ *
23
+ * `types` maps a field name to a converter: Number, Boolean, String, Date, or any function
24
+ * taking the string and returning a value. Boolean is true for any string except 'false'
25
+ * and '0', so a bare attribute like `<my-timer auto-start>` reads as true. Date uses
26
+ * new Date(value). No type is inferred from the field's existing value.
27
+ *
28
+ * Field names listed in `ignore` are skipped.
29
+ * @param dest {HTMLElement}
30
+ * @param types {Object<string, Function>}
31
+ * @param ignore {string[]} */
32
+ export function assignAttributes(dest, types={}, ignore=[]) {
33
+ for (let attrib of dest.attributes) {
34
+ let name = Util.dashesToCamel(attrib.name);
35
+ if (!(name in dest) || ignore.includes(name))
36
+ continue;
37
+
38
+ let value = attrib.value;
39
+ let type = types[name];
40
+
41
+ // 1. A `${...}` attribute holds an already-typed JSON value.
42
+ if (value.startsWith('${') && value.endsWith('}'))
43
+ dest[name] = JSON.parse(value.slice(2, -1));
44
+
45
+ // 2. Cast the string with the converter named in `types`, if any.
46
+ else if (type === Date)
47
+ dest[name] = new Date(value);
48
+ else if (type === Boolean)
49
+ dest[name] = !['false', '0'].includes(value);
50
+ else if (type === Number)
51
+ dest[name] = Number(value);
52
+ else if (type === String)
53
+ dest[name] = String(value);
54
+ else if (type) // custom string=>value function
55
+ dest[name] = type(value);
56
+
57
+ // 3. No converter named: assign the raw string. But an empty value over a function/object
58
+ // field is just the serialization residue of a template expression (functions render as
59
+ // attribute="") — skip it, or it clobbers the real value the expression already assigned.
60
+ else if (value !== '' || !(typeof dest[name] === 'function' || (typeof dest[name] === 'object' && dest[name] !== null)))
61
+ dest[name] = value;
62
+ }
63
+ }
package/src/delve.js CHANGED
@@ -1,44 +1,56 @@
1
- /**
2
- * Follow a path into an object.
3
- * @param obj {object}
4
- * @param path {string[]}
5
- * @param createVal {*} If set, non-existent paths will be created and value at path will be set to createVal.
6
- * @return {*} The value, or undefined if it can't be reached. */
7
- export default function delve(obj, path, createVal = d) {
8
- let isCreate = createVal !== d;
9
-
10
- let len = path.length;
11
- if (!obj && !isCreate && len)
12
- return undefined;
13
-
14
- let i = 0;
15
- for (let srcProp of path) {
16
-
17
- // If the path is undefined and we're not to the end yet:
18
- if (obj[srcProp] === undefined) {
19
-
20
- // If the next index is an integer or integer string.
21
- if (isCreate) {
22
- if (i < len - 1) {
23
- // If next level path is a number, create as an array
24
- let isArray = (path[i + 1] + '').match(/^\d+$/);
25
- obj[srcProp] = isArray ? [] : {};
26
- }
27
- } else
28
- return undefined; // can't traverse
29
- }
30
-
31
- // If last item in path
32
- if (isCreate && i === len - 1)
33
- obj[srcProp] = createVal;
34
-
35
- // Traverse deeper along destination object.
36
- obj = obj[srcProp];
37
- i++;
38
- }
39
-
40
- return obj;
41
- }
42
-
43
- // d means "don't create"
1
+ /**
2
+ * Follow a path into an object.
3
+ * @param obj {object}
4
+ * @param path {string[]}
5
+ * @param createVal {*} If set, non-existent paths will be created and value at path will be set to createVal.
6
+ * @return {*} The value, or undefined if it can't be reached. */
7
+ export default function delve(obj, path, createVal = d) {
8
+ let isCreate = createVal !== d;
9
+
10
+ let len = path.length;
11
+ if (!obj && !isCreate && len)
12
+ return undefined;
13
+
14
+ let i = 0;
15
+ for (let srcProp of path) {
16
+
17
+ // If the path is undefined and we're not to the end yet:
18
+ if (obj[srcProp] === undefined) {
19
+
20
+ // If the next index is an integer or integer string.
21
+ if (isCreate) {
22
+ if (i < len - 1) {
23
+ // If next level path is a number, create as an array
24
+ let isArray = (path[i + 1] + '').match(/^\d+$/);
25
+ obj[srcProp] = isArray ? [] : {};
26
+ }
27
+ } else
28
+ return undefined; // can't traverse
29
+ }
30
+
31
+ // If last item in path
32
+ if (isCreate && i === len - 1)
33
+ obj[srcProp] = createVal;
34
+
35
+ // Traverse deeper along destination object.
36
+ obj = obj[srcProp];
37
+ i++;
38
+ }
39
+
40
+ return obj;
41
+ }
42
+
43
+
44
+ /**
45
+ * Is it an array and a path that can be evaluated by delve() ?
46
+ * We allow the first element to be null/undefined so binding can report errors.
47
+ * @param arr {Array|*}
48
+ * @returns {boolean} */
49
+ export function isDelvePath(arr) {
50
+ return Array.isArray(arr) && arr.length >=2 // An array of at least two elements.
51
+ && (typeof arr[0] === 'object' || arr[0] === undefined) // Where the first element is an object, null, or undefined.
52
+ && !arr.slice(1).find(p => typeof p !== 'string' && typeof p !== 'number'); // Path 1..x is only numbers and strings.
53
+ }
54
+
55
+ // d means "don't create"
44
56
  let d = {};
package/src/h.js CHANGED
@@ -1,138 +1,220 @@
1
- import Template from "./Template.js";
2
- import Globals from "./Globals.js";
3
- import toEl from "./toEl.js";
4
- import Util from "./Util.js";
5
-
6
- /**
7
- * Convert strings to HTMLNodes.
8
- * Using h`...` as a tag will always create a Template.
9
- * Using h() as a function() will always create a DOM element.
10
- *
11
- * Features beyond what standard js tagged template strings do:
12
- * 1. h`` sub-expressions
13
- * 2. functions, nodes, and arrays of nodes as sub-expressions.
14
- * 3. html-escape all expressions by default, unless wrapped in h()
15
- * 4. event binding
16
- * 5. TODO: list more
17
- *
18
- * General rule:
19
- * If h() is a function with null or an HTMLElement as its first argument create a Node.
20
- * Otherwise create a template
21
- *
22
- * Currently supported:
23
- *
24
- * Create Tempataes
25
- * 1. h`<b>Hello</b> ${'World'}!` // Create Template that can later be used to create nodes.
26
- * 2. h('<b>Hello</b><u>Goodbye</u>'); // Create Template from string, that can later be used to create nodes.
27
- *
28
- * Add children to an element.
29
- * 3. h(el, h`<b>${'Hi'}</b>`, ?options)
30
- * 4. h(el, ?options)`<b>${'Hi'}</b>` // typical path used in render(). Create template and render its nodes to el.
31
- *
32
- * Create top-level element
33
- * 5. h()`Hello<b>${'World'}!</b>`
34
- *
35
- * 6. h(string, object, ...) // Used for JSX
36
- * @param htmlStrings {?HTMLElement|string|string[]|function():Template|{render:function()}}
37
- * @param exprs {*[]|string|Template|Object}
38
- * @return {Node|HTMLElement|Template|Function} */
39
- export default function h(htmlStrings=undefined, ...exprs) {
40
-
41
- // 1. Tagged template: h`<div>...</div>`
42
- if (Array.isArray(arguments[0])) {
43
- return new Template(arguments[0], exprs);
44
- }
45
-
46
- // 2. String to template, or JSX factory form h(tag, props, ...children)
47
- else if (typeof arguments[0] === 'string' || arguments[0] instanceof String) {
48
- let tagOrHtml = arguments[0];
49
-
50
- // 2a. JSX: h("tag", {props}, ...children)
51
- if (exprs.length && (typeof exprs[0] === 'object' || exprs[0] === null)) {
52
- let tag = tagOrHtml + '';
53
- let props = exprs[0] || {};
54
- let children = exprs.slice(1);
55
-
56
- return Template.fromJsx(tag, props, children);
57
- }
58
-
59
- // 2b. Plain html string => template: h('<div>...</div>')
60
- else {
61
- let html = tagOrHtml;
62
- // If it starts with whitespace and then a tag, trim it.
63
- if (html.match(/^\s^</))
64
- html = html.trim();
65
- return new Template([html], []);
66
- }
67
- }
68
-
69
- else if (arguments[0] instanceof HTMLElement || arguments[0] instanceof DocumentFragment) {
70
-
71
- // 3. Render template to element: h(el, template)
72
- if (arguments[1] instanceof Template) {
73
-
74
- /** @type Template */
75
- let template = arguments[1];
76
- let parent = arguments[0];
77
- let options = arguments[2];
78
- template.render(parent, options);
79
- }
80
-
81
- // 4. Render tagged template to element: h(el)`<div>...</div>`
82
- else {
83
- let parent = arguments[0], options = arguments[1];
84
-
85
- // Remove shadowroot if present. TODO: This could mess up paths?
86
- if (parent.shadowRoot)
87
- parent.innerHTML = '';
88
-
89
- // Return a tagged template function that applies the tagged template to parent.
90
- let renderTemplate = (htmlStrings, ...exprs) => {
91
- Globals.rendered.add(parent)
92
- let template = new Template(htmlStrings, exprs);
93
- return template.render(parent, options);
94
- }
95
- return renderTemplate;
96
- }
97
- }
98
-
99
- // 5. Create a static element: h()`<div></div>`
100
- else if (!arguments.length) {
101
- return (htmlStrings, ...exprs) => {
102
- let template = h(htmlStrings, ...exprs);
103
- return toEl(template);
104
- }
105
- }
106
-
107
- // 6. Help toEl() with objects: h(this)`<div>...</div>` inside an object's render()
108
- // Intercepts the main h(this)`...` function call inside render().
109
- // TODO: This path doesn't handle embeds like data-id="..."
110
- else if (typeof arguments[0] === 'object' && Globals.objToEl.has(arguments[0])) {
111
- let obj = arguments[0];
112
-
113
- if (obj.constructor.name !== 'Object')
114
- throw new Error(`Solarate Web Component class ${obj.constructor?.name} must extend HTMLElement.`);
115
-
116
- // Jsx with h(this, <jsx>)
117
- if (arguments[1] instanceof Template) {
118
- let template = arguments[1];
119
- let el = template.render();
120
- Globals.objToEl.set(obj, el);
121
- }
122
-
123
- // h(this)`<div>...</div>`
124
- else
125
- return function(...args) {
126
- let template = h(...args);
127
- let el = template.render();
128
- Globals.objToEl.set(obj, el);
129
- }.bind(obj);
130
- }
131
- // TODO: Handle other primitive types?
132
- else if (Util.isFalsy(arguments[0]))
133
- return new Template();
134
-
135
- else
136
- throw new Error('h() does not support argument of type: ' + (arguments[0] ? typeof arguments[0] : arguments[0]))
137
- }
138
-
1
+ import Template from "./Template.js";
2
+ import Globals from "./Globals.js";
3
+ import toEl from "./toEl.js";
4
+ import Util from "./Util.js";
5
+ import {jsxToTemplate, Fragment} from "./jsx.js";
6
+
7
+ /**
8
+ * Convert strings to HTMLNodes.
9
+ * Using h`...` as a tag will always create a Template.
10
+ * Using h() as a function() will always create a DOM element.
11
+ *
12
+ * Features beyond what standard js tagged template strings do:
13
+ * 1. h`` sub-expressions
14
+ * 2. functions, nodes, and arrays of nodes as sub-expressions.
15
+ * 3. html-escape all expressions by default, unless wrapped in h()
16
+ * 4. event binding
17
+ * 5. TODO: list more
18
+ *
19
+ * General rule:
20
+ * If h() is a function with null or an HTMLElement as its first argument create a Node.
21
+ * Otherwise create a template
22
+ *
23
+ * Currently supported:
24
+ *
25
+ * Create Tempataes
26
+ * 1. h`<b>Hello</b> ${'World'}!` // Create Template that can later be used to create nodes.
27
+ * 2. h('<b>Hello</b><u>Goodbye</u>'); // Create Template from string, that can later be used to create nodes.
28
+ *
29
+ * Add children to an element.
30
+ * 3. h(el, h`<b>${'Hi'}</b>`, ?options)
31
+ * 4. h(el, ?options)`<b>${'Hi'}</b>` // typical path used in render(). Create template and render its nodes to el.
32
+ *
33
+ * Create top-level element
34
+ * 5. h()`Hello<b>${'World'}!</b>`
35
+ *
36
+ * 6. h(string, object, ...) // Used for JSX
37
+ * @param htmlStrings {?HTMLElement|string|string[]|function():Template|{render:function()}}
38
+ * @param exprs {*[]|string|Template|Object}
39
+ * @return {Node|HTMLElement|Template|Function} */
40
+ /**
41
+ * Like h`...` but the fragment is parsed in the SVG namespace.
42
+ * Required for nested SVG fragments, since they're parsed standalone without an <svg> ancestor:
43
+ * h`<svg>${svg`<circle r="1"/>`}</svg>`
44
+ * @param htmlStrings {string[]}
45
+ * @param exprs {*[]}
46
+ * @return {Template} */
47
+ export function svg(htmlStrings, ...exprs) {
48
+ let template = new Template(htmlStrings, exprs);
49
+ template.svgMode = true;
50
+ return template;
51
+ }
52
+
53
+ const renderTemplateKey = Symbol('solariteRender');
54
+
55
+ // Unique default that detects h() called with no arguments.
56
+ // Using `arguments` alongside rest params would force the engine to materialize both per call.
57
+ const noArg = Symbol();
58
+
59
+ export default function h(htmlStrings=noArg, ...exprs) {
60
+
61
+ // 1. Tagged template: h`<div>...</div>`
62
+ if (Array.isArray(htmlStrings)) {
63
+ return new Template(htmlStrings, exprs);
64
+ }
65
+
66
+ // 2. String to template, or JSX factory form h(tag, props, ...children)
67
+ else if (typeof htmlStrings === 'string' || htmlStrings instanceof String) {
68
+ let tagOrHtml = htmlStrings;
69
+
70
+ // 2a. JSX classic factory: h("tag", {props}, ...children)
71
+ if (exprs.length && (typeof exprs[0] === 'object' || exprs[0] === null)) {
72
+ let tag = tagOrHtml + '';
73
+ let props = exprs[0] || {};
74
+ let children = exprs.slice(1);
75
+
76
+ return jsxToTemplate(tag, props, children);
77
+ }
78
+
79
+ // 2b. Plain html string => template: h('<div>...</div>')
80
+ else {
81
+ let html = tagOrHtml;
82
+ // If it starts with whitespace and then a tag, trim it.
83
+ if (/^\s+</.test(html))
84
+ html = html.trim();
85
+ return new Template([html], []);
86
+ }
87
+ }
88
+
89
+ // 2c. JSX classic factory for a component or Fragment: h(Component, {props}, ...children)
90
+ // The transform passes the class/function (or the Fragment symbol) as the first argument.
91
+ else if (typeof htmlStrings === 'function' || htmlStrings === Fragment) {
92
+ return jsxToTemplate(htmlStrings, exprs[0] || {}, exprs.slice(1));
93
+ }
94
+
95
+ else if (htmlStrings instanceof HTMLElement || htmlStrings instanceof DocumentFragment) {
96
+
97
+ // 3. Render template to element: h(el, template)
98
+ if (exprs[0] instanceof Template) {
99
+
100
+ /** @type Template */
101
+ let template = exprs[0];
102
+ let parent = htmlStrings;
103
+ let options = exprs[1];
104
+ template.render(parent, options);
105
+ }
106
+
107
+ // 4. Render tagged template to element: h(el)`<div>...</div>`
108
+ else {
109
+ let parent = htmlStrings, options = exprs[0];
110
+
111
+ // The closure is cached on the element so repeated renders don't recreate it.
112
+ if (options === undefined) {
113
+ let cached = parent[renderTemplateKey];
114
+ if (cached)
115
+ return cached;
116
+ }
117
+
118
+ // Return a tagged template function that applies the tagged template to parent.
119
+ let renderTemplate = (htmlStrings, ...exprs) => {
120
+ // Remove shadowroot if present. TODO: This could mess up paths?
121
+ if (parent.shadowRoot)
122
+ parent.innerHTML = '';
123
+
124
+ Globals.rendered.add(parent)
125
+ let template = new Template(htmlStrings, exprs);
126
+ return template.render(parent, options);
127
+ }
128
+ if (options === undefined)
129
+ parent[renderTemplateKey] = renderTemplate;
130
+ return renderTemplate;
131
+ }
132
+ }
133
+
134
+ // 5. Create a static element: h()`<div></div>`
135
+ else if (htmlStrings === noArg) {
136
+ return (htmlStrings, ...exprs) => {
137
+ let template = h(htmlStrings, ...exprs);
138
+ return toEl(template);
139
+ }
140
+ }
141
+
142
+ // 6. Help toEl() with objects: h(this)`<div>...</div>` inside an object's render()
143
+ // Intercepts the main h(this)`...` function call inside render().
144
+ // TODO: This path doesn't handle embeds like data-id="..."
145
+ else if (typeof htmlStrings === 'object' && Globals.objToEl.has(htmlStrings)) {
146
+ let obj = htmlStrings;
147
+
148
+ if (obj.constructor.name !== 'Object')
149
+ throw new Error(`Solarate Web Component class ${obj.constructor?.name} must extend HTMLElement.`);
150
+
151
+ // Jsx with h(this, <jsx>)
152
+ if (exprs[0] instanceof Template) {
153
+ let template = exprs[0];
154
+ let el = template.render();
155
+ Globals.objToEl.set(obj, el);
156
+ }
157
+
158
+ // h(this)`<div>...</div>`
159
+ else
160
+ return function(...args) {
161
+ let template = h(...args);
162
+ let el = template.render();
163
+ Globals.objToEl.set(obj, el);
164
+ }.bind(obj);
165
+ }
166
+ // TODO: Handle other primitive types?
167
+ else if (Util.isFalsy(htmlStrings))
168
+ return new Template();
169
+
170
+ else
171
+ throw new Error('h() does not support argument of type: ' + (htmlStrings ? typeof htmlStrings : htmlStrings))
172
+ }
173
+
174
+ // h.map caches each item's Template keyed by the item's identity, so a re-render returns
175
+ // the SAME Template instance for any item whose reference is unchanged. The reconciler's
176
+ // `ng.template === item` fast path (PathToNodes.applyKeyed/applyDiff) then skips rebuilding
177
+ // and comparing that row. A WeakMap is used instead of a symbol property so the idiomatic
178
+ // immutable update `{...item, x}` yields a fresh object that ISN'T in the cache and re-renders;
179
+ // a symbol property would be copied by spread and silently reuse the stale Template.
180
+ const mapCache = new WeakMap();
181
+
182
+ /**
183
+ * Render a list, reusing each item's DOM for as long as the item is the SAME object.
184
+ *
185
+ * Treat items as immutable: to change a row, replace it with a new object rather than
186
+ * mutating it in place, so its identity changes and it re-renders. This is the contract
187
+ * Solid's <For> and React's keyed lists use. It takes no deps — the object identity IS
188
+ * the dependency — so the call site stays a plain list with no caching code.
189
+ *
190
+ * Each item must be a distinct object, and an object must appear in only one h.map.
191
+ * Non-object items (strings, numbers) are never cached and rebuild every render.
192
+ *
193
+ * h.immutableMap is the same function under a longer, self-documenting name; use whichever
194
+ * reads better: h.map for brevity, h.immutableMap to flag the immutability contract.
195
+ *
196
+ * ${h.map(this.rows, row => h`<tr key=${row.id}>${row.label}</tr>`)}
197
+ *
198
+ * @param items {Array} The list to render.
199
+ * @param fn {function(item:*):Template} Builds an item's Template; called only for new items.
200
+ * @return {Template[]} */
201
+ h.map = (items, fn) => {
202
+ let result = new Array(items.length);
203
+ for (let i=0; i<items.length; i++) {
204
+ let item = items[i];
205
+ if (item !== null && typeof item === 'object') {
206
+ let template = mapCache.get(item);
207
+ if (template === undefined) {
208
+ template = fn(item);
209
+ mapCache.set(item, template);
210
+ }
211
+ result[i] = template;
212
+ }
213
+ else
214
+ result[i] = fn(item);
215
+ }
216
+ return result;
217
+ }
218
+
219
+ h.immutableMap = h.map;
220
+
@@ -0,0 +1 @@
1
+ export { jsx, jsxs, jsxDEV, Fragment, jsxTemplate, jsxAttr, jsxEscape, JSX } from './jsx-runtime';
@@ -0,0 +1,5 @@
1
+ /** Dev entry point used by toolchains configured with the automatic runtime in development mode
2
+ * (e.g. esbuild/tsc `jsxDEV`). It re-exports the same runtime; the extra dev source args are
3
+ * ignored. */
4
+ export { jsx, jsxs, jsxDEV, Fragment, jsxTemplate, jsxAttr, jsxEscape } from './jsx-runtime.js';
5
+ export { jsxDEV as jsxDEVRuntime } from './jsx-runtime.js';
@@ -0,0 +1,21 @@
1
+ import { Template } from './Solarite';
2
+
3
+ export function jsxTemplate(strings: string[], ...exprs: any[]): Template;
4
+ export function jsxAttr(name: string, value: any): any;
5
+ export function jsxEscape(value: any): any;
6
+ export function jsx(tag: any, props: any, key?: any): Template;
7
+ export function jsxs(tag: any, props: any, key?: any): Template;
8
+ export function jsxDEV(tag: any, props: any, key?: any): Template;
9
+ export const Fragment: unique symbol;
10
+
11
+ /**
12
+ * Types for `tsconfig` / `deno.json` with `jsx: "react-jsx" | "precompile"` and
13
+ * `jsxImportSource: "solarite"`. IntrinsicElements is intentionally permissive for now: any
14
+ * lowercase tag with any attributes is allowed. A JSX expression evaluates to a Solarite Template. */
15
+ export namespace JSX {
16
+ type Element = Template;
17
+ interface ElementChildrenAttribute { children: {}; }
18
+ interface IntrinsicElements {
19
+ [tagName: string]: any;
20
+ }
21
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Solarite JSX runtime. Configure your toolchain with `jsxImportSource: "solarite"` (automatic
3
+ * runtime) or have Deno's `jsx:"precompile"` / a Solarite build plugin target this module.
4
+ *
5
+ * Tier 1 (precompile): jsxTemplate/jsxAttr/jsxEscape map hoisted statics straight onto Template.
6
+ * Tier 2 (automatic): jsx/jsxs/jsxDEV build a Template per render via the shape-interning factory.
7
+ *
8
+ * See src/jsx.js for the shared core (jsxToTemplate, JsxAttr, Fragment). */
9
+ import Template from "./Template.js";
10
+ import {JsxAttr, jsxToTemplate, Fragment} from "./jsx.js";
11
+
12
+ export {Fragment};
13
+
14
+ /**
15
+ * Tier 1: build a Template from hoisted static strings and expression holes, with the statics'
16
+ * stable array identity feeding Shell cache / NodeGroup reuse just like a tagged template.
17
+ * @param strings {string[]} Module-hoisted static html (same array every render).
18
+ * @param exprs {...*} jsxAttr() pairs, jsxEscape() children, and bare boolean-attr strings.
19
+ * @return {Template} */
20
+ export function jsxTemplate(strings, ...exprs) {
21
+ let key;
22
+ for (let i = 0; i < exprs.length; i++) {
23
+ let e = exprs[i];
24
+ // A `key` prop arrives as jsxAttr("key", value) at an attribute hole. Lift it onto the
25
+ // Template for keyed diffing and blank the hole so it never renders as an attribute.
26
+ if (e instanceof JsxAttr && e.name === 'key') {
27
+ key = e.value;
28
+ exprs[i] = '';
29
+ }
30
+ }
31
+ let t = new Template(strings, exprs);
32
+ if (key !== undefined)
33
+ t.key = key;
34
+ return t;
35
+ }
36
+
37
+ /**
38
+ * Tier 1: a whole-attribute hole, e.g. `<a ` + jsxAttr("href", v) + `>`. PathToAttribs detects
39
+ * this and routes the value through normal attribute/event/property application.
40
+ * @param name {string}
41
+ * @param value {*}
42
+ * @return {JsxAttr} */
43
+ export function jsxAttr(name, value) {
44
+ return new JsxAttr(name, value);
45
+ }
46
+
47
+ /**
48
+ * Tier 1: a child hole. Solarite already html-escapes child expressions (strings render as text,
49
+ * Templates/arrays as nodes), so this is the identity function.
50
+ * @param value {*}
51
+ * @return {*} */
52
+ export function jsxEscape(value) {
53
+ return value;
54
+ }
55
+
56
+ /**
57
+ * Tier 2 automatic runtime: a single-child element. props.children is one child hole.
58
+ * @param tag {string|Function|symbol}
59
+ * @param props {Object}
60
+ * @param key {*}
61
+ * @return {Template} */
62
+ export function jsx(tag, props, key) {
63
+ props = props || {};
64
+ let children = ('children' in props) ? [props.children] : [];
65
+ return jsxToTemplate(tag, props, children, key);
66
+ }
67
+
68
+ /**
69
+ * Tier 2 automatic runtime: multiple static children. props.children is the children array.
70
+ * @param tag {string|Function|symbol}
71
+ * @param props {Object}
72
+ * @param key {*}
73
+ * @return {Template} */
74
+ export function jsxs(tag, props, key) {
75
+ props = props || {};
76
+ let children = props.children;
77
+ children = Array.isArray(children) ? children : (children === undefined ? [] : [children]);
78
+ return jsxToTemplate(tag, props, children, key);
79
+ }
80
+
81
+ /** Dev variant (extra source/self args are ignored). */
82
+ export function jsxDEV(tag, props, key) {
83
+ return jsx(tag, props, key);
84
+ }