{"id":16525900,"url":"https://github.com/thetarnav/solid-watch-primitives","last_synced_at":"2026-06-08T17:31:33.837Z","repository":{"id":46079067,"uuid":"427932249","full_name":"thetarnav/solid-watch-primitives","owner":"thetarnav","description":"An experimental collection of reactive helpers built around watching computation changes. Inspired by: https://vueuse.org/functions.html#watch. Made For: https://github.com/davedbase/solid-primitives","archived":false,"fork":false,"pushed_at":"2021-11-16T21:13:56.000Z","size":195,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-04T00:09:26.229Z","etag":null,"topics":["effects","primitives","solid","watch"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/solid-watch-primitives","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thetarnav.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-14T13:11:57.000Z","updated_at":"2021-11-16T21:13:59.000Z","dependencies_parsed_at":"2022-08-26T08:00:53.529Z","dependency_job_id":null,"html_url":"https://github.com/thetarnav/solid-watch-primitives","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/thetarnav/solid-watch-primitives","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thetarnav%2Fsolid-watch-primitives","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thetarnav%2Fsolid-watch-primitives/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thetarnav%2Fsolid-watch-primitives/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thetarnav%2Fsolid-watch-primitives/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thetarnav","download_url":"https://codeload.github.com/thetarnav/solid-watch-primitives/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thetarnav%2Fsolid-watch-primitives/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34073682,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["effects","primitives","solid","watch"],"created_at":"2024-10-11T17:07:52.550Z","updated_at":"2026-06-08T17:31:33.815Z","avatar_url":"https://github.com/thetarnav.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# solid-watch-primitives\n\n#### 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](https://www.solidjs.com/). Eventually to be merged to [solid-primitives](https://github.com/davedbase/solid-primitives) if proven useful.\n\n#### Feel free to play around with it, I would appreciate any feedback or ideas that you may have, you can join the discussion [here](https://github.com/davedbase/solid-primitives/pull/19) or simply open an issue if you have some opinions to share.\n\n#### The original idea and parts of the used logic comes from [Anthony Fu's vueuse library](https://github.com/vueuse/vueuse) for Vue.\n\n[try on codesandbox](https://codesandbox.io/s/solid-watch-primitives-urb2u?file=/src/index.tsx)\n\n## The Usage:\n\n### Installation:\n\n```sh\nnpm i solid-watch-primitives\n```\n\n### Available Primitives:\n\n```ts\nimport { createFilteredEffect, createFilter, until } from 'solid-watch-primitives'\n```\n\n### createFilteredEffect\n\nWhen used alone, it's a shortcut for `createEffect(on(source, fn))`. But it can be combined with [Filters](#available-filters) to extend it's functionality.\n\n```ts\nconst [counter, setCounter] = createSignal(0)\n\n// alone:\ncreateFilteredEffect(counter, n =\u003e console.log(n))\n\n// accepts \"defer\" option, same as on()\ncreateFilteredEffect(counter, n =\u003e console.log(n), { defer: true })\n\n// with filter:\ncreateFilteredEffect(debounced(counter, n =\u003e console.log(n), { wait: 300 }))\n\n// with nested filters:\nconst { stop, pause } = createFilteredEffect(stoppable(pausable(counter, n =\u003e console.log(n))))\n```\n\n### createFilter\n\nA utility for creating your own custom filters. Every available filter was made using this.\n\n```ts\nfunction createFilter\u003cConfig, Returns, RequireStop\u003e(\n   modifier: (\n      source: Fn\u003cany\u003e | Fn\u003cany\u003e[], // like source of \"on\"\n      callback: EffectCallback, // like callback of \"on\"\n      config: Config, // config for your filter\n      stop: StopEffect | undefined, // a StopEffect if RequireStop\n   ) =\u003e [CustomCallback, Returns], // return your modified callback and custom return values\n   requireStop?: RequireStop, // true if you want to use StopEffect\n): Filter {}\n\n// for example, thats the source of \"debounce\"\nconst debounce = createFilter\u003c{\n   wait: number\n}\u003e((s, fn, options) =\u003e {\n   const [_fn, clear] = _debounce(fn, options.wait)\n   onCleanup(clear)\n   return [_fn, {}]\n})\n\n// and this is \"atMost\", notice the required double \"true\" to use stop\nconst atMost = createFilter\u003c\n   { limit: MaybeAccessor\u003cnumber\u003e }, // config you require\n   { count: Accessor\u003cnumber\u003e }, // what you want to return\n   true // if you want to use stop()\n\u003e(\n   (s, callback, config, stop) =\u003e {\n      const [count, setCount] = createSignal(0)\n      const _fn = (...a: [any, any, any]) =\u003e {\n         setCount(p =\u003e p + 1)\n         count() + 1 \u003e= access(config.limit) \u0026\u0026 stop()\n         callback(...a)\n      }\n      return [_fn, { count }] // [CustomCallback, Returns]\n   },\n   true, // if you want to use stop()\n)\n```\n\n### until\n\n`until` instead of being a simple shortcut, this one solves an actual problem.\nThe 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.\n\n```ts\nconst [data] = createFetch('https://my-url/')\n\nawait until(data).not.toBeNull()\nconsole.log(data)\n```\n\n[More until usage here](https://vueuse.org/shared/until/#usage)\n\n### Available Filters\n\n```ts\nimport {\n   stoppable,\n   once,\n   atMost,\n   debounce,\n   throttle,\n   whenever,\n   pausable,\n   ignorable,\n} from 'solid-watch-primitives'\n```\n\n### stoppable\n\nreturns `{ stop: StopEffect }`, that can be used to manually dispose of the effects.\n\n```ts\nconst { stop } = createFilteredEffect(stoppable(counter, n =\u003e console.log(n)))\n```\n\n### once\n\ndisposes itself on the first captured change. **Set the defer option to true**, otherwise the callback will run and dispose itself on the initial setup.\n\n```ts\ncreateFilteredEffect(\n   once(counter, n =\u003e console.log(n)),\n   { defer: true },\n)\n```\n\n### atMost\n\nyou specify the number of times it can triggered, until disposes itself.\n\n```ts\nconst { count } = createFilteredEffect(atMost(counter, n =\u003e console.log(n), { limit: 8 }))\n```\n\n### debounce\n\ndebounces callback\n\n```ts\nconst position = createScrollObserver()\n\ncreateFilteredEffect(debounce(position, x =\u003e console.log(x), { wait: 300 }))\n```\n\n### throttle\n\nThe callback is throttled\n\n```ts\nconst position = createScrollObserver()\n\ncreateFilteredEffect(throttle(position, x =\u003e console.log(x), { wait: 300 }))\n```\n\n### whenever\n\nRuns callback each time the source is truthy.\n\n```ts\nsetInterval(() =\u003e setCount(p =\u003e p + 1), 1000)\n\ncreateFilteredEffect(\n   whenever(\n      () =\u003e count() \u003e 5,\n      () =\u003e console.log(count()),\n   ),\n)\n// will fire on each count change, if count is gt 5\n// =\u003e 6, 7, 8, 9, 10, ...\n\ncreateFilteredEffect(\n   whenever(\n      createMemo(() =\u003e count() \u003e 5),\n      () =\u003e console.log(count()),\n   ),\n)\n// will fire only when the memo changes\n// =\u003e 6\n```\n\n### pausable\n\nManually controll if the callback gets to be executed\n\n```ts\nconst { pause, resume, toggle } = createFilteredEffect(\n   pausable(counter, x =\u003e console.log(x), { active: false }),\n)\n```\n\n### ignorable\n\nSomewhat similar to `pausable`, but ignore changes that would cause the next effect to run.\n\nBecause Solid batches together changes made in effects, the usage inside and outside effects will differ.\n\n```ts\nconst { ignoreNext, ignoring } = createFilteredEffect(ignorable(\n   counter,\n   x =\u003e {\n      // next effect will be ignored:\n      ignoreNext()\n      setCounter(p =\u003e p + 1)\n\n      // this change happens in the same effect, so it will also be ignored\n      setCounter(5)\n   }\n));\n\n\nconst ignoreMe = () =\u003e {\n   ignoring(() =\u003e {\n      // both changes will be ignored:\n      setCounter(420)\n      setCounter(69)\n   })\n   // but not this one:\n   setCounter(p =\u003e p + 2)\n}\n\n// this watcher will work normally,\n// ignoring only affects the ignorableWatch above\ncreateFilteredEffect(counter, () =\u003e {...})\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthetarnav%2Fsolid-watch-primitives","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthetarnav%2Fsolid-watch-primitives","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthetarnav%2Fsolid-watch-primitives/lists"}