@elice/material-quiz 1.240709.0 → 1.240711.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/cjs/components/material-quiz/MaterialQuiz.js +32 -12
- package/cjs/components/material-quiz/MaterialQuizInfo.js +57 -12
- package/cjs/components/material-quiz/MaterialQuizSelectMultiple.js +12 -5
- package/cjs/components/material-quiz/MaterialQuizSelectMultipleOrder.js +11 -5
- package/cjs/components/material-quiz/MaterialQuizSelectOne.js +12 -5
- package/cjs/components/material-quiz/MaterialQuizText.js +11 -5
- package/cjs/components/material-quiz/context/MaterialQuizContext.d.ts +2 -0
- package/cjs/components/material-quiz/context/MaterialQuizContext.js +14 -2
- package/cjs/components/material-quiz/locales/en.json.js +1 -1
- package/cjs/components/material-quiz/locales/ja.json.js +1 -1
- package/cjs/components/material-quiz/locales/ko.json.js +1 -1
- package/cjs/components/material-quiz/locales/th.json.js +1 -1
- package/cjs/components/material-quiz/material-quiz-group/MaterialQuizGroup.js +23 -30
- package/cjs/components/shared/QuestionBox.js +57 -37
- package/cjs/components/shared/utils/mergeRefs.d.ts +2 -0
- package/cjs/components/shared/utils/mergeRefs.js +11 -0
- package/cjs/hooks/useCaculatePassage.js +11 -3
- package/es/components/material-quiz/MaterialQuiz.js +32 -12
- package/es/components/material-quiz/MaterialQuizInfo.js +58 -13
- package/es/components/material-quiz/MaterialQuizSelectMultiple.js +14 -7
- package/es/components/material-quiz/MaterialQuizSelectMultipleOrder.js +12 -6
- package/es/components/material-quiz/MaterialQuizSelectOne.js +13 -6
- package/es/components/material-quiz/MaterialQuizText.js +12 -6
- package/es/components/material-quiz/context/MaterialQuizContext.d.ts +2 -0
- package/es/components/material-quiz/context/MaterialQuizContext.js +15 -3
- package/es/components/material-quiz/locales/en.json.js +1 -1
- package/es/components/material-quiz/locales/ja.json.js +1 -1
- package/es/components/material-quiz/locales/ko.json.js +1 -1
- package/es/components/material-quiz/locales/th.json.js +1 -1
- package/es/components/material-quiz/material-quiz-group/MaterialQuizGroup.js +24 -31
- package/es/components/shared/QuestionBox.js +57 -37
- package/es/components/shared/utils/mergeRefs.d.ts +2 -0
- package/es/components/shared/utils/mergeRefs.js +9 -0
- package/es/hooks/useCaculatePassage.js +12 -4
- package/package.json +5 -4
|
@@ -7,7 +7,7 @@ var apiClient = require('@elice/api-client');
|
|
|
7
7
|
var blocks = require('@elice/blocks');
|
|
8
8
|
var designTokens = require('@elice/design-tokens');
|
|
9
9
|
var intl = require('@elice/intl');
|
|
10
|
-
var
|
|
10
|
+
var material = require('@mui/material');
|
|
11
11
|
var cloneDeep = require('lodash-es/cloneDeep');
|
|
12
12
|
var flattenDeep = require('lodash-es/flattenDeep');
|
|
13
13
|
var element = require('../../../constant/element.js');
|
|
@@ -16,6 +16,7 @@ var useCaculatePassage = require('../../../hooks/useCaculatePassage.js');
|
|
|
16
16
|
var QuestionBox = require('../../shared/QuestionBox.js');
|
|
17
17
|
var MaterialQuizContext = require('../context/MaterialQuizContext.js');
|
|
18
18
|
var MaterialQuizAnswerExplanation = require('../MaterialQuizAnswerExplanation.js');
|
|
19
|
+
var MaterialQuizInfo = require('../MaterialQuizInfo.js');
|
|
19
20
|
var QuizResultBadge = require('../QuizResultBadge.js');
|
|
20
21
|
var QuizSubmitStatusText = require('../QuizSubmitStatusText.js');
|
|
21
22
|
var context = require('./context/context.js');
|
|
@@ -31,7 +32,8 @@ const MaterialQuizGroup = () => {
|
|
|
31
32
|
const {
|
|
32
33
|
materialQuiz,
|
|
33
34
|
userId,
|
|
34
|
-
vertical
|
|
35
|
+
vertical,
|
|
36
|
+
isLongPassage
|
|
35
37
|
} = MaterialQuizContext.useMaterialQuizState();
|
|
36
38
|
const {
|
|
37
39
|
onSubmit,
|
|
@@ -39,6 +41,7 @@ const MaterialQuizGroup = () => {
|
|
|
39
41
|
refreshOrgMaterialQuiz,
|
|
40
42
|
onDirty
|
|
41
43
|
} = MaterialQuizContext.useMaterialQuizDispatch();
|
|
44
|
+
const theme = material.useTheme();
|
|
42
45
|
const [groupList, setGroupList] = React.useState([]);
|
|
43
46
|
const [optionList, setOptionList] = React.useState([]);
|
|
44
47
|
const [currentAnswerList, setCurrentAnswerList] = React.useState([]);
|
|
@@ -47,9 +50,12 @@ const MaterialQuizGroup = () => {
|
|
|
47
50
|
const [submitStatus, setSubmitStatus] = React.useState('idle');
|
|
48
51
|
const [hasSubmitted, setHasSubmitted] = React.useState(false);
|
|
49
52
|
const isNextActive = hasSubmitted && typeof onNext === 'function';
|
|
53
|
+
const isDisabled = !flattenDeep(currentAnswerList).length || !!userId;
|
|
50
54
|
const {
|
|
51
|
-
questionRef
|
|
55
|
+
questionRef,
|
|
56
|
+
containerRef
|
|
52
57
|
} = useCaculatePassage.useCaculatePassage();
|
|
58
|
+
const isVisibleSideBySide = !vertical && isLongPassage;
|
|
53
59
|
/**
|
|
54
60
|
*
|
|
55
61
|
*/
|
|
@@ -231,7 +237,7 @@ const MaterialQuizGroup = () => {
|
|
|
231
237
|
*
|
|
232
238
|
*/
|
|
233
239
|
const renderQuizInfo = () => {
|
|
234
|
-
if (!materialQuiz) {
|
|
240
|
+
if (!materialQuiz || isVisibleSideBySide) {
|
|
235
241
|
return null;
|
|
236
242
|
}
|
|
237
243
|
return React.createElement(blocks.Flex, {
|
|
@@ -239,26 +245,9 @@ const MaterialQuizGroup = () => {
|
|
|
239
245
|
id: element.MATERIAL_QUIZ_PASSIVE_ID,
|
|
240
246
|
column: true,
|
|
241
247
|
ref: questionRef
|
|
242
|
-
}, React.createElement(
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
customStyles: {
|
|
246
|
-
color: designTokens.base.color.primary3,
|
|
247
|
-
marginRight: '0.5rem'
|
|
248
|
-
}
|
|
249
|
-
}, 'Q.'), React.createElement(blocks.Text, {
|
|
250
|
-
bold: true,
|
|
251
|
-
role: "white",
|
|
252
|
-
size: "large",
|
|
253
|
-
wordBreak: "break-word"
|
|
254
|
-
}, materialQuiz.questionTitle)), materialQuiz.questionDescription ? React.createElement(React.Fragment, null, React.createElement(blocks.Vspace, {
|
|
255
|
-
height: 1
|
|
256
|
-
}), React.createElement(markdown.MarkdownSSR, {
|
|
257
|
-
children: materialQuiz.questionDescription,
|
|
258
|
-
dark: true,
|
|
259
|
-
paddingx: 0,
|
|
260
|
-
paddingy: 0
|
|
261
|
-
})) : null, React.createElement(MaterialQuizAnswerExplanation.default, null));
|
|
248
|
+
}, React.createElement(MaterialQuizInfo.default, {
|
|
249
|
+
renderWithBox: false
|
|
250
|
+
}));
|
|
262
251
|
};
|
|
263
252
|
//
|
|
264
253
|
//
|
|
@@ -287,21 +276,25 @@ const MaterialQuizGroup = () => {
|
|
|
287
276
|
submitResult: React.createElement(QuizResultBadge.default, {
|
|
288
277
|
materialQuizResponse: materialQuizResponse
|
|
289
278
|
}),
|
|
279
|
+
bodyContainerRef: containerRef,
|
|
290
280
|
footerActions: [{
|
|
291
|
-
border:
|
|
292
|
-
disabled:
|
|
281
|
+
border: false,
|
|
282
|
+
disabled: isDisabled,
|
|
293
283
|
loading: submitStatus === 'pending',
|
|
294
284
|
tabIndex: 0,
|
|
295
285
|
transparent: false,
|
|
296
|
-
role: isNextActive ? 'secondary' : 'lightpurple',
|
|
297
286
|
onClick: handleSubmit,
|
|
298
287
|
children: intl$1.formatMessage({
|
|
299
288
|
id: isNextActive ? 'materialQuiz.resubmit' : 'materialQuiz.submit'
|
|
300
|
-
})
|
|
289
|
+
}),
|
|
290
|
+
customStyles: {
|
|
291
|
+
backgroundColor: isNextActive ? theme.palette.secondary.main : isDisabled ? designTokens.base.color.gray6 : theme.palette.primary.main,
|
|
292
|
+
color: isNextActive ? theme.palette.secondary.contrastText : isDisabled ? designTokens.base.color.gray3 : theme.palette.primary.contrastText
|
|
293
|
+
}
|
|
301
294
|
}]
|
|
302
|
-
}, renderQuizInfo(), vertical ? React.createElement("div", {
|
|
295
|
+
}, renderQuizInfo(), vertical || isVisibleSideBySide ? React.createElement("div", {
|
|
303
296
|
id: element.MATERIAL_QUIZ_ANSWER_ID
|
|
304
|
-
}, React.createElement(MaterialQuizGroupMobile.default, null)) : React.createElement(MaterialQuizGroupDesktop.default, null)));
|
|
297
|
+
}, React.createElement(MaterialQuizGroupMobile.default, null)) : React.createElement(React.Fragment, null, React.createElement(MaterialQuizGroupDesktop.default, null)), React.createElement(MaterialQuizAnswerExplanation.default, null)));
|
|
305
298
|
};
|
|
306
299
|
var MaterialQuizGroup$1 = MaterialQuizGroup;
|
|
307
300
|
|
|
@@ -8,10 +8,16 @@ var reactUse = require('react-use');
|
|
|
8
8
|
var blocks = require('@elice/blocks');
|
|
9
9
|
var designTokens = require('@elice/design-tokens');
|
|
10
10
|
var intl = require('@elice/intl');
|
|
11
|
+
var material = require('@mui/material');
|
|
12
|
+
var animateScrollTo = require('animated-scroll-to');
|
|
11
13
|
var styled = require('styled-components');
|
|
12
14
|
var element = require('../../constant/element.js');
|
|
13
15
|
var MaterialQuizContext = require('../material-quiz/context/MaterialQuizContext.js');
|
|
16
|
+
var mergeRefs = require('./utils/mergeRefs.js');
|
|
14
17
|
|
|
18
|
+
const easeInOutCubic = t => {
|
|
19
|
+
return t < 0.5 ? 4 * Math.pow(t, 3) : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
|
|
20
|
+
};
|
|
15
21
|
const StyledQuestionBox = styled.div.withConfig({
|
|
16
22
|
componentId: "sc-6qfyxj-0"
|
|
17
23
|
})(["position:relative;display:flex;flex-direction:column;overflow:", ";border-radius:", ";width:100%;background-color:", ";", ";"], ({
|
|
@@ -26,7 +32,9 @@ const StyledQuestionBox = styled.div.withConfig({
|
|
|
26
32
|
`);
|
|
27
33
|
const StyledQuestionBoxHeader = styled.div.withConfig({
|
|
28
34
|
componentId: "sc-6qfyxj-1"
|
|
29
|
-
})(["display:flex;justify-content:space-between;background-color:", ";padding:
|
|
35
|
+
})(["display:flex;justify-content:space-between;background-color:", ";padding:", ";flex:none;", ""], designTokens.base.color.navy8, ({
|
|
36
|
+
vertical
|
|
37
|
+
}) => !vertical ? '1.5rem' : '1.5rem 1rem 1rem', ({
|
|
30
38
|
vertical
|
|
31
39
|
}) => vertical ? `
|
|
32
40
|
position: sticky;
|
|
@@ -36,18 +44,16 @@ const StyledQuestionBoxHeader = styled.div.withConfig({
|
|
|
36
44
|
` : '');
|
|
37
45
|
const StyledQuestionBoxBody = styled.div.withConfig({
|
|
38
46
|
componentId: "sc-6qfyxj-2"
|
|
39
|
-
})(["background-color:", ";flex:
|
|
40
|
-
vertical
|
|
41
|
-
}) => vertical ? 'none' : 'auto', ({
|
|
47
|
+
})(["background-color:", ";flex:auto;", ";"], designTokens.base.color.navy8, ({
|
|
42
48
|
hasFooter,
|
|
43
49
|
vertical
|
|
44
|
-
}) => hasFooter && !vertical ? 'height: 100%; padding: 0 1.5rem 1.5rem; overflow-y: auto;' : 'padding: 1.5rem');
|
|
50
|
+
}) => hasFooter && !vertical ? 'height: 100%; padding: 0 1.5rem 1.5rem; overflow-y: auto;' : 'padding: 0.25rem 1.5rem 1.5rem');
|
|
45
51
|
const StyledAnchorBox = styled.div.withConfig({
|
|
46
52
|
componentId: "sc-6qfyxj-3"
|
|
47
53
|
})(["position:sticky;bottom:0;left:0;display:flex;justify-content:center;background-color:", ";border-top:1px solid ", ";"], designTokens.base.color.navy8, designTokens.base.color.gray7);
|
|
48
54
|
const StyledQuestionBoxFooter = styled.div.withConfig({
|
|
49
55
|
componentId: "sc-6qfyxj-4"
|
|
50
|
-
})(["flex:none;display:flex;align-items:center;padding:1rem
|
|
56
|
+
})(["flex:none;display:flex;align-items:center;padding:1rem;background-color:", ";", ""], designTokens.base.color.navy8, ({
|
|
51
57
|
vertical
|
|
52
58
|
}) => {
|
|
53
59
|
return vertical ? `
|
|
@@ -66,16 +72,6 @@ const StyledQuestionBoxFooterActions = styled.div.withConfig({
|
|
|
66
72
|
}) => {
|
|
67
73
|
return vertical ? 'width: 100%' : '';
|
|
68
74
|
});
|
|
69
|
-
const StyledQuestionBoxFooterStatus = styled.div.withConfig({
|
|
70
|
-
componentId: "sc-6qfyxj-6"
|
|
71
|
-
})(["margin-left:0.75rem;", ""], ({
|
|
72
|
-
vertical
|
|
73
|
-
}) => {
|
|
74
|
-
return vertical ? `
|
|
75
|
-
margin-top: 0.75rem;
|
|
76
|
-
order: 1;
|
|
77
|
-
` : '';
|
|
78
|
-
});
|
|
79
75
|
const QuestionBox = _a => {
|
|
80
76
|
var {
|
|
81
77
|
children,
|
|
@@ -89,18 +85,22 @@ const QuestionBox = _a => {
|
|
|
89
85
|
bodyContainerRef
|
|
90
86
|
} = _a,
|
|
91
87
|
props = tslib.__rest(_a, ["children", "footerActions", "title", "titlePrefix", "submitResult", "submitStatus", "onNext", "isNextActive", "bodyContainerRef"]);
|
|
88
|
+
const theme = material.useTheme();
|
|
92
89
|
const intl$1 = intl.useRawEliceIntl();
|
|
93
90
|
const {
|
|
94
91
|
vertical,
|
|
95
92
|
isLongPassage
|
|
96
93
|
} = MaterialQuizContext.useMaterialQuizState();
|
|
97
94
|
const intersectionRef = React.useRef(null);
|
|
95
|
+
const headerRef = React.useRef(null);
|
|
96
|
+
const bodyRef = React.useRef(null);
|
|
97
|
+
const currentBodyRef = mergeRefs.mergeRefs(bodyContainerRef, bodyRef);
|
|
98
98
|
const hasFooter = footerActions.length > 0;
|
|
99
99
|
const visibleAnchorSection = vertical && isLongPassage;
|
|
100
100
|
const intersection = reactUse.useIntersection(intersectionRef, {
|
|
101
101
|
root: null,
|
|
102
102
|
rootMargin: '0px',
|
|
103
|
-
threshold: 1
|
|
103
|
+
threshold: 0.1
|
|
104
104
|
});
|
|
105
105
|
const isViewingAnswerContainer = Boolean(intersection === null || intersection === void 0 ? void 0 : intersection.isIntersecting);
|
|
106
106
|
React.useEffect(() => {
|
|
@@ -108,15 +108,22 @@ const QuestionBox = _a => {
|
|
|
108
108
|
// only enable for vertical mode
|
|
109
109
|
if (answerContainer && vertical) intersectionRef.current = answerContainer;
|
|
110
110
|
}, [intersectionRef, vertical]);
|
|
111
|
-
const scrollToElement = elementId => {
|
|
111
|
+
const scrollToElement = async elementId => {
|
|
112
|
+
var _a, _b;
|
|
112
113
|
const target = document.getElementById(elementId);
|
|
113
|
-
target &&
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
if (target && bodyRef.current) {
|
|
115
|
+
await animateScrollTo(target.offsetTop, {
|
|
116
|
+
elementToScroll: bodyRef.current,
|
|
117
|
+
verticalOffset: -((_b = (_a = headerRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) !== null && _b !== void 0 ? _b : 0),
|
|
118
|
+
easing: easeInOutCubic,
|
|
119
|
+
minDuration: 50,
|
|
120
|
+
speed: 200
|
|
121
|
+
});
|
|
122
|
+
}
|
|
117
123
|
};
|
|
118
124
|
const header = title ? React.createElement(StyledQuestionBoxHeader, {
|
|
119
|
-
vertical: vertical
|
|
125
|
+
vertical: vertical,
|
|
126
|
+
ref: headerRef
|
|
120
127
|
}, React.createElement(blocks.Flex, null, titlePrefix ? React.createElement(blocks.Text, {
|
|
121
128
|
bold: true,
|
|
122
129
|
size: "large",
|
|
@@ -131,36 +138,38 @@ const QuestionBox = _a => {
|
|
|
131
138
|
wordBreak: "break-word"
|
|
132
139
|
}, title)), submitResult ? React.createElement(blocks.Box, null, submitResult) : null) : null;
|
|
133
140
|
const body = React.createElement(StyledQuestionBoxBody, {
|
|
141
|
+
ref: !vertical ? currentBodyRef : undefined,
|
|
134
142
|
hasFooter: hasFooter,
|
|
135
|
-
ref: bodyContainerRef,
|
|
136
143
|
vertical: vertical
|
|
137
144
|
}, children);
|
|
138
145
|
const footer = React.createElement(StyledQuestionBoxFooter, {
|
|
139
146
|
vertical: vertical
|
|
140
|
-
}, React.createElement(
|
|
141
|
-
vertical: vertical
|
|
142
|
-
}, submitStatus), React.createElement(StyledQuestionBoxFooterActions, {
|
|
147
|
+
}, React.createElement(StyledQuestionBoxFooterActions, {
|
|
143
148
|
vertical: vertical
|
|
144
149
|
}, footerActions.map((action, index) => React.createElement(blocks.Button, Object.assign({
|
|
145
|
-
isFluid:
|
|
150
|
+
isFluid: vertical,
|
|
146
151
|
key: index,
|
|
147
152
|
size: "small"
|
|
148
153
|
}, action), action.children)), isNextActive ? React.createElement(blocks.Button, {
|
|
149
|
-
isFluid:
|
|
154
|
+
isFluid: vertical,
|
|
150
155
|
size: "small",
|
|
151
|
-
border:
|
|
156
|
+
border: false,
|
|
152
157
|
tabIndex: 0,
|
|
153
158
|
transparent: false,
|
|
154
|
-
|
|
155
|
-
|
|
159
|
+
onClick: onNext,
|
|
160
|
+
customStyles: {
|
|
161
|
+
backgroundColor: theme.palette.primary.main,
|
|
162
|
+
color: theme.palette.primary.contrastText
|
|
163
|
+
}
|
|
156
164
|
}, intl$1.formatMessage({
|
|
157
165
|
id: 'materialQuiz.next'
|
|
158
166
|
})) : null));
|
|
159
167
|
const _renderAnchorSection = () => {
|
|
160
168
|
const getCustomStyles = active => ({
|
|
161
|
-
borderBottom:
|
|
169
|
+
borderBottom: '3px solid currentColor',
|
|
162
170
|
background: 'none',
|
|
163
|
-
|
|
171
|
+
borderColor: active ? 'currentColor' : 'transparent',
|
|
172
|
+
color: active ? theme.palette.primary.main : theme.palette.secondary.light
|
|
164
173
|
});
|
|
165
174
|
return visibleAnchorSection && React.createElement(StyledAnchorBox, null, React.createElement(blocks.Button, {
|
|
166
175
|
size: "small",
|
|
@@ -168,7 +177,6 @@ const QuestionBox = _a => {
|
|
|
168
177
|
hasBorderRadius: false,
|
|
169
178
|
tabIndex: 0,
|
|
170
179
|
transparent: true,
|
|
171
|
-
role: isViewingAnswerContainer ? 'white' : 'primary',
|
|
172
180
|
onClick: scrollToElement.bind(null, element.MATERIAL_QUIZ_PASSIVE_ID),
|
|
173
181
|
customStyles: getCustomStyles(!isViewingAnswerContainer)
|
|
174
182
|
}, intl$1.formatMessage({
|
|
@@ -179,16 +187,28 @@ const QuestionBox = _a => {
|
|
|
179
187
|
hasBorderRadius: false,
|
|
180
188
|
tabIndex: 0,
|
|
181
189
|
transparent: true,
|
|
182
|
-
role: isViewingAnswerContainer ? 'primary' : 'white',
|
|
183
190
|
onClick: scrollToElement.bind(null, element.MATERIAL_QUIZ_ANSWER_ID),
|
|
184
191
|
customStyles: getCustomStyles(isViewingAnswerContainer)
|
|
185
192
|
}, intl$1.formatMessage({
|
|
186
193
|
id: 'materialQuiz.anchorLabel.answer'
|
|
187
194
|
})));
|
|
188
195
|
};
|
|
196
|
+
const renderContent = () => {
|
|
197
|
+
const content = React.createElement(React.Fragment, null, body, footerActions.length > 0 ? footer : null);
|
|
198
|
+
if (vertical) {
|
|
199
|
+
return React.createElement("div", {
|
|
200
|
+
ref: currentBodyRef,
|
|
201
|
+
style: {
|
|
202
|
+
height: '100%',
|
|
203
|
+
overflow: 'auto'
|
|
204
|
+
}
|
|
205
|
+
}, content);
|
|
206
|
+
}
|
|
207
|
+
return content;
|
|
208
|
+
};
|
|
189
209
|
return React.createElement(StyledQuestionBox, Object.assign({}, props, {
|
|
190
210
|
vertical: vertical
|
|
191
|
-
}), header,
|
|
211
|
+
}), header, renderContent(), _renderAnchorSection());
|
|
192
212
|
};
|
|
193
213
|
|
|
194
214
|
exports.StyledQuestionBox = StyledQuestionBox;
|
|
@@ -11,7 +11,8 @@ const useCaculatePassage = () => {
|
|
|
11
11
|
vertical
|
|
12
12
|
} = MaterialQuizContext.useMaterialQuizState();
|
|
13
13
|
const {
|
|
14
|
-
setIsLongPassage
|
|
14
|
+
setIsLongPassage,
|
|
15
|
+
setIsInitialLoading
|
|
15
16
|
} = MaterialQuizContext.useMaterialQuizDispatch();
|
|
16
17
|
const [questionRef, {
|
|
17
18
|
height: questionDetailHeight
|
|
@@ -19,13 +20,20 @@ const useCaculatePassage = () => {
|
|
|
19
20
|
const [containerRef, {
|
|
20
21
|
height: containerHeight
|
|
21
22
|
}] = reactUse.useMeasure();
|
|
22
|
-
React.
|
|
23
|
+
React.useEffect(() => {
|
|
23
24
|
var _a, _b;
|
|
24
25
|
const currentContainerHeight = vertical ? (_b = (_a = document.getElementById(element.MATERIAL_QUIZ_CONTAINER_ID)) === null || _a === void 0 ? void 0 : _a.offsetHeight) !== null && _b !== void 0 ? _b : 0 : containerHeight;
|
|
25
26
|
if (currentContainerHeight && questionDetailHeight && materialQuiz) {
|
|
26
27
|
setIsLongPassage(questionDetailHeight > currentContainerHeight);
|
|
28
|
+
// add timeout for forcing caculate layout and render in the parent
|
|
29
|
+
// finish before turning off loading
|
|
30
|
+
setTimeout(() => {
|
|
31
|
+
setIsInitialLoading(false);
|
|
32
|
+
}, 300);
|
|
33
|
+
} else if (materialQuiz && !materialQuiz.questionDescription) {
|
|
34
|
+
setIsInitialLoading(false);
|
|
27
35
|
}
|
|
28
|
-
}, [containerHeight, questionDetailHeight, materialQuiz, setIsLongPassage, vertical]);
|
|
36
|
+
}, [containerHeight, questionDetailHeight, materialQuiz, setIsLongPassage, vertical, setIsInitialLoading]);
|
|
29
37
|
return {
|
|
30
38
|
questionRef,
|
|
31
39
|
containerRef
|
|
@@ -2,7 +2,9 @@ import React from 'react';
|
|
|
2
2
|
import { useMeasure } from 'react-use';
|
|
3
3
|
import { base } from '@elice/design-tokens';
|
|
4
4
|
import { IntlComponentBuilder, RawEliceIntlProvider } from '@elice/intl';
|
|
5
|
+
import { createEliceTheme } from '@elice/mui-system';
|
|
5
6
|
import { enums } from '@elice/types';
|
|
7
|
+
import { ThemeProvider } from '@mui/material';
|
|
6
8
|
import styled from 'styled-components';
|
|
7
9
|
import { MATERIAL_QUIZ_CONTAINER_ID } from '../../constant/element.js';
|
|
8
10
|
import { MaterialQuizProvider, useMaterialQuizState, useMaterialQuizDispatch } from './context/MaterialQuizContext.js';
|
|
@@ -11,27 +13,39 @@ import messageKo from './locales/ko.json.js';
|
|
|
11
13
|
import MaterialQuizShimmer from './MaterialQuizShimmer.js';
|
|
12
14
|
import MaterialQuizInfo from './MaterialQuizInfo.js';
|
|
13
15
|
|
|
16
|
+
const eliceTheme = createEliceTheme({
|
|
17
|
+
paletteMode: 'dark',
|
|
18
|
+
paletteName: 'purple'
|
|
19
|
+
});
|
|
14
20
|
const AsyncMaterialQuizSelectMultiple = React.lazy(() => import('./MaterialQuizSelectMultiple.js'));
|
|
15
21
|
const AsyncMaterialQuizSelectMultipleOrder = React.lazy(() => import('./MaterialQuizSelectMultipleOrder.js'));
|
|
16
22
|
const AsyncMaterialQuizText = React.lazy(() => import('./MaterialQuizText.js'));
|
|
17
23
|
const AsyncMaterialQuizSelectOne = React.lazy(() => import('./MaterialQuizSelectOne.js'));
|
|
18
24
|
const AsyncMaterialQuizGroup = React.lazy(() => import('./material-quiz-group/index.js'));
|
|
25
|
+
// 746px
|
|
26
|
+
const MAX_CONTENT_WIDTH = '46.625rem';
|
|
19
27
|
const StyledMaterialQuizInfo = styled.div.withConfig({
|
|
20
28
|
componentId: "sc-1eyn8fb-0"
|
|
21
29
|
})([""]);
|
|
22
30
|
const StyledMaterialQuizContent = styled.div.withConfig({
|
|
23
31
|
componentId: "sc-1eyn8fb-1"
|
|
24
|
-
})(["min-width:0;margin:", ";height:100%;"], ({
|
|
32
|
+
})(["position:relative;z-index:0;min-width:0;margin:", ";height:100%;"], ({
|
|
25
33
|
vertical
|
|
26
34
|
}) => vertical ? 'unset' : 'auto');
|
|
27
|
-
const
|
|
35
|
+
const LoadingContainer = styled.div.withConfig({
|
|
28
36
|
componentId: "sc-1eyn8fb-2"
|
|
29
|
-
})(["
|
|
37
|
+
})(["position:absolute;width:100%;height:100%;top:0;left:0;z-index:1;max-width:none !important;background-color:", ";"], base.color.navy8);
|
|
38
|
+
const StyledMaterialQuizWrapper = styled.div.withConfig({
|
|
39
|
+
componentId: "sc-1eyn8fb-3"
|
|
40
|
+
})(["-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;width:100%;height:100%;flex-direction:", ";position:relative;& > *{flex:", ";max-width:", ";}gap:1rem;", "{height:", ";overflow-y:", ";& > div{max-height:unset;}}"], ({
|
|
30
41
|
vertical
|
|
31
42
|
}) => vertical ? 'column' : 'row', ({
|
|
43
|
+
vertical
|
|
44
|
+
}) => vertical ? 'auto' : '1', ({
|
|
32
45
|
vertical,
|
|
33
|
-
isQuizGroupType
|
|
34
|
-
|
|
46
|
+
isQuizGroupType,
|
|
47
|
+
isLongPassage
|
|
48
|
+
}) => !isLongPassage && !vertical && !isQuizGroupType ? `${MAX_CONTENT_WIDTH}` : 'unset', StyledMaterialQuizInfo, ({
|
|
35
49
|
vertical
|
|
36
50
|
}) => vertical ? 'auto' : '100%', ({
|
|
37
51
|
vertical
|
|
@@ -41,7 +55,8 @@ const MaterialQuiz = () => {
|
|
|
41
55
|
materialQuiz,
|
|
42
56
|
vertical,
|
|
43
57
|
course,
|
|
44
|
-
isLongPassage
|
|
58
|
+
isLongPassage,
|
|
59
|
+
isInitialLoading
|
|
45
60
|
} = useMaterialQuizState();
|
|
46
61
|
const {
|
|
47
62
|
setVertical
|
|
@@ -50,7 +65,9 @@ const MaterialQuiz = () => {
|
|
|
50
65
|
width
|
|
51
66
|
}] = useMeasure();
|
|
52
67
|
const isQuizGroupType = Boolean((materialQuiz === null || materialQuiz === void 0 ? void 0 : materialQuiz.optionType) === enums.QuizOptionType.Group);
|
|
53
|
-
const
|
|
68
|
+
const isFetchingData = !materialQuiz || !course;
|
|
69
|
+
const isLoadingLayout = isFetchingData || isInitialLoading;
|
|
70
|
+
const isVisibleSideBySide = !vertical && isLongPassage;
|
|
54
71
|
const isRenderQuestionWithPassage = (vertical || !isLongPassage || isQuizGroupType) && !!materialQuiz;
|
|
55
72
|
React.useEffect(() => {
|
|
56
73
|
if (width > 0) {
|
|
@@ -58,8 +75,8 @@ const MaterialQuiz = () => {
|
|
|
58
75
|
}
|
|
59
76
|
}, [width, setVertical]);
|
|
60
77
|
const renderQuestionOption = () => {
|
|
61
|
-
if (
|
|
62
|
-
return
|
|
78
|
+
if (isFetchingData) {
|
|
79
|
+
return null;
|
|
63
80
|
}
|
|
64
81
|
switch (materialQuiz.optionType) {
|
|
65
82
|
case enums.QuizOptionType.SelectOne:
|
|
@@ -87,8 +104,9 @@ const MaterialQuiz = () => {
|
|
|
87
104
|
}, React.createElement(StyledMaterialQuizWrapper, {
|
|
88
105
|
ref: ref,
|
|
89
106
|
vertical: vertical,
|
|
90
|
-
isQuizGroupType: isQuizGroupType
|
|
91
|
-
|
|
107
|
+
isQuizGroupType: isQuizGroupType,
|
|
108
|
+
isLongPassage: isLongPassage
|
|
109
|
+
}, isLoadingLayout && React.createElement(LoadingContainer, null, React.createElement(MaterialQuizShimmer, null)), isVisibleSideBySide && React.createElement(StyledMaterialQuizInfo, null, React.createElement(MaterialQuizInfo, null)), React.createElement(StyledMaterialQuizContent, {
|
|
92
110
|
id: MATERIAL_QUIZ_CONTAINER_ID,
|
|
93
111
|
vertical: vertical
|
|
94
112
|
}, renderQuestionOption())));
|
|
@@ -103,13 +121,15 @@ const MaterialQuizContainer = ({
|
|
|
103
121
|
}) => {
|
|
104
122
|
return React.createElement(RawEliceIntlProvider, {
|
|
105
123
|
value: __intl
|
|
124
|
+
}, React.createElement(ThemeProvider, {
|
|
125
|
+
theme: eliceTheme
|
|
106
126
|
}, React.createElement(MaterialQuizProvider, {
|
|
107
127
|
materialQuizId: materialQuizId,
|
|
108
128
|
userId: userId,
|
|
109
129
|
onDirty: onDirty,
|
|
110
130
|
onSubmit: onSubmit,
|
|
111
131
|
onNext: onNext
|
|
112
|
-
}, React.createElement(MaterialQuiz, null)));
|
|
132
|
+
}, React.createElement(MaterialQuiz, null))));
|
|
113
133
|
};
|
|
114
134
|
var MaterialQuiz$1 = new IntlComponentBuilder(MaterialQuizContainer).add('en', messageEn).add('ko', messageKo).addAsync('th', import('./locales/th.json.js')).addAsync('ja', import('./locales/ja.json.js')).build();
|
|
115
135
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React, { useState, useRef, useEffect } from 'react';
|
|
2
|
+
import { useMeasure } from 'react-use';
|
|
2
3
|
import { Vspace, Shimmer, IconButton } from '@elice/blocks';
|
|
3
|
-
import { base } from '@elice/design-tokens';
|
|
4
4
|
import { eilMathsignMultiplyBasic } from '@elice/icons';
|
|
5
5
|
import { MarkdownSSR } from '@elice/markdown';
|
|
6
|
-
import { Modal, Box } from '@mui/material';
|
|
6
|
+
import { styled as styled$1, Modal, Box } from '@mui/material';
|
|
7
7
|
import styled from 'styled-components';
|
|
8
8
|
import QuestionBox from '../shared/QuestionBox.js';
|
|
9
|
+
import { mergeRefs } from '../shared/utils/mergeRefs.js';
|
|
9
10
|
import { useMaterialQuizState } from './context/MaterialQuizContext.js';
|
|
10
|
-
import MaterialQuizAnswerExplanation from './MaterialQuizAnswerExplanation.js';
|
|
11
11
|
|
|
12
12
|
//
|
|
13
13
|
//
|
|
@@ -20,23 +20,51 @@ const StyledMarkdownSSR = styled(MarkdownSSR).withConfig({
|
|
|
20
20
|
//
|
|
21
21
|
const IMAGE_CONTAINER_CLASSNAME = 'markdown-zoomable-image-container';
|
|
22
22
|
const ZOOM_ICON_CLASSNAME = 'markdown-zoom-icon';
|
|
23
|
-
const MarkdownContainer = styled
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const MarkdownContainer = styled$1('div')`
|
|
24
|
+
.${IMAGE_CONTAINER_CLASSNAME} {
|
|
25
|
+
position: relative;
|
|
26
|
+
|
|
27
|
+
span.${ZOOM_ICON_CLASSNAME} {
|
|
28
|
+
cursor: pointer;
|
|
29
|
+
|
|
30
|
+
position: absolute;
|
|
31
|
+
top: 0;
|
|
32
|
+
right: ${({
|
|
33
|
+
vertical
|
|
34
|
+
}) => vertical ? '0!important' : '0'};
|
|
35
|
+
|
|
36
|
+
width: 2rem;
|
|
37
|
+
aspect-ratio: 1;
|
|
38
|
+
background-color: ${({
|
|
39
|
+
theme
|
|
40
|
+
}) => theme.palette.inverse.main};
|
|
41
|
+
margin: 0.5rem;
|
|
42
|
+
border-radius: 50%;
|
|
43
|
+
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
26
50
|
const MaterialQuizInfo = ({
|
|
27
51
|
renderWithBox = true
|
|
28
52
|
}) => {
|
|
29
53
|
const {
|
|
30
|
-
materialQuiz
|
|
54
|
+
materialQuiz,
|
|
55
|
+
vertical
|
|
31
56
|
} = useMaterialQuizState();
|
|
32
57
|
const [isRenderFinish, setIsRenderFinish] = useState(false);
|
|
33
58
|
const containerRef = useRef(null);
|
|
59
|
+
const [markdownMeasueRef, {
|
|
60
|
+
width
|
|
61
|
+
}] = useMeasure();
|
|
62
|
+
const ref = mergeRefs(containerRef, markdownMeasueRef);
|
|
34
63
|
const [zoomImageUrl, setZoomImageUrl] = useState('');
|
|
35
64
|
useEffect(() => {
|
|
36
65
|
if (!(materialQuiz === null || materialQuiz === void 0 ? void 0 : materialQuiz.questionDescription) || !isRenderFinish || !containerRef.current) return;
|
|
37
|
-
const images = containerRef.current.querySelectorAll('img');
|
|
38
66
|
// append zoom icon for image html render by MarkdownSSR
|
|
39
|
-
|
|
67
|
+
containerRef.current.querySelectorAll('img').forEach(img => {
|
|
40
68
|
const parent = img.parentElement;
|
|
41
69
|
const zoomIconStr = `
|
|
42
70
|
<svg width="25" height="25" viewBox="0 0 25 25" fill="white" xmlns="http://www.w3.org/2000/svg">
|
|
@@ -44,27 +72,44 @@ const MaterialQuizInfo = ({
|
|
|
44
72
|
</svg>
|
|
45
73
|
`;
|
|
46
74
|
if (parent) {
|
|
75
|
+
const imageRect = img.getBoundingClientRect();
|
|
76
|
+
const parentRect = parent.getBoundingClientRect();
|
|
77
|
+
const zoomIcons = parent.querySelectorAll(`.${ZOOM_ICON_CLASSNAME}`);
|
|
78
|
+
const totalImages = Array.from(parent.querySelectorAll(`img`));
|
|
79
|
+
const idx = totalImages.findIndex(item => item === img);
|
|
80
|
+
// restyle the zoom position when chaging the width instead of recreate it
|
|
81
|
+
if (zoomIcons.length === totalImages.length && idx !== -1) {
|
|
82
|
+
zoomIcons[idx].style.top = `${imageRect.top - parentRect.top}px`;
|
|
83
|
+
zoomIcons[idx].style.right = `${parentRect.right - imageRect.right}px`;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
47
86
|
parent.classList.add(IMAGE_CONTAINER_CLASSNAME);
|
|
48
87
|
parent.style.position = 'relative';
|
|
49
88
|
const span = document.createElement('span');
|
|
50
89
|
span.innerHTML = zoomIconStr;
|
|
51
90
|
span.classList.add(ZOOM_ICON_CLASSNAME);
|
|
91
|
+
span.style.top = `${imageRect.top - parentRect.top}px`;
|
|
92
|
+
span.style.right = `${parentRect.right - imageRect.right}px`;
|
|
52
93
|
span.onclick = () => {
|
|
53
94
|
setZoomImageUrl(img.src);
|
|
54
95
|
};
|
|
55
96
|
parent.appendChild(span);
|
|
56
97
|
}
|
|
57
98
|
});
|
|
58
|
-
}, [materialQuiz === null || materialQuiz === void 0 ? void 0 : materialQuiz.questionDescription, isRenderFinish]);
|
|
99
|
+
}, [materialQuiz === null || materialQuiz === void 0 ? void 0 : materialQuiz.questionDescription, isRenderFinish, width]);
|
|
59
100
|
const onCloseImageModal = () => {
|
|
60
101
|
setZoomImageUrl('');
|
|
61
102
|
};
|
|
62
103
|
const _renderQuiz = () => {
|
|
63
104
|
return React.createElement(React.Fragment, null, materialQuiz ? React.createElement(MarkdownContainer, {
|
|
64
|
-
ref:
|
|
105
|
+
ref: ref,
|
|
106
|
+
vertical: vertical
|
|
65
107
|
}, React.createElement(StyledMarkdownSSR, {
|
|
66
108
|
onRender: () => {
|
|
67
|
-
|
|
109
|
+
// set timeout for waiting time to the image can render
|
|
110
|
+
setTimeout(() => {
|
|
111
|
+
setIsRenderFinish(true);
|
|
112
|
+
}, 300);
|
|
68
113
|
},
|
|
69
114
|
children: materialQuiz === null || materialQuiz === void 0 ? void 0 : materialQuiz.questionDescription,
|
|
70
115
|
dark: true,
|
|
@@ -137,7 +182,7 @@ const MaterialQuizInfo = ({
|
|
|
137
182
|
top: '-10%'
|
|
138
183
|
},
|
|
139
184
|
onClick: onCloseImageModal
|
|
140
|
-
})))
|
|
185
|
+
}))));
|
|
141
186
|
};
|
|
142
187
|
if (renderWithBox) return React.createElement(QuestionBox, null, _renderQuiz());
|
|
143
188
|
return React.createElement(React.Fragment, null, _renderQuiz());
|