@pie-lib/render-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/assets/enableAudioAutoplayImage.d.ts +11 -0
- package/dist/assets/enableAudioAutoplayImage.d.ts.map +1 -0
- package/dist/assets/enableAudioAutoplayImage.js +4 -0
- package/dist/collapsible/index.d.ts +32 -0
- package/dist/collapsible/index.d.ts.map +1 -0
- package/dist/collapsible/index.js +53 -0
- package/dist/color.d.ts +115 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +118 -0
- package/dist/feedback.d.ts +21 -0
- package/dist/feedback.d.ts.map +1 -0
- package/dist/feedback.js +65 -0
- package/dist/has-media.d.ts +10 -0
- package/dist/has-media.d.ts.map +1 -0
- package/dist/has-media.js +10 -0
- package/dist/has-text.d.ts +10 -0
- package/dist/has-text.d.ts.map +1 -0
- package/dist/has-text.js +10 -0
- package/dist/html-and-math.d.ts +23 -0
- package/dist/html-and-math.d.ts.map +1 -0
- package/dist/html-and-math.js +25 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/inline-menu.d.ts +34 -0
- package/dist/inline-menu.d.ts.map +1 -0
- package/dist/inline-menu.js +29 -0
- package/dist/input-container.d.ts +23 -0
- package/dist/input-container.d.ts.map +1 -0
- package/dist/input-container.js +39 -0
- package/dist/preview-layout.d.ts +25 -0
- package/dist/preview-layout.d.ts.map +1 -0
- package/dist/preview-layout.js +37 -0
- package/dist/preview-prompt.d.ts +39 -0
- package/dist/preview-prompt.d.ts.map +1 -0
- package/dist/preview-prompt.js +153 -0
- package/dist/purpose.d.ts +18 -0
- package/dist/purpose.d.ts.map +1 -0
- package/dist/purpose.js +11 -0
- package/dist/readable.d.ts +18 -0
- package/dist/readable.d.ts.map +1 -0
- package/dist/readable.js +11 -0
- package/dist/response-indicators.d.ts +37 -0
- package/dist/response-indicators.d.ts.map +1 -0
- package/dist/response-indicators.js +62 -0
- package/dist/ui-layout.d.ts +32 -0
- package/dist/ui-layout.d.ts.map +1 -0
- package/dist/ui-layout.js +55 -0
- package/dist/withUndoReset.d.ts +26 -0
- package/dist/withUndoReset.d.ts.map +1 -0
- package/dist/withUndoReset.js +84 -0
- package/package.json +39 -0
- package/src/assets/enableAudioAutoplayImage.ts +11 -0
- package/src/collapsible/index.tsx +74 -0
- package/src/color.ts +147 -0
- package/src/feedback.tsx +94 -0
- package/src/has-media.ts +26 -0
- package/src/has-text.ts +28 -0
- package/src/html-and-math.tsx +31 -0
- package/src/index.ts +45 -0
- package/src/inline-menu.tsx +62 -0
- package/src/input-container.tsx +57 -0
- package/src/preview-layout.tsx +51 -0
- package/src/preview-prompt.tsx +286 -0
- package/src/purpose.tsx +27 -0
- package/src/readable.tsx +29 -0
- package/src/response-indicators.tsx +92 -0
- package/src/ui-layout.tsx +106 -0
- package/src/withUndoReset.tsx +124 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* @synced-from pie-lib/packages/render-ui/src/preview-prompt.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, { Component } from 'react';
|
|
12
|
+
import { styled } from '@mui/material/styles';
|
|
13
|
+
import PropTypes from 'prop-types';
|
|
14
|
+
import * as color from './color.js';
|
|
15
|
+
import { renderMath } from '@pie-element/shared-math-rendering-mathjax';
|
|
16
|
+
|
|
17
|
+
const StyledPromptContainer: any = styled('div')(({ theme, tagName }) => ({
|
|
18
|
+
// Base promptTable styles
|
|
19
|
+
'&:not(.MathJax) > table': {
|
|
20
|
+
borderCollapse: 'collapse',
|
|
21
|
+
},
|
|
22
|
+
// Apply vertical striping when first column is a header (th) and NOT mixed with td
|
|
23
|
+
'&:not(.MathJax) > table:has(tbody tr > th:first-child):not(:has(tbody tr > td:first-child)) tbody td:nth-child(even)':
|
|
24
|
+
{
|
|
25
|
+
backgroundColor: '#f6f8fa',
|
|
26
|
+
color: theme.palette.common.black,
|
|
27
|
+
},
|
|
28
|
+
// Apply horizontal striping for tables where first element is a data cell (td)
|
|
29
|
+
'&:not(.MathJax) > table:has(tbody tr > td:first-child) tbody tr:nth-child(even) td': {
|
|
30
|
+
backgroundColor: '#f6f8fa',
|
|
31
|
+
color: theme.palette.common.black,
|
|
32
|
+
},
|
|
33
|
+
// align table content to left as per STAR requirement PD-3687
|
|
34
|
+
'&:not(.MathJax) table td, &:not(.MathJax) table th': {
|
|
35
|
+
padding: '.6em 1em',
|
|
36
|
+
textAlign: 'left',
|
|
37
|
+
},
|
|
38
|
+
// added this to fix alignment of text in prompt imported from studio (PD-3423)
|
|
39
|
+
'&:not(.MathJax) > table td > p.kds-indent': {
|
|
40
|
+
textAlign: 'initial',
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
// Conditional styles based on class names
|
|
44
|
+
'&.prompt': {
|
|
45
|
+
verticalAlign: 'middle',
|
|
46
|
+
color: color.text(),
|
|
47
|
+
},
|
|
48
|
+
'&.legend': {
|
|
49
|
+
width: '100%',
|
|
50
|
+
fontSize: 'inherit !important',
|
|
51
|
+
},
|
|
52
|
+
'&.rationale': {
|
|
53
|
+
paddingLeft: theme.spacing(4),
|
|
54
|
+
paddingBottom: theme.spacing(1),
|
|
55
|
+
},
|
|
56
|
+
'&.prompt-label': {
|
|
57
|
+
color: `${color.text()} !important`,
|
|
58
|
+
display: 'flex',
|
|
59
|
+
flexDirection: 'column',
|
|
60
|
+
verticalAlign: 'middle',
|
|
61
|
+
cursor: 'pointer',
|
|
62
|
+
'& > p': {
|
|
63
|
+
margin: '0 0 0 0 !important',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
}));
|
|
67
|
+
|
|
68
|
+
//Used these below to replace \\embed{newLine} with \\newline from prompt which will get parsed in MathJax
|
|
69
|
+
const NEWLINE_BLOCK_REGEX = /\\embed\{newLine\}\[\]/g;
|
|
70
|
+
const NEWLINE_LATEX = '\\newline ';
|
|
71
|
+
|
|
72
|
+
export class PreviewPrompt extends Component {
|
|
73
|
+
static propTypes = {
|
|
74
|
+
prompt: PropTypes.string,
|
|
75
|
+
tagName: PropTypes.string,
|
|
76
|
+
className: PropTypes.string,
|
|
77
|
+
onClick: PropTypes.func,
|
|
78
|
+
defaultClassName: PropTypes.string,
|
|
79
|
+
autoplayAudioEnabled: PropTypes.bool,
|
|
80
|
+
customAudioButton: PropTypes.shape({
|
|
81
|
+
playImage: PropTypes.string,
|
|
82
|
+
pauseImage: PropTypes.string,
|
|
83
|
+
}),
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
static defaultProps = {
|
|
87
|
+
onClick: () => {},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
parsedText: any = (text) => {
|
|
91
|
+
const { customAudioButton } = this.props;
|
|
92
|
+
const div = document.createElement('div');
|
|
93
|
+
div.innerHTML = text;
|
|
94
|
+
|
|
95
|
+
const audio = div.querySelector('audio');
|
|
96
|
+
if (audio) {
|
|
97
|
+
const source = document.createElement('source');
|
|
98
|
+
|
|
99
|
+
source.setAttribute('type', 'audio/mp3');
|
|
100
|
+
source.setAttribute('src', audio.getAttribute('src'));
|
|
101
|
+
|
|
102
|
+
audio.removeAttribute('src');
|
|
103
|
+
audio.setAttribute('id', 'pie-prompt-audio-player');
|
|
104
|
+
|
|
105
|
+
audio.appendChild(source);
|
|
106
|
+
|
|
107
|
+
if (customAudioButton) {
|
|
108
|
+
audio.style.display = 'none';
|
|
109
|
+
|
|
110
|
+
const playButton = document.createElement('div');
|
|
111
|
+
playButton.id = 'play-audio-button';
|
|
112
|
+
|
|
113
|
+
Object.assign(playButton.style, {
|
|
114
|
+
cursor: 'pointer',
|
|
115
|
+
display: 'block',
|
|
116
|
+
width: '128px',
|
|
117
|
+
height: '128px',
|
|
118
|
+
backgroundImage: `url(${customAudioButton.pauseImage})`,
|
|
119
|
+
backgroundSize: 'cover',
|
|
120
|
+
borderRadius: '50%',
|
|
121
|
+
border: '1px solid #326295',
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
audio.parentNode.insertBefore(playButton, audio);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return div.innerHTML;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
addCustomAudioButtonControls() {
|
|
132
|
+
const { autoplayAudioEnabled, customAudioButton } = this.props;
|
|
133
|
+
const playButton = document.getElementById('play-audio-button');
|
|
134
|
+
const audio = document.getElementById('pie-prompt-audio-player');
|
|
135
|
+
|
|
136
|
+
if (autoplayAudioEnabled && audio) {
|
|
137
|
+
audio
|
|
138
|
+
.play()
|
|
139
|
+
.then(() => {
|
|
140
|
+
if (playButton && customAudioButton) {
|
|
141
|
+
audio.addEventListener('ended', handleAudioEnded);
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
.catch((error) => {
|
|
145
|
+
console.error('Error playing audio', error);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (!playButton || !audio || !customAudioButton) return;
|
|
150
|
+
|
|
151
|
+
const handlePlayClick = () => {
|
|
152
|
+
// if already playing, don't play again
|
|
153
|
+
if (!audio.paused) return;
|
|
154
|
+
if (playButton.style.backgroundImage.includes(customAudioButton.pauseImage)) return;
|
|
155
|
+
|
|
156
|
+
audio.play();
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const handleAudioEnded = () => {
|
|
160
|
+
playButton.style.backgroundImage = `url(${customAudioButton.playImage})`;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const handleAudioPlay = () => {
|
|
164
|
+
Object.assign(playButton.style, {
|
|
165
|
+
backgroundImage: `url(${customAudioButton.pauseImage})`,
|
|
166
|
+
border: '1px solid #ccc',
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const handleAudioPause = () => {
|
|
171
|
+
Object.assign(playButton.style, {
|
|
172
|
+
backgroundImage: `url(${customAudioButton.playImage})`,
|
|
173
|
+
border: '1px solid #326295',
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
playButton.addEventListener('click', handlePlayClick);
|
|
178
|
+
audio.addEventListener('play', handleAudioPlay);
|
|
179
|
+
audio.addEventListener('pause', handleAudioPause);
|
|
180
|
+
audio.addEventListener('ended', handleAudioEnded);
|
|
181
|
+
|
|
182
|
+
// store event handler references so they can be removed later
|
|
183
|
+
this._handlePlayClick = handlePlayClick;
|
|
184
|
+
this._handleAudioPlay = handleAudioPlay;
|
|
185
|
+
this._handleAudioPause = handleAudioPause;
|
|
186
|
+
this._handleAudioEnded = handleAudioEnded;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
removeCustomAudioButtonListeners() {
|
|
190
|
+
const playButton = document.getElementById('play-audio-button');
|
|
191
|
+
const audio = document.querySelector('audio');
|
|
192
|
+
|
|
193
|
+
if (!playButton || !audio) return;
|
|
194
|
+
|
|
195
|
+
// remove event listeners using stored references
|
|
196
|
+
playButton.removeEventListener('click', this._handlePlayClick);
|
|
197
|
+
audio.removeEventListener('play', this._handleAudioPlay);
|
|
198
|
+
audio.removeEventListener('pause', this._handleAudioPause);
|
|
199
|
+
audio.removeEventListener('ended', this._handleAudioEnded);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
componentDidMount() {
|
|
203
|
+
this.alignImages();
|
|
204
|
+
this.addCustomAudioButtonControls();
|
|
205
|
+
this.setupMathRendering();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
componentDidUpdate(prevProps) {
|
|
209
|
+
this.alignImages();
|
|
210
|
+
|
|
211
|
+
if (prevProps.prompt !== this.props.prompt) {
|
|
212
|
+
this.renderMathContent();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
componentWillUnmount() {
|
|
217
|
+
this.removeCustomAudioButtonListeners();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
setupMathRendering() {
|
|
221
|
+
this.renderMathContent();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
renderMathContent() {
|
|
225
|
+
const container = document.getElementById('preview-prompt');
|
|
226
|
+
if (container && typeof renderMath === 'function') {
|
|
227
|
+
renderMath(container);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
alignImages() {
|
|
232
|
+
const previewPrompts = document.querySelectorAll('#preview-prompt');
|
|
233
|
+
|
|
234
|
+
previewPrompts.forEach((previewPrompt) => {
|
|
235
|
+
const images = previewPrompt.getElementsByTagName('img');
|
|
236
|
+
|
|
237
|
+
if (images && images.length) {
|
|
238
|
+
for (let image of images) {
|
|
239
|
+
// check if alignment property was set
|
|
240
|
+
if (image.attributes && image.attributes.alignment && image.attributes.alignment.value) {
|
|
241
|
+
const parentNode = image.parentElement;
|
|
242
|
+
|
|
243
|
+
// check if div is not already added to dom and replace current image with wrapped image
|
|
244
|
+
if (
|
|
245
|
+
!(
|
|
246
|
+
parentNode.tagName === 'DIV' &&
|
|
247
|
+
parentNode.style.display === 'flex' &&
|
|
248
|
+
parentNode.style.width === '100%'
|
|
249
|
+
)
|
|
250
|
+
) {
|
|
251
|
+
const div = document.createElement('div');
|
|
252
|
+
div.style.display = 'flex';
|
|
253
|
+
div.style.width = '100%';
|
|
254
|
+
|
|
255
|
+
const copyImage = image.cloneNode(true);
|
|
256
|
+
div.appendChild(copyImage);
|
|
257
|
+
parentNode.replaceChild(div, image);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
render() {
|
|
266
|
+
const { prompt, tagName, className, onClick, defaultClassName } = this.props;
|
|
267
|
+
// legend tag was added once with accessibility tasks, we need extra style to make it work with images alignment
|
|
268
|
+
const legendClass = tagName === 'legend' ? 'legend' : '';
|
|
269
|
+
const customClasses = `${className || ''} ${defaultClassName || ''} ${legendClass}`.trim();
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<StyledPromptContainer
|
|
273
|
+
as={tagName || 'div'}
|
|
274
|
+
id={'preview-prompt'}
|
|
275
|
+
onClick={onClick}
|
|
276
|
+
className={customClasses}
|
|
277
|
+
tagName={tagName}
|
|
278
|
+
dangerouslySetInnerHTML={{
|
|
279
|
+
__html: this.parsedText(prompt || '').replace(NEWLINE_BLOCK_REGEX, NEWLINE_LATEX),
|
|
280
|
+
}}
|
|
281
|
+
/>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export default PreviewPrompt;
|
package/src/purpose.tsx
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* @synced-from pie-lib/packages/render-ui/src/purpose.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 PropTypes from 'prop-types';
|
|
12
|
+
import React from 'react';
|
|
13
|
+
|
|
14
|
+
const Purpose = (props) => {
|
|
15
|
+
return (
|
|
16
|
+
<>
|
|
17
|
+
{React.Children.map(props.children, (child) => React.cloneElement(child, { 'data-pie-purpose': props.purpose }))}
|
|
18
|
+
</>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
Purpose.propTypes = {
|
|
23
|
+
children: PropTypes.node,
|
|
24
|
+
purpose: PropTypes.string,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default Purpose;
|
package/src/readable.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* @synced-from pie-lib/packages/render-ui/src/readable.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 PropTypes from 'prop-types';
|
|
12
|
+
import React from 'react';
|
|
13
|
+
|
|
14
|
+
const Readable = (props) => {
|
|
15
|
+
return (
|
|
16
|
+
<>
|
|
17
|
+
{React.Children.map(props.children, (child) =>
|
|
18
|
+
React.cloneElement(child, { 'data-pie-readable': props.false === undefined }),
|
|
19
|
+
)}
|
|
20
|
+
</>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
Readable.propTypes = {
|
|
25
|
+
children: PropTypes.node,
|
|
26
|
+
false: PropTypes.bool,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default Readable;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* @synced-from pie-lib/packages/render-ui/src/response-indicators.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 * as icons from '@pie-lib/icons';
|
|
14
|
+
import Popover from '@mui/material/Popover';
|
|
15
|
+
import { styled } from '@mui/material/styles';
|
|
16
|
+
import Feedback from './feedback.js';
|
|
17
|
+
import debug from 'debug';
|
|
18
|
+
|
|
19
|
+
const log = debug('pie-libs:render-ui:response-indicators');
|
|
20
|
+
|
|
21
|
+
const ResponseIndicatorContainer: any = styled('div')(({ hasFeedback }) => ({
|
|
22
|
+
cursor: hasFeedback ? 'pointer' : 'default',
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
const StyledPopover: any = styled(Popover)({
|
|
26
|
+
cursor: 'pointer',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const PopoverPaper: any = styled('div')({
|
|
30
|
+
padding: '0',
|
|
31
|
+
borderRadius: '4px',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const BuildIndicator = (Icon, correctness) => {
|
|
35
|
+
class Indicator extends React.Component {
|
|
36
|
+
constructor(props) {
|
|
37
|
+
super(props);
|
|
38
|
+
this.state = {};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
handlePopoverOpen: any = (event) => {
|
|
42
|
+
log('[handlePopoverOpen]', event.target);
|
|
43
|
+
this.setState({ anchorEl: event.target });
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
handlePopoverClose: any = () => {
|
|
47
|
+
this.setState({ anchorEl: null });
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
render() {
|
|
51
|
+
const { feedback } = this.props;
|
|
52
|
+
const { anchorEl } = this.state;
|
|
53
|
+
return (
|
|
54
|
+
<ResponseIndicatorContainer hasFeedback={!!feedback}>
|
|
55
|
+
<span ref={(r) => (this.icon = r)} onClick={this.handlePopoverOpen}>
|
|
56
|
+
<Icon />
|
|
57
|
+
</span>
|
|
58
|
+
|
|
59
|
+
{feedback && (
|
|
60
|
+
<StyledPopover
|
|
61
|
+
PaperComponent={PopoverPaper}
|
|
62
|
+
open={!!anchorEl}
|
|
63
|
+
anchorEl={anchorEl}
|
|
64
|
+
anchorOrigin={{
|
|
65
|
+
vertical: 'bottom',
|
|
66
|
+
horizontal: 'left',
|
|
67
|
+
}}
|
|
68
|
+
transformOrigin={{
|
|
69
|
+
vertical: 'top',
|
|
70
|
+
horizontal: 'left',
|
|
71
|
+
}}
|
|
72
|
+
onClose={this.handlePopoverClose}
|
|
73
|
+
>
|
|
74
|
+
<Feedback feedback={feedback} correctness={correctness} />
|
|
75
|
+
</StyledPopover>
|
|
76
|
+
)}
|
|
77
|
+
</ResponseIndicatorContainer>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
Indicator.propTypes = {
|
|
83
|
+
feedback: PropTypes.string,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return Indicator;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const Correct = BuildIndicator(icons.Correct, 'correct');
|
|
90
|
+
export const Incorrect = BuildIndicator(icons.Incorrect, 'incorrect');
|
|
91
|
+
export const PartiallyCorrect = BuildIndicator(icons.PartiallyCorrect, 'partially-correct');
|
|
92
|
+
export const NothingSubmitted = BuildIndicator(icons.NothingSubmitted, 'nothing-submitted');
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* @synced-from pie-lib/packages/render-ui/src/ui-layout.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 { createTheme, styled, StyledEngineProvider, ThemeProvider } from '@mui/material/styles';
|
|
13
|
+
import PropTypes from 'prop-types';
|
|
14
|
+
|
|
15
|
+
const theme = createTheme({
|
|
16
|
+
typography: {
|
|
17
|
+
fontFamily: 'inherit',
|
|
18
|
+
},
|
|
19
|
+
palette: {
|
|
20
|
+
action: {
|
|
21
|
+
disabled: 'rgba(0, 0, 0, 0.54);',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
components: {
|
|
25
|
+
MuiTypography: {
|
|
26
|
+
styleOverrides: {
|
|
27
|
+
root: { fontFamily: 'inherit' },
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
MuiButton: {
|
|
31
|
+
styleOverrides: {
|
|
32
|
+
contained: {
|
|
33
|
+
backgroundColor: '#e0e0e0',
|
|
34
|
+
color: '#000000',
|
|
35
|
+
'&:hover': {
|
|
36
|
+
backgroundColor: '#bdbdbd',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const StyledContainer: any = styled('div')({
|
|
45
|
+
// need this because some browsers set their own style on table
|
|
46
|
+
'& table, th, td': {
|
|
47
|
+
fontSize: 'inherit' /* Ensure table elements inherit font size */,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
class UiLayout extends React.Component {
|
|
52
|
+
static propTypes = {
|
|
53
|
+
className: PropTypes.string,
|
|
54
|
+
children: PropTypes.array,
|
|
55
|
+
extraCSSRules: PropTypes.shape({
|
|
56
|
+
names: PropTypes.arrayOf(PropTypes.string),
|
|
57
|
+
rules: PropTypes.string,
|
|
58
|
+
}),
|
|
59
|
+
fontSizeFactor: PropTypes.number,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
static defaultProps = {
|
|
63
|
+
extraCSSRules: {},
|
|
64
|
+
fontSizeFactor: 1,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
constructor(props) {
|
|
68
|
+
super(props);
|
|
69
|
+
this.classesSheet = document.createElement('style');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
computeStyle(fontSizeFactor) {
|
|
73
|
+
const getFontSize = (element) => parseFloat(getComputedStyle(element).fontSize);
|
|
74
|
+
|
|
75
|
+
const rootFontSize = getFontSize(document.documentElement);
|
|
76
|
+
const bodyFontSize = getFontSize(document.body);
|
|
77
|
+
const effectiveFontSize = Math.max(rootFontSize, bodyFontSize);
|
|
78
|
+
|
|
79
|
+
// Handle null, undefined, or invalid values by defaulting to 1
|
|
80
|
+
const factor = fontSizeFactor != null && typeof fontSizeFactor === 'number' ? fontSizeFactor : 1;
|
|
81
|
+
return factor !== 1 ? { fontSize: `${effectiveFontSize * factor}px` } : null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
render() {
|
|
85
|
+
const { children, className, fontSizeFactor, ...rest } = this.props;
|
|
86
|
+
|
|
87
|
+
const { extraCSSRules, ...restProps } = rest;
|
|
88
|
+
const style = this.computeStyle(fontSizeFactor);
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<StyledEngineProvider injectFirst>
|
|
92
|
+
<ThemeProvider theme={theme}>
|
|
93
|
+
{extraCSSRules?.rules ? (
|
|
94
|
+
<style dangerouslySetInnerHTML={{ __html: `.extraCSSRules { ${extraCSSRules.rules} }` }} />
|
|
95
|
+
) : null}
|
|
96
|
+
|
|
97
|
+
<StyledContainer className={`${className} extraCSSRules`} {...restProps} {...(style && { style })}>
|
|
98
|
+
{children}
|
|
99
|
+
</StyledContainer>
|
|
100
|
+
</ThemeProvider>
|
|
101
|
+
</StyledEngineProvider>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export default UiLayout;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* @synced-from pie-lib/packages/render-ui/src/withUndoReset.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 * as React from 'react';
|
|
12
|
+
import PropTypes from 'prop-types';
|
|
13
|
+
import Button from '@mui/material/Button';
|
|
14
|
+
import { styled } from '@mui/material/styles';
|
|
15
|
+
import Restore from '@mui/icons-material/Restore';
|
|
16
|
+
import Undo from '@mui/icons-material/Undo';
|
|
17
|
+
|
|
18
|
+
const Wrapper: any = styled('div')({
|
|
19
|
+
display: 'flex',
|
|
20
|
+
flexDirection: 'column',
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const ResetUndoContainer: any = styled('div')({
|
|
24
|
+
display: 'flex',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
justifyContent: 'center',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const StyledIcon: any = styled('div')(({ theme }) => ({
|
|
30
|
+
width: '24px',
|
|
31
|
+
height: '24px',
|
|
32
|
+
color: 'gray',
|
|
33
|
+
marginRight: theme.spacing(1),
|
|
34
|
+
display: 'flex',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
const StyledButton: any = styled(Button)(({ theme }) => ({
|
|
39
|
+
display: 'flex',
|
|
40
|
+
alignItems: 'center',
|
|
41
|
+
marginLeft: theme.spacing(3),
|
|
42
|
+
marginRight: theme.spacing(3),
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* HOC that adds undo and reset functionality for session values
|
|
47
|
+
*/
|
|
48
|
+
const withUndoReset = (WrappedComponent) => {
|
|
49
|
+
class WithUndoReset extends React.Component {
|
|
50
|
+
static propTypes = {
|
|
51
|
+
session: PropTypes.object,
|
|
52
|
+
onSessionChange: PropTypes.func,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
constructor(props) {
|
|
56
|
+
super(props);
|
|
57
|
+
|
|
58
|
+
this.state = {
|
|
59
|
+
sessionInitialValues: JSON.parse(JSON.stringify(props.session)),
|
|
60
|
+
session: props.session,
|
|
61
|
+
changes: [],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
onSessionChange: any = (session) => {
|
|
66
|
+
this.setState(
|
|
67
|
+
(state) => ({ session, changes: [...state.changes, session] }),
|
|
68
|
+
() => this.props.onSessionChange(session),
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
onUndo: any = () => {
|
|
73
|
+
this.setState(
|
|
74
|
+
(state) => {
|
|
75
|
+
const newChanges = [...state.changes];
|
|
76
|
+
|
|
77
|
+
newChanges.pop();
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
changes: newChanges,
|
|
81
|
+
session: newChanges.length ? newChanges[newChanges.length - 1] : state.sessionInitialValues,
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
() => this.props.onSessionChange(this.state.session),
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
onReset: any = () => {
|
|
89
|
+
this.setState(
|
|
90
|
+
(state) => ({ session: state.sessionInitialValues, changes: [] }),
|
|
91
|
+
() => this.props.onSessionChange(this.state.sessionInitialValues),
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
render() {
|
|
96
|
+
const { ...rest } = this.props;
|
|
97
|
+
const { changes, session } = this.state;
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<Wrapper>
|
|
101
|
+
<ResetUndoContainer>
|
|
102
|
+
<StyledButton color="primary" disabled={changes.length === 0} onClick={this.onUndo}>
|
|
103
|
+
<StyledIcon>
|
|
104
|
+
<Undo />
|
|
105
|
+
</StyledIcon>
|
|
106
|
+
Undo
|
|
107
|
+
</StyledButton>
|
|
108
|
+
<StyledButton color="primary" disabled={changes.length === 0} onClick={this.onReset}>
|
|
109
|
+
<StyledIcon>
|
|
110
|
+
<Restore />
|
|
111
|
+
</StyledIcon>
|
|
112
|
+
Start Over
|
|
113
|
+
</StyledButton>
|
|
114
|
+
</ResetUndoContainer>
|
|
115
|
+
<WrappedComponent {...rest} session={session} onSessionChange={this.onSessionChange} />
|
|
116
|
+
</Wrapper>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return WithUndoReset;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export default withUndoReset;
|