ripple 0.3.68 → 0.3.70
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/CHANGELOG.md +57 -0
- package/package.json +3 -3
- package/src/jsx-runtime.d.ts +2 -2
- package/src/runtime/element.js +1 -1
- package/src/runtime/index-client.js +11 -11
- package/src/runtime/index-server.js +7 -4
- package/src/runtime/internal/client/bindings.js +1 -1
- package/src/runtime/internal/client/blocks.js +13 -4
- package/src/runtime/internal/client/component.js +55 -0
- package/src/runtime/internal/client/composite.js +4 -2
- package/src/runtime/internal/client/expression.js +65 -7
- package/src/runtime/internal/client/hmr.js +54 -43
- package/src/runtime/internal/client/index.js +5 -1
- package/src/runtime/internal/client/portal.js +70 -69
- package/src/runtime/internal/client/render.js +3 -0
- package/src/runtime/internal/server/index.js +92 -8
- package/tests/client/__snapshots__/html.test.tsrx.snap +3 -3
- package/tests/client/array/array.copy-within.test.tsrx +33 -31
- package/tests/client/array/array.derived.test.tsrx +186 -169
- package/tests/client/array/array.iteration.test.tsrx +40 -37
- package/tests/client/array/array.mutations.test.tsrx +113 -101
- package/tests/client/array/array.static.test.tsrx +119 -101
- package/tests/client/array/array.to-methods.test.tsrx +24 -21
- package/tests/client/async-suspend.test.tsrx +247 -246
- package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +0 -1
- package/tests/client/basic/basic.attributes.test.tsrx +428 -423
- package/tests/client/basic/basic.collections.test.tsrx +109 -102
- package/tests/client/basic/basic.components.test.tsrx +323 -205
- package/tests/client/basic/basic.errors.test.tsrx +91 -91
- package/tests/client/basic/basic.events.test.tsrx +114 -115
- package/tests/client/basic/basic.get-set.test.tsrx +97 -87
- package/tests/client/basic/basic.hmr.test.tsrx +19 -16
- package/tests/client/basic/basic.reactivity.test.tsrx +199 -191
- package/tests/client/basic/basic.rendering.test.tsrx +272 -182
- package/tests/client/basic/basic.styling.test.tsrx +23 -22
- package/tests/client/basic/basic.utilities.test.tsrx +10 -8
- package/tests/client/boundaries.test.tsrx +26 -26
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.rsrx.snap +5 -5
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +5 -5
- package/tests/client/compiler/compiler.assignments.test.tsrx +77 -81
- package/tests/client/compiler/compiler.attributes.test.tsrx +15 -15
- package/tests/client/compiler/compiler.basic.test.tsrx +322 -314
- package/tests/client/compiler/compiler.regex.test.tsrx +44 -47
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +38 -38
- package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
- package/tests/client/compiler/compiler.typescript.test.tsrx +2 -2
- package/tests/client/composite/composite.dynamic-components.test.tsrx +47 -48
- package/tests/client/composite/composite.generics.test.tsrx +168 -192
- package/tests/client/composite/composite.props.test.tsrx +97 -81
- package/tests/client/composite/composite.reactivity.test.tsrx +177 -147
- package/tests/client/composite/composite.render.test.tsrx +122 -105
- package/tests/client/computed-properties.test.tsrx +28 -28
- package/tests/client/context.test.tsrx +21 -21
- package/tests/client/css/global-additional-cases.test.tsrx +58 -58
- package/tests/client/css/global-advanced-selectors.test.tsrx +16 -16
- package/tests/client/css/global-at-rules.test.tsrx +10 -10
- package/tests/client/css/global-basic.test.tsrx +14 -14
- package/tests/client/css/global-classes-ids.test.tsrx +14 -14
- package/tests/client/css/global-combinators.test.tsrx +10 -10
- package/tests/client/css/global-complex-nesting.test.tsrx +14 -14
- package/tests/client/css/global-edge-cases.test.tsrx +18 -18
- package/tests/client/css/global-keyframes.test.tsrx +12 -12
- package/tests/client/css/global-nested.test.tsrx +10 -10
- package/tests/client/css/global-pseudo.test.tsrx +12 -12
- package/tests/client/css/global-scoping.test.tsrx +20 -20
- package/tests/client/css/style-identifier.test.tsrx +126 -259
- package/tests/client/date.test.tsrx +146 -133
- package/tests/client/dynamic-elements.test.tsrx +398 -365
- package/tests/client/events.test.tsrx +292 -290
- package/tests/client/for.test.tsrx +156 -153
- package/tests/client/head.test.tsrx +105 -96
- package/tests/client/html.test.tsrx +122 -26
- package/tests/client/input-value.test.tsrx +1361 -1314
- package/tests/client/lazy-array.test.tsrx +16 -13
- package/tests/client/lazy-destructuring.test.tsrx +257 -213
- package/tests/client/map.test.tsrx +65 -60
- package/tests/client/media-query.test.tsrx +22 -20
- package/tests/client/object.test.tsrx +87 -81
- package/tests/client/portal.test.tsrx +57 -51
- package/tests/client/ref.test.tsrx +233 -202
- package/tests/client/return.test.tsrx +71 -2560
- package/tests/client/set.test.tsrx +54 -45
- package/tests/client/svg.test.tsrx +216 -186
- package/tests/client/switch.test.tsrx +194 -193
- package/tests/client/track-async-hydration.test.tsrx +18 -14
- package/tests/client/tracked-index-access.test.tsrx +28 -18
- package/tests/client/try.test.tsrx +675 -548
- package/tests/client/tsx.test.tsrx +373 -311
- package/tests/client/typescript-generics.test.tsrx +145 -145
- package/tests/client/url/url.derived.test.tsrx +33 -28
- package/tests/client/url/url.parsing.test.tsrx +61 -51
- package/tests/client/url/url.partial-removal.test.tsrx +56 -48
- package/tests/client/url/url.reactivity.test.tsrx +142 -125
- package/tests/client/url/url.serialization.test.tsrx +13 -11
- package/tests/client/url-search-params/url-search-params.derived.test.tsrx +34 -29
- package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +25 -21
- package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +50 -45
- package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +111 -99
- package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +49 -43
- package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +14 -12
- package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +16 -14
- package/tests/hydration/basic.test.js +3 -3
- package/tests/hydration/compiled/client/basic.js +586 -651
- package/tests/hydration/compiled/client/composite.js +79 -104
- package/tests/hydration/compiled/client/events.js +140 -148
- package/tests/hydration/compiled/client/for.js +1005 -1018
- package/tests/hydration/compiled/client/head.js +124 -134
- package/tests/hydration/compiled/client/hmr.js +41 -48
- package/tests/hydration/compiled/client/html-in-template.js +38 -41
- package/tests/hydration/compiled/client/html.js +970 -1314
- package/tests/hydration/compiled/client/if-children.js +234 -249
- package/tests/hydration/compiled/client/if.js +182 -189
- package/tests/hydration/compiled/client/mixed-control-flow.js +347 -303
- package/tests/hydration/compiled/client/nested-control-flow.js +1084 -832
- package/tests/hydration/compiled/client/portal.js +65 -85
- package/tests/hydration/compiled/client/reactivity.js +84 -90
- package/tests/hydration/compiled/client/return.js +38 -1939
- package/tests/hydration/compiled/client/switch.js +218 -224
- package/tests/hydration/compiled/client/track-async-serialization.js +250 -259
- package/tests/hydration/compiled/client/try.js +123 -132
- package/tests/hydration/compiled/server/basic.js +773 -831
- package/tests/hydration/compiled/server/composite.js +166 -191
- package/tests/hydration/compiled/server/events.js +170 -184
- package/tests/hydration/compiled/server/for.js +851 -909
- package/tests/hydration/compiled/server/head.js +206 -216
- package/tests/hydration/compiled/server/hmr.js +64 -72
- package/tests/hydration/compiled/server/html-in-template.js +42 -76
- package/tests/hydration/compiled/server/html.js +1362 -1667
- package/tests/hydration/compiled/server/if-children.js +419 -445
- package/tests/hydration/compiled/server/if.js +194 -208
- package/tests/hydration/compiled/server/mixed-control-flow.js +249 -257
- package/tests/hydration/compiled/server/nested-control-flow.js +491 -515
- package/tests/hydration/compiled/server/portal.js +152 -160
- package/tests/hydration/compiled/server/reactivity.js +94 -106
- package/tests/hydration/compiled/server/return.js +28 -2172
- package/tests/hydration/compiled/server/switch.js +274 -286
- package/tests/hydration/compiled/server/track-async-serialization.js +340 -358
- package/tests/hydration/compiled/server/try.js +167 -185
- package/tests/hydration/components/basic.tsrx +320 -272
- package/tests/hydration/components/composite.tsrx +44 -32
- package/tests/hydration/components/events.tsrx +101 -91
- package/tests/hydration/components/for.tsrx +510 -452
- package/tests/hydration/components/head.tsrx +87 -80
- package/tests/hydration/components/hmr.tsrx +22 -17
- package/tests/hydration/components/html-in-template.tsrx +22 -17
- package/tests/hydration/components/html.tsrx +525 -443
- package/tests/hydration/components/if-children.tsrx +158 -148
- package/tests/hydration/components/if.tsrx +109 -95
- package/tests/hydration/components/mixed-control-flow.tsrx +100 -96
- package/tests/hydration/components/nested-control-flow.tsrx +215 -203
- package/tests/hydration/components/portal.tsrx +41 -34
- package/tests/hydration/components/reactivity.tsrx +37 -27
- package/tests/hydration/components/return.tsrx +12 -556
- package/tests/hydration/components/switch.tsrx +120 -114
- package/tests/hydration/components/track-async-serialization.tsrx +107 -91
- package/tests/hydration/components/try.tsrx +55 -40
- package/tests/hydration/html.test.js +4 -4
- package/tests/hydration/return.test.js +13 -532
- package/tests/server/await.test.tsrx +3 -3
- package/tests/server/basic.attributes.test.tsrx +264 -195
- package/tests/server/basic.components.test.tsrx +296 -169
- package/tests/server/basic.test.tsrx +300 -198
- package/tests/server/compiler.test.tsrx +62 -60
- package/tests/server/composite.props.test.tsrx +77 -63
- package/tests/server/composite.test.tsrx +168 -192
- package/tests/server/context.test.tsrx +18 -12
- package/tests/server/dynamic-elements.test.tsrx +197 -180
- package/tests/server/for.test.tsrx +85 -78
- package/tests/server/head.test.tsrx +50 -43
- package/tests/server/html-nesting-validation.test.tsrx +8 -8
- package/tests/server/if.test.tsrx +57 -51
- package/tests/server/lazy-destructuring.test.tsrx +366 -294
- package/tests/server/return.test.tsrx +76 -1355
- package/tests/server/streaming-ssr.test.tsrx +4 -75
- package/tests/server/style-identifier.test.tsrx +169 -131
- package/tests/server/switch.test.tsrx +91 -85
- package/tests/server/track-async-serialization.test.tsrx +105 -85
- package/tests/server/try.test.tsrx +374 -280
- package/tests/utils/compiler-compat-config.test.js +2 -2
- package/tests/utils/runtime-imports.test.js +10 -0
- package/types/index.d.ts +8 -0
- package/tests/client/__snapshots__/html.test.rsrx.snap +0 -40
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,62 @@
|
|
|
1
1
|
# ripple
|
|
2
2
|
|
|
3
|
+
## 0.3.70
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
[[`5c0b0ff`](https://github.com/Ripple-TS/ripple/commit/5c0b0ff031ddfb319bb048d627e2d2a2a49c1f1d)]:
|
|
9
|
+
- @tsrx/core@0.1.18
|
|
10
|
+
- @tsrx/ripple@0.1.18
|
|
11
|
+
|
|
12
|
+
## 0.3.69
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [#1177](https://github.com/Ripple-TS/ripple/pull/1177)
|
|
17
|
+
[`054bd1e`](https://github.com/Ripple-TS/ripple/commit/054bd1e75347e395f6c096f8e293d1baf8e03549)
|
|
18
|
+
Thanks [@trueadm](https://github.com/trueadm)! - Parse tags and bare fragments
|
|
19
|
+
as native TSRX by default, remove `component` keyword parsing, and
|
|
20
|
+
compile/format/lint function components that return native TSRX across the
|
|
21
|
+
React, Preact, Solid, Vue, and Ripple targets. Ripple component compilation now
|
|
22
|
+
only renders TSRX reachable from returned values and supports string and `null`
|
|
23
|
+
component returns.
|
|
24
|
+
|
|
25
|
+
Ripple now also preserves directly called PascalCase helpers as ordinary
|
|
26
|
+
functions while still compiling renderable component functions used as
|
|
27
|
+
components or render entries.
|
|
28
|
+
|
|
29
|
+
The old explicit TSRX wrapper tag is no longer special; TSRX elements and
|
|
30
|
+
fragments are the default expression syntax, and the tag name is treated like
|
|
31
|
+
any ordinary element name.
|
|
32
|
+
|
|
33
|
+
Ripple now exports a typed `Fragment` helper from its public runtimes and
|
|
34
|
+
supports `innerHTML` on both host elements and `Fragment`. Ripple also treats
|
|
35
|
+
`innerHTML` from element spreads as rendered content instead of serializing it
|
|
36
|
+
as an `innerhtml` attribute.
|
|
37
|
+
|
|
38
|
+
The `{html ...}` template directive has been removed. Use each target's native
|
|
39
|
+
raw HTML prop instead, such as `innerHTML` for Ripple/Solid/Vue or
|
|
40
|
+
`dangerouslySetInnerHTML` for React/Preact.
|
|
41
|
+
|
|
42
|
+
The `{text ...}` template directive has also been removed. Text values now use
|
|
43
|
+
ordinary `{expr}` containers, with explicit coercion written as JavaScript
|
|
44
|
+
(`String(value)`, `value + ''`, or a typed string value). Ripple optimizes
|
|
45
|
+
clearly string-shaped expressions and typed string props into text-node updates
|
|
46
|
+
without requiring a TSRX-specific directive.
|
|
47
|
+
|
|
48
|
+
- [#1177](https://github.com/Ripple-TS/ripple/pull/1177)
|
|
49
|
+
[`054bd1e`](https://github.com/Ripple-TS/ripple/commit/054bd1e75347e395f6c096f8e293d1baf8e03549)
|
|
50
|
+
Thanks [@trueadm](https://github.com/trueadm)! - Compile native TSRX functions
|
|
51
|
+
as value-producing functions and route component syntax through runtime
|
|
52
|
+
component helpers.
|
|
53
|
+
|
|
54
|
+
- Updated dependencies
|
|
55
|
+
[[`054bd1e`](https://github.com/Ripple-TS/ripple/commit/054bd1e75347e395f6c096f8e293d1baf8e03549),
|
|
56
|
+
[`054bd1e`](https://github.com/Ripple-TS/ripple/commit/054bd1e75347e395f6c096f8e293d1baf8e03549)]:
|
|
57
|
+
- @tsrx/core@0.1.17
|
|
58
|
+
- @tsrx/ripple@0.1.17
|
|
59
|
+
|
|
3
60
|
## 0.3.68
|
|
4
61
|
|
|
5
62
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Ripple is an elegant TypeScript UI framework",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.3.
|
|
6
|
+
"version": "0.3.70",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index-client.js",
|
|
9
9
|
"main": "src/runtime/index-client.js",
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"clsx": "^2.1.1",
|
|
75
75
|
"devalue": "^5.8.1",
|
|
76
76
|
"esm-env": "^1.2.2",
|
|
77
|
-
"@tsrx/core": "0.1.
|
|
78
|
-
"@tsrx/ripple": "0.1.
|
|
77
|
+
"@tsrx/core": "0.1.18",
|
|
78
|
+
"@tsrx/ripple": "0.1.18"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@types/estree": "^1.0.8",
|
package/src/jsx-runtime.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AddEventObject, RefKey, TSRXElement } from '#public';
|
|
1
|
+
import type { AddEventObject, FragmentProps, RefKey, TSRXElement } from '#public';
|
|
2
2
|
import type { Nullable } from '#helpers';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -40,7 +40,7 @@ export function jsxs(
|
|
|
40
40
|
* JSX Fragment component
|
|
41
41
|
* Ripple fragments are renderable expression values.
|
|
42
42
|
*/
|
|
43
|
-
export function Fragment(props:
|
|
43
|
+
export function Fragment(props: FragmentProps): TSRXElement;
|
|
44
44
|
|
|
45
45
|
export type ClassValue = string | import('clsx').ClassArray | import('clsx').ClassDictionary;
|
|
46
46
|
|
package/src/runtime/element.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import {
|
|
1
|
+
/** @import { CompatOptions, RootBoundaryOptions } from '#client' */
|
|
2
2
|
|
|
3
3
|
import { destroy_block, root } from './internal/client/blocks.js';
|
|
4
4
|
import { handle_root_events } from './internal/client/events.js';
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
get_next_sibling,
|
|
8
8
|
init_operations,
|
|
9
9
|
} from './internal/client/operations.js';
|
|
10
|
-
import {
|
|
10
|
+
import { render_component } from './internal/client/component.js';
|
|
11
11
|
import { create_anchor } from './internal/client/utils.js';
|
|
12
12
|
import { try_block } from './internal/client/try.js';
|
|
13
13
|
import { remove_ssr_css } from './internal/client/css.js';
|
|
@@ -39,34 +39,34 @@ function get_default_compat() {
|
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* @param {Node} anchor
|
|
42
|
-
* @param {(anchor: Node) => void}
|
|
42
|
+
* @param {(anchor: Node) => void} render_content
|
|
43
43
|
* @param {RootBoundaryOptions | undefined} boundary
|
|
44
44
|
* @returns {void}
|
|
45
45
|
*/
|
|
46
|
-
function render_root_boundary(anchor,
|
|
46
|
+
function render_root_boundary(anchor, render_content, boundary) {
|
|
47
47
|
const Pending = boundary?.pending;
|
|
48
48
|
const Catch = boundary?.catch;
|
|
49
49
|
|
|
50
50
|
try_block(
|
|
51
51
|
anchor,
|
|
52
52
|
(component_anchor) => {
|
|
53
|
-
|
|
53
|
+
render_content(component_anchor);
|
|
54
54
|
},
|
|
55
55
|
Catch
|
|
56
56
|
? (catch_anchor, error, reset) => {
|
|
57
|
-
Catch
|
|
57
|
+
render_component(Catch, catch_anchor, { error, reset: reset ?? (() => {}) });
|
|
58
58
|
}
|
|
59
59
|
: null,
|
|
60
60
|
(pending_anchor) => {
|
|
61
61
|
if (Pending) {
|
|
62
|
-
Pending
|
|
62
|
+
render_component(Pending, pending_anchor, {});
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
|
-
* @param {
|
|
69
|
+
* @param {Function} component
|
|
70
70
|
* @param {{ props?: Record<string, any>, target: HTMLElement, rootBoundary?: RootBoundaryOptions }} options
|
|
71
71
|
* @returns {() => void}
|
|
72
72
|
*/
|
|
@@ -92,7 +92,7 @@ export function mount(component, options) {
|
|
|
92
92
|
render_root_boundary(
|
|
93
93
|
anchor,
|
|
94
94
|
(component_anchor) => {
|
|
95
|
-
component
|
|
95
|
+
render_component(component, component_anchor, props);
|
|
96
96
|
},
|
|
97
97
|
options.rootBoundary,
|
|
98
98
|
);
|
|
@@ -105,7 +105,7 @@ export function mount(component, options) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
|
-
* @param {
|
|
108
|
+
* @param {Function} component
|
|
109
109
|
* @param {{ props?: Record<string, any>, target: HTMLElement, rootBoundary?: RootBoundaryOptions }} options
|
|
110
110
|
* @returns {() => void}
|
|
111
111
|
*/
|
|
@@ -138,7 +138,7 @@ export function hydrate(component, options) {
|
|
|
138
138
|
render_root_boundary(
|
|
139
139
|
/** @type {Comment} */ (anchor),
|
|
140
140
|
(component_anchor) => {
|
|
141
|
-
component
|
|
141
|
+
render_component(component, component_anchor, props);
|
|
142
142
|
},
|
|
143
143
|
options.rootBoundary,
|
|
144
144
|
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { output_push, noop } from './internal/server/index.js';
|
|
1
|
+
import { output_push, noop, tsrx_element } from './internal/server/index.js';
|
|
2
2
|
|
|
3
|
+
export { Fragment } from '../jsx-runtime.js';
|
|
3
4
|
export { Context } from './internal/server/context.js';
|
|
4
5
|
export {
|
|
5
6
|
untrack,
|
|
@@ -73,7 +74,9 @@ export const bindOffsetHeight = noop;
|
|
|
73
74
|
* However, we need to output a marker comment so hydration can work correctly.
|
|
74
75
|
*/
|
|
75
76
|
export function Portal() {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
return tsrx_element(function render_portal() {
|
|
78
|
+
// Portals are client-only, but we need to output a marker for hydration
|
|
79
|
+
// Output an empty HTML comment as a placeholder
|
|
80
|
+
output_push('<!--portal-->');
|
|
81
|
+
});
|
|
79
82
|
}
|
|
@@ -717,7 +717,7 @@ export function bindFiles(maybe_tracked, set_func = undefined) {
|
|
|
717
717
|
}
|
|
718
718
|
|
|
719
719
|
/**
|
|
720
|
-
* Syntactic sugar for binding a HTMLElement with {
|
|
720
|
+
* Syntactic sugar for binding a HTMLElement with ref={fn}
|
|
721
721
|
* @param {unknown} maybe_tracked
|
|
722
722
|
* @param {SetFunction | undefined} set_func
|
|
723
723
|
* @returns {(node: HTMLElement) => void}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from './constants.js';
|
|
19
19
|
import { next_sibling } from './operations.js';
|
|
20
20
|
import { apply_element_spread } from './render.js';
|
|
21
|
+
import { is_array } from '@tsrx/core/runtime/language-helpers';
|
|
21
22
|
import {
|
|
22
23
|
active_block,
|
|
23
24
|
active_component,
|
|
@@ -99,18 +100,19 @@ export function branch(fn, flags = 0, state = null) {
|
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
/**
|
|
102
|
-
* Wire up a `{
|
|
103
|
+
* Wire up a `ref={expr}` attribute. `expr` may be:
|
|
103
104
|
* - a callback function — invoked with the element on mount; if it returns
|
|
104
105
|
* a function, that function runs as the cleanup on unmount.
|
|
105
106
|
* - a `Tracked` (e.g. from `track()`) — `tracked.value` is set to the
|
|
106
107
|
* element on mount and reset to `null` on unmount.
|
|
107
108
|
* - a plain mutable var (`let foo;`) — the element is assigned to the
|
|
108
109
|
* variable on mount and reset to `null` on unmount.
|
|
110
|
+
* - an array of any of the above.
|
|
109
111
|
*
|
|
110
112
|
* `get_fn` is invoked through `untrack` so the surrounding render block
|
|
111
113
|
* doesn't subscribe to whatever the thunk happens to read. The supported
|
|
112
|
-
* shape is to pass the ref slot itself (`{
|
|
113
|
-
* `{
|
|
114
|
+
* shape is to pass the ref slot itself (`ref={tracker}`); a foot-gun like
|
|
115
|
+
* `ref={tracker.value}` would otherwise read the cell reactively and cause
|
|
114
116
|
* spurious re-runs.
|
|
115
117
|
*
|
|
116
118
|
* @param {Element} element
|
|
@@ -134,7 +136,14 @@ export function ref(element, get_fn, set_fn) {
|
|
|
134
136
|
e = null;
|
|
135
137
|
}
|
|
136
138
|
|
|
137
|
-
if (
|
|
139
|
+
if (is_array(ref_value)) {
|
|
140
|
+
e = branch(() => {
|
|
141
|
+
for (var i = 0; i < ref_value.length; i++) {
|
|
142
|
+
let current = ref_value[i];
|
|
143
|
+
ref(element, () => current);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
} else if (typeof ref_value === 'function') {
|
|
138
147
|
e = branch(() => {
|
|
139
148
|
effect(() => ref_value(element));
|
|
140
149
|
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** @import { Block } from '#client' */
|
|
2
|
+
|
|
3
|
+
import { is_tsrx_element } from '../../element.js';
|
|
4
|
+
import { render_value } from './expression.js';
|
|
5
|
+
import { active_block, pop_component, push_component } from './runtime.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {Function} fn
|
|
9
|
+
* @param {Node} anchor
|
|
10
|
+
* @param {Record<string, any>} props
|
|
11
|
+
* @param {Block | null} [block=active_block]
|
|
12
|
+
* @returns {void}
|
|
13
|
+
*/
|
|
14
|
+
export function render_component(fn, anchor, props, block = active_block) {
|
|
15
|
+
if (typeof fn !== 'function' || is_tsrx_element(fn)) {
|
|
16
|
+
throw_invalid_component_type(fn);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
run_component(fn, anchor, props, block);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {Function} fn
|
|
24
|
+
* @param {Node} anchor
|
|
25
|
+
* @param {Record<string, any>} props
|
|
26
|
+
* @param {Block | null} [block=active_block]
|
|
27
|
+
* @returns {void}
|
|
28
|
+
*/
|
|
29
|
+
function run_component(fn, anchor, props, block = active_block) {
|
|
30
|
+
push_component();
|
|
31
|
+
render_value(fn(props), /** @type {ChildNode} */ (anchor), block);
|
|
32
|
+
pop_component();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {import('../../element.js').TSRXElement} value
|
|
37
|
+
* @param {Node} anchor
|
|
38
|
+
* @param {Block | null} [block=active_block]
|
|
39
|
+
* @returns {void}
|
|
40
|
+
*/
|
|
41
|
+
export function render_tsrx_element(value, anchor, block = active_block) {
|
|
42
|
+
render_value(value, /** @type {ChildNode} */ (anchor), block);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {any} value
|
|
47
|
+
* @returns {never}
|
|
48
|
+
*/
|
|
49
|
+
function throw_invalid_component_type(value) {
|
|
50
|
+
if (is_tsrx_element(value)) {
|
|
51
|
+
throw new TypeError('Invalid component type: received a TSRXElement value.');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
throw new TypeError('Invalid component type: expected a component function.');
|
|
55
|
+
}
|
|
@@ -6,6 +6,7 @@ import { hydrate_next, hydrating } from './hydration.js';
|
|
|
6
6
|
import { active_block, active_namespace, get, with_ns } from './runtime.js';
|
|
7
7
|
import { top_element_to_ns } from './utils.js';
|
|
8
8
|
import { is_tsrx_element } from '../../element.js';
|
|
9
|
+
import { render_component } from './component.js';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* @typedef {((anchor: Node, props: Record<string, any>, block: Block | null) => void)} ComponentFunction
|
|
@@ -41,9 +42,10 @@ export function composite(get_component, node, props) {
|
|
|
41
42
|
if (typeof component === 'function') {
|
|
42
43
|
// Handle as regular component
|
|
43
44
|
b = branch(() => {
|
|
44
|
-
|
|
45
|
-
/** @type {ComponentFunction} */ (component)(anchor, props, block);
|
|
45
|
+
render_component(component, anchor, props);
|
|
46
46
|
});
|
|
47
|
+
} else if (is_tsrx_element(component)) {
|
|
48
|
+
throw new TypeError('Invalid component type: received a TSRXElement value.');
|
|
47
49
|
} else if (component != null) {
|
|
48
50
|
// Custom element - only create if component is not null/undefined
|
|
49
51
|
const ns = top_element_to_ns(component, active_namespace);
|
|
@@ -25,10 +25,29 @@ function find_enclosing_branch(block) {
|
|
|
25
25
|
return null;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* @param {any} value
|
|
30
|
+
* @param {ChildNode} anchor
|
|
31
|
+
* @param {Block | null} block
|
|
32
|
+
* @returns {void}
|
|
33
|
+
*/
|
|
34
|
+
export function render_value(value, anchor, block) {
|
|
35
|
+
if (is_tsrx_element(value)) {
|
|
36
|
+
render_tsrx_element(value, anchor, block);
|
|
37
|
+
} else if (is_array(value)) {
|
|
38
|
+
render_tsrx_collection(value, anchor, block);
|
|
39
|
+
} else if (value != null) {
|
|
40
|
+
var text = value + '';
|
|
41
|
+
if (text !== '') {
|
|
42
|
+
render_tsrx_collection_text(text, anchor, true);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
28
47
|
/**
|
|
29
48
|
* @param {any[]} value
|
|
30
49
|
* @param {ChildNode} anchor
|
|
31
|
-
* @param {Block} block
|
|
50
|
+
* @param {Block | null} block
|
|
32
51
|
* @returns {void}
|
|
33
52
|
*/
|
|
34
53
|
function render_tsrx_collection(value, anchor, block) {
|
|
@@ -49,7 +68,7 @@ function render_tsrx_collection(value, anchor, block) {
|
|
|
49
68
|
/**
|
|
50
69
|
* @param {any[]} value
|
|
51
70
|
* @param {ChildNode} anchor
|
|
52
|
-
* @param {Block} block
|
|
71
|
+
* @param {Block | null} block
|
|
53
72
|
* @returns {void}
|
|
54
73
|
*/
|
|
55
74
|
function render_tsrx_collection_items(value, anchor, block) {
|
|
@@ -57,7 +76,7 @@ function render_tsrx_collection_items(value, anchor, block) {
|
|
|
57
76
|
var item = value[i];
|
|
58
77
|
|
|
59
78
|
if (is_tsrx_element(item)) {
|
|
60
|
-
item
|
|
79
|
+
render_tsrx_element(item, anchor, block);
|
|
61
80
|
} else if (is_array(item)) {
|
|
62
81
|
render_tsrx_collection_items(item, anchor, block);
|
|
63
82
|
} else if (item != null) {
|
|
@@ -66,19 +85,46 @@ function render_tsrx_collection_items(value, anchor, block) {
|
|
|
66
85
|
}
|
|
67
86
|
}
|
|
68
87
|
|
|
88
|
+
/**
|
|
89
|
+
* @param {import('../../element.js').TSRXElement} value
|
|
90
|
+
* @param {ChildNode} anchor
|
|
91
|
+
* @param {Block | null} block
|
|
92
|
+
* @returns {void}
|
|
93
|
+
*/
|
|
94
|
+
function render_tsrx_element(value, anchor, block) {
|
|
95
|
+
var result = value.render(anchor, block);
|
|
96
|
+
|
|
97
|
+
if (is_tsrx_element(result)) {
|
|
98
|
+
render_tsrx_element(result, anchor, block);
|
|
99
|
+
} else if (is_array(result)) {
|
|
100
|
+
render_tsrx_collection(result, anchor, block);
|
|
101
|
+
} else if (result != null) {
|
|
102
|
+
render_tsrx_collection_text(result + '', anchor, true);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
69
106
|
/**
|
|
70
107
|
* @param {string} value
|
|
71
108
|
* @param {ChildNode} anchor
|
|
109
|
+
* @param {boolean} [assign=false]
|
|
72
110
|
* @returns {void}
|
|
73
111
|
*/
|
|
74
|
-
function render_tsrx_collection_text(value, anchor) {
|
|
112
|
+
function render_tsrx_collection_text(value, anchor, assign = false) {
|
|
75
113
|
if (!hydrating) {
|
|
76
|
-
|
|
114
|
+
var text = create_text(value);
|
|
115
|
+
anchor.before(text);
|
|
116
|
+
if (assign) {
|
|
117
|
+
assign_nodes(text, text);
|
|
118
|
+
}
|
|
77
119
|
return;
|
|
78
120
|
}
|
|
79
121
|
|
|
80
122
|
var node = hydrate_node;
|
|
81
123
|
|
|
124
|
+
if (node?.nodeType === COMMENT_NODE && /** @type {Comment} */ (node).data === HYDRATION_START) {
|
|
125
|
+
node = get_next_sibling(node);
|
|
126
|
+
}
|
|
127
|
+
|
|
82
128
|
if (node?.nodeType === TEXT_NODE) {
|
|
83
129
|
var current_value = /** @type {Text} */ (node).nodeValue ?? '';
|
|
84
130
|
|
|
@@ -91,12 +137,18 @@ function render_tsrx_collection_text(value, anchor) {
|
|
|
91
137
|
if (remaining !== '') {
|
|
92
138
|
var remaining_text = create_text(remaining);
|
|
93
139
|
/** @type {ChildNode} */ (node).after(remaining_text);
|
|
140
|
+
if (assign) {
|
|
141
|
+
assign_nodes(node, node);
|
|
142
|
+
}
|
|
94
143
|
set_hydrate_node(remaining_text);
|
|
95
144
|
return;
|
|
96
145
|
}
|
|
97
146
|
}
|
|
98
147
|
}
|
|
99
148
|
|
|
149
|
+
if (assign) {
|
|
150
|
+
assign_nodes(node, node);
|
|
151
|
+
}
|
|
100
152
|
set_hydrate_node(get_next_sibling(node) ?? anchor);
|
|
101
153
|
return;
|
|
102
154
|
}
|
|
@@ -109,6 +161,9 @@ function render_tsrx_collection_text(value, anchor) {
|
|
|
109
161
|
anchor.before(new_text);
|
|
110
162
|
}
|
|
111
163
|
|
|
164
|
+
if (assign) {
|
|
165
|
+
assign_nodes(new_text, new_text);
|
|
166
|
+
}
|
|
112
167
|
set_hydrate_node(node ?? anchor);
|
|
113
168
|
}
|
|
114
169
|
|
|
@@ -138,7 +193,10 @@ export function expression(node, get_value) {
|
|
|
138
193
|
var next_value = get_value();
|
|
139
194
|
var next_is_collection = is_array(next_value);
|
|
140
195
|
var next_is_element = next_is_collection || is_tsrx_element(next_value);
|
|
141
|
-
var is_hydration_marker =
|
|
196
|
+
var is_hydration_marker =
|
|
197
|
+
hydrating &&
|
|
198
|
+
anchor.nodeType === COMMENT_NODE &&
|
|
199
|
+
/** @type {Comment} */ (anchor).data === HYDRATION_START;
|
|
142
200
|
|
|
143
201
|
if (is_hydration_marker) {
|
|
144
202
|
end ??= ensure_expression_end(anchor);
|
|
@@ -187,7 +245,7 @@ export function expression(node, get_value) {
|
|
|
187
245
|
if (next_is_collection) {
|
|
188
246
|
render_tsrx_collection(next_value, end ?? anchor, block);
|
|
189
247
|
} else {
|
|
190
|
-
next_value
|
|
248
|
+
render_tsrx_element(next_value, end ?? anchor, block);
|
|
191
249
|
}
|
|
192
250
|
});
|
|
193
251
|
|
|
@@ -5,8 +5,10 @@ import { HMR } from './constants.js';
|
|
|
5
5
|
import { hydrate_node, hydrating } from './hydration.js';
|
|
6
6
|
import { branch, destroy_block, render } from './blocks.js';
|
|
7
7
|
import { active_block, get, set, tracked } from './runtime.js';
|
|
8
|
+
import { render_component } from './component.js';
|
|
9
|
+
import { tsrx_element } from '../../element.js';
|
|
8
10
|
|
|
9
|
-
/** @typedef {(
|
|
11
|
+
/** @typedef {(props?: any) => any} Component */
|
|
10
12
|
|
|
11
13
|
/** @typedef {Component & { [HMR]: { fn: Component; current: Tracked | undefined; update: (incoming: ComponentWrapper) => void; } }} ComponentWrapper */
|
|
12
14
|
|
|
@@ -23,53 +25,62 @@ export function hmr(fn) {
|
|
|
23
25
|
var current;
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
|
-
* @param {Node} anchor
|
|
27
28
|
* @param {any} props
|
|
28
|
-
* @param {Block | null} [block]
|
|
29
29
|
*/
|
|
30
|
-
function wrapper(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
/** @type {Block | null} */
|
|
44
|
-
var effect = null;
|
|
45
|
-
|
|
46
|
-
render(
|
|
47
|
-
() => {
|
|
48
|
-
var next_component = get(/** @type {Tracked} */ (current));
|
|
49
|
-
|
|
50
|
-
if (component === next_component) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
component = next_component;
|
|
55
|
-
|
|
56
|
-
if (effect) {
|
|
57
|
-
destroy_block(effect);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
effect = branch(() => {
|
|
61
|
-
/** @type {Function} */ (component)(target, props, active_block);
|
|
62
|
-
});
|
|
63
|
-
},
|
|
64
|
-
null,
|
|
65
|
-
RENDER_BLOCK,
|
|
66
|
-
);
|
|
30
|
+
function wrapper(props) {
|
|
31
|
+
/**
|
|
32
|
+
* @param {Node} anchor
|
|
33
|
+
* @param {Block | null} [block]
|
|
34
|
+
* @returns {void}
|
|
35
|
+
*/
|
|
36
|
+
function render_children(anchor, block = active_block) {
|
|
37
|
+
if (current === undefined) {
|
|
38
|
+
current = wrapper[HMR].current;
|
|
39
|
+
}
|
|
40
|
+
/** @type {Node} */
|
|
41
|
+
var target = anchor;
|
|
67
42
|
|
|
68
|
-
|
|
69
|
-
|
|
43
|
+
if (current === undefined) {
|
|
44
|
+
current = tracked(fn, /** @type {Block} */ (block));
|
|
45
|
+
wrapper[HMR].current = current;
|
|
46
|
+
}
|
|
47
|
+
var component = {};
|
|
48
|
+
|
|
49
|
+
/** @type {Block | null} */
|
|
50
|
+
var effect = null;
|
|
51
|
+
|
|
52
|
+
render(
|
|
53
|
+
() => {
|
|
54
|
+
var next_component = get(/** @type {Tracked} */ (current));
|
|
55
|
+
|
|
56
|
+
if (component === next_component) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
component = next_component;
|
|
61
|
+
|
|
62
|
+
if (effect) {
|
|
63
|
+
destroy_block(effect);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
effect = branch(() => {
|
|
67
|
+
render_component(
|
|
68
|
+
/** @type {Function} */ (component),
|
|
69
|
+
/** @type {ChildNode} */ (target),
|
|
70
|
+
props,
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
null,
|
|
75
|
+
RENDER_BLOCK,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (hydrating) {
|
|
79
|
+
target = /** @type {Node} */ (hydrate_node);
|
|
80
|
+
}
|
|
70
81
|
}
|
|
71
82
|
|
|
72
|
-
return
|
|
83
|
+
return tsrx_element(render_children);
|
|
73
84
|
}
|
|
74
85
|
|
|
75
86
|
wrapper[HMR] = {
|
|
@@ -85,6 +85,8 @@ export {
|
|
|
85
85
|
|
|
86
86
|
export { composite } from './composite.js';
|
|
87
87
|
|
|
88
|
+
export { render_component } from './component.js';
|
|
89
|
+
|
|
88
90
|
export { for_block as for, for_block_keyed as for_keyed } from './for.js';
|
|
89
91
|
|
|
90
92
|
export { if_block as if } from './if.js';
|
|
@@ -127,10 +129,12 @@ export { rpc } from './rpc.js';
|
|
|
127
129
|
|
|
128
130
|
export { tsx_compat } from './compat.js';
|
|
129
131
|
|
|
132
|
+
export { render_tsrx_element } from './component.js';
|
|
133
|
+
|
|
130
134
|
export { TRY_BLOCK, HMR } from './constants.js';
|
|
131
135
|
|
|
132
136
|
export { hmr } from './hmr.js';
|
|
133
137
|
|
|
134
138
|
export { pop, next } from './hydration.js';
|
|
135
139
|
|
|
136
|
-
export { tsrx_element, normalize_children } from '../../element.js';
|
|
140
|
+
export { is_tsrx_element, tsrx_element, normalize_children } from '../../element.js';
|