Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to add custom format? #178

Open
lukaszrys opened this issue Nov 14, 2019 · 2 comments
Open

Is it possible to add custom format? #178

lukaszrys opened this issue Nov 14, 2019 · 2 comments

Comments

@lukaszrys
Copy link

The original plugin (http://schemaform.io/examples/bootstrap-example.html) has the Color pallette in "Kitchen Sink - More stuff").

Unfortunately, I do not see this one here. Is it possible to create it?

@stevehu
Copy link
Contributor

stevehu commented Nov 14, 2019

It looks pretty cool and I think it is very easy to implement it. The look and feel might be a little different since we are using the material-ui instead of bootstrap. There might be other material-ui components available thought. Would you like to try it out and submit a PR?

https://material-ui.com/customization/color/

@naeemba
Copy link
Contributor

naeemba commented Nov 14, 2019

@lukaszrys I think you can add any component to your list of available components, the SchemaForm component that you can import it using import { SchemaForm } from 'react-schema-form' accepts a property named mapper, the mapper is an object which can be like this

const mapper = {
	'my-own-color-picker': YourColorPicker,
	.... other components that you want to use in your forms
}

In your component you can debug the probs, they are straight forward, also it may help to use our color picker: if you are implementing your color picker, consider the ComposedComponent which may be required, also utils can be totally helpful during the implementation.

// @flow
import React from 'react';
import { CirclePicker, ChromePicker } from 'react-color';
import Icon from '@material-ui/core/Icon';
import Dialog from 'packages/common/web/dialog';
import Typography from '@material-ui/core/Typography';
import { withStyles } from '@material-ui/core/styles';
import Collapse from '@material-ui/core/Collapse';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import IconButton from '@material-ui/core/IconButton';
import ColorizeIcon from '@material-ui/icons/Colorize';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
import type { SchemaFormLocalization } from 'packages/common/shared/types';
import { ComposedComponent, utils } from 'react-schema-form';
import { colorDialogStyles as styles } from './styles';

type Props = {
  form: {
    className: string,
    key: string,
    readonly: boolean,
    title: string,
    required: boolean,
    style: any,
  },
  onChange: (key: string, value: string) => void,
  model: any,
  classes: any,
  localization: SchemaFormLocalization,
};

type State = {
  open: boolean,
  color: string,
  selectedColor: string,
  disabled: boolean,
  colorPickerOpen: boolean,
};

class ColorSelect extends React.Component<Props, State> {
  state = {
    open: false,
    color: '',
    disabled: true,
    selectedColor: '',
    colorPickerOpen: false,
  };

  static getDerivedStateFromProps(nextProps: Props, prevState: State) {
    if (prevState.color == null || prevState.color === '') {
      return {
        color: '',
      };
    }

    return null;
  }

  componentDidMount() {
    this.setColor();
  }

  setColor = () => {
    const { form, model } = this.props;
    const color = utils.selectOrSet(form.key, model);
    this.setState({
      color: color || '',
      selectedColor: color || '',
    });
  };

  open = () => {
    this.setState({ open: true });
  };

  handleClose = () => {
    this.setState({ open: false });
  };

  onChangeColor = color => {
    this.setState({ selectedColor: color.hex, disabled: false });
  };

  submit = () => {
    const { selectedColor } = this.state;
    const {
      form: { key },
      onChange,
    } = this.props;
    onChange(key, selectedColor);
    this.setState({ color: selectedColor, open: false, disabled: true });
  };

  colorPickerOpenHandle = () => {
    this.setState(state => ({ colorPickerOpen: !state.colorPickerOpen }));
  };

  render() {
    const {
      classes,
      form: { title, required, style },
      localization: { getLocalizedString },
    } = this.props;

    const label = getLocalizedString(title) + (required ? ' *' : '');

    const {
      disabled,
      selectedColor,
      colorPickerOpen,
      color,
      open,
    } = this.state;

    const colors = [
      '#D50000',
      '#F44336',
      '#e81d62',
      '#9C27B0',
      '#7341f2',
      '#3F51B5',
      '#2196F3',
      '#03A9F4',
      '#00BCD4',
      '#009688',
      '#4CAF50',
      '#8ac249',
      '#CDDC39',
      '#FFEB3B',
      '#FFC107',
      '#fe9700',
      '#fe5621',
      '#795548',
      '#9E9E9E',
      '#607D8B',
    ];

    return (
      <div style={style}>
        <div className={classes.div}>
          <IconButton onClick={this.open}>
            <Icon style={{ color }}>
              {selectedColor ? 'lens' : 'panorama_fish_eye'}
            </Icon>
          </IconButton>
          <Typography component="span" className={classes.title}>
            {label}
          </Typography>
        </div>
        <Dialog
          title={getLocalizedString('form.select.color')}
          open={open}
          onClose={this.handleClose}
          classes={{
            paper: classes.colorDialog,
            content: classes.colorDialogContent,
          }}
          actions={[
            {
              label: getLocalizedString('clear'),
              onClick: () => {
                this.setState(
                  {
                    selectedColor: '',
                  },
                  this.submit
                );
                this.handleClose();
              },
            },
            {
              label: getLocalizedString('submit'),
              type: 'primary',
              onClick: this.submit,
              disabled,
            },
          ]}
        >
          <List>
            <ListItem>
              <CirclePicker
                width="185px"
                circleSize={23}
                color={selectedColor}
                colors={colors}
                onChange={this.onChangeColor}
              />
            </ListItem>
            <ListItem button onClick={this.colorPickerOpenHandle}>
              <ListItemIcon className={classes.colorizeIcon}>
                <ColorizeIcon />
              </ListItemIcon>
              <ListItemText primary="Color Picker" />
              {colorPickerOpen ? <ExpandLess /> : <ExpandMore />}
            </ListItem>
            <Collapse in={colorPickerOpen} timeout="auto" unmountOnExit>
              <ChromePicker
                color={selectedColor}
                onChange={this.onChangeColor}
              />
            </Collapse>
          </List>
        </Dialog>
      </div>
    );
  }
}

export default withStyles(styles)(ComposedComponent(ColorSelect));

At the end you can use this with your form object which you should pass to SchemaForm like this:

{ key: 'color', type: 'my-own-color-picker'}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants