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

storybook-react-utils

v1.0.32

Published

[![codecov](https://codecov.io/gh/i-oktav-i/storybook-react-utils/branch/master/graph/badge.svg)](https://codecov.io/gh/i-oktav-i/storybook-react-utils) [![GitHub license](https://img.shields.io/github/license/i-oktav-i/storybook-react-utils)](https://git

Downloads

54

Readme

storybook-react-utils

codecov GitHub license npm npm

This package provides:

How to use

// Component.jsx
import { VFC } from 'react'

export type ComponentProps = {
  /* Component props */
}

export const Component: VFC<ComponentProps> = () => {
  /* your component code */
};

// Component.stories.jsx
import { Meta } from '@storybook/react';
import { getStoryCreator } from 'storybook-react-utils';
import { Component, ComponentProps } from './Component';

const componentMeta: Meta<SubstrateProps> = {
  component: Substrate,
  title:     'Util Components / Substrate',
};

export default componentMeta;

/* Init story creator */
const getStory = getStoryCreator(
  Component,
  { /* Default story config (optional) */
    args: {
      /* default args */
    },
    argTypes: {
      /* default args types */
    },
    /* ... Other story and stories plugins attributes */
  },
  "ComponentDisplayName" /* Display name (optional) */
);

/* Create story */
export const ComponentStory = getStory({
  /* Story config (optional) */
  /* Will be merged with default config */
});

/* Create another story */
export const AnotherComponentStory = getStory({
  /* Another story config (optional) */
  /* Will be merged with default config */
});

Wrappers

storybook-react-utils provides one story wrapper and wrappers creator for dispatching store actions with story controls

Provides containerWidth and containerHeight story controls for stretchable components.
Сan also get the containerStyles prop

import {
  containerWrapper,
  containerWrapperArgTypes,
  getStoryCreator,
} from 'storybook-react-utils';

import { Component } from './Component';

const wrapped = containerWrapper(Component)

const getStory = getStoryCreator(wrapped, {
  argTypes: {
    ...containerWrapperArgTypes, /* Default wrapper controls config */
    /* Equals to
    containerWidth: {
      defaultValue: 300,
      control:      {
        type: 'range',
        min:  0,
        max:  1000,
      },
      description: 'Not component property',
    },
    containerHeight: {
      defaultValue: 200,
      control:      {
        type: 'range',
        min:  0,
        max:  1000,
      },
      description: 'Not component property',
    },
    containerStyles: {
      table: { disable: true },
    }, */
  }
});

Creates a wrapper with which you can change the store state

import { getStorePropertyWrapper } from 'storybook-react-utils';

const isMobile = getStorePropertyWrapper(
  'isMobile', /* Prop/Control name */
  setIsMobile, /* function that returns action or thunk action */
  false, /* if provided dispatch(setIsMobile(false)) will be called on unmount (optional) */
);

Creates wrapper and argsTypes for css variable. By default controls type is {type: 'text'}, another control config can be provided with second argument

import {
  getCssVarWrapper,
  getStoryCreator,
} from 'storybook-react-utils';
import { Component } from './Component';

const [paddingWrapper, paddingWrapperArgType] = getCssVarWrapper('--my-padding-var'/*, {
  type: 'range',
  min: 1,
  max: 3,
  step: 1,
}*/);

const wrapped = paddingWrapper(Component)

const getStory = getStoryCreator(wrapped, {
  argType: {
    ...paddingWrapperArgType,
  },
});

Creates a wrapper for components that have two-way data bindings If the value is changed using the control panel, it will be overwritten

/* Component.tsx */
type ComponentProps = {
  inputValue: string
  onInput: (newValue: string) => void
}

export const Component: VFC<ComponentProps> = ({
  inputValue,
  onInput,
}) => {
  return (
    <input
      value={inputValue}
      onInput={onInput}
    />
  );
};

/* Component.stories.tsx */
import { getValueControlWrapper, getStoryCreator } from 'storybook-react-utils';
import { Component } from './Component';

// Some code

const valueControlWrapper = getValueControlWrapper(
  'inputValue', /* default value - 'value' */
  'onInput', /* default value - 'onChange' */
);

const wrapped = valueControlWrapper(Component);
const getStory = getStoryCreator(wrapped);

export const Default = getStory();

Creates a wrapper that replace prop with boolean prop, and apply provided value when it's true of undefined when it's false

import {
  getPropApplicatorWrapper,
  getStoryCreator,
} from 'storybook-react-utils';
import { Component } from './Component';

const iconApplicator = getPropApplicatorWrapper('icon', (
  <div>
    icon
  </div>
));

const wrapped = iconApplicator(Component);

const getStory = getStoryCreator(wrapped);

export const Default = getStory({args: {icon: true}});

Provides ref prop into component. Need when create stories for forwardRef(Comp)

import {
  refWrapper,
  getStoryCreator,
} from 'storybook-react-utils';

const Comp = forwardRef<
  HTMLInputElement,
  {}
>((props, ref) => <input ref={ref} />);

const wrapped = refWrapper(TestComp);

const getStory = getStoryCreator(wrapped);
const Default = getStory();

This wrapper replace object prop with its fields (can be proxied). NOTE: because of typing restrictions, it is required to call the function twice. First time without arguments and with generic param to provide typings, and second time just with arguments.

/* ./Component.tsx */
import { VFC } from 'react';

export type ComponentProps = {
  objProp: {
    first: string
    second: number
    third: boolean
  }
  third: any
}

export const Component: VFC<ComponentProps> = props => {/* code */};

/* ./Component.stories.tsx */
import {
  getStoryCreator,
  getPropFlatterWrapper,
} from 'storybook-react-utils';

import { Component, ComponentProps } from './Component';

const objPropWrapper = getPropFlatterWrapper<ComponentProps['objProp']>()(
  'objProp', /* name of prop, that need to replace */
  {
    first: true, /* in controls will have same name */
    second: true,
    third: 'objProp.third', /* in controls with have 'thirdProxy' to avoid identical names  */
  },
);

const wrapped = objPropWrapper(Component);
const getStory = getStoryCreator(wrapped, {
  args: {
    first: '',
    second: 0,
    'objProp.third': true,
    third: {},
  }
});

Do not forget, that getPropFlatterWrapper can be used with getValueControlWrapper, getPropApplicatorWrapper and on object in object


/* ./Component.tsx */
import { VFC } from 'react';

type Data = {
  first: string
  second: number
  thirdObj: {
    innerFirst: string
    innerSecond: string
  }
}
export type ComponentProps = {
  value: Data
  onChange: (newValue: Data) => void
}

export const Component: VFC<ComponentProps> = props => {/* code */};


/* ./Component.stories.tsx */
import {
  getStoryCreator,
  getPropFlatterWrapper,
  getValueControlWrapper,
  compose,
} from 'storybook-react-utils';
import { Component, ComponentProps } from './Component';

const valueWrapper = getPropFlatterWrapper<ComponentProps['value']>()('value', {
  first: 'value.first',
  second: 'value.second',
  thirdObj: 'value.thirdObj',
});

const valueThirdObjWrapper = getPropFlatterWrapper<ComponentProps['value']['thirdObj']>()(
  'value.thirdObj', 
  {
    innerFirst: 'value.thirdObj.innerFirst',
    innerSecond: 'value.thirdObj.innerSecond',
  },
);

const wrapped = compose(
  /* Do not forget, this is order sensitive */
  getValueControlWrapper(),
  valueWrapper,
  valueThirdObjWrapper,
)(Component);

creates wrapper that gets value from redux store and provide into a component as prop

import { getSelectorWrapper } from 'storybook-react-utils';
import { Component } from './Component';

const valueWrapper = getSelectorWrapper(
  'propName', /* Name of prop to provide stored value */
  (store/*: AppStore */) => store.value, /* getter from store, provides into useSelector */
);

const wrapped = valueWrapper(Component);

This function compose wrappers into one

import { compose } from 'storybook-react-utils';
import { Component } from './Component';

// Some code

const wrapped = compose(
  wrapper1,
  wrapper2,
  wrapper3,
  wrapper4,
  // ...
)(Component)

type Wrapper

Type of wrapper function to enhance props types for controls addon

import { Wrapper } from 'storybook-react-utils';

type MyWrapperProps = {
  /* Wrapper props */
}

type PropsToOmit = 'prop1' | 'prop2'

const myWrapper: Wrapper<
  MyWrapperProps, 
  /* PropsToOmit, // if need to omit props */
> = (
  Elem // Component to wrap
) => (
  props // will be equal tp (Omit<ComponentProps<typeof Elem>, PropsToOmit> & MyWrapperProps)
) => {
  /* Code here */

  return (
    /* Additional elements and containers */
    <Elem {...props}>
  );
}

Exported types


export type {
  Wrapper, /* Type for wrapper function */
  StoryConfig, /* Story config type */
  StoryArgTypes, /* Story config argTypes filed type */
  ArgTypesControl, /* Type of control field in argTypes */
  ControlType, /* Union of control type (except null) */
  ControlsOptions, /* Map of ControlType and addition options  */
};

TODO

  • Allow provide forwardRef() components as wrapper argument