@joewinke/jatui 0.41.0 → 0.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">
2
2
  import { untrack } from 'svelte';
3
- import { Tween } from 'svelte/motion';
4
3
  import { cubicOut } from 'svelte/easing';
5
4
  import { getMotionContext, motionDuration } from '../motion/level';
6
5
 
@@ -21,13 +20,32 @@
21
20
 
22
21
  // ── Tween mode ─────────────────────────────────────────────────────────
23
22
  let tweenEl: HTMLSpanElement | undefined = $state();
24
- const tween = new Tween(untrack(() => value), { easing: cubicOut, duration: 0 });
23
+ // A hand-rolled rAF tween, NOT svelte/motion's Tween: importing svelte/motion
24
+ // creates a prefers-reduced-motion MediaQuery at MODULE load, which throws
25
+ // 'window.matchMedia is not a function' in any jsdom test that merely
26
+ // imports 'jatui' (jatui-oozkb). Reduced motion comes from motionDuration,
27
+ // which is 0 under prefers-reduced-motion.
28
+ let tweenCurrent = $state(untrack(() => value));
25
29
  $effect(() => {
26
30
  if (mode !== 'tween') return;
27
31
  const target = value;
28
32
  // Level-aware (data-motion) and instant under prefers-reduced-motion.
29
33
  const ms = motionDuration(duration ?? 'move', getMotionContext(tweenEl ?? null));
30
- void tween.set(target, { duration: ms });
34
+ const from = untrack(() => tweenCurrent);
35
+ if (ms <= 0 || from === target || typeof requestAnimationFrame !== 'function') {
36
+ tweenCurrent = target;
37
+ return;
38
+ }
39
+ let frame = 0;
40
+ let start: number | null = null;
41
+ const step = (now: number) => {
42
+ start ??= now;
43
+ const t = Math.min(1, (now - start) / ms);
44
+ tweenCurrent = from + (target - from) * cubicOut(t);
45
+ if (t < 1) frame = requestAnimationFrame(step);
46
+ };
47
+ frame = requestAnimationFrame(step);
48
+ return () => cancelAnimationFrame(frame);
31
49
  });
32
50
  /** Decimals to show mid-tween: the target's own, unless `format` decides. */
33
51
  const tweenDecimals = $derived.by(() => {
@@ -36,7 +54,7 @@
36
54
  return s.includes('.') && !s.includes('e') ? s.split('.')[1].length : 0;
37
55
  });
38
56
  const tweenText = $derived.by(() => {
39
- const v = tween.current;
57
+ const v = tweenCurrent;
40
58
  const shown = tweenDecimals == null ? v : Number(v.toFixed(tweenDecimals));
41
59
  return formatNumber(shown, format);
42
60
  });
@@ -37,7 +37,7 @@
37
37
  let paused = false;
38
38
 
39
39
  const prefersReducedMotion =
40
- typeof window !== 'undefined'
40
+ typeof window !== 'undefined' && typeof window.matchMedia === 'function'
41
41
  ? window.matchMedia('(prefers-reduced-motion: reduce)').matches
42
42
  : false;
43
43
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joewinke/jatui",
3
- "version": "0.41.0",
3
+ "version": "0.41.1",
4
4
  "private": false,
5
5
  "description": "Shared Svelte 5 component library for JAT projects",
6
6
  "type": "module",