Adding New Component Props Inside CreateTheme V5 - material-ui

How can I add new props to a component inside createTheme in version 5? I see how to add new variants but not new props. Also is there a way to know what TypeScript interfaces there are to extend / augment for this purpose?
Below seems like an example of how to add a variant, however I want "hoverable" to be a prop.
Example:
MuiCard: {
variants: [
{
props: { variant: "hoverable" },
style: {
"&:hover": {
boxShadow: "0px 12px 30px rgba(37, 15, 127, 0.08)",
},
},
},
],
}
TypeScript ( This doesnt seem right / work ):
declare module "#material-ui/core/Card" {
interface CardPropsVariantsOverrides {
hoverable: true;
}
}

This is how I'd do it (taken from mui.com)
import * as React from 'react';
import { styled, createTheme, ThemeProvider } from '#mui/system';
interface MyThemeComponentProps {
color?: 'primary' | 'secondary';
variant?: 'normal' | 'dashed';
}
const customTheme = createTheme({
components: {
MyThemeComponent: {
styleOverrides: {
root: {
color: 'darkslategray',
},
primary: {
color: 'darkblue',
},
secondary: {
color: 'darkred',
backgroundColor: 'pink',
},
},
variants: [
{
props: { variant: 'dashed', color: 'primary' },
style: {
border: '1px dashed darkblue',
},
},
{
props: { variant: 'dashed', color: 'secondary' },
style: {
border: '1px dashed darkred',
},
},
],
},
},
});
const MyThemeComponent = styled('div', {
// Configure which props should be forwarded on DOM
shouldForwardProp: (prop) => prop !== 'color' && prop !== 'variant',
name: 'MyThemeComponent',
slot: 'Root',
// We are specifying here how the styleOverrides are being applied based on props
overridesResolver: (props, styles) => [
styles.root,
props.color === 'primary' && styles.primary,
props.color === 'secondary' && styles.secondary,
],
})<MyThemeComponentProps>(({ theme }) => ({
backgroundColor: 'aliceblue',
padding: theme.spacing(1),
}));
export default function UsingOptions() {
return (
<ThemeProvider theme={customTheme}>
<MyThemeComponent sx={{ m: 1 }} color="primary" variant="dashed">
Primary
</MyThemeComponent>
<MyThemeComponent sx={{ m: 1 }} color="secondary">
Secondary
</MyThemeComponent>
</ThemeProvider>
);
}

The error you're getting, should be something like this -
The types of 'props.variant' are incompatible between these types.
Type 'string' is not assignable to type '"dashed" | "outlined" | "text" | "contained" | undefined'.
It says, variant can only accept '"hoverable" | "outlined" | "text" | "contained" | undefined'
Try using props: { variant: "hoverable" as const } instead of props: { variant: "hoverable" }.
For more detail on this typescript issue check - Typescript Type 'string' is not assignable to type

Related

Display all row instead of 3 row

Goal:
Display all row in the in table at the same time.
Problem:
It display only 3 row at the same time in the table.
I would like to display all row at the same time without any limitation.
It doesn't work to use "height: '100%'"
Any idea?
Codesandbox:
https://codesandbox.io/s/mkd4dw?file=/demo.tsx
Thank you!
demo.tsx
import * as React from 'react';
import Box from '#mui/material/Box';
import Rating from '#mui/material/Rating';
import {
DataGrid,
GridRenderCellParams,
GridColDef,
useGridApiContext,
} from '#mui/x-data-grid';
function renderRating(params: GridRenderCellParams<number>) {
return <Rating readOnly value={params.value} />;
}
function RatingEditInputCell(props: GridRenderCellParams<number>) {
const { id, value, field } = props;
const apiRef = useGridApiContext();
const handleChange = (event: React.SyntheticEvent, newValue: number | null) => {
apiRef.current.setEditCellValue({ id, field, value: newValue });
};
const handleRef = (element: HTMLSpanElement) => {
if (element) {
const input = element.querySelector<HTMLInputElement>(
`input[value="${value}"]`,
);
input?.focus();
}
};
return (
<Box sx={{ display: 'flex', alignItems: 'center', pr: 2 }}>
<Rating
ref={handleRef}
name="rating"
precision={1}
value={value}
onChange={handleChange}
/>
</Box>
);
}
const renderRatingEditInputCell: GridColDef['renderCell'] = (params) => {
return <RatingEditInputCell {...params} />;
};
export default function CustomEditComponent() {
return (
<div style={{ height: 250, width: '100%' }}>
<DataGrid
rows={rows}
columns={columns}
experimentalFeatures={{ newEditingApi: true }}
/>
</div>
);
}
const columns = [
{
field: 'places',
headerName: 'Places',
width: 120,
},
{
field: 'rating',
headerName: 'Rating',
renderCell: renderRating,
renderEditCell: renderRatingEditInputCell,
editable: true,
width: 180,
type: 'number',
},
];
const rows = [
{ id: 1, places: 'Barcelona', rating: 5 },
{ id: 2, places: 'Rio de Janeiro', rating: 4 },
{ id: 3, places: 'London', rating: 3 },
{ id: 4, places: 'New York', rating: 2 },
];
You need to make use of autoHeight prop supported by the <DataGrid /> component, update your DataGrid component usage to this:
<DataGrid
autoHeight
rows={rows}
columns={columns}
experimentalFeatures={{ newEditingApi: true }}
/>
Reference: https://mui.com/x/react-data-grid/layout/#auto-height

how do i remove the outline on focus in DataGrid

I'm trying to remove the outline that appears when you focus on a cell in Material UI's DataGrid component.
None of these methods work:
const useStyles = makeStyles((theme) => ({
// Method 1:
'#global': {
'.MuiDataGrid-cell:focus': {
outline: 0,
},
},
// Method 2:
cell: {
'& .MuiDataGrid-cell:focus': {
outline: 0,
},
},
// Method 3:
cell: {
':focus': { outline: 0 },
},
const classes = useStyles()
const dataGridColumns: GridColumns = [
{
...other,
cellClassName: classes.cell,
}]
Edit:
'#global': {
'.MuiDataGrid-root .MuiDataGrid-cell:focus': {
outline: 0,
},
},
worked for me, but I would prefer not to use a global css adjustment.
You can modify the MuiDataGrid-cell class by using Material UI's useStyles() function like the following (no need to declare globally):
import { makeStyles } from '#material-ui/core/styles';
import { DataGrid } from '#material-ui/data-grid';
const useStyles = makeStyles({
root: {
'&.MuiDataGrid-root .MuiDataGrid-cell:focus': {
outline: 'none',
},
}
});
const MyComponent = () => {
const classes = useStyles();
return (
<DataGrid
className={classes.root}
// ...other table setup props
/>
);
}
export default MyComponent;
Resources:
https://material-ui.com/styles/advanced/#with-material-ui-core
https://material-ui.com/api/data-grid/#css
https://github.com/mui-org/material-ui-x/issues/420
Edit: Updated for 4.0.0-alpha.29
const useStyles = makeStyles({
root: {
'&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus, &.MuiDataGrid-root .MuiDataGrid-cell:focus': {
outline: 'none',
},
}
});
Just for completion sake this is how I styled the DataGrid with styled components and it worked.
const StyledDataGrid = styled(DataGrid)`
&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus,
&.MuiDataGrid-root .MuiDataGrid-cell:focus {
outline: none;
}
`;
If you're using MUI >= 5, you can simply do the follow:
<DataGrid
sx={{
"&.MuiDataGrid-root .MuiDataGrid-cell:focus-within": {
outline: "none !important",
},
}}
...
/>
const useStyles = makeStyles(
() => createStyles({
root: {
'& .MuiDataGrid-columnHeader:focus-within, & .MuiDataGrid-cell:focus-within': {
outline: 'none',
},
'& .MuiDataGrid-columnHeader:focus, & .MuiDataGrid-cell:focus': {
outline: 'none',
},
},
}),
);
I just needed to do this as well for a project I'm working on.
You can override many of the classes used by the datagrid, but you'll need to make sure that the selector being used is more specific in order for it to take precedence.
Many of their classes are documented here in the CSS section.
The below snippet worked for me.
const useStyles = makeStyles((theme) => ({
root: {
"& .MuiDataGrid-root": {
"& .MuiDataGrid-colCell:focus": {
outline: "none"
},
},
},
}));
The perfect way for me was add this code to your css file:
.MuiDataGrid-root .MuiDataGrid-columnHeader,
.MuiDataGrid-root .MuiDataGrid-cell {
outline: none !important;
}
I found that if we set it just for :focus, then if we click to a button of cell, outline still visible

Search bar in React Native not updating or filtering

I'm trying to set up data filtering by SearchBar from react-native-elements. I'm returning some data from the server in a JSON format so it arrives in this form of an Array of Objects.
This is what I have so far:
export default function AktList() {
const [akt, setAkt] = useState([]);
const [temp, setTemp] = useState([]);
async function request() {
fetch("http://192.168.5.12:5000/aktprikaz", {
method: "get"
})
.then(res => res.json())
.then(res => setAkt(res))
.then(temp => setTemp(akt));
}
useEffect(() => {
request();
}, []);
function Item({ title, selected }) {
return (
<TouchableOpacity
onPress={() => console.log(temp)}
style={[
styles.item,
{ backgroundColor: selected ? "#6e3b6e" : "#f9c2ff" }
]}
>
<Text style={styles.title}>{title}</Text>
</TouchableOpacity>
);
}
function contains(text) {
const newData = temp.filter(item => {
const itemData = {title};
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
setAkt(newData);
}
return (
<SafeAreaView style={styles.container}>
<Header />
<SearchBar onChangeText={text => contains(text)} />
<FlatList
data={akt}
renderItem={({ item }) => <Item title={item.title} />}
keyExtractor={item => item.id}
/>
</SafeAreaView>
);
}
Currently, nor is the text updating nor is it filter anything. I've tried following this tutorial online (tho it is written using classes not functions). What am I doing wrong here?
Check below example which i created using flatlist and TextInput. Items are displayed in the form of a dropdown list when you search items. i think this will help you.
import React, { Component } from 'react';
import { View, Text, FlatList, TextInput, ListItem } from 'react-native';
class FlatListDropDown extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
value: '',
};
this.arrayNew = [
{ name: 'Robert' },
{ name: 'Bryan' },
{ name: 'Vicente' },
{ name: 'Tristan' },
{ name: 'Marie' },
{ name: 'Onni' },
{ name: 'sophie' },
{ name: 'Brad' },
{ name: 'Samual' },
{ name: 'Omur' },
{ name: 'Ower' },
{ name: 'Awery' },
{ name: 'Ann' },
{ name: 'Jhone' },
{ name: 'z' },
{ name: 'bb' },
{ name: 'cc' },
{ name: 'd' },
{ name: 'e' },
{ name: 'f' },
{ name: 'g' },
{ name: 'h' },
{ name: 'i' },
{ name: 'j' },
{ name: 'k' },
{ name: 'l' },
];
}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: '100%',
backgroundColor: '#CED0CE',
}}
/>
);
};
searchItems = text => {
const newData = this.arrayNew.filter(item => {
const itemData = `${item.name.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
this.setState({
data: newData,
value: text,
});
};
renderHeader = () => {
return (
<TextInput
style={{ height: 60, borderColor: '#000', borderWidth: 1 }}
placeholder=" Type Here...Key word"
onChangeText={text => this.searchItems(text)}
value={this.state.value}
/>
);
};
render() {
return (
<View
style={{
flex: 1,
padding: 25,
width: '98%',
alignSelf: 'center',
justifyContent: 'center',
}}>
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<Text style={{ padding: 10 }}>{item.name} </Text>
)}
keyExtractor={item => item.name}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
/>
</View>
);
}
}
export default FlatListDropDown;
Feel free for doubts.

Highcharts :Donut chart overlaps data labels

I'm working on a donut chart type, with the Highcharts library.
As you can see in the image below, some of the inner data labels are overlapped.
I've been playing with the parameter "distance" but doesn't fix this.
Find attached the code below,
// Create the chart
$(container).highcharts({
chart: {
type: 'pie'
},
credits: {
enabled: false
},
exporting: {
buttons: {
contextButton: {
symbol: 'url(/icon-turn-down.png)'
}
}
},
title: {
text: _title,
margin: 50
},
plotOptions: {
pie: {
shadow: false,
center: ['50%', '50%']
}
},
tooltip: {
formatter: function() {
var s = this.point.name.split('.');
if (s.length == 1) {
return this.y > 1? '<b>'+this.point.name+':</b> '+Highcharts.numberFormat(this.point.y) : null;
}
return this.y > 1? s[0]+'<br /><b>'+$.trim(s[1])+':</b> '+Highcharts.numberFormat(this.point.y) : null;
}
},
series: [{
name: '',
data: innerData,
size: '80%',
dataLabels: {
formatter: function() {
return this.y > 0 ? this.point.name : null;
},
color: 'white',
distance: -50
}
}, {
name: '',
data: outerData,
size: '100%',
innerSize: '80%',
dataLabels: {
formatter: function() {
var s = this.point.name.split('.');
if (s.length == 1) {
return this.y > 1 ? '<b>'+ this.point.name+':</b> '+ Highcharts.numberFormat(this.point.y) : null ;
}
s = this.point.name.substring(this.point.name.indexOf(".")+2);
return this.y > 1 ? '<b>'+ s+':</b> '+ Highcharts.numberFormat(this.point.y): null;
},
style: {
fontSize: "10px",
fontColor: "#000000"
}
}
}]
});
Finally, I found a solution, which is playing with the "startangle" attribute.
series: [{
name: '',
data: innerData,
startAngle:110,
size: '80%',
dataLabels: {
formatter: function() {
return this.y > 0 ? this.point.name : null;
},
color: 'white',
distance: -45
}, {
...
Distance parameter cannot be applied for each point, only general, so only what comes to my mind is iteared on each datalabel and use translate() function, or use formatter, apply CSS class and dhten use top/left parameter for each element. But will be helpful if you recreate your example as fiddle.

Extjs chart shadow

I have the following code to contruct a pie chart.
The problem is i don't get a shadow.
Note : If the chart config, theme='Base', then the pie has a shadow
Ext.define('ChartPanel', {
extend: 'Ext.panel.Panel',
//------------------CONSTRUCTOR
, constructor: function(externalConfigs) {
externalConfigs = externalConfigs || {};
var configs = {
title: 'My panel',
items: [
{
xtype: 'chart',
store: myStore,
width: '30%',
series: [{
type: 'pie'
, field: 'persentage'
, shadow: 'sides'
, showInLegend: false
, donut: false
, renderer: function(sprite, record, attributes, index, store) {
if (record.data.description == 'option1') {
sprite.setAttributes({
fill: 'url(#redGradient)',
stroke: '#ffffff'
}, false);
} else if (record.data.description == 'option2') {
sprite.setAttributes({
fill: 'url(#greenGradient)',
stroke: '#ffffff'
}, false);
}
}
}]
, gradients: [{
id: 'redGradient',
angle: 45,
stops: {
0: { color: '#820000' },
100: { color: '#BD1E00' }
}
}, {
id: 'greenGradient',
angle: 0,
stops: {
0: { color: '#89AC10' },
100: { color: '#A1C22D' }
}
}]
}
]
}
Ext.apply(configs, externalConfigs);
this.callParent([configs]); //Call the parent constructor
}
});
Any ideas how to get a shadow?
Thanks
Use shadow: true (see the docs in the previous link to see other possible options) within your chart definition. (Not within the pie definition). There is no shadow config property for Ext.chart.series.Pie. You would need to use shadowAttributes within Ext.chart.series.Pie.
I found that
return attributes;
inside the renderer is essential.