mirror of https://github.com/sveltejs/svelte
parent
3009a0208f
commit
2c877e0bd4
@ -0,0 +1,34 @@
|
||||
/** @import { AST } from '#compiler' */
|
||||
/** @import { Context } from '../types' */
|
||||
import { mark_subtree_dynamic } from './shared/fragment.js';
|
||||
import { validate_block_not_empty, validate_opening_tag } from './shared/utils.js';
|
||||
import * as e from '../../../errors.js';
|
||||
|
||||
/**
|
||||
* @param {AST.SwitchBlock} node
|
||||
* @param {Context} context
|
||||
*/
|
||||
export function SwitchBlock(node, context) {
|
||||
mark_subtree_dynamic(context.path);
|
||||
node.consequences.forEach((consequence) => validate_block_not_empty(consequence, context));
|
||||
|
||||
if (context.state.analysis.runes) {
|
||||
validate_opening_tag(node, context.state, '#');
|
||||
|
||||
for (const value of node.values) {
|
||||
if (value === null) continue;
|
||||
|
||||
const start = /** @type {number} */ (value.start);
|
||||
const match = context.state.analysis.source
|
||||
.substring(start - 10, start)
|
||||
.match(/{(\s*):case\s+$/);
|
||||
|
||||
if (match && match[1] !== '') {
|
||||
// { :case ...} -- space after "{" not allowed
|
||||
e.block_unexpected_character({ start: start - 10, end: start }, ':');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.next();
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
/** @import { BlockStatement, Expression } from 'estree' */
|
||||
/** @import { AST } from '#compiler' */
|
||||
/** @import { ComponentContext } from '../types' */
|
||||
import * as b from '../../../../utils/builders.js';
|
||||
|
||||
/**
|
||||
* @param {AST.SwitchBlock} node
|
||||
* @param {ComponentContext} context
|
||||
*/
|
||||
export function SwitchBlock(node, context) {
|
||||
context.state.template.push_comment();
|
||||
const statements = [];
|
||||
|
||||
const value = /** @type {Expression} */ (context.visit(node.value));
|
||||
|
||||
/** @type {Expression[]} */
|
||||
const args = [
|
||||
context.state.node,
|
||||
b.arrow(
|
||||
[b.id('$$render')],
|
||||
b.block([
|
||||
b.switch_statement(
|
||||
value,
|
||||
node.consequences.map((node_consequent, index) => {
|
||||
const consequent = /** @type {BlockStatement} */ (context.visit(node_consequent));
|
||||
const consequent_id = context.state.scope.generate('consequent');
|
||||
statements.push(b.var(b.id(consequent_id), b.arrow([b.id('$$anchor')], consequent)));
|
||||
|
||||
return b.switch_case(node.values[index], [
|
||||
b.stmt(b.call(b.id('$$render'), b.id(consequent_id), b.literal(index))),
|
||||
b.break()
|
||||
]);
|
||||
})
|
||||
)
|
||||
])
|
||||
)
|
||||
];
|
||||
|
||||
statements.push(b.stmt(b.call('$.switch', ...args)));
|
||||
|
||||
context.state.init.push(b.block(statements));
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
/** @import { BlockStatement, Expression } from 'estree' */
|
||||
/** @import { AST } from '#compiler' */
|
||||
/** @import { ComponentContext } from '../types.js' */
|
||||
import { HYDRATION_START } from '../../../../../constants.js';
|
||||
import * as b from '../../../../utils/builders.js';
|
||||
import { block_close } from './shared/utils.js';
|
||||
|
||||
/**
|
||||
* @param {AST.SwitchBlock} node
|
||||
* @param {ComponentContext} context
|
||||
*/
|
||||
export function SwitchBlock(node, context) {
|
||||
const discriminant = /** @type {Expression} */ (context.visit(node.value));
|
||||
|
||||
const cases = node.consequences.map((node_consequent, index) => {
|
||||
const consequent = /** @type {BlockStatement} */ (context.visit(node_consequent));
|
||||
consequent.body.unshift(
|
||||
b.stmt(b.call(b.id('$$renderer.push'), b.literal(`<!--${HYDRATION_START}${index}-->`)))
|
||||
);
|
||||
consequent.body.push(b.break());
|
||||
|
||||
return b.switch_case(node.values[index], consequent.body);
|
||||
});
|
||||
|
||||
// if there is no default block, we still have to create a hydration open marker
|
||||
if (node.values.at(-1) !== null) {
|
||||
const default_consequent = b.block([]);
|
||||
default_consequent.body.unshift(
|
||||
b.stmt(
|
||||
b.call(b.id('$$renderer.push'), b.literal(`<!--${HYDRATION_START}${node.values.length}-->`))
|
||||
)
|
||||
);
|
||||
cases.push(b.switch_case(null, default_consequent.body));
|
||||
}
|
||||
|
||||
context.state.template.push(b.switch_statement(discriminant, cases), block_close);
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
/** @import { Effect, TemplateNode } from '#client' */
|
||||
import {
|
||||
hydrate_next,
|
||||
hydrating,
|
||||
read_hydration_instruction,
|
||||
set_hydrate_node,
|
||||
set_hydrating,
|
||||
skip_nodes
|
||||
} from '../hydration.js';
|
||||
import { block } from '../../reactivity/effects.js';
|
||||
import { HYDRATION_START } from '../../../../constants.js';
|
||||
import { BranchManager } from './branches.js';
|
||||
|
||||
/**
|
||||
* @param {TemplateNode} node
|
||||
* @param {(branch: (fn: (anchor: Node) => void, index: number) => void) => void} fn
|
||||
* @returns {void}
|
||||
*/
|
||||
export function switch_block(node, fn) {
|
||||
if (hydrating) {
|
||||
hydrate_next();
|
||||
}
|
||||
|
||||
var branches = new BranchManager(node);
|
||||
|
||||
/**
|
||||
* @param {number} index,
|
||||
* @param {null | ((anchor: Node) => void)} fn
|
||||
*/
|
||||
function update_branch(index, fn) {
|
||||
if (hydrating) {
|
||||
const hydration_tag = read_hydration_instruction(node);
|
||||
const hydration_index = Number(hydration_tag.slice(HYDRATION_START.length));
|
||||
|
||||
if (index !== hydration_index) {
|
||||
// Hydration mismatch: remove everything inside the anchor and start fresh.
|
||||
// This could happen with `{#switch browser}...{/switch}`, for example
|
||||
var anchor = skip_nodes();
|
||||
|
||||
set_hydrate_node(anchor);
|
||||
branches.anchor = anchor;
|
||||
|
||||
set_hydrating(false);
|
||||
branches.ensure(index, fn);
|
||||
set_hydrating(true);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
branches.ensure(index, fn);
|
||||
}
|
||||
|
||||
block(() => {
|
||||
var has_branch = false;
|
||||
|
||||
fn((fn, index) => {
|
||||
has_branch = true;
|
||||
update_branch(index, fn);
|
||||
});
|
||||
|
||||
if (!has_branch) {
|
||||
update_branch(-1, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
{#switch foo case "bar"}
|
||||
<p>foo</p>
|
||||
{/switch}
|
||||
@ -0,0 +1,93 @@
|
||||
{
|
||||
"css": null,
|
||||
"js": [],
|
||||
"start": 0,
|
||||
"end": 46,
|
||||
"type": "Root",
|
||||
"fragment": {
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "SwitchBlock",
|
||||
"start": 0,
|
||||
"end": 46,
|
||||
"value": {
|
||||
"type": "Identifier",
|
||||
"start": 9,
|
||||
"end": 12,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "foo"
|
||||
},
|
||||
"consequences": [
|
||||
{
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 24,
|
||||
"end": 26,
|
||||
"raw": "\n\t",
|
||||
"data": "\n\t"
|
||||
},
|
||||
{
|
||||
"type": "RegularElement",
|
||||
"start": 26,
|
||||
"end": 36,
|
||||
"name": "p",
|
||||
"attributes": [],
|
||||
"fragment": {
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 29,
|
||||
"end": 32,
|
||||
"raw": "foo",
|
||||
"data": "foo"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 36,
|
||||
"end": 37,
|
||||
"raw": "\n",
|
||||
"data": "\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
{
|
||||
"type": "Literal",
|
||||
"start": 18,
|
||||
"end": 23,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 23
|
||||
}
|
||||
},
|
||||
"value": "bar",
|
||||
"raw": "\"bar\""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": null
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
{#switch foo}bar{/switch}
|
||||
@ -0,0 +1,49 @@
|
||||
{
|
||||
"css": null,
|
||||
"js": [],
|
||||
"start": 0,
|
||||
"end": 25,
|
||||
"type": "Root",
|
||||
"fragment": {
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "SwitchBlock",
|
||||
"start": 0,
|
||||
"end": 25,
|
||||
"value": {
|
||||
"type": "Identifier",
|
||||
"start": 9,
|
||||
"end": 12,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "foo"
|
||||
},
|
||||
"consequences": [
|
||||
{
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 13,
|
||||
"end": 16,
|
||||
"raw": "bar",
|
||||
"data": "bar"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [null]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": null
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
{#switch foo}
|
||||
{:case "foo"}
|
||||
{#switch bar}
|
||||
{:case "bar"}
|
||||
<p>bar</p>
|
||||
{/switch}
|
||||
{/switch}
|
||||
@ -0,0 +1,154 @@
|
||||
{
|
||||
"css": null,
|
||||
"js": [],
|
||||
"start": 0,
|
||||
"end": 91,
|
||||
"type": "Root",
|
||||
"fragment": {
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "SwitchBlock",
|
||||
"start": 0,
|
||||
"end": 91,
|
||||
"value": {
|
||||
"type": "Identifier",
|
||||
"start": 9,
|
||||
"end": 12,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "foo"
|
||||
},
|
||||
"consequences": [
|
||||
{
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 27,
|
||||
"end": 29,
|
||||
"raw": "\n\t",
|
||||
"data": "\n\t"
|
||||
},
|
||||
{
|
||||
"type": "SwitchBlock",
|
||||
"start": 29,
|
||||
"end": 81,
|
||||
"value": {
|
||||
"type": "Identifier",
|
||||
"start": 38,
|
||||
"end": 41,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 13
|
||||
}
|
||||
},
|
||||
"name": "bar"
|
||||
},
|
||||
"consequences": [
|
||||
{
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 57,
|
||||
"end": 60,
|
||||
"raw": "\n\t\t",
|
||||
"data": "\n\t\t"
|
||||
},
|
||||
{
|
||||
"type": "RegularElement",
|
||||
"start": 60,
|
||||
"end": 70,
|
||||
"name": "p",
|
||||
"attributes": [],
|
||||
"fragment": {
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 63,
|
||||
"end": 66,
|
||||
"raw": "bar",
|
||||
"data": "bar"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 70,
|
||||
"end": 72,
|
||||
"raw": "\n\t",
|
||||
"data": "\n\t"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
{
|
||||
"type": "Literal",
|
||||
"start": 51,
|
||||
"end": 56,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 4,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 13
|
||||
}
|
||||
},
|
||||
"value": "bar",
|
||||
"raw": "\"bar\""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 81,
|
||||
"end": 82,
|
||||
"raw": "\n",
|
||||
"data": "\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
{
|
||||
"type": "Literal",
|
||||
"start": 21,
|
||||
"end": 26,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"value": "foo",
|
||||
"raw": "\"foo\""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": null
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
{#switch foo}
|
||||
{:case "bar"}
|
||||
<p>foo</p>
|
||||
{:case "baz"}
|
||||
<p>baz</p>
|
||||
{/switch}
|
||||
@ -0,0 +1,148 @@
|
||||
{
|
||||
"css": null,
|
||||
"js": [],
|
||||
"start": 0,
|
||||
"end": 75,
|
||||
"type": "Root",
|
||||
"fragment": {
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "SwitchBlock",
|
||||
"start": 0,
|
||||
"end": 75,
|
||||
"value": {
|
||||
"type": "Identifier",
|
||||
"start": 9,
|
||||
"end": 12,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "foo"
|
||||
},
|
||||
"consequences": [
|
||||
{
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 27,
|
||||
"end": 29,
|
||||
"raw": "\n\t",
|
||||
"data": "\n\t"
|
||||
},
|
||||
{
|
||||
"type": "RegularElement",
|
||||
"start": 29,
|
||||
"end": 39,
|
||||
"name": "p",
|
||||
"attributes": [],
|
||||
"fragment": {
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 32,
|
||||
"end": 35,
|
||||
"raw": "foo",
|
||||
"data": "foo"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 39,
|
||||
"end": 40,
|
||||
"raw": "\n",
|
||||
"data": "\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 53,
|
||||
"end": 55,
|
||||
"raw": "\n\t",
|
||||
"data": "\n\t"
|
||||
},
|
||||
{
|
||||
"type": "RegularElement",
|
||||
"start": 55,
|
||||
"end": 65,
|
||||
"name": "p",
|
||||
"attributes": [],
|
||||
"fragment": {
|
||||
"type": "Fragment",
|
||||
"nodes": [
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 58,
|
||||
"end": 61,
|
||||
"raw": "baz",
|
||||
"data": "baz"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"start": 65,
|
||||
"end": 66,
|
||||
"raw": "\n",
|
||||
"data": "\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
{
|
||||
"type": "Literal",
|
||||
"start": 21,
|
||||
"end": 26,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"value": "bar",
|
||||
"raw": "\"bar\""
|
||||
},
|
||||
{
|
||||
"type": "Literal",
|
||||
"start": 47,
|
||||
"end": 52,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 4,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"value": "baz",
|
||||
"raw": "\"baz\""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": null
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
await Promise.resolve();
|
||||
|
||||
let [btn1] = target.querySelectorAll('button');
|
||||
|
||||
flushSync(() => {
|
||||
btn1?.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`false\ntrue\n<button>Toggle</button>\nfirst:\nfalse\n<br>\nsecond:\ntrue`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,22 @@
|
||||
<script>
|
||||
let first = $state(true)
|
||||
let second = $state(false)
|
||||
let derivedSecond = $derived(second)
|
||||
|
||||
queueMicrotask(() => {
|
||||
first = false
|
||||
});
|
||||
</script>
|
||||
|
||||
{first} {second}
|
||||
|
||||
<button onclick={() => {
|
||||
second = true
|
||||
}}>Toggle</button>
|
||||
|
||||
{#switch first || derivedSecond}
|
||||
{:case true}
|
||||
first: {first}
|
||||
<br />
|
||||
second: {derivedSecond}
|
||||
{/switch}
|
||||
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
let { post } = $props();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{post.title}</title>
|
||||
</svelte:head>
|
||||
|
||||
<p>{post.title}</p>
|
||||
@ -0,0 +1,22 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target, window }) {
|
||||
const [btn1] = target.querySelectorAll('button');
|
||||
|
||||
assert.htmlEqual(window.document.head.innerHTML, ``);
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(window.document.head.innerHTML, `<title>hello world</title>`);
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(window.document.head.innerHTML, `<title>hello world</title>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import Seo from './Seo.svelte';
|
||||
|
||||
let post = $state(null);
|
||||
|
||||
function toggle() {
|
||||
post = post ? null : { title: 'hello world' };
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={toggle}>
|
||||
toggle
|
||||
</button>
|
||||
|
||||
{#switch !!post case true}
|
||||
<Seo {post} />
|
||||
{/switch}
|
||||
@ -0,0 +1,16 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<button>Click</button><p>expires in 1 click</p>`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const [btn1] = target.querySelectorAll('button');
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(target.innerHTML, ``);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,13 @@
|
||||
<script>
|
||||
let data = $state({ num: 1 });
|
||||
|
||||
function expire() {
|
||||
data.num = data.num - 1;
|
||||
if (data.num <= 0) data = undefined;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#switch data?.num case 1}
|
||||
<button onclick={expire}>Click</button>
|
||||
<p>expires in {data.num} click</p>
|
||||
{/switch}
|
||||
@ -0,0 +1,16 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<button>hide</button><div>hello</div>`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const [btn1, btn2] = target.querySelectorAll('button');
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(target.innerHTML, `<button>hide</button><div style="opacity: 0;">hello</div>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,16 @@
|
||||
<script>
|
||||
import { fade } from "svelte/transition";
|
||||
|
||||
let state = $state("hello");
|
||||
</script>
|
||||
|
||||
<button onclick={() => state = ''}>hide</button>
|
||||
|
||||
{#switch !!state case true}
|
||||
<div in:fade={{ duration: 2000 }} out:fade={{ duration: 2000 }}>
|
||||
{#if true}
|
||||
{state}
|
||||
{/if}
|
||||
</div>
|
||||
{/switch}
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<button>show</button><button>animate</button>`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const [btn1, btn2] = target.querySelectorAll('button');
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<button>show</button><button>animate</button><h1>Hello\n!</h1>`
|
||||
);
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(target.innerHTML, `<button>show</button><button>animate</button>`);
|
||||
|
||||
flushSync(() => {
|
||||
btn2.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(target.innerHTML, `<button>show</button><button>animate</button>`);
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<button>show</button><button>animate</button><h1 style="opacity: 0;">Hello\n!</h1>`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,16 @@
|
||||
<script>
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
let show = $state(false);
|
||||
let animate = $state(false);
|
||||
|
||||
function maybe(node, animate) {
|
||||
if (animate) return fade(node);
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={() => show = !show}>show</button><button onclick={() => animate = !animate}>animate</button>
|
||||
|
||||
{#switch show case true}
|
||||
<h1 transition:maybe={animate}>Hello {name}!</h1>
|
||||
{/switch}
|
||||
@ -0,0 +1,7 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
props: {
|
||||
foo: true
|
||||
}
|
||||
});
|
||||
@ -0,0 +1 @@
|
||||
<p>foo is true</p>
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
export let foo;
|
||||
</script>
|
||||
|
||||
{#switch foo case true}
|
||||
<p>foo is true</p>
|
||||
{/switch}
|
||||
@ -0,0 +1,7 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
props: {
|
||||
foo: false
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
export let foo;
|
||||
</script>
|
||||
|
||||
{#switch foo case true}
|
||||
<p>foo is false</p>
|
||||
{/switch}
|
||||
@ -0,0 +1,7 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
props: {
|
||||
foo: false
|
||||
}
|
||||
});
|
||||
@ -0,0 +1 @@
|
||||
<p>default</p>
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
export let foo;
|
||||
</script>
|
||||
|
||||
{#switch foo}
|
||||
<p>default</p>
|
||||
{/switch}
|
||||
Loading…
Reference in new issue