npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

solid-watch-primitives

v0.1.2

Published

Reactive helpers built around watching computation changes.

Downloads

3

Readme

solid-watch-primitives

This package is experimental, made to test the concept and usability of primitives build around watching computation changes, to see how it can be used in Solid. Eventually to be merged to solid-primitives if proven useful.

Feel free to play around with it, I would appreciate any feedback or ideas that you may have, you can join the discussion here or simply open an issue if you have some opinions to share.

The original idea and parts of the used logic comes from Anthony Fu's vueuse library for Vue.

try on codesandbox

The Usage:

Installation:

npm i solid-watch-primitives

Available Primitives:

import {
   createFilteredEffect,
   createFilter,
   until,
} from 'solid-watch-primitives'

createFilteredEffect

When used alone, it's a shortcut for createEffect(on(source, fn)). But it can be combined with Filters to extend it's functionality.

const [counter, setCounter] = createSignal(0)

// alone:
createFilteredEffect(counter, n => console.log(n))

// accepts "defer" option, same as on()
createFilteredEffect(counter, n => console.log(n), { defer: true })

// with filter:
createFilteredEffect(debounced(counter, n => console.log(n), { wait: 300 }))

// with nested filters:
const { stop, pause } = createFilteredEffect(
   stoppable(pausable(counter, n => console.log(n))),
)

createFilter

A utility for creating your own custom filters. Every available filter was made using this.

function createFilter<Config, Returns, RequireStop>(
   modifier: (
      source: Fn<any> | Fn<any>[], // like source of "on"
      callback: EffectCallback, // like callback of "on"
      config: Config, // config for your filter
      stop: StopEffect | undefined, // a StopEffect if RequireStop
   ) => [CustomCallback, Returns], // return your modified callback and custom return values
   requireStop?: RequireStop, // true if you want to use StopEffect
): Filter {}

// for example, thats the source of "debounce"
const debounce = createFilter<{
   wait: number
}>((s, fn, options) => {
   const [_fn, clear] = _debounce(fn, options.wait)
   onCleanup(clear)
   return [_fn, {}]
})

// and this is "atMost", notice the required double "true" to use stop
const atMost = createFilter<
   { limit: MaybeAccessor<number> }, // config you require
   { count: Accessor<number> }, // what you want to return
   true // if you want to use stop()
>(
   (s, callback, config, stop) => {
      const [count, setCount] = createSignal(0)
      const _fn = (...a: [any, any, any]) => {
         setCount(p => p + 1)
         count() + 1 >= access(config.limit) && stop()
         callback(...a)
      }
      return [_fn, { count }] // [CustomCallback, Returns]
   },
   true, // if you want to use stop()
)

until

until instead of being a simple shortcut, this one solves an actual problem. The problem is that, when you use someting like createFetch to abstract an asynchronous operation into a reactive helper, you loose the option to use await. Because you are turning Promise into a Signal. The until tries to brings that functionality back.

const [data] = createFetch('https://my-url/')

await until(data).not.toBeNull()
console.log(data)

More until usage here

Available Filters

import {
   stoppable,
   once,
   atMost,
   debounce,
   throttle,
   whenever,
   pausable,
   ignorable,
} from 'solid-watch-primitives'

stoppable

returns { stop: StopEffect }, that can be used to manually dispose of the effects.

const { stop } = createFilteredEffect(stoppable(counter, n => console.log(n)))

once

disposes itself on the first captured change. Set the defer option to true, otherwise the callback will run and dispose itself on the initial setup.

createFilteredEffect(
   once(counter, n => console.log(n)),
   { defer: true },
)

atMost

you specify the number of times it can triggered, until disposes itself.

const { count } = createFilteredEffect(
   atMost(counter, n => console.log(n), { limit: 8 }),
)

debounce

debounces callback

const position = createScrollObserver()

createFilteredEffect(debounce(position, x => console.log(x), { wait: 300 }))

throttle

The callback is throttled

const position = createScrollObserver()

createFilteredEffect(throttle(position, x => console.log(x), { wait: 300 }))

whenever

Runs callback each time the source is truthy.

setInterval(() => setCount(p => p + 1), 1000)

createFilteredEffect(
   whenever(
      () => count() > 5,
      () => console.log(count()),
   ),
)
// will fire on each count change, if count is gt 5
// => 6, 7, 8, 9, 10, ...

createFilteredEffect(
   whenever(
      createMemo(() => count() > 5),
      () => console.log(count()),
   ),
)
// will fire only when the memo changes
// => 6

pausable

Manually controll if the callback gets to be executed

const { pause, resume, toggle } = createFilteredEffect(
   pausable(counter, x => console.log(x), { active: false }),
)

ignorable

Somewhat similar to pausable, but ignore changes that would cause the next effect to run.

Because Solid batches together changes made in effects, the usage inside and outside effects will differ.

const { ignoreNext, ignoring } = createFilteredEffect(ignorable(
   counter,
   x => {
      // next effect will be ignored:
      ignoreNext()
      setCounter(p => p + 1)

      // this change happens in the same effect, so it will also be ignored
      setCounter(5)
   }
));


const ignoreMe = () => {
   ignoring(() => {
      // both changes will be ignored:
      setCounter(420)
      setCounter(69)
   })
   // but not this one:
   setCounter(p => p + 2)
}

// this watcher will work normally,
// ignoring only affects the ignorableWatch above
createFilteredEffect(counter, () => {...})