@pie-lib/mask-markup 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +4 -0
  2. package/dist/choices/choice.d.ts +24 -0
  3. package/dist/choices/choice.d.ts.map +1 -0
  4. package/dist/choices/choice.js +77 -0
  5. package/dist/choices/index.d.ts +26 -0
  6. package/dist/choices/index.d.ts.map +1 -0
  7. package/dist/choices/index.js +49 -0
  8. package/dist/componentize.d.ts +13 -0
  9. package/dist/componentize.d.ts.map +1 -0
  10. package/dist/componentize.js +4 -0
  11. package/dist/components/blank.d.ts +39 -0
  12. package/dist/components/blank.d.ts.map +1 -0
  13. package/dist/components/blank.js +236 -0
  14. package/dist/components/correct-input.d.ts +11 -0
  15. package/dist/components/correct-input.d.ts.map +1 -0
  16. package/dist/components/dropdown.d.ts +38 -0
  17. package/dist/components/dropdown.d.ts.map +1 -0
  18. package/dist/components/dropdown.js +309 -0
  19. package/dist/components/input.d.ts +37 -0
  20. package/dist/components/input.d.ts.map +1 -0
  21. package/dist/constructed-response.d.ts +24 -0
  22. package/dist/constructed-response.d.ts.map +1 -0
  23. package/dist/constructed-response.js +55 -0
  24. package/dist/customizable.d.ts +24 -0
  25. package/dist/customizable.d.ts.map +1 -0
  26. package/dist/customizable.js +8 -0
  27. package/dist/drag-in-the-blank.d.ts +38 -0
  28. package/dist/drag-in-the-blank.d.ts.map +1 -0
  29. package/dist/drag-in-the-blank.js +164 -0
  30. package/dist/index.d.ts +16 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +7 -0
  33. package/dist/inline-dropdown.d.ts +24 -0
  34. package/dist/inline-dropdown.d.ts.map +1 -0
  35. package/dist/inline-dropdown.js +24 -0
  36. package/dist/mask.d.ts +31 -0
  37. package/dist/mask.d.ts.map +1 -0
  38. package/dist/mask.js +98 -0
  39. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/index.js +17 -0
  40. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/cssPrefix.js +9 -0
  41. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/cssUnitless.js +26 -0
  42. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/hasOwn.js +11 -0
  43. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/isFunction.js +11 -0
  44. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/isObject.js +11 -0
  45. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/prefixInfo.js +24 -0
  46. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/prefixProperties.js +32 -0
  47. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/prefixer.js +29 -0
  48. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/stringUtils/camelize.js +14 -0
  49. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/stringUtils/hyphenRe.js +8 -0
  50. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/stringUtils/hyphenate.js +12 -0
  51. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/stringUtils/separate.js +11 -0
  52. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/stringUtils/toLowerFirst.js +10 -0
  53. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/stringUtils/toUpperFirst.js +10 -0
  54. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/toStyleObject.js +55 -0
  55. package/dist/node_modules/.bun/to-style@1.3.3/node_modules/to-style/src/toStyleString.js +16 -0
  56. package/dist/serialization.d.ts +35 -0
  57. package/dist/serialization.d.ts.map +1 -0
  58. package/dist/serialization.js +132 -0
  59. package/dist/with-mask.d.ts +35 -0
  60. package/dist/with-mask.d.ts.map +1 -0
  61. package/dist/with-mask.js +45 -0
  62. package/package.json +44 -0
  63. package/src/choices/choice.tsx +107 -0
  64. package/src/choices/index.tsx +74 -0
  65. package/src/componentize.tsx +23 -0
  66. package/src/components/blank.tsx +396 -0
  67. package/src/components/correct-input.tsx +92 -0
  68. package/src/components/dropdown.tsx +448 -0
  69. package/src/components/input.tsx +58 -0
  70. package/src/constructed-response.tsx +91 -0
  71. package/src/customizable.tsx +44 -0
  72. package/src/drag-in-the-blank.tsx +251 -0
  73. package/src/index.ts +26 -0
  74. package/src/inline-dropdown.tsx +39 -0
  75. package/src/mask.tsx +178 -0
  76. package/src/serialization.ts +270 -0
  77. package/src/with-mask.tsx +85 -0
@@ -0,0 +1,270 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * @synced-from pie-lib/packages/mask-markup/src/serialization.js
4
+ * @auto-generated
5
+ *
6
+ * This file is automatically synced from pie-elements and converted to TypeScript.
7
+ * Manual edits will be overwritten on next sync.
8
+ * To make changes, edit the upstream JavaScript file and run sync again.
9
+ */
10
+
11
+ import { object as toStyleObject } from 'to-style';
12
+ import debug from 'debug';
13
+
14
+ const log = debug('@pie-lib:mask-markup:serialization');
15
+
16
+ const INLINE = ['span'];
17
+ const MARK = ['em', 'strong', 'u'];
18
+ const TEXT_NODE = 3;
19
+ const COMMENT_NODE = 8;
20
+ const ELEMENT_NODE = 1;
21
+
22
+ const attr = (el) => {
23
+ if (!el.attributes || el.attributes.length <= 0) {
24
+ return undefined;
25
+ }
26
+
27
+ const out = {};
28
+ let i;
29
+
30
+ for (i = 0; i < el.attributes.length; i++) {
31
+ const a = el.attributes[i];
32
+
33
+ out[a.name] = a.value;
34
+ }
35
+
36
+ return out;
37
+ };
38
+
39
+ const getObject = (type) => {
40
+ if (INLINE.includes(type)) {
41
+ return 'inline';
42
+ } else if (MARK.includes(type)) {
43
+ return 'mark';
44
+ }
45
+ return 'block';
46
+ };
47
+
48
+ export const parseStyleString = (s) => {
49
+ const regex = /([\w-]*)\s*:\s*([^;]*)/g;
50
+ let match;
51
+ const result = {};
52
+ while ((match = regex.exec(s))) {
53
+ result[match[1]] = match[2].trim();
54
+ }
55
+ return result;
56
+ };
57
+
58
+ export const reactAttributes = (o) => toStyleObject(o, { camelize: true, addUnits: false });
59
+
60
+ const handleStyles = (el, attribute) => {
61
+ const styleString = el.getAttribute(attribute);
62
+
63
+ return reactAttributes(parseStyleString(styleString));
64
+ };
65
+
66
+ const handleClass = (el, acc, attribute) => {
67
+ const classNames = el.getAttribute(attribute);
68
+
69
+ delete acc.class;
70
+
71
+ return classNames;
72
+ };
73
+
74
+ const attributesToMap = (el) => (acc, attribute) => {
75
+ if (!el.getAttribute) {
76
+ return acc;
77
+ }
78
+
79
+ const value = el.getAttribute(attribute);
80
+
81
+ if (value) {
82
+ switch (attribute) {
83
+ case 'style':
84
+ acc.style = handleStyles(el, attribute);
85
+ break;
86
+ case 'class':
87
+ acc.className = handleClass(el, acc, attribute);
88
+ break;
89
+ default:
90
+ acc[attribute] = el.getAttribute(attribute);
91
+ break;
92
+ }
93
+ }
94
+
95
+ return acc;
96
+ };
97
+
98
+ const attributes = ['border', 'class', 'style'];
99
+
100
+ /**
101
+ * Tags to marks.
102
+ *
103
+ * @type {Object}
104
+ */
105
+
106
+ export const MARK_TAGS = {
107
+ b: 'bold',
108
+ em: 'italic',
109
+ u: 'underline',
110
+ s: 'strikethrough',
111
+ code: 'code',
112
+ strong: 'strong',
113
+ };
114
+
115
+ /**
116
+ * Recursively process DOM nodes and convert them to Slate JSON format
117
+ */
118
+ const processNode = (node, marks = []) => {
119
+ // Skip comment nodes
120
+ if (node.nodeType === COMMENT_NODE) {
121
+ return null;
122
+ }
123
+
124
+ // Handle text nodes
125
+ if (node.nodeType === TEXT_NODE) {
126
+ const text = node.textContent;
127
+ const leaf = { text };
128
+
129
+ if (marks.length > 0) {
130
+ leaf.marks = marks.map((m) => ({ type: m, data: undefined }));
131
+ }
132
+
133
+ return {
134
+ object: 'text',
135
+ leaves: [leaf],
136
+ };
137
+ }
138
+
139
+ // Handle element nodes
140
+ if (node.nodeType === ELEMENT_NODE) {
141
+ const type = node.tagName.toLowerCase();
142
+
143
+ // Check if this is a mark tag
144
+ const markType = MARK_TAGS[type];
145
+ if (markType) {
146
+ log('[deserialize] mark: ', markType);
147
+ // Process children with this mark added and return them flattened
148
+ const childNodes = processNodes(node.childNodes, [...marks, markType]);
149
+ // Return an array indicator with the nodes (will be flattened by parent)
150
+ return { _flatten: true, nodes: childNodes };
151
+ }
152
+
153
+ // Handle math elements specially
154
+ if (type === 'math') {
155
+ return {
156
+ isMath: true,
157
+ nodes: [node],
158
+ };
159
+ }
160
+
161
+ // Process regular elements
162
+ const normalAttrs = attr(node) || {};
163
+
164
+ if (type === 'audio' && normalAttrs.controls === '') {
165
+ normalAttrs.controls = true;
166
+ }
167
+
168
+ const allAttrs = attributes.reduce(attributesToMap(node), { ...normalAttrs });
169
+ const object = getObject(type);
170
+
171
+ const childNodes = processNodes(node.childNodes, marks);
172
+
173
+ return {
174
+ object,
175
+ type,
176
+ data: { dataset: { ...node.dataset }, attributes: { ...allAttrs } },
177
+ nodes: childNodes,
178
+ };
179
+ }
180
+
181
+ return null;
182
+ };
183
+
184
+ /**
185
+ * Process a NodeList and convert to array of Slate nodes
186
+ */
187
+ const processNodes = (nodeList, marks = []) => {
188
+ const nodes = [];
189
+ for (let i = 0; i < nodeList.length; i++) {
190
+ const result = processNode(nodeList[i], marks);
191
+ if (result !== null) {
192
+ // Handle flattening for mark nodes
193
+ if (result._flatten && result.nodes) {
194
+ nodes.push(...result.nodes);
195
+ } else {
196
+ nodes.push(result);
197
+ }
198
+ }
199
+ }
200
+ return nodes;
201
+ };
202
+
203
+ /**
204
+ * Deserialize HTML string to Slate JSON format
205
+ */
206
+ export const deserialize = (htmlString) => {
207
+ // Handle empty or whitespace-only strings
208
+ if (!htmlString || !htmlString.trim()) {
209
+ return {
210
+ object: 'value',
211
+ document: {
212
+ object: 'document',
213
+ data: {},
214
+ nodes: [
215
+ {
216
+ object: 'block',
217
+ type: 'span',
218
+ data: {},
219
+ isVoid: false,
220
+ nodes: [],
221
+ },
222
+ ],
223
+ },
224
+ };
225
+ }
226
+
227
+ // Use DOMParser to parse the HTML
228
+ const parser = new DOMParser();
229
+ const doc = parser.parseFromString(htmlString, 'text/html');
230
+
231
+ // Process all nodes in the body
232
+ let nodes = processNodes(doc.body.childNodes);
233
+
234
+ // If we only have text nodes (no block elements), wrap in default span block
235
+ const hasBlockElements = nodes.some((node) => node.object === 'block' || node.object === 'inline');
236
+
237
+ if (!hasBlockElements && nodes.length > 0) {
238
+ nodes = [
239
+ {
240
+ object: 'block',
241
+ type: 'span',
242
+ data: {},
243
+ isVoid: false,
244
+ nodes: nodes,
245
+ },
246
+ ];
247
+ }
248
+
249
+ // If no nodes were produced, add a default span block
250
+ if (nodes.length === 0) {
251
+ nodes = [
252
+ {
253
+ object: 'block',
254
+ type: 'span',
255
+ data: {},
256
+ isVoid: false,
257
+ nodes: [],
258
+ },
259
+ ];
260
+ }
261
+
262
+ return {
263
+ object: 'value',
264
+ document: {
265
+ object: 'document',
266
+ data: {},
267
+ nodes,
268
+ },
269
+ };
270
+ };
@@ -0,0 +1,85 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * @synced-from pie-lib/packages/mask-markup/src/with-mask.jsx
4
+ * @auto-generated
5
+ *
6
+ * This file is automatically synced from pie-elements and converted to TypeScript.
7
+ * Manual edits will be overwritten on next sync.
8
+ * To make changes, edit the upstream JavaScript file and run sync again.
9
+ */
10
+
11
+ import React from 'react';
12
+ import PropTypes from 'prop-types';
13
+ import Mask from './mask.js';
14
+ import componentize from './componentize.js';
15
+ import { deserialize } from './serialization.js';
16
+
17
+ export const buildLayoutFromMarkup = (markup, type) => {
18
+ const { markup: processed } = componentize(markup, type);
19
+ const value = deserialize(processed);
20
+ return value.document;
21
+ };
22
+
23
+ export const withMask = (type, renderChildren) => {
24
+ return class WithMask extends React.Component {
25
+ static propTypes = {
26
+ /**
27
+ * At the start we'll probably work with markup
28
+ */
29
+ markup: PropTypes.string,
30
+ /**
31
+ * Once we start authoring, it may make sense for use to us layout, which will be a simple js object that maps to `slate.Value`.
32
+ */
33
+ layout: PropTypes.object,
34
+ value: PropTypes.object,
35
+ onChange: PropTypes.func,
36
+ customMarkMarkupComponent: PropTypes.func,
37
+ elementType: PropTypes.string,
38
+ };
39
+
40
+ constructor(props) {
41
+ super(props);
42
+ this.containerRef = React.createRef();
43
+ }
44
+
45
+ componentDidUpdate(prevProps) {
46
+ if (this.props.markup !== prevProps.markup) {
47
+ const domNode = this.containerRef.current;
48
+ const mathElements = domNode && domNode.querySelectorAll('[data-latex][data-math-handled="true"]');
49
+
50
+ // Clean up for fresh MathJax processing
51
+ (mathElements || []).forEach((el) => {
52
+ // Remove the MathJax container to allow for clean updates
53
+ const mjxContainer = el.querySelector('mjx-container');
54
+
55
+ if (mjxContainer) {
56
+ el.removeChild(mjxContainer);
57
+ }
58
+
59
+ // Update the innerHTML to match the raw LaTeX data, ensuring it is reprocessed correctly
60
+ const latexCode = el.getAttribute('data-raw');
61
+ el.innerHTML = latexCode;
62
+
63
+ // Remove the attribute to signal that MathJax should reprocess this element
64
+ el.removeAttribute('data-math-handled');
65
+ });
66
+ }
67
+ }
68
+
69
+ render() {
70
+ const { markup, layout, value, onChange, elementType } = this.props;
71
+
72
+ const maskLayout = layout ? layout : buildLayoutFromMarkup(markup, type);
73
+ return (
74
+ <Mask
75
+ containerRef={this.containerRef}
76
+ elementType={elementType}
77
+ layout={maskLayout}
78
+ value={value}
79
+ onChange={onChange}
80
+ renderChildren={renderChildren(this.props)}
81
+ />
82
+ );
83
+ }
84
+ };
85
+ };