DEMO HERE https://material-ui-pack.xyz
Why? Because I love the Material UI api but <TextField name="phone" phone>
is nicer than <TextField variant="outlined" size="medium" value={state.phone} label="Phone" onChange={handlePhoneFormatAndSetState}/>
when you manage a lot of forms and many projects.
# use with mui v5
npm i material-ui-pack@5
# use with mui v4
npm i material-ui-pack@4
Pass your own state
and setState
into the surrounding Form
component.
Property | Description |
---|---|
state | React useState to contain all your form values. |
setState | From React useState |
onSubmit | Callback function to fire when form is submitted |
busy | Boolean used to disable inputs and submit button after your form is submitted |
margin | Default for TextField components `"normal" |
size | Default for TextField components `"small" |
debug | Display state values stringified |
import React from "react"
import { Form, SubmitButton, TextField } from "material-ui-pack"
export default function App() {
const [state, setState] = React.useState({
email: "",
password: "",
})
const [busy, setBusy] = React.useState(false)
function handleSubmit() {
setBusy(true)
// do something with state here
...
setBusy(false)
}
return (
<Form state={state} setState={setState} onSubmit={handleSubmit} busy={busy}>
<TextField name="email" type="email" />
<TextField name="password" fomatter="password" />
<SubmitButton>Submit</SubmitButton>
</Form>
)
}
You can optionally use this React hook to compose your own custom form components.
import React from "react"
import { useForm } from "./FormProvider"
export function CustomFormInput(props) {
const { formProps, getValue, setValue } = useForm<FormData>()
return (
<input
type="text"
disabled={formProps.busy}
value={getValue(props.name)}
onChange={e => setValue(props.name, e.currentTarget.value)}
/>
)
}
No need to set type="submit"
or an onClick
action.
<SubmitButton>Submit</SubmitButton>
The wrapped TextField
will default with variant="outlined"
and you can skip properties such as label
, value
, and onChange
. Labels are automtically derived from the name property name="firstName"
will be labeled First Name.
Property | Description |
---|---|
name | String key name from your state object, can also be an object path like address.street1 or alternateEmails[0].email . It uses lodash to get/set values in your state. |
lowercase | All lowercase formatting |
password | Hidden text with toggle button to view |
newPassword | Display warning if it is too short or does not contain upper, lower, and numeric characters |
phone | Standard 10 digit phone formatting |
capitalize | Auto capitcalize words |
// labeled "First Name"
<TextField name="firstName" />
// supports object paths in the name (uses lodash.get() and lodash.set())
<TextField name="alternateEmails[0]" label="Alternate Email"/>
<TextField name="email" formatter="lowercase" />
<TextField name="password" formatter="password" />
<TextField name="newPassword" formatter="newPassword" />
<TextField name="phone" formatter="phone" />
<TextField name="capitalizedWords" formatter="capitalize" />
<CurrencyField name="price" />
<PercentageField name="taxRate" decimals={3} />
<NumberField name="myNumber" decimals={1} />
// auto labeled "A Checkbox"
<Checkbox name="aCheckbox" />
A drop-down/input combo box. User can enter or select options.
Property | Description |
---|---|
options | Array of objects containing value and label |
<SelectCombo
options={[
{ value: "blue", label: "Blue" },
{ value: "red", label: "Red" },
]}
name="favoriteColor"
/>
This component uses i18n-iso-countries to build a full list of countries for your address forms. Values are set as ISO 3166-1 alpha-3, but support alpha-2
also.
Property | Description |
---|---|
isoType | `"isoAlpha2" |
<SelectCountry name="country" />
This component uses country-region-data to build a full list of states/provinces with the props value country
.
Property | Description |
---|---|
country | To control which regions are loaded. |
countryIsoType | `"isoAlpha3" |
<SelectRegion country="USA" name="stateOrProvince" />
Property | Description |
---|---|
country | To optionall filter the zones. |
countryIsoType | `"isoAlpha3" |
<SelectTimeZone name="timeZone" />
This is a simple native drop-down select component.
Property | Description |
---|---|
options | Array of objects containing `(string |
<Select
name="color"
options={[
{ value: "blue", label: "Blue" },
{ value: "red", label: "Red" },
]}
/>
This component uses @material-ui/pickers and sets values in ISO 8601 format.
<DateTimePicker name="dateAndTime" />
This component uses @material-ui/pickers and sets values in "yyyy-mm-dd" format.
<DatePicker name="date" />
This component uses @material-ui/pickers and sets values in "hh:mm:ss" format.
<TimePicker name="time" />
import React from "react"
import { ResponsiveTable } from "material-ui-pack"
export function ResponsiveTableExample() {
return (
<ResponsiveTable
onSelectChange={film => {
console.log(film)
}}
onEdit={film => alert(`Edit ${film.title}`)}
onDelete={film => alert(`Delete ${film.title}`)}
rowData={[
{ id: 1, title: "Star Wars", category: "Sci-Fi" },
{ id: 2, title: "The Shining", category: "Horror" },
]}
schema={[
{
label: "Title",
render: function(item) {
return item.title
},
},
{
xsDownHidden: true,
label: "Category",
render: function(item) {
return item.category
},
},
]}
/>
)
}
Allow useDarkMode
and DarkModeProvider
to manage dark mode state. User can select dark mode in their operating system OR using the DarkModeToggle
switch component. It sets a storage property to remember the user's preference.
import React from "react"
import { ThemeProvider, CssBaseline } from "@material-ui/core"
import { useDarkMode, DarkModeProvider } from "material-ui-pack/dist/DarkModeProvider"
import DarkModeToggle from "material-ui-pack/dist/DarkModeToggle"
function ThemedContent() {
const { createMuiThemeWithDarkMode } = useDarkMode()
const theme = createMuiThemeWithDarkMode({
palette: {
primary: {
main: "#db544c",
},
},
})
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<DarkModeToggle />
</ThemeProvider>
)
}
export default function App() {
return (
<DarkModeProvider>
<ThemedContent />
</DarkModeProvider>
)
<DisplayDateTime
iso8601="2020-02-21T06:15:06.149Z"
timeZone="America/New_York"
fromNow
/>
<DisplayDate ymd="1978-09-22" fromNow />
formatDateTime("2020-02-21T06:15:06.149Z", "America/Chicago")
formatDate("1978-09-22")
import IconButton from "@material-ui/core/IconButton"
import Add from "@material-ui/icons/Add"
import Remove from "@material-ui/icons/Remove"
import React from "react"
import useCounter from "../hooks/useCounter"
export function UseCounterExample() {
const [count, increase, decrease] = useCounter(100)
return (
<>
{count}
<IconButton onClick={increase}>
<Add />
</IconButton>
<IconButton onClick={decrease}>
<Remove />
</IconButton>
</>
)
}
import { Collapse } from "@material-ui/core"
import React from "react"
import useEscapeKey from "../hooks/useEscapeKey"
export function UseEscapeKeyExample() {
const [isOpen, setIsOpen] = React.useState(true)
useEscapeKey(
React.useCallback(() => {
setIsOpen(false)
}, [])
)
return (
<Collapse in={isOpen}>
<h1>ESC to hide this</h1>
</Collapse>
)
}
import { Button, Collapse } from "@material-ui/core"
import React from "react"
import useHandleState from "../hooks/useHandleState"
export function UseHandleStateExample() {
const [isOpen, handleIsOpen, setIsOpen] = useHandleState(true)
return (
<Collapse in={isOpen}>
<Button onClick={() => setIsOpen(false)}>Hide with Setter</Button>
<Button onClick={handleIsOpen(false)}>Hide with Handler</Button>
</Collapse>
)
}