2.2.1 • Published 2 years ago

@craigmcc/shared-react v2.2.1

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
2 years ago

Shared React Components Library

This module contains a number of React components that I have shared across multiple applications the old fashioned way (cut-n-paste). It's time to make them a separate thing that can be maintained and updated in one place.

Installation

This library depends on the following peer dependencies, but is flexible about which version is used. Check the peerDependencies section of the package.json file to see what minimum versions are required.

If needed, you can install the peer dependencies:

npm install bootstrap react react-bootstrap react-bootstrap-icons react-dom react-hook-form react-toastify

To install this library itself:

npm install @craigmcc/shared-react

The components depend on react-bootstrap (and therefore bootstrap itself) for styling, so somewhere in your application you will need to import the Bootstrap styles. The easiest way is to include the following in your outermost App.tsx or App.jsx file:

import 'bootstrap/dist/css/bootstrap-min.css';

Likewise, you will need to import the react-toastify styles, along with the declaration for the <ToastContainer> component. Again, the easiest way is to include the following in your outermost App.tsx or App.jsx file:

import {ToastContainer} from 'react-toastify';
import `react-toastify/dist/ReactToastify.css`;

Finally, in your App.tsx or App.jsx file, include a <ToastContainer> component, normally above and outside all of your application components. This component is used to configure the default characteristics for all toast notifications that your application produces -- see the react-toastify documentation for details.

Data Handler Types

The following function definitions are used to declare Typescript method signatures for functions that respond to events:

export type HandleAction = () => void;
export type HandleBoolean = (newBoolean: boolean) => void;
export type HandleValue = (newValue: string) => void;

Included Components

The following general purpose components are provided by this library:

Component NameDescription
AddButonA stylized button with a "+" icon.
BackButonA stylized button with a "<" icon.
CalloutA text area with variant background colors, useful in documentation.
CheckBoxA standalone checkbox input, with optional decorations. Suitable for use cases where a form is overkill.
PaginationVery simple pagination controls when managing a multiple page table.
SearchBarGeneral purpose search bar, with optional decorations. You can choose to be notified on each keystroke, or only when the value is completed.

In addition, the following components render a <Form.Group> element (from react-bootstrap) that are useful in creating fields for an HTML form:

Component NameDescription
CheckBoxFieldA form input element for a checkbox.
SelectFieldA form element for a select dropdown.
TextFieldA form element for a text input.

Also, the following components render a toast notification, while a fetching or mutating operation is in progress. They are typically used in conjunction with a corresponding React custom hook that performs the requested function asynchronously, but this is not required.

Component NameDescription
FetchingProgressDisplay a toast while a "fetching" API call is in progress, or an error toast if it fails.
MutatingProgressDisplay a toast while a "mutating" API call is in progress, or an error toast if it fails.

AddButton

Usage

Import this component in your using component module (either JSX or TSX):

import {AddButton, HandleAction} from "@craigmcc/shared-react";

Then use it in your rendered return value, in the usual way:

<AddButton {AddButtonProps}/>

Supported Configuration Properties

NameData TypeRequiredDescriptionDefault Value
disabledbooleanNoShould the rendered element be marked disabled?false
handleAddHandleActionNoFunction to handle button clicksno handler
testIdstringNoOptional "data-testid" value for testsno data-testid

BackButton

Usage

Import this component in your using component module (either JSX or TSX):

import {BackButton, HandleAction} from "@craigmcc/shared-react";

Then use it in your rendered return value, in the usual way:

<BackButton {BackButtonProps}/>

Supported Configuration Properties

NameData TypeRequiredDescriptionDefault Value
disabledbooleanNoShould the rendered element be marked disabled?false
handleBackHandleActionNoFunction to handle button clicksno handler
testIdstringNoOptional "data-testid" value for testsno data-testid

Callout

Usage

Import this component in your using component module (either JSX or TSX):

import {Callout} from "@craigmcc/shared-react";

Then use it in your rendered return value, in the usual way:

<Callout {CalloutProps}/>

Supported Configuration Properties

NameData TypeRequiredDescriptionDefault Value
childrenReactNodeYesText content to be rendered in this CalloutNO DEFAULT
iconbooleanNoShould a title icon be rendered?true (if title specified)
titlestringNoOptional title (header) for this Calloutno title
variantstringNoBootstrap variant style for background colorinfo

The variant values are the standard ones for Bootstrap: primary, secondary, success, danger, warning, info, light, and dark. This chooses the color of the background for the callout, and also the complementary color for the displayed text.

CheckBox

Usage:

Import this component in your using component module (either JSX or TSX):

import {CheckBox, HandleBoolean} from '@craigmcc/shared-react';

Then use it in your rendered return value, in the usual way:

<CheckBox {CheckBoxProps} />

Supported Configuration Properties:

NameData TypeRequiredDescriptionDefault Value
autoFocusbooleanNoShould the rendered element receive autoFocus?false
disabledbooleanNoShould the rendered element be marked disabled?false
handleChangeHandleBooleanYesFunction to handle value changesNO DEFAULT
labelstringYesElement labelNO DEFAULT
namestringNoInput control namecheckBox
valuebooleanNoInitially rendered valuefalse

Examples:

<CheckBox
    handleChange={handleMagicChange}
    label="Enable the magic?"
    value={true}
/>
<form class="align-items-center">
    <div id="checkBoxGroup">
        <input type="checkbox" id="checkBox" class="form-check-input" checked>
        <label for="checkBox" class="ms-2 form-check-label">Enable the magic?</label>
    </div>
</form>
<CheckBox
    disabled={true}
    handleChange={handleActiveChange}
    label="Active items only?"
    name="active"
/>
<form class="align-items-center">
    <div id="activeGroup">
        <input disabled type="checkbox" id="active" class="form-check-input">
        <label for="active" class="ms-2 form-check-label">Active items only?</label>
    </div>
</form>

Behavior Notes:

  • The handleChange function will be called whenever the checkbox is checked or unchecked.

CheckBoxField

Usage:

Import this component in your using component module (either JSX or TSX):

import {CheckBoxField} from "@craigmcc/shared-react";

Then use in your rendered return value (within a <Form> component from react-boostrap) in the usual way:

<CheckBoxField {CheckBoxFieldProps}/>

Supported Configuration Properties

NameData TypeRequiredDescriptionDefault Value
asElementTypeNoRender the <Form.Group> as a component of this type.Col
autoFocusbooleanNoShould this field receive autoFocus?false
classNamestringNoCSS style class names (space separated) for the <Form.Group>.none
disabledbooleanNoShould this field be disabled?false
errorFieldErrorNoFieldError object for this field (if any).no error
invalid?stringNoError message if input is invalidno message
labelstringYesField label.NO DEFAULT
namestringYesName of this field (must be unique in a form).NO DEFAULT
readOnlybooleanNoShould this field be marked as read only?false
registerUseFormRegisterYesregister object from useForm().NO DEFAULT
typestringNoInput control type ("checkbox" or "radio").checkbox

Behavior Notes

  • The field label will appear after the checkbox, in the usual react-bootstrap style.

FetchingProgress

Usage:

Import this component in your using component module (either JSX or TSX):

import {FetchingProgress} from '@craigmcc/shared-react';

Then, render this component somewhere in your component's output. The actual location of the rendered toast is based on the settings you configured in the <ToastContainer> component described earlier.

Supported Configuration Properties

NameData TypeRequiredDescriptionDefault Value
durationnumberNoNumber of ms to display this toast if not cleared (0=forever)Default from <ToastContainer>
errorError or nullNoError thrown by fetch logic (typically from a custom hook)No notification
loadingbooleanNoFlag indicating a fetch is in progress (typically from a custom hook)No notification
messagestringYesMessage displayed in this toast while loading is in progressNO DEFAULT

Example:

Assume you have a custom hook that performs a fetch, and returns (among other things):

  • error: Error | null - Javascript error thrown by the fetch operation.
  • loading: boolean - Flag indicating that the fetch operation is in progress.

Then, you might include a progress component like this:

<FetchingProgress
    error={customHook.error}
    loading={customHook.loading}
    message="Fetching selected customers"
/>

MutatingProgress

Usage:

Import this component in your using component module (either JSX or TSX):

import {MutatingProgress} from '@craigmcc/shared-react';

Then, render this component somewhere in your component's output. The actual location of the rendered toast is based on the settings you configured in the <ToastContainer> component described earlier.

Supported Configuration Properties

NameData TypeRequiredDescriptionDefault Value
durationnumberNoNumber of ms to display this toast if not cleared (0=forever)Default from <ToastContainer>
errorError or nullNoError thrown by mutating logic (typically from a custom hook)No notification
executingbooleanNoFlag indicating a mutation is in progress (typically from a custom hook)No notification
messagestringYesMessage displayed in this toast while mutation is in progressNO DEFAULT

Example:

Assume you have a custom hook that performs a mutation, and returns (among other things):

  • error: Error | null - Javascript error thrown by the mutation operation.
  • executing: boolean - Flag indicating that the mutation operation is in progress.

Then, you might include a progress component like this:

<MutatingProgress
    error={customHook.error}
    executing={customHook.executing}
    message="Updating the selected order"
/>

Pagination

Usage:

Import this component in your using component module (either JSX or TSX):

import {Pagination, HandleAction} from '@craigmcc/shared-react';

Then use it in your rendered return value, in the usual way:

<Pagination {PaginationProps} />

Supported Configuration Properties:

NameData TypeRequiredDescriptionDefault Value
currentPagenumberYesOne-relative current page numberNO DEFAULT
handleNextHandleActionNoFunction to handle "next" button clicksNo handler
handlePreviousHandleActionNoFunction to handle "previous" button clicksNo handler
lastPagebooleanYesIs this the last page (disables "Next")?NO DEFAULT
variantstringNoBootstrap variant style for buttonsoutline-secondary

Examples:

<Pagination
    handleNext={handlePaginationNext}
    handlePrevious={handlePaginationPrevious}
    lastPage={false}
    variant="secondary"
/>
<button type="button" class="me-1 btn btn-secondary">&lt;</button>
<button type="button" disabled class="me-1 btn btn-secondary">2</button>
<button type="button" class="btn btn-secondary">&gt;</button>

Behavior Notes:

  • Previous Page control (<) will be disabled on the first page, and enabled otherwise.
  • Current page number will always be disabled. It is styled as a button for visual consistency only.
  • Next Page control ('>') will be disabled if lastPage is set to true.

SearchBar

Usage:

Import this component in your using component module (either JSX or TSX):

import {SearchBar, HandleValue} from '@craigmcc/shared-react';

Then use it in your rendered return value, in the usual way:

<SearchBar {SearchBarProps} />

Supported Configuration Properties:

NameData TypeRequiredDescriptionDefault Value
autoFocusbooleanNoShould the rendered element receive autoFocus?false
disabledbooleanNoShould the rendered element be marked disabled?false
handleChangeHandleValueNoFunction to handle value changes on each keystrokeNo handler
handleValueHandleValueNoFunction to handle value on enter/tabNo handler
htmlSizenumberNoNumber of characters hint for input controlNot set
labelstringNoElement label"Search For:"
namestringNoInput control namesearchBar
placeholderstringNoPlaceholder textNot set
valuebooleanNoInitially rendered value""

Examples:

<SearchBar
    handleChange={handleSearchBarChange}
    handleValue={handleSearchBarValue}
    label="Select Customer:"
    name="selectCustomer"
    placeholder="Specify all or part of the customer name"
/>
<form class="align-items-center">
    <div id="selectCustomerGroup" class="row">
        <label for="selectCustomer" class="form-label col-auto">Select Customer:</label>
        <div class="col-auto">
            <input placeholder="Specify all or part of customer name" id="selectCustomer" class="form-control form-control-sm" value>
        </div>
    </div>
</form>

Behavior Notes:

  • The handleChange function (if any) will be called on each keystroke.
  • The handleValue function (if any) will be called when Enter or Tab is pressed.

SelectField

Usage:

Import this component in your using component module (either JSX or TSX):

import {SelectField} from "@craigmcc/shared-react";

Then use in your rendered return value (within a <Form> component from react-boostrap) in the usual way:

<SelectField {SelectFieldProps}/>

Supported Configuration Properties

NameData TypeRequiredDescriptionDefault Value
asElementTypeNoRender the <Form.Group> as a component of this type.Col
autoFocusbooleanNoShould this field receive autoFocus?false
classNamestringNoCSS style class names (space separated) for the <Form.Group>.none
disabledbooleanNoShould this field be disabled?false
errorFieldErrorNoFieldError object for this field (if any).no error
headerSelectOptionNoOptional placeholder rendered above the options list.none
labelstringYesField label.NO DEFAULT
namestringYesName of this field (must be unique in a form).NO DEFAULT
optionsSelectOption[]YesArray of select options with label and value properties.NO DEFAULT
readOnlybooleanNoShould this field be marked as read only?false
registerUseFormRegisterYesregister object from useForm().NO DEFAULT
validstringNoHelp message for valid inputnone

Behavior Notes

  • The field label will appear above the select field, in the usual react-bootstrap style.

TextField

Usage:

Import this component in your using component module (either JSX or TSX):

import {TextField} from "@craigmcc/shared-react";

Then use in your rendered return value (within a <Form> component from react-boostrap) in the usual way:

<TextField {TextFieldProps}/>

Supported Configuration Properties

NameData TypeRequiredDescriptionDefault Value
asElementTypeNoRender the <Form.Group> as a component of this type.Col
autoFocusbooleanNoShould this field receive autoFocus?false
classNamestringNoCSS style class names (space separated) for the <Form.Group>.none
disabledbooleanNoShould this field be disabled?false
errorFieldErrorNoFieldError object for this field (if any).no error
htmlSizenumberNoHTML size of text field.none
labelstringYesField label.NO DEFAULT
namestringYesName of this field (must be unique in a form).NO DEFAULT
placeholderstringNoPlaceholder text when the field has no value.none
readOnlybooleanNoShould this field be marked as read only?false
registerUseFormRegisterYesregister object from useForm().NO DEFAULT
typestringNoInput field type (datehiddenmonthnumberpasswordtexttime).text
validstringNoHelp message for valid inputnone

Behavior Notes

  • The field label will appear above the text field, in the usual react-bootstrap style.
2.1.1-beta0

2 years ago

2.1.1-beta4

2 years ago

2.1.1-alpha9

2 years ago

2.1.1-beta3

2 years ago

2.1.1-beta2

2 years ago

2.1.1-beta1

2 years ago

2.2.1

2 years ago

2.1.1-alpha5

2 years ago

2.2.0

2 years ago

2.1.1-alpha6

2 years ago

2.1.1-alpha7

2 years ago

2.1.1-alpha8

2 years ago

2.1.1-alpha1

2 years ago

2.1.1-alpha2

2 years ago

2.1.1-alpha3

2 years ago

2.1.1-alpha4

2 years ago

2.1.1-alpha10

2 years ago

2.1.0

3 years ago

2.0.2

3 years ago

2.0.1

3 years ago

2.0.0

3 years ago

1.2.1

3 years ago

1.2.0

3 years ago

1.1.2

3 years ago

1.1.1

3 years ago

1.1.0

3 years ago

1.0.0

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago