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

@beqa/react-slots

v1.1.3

Published

The react-slots runtime library

Downloads

110

Readme

beqa/react-slots - Responsible React Parenting

react-slots empowers you to prioritize composability in your component APIs.

Featuring

  • Lightweight (< 8KB minified, < 3KB minified & gzipped)
  • Composability with ease
  • Type-safety
  • Server Components support
  • Not implemented with context
  • Intuitive API
  • Self-documenting with typescript
  • Elegant solution to a11y attributes
  • Inversion of control

Installation

The installation process consists of two parts: installing the core library (around 3KB gzipped piece of code that runs in your users' browsers and handles the core logic) and an optional compile-time plugin (for transpiling JSX syntax for your slot elements into regular function invocations).

Installation steps

Docs

You can find the docs on the docs website

Discord

If you need any assistance, feel free to join our Discord server

Implementing

import { useSlot, SlotChildren, Slot } from "@beqa/react-slots";

type ListItemProps = {
  children: SlotChildren<
    | Slot<"title"> // Shorthand of Slot<"title", {}>
    | Slot<"thumbnail"> // Shorthand of Slot<"thumbnail", {}>
    | Slot<{ isExpanded: boolean }> // Shorthand of Slot<"default", {isExpanded: boolean}>
  >;
};

function ListItem({ children }: ListItemProps) {
  const { slot } = useSlot(children);
  const [isExpanded, setIsExpanded] = useState();

  return (
    <li
      className={`${isExpanded ? "expanded" : "collapsed"}`}
      onClick={() => setIsExpanded(!isExpanded)}
    >
      {/* Render thumbnail if provided, otherwise nothing*/}
      <slot.thumbnail />
      <div>
        {/* Render a fallback if title is not provided*/}
        <slot.title>Expand for more</slot.title>
        {/* Render the description and pass the prop up to the parent */}
        <slot.default isExpanded={isExpanded} />
      </div>
    </li>
  );
}

Specifying Slot Content From the Parent

With slot-name attribute

<ListItem>
  <img slot-name="thumbnail" src="..." />
  <div slot-name="title">A title</div>
  this is a description
</ListItem>

With Templates

import { template } from "beqa/react-slots";

<ListItem>
  <template.thumbnail>
    <img src=".." />
  </template.thumbnail>
  <template.title>A title</template.title>
  <template.default>
    {({ isExpanded }) =>
      isExpanded ? <strong>A description</strong> : "A description"
    }
  </template.default>
  <template.default>doesn't have to be a function</template.default>
</ListItem>;

With type-safe templates

// Option #1
import { createTemplate } from "@beqa/react-slots";
const template = createTemplate<ListItemProps["children"]>();

// Option #2
import { template, CreateTemplate } from "@beqa/react-slots";
const template = template as CreateTemplate<ListItemProps["children"]>;

// Typo-free and auto-complete for props!
<ListItem>
  <template.thumbnail>
    <img src="..." />
  </template.thumbnail>
  <template.title>A title</template.title>
  <template.default>
    {({ isExpanded }) =>
      isExpanded ? <strong>A description</strong> : "A description"
    }
  </template.default>
  <template.default>doesn't have to be a function</template.default>
</ListItem>;

Advanced Examples

| The code samples below represent actual implementations. No need to define external state or event handlers for these components to function. | | --------------------------------------------------------------------------------------------------------------------------------------------- |

Creating highly composable Accordion and AccordionList components using react-slots

Checkout live example

<AccordionList>
  <Accordion key={1}>
    <span slot-name="summary">First Accordion</span>
    This part of Accordion is hidden
  </Accordion>
  <Accordion key={2}>
    <span slot-name="summary">Second Accordion</span>
    AccordionList makes it so that only one Accordion is open at a time
  </Accordion>
  <Accordion key={3}>
    <span slot-name="summary">Third Accordion</span>
    No external state required
  </Accordion>
</AccordionList>

Creating highly composable Dialog and DialogTrigger components using react-slots

Checkout live example

<DialogTrigger>
  <Button>Trigger Dialog</Button>
  <Dialog slot-name="dialog">
    <span slot-name="title">Look Ma, No External State</span>
    <p slot-name="content">... And no event handlers.</p>
    <p slot-name="content">Closes automatically on button click.</p>
    <p slot-name="content">Can work with external state if desired.</p>
    <Button
      slot-name="secondary"
      onClick={() => alert("But how are the button variants different?")}
    >
      Close??
    </Button>
    <Button slot-name="primary">Close!</Button>
  </Dialog>
</DialogTrigger>

If you like this project please show support by starring it on Github