svelte 5.56.10 → 5.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiler/index.js +1 -1
- package/elements.d.ts +3 -0
- package/package.json +3 -3
- package/src/compiler/phases/1-parse/acorn.js +1 -1
- package/src/compiler/phases/1-parse/utils/html.js +12 -7
- package/src/compiler/phases/2-analyze/css/css-prune.js +10 -0
- package/src/compiler/phases/2-analyze/index.js +26 -3
- package/src/compiler/phases/2-analyze/visitors/AwaitExpression.js +10 -4
- package/src/compiler/phases/2-analyze/visitors/CallExpression.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/DeclarationTag.js +2 -1
- package/src/compiler/phases/2-analyze/visitors/ExportNamedDeclaration.js +10 -10
- package/src/compiler/phases/2-analyze/visitors/SvelteBody.js +4 -4
- package/src/compiler/phases/2-analyze/visitors/SvelteDocument.js +4 -4
- package/src/compiler/phases/2-analyze/visitors/SvelteWindow.js +4 -4
- package/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js +14 -2
- package/src/compiler/phases/2-analyze/visitors/shared/element.js +2 -8
- package/src/compiler/phases/2-analyze/visitors/shared/utils.js +23 -1
- package/src/compiler/phases/3-transform/client/transform-client.js +2 -2
- package/src/compiler/phases/3-transform/client/transform-template/index.js +6 -0
- package/src/compiler/phases/3-transform/client/utils.js +35 -8
- package/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js +6 -6
- package/src/compiler/phases/3-transform/client/visitors/BindDirective.js +10 -13
- package/src/compiler/phases/3-transform/client/visitors/ConstTag.js +19 -8
- package/src/compiler/phases/3-transform/client/visitors/DeclarationTag.js +3 -2
- package/src/compiler/phases/3-transform/client/visitors/EachBlock.js +4 -1
- package/src/compiler/phases/3-transform/client/visitors/Fragment.js +2 -7
- package/src/compiler/phases/3-transform/client/visitors/HtmlTag.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/IfBlock.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/KeyBlock.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/RegularElement.js +106 -44
- package/src/compiler/phases/3-transform/client/visitors/SvelteElement.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +11 -4
- package/src/compiler/phases/3-transform/client/visitors/shared/element.js +6 -1
- package/src/compiler/phases/3-transform/client/visitors/shared/fragment.js +1 -6
- package/src/compiler/phases/3-transform/client/visitors/shared/utils.js +5 -5
- package/src/compiler/phases/3-transform/server/transform-server.js +20 -9
- package/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/DeclarationTag.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/EachBlock.js +8 -2
- package/src/compiler/phases/3-transform/server/visitors/IfBlock.js +4 -4
- package/src/compiler/phases/3-transform/server/visitors/RegularElement.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js +9 -4
- package/src/compiler/phases/3-transform/server/visitors/shared/element.js +5 -4
- package/src/compiler/phases/3-transform/server/visitors/shared/utils.js +30 -0
- package/src/compiler/phases/bindings.js +3 -1
- package/src/compiler/phases/nodes.js +4 -0
- package/src/compiler/print/index.js +21 -16
- package/src/easing/index.js +62 -0
- package/src/internal/client/constants.js +9 -0
- package/src/internal/client/context.js +15 -5
- package/src/internal/client/dev/hmr.js +15 -4
- package/src/internal/client/dom/blocks/boundary.js +21 -12
- package/src/internal/client/dom/blocks/slot.js +19 -0
- package/src/internal/client/dom/blocks/svelte-head.js +8 -0
- package/src/internal/client/dom/elements/attributes.js +35 -34
- package/src/internal/client/dom/elements/bindings/select.js +99 -9
- package/src/internal/client/dom/elements/bindings/this.js +7 -2
- package/src/internal/client/dom/elements/transitions.js +81 -68
- package/src/internal/client/dom/operations.js +21 -1
- package/src/internal/client/error-handling.js +10 -2
- package/src/internal/client/index.js +9 -2
- package/src/internal/client/proxy.js +8 -3
- package/src/internal/client/reactivity/async.js +23 -3
- package/src/internal/client/reactivity/effects.js +14 -1
- package/src/internal/client/render.js +4 -8
- package/src/internal/client/runtime.js +45 -33
- package/src/internal/client/warnings.js +0 -11
- package/src/internal/server/abort-signal.js +8 -9
- package/src/internal/server/context.js +2 -2
- package/src/internal/server/index.js +1 -1
- package/src/internal/server/renderer.js +163 -52
- package/src/internal/shared/attributes.js +2 -1
- package/src/internal/shared/clone.js +2 -0
- package/src/internal/shared/context.js +3 -2
- package/src/legacy/legacy-server.js +1 -1
- package/src/reactivity/map.js +22 -0
- package/src/reactivity/url.js +2 -0
- package/src/transition/index.js +18 -7
- package/src/version.js +1 -1
- package/types/index.d.ts +135 -37
- package/types/index.d.ts.map +2 -2
|
@@ -26,7 +26,12 @@ import { set_class } from './class.js';
|
|
|
26
26
|
import { set_style } from './style.js';
|
|
27
27
|
import { ATTACHMENT_KEY, NAMESPACE_HTML, UNINITIALIZED } from '../../../../constants.js';
|
|
28
28
|
import { branch, destroy_effect, effect, managed } from '../../reactivity/effects.js';
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
init_select,
|
|
31
|
+
select_option,
|
|
32
|
+
set_default_select_value,
|
|
33
|
+
set_selected
|
|
34
|
+
} from './bindings/select.js';
|
|
30
35
|
import { flatten } from '../../reactivity/async.js';
|
|
31
36
|
|
|
32
37
|
export const CLASS = Symbol('class');
|
|
@@ -122,25 +127,6 @@ export function set_checked(element, checked) {
|
|
|
122
127
|
element.checked = checked;
|
|
123
128
|
}
|
|
124
129
|
|
|
125
|
-
/**
|
|
126
|
-
* Sets the `selected` attribute on an `option` element.
|
|
127
|
-
* Not set through the property because that doesn't reflect to the DOM,
|
|
128
|
-
* which means it wouldn't be taken into account when a form is reset.
|
|
129
|
-
* @param {HTMLOptionElement} element
|
|
130
|
-
* @param {boolean} selected
|
|
131
|
-
*/
|
|
132
|
-
export function set_selected(element, selected) {
|
|
133
|
-
if (selected) {
|
|
134
|
-
// The selected option could've changed via user selection, and
|
|
135
|
-
// setting the value without this check would set it back.
|
|
136
|
-
if (!element.hasAttribute('selected')) {
|
|
137
|
-
element.setAttribute('selected', '');
|
|
138
|
-
}
|
|
139
|
-
} else {
|
|
140
|
-
element.removeAttribute('selected');
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
130
|
/**
|
|
145
131
|
* Applies the default checked property without influencing the current checked property.
|
|
146
132
|
* @param {HTMLInputElement} element
|
|
@@ -201,7 +187,7 @@ export function set_attribute(element, attribute, value, skip_warning) {
|
|
|
201
187
|
|
|
202
188
|
if (value == null) {
|
|
203
189
|
element.removeAttribute(attribute);
|
|
204
|
-
} else if (typeof value !== 'string' && get_setters(element).
|
|
190
|
+
} else if (typeof value !== 'string' && get_setters(element).has(attribute)) {
|
|
205
191
|
// @ts-ignore
|
|
206
192
|
element[attribute] = value;
|
|
207
193
|
} else {
|
|
@@ -252,7 +238,7 @@ export function set_custom_element_data(node, prop, value) {
|
|
|
252
238
|
// customElements may not be available in browser extension contexts
|
|
253
239
|
!customElements ||
|
|
254
240
|
customElements.get(node.getAttribute('is') || node.nodeName.toLowerCase())
|
|
255
|
-
? get_setters(node).
|
|
241
|
+
? get_setters(node).has(prop)
|
|
256
242
|
: value && typeof value === 'object')
|
|
257
243
|
) {
|
|
258
244
|
// @ts-expect-error
|
|
@@ -291,11 +277,8 @@ function set_attributes(
|
|
|
291
277
|
skip_warning = false
|
|
292
278
|
) {
|
|
293
279
|
if (hydrating && should_remove_defaults && element.nodeName === INPUT_TAG) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (!(attribute in next)) {
|
|
298
|
-
remove_input_defaults(input);
|
|
280
|
+
if (!('defaultValue' in next || 'defaultChecked' in next)) {
|
|
281
|
+
remove_input_defaults(/** @type {HTMLInputElement} */ (element));
|
|
299
282
|
}
|
|
300
283
|
}
|
|
301
284
|
|
|
@@ -313,6 +296,7 @@ function set_attributes(
|
|
|
313
296
|
|
|
314
297
|
var current = prev || {};
|
|
315
298
|
var is_option_element = element.nodeName === OPTION_TAG;
|
|
299
|
+
var is_select_element = element.nodeName === SELECT_TAG;
|
|
316
300
|
|
|
317
301
|
for (var key in prev) {
|
|
318
302
|
// don't null our internal $$onX listeners
|
|
@@ -449,6 +433,9 @@ function set_attributes(
|
|
|
449
433
|
|
|
450
434
|
var is_default = name === 'defaultValue' || name === 'defaultChecked';
|
|
451
435
|
|
|
436
|
+
// A select's default value is represented by selected options, not a property.
|
|
437
|
+
if (is_select_element && name === 'defaultValue') continue;
|
|
438
|
+
|
|
452
439
|
if (value == null && !is_custom_element && !is_default) {
|
|
453
440
|
attributes[key] = null;
|
|
454
441
|
|
|
@@ -473,7 +460,7 @@ function set_attributes(
|
|
|
473
460
|
}
|
|
474
461
|
} else if (
|
|
475
462
|
is_default ||
|
|
476
|
-
(
|
|
463
|
+
((is_custom_element || typeof value !== 'string') && setters.has(name))
|
|
477
464
|
) {
|
|
478
465
|
// @ts-ignore
|
|
479
466
|
element[name] = value;
|
|
@@ -534,8 +521,16 @@ export function attribute_effect(
|
|
|
534
521
|
skip_warning
|
|
535
522
|
);
|
|
536
523
|
|
|
537
|
-
if (inited && is_select
|
|
538
|
-
|
|
524
|
+
if (inited && is_select) {
|
|
525
|
+
var select = /** @type {HTMLSelectElement} */ (element);
|
|
526
|
+
|
|
527
|
+
if ('defaultValue' in next) {
|
|
528
|
+
set_default_select_value(select, next.defaultValue);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if ('value' in next) {
|
|
532
|
+
select_option(select, next.value);
|
|
533
|
+
}
|
|
539
534
|
}
|
|
540
535
|
|
|
541
536
|
for (let symbol of Object.getOwnPropertySymbols(effects)) {
|
|
@@ -560,7 +555,13 @@ export function attribute_effect(
|
|
|
560
555
|
var select = /** @type {HTMLSelectElement} */ (element);
|
|
561
556
|
|
|
562
557
|
effect(() => {
|
|
563
|
-
|
|
558
|
+
var attrs = /** @type {Record<string | symbol, any>} */ (prev);
|
|
559
|
+
|
|
560
|
+
if ('defaultValue' in attrs) {
|
|
561
|
+
set_default_select_value(select, attrs.defaultValue);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
select_option(select, attrs.value, true);
|
|
564
565
|
init_select(select);
|
|
565
566
|
});
|
|
566
567
|
}
|
|
@@ -582,7 +583,7 @@ function get_attributes(element) {
|
|
|
582
583
|
);
|
|
583
584
|
}
|
|
584
585
|
|
|
585
|
-
/** @type {Map<string, string
|
|
586
|
+
/** @type {Map<string, Set<string>>} */
|
|
586
587
|
var setters_cache = new Map();
|
|
587
588
|
|
|
588
589
|
/** @param {Element} element */
|
|
@@ -590,7 +591,7 @@ function get_setters(element) {
|
|
|
590
591
|
var cache_key = element.getAttribute('is') || element.nodeName;
|
|
591
592
|
var setters = setters_cache.get(cache_key);
|
|
592
593
|
if (setters) return setters;
|
|
593
|
-
setters_cache.set(cache_key, (setters =
|
|
594
|
+
setters_cache.set(cache_key, (setters = new Set()));
|
|
594
595
|
|
|
595
596
|
var descriptors;
|
|
596
597
|
var proto = element; // In the case of custom elements there might be setters on the instance
|
|
@@ -609,7 +610,7 @@ function get_setters(element) {
|
|
|
609
610
|
key !== 'textContent' &&
|
|
610
611
|
key !== 'innerText'
|
|
611
612
|
) {
|
|
612
|
-
setters.
|
|
613
|
+
setters.add(key);
|
|
613
614
|
}
|
|
614
615
|
}
|
|
615
616
|
|
|
@@ -6,6 +6,71 @@ import * as w from '../../../warnings.js';
|
|
|
6
6
|
import { Batch, current_batch, previous_batch } from '../../../reactivity/batch.js';
|
|
7
7
|
import { async_mode_flag } from '../../../../flags/index.js';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Sets the `selected` attribute on an option so form reset can restore it.
|
|
11
|
+
* @param {HTMLOptionElement} option
|
|
12
|
+
* @param {boolean} selected
|
|
13
|
+
*/
|
|
14
|
+
export function set_selected(option, selected) {
|
|
15
|
+
if (selected) {
|
|
16
|
+
if (!option.hasAttribute('selected')) option.setAttribute('selected', '');
|
|
17
|
+
} else {
|
|
18
|
+
option.removeAttribute('selected');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Sets the options a form reset should restore. The first call selects
|
|
24
|
+
* them if nothing has set a value, later calls leave the current selection alone.
|
|
25
|
+
* @param {HTMLSelectElement} select
|
|
26
|
+
* @param {any} value
|
|
27
|
+
*/
|
|
28
|
+
export function set_default_select_value(select, value) {
|
|
29
|
+
var mounting = !('__defaultValue' in select);
|
|
30
|
+
// @ts-expect-error
|
|
31
|
+
if (!mounting && select.__defaultValue === value) return;
|
|
32
|
+
// @ts-expect-error
|
|
33
|
+
select.__defaultValue = value;
|
|
34
|
+
apply_default_select_value(select, !mounting || '__value' in select);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Marks the options matching `__defaultValue` as selected. Without `preserve`
|
|
39
|
+
* a newly matching option gets selected, as an inserted `<option selected>` would.
|
|
40
|
+
* @param {HTMLSelectElement} select
|
|
41
|
+
* @param {boolean} preserve
|
|
42
|
+
*/
|
|
43
|
+
function apply_default_select_value(select, preserve) {
|
|
44
|
+
// @ts-expect-error
|
|
45
|
+
var value = select.__defaultValue;
|
|
46
|
+
var multiple = select.multiple;
|
|
47
|
+
var values = multiple ? value ?? [] : null;
|
|
48
|
+
|
|
49
|
+
if (multiple && !is_array(values)) return;
|
|
50
|
+
|
|
51
|
+
var index = select.selectedIndex;
|
|
52
|
+
var selected = preserve && multiple ? new Set(select.selectedOptions) : null;
|
|
53
|
+
|
|
54
|
+
for (var option of select.options) {
|
|
55
|
+
var option_value = get_option_value(option);
|
|
56
|
+
set_selected(
|
|
57
|
+
option,
|
|
58
|
+
multiple ? /** @type {any[]} */ (values).includes(option_value) : is(option_value, value)
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!preserve) return;
|
|
63
|
+
|
|
64
|
+
if (selected !== null) {
|
|
65
|
+
for (option of select.options) {
|
|
66
|
+
var was_selected = selected.has(option);
|
|
67
|
+
if (option.selected !== was_selected) option.selected = was_selected;
|
|
68
|
+
}
|
|
69
|
+
} else if (select.selectedIndex !== index) {
|
|
70
|
+
select.selectedIndex = index;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
9
74
|
/**
|
|
10
75
|
* Selects the correct option(s) (depending on whether this is a multiple select)
|
|
11
76
|
* @template V
|
|
@@ -47,17 +112,25 @@ export function select_option(select, value, mounting = false) {
|
|
|
47
112
|
}
|
|
48
113
|
|
|
49
114
|
/**
|
|
50
|
-
*
|
|
51
|
-
* and
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* inside an `#each` block.
|
|
115
|
+
* Sets up a mutation observer to sync the current selection
|
|
116
|
+
* and default to the dom when the options change, for example
|
|
117
|
+
* when they are inside an `#each` block. Called once per `<select>`,
|
|
118
|
+
* by the compiled output or by `attribute_effect` for spreads.
|
|
55
119
|
* @param {HTMLSelectElement} select
|
|
56
120
|
*/
|
|
57
121
|
export function init_select(select) {
|
|
58
|
-
var observer = new MutationObserver(() => {
|
|
122
|
+
var observer = new MutationObserver((entries) => {
|
|
123
|
+
// Mutations related to `<selectedcontent>` can never affect the option list.
|
|
124
|
+
// Reacting to them could revert a user-initiated selection change, because the
|
|
125
|
+
// records are delivered as soon as any listener returns (e.g. a delegated `input`
|
|
126
|
+
// handler), which can happen before the `change` handler has updated `__value`
|
|
127
|
+
if (entries.every(is_selectedcontent_mutation)) return;
|
|
128
|
+
|
|
129
|
+
if ('__defaultValue' in select) {
|
|
130
|
+
apply_default_select_value(select, false);
|
|
131
|
+
}
|
|
132
|
+
|
|
59
133
|
if ('__value' in select) {
|
|
60
|
-
// @ts-ignore
|
|
61
134
|
select_option(select, select.__value);
|
|
62
135
|
}
|
|
63
136
|
// Deliberately don't update the potential binding value,
|
|
@@ -151,8 +224,6 @@ export function bind_select_value(select, get, set = get) {
|
|
|
151
224
|
select.__value = value;
|
|
152
225
|
mounting = false;
|
|
153
226
|
});
|
|
154
|
-
|
|
155
|
-
init_select(select);
|
|
156
227
|
}
|
|
157
228
|
|
|
158
229
|
/** @param {HTMLOptionElement} option */
|
|
@@ -164,3 +235,22 @@ function get_option_value(option) {
|
|
|
164
235
|
return option.value;
|
|
165
236
|
}
|
|
166
237
|
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Returns `true` if the mutation stems from the browser mirroring the selected
|
|
241
|
+
* option's content into `<selectedcontent>`, or from us replacing the
|
|
242
|
+
* `<selectedcontent>` element with a clone of itself
|
|
243
|
+
* @param {MutationRecord} entry
|
|
244
|
+
*/
|
|
245
|
+
function is_selectedcontent_mutation(entry) {
|
|
246
|
+
if (/** @type {Element} */ (entry.target).closest('selectedcontent') !== null) {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (entry.type === 'childList') {
|
|
251
|
+
var nodes = [...entry.addedNodes, ...entry.removedNodes];
|
|
252
|
+
return nodes.length > 0 && nodes.every((node) => node.nodeName === 'SELECTEDCONTENT');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @import { ComponentContext, Effect } from '#client' */
|
|
2
2
|
import { DESTROYING, STATE_SYMBOL } from '#client/constants';
|
|
3
|
-
import { component_context } from '../../../context.js';
|
|
3
|
+
import { component_context, mark_as_component } from '../../../context.js';
|
|
4
4
|
import { effect, render_effect } from '../../../reactivity/effects.js';
|
|
5
5
|
import { active_effect, untrack } from '../../../runtime.js';
|
|
6
6
|
|
|
@@ -23,7 +23,12 @@ function is_bound_this(bound_value, element_or_component) {
|
|
|
23
23
|
* returns all the parts of the each block context that are used in the expression
|
|
24
24
|
* @returns {void}
|
|
25
25
|
*/
|
|
26
|
-
export function bind_this(
|
|
26
|
+
export function bind_this(
|
|
27
|
+
element_or_component = mark_as_component(),
|
|
28
|
+
update,
|
|
29
|
+
get_value,
|
|
30
|
+
get_parts
|
|
31
|
+
) {
|
|
27
32
|
var component_effect = /** @type {ComponentContext} */ (component_context).r;
|
|
28
33
|
var parent = /** @type {Effect} */ (active_effect);
|
|
29
34
|
|
|
@@ -337,6 +337,7 @@ export function transition(flags, element, get_fn, get_params) {
|
|
|
337
337
|
*/
|
|
338
338
|
function animate(element, options, counterpart, t2, on_begin, on_finish) {
|
|
339
339
|
var is_intro = t2 === 1;
|
|
340
|
+
var aborted = false;
|
|
340
341
|
|
|
341
342
|
if (is_function(options)) {
|
|
342
343
|
// In the case of a deferred transition (such as `crossfade`), `option` will be
|
|
@@ -344,7 +345,6 @@ function animate(element, options, counterpart, t2, on_begin, on_finish) {
|
|
|
344
345
|
// once the DOM has been updated...
|
|
345
346
|
/** @type {Animation} */
|
|
346
347
|
var a;
|
|
347
|
-
var aborted = false;
|
|
348
348
|
|
|
349
349
|
queue_micro_task(() => {
|
|
350
350
|
if (aborted) return;
|
|
@@ -381,99 +381,112 @@ function animate(element, options, counterpart, t2, on_begin, on_finish) {
|
|
|
381
381
|
|
|
382
382
|
const { delay = 0, css, tick, easing = linear } = options;
|
|
383
383
|
|
|
384
|
-
|
|
384
|
+
/** @type {globalThis.Animation} */
|
|
385
|
+
var animation;
|
|
385
386
|
|
|
386
|
-
|
|
387
|
-
if (tick) {
|
|
388
|
-
tick(0, 1); // TODO put in nested effect, to avoid interleaved reads/writes?
|
|
389
|
-
}
|
|
387
|
+
var get_t = () => 1 - t2;
|
|
390
388
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
389
|
+
// wait a microtask before applying the initial styles and creating the dummy animation,
|
|
390
|
+
// so that transitions created in the same batch (e.g. on nested elements) all measure
|
|
391
|
+
// the DOM first (#18421). this still happens before the next paint, so the element
|
|
392
|
+
// won't be rendered without styles applied (#14732)
|
|
393
|
+
queue_micro_task(() => {
|
|
394
|
+
if (aborted) return;
|
|
396
395
|
|
|
397
|
-
|
|
396
|
+
var keyframes = [];
|
|
398
397
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
// fill forwards to prevent the element from rendering without styles applied
|
|
404
|
-
// see https://github.com/sveltejs/svelte/issues/14732
|
|
405
|
-
var animation = element.animate(keyframes, { duration: delay, fill: 'forwards' });
|
|
398
|
+
if (is_intro && counterpart === undefined) {
|
|
399
|
+
if (tick) {
|
|
400
|
+
tick(0, 1); // TODO put in nested effect, to avoid interleaved reads/writes?
|
|
401
|
+
}
|
|
406
402
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
403
|
+
if (css) {
|
|
404
|
+
var styles = css_to_keyframe(css(0, 1));
|
|
405
|
+
keyframes.push(styles, styles);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
410
408
|
|
|
411
|
-
|
|
409
|
+
// create a dummy animation that lasts as long as the delay (but with whatever devtools
|
|
410
|
+
// multiplier is in effect). in the common case that it is `0`, we keep it anyway so that
|
|
411
|
+
// the CSS keyframes aren't created until the DOM is updated
|
|
412
|
+
//
|
|
413
|
+
// fill forwards to prevent the element from rendering without styles applied
|
|
414
|
+
// see https://github.com/sveltejs/svelte/issues/14732
|
|
415
|
+
animation = element.animate(keyframes, { duration: delay, fill: 'forwards' });
|
|
412
416
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
counterpart?.abort();
|
|
417
|
+
animation.onfinish = () => {
|
|
418
|
+
// remove dummy animation from the stack to prevent conflict with main animation
|
|
419
|
+
animation.cancel();
|
|
417
420
|
|
|
418
|
-
|
|
419
|
-
var duration = /** @type {number} */ (options.duration) * Math.abs(delta);
|
|
420
|
-
var keyframes = [];
|
|
421
|
+
on_begin();
|
|
421
422
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
* TODO 6.0 remove this, if possible
|
|
427
|
-
*/
|
|
428
|
-
var needs_overflow_hidden = false;
|
|
423
|
+
// for bidirectional transitions, we start from the current position,
|
|
424
|
+
// rather than doing a full intro/outro
|
|
425
|
+
var t1 = counterpart?.t() ?? 1 - t2;
|
|
426
|
+
counterpart?.abort();
|
|
429
427
|
|
|
430
|
-
|
|
431
|
-
|
|
428
|
+
var delta = t2 - t1;
|
|
429
|
+
var duration = /** @type {number} */ (options.duration) * Math.abs(delta);
|
|
430
|
+
var keyframes = [];
|
|
431
|
+
|
|
432
|
+
if (duration > 0) {
|
|
433
|
+
/**
|
|
434
|
+
* Whether or not the CSS includes `overflow: hidden`, in which case we need to
|
|
435
|
+
* add it as an inline style to work around a Safari <18 bug
|
|
436
|
+
* TODO 6.0 remove this, if possible
|
|
437
|
+
*/
|
|
438
|
+
var needs_overflow_hidden = false;
|
|
432
439
|
|
|
433
|
-
|
|
434
|
-
var
|
|
435
|
-
var styles = css_to_keyframe(css(t, 1 - t));
|
|
436
|
-
keyframes.push(styles);
|
|
440
|
+
if (css) {
|
|
441
|
+
var n = Math.ceil(duration / (1000 / 60)); // `n` must be an integer, or we risk missing the `t2` value
|
|
437
442
|
|
|
438
|
-
|
|
443
|
+
for (var i = 0; i <= n; i += 1) {
|
|
444
|
+
var t = t1 + delta * easing(i / n);
|
|
445
|
+
var styles = css_to_keyframe(css(t, 1 - t));
|
|
446
|
+
keyframes.push(styles);
|
|
447
|
+
|
|
448
|
+
needs_overflow_hidden ||= styles.overflow === 'hidden';
|
|
449
|
+
}
|
|
439
450
|
}
|
|
440
|
-
}
|
|
441
451
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
452
|
+
if (needs_overflow_hidden) {
|
|
453
|
+
/** @type {HTMLElement} */ (element).style.overflow = 'hidden';
|
|
454
|
+
}
|
|
445
455
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
456
|
+
get_t = () => {
|
|
457
|
+
var time = /** @type {number} */ (
|
|
458
|
+
/** @type {globalThis.Animation} */ (animation).currentTime
|
|
459
|
+
);
|
|
450
460
|
|
|
451
|
-
|
|
452
|
-
|
|
461
|
+
return t1 + delta * easing(time / duration);
|
|
462
|
+
};
|
|
453
463
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
464
|
+
if (tick) {
|
|
465
|
+
loop(() => {
|
|
466
|
+
if (animation.playState !== 'running') return false;
|
|
457
467
|
|
|
458
|
-
|
|
459
|
-
|
|
468
|
+
var t = get_t();
|
|
469
|
+
tick(t, 1 - t);
|
|
460
470
|
|
|
461
|
-
|
|
462
|
-
|
|
471
|
+
return true;
|
|
472
|
+
});
|
|
473
|
+
}
|
|
463
474
|
}
|
|
464
|
-
}
|
|
465
475
|
|
|
466
|
-
|
|
476
|
+
animation = element.animate(keyframes, { duration, fill: 'forwards' });
|
|
467
477
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
478
|
+
animation.onfinish = () => {
|
|
479
|
+
get_t = () => t2;
|
|
480
|
+
tick?.(t2, 1 - t2);
|
|
481
|
+
on_finish();
|
|
482
|
+
};
|
|
472
483
|
};
|
|
473
|
-
};
|
|
484
|
+
});
|
|
474
485
|
|
|
475
486
|
return {
|
|
476
487
|
abort: () => {
|
|
488
|
+
aborted = true;
|
|
489
|
+
|
|
477
490
|
if (animation) {
|
|
478
491
|
animation.cancel();
|
|
479
492
|
// This prevents memory leaks in Chromium
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @import { Effect, TemplateNode } from '#client' */
|
|
2
|
-
import { hydrate_node, hydrating, set_hydrate_node } from './hydration.js';
|
|
2
|
+
import { hydrate_node, hydrating, reset, set_hydrate_node } from './hydration.js';
|
|
3
3
|
import { DEV } from 'esm-env';
|
|
4
4
|
import { init_array_prototype_warnings } from '../dev/equality.js';
|
|
5
5
|
import { get_descriptor, is_extensible } from '../../shared/utils.js';
|
|
@@ -165,6 +165,26 @@ export function first_child(node, is_text = false) {
|
|
|
165
165
|
return hydrate_node;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
/**
|
|
169
|
+
* `child`, for the very common case of an element with exactly one child. Resetting the
|
|
170
|
+
* hydration cursor is part of the same step, so the compiler doesn't have to emit a
|
|
171
|
+
* separate `reset` call for every `<p>{text}</p>` in an app.
|
|
172
|
+
* Don't mark this as side-effect-free, hydration needs to walk all nodes
|
|
173
|
+
* @param {TemplateNode} node
|
|
174
|
+
* @param {boolean} [is_text]
|
|
175
|
+
* @returns {TemplateNode | null}
|
|
176
|
+
*/
|
|
177
|
+
export function only_child(node, is_text = false) {
|
|
178
|
+
if (!hydrating) {
|
|
179
|
+
return get_first_child(node);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
var first = child(node, is_text);
|
|
183
|
+
reset(node);
|
|
184
|
+
|
|
185
|
+
return first;
|
|
186
|
+
}
|
|
187
|
+
|
|
168
188
|
/**
|
|
169
189
|
* Don't mark this as side-effect-free, hydration needs to walk all nodes
|
|
170
190
|
* @param {TemplateNode} node
|
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
import { DEV } from 'esm-env';
|
|
4
4
|
import { FILENAME } from '../../constants.js';
|
|
5
5
|
import { is_firefox } from './dom/operations.js';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ERROR_VALUE,
|
|
8
|
+
BOUNDARY_EFFECT,
|
|
9
|
+
REACTION_RAN,
|
|
10
|
+
EFFECT,
|
|
11
|
+
DESTROYED,
|
|
12
|
+
DESTROYING
|
|
13
|
+
} from './constants.js';
|
|
7
14
|
import { define_property, get_descriptor } from '../shared/utils.js';
|
|
8
15
|
import { active_effect, active_reaction } from './runtime.js';
|
|
9
16
|
|
|
@@ -50,7 +57,8 @@ export function invoke_error_boundary(error, effect) {
|
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
while (effect !== null) {
|
|
53
|
-
|
|
60
|
+
// Skip boundaries that are destroyed/destroying and cannot meaningfully handle the error.
|
|
61
|
+
if ((effect.f & BOUNDARY_EFFECT) !== 0 && (effect.f & (DESTROYED | DESTROYING)) === 0) {
|
|
54
62
|
if ((effect.f & REACTION_RAN) === 0) {
|
|
55
63
|
// we are still creating the boundary effect
|
|
56
64
|
throw error;
|
|
@@ -33,7 +33,6 @@ export {
|
|
|
33
33
|
set_xlink_attribute,
|
|
34
34
|
set_value,
|
|
35
35
|
set_checked,
|
|
36
|
-
set_selected,
|
|
37
36
|
set_default_checked,
|
|
38
37
|
set_default_value,
|
|
39
38
|
CLASS,
|
|
@@ -62,7 +61,13 @@ export {
|
|
|
62
61
|
} from './dom/elements/bindings/media.js';
|
|
63
62
|
export { bind_online } from './dom/elements/bindings/navigator.js';
|
|
64
63
|
export { bind_prop } from './dom/elements/bindings/props.js';
|
|
65
|
-
export {
|
|
64
|
+
export {
|
|
65
|
+
bind_select_value,
|
|
66
|
+
init_select,
|
|
67
|
+
select_option,
|
|
68
|
+
set_selected,
|
|
69
|
+
set_default_select_value
|
|
70
|
+
} from './dom/elements/bindings/select.js';
|
|
66
71
|
export { bind_element_size, bind_resize_observer } from './dom/elements/bindings/size.js';
|
|
67
72
|
export { bind_this } from './dom/elements/bindings/this.js';
|
|
68
73
|
export {
|
|
@@ -103,6 +108,7 @@ export {
|
|
|
103
108
|
run,
|
|
104
109
|
save,
|
|
105
110
|
track_reactivity_loss,
|
|
111
|
+
unsave,
|
|
106
112
|
run_after_blockers,
|
|
107
113
|
wait
|
|
108
114
|
} from './reactivity/async.js';
|
|
@@ -163,6 +169,7 @@ export { proxy } from './proxy.js';
|
|
|
163
169
|
export { create_custom_element } from './dom/elements/custom-element.js';
|
|
164
170
|
export {
|
|
165
171
|
child,
|
|
172
|
+
only_child,
|
|
166
173
|
first_child,
|
|
167
174
|
sibling,
|
|
168
175
|
$window as window,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
flush_eager_effects,
|
|
23
23
|
set_eager_effects_deferred
|
|
24
24
|
} from './reactivity/sources.js';
|
|
25
|
-
import { PROXY_PATH_SYMBOL, STATE_SYMBOL } from '#client/constants';
|
|
25
|
+
import { COMPONENT_SYMBOL, PROXY_PATH_SYMBOL, STATE_SYMBOL } from '#client/constants';
|
|
26
26
|
import { UNINITIALIZED } from '../../constants.js';
|
|
27
27
|
import * as e from './errors.js';
|
|
28
28
|
import { tag } from './dev/tracing.js';
|
|
@@ -38,8 +38,13 @@ const regex_is_valid_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
|
|
|
38
38
|
* @returns {T}
|
|
39
39
|
*/
|
|
40
40
|
export function proxy(value) {
|
|
41
|
-
// if non-proxyable, or
|
|
42
|
-
if (
|
|
41
|
+
// if non-proxyable, a component instance, or already a proxy, return `value`
|
|
42
|
+
if (
|
|
43
|
+
typeof value !== 'object' ||
|
|
44
|
+
value === null ||
|
|
45
|
+
STATE_SYMBOL in value ||
|
|
46
|
+
COMPONENT_SYMBOL in value
|
|
47
|
+
) {
|
|
43
48
|
return value;
|
|
44
49
|
}
|
|
45
50
|
|