0.2.4 • Published 6 months ago

inherited-component v0.2.4

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

Inherited Component

NPM version Build Status Test Coverage License PR Welcome

A set of utility functions that takes component reusing to a higher level. Inherited Component is the styled-component of the tailwind age.

Features

  • ✅ Classed component that works great with tailwind
  • ✅ Classed component with additional props
  • ✅ Inherited component with default prop values
  • ✅ Inherited component with additional props
  • ✅ Component inheritance
  • ✅ Supports hooks inside the function body
  • ✅ Component transformers that works great with headless components
  • ✅ Type-strict, a higher level of type-safe

Installation

Install inherited-component simply with this command. No transpiling plugins required.

npm i inherited-component

Usage

Define a intrinsic classed component

Define a component which behaves just like the intrinsic component with predefined classes in one line.

import { classed } from 'inherited-component'

const Container = classed.div`container max-sm:px-4 mx-auto`

Inherit a component with additional classes

Take a component which may or may not have class names, create a new component by appending more classes on it. The other props and hooks are preserved. The newly created component takes any parameter that the previous component accepts.

Note: The wrapped component should accept className property.

import { classed } from 'inherited-component'

const FlexContainer = classed(Container)`flex flex-col`

Define a intrinsic classed component with custom props

Define a classed component with dynamic classes calculated from additional props. The type checker helps you to remove the additional properties in case of passing it to the underlying component.

import { classed } from 'inherited-component'

const Button = classed.button<{ variant: "m" | "l" }>(
  ({ variant = "m" }) => `${variant === 'm' ? 'text-xl' : 'text-2xl'}`,
  { unforwardableProps: ['variant'] })

Inherit a component with classes from custom props

This works with custom components in the same way, too. Just wrap the original component in a pair of parens.

import { classed } from 'inherited-component'

const Button = classed(BaseButton)<{ variant: "m" | "l" }>(
  ({ variant = "m" }) => `${variant === 'm' ? 'text-xl' : 'text-2xl'}`,
  { unforwardableProps: ['variant'] })

Define a intrinsic component with custom attributes

With inherited, any properties can be merged and passed down. Use dot syntax for intrinsic components.

import { inherited } from 'inherited-component'

const Input = inherited.input({
  className: "outline-none border-1 border-black border-solid",
  disabled: true
})

Inherit a component with custom attributes

Inherited component can inherit any component, not only intrinsic ones.

import { inherited } from 'inherited-component'

const Input = inherited(BaseInput)({
  className: "outline-none border-1 border-black border-solid",
  disabled: true
})

Define a intrinsic inherited component with attributes from custom props

Like its counterpart classed, inherited works with additional props. Don't forget to prevent the undesired props from passing down.

import { inherited } from 'inherited-component'

const Button = inherited.button<{ variant: "m" | "l" }>(
  ({ variant = "m" }) => ({
    className: `${props.variant === 'm' ? 'text-xl' : 'text-2xl'}`,
    disabled: true
  }),
  { unforwardableProps: ['variant'] })

Inherit a component with attributes from custom props

The same works for any component. You can even put hooks inside the function body.

import { inherited } from 'inherited-component'

const Button = inherited(Button)<{ variant: "m" | "l" }>(
  ({ variant = "m" }) => ({
    className: `${props.variant === 'm' ? 'text-xl' : 'text-2xl'}`,
    disabled: true
  }),
  { unforwardableProps: ['variant'] })

Define a reusable transformer with predefined classes

In some cases, we want different components to look the same. For example, we may want a, button and some headless components to look and feel the same in a header. Then simply do this. The withClasses takes the same parameters as the classed function.

import { withClasses } from 'inherited-component'

const intoHeaderButton = withClasses`
  hover:bg-gray-100 dark:hover:bg-gray-900 rounded-xl p-2 cursor-pointer
`

const HeaderButton = intoHeaderButton.button
const HeaderLink = intoHeaderButton(Link)
const HeaderDropdownTrigger = intoHeaderButton(DropdownTrigger)

Define a reusable transformer with predefined properties

withProps is a more generic alternative to the withClasses counterpart. It allows class name and other properties to be set. It takes the same parameters as inherited.

import { withProps } from 'inherited-component'

const intoDefaultDisabled = withProps({ disable: true })

const DefaultDisabledButton = intoDefaultDisabled.button
const DefaultDisabledInput = intoDefaultDisabled.input
const DefaultDisabledSwitch = intoDefaultDisabled(Switch)

Props Passing

Just like styled-component, props are merged and passed down by default. To prevent unexpected props being passed down, we enforce you to declare unforwardable props.

Unforwardable Props

Pass a list of prop names which shouldn't be passed down.

import { inherited } from 'inherited-component'

const Button = inherited(Button)<{ variant: "m" | "l" }>(
  ({ variant = "m" }) => ({
    className: `${props.variant === 'm' ? 'text-xl' : 'text-2xl'}`,
    disabled: true
  }),
  { unforwardableProps: ['variant'] })

Editor Config

By adding this script to your settings.json in the workspace or globally, you can set the regex for the classed method to match the class names and provide intellisense.

{
  "tailwindCSS.experimental.classRegex": [
    ["classed(?:\\.\\w*)?\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
  ]
}

License

This package is an open-sourced software licensed under the MIT License.

Contributing

Issues and PRs are obviously welcomed and encouraged, for bug fixing, more accurate type definitions, new features as well as documentation.

0.2.4

6 months ago

0.2.3

6 months ago

0.2.2

6 months ago

0.2.1

6 months ago

0.2.0

6 months ago

0.1.2

6 months ago

0.1.1

6 months ago

0.0.12

6 months ago

0.0.11

6 months ago

0.0.10

6 months ago

0.0.9

6 months ago

0.0.8

6 months ago

0.0.7

6 months ago

0.0.6

6 months ago

0.0.5

6 months ago

0.0.4

6 months ago

0.0.3

6 months ago

0.0.2

6 months ago

0.0.1

6 months ago