signal.ts 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import { createEffect, createSignal, on, onCleanup, type Accessor } from "solid-js"
  2. export function createDebouncedSignal<T>(value: T, ms: number): [Accessor<T>, (value: T) => void] {
  3. const [get, set] = createSignal(value)
  4. let timer: ReturnType<typeof setTimeout> | undefined
  5. const debounced = (next: T) => {
  6. if (timer) clearTimeout(timer)
  7. timer = setTimeout(() => {
  8. timer = undefined
  9. set(() => next)
  10. }, ms)
  11. }
  12. onCleanup(() => {
  13. if (timer) clearTimeout(timer)
  14. })
  15. return [get, debounced]
  16. }
  17. export function createFadeIn(show: Accessor<boolean>, enabled: Accessor<boolean>) {
  18. const [alpha, setAlpha] = createSignal(show() ? 1 : 0)
  19. let revealed = show()
  20. createEffect(
  21. on([show, enabled], ([visible, animate]) => {
  22. if (!visible) {
  23. setAlpha(0)
  24. return
  25. }
  26. if (!animate || revealed) {
  27. revealed = true
  28. setAlpha(1)
  29. return
  30. }
  31. const start = performance.now()
  32. revealed = true
  33. setAlpha(0)
  34. const timer = setInterval(() => {
  35. const progress = Math.min((performance.now() - start) / 160, 1)
  36. setAlpha(progress * progress * (3 - 2 * progress))
  37. if (progress >= 1) clearInterval(timer)
  38. }, 16)
  39. onCleanup(() => clearInterval(timer))
  40. }),
  41. )
  42. return alpha
  43. }