slots-component
TypeScript icon, indicating that this package has built-in type declarations

0.1.3 • Public • Published

Slots Component

This package provides flexible types for writing highly customziable components that accepts slots. it adds slots and slotProps to your component props with full TypeScript support.

Using this package, you can write components that can be used like the following:

<List
  rows={data}
  slots={{
    Container: (props: { children: ReactNode }) => <div>{props.children}</div>,
  }}
  slotProps={{
    row: ({ name }) => ({ onClick: () => alert(name) }),
  }}
/>

You can pass another slot to replace the default or extra props.

See the example below to see how to write such a component.

Installation

You can install slots-components via npm:

npm i -D slots-components

Or using yarn:

yarn add slots-components

How to use it?

First you need to define your default slots

import { SlotsProps, Slots, SlotsConfigCreator } from 'slots-component';

const DEFAULT_SLOTS = {
  Container: 'ul',
  Row: 'li',
} satisfies Slots;

Then you need to define the config, if you want to pass extra values to your props, let's say we want to pass item to Row component:

interface TItem {
  id: string;
  name: string;
}

type SlotsConfig = SlotsCreator<typeof DEFAULT_SLOTS, {
  Row: [TItem]
}>

Now define your component:

interface Props {
  rows: TItem[];
}

export const List = <
  TSlots extends SlotsConfig["Slots"],
  >({ rows, slots, slotProps }: Props & SlotsProps<SlotsConfig, TSlots>) => {
  const combinedSlots = { ...DEFAULT_SLOTS, ...slots };

  return (
    <combinedSlots.Container {...slotProps?.container}>
      {rows.map((entity) => (
        <combinedSlots.Row
          key={row.id}
          {...(typeof slotProps?.row === 'function'
            ? slotProps?.row(entity)
            : slotProps?.row)}
        >
          {row.name}
        </combinedSlots.Row>
      ))}
    </combinedSlots.Container>
  );
};

Full example

import { SlotsProps, Slots, SlotsCreator } from 'slots-component';

const DEFAULT_SLOTS = {
  Container: 'ul',
  Row: 'li',
} satisfies Slots;

interface TItem {
  id: string;
  name: string;
}

type SlotsConfig = SlotsConfigCreator<typeof DEFAULT_SLOTS, {
  Row: [TItem];
}>

interface Props {
  rows: TItem[];
}

export const List = <
  TSlots extends SlotsConfig["Slots"],
  >({ rows, slots, slotProps }: Props & SlotsProps<SlotsConfig, TSlots>) => {
  const combinedSlots = {
    ...DEFAULT_SLOTS,
    ...slots,
  };

  return (
    <combinedSlots.Container {...slotProps?.container}>
      {rows.map((entity) => (
        <combinedSlots.Row
          key={row.id}
          {...(typeof slotProps?.row === 'function'
            ? slotProps?.row(entity)
            : slotProps?.row)}
        >
          {row.name}
        </combinedSlots.Row>
      ))}
    </combinedSlots.Container>
  );
};

Roadmap

  • [ ] Add CD
  • [ ] Write a simpler generic
  • [ ] Better documentation
  • [ ] Add example

Readme

Keywords

none

Package Sidebar

Install

npm i slots-component

Weekly Downloads

0

Version

0.1.3

License

MIT

Unpacked Size

11.4 kB

Total Files

10

Last publish

Collaborators

  • theabdollah