@pie-lib/text-select 2.2.0-next.8 → 3.0.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/CHANGELOG.md +10 -0
- package/lib/token-select/index.js +114 -53
- package/lib/token-select/index.js.map +1 -1
- package/package.json +6 -6
- package/src/token-select/__tests__/index.test.jsx +245 -9
- package/src/token-select/index.jsx +126 -54
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
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
|
+
# [2.2.0-next.10](https://github.com/pie-framework/pie-lib/compare/@pie-lib/text-select@2.2.0-next.9...@pie-lib/text-select@2.2.0-next.10) (2026-04-23)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @pie-lib/text-select
|
|
9
|
+
|
|
10
|
+
# [2.2.0-next.9](https://github.com/pie-framework/pie-lib/compare/@pie-lib/text-select@2.2.0-next.8...@pie-lib/text-select@2.2.0-next.9) (2026-04-16)
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- **text-select:** adjust markup rendering PIE-25 PIE-13 ([1d4d91d](https://github.com/pie-framework/pie-lib/commit/1d4d91d09efdaf861e384beda7d6d1e512a2281c))
|
|
15
|
+
|
|
6
16
|
# [2.2.0-next.8](https://github.com/pie-framework/pie-lib/compare/@pie-lib/text-select@2.2.0-next.7...@pie-lib/text-select@2.2.0-next.8) (2026-04-15)
|
|
7
17
|
|
|
8
18
|
**Note:** Version bump only for package @pie-lib/text-select
|
|
@@ -14,6 +14,7 @@ var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/ge
|
|
|
14
14
|
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
|
|
15
15
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
16
16
|
var _react = _interopRequireDefault(require("react"));
|
|
17
|
+
var _server = require("react-dom/server");
|
|
17
18
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
18
19
|
var _token = _interopRequireWildcard(require("./token"));
|
|
19
20
|
var _styles = require("@mui/material/styles");
|
|
@@ -32,18 +33,29 @@ var StyledTokenSelect = (0, _styles.styled)('div')(function () {
|
|
|
32
33
|
whiteSpace: 'pre'
|
|
33
34
|
}, (0, _styleUtils.noSelect)()), {}, {
|
|
34
35
|
'& p': {
|
|
35
|
-
whiteSpace: 'break-spaces'
|
|
36
|
-
margin: 0
|
|
36
|
+
whiteSpace: 'break-spaces'
|
|
37
37
|
}
|
|
38
38
|
});
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
// Invisible container whose only job is to make Emotion inject CSS for all Token variants.
|
|
42
|
+
// renderToString produces correct class names but never triggers Emotion's DOM-side injection,
|
|
43
|
+
// so without this the class names exist in the HTML but have no matching CSS rules.
|
|
44
|
+
var HiddenCssPrimer = (0, _styles.styled)('div')(function () {
|
|
45
|
+
return {
|
|
46
|
+
display: 'none',
|
|
47
|
+
position: 'absolute',
|
|
48
|
+
visibility: 'hidden',
|
|
49
|
+
pointerEvents: 'none'
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
var normalizeCommonEntities = function normalizeCommonEntities() {
|
|
53
|
+
var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
54
|
+
return text.replace(/ /gi, "\xA0");
|
|
55
|
+
};
|
|
56
|
+
var normalizeSelectableText = function normalizeSelectableText() {
|
|
57
|
+
var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
58
|
+
return normalizeCommonEntities(text).replace(/<\/p>\s*<p[^>]*>/gi, '\n\n').replace(/<br\s*\/?>/gi, '\n').replace(/<\/?(table|tbody|tr|td|p)[^>]*>/gi, '');
|
|
47
59
|
};
|
|
48
60
|
var TokenSelect = exports.TokenSelect = /*#__PURE__*/function (_React$Component) {
|
|
49
61
|
function TokenSelect() {
|
|
@@ -113,65 +125,42 @@ var TokenSelect = exports.TokenSelect = /*#__PURE__*/function (_React$Component)
|
|
|
113
125
|
}
|
|
114
126
|
}
|
|
115
127
|
});
|
|
116
|
-
/**
|
|
117
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Build an HTML string so that non-selectable token text (which may contain arbitrary or even
|
|
130
|
+
* *partial* HTML — e.g. just an opening <table><tbody><tr><td> in one token and the matching
|
|
131
|
+
* closing tags in another) is preserved exactly as-is. Selectable Token components are
|
|
132
|
+
* serialised via renderToString; their Emotion class names are stable hashes so they match the
|
|
133
|
+
* CSS that the HiddenCssPrimer forces Emotion to inject into the document.
|
|
134
|
+
*/
|
|
135
|
+
(0, _defineProperty2["default"])(_this, "generateTokensInHtml", function () {
|
|
118
136
|
var _this$props3 = _this.props,
|
|
119
137
|
tokens = _this$props3.tokens,
|
|
120
138
|
disabled = _this$props3.disabled,
|
|
121
139
|
highlightChoices = _this$props3.highlightChoices,
|
|
122
140
|
animationsDisabled = _this$props3.animationsDisabled;
|
|
123
141
|
var selectedCount = _this.selectedCount();
|
|
124
|
-
var
|
|
125
|
-
return text === '\n';
|
|
126
|
-
};
|
|
127
|
-
var isNewParagraph = function isNewParagraph(text) {
|
|
128
|
-
return text === '\n\n';
|
|
129
|
-
};
|
|
130
|
-
var paragraphs = [];
|
|
131
|
-
var currentChildren = [];
|
|
132
|
-
var flushParagraph = function flushParagraph() {
|
|
133
|
-
// Always push a <p>, even if empty, to mirror previous behavior
|
|
134
|
-
paragraphs.push(/*#__PURE__*/_react["default"].createElement("p", {
|
|
135
|
-
key: "p-".concat(paragraphs.length)
|
|
136
|
-
}, currentChildren));
|
|
137
|
-
currentChildren = [];
|
|
138
|
-
};
|
|
139
|
-
(tokens || []).forEach(function (t, index) {
|
|
142
|
+
var reducer = function reducer(accumulator, t, index) {
|
|
140
143
|
var selectable = t.selected || t.selectable && _this.canSelectMore(selectedCount);
|
|
141
144
|
var showCorrectAnswer = t.correct !== undefined && (t.selectable || t.selected);
|
|
142
|
-
if (
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (isLineBreak(t.text)) {
|
|
147
|
-
currentChildren.push(/*#__PURE__*/_react["default"].createElement("br", {
|
|
148
|
-
key: "br-".concat(index)
|
|
149
|
-
}));
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
if (selectable && !disabled || showCorrectAnswer || t.selected || t.isMissing || animationsDisabled && t.predefined // print mode
|
|
153
|
-
) {
|
|
154
|
-
currentChildren.push(/*#__PURE__*/_react["default"].createElement(_token["default"], (0, _extends2["default"])({
|
|
145
|
+
if (t.text === '\n\n') return "".concat(accumulator, "</p><p>");
|
|
146
|
+
if (t.text === '\n') return "".concat(accumulator, "<br>");
|
|
147
|
+
if (selectable && !disabled || showCorrectAnswer || t.selected || t.isMissing || animationsDisabled && t.predefined) {
|
|
148
|
+
return accumulator + (0, _server.renderToString)(/*#__PURE__*/_react["default"].createElement(_token["default"], (0, _extends2["default"])({
|
|
155
149
|
key: index,
|
|
156
150
|
disabled: disabled,
|
|
157
151
|
index: index
|
|
158
152
|
}, t, {
|
|
159
|
-
text:
|
|
153
|
+
text: normalizeSelectableText(t.text),
|
|
160
154
|
selectable: selectable,
|
|
161
155
|
highlight: highlightChoices,
|
|
162
156
|
animationsDisabled: animationsDisabled
|
|
163
157
|
})));
|
|
164
|
-
} else {
|
|
165
|
-
// raw text node – React will escape as needed
|
|
166
|
-
currentChildren.push(/*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, {
|
|
167
|
-
key: index
|
|
168
|
-
}, stripHtmlTags(t.text)));
|
|
169
158
|
}
|
|
170
|
-
});
|
|
171
159
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
160
|
+
// Non-selectable: emit raw HTML unchanged (may contain partial tags, tables, lists, etc.)
|
|
161
|
+
return accumulator + normalizeCommonEntities(t.text);
|
|
162
|
+
};
|
|
163
|
+
return (tokens || []).reduce(reducer, '<p>') + '</p>';
|
|
175
164
|
});
|
|
176
165
|
return _this;
|
|
177
166
|
}
|
|
@@ -180,11 +169,83 @@ var TokenSelect = exports.TokenSelect = /*#__PURE__*/function (_React$Component)
|
|
|
180
169
|
key: "render",
|
|
181
170
|
value: function render() {
|
|
182
171
|
var classNameProp = this.props.className;
|
|
183
|
-
var
|
|
184
|
-
|
|
172
|
+
var html = this.generateTokensInHtml();
|
|
173
|
+
|
|
174
|
+
// Render one invisible Token per visual variant so Emotion injects all CSS rules into the
|
|
175
|
+
// document before the browser paints the dangerouslySetInnerHTML content.
|
|
176
|
+
var primerText = ' ';
|
|
177
|
+
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(HiddenCssPrimer, {
|
|
178
|
+
"aria-hidden": "true"
|
|
179
|
+
}, /*#__PURE__*/_react["default"].createElement(_token["default"], {
|
|
180
|
+
text: primerText,
|
|
181
|
+
index: -1,
|
|
182
|
+
selectable: true,
|
|
183
|
+
disabled: false,
|
|
184
|
+
highlight: false,
|
|
185
|
+
animationsDisabled: false
|
|
186
|
+
}), /*#__PURE__*/_react["default"].createElement(_token["default"], {
|
|
187
|
+
text: primerText,
|
|
188
|
+
index: -1,
|
|
189
|
+
selectable: true,
|
|
190
|
+
disabled: false,
|
|
191
|
+
highlight: true,
|
|
192
|
+
animationsDisabled: false
|
|
193
|
+
}), /*#__PURE__*/_react["default"].createElement(_token["default"], {
|
|
194
|
+
text: primerText,
|
|
195
|
+
index: -1,
|
|
196
|
+
selectable: true,
|
|
197
|
+
selected: true,
|
|
198
|
+
disabled: false,
|
|
199
|
+
highlight: false,
|
|
200
|
+
animationsDisabled: false
|
|
201
|
+
}), /*#__PURE__*/_react["default"].createElement(_token["default"], {
|
|
202
|
+
text: primerText,
|
|
203
|
+
index: -1,
|
|
204
|
+
selectable: true,
|
|
205
|
+
selected: true,
|
|
206
|
+
disabled: true,
|
|
207
|
+
highlight: false,
|
|
208
|
+
animationsDisabled: false
|
|
209
|
+
}), /*#__PURE__*/_react["default"].createElement(_token["default"], {
|
|
210
|
+
text: primerText,
|
|
211
|
+
index: -1,
|
|
212
|
+
selectable: true,
|
|
213
|
+
disabled: false,
|
|
214
|
+
highlight: false,
|
|
215
|
+
animationsDisabled: true,
|
|
216
|
+
predefined: true
|
|
217
|
+
}), /*#__PURE__*/_react["default"].createElement(_token["default"], {
|
|
218
|
+
text: primerText,
|
|
219
|
+
index: -1,
|
|
220
|
+
selectable: true,
|
|
221
|
+
selected: true,
|
|
222
|
+
correct: true,
|
|
223
|
+
disabled: false,
|
|
224
|
+
highlight: false,
|
|
225
|
+
animationsDisabled: false
|
|
226
|
+
}), /*#__PURE__*/_react["default"].createElement(_token["default"], {
|
|
227
|
+
text: primerText,
|
|
228
|
+
index: -1,
|
|
229
|
+
selectable: true,
|
|
230
|
+
selected: true,
|
|
231
|
+
correct: false,
|
|
232
|
+
disabled: false,
|
|
233
|
+
highlight: false,
|
|
234
|
+
animationsDisabled: false
|
|
235
|
+
}), /*#__PURE__*/_react["default"].createElement(_token["default"], {
|
|
236
|
+
text: primerText,
|
|
237
|
+
index: -1,
|
|
238
|
+
isMissing: true,
|
|
239
|
+
disabled: false,
|
|
240
|
+
highlight: false,
|
|
241
|
+
animationsDisabled: false
|
|
242
|
+
})), /*#__PURE__*/_react["default"].createElement(StyledTokenSelect, {
|
|
185
243
|
className: classNameProp,
|
|
186
|
-
onClick: this.toggleToken
|
|
187
|
-
|
|
244
|
+
onClick: this.toggleToken,
|
|
245
|
+
dangerouslySetInnerHTML: {
|
|
246
|
+
__html: html
|
|
247
|
+
}
|
|
248
|
+
}));
|
|
188
249
|
}
|
|
189
250
|
}]);
|
|
190
251
|
}(_react["default"].Component);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_react","_interopRequireDefault","require","_propTypes","_token","_interopRequireWildcard","_styles","_lodashEs","_debug","_styleUtils","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_callSuper","_getPrototypeOf2","_possibleConstructorReturn2","_isNativeReflectConstruct","Reflect","construct","constructor","apply","Boolean","prototype","valueOf","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","log","debug","StyledTokenSelect","styled","backgroundColor","whiteSpace","noSelect","margin","stripHtmlTags","text","replace","TokenSelect","exports","_React$Component","_this","_classCallCheck2","_len","args","Array","_key","concat","props","tokens","selected","selectedCount","maxNoOfSelections","isFinite","event","_target$closest","_targetSpanWrapper$da","target","_this$props","animationsDisabled","tokensCloned","clone","targetSpanWrapper","closest","Token","rootClassName","targetedTokenIndex","dataset","indexkey","undefined","correct","isMissing","_this$props2","onChange","selectedToken","tk","updatedTokens","map","token","isEqual","selectable","update","splice","_this$props3","disabled","highlightChoices","isLineBreak","isNewParagraph","paragraphs","currentChildren","flushParagraph","createElement","key","index","canSelectMore","showCorrectAnswer","predefined","_extends2","highlight","Fragment","_inherits2","_createClass2","value","render","classNameProp","className","nodes","generateTokensNodes","onClick","toggleToken","React","Component","PropTypes","arrayOf","shape","TokenTypes","isRequired","string","func","bool","number","_default"],"sources":["../../src/token-select/index.jsx"],"sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport Token, { TokenTypes } from './token';\nimport { styled } from '@mui/material/styles';\nimport { clone, isEqual } from 'lodash-es';\nimport debug from 'debug';\nimport { noSelect } from '@pie-lib/style-utils';\n\nconst log = debug('@pie-lib:text-select:token-select');\n\nconst StyledTokenSelect = styled('div')(() => ({\n backgroundColor: 'none',\n whiteSpace: 'pre',\n ...noSelect(),\n '& p': {\n whiteSpace: 'break-spaces',\n margin: 0,\n },\n}));\n\n// strip HTML tags for plain text rendering\nconst stripHtmlTags = (text) => {\n if (!text) {\n return text;\n }\n\n return text.replace(/<[^>]+>/g, '');\n};\n\nexport class TokenSelect extends React.Component {\n static propTypes = {\n tokens: PropTypes.arrayOf(PropTypes.shape(TokenTypes)).isRequired,\n className: PropTypes.string,\n onChange: PropTypes.func.isRequired,\n disabled: PropTypes.bool,\n highlightChoices: PropTypes.bool,\n animationsDisabled: PropTypes.bool,\n maxNoOfSelections: PropTypes.number,\n };\n\n static defaultProps = {\n highlightChoices: false,\n maxNoOfSelections: 0,\n tokens: [],\n };\n\n selectedCount = () => this.props.tokens.filter((t) => t.selected).length;\n\n canSelectMore = (selectedCount) => {\n const { maxNoOfSelections } = this.props;\n\n if (maxNoOfSelections === 1) return true;\n\n log('[canSelectMore] maxNoOfSelections: ', maxNoOfSelections, 'selectedCount: ', selectedCount);\n return maxNoOfSelections <= 0 || (isFinite(maxNoOfSelections) && selectedCount < maxNoOfSelections);\n };\n\n toggleToken = (event) => {\n const { target } = event;\n const { tokens, animationsDisabled } = this.props;\n const tokensCloned = clone(tokens);\n\n const targetSpanWrapper = target.closest?.(`.${Token.rootClassName}`);\n const targetedTokenIndex = targetSpanWrapper?.dataset?.indexkey;\n const t = targetedTokenIndex !== undefined ? tokensCloned[targetedTokenIndex] : undefined;\n\n // don't toggle if in print mode, correctness is defined, or is missing\n if (t && t.correct === undefined && !animationsDisabled && !t.isMissing) {\n const { onChange, maxNoOfSelections } = this.props;\n const selected = !t.selected;\n\n if (maxNoOfSelections === 1 && this.selectedCount() === 1) {\n const selectedToken = (tokens || []).filter((tk) => tk.selected);\n const updatedTokens = tokensCloned.map((token) => {\n if (isEqual(token, selectedToken[0])) {\n return { ...token, selected: false };\n }\n return { ...token, selectable: true };\n });\n\n const update = { ...t, selected };\n updatedTokens.splice(targetedTokenIndex, 1, update);\n onChange(updatedTokens);\n } else {\n if (selected && maxNoOfSelections > 0 && this.selectedCount() >= maxNoOfSelections) {\n log('skip toggle max reached');\n return;\n }\n const update = { ...t, selected };\n tokensCloned.splice(targetedTokenIndex, 1, update);\n onChange(tokensCloned);\n }\n }\n };\n\n /** Build a React tree instead of an HTML string so Emotion can inject CSS */\n generateTokensNodes = () => {\n const { tokens, disabled, highlightChoices, animationsDisabled } = this.props;\n const selectedCount = this.selectedCount();\n\n const isLineBreak = (text) => text === '\\n';\n const isNewParagraph = (text) => text === '\\n\\n';\n\n const paragraphs = [];\n let currentChildren = [];\n\n const flushParagraph = () => {\n // Always push a <p>, even if empty, to mirror previous behavior\n paragraphs.push(<p key={`p-${paragraphs.length}`}>{currentChildren}</p>);\n currentChildren = [];\n };\n\n (tokens || []).forEach((t, index) => {\n const selectable = t.selected || (t.selectable && this.canSelectMore(selectedCount));\n const showCorrectAnswer = t.correct !== undefined && (t.selectable || t.selected);\n\n if (isNewParagraph(t.text)) {\n flushParagraph();\n return;\n }\n\n if (isLineBreak(t.text)) {\n currentChildren.push(<br key={`br-${index}`} />);\n return;\n }\n\n if (\n (selectable && !disabled) ||\n showCorrectAnswer ||\n t.selected ||\n t.isMissing ||\n (animationsDisabled && t.predefined) // print mode\n ) {\n currentChildren.push(\n <Token\n key={index}\n disabled={disabled}\n index={index}\n {...t}\n text={stripHtmlTags(t.text)}\n selectable={selectable}\n highlight={highlightChoices}\n animationsDisabled={animationsDisabled}\n />,\n );\n } else {\n // raw text node – React will escape as needed\n currentChildren.push(<React.Fragment key={index}>{stripHtmlTags(t.text)}</React.Fragment>);\n }\n });\n\n // flush last paragraph\n flushParagraph();\n\n return paragraphs;\n };\n\n render() {\n const { className: classNameProp } = this.props;\n const nodes = this.generateTokensNodes();\n\n return (\n <StyledTokenSelect className={classNameProp} onClick={this.toggleToken}>\n {nodes}\n </StyledTokenSelect>\n );\n }\n}\n\nexport default TokenSelect;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["_react","_interopRequireDefault","require","_server","_propTypes","_token","_interopRequireWildcard","_styles","_lodashEs","_debug","_styleUtils","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","_typeof","has","get","set","_t","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_callSuper","_getPrototypeOf2","_possibleConstructorReturn2","_isNativeReflectConstruct","Reflect","construct","constructor","apply","Boolean","prototype","valueOf","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","_objectSpread","arguments","length","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","log","debug","StyledTokenSelect","styled","backgroundColor","whiteSpace","noSelect","HiddenCssPrimer","display","position","visibility","pointerEvents","normalizeCommonEntities","text","undefined","replace","normalizeSelectableText","TokenSelect","exports","_React$Component","_this","_classCallCheck2","_len","args","Array","_key","concat","props","tokens","selected","selectedCount","maxNoOfSelections","isFinite","event","_target$closest","_targetSpanWrapper$da","target","_this$props","animationsDisabled","tokensCloned","clone","targetSpanWrapper","closest","Token","rootClassName","targetedTokenIndex","dataset","indexkey","correct","isMissing","_this$props2","onChange","selectedToken","tk","updatedTokens","map","token","isEqual","selectable","update","splice","_this$props3","disabled","highlightChoices","reducer","accumulator","index","canSelectMore","showCorrectAnswer","predefined","renderToString","createElement","_extends2","key","highlight","reduce","_inherits2","_createClass2","value","render","classNameProp","className","html","generateTokensInHtml","primerText","Fragment","onClick","toggleToken","dangerouslySetInnerHTML","__html","React","Component","PropTypes","arrayOf","shape","TokenTypes","isRequired","string","func","bool","number","_default"],"sources":["../../src/token-select/index.jsx"],"sourcesContent":["import React from 'react';\nimport { renderToString } from 'react-dom/server';\nimport PropTypes from 'prop-types';\nimport Token, { TokenTypes } from './token';\nimport { styled } from '@mui/material/styles';\nimport { clone, isEqual } from 'lodash-es';\nimport debug from 'debug';\nimport { noSelect } from '@pie-lib/style-utils';\n\nconst log = debug('@pie-lib:text-select:token-select');\n\nconst StyledTokenSelect = styled('div')(() => ({\n backgroundColor: 'none',\n whiteSpace: 'pre',\n ...noSelect(),\n '& p': {\n whiteSpace: 'break-spaces',\n },\n}));\n\n// Invisible container whose only job is to make Emotion inject CSS for all Token variants.\n// renderToString produces correct class names but never triggers Emotion's DOM-side injection,\n// so without this the class names exist in the HTML but have no matching CSS rules.\nconst HiddenCssPrimer = styled('div')(() => ({\n display: 'none',\n position: 'absolute',\n visibility: 'hidden',\n pointerEvents: 'none',\n}));\n\nconst normalizeCommonEntities = (text = '') => text.replace(/ /gi, '\\u00a0');\n\nconst normalizeSelectableText = (text = '') =>\n normalizeCommonEntities(text)\n .replace(/<\\/p>\\s*<p[^>]*>/gi, '\\n\\n')\n .replace(/<br\\s*\\/?>/gi, '\\n')\n .replace(/<\\/?(table|tbody|tr|td|p)[^>]*>/gi, '');\n\nexport class TokenSelect extends React.Component {\n static propTypes = {\n tokens: PropTypes.arrayOf(PropTypes.shape(TokenTypes)).isRequired,\n className: PropTypes.string,\n onChange: PropTypes.func.isRequired,\n disabled: PropTypes.bool,\n highlightChoices: PropTypes.bool,\n animationsDisabled: PropTypes.bool,\n maxNoOfSelections: PropTypes.number,\n };\n\n static defaultProps = {\n highlightChoices: false,\n maxNoOfSelections: 0,\n tokens: [],\n };\n\n selectedCount = () => this.props.tokens.filter((t) => t.selected).length;\n\n canSelectMore = (selectedCount) => {\n const { maxNoOfSelections } = this.props;\n\n if (maxNoOfSelections === 1) return true;\n\n log('[canSelectMore] maxNoOfSelections: ', maxNoOfSelections, 'selectedCount: ', selectedCount);\n return maxNoOfSelections <= 0 || (isFinite(maxNoOfSelections) && selectedCount < maxNoOfSelections);\n };\n\n toggleToken = (event) => {\n const { target } = event;\n const { tokens, animationsDisabled } = this.props;\n const tokensCloned = clone(tokens);\n\n const targetSpanWrapper = target.closest?.(`.${Token.rootClassName}`);\n const targetedTokenIndex = targetSpanWrapper?.dataset?.indexkey;\n const t = targetedTokenIndex !== undefined ? tokensCloned[targetedTokenIndex] : undefined;\n\n // don't toggle if in print mode, correctness is defined, or is missing\n if (t && t.correct === undefined && !animationsDisabled && !t.isMissing) {\n const { onChange, maxNoOfSelections } = this.props;\n const selected = !t.selected;\n\n if (maxNoOfSelections === 1 && this.selectedCount() === 1) {\n const selectedToken = (tokens || []).filter((tk) => tk.selected);\n const updatedTokens = tokensCloned.map((token) => {\n if (isEqual(token, selectedToken[0])) {\n return { ...token, selected: false };\n }\n return { ...token, selectable: true };\n });\n\n const update = { ...t, selected };\n updatedTokens.splice(targetedTokenIndex, 1, update);\n onChange(updatedTokens);\n } else {\n if (selected && maxNoOfSelections > 0 && this.selectedCount() >= maxNoOfSelections) {\n log('skip toggle max reached');\n return;\n }\n const update = { ...t, selected };\n tokensCloned.splice(targetedTokenIndex, 1, update);\n onChange(tokensCloned);\n }\n }\n };\n\n /**\n * Build an HTML string so that non-selectable token text (which may contain arbitrary or even\n * *partial* HTML — e.g. just an opening <table><tbody><tr><td> in one token and the matching\n * closing tags in another) is preserved exactly as-is. Selectable Token components are\n * serialised via renderToString; their Emotion class names are stable hashes so they match the\n * CSS that the HiddenCssPrimer forces Emotion to inject into the document.\n */\n generateTokensInHtml = () => {\n const { tokens, disabled, highlightChoices, animationsDisabled } = this.props;\n const selectedCount = this.selectedCount();\n\n const reducer = (accumulator, t, index) => {\n const selectable = t.selected || (t.selectable && this.canSelectMore(selectedCount));\n const showCorrectAnswer = t.correct !== undefined && (t.selectable || t.selected);\n\n if (t.text === '\\n\\n') return `${accumulator}</p><p>`;\n\n if (t.text === '\\n') return `${accumulator}<br>`;\n\n if (\n (selectable && !disabled) ||\n showCorrectAnswer ||\n t.selected ||\n t.isMissing ||\n (animationsDisabled && t.predefined)\n ) {\n return (\n accumulator +\n renderToString(\n <Token\n key={index}\n disabled={disabled}\n index={index}\n {...t}\n text={normalizeSelectableText(t.text)}\n selectable={selectable}\n highlight={highlightChoices}\n animationsDisabled={animationsDisabled}\n />,\n )\n );\n }\n\n // Non-selectable: emit raw HTML unchanged (may contain partial tags, tables, lists, etc.)\n return accumulator + normalizeCommonEntities(t.text);\n };\n\n return (tokens || []).reduce(reducer, '<p>') + '</p>';\n };\n\n render() {\n const { className: classNameProp } = this.props;\n const html = this.generateTokensInHtml();\n\n // Render one invisible Token per visual variant so Emotion injects all CSS rules into the\n // document before the browser paints the dangerouslySetInnerHTML content.\n const primerText = ' ';\n return (\n <>\n <HiddenCssPrimer aria-hidden=\"true\">\n {/* base / selectable */}\n <Token\n text={primerText}\n index={-1}\n selectable\n disabled={false}\n highlight={false}\n animationsDisabled={false}\n />\n {/* highlight */}\n <Token text={primerText} index={-1} selectable disabled={false} highlight animationsDisabled={false} />\n {/* selected */}\n <Token\n text={primerText}\n index={-1}\n selectable\n selected\n disabled={false}\n highlight={false}\n animationsDisabled={false}\n />\n {/* disabled + selected */}\n <Token\n text={primerText}\n index={-1}\n selectable\n selected\n disabled\n highlight={false}\n animationsDisabled={false}\n />\n {/* print / animationsDisabled */}\n <Token\n text={primerText}\n index={-1}\n selectable\n disabled={false}\n highlight={false}\n animationsDisabled\n predefined\n />\n {/* correct */}\n <Token\n text={primerText}\n index={-1}\n selectable\n selected\n correct\n disabled={false}\n highlight={false}\n animationsDisabled={false}\n />\n {/* incorrect */}\n <Token\n text={primerText}\n index={-1}\n selectable\n selected\n correct={false}\n disabled={false}\n highlight={false}\n animationsDisabled={false}\n />\n {/* missing */}\n <Token text={primerText} index={-1} isMissing disabled={false} highlight={false} animationsDisabled={false} />\n </HiddenCssPrimer>\n\n <StyledTokenSelect\n className={classNameProp}\n onClick={this.toggleToken}\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </>\n );\n }\n}\n\nexport default TokenSelect;\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": "
|
|
6
|
+
"version": "3.0.0",
|
|
7
7
|
"description": "Some react components for text selection",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"react",
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
"@mui/icons-material": "^7.3.4",
|
|
23
23
|
"@mui/material": "^7.3.4",
|
|
24
24
|
"@pie-framework/parse-english": "^1.0.0",
|
|
25
|
-
"@pie-lib/render-ui": "^
|
|
26
|
-
"@pie-lib/style-utils": "^
|
|
27
|
-
"@pie-lib/translator": "^
|
|
25
|
+
"@pie-lib/render-ui": "^6.0.0",
|
|
26
|
+
"@pie-lib/style-utils": "^2.0.0",
|
|
27
|
+
"@pie-lib/translator": "^4.0.0",
|
|
28
28
|
"classnames": "^2.2.6",
|
|
29
29
|
"debug": "^4.1.1",
|
|
30
30
|
"lodash-es": "^4.17.23",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@pie-framework/parse-english": "^1.0.0",
|
|
35
|
-
"@pie-lib/test-utils": "^
|
|
35
|
+
"@pie-lib/test-utils": "^2.0.0",
|
|
36
36
|
"natural": "^0.6.3",
|
|
37
37
|
"react": "^18.2.0",
|
|
38
38
|
"react-dom": "^18.2.0"
|
|
@@ -40,6 +40,6 @@
|
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"react": "^18.2.0"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "bf0904ba8bdd2d6f88fb8ad99060e45e40180348",
|
|
44
44
|
"scripts": {}
|
|
45
45
|
}
|
|
@@ -14,7 +14,6 @@ describe('token-select', () => {
|
|
|
14
14
|
selected: false,
|
|
15
15
|
},
|
|
16
16
|
],
|
|
17
|
-
classes: {},
|
|
18
17
|
onChange: jest.fn(),
|
|
19
18
|
};
|
|
20
19
|
|
|
@@ -134,12 +133,18 @@ describe('token-select', () => {
|
|
|
134
133
|
];
|
|
135
134
|
const { container } = render(<TokenSelect {...defaultProps} tokens={tokens} />);
|
|
136
135
|
expect(container.textContent).toContain('bold text');
|
|
137
|
-
|
|
136
|
+
// The selectable token should have HTML tags stripped before rendering
|
|
137
|
+
// Look specifically in the main content div (not the hidden primer)
|
|
138
|
+
const mainDiv = container.querySelectorAll('div[class*="css-"]')[1];
|
|
139
|
+
expect(mainDiv.textContent).toContain('bold text');
|
|
138
140
|
});
|
|
139
141
|
|
|
140
142
|
it('renders with custom className', () => {
|
|
141
143
|
const { container } = render(<TokenSelect {...defaultProps} className="custom-token-select" />);
|
|
142
|
-
|
|
144
|
+
// The second div with Emotion class should have the custom className
|
|
145
|
+
const styledDivs = container.querySelectorAll('div[class*="css-"]');
|
|
146
|
+
const mainDiv = styledDivs[styledDivs.length - 1];
|
|
147
|
+
expect(mainDiv).toHaveClass('custom-token-select');
|
|
143
148
|
});
|
|
144
149
|
|
|
145
150
|
it('renders tokens with correct and incorrect states', () => {
|
|
@@ -205,7 +210,15 @@ describe('token-select', () => {
|
|
|
205
210
|
];
|
|
206
211
|
const { container } = render(<TokenSelect {...defaultProps} tokens={tokens} onChange={onChange} />);
|
|
207
212
|
|
|
208
|
-
const
|
|
213
|
+
const tokenElements = container.querySelectorAll('.tokenRootClass');
|
|
214
|
+
// Find the first token with data-indexkey >= 0 (skip primer tokens at -1)
|
|
215
|
+
let tokenElement = null;
|
|
216
|
+
for (const el of tokenElements) {
|
|
217
|
+
if (parseInt(el.getAttribute('data-indexkey'), 10) >= 0) {
|
|
218
|
+
tokenElement = el;
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
209
222
|
if (tokenElement) {
|
|
210
223
|
fireEvent.click(tokenElement);
|
|
211
224
|
expect(onChange).toHaveBeenCalled();
|
|
@@ -239,8 +252,12 @@ describe('token-select', () => {
|
|
|
239
252
|
);
|
|
240
253
|
|
|
241
254
|
const tokenElements = container.querySelectorAll('.tokenRootClass');
|
|
242
|
-
|
|
243
|
-
|
|
255
|
+
// Find tokens with data-indexkey >= 0 (skip primer tokens)
|
|
256
|
+
const realTokens = Array.from(tokenElements).filter(
|
|
257
|
+
(el) => parseInt(el.getAttribute('data-indexkey'), 10) >= 0,
|
|
258
|
+
);
|
|
259
|
+
if (realTokens.length > 1) {
|
|
260
|
+
fireEvent.click(realTokens[1]);
|
|
244
261
|
expect(onChange).toHaveBeenCalled();
|
|
245
262
|
const updatedTokens = onChange.mock.calls[0][0];
|
|
246
263
|
expect(updatedTokens[0].selected).toBe(false);
|
|
@@ -281,8 +298,11 @@ describe('token-select', () => {
|
|
|
281
298
|
);
|
|
282
299
|
|
|
283
300
|
const tokenElements = container.querySelectorAll('.tokenRootClass');
|
|
284
|
-
|
|
285
|
-
|
|
301
|
+
const realTokens = Array.from(tokenElements).filter(
|
|
302
|
+
(el) => parseInt(el.getAttribute('data-indexkey'), 10) >= 0,
|
|
303
|
+
);
|
|
304
|
+
if (realTokens.length > 2) {
|
|
305
|
+
fireEvent.click(realTokens[2]);
|
|
286
306
|
// onChange should not be called because max is reached
|
|
287
307
|
expect(onChange).not.toHaveBeenCalled();
|
|
288
308
|
}
|
|
@@ -369,7 +389,14 @@ describe('token-select', () => {
|
|
|
369
389
|
];
|
|
370
390
|
const { container } = render(<TokenSelect {...defaultProps} tokens={tokens} onChange={onChange} />);
|
|
371
391
|
|
|
372
|
-
const
|
|
392
|
+
const tokenElements = container.querySelectorAll('.tokenRootClass');
|
|
393
|
+
let tokenElement = null;
|
|
394
|
+
for (const el of tokenElements) {
|
|
395
|
+
if (parseInt(el.getAttribute('data-indexkey'), 10) >= 0) {
|
|
396
|
+
tokenElement = el;
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
373
400
|
if (tokenElement) {
|
|
374
401
|
fireEvent.click(tokenElement);
|
|
375
402
|
expect(onChange).toHaveBeenCalled();
|
|
@@ -379,6 +406,215 @@ describe('token-select', () => {
|
|
|
379
406
|
});
|
|
380
407
|
});
|
|
381
408
|
|
|
409
|
+
describe('CSS injection and styling', () => {
|
|
410
|
+
it('renders HiddenCssPrimer to inject CSS for all Token variants', () => {
|
|
411
|
+
const { container } = render(<TokenSelect {...defaultProps} />);
|
|
412
|
+
// Check that the component renders without errors; the HiddenCssPrimer
|
|
413
|
+
// ensures CSS is injected into the document for all token states.
|
|
414
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
415
|
+
// The HiddenCssPrimer should have aria-hidden to mark it as invisible
|
|
416
|
+
const primer = container.querySelector('[aria-hidden="true"]');
|
|
417
|
+
expect(primer).toBeInTheDocument();
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('renders tokens with Emotion CSS class names', () => {
|
|
421
|
+
const { container } = render(<TokenSelect {...defaultProps} />);
|
|
422
|
+
const tokenElement = container.querySelector('.tokenRootClass');
|
|
423
|
+
expect(tokenElement).toBeInTheDocument();
|
|
424
|
+
// Should have Emotion-generated class name like css-xxxxx
|
|
425
|
+
const hasEmotionClass = Array.from(tokenElement.classList).some((cls) => cls.startsWith('css-'));
|
|
426
|
+
expect(hasEmotionClass).toBe(true);
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
describe('HTML preservation', () => {
|
|
431
|
+
it('preserves non-selectable HTML content', () => {
|
|
432
|
+
const tokens = [
|
|
433
|
+
{
|
|
434
|
+
text: '<table><tr><td>table content</td></tr></table>',
|
|
435
|
+
start: 0,
|
|
436
|
+
end: 46,
|
|
437
|
+
predefined: false,
|
|
438
|
+
selectable: false,
|
|
439
|
+
selected: false,
|
|
440
|
+
},
|
|
441
|
+
];
|
|
442
|
+
const { container } = render(<TokenSelect {...defaultProps} tokens={tokens} />);
|
|
443
|
+
// Non-selectable HTML should be rendered as-is
|
|
444
|
+
const html = container.innerHTML;
|
|
445
|
+
expect(html).toContain('table');
|
|
446
|
+
expect(html).toContain('table content');
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it('preserves non-breaking spaces in HTML', () => {
|
|
450
|
+
const tokens = [
|
|
451
|
+
{
|
|
452
|
+
text: 'word space',
|
|
453
|
+
start: 0,
|
|
454
|
+
end: 14,
|
|
455
|
+
predefined: false,
|
|
456
|
+
selectable: false,
|
|
457
|
+
selected: false,
|
|
458
|
+
},
|
|
459
|
+
];
|
|
460
|
+
const { container } = render(<TokenSelect {...defaultProps} tokens={tokens} />);
|
|
461
|
+
// should be converted to non-breaking space character
|
|
462
|
+
expect(container.textContent).toContain('word');
|
|
463
|
+
expect(container.textContent).toContain('space');
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
it('handles mixed selectable and non-selectable tokens', () => {
|
|
467
|
+
const tokens = [
|
|
468
|
+
{
|
|
469
|
+
text: 'prefix ',
|
|
470
|
+
start: 0,
|
|
471
|
+
end: 7,
|
|
472
|
+
predefined: false,
|
|
473
|
+
selectable: false,
|
|
474
|
+
selected: false,
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
text: 'selectable token',
|
|
478
|
+
start: 7,
|
|
479
|
+
end: 22,
|
|
480
|
+
predefined: true,
|
|
481
|
+
selectable: true,
|
|
482
|
+
selected: false,
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
text: ' suffix',
|
|
486
|
+
start: 22,
|
|
487
|
+
end: 29,
|
|
488
|
+
predefined: false,
|
|
489
|
+
selectable: false,
|
|
490
|
+
selected: false,
|
|
491
|
+
},
|
|
492
|
+
];
|
|
493
|
+
const { container } = render(<TokenSelect {...defaultProps} tokens={tokens} />);
|
|
494
|
+
expect(container.textContent).toContain('prefix');
|
|
495
|
+
expect(container.textContent).toContain('selectable token');
|
|
496
|
+
expect(container.textContent).toContain('suffix');
|
|
497
|
+
});
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
describe('newline handling', () => {
|
|
501
|
+
it('renders single newlines as <br> tags', () => {
|
|
502
|
+
const tokens = [
|
|
503
|
+
{
|
|
504
|
+
text: 'line1',
|
|
505
|
+
start: 0,
|
|
506
|
+
end: 5,
|
|
507
|
+
predefined: true,
|
|
508
|
+
selectable: true,
|
|
509
|
+
selected: false,
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
text: '\n',
|
|
513
|
+
start: 5,
|
|
514
|
+
end: 6,
|
|
515
|
+
selected: false,
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
text: 'line2',
|
|
519
|
+
start: 6,
|
|
520
|
+
end: 11,
|
|
521
|
+
predefined: true,
|
|
522
|
+
selectable: true,
|
|
523
|
+
selected: false,
|
|
524
|
+
},
|
|
525
|
+
];
|
|
526
|
+
const { container } = render(<TokenSelect {...defaultProps} tokens={tokens} />);
|
|
527
|
+
const html = container.innerHTML;
|
|
528
|
+
expect(html).toContain('<br>');
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
it('renders double newlines as paragraph breaks', () => {
|
|
532
|
+
const tokens = [
|
|
533
|
+
{
|
|
534
|
+
text: 'paragraph1',
|
|
535
|
+
start: 0,
|
|
536
|
+
end: 10,
|
|
537
|
+
predefined: true,
|
|
538
|
+
selectable: true,
|
|
539
|
+
selected: false,
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
text: '\n\n',
|
|
543
|
+
start: 10,
|
|
544
|
+
end: 12,
|
|
545
|
+
selected: false,
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
text: 'paragraph2',
|
|
549
|
+
start: 12,
|
|
550
|
+
end: 22,
|
|
551
|
+
predefined: true,
|
|
552
|
+
selectable: true,
|
|
553
|
+
selected: false,
|
|
554
|
+
},
|
|
555
|
+
];
|
|
556
|
+
const { container } = render(<TokenSelect {...defaultProps} tokens={tokens} />);
|
|
557
|
+
const html = container.innerHTML;
|
|
558
|
+
expect(html).toContain('</p>');
|
|
559
|
+
expect(html).toContain('<p>');
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
describe('edge cases', () => {
|
|
564
|
+
it('handles empty token list', () => {
|
|
565
|
+
const { container } = render(<TokenSelect {...defaultProps} tokens={[]} />);
|
|
566
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
it('handles tokens with special characters', () => {
|
|
570
|
+
const tokens = [
|
|
571
|
+
{
|
|
572
|
+
text: 'special & < > " chars',
|
|
573
|
+
start: 0,
|
|
574
|
+
end: 21,
|
|
575
|
+
predefined: true,
|
|
576
|
+
selectable: true,
|
|
577
|
+
selected: false,
|
|
578
|
+
},
|
|
579
|
+
];
|
|
580
|
+
const { container } = render(<TokenSelect {...defaultProps} tokens={tokens} />);
|
|
581
|
+
expect(container.textContent).toContain('special');
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
it('renders with disabled and highlightChoices together', () => {
|
|
585
|
+
const tokens = [
|
|
586
|
+
{
|
|
587
|
+
text: 'token',
|
|
588
|
+
start: 0,
|
|
589
|
+
end: 5,
|
|
590
|
+
predefined: true,
|
|
591
|
+
selectable: true,
|
|
592
|
+
selected: false,
|
|
593
|
+
},
|
|
594
|
+
];
|
|
595
|
+
const { container } = render(
|
|
596
|
+
<TokenSelect {...defaultProps} tokens={tokens} disabled highlightChoices />,
|
|
597
|
+
);
|
|
598
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
it('handles very long token text', () => {
|
|
602
|
+
const longText = 'Lorem ipsum '.repeat(100);
|
|
603
|
+
const tokens = [
|
|
604
|
+
{
|
|
605
|
+
text: longText,
|
|
606
|
+
start: 0,
|
|
607
|
+
end: longText.length,
|
|
608
|
+
predefined: true,
|
|
609
|
+
selectable: true,
|
|
610
|
+
selected: false,
|
|
611
|
+
},
|
|
612
|
+
];
|
|
613
|
+
const { container } = render(<TokenSelect {...defaultProps} tokens={tokens} />);
|
|
614
|
+
expect(container.textContent).toContain('Lorem ipsum');
|
|
615
|
+
});
|
|
616
|
+
});
|
|
617
|
+
|
|
382
618
|
// Note: Tests for internal methods (selectedCount, canSelectMore, toggleToken) are
|
|
383
619
|
// implementation details and cannot be directly tested with RTL. The original tests
|
|
384
620
|
// used wrapper.instance() to test these methods, which tests implementation rather
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { renderToString } from 'react-dom/server';
|
|
2
3
|
import PropTypes from 'prop-types';
|
|
3
4
|
import Token, { TokenTypes } from './token';
|
|
4
5
|
import { styled } from '@mui/material/styles';
|
|
@@ -14,18 +15,26 @@ const StyledTokenSelect = styled('div')(() => ({
|
|
|
14
15
|
...noSelect(),
|
|
15
16
|
'& p': {
|
|
16
17
|
whiteSpace: 'break-spaces',
|
|
17
|
-
margin: 0,
|
|
18
18
|
},
|
|
19
19
|
}));
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
// Invisible container whose only job is to make Emotion inject CSS for all Token variants.
|
|
22
|
+
// renderToString produces correct class names but never triggers Emotion's DOM-side injection,
|
|
23
|
+
// so without this the class names exist in the HTML but have no matching CSS rules.
|
|
24
|
+
const HiddenCssPrimer = styled('div')(() => ({
|
|
25
|
+
display: 'none',
|
|
26
|
+
position: 'absolute',
|
|
27
|
+
visibility: 'hidden',
|
|
28
|
+
pointerEvents: 'none',
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
const normalizeCommonEntities = (text = '') => text.replace(/ /gi, '\u00a0');
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
const normalizeSelectableText = (text = '') =>
|
|
34
|
+
normalizeCommonEntities(text)
|
|
35
|
+
.replace(/<\/p>\s*<p[^>]*>/gi, '\n\n')
|
|
36
|
+
.replace(/<br\s*\/?>/gi, '\n')
|
|
37
|
+
.replace(/<\/?(table|tbody|tr|td|p)[^>]*>/gi, '');
|
|
29
38
|
|
|
30
39
|
export class TokenSelect extends React.Component {
|
|
31
40
|
static propTypes = {
|
|
@@ -93,76 +102,139 @@ export class TokenSelect extends React.Component {
|
|
|
93
102
|
}
|
|
94
103
|
};
|
|
95
104
|
|
|
96
|
-
/**
|
|
97
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Build an HTML string so that non-selectable token text (which may contain arbitrary or even
|
|
107
|
+
* *partial* HTML — e.g. just an opening <table><tbody><tr><td> in one token and the matching
|
|
108
|
+
* closing tags in another) is preserved exactly as-is. Selectable Token components are
|
|
109
|
+
* serialised via renderToString; their Emotion class names are stable hashes so they match the
|
|
110
|
+
* CSS that the HiddenCssPrimer forces Emotion to inject into the document.
|
|
111
|
+
*/
|
|
112
|
+
generateTokensInHtml = () => {
|
|
98
113
|
const { tokens, disabled, highlightChoices, animationsDisabled } = this.props;
|
|
99
114
|
const selectedCount = this.selectedCount();
|
|
100
115
|
|
|
101
|
-
const
|
|
102
|
-
const isNewParagraph = (text) => text === '\n\n';
|
|
103
|
-
|
|
104
|
-
const paragraphs = [];
|
|
105
|
-
let currentChildren = [];
|
|
106
|
-
|
|
107
|
-
const flushParagraph = () => {
|
|
108
|
-
// Always push a <p>, even if empty, to mirror previous behavior
|
|
109
|
-
paragraphs.push(<p key={`p-${paragraphs.length}`}>{currentChildren}</p>);
|
|
110
|
-
currentChildren = [];
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
(tokens || []).forEach((t, index) => {
|
|
116
|
+
const reducer = (accumulator, t, index) => {
|
|
114
117
|
const selectable = t.selected || (t.selectable && this.canSelectMore(selectedCount));
|
|
115
118
|
const showCorrectAnswer = t.correct !== undefined && (t.selectable || t.selected);
|
|
116
119
|
|
|
117
|
-
if (
|
|
118
|
-
flushParagraph();
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
120
|
+
if (t.text === '\n\n') return `${accumulator}</p><p>`;
|
|
121
121
|
|
|
122
|
-
if (
|
|
123
|
-
currentChildren.push(<br key={`br-${index}`} />);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
122
|
+
if (t.text === '\n') return `${accumulator}<br>`;
|
|
126
123
|
|
|
127
124
|
if (
|
|
128
125
|
(selectable && !disabled) ||
|
|
129
126
|
showCorrectAnswer ||
|
|
130
127
|
t.selected ||
|
|
131
128
|
t.isMissing ||
|
|
132
|
-
(animationsDisabled && t.predefined)
|
|
129
|
+
(animationsDisabled && t.predefined)
|
|
133
130
|
) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
131
|
+
return (
|
|
132
|
+
accumulator +
|
|
133
|
+
renderToString(
|
|
134
|
+
<Token
|
|
135
|
+
key={index}
|
|
136
|
+
disabled={disabled}
|
|
137
|
+
index={index}
|
|
138
|
+
{...t}
|
|
139
|
+
text={normalizeSelectableText(t.text)}
|
|
140
|
+
selectable={selectable}
|
|
141
|
+
highlight={highlightChoices}
|
|
142
|
+
animationsDisabled={animationsDisabled}
|
|
143
|
+
/>,
|
|
144
|
+
)
|
|
145
145
|
);
|
|
146
|
-
} else {
|
|
147
|
-
// raw text node – React will escape as needed
|
|
148
|
-
currentChildren.push(<React.Fragment key={index}>{stripHtmlTags(t.text)}</React.Fragment>);
|
|
149
146
|
}
|
|
150
|
-
});
|
|
151
147
|
|
|
152
|
-
|
|
153
|
-
|
|
148
|
+
// Non-selectable: emit raw HTML unchanged (may contain partial tags, tables, lists, etc.)
|
|
149
|
+
return accumulator + normalizeCommonEntities(t.text);
|
|
150
|
+
};
|
|
154
151
|
|
|
155
|
-
return
|
|
152
|
+
return (tokens || []).reduce(reducer, '<p>') + '</p>';
|
|
156
153
|
};
|
|
157
154
|
|
|
158
155
|
render() {
|
|
159
156
|
const { className: classNameProp } = this.props;
|
|
160
|
-
const
|
|
157
|
+
const html = this.generateTokensInHtml();
|
|
161
158
|
|
|
159
|
+
// Render one invisible Token per visual variant so Emotion injects all CSS rules into the
|
|
160
|
+
// document before the browser paints the dangerouslySetInnerHTML content.
|
|
161
|
+
const primerText = ' ';
|
|
162
162
|
return (
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
163
|
+
<>
|
|
164
|
+
<HiddenCssPrimer aria-hidden="true">
|
|
165
|
+
{/* base / selectable */}
|
|
166
|
+
<Token
|
|
167
|
+
text={primerText}
|
|
168
|
+
index={-1}
|
|
169
|
+
selectable
|
|
170
|
+
disabled={false}
|
|
171
|
+
highlight={false}
|
|
172
|
+
animationsDisabled={false}
|
|
173
|
+
/>
|
|
174
|
+
{/* highlight */}
|
|
175
|
+
<Token text={primerText} index={-1} selectable disabled={false} highlight animationsDisabled={false} />
|
|
176
|
+
{/* selected */}
|
|
177
|
+
<Token
|
|
178
|
+
text={primerText}
|
|
179
|
+
index={-1}
|
|
180
|
+
selectable
|
|
181
|
+
selected
|
|
182
|
+
disabled={false}
|
|
183
|
+
highlight={false}
|
|
184
|
+
animationsDisabled={false}
|
|
185
|
+
/>
|
|
186
|
+
{/* disabled + selected */}
|
|
187
|
+
<Token
|
|
188
|
+
text={primerText}
|
|
189
|
+
index={-1}
|
|
190
|
+
selectable
|
|
191
|
+
selected
|
|
192
|
+
disabled
|
|
193
|
+
highlight={false}
|
|
194
|
+
animationsDisabled={false}
|
|
195
|
+
/>
|
|
196
|
+
{/* print / animationsDisabled */}
|
|
197
|
+
<Token
|
|
198
|
+
text={primerText}
|
|
199
|
+
index={-1}
|
|
200
|
+
selectable
|
|
201
|
+
disabled={false}
|
|
202
|
+
highlight={false}
|
|
203
|
+
animationsDisabled
|
|
204
|
+
predefined
|
|
205
|
+
/>
|
|
206
|
+
{/* correct */}
|
|
207
|
+
<Token
|
|
208
|
+
text={primerText}
|
|
209
|
+
index={-1}
|
|
210
|
+
selectable
|
|
211
|
+
selected
|
|
212
|
+
correct
|
|
213
|
+
disabled={false}
|
|
214
|
+
highlight={false}
|
|
215
|
+
animationsDisabled={false}
|
|
216
|
+
/>
|
|
217
|
+
{/* incorrect */}
|
|
218
|
+
<Token
|
|
219
|
+
text={primerText}
|
|
220
|
+
index={-1}
|
|
221
|
+
selectable
|
|
222
|
+
selected
|
|
223
|
+
correct={false}
|
|
224
|
+
disabled={false}
|
|
225
|
+
highlight={false}
|
|
226
|
+
animationsDisabled={false}
|
|
227
|
+
/>
|
|
228
|
+
{/* missing */}
|
|
229
|
+
<Token text={primerText} index={-1} isMissing disabled={false} highlight={false} animationsDisabled={false} />
|
|
230
|
+
</HiddenCssPrimer>
|
|
231
|
+
|
|
232
|
+
<StyledTokenSelect
|
|
233
|
+
className={classNameProp}
|
|
234
|
+
onClick={this.toggleToken}
|
|
235
|
+
dangerouslySetInnerHTML={{ __html: html }}
|
|
236
|
+
/>
|
|
237
|
+
</>
|
|
166
238
|
);
|
|
167
239
|
}
|
|
168
240
|
}
|