@pie-lib/config-ui 0.1.0
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/dist/_virtual/_rolldown/runtime.js +11 -0
- package/dist/alert-dialog.d.ts +44 -0
- package/dist/alert-dialog.d.ts.map +1 -0
- package/dist/alert-dialog.js +47 -0
- package/dist/checkbox.d.ts +34 -0
- package/dist/checkbox.d.ts.map +1 -0
- package/dist/checkbox.js +57 -0
- package/dist/choice-configuration/feedback-menu.d.ts +33 -0
- package/dist/choice-configuration/feedback-menu.d.ts.map +1 -0
- package/dist/choice-configuration/feedback-menu.js +85 -0
- package/dist/choice-configuration/index.d.ts +63 -0
- package/dist/choice-configuration/index.d.ts.map +1 -0
- package/dist/choice-configuration/index.js +240 -0
- package/dist/choice-utils.d.ts +22 -0
- package/dist/choice-utils.d.ts.map +1 -0
- package/dist/choice-utils.js +15 -0
- package/dist/feedback-config/feedback-selector.d.ts +34 -0
- package/dist/feedback-config/feedback-selector.d.ts.map +1 -0
- package/dist/feedback-config/feedback-selector.js +92 -0
- package/dist/feedback-config/group.d.ts +21 -0
- package/dist/feedback-config/group.d.ts.map +1 -0
- package/dist/feedback-config/group.js +33 -0
- package/dist/feedback-config/index.d.ts +49 -0
- package/dist/feedback-config/index.d.ts.map +1 -0
- package/dist/feedback-config/index.js +96 -0
- package/dist/form-section.d.ts +25 -0
- package/dist/form-section.d.ts.map +1 -0
- package/dist/form-section.js +25 -0
- package/dist/help.d.ts +42 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +61 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/input.d.ts +30 -0
- package/dist/input.d.ts.map +1 -0
- package/dist/input.js +65 -0
- package/dist/inputs.d.ts +63 -0
- package/dist/inputs.d.ts.map +1 -0
- package/dist/inputs.js +70 -0
- package/dist/langs.d.ts +42 -0
- package/dist/langs.d.ts.map +1 -0
- package/dist/langs.js +76 -0
- package/dist/layout/config-layout.d.ts +11 -0
- package/dist/layout/config-layout.d.ts.map +1 -0
- package/dist/layout/config-layout.js +75 -0
- package/dist/layout/index.d.ts +12 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +10 -0
- package/dist/layout/layout-contents.d.ts +22 -0
- package/dist/layout/layout-contents.d.ts.map +1 -0
- package/dist/layout/layout-contents.js +70 -0
- package/dist/layout/settings-box.d.ts +20 -0
- package/dist/layout/settings-box.d.ts.map +1 -0
- package/dist/layout/settings-box.js +31 -0
- package/dist/mui-box/index.d.ts +21 -0
- package/dist/mui-box/index.d.ts.map +1 -0
- package/dist/mui-box/index.js +47 -0
- package/dist/node_modules/.bun/@babel_runtime@7.28.6/node_modules/@babel/runtime/helpers/esm/extends.js +12 -0
- package/dist/node_modules/.bun/@babel_runtime@7.28.6/node_modules/@babel/runtime/helpers/esm/inheritsLoose.js +7 -0
- package/dist/node_modules/.bun/@babel_runtime@7.28.6/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +12 -0
- package/dist/node_modules/.bun/@babel_runtime@7.28.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js +8 -0
- package/dist/node_modules/.bun/react-measure@2.5.2_6dbf9a050bc9aadb/node_modules/react-measure/dist/index.esm.js +122 -0
- package/dist/node_modules/.bun/resize-observer-polyfill@1.5.1/node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js +276 -0
- package/dist/number-text-field-custom.d.ts +52 -0
- package/dist/number-text-field-custom.d.ts.map +1 -0
- package/dist/number-text-field-custom.js +192 -0
- package/dist/number-text-field.d.ts +48 -0
- package/dist/number-text-field.d.ts.map +1 -0
- package/dist/number-text-field.js +122 -0
- package/dist/radio-with-label.d.ts +25 -0
- package/dist/radio-with-label.d.ts.map +1 -0
- package/dist/radio-with-label.js +27 -0
- package/dist/settings/display-size.d.ts +26 -0
- package/dist/settings/display-size.d.ts.map +1 -0
- package/dist/settings/display-size.js +45 -0
- package/dist/settings/index.d.ts +46 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +63 -0
- package/dist/settings/panel.d.ts +28 -0
- package/dist/settings/panel.d.ts.map +1 -0
- package/dist/settings/panel.js +201 -0
- package/dist/settings/settings-radio-label.d.ts +25 -0
- package/dist/settings/settings-radio-label.d.ts.map +1 -0
- package/dist/settings/settings-radio-label.js +29 -0
- package/dist/settings/toggle.d.ts +25 -0
- package/dist/settings/toggle.d.ts.map +1 -0
- package/dist/settings/toggle.js +33 -0
- package/dist/tabs/index.d.ts +23 -0
- package/dist/tabs/index.d.ts.map +1 -0
- package/dist/tabs/index.js +39 -0
- package/dist/tags-input/index.d.ts +22 -0
- package/dist/tags-input/index.d.ts.map +1 -0
- package/dist/tags-input/index.js +83 -0
- package/dist/two-choice.d.ts +44 -0
- package/dist/two-choice.d.ts.map +1 -0
- package/dist/two-choice.js +79 -0
- package/dist/with-stateful-model.d.ts +22 -0
- package/dist/with-stateful-model.d.ts.map +1 -0
- package/dist/with-stateful-model.js +32 -0
- package/package.json +40 -0
- package/src/alert-dialog.tsx +85 -0
- package/src/checkbox.tsx +71 -0
- package/src/choice-configuration/feedback-menu.tsx +134 -0
- package/src/choice-configuration/index.tsx +400 -0
- package/src/choice-utils.ts +40 -0
- package/src/feedback-config/feedback-selector.tsx +153 -0
- package/src/feedback-config/group.tsx +61 -0
- package/src/feedback-config/index.tsx +121 -0
- package/src/form-section.tsx +41 -0
- package/src/help.tsx +89 -0
- package/src/index.ts +93 -0
- package/src/input.tsx +109 -0
- package/src/inputs.tsx +107 -0
- package/src/langs.tsx +121 -0
- package/src/layout/config-layout.tsx +113 -0
- package/src/layout/index.ts +14 -0
- package/src/layout/layout-contents.tsx +127 -0
- package/src/layout/settings-box.tsx +42 -0
- package/src/mui-box/index.tsx +66 -0
- package/src/number-text-field-custom.tsx +343 -0
- package/src/number-text-field.tsx +229 -0
- package/src/radio-with-label.tsx +40 -0
- package/src/settings/display-size.tsx +63 -0
- package/src/settings/index.ts +93 -0
- package/src/settings/panel.tsx +343 -0
- package/src/settings/settings-radio-label.tsx +42 -0
- package/src/settings/toggle.tsx +56 -0
- package/src/tabs/index.tsx +57 -0
- package/src/tags-input/index.tsx +126 -0
- package/src/two-choice.tsx +128 -0
- package/src/with-stateful-model.tsx +46 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* @synced-from pie-lib/packages/config-ui/src/choice-configuration/feedback-menu.jsx
|
|
4
|
+
* @auto-generated
|
|
5
|
+
*
|
|
6
|
+
* This file is automatically synced from pie-elements and converted to TypeScript.
|
|
7
|
+
* Manual edits will be overwritten on next sync.
|
|
8
|
+
* To make changes, edit the upstream JavaScript file and run sync again.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { InlineMenu as MenuImport } from '@pie-lib/render-ui';
|
|
12
|
+
|
|
13
|
+
function isRenderableReactInteropType(value: any) {
|
|
14
|
+
return (
|
|
15
|
+
typeof value === 'function' ||
|
|
16
|
+
(typeof value === 'object' && value !== null && typeof value.$$typeof === 'symbol')
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function unwrapReactInteropSymbol(maybeSymbol: any, namedExport?: string) {
|
|
21
|
+
if (!maybeSymbol) return maybeSymbol;
|
|
22
|
+
if (isRenderableReactInteropType(maybeSymbol)) return maybeSymbol;
|
|
23
|
+
if (isRenderableReactInteropType(maybeSymbol.default)) return maybeSymbol.default;
|
|
24
|
+
if (namedExport && isRenderableReactInteropType(maybeSymbol[namedExport])) {
|
|
25
|
+
return maybeSymbol[namedExport];
|
|
26
|
+
}
|
|
27
|
+
if (namedExport && isRenderableReactInteropType(maybeSymbol[namedExport]?.default)) {
|
|
28
|
+
return maybeSymbol[namedExport].default;
|
|
29
|
+
}
|
|
30
|
+
return maybeSymbol;
|
|
31
|
+
}
|
|
32
|
+
const Menu = unwrapReactInteropSymbol(MenuImport, 'InlineMenu') || unwrapReactInteropSymbol(renderUi.InlineMenu, 'InlineMenu');
|
|
33
|
+
import * as RenderUiNamespace from '@pie-lib/render-ui';
|
|
34
|
+
const renderUiNamespaceAny = RenderUiNamespace as any;
|
|
35
|
+
const renderUiDefaultMaybe = renderUiNamespaceAny['default'];
|
|
36
|
+
const renderUi =
|
|
37
|
+
renderUiDefaultMaybe && typeof renderUiDefaultMaybe === 'object'
|
|
38
|
+
? renderUiDefaultMaybe
|
|
39
|
+
: renderUiNamespaceAny;
|
|
40
|
+
import MenuItem from '@mui/material/MenuItem';
|
|
41
|
+
import ActionFeedback from '@mui/icons-material/Feedback';
|
|
42
|
+
import IconButton from '@mui/material/IconButton';
|
|
43
|
+
import PropTypes from 'prop-types';
|
|
44
|
+
import React from 'react';
|
|
45
|
+
|
|
46
|
+
export class IconMenu extends React.Component {
|
|
47
|
+
static propTypes = {
|
|
48
|
+
opts: PropTypes.object,
|
|
49
|
+
onClick: PropTypes.func.isRequired,
|
|
50
|
+
iconButtonElement: PropTypes.any,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
constructor(props) {
|
|
54
|
+
super(props);
|
|
55
|
+
this.state = {
|
|
56
|
+
anchorEl: undefined,
|
|
57
|
+
open: false,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
handleClick: any = (event) => {
|
|
62
|
+
this.setState({ open: true, anchorEl: event.currentTarget });
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
handleRequestClose: any = () => {
|
|
66
|
+
this.setState({ open: false });
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
render() {
|
|
70
|
+
const { opts, onClick } = this.props;
|
|
71
|
+
const keys = Object.keys(opts);
|
|
72
|
+
|
|
73
|
+
const handleMenuClick = (key) => () => {
|
|
74
|
+
onClick(key);
|
|
75
|
+
this.handleRequestClose();
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div>
|
|
80
|
+
<div onClick={this.handleClick}>{this.props.iconButtonElement}</div>
|
|
81
|
+
<Menu
|
|
82
|
+
id="simple-menu"
|
|
83
|
+
anchorEl={this.state.anchorEl}
|
|
84
|
+
open={this.state.open}
|
|
85
|
+
onClose={this.handleRequestClose}
|
|
86
|
+
transitionDuration={{ enter: 225, exit: 195 }}
|
|
87
|
+
>
|
|
88
|
+
{keys.map((k, index) => (
|
|
89
|
+
<MenuItem key={index} onClick={handleMenuClick(k)}>
|
|
90
|
+
{opts[k]}
|
|
91
|
+
</MenuItem>
|
|
92
|
+
))}
|
|
93
|
+
</Menu>
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export default class FeedbackMenu extends React.Component {
|
|
100
|
+
static propTypes = {
|
|
101
|
+
value: PropTypes.object,
|
|
102
|
+
onChange: PropTypes.func.isRequired,
|
|
103
|
+
classes: PropTypes.object.isRequired,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
static defaultProps = {
|
|
107
|
+
classes: {},
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
render() {
|
|
111
|
+
const { value, onChange, classes } = this.props;
|
|
112
|
+
const t = value && value.type;
|
|
113
|
+
const iconColor = t === 'custom' || t === 'default' ? 'primary' : 'disabled';
|
|
114
|
+
const tooltip = t === 'custom' ? 'Custom Feedback' : t === 'default' ? 'Default Feedback' : 'Feedback disabled';
|
|
115
|
+
|
|
116
|
+
const icon = (
|
|
117
|
+
<IconButton className={classes.icon} aria-label={tooltip} size="large">
|
|
118
|
+
<ActionFeedback color={iconColor} />
|
|
119
|
+
</IconButton>
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<IconMenu
|
|
124
|
+
iconButtonElement={icon}
|
|
125
|
+
onClick={(key) => onChange(key)}
|
|
126
|
+
opts={{
|
|
127
|
+
none: 'No Feedback',
|
|
128
|
+
default: 'Default',
|
|
129
|
+
custom: 'Custom',
|
|
130
|
+
}}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* @synced-from pie-lib/packages/config-ui/src/choice-configuration/index.jsx
|
|
4
|
+
* @auto-generated
|
|
5
|
+
*
|
|
6
|
+
* This file is automatically synced from pie-elements and converted to TypeScript.
|
|
7
|
+
* Manual edits will be overwritten on next sync.
|
|
8
|
+
* To make changes, edit the upstream JavaScript file and run sync again.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import PropTypes from 'prop-types';
|
|
13
|
+
import { styled } from '@mui/material/styles';
|
|
14
|
+
import TextField from '@mui/material/TextField';
|
|
15
|
+
import ActionDelete from '@mui/icons-material/Delete';
|
|
16
|
+
import ArrowRight from '@mui/icons-material/SubdirectoryArrowRight';
|
|
17
|
+
import IconButton from '@mui/material/IconButton';
|
|
18
|
+
import { InputContainer as InputContainerImport } from '@pie-lib/render-ui';
|
|
19
|
+
|
|
20
|
+
function isRenderableReactInteropType(value: any) {
|
|
21
|
+
return (
|
|
22
|
+
typeof value === 'function' ||
|
|
23
|
+
(typeof value === 'object' && value !== null && typeof value.$$typeof === 'symbol')
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function unwrapReactInteropSymbol(maybeSymbol: any, namedExport?: string) {
|
|
28
|
+
if (!maybeSymbol) return maybeSymbol;
|
|
29
|
+
if (isRenderableReactInteropType(maybeSymbol)) return maybeSymbol;
|
|
30
|
+
if (isRenderableReactInteropType(maybeSymbol.default)) return maybeSymbol.default;
|
|
31
|
+
if (namedExport && isRenderableReactInteropType(maybeSymbol[namedExport])) {
|
|
32
|
+
return maybeSymbol[namedExport];
|
|
33
|
+
}
|
|
34
|
+
if (namedExport && isRenderableReactInteropType(maybeSymbol[namedExport]?.default)) {
|
|
35
|
+
return maybeSymbol[namedExport].default;
|
|
36
|
+
}
|
|
37
|
+
return maybeSymbol;
|
|
38
|
+
}
|
|
39
|
+
const InputContainer = unwrapReactInteropSymbol(InputContainerImport, 'InputContainer') || unwrapReactInteropSymbol(renderUi.InputContainer, 'InputContainer');
|
|
40
|
+
import * as RenderUiNamespace from '@pie-lib/render-ui';
|
|
41
|
+
const renderUiNamespaceAny = RenderUiNamespace as any;
|
|
42
|
+
const renderUiDefaultMaybe = renderUiNamespaceAny['default'];
|
|
43
|
+
const renderUi =
|
|
44
|
+
renderUiDefaultMaybe && typeof renderUiDefaultMaybe === 'object'
|
|
45
|
+
? renderUiDefaultMaybe
|
|
46
|
+
: renderUiNamespaceAny;
|
|
47
|
+
// import EditableHtml from '@pie-lib/editable-html-tip-tap';
|
|
48
|
+
import { InputCheckbox, InputRadio } from '../inputs.js';
|
|
49
|
+
import FeedbackMenu from './feedback-menu.js';
|
|
50
|
+
|
|
51
|
+
// - mathquill error window not defined
|
|
52
|
+
import EditableHtmlImport from '@pie-lib/editable-html-tip-tap';
|
|
53
|
+
|
|
54
|
+
const EditableHtml = EditableHtmlImport;
|
|
55
|
+
|
|
56
|
+
const StyledEditorHolder: any = styled('div')(({ theme }) => ({
|
|
57
|
+
marginTop: theme.spacing(2),
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
const EditableHtmlContainer = ({
|
|
61
|
+
label,
|
|
62
|
+
onChange,
|
|
63
|
+
value,
|
|
64
|
+
className,
|
|
65
|
+
imageSupport,
|
|
66
|
+
disableImageAlignmentButtons,
|
|
67
|
+
disabled,
|
|
68
|
+
spellCheck,
|
|
69
|
+
nonEmpty,
|
|
70
|
+
pluginOpts,
|
|
71
|
+
toolbarOpts,
|
|
72
|
+
error,
|
|
73
|
+
maxImageWidth,
|
|
74
|
+
maxImageHeight,
|
|
75
|
+
uploadSoundSupport,
|
|
76
|
+
mathMlOptions = {},
|
|
77
|
+
}) => {
|
|
78
|
+
return (
|
|
79
|
+
<InputContainer label={label} className={className}>
|
|
80
|
+
<StyledEditorHolder>
|
|
81
|
+
<EditableHtml
|
|
82
|
+
markup={value || ''}
|
|
83
|
+
disabled={disabled}
|
|
84
|
+
spellCheck={spellCheck}
|
|
85
|
+
nonEmpty={nonEmpty}
|
|
86
|
+
onChange={onChange}
|
|
87
|
+
imageSupport={imageSupport}
|
|
88
|
+
disableImageAlignmentButtons={disableImageAlignmentButtons}
|
|
89
|
+
pluginProps={pluginOpts || {}}
|
|
90
|
+
toolbarOpts={toolbarOpts}
|
|
91
|
+
error={error}
|
|
92
|
+
maxImageWidth={maxImageWidth}
|
|
93
|
+
maxImageHeight={maxImageHeight}
|
|
94
|
+
uploadSoundSupport={uploadSoundSupport}
|
|
95
|
+
languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
|
|
96
|
+
mathMlOptions={mathMlOptions}
|
|
97
|
+
/>
|
|
98
|
+
</StyledEditorHolder>
|
|
99
|
+
</InputContainer>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const StyledFeedbackContainer: any = styled('div')(() => ({
|
|
104
|
+
position: 'relative',
|
|
105
|
+
}));
|
|
106
|
+
|
|
107
|
+
const StyledArrowIcon: any = styled(ArrowRight)(({ theme }) => ({
|
|
108
|
+
fill: theme.palette.grey[400],
|
|
109
|
+
left: -56,
|
|
110
|
+
position: 'absolute',
|
|
111
|
+
top: 40,
|
|
112
|
+
}));
|
|
113
|
+
|
|
114
|
+
const StyledTextField: any = styled(TextField)(({ theme }) => ({
|
|
115
|
+
width: '100%',
|
|
116
|
+
marginTop: theme.spacing(2),
|
|
117
|
+
}));
|
|
118
|
+
|
|
119
|
+
const StyledEditableHtmlContainer: any = styled(EditableHtmlContainer)(({ theme }) => ({
|
|
120
|
+
width: '100%',
|
|
121
|
+
marginTop: theme.spacing(2),
|
|
122
|
+
}));
|
|
123
|
+
|
|
124
|
+
const Feedback = ({ value, onChange, type, correct, defaults, toolbarOpts, mathMlOptions = {} }) => {
|
|
125
|
+
if (!type || type === 'none') {
|
|
126
|
+
return null;
|
|
127
|
+
} else if (type === 'default') {
|
|
128
|
+
return (
|
|
129
|
+
<StyledFeedbackContainer>
|
|
130
|
+
<StyledArrowIcon />
|
|
131
|
+
<StyledTextField
|
|
132
|
+
label="Feedback Text"
|
|
133
|
+
value={correct ? defaults.correct : defaults.incorrect}
|
|
134
|
+
variant="standard"
|
|
135
|
+
/>
|
|
136
|
+
</StyledFeedbackContainer>
|
|
137
|
+
);
|
|
138
|
+
} else {
|
|
139
|
+
return (
|
|
140
|
+
<StyledFeedbackContainer>
|
|
141
|
+
<StyledArrowIcon />
|
|
142
|
+
<StyledEditableHtmlContainer
|
|
143
|
+
label="Feedback Text"
|
|
144
|
+
value={value}
|
|
145
|
+
onChange={onChange}
|
|
146
|
+
toolbarOpts={toolbarOpts}
|
|
147
|
+
mathMlOptions={mathMlOptions}
|
|
148
|
+
/>
|
|
149
|
+
</StyledFeedbackContainer>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const StyledIndex: any = styled('span')(({ theme }) => ({
|
|
155
|
+
paddingRight: theme.spacing(1),
|
|
156
|
+
paddingTop: theme.spacing(3),
|
|
157
|
+
}));
|
|
158
|
+
|
|
159
|
+
const StyledTopRow: any = styled('div')(() => ({
|
|
160
|
+
display: 'flex',
|
|
161
|
+
alignItems: 'center',
|
|
162
|
+
}));
|
|
163
|
+
|
|
164
|
+
const StyledToggle: any = styled('div')(({ theme }) => ({
|
|
165
|
+
flex: '0 1 auto',
|
|
166
|
+
paddingTop: theme.spacing(0.5),
|
|
167
|
+
paddingBottom: 0,
|
|
168
|
+
marginRight: 0,
|
|
169
|
+
marginLeft: theme.spacing(1),
|
|
170
|
+
}));
|
|
171
|
+
|
|
172
|
+
const StyledFeedback: any = styled('div')(({ theme }) => ({
|
|
173
|
+
flex: '0 1 auto',
|
|
174
|
+
paddingTop: theme.spacing(2),
|
|
175
|
+
paddingLeft: 0,
|
|
176
|
+
marginLeft: 0,
|
|
177
|
+
marginRight: theme.spacing(1),
|
|
178
|
+
}));
|
|
179
|
+
|
|
180
|
+
const StyledFeedbackIcon: any = styled('div')(() => ({
|
|
181
|
+
margin: 0,
|
|
182
|
+
width: 'inherit',
|
|
183
|
+
}));
|
|
184
|
+
|
|
185
|
+
const StyledDeleteIcon: any = styled('div')(() => ({
|
|
186
|
+
margin: 0,
|
|
187
|
+
width: 'inherit',
|
|
188
|
+
}));
|
|
189
|
+
|
|
190
|
+
const StyledDelete: any = styled('div')(({ theme }) => ({
|
|
191
|
+
flex: '0 1 auto',
|
|
192
|
+
paddingTop: theme.spacing(2),
|
|
193
|
+
paddingLeft: 0,
|
|
194
|
+
marginLeft: 0,
|
|
195
|
+
}));
|
|
196
|
+
|
|
197
|
+
const StyledMiddleColumn: any = styled('div')(({ theme }) => ({
|
|
198
|
+
display: 'flex',
|
|
199
|
+
flex: 1,
|
|
200
|
+
flexDirection: 'column',
|
|
201
|
+
marginRight: theme.spacing(1),
|
|
202
|
+
}));
|
|
203
|
+
|
|
204
|
+
const StyledErrorText: any = styled('div')(({ theme }) => ({
|
|
205
|
+
fontSize: theme.typography.fontSize - 2,
|
|
206
|
+
color: theme.palette.error.main,
|
|
207
|
+
}));
|
|
208
|
+
|
|
209
|
+
export class ChoiceConfiguration extends React.Component {
|
|
210
|
+
static propTypes = {
|
|
211
|
+
noLabels: PropTypes.bool,
|
|
212
|
+
useLetterOrdering: PropTypes.bool,
|
|
213
|
+
className: PropTypes.string,
|
|
214
|
+
error: PropTypes.string,
|
|
215
|
+
mode: PropTypes.oneOf(['checkbox', 'radio']),
|
|
216
|
+
defaultFeedback: PropTypes.object.isRequired,
|
|
217
|
+
disabled: PropTypes.bool,
|
|
218
|
+
nonEmpty: PropTypes.bool,
|
|
219
|
+
data: PropTypes.shape({
|
|
220
|
+
label: PropTypes.string.isRequired,
|
|
221
|
+
value: PropTypes.string.isRequired,
|
|
222
|
+
correct: PropTypes.bool,
|
|
223
|
+
feedback: PropTypes.shape({
|
|
224
|
+
type: PropTypes.string,
|
|
225
|
+
value: PropTypes.string,
|
|
226
|
+
}),
|
|
227
|
+
}),
|
|
228
|
+
onDelete: PropTypes.func,
|
|
229
|
+
onChange: PropTypes.func,
|
|
230
|
+
index: PropTypes.number,
|
|
231
|
+
imageSupport: PropTypes.shape({
|
|
232
|
+
add: PropTypes.func.isRequired,
|
|
233
|
+
delete: PropTypes.func.isRequired,
|
|
234
|
+
}),
|
|
235
|
+
disableImageAlignmentButtons: PropTypes.bool,
|
|
236
|
+
allowFeedBack: PropTypes.bool,
|
|
237
|
+
allowDelete: PropTypes.bool,
|
|
238
|
+
noCorrectAnswerError: PropTypes.string,
|
|
239
|
+
spellCheck: PropTypes.bool,
|
|
240
|
+
pluginOpts: PropTypes.object,
|
|
241
|
+
toolbarOpts: PropTypes.object,
|
|
242
|
+
uploadSoundSupport: PropTypes.object,
|
|
243
|
+
maxImageWidth: PropTypes.number,
|
|
244
|
+
maxImageHeight: PropTypes.number,
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
static defaultProps = {
|
|
248
|
+
index: -1,
|
|
249
|
+
noLabels: false,
|
|
250
|
+
useLetterOrdering: false,
|
|
251
|
+
allowFeedBack: true,
|
|
252
|
+
allowDelete: true,
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
_changeFn = (key) => (update) => {
|
|
256
|
+
const { data, onChange } = this.props;
|
|
257
|
+
|
|
258
|
+
if (onChange) {
|
|
259
|
+
onChange({ ...data, [key]: update });
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
onLabelChange = this._changeFn('label');
|
|
264
|
+
|
|
265
|
+
onCheckedChange: any = (event) => {
|
|
266
|
+
const correct = event.target.checked;
|
|
267
|
+
const { data, onChange } = this.props;
|
|
268
|
+
|
|
269
|
+
if (onChange) {
|
|
270
|
+
onChange({ ...data, correct });
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
onFeedbackValueChange: any = (v) => {
|
|
275
|
+
const { data, onChange } = this.props;
|
|
276
|
+
|
|
277
|
+
if (data.feedback.type !== 'custom') {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const fb = { ...data.feedback, value: v };
|
|
282
|
+
|
|
283
|
+
if (onChange) onChange({ ...data, feedback: fb });
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
onFeedbackTypeChange: any = (t) => {
|
|
287
|
+
const { data, onChange } = this.props;
|
|
288
|
+
const fb = { ...data.feedback, type: t };
|
|
289
|
+
|
|
290
|
+
if (fb.type !== 'custom') {
|
|
291
|
+
fb.value = undefined;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (onChange) onChange({ ...data, feedback: fb });
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
render() {
|
|
298
|
+
const {
|
|
299
|
+
data,
|
|
300
|
+
mode,
|
|
301
|
+
onDelete,
|
|
302
|
+
defaultFeedback,
|
|
303
|
+
index,
|
|
304
|
+
className,
|
|
305
|
+
noLabels,
|
|
306
|
+
useLetterOrdering,
|
|
307
|
+
imageSupport,
|
|
308
|
+
disableImageAlignmentButtons,
|
|
309
|
+
disabled,
|
|
310
|
+
spellCheck,
|
|
311
|
+
nonEmpty,
|
|
312
|
+
allowFeedBack,
|
|
313
|
+
allowDelete,
|
|
314
|
+
pluginOpts,
|
|
315
|
+
toolbarOpts,
|
|
316
|
+
error,
|
|
317
|
+
noCorrectAnswerError,
|
|
318
|
+
uploadSoundSupport,
|
|
319
|
+
maxImageWidth,
|
|
320
|
+
maxImageHeight,
|
|
321
|
+
mathMlOptions = {},
|
|
322
|
+
} = this.props;
|
|
323
|
+
|
|
324
|
+
const InputToggle = mode === 'checkbox' ? InputCheckbox : InputRadio;
|
|
325
|
+
|
|
326
|
+
return (
|
|
327
|
+
<StyledTopRow>
|
|
328
|
+
{index > 0 && (
|
|
329
|
+
<StyledIndex type="title">
|
|
330
|
+
{useLetterOrdering ? String.fromCharCode(96 + index).toUpperCase() : index}
|
|
331
|
+
</StyledIndex>
|
|
332
|
+
)}
|
|
333
|
+
|
|
334
|
+
<StyledToggle>
|
|
335
|
+
<InputToggle
|
|
336
|
+
onChange={this.onCheckedChange}
|
|
337
|
+
label={!noLabels ? 'Correct' : ''}
|
|
338
|
+
checked={!!data.correct}
|
|
339
|
+
error={noCorrectAnswerError}
|
|
340
|
+
/>
|
|
341
|
+
</StyledToggle>
|
|
342
|
+
|
|
343
|
+
<StyledMiddleColumn>
|
|
344
|
+
<EditableHtmlContainer
|
|
345
|
+
label={!noLabels ? 'Label' : ''}
|
|
346
|
+
value={data.label}
|
|
347
|
+
onChange={this.onLabelChange}
|
|
348
|
+
imageSupport={imageSupport}
|
|
349
|
+
disableImageAlignmentButtons={disableImageAlignmentButtons}
|
|
350
|
+
disabled={disabled}
|
|
351
|
+
spellCheck={spellCheck}
|
|
352
|
+
nonEmpty={nonEmpty}
|
|
353
|
+
pluginOpts={pluginOpts}
|
|
354
|
+
toolbarOpts={toolbarOpts}
|
|
355
|
+
error={error}
|
|
356
|
+
uploadSoundSupport={uploadSoundSupport}
|
|
357
|
+
mathMlOptions={mathMlOptions}
|
|
358
|
+
maxImageWidth={maxImageWidth}
|
|
359
|
+
maxImageHeight={maxImageHeight}
|
|
360
|
+
/>
|
|
361
|
+
{error && <StyledErrorText>{error}</StyledErrorText>}
|
|
362
|
+
|
|
363
|
+
{allowFeedBack && (
|
|
364
|
+
<Feedback
|
|
365
|
+
{...data.feedback}
|
|
366
|
+
correct={data.correct}
|
|
367
|
+
defaults={defaultFeedback}
|
|
368
|
+
onChange={this.onFeedbackValueChange}
|
|
369
|
+
toolbarOpts={toolbarOpts}
|
|
370
|
+
/>
|
|
371
|
+
)}
|
|
372
|
+
</StyledMiddleColumn>
|
|
373
|
+
|
|
374
|
+
{allowFeedBack && (
|
|
375
|
+
<StyledFeedback>
|
|
376
|
+
<InputContainer label={!noLabels ? 'Feedback' : ''}>
|
|
377
|
+
<StyledFeedbackIcon>
|
|
378
|
+
<FeedbackMenu onChange={this.onFeedbackTypeChange} value={data.feedback} />
|
|
379
|
+
</StyledFeedbackIcon>
|
|
380
|
+
</InputContainer>
|
|
381
|
+
</StyledFeedback>
|
|
382
|
+
)}
|
|
383
|
+
|
|
384
|
+
{allowDelete && (
|
|
385
|
+
<StyledDelete>
|
|
386
|
+
<InputContainer label={!noLabels ? 'Delete' : ''}>
|
|
387
|
+
<StyledDeleteIcon>
|
|
388
|
+
<IconButton aria-label="delete" onClick={onDelete} size="large">
|
|
389
|
+
<ActionDelete />
|
|
390
|
+
</IconButton>
|
|
391
|
+
</StyledDeleteIcon>
|
|
392
|
+
</InputContainer>
|
|
393
|
+
</StyledDelete>
|
|
394
|
+
)}
|
|
395
|
+
</StyledTopRow>
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export default ChoiceConfiguration;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* @synced-from pie-lib/packages/config-ui/src/choice-utils.js
|
|
4
|
+
* @auto-generated
|
|
5
|
+
*
|
|
6
|
+
* This file is automatically synced from pie-elements and converted to TypeScript.
|
|
7
|
+
* Manual edits will be overwritten on next sync.
|
|
8
|
+
* To make changes, edit the upstream JavaScript file and run sync again.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { includes } from 'lodash-es';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Add value to every model.choices.
|
|
15
|
+
* @param {Object} model the model to normalize
|
|
16
|
+
* @return {Object} the updated model
|
|
17
|
+
*/
|
|
18
|
+
export const normalizeChoices = (model) => {
|
|
19
|
+
const choices = model.choices.map((c, index) => {
|
|
20
|
+
if (!c.value) {
|
|
21
|
+
c.value = `${index}`;
|
|
22
|
+
}
|
|
23
|
+
return c;
|
|
24
|
+
});
|
|
25
|
+
return { ...model, choices };
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Find the first available index.
|
|
30
|
+
* @param {string[]} values
|
|
31
|
+
* @param {number} index
|
|
32
|
+
* @return {string}
|
|
33
|
+
*/
|
|
34
|
+
export const firstAvailableIndex = (values, index) => {
|
|
35
|
+
if (includes(values, `${index}`)) {
|
|
36
|
+
return firstAvailableIndex(values, index + 1);
|
|
37
|
+
} else {
|
|
38
|
+
return `${index}`;
|
|
39
|
+
}
|
|
40
|
+
};
|