mirror of https://github.com/sveltejs/svelte
feat: Variadic snippets (#9988)
* give this another try * fix: lint * fix: Forgot to save * feat: it works boiiii * look, ok, it did work, i just needed to update the snapshots * bruh * changeset * feat: ok I think the client snippet block finally works * feat: current tests pass; I'm sure I'm missing stuff for new things * fix: snapshot * feat: I think non-destructured rest should work now? * chore: duplicated computation * feat: Tests (passing and failing * feat: it's... alive? * chore: Clean up my messes * chore: devtime stuff * fix: fmt * chore: see if this fixes repl * chore: make naming more offensive * fix: Don't throw on missing keys, return undefined as it usually would * Update packages/svelte/src/compiler/phases/1-parse/state/tag.js Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> * Update packages/svelte/src/compiler/phases/1-parse/state/tag.js Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> * fix: Hopefully default param values now work * dumb * types * feat: Test it * fix: Turns out javascript parameters are optional * feat: The Final Solution * document function * feat: Better bracket matching, unit tests * feat: exclude test files from publish * feat: More unit tests * feat: Use more efficient parsing for @const * Update .changeset/curvy-cups-cough.md Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> * Update packages/svelte/package.json Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> * Update packages/svelte/src/compiler/phases/1-parse/utils/bracket.js Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> * fix: changesets * chore: additional comments * fix: kill foreach * fix: foreach again * feat: Docs * Revert "fix: kill foreach" This reverts commitpull/10349/head9a688cc543
. * fix: My own stupidity * fix: style * fix - maybe * Update sites/svelte-5-preview/src/routes/docs/content/01-api/03-snippets.md * Update tag.js Co-authored-by: Rich Harris <richard.a.harris@gmail.com> * Update .changeset/curvy-cups-cough.md Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> * chore: Remove rest params * Delete .changeset/eighty-rivers-wash.md * fix: Honestly idk why it was broken but it's fixed now * fix: var name lol * fix: typegen * fix: idk * fix: It looks like a bunch of unformatted shit came in through main?? idk * Revert "fix: It looks like a bunch of unformatted shit came in through main?? idk" This reverts commitab851d5627
. * fix: format again * this is getting ridiculous * Update tag.js Co-authored-by: Rich Harris <richard.a.harris@gmail.com> * fix errors * simplify a bit * use read_context * use read_context for const as well * remove unused code * unused import * unused export * remove spread args. sorry elliott * tidy up SnippetBlock interface * fix test * simplify * tweak * revert example, so that it matches the surrounding text * move PropsWithChildren back to public.d.ts * update typing docs, so that it flows from previous example * temporarily revert const parsing changes, to get prettier working again (???) * oops --------- Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> Co-authored-by: Rich Harris <richard.a.harris@gmail.com> Co-authored-by: Rich Harris <rich.harris@vercel.com>
parent
d6fa5c7f97
commit
d309a9d47a
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
breaking: snippets can now take multiple arguments, support default parameters. Because of this, the type signature has changed
|
@ -0,0 +1,21 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `
|
||||
<p>clicks: 0, doubled: 0</p>
|
||||
<button>click me</button>
|
||||
`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const btn = target.querySelector('button');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<p>clicks: 1, doubled: 2</p>
|
||||
<button>click me</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
let count = $state(0);
|
||||
let doubled = $derived(count * 2);
|
||||
</script>
|
||||
|
||||
{#snippet foo({ count }, { doubled })}
|
||||
<p>clicks: {count}, doubled: {doubled}</p>
|
||||
{/snippet}
|
||||
|
||||
{@render foo({ count }, { doubled })}
|
||||
|
||||
<button on:click={() => count += 1}>
|
||||
click me
|
||||
</button>
|
@ -0,0 +1,21 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `
|
||||
<p>clicks: 0, doubled: 0</p>
|
||||
<button>click me</button>
|
||||
`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const btn = target.querySelector('button');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<p>clicks: 1, doubled: 2</p>
|
||||
<button>click me</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
@ -0,0 +1,14 @@
|
||||
<script lang="ts">
|
||||
let count = $state(0);
|
||||
let doubled = $derived(count * 2);
|
||||
</script>
|
||||
|
||||
{#snippet foo(n: number, doubled: number)}
|
||||
<p>clicks: {n}, doubled: {doubled}</p>
|
||||
{/snippet}
|
||||
|
||||
{@render foo(count, doubled)}
|
||||
|
||||
<button on:click={() => count += 1}>
|
||||
click me
|
||||
</button>
|
@ -0,0 +1,31 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
/** @type {HTMLButtonElement | null} */
|
||||
const increment = target.querySelector('#increment');
|
||||
/** @type {HTMLButtonElement | null} */
|
||||
const change_ref = target.querySelector('#change-ref');
|
||||
/** @type {HTMLParagraphElement | null} */
|
||||
const count = target.querySelector('#count');
|
||||
/** @type {HTMLParagraphElement | null} */
|
||||
const fallback_count = target.querySelector('#fallback-count');
|
||||
|
||||
assert.htmlEqual(count?.innerHTML ?? '', 'Count: 0');
|
||||
assert.htmlEqual(fallback_count?.innerHTML ?? '', 'Fallback count: 0');
|
||||
|
||||
await increment?.click();
|
||||
assert.htmlEqual(count?.innerHTML ?? '', 'Count: 1');
|
||||
assert.htmlEqual(fallback_count?.innerHTML ?? '', 'Fallback count: 0');
|
||||
|
||||
await change_ref?.click();
|
||||
await increment?.click();
|
||||
assert.htmlEqual(count?.innerHTML ?? '', 'Count: 1');
|
||||
assert.htmlEqual(fallback_count?.innerHTML ?? '', 'Fallback count: 1');
|
||||
|
||||
await change_ref?.click();
|
||||
await increment?.click();
|
||||
assert.htmlEqual(count?.innerHTML ?? '', 'Count: 2');
|
||||
assert.htmlEqual(fallback_count?.innerHTML ?? '', 'Fallback count: 1');
|
||||
}
|
||||
});
|
@ -0,0 +1,26 @@
|
||||
<script>
|
||||
function box(value) {
|
||||
let state = $state(value);
|
||||
return {
|
||||
get value() {
|
||||
return state
|
||||
},
|
||||
set value(v) {
|
||||
state = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let count = box(0);
|
||||
let fallback_count = box(0);
|
||||
let toggle_state = $state(false);
|
||||
</script>
|
||||
|
||||
{#snippet counter(c = count)}
|
||||
<p id="count">Count: {count.value}</p>
|
||||
<p id="fallback-count">Fallback count: {fallback_count.value}</p>
|
||||
<button id="increment" on:click={() => (c.value += 1)}>Click to change referenced state value</button>
|
||||
<button id="change-ref" on:click={() => toggle_state = !toggle_state}>Click to change state reference</button>
|
||||
{/snippet}
|
||||
|
||||
{@render counter(toggle_state ? fallback_count : undefined)}
|
@ -0,0 +1,15 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
const count = target.querySelector('button');
|
||||
const fallback = target.querySelector('p');
|
||||
|
||||
assert.htmlEqual(count?.innerHTML ?? '', '0');
|
||||
assert.htmlEqual(fallback?.innerHTML ?? '', 'fallback');
|
||||
|
||||
await count?.click();
|
||||
assert.htmlEqual(count?.innerHTML ?? '', '1');
|
||||
assert.htmlEqual(fallback?.innerHTML ?? '', 'fallback');
|
||||
}
|
||||
});
|
@ -0,0 +1,28 @@
|
||||
<script>
|
||||
function box(value) {
|
||||
let state = $state(value);
|
||||
|
||||
return {
|
||||
get value() {
|
||||
return state
|
||||
},
|
||||
set value(v) {
|
||||
state = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let count = box(0);
|
||||
</script>
|
||||
|
||||
{#snippet counter(c)}
|
||||
{#if c}
|
||||
<button on:click={() => (c.value += 1)}>{c.value}</button>
|
||||
{:else}
|
||||
<p>fallback</p>
|
||||
{/if}
|
||||
{/snippet}
|
||||
|
||||
{@render counter()}
|
||||
{@render counter(count)}
|
||||
|
Loading…
Reference in new issue