@pie-lib/config-ui 9.0.3-next.2 → 10.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CHANGELOG.json +605 -0
  2. package/CHANGELOG.md +976 -328
  3. package/lib/alert-dialog.js +44 -0
  4. package/lib/alert-dialog.js.map +1 -0
  5. package/lib/checkbox.js +5 -5
  6. package/lib/checkbox.js.map +1 -1
  7. package/lib/choice-configuration/feedback-menu.js +42 -54
  8. package/lib/choice-configuration/feedback-menu.js.map +1 -1
  9. package/lib/choice-configuration/index.js +102 -86
  10. package/lib/choice-configuration/index.js.map +1 -1
  11. package/lib/choice-utils.js +9 -7
  12. package/lib/choice-utils.js.map +1 -1
  13. package/lib/feedback-config/feedback-selector.js +45 -49
  14. package/lib/feedback-config/feedback-selector.js.map +1 -1
  15. package/lib/feedback-config/group.js +13 -13
  16. package/lib/feedback-config/group.js.map +1 -1
  17. package/lib/feedback-config/index.js +57 -56
  18. package/lib/feedback-config/index.js.map +1 -1
  19. package/lib/form-section.js +19 -15
  20. package/lib/form-section.js.map +1 -1
  21. package/lib/help.js +31 -38
  22. package/lib/help.js.map +1 -1
  23. package/lib/index.js +73 -52
  24. package/lib/index.js.map +1 -1
  25. package/lib/input.js +36 -41
  26. package/lib/input.js.map +1 -1
  27. package/lib/inputs.js +42 -29
  28. package/lib/inputs.js.map +1 -1
  29. package/lib/langs.js +38 -46
  30. package/lib/langs.js.map +1 -1
  31. package/lib/layout/config-layout.js +36 -42
  32. package/lib/layout/config-layout.js.map +1 -1
  33. package/lib/layout/index.js +3 -3
  34. package/lib/layout/index.js.map +1 -1
  35. package/lib/layout/layout-contents.js +35 -35
  36. package/lib/layout/layout-contents.js.map +1 -1
  37. package/lib/layout/settings-box.js +29 -40
  38. package/lib/layout/settings-box.js.map +1 -1
  39. package/lib/mui-box/index.js +4 -4
  40. package/lib/mui-box/index.js.map +1 -1
  41. package/lib/number-text-field-custom.js +364 -0
  42. package/lib/number-text-field-custom.js.map +1 -0
  43. package/lib/number-text-field.js +46 -46
  44. package/lib/number-text-field.js.map +1 -1
  45. package/lib/radio-with-label.js +5 -5
  46. package/lib/radio-with-label.js.map +1 -1
  47. package/lib/settings/display-size.js +12 -10
  48. package/lib/settings/display-size.js.map +1 -1
  49. package/lib/settings/index.js +81 -14
  50. package/lib/settings/index.js.map +1 -1
  51. package/lib/settings/panel.js +297 -79
  52. package/lib/settings/panel.js.map +1 -1
  53. package/lib/settings/settings-radio-label.js +43 -0
  54. package/lib/settings/settings-radio-label.js.map +1 -0
  55. package/lib/settings/toggle.js +9 -7
  56. package/lib/settings/toggle.js.map +1 -1
  57. package/lib/tabs/index.js +29 -36
  58. package/lib/tabs/index.js.map +1 -1
  59. package/lib/tags-input/index.js +33 -41
  60. package/lib/tags-input/index.js.map +1 -1
  61. package/lib/two-choice.js +46 -50
  62. package/lib/two-choice.js.map +1 -1
  63. package/lib/with-stateful-model.js +24 -31
  64. package/lib/with-stateful-model.js.map +1 -1
  65. package/package.json +9 -7
  66. package/src/alert-dialog.jsx +43 -0
  67. package/src/checkbox.jsx +63 -0
  68. package/src/choice-configuration/feedback-menu.jsx +103 -0
  69. package/src/choice-configuration/index.jsx +319 -0
  70. package/src/choice-utils.js +30 -0
  71. package/src/feedback-config/feedback-selector.jsx +116 -0
  72. package/src/feedback-config/group.jsx +54 -0
  73. package/src/feedback-config/index.jsx +98 -0
  74. package/src/form-section.jsx +23 -0
  75. package/src/help.jsx +88 -0
  76. package/src/index.js +58 -0
  77. package/src/input.jsx +72 -0
  78. package/src/inputs.jsx +96 -0
  79. package/src/langs.jsx +122 -0
  80. package/src/layout/config-layout.jsx +64 -0
  81. package/src/layout/index.js +4 -0
  82. package/src/layout/layout-contents.jsx +60 -0
  83. package/src/layout/settings-box.jsx +31 -0
  84. package/src/mui-box/index.jsx +64 -0
  85. package/src/number-text-field-custom.jsx +276 -0
  86. package/src/number-text-field.jsx +196 -0
  87. package/src/radio-with-label.jsx +18 -0
  88. package/src/settings/display-size.jsx +52 -0
  89. package/src/settings/index.js +75 -0
  90. package/src/settings/panel.jsx +297 -0
  91. package/src/settings/settings-radio-label.jsx +20 -0
  92. package/src/settings/toggle.jsx +31 -0
  93. package/src/tabs/index.jsx +51 -0
  94. package/src/tags-input/index.jsx +121 -0
  95. package/src/two-choice.jsx +94 -0
  96. package/src/with-stateful-model.jsx +36 -0
  97. package/NEXT.CHANGELOG.json +0 -1
  98. package/__mocks__/@pie-lib/editable-html.jsx +0 -3
  99. package/lib/input-container.js +0 -59
  100. package/lib/input-container.js.map +0 -1
@@ -0,0 +1,98 @@
1
+ import FeedbackSelector, { FeedbackType } from './feedback-selector';
2
+ import PropTypes from 'prop-types';
3
+ import React from 'react';
4
+ import { withStyles } from '@material-ui/core/styles';
5
+ import ExpansionPanel from '@material-ui/core/ExpansionPanel';
6
+ import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
7
+ import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
8
+ import Typography from '@material-ui/core/Typography';
9
+ import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
10
+ import merge from 'lodash/merge';
11
+
12
+ export { FeedbackSelector };
13
+
14
+ const style = {
15
+ feedbackContainer: {
16
+ display: 'flex',
17
+ flexDirection: 'column'
18
+ }
19
+ };
20
+
21
+ export const buildDefaults = input => {
22
+ return merge(
23
+ {},
24
+ {
25
+ correct: { type: 'default', default: 'Correct' },
26
+ incorrect: { type: 'default', default: 'Incorrect' },
27
+ partial: { type: 'default', default: 'Nearly' }
28
+ },
29
+ input
30
+ );
31
+ };
32
+
33
+ export class FeedbackConfig extends React.Component {
34
+ static propTypes = {
35
+ allowPartial: PropTypes.bool,
36
+ feedback: PropTypes.shape({
37
+ correct: PropTypes.shape(FeedbackType),
38
+ incorrect: PropTypes.shape(FeedbackType),
39
+ partial: PropTypes.shape(FeedbackType)
40
+ }),
41
+ onChange: PropTypes.func.isRequired,
42
+ classes: PropTypes.object.isRequired,
43
+ toolbarOpts: PropTypes.object
44
+ };
45
+
46
+ static defaultProps = {
47
+ allowPartial: true,
48
+ feedback: buildDefaults()
49
+ };
50
+
51
+ onChange(key, config) {
52
+ const { feedback, onChange } = this.props;
53
+ const update = { ...feedback, [key]: config };
54
+ onChange(update);
55
+ }
56
+
57
+ onCorrectChange = this.onChange.bind(this, 'correct');
58
+ onIncorrectChange = this.onChange.bind(this, 'incorrect');
59
+ onPartialChange = this.onChange.bind(this, 'partial');
60
+
61
+ render() {
62
+ const { classes, allowPartial, feedback, toolbarOpts } = this.props;
63
+
64
+ return (
65
+ <ExpansionPanel>
66
+ <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
67
+ <Typography className={classes.heading}>Feedback</Typography>
68
+ </ExpansionPanelSummary>
69
+ <ExpansionPanelDetails>
70
+ <div className={classes.feedbackContainer}>
71
+ <FeedbackSelector
72
+ label="If correct, show"
73
+ feedback={feedback.correct}
74
+ onChange={this.onCorrectChange}
75
+ toolbarOpts={toolbarOpts}
76
+ />
77
+ {allowPartial && (
78
+ <FeedbackSelector
79
+ label="If partially correct, show"
80
+ feedback={feedback.partial}
81
+ onChange={this.onPartialChange}
82
+ toolbarOpts={toolbarOpts}
83
+ />
84
+ )}
85
+ <FeedbackSelector
86
+ label="If incorrect, show"
87
+ feedback={feedback.incorrect}
88
+ onChange={this.onIncorrectChange}
89
+ toolbarOpts={toolbarOpts}
90
+ />
91
+ </div>
92
+ </ExpansionPanelDetails>
93
+ </ExpansionPanel>
94
+ );
95
+ }
96
+ }
97
+
98
+ export default withStyles(style)(FeedbackConfig);
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import Typography from '@material-ui/core/Typography';
3
+ import classNames from 'classnames';
4
+ import { withStyles } from '@material-ui/core/styles';
5
+
6
+ const styles = theme => ({
7
+ formSection: {
8
+ marginTop: theme.spacing.unit * 2,
9
+ marginBottom: theme.spacing.unit * 2
10
+ },
11
+ label: {
12
+ marginBottom: theme.spacing.unit
13
+ }
14
+ });
15
+
16
+ export default withStyles(styles)(({ className, classes, label, children, labelExtraStyle }) => (
17
+ <div className={classNames(classes.formSection, className)}>
18
+ <Typography className={classes.label} type="subheading" style={labelExtraStyle}>
19
+ {label}
20
+ </Typography>
21
+ {children}
22
+ </div>
23
+ ));
package/src/help.jsx ADDED
@@ -0,0 +1,88 @@
1
+ import Dialog from '@material-ui/core/Dialog';
2
+ import DialogTitle from '@material-ui/core/DialogTitle';
3
+ import DialogContentText from '@material-ui/core/DialogContentText';
4
+ import DialogContent from '@material-ui/core/DialogContent';
5
+ import DialogActions from '@material-ui/core/DialogActions';
6
+ import PropTypes from 'prop-types';
7
+
8
+ import Button from '@material-ui/core/Button';
9
+ import HelpIcon from '@material-ui/icons/Help';
10
+ import IconButton from '@material-ui/core/IconButton';
11
+ import React from 'react';
12
+ import { withStyles } from '@material-ui/core/styles';
13
+
14
+ const RawHelpButton = ({ onClick, classes }) => (
15
+ <IconButton
16
+ classes={{
17
+ label: classes.icon
18
+ }}
19
+ onClick={onClick}
20
+ >
21
+ <HelpIcon />
22
+ </IconButton>
23
+ );
24
+ RawHelpButton.propTypes = {
25
+ onClick: PropTypes.func,
26
+ classes: PropTypes.object.isRequired
27
+ };
28
+
29
+ export const HelpButton = withStyles({
30
+ icon: {
31
+ '&:hover': {
32
+ color: '#ddd'
33
+ }
34
+ }
35
+ })(RawHelpButton);
36
+
37
+ export const HelpDialog = ({ open, onClose, children, title }) => (
38
+ <Dialog open={open} onRequestClose={onClose}>
39
+ <DialogTitle>{title}</DialogTitle>
40
+ <DialogContent>
41
+ <DialogContentText>{children}</DialogContentText>
42
+ </DialogContent>
43
+ <DialogActions>
44
+ <Button onClick={onClose} color="primary">
45
+ OK
46
+ </Button>
47
+ </DialogActions>
48
+ </Dialog>
49
+ );
50
+
51
+ HelpDialog.propTypes = {
52
+ open: PropTypes.bool,
53
+ onClose: PropTypes.func,
54
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
55
+ title: PropTypes.string.isRequired
56
+ };
57
+
58
+ class Help extends React.Component {
59
+ static propTypes = {
60
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
61
+ title: PropTypes.string
62
+ };
63
+
64
+ constructor(props) {
65
+ super(props);
66
+ this.state = {
67
+ open: false
68
+ };
69
+ }
70
+
71
+ render() {
72
+ const { children, title } = this.props;
73
+ return (
74
+ <div>
75
+ <HelpButton color="accent" onClick={() => this.setState({ open: true })} />
76
+ <HelpDialog
77
+ open={this.state.open}
78
+ title={title}
79
+ onClose={() => this.setState({ open: false })}
80
+ >
81
+ {children}
82
+ </HelpDialog>
83
+ </div>
84
+ );
85
+ }
86
+ }
87
+
88
+ export default Help;
package/src/index.js ADDED
@@ -0,0 +1,58 @@
1
+ import AlertDialog from './alert-dialog';
2
+ import FeedbackConfig, {
3
+ FeedbackSelector,
4
+ buildDefaults as feedbackConfigDefaults
5
+ } from './feedback-config';
6
+ import { InputCheckbox, InputSwitch, InputRadio } from './inputs';
7
+ import Langs, { LanguageControls } from './langs';
8
+ import Tabs from './tabs';
9
+ import Checkbox from './checkbox';
10
+ import FormSection from './form-section';
11
+ import Help from './help';
12
+ import Input from './input';
13
+ import { InputContainer } from '@pie-lib/render-ui';
14
+ import NumberTextField from './number-text-field';
15
+ import NumberTextFieldCustom from './number-text-field-custom';
16
+ import TwoChoice, { NChoice } from './two-choice';
17
+ import TagsInput from './tags-input';
18
+ import MuiBox from './mui-box';
19
+ import ChoiceConfiguration from './choice-configuration';
20
+ import * as layout from './layout';
21
+
22
+ import * as choiceUtils from './choice-utils';
23
+ import withStatefulModel from './with-stateful-model';
24
+ import Toggle from './settings/toggle';
25
+ import DisplaySize from './settings/display-size';
26
+
27
+ import * as settings from './settings';
28
+
29
+ export {
30
+ AlertDialog,
31
+ FeedbackConfig,
32
+ FeedbackSelector,
33
+ feedbackConfigDefaults,
34
+ InputCheckbox,
35
+ InputSwitch,
36
+ InputRadio,
37
+ Langs,
38
+ LanguageControls,
39
+ Tabs,
40
+ Checkbox,
41
+ FormSection,
42
+ Help,
43
+ Input,
44
+ InputContainer,
45
+ NumberTextField,
46
+ NumberTextFieldCustom,
47
+ TwoChoice,
48
+ NChoice,
49
+ TagsInput,
50
+ MuiBox,
51
+ ChoiceConfiguration,
52
+ layout,
53
+ choiceUtils,
54
+ withStatefulModel,
55
+ Toggle,
56
+ DisplaySize,
57
+ settings
58
+ };
package/src/input.jsx ADDED
@@ -0,0 +1,72 @@
1
+ import * as React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { default as MaterialInput } from '@material-ui/core/Input';
4
+ import { InputContainer } from '@pie-lib/render-ui';
5
+
6
+ export default class Input extends React.Component {
7
+ static propTypes = {
8
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
9
+ onChange: PropTypes.func.isRequired,
10
+ label: PropTypes.string,
11
+ type: PropTypes.string.isRequired,
12
+ error: PropTypes.func,
13
+ noModelUpdateOnError: PropTypes.bool
14
+ };
15
+
16
+ static defaultProps = {
17
+ type: 'text',
18
+ error: (value, type) => (type === 'number' ? !value || isNaN(value) : !value),
19
+ noModelUpdateOnError: false
20
+ };
21
+
22
+ constructor(props) {
23
+ super(props);
24
+
25
+ this.state = {
26
+ value: props.value
27
+ };
28
+ }
29
+
30
+ componentWillReceiveProps(newProps) {
31
+ this.setState({
32
+ value: newProps.value
33
+ });
34
+ }
35
+
36
+ onChange = event => {
37
+ const { type, onChange, error } = this.props;
38
+ const value = event.target.value;
39
+
40
+ if (error(value, type)) {
41
+ this.setState({
42
+ error: true,
43
+ value: event.target.value
44
+ });
45
+ } else {
46
+ this.setState({
47
+ error: false,
48
+ value: event.target.value
49
+ });
50
+
51
+ onChange(event);
52
+ }
53
+ };
54
+
55
+ render() {
56
+ const {
57
+ label,
58
+ type,
59
+ noModelUpdateOnError, // eslint-disable-line no-unused-vars
60
+ ...rest
61
+ } = this.props;
62
+ const { value, error } = this.state;
63
+
64
+ return label ? (
65
+ <InputContainer label={label}>
66
+ <MaterialInput type={type} {...rest} value={value} onChange={this.onChange} error={error} />
67
+ </InputContainer>
68
+ ) : (
69
+ <MaterialInput type={type} {...rest} value={value} onChange={this.onChange} error={error} />
70
+ );
71
+ }
72
+ }
package/src/inputs.jsx ADDED
@@ -0,0 +1,96 @@
1
+ import Checkbox from '@material-ui/core/Checkbox';
2
+ import Radio from '@material-ui/core/Radio';
3
+ import { InputContainer } from '@pie-lib/render-ui';
4
+ import PropTypes from 'prop-types';
5
+ import React from 'react';
6
+ import Switch from '@material-ui/core/Switch';
7
+ import { withStyles } from '@material-ui/core/styles';
8
+ import classNames from 'classnames';
9
+
10
+ const InputTypes = {
11
+ classes: PropTypes.object.isRequired,
12
+ className: PropTypes.string,
13
+ label: PropTypes.string,
14
+ checked: PropTypes.bool,
15
+ onChange: PropTypes.func,
16
+ disabled: PropTypes.bool,
17
+ error: PropTypes.string
18
+ };
19
+
20
+ const RawInputSwitch = ({ classes, className, label, checked, onChange }) => {
21
+ return (
22
+ <InputContainer className={className} label={label}>
23
+ <Switch
24
+ className={classes.switchRoot}
25
+ checked={checked}
26
+ onChange={onChange}
27
+ aria-label={label}
28
+ />
29
+ </InputContainer>
30
+ );
31
+ };
32
+
33
+ RawInputSwitch.propTypes = { ...InputTypes };
34
+
35
+ const InputSwitch = withStyles({
36
+ switchRoot: {
37
+ justifyContent: 'inherit',
38
+ transform: 'translate(-20%, 20%)'
39
+ }
40
+ })(RawInputSwitch);
41
+
42
+ const RawInputCheckbox = props => {
43
+ const { classes, className, label, checked, onChange, disabled, error } = props;
44
+
45
+ return (
46
+ <InputContainer className={className} label={label}>
47
+ <Checkbox
48
+ className={classNames(classes.checkboxRoot, error && classes.error)}
49
+ disabled={disabled}
50
+ checked={checked}
51
+ onChange={onChange}
52
+ aria-label={label}
53
+ />
54
+ </InputContainer>
55
+ );
56
+ };
57
+
58
+ RawInputCheckbox.propTypes = { ...InputTypes };
59
+
60
+ const RawInputRadio = props => {
61
+ const { classes, className, label, checked, onChange, disabled, error } = props;
62
+
63
+ return (
64
+ <InputContainer className={className} label={label}>
65
+ <Radio
66
+ className={classNames(classes.radioRoot, error && classes.error)}
67
+ disabled={disabled}
68
+ checked={checked}
69
+ onChange={onChange}
70
+ aria-label={label}
71
+ />
72
+ </InputContainer>
73
+ );
74
+ };
75
+
76
+ RawInputRadio.propTypes = { ...InputTypes };
77
+
78
+ const InputCheckbox = withStyles({
79
+ checkboxRoot: {
80
+ transform: 'translate(-25%, 20%)'
81
+ },
82
+ error: {
83
+ color: 'red'
84
+ }
85
+ })(RawInputCheckbox);
86
+
87
+ const InputRadio = withStyles(() => ({
88
+ radioRoot: {
89
+ transform: 'translate(-20%, 20%)'
90
+ },
91
+ error: {
92
+ color: 'red'
93
+ }
94
+ }))(RawInputRadio);
95
+
96
+ export { InputSwitch, InputCheckbox, InputRadio };
package/src/langs.jsx ADDED
@@ -0,0 +1,122 @@
1
+ import Input from '@material-ui/core/Input';
2
+ import InputLabel from '@material-ui/core/InputLabel';
3
+ import PropTypes from 'prop-types';
4
+ import React from 'react';
5
+ import classNames from 'classnames';
6
+ import { withStyles } from '@material-ui/core/styles';
7
+ import Select from '@material-ui/core/Select';
8
+ import MenuItem from '@material-ui/core/MenuItem';
9
+ import FormControl from '@material-ui/core/FormControl';
10
+ import debug from 'debug';
11
+
12
+ const log = debug('pie-elements:config-ui:langs');
13
+
14
+ const styles = theme => ({
15
+ root: {
16
+ flexDirection: 'column',
17
+ alignItems: 'start',
18
+ display: 'flex',
19
+ position: 'relative',
20
+ paddingTop: '0px',
21
+ paddingRight: '0px'
22
+ },
23
+ formControl: {
24
+ position: 'initial'
25
+ },
26
+ inputLabel: {
27
+ paddingBottom: theme.spacing.unit
28
+ }
29
+ });
30
+
31
+ export class RawLangs extends React.Component {
32
+ static propTypes = {
33
+ onChange: PropTypes.func,
34
+ langs: PropTypes.array,
35
+ selected: PropTypes.string,
36
+ label: PropTypes.string,
37
+ classes: PropTypes.object.isRequired,
38
+ uid: PropTypes.string
39
+ };
40
+
41
+ constructor(props) {
42
+ super(props);
43
+ this.uid = props.uid || (Math.random() * 10000).toFixed();
44
+ }
45
+
46
+ choose = event => {
47
+ log('[choose] event: ', event);
48
+ if (this.props.onChange) {
49
+ this.props.onChange(event.target.value);
50
+ }
51
+ };
52
+
53
+ render() {
54
+ let { langs, selected, label, classes } = this.props;
55
+ log('[render] selected:', selected);
56
+ return (
57
+ <div className={classes.root}>
58
+ <FormControl className={classes.formControl}>
59
+ <InputLabel className={classes.inputLabel} htmlFor={this.uid}>
60
+ {label}
61
+ </InputLabel>
62
+ <Select value={selected} onChange={this.choose} input={<Input id={this.uid} />}>
63
+ {langs.map((l, index) => (
64
+ <MenuItem key={index} value={l}>
65
+ {l}
66
+ </MenuItem>
67
+ ))}
68
+ </Select>
69
+ </FormControl>
70
+ </div>
71
+ );
72
+ }
73
+ }
74
+
75
+ const Langs = withStyles(styles, { name: 'Langs' })(RawLangs);
76
+ export default Langs;
77
+
78
+ export const LanguageControls = withStyles({
79
+ languageControls: {
80
+ display: 'grid',
81
+ gridAutoFlow: 'column',
82
+ gridAutoColumns: '1fr',
83
+ gridGap: '8px'
84
+ }
85
+ })(
86
+ ({
87
+ classes,
88
+ langs,
89
+ activeLang,
90
+ defaultLang,
91
+ onActiveLangChange,
92
+ onDefaultLangChange,
93
+ className
94
+ }) => {
95
+ const names = classNames(classes.languageControls, className);
96
+
97
+ return (
98
+ <div className={names}>
99
+ <Langs
100
+ label="Choose language to edit"
101
+ langs={langs}
102
+ selected={activeLang}
103
+ onChange={l => onActiveLangChange(l)}
104
+ />
105
+ <Langs
106
+ label="Default language"
107
+ langs={langs}
108
+ selected={defaultLang}
109
+ onChange={l => onDefaultLangChange(l)}
110
+ />
111
+ </div>
112
+ );
113
+ }
114
+ );
115
+
116
+ LanguageControls.propTypes = {
117
+ langs: PropTypes.array,
118
+ activeLang: PropTypes.string.isRequired,
119
+ defaultLang: PropTypes.string.isRequired,
120
+ onActiveLangChange: PropTypes.func.isRequired,
121
+ onDefaultLangChange: PropTypes.func.isRequired
122
+ };
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import Measure from 'react-measure';
3
+ import PropTypes from 'prop-types';
4
+ import LayoutContents from './layout-contents';
5
+ import SettingsBox from './settings-box';
6
+
7
+ class ConfigLayout extends React.Component {
8
+ static propTypes = {
9
+ children: PropTypes.oneOfType([
10
+ PropTypes.string,
11
+ PropTypes.arrayOf(PropTypes.element),
12
+ PropTypes.element
13
+ ]),
14
+ settings: PropTypes.element,
15
+ className: PropTypes.string,
16
+ classes: PropTypes.object,
17
+ sidePanelMinWidth: PropTypes.number
18
+ };
19
+
20
+ static defaultProps = {
21
+ sidePanelMinWidth: 950
22
+ };
23
+
24
+ constructor(props) {
25
+ super(props);
26
+ this.state = {
27
+ layoutMode: undefined
28
+ };
29
+ }
30
+
31
+ onResize = contentRect => {
32
+ const { bounds } = contentRect;
33
+ const { sidePanelMinWidth } = this.props;
34
+ const layoutMode = bounds.width >= sidePanelMinWidth ? 'inline' : 'tabbed';
35
+
36
+ this.setState({ layoutMode });
37
+ };
38
+
39
+ render() {
40
+ return (
41
+ <Measure bounds onResize={this.onResize}>
42
+ {({ measureRef }) => {
43
+ const { settings, children } = this.props;
44
+ const { layoutMode } = this.state;
45
+
46
+ return (
47
+ <div ref={measureRef}>
48
+ <LayoutContents
49
+ mode={layoutMode}
50
+ secondary={
51
+ layoutMode === 'inline' ? <SettingsBox>{settings}</SettingsBox> : settings
52
+ }
53
+ >
54
+ {children}
55
+ </LayoutContents>
56
+ </div>
57
+ );
58
+ }}
59
+ </Measure>
60
+ );
61
+ }
62
+ }
63
+
64
+ export default ConfigLayout;
@@ -0,0 +1,4 @@
1
+ import ConfigLayout from './config-layout';
2
+ import LayoutContents from './layout-contents';
3
+
4
+ export { LayoutContents, ConfigLayout };
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ import { withStyles } from '@material-ui/core';
3
+ import Tabs from '../tabs';
4
+ import classnames from 'classnames';
5
+ import PropTypes from 'prop-types';
6
+
7
+ class RawLayoutContents extends React.Component {
8
+ static propTypes = {
9
+ mode: PropTypes.oneOf(['tabbed', 'inline']),
10
+ secondary: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
11
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
12
+ classes: PropTypes.object
13
+ };
14
+
15
+ render() {
16
+ const { mode, secondary, children, classes } = this.props;
17
+
18
+ return (
19
+ <div className={classnames(classes.container)}>
20
+ {mode === 'inline' && (
21
+ <div className={classes.flow}>
22
+ <div className={classes.configContainer}>{children}</div>
23
+ <div>{secondary}</div>
24
+ </div>
25
+ )}
26
+ {mode === 'tabbed' && (
27
+ <Tabs
28
+ onChange={this.onTabsChange}
29
+ contentClassName={classes.contentContainer}
30
+ indicatorColor="primary"
31
+ >
32
+ <div title="Design">{children}</div>
33
+ <div title="settings">{secondary}</div>
34
+ </Tabs>
35
+ )}
36
+ </div>
37
+ );
38
+ }
39
+ }
40
+
41
+ const styles = () => ({
42
+ flow: {
43
+ display: 'flex',
44
+ justifyContent: 'space-between'
45
+ },
46
+ container: {
47
+ display: 'flex',
48
+ flexDirection: 'column',
49
+ position: 'relative'
50
+ },
51
+ contentContainer: {
52
+ padding: '32px 16px 0 16px'
53
+ },
54
+ configContainer: {
55
+ flex: '1',
56
+ marginRight: '20px'
57
+ }
58
+ });
59
+
60
+ export default withStyles(styles)(RawLayoutContents);