ripple 0.4.1 → 0.4.3
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 +162 -0
- package/package.json +9 -3
- package/src/constants.js +4 -0
- package/src/jsx-runtime.d.ts +2 -1
- package/src/runtime/array.js +15 -9
- package/src/runtime/index-client.js +25 -7
- package/src/runtime/index-server.js +1 -0
- package/src/runtime/internal/client/attributes.js +313 -0
- package/src/runtime/internal/client/blocks.js +4 -14
- package/src/runtime/internal/client/component.js +2 -5
- package/src/runtime/internal/client/composite.js +14 -6
- package/src/runtime/internal/client/constants.js +12 -6
- package/src/runtime/internal/client/context.js +3 -2
- package/src/runtime/internal/client/css.js +11 -26
- package/src/runtime/internal/client/errors.js +188 -0
- package/src/runtime/internal/client/events.js +79 -34
- package/src/runtime/internal/client/expression.js +21 -116
- package/src/runtime/internal/client/for.js +272 -222
- package/src/runtime/internal/client/head.js +4 -3
- package/src/runtime/internal/client/html.js +5 -3
- package/src/runtime/internal/client/hydrate.js +484 -0
- package/src/runtime/internal/client/hydration-enabled.js +7 -0
- package/src/runtime/internal/client/hydration.js +16 -97
- package/src/runtime/internal/client/if.js +13 -9
- package/src/runtime/internal/client/index.js +16 -8
- package/src/runtime/internal/client/operations.js +12 -9
- package/src/runtime/internal/client/portal.js +3 -2
- package/src/runtime/internal/client/render.js +75 -321
- package/src/runtime/internal/client/root-boundary-enabled.js +7 -0
- package/src/runtime/internal/client/runtime.js +129 -362
- package/src/runtime/internal/client/template-ns.js +47 -0
- package/src/runtime/internal/client/template.js +63 -140
- package/src/runtime/internal/client/track-async.js +356 -0
- package/src/runtime/internal/client/try.js +133 -319
- package/src/runtime/internal/client/types.d.ts +48 -24
- package/src/runtime/internal/server/index.js +38 -33
- package/src/runtime/internal/server/prerender.js +27 -0
- package/src/server/index.js +1 -0
- package/src/utils/class-name.js +28 -0
- package/tests/client/basic/basic.errors.test.tsrx +3 -3
- package/tests/client/compiler/__snapshots__/compiler.typescript.test.tsrx.snap +0 -2
- package/tests/client/compiler/compiler.basic.test.tsrx +4 -4
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +3 -3
- package/tests/client/composite/composite.props.test.tsrx +10 -10
- package/tests/client/derived-release.test.tsrx +3 -3
- package/tests/client/for-item.test.tsrx +443 -0
- package/tests/client/for-selector.test.tsrx +95 -0
- package/tests/hydration/compiled/client/basic.js +97 -123
- package/tests/hydration/compiled/client/composite.js +5 -5
- package/tests/hydration/compiled/client/events.js +84 -79
- package/tests/hydration/compiled/client/for.js +229 -233
- package/tests/hydration/compiled/client/fragment-cursor.js +781 -481
- package/tests/hydration/compiled/client/head.js +23 -26
- package/tests/hydration/compiled/client/hmr.js +4 -4
- package/tests/hydration/compiled/client/html-in-template.js +5 -5
- package/tests/hydration/compiled/client/html.js +174 -208
- package/tests/hydration/compiled/client/if-children.js +71 -70
- package/tests/hydration/compiled/client/if-fragment-controlflow.js +46 -46
- package/tests/hydration/compiled/client/if.js +26 -26
- package/tests/hydration/compiled/client/mixed-control-flow.js +63 -105
- package/tests/hydration/compiled/client/nested-control-flow.js +170 -390
- package/tests/hydration/compiled/client/portal.js +10 -10
- package/tests/hydration/compiled/client/reactivity.js +36 -50
- package/tests/hydration/compiled/client/return.js +2 -2
- package/tests/hydration/compiled/client/streaming.js +34 -40
- package/tests/hydration/compiled/client/switch.js +25 -25
- package/tests/hydration/compiled/client/track-async-serialization.js +41 -41
- package/tests/hydration/compiled/client/try.js +15 -15
- package/tests/hydration/compiled/client/typed-text.js +8 -19
- package/tests/hydration/compiled/server/basic.js +6 -6
- package/tests/hydration/compiled/server/events.js +13 -61
- package/tests/hydration/compiled/server/for.js +23 -31
- package/tests/hydration/compiled/server/fragment-cursor.js +214 -366
- package/tests/hydration/compiled/server/head.js +6 -6
- package/tests/hydration/compiled/server/hmr.js +1 -1
- package/tests/hydration/compiled/server/html.js +1 -1
- package/tests/hydration/compiled/server/if-children.js +9 -9
- package/tests/hydration/compiled/server/if.js +5 -5
- package/tests/hydration/compiled/server/mixed-control-flow.js +4 -4
- package/tests/hydration/compiled/server/portal.js +1 -1
- package/tests/hydration/compiled/server/reactivity.js +9 -9
- package/tests/hydration/compiled/server/streaming.js +9 -9
- package/tests/hydration/compiled/server/switch.js +4 -4
- package/tests/hydration/compiled/server/track-async-serialization.js +16 -16
- package/tests/hydration/compiled/server/try.js +4 -4
- package/tests/hydration/compiled/server/typed-text.js +1 -1
- package/tests/hydration/components/fragment-cursor.tsrx +60 -0
- package/tests/hydration/components/track-async-serialization.tsrx +2 -2
- package/tests/hydration/fragment-cursor.test.js +34 -1
- package/tests/hydration/track-async-serialization.test.js +1 -1
- package/tests/server/basic.components.test.tsrx +3 -3
- package/tests/server/basic.test.tsrx +23 -0
- package/tests/server/track-async-serialization.test.tsrx +6 -6
- package/tests/utils/tracked-types.test.js +3 -3
- package/types/index.d.ts +8 -8
- package/types/server.d.ts +17 -0
|
@@ -14,6 +14,7 @@ import { hydrate_next, hydrate_node, hydrating } from './hydration.js';
|
|
|
14
14
|
import { create_text, resolve_anchor } from './operations.js';
|
|
15
15
|
import { active_block, probe_if, run_untracked } from './runtime.js';
|
|
16
16
|
import { append } from './template.js';
|
|
17
|
+
import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* The if block renders its branch directly: the block owns the branch's DOM
|
|
@@ -108,7 +109,9 @@ function destroy_branch(state, block) {
|
|
|
108
109
|
* is materialized as late as possible: when a branch swap needs the position
|
|
109
110
|
* of the branch being replaced (still rendered), or when the if renders
|
|
110
111
|
* nothing and would otherwise have no position at all. Until then a list of
|
|
111
|
-
* `@if` items keeps no anchor nodes in the DOM.
|
|
112
|
+
* `@if` items keeps no anchor nodes in the DOM. A tail sentinel (the if is
|
|
113
|
+
* the last thing rendered into its parent) is never materialized: appending
|
|
114
|
+
* to the parent stays right for the if's whole life.
|
|
112
115
|
* @param {IfState} state
|
|
113
116
|
* @param {Block} block
|
|
114
117
|
*/
|
|
@@ -147,9 +150,14 @@ function update_branch(state, fn) {
|
|
|
147
150
|
|
|
148
151
|
var block = /** @type {Block} */ (active_block);
|
|
149
152
|
|
|
153
|
+
var anchor = /** @type {AppendIntoAnchor} */ (state.a);
|
|
154
|
+
// A sentinel the if may still materialize (a tail sentinel never is).
|
|
155
|
+
var sentinel = anchor.into === true && anchor.tail !== true;
|
|
156
|
+
|
|
150
157
|
if (previous !== UNINITIALIZED) {
|
|
151
|
-
if (
|
|
158
|
+
if (sentinel) {
|
|
152
159
|
materialize_anchor(state, block);
|
|
160
|
+
sentinel = false;
|
|
153
161
|
}
|
|
154
162
|
destroy_branch(state, block);
|
|
155
163
|
}
|
|
@@ -161,14 +169,10 @@ function update_branch(state, fn) {
|
|
|
161
169
|
|
|
162
170
|
if (o !== null) {
|
|
163
171
|
move_block_last(o);
|
|
164
|
-
} else if (
|
|
165
|
-
/** @type {AppendIntoAnchor} */ (state.a).into === true &&
|
|
166
|
-
state.start === null &&
|
|
167
|
-
first_child_node(block, null) === null
|
|
168
|
-
) {
|
|
172
|
+
} else if (sentinel && state.start === null && first_child_node(block, null) === null) {
|
|
169
173
|
materialize_anchor(state, block);
|
|
170
174
|
}
|
|
171
|
-
} else if (
|
|
175
|
+
} else if (sentinel) {
|
|
172
176
|
materialize_anchor(state, block);
|
|
173
177
|
}
|
|
174
178
|
}
|
|
@@ -222,7 +226,7 @@ export function if_block(node, fn, root_controlled, x) {
|
|
|
222
226
|
var boundary;
|
|
223
227
|
var anchor = node;
|
|
224
228
|
|
|
225
|
-
if (!hydrating) {
|
|
229
|
+
if (!(HYDRATION && hydrating)) {
|
|
226
230
|
// Evaluate the condition before deciding whether the if needs a block:
|
|
227
231
|
// a condition that read no tracked state has its branch rendered by the
|
|
228
232
|
// probe itself, directly under the current block, with no if block, no
|
|
@@ -4,7 +4,6 @@ export {
|
|
|
4
4
|
next_sibling as sibling,
|
|
5
5
|
hydrate_first_child as hydrate_child,
|
|
6
6
|
hydrate_next_sibling as hydrate_sibling,
|
|
7
|
-
hydrate_text_child as hydrate_text,
|
|
8
7
|
append_into,
|
|
9
8
|
document,
|
|
10
9
|
create_text,
|
|
@@ -13,9 +12,9 @@ export {
|
|
|
13
12
|
|
|
14
13
|
export {
|
|
15
14
|
set_text,
|
|
15
|
+
set_text_content,
|
|
16
16
|
set_class,
|
|
17
|
-
|
|
18
|
-
set_attribute,
|
|
17
|
+
set_class_value,
|
|
19
18
|
set_value,
|
|
20
19
|
set_checked,
|
|
21
20
|
set_selected,
|
|
@@ -23,7 +22,6 @@ export {
|
|
|
23
22
|
|
|
24
23
|
export {
|
|
25
24
|
render,
|
|
26
|
-
render_spread,
|
|
27
25
|
ref,
|
|
28
26
|
branch,
|
|
29
27
|
destroy_block,
|
|
@@ -41,7 +39,8 @@ export {
|
|
|
41
39
|
SUSPENSE_REJECTED,
|
|
42
40
|
RENDER_ENTRY as $r,
|
|
43
41
|
} from './constants.js';
|
|
44
|
-
export { event, render_event, delegate } from './events.js';
|
|
42
|
+
export { event, render_event, delegate, listen } from './events.js';
|
|
43
|
+
export { set_style, set_attribute, render_spread } from './attributes.js';
|
|
45
44
|
export { portal } from './portal.js';
|
|
46
45
|
|
|
47
46
|
export {
|
|
@@ -63,7 +62,7 @@ export {
|
|
|
63
62
|
update_property,
|
|
64
63
|
update_pre_property,
|
|
65
64
|
track,
|
|
66
|
-
|
|
65
|
+
track_read_only,
|
|
67
66
|
is_tracked_pending,
|
|
68
67
|
peek_tracked,
|
|
69
68
|
push_component,
|
|
@@ -80,11 +79,13 @@ export {
|
|
|
80
79
|
schedule_update,
|
|
81
80
|
} from './runtime.js';
|
|
82
81
|
|
|
82
|
+
export { track_async } from './track-async.js';
|
|
83
|
+
|
|
83
84
|
export { composite } from './composite.js';
|
|
84
85
|
|
|
85
86
|
export { render_component } from './component.js';
|
|
86
87
|
|
|
87
|
-
export { for_block as for, for_block_keyed as for_keyed } from './for.js';
|
|
88
|
+
export { for_block as for, for_block_keyed as for_keyed, item } from './for.js';
|
|
88
89
|
|
|
89
90
|
export { selector, selector_match } from './selector.js';
|
|
90
91
|
|
|
@@ -96,7 +97,14 @@ export { if_block as switch } from './if.js';
|
|
|
96
97
|
|
|
97
98
|
export { template, append, text } from './template.js';
|
|
98
99
|
|
|
99
|
-
export {
|
|
100
|
+
export { template_ns } from './template-ns.js';
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
ripple_array,
|
|
104
|
+
ripple_array_from,
|
|
105
|
+
ripple_array_of,
|
|
106
|
+
ripple_array_from_async,
|
|
107
|
+
} from '../../array.js';
|
|
100
108
|
|
|
101
109
|
export { ripple_object } from '../../object.js';
|
|
102
110
|
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
hydrate_first_child,
|
|
5
5
|
hydrate_next_sibling,
|
|
6
6
|
hydrate_node,
|
|
7
|
-
hydrate_text_child,
|
|
8
7
|
hydrating,
|
|
9
8
|
set_hydrate_node,
|
|
10
9
|
} from './hydration.js';
|
|
11
10
|
import { get_descriptor } from '@tsrx/core/runtime/language-helpers';
|
|
11
|
+
import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
|
|
12
12
|
|
|
13
|
-
export { hydrate_first_child, hydrate_next_sibling
|
|
13
|
+
export { hydrate_first_child, hydrate_next_sibling };
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* The `firstChild` / `nextSibling` getters, called directly so a traversal
|
|
@@ -77,7 +77,7 @@ export function get_last_child(node) {
|
|
|
77
77
|
* @returns {Node | null}
|
|
78
78
|
*/
|
|
79
79
|
export function first_child(node, is_text) {
|
|
80
|
-
if (!hydrating) {
|
|
80
|
+
if (!(HYDRATION && hydrating)) {
|
|
81
81
|
return node.firstChild;
|
|
82
82
|
}
|
|
83
83
|
return hydrate_first_child(is_text);
|
|
@@ -90,10 +90,13 @@ export function first_child(node, is_text) {
|
|
|
90
90
|
* hydration we descend the cursor into `parent` (mirroring first_child) so the
|
|
91
91
|
* first appended component adopts the server's first child of `parent`.
|
|
92
92
|
* @param {Node} parent
|
|
93
|
+
* @param {boolean} [tail] the sentinel stands for the tail of `parent`: what
|
|
94
|
+
* it anchors is the last thing the framework appends there, so it stays the
|
|
95
|
+
* right insertion point for its whole life (see the `if` runtime)
|
|
93
96
|
* @returns {AppendIntoAnchor}
|
|
94
97
|
*/
|
|
95
|
-
export function append_into(parent) {
|
|
96
|
-
if (hydrating) {
|
|
98
|
+
export function append_into(parent, tail) {
|
|
99
|
+
if (HYDRATION && hydrating) {
|
|
97
100
|
var child = get_first_child(/** @type {Node} */ (hydrate_node));
|
|
98
101
|
|
|
99
102
|
if (child === null) {
|
|
@@ -103,7 +106,7 @@ export function append_into(parent) {
|
|
|
103
106
|
set_hydrate_node(child);
|
|
104
107
|
}
|
|
105
108
|
|
|
106
|
-
return { parent, into: true };
|
|
109
|
+
return { parent, into: true, tail: tail === true };
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
/**
|
|
@@ -122,7 +125,7 @@ export function resolve_anchor(node) {
|
|
|
122
125
|
if (/** @type {AppendIntoAnchor} */ (node).into !== true) {
|
|
123
126
|
return /** @type {Node} */ (node);
|
|
124
127
|
}
|
|
125
|
-
if (hydrating) {
|
|
128
|
+
if (HYDRATION && hydrating) {
|
|
126
129
|
return /** @type {Node} */ (hydrate_node);
|
|
127
130
|
}
|
|
128
131
|
return /** @type {AppendIntoAnchor} */ (node).parent.appendChild(create_text());
|
|
@@ -137,7 +140,7 @@ export function resolve_anchor(node) {
|
|
|
137
140
|
export function first_child_frag(node, is_text) {
|
|
138
141
|
// During hydration, for fragment templates, hydrate_node is already
|
|
139
142
|
// pointing to the first element of the fragment. Don't descend into it.
|
|
140
|
-
if (hydrating) {
|
|
143
|
+
if (HYDRATION && hydrating) {
|
|
141
144
|
return hydrate_node;
|
|
142
145
|
}
|
|
143
146
|
var child = /** @type {Text} */ (first_child(node, is_text));
|
|
@@ -164,7 +167,7 @@ export function get_next_sibling(node) {
|
|
|
164
167
|
* @returns {Node | null}
|
|
165
168
|
*/
|
|
166
169
|
export function next_sibling(node, is_text) {
|
|
167
|
-
if (!hydrating) {
|
|
170
|
+
if (!(HYDRATION && hydrating)) {
|
|
168
171
|
return node.nextSibling;
|
|
169
172
|
}
|
|
170
173
|
return hydrate_next_sibling(is_text);
|
|
@@ -6,6 +6,7 @@ import { handle_root_events, release_root_events } from './events.js';
|
|
|
6
6
|
import { active_block } from './runtime.js';
|
|
7
7
|
import { hydrating, hydrate_node, set_hydration, set_hydrating } from './hydration.js';
|
|
8
8
|
import { is_tsrx_element, tsrx_element } from '../../element.js';
|
|
9
|
+
import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* @typedef {(anchor: AppendIntoAnchor, block: Block) => void} PortalRender
|
|
@@ -67,7 +68,7 @@ function run_portal(s) {
|
|
|
67
68
|
end: null,
|
|
68
69
|
r: s.r,
|
|
69
70
|
c: next_children,
|
|
70
|
-
a: { parent: next_target, into: true },
|
|
71
|
+
a: { parent: next_target, into: true, tail: false },
|
|
71
72
|
b: /** @type {Block} */ (s.p),
|
|
72
73
|
});
|
|
73
74
|
|
|
@@ -126,7 +127,7 @@ function create_portal(get_target, render_children, get_children) {
|
|
|
126
127
|
p: null,
|
|
127
128
|
};
|
|
128
129
|
|
|
129
|
-
if (!hydrating) {
|
|
130
|
+
if (!(HYDRATION && hydrating)) {
|
|
130
131
|
render(run_portal, state);
|
|
131
132
|
return;
|
|
132
133
|
}
|
|
@@ -1,191 +1,85 @@
|
|
|
1
1
|
/** @import { Block } from '#client' */
|
|
2
2
|
|
|
3
|
-
import { branch, destroy_block, ref } from './blocks.js';
|
|
4
|
-
import { DESTROYED, REF_PROP } from './constants.js';
|
|
5
|
-
import { isRefProp as is_ref_prop } from '@tsrx/core/runtime/ref';
|
|
6
|
-
import { is_ripple_object } from './utils.js';
|
|
7
|
-
import {
|
|
8
|
-
get_descriptors,
|
|
9
|
-
get_own_property_symbols,
|
|
10
|
-
get_prototype_of,
|
|
11
|
-
} from '@tsrx/core/runtime/language-helpers';
|
|
12
|
-
import { event_listener } from './events.js';
|
|
13
|
-
import { get_attribute_event_name, is_event_attribute } from '@tsrx/core/runtime/events';
|
|
14
|
-
import { get } from './runtime.js';
|
|
15
3
|
import { hydrating } from './hydration.js';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
4
|
+
import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
|
|
5
|
+
import { TEXT_NODE } from '../../../constants.js';
|
|
6
|
+
import { class_name } from '../../../utils/class-name.js';
|
|
18
7
|
|
|
19
8
|
/**
|
|
20
|
-
*
|
|
9
|
+
* Sets the text of an element whose only child is that text. The template
|
|
10
|
+
* leaves such an element empty, so the first write creates the text node and
|
|
11
|
+
* later writes update it in place; server-rendered text is adopted as is.
|
|
12
|
+
* The element has a text node exactly when the value last written did not
|
|
13
|
+
* read as empty (an empty write drops the node again), so `prev`, the value
|
|
14
|
+
* the render block wrote before, says whether one exists without a DOM read.
|
|
15
|
+
* @param {Element} element
|
|
21
16
|
* @param {any} value
|
|
17
|
+
* @param {any} prev the value of the previous write (`''` before the first)
|
|
22
18
|
* @returns {void}
|
|
23
19
|
*/
|
|
24
|
-
export function
|
|
20
|
+
export function set_text_content(element, value, prev) {
|
|
25
21
|
var str = value == null ? '' : value + '';
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
text.nodeValue = str;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** @type {Map<string, string[]>} */
|
|
36
|
-
var setters_cache = new Map();
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param {Element} element
|
|
40
|
-
* @returns {string[]}
|
|
41
|
-
*/
|
|
42
|
-
function get_setters(element) {
|
|
43
|
-
var setters = setters_cache.get(element.nodeName);
|
|
44
|
-
if (setters) return setters;
|
|
45
|
-
setters_cache.set(element.nodeName, (setters = []));
|
|
46
|
-
|
|
47
|
-
var descriptors;
|
|
48
|
-
var proto = element; // In the case of custom elements there might be setters on the instance
|
|
49
|
-
var element_proto = Element.prototype;
|
|
50
|
-
|
|
51
|
-
// Stop at Element, from there on there's only unnecessary setters we're not interested in
|
|
52
|
-
// Do not use constructor.name here as that's unreliable in some browser environments
|
|
53
|
-
while (element_proto !== proto) {
|
|
54
|
-
descriptors = get_descriptors(proto);
|
|
55
|
-
|
|
56
|
-
for (var key in descriptors) {
|
|
57
|
-
if (descriptors[key].set) {
|
|
58
|
-
setters.push(key);
|
|
22
|
+
if (HYDRATION && hydrating) {
|
|
23
|
+
var text = element.firstChild;
|
|
24
|
+
if (text === null) {
|
|
25
|
+
if (str !== '') {
|
|
26
|
+
element.textContent = str;
|
|
59
27
|
}
|
|
28
|
+
} else if (text.nodeType !== TEXT_NODE || str === '') {
|
|
29
|
+
element.textContent = str;
|
|
30
|
+
} else if (text.nodeValue !== str) {
|
|
31
|
+
text.nodeValue = str;
|
|
60
32
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* @param {Element} element
|
|
70
|
-
* @param {any} value
|
|
71
|
-
* @param {Record<string, string | number | null | undefined> | undefined} prev
|
|
72
|
-
* @returns {void}
|
|
73
|
-
*/
|
|
74
|
-
export function set_style(element, value, prev = {}) {
|
|
75
|
-
if (value == null) {
|
|
76
|
-
element.removeAttribute('style');
|
|
77
|
-
} else if (typeof value !== 'string') {
|
|
78
|
-
apply_styles(/** @type {HTMLElement} */ (element), value, prev);
|
|
33
|
+
} else if (prev == null || prev === '') {
|
|
34
|
+
if (str !== '') {
|
|
35
|
+
element.textContent = str;
|
|
36
|
+
}
|
|
37
|
+
} else if (str === '') {
|
|
38
|
+
element.textContent = '';
|
|
79
39
|
} else {
|
|
80
|
-
|
|
81
|
-
element.style.cssText = value;
|
|
40
|
+
/** @type {Text} */ (element.firstChild).nodeValue = str;
|
|
82
41
|
}
|
|
83
42
|
}
|
|
84
43
|
|
|
85
44
|
/**
|
|
86
|
-
* @param {
|
|
87
|
-
* @param {string} attribute
|
|
45
|
+
* @param {Text} text
|
|
88
46
|
* @param {any} value
|
|
89
47
|
* @returns {void}
|
|
90
48
|
*/
|
|
91
|
-
export function
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* @param {HTMLElement} element
|
|
103
|
-
* @param {Record<string, string | number | null | undefined>} new_styles
|
|
104
|
-
* @param {Record<string, string | number | null | undefined>} prev
|
|
105
|
-
*/
|
|
106
|
-
function apply_styles(element, new_styles, prev) {
|
|
107
|
-
const style = element.style;
|
|
108
|
-
|
|
109
|
-
// Apply new styles
|
|
110
|
-
for (const key in new_styles) {
|
|
111
|
-
const css_prop = normalize_css_property_name(key);
|
|
112
|
-
const raw_value = new_styles[key];
|
|
113
|
-
const value = raw_value == null ? null : String(raw_value);
|
|
114
|
-
|
|
115
|
-
if (!(key in prev) || prev[key] !== value) {
|
|
116
|
-
style.setProperty(css_prop, value);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Remove properties that were in prev but not in new_styles
|
|
121
|
-
for (const key in prev) {
|
|
122
|
-
if (!(key in new_styles)) {
|
|
123
|
-
const css_prop = normalize_css_property_name(key);
|
|
124
|
-
style.removeProperty(css_prop);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Helper function to set a single attribute
|
|
131
|
-
* @param {Element} element
|
|
132
|
-
* @param {string} key
|
|
133
|
-
* @param {any} value
|
|
134
|
-
* @param {Record<string, (() => void) | undefined>} remove_listeners
|
|
135
|
-
* @param {Record<string | symbol, any>} prev
|
|
136
|
-
*/
|
|
137
|
-
function set_attribute_helper(element, key, value, remove_listeners, prev) {
|
|
138
|
-
if (key === 'class') {
|
|
139
|
-
const is_html = element.namespaceURI === 'http://www.w3.org/1999/xhtml';
|
|
140
|
-
set_class(/** @type {HTMLElement} */ (element), value, undefined, is_html);
|
|
141
|
-
} else if (key === 'innerHTML') {
|
|
142
|
-
element.removeAttribute('innerhtml');
|
|
143
|
-
/** @type {HTMLElement} */ (element).innerHTML = value == null ? '' : String(value);
|
|
144
|
-
} else if (key === 'style') {
|
|
145
|
-
set_style(element, value, prev.style);
|
|
146
|
-
} else if (key === '#class') {
|
|
147
|
-
// Special case for the scope classes of an element that spreads props:
|
|
148
|
-
// one token per scope hash and applied theme.
|
|
149
|
-
element.classList.add(...String(value).split(' ').filter(Boolean));
|
|
150
|
-
} else if (typeof key === 'string' && is_event_attribute(key)) {
|
|
151
|
-
// Handle event handlers in spread props
|
|
152
|
-
if (remove_listeners[key]) {
|
|
153
|
-
remove_listeners[key]();
|
|
154
|
-
remove_listeners[key] = undefined;
|
|
155
|
-
}
|
|
156
|
-
if (value != null) {
|
|
157
|
-
const event_name = get_attribute_event_name(key, value);
|
|
158
|
-
remove_listeners[key] = event_listener(event_name, element, value);
|
|
159
|
-
}
|
|
160
|
-
} else {
|
|
161
|
-
set_attribute(element, key, value);
|
|
49
|
+
export function set_text(text, value) {
|
|
50
|
+
var str = value == null ? '' : value + '';
|
|
51
|
+
// The compiled render block compares against the value it last wrote, so
|
|
52
|
+
// nothing is cached on the node. Only server-rendered text can already
|
|
53
|
+
// hold the value; a fresh template text node never does.
|
|
54
|
+
if (HYDRATION && hydrating && text.nodeValue === str) {
|
|
55
|
+
return;
|
|
162
56
|
}
|
|
57
|
+
text.nodeValue = str;
|
|
163
58
|
}
|
|
164
59
|
|
|
165
60
|
/**
|
|
61
|
+
* Writes a class the compiler proved to be a string (or nullish). The
|
|
62
|
+
* compiled render block compares against the class it last applied, so
|
|
63
|
+
* nothing is cached on the element. Removing the attribute when the value is
|
|
64
|
+
* only an empty string costs more than an empty className, so the class is
|
|
65
|
+
* removed only for a nullish value; an element that has no class does not
|
|
66
|
+
* receive an empty one either (the server omits an empty class attribute as
|
|
67
|
+
* well).
|
|
166
68
|
* @param {HTMLElement} dom
|
|
167
|
-
* @param {string} value
|
|
69
|
+
* @param {string | null | undefined} value
|
|
168
70
|
* @param {string} [hash]
|
|
169
71
|
* @param {boolean} [is_html]
|
|
170
72
|
* @returns {void}
|
|
171
73
|
*/
|
|
172
74
|
export function set_class(dom, value, hash, is_html = true) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
? value + (hash ? ' ' + hash : '')
|
|
181
|
-
: clsx([value, hash]);
|
|
75
|
+
/** @type {string | null} */
|
|
76
|
+
var class_value;
|
|
77
|
+
if (value == null) {
|
|
78
|
+
class_value = hash === undefined ? null : hash;
|
|
79
|
+
} else {
|
|
80
|
+
class_value = hash ? (value === '' ? hash : value + ' ' + hash) : value;
|
|
81
|
+
}
|
|
182
82
|
|
|
183
|
-
// The compiled render block compares against the class it last applied,
|
|
184
|
-
// so nothing is cached on the element. Removing the attribute when the
|
|
185
|
-
// value is only an empty string costs more than an empty className, so the
|
|
186
|
-
// class is removed only for a nullish value; an element that has no class
|
|
187
|
-
// does not receive an empty one either (the server omits an empty class
|
|
188
|
-
// attribute as well).
|
|
189
83
|
if (class_value === null) {
|
|
190
84
|
dom.removeAttribute('class');
|
|
191
85
|
} else if (is_html) {
|
|
@@ -197,6 +91,24 @@ export function set_class(dom, value, hash, is_html = true) {
|
|
|
197
91
|
}
|
|
198
92
|
}
|
|
199
93
|
|
|
94
|
+
/**
|
|
95
|
+
* `set_class` for a value of any shape: arrays, objects and numbers compose
|
|
96
|
+
* as clsx does. Only a bundle with such a class expression carries the joiner.
|
|
97
|
+
* @param {HTMLElement} dom
|
|
98
|
+
* @param {any} value
|
|
99
|
+
* @param {string} [hash]
|
|
100
|
+
* @param {boolean} [is_html]
|
|
101
|
+
* @returns {void}
|
|
102
|
+
*/
|
|
103
|
+
export function set_class_value(dom, value, hash, is_html = true) {
|
|
104
|
+
set_class(
|
|
105
|
+
dom,
|
|
106
|
+
value == null || typeof value === 'string' ? value : class_name(value),
|
|
107
|
+
hash,
|
|
108
|
+
is_html,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
200
112
|
/**
|
|
201
113
|
* @param {HTMLInputElement | HTMLProgressElement | HTMLOptionElement} element
|
|
202
114
|
* @param {any} value
|
|
@@ -229,18 +141,12 @@ export function set_value(element, value) {
|
|
|
229
141
|
* @returns {void}
|
|
230
142
|
*/
|
|
231
143
|
export function set_checked(element, checked) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
// treat null and undefined the same for the initial value
|
|
238
|
-
checked ?? undefined)
|
|
239
|
-
) {
|
|
240
|
-
return;
|
|
144
|
+
// Compared against the element itself rather than a record of the last
|
|
145
|
+
// write: no expando per checkbox, and a box the user just toggled to the
|
|
146
|
+
// value being set needs no write at all.
|
|
147
|
+
if (element.checked !== (checked = !!checked)) {
|
|
148
|
+
element.checked = checked;
|
|
241
149
|
}
|
|
242
|
-
|
|
243
|
-
element.checked = checked;
|
|
244
150
|
}
|
|
245
151
|
|
|
246
152
|
/**
|
|
@@ -259,155 +165,3 @@ export function set_selected(element, selected) {
|
|
|
259
165
|
element.removeAttribute('selected');
|
|
260
166
|
}
|
|
261
167
|
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* @param {Element} element
|
|
265
|
-
* @param {() => Record<string | symbol, any>} fn
|
|
266
|
-
* @returns {() => void}
|
|
267
|
-
*/
|
|
268
|
-
export function apply_element_spread(element, fn) {
|
|
269
|
-
/** @type {Record<string | symbol, any>} */
|
|
270
|
-
var prev = {};
|
|
271
|
-
/** @type {Record<string | symbol, Block | undefined>} */
|
|
272
|
-
var effects = {};
|
|
273
|
-
/** @type {Record<string | symbol, (() => void) | undefined>} */
|
|
274
|
-
var remove_listeners = {};
|
|
275
|
-
|
|
276
|
-
/** @type {Record<symbol, any>} */
|
|
277
|
-
var prev_symbols = {};
|
|
278
|
-
/** @type {Record<string, any>} */
|
|
279
|
-
var prev_ref_props = {};
|
|
280
|
-
|
|
281
|
-
return () => {
|
|
282
|
-
var next = fn();
|
|
283
|
-
var current_symbols = /** @type {Record<symbol, any>} */ ({});
|
|
284
|
-
|
|
285
|
-
for (const symbol of get_own_property_symbols(next)) {
|
|
286
|
-
if (symbol.description !== REF_PROP) {
|
|
287
|
-
continue;
|
|
288
|
-
}
|
|
289
|
-
const ref_fn = next[symbol];
|
|
290
|
-
current_symbols[symbol] = ref_fn;
|
|
291
|
-
|
|
292
|
-
if (
|
|
293
|
-
!(symbol in prev_symbols) ||
|
|
294
|
-
ref_fn !== prev_symbols[symbol] ||
|
|
295
|
-
(effects[symbol] && (effects[symbol].f & DESTROYED) !== 0)
|
|
296
|
-
) {
|
|
297
|
-
if (effects[symbol] && (effects[symbol].f & DESTROYED) === 0) {
|
|
298
|
-
destroy_block(effects[symbol]);
|
|
299
|
-
}
|
|
300
|
-
effects[symbol] = create_spread_ref_effect(element, ref_fn);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
for (const symbol of get_own_property_symbols(prev_symbols)) {
|
|
305
|
-
if (!(symbol in current_symbols) && effects[symbol]) {
|
|
306
|
-
destroy_block(/** @type {Block} */ (effects[symbol]));
|
|
307
|
-
effects[symbol] = undefined;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
prev_symbols = current_symbols;
|
|
312
|
-
|
|
313
|
-
/** @type {Record<string, any>} */
|
|
314
|
-
var current_ref_props = {};
|
|
315
|
-
var keys = spread_keys(next);
|
|
316
|
-
|
|
317
|
-
for (const key of keys) {
|
|
318
|
-
const ref_fn = next[key];
|
|
319
|
-
if (!is_ref_prop(ref_fn)) {
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
current_ref_props[key] = ref_fn;
|
|
324
|
-
|
|
325
|
-
if (
|
|
326
|
-
!(key in prev_ref_props) ||
|
|
327
|
-
ref_fn !== prev_ref_props[key] ||
|
|
328
|
-
(effects[key] && (effects[key].f & DESTROYED) !== 0)
|
|
329
|
-
) {
|
|
330
|
-
if (effects[key] && (effects[key].f & DESTROYED) === 0) {
|
|
331
|
-
destroy_block(effects[key]);
|
|
332
|
-
}
|
|
333
|
-
effects[key] = create_spread_ref_effect(element, ref_fn);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
for (const key in prev_ref_props) {
|
|
338
|
-
if (!(key in current_ref_props) && effects[key]) {
|
|
339
|
-
destroy_block(/** @type {Block} */ (effects[key]));
|
|
340
|
-
effects[key] = undefined;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
prev_ref_props = current_ref_props;
|
|
345
|
-
|
|
346
|
-
for (let key in remove_listeners) {
|
|
347
|
-
// Remove event listeners that are no longer present
|
|
348
|
-
if ((!keys.includes(key) || is_ref_prop(next[key])) && remove_listeners[key]) {
|
|
349
|
-
remove_listeners[key]();
|
|
350
|
-
remove_listeners[key] = undefined;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
for (const key in prev) {
|
|
355
|
-
if (!keys.includes(key) || is_ref_prop(next[key])) {
|
|
356
|
-
if (key === '#class') {
|
|
357
|
-
continue;
|
|
358
|
-
}
|
|
359
|
-
set_attribute_helper(element, key, null, remove_listeners, prev);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/** @type {typeof prev} */
|
|
364
|
-
const current = {};
|
|
365
|
-
for (const key of keys) {
|
|
366
|
-
if (key === 'children') continue;
|
|
367
|
-
|
|
368
|
-
let value = next[key];
|
|
369
|
-
if (is_ref_prop(value)) {
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
if (is_ripple_object(value)) {
|
|
373
|
-
value = get(value);
|
|
374
|
-
}
|
|
375
|
-
current[key] = value;
|
|
376
|
-
|
|
377
|
-
if (key in prev && prev[key] === value && key !== '#class') {
|
|
378
|
-
continue;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
set_attribute_helper(element, key, value, remove_listeners, prev);
|
|
382
|
-
}
|
|
383
|
-
prev = current;
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
/**
|
|
388
|
-
* The keys an element spread applies: every prop of a props instance, or the
|
|
389
|
-
* enumerable keys of a plain object.
|
|
390
|
-
* @param {Record<string | symbol, any>} next
|
|
391
|
-
* @returns {string[]}
|
|
392
|
-
*/
|
|
393
|
-
function spread_keys(next) {
|
|
394
|
-
/** @type {string[]} */
|
|
395
|
-
var keys = [];
|
|
396
|
-
for (var key in next) keys.push(key);
|
|
397
|
-
return keys;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Keep spread refs in a branch block so ordinary spread updates do not destroy
|
|
402
|
-
* and recreate the ref block before `apply_element_spread` can compare the
|
|
403
|
-
* previous and current ref values.
|
|
404
|
-
*
|
|
405
|
-
* @param {Element} element
|
|
406
|
-
* @param {any} ref_fn
|
|
407
|
-
* @returns {Block}
|
|
408
|
-
*/
|
|
409
|
-
function create_spread_ref_effect(element, ref_fn) {
|
|
410
|
-
return branch(() => {
|
|
411
|
-
ref(element, () => ref_fn);
|
|
412
|
-
});
|
|
413
|
-
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether `mount()` and `hydrate()` render the app under a default
|
|
3
|
+
* try/pending/catch boundary. The Vite plugin's `rootBoundary: false` build
|
|
4
|
+
* aliases this module to one exporting `false`; the bundler then drops the
|
|
5
|
+
* boundary runtime from an app that renders without one.
|
|
6
|
+
*/
|
|
7
|
+
export const ROOT_BOUNDARY = true;
|