Skip to content

Conversation

@Refzlund
Copy link

@Refzlund Refzlund commented Dec 21, 2024

This would solve #14792 which still needs to be discussed. I'm opening this PR as an initiative.

This feature allows the use of the animate: directive within snippets:

{#snippet example(item)} <div animate:flip={{ duration: 200 }}>{item}</div> {/snippet} {#each items as item (item)} {@render example(item)} {/each}

I've added error feedback:

  • If you try to render a snippet with animate: directive and
    • it isn't inside an each-block
    • the each-block isn't keyed
  • If the each-block have multiple children, with an animated snippet.

Svelte Playground for #14796


  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • Prefix your PR title with feat:, fix:, chore:, or docs:.
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.
  • If this PR changes code within packages/svelte/src, add a changeset (npx changeset).

Tests and linting

  • Run the tests with pnpm test and lint the project with pnpm lint
@changeset-bot
Copy link

changeset-bot bot commented Dec 21, 2024

🦋 Changeset detected

Latest commit: 10c01bc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
svelte Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@Rich-Harris
Copy link
Member

}

/** @param {AST.Text | AST.Tag | AST.ElementLike | AST.Comment | AST.Block} child */
function is_animate_directive(child) {
Copy link
Author

@Refzlund Refzlund Dec 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is used twice as it is also in phases/3-transform/client/visitors/EachBlock.js#L347. Do I put it anywhere to re-use it across the two phases?

}
else if (!parent.key) {
e.animation_missing_key(parent);
} else if (parent.body.nodes.filter((n) =>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same logic as in phases/2-analyze/visitors/shared/element.js#L92. Maybe re-use logic for consistent maintainence for future updates to this logic?

@Refzlund
Copy link
Author

Refzlund commented Dec 28, 2024

For this PR, if an each loop snippet gets exported from a file, and then imported into another file, animations won't work. I'll try looking into it🦒

For instance, if you have a file, e.g. ArraySnippet.svelte

<script module lang='ts'> export { renderArray } </script> {#snippet renderArray(array, snippet)} {#each array as item, i (item)} {@render snippet(item)} {/each} {/snippet}

And then render this each-loop in Main.svelte

<script> import { renderArray } from './ArraySnippet.svelte' let array = $state([ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ]) function randomOrder() { array.sort((a,b) => Math.random() > 0.5) } </script> <button onclick={randomOrder}> Randomize order </button> <#snippet itemSnippet(value)> <div animate:flip> {value} </div> </snippet {@render renderArray(array, itemSnippet)}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants