@pie-lib/render-ui 6.1.1-next.1 → 6.1.1-next.37

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