Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-customize-token-input

Package Overview
Dependencies
Maintainers
1
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-customize-token-input

A react token (tag) input component. Allow customize data structure and Look & Feel

  • 2.0.0-beta.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
636
decreased by-66.13%
Maintainers
1
Weekly downloads
 
Created
Source

React TokenInput build status Coverage Status

NPM

Live Demo: https://seawind543.github.io/react-token-input/

React TokenInput (react-customize-token-input)

A react token (tag) controlled input component, which support:

  • Accept customize data structure.
  • Customize token (tag) Look & Feel on the label Demo, delete button Demo, or even override the whole Token component Demo.
  • Customize separate characters to separate the end-user input string. Demo
  • Inline editing on exist token.
  • Paste values. Demo
  • Preprocessing function to normalized user input value. It could be helpful to reproduce a single value into multiple values too. Demo
  • Validate function.

Installation

  1. Install the latest version of react and react-customize-token-input:
yarn add react react-customize-token-input
  1. At this point you can import react-customize-token-input and its styles in your application by:
import TokenInput from 'react-customize-token-input';

// Be sure to include styles at some point, probably during your bootstraping
import 'react-customize-token-input/dist/react-customize-token-input.css';

// Could find the not minimize version to easily customize style from:
// 'react-customize-token-input/dist/react-customize-token-input.original.css';

Dev

  1. Run yarn install to install required packages.
  2. Run yarn dev to launch webpack-dev-server.
  3. After step 2, you will see following message output in command console.
「wds」: Project is running at http://0.0.0.0:8000/
「wds」: webpack output is served from /
「wds」: Content not from webpack is served from ../docs

Note: To stop the program, just type ctrl + c in command console.

  1. After step 3 complete, you could access http://localhost:8000/ to see result.

Usage

See Live Examples: https://seawind543.github.io/react-token-input/

Note: Sources code of Examples in the folder examples

Props

type Props<ValueType, ErrorType> = {
  /**
   * For assign style to the TokenInput
   */
  style?: CSSProperties;

  /**
   * For assign class to the TokenInput
   */
  className?: string;

  /**
   * For set placeholder to the TokenInput
   */
  placeholder?: string;

  /**
   * To specific TokenInput is `readOnly` mode or not
   * @default false
   */
  readOnly?: boolean;

  /**
   * To specific TokenInput should be autoFocus or not
   * @default false
   */
  autoFocus?: boolean;

  /**
   * The array of tokenValue of TokenInput.
   * This array will be used to render the tokens.
   *
   * Type: ValueType
   * Description:
   * Customize data structure data
   * Could be string | number | object | customize data structure...etc.
   */
  tokenValues: ValueType[];

  // TokenCreator props

  /**
   * An array of characters to split the user input string into array.
   * For example,
   * Split the user input string `abc;def` into `['abc', 'def']`
   * by separators `[';']`
   *
   * Note:
   * It take the `String.prototype.split()` and `RegExp` to split the user input string.
   * Make sure your customized separators could be used with `RegExp`.
   * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
   */
  separators?: TokenSeparator[];

  /**
   * [Beta; Might be change in the future version]
   * Current only apply to the `TokenCreator`
   *
   * The settings to control the behavior of specials keyDown's event handler.
   * Recommend to use the build-in constant `KEY_DOWN_HANDLER_CONFIG_OPTION` to config the setting.
   *
   * `KEY_DOWN_HANDLER_CONFIG_OPTION.OFF` means turn `off`
   * (Took native browser behavior. The TokenInput should NOT handle it).
   *
   * `KEY_DOWN_HANDLER_CONFIG_OPTION.ON` means apply TokenInput predefined event handler.
   *
   * Default setting as below.
   * specialKeyDown: {
   *   onBackspace: KEY_DOWN_HANDLER_CONFIG_OPTION.ON,
   *   onTab: KEY_DOWN_HANDLER_CONFIG_OPTION.OFF,
   *   onEnter: KEY_DOWN_HANDLER_CONFIG_OPTION.ON,
   *   onEscape: KEY_DOWN_HANDLER_CONFIG_OPTION.ON,
   * },
   */
  specialKeyDown?: SpecialKeyDownConfig;

  /**
   * A callback function invoked when end-user typing but not become token yet
   *
   * onInputValueChange(newValue, previousValue)
   *
   * @ newValue
   * Type: InputString
   * Description: end-user's input string
   *
   * @ previousValue
   * Type: InputString
   * Description: previous end-user's input string
   */
  onInputValueChange?: OnInputValueChange;

  /**
   * A callback function to `preprocessing` the user input string.
   *
   * Note: This function execute after `split by TokenSeparator[]` but before `onBuildTokenValue`
   * inputString -> spilt(inputString) -> preprocess(spilt(inputString)) -> onBuildTokenValue(preprocess(spilt(inputString)))
   *
   * [Use case 1]
   *  Make your normalize process in this function, such as `String.prototype.trim()`.
   *
   * [Use case 2]
   * Sometimes, we will want to auto-fit the user input, this function could help with it.
   * For example, the user input string is `www.google.com`,
   * and we want to auto-fit it into `http://www.google.com` and `https://www.google.com`.
   *
   * onPreprocess(inputStringValues)
   *
   * @ inputStringValues
   * Type: InputString[]
   * Description:
   * The user input string values // (split by the `separators`)
   *
   * @ return
   * Type: InputString[]
   * Description: The values after preprocess
   */
  onPreprocess?: OnPreprocess;

  /**
   * A callback function to validate a tokenValue
   * (The returned result will be use by `onGetTokenErrorMessage`)
   *
   * onTokenValueValidate(tokenValue, tokenIndex, tokenValues)
   *
   * @ tokenValue
   * Type: ValueType
   * Description: The tokenValue build by `onBuildTokenValue`
   *
   * @ tokenIndex
   * Type: number
   * Description: The array index of this tokenValue in tokenValues
   *
   * @ tokenValues
   * Type: ValueType[]
   * Description: The array of tokenValue of TokenInput
   *
   * @ return
   * Type: TokenMeta<ErrorType>['error']
   * Description:
   * The customize error.
   * Specific the token's validate status or errorMessage.
   * Could be `an error message` to display, or an error object for further operations.
   *
   * Return `Nullish` types means the token is valid.
   */
  onTokenValueValidate?: OnTokenValueValidate<ValueType, ErrorType>;

  // Token props

  /**
   * A callback function invoked when tokenValues update
   *
   * onTokenValuesChange(modifiedTokenValues)
   *
   * @ modifiedTokenValues
   * Type: ValueType[]
   * Description: the new tokenValues
   */
  onTokenValuesChange?: OnTokenValuesChange<ValueType>;

  /**
   * A callback function to building `user input string value` into
   * the `tokenValue` (customize data structure).
   *
   * Note: You could make your normalize process in this function too.
   *
   * onBuildTokenValue(inputString)
   *
   * @ inputString
   * Type: InputString
   * Description: The user input value // (A value split by TokenSeparator[])
   *
   * @ return
   * Type: ValueType
   * Description:
   * Customize data structure data
   * Could be string | number | object | customize data structure...etc.
   */
  onBuildTokenValue?: OnBuildTokenValue<ValueType>;

  /**
   * A customize react functional component to rendering a token
   * Apply this to customize all token function.
   *
   * customizeTokenComponent={MyToken}
   */
  // TODO: make detail type for props
  customizeTokenComponent?: FunctionComponent<TokenProps<ValueType, ErrorType>>;

  /**
   * A callback function to getting customizes `className` to set on a `token`
   *
   * onGetTokenClassName(tokenValue, tokenMeta)
   *
   * @ tokenValue
   * Type: ValueType
   * Description: The tokenValue build by `onBuildTokenValue`
   *
   * @ tokenMeta
   * Type: TokenMeta<ErrorType>
   * Description: token's meta data
   *
   * @ return
   * Type: string
   * Description: The customizes className
   */
  onGetTokenClassName?: OnGetTokenClassName<ValueType, ErrorType>;

  /**
   * A callback function to getting displayable `label` of a token
   * Apply this to customize the token's content
   * For example, render token with `icon` or `Additional text`
   *
   * onGetTokenDisplayLabel(tokenValue, tokenMeta)
   *
   * @ tokenValue
   * Type: ValueType
   * Description: The tokenValue build by `onBuildTokenValue`
   *
   * @ tokenMeta
   * Type: TokenMeta<ErrorType>
   * Description: token's meta data
   *
   * @ return
   * Type: InputString | ReactNode
   * Description: The token's content.
   * By default, will apply `getDefaultTokenEditableValue`
   */
  onGetTokenDisplayLabel?: OnGetTokenDisplayLabel<ValueType, ErrorType>;

  /**
   * A callback function to render content of the delete button of token
   * Apply this to customize the token's content of the delete button
   * For example, replace the build-in `x` by Google font material-icons
   *
   * onRenderTokenDeleteButtonContent()
   *
   * @ return
   * Type: ReactNode
   * Description: The content of the delete button of the token.
   * By default, TokenInput render a build-in `x` icon
   */
  onRenderTokenDeleteButtonContent?: OnRenderTokenDeleteButtonContent;

  /**
   * A callback function to determine whether the token is `inline editable`.
   * By default, TokenInput will render a `inline editable` token.
   *
   * onGetIsTokenEditable(tokenValue, tokenMeta)
   *
   * @ tokenValue
   * Type: ValueType
   * Description: The tokenValue build by `onBuildTokenValue`
   *
   * @ tokenMeta
   * Type: TokenMeta<ErrorType>
   * Description: token's meta data
   *
   * @ return
   * Type: boolean
   * Description: `true` if editable. `false` if not.
   */
  onGetIsTokenEditable?: OnGetIsTokenEditable<ValueType, ErrorType>;

  /**
   * A callback function to getting `string input value`
   * from `tokenValue` for the end-user to perform `inline edit`
   *
   * onGetTokenEditableValue(tokenValue, tokenMeta)
   *
   * @ tokenValue
   * Type: ValueType
   * Description: The tokenValue build by `onBuildTokenValue`
   *
   * @ tokenMeta
   * Type: TokenMeta<ErrorType>
   * Description: token's meta data
   *
   * @ return
   * Type: InputString
   * Description: The value for end-user to `edit` in an input field
   */
  onGetTokenEditableValue?: OnGetTokenEditableValue<ValueType, ErrorType>;

  /**
   * A callback function to getting the error message from the customize error
   * The `customize error` is generate by `onTokenValueValidate`
   *
   * onGetTokenErrorMessage(tokenValue, tokenMeta)
   *
   * @ tokenValue
   * Type: ValueType
   * Description: The tokenValue build by `onBuildTokenValue`
   *
   * @ tokenMeta
   * Type: TokenMeta<ErrorType>
   * Description: token's meta data
   *
   * @ return
   * Type: Nullish | ErrorType
   * Description: The error message to describe an invalid token
   */
  onGetTokenErrorMessage?: OnGetTokenErrorMessage<ValueType, ErrorType>;
};

Predefined KeyDown Event Handlers

TokenInput has the following Predefined KeyDown event handlers.

For Token Create

KeyDownDescriptionNote
BackspaceIn case the current inputValue is an empty string, the latest token in the list tail will be deleted.
EscapeClear the input-box's value.A.K.A. Reset.
EnterCreate a token with the inputValue and continually focused on the inputBox for the next inputting.
TabSame as onEnter.
  • Default not apply
  • Under Beta

For Inline editing

KeyDownDescriptionNote
EscapeEnd editing without change the value of the token.A.K.A. Reset
EnterEnd editing and apply the new value. In case the new value is an empty string, will perform the onEscape.

Default value of the optional Props

    style = undefined,
    className = undefined,
    placeholder = undefined,
    readOnly = false,
    autoFocus = false,

    // TokenCreator
    separators = DEFAULT_SEPARATORS,
    /*
    [
      ',',
      ';',
      '\n', // for copy and paste
      '\r', // for copy and paste
      '\r\n', // for copy and paste
    ];
    */

    specialKeyDown = DEFAULT_SPECIAL_KEY_DOWN_CONFIG,
    /*
    {
      onBackspace: KEY_DOWN_HANDLER_CONFIG_OPTION.ON,
      onTab: KEY_DOWN_HANDLER_CONFIG_OPTION.OFF,
      onEnter: KEY_DOWN_HANDLER_CONFIG_OPTION.ON,
      onEscape: KEY_DOWN_HANDLER_CONFIG_OPTION.ON,
    },
    */

    onInputValueChange = undefined,
    onPreprocess = undefined,

    onTokenValueValidate = defaultTokenValueValidate,

    onTokenValuesChange = undefined,

    // Token
    onBuildTokenValue = defaultBuildTokenValue,

    customizeTokenComponent = undefined,
    onGetTokenClassName = undefined,

    onGetTokenDisplayLabel = defaultGetTokenEditableValue,

    onRenderTokenDeleteButtonContent = undefined,

    onGetIsTokenEditable = defaultGetIsTokenEditable,
    onGetTokenEditableValue = defaultGetTokenEditableValue,
    onGetTokenErrorMessage = defaultGetTokenErrorMessage,

Props of customizeTokenComponent

Your CustomizeTokenComponent will receive these props from the TokenInput. You could decide where & how to use them to Customize your Token component.

Could also reference this Example Demo and its source code ExampleCustomizeToken from the folder examples.

export type Props<ValueType, ErrorType> = {
  /**
   * Same as props of TokenInput
   */
  readOnly: boolean;

  tokenValue: ValueType;
  tokenMeta: TokenMeta<ErrorType>;

  /**
   * Same as props `onGetTokenClassName` of TokenInput
   */
  onGetClassName?: OnGetTokenClassName<ValueType, ErrorType>;

  /**
   * Same as props `onGetTokenDisplayLabel` of TokenInput
   */
  onGetDisplayLabel: OnGetTokenDisplayLabel<ValueType, ErrorType>;

  /**
   * Same as props `onRenderTokenDeleteButtonContent` of TokenInput
   */
  onRenderDeleteButtonContent?: OnRenderTokenDeleteButtonContent;

  /**
   * Same as props `onGetIsTokenEditable` of TokenInput
   */
  onGetIsEditable: OnGetIsTokenEditable<ValueType, ErrorType>;
  /**
   * Same as props `onGetTokenEditableValue` of TokenInput
   */
  onGetEditableValue: OnGetTokenEditableValue<ValueType, ErrorType>;
  /**
   * Same as props `onBuildTokenValue` of TokenInput
   */
  onBuildTokenValue: OnBuildTokenValue<ValueType>;
  /**
   * Same as props `onGetTokenErrorMessage` of TokenInput
   */
  onGetErrorMessage: OnGetTokenErrorMessage<ValueType, ErrorType>;

  /**
   * A callback function, which should be `invoked`
   * when end-user `start editing`
   *
   * Note:
   * Call this function to tell TokenInput it is start to editing the token.
   * As result, TokenInput will set `tokenMeta.activate` to `true`
   *
   * onEditStart()
   *
   * @ return
   * Type: void
   */
  onEditStart: () => void;

  /**
   * A callback function, which should be `invoked`
   * when end-user `end editing`
   *
   * Note:
   * Call this function to tell TokenInput to finish the `editing` of the token.
   * As result, TokenInput will set `tokenMeta.activate` to `false`.
   *
   * Also, TokenInput will based on the value of the parameter newTokenValue to
   * update the tokenValue of the token,
   * and call `onTokenValuesChange`
   *
   * onEditEnd(newTokenValue?)
   *
   * @ newTokenValue
   * Type: undefined | ValueType
   * Description:
   * The new tokenValue build by `onBuildTokenValue.
   *
   * Note:
   * if `newTokenValue` is `undefined`,
   * TokenInput will treat as `Cancel` (Edit will end without update the tokenValue).
   * The `onTokenValuesChange` will also not be called.
   *
   * @ return
   * Type: void
   */
  onEditEnd: (newTokenValue?: ValueType) => void;

  /**
   * A callback function, which should be `invoked`
   * when end-user `delete` the token
   *
   * Note:
   * Call this function to tell TokenInput to delete the token.
   * As result, TokenInput will remove the token,
   * and call `onTokenValuesChange` to update tokenValues.
   *
   * onDelete()
   *
   * @ return
   * Type: void
   */
  onDelete: () => void;
};

License

MIT

Keywords

FAQs

Package last updated on 21 Mar 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc