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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@solid-hooks/core

v0.6.0

Published

useful hooks for solid.js

Readme

@solid-hooks/core

useful hooks for solid.js

[!WARNING] Breaking change expected. Use at your own risk.

Install

npm i @solid-hooks/core
yarn add @solid-hooks/core
pnpm add @solid-hooks/core

Usage

createRef

read / write signal in one function

import { createRef } from '@solid-hooks/core'
import { onMounted } from 'solid-js'

function Test() {
  const divRef = createRef<HTMLDivElement>()
  return <div ref={divRef} />
}

function Counter() {
  const counter = createRef(0)
  return <button onClick={() => counter(c => c + 1)}>{counter()}</button>
}

function useSomethingRef() {
  return createRef(useSomething())
}

createTracker

Track plain object property, make it reactive

import { createTracker } from '@solid-hooks/core'

const audio = new Audio()
const [time, setCurrentTime] = createTracker(audio, 'currentTime')

Before v0.4.0 is createReactive

createArray

create array signal

import { createArray } from '@solid-hooks/core'

const [array, setArray] = createArray(['a', 'b', 'c'])

const push = setArray(l => l.push('d'))
const pop = setArray(l => l.pop())
const reset = setArray(['a', 'b', 'c'])

createToggle

create toggle signal

import { createToggle } from '@solid-hooks/core'

const [state, toggle] = createToggle(
  false,
  value => console.log(value)
)
toggle()
toggle(true)
toggle(false)

createDirective

another way to create directive

import type { Accessor, Setter } from 'solid-js'

import { createDirective } from '@solid-hooks/core'
import { createRenderEffect, createSignal } from 'solid-js'

const model = createDirective((ref: Element, getter: Accessor<string>, setter: Setter<string>) => {
  createRenderEffect(() => ((ref as HTMLInputElement).value = getter()))
  ref.addEventListener('input', e => setter((e.target as HTMLInputElement | null)?.value ?? ''))
})

function TextInput() {
  const [text, setText] = createSignal('')
  return (
    <>
      <input type="text" ref={model(text, setText)} />
      <div>{text()}</div>
    </>
  )
}

reference from voby

watch

filterable and pausable createEffect(on()) like, defer by default

import { watch } from '@solid-hooks/core'
import { throttle } from '@solid-primitives/scheduled'

const [count, setCount] = createSignal(0)
const { pause, resume, isWatching, callTimes, ignoreUpdate } = watch(
  count,
  (value, oldValue, callTimes) => {
    console.log(value, oldValue, callTimes)
    const cleanup = () => { }
    return cleanup
  },
  {
    eventFilter: fn => throttle(fn, 100),
    count: 5,
    defer: false /* true by default */
  }
)

watchOnce

watch once, using createReaction

import { watchOnce } from '@solid-hooks/core'

const [count, setCount] = createSignal(0)
watchOnce(count, console.log)

watchImmediate

like watch, use createComputed

watchRendered

like watch, use createRendered

useEmits

like defineEmits in Vue, emit event from child component

import { useEmits } from '@solid-hooks/core'

type Emits = {
  // sync
  $var: (data: number) => void
  $update: (d1: string, d2?: string, d3?: string) => void
  // or async
  fn: (test: string) => Promise<void>
}
function Child(prop: Emits & { num: number }) {
  const emit = useEmits(prop)
  const handleClick = () => {
    emit('var', { id: 1 })
    emit('update', `emit from child: ${prop.num}`, 'second param')
    emit('fn', ['a', 'b'])
  }
  return (
    <div>
      <div>
        child prop: {prop.num}
      </div>
      <button onClick={handleClick}>click and see console</button>
    </div>
  )
}

export default function Father() {
  return (
    <Child
      num={1}
      $var={e => console.log('[emit] $var:', e)}
      $update={(d, d1) => console.log(`[emit] $update:`, d, d1)}
      $fn={test => console.log('[emit] $fn:', test)}
    />
  )
}

createApp

like createApp() in Vue

import { createApp } from '@solid-hooks/core'

import App from './App'

createApp(App)
  .use(RouterProvider, { props })
  .use(I18nProvider)
  .use(GlobalStoreProvider)
  .mount('#app')

is equal to:

render(
  <RouterProvider props={props}>
    <I18nProvider>
      <GlobalStoreProvider>
        <App />
      </GlobalStoreProvider>
    </I18nProvider>
  </RouterProvider>,
  document.querySelector('#app')
)

reference from solid-utils

createContextProvider

reference from @solid-primitives/context

if default value is not defined and use context outside provider, throw Error when DEV

import { createContextProvider } from '@solid-hooks/core'
import { createSignal } from 'solid-js'

export const [TestProvider, useTestContext] = createContextProvider((param: { initial: number }) => {
  const [count, setCount] = createSignal(param.initial)
  const increment = () => setCount(count() + 1)

  return { count, increment }
})

function Child() {
  const { count, increment } = useTestContext()
  return (
    <button onClick={increment}>
      {count()}
    </button>
  )
}

export function TestContextProvider() {
  console.log('call useTestContext() outside provider:', useTestContext())
  return (
    <TestProvider initial={0}>
      <Child />
    </TestProvider>
  )
}

useCallback

create callbacks with runWithOwner, auto get current owner

reference from @solid-primitives/rootless

import { useCallback } from '@solid-hooks/core'

const handleClick = useCallback(() => {
  console.log('after 100 ms!')
})
setTimeOut(handleClick, 100)

useProps

Splits props object into two parts based on given keys.

import { accessProps, useProps } from '@solid-hooks/core'

function TestComponent(props: { name: string, age: number, role?: 'admin' | 'user' }) {
  const [picked, rest] = useProps(props, ['name', 'age'], { role: 'user' })
  picked.name() // 'John'
  rest.role() // 'user'
  accessProps(picked) // { name: 'John', age: 18 }
}

@solid-hooks/core/web

cls

[!WARNING] DEPRECATED, use cls-variant instead

merge classes, lightweight version of clsx

import { cls } from '@solid-hooks/core/web'

cls('foo', true && 'bar', false && ['bar', true && 'baz'], 1)
// => 'foo baz'

useHover

check if element is hovered

import { useHover } from '@solid-hooks/core/web'

function App() {
  let el
  const [hovered] = useHover(() => el)
  return <div ref={el}>{hovered() ? 'hovered' : 'not hovered'}</div>
}

useClickOutside

check if element is clicked outside

import { useClickOutside } from '@solid-hooks/core/web'

function App() {
  let el
  const [isClickOutside] = useClickOutside(() => el)
  return <div ref={el}>{isClickOutside() ? 'clicked outside' : 'clicked inside'}</div>
}

useLongPress

check if element is long pressed

import { useLongPress } from '@solid-hooks/core/web'

function App() {
  let el
  const [isLongPress] = useLongPress(() => el)
  return <div ref={el}>{isLongPress() ? 'long pressed' : 'not long pressed'}</div>
}

useTitle

reactive document title

import { useTitle } from '@solid-hooks/core/web'

const [title, setTitle] = useTitle()

// or with external signal
const [title, setTitle] = createSignal('')
useTitle(title)
setTitle('new title')

createObjectURL

convert blob / File / MediaSource / ArrayBuffer / ArrayBufferView / string to signal URL, auto revoke on cleanup

import { createObjectURL } from '@solid-hooks/core/web'

const [source, setMediaSource, cleanupSource] = createObjectURL(new MediaSource())
const [url, setURL, cleanupURL] = createObjectURL(new Uint8Array(8), { type: 'image/png' })

useWorkerFn

run function in worker, support local functions or external dependencies

reference from vueuse

import { useWebWorkerFn } from '@solid-hooks/core/web'
import { createMemo, createSignal } from 'solid-js'

const randomNumber = () => Math.trunc(Math.random() * 5_000_00)

function heavyTask() {
  const numbers: number[] = Array.from({ length: 5_000_000 }).fill(undefined).map(randomNumber)
  numbers.sort()
  return numbers.slice(0, 5)
}

export default function TestWorker() {
  const [fn, { status, terminate }] = useWebWorkerFn(heavyTask, { func: [randomNumber] })
  const isRunning = createMemo(() => status() === 'RUNNING')
  return (
    <>
      <div>Status: {status()}</div>
      <button onClick={() => isRunning() ? terminate() : fn().then(setData)}>
        {isRunning() ? 'terminate' : 'sort in worker'}
      </button>
    </>
  )
}

useExternal

load external CSS/JS

import { useExternal } from '@solid-hooks/core/web'

const script = 'console.log(`test load script`)'
const [scriptElement, cleanupScript] = useExternal('script', script, {/* options */})
const [styleElement, cleanupStyle] = useExternal('style', style, {/* options */})

useEventListener / useEventListenerStack / useDocumentListener / useWindowListener

auto cleanup event listener, allow nullish target

reference from @solid-primitives/event-listener

useMediaQuery

create media query signal

import { useMediaQuery, usePrefersDark } from '@solid-hooks/core/web'

const isLg = useMediaQuery('(min-width: 1024px)')
const isDark = usePrefersDark()

useColorMode

auto color mode with attribute toggle, disable transition by default

import { useColorMode } from '@solid-hooks/core/web'

export default function TestColorMode() {
  const [mode, setMode, isDark] = useColorMode()
  return (
    <>
      <div>{isDark() ? 'dark' : 'light'} theme</div>
      <div>{mode()}</div>
      <button onClick={() => setMode(m => m === 'dark' ? 'light' : 'dark')}>click</button>
    </>
  )
}

useNetwork

signals of network status, with onChanges callback

import { useNetwork } from '@solid-hooks/core/web'

const net = useNetwork()
const isOnline = net.online

types:

type NetworkType = 'bluetooth' | 'cellular' | 'ethernet' | 'none' | 'wifi' | 'wimax' | 'other' | 'unknown'

type EffectiveType = 'slow-2g' | '2g' | '3g' | '4g'
export type NetworkState = {
  /**
   * the time at which the connection was changed
   */
  since?: Date
  /**
   * whether the device is online
   */
  online?: boolean
  /**
   * the estimated effective round-trip time of the current connection
   */
  rtt?: number
  /**
   * type of connection a device is using to communicate with the network
   */
  type?: NetworkType
  /**
   * true if the user has set a reduced data usage option on the user agent
   */
  saveData?: boolean
  /**
   * the estimated effective bandwidth (Mb/s)
   */
  downlink?: number
  /**
   * maximum downlink speed (Mb/s)
   */
  downlinkMax?: number
  /**
   * the effective type of the connection
   */
  effectiveType?: EffectiveType
}

useIdleCallback

executes a callback using the requestIdleCallback API, fallback to setTimeout.

auto cleanup, return cleanup function.

see https://developer.mozilla.org/zh-CN/docs/Web/API/Background_Tasks_API

useCssVar

bind css variable to signal

import { useCssVar } from '@solid-hooks/core/web'

const [color, setColor] = createSignal('red')
useCssVar('bg', color)

useCopy / usePaste / createClipboardItem

hooks that paste from clipboard

import { createClipboardItem, useCopy, usePaste } from '@solid-hooks/web'

export default () => {
  const [data, setData] = createClipboardItem('test')
  const { isCopied, copy } = useCopy()

  const paste = usePaste({
    onPaste: (data, mime) => console.log(data, mime)
  })
  return (
    <>
      <div>is copied: {isCopied() ? 'true' : 'false'}</div>
      <button onClick={() => copy(data())}>copy</button>
      <button onClick={paste}>paste</button>
    </>
  )
}

License

MIT