UNPKG

@solid-primitives/refs

Version:

Library of primitives, components and directives for SolidJS that help managing references to JSX elements.

196 lines (133 loc) 5.49 kB
<p> <img width="100%" src="https://assets.solidjs.com/banner?type=Primitives&background=tiles&project=Refs" alt="Solid Primitives Refs"> </p> # @solid-primitives/refs [![size](https://img.shields.io/bundlephobia/minzip/@solid-primitives/refs?style=for-the-badge&label=size)](https://bundlephobia.com/package/@solid-primitives/refs) [![version](https://img.shields.io/npm/v/@solid-primitives/refs?style=for-the-badge)](https://www.npmjs.com/package/@solid-primitives/refs) [![stage](https://img.shields.io/endpoint?style=for-the-badge&url=https%3A%2F%2Fraw.githubusercontent.com%2Fsolidjs-community%2Fsolid-primitives%2Fmain%2Fassets%2Fbadges%2Fstage-2.json)](https://github.com/solidjs-community/solid-primitives#contribution-process) Collection of primitives, components and directives that help managing references to JSX elements, keeping track of mounted/unmounted elements. ##### Primitives: - [`mergeRefs`](#mergerefs) - Utility for chaining multiple `ref` assignments with `props.ref` forwarding. - [`resolveElements`](#resolveelements) - Utility for resolving recursively nested JSX children to a single element or an array of elements. - [`resolveFirst`](#resolvefirst) - Utility for resolving recursively nested JSX children in search of the first element that matches a predicate. - [`<Refs>`](#refs) - Get up-to-date references of the multiple children elements. - [`<Ref>`](#ref) - Get up-to-date reference to a single child element. ## Installation ```bash npm install @solid-primitives/refs # or pnpm add @solid-primitives/refs # or yarn add @solid-primitives/refs ``` ## `mergeRefs` Utility for chaining multiple `ref` assignments with `props.ref` forwarding. ### How to use it ```tsx import { mergeRefs, Ref } from "@solid-primitives/refs"; interface ButtonProps { ref?: Ref<HTMLButtonElement>; } function Button(props: ButtonProps) { let ref: HTMLButtonElement | undefined; onMount(() => { // use the local ref }); return <button ref={mergeRefs(props.ref, el => (ref = el))} />; } // in consumer's component: let ref: HTMLButtonElement | undefined; <Button ref={ref} />; ``` ## `resolveElements` Utility for resolving recursively nested JSX children to a single element or an array of elements using a predicate. ### How to use it `resolveElements`'s API is similar to Solid's `children` helper. It accepts a function that returns JSX children and a predicate function that filters the elements. ```tsx function Button(props: ParentProps) { const children = resolveElements(() => props.children); // ^?: Accessor<Element | Element[] | null> return ( // Similarly to `children` helper, a `toArray` method is available <For each={children.toArray()}> {child => ( <div> {child.localName}: {child} </div> )} </For> ); } ``` ### Using a custom predicate The default predicate is `el => el instanceof Element`. You can provide a custom predicate to `resolveElements` to filter the elements. ```tsx const els = resolveElements( () => props.children, (el): el is HTMLDivElement => el instanceof HTMLDivElement, ); els(); // => HTMLDivElement | HTMLDivElement[] | null ``` On the server side the custom predicate will be ignored, but can be overridden by passing it as a third argument. The default predicate can be imported from `@solid-primitives/refs`: ```tsx import { defaultElementPredicate } from "@solid-primitives/refs"; ``` On the client it uses `instanceof Element` check, on the server it checks for the object with `t` property. (generated by compiling JSX) ## `resolveFirst` Utility for resolving recursively nested JSX children in search of the first element that matches a predicate. ### How to use it `resolveFirst` matches the API of [`resolveElements`](#resolveelements) but returns only the first element that matches the predicate. ```tsx function Button(props: ParentProps) { const child = resolveFirst(() => props.children); // ^?: Accessor<Element | null> return ( <div> {child()?.localName}: {child()} </div> ); } ``` `resolveFirst` also accepts a custom predicate as a second argument. See [`Using a custom predicate`](#using-a-custom-predicate) section for more details. ## `<Ref>` Get up-to-date reference to a single child element. ### How to use it `<Ref>` accepts only a `ref` property for getting the current element or `undefined`, and requires `children` to be passed in. ```tsx import { Ref } from "@solid-primitives/refs"; const [ref, setRef] = createSignal<Element | undefined>(); <Ref ref={setRef}>{props.children}</Ref>; ``` ## `<Refs>` Get up-to-date references of the multiple children elements. ### How to use it `<Refs>` accepts only a `ref` property for getting the current array of elements, and requires `children` to be passed in. ```tsx import { Refs } from "@solid-primitives/refs"; const [refs, setRefs] = createSignal<Element[]>([]); <Refs ref={setRefs}> <For each={my_list()}>{item => <div>{item}</div>}</For> <Show when={show()}> <div>Hello</div> </Show> </Refs>; ``` #### Demo https://stackblitz.com/edit/solid-vite-unocss-bkbgap?file=index.tsx (run `npm start` in the terminal) ## Types ### `Ref` Type for the `ref` prop ```ts export type Ref<T> = T | ((el: T) => void) | undefined; ``` ### `RefProps` Component properties with types for `ref` prop ```ts interface RefProps<T> { ref?: Ref<T>; } ``` ## Changelog See [CHANGELOG.md](./CHANGELOG.md)