@pie-lib/graphing 4.0.16 → 4.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/lib/mark-label.js +86 -18
- package/lib/mark-label.js.map +1 -1
- package/package.json +6 -6
- package/src/__tests__/graph.test.jsx +76 -1
- package/src/__tests__/mark-label.test.jsx +128 -3
- package/src/mark-label.jsx +87 -18
- package/src/tools/point/__tests__/component.test.jsx +17 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [4.0.18](https://github.com/pie-framework/pie-lib/compare/@pie-lib/graphing@4.0.17...@pie-lib/graphing@4.0.18) (2026-08-26)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **graphing:** hold the focus on a new label and save it on blur PIE-681 ([26c5f98](https://github.com/pie-framework/pie-lib/commit/26c5f9875b45f4495d76827633f28d82d93d8cb9))
|
|
11
|
+
|
|
12
|
+
## [4.0.17](https://github.com/pie-framework/pie-lib/compare/@pie-lib/graphing@4.0.16...@pie-lib/graphing@4.0.17) (2026-08-21)
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
- **graphing:** focus a new label even if its tool was remounted PIE-681 ([663177b](https://github.com/pie-framework/pie-lib/commit/663177b95aa73f4f53ee2aff31c3bde750435d6e))
|
|
17
|
+
|
|
6
18
|
## [4.0.16](https://github.com/pie-framework/pie-lib/compare/@pie-lib/graphing@4.0.15...@pie-lib/graphing@4.0.16) (2026-08-18)
|
|
7
19
|
|
|
8
20
|
### Bug Fixes
|
package/lib/mark-label.js
CHANGED
|
@@ -20,6 +20,11 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
20
20
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
21
21
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
22
22
|
var DEBOUNCE_DELAY = 500;
|
|
23
|
+
// A new label insists on the focus for this long: in the DNA env something moves the focus while the
|
|
24
|
+
// model save that creating the label triggered is handled, after the last render. Nothing typed yet
|
|
25
|
+
// is what tells that apart from the user leaving the label.
|
|
26
|
+
var INSIST_ON_FOCUS_FOR = 500;
|
|
27
|
+
var INSIST_AT = [0, 50, 120, 250, 400];
|
|
23
28
|
var StyledInputCorrect = (0, _styles.styled)('div')(function (_ref2) {
|
|
24
29
|
var theme = _ref2.theme;
|
|
25
30
|
return {
|
|
@@ -168,13 +173,16 @@ LabelInput.propTypes = {
|
|
|
168
173
|
onBlur: _propTypes["default"].func
|
|
169
174
|
};
|
|
170
175
|
var MarkLabel = exports.MarkLabel = function MarkLabel(props) {
|
|
176
|
+
// the state repositions the label once the input has a size, the ref is never a render behind
|
|
177
|
+
var inputNode = (0, _react.useRef)(null);
|
|
171
178
|
var _useState = (0, _react.useState)(null),
|
|
172
179
|
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
|
|
173
180
|
input = _useState2[0],
|
|
174
181
|
setInput = _useState2[1];
|
|
175
182
|
var _ref = (0, _react.useCallback)(function (node) {
|
|
176
|
-
|
|
177
|
-
|
|
183
|
+
inputNode.current = node;
|
|
184
|
+
setInput(node);
|
|
185
|
+
}, []);
|
|
178
186
|
var theme = (0, _styles.useTheme)();
|
|
179
187
|
var mark = props.mark,
|
|
180
188
|
graphProps = props.graphProps,
|
|
@@ -189,26 +197,51 @@ var MarkLabel = exports.MarkLabel = function MarkLabel(props) {
|
|
|
189
197
|
correctnesslabel = mark.correctnesslabel,
|
|
190
198
|
correctlabel = mark.correctlabel;
|
|
191
199
|
var isFocused = function isFocused() {
|
|
192
|
-
return !!
|
|
200
|
+
return !!inputNode.current && typeof document !== 'undefined' && document.activeElement === inputNode.current;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// an empty label with an enabled input is one the user just added: label mode has to be on and it
|
|
204
|
+
// always starts off. Read from the mark, not from autoFocus, because the tool that asked for the
|
|
205
|
+
// label can be remounted by the marks coming back from the host before the input renders.
|
|
206
|
+
var isNewLabel = (0, _react.useRef)(mark.label === '' && !disabled && !mark.disabled);
|
|
207
|
+
var insistUntil = (0, _react.useRef)(0);
|
|
208
|
+
var lastSaved = (0, _react.useRef)(mark.label);
|
|
209
|
+
var insisting = function insisting() {
|
|
210
|
+
return Date.now() < insistUntil.current && !(inputNode.current && inputNode.current.value);
|
|
193
211
|
};
|
|
194
212
|
var onChange = function onChange(e) {
|
|
195
213
|
return setLabel(e.target.value);
|
|
196
214
|
};
|
|
215
|
+
var saveLabel = function saveLabel(value) {
|
|
216
|
+
if (value === lastSaved.current) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
lastSaved.current = value;
|
|
220
|
+
props.onChange(value);
|
|
221
|
+
};
|
|
197
222
|
var handleBlur = (0, _react.useCallback)(function () {
|
|
223
|
+
// in the DNA env the focus is moved while the model is saved - not the user leaving the label
|
|
224
|
+
if (insisting()) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
isNewLabel.current = false;
|
|
198
228
|
if (label === '') {
|
|
199
229
|
props.onChange('');
|
|
230
|
+
} else if (label !== mark.label) {
|
|
231
|
+
// the debounce can still be pending, and once the focus is gone an echo of the model would
|
|
232
|
+
// overwrite what was typed before it fires
|
|
233
|
+
saveLabel(label);
|
|
200
234
|
}
|
|
201
235
|
|
|
202
236
|
// lets the tool know that this label is not being edited anymore, so it stops auto focusing it
|
|
203
237
|
if (props.onBlur) {
|
|
204
238
|
props.onBlur();
|
|
205
239
|
}
|
|
206
|
-
}, [label, props.onChange, props.onBlur]);
|
|
240
|
+
}, [label, mark.label, props.onChange, props.onBlur]);
|
|
207
241
|
var debouncedLabel = (0, _useDebounce.useDebounce)(label, DEBOUNCE_DELAY);
|
|
208
242
|
|
|
209
|
-
//
|
|
210
|
-
//
|
|
211
|
-
// (async) model save with an older label and that would overwrite the characters typed meanwhile.
|
|
243
|
+
// props to state, but not while focused: the mark can come back from an async model save with an
|
|
244
|
+
// older label and overwrite what was typed meanwhile
|
|
212
245
|
(0, _react.useEffect)(function () {
|
|
213
246
|
if (isFocused()) {
|
|
214
247
|
return;
|
|
@@ -219,25 +252,54 @@ var MarkLabel = exports.MarkLabel = function MarkLabel(props) {
|
|
|
219
252
|
// pick up the change to debouncedLabel and save it
|
|
220
253
|
(0, _react.useEffect)(function () {
|
|
221
254
|
if (typeof debouncedLabel === 'string' && debouncedLabel !== mark.label) {
|
|
222
|
-
|
|
255
|
+
saveLabel(debouncedLabel);
|
|
223
256
|
}
|
|
224
257
|
}, [debouncedLabel]);
|
|
258
|
+
var focusInput = function focusInput() {
|
|
259
|
+
var node = inputNode.current;
|
|
225
260
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
// is done by the host (api call) and the model that comes back can replace the input node.
|
|
229
|
-
(0, _react.useEffect)(function () {
|
|
230
|
-
if (!autoFocus || !input || disabled || isFocused()) {
|
|
261
|
+
// node.disabled, not the disabled prop: a disabled input silently ignores focus()
|
|
262
|
+
if (!autoFocus && !isNewLabel.current && !insisting() || !node || node.disabled || isFocused()) {
|
|
231
263
|
return;
|
|
232
264
|
}
|
|
233
|
-
|
|
265
|
+
node.focus();
|
|
266
|
+
|
|
267
|
+
// a new label is focused once, so it cannot fight over the focus with another one
|
|
268
|
+
if (isFocused()) {
|
|
269
|
+
isNewLabel.current = false;
|
|
270
|
+
}
|
|
234
271
|
|
|
235
272
|
// keep the caret at the end, otherwise typing continues in front of the existing label
|
|
236
|
-
var caret = (
|
|
237
|
-
if (
|
|
238
|
-
|
|
273
|
+
var caret = (node.value || '').length;
|
|
274
|
+
if (node.setSelectionRange) {
|
|
275
|
+
node.setSelectionRange(caret, caret);
|
|
239
276
|
}
|
|
240
|
-
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// after every render: the input can appear a render or more later (the mark comes back from an
|
|
280
|
+
// async model save) and a replaced node loses the focus without this component being told
|
|
281
|
+
(0, _react.useEffect)(function () {
|
|
282
|
+
return focusInput();
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// and again on a timer, for the DNA env, where the focus is moved once the renders are over. The
|
|
286
|
+
// original code focused from a setTimeout, which is what let it survive that.
|
|
287
|
+
(0, _react.useEffect)(function () {
|
|
288
|
+
if (!autoFocus && !isNewLabel.current) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (!insistUntil.current) {
|
|
292
|
+
insistUntil.current = Date.now() + INSIST_ON_FOCUS_FOR;
|
|
293
|
+
}
|
|
294
|
+
var timers = INSIST_AT.map(function (delay) {
|
|
295
|
+
return setTimeout(focusInput, delay);
|
|
296
|
+
});
|
|
297
|
+
return function () {
|
|
298
|
+
return timers.forEach(function (t) {
|
|
299
|
+
return clearTimeout(t);
|
|
300
|
+
});
|
|
301
|
+
};
|
|
302
|
+
}, [autoFocus]);
|
|
241
303
|
var rect = input ? input.getBoundingClientRect() : {
|
|
242
304
|
width: 0,
|
|
243
305
|
height: 0
|
|
@@ -301,6 +363,12 @@ var MarkLabel = exports.MarkLabel = function MarkLabel(props) {
|
|
|
301
363
|
style: style
|
|
302
364
|
}, renderInput(studentInputStyle, label));
|
|
303
365
|
}
|
|
366
|
+
|
|
367
|
+
// an empty label that cannot be edited is just an empty box - the config draws the background
|
|
368
|
+
// marks into every correct answer graph too
|
|
369
|
+
if (disabledInput && !label) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
304
372
|
return /*#__PURE__*/_react["default"].createElement("div", {
|
|
305
373
|
style: style
|
|
306
374
|
}, renderInput(getInputStyles(theme, disabled, mark.disabled), label));
|
package/lib/mark-label.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mark-label.js","names":["_react","_interopRequireWildcard","require","_propTypes","_interopRequireDefault","_styles","_reactInputAutosize","_useDebounce","_plot","_renderUi","_labelSvgIcon","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","DEBOUNCE_DELAY","StyledInputCorrect","styled","_ref2","theme","padding","spacing","borderRadius","fontSize","backgroundColor","color","defaults","WHITE","CORRECT_WITH_ICON","border","concat","StyledInputIncorrect","_ref3","INCORRECT_WITH_ICON","StyledInputMissing","_ref4","MISSING_WITH_ICON","fontWeight","StyledIncorrect","getInputStyles","disabled","markDisabled","fontFamily","typography","PRIMARY_DARK","SECONDARY","WebkitOpacity","undefined","WebkitTextFillColor","getStudentInputStyles","position","exports","graphProps","mark","rect","width","height","scale","domain","range","shift","rightEdge","x","bottomEdge","y","h","max","v","min","coordinates","left","top","LabelInput","_ref5","_ref","externalInputRef","label","inputStyle","onChange","onBlur","createElement","inputRef","value","propTypes","PropTypes","func","string","bool","object","MarkLabel","props","_useState","useState","_useState2","_slicedToArray2","input","setInput","useCallback","node","useTheme","autoFocus","_useState3","_useState4","setLabel","correctness","correctnesslabel","correctlabel","isFocused","document","activeElement","target","handleBlur","debouncedLabel","useDebounce","useEffect","focus","caret","setSelectionRange","getBoundingClientRect","pos","leftTop","style","pointerEvents","display","alignItems","gap","secondLabelStyle","disabledInput","renderInput","labelValue","studentInputStyle","type","Fragment","marginLeft","types","GraphPropsType","_default"],"sources":["../src/mark-label.jsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { styled, useTheme } from '@mui/material/styles';\nimport AutosizeInput from 'react-input-autosize';\nimport { useDebounce } from './use-debounce';\nimport { types } from '@pie-lib/plot';\nimport { color } from '@pie-lib/render-ui';\nimport SvgIcon from './label-svg-icon';\n\nconst DEBOUNCE_DELAY = 500;\n\nconst StyledInputCorrect = styled('div')(({ theme }) => ({\n float: 'right',\n padding: theme.spacing(0.5),\n borderRadius: '4px',\n fontSize: '10px',\n backgroundColor: color.defaults.WHITE,\n color: color.defaults.CORRECT_WITH_ICON,\n border: `solid 1px ${color.defaults.CORRECT_WITH_ICON}`,\n}));\n\nconst StyledInputIncorrect = styled('div')(({ theme }) => ({\n float: 'right',\n padding: theme.spacing(0.5),\n borderRadius: '4px',\n fontSize: '10px',\n backgroundColor: color.defaults.WHITE,\n color: color.defaults.INCORRECT_WITH_ICON,\n border: `solid 1px ${color.defaults.INCORRECT_WITH_ICON}`,\n}));\n\nconst StyledInputMissing = styled('div')(({ theme }) => ({\n float: 'right',\n padding: theme.spacing(0.5),\n borderRadius: '4px',\n fontSize: '10px',\n backgroundColor: color.defaults.WHITE,\n color: color.defaults.MISSING_WITH_ICON,\n border: `solid 1px ${color.defaults.MISSING_WITH_ICON}`,\n fontWeight: 'bold',\n}));\n\nconst StyledIncorrect = styled('div')(() => ({\n float: 'right',\n padding: 0,\n borderRadius: '4px',\n fontSize: '10px',\n backgroundColor: color.defaults.WHITE,\n color: color.defaults.INCORRECT_WITH_ICON,\n fontWeight: 'bold',\n}));\n\nconst getInputStyles = (theme, disabled, markDisabled) => ({\n float: 'right',\n padding: theme.spacing(0.5),\n fontFamily: theme.typography.fontFamily,\n fontSize: '10px',\n border: disabled\n ? `solid 1px ${color.defaults.PRIMARY_DARK}`\n : markDisabled\n ? `solid 1px ${color.disabled()}`\n : `solid 1px ${color.defaults.SECONDARY}`,\n borderRadius: '3px',\n color: markDisabled ? color.disabled() : color.defaults.PRIMARY_DARK,\n backgroundColor: color.defaults.WHITE,\n WebkitOpacity: disabled ? '1' : undefined,\n WebkitTextFillColor: markDisabled ? color.disabled() : undefined,\n});\n\nconst getStudentInputStyles = () => ({\n padding: '0',\n border: 'none',\n color: 'inherit',\n fontWeight: 'bold',\n});\n\nexport const position = (graphProps, mark, rect = { width: 0, height: 0 }) => {\n const { scale, domain, range } = graphProps;\n const shift = 5;\n\n const rightEdge = scale.x(mark.x) + rect.width + shift;\n const bottomEdge = scale.y(mark.y) + rect.height + shift;\n\n const h = rightEdge >= scale.x(domain.max) ? 'left' : 'right';\n const v = bottomEdge >= scale.y(range.min) ? 'top' : 'bottom';\n\n return `${v}-${h}`;\n};\n\nexport const coordinates = (graphProps, mark, rect = { width: 0, height: 0 }, position) => {\n const { scale } = graphProps;\n const shift = 5;\n\n switch (position) {\n case 'bottom-right':\n return { left: scale.x(mark.x) + shift, top: scale.y(mark.y) + shift };\n case 'bottom-left':\n return { left: scale.x(mark.x) - shift - rect.width, top: scale.y(mark.y) + shift };\n case 'top-left':\n return { left: scale.x(mark.x) - shift - rect.width, top: scale.y(mark.y) - shift - rect.height };\n case 'top-right':\n return { left: scale.x(mark.x) + shift, top: scale.y(mark.y) - shift - rect.height };\n default:\n return {};\n }\n};\n\nconst LabelInput = ({ _ref, externalInputRef, label, disabled, inputStyle, onChange, onBlur }) => (\n <AutosizeInput\n inputRef={(r) => {\n _ref(r);\n externalInputRef(r);\n }}\n disabled={disabled}\n inputStyle={inputStyle}\n value={label}\n onChange={onChange}\n onBlur={onBlur}\n />\n);\n\nLabelInput.propTypes = {\n _ref: PropTypes.func,\n externalInputRef: PropTypes.func,\n label: PropTypes.string,\n disabled: PropTypes.bool,\n inputStyle: PropTypes.object,\n onChange: PropTypes.func,\n onBlur: PropTypes.func,\n};\n\nexport const MarkLabel = (props) => {\n const [input, setInput] = useState(null);\n const _ref = useCallback((node) => setInput(node));\n const theme = useTheme();\n\n const { mark, graphProps, disabled, autoFocus, inputRef: externalInputRef } = props;\n\n const [label, setLabel] = useState(mark.label);\n const { correctness, correctnesslabel, correctlabel } = mark;\n\n const isFocused = () => !!input && typeof document !== 'undefined' && document.activeElement === input;\n\n const onChange = (e) => setLabel(e.target.value);\n\n const handleBlur = useCallback(() => {\n if (label === '') {\n props.onChange('');\n }\n\n // lets the tool know that this label is not being edited anymore, so it stops auto focusing it\n if (props.onBlur) {\n props.onBlur();\n }\n }, [label, props.onChange, props.onBlur]);\n\n const debouncedLabel = useDebounce(label, DEBOUNCE_DELAY);\n\n // useState only sets the value once, to synch props to state need useEffect.\n // While this input has the focus we keep what the user typed: the mark can come back from an\n // (async) model save with an older label and that would overwrite the characters typed meanwhile.\n useEffect(() => {\n if (isFocused()) {\n return;\n }\n\n setLabel(mark.label);\n }, [mark.label]);\n\n // pick up the change to debouncedLabel and save it\n useEffect(() => {\n if (typeof debouncedLabel === 'string' && debouncedLabel !== mark.label) {\n props.onChange(debouncedLabel);\n }\n }, [debouncedLabel]);\n\n // A label that has just been added has to be focused so that it can be typed into right away.\n // This also re-focuses the input if it gets remounted while it is being edited - saving the model\n // is done by the host (api call) and the model that comes back can replace the input node.\n useEffect(() => {\n if (!autoFocus || !input || disabled || isFocused()) {\n return;\n }\n\n input.focus();\n\n // keep the caret at the end, otherwise typing continues in front of the existing label\n const caret = (input.value || '').length;\n\n if (input.setSelectionRange) {\n input.setSelectionRange(caret, caret);\n }\n }, [autoFocus, input, disabled]);\n\n const rect = input ? input.getBoundingClientRect() : { width: 0, height: 0 };\n const pos = position(graphProps, mark, rect);\n const leftTop = coordinates(graphProps, mark, rect, pos);\n\n const style = {\n position: 'fixed',\n pointerEvents: 'auto',\n display: 'flex',\n alignItems: 'center',\n gap: '3px',\n ...leftTop,\n };\n\n const secondLabelStyle = {\n ...style,\n top: leftTop.top + 25,\n };\n\n const disabledInput = disabled || mark.disabled;\n\n const renderInput = (inputStyle, labelValue) => (\n <LabelInput\n _ref={_ref}\n externalInputRef={externalInputRef}\n label={labelValue}\n disabled={disabledInput}\n inputStyle={inputStyle}\n onChange={onChange}\n onBlur={handleBlur}\n />\n );\n\n const studentInputStyle = getStudentInputStyles();\n\n if (correctness === 'correct' && correctnesslabel === 'correct' && correctlabel) {\n return (\n <StyledInputCorrect style={style}>\n <SvgIcon type=\"correct\" />\n {renderInput(studentInputStyle, correctlabel)}\n </StyledInputCorrect>\n );\n }\n\n if (correctness === 'correct' && correctnesslabel === 'correct' && !correctlabel) {\n return null;\n }\n\n if (correctness === 'correct' && correctnesslabel === 'incorrect') {\n return (\n <>\n <StyledInputIncorrect style={style}>\n <SvgIcon type=\"incorrect\" />\n {label === '' ? (\n <SvgIcon type=\"empty\" style={{ marginLeft: '3px' }} />\n ) : (\n renderInput(studentInputStyle, label)\n )}\n </StyledInputIncorrect>\n <StyledInputMissing style={secondLabelStyle}>{renderInput(studentInputStyle, correctlabel)}</StyledInputMissing>\n </>\n );\n }\n\n if (correctness === 'missing') {\n return <StyledInputMissing style={style}>{renderInput(studentInputStyle, label)}</StyledInputMissing>;\n }\n\n if (correctness === 'incorrect') {\n return <StyledIncorrect style={style}>{renderInput(studentInputStyle, label)}</StyledIncorrect>;\n }\n\n return <div style={style}>{renderInput(getInputStyles(theme, disabled, mark.disabled), label)}</div>;\n};\n\nMarkLabel.propTypes = {\n autoFocus: PropTypes.bool,\n disabled: PropTypes.bool,\n onBlur: PropTypes.func,\n onChange: PropTypes.func,\n graphProps: types.GraphPropsType,\n inputRef: PropTypes.func,\n mark: PropTypes.object,\n};\n\nexport default MarkLabel;\n"],"mappings":";;;;;;;;;;AAAA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,UAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AACA,IAAAI,mBAAA,GAAAF,sBAAA,CAAAF,OAAA;AACA,IAAAK,YAAA,GAAAL,OAAA;AACA,IAAAM,KAAA,GAAAN,OAAA;AACA,IAAAO,SAAA,GAAAP,OAAA;AACA,IAAAQ,aAAA,GAAAN,sBAAA,CAAAF,OAAA;AAAuC,SAAAD,wBAAAU,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAZ,uBAAA,YAAAA,wBAAAU,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,mBAAAT,CAAA,iBAAAA,CAAA,gBAAAU,OAAA,CAAAV,CAAA,0BAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,cAAAM,EAAA,IAAAd,CAAA,gBAAAc,EAAA,OAAAC,cAAA,CAAAC,IAAA,CAAAhB,CAAA,EAAAc,EAAA,OAAAP,CAAA,IAAAD,CAAA,GAAAW,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAnB,CAAA,EAAAc,EAAA,OAAAP,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAM,EAAA,EAAAP,CAAA,IAAAC,CAAA,CAAAM,EAAA,IAAAd,CAAA,CAAAc,EAAA,WAAAN,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAAA,SAAAmB,QAAApB,CAAA,EAAAG,CAAA,QAAAF,CAAA,GAAAgB,MAAA,CAAAI,IAAA,CAAArB,CAAA,OAAAiB,MAAA,CAAAK,qBAAA,QAAAhB,CAAA,GAAAW,MAAA,CAAAK,qBAAA,CAAAtB,CAAA,GAAAG,CAAA,KAAAG,CAAA,GAAAA,CAAA,CAAAiB,MAAA,WAAApB,CAAA,WAAAc,MAAA,CAAAE,wBAAA,CAAAnB,CAAA,EAAAG,CAAA,EAAAqB,UAAA,OAAAvB,CAAA,CAAAwB,IAAA,CAAAC,KAAA,CAAAzB,CAAA,EAAAK,CAAA,YAAAL,CAAA;AAAA,SAAA0B,cAAA3B,CAAA,aAAAG,CAAA,MAAAA,CAAA,GAAAyB,SAAA,CAAAC,MAAA,EAAA1B,CAAA,UAAAF,CAAA,WAAA2B,SAAA,CAAAzB,CAAA,IAAAyB,SAAA,CAAAzB,CAAA,QAAAA,CAAA,OAAAiB,OAAA,CAAAH,MAAA,CAAAhB,CAAA,OAAA6B,OAAA,WAAA3B,CAAA,QAAA4B,gBAAA,aAAA/B,CAAA,EAAAG,CAAA,EAAAF,CAAA,CAAAE,CAAA,SAAAc,MAAA,CAAAe,yBAAA,GAAAf,MAAA,CAAAgB,gBAAA,CAAAjC,CAAA,EAAAiB,MAAA,CAAAe,yBAAA,CAAA/B,CAAA,KAAAmB,OAAA,CAAAH,MAAA,CAAAhB,CAAA,GAAA6B,OAAA,WAAA3B,CAAA,IAAAc,MAAA,CAAAC,cAAA,CAAAlB,CAAA,EAAAG,CAAA,EAAAc,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAE,CAAA,iBAAAH,CAAA;AAEvC,IAAMkC,cAAc,GAAG,GAAG;AAE1B,IAAMC,kBAAkB,GAAG,IAAAC,cAAM,EAAC,KAAK,CAAC,CAAC,UAAAC,KAAA;EAAA,IAAGC,KAAK,GAAAD,KAAA,CAALC,KAAK;EAAA,OAAQ;IACvD,SAAO,OAAO;IACdC,OAAO,EAAED,KAAK,CAACE,OAAO,CAAC,GAAG,CAAC;IAC3BC,YAAY,EAAE,KAAK;IACnBC,QAAQ,EAAE,MAAM;IAChBC,eAAe,EAAEC,eAAK,CAACC,QAAQ,CAACC,KAAK;IACrCF,KAAK,EAAEA,eAAK,CAACC,QAAQ,CAACE,iBAAiB;IACvCC,MAAM,eAAAC,MAAA,CAAeL,eAAK,CAACC,QAAQ,CAACE,iBAAiB;EACvD,CAAC;AAAA,CAAC,CAAC;AAEH,IAAMG,oBAAoB,GAAG,IAAAd,cAAM,EAAC,KAAK,CAAC,CAAC,UAAAe,KAAA;EAAA,IAAGb,KAAK,GAAAa,KAAA,CAALb,KAAK;EAAA,OAAQ;IACzD,SAAO,OAAO;IACdC,OAAO,EAAED,KAAK,CAACE,OAAO,CAAC,GAAG,CAAC;IAC3BC,YAAY,EAAE,KAAK;IACnBC,QAAQ,EAAE,MAAM;IAChBC,eAAe,EAAEC,eAAK,CAACC,QAAQ,CAACC,KAAK;IACrCF,KAAK,EAAEA,eAAK,CAACC,QAAQ,CAACO,mBAAmB;IACzCJ,MAAM,eAAAC,MAAA,CAAeL,eAAK,CAACC,QAAQ,CAACO,mBAAmB;EACzD,CAAC;AAAA,CAAC,CAAC;AAEH,IAAMC,kBAAkB,GAAG,IAAAjB,cAAM,EAAC,KAAK,CAAC,CAAC,UAAAkB,KAAA;EAAA,IAAGhB,KAAK,GAAAgB,KAAA,CAALhB,KAAK;EAAA,OAAQ;IACvD,SAAO,OAAO;IACdC,OAAO,EAAED,KAAK,CAACE,OAAO,CAAC,GAAG,CAAC;IAC3BC,YAAY,EAAE,KAAK;IACnBC,QAAQ,EAAE,MAAM;IAChBC,eAAe,EAAEC,eAAK,CAACC,QAAQ,CAACC,KAAK;IACrCF,KAAK,EAAEA,eAAK,CAACC,QAAQ,CAACU,iBAAiB;IACvCP,MAAM,eAAAC,MAAA,CAAeL,eAAK,CAACC,QAAQ,CAACU,iBAAiB,CAAE;IACvDC,UAAU,EAAE;EACd,CAAC;AAAA,CAAC,CAAC;AAEH,IAAMC,eAAe,GAAG,IAAArB,cAAM,EAAC,KAAK,CAAC,CAAC;EAAA,OAAO;IAC3C,SAAO,OAAO;IACdG,OAAO,EAAE,CAAC;IACVE,YAAY,EAAE,KAAK;IACnBC,QAAQ,EAAE,MAAM;IAChBC,eAAe,EAAEC,eAAK,CAACC,QAAQ,CAACC,KAAK;IACrCF,KAAK,EAAEA,eAAK,CAACC,QAAQ,CAACO,mBAAmB;IACzCI,UAAU,EAAE;EACd,CAAC;AAAA,CAAC,CAAC;AAEH,IAAME,cAAc,GAAG,SAAjBA,cAAcA,CAAIpB,KAAK,EAAEqB,QAAQ,EAAEC,YAAY;EAAA,OAAM;IACzD,SAAO,OAAO;IACdrB,OAAO,EAAED,KAAK,CAACE,OAAO,CAAC,GAAG,CAAC;IAC3BqB,UAAU,EAAEvB,KAAK,CAACwB,UAAU,CAACD,UAAU;IACvCnB,QAAQ,EAAE,MAAM;IAChBM,MAAM,EAAEW,QAAQ,gBAAAV,MAAA,CACCL,eAAK,CAACC,QAAQ,CAACkB,YAAY,IACxCH,YAAY,gBAAAX,MAAA,CACGL,eAAK,CAACe,QAAQ,CAAC,CAAC,iBAAAV,MAAA,CAChBL,eAAK,CAACC,QAAQ,CAACmB,SAAS,CAAE;IAC7CvB,YAAY,EAAE,KAAK;IACnBG,KAAK,EAAEgB,YAAY,GAAGhB,eAAK,CAACe,QAAQ,CAAC,CAAC,GAAGf,eAAK,CAACC,QAAQ,CAACkB,YAAY;IACpEpB,eAAe,EAAEC,eAAK,CAACC,QAAQ,CAACC,KAAK;IACrCmB,aAAa,EAAEN,QAAQ,GAAG,GAAG,GAAGO,SAAS;IACzCC,mBAAmB,EAAEP,YAAY,GAAGhB,eAAK,CAACe,QAAQ,CAAC,CAAC,GAAGO;EACzD,CAAC;AAAA,CAAC;AAEF,IAAME,qBAAqB,GAAG,SAAxBA,qBAAqBA,CAAA;EAAA,OAAU;IACnC7B,OAAO,EAAE,GAAG;IACZS,MAAM,EAAE,MAAM;IACdJ,KAAK,EAAE,SAAS;IAChBY,UAAU,EAAE;EACd,CAAC;AAAA,CAAC;AAEK,IAAMa,QAAQ,GAAAC,OAAA,CAAAD,QAAA,GAAG,SAAXA,QAAQA,CAAIE,UAAU,EAAEC,IAAI,EAAqC;EAAA,IAAnCC,IAAI,GAAA7C,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAsC,SAAA,GAAAtC,SAAA,MAAG;IAAE8C,KAAK,EAAE,CAAC;IAAEC,MAAM,EAAE;EAAE,CAAC;EACvE,IAAQC,KAAK,GAAoBL,UAAU,CAAnCK,KAAK;IAAEC,MAAM,GAAYN,UAAU,CAA5BM,MAAM;IAAEC,KAAK,GAAKP,UAAU,CAApBO,KAAK;EAC5B,IAAMC,KAAK,GAAG,CAAC;EAEf,IAAMC,SAAS,GAAGJ,KAAK,CAACK,CAAC,CAACT,IAAI,CAACS,CAAC,CAAC,GAAGR,IAAI,CAACC,KAAK,GAAGK,KAAK;EACtD,IAAMG,UAAU,GAAGN,KAAK,CAACO,CAAC,CAACX,IAAI,CAACW,CAAC,CAAC,GAAGV,IAAI,CAACE,MAAM,GAAGI,KAAK;EAExD,IAAMK,CAAC,GAAGJ,SAAS,IAAIJ,KAAK,CAACK,CAAC,CAACJ,MAAM,CAACQ,GAAG,CAAC,GAAG,MAAM,GAAG,OAAO;EAC7D,IAAMC,CAAC,GAAGJ,UAAU,IAAIN,KAAK,CAACO,CAAC,CAACL,KAAK,CAACS,GAAG,CAAC,GAAG,KAAK,GAAG,QAAQ;EAE7D,UAAAtC,MAAA,CAAUqC,CAAC,OAAArC,MAAA,CAAImC,CAAC;AAClB,CAAC;AAEM,IAAMI,WAAW,GAAAlB,OAAA,CAAAkB,WAAA,GAAG,SAAdA,WAAWA,CAAIjB,UAAU,EAAEC,IAAI,EAA+C;EAAA,IAA7CC,IAAI,GAAA7C,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAsC,SAAA,GAAAtC,SAAA,MAAG;IAAE8C,KAAK,EAAE,CAAC;IAAEC,MAAM,EAAE;EAAE,CAAC;EAAA,IAAEN,QAAQ,GAAAzC,SAAA,CAAAC,MAAA,OAAAD,SAAA,MAAAsC,SAAA;EACpF,IAAQU,KAAK,GAAKL,UAAU,CAApBK,KAAK;EACb,IAAMG,KAAK,GAAG,CAAC;EAEf,QAAQV,QAAQ;IACd,KAAK,cAAc;MACjB,OAAO;QAAEoB,IAAI,EAAEb,KAAK,CAACK,CAAC,CAACT,IAAI,CAACS,CAAC,CAAC,GAAGF,KAAK;QAAEW,GAAG,EAAEd,KAAK,CAACO,CAAC,CAACX,IAAI,CAACW,CAAC,CAAC,GAAGJ;MAAM,CAAC;IACxE,KAAK,aAAa;MAChB,OAAO;QAAEU,IAAI,EAAEb,KAAK,CAACK,CAAC,CAACT,IAAI,CAACS,CAAC,CAAC,GAAGF,KAAK,GAAGN,IAAI,CAACC,KAAK;QAAEgB,GAAG,EAAEd,KAAK,CAACO,CAAC,CAACX,IAAI,CAACW,CAAC,CAAC,GAAGJ;MAAM,CAAC;IACrF,KAAK,UAAU;MACb,OAAO;QAAEU,IAAI,EAAEb,KAAK,CAACK,CAAC,CAACT,IAAI,CAACS,CAAC,CAAC,GAAGF,KAAK,GAAGN,IAAI,CAACC,KAAK;QAAEgB,GAAG,EAAEd,KAAK,CAACO,CAAC,CAACX,IAAI,CAACW,CAAC,CAAC,GAAGJ,KAAK,GAAGN,IAAI,CAACE;MAAO,CAAC;IACnG,KAAK,WAAW;MACd,OAAO;QAAEc,IAAI,EAAEb,KAAK,CAACK,CAAC,CAACT,IAAI,CAACS,CAAC,CAAC,GAAGF,KAAK;QAAEW,GAAG,EAAEd,KAAK,CAACO,CAAC,CAACX,IAAI,CAACW,CAAC,CAAC,GAAGJ,KAAK,GAAGN,IAAI,CAACE;MAAO,CAAC;IACtF;MACE,OAAO,CAAC,CAAC;EACb;AACF,CAAC;AAED,IAAMgB,UAAU,GAAG,SAAbA,UAAUA,CAAAC,KAAA;EAAA,IAAMC,IAAI,GAAAD,KAAA,CAAJC,IAAI;IAAEC,gBAAgB,GAAAF,KAAA,CAAhBE,gBAAgB;IAAEC,KAAK,GAAAH,KAAA,CAALG,KAAK;IAAEpC,QAAQ,GAAAiC,KAAA,CAARjC,QAAQ;IAAEqC,UAAU,GAAAJ,KAAA,CAAVI,UAAU;IAAEC,QAAQ,GAAAL,KAAA,CAARK,QAAQ;IAAEC,MAAM,GAAAN,KAAA,CAANM,MAAM;EAAA,oBACzF7G,MAAA,YAAA8G,aAAA,CAACxG,mBAAA,WAAa;IACZyG,QAAQ,EAAE,SAAVA,QAAQA,CAAGjG,CAAC,EAAK;MACf0F,IAAI,CAAC1F,CAAC,CAAC;MACP2F,gBAAgB,CAAC3F,CAAC,CAAC;IACrB,CAAE;IACFwD,QAAQ,EAAEA,QAAS;IACnBqC,UAAU,EAAEA,UAAW;IACvBK,KAAK,EAAEN,KAAM;IACbE,QAAQ,EAAEA,QAAS;IACnBC,MAAM,EAAEA;EAAO,CAChB,CAAC;AAAA,CACH;AAEDP,UAAU,CAACW,SAAS,GAAG;EACrBT,IAAI,EAAEU,qBAAS,CAACC,IAAI;EACpBV,gBAAgB,EAAES,qBAAS,CAACC,IAAI;EAChCT,KAAK,EAAEQ,qBAAS,CAACE,MAAM;EACvB9C,QAAQ,EAAE4C,qBAAS,CAACG,IAAI;EACxBV,UAAU,EAAEO,qBAAS,CAACI,MAAM;EAC5BV,QAAQ,EAAEM,qBAAS,CAACC,IAAI;EACxBN,MAAM,EAAEK,qBAAS,CAACC;AACpB,CAAC;AAEM,IAAMI,SAAS,GAAAtC,OAAA,CAAAsC,SAAA,GAAG,SAAZA,SAASA,CAAIC,KAAK,EAAK;EAClC,IAAAC,SAAA,GAA0B,IAAAC,eAAQ,EAAC,IAAI,CAAC;IAAAC,UAAA,OAAAC,eAAA,aAAAH,SAAA;IAAjCI,KAAK,GAAAF,UAAA;IAAEG,QAAQ,GAAAH,UAAA;EACtB,IAAMnB,IAAI,GAAG,IAAAuB,kBAAW,EAAC,UAACC,IAAI;IAAA,OAAKF,QAAQ,CAACE,IAAI,CAAC;EAAA,EAAC;EAClD,IAAM/E,KAAK,GAAG,IAAAgF,gBAAQ,EAAC,CAAC;EAExB,IAAQ9C,IAAI,GAAkEqC,KAAK,CAA3ErC,IAAI;IAAED,UAAU,GAAsDsC,KAAK,CAArEtC,UAAU;IAAEZ,QAAQ,GAA4CkD,KAAK,CAAzDlD,QAAQ;IAAE4D,SAAS,GAAiCV,KAAK,CAA/CU,SAAS;IAAYzB,gBAAgB,GAAKe,KAAK,CAApCT,QAAQ;EAEvD,IAAAoB,UAAA,GAA0B,IAAAT,eAAQ,EAACvC,IAAI,CAACuB,KAAK,CAAC;IAAA0B,UAAA,OAAAR,eAAA,aAAAO,UAAA;IAAvCzB,KAAK,GAAA0B,UAAA;IAAEC,QAAQ,GAAAD,UAAA;EACtB,IAAQE,WAAW,GAAqCnD,IAAI,CAApDmD,WAAW;IAAEC,gBAAgB,GAAmBpD,IAAI,CAAvCoD,gBAAgB;IAAEC,YAAY,GAAKrD,IAAI,CAArBqD,YAAY;EAEnD,IAAMC,SAAS,GAAG,SAAZA,SAASA,CAAA;IAAA,OAAS,CAAC,CAACZ,KAAK,IAAI,OAAOa,QAAQ,KAAK,WAAW,IAAIA,QAAQ,CAACC,aAAa,KAAKd,KAAK;EAAA;EAEtG,IAAMjB,QAAQ,GAAG,SAAXA,QAAQA,CAAIjG,CAAC;IAAA,OAAK0H,QAAQ,CAAC1H,CAAC,CAACiI,MAAM,CAAC5B,KAAK,CAAC;EAAA;EAEhD,IAAM6B,UAAU,GAAG,IAAAd,kBAAW,EAAC,YAAM;IACnC,IAAIrB,KAAK,KAAK,EAAE,EAAE;MAChBc,KAAK,CAACZ,QAAQ,CAAC,EAAE,CAAC;IACpB;;IAEA;IACA,IAAIY,KAAK,CAACX,MAAM,EAAE;MAChBW,KAAK,CAACX,MAAM,CAAC,CAAC;IAChB;EACF,CAAC,EAAE,CAACH,KAAK,EAAEc,KAAK,CAACZ,QAAQ,EAAEY,KAAK,CAACX,MAAM,CAAC,CAAC;EAEzC,IAAMiC,cAAc,GAAG,IAAAC,wBAAW,EAACrC,KAAK,EAAE7D,cAAc,CAAC;;EAEzD;EACA;EACA;EACA,IAAAmG,gBAAS,EAAC,YAAM;IACd,IAAIP,SAAS,CAAC,CAAC,EAAE;MACf;IACF;IAEAJ,QAAQ,CAAClD,IAAI,CAACuB,KAAK,CAAC;EACtB,CAAC,EAAE,CAACvB,IAAI,CAACuB,KAAK,CAAC,CAAC;;EAEhB;EACA,IAAAsC,gBAAS,EAAC,YAAM;IACd,IAAI,OAAOF,cAAc,KAAK,QAAQ,IAAIA,cAAc,KAAK3D,IAAI,CAACuB,KAAK,EAAE;MACvEc,KAAK,CAACZ,QAAQ,CAACkC,cAAc,CAAC;IAChC;EACF,CAAC,EAAE,CAACA,cAAc,CAAC,CAAC;;EAEpB;EACA;EACA;EACA,IAAAE,gBAAS,EAAC,YAAM;IACd,IAAI,CAACd,SAAS,IAAI,CAACL,KAAK,IAAIvD,QAAQ,IAAImE,SAAS,CAAC,CAAC,EAAE;MACnD;IACF;IAEAZ,KAAK,CAACoB,KAAK,CAAC,CAAC;;IAEb;IACA,IAAMC,KAAK,GAAG,CAACrB,KAAK,CAACb,KAAK,IAAI,EAAE,EAAExE,MAAM;IAExC,IAAIqF,KAAK,CAACsB,iBAAiB,EAAE;MAC3BtB,KAAK,CAACsB,iBAAiB,CAACD,KAAK,EAAEA,KAAK,CAAC;IACvC;EACF,CAAC,EAAE,CAAChB,SAAS,EAAEL,KAAK,EAAEvD,QAAQ,CAAC,CAAC;EAEhC,IAAMc,IAAI,GAAGyC,KAAK,GAAGA,KAAK,CAACuB,qBAAqB,CAAC,CAAC,GAAG;IAAE/D,KAAK,EAAE,CAAC;IAAEC,MAAM,EAAE;EAAE,CAAC;EAC5E,IAAM+D,GAAG,GAAGrE,QAAQ,CAACE,UAAU,EAAEC,IAAI,EAAEC,IAAI,CAAC;EAC5C,IAAMkE,OAAO,GAAGnD,WAAW,CAACjB,UAAU,EAAEC,IAAI,EAAEC,IAAI,EAAEiE,GAAG,CAAC;EAExD,IAAME,KAAK,GAAAjH,aAAA;IACT0C,QAAQ,EAAE,OAAO;IACjBwE,aAAa,EAAE,MAAM;IACrBC,OAAO,EAAE,MAAM;IACfC,UAAU,EAAE,QAAQ;IACpBC,GAAG,EAAE;EAAK,GACPL,OAAO,CACX;EAED,IAAMM,gBAAgB,GAAAtH,aAAA,CAAAA,aAAA,KACjBiH,KAAK;IACRlD,GAAG,EAAEiD,OAAO,CAACjD,GAAG,GAAG;EAAE,EACtB;EAED,IAAMwD,aAAa,GAAGvF,QAAQ,IAAIa,IAAI,CAACb,QAAQ;EAE/C,IAAMwF,WAAW,GAAG,SAAdA,WAAWA,CAAInD,UAAU,EAAEoD,UAAU;IAAA,oBACzC/J,MAAA,YAAA8G,aAAA,CAACR,UAAU;MACTE,IAAI,EAAEA,IAAK;MACXC,gBAAgB,EAAEA,gBAAiB;MACnCC,KAAK,EAAEqD,UAAW;MAClBzF,QAAQ,EAAEuF,aAAc;MACxBlD,UAAU,EAAEA,UAAW;MACvBC,QAAQ,EAAEA,QAAS;MACnBC,MAAM,EAAEgC;IAAW,CACpB,CAAC;EAAA,CACH;EAED,IAAMmB,iBAAiB,GAAGjF,qBAAqB,CAAC,CAAC;EAEjD,IAAIuD,WAAW,KAAK,SAAS,IAAIC,gBAAgB,KAAK,SAAS,IAAIC,YAAY,EAAE;IAC/E,oBACExI,MAAA,YAAA8G,aAAA,CAAChE,kBAAkB;MAACyG,KAAK,EAAEA;IAAM,gBAC/BvJ,MAAA,YAAA8G,aAAA,CAACpG,aAAA,WAAO;MAACuJ,IAAI,EAAC;IAAS,CAAE,CAAC,EACzBH,WAAW,CAACE,iBAAiB,EAAExB,YAAY,CAC1B,CAAC;EAEzB;EAEA,IAAIF,WAAW,KAAK,SAAS,IAAIC,gBAAgB,KAAK,SAAS,IAAI,CAACC,YAAY,EAAE;IAChF,OAAO,IAAI;EACb;EAEA,IAAIF,WAAW,KAAK,SAAS,IAAIC,gBAAgB,KAAK,WAAW,EAAE;IACjE,oBACEvI,MAAA,YAAA8G,aAAA,CAAA9G,MAAA,YAAAkK,QAAA,qBACElK,MAAA,YAAA8G,aAAA,CAACjD,oBAAoB;MAAC0F,KAAK,EAAEA;IAAM,gBACjCvJ,MAAA,YAAA8G,aAAA,CAACpG,aAAA,WAAO;MAACuJ,IAAI,EAAC;IAAW,CAAE,CAAC,EAC3BvD,KAAK,KAAK,EAAE,gBACX1G,MAAA,YAAA8G,aAAA,CAACpG,aAAA,WAAO;MAACuJ,IAAI,EAAC,OAAO;MAACV,KAAK,EAAE;QAAEY,UAAU,EAAE;MAAM;IAAE,CAAE,CAAC,GAEtDL,WAAW,CAACE,iBAAiB,EAAEtD,KAAK,CAElB,CAAC,eACvB1G,MAAA,YAAA8G,aAAA,CAAC9C,kBAAkB;MAACuF,KAAK,EAAEK;IAAiB,GAAEE,WAAW,CAACE,iBAAiB,EAAExB,YAAY,CAAsB,CAC/G,CAAC;EAEP;EAEA,IAAIF,WAAW,KAAK,SAAS,EAAE;IAC7B,oBAAOtI,MAAA,YAAA8G,aAAA,CAAC9C,kBAAkB;MAACuF,KAAK,EAAEA;IAAM,GAAEO,WAAW,CAACE,iBAAiB,EAAEtD,KAAK,CAAsB,CAAC;EACvG;EAEA,IAAI4B,WAAW,KAAK,WAAW,EAAE;IAC/B,oBAAOtI,MAAA,YAAA8G,aAAA,CAAC1C,eAAe;MAACmF,KAAK,EAAEA;IAAM,GAAEO,WAAW,CAACE,iBAAiB,EAAEtD,KAAK,CAAmB,CAAC;EACjG;EAEA,oBAAO1G,MAAA,YAAA8G,aAAA;IAAKyC,KAAK,EAAEA;EAAM,GAAEO,WAAW,CAACzF,cAAc,CAACpB,KAAK,EAAEqB,QAAQ,EAAEa,IAAI,CAACb,QAAQ,CAAC,EAAEoC,KAAK,CAAO,CAAC;AACtG,CAAC;AAEDa,SAAS,CAACN,SAAS,GAAG;EACpBiB,SAAS,EAAEhB,qBAAS,CAACG,IAAI;EACzB/C,QAAQ,EAAE4C,qBAAS,CAACG,IAAI;EACxBR,MAAM,EAAEK,qBAAS,CAACC,IAAI;EACtBP,QAAQ,EAAEM,qBAAS,CAACC,IAAI;EACxBjC,UAAU,EAAEkF,WAAK,CAACC,cAAc;EAChCtD,QAAQ,EAAEG,qBAAS,CAACC,IAAI;EACxBhC,IAAI,EAAE+B,qBAAS,CAACI;AAClB,CAAC;AAAC,IAAAgD,QAAA,GAAArF,OAAA,cAEasC,SAAS","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"mark-label.js","names":["_react","_interopRequireWildcard","require","_propTypes","_interopRequireDefault","_styles","_reactInputAutosize","_useDebounce","_plot","_renderUi","_labelSvgIcon","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","DEBOUNCE_DELAY","INSIST_ON_FOCUS_FOR","INSIST_AT","StyledInputCorrect","styled","_ref2","theme","padding","spacing","borderRadius","fontSize","backgroundColor","color","defaults","WHITE","CORRECT_WITH_ICON","border","concat","StyledInputIncorrect","_ref3","INCORRECT_WITH_ICON","StyledInputMissing","_ref4","MISSING_WITH_ICON","fontWeight","StyledIncorrect","getInputStyles","disabled","markDisabled","fontFamily","typography","PRIMARY_DARK","SECONDARY","WebkitOpacity","undefined","WebkitTextFillColor","getStudentInputStyles","position","exports","graphProps","mark","rect","width","height","scale","domain","range","shift","rightEdge","x","bottomEdge","y","h","max","v","min","coordinates","left","top","LabelInput","_ref5","_ref","externalInputRef","label","inputStyle","onChange","onBlur","createElement","inputRef","value","propTypes","PropTypes","func","string","bool","object","MarkLabel","props","inputNode","useRef","_useState","useState","_useState2","_slicedToArray2","input","setInput","useCallback","node","current","useTheme","autoFocus","_useState3","_useState4","setLabel","correctness","correctnesslabel","correctlabel","isFocused","document","activeElement","isNewLabel","insistUntil","lastSaved","insisting","Date","now","target","saveLabel","handleBlur","debouncedLabel","useDebounce","useEffect","focusInput","focus","caret","setSelectionRange","timers","map","delay","setTimeout","clearTimeout","getBoundingClientRect","pos","leftTop","style","pointerEvents","display","alignItems","gap","secondLabelStyle","disabledInput","renderInput","labelValue","studentInputStyle","type","Fragment","marginLeft","types","GraphPropsType","_default"],"sources":["../src/mark-label.jsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { styled, useTheme } from '@mui/material/styles';\nimport AutosizeInput from 'react-input-autosize';\nimport { useDebounce } from './use-debounce';\nimport { types } from '@pie-lib/plot';\nimport { color } from '@pie-lib/render-ui';\nimport SvgIcon from './label-svg-icon';\n\nconst DEBOUNCE_DELAY = 500;\n// A new label insists on the focus for this long: in the DNA env something moves the focus while the\n// model save that creating the label triggered is handled, after the last render. Nothing typed yet\n// is what tells that apart from the user leaving the label.\nconst INSIST_ON_FOCUS_FOR = 500;\nconst INSIST_AT = [0, 50, 120, 250, 400];\n\nconst StyledInputCorrect = styled('div')(({ theme }) => ({\n float: 'right',\n padding: theme.spacing(0.5),\n borderRadius: '4px',\n fontSize: '10px',\n backgroundColor: color.defaults.WHITE,\n color: color.defaults.CORRECT_WITH_ICON,\n border: `solid 1px ${color.defaults.CORRECT_WITH_ICON}`,\n}));\n\nconst StyledInputIncorrect = styled('div')(({ theme }) => ({\n float: 'right',\n padding: theme.spacing(0.5),\n borderRadius: '4px',\n fontSize: '10px',\n backgroundColor: color.defaults.WHITE,\n color: color.defaults.INCORRECT_WITH_ICON,\n border: `solid 1px ${color.defaults.INCORRECT_WITH_ICON}`,\n}));\n\nconst StyledInputMissing = styled('div')(({ theme }) => ({\n float: 'right',\n padding: theme.spacing(0.5),\n borderRadius: '4px',\n fontSize: '10px',\n backgroundColor: color.defaults.WHITE,\n color: color.defaults.MISSING_WITH_ICON,\n border: `solid 1px ${color.defaults.MISSING_WITH_ICON}`,\n fontWeight: 'bold',\n}));\n\nconst StyledIncorrect = styled('div')(() => ({\n float: 'right',\n padding: 0,\n borderRadius: '4px',\n fontSize: '10px',\n backgroundColor: color.defaults.WHITE,\n color: color.defaults.INCORRECT_WITH_ICON,\n fontWeight: 'bold',\n}));\n\nconst getInputStyles = (theme, disabled, markDisabled) => ({\n float: 'right',\n padding: theme.spacing(0.5),\n fontFamily: theme.typography.fontFamily,\n fontSize: '10px',\n border: disabled\n ? `solid 1px ${color.defaults.PRIMARY_DARK}`\n : markDisabled\n ? `solid 1px ${color.disabled()}`\n : `solid 1px ${color.defaults.SECONDARY}`,\n borderRadius: '3px',\n color: markDisabled ? color.disabled() : color.defaults.PRIMARY_DARK,\n backgroundColor: color.defaults.WHITE,\n WebkitOpacity: disabled ? '1' : undefined,\n WebkitTextFillColor: markDisabled ? color.disabled() : undefined,\n});\n\nconst getStudentInputStyles = () => ({\n padding: '0',\n border: 'none',\n color: 'inherit',\n fontWeight: 'bold',\n});\n\nexport const position = (graphProps, mark, rect = { width: 0, height: 0 }) => {\n const { scale, domain, range } = graphProps;\n const shift = 5;\n\n const rightEdge = scale.x(mark.x) + rect.width + shift;\n const bottomEdge = scale.y(mark.y) + rect.height + shift;\n\n const h = rightEdge >= scale.x(domain.max) ? 'left' : 'right';\n const v = bottomEdge >= scale.y(range.min) ? 'top' : 'bottom';\n\n return `${v}-${h}`;\n};\n\nexport const coordinates = (graphProps, mark, rect = { width: 0, height: 0 }, position) => {\n const { scale } = graphProps;\n const shift = 5;\n\n switch (position) {\n case 'bottom-right':\n return { left: scale.x(mark.x) + shift, top: scale.y(mark.y) + shift };\n case 'bottom-left':\n return { left: scale.x(mark.x) - shift - rect.width, top: scale.y(mark.y) + shift };\n case 'top-left':\n return { left: scale.x(mark.x) - shift - rect.width, top: scale.y(mark.y) - shift - rect.height };\n case 'top-right':\n return { left: scale.x(mark.x) + shift, top: scale.y(mark.y) - shift - rect.height };\n default:\n return {};\n }\n};\n\nconst LabelInput = ({ _ref, externalInputRef, label, disabled, inputStyle, onChange, onBlur }) => (\n <AutosizeInput\n inputRef={(r) => {\n _ref(r);\n externalInputRef(r);\n }}\n disabled={disabled}\n inputStyle={inputStyle}\n value={label}\n onChange={onChange}\n onBlur={onBlur}\n />\n);\n\nLabelInput.propTypes = {\n _ref: PropTypes.func,\n externalInputRef: PropTypes.func,\n label: PropTypes.string,\n disabled: PropTypes.bool,\n inputStyle: PropTypes.object,\n onChange: PropTypes.func,\n onBlur: PropTypes.func,\n};\n\nexport const MarkLabel = (props) => {\n // the state repositions the label once the input has a size, the ref is never a render behind\n const inputNode = useRef(null);\n const [input, setInput] = useState(null);\n const _ref = useCallback((node) => {\n inputNode.current = node;\n setInput(node);\n }, []);\n const theme = useTheme();\n\n const { mark, graphProps, disabled, autoFocus, inputRef: externalInputRef } = props;\n\n const [label, setLabel] = useState(mark.label);\n const { correctness, correctnesslabel, correctlabel } = mark;\n\n const isFocused = () =>\n !!inputNode.current && typeof document !== 'undefined' && document.activeElement === inputNode.current;\n\n // an empty label with an enabled input is one the user just added: label mode has to be on and it\n // always starts off. Read from the mark, not from autoFocus, because the tool that asked for the\n // label can be remounted by the marks coming back from the host before the input renders.\n const isNewLabel = useRef(mark.label === '' && !disabled && !mark.disabled);\n const insistUntil = useRef(0);\n const lastSaved = useRef(mark.label);\n const insisting = () => Date.now() < insistUntil.current && !(inputNode.current && inputNode.current.value);\n\n const onChange = (e) => setLabel(e.target.value);\n\n const saveLabel = (value) => {\n if (value === lastSaved.current) {\n return;\n }\n\n lastSaved.current = value;\n props.onChange(value);\n };\n\n const handleBlur = useCallback(() => {\n // in the DNA env the focus is moved while the model is saved - not the user leaving the label\n if (insisting()) {\n return;\n }\n\n isNewLabel.current = false;\n\n if (label === '') {\n props.onChange('');\n } else if (label !== mark.label) {\n // the debounce can still be pending, and once the focus is gone an echo of the model would\n // overwrite what was typed before it fires\n saveLabel(label);\n }\n\n // lets the tool know that this label is not being edited anymore, so it stops auto focusing it\n if (props.onBlur) {\n props.onBlur();\n }\n }, [label, mark.label, props.onChange, props.onBlur]);\n\n const debouncedLabel = useDebounce(label, DEBOUNCE_DELAY);\n\n // props to state, but not while focused: the mark can come back from an async model save with an\n // older label and overwrite what was typed meanwhile\n useEffect(() => {\n if (isFocused()) {\n return;\n }\n\n setLabel(mark.label);\n }, [mark.label]);\n\n // pick up the change to debouncedLabel and save it\n useEffect(() => {\n if (typeof debouncedLabel === 'string' && debouncedLabel !== mark.label) {\n saveLabel(debouncedLabel);\n }\n }, [debouncedLabel]);\n\n const focusInput = () => {\n const node = inputNode.current;\n\n // node.disabled, not the disabled prop: a disabled input silently ignores focus()\n if ((!autoFocus && !isNewLabel.current && !insisting()) || !node || node.disabled || isFocused()) {\n return;\n }\n\n node.focus();\n\n // a new label is focused once, so it cannot fight over the focus with another one\n if (isFocused()) {\n isNewLabel.current = false;\n }\n\n // keep the caret at the end, otherwise typing continues in front of the existing label\n const caret = (node.value || '').length;\n\n if (node.setSelectionRange) {\n node.setSelectionRange(caret, caret);\n }\n };\n\n // after every render: the input can appear a render or more later (the mark comes back from an\n // async model save) and a replaced node loses the focus without this component being told\n useEffect(() => focusInput());\n\n // and again on a timer, for the DNA env, where the focus is moved once the renders are over. The\n // original code focused from a setTimeout, which is what let it survive that.\n useEffect(() => {\n if (!autoFocus && !isNewLabel.current) {\n return;\n }\n\n if (!insistUntil.current) {\n insistUntil.current = Date.now() + INSIST_ON_FOCUS_FOR;\n }\n\n const timers = INSIST_AT.map((delay) => setTimeout(focusInput, delay));\n\n return () => timers.forEach((t) => clearTimeout(t));\n }, [autoFocus]);\n\n const rect = input ? input.getBoundingClientRect() : { width: 0, height: 0 };\n const pos = position(graphProps, mark, rect);\n const leftTop = coordinates(graphProps, mark, rect, pos);\n\n const style = {\n position: 'fixed',\n pointerEvents: 'auto',\n display: 'flex',\n alignItems: 'center',\n gap: '3px',\n ...leftTop,\n };\n\n const secondLabelStyle = {\n ...style,\n top: leftTop.top + 25,\n };\n\n const disabledInput = disabled || mark.disabled;\n\n const renderInput = (inputStyle, labelValue) => (\n <LabelInput\n _ref={_ref}\n externalInputRef={externalInputRef}\n label={labelValue}\n disabled={disabledInput}\n inputStyle={inputStyle}\n onChange={onChange}\n onBlur={handleBlur}\n />\n );\n\n const studentInputStyle = getStudentInputStyles();\n\n if (correctness === 'correct' && correctnesslabel === 'correct' && correctlabel) {\n return (\n <StyledInputCorrect style={style}>\n <SvgIcon type=\"correct\" />\n {renderInput(studentInputStyle, correctlabel)}\n </StyledInputCorrect>\n );\n }\n\n if (correctness === 'correct' && correctnesslabel === 'correct' && !correctlabel) {\n return null;\n }\n\n if (correctness === 'correct' && correctnesslabel === 'incorrect') {\n return (\n <>\n <StyledInputIncorrect style={style}>\n <SvgIcon type=\"incorrect\" />\n {label === '' ? (\n <SvgIcon type=\"empty\" style={{ marginLeft: '3px' }} />\n ) : (\n renderInput(studentInputStyle, label)\n )}\n </StyledInputIncorrect>\n <StyledInputMissing style={secondLabelStyle}>{renderInput(studentInputStyle, correctlabel)}</StyledInputMissing>\n </>\n );\n }\n\n if (correctness === 'missing') {\n return <StyledInputMissing style={style}>{renderInput(studentInputStyle, label)}</StyledInputMissing>;\n }\n\n if (correctness === 'incorrect') {\n return <StyledIncorrect style={style}>{renderInput(studentInputStyle, label)}</StyledIncorrect>;\n }\n\n // an empty label that cannot be edited is just an empty box - the config draws the background\n // marks into every correct answer graph too\n if (disabledInput && !label) {\n return null;\n }\n\n return <div style={style}>{renderInput(getInputStyles(theme, disabled, mark.disabled), label)}</div>;\n};\n\nMarkLabel.propTypes = {\n autoFocus: PropTypes.bool,\n disabled: PropTypes.bool,\n onBlur: PropTypes.func,\n onChange: PropTypes.func,\n graphProps: types.GraphPropsType,\n inputRef: PropTypes.func,\n mark: PropTypes.object,\n};\n\nexport default MarkLabel;\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.18",
|
|
7
7
|
"description": "Graphing components",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"react",
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"@mapbox/point-geometry": "^1.1.0",
|
|
23
23
|
"@mui/icons-material": "^7.3.4",
|
|
24
24
|
"@mui/material": "^7.3.4",
|
|
25
|
-
"@pie-lib/drag": "^4.1.
|
|
26
|
-
"@pie-lib/editable-html-tip-tap": "^2.1.
|
|
25
|
+
"@pie-lib/drag": "^4.1.2",
|
|
26
|
+
"@pie-lib/editable-html-tip-tap": "^2.1.15",
|
|
27
27
|
"@pie-lib/graphing-utils": "^3.0.2",
|
|
28
|
-
"@pie-lib/plot": "^4.0.
|
|
29
|
-
"@pie-lib/render-ui": "^
|
|
28
|
+
"@pie-lib/plot": "^4.0.17",
|
|
29
|
+
"@pie-lib/render-ui": "^7.0.1",
|
|
30
30
|
"@pie-lib/translator": "^4.0.2",
|
|
31
31
|
"@visx/axis": "^3.0.0",
|
|
32
32
|
"@visx/clip-path": "^3.0.0",
|
|
@@ -54,6 +54,6 @@
|
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"react": "^18.2.0"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "38176e40de37e31fc3bf4edb8669cf2238e910d3",
|
|
58
58
|
"scripts": {}
|
|
59
59
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render } from '@pie-lib/test-utils';
|
|
2
|
+
import { act, fireEvent, render } from '@pie-lib/test-utils';
|
|
3
3
|
import { graphProps } from './utils';
|
|
4
4
|
import Graph, { removeBuildingToolIfCurrentToolDiffers } from '../graph';
|
|
5
5
|
import { toolsArr } from '../tools';
|
|
@@ -719,3 +719,78 @@ describe('Graph', () => {
|
|
|
719
719
|
});
|
|
720
720
|
});
|
|
721
721
|
});
|
|
722
|
+
|
|
723
|
+
describe('label focus', () => {
|
|
724
|
+
// the marks are owned by the host and come back from a model save asynchronously; a mark that
|
|
725
|
+
// shows up in front of the labelled one changes its key, so the tool that handled the click is
|
|
726
|
+
// remounted and the editingLabel it set is gone before the label input ever renders
|
|
727
|
+
const Host = ({ shiftMarks }) => {
|
|
728
|
+
const [marks, setMarks] = React.useState([{ type: 'point', x: 2, y: 2 }]);
|
|
729
|
+
|
|
730
|
+
return (
|
|
731
|
+
<Graph
|
|
732
|
+
tools={toolsArr}
|
|
733
|
+
marks={marks}
|
|
734
|
+
labelModeEnabled={true}
|
|
735
|
+
onChangeMarks={(next) =>
|
|
736
|
+
setTimeout(() => setMarks(shiftMarks ? [{ type: 'point', x: 5, y: 5 }, ...next] : next), 30)
|
|
737
|
+
}
|
|
738
|
+
domain={{ min: 0, max: 10, step: 1 }}
|
|
739
|
+
range={{ min: 0, max: 10, step: 1 }}
|
|
740
|
+
size={{ width: 400, height: 400 }}
|
|
741
|
+
{...graphProps(0, 10, 0, 10)}
|
|
742
|
+
/>
|
|
743
|
+
);
|
|
744
|
+
};
|
|
745
|
+
|
|
746
|
+
const clickPoint = (container) => {
|
|
747
|
+
const circle = container.querySelector('circle');
|
|
748
|
+
|
|
749
|
+
fireEvent.mouseDown(circle, { button: 0 });
|
|
750
|
+
fireEvent.mouseUp(circle, { button: 0 });
|
|
751
|
+
fireEvent.click(circle, { button: 0 });
|
|
752
|
+
act(() => jest.advanceTimersByTime(200));
|
|
753
|
+
};
|
|
754
|
+
|
|
755
|
+
beforeEach(() => jest.useFakeTimers());
|
|
756
|
+
afterEach(() => jest.useRealTimers());
|
|
757
|
+
|
|
758
|
+
it('focuses the label that was just added', () => {
|
|
759
|
+
const { container } = render(<Host />);
|
|
760
|
+
|
|
761
|
+
clickPoint(container);
|
|
762
|
+
|
|
763
|
+
const input = container.querySelector('foreignObject input');
|
|
764
|
+
expect(input).not.toBe(null);
|
|
765
|
+
expect(document.activeElement).toBe(input);
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
// in the DNA env the focus is moved while the model save is handled, after the last render
|
|
769
|
+
it('takes the focus back when something steals it while the model is saved', () => {
|
|
770
|
+
const { container } = render(<Host />);
|
|
771
|
+
|
|
772
|
+
clickPoint(container);
|
|
773
|
+
const input = container.querySelector('foreignObject input');
|
|
774
|
+
expect(document.activeElement).toBe(input);
|
|
775
|
+
|
|
776
|
+
const elsewhere = document.createElement('input');
|
|
777
|
+
document.body.appendChild(elsewhere);
|
|
778
|
+
elsewhere.focus();
|
|
779
|
+
expect(document.activeElement).toBe(elsewhere);
|
|
780
|
+
|
|
781
|
+
act(() => jest.advanceTimersByTime(300));
|
|
782
|
+
|
|
783
|
+
expect(document.activeElement).toBe(input);
|
|
784
|
+
elsewhere.remove();
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
it('focuses the label even if the tool was remounted before it rendered', () => {
|
|
788
|
+
const { container } = render(<Host shiftMarks={true} />);
|
|
789
|
+
|
|
790
|
+
clickPoint(container);
|
|
791
|
+
|
|
792
|
+
const input = container.querySelector('foreignObject input');
|
|
793
|
+
expect(input).not.toBe(null);
|
|
794
|
+
expect(document.activeElement).toBe(input);
|
|
795
|
+
});
|
|
796
|
+
});
|
|
@@ -75,18 +75,50 @@ describe('MarkLabel - editing', () => {
|
|
|
75
75
|
expect(input.selectionEnd).toBe(2);
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
it('does not focus the input when autoFocus is not set', () => {
|
|
79
|
-
const { input } = renderComponent();
|
|
78
|
+
it('does not focus the input of an existing label when autoFocus is not set', () => {
|
|
79
|
+
const { input } = renderComponent({ mark: { x: 1, y: 1, label: 'A' } });
|
|
80
80
|
|
|
81
81
|
expect(document.activeElement).not.toBe(input);
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
it('does not focus the input when disabled', () => {
|
|
85
|
-
const { input } = renderComponent({ autoFocus: true, disabled: true });
|
|
85
|
+
const { input } = renderComponent({ autoFocus: true, disabled: true, mark: { x: 1, y: 1, label: 'A' } });
|
|
86
|
+
|
|
87
|
+
expect(document.activeElement).not.toBe(input);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('does not focus the input of a disabled mark', () => {
|
|
91
|
+
const { input } = renderComponent({ autoFocus: true, mark: { x: 1, y: 1, label: 'A', disabled: true } });
|
|
86
92
|
|
|
87
93
|
expect(document.activeElement).not.toBe(input);
|
|
88
94
|
});
|
|
89
95
|
|
|
96
|
+
// the focus can go away without this component hearing about it - the input node gets replaced
|
|
97
|
+
// by a render higher up, so no blur is fired and autoFocus is still on
|
|
98
|
+
it('takes the focus back on the next render while it is still being edited', () => {
|
|
99
|
+
const { input, rerenderWith } = renderComponent({ autoFocus: true, mark: { x: 1, y: 1, label: 'A' } });
|
|
100
|
+
|
|
101
|
+
expect(document.activeElement).toBe(input);
|
|
102
|
+
|
|
103
|
+
input.blur();
|
|
104
|
+
expect(document.activeElement).not.toBe(input);
|
|
105
|
+
|
|
106
|
+
rerenderWith({ mark: { x: 1, y: 1, label: 'A' } });
|
|
107
|
+
|
|
108
|
+
expect(document.activeElement).toBe(input);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('leaves the caret where the user put it while the input has the focus', () => {
|
|
112
|
+
const { input, rerenderWith } = renderComponent({ autoFocus: true, mark: { x: 1, y: 1, label: 'ABC' } });
|
|
113
|
+
|
|
114
|
+
input.setSelectionRange(1, 1);
|
|
115
|
+
|
|
116
|
+
rerenderWith({ mark: { x: 1, y: 1, label: 'ABC' } });
|
|
117
|
+
|
|
118
|
+
expect(document.activeElement).toBe(input);
|
|
119
|
+
expect(input.selectionStart).toBe(1);
|
|
120
|
+
});
|
|
121
|
+
|
|
90
122
|
it('focuses the input once it is no longer disabled', () => {
|
|
91
123
|
const { rerenderWith, container } = renderComponent({ autoFocus: true, disabled: true });
|
|
92
124
|
|
|
@@ -118,6 +150,76 @@ describe('MarkLabel - editing', () => {
|
|
|
118
150
|
});
|
|
119
151
|
});
|
|
120
152
|
|
|
153
|
+
// the tool asks for the focus with autoFocus, but its state can be gone before the input renders:
|
|
154
|
+
// the marks come back from the host asynchronously and can remount the tool. An empty label in
|
|
155
|
+
// label mode is a label the user has just added, so the input can tell on its own.
|
|
156
|
+
describe('a label that was just added', () => {
|
|
157
|
+
it('focuses itself without the tool asking', () => {
|
|
158
|
+
const { input } = renderComponent({ mark: { x: 1, y: 1, label: '' } });
|
|
159
|
+
|
|
160
|
+
expect(document.activeElement).toBe(input);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('focuses itself again when it is remounted before it was typed into', () => {
|
|
164
|
+
const props = {
|
|
165
|
+
onChange,
|
|
166
|
+
onBlur,
|
|
167
|
+
inputRef: jest.fn(),
|
|
168
|
+
mark: { x: 1, y: 1, label: '' },
|
|
169
|
+
graphProps: getGraphProps(0, 10, 0, 10),
|
|
170
|
+
};
|
|
171
|
+
const { container, rerender } = render(<MarkLabel key="first" {...props} />);
|
|
172
|
+
const first = input(container);
|
|
173
|
+
|
|
174
|
+
rerender(<MarkLabel key="second" {...props} />);
|
|
175
|
+
const second = input(container);
|
|
176
|
+
|
|
177
|
+
expect(second).not.toBe(first);
|
|
178
|
+
expect(document.activeElement).toBe(second);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('stops chasing the focus once it has been left', () => {
|
|
182
|
+
const { input, rerenderWith } = renderComponent({ mark: { x: 1, y: 1, label: '' } });
|
|
183
|
+
|
|
184
|
+
expect(document.activeElement).toBe(input);
|
|
185
|
+
|
|
186
|
+
input.blur();
|
|
187
|
+
rerenderWith({ mark: { x: 1, y: 1, label: '' } });
|
|
188
|
+
|
|
189
|
+
expect(document.activeElement).not.toBe(input);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// outside of label mode the input is disabled, which is how an empty label that was loaded with
|
|
193
|
+
// the item is told apart from one the user has just added - label mode always starts off
|
|
194
|
+
// the config draws the background marks into the correct answer graphs as disabled marks
|
|
195
|
+
it('is not rendered at all while it cannot be edited', () => {
|
|
196
|
+
const { container } = renderComponent({ disabled: true, mark: { x: 1, y: 1, label: '' } });
|
|
197
|
+
|
|
198
|
+
expect(container.querySelector('input')).toBe(null);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('is still rendered uneditable once it has text', () => {
|
|
202
|
+
const { container } = renderComponent({ disabled: true, mark: { x: 1, y: 1, label: 'A' } });
|
|
203
|
+
|
|
204
|
+
expect(container.querySelector('input').value).toBe('A');
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('is not focused when label mode is turned on afterwards', () => {
|
|
208
|
+
const { rerenderWith, container } = renderComponent({ disabled: true, mark: { x: 1, y: 1, label: '' } });
|
|
209
|
+
|
|
210
|
+
rerenderWith({ disabled: false });
|
|
211
|
+
|
|
212
|
+
expect(input(container)).not.toBe(null);
|
|
213
|
+
expect(document.activeElement).not.toBe(input(container));
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('is not rendered for a disabled mark while it is empty', () => {
|
|
217
|
+
const { container } = renderComponent({ mark: { x: 1, y: 1, label: '', disabled: true } });
|
|
218
|
+
|
|
219
|
+
expect(container.querySelector('input')).toBe(null);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
121
223
|
describe('syncing mark.label into the input', () => {
|
|
122
224
|
it('picks up a new mark.label while the input does not have the focus', () => {
|
|
123
225
|
const { rerenderWith, container } = renderComponent({ mark: { x: 1, y: 1, label: 'A' } });
|
|
@@ -153,6 +255,29 @@ describe('MarkLabel - editing', () => {
|
|
|
153
255
|
expect(onBlur).toHaveBeenCalled();
|
|
154
256
|
});
|
|
155
257
|
|
|
258
|
+
// clicking a button or anything else interactive blurs the label while the debounce is pending
|
|
259
|
+
it('saves what was typed straight away', () => {
|
|
260
|
+
const { input } = renderComponent({ mark: { x: 1, y: 1, label: '' } });
|
|
261
|
+
|
|
262
|
+
fireEvent.change(input, { target: { value: 'AB' } });
|
|
263
|
+
fireEvent.blur(input);
|
|
264
|
+
|
|
265
|
+
expect(onChange).toHaveBeenCalledWith('AB');
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('does not save it twice when the debounce catches up', () => {
|
|
269
|
+
jest.useFakeTimers();
|
|
270
|
+
const { input } = renderComponent({ mark: { x: 1, y: 1, label: '' } });
|
|
271
|
+
|
|
272
|
+
fireEvent.change(input, { target: { value: 'AB' } });
|
|
273
|
+
fireEvent.blur(input);
|
|
274
|
+
act(() => jest.advanceTimersByTime(1000));
|
|
275
|
+
|
|
276
|
+
expect(onChange).toHaveBeenCalledTimes(1);
|
|
277
|
+
expect(onChange).toHaveBeenCalledWith('AB');
|
|
278
|
+
jest.useRealTimers();
|
|
279
|
+
});
|
|
280
|
+
|
|
156
281
|
it('reports an empty label on blur', () => {
|
|
157
282
|
const { input } = renderComponent({ mark: { x: 1, y: 1, label: 'A' } });
|
|
158
283
|
|
package/src/mark-label.jsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { styled, useTheme } from '@mui/material/styles';
|
|
4
4
|
import AutosizeInput from 'react-input-autosize';
|
|
@@ -8,6 +8,11 @@ import { color } from '@pie-lib/render-ui';
|
|
|
8
8
|
import SvgIcon from './label-svg-icon';
|
|
9
9
|
|
|
10
10
|
const DEBOUNCE_DELAY = 500;
|
|
11
|
+
// A new label insists on the focus for this long: in the DNA env something moves the focus while the
|
|
12
|
+
// model save that creating the label triggered is handled, after the last render. Nothing typed yet
|
|
13
|
+
// is what tells that apart from the user leaving the label.
|
|
14
|
+
const INSIST_ON_FOCUS_FOR = 500;
|
|
15
|
+
const INSIST_AT = [0, 50, 120, 250, 400];
|
|
11
16
|
|
|
12
17
|
const StyledInputCorrect = styled('div')(({ theme }) => ({
|
|
13
18
|
float: 'right',
|
|
@@ -130,8 +135,13 @@ LabelInput.propTypes = {
|
|
|
130
135
|
};
|
|
131
136
|
|
|
132
137
|
export const MarkLabel = (props) => {
|
|
138
|
+
// the state repositions the label once the input has a size, the ref is never a render behind
|
|
139
|
+
const inputNode = useRef(null);
|
|
133
140
|
const [input, setInput] = useState(null);
|
|
134
|
-
const _ref = useCallback((node) =>
|
|
141
|
+
const _ref = useCallback((node) => {
|
|
142
|
+
inputNode.current = node;
|
|
143
|
+
setInput(node);
|
|
144
|
+
}, []);
|
|
135
145
|
const theme = useTheme();
|
|
136
146
|
|
|
137
147
|
const { mark, graphProps, disabled, autoFocus, inputRef: externalInputRef } = props;
|
|
@@ -139,26 +149,54 @@ export const MarkLabel = (props) => {
|
|
|
139
149
|
const [label, setLabel] = useState(mark.label);
|
|
140
150
|
const { correctness, correctnesslabel, correctlabel } = mark;
|
|
141
151
|
|
|
142
|
-
const isFocused = () =>
|
|
152
|
+
const isFocused = () =>
|
|
153
|
+
!!inputNode.current && typeof document !== 'undefined' && document.activeElement === inputNode.current;
|
|
154
|
+
|
|
155
|
+
// an empty label with an enabled input is one the user just added: label mode has to be on and it
|
|
156
|
+
// always starts off. Read from the mark, not from autoFocus, because the tool that asked for the
|
|
157
|
+
// label can be remounted by the marks coming back from the host before the input renders.
|
|
158
|
+
const isNewLabel = useRef(mark.label === '' && !disabled && !mark.disabled);
|
|
159
|
+
const insistUntil = useRef(0);
|
|
160
|
+
const lastSaved = useRef(mark.label);
|
|
161
|
+
const insisting = () => Date.now() < insistUntil.current && !(inputNode.current && inputNode.current.value);
|
|
143
162
|
|
|
144
163
|
const onChange = (e) => setLabel(e.target.value);
|
|
145
164
|
|
|
165
|
+
const saveLabel = (value) => {
|
|
166
|
+
if (value === lastSaved.current) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
lastSaved.current = value;
|
|
171
|
+
props.onChange(value);
|
|
172
|
+
};
|
|
173
|
+
|
|
146
174
|
const handleBlur = useCallback(() => {
|
|
175
|
+
// in the DNA env the focus is moved while the model is saved - not the user leaving the label
|
|
176
|
+
if (insisting()) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
isNewLabel.current = false;
|
|
181
|
+
|
|
147
182
|
if (label === '') {
|
|
148
183
|
props.onChange('');
|
|
184
|
+
} else if (label !== mark.label) {
|
|
185
|
+
// the debounce can still be pending, and once the focus is gone an echo of the model would
|
|
186
|
+
// overwrite what was typed before it fires
|
|
187
|
+
saveLabel(label);
|
|
149
188
|
}
|
|
150
189
|
|
|
151
190
|
// lets the tool know that this label is not being edited anymore, so it stops auto focusing it
|
|
152
191
|
if (props.onBlur) {
|
|
153
192
|
props.onBlur();
|
|
154
193
|
}
|
|
155
|
-
}, [label, props.onChange, props.onBlur]);
|
|
194
|
+
}, [label, mark.label, props.onChange, props.onBlur]);
|
|
156
195
|
|
|
157
196
|
const debouncedLabel = useDebounce(label, DEBOUNCE_DELAY);
|
|
158
197
|
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
// (async) model save with an older label and that would overwrite the characters typed meanwhile.
|
|
198
|
+
// props to state, but not while focused: the mark can come back from an async model save with an
|
|
199
|
+
// older label and overwrite what was typed meanwhile
|
|
162
200
|
useEffect(() => {
|
|
163
201
|
if (isFocused()) {
|
|
164
202
|
return;
|
|
@@ -170,27 +208,52 @@ export const MarkLabel = (props) => {
|
|
|
170
208
|
// pick up the change to debouncedLabel and save it
|
|
171
209
|
useEffect(() => {
|
|
172
210
|
if (typeof debouncedLabel === 'string' && debouncedLabel !== mark.label) {
|
|
173
|
-
|
|
211
|
+
saveLabel(debouncedLabel);
|
|
174
212
|
}
|
|
175
213
|
}, [debouncedLabel]);
|
|
176
214
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (!autoFocus || !
|
|
215
|
+
const focusInput = () => {
|
|
216
|
+
const node = inputNode.current;
|
|
217
|
+
|
|
218
|
+
// node.disabled, not the disabled prop: a disabled input silently ignores focus()
|
|
219
|
+
if ((!autoFocus && !isNewLabel.current && !insisting()) || !node || node.disabled || isFocused()) {
|
|
182
220
|
return;
|
|
183
221
|
}
|
|
184
222
|
|
|
185
|
-
|
|
223
|
+
node.focus();
|
|
224
|
+
|
|
225
|
+
// a new label is focused once, so it cannot fight over the focus with another one
|
|
226
|
+
if (isFocused()) {
|
|
227
|
+
isNewLabel.current = false;
|
|
228
|
+
}
|
|
186
229
|
|
|
187
230
|
// keep the caret at the end, otherwise typing continues in front of the existing label
|
|
188
|
-
const caret = (
|
|
231
|
+
const caret = (node.value || '').length;
|
|
232
|
+
|
|
233
|
+
if (node.setSelectionRange) {
|
|
234
|
+
node.setSelectionRange(caret, caret);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// after every render: the input can appear a render or more later (the mark comes back from an
|
|
239
|
+
// async model save) and a replaced node loses the focus without this component being told
|
|
240
|
+
useEffect(() => focusInput());
|
|
241
|
+
|
|
242
|
+
// and again on a timer, for the DNA env, where the focus is moved once the renders are over. The
|
|
243
|
+
// original code focused from a setTimeout, which is what let it survive that.
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
if (!autoFocus && !isNewLabel.current) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
189
248
|
|
|
190
|
-
if (
|
|
191
|
-
|
|
249
|
+
if (!insistUntil.current) {
|
|
250
|
+
insistUntil.current = Date.now() + INSIST_ON_FOCUS_FOR;
|
|
192
251
|
}
|
|
193
|
-
|
|
252
|
+
|
|
253
|
+
const timers = INSIST_AT.map((delay) => setTimeout(focusInput, delay));
|
|
254
|
+
|
|
255
|
+
return () => timers.forEach((t) => clearTimeout(t));
|
|
256
|
+
}, [autoFocus]);
|
|
194
257
|
|
|
195
258
|
const rect = input ? input.getBoundingClientRect() : { width: 0, height: 0 };
|
|
196
259
|
const pos = position(graphProps, mark, rect);
|
|
@@ -263,6 +326,12 @@ export const MarkLabel = (props) => {
|
|
|
263
326
|
return <StyledIncorrect style={style}>{renderInput(studentInputStyle, label)}</StyledIncorrect>;
|
|
264
327
|
}
|
|
265
328
|
|
|
329
|
+
// an empty label that cannot be edited is just an empty box - the config draws the background
|
|
330
|
+
// marks into every correct answer graph too
|
|
331
|
+
if (disabledInput && !label) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
|
|
266
335
|
return <div style={style}>{renderInput(getInputStyles(theme, disabled, mark.disabled), label)}</div>;
|
|
267
336
|
};
|
|
268
337
|
|
|
@@ -409,7 +409,8 @@ describe('Component', () => {
|
|
|
409
409
|
expect(document.activeElement).not.toBe(labelNode.querySelector('input'));
|
|
410
410
|
});
|
|
411
411
|
|
|
412
|
-
|
|
412
|
+
// the blur that the DNA env causes by moving the focus is not the user leaving the label
|
|
413
|
+
it('keeps the focus on a new empty label that something else blurred', () => {
|
|
413
414
|
const { container } = render(<Controlled initialMark={xy(1, 1)} labelModeEnabled={true} />);
|
|
414
415
|
|
|
415
416
|
clickPoint(container);
|
|
@@ -417,9 +418,23 @@ describe('Component', () => {
|
|
|
417
418
|
expect(document.activeElement).toBe(input);
|
|
418
419
|
|
|
419
420
|
fireEvent.blur(input);
|
|
421
|
+
fireEvent.change(input, { target: { value: 'A' } });
|
|
422
|
+
|
|
423
|
+
expect(document.activeElement).toBe(input);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
it('stops auto focusing the label once it has text and is blurred', () => {
|
|
427
|
+
const { container } = render(<Controlled initialMark={xy(1, 1)} labelModeEnabled={true} />);
|
|
428
|
+
|
|
429
|
+
clickPoint(container);
|
|
430
|
+
const input = labelNode.querySelector('input');
|
|
420
431
|
|
|
421
|
-
// a re-render must not pull the focus back into the label the user just left
|
|
422
432
|
fireEvent.change(input, { target: { value: 'A' } });
|
|
433
|
+
fireEvent.blur(input);
|
|
434
|
+
input.blur();
|
|
435
|
+
|
|
436
|
+
// a re-render must not pull the focus back into the label the user just left
|
|
437
|
+
fireEvent.change(input, { target: { value: 'AB' } });
|
|
423
438
|
expect(document.activeElement).not.toBe(input);
|
|
424
439
|
});
|
|
425
440
|
|