The value type for AddressInput
.
The value type for ValidatedAsyncSelect
.
The "contract" that all async validators must implement.
This moment doesn't have to be a specific time zone. UTC is fine, for example.
The value type for ValidatedMultiSelect
.
The value type for RadioInput
.
The value type for ValidatedSelect
.
[tabId, tabName, tabOptions]
A tuple representing the content of a tab in TabManager
.
The tuple elements represent tabName
, isTabReadyForDisplay
(loading
indicator shown if false), and finally the actual tab content JSX.
The value type of the TimeInput
component.
hours
will always be between 1 and 12.
We don't do TimeInputValue = Moment
because representing time of day with a datetime
leads to DST bugs.
The "contract" that all validators must implement.
If the value is valid, a validator should return something falsy
(undefined
, null
, or ''
). If the value is invalid, the validator should
return validation feedback which will be displayed to the user. The
validation feedback can be a string or a ReactNode
(e.g. a JSX element).
There are two special values of ValidatorOutput
:
ASYNC_VALIDATION_PENDING
: The value should be considered invalid
because async validation is in progress.ASYNC_VALIDATION_DEBOUNCE_PENDING
: The value should be considered invalid
because async validation has not started yet.INVALID_NO_FEEDBACK
: The value is invalid but no feedback should be
displayed because the reason why the input is invalid is being displayed
somewhere else.A validated address input. Supports US and Canadian addresses.
Field lengths and the default value of allowCanadian
are configured via
ItiReactContext
.
Validators for use with AddressInput
.
e.g. "No users matched your search" or "Begin typing to see matching users"
e.g. "Search users..."
A datetime input with a datepicker popover. See also DateInputNoPicker
.
It is implemented using react-datepicker
.
A datetime input without a datepicker popover. Its value is just a string
.
Good for things like date of birth. See also DateInput
.
Use formatDateInputNoPickerValue
to get the initial value for this input.
Use parseDateInputNoPickerValue
to get a moment
object from the string.
Validators for use with DateInputNoPicker
.
Validators for use with DateInput
.
For use with FileInput
.
An easy to use checkbox component.
<FormCheck
checked={myBoolean}
onChange={() => setMyBoolean(b => !b)}
label="My checkbox"
/>
inline
is true by default and should be set to false if you want to display
a vertical stack of checkboxes.
Validators you can use to build your own custom address input.
Only use this if making your own address input.
Only use this if making your own address input.
Only use this if making your own address input.
A context that provides configuration values used by code within iti-react-core
.
You must wrap your application in with <ItiReactContext.Provider>
and
<ItiReactCoreContext.Provider>
.
A context that provides configuration values used by code within iti-react-core
.
You must wrap your application in with <ItiReactCoreContext.Provider>
.
A simple pagination control that does not allow setting the number of items on a page.
These days, ConfigurablePager
is generally preferred.
A person name input that displays inputs for first name, middle name (optional), and last name.
If we just want first and last name, we will often just use two normal [[ValidatedInputs
]]
instead of PersonNameInput
.
Validators for use with PersonNameInput
.
Radio button input. It renders a group of radio buttons based on the options
you
pass in.
You can customize the style of both the container and the individual radio buttons / labels. Use the devtools element inspector to see the class names you need to target.
A time of day input with dropdowns for hours, minutes, and am/pm.
Make sure to pass individualInputsRequired=true
and isClearable=false
as well as TimeValidators.required()
if the time is required.
It's not the most performant or user-friendly component but it has gotten the job done so far.
Validators for use with TimeInput
.
A validated dropdown component based on react-select
that loads its
options via an API call.
This component is expensive to render so use React.memo
when necessary.
A validated dropdown component based on react-select
that allows selecting
multiple options.
If any options have isFixed: true, you should sort the options so that fixed options come before unfixed. Sorting the options in the component would cause poor performance when there are many options and the options array is not referentially stable.
This component is expensive to render so use React.memo
when necessary.
A validated dropdown component based on react-select
.
This component is expensive to render so use React.memo
when necessary.
Validators for string
values. Each property on this object is a function that returns
a Validator<string>
.
const validators = [Validators.required(), Validators.integer(), Validators.greaterThan(0)]
The moment format string used by DateInput
and DateInputNoPicker
when
includesTime
is false.
The moment format string used by DateInput
and DateInputNoPicker
when
includesTime
is true.
A blank AddressInputValue
.
Defaults for parts of ItiReactContextData
. Does not include defaults
for properties where there is no reasonable default value.
Defaults for parts of ItiReactCoreContextData
. Does not include defaults
for properties where there is no reasonable default value.
A Dialog
that has an action button and a cancel button.
A component that displays an address.
Wrapper around RadioInput
for when there are only two options, true and false.
A navigation breadcrumbs component.
Renders an icon that you can click to copy some text.
Relies on FontAwesome and @tippyjs/react
.
A pagination control that lets the user select how many items to show on a page.
The default page sizes are configured in ItiReactContext
and can be
overridden with the pageSizes
prop.
You can show an "All" option by setting showAllOption
to true. "All"
actually means a pageSize
of 10000.
Standalone confirm dialog that does not use react-confirm
.
The default clear button used in TimeInput
. You can provide a different
clear button component if you want.
Wrapper around the Bootstrap dialog component.
onClose
function. This will cause
the dialog to be abruptly removed without an animation.closeRef
to close the dialog from the parent component.focusFirst
and focusFirstOptions
props.A wrapper around ActionDialog
that removes a lot of the boilerplate needed
for dialogs that contain a form.
interface ExampleProps {
onSuccess(responseData: number): Promise<void>
onClose(): void
}
export function Example({
onSuccess,
onClose,
}: ExampleProps): ReactElement {
const { onChildValidChange, allFieldsValid } = useFieldValidity()
const [showValidation, setShowValidation] = useState(false)
const vProps = { showValidation, onValidChange: onChildValidChange }
const [myNumber, setMyNumber] = useState('')
async function submit() {
await api.product.performOperation()
return {
responseData: parseInt(myNumber),
}
}
return (
<EasyFormDialog
title="Enter a Number"
submitButtonText="Submit"
formIsValid={allFieldsValid}
showValidation={showValidation}
onShowValidationChange={setShowValidation}
onSubmit={submit}
onSuccess={onSuccess}
onClose={onClose}
>
<FormGroup label="My number">
{(id) => (
<ValidatedInput
id={id}
name="myNumber"
validators={[Validators.required(), Validators.integer()]}
value={myNumber}
onChange={setMyNumber}
{...vProps}
/>
)}
</FormGroup>
</EasyFormDialog>
)
}
A React component that adds a URL search param (usually error
) if the error
prop is non-null. If the error
prop is null, the URL search param is removed.
Usually, the error
prop will come from the Redux store. This allows you to display
an error page whenever an error occurs anywhere in your application.
A file upload control that can be made a required field.
Renders a form input and corresponding label.
The children of this component can either be a JSX element or a function that
maps id
string to a JSX element (better for accessibility).
A quick way to create an element that looks like a link but behaves like a button.
Displays a dollar sign at the beginning of a text input.
A validated phone number input. It automatically adds the US/Canada country code (1) to the value. Other country codes are not currently supported.
You don't have to pass in a validator that checks that the phone number is valid —
this is done automatically. PhoneInput
can be used with Validators.required()
.
Shows a "✔ Saved" message next to your "Save changes" button to show that user that the change went through. The message fades in and out.
const showSavedMessageRef = useRef(() => {})
function saveChanges() {
// call the API
showSavedMessageRef.current()
}
return <div>
...
<SavedMessage
showSavedMessageRef={showSavedMessageRef}
className="saved-message-me"
/>
...
</div>
Submit button/link that displays a loading indicator and disables the onClick handler
when submitting=true
.
The component that is displayed while a tab is loading in TabManager
.
A presentational component for building user interfaces with tabs.
Usually you want to use TabManager
which builds on top of TabLayout
.
A high-level component for creating user interfaces with tabs.
mountAllTabs
to true.)A time zone dropdown. The 4 common US time zones are shown first, followed by every
other time zone. It uses the @vvo/tzdb
time zone database.
Displays an input along with a unit.
<UnitInputContainer unit="km">
<ValidatedInput />
</UnitInputContainer>
Displays validation feedback below an input. Used by ValidatedInput
, .etc.
You usually won't use this directly unless creating your own input component.
Imperative-style alert function backed by react-confirm
.
a Promise which resolves when the alert is closed.
Returns true if all values in the object are true. For use with
useReadiness
.
Takes in multiple ValidatorOutput
's and returns the first invalid one, or
undefined
if all are valid.
Imperative-style confirm dialog backed by react-confirm
.
Formats the "city state zip" part of an address.
Get the initial value for a DateInputNoPicker
component.
a formatted date string or ''
if the input moment was invalid
A configurable function for formatting a moment.
any moment object
onlyShowDateIfNotToday
: when true, does not display the day if mo
is todayconvertToLocal
: if mo
should be converted to local timedateTimeFormat
: format used if date & time are displayedtimeFormat
: format used if only time is displayedFormats a dollar amount. Supports negative values.
Formats a number as a percent. An input value of 1
means 100%.
Supports negative values.
'display'
if this percentage will be displayed, 'userInput'
if
percent will be used as the default value for a text input.
Format a phone number for display. Uses normalizePhoneNumber
.
Normalizes and converts a postal code to a string. Handles 5 & 9 digit US postal codes and Canadian postal codes.
A component factory that returns an AsyncRouter
. When using AsyncRouter
and a link changes the route, the new page is mounted but not displayed until
it has finished loading data and calls onReady
. A progress bar at the top
of the page (usually NProgress) indicates to the user that the new page is
loading.
It is fine if a page calls onReady
multiple times.
Example:
export interface OnReadyArgs {
title: string
}
const AsyncRouter = getAsyncRouter<OnReadyArgs>()
export function MyAsyncRouter(): React.ReactElement {
const onReady = useCallback(
({ title }: OnReadyArgs): void => {
updateTitle(title)
},
[]
)
const onInitialPageReady = useCallback((): void => {
removeLoadingScreen()
}, [])
return (
<AsyncRouter
renderRoutes={props => <AppRoutes {...props} />}
renderLayout={(children) => (
<Layout>
{children}
</Layout>
)}
getLocationKey={getLocationKey}
onNavigationStart={NProgress.start}
onNavigationDone={NProgress.done}
onReady={onReady}
onInitialPageReady={onInitialPageReady}
/>
)
}
function getLocationKey(location: Location): string {
return location.pathname.toLowerCase()
}
getLocationKey
If you want to be able to change the route parameters without the page
unmounting and remounting, you should implement getLocationKey
, so that
the page has the same location key regardless of the route params.
Example: you want to be able to navigate from /job/0
to /job/1
without
the page remounting. You should make getLocationKey
return '/job'
for
any path that matches '/job/:page?
. Use matchPath
for this.
LocationKey is NOT the same as the key
property of the location
object.
When implementing getLocationKey
, if the current path does not correspond
to a route in your application, you must return the current path without
any modifications.
Consider this example to see why you must return the path unmodified. Say
you have a route /job/:page?
and you have implemented getLocationKey
to
return '/job'
for any path that starts with /job
. The user enters
/job/bogus/path/here
into the URL bar. The "Page not found" page will be
rendered. Then the user clicks the navbar link to the job list. The
location key does not change when the location changes, so AsyncRouter
does not unmount the previous page and mount the new page. But the two
pages are actually different! So yeah weird stuff can happen if you
implement getLocationKey
like this. Always use matchPath
in
getLocationKey
!
test-website
and follow the steps.test-website
while on
/home
. The logo is a link to /
. When the path is /
, a redirect
to /home
is rendered, putting you back where you started.the arguments your pages will pass to onReady
Applies multiple validators to a value and returns the combined result. Thin wrapper
around combineValidatorOutput
.
Takes in a list of normal SelectOption
s and "group" select options
and flattens it out into a list of normal SelectOption
s.
Returns a page of items, given the page number (which starts at 1) and the page size.
Styles the react-select
component to match Bootstrap form-control inputs.
Get a list of SelectOption
s for US states and/or Canadian provinces.
Get a list of US states and/or Canadian provinces.
Returns a boolean indicating if a form's submit button should be enabled.
Returns true if formIsValid === true
or showValidation === false
.
This has the effect of disabling the submit button while async validation is in progress if validation is being shown.
Determines the current tab from the Location
object.
Makes a table cell into a link.
TdLink
has styles that are required for it to work correctly.
<table className="table table-hover table-td-link">
<tbody>
{products.map(p => {
const Td = getTdLink('/product/detail/' + p.id)
return (
<tr key={p.id}>
<Td>{p.id}</Td>
<Td>{p.name}</Td>
<Td>{p.stock}</Td>
</tr>
)
})}
</tbody>
</table>
Returns the total numbers of pages based on the number of items and the page size.
Returns a Bootstrap validation class depending on valid
and showValidation
.
true if the postal code is Canadian e.g. A1A 1A1
Determines if a postal code is valid. US 5-digit, US 9-digit, and Canadian postal codes are supported.
Used to run different code if running in a Jest test.
Takes in a phone number in any format and converts it to an 11-digit string that starts with the US/Canada country code of 1.
Returns a postal code with the space or hyphen removed.
Converts T | null | undefined
to T | undefined
.
Parse the value
of a DateInputNoPicker
component.
a Moment object or undefined if the value
was invalid
Validates a phone number. Automatically used by PhoneInput
.
Validator for a postal code input. Uses isPostalCodeValid
.
Use this whenever doing server-side paging to account for items being deleted while the user has the list open. Without this function, the user could see an empty page because the number of items, and thus the total number of pages, has decreased.
Part of usePaginationHelpers
. Usually not used directly.
Compares the filters between the current query params and the new query params and resets to the first page if any of the filters have changed.
Part of usePaginationHelpers
. Usually not used directly.
determines which properties of the query params object are
considered filters. By default, everything other than page
and pageSize
is
considered a filter.
Example:
timeInputValueFromDecimalHours(9.75)
// returns { hours: 9, minutes: 45, ampm: 'am' }
a TimeInputValue
or undefined
if decimalHours
is undefined
.
Converts hours & minutes to a decimal number of hours.
toDecimalHours(5, 30) // -> 5.5
should be an integer
Converts a decimal number of hours to integer hours & minutes.
toHoursAndMinutes(5.5) // -> { hours: 5, minutes: 30 }
Converts T | null | undefined
to T | null
.
Returns a capture
function which "captures" CancellablePromise
's and cancels
them when the component unmounts. This prevents "set state after unmount"
warnings.
const capture = useCancellablePromiseCleanup()
// Later, in an async function:
const result = await capture(api.get('xyz'))
Allows an input to work as either a controlled or uncontrolled component depending on which props are provided.
Used to show a loading indicator when async validation is progress. Uses debouncing so the loading indicator is never displayed if the async validation completes quickly.
Keep tracks of a FieldValidity
and returns a function to update the
the FieldValidty
.
You don't need to use this if there is only one validated input. In that case,
a simple const [valid, setValid] = useState(false)
is sufficient.
Top-level usage (e.g. when using EasyFormDialog
):
const { onChildValidChange, allFieldsValid } = useFieldValidity()
Usage with onValidChange
from props:
const { onChildValidChange } = useFieldValidity({ onValidChange })
Like useFieldValidity
, but lets you pass in whatever
fieldValidityIsValid
function you want.
Usually you'll want to use useFieldValidity
.
A hook that combines three things that need to be implemented when using pagination:
const totalPages = usePaginationHelpers(...)
A hook that detects when the user has clicked outside of a popover, indicating that the popover should be closed.
Stores and returns the previous value of something. Useful in niche situations.
Internally, it uses useRef
.
const previousLocation = usePrevious(location)
Used to call onReady
when all of the components/queries in a page are ready.
const [onChildReady, readiness] = useReadiness(
{
a: false, b: false, c: false
},
readiness => {
if (allReady(readiness)) {
onReady({ ... })
}
},
)
the parameters of the query
the type returned by the query
the type returned by the query
the type returned by the query
the parameters of the query
the type returned by the query
an object containing doQuery
and doQueryAsync
functions. doQueryAsync
must be called within a try-catch
.
A hook that allows implementing validation in any input component.
Internally, useValidation
calls useMemo
on validators
and asyncValidator
since those props won't have stable identities if defined during the render
as is typical. If useValidation
did not do this, every component that rendered
a validated component would have to call useMemo
on validators
and
asyncValidator
(or move the definitions outside of the component) to prevent
infinite useEffect
loops.
If and when your validators
or asyncValidator
do change, you must pass a
different validationKey
for useValidation
to pick up the changes.
the type of the input's value
To be used with Jest fake timers. Lets timers and React component async updates run.
import { act as reactAct } from '@testing-library/react'
import { act as hooksAct } from '@testing-library/react-hooks'
import { waitForReactUpdatesFactory } from '@interface-technologies/iti-react/src/TestHelpers'
export const waitForReactUpdates = waitForReactUpdatesFactory(reactAct)
export const waitForHookUpdates = waitForReactUpdatesFactory(hooksAct)
To be used with Jest fake timers. Lets timers and React component async updates run.
import { act as reactAct } from '@testing-library/react'
import { act as hooksAct } from '@testing-library/react-hooks'
import { waitForReactUpdatesFactory } from '@interface-technologies/iti-react/src/TestHelpers'
export const waitForReactUpdates = waitForReactUpdatesFactory(reactAct)
export const waitForHookUpdates = waitForReactUpdatesFactory(hooksAct)
Generated using TypeDoc
The field lengths required by
AddressInput
.