Valexr / Slidy

📸 Sliding action script
https://valexr.github.io/Slidy/
MIT License
316 stars 13 forks source link

Svelte 5 Compatibility #133

Open scart88 opened 2 weeks ago

scart88 commented 2 weeks ago

Hey @Valexr

Is this library compatible with Svelte 5?

Thank you!

Valexr commented 2 weeks ago

I think you mean package @slidy/svelte...🤔 You can check it yourself in this playground

scart88 commented 2 weeks ago

Thank you very much!

Do you have any idea about the svelte:fragments ?

svelte:fragments are deprecated in Svelte 5 in favor of snippets

Is there a way to hide the slidy-overlay other than .slidy-overlay { display: none; }?

The svelte migration tool converted from something like this

<svelte:component this={c.Slidy} {...slides} let:item>
  <Review item={item} />
</svelte:component>

To something like this, and it works, however, it doesn't work with svelte:fragment

<Slidy --slidy-slide-width="300px" --slidy-slide-gap="2rem"  {slides} {snap} {loop} {arrows} {width} {height} {groups} {progress} {navigation} {thumbnail} let:item bind:index bind:position
    classNames={{
      root: `${classNames.root} custom-class`,
      ...classNames
    }}>

  {#snippet children({ item })}
     <Review {item} />
  {/snippet}
</Slidy>
Valexr commented 2 weeks ago

Sorry, I don't understand you... can you explain in playground more detailed code?

hiromon0125 commented 6 days ago

Hey, big fan of your library. I just wanted to give help out here with a new svelte 5 update changes.

Svelte 4 let us do named slots like below where we use svelte:fragments. This is directly from you guys' docs:

<Slidy>
    <svelte:fragment slot="arrows">
        <button data-step="-1"> Show the previous slide </button>
        <button data-step="1"> Show the next slide </button>
    </svelte:fragment>
</Slidy>

But now in svelte 5 we no longer have svelte:fragments in favor of using #snippets and @render. I think these svelte docs are helpful summary of the new syntax:

Hope that helps! Happy coding.

Valexr commented 6 days ago

Tx @hiromon0125 it became clearer, but it's backward compatibility problem - using the same logic for slot or snippet... 🤔 now I haven't any ideas...

scart88 commented 6 days ago

Thanks @Valexr and @hiromon0125

I don't have a REPL account, and saving the playground was challenging. Thanks for stepping in.

Here is a comparison between slots in (Svelte 4) and Render in (Svelte 5). https://component-party.dev/compare/svelte4-vs-svelte5#component-composition.slot-fallback

// App.svelte
<script>
    import MediaQuery from "./MediaQuery.svelte"
</script>

<MediaQuery query="(max-width: 580px)">
    {#snippet children(matches)}
      {matches}
        {#if matches}
            <h1>Hello World</h1>
        {/if}
    {/snippet}

    {#snippet children2()}
        <h2>TEST</h2>
    {/snippet}
</MediaQuery>
// MediaQuery.svelte
<script>    
    let { children, children2, query } = $props()

    let matches = $state(false);

    $effect(() => {
        function handleChange(e) {
            matches = e.matches;
        }

        const mql = window.matchMedia(query)
        mql.addEventListener("change", handleChange)
        return () => {
            mql.removeEventListener(handleChange)
        }
    })
</script>

{@render children(matches)}
{@render children2?.()}
scart88 commented 6 days ago

The svelte:fragment would look something like this in Svelte 5

<Slidy>
    {#snippet arrows()}
          <button data-step="-1"> Show the previous slide </button>
          <button data-step="1"> Show the next slide </button>
    {/snippet}
</Slidy>

I guess, somewhere in the the Slidy library https://github.com/Valexr/Slidy/blob/main/packages/svelte/src/components/Slidy/Slidy.svelte#L135C2-L158C7, the snippet will be rendered with {@render arrows?.()}

hiromon0125 commented 5 days ago

Yeah I think @scart88's idea is correct. In terms of how to convert svelte 4 to svelte 5, we would just declare a snippet function for each "name" slot. Therefore we need a snippet function declaration for arrow, arrows, default, nav-item, overlay, and thumbnail for slidy. We also need children snippet declared in both Core and slidy because I realized now that they got rid of <slot/> altogether 😅. They have a migration guide here so you can reference that. So something like this in Slidy.svelte to give you a general idea.

<script>
     let { arrow, arrows, default, navItem, overlay, thumbnail, children} = $props();
</script>

{#snippet counter()}
    <output class="{classNames?.counter}">
        {format(i18n.counter, index + 1, length)}
    </output>
{/snippet}
{#snippet defaultChildren(item)}
    {#if !background}
        <Image src={getImgSrc(item)} {...item} />
    {/if}
{/snippet}

<section>
    {@render (overlay ?? counter)()}
    <Core >
        {#snippet children()} // This is core's children
            {#each slides as item, i (item.id ?? getImgSrc(item) ?? i)}
                {@const active = i === index}
                <li>
                    {@render (children ?? defaultChildren)(item)}
                </li>
            {/each}
        {/snippet}
    </Core >
    ... more {@render snippetItem} stuff down here
</section>

I am also still trying to understand all of the things that changed with this new version of svelte, so I could be wrong here.

Valexr commented 4 days ago

Looks like new major version of @slidy/svelte with 5 compatibility 🤔

Valexr commented 4 days ago

@hiromon0125 & @scart88 if you have ideas, PR welcome. @EricRovell (core maintainer @slidy/svelte) can do this near NewYear holidays…

scart88 commented 4 days ago

I want to help because I'm a big fan of Slidy. However, I'm still learning Svelte, so I don't think I'm the best person to do it; however, I can try to see how I can help.

I discovered a minor bug in Svelte 5. If the slide item content changes when (e.g., clicking on a button or changing an item in a select element), the slides shift similarly to the Go to the next slide button works.

Is there a way to prevent or stop the slide from moving if a user interacts with a slide item?

Thank you!

Valexr commented 4 days ago

I think it’s just reactivity depending in Slidy props… or if you interacting with wrapper section (it’s listening click event)… but for more constructive dialog, I ask you to create a playground. Auth in it for saving examples, just auth in GitHub third party app… it’s safe 🤓

scart88 commented 4 days ago

Thanks! I just created a Playground

If you click the "Check" button, I'm using an if / else to show a loading state and simulate a fetch request. When the content inside the slide item changes, the slide shifts because the HTML content changes.

If the class name changes, it works as expected. However, it doesn't work if you use if/else to update content inside the slide item.

Please let me know your thoughts.

Thank you!

scart88 commented 3 days ago

Update: I notice the bug goes away if the loop option is set to false.

Valexr commented 3 days ago

Fixed - check Playground

scart88 commented 3 days ago

Thank you so much for fixing this so quickly!

Valexr commented 3 days ago

Tx you for bug-report 👍🏻