Skip to content

[bug] Svelte 5 Range handles are not moving when dragged. #130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
serferdinand2 opened this issue Jan 24, 2024 · 17 comments · Fixed by sveltejs/svelte#10543
Closed

[bug] Svelte 5 Range handles are not moving when dragged. #130

serferdinand2 opened this issue Jan 24, 2024 · 17 comments · Fixed by sveltejs/svelte#10543
Labels
bug Something isn't working investigating Not quite sure if it's valid, yet

Comments

@serferdinand2
Copy link

serferdinand2 commented Jan 24, 2024

Describe the bug
The slider handles are not moving even tho the value is being read and the handler recognizes the value
EDIT: It looks like this is, in general, an issue with bind: values = {...} and it is not limited to range property. As soon as you bind the values the slider handles will stop moving.
To Reproduce

Steps to reproduce the behavior:

  1. npmi svelte-range-slider-pips components into svelte 5 project
let {min, max} = $props();
// old export let min

let values = $state([0, 8]);
// old $: values = [0,8]
<RangeSlider
		float
		range
		pips
		hoverable
		{id}
		{min}
		{max}
		all="label"
		bind:values
		on:stop={someHandler} />
  1. Run in Vite

Screenshots
As seen from the picture below, even tho the handle was moved and the value was read, the actual handle element stayed in place.

Screenshot 2024-01-24 at 19 59 39
Screenshot 2024-01-24 at 20 00 37

Device/Environtment

Svelte 5 with typescript and sveltekit 2

Additional context
I have noticed that this component is on svelte 3.0.0. It would be great to create an alpha version of svelte-range-slider-pips that is accommodating the new runes system. If not, it should be crosscompatible with at least Svelte 4.

@serferdinand2 serferdinand2 added bug Something isn't working investigating Not quite sure if it's valid, yet labels Jan 24, 2024
@simeydotme
Copy link
Owner

thanks @serferdinand2 for the detailed explainer!
I have a question, though, your last line indicates the issue exists in svelte4?

Also I note you've written Sveltekit2 ... is this a SSR issue? Does the same thing happen when SSR is off? Perhaps the new runes are not compatible with binding to an array?

@serferdinand2
Copy link
Author

@simeydotme

I have made sure that the component is rendered in the browser with {#if browser} module. If not, an error occurs:

ReferenceError: document is not defined
    at pureText (/Users/***/Work/***/svelte_components/node_modules/svelte-range-slider-pips/src/RangeSlider.svelte:396:17)
    ...

So yes, I made sure that it is CSR.

As for the comment on Svelte 4, different issues might occur. The bundler support has changed. I am not 100% sure how exactly this might affect the slider. I did not dig into its code but I think it might be the reason for the #125 issue.

https://svelte.dev/docs/v4-migration-guide#browser-conditions-for-bundlers

I'd love to try and experimentally upgrade this component to Svelte 5 when I find some time.

@simeydotme
Copy link
Owner

Ah that was my bad, I fixed it with 2.3.1, apologies on that

@simeydotme
Copy link
Owner

simeydotme commented Jan 26, 2024

Regarding Svelte 5;

Every few weeks I sit down and think "today is the day"... I install Svelte in a fresh branch and look at it and get mad.

There's no clear way, and no good tutorials, on how to build and bundle the Svelte components from the new Sveltekit library project into a UMD plain js.

I haven't upgraded from Svelte 3 because that was the last time the rollup bundler was able to convert the Svelte components into a .js file.

I feel quite disappointed, because I don't really want to isolate this component to Svelte. I've used it in my own Vue projects and jQuery projects. I don't want to lose that. can't seem to get the "custom element" bundle working.

If you have any information, or know any good resources on this I'd really appreciate it

I've learned a lot since I first started this project so I would love to rebuild it in Svelte 4/5 , maybe even with TypeScript 😬 .. but yeh I just can't get over that problem of locking it in to Svelte only.

@simeydotme
Copy link
Owner

ok, I have something working.
😅

watch this space

@serferdinand2
Copy link
Author

Sorry, long weekend.

I am glad if you found something that works.

Usually you can control SSR with onMount, {browser}, +page.js/ts and other.

@simeydotme
Copy link
Owner

hey @serferdinand2 do you mind to try with the beta version I just published?
https://www.npmjs.com/package/svelte-range-slider-pips/v/3.0.0-beta.3
see if that is working?

I updated to svelte4 and added types and other small improvements. Haven't updated readme/docs yet ... need to make sure I didn't break anything first

@serferdinand2
Copy link
Author

I've installed the beta version, unfortunately, the issue with handles moving is persisting on Svelte 5 with Sveltekit 2

It looks like the value is updated but the nub is not moving still..

@serferdinand2
Copy link
Author

It also looks like if you pass the value like

<RangeSlider 
    {min}
    {max}
    value = {2}
    />

The numb is moved to the position indicated by the value. I hope this helps!

@simeydotme
Copy link
Owner

thanks @serferdinand2 , I'll look into it!

@simeydotme
Copy link
Owner

ok, I think it's to do with how Svelte5 Runes have compiled with the spring store;

$.untrack(() => {
  const trimmedAlignedValues = trimRange(values().map((v) => alignValueToStep(v, min(), max(), step(), precision())));
  
  if (!(values().length === trimmedAlignedValues.length) || !values().every((element, index) => coerceFloat(element, precision()) === trimmedAlignedValues[index])) {
    values(trimmedAlignedValues);
  }
  
  if ($.get(valueLength) !== values().length) {
    $.set(springPositions, spring(values().map((v) => valueAsPercent(v, min(), max())), springValues()));
  } else {
    $.get(springPositions).set(values().map((v) => valueAsPercent(v, min(), max())));
  }
  
  $.set(valueLength, values().length);
});

This is the compiled svelte5 (internal) rune code, and it seems to be not tracking anything inside this reactive chunk ($.untrack) when the values[] array changes .. I guess something about the way my reactive block code is done just doesn't convert well;

$: {
  // trim the range so it remains as a min/max (only 2 handles)
  // and also align the handles to the steps
  const trimmedAlignedValues = trimRange(
    values.map((v) => alignValueToStep(v, min, max, step, precision))
  );
  if (
    !(values.length === trimmedAlignedValues.length) ||
    !values.every(
      (element, index) =>
        coerceFloat(element, precision) === trimmedAlignedValues[index]
    )
  ) {
    values = trimmedAlignedValues;
  }

  // check if the valueLength (length of values[]) has changed,
  // because if so we need to re-seed the spring function with the
  // new values array.
  if (valueLength !== values.length) {
    // set the initial spring values when the slider initialises,
    // or when values array length has changed
    springPositions = spring(
      values.map((v) => valueAsPercent(v, min, max)),
      springValues
    );
  } else {
    // update the value of the spring function for animated handles
    // whenever the values has updated
    springPositions.set(values.map((v) => valueAsPercent(v, min, max)));
  }
  // set the valueLength for the next check
  valueLength = values.length;
}

None of this executes (I've run the debugger), but the specifically problematic code for this issue is; springPositions.set(values.map((v) => valueAsPercent(v, min, max)));

I might be able to modify the code execution and explicitly set the spring store when modifying the values array... however I feel there must be more deeper problems than this.

It might be that Svelte5 just simply breaks this component and we'll need to re-write it in Svelte5.

What's funny, though, is that in my Svelte4 branch I added the prop value as an option which still works, as it's not defined in the untrack parameters?

@serferdinand2
Copy link
Author

Oh so it is Svelte compiler doing this.

If the issue is with the spring library, it might not even work to convert it to Svelte 5.

I didn't see any issues regarding spring in svelte that are newer tho :/

@simeydotme
Copy link
Owner

no, it's not the Spring library .. its the way the "untrack" super-helper (no idea what to call that) is interpreting my code as something that doesn't need to be reactive... even though it's in a freaking reactive block. Seems the logic they are using is not fully walking my syntax tree

dummdidumm added a commit to sveltejs/svelte that referenced this issue Feb 19, 2024
Ensure update methods of actions and reactive statements work with fine-grained `$state` by deep-reading them. This is necessary because mutations to `$state` objects don't notify listeners to only the object as a whole, it only notifies the listeners of the property that changed.
fixes #10460
fixes simeydotme/svelte-range-slider-pips#130
@dummdidumm
Copy link

The problem is on Svelte's side. The problem is the combination of passing in $state (which is fine-grained, compared to the old let which is not) in combination with the transformation of $: which only checks that the property as a whole, not its properties, have changed, in order to rerun. sveltejs/svelte#10543 will fix this.

@simeydotme
Copy link
Owner

The problem is on Svelte's side. The problem is the combination of passing in $state (which is fine-grained, compared to the old let which is not) in combination with the transformation of $: which only checks that the property as a whole, not its properties, have changed, in order to rerun. sveltejs/svelte#10543 will fix this.

Thank you so much for following up on this! 🙏
Let me know if anything I can do to help

dummdidumm added a commit to sveltejs/svelte that referenced this issue Feb 20, 2024
Ensure update methods of actions and reactive statements work with fine-grained `$state` by deep-reading them. This is necessary because mutations to `$state` objects don't notify listeners to only the object as a whole, it only notifies the listeners of the property that changed.
fixes #10460
fixes simeydotme/svelte-range-slider-pips#130
@serferdinand2
Copy link
Author

Looks like it works now after the latest svelte update!

@simeydotme
Copy link
Owner

amaze!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working investigating Not quite sure if it's valid, yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants