@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.
- package/CHANGELOG.json +605 -0
- package/CHANGELOG.md +976 -328
- package/lib/alert-dialog.js +44 -0
- package/lib/alert-dialog.js.map +1 -0
- package/lib/checkbox.js +5 -5
- package/lib/checkbox.js.map +1 -1
- package/lib/choice-configuration/feedback-menu.js +42 -54
- package/lib/choice-configuration/feedback-menu.js.map +1 -1
- package/lib/choice-configuration/index.js +102 -86
- package/lib/choice-configuration/index.js.map +1 -1
- package/lib/choice-utils.js +9 -7
- package/lib/choice-utils.js.map +1 -1
- package/lib/feedback-config/feedback-selector.js +45 -49
- package/lib/feedback-config/feedback-selector.js.map +1 -1
- package/lib/feedback-config/group.js +13 -13
- package/lib/feedback-config/group.js.map +1 -1
- package/lib/feedback-config/index.js +57 -56
- package/lib/feedback-config/index.js.map +1 -1
- package/lib/form-section.js +19 -15
- package/lib/form-section.js.map +1 -1
- package/lib/help.js +31 -38
- package/lib/help.js.map +1 -1
- package/lib/index.js +73 -52
- package/lib/index.js.map +1 -1
- package/lib/input.js +36 -41
- package/lib/input.js.map +1 -1
- package/lib/inputs.js +42 -29
- package/lib/inputs.js.map +1 -1
- package/lib/langs.js +38 -46
- package/lib/langs.js.map +1 -1
- package/lib/layout/config-layout.js +36 -42
- package/lib/layout/config-layout.js.map +1 -1
- package/lib/layout/index.js +3 -3
- package/lib/layout/index.js.map +1 -1
- package/lib/layout/layout-contents.js +35 -35
- package/lib/layout/layout-contents.js.map +1 -1
- package/lib/layout/settings-box.js +29 -40
- package/lib/layout/settings-box.js.map +1 -1
- package/lib/mui-box/index.js +4 -4
- package/lib/mui-box/index.js.map +1 -1
- package/lib/number-text-field-custom.js +364 -0
- package/lib/number-text-field-custom.js.map +1 -0
- package/lib/number-text-field.js +46 -46
- package/lib/number-text-field.js.map +1 -1
- package/lib/radio-with-label.js +5 -5
- package/lib/radio-with-label.js.map +1 -1
- package/lib/settings/display-size.js +12 -10
- package/lib/settings/display-size.js.map +1 -1
- package/lib/settings/index.js +81 -14
- package/lib/settings/index.js.map +1 -1
- package/lib/settings/panel.js +297 -79
- package/lib/settings/panel.js.map +1 -1
- package/lib/settings/settings-radio-label.js +43 -0
- package/lib/settings/settings-radio-label.js.map +1 -0
- package/lib/settings/toggle.js +9 -7
- package/lib/settings/toggle.js.map +1 -1
- package/lib/tabs/index.js +29 -36
- package/lib/tabs/index.js.map +1 -1
- package/lib/tags-input/index.js +33 -41
- package/lib/tags-input/index.js.map +1 -1
- package/lib/two-choice.js +46 -50
- package/lib/two-choice.js.map +1 -1
- package/lib/with-stateful-model.js +24 -31
- package/lib/with-stateful-model.js.map +1 -1
- package/package.json +9 -7
- package/src/alert-dialog.jsx +43 -0
- package/src/checkbox.jsx +63 -0
- package/src/choice-configuration/feedback-menu.jsx +103 -0
- package/src/choice-configuration/index.jsx +319 -0
- package/src/choice-utils.js +30 -0
- package/src/feedback-config/feedback-selector.jsx +116 -0
- package/src/feedback-config/group.jsx +54 -0
- package/src/feedback-config/index.jsx +98 -0
- package/src/form-section.jsx +23 -0
- package/src/help.jsx +88 -0
- package/src/index.js +58 -0
- package/src/input.jsx +72 -0
- package/src/inputs.jsx +96 -0
- package/src/langs.jsx +122 -0
- package/src/layout/config-layout.jsx +64 -0
- package/src/layout/index.js +4 -0
- package/src/layout/layout-contents.jsx +60 -0
- package/src/layout/settings-box.jsx +31 -0
- package/src/mui-box/index.jsx +64 -0
- package/src/number-text-field-custom.jsx +276 -0
- package/src/number-text-field.jsx +196 -0
- package/src/radio-with-label.jsx +18 -0
- package/src/settings/display-size.jsx +52 -0
- package/src/settings/index.js +75 -0
- package/src/settings/panel.jsx +297 -0
- package/src/settings/settings-radio-label.jsx +20 -0
- package/src/settings/toggle.jsx +31 -0
- package/src/tabs/index.jsx +51 -0
- package/src/tags-input/index.jsx +121 -0
- package/src/two-choice.jsx +94 -0
- package/src/with-stateful-model.jsx +36 -0
- package/NEXT.CHANGELOG.json +0 -1
- package/__mocks__/@pie-lib/editable-html.jsx +0 -3
- package/lib/input-container.js +0 -59
- 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,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);
|