This project aims to bring React's Material-UI to ember octane.
Explore React Material-UI docs »
Examples/Demo can be found at: https://github.com/ctwoolsey/ember-paper-react-demo
- Ember.js v3.28 or above
- Ember CLI v3.28 or above
- Node.js v13 or above
$ ember install --save --dev ember-paper-react
This addon requires the use of SASS.
$ ember install --save ember-cli-sass
In the ember-cli-build.js
file add the following:
rename the app/styles/app.css
file to app.scss
This addon uses React's material-ui
components but layout styling is done as in ember-paper
. This is because material-ui styling is done through react constructs and would not allow styling via ember's HTML.
See ember-paper layout docs »
If you wish to theme the material-ui components using predefined colors from material-ui, you will need to install:
$ npm install --save --dev @mui/material @emotion/react @emotion/style
To use the material-ui theme palette globally, inject the service themeManager
. This should be done within application.js.
application.js
To change the global theme, this same pattern can be called from anywhere in the ember app. To change a specific component, modify the appropriate css file.
All components support the @style
and @class
arguments as well as @sx
.
@style
can be inline or as a passed object:
<MyComponent @style="backgroundColor:blue; width:100px" />
or
<MyComponent @style={{this.myStyle}} />
this.myStyle = { backgroundColor: 'blue', width: '500px' };
A few important notes that effect all components:
Components need to have a parent html tag at some level. This cannot be a wrap of the
{{outlet}}
tag. This can be at the page level in a controler template like so:
role
andaria-*
anddata-*
these attributes will be recognized on all components. It is the user's responsibility to make sure the component should have arole
oraria-*
attribute. These fields can be static or dynamic:The first example will update
Components that have
icon
as an attribute take an icon object. The form of this object is:
{icon: ..., iconProps: ...}
if no iconProps are needed the icon can be passed directly.
All properties listed on the Material-ui site are available are implemented on the components with the use of @
. Properties that might be dynamic and change are implemented so that they will update accordingly. Properties or functions that return a ReactNode will generally not work unless you pass or return a ReactNode. Some components have special ways of dealing with this known as Attribute Children
.
Explore React Material-UI Alert docs
The most basic usages are:
Note: any time an action is needed use the named block methods as shown.
Explore React Material-UI AppBar docs
The most basic usages are:
Explore React Material-UI Autocomplete docs
The most basic usage is:
This component supports validation messages:
NormalTextField
error
andhelperText
fields are available. But special fields have been added to make validation work easier withember-changeset
. The following attributes have been added:
@isTouched
- this field will need to be true to display the error messages passed to the next attribute@errors
- this is an array of error validation messages.
In addition to the defined options, the following options have been added for convenience:
@popupClass
- this option will add this class name to thepopup
so that styling the popup can be unique to the component@readOnly
- this option makes theautocomplete
act more like a normal select component. This can also be achieved by setting@inputProps
equal to an object{ readOnly: true }
.
Note: The following options will not work unless a react Node is returned from the function:
@renderGroup
@renderOption
@renderTags
@getLimitTagsText
@renderInput
is fixed internally to use a TextField
and cannot be changed.
All properties of the TextField
are available for the TextField
component unless the Autocomplete
component uses the same property.
If @nativeOnChange={{true}}
:
The onChange
function will return the mui specified (event, value, reason, details)
.
Otherwise, @onChange
will return (value)
.
If @multiple={{true}}
the value
returned will be an EmberArray
.
While options and groupings can all be set through passed arguments, it is possible if desired to customize the grouping headers or options.
By using <:groupHeaders>
or <:options>
those sections may be customized. Each customization must be wrapped within a <li>
element.
If using custom text in the options, to ensure that autocomplete updates these options, @filterOptions
must be used as in the example below.
@tracked filmOptionsFiltered;
@tracked groupHeaders;
this.top100Films = [
{ title: 'The Shawshank Redemption', year: 1994 },
{ title: 'The Godfather', year: 1972 },
{ title: 'The Godfather: Part II', year: 1974 },
{ title: 'The Dark Knight', year: 2008 },
{ title: '12 Angry Men', year: 1957 },
{ title: "Schindler's List", year: 1993 },
{ title: 'Pulp Fiction', year: 1994 },...];
movieOptionLabel(option) {
if (option) {
return option.title + ' (' + option.year + ') ';
} else {
return '';
}
}
movieGrouping(option) {
return option.firstLetter;
}
@action
filterOptions(options, state) {
return this.filteredOptions(options, state.inputValue);
}
filteredOptions(options, inputValue) {
this.filmOptionsFiltered = [];
options.forEach((option) => {
const showValue = option.title + ' ' + option.year;
if (showValue.toLowerCase().includes(inputValue.toLowerCase())) {
this.filmOptionsFiltered.push(option);
}
});
this.createGroupHeaders();
return this.filmOptionsFiltered;
}
createGroupHeaders() {
this.groupHeaders = A();
this.filmOptionsFiltered.forEach((filmOption) => {
if (!this.groupHeaders.includes(filmOption.firstLetter)) {
this.groupHeaders.addObject(filmOption.firstLetter);
}
});
}
Explore React Material-UI Avatar docs
This component does not use theme in React. The color of the avatar can be set by @sx
, @class
, or @style
.
The most basic usages are:
This component also adds the attribute @onDisplayed
. If used, the function passed to it will be called when the content
has been displayed. This may be called more than once due to the nature of some components or the way React re-renders.
Explore React Material-UI Avatar docs
An example usage is:
Explore React Material-UI Backdrop docs
The most basic usage is:
Explore React Material-UI Badge docs
The most basic usage is:
This component also adds the attribute @onDisplayed
. If used, the function passed to it will be called when the content
has been displayed. This may be called more than once due to the nature of some components or the way React re-renders.
Explore React Material-UI Button docs
The most basic usage is:
Using the @href
attribute in button will use ember's transitionTo
method so that in app links work as expected. To transition to an external link a fully qualified link should be used: http://...
This component also adds the attribute @onDisplayed
. If used, the function passed to it will be called when the content
has been displayed. This may be called more than once due to the nature of some components or the way React re-renders.
Explore React Material-UI Card docs
The most basic usage is:
In the RPaperCardHeader
the following attributes can be written as children like so:
@title -> <:title>My Title</:title>
@subheader -> <:subheader>My Sub-header</:subheader>
@avatar -> <:avatar>Place an avatar here</:avatar>
@action -> <:action>Place some action Icon here</:action>
@title
and @subheader
have the option of being passed as an argument using @
or being passed as an Attribute Child
for more flexibility.
Explore React Material-UI Checkbox docs
Explore React Material-UI Switch docs
Explore React Material-UI Radio Button docs
The most basic usage is:
The radio component also adds the attribute @onDisplayed
. If used, the function passed to it will be called when the content
has been displayed. This may be called more than once due to the nature of some components or the way React re-renders.
The checkbox component also adds the attribute @nativeOnChange
. If set to true, the @onChange
callback will return the native event
object.
The checked state can be found out event.target.checked
. If not set, or set to false, the @onChange
callback will return the checked state.
Explore React Material-UI Chips docs
The most basic usages are:
A chip can contain an icon or avatar but not both. If an icon and avatar are provided, the icon will be displayed.
Label can also be passed as an attribute node <:label></:label>
to make HTML rendering easier.
Explore React Material-UI Progress docs
The most basic usage is:
This component is usually used with <RPaperBackdrop/>
Explore React Material-UI DatePicker docs
The most basic usages are:
All attributes from LocalizationProvider
are supported. The attribute dateAdapter
defaults to using AdapterMoment
if not specified in the component.
This component supports validation using the following attributes:
Explore React Material-UI DateTimePicker docs
The most basic usages are:
All attributes from LocalizationProvider
are supported. The attribute dateAdapter
defaults to using AdapterMoment
if not specified in the component.
This component supports validation using the following attributes:
Explore React Material-UI Drawers docs
The most basic usages are:
The onClose
handler should close the drawer by setting @open
= false.
This component also adds the attribute @onDisplayed
. If used, the function passed to it will be called when the content
has been displayed. This may be called more than once due to the nature of some components or the way React re-renders.
Explore React Material-UI Dialog docs
The most common usage is:
This component adds the following attributes:
@keepOpenOnClickOutside
- boolean value. If set to true, the dialog will not close if the user clicks outside of the background.@onDisplayed
- If used, the function passed to it will be called when the content has been displayed. This may be called more than once due to the nature of some components or the way React re-renders.
Explore React Material-UI Icon docs
There are four different ways of creating icons, similar to the React Icon specification.
Properties for icons are found in the documentation for Icon
or SvgIcon
.
To use a Font Icon
:
In the head of the index.html
file add the icon fonts you want to use. For example:
To use a Fontawesome Icon
Note: the ember-fontawesome package will not work for react based font awesome icons.
In the ember app:
- In the head of the
index.html
file add the fontawesome fonts you want to use. For example:
To use a React Material Icon
:
In the ember app:
- Install material-ui icons package:
npm install @mui/icons-material
- Import the material-ui icon:
import AccessAlarmRounded from '@mui/icons-material/AccessAlarmRounded';
- Pass the instance of
AccessAlarmRounded
to the@reactIcon
property of<RPaperIcon/>
To use a SVG Icon with path
- Set the
@hasPath
property of<RPaperIcon/>
totrue
- Include a
path
element with ad
attribute. Only 1path
element will work. No attributes will be copied to react.
Explore React Material-UI Fab docs
Basic Usage:
Explore React Material-UI Icon docs
Basic Usage:
The most basic usages are:
Note: RPaperMenu
can use @anchorEl
and provide a function that returns an HTML refernce to the trigger
element. But to make life easier, @triggerId
has been added to the attributes so the trigger element can
be referenced in the HTML.
This component also adds the attribute @onDisplayed
. If used, the function passed to it will be called when the content
has been displayed. This may be called more than once due to the nature of some components or the way React re-renders.
Explore React Material-UI Paper docs
The most basic usage is:
Explore React Material-UI Radio Group docs
The most basic usage is:
Explore React Material-UI Snackbar docs
The most basic usage is:
The basic usage is:
Where this.handleChange
is:
@tracked tabValue = 0;
@action
handleChange(evt, newValue) {
this.tabValue = newValue;
}
This differs slightly from the Material-UI Tabs documentation. With ember-paper-react
@value
is
required on the <RPaperTab/>
component. It behaves as an index.
If used as above, only one RPaperTab
can be used per page because of the aria-controls
and id
fields default values.
If it was desired to have more than one RPaperTab
component per page, the component could be customized like so:
This component can also be used to render router links:
Explore React Material-UI TimePicker docs
The most basic usages are:
All attributes from LocalizationProvider
are supported. The attribute dateAdapter
defaults to using AdapterMoment
if not specified in the component.
This component supports validation using the following attributes:
Explore React Material-UI Textfield docs
The most basic usage is:
Unless @nativeValue
is set to true, the onChange function will return the value. If the event object is desired, set @nativeValue={{true}}
.
Note: this component can also act as a select component. When @select={{true}}
is set, the component will automatically add the object {native:true}
to the selectProps
property. <option/>
tags are the only supported children of this component. When functioning as a select, only native mode is currently supported.
When using the component as a select component, the selected value can be initialized by setting @value
to the value desired. @value
and @onChange
must be set so that the select updates when the user changes the value of the select.
Input Masking
The following Components are available
<RPaperNumberFormatTextField/>
and <RPaperIMaskTextField/>
This component uses all of the regular TextField properties as well as that of ReactNumberFormat.
Explore iMask Docs
The service inputMaskTypes
is available to predefine masks for this component.
export default class TestClass extends Component {
@service inputMaskTypes
constructor() {
super(...arguments);
const currencyNoDecimalIMask = {
mask: '$num',
blocks: {
num: {
mask: Number,
thousandsSeparator: ',',
},
},
};
const percentageWithDecimalIMask = {
mask: [
{
mask: '',
},
{
mask: 'num %',
lazy: false,
blocks: {
num: {
mask: Number,
scale: 3,
min: 1,
max: 100,
radix: '.',
mapToRadix: [','],
},
},
}
]
};
this.inputMaskTypes.addIMaskType(
'currencyNoDecimal',
currencyNoDecimalIMask
);
this.inputMaskTypes.addIMaskType(
'percentageWithDecimal',
percentageWithDecimalIMask
);
}
}
And to use it:
If @nativeOnChange={{true}}
:
The onChange function will return the event object. If nativeOnChange
is not defined or false, the unmasked value will be returned. The event object returns the following object a target object with a value
and maskedValue
.
This component uses all of the regular TextField properties as well as that of ReactNumberFormat Numeric.
Explore React Number Format Docs
This component will only accept numbers as input.
The service inputMaskTypes
is available to predefine masks for this component.
export default class TestClass extends Component {
@service inputMaskTypes
constructor() {
super(...arguments);
const currencyNoDecimalNMask = {
thousandSeparator: true,
prefix: '$ ',
decimalScale: 0,
};
const percentageWithDecimalNFMask = {
suffix: ' %',
decimalScale: 2,
isAllowed: (value) => {
return value.floatValue <= 100 || value.value === '';
},
};
this.inputMaskTypes.addNumberFormatNumericType(
'currencyNoDecimal',
currencyNoDecimalNMask
);
this.inputMaskTypes.addNumberFormatNumericType(
'percentageWithDecimal',
percentageWithDecimalNFMask
);
}
}
And to use it:
If @nativeOnChange={{true}}
:
The onChange function will return the event object. If nativeOnChange
is not defined or false, the unmasked value will be returned. The event object returns the following object a target object with a value
and maskedValue
.
This component will by default select the entire text area when focus is received. If this trait is not desired, the attribute @selectAllOnFocus={{false}}
must be explicitly set.
If @clearOnFocus={{true}}
then instead of selecting the entire area, the value will be cleared. If the user does not set a value, the previous value will be restored.
This component uses all of the regular TextField properties as well as that of ReactNumberFormat Pattern.
Explore React Number Format Docs
This component will only accept numbers as input.
The service inputMaskTypes
is available to predefine masks for this component.
export default class TestClass extends Component {
@service inputMaskTypes
constructor() {
super(...arguments);
const myPatternFormat = {
format: "### ###",
};
this.inputMaskTypes.addNumberFormatPatternType(
'myPattern',
myPatternFormat
);
}
}
And to use it:
If @nativeOnChange={{true}}
:
The onChange function will return the event object. If nativeOnChange
is not defined or false, the unmasked value will be returned. The event object returns the following object a target object with a value
and maskedValue
.
This component will by default select the entire text area when focus is received. If this trait is not desired, the attribute @selectAllOnFocus={{false}}
must be explicitly set.
If @clearOnFocus={{true}}
then instead of selecting the entire area, the value will be cleared. If the user does not set a value, the previous value will be restored.
Explore React Material-UI TimePicker docs
The most basic usages are:
All attributes from LocalizationProvider
are supported. The attribute dateAdapter
defaults to using AdapterMoment
if not specified in the component.
This component supports validation using the following attributes:
Explore React Material-UI Tooltip docs
The most basic usage is:
The @title
parameter can contain html.
This project is licensed under the MIT License.