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-hooks/core

v0.2.3

Published

useful hooks for solid.js

Downloads

237

Readme

@solid-hooks/core

useful hooks for solid.js

Install

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

Usage

createReactive

make plain object props reactive

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

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

createDirective

another way to create directive

import { createDirective } from '@solid-hooks/core'
import { type Accessor, type Setter, 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 { throttle } from '@solid-primitives/scheduled'
import { watch } from '@solid-hooks/core'

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, (value))

watchInstant

like watch, use createComputed

watchRendered

like watch, use createRendered

useEmits

like defineEmit in Vue, emit event from child component, auto handle optional prop

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

// must start with `$`
type Emits = {
  $var: (num: number) => void
  $update: (d1: string, d2?: string, d3?: string) => void
  $optional?: (data: { test: number }) => void
}

type BaseProps = { num: number }

function Child(props: Emits & BaseProps) {
  const { emit, createEmitSignal } = useEmits<Emits>(props)

  // auto emit after value changing, like `defineModel` in Vue
  const [variable, setVariable] = createEmitSignal('var', 1)
  const handleClick = () => {
    setVariable(v => v + 1)

    // manully emit
    emit('update', `emit from child: ${props.num}`, 'second')
    emit('optional', { test: 1 })
  }
  return (
    <div>
      child: {props.num}
      <button onClick={handleClick}>+</button>
    </div>
  )
}
function Father() {
  const [count] = createSignal('init')
  return (
    <Child
      num={count()}
      $update={console.log}
      $var={e => console.log('useEmits:', e)}
    />
  )
}

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

object style useContext and Provider

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

reference from @solid-primitives/context

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

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 class="btn" onClick={increment}>
        {count()}
      </button>
    </>
  )
}

export function TestContextProvider() {
  console.log('call useTestContext() outside provider:', useTestContext())
  return (
    <>
      <h1>Test <code>createContextProvider</code> :</h1>
      <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)

withEffect

add callback for setter

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

export function TestWithEffect() {
  // eslint-disable-next-line solid/reactivity
  const [count, setCount] = withEffect(createSignal(1), value => console.log('[withEffect] value:', value))
  return (
    <>
      <h1>Test <code>withEffect</code> :</h1>
      <button onClick={() => setCount(c => c + 1)}>click and see console</button>
      <div>count: {count()}</div>
    </>
  )
}

@solid-hooks/core/web

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

reference from vueuse

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

function heavyTask() {
  const randomNumber = () => Math.trunc(Math.random() * 5_000_00)
  const numbers: number[] = Array(5_000_000).fill(undefined).map(randomNumber)
  numbers.sort()
  return numbers.slice(0, 5)
}

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

useResourceTag

load external CSS/JS

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

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

useEventListener / useEventListenerStack / useDocumentListener / useWindowListener

auto cleanup event listener

use @solid-primitives/event-listener

useDark

auto color mode with attribute toggle, disable transition by default

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

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

useNetwork / useOnline

signals of network status, with onChanges callback

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)

License

MIT