@mathscan/math-exercise-engine 1.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/README.md +268 -0
- package/dist/index.d.ts +2030 -0
- package/dist/index.js +6083 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +6083 -0
- package/dist/index.mjs.map +1 -0
- package/dist/style.css +346 -0
- package/package.json +87 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2030 @@
|
|
|
1
|
+
import { CstNode } from 'chevrotain';
|
|
2
|
+
import { default as default_2 } from 'react';
|
|
3
|
+
import { ForwardRefExoticComponent } from 'react';
|
|
4
|
+
import { ILexingError } from 'chevrotain';
|
|
5
|
+
import { IRecognitionException } from 'chevrotain';
|
|
6
|
+
import { IToken } from 'chevrotain';
|
|
7
|
+
import { RefAttributes } from 'react';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Compile DSL text directly to JSON (convenience function)
|
|
12
|
+
*
|
|
13
|
+
* This combines tokenize → parse → toAST → toJSON in one call.
|
|
14
|
+
*
|
|
15
|
+
* @param dsl - The DSL text to compile
|
|
16
|
+
* @returns The exercise JSON
|
|
17
|
+
* @throws LexerError if tokenization fails
|
|
18
|
+
* @throws ParseError if parsing fails
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const json = compile(`
|
|
23
|
+
* QUESTION_TEXT["Solve"]
|
|
24
|
+
* 25 + W_S_I[name="x", length=2, answer="5"] = 30
|
|
25
|
+
* WIDGET_ANSWER[type="simple"]
|
|
26
|
+
* `);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function compile(dsl: string): ExerciseJSON;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Compile DSL and return both AST and JSON
|
|
33
|
+
*
|
|
34
|
+
* Useful when you need access to both representations.
|
|
35
|
+
*
|
|
36
|
+
* @param dsl - The DSL text to compile
|
|
37
|
+
* @returns Object containing both ast and json
|
|
38
|
+
*/
|
|
39
|
+
export declare function compileWithAST(dsl: string): {
|
|
40
|
+
ast: {
|
|
41
|
+
validation: {
|
|
42
|
+
type: "SimpleValidation";
|
|
43
|
+
} | {
|
|
44
|
+
type: "ExpressionValidation";
|
|
45
|
+
expression: string;
|
|
46
|
+
};
|
|
47
|
+
type: "ExerciseDocument";
|
|
48
|
+
lines: {
|
|
49
|
+
type: "LineBlock";
|
|
50
|
+
inlines: ({
|
|
51
|
+
value: string;
|
|
52
|
+
type: "FreeText";
|
|
53
|
+
} | {
|
|
54
|
+
type: "Space";
|
|
55
|
+
} | {
|
|
56
|
+
value: string;
|
|
57
|
+
type: "NumberText";
|
|
58
|
+
highlight?: [number, number] | undefined;
|
|
59
|
+
} | {
|
|
60
|
+
length: number;
|
|
61
|
+
type: "InlineInput";
|
|
62
|
+
inputType: "string";
|
|
63
|
+
name: string;
|
|
64
|
+
answer?: string | number | undefined;
|
|
65
|
+
} | {
|
|
66
|
+
type: "InlineInput";
|
|
67
|
+
inputType: "numeric";
|
|
68
|
+
name: string;
|
|
69
|
+
digits: number;
|
|
70
|
+
answer?: string | number | undefined;
|
|
71
|
+
})[];
|
|
72
|
+
}[];
|
|
73
|
+
question?: {
|
|
74
|
+
value: string;
|
|
75
|
+
type: "TextBlock";
|
|
76
|
+
} | undefined;
|
|
77
|
+
tools?: ({
|
|
78
|
+
type: "DragOptions";
|
|
79
|
+
options: string[];
|
|
80
|
+
} | {
|
|
81
|
+
type: "NumericKeypad";
|
|
82
|
+
includeDecimal: boolean;
|
|
83
|
+
includeNegative: boolean;
|
|
84
|
+
})[] | undefined;
|
|
85
|
+
};
|
|
86
|
+
json: {
|
|
87
|
+
validation: {
|
|
88
|
+
mode: "expression" | "simple";
|
|
89
|
+
expression?: string | undefined;
|
|
90
|
+
answers?: Record<string, string | number> | undefined;
|
|
91
|
+
variables?: string[] | undefined;
|
|
92
|
+
};
|
|
93
|
+
version: "2.0";
|
|
94
|
+
layout: any[];
|
|
95
|
+
widgets: Record<string, {
|
|
96
|
+
length: number;
|
|
97
|
+
type: "inline-input";
|
|
98
|
+
inputType: "string";
|
|
99
|
+
} | {
|
|
100
|
+
type: "inline-input";
|
|
101
|
+
inputType: "numeric";
|
|
102
|
+
digits: number;
|
|
103
|
+
} | {
|
|
104
|
+
type: "drag-options";
|
|
105
|
+
options: string[];
|
|
106
|
+
} | {
|
|
107
|
+
type: "numeric-keypad";
|
|
108
|
+
includeDecimal: boolean;
|
|
109
|
+
}>;
|
|
110
|
+
id?: string | undefined;
|
|
111
|
+
meta?: {
|
|
112
|
+
createdAt?: string | undefined;
|
|
113
|
+
author?: string | undefined;
|
|
114
|
+
tags?: string[] | undefined;
|
|
115
|
+
difficulty?: number | undefined;
|
|
116
|
+
} | undefined;
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Create a drag options tool
|
|
122
|
+
*/
|
|
123
|
+
export declare function createDragOptions(options: string[]): DragOptionsTool;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Create an exercise document
|
|
127
|
+
*/
|
|
128
|
+
export declare function createExerciseDocument(question: z.infer<typeof TextBlockSchema> | undefined, lines: z.infer<typeof LineBlockSchema>[], validation: z.infer<typeof ValidationNodeSchema>, tools?: z.infer<typeof ToolNodeSchema>[]): ExerciseDocument;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Create an expression validation node
|
|
132
|
+
*/
|
|
133
|
+
export declare function createExpressionValidation(expression: string): ExpressionValidation;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Create a free text inline element
|
|
137
|
+
*/
|
|
138
|
+
export declare function createFreeText(value: string): FreeTextInline;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @deprecated Use createStringInput or createNumericInput instead
|
|
142
|
+
*/
|
|
143
|
+
export declare function createInlineInput(name: string, inputType: "string" | "numeric", lengthOrDigits: number, answer?: string | number): InlineInputWidget;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Create a line block
|
|
147
|
+
*/
|
|
148
|
+
export declare function createLineBlock(inlines: any[]): LineBlock;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Create a number text inline element
|
|
152
|
+
*/
|
|
153
|
+
export declare function createNumberText(value: string, highlight?: [number, number]): NumberTextInline;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Create a numeric inline input widget (W_N_I)
|
|
157
|
+
*/
|
|
158
|
+
export declare function createNumericInput(name: string, digits: number, answer?: string | number): InlineInputWidget;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Create a numeric keypad tool
|
|
162
|
+
*/
|
|
163
|
+
export declare function createNumericKeypad(includeDecimal?: boolean, includeNegative?: boolean): NumericKeypadTool;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Create a simple validation node
|
|
167
|
+
*/
|
|
168
|
+
export declare function createSimpleValidation(): SimpleValidation;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Create a space inline element
|
|
172
|
+
*/
|
|
173
|
+
export declare function createSpace(): SpaceInline;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Create a string inline input widget (W_S_I)
|
|
177
|
+
*/
|
|
178
|
+
export declare function createStringInput(name: string, length: number, answer?: string | number): InlineInputWidget;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Create a text block (question)
|
|
182
|
+
*/
|
|
183
|
+
export declare function createTextBlock(value: string): TextBlock;
|
|
184
|
+
|
|
185
|
+
export declare type DragOptionsJSON = z.infer<typeof DragOptionsJSONSchema>;
|
|
186
|
+
|
|
187
|
+
export declare const DragOptionsJSONSchema: z.ZodObject<{
|
|
188
|
+
type: z.ZodLiteral<"drag-options">;
|
|
189
|
+
options: z.ZodArray<z.ZodString, "many">;
|
|
190
|
+
}, "strip", z.ZodTypeAny, {
|
|
191
|
+
type: "drag-options";
|
|
192
|
+
options: string[];
|
|
193
|
+
}, {
|
|
194
|
+
type: "drag-options";
|
|
195
|
+
options: string[];
|
|
196
|
+
}>;
|
|
197
|
+
|
|
198
|
+
export declare type DragOptionsTool = z.infer<typeof DragOptionsToolSchema>;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Drag options tool schema - draggable buttons/options
|
|
202
|
+
*
|
|
203
|
+
* Common use cases:
|
|
204
|
+
* - Comparison symbols: ["<", ">", "="]
|
|
205
|
+
* - Yes/No: ["نعم", "لا"]
|
|
206
|
+
* - Multiple choice: ["A", "B", "C", "D"]
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* {
|
|
210
|
+
* type: "DragOptions",
|
|
211
|
+
* options: ["<", ">", "="]
|
|
212
|
+
* }
|
|
213
|
+
*/
|
|
214
|
+
export declare const DragOptionsToolSchema: z.ZodObject<{
|
|
215
|
+
type: z.ZodLiteral<"DragOptions">;
|
|
216
|
+
options: z.ZodArray<z.ZodString, "many">;
|
|
217
|
+
}, "strip", z.ZodTypeAny, {
|
|
218
|
+
type: "DragOptions";
|
|
219
|
+
options: string[];
|
|
220
|
+
}, {
|
|
221
|
+
type: "DragOptions";
|
|
222
|
+
options: string[];
|
|
223
|
+
}>;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Base error class for all engine errors
|
|
227
|
+
*/
|
|
228
|
+
export declare class EngineError extends Error {
|
|
229
|
+
constructor(message: string);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Evaluate a mathematical expression with the given variable scope
|
|
234
|
+
*
|
|
235
|
+
* @param expression - The expression to evaluate (e.g., "(a * b) + (c * d) == 1200")
|
|
236
|
+
* @param scope - Variable bindings (e.g., { a: 10, b: 5, c: 20, d: 30 })
|
|
237
|
+
* @returns The boolean result of the expression
|
|
238
|
+
* @throws Error if evaluation fails
|
|
239
|
+
*/
|
|
240
|
+
export declare function evaluate(expression: string, scope: Record<string, number>): boolean;
|
|
241
|
+
|
|
242
|
+
export declare type ExerciseDocument = z.infer<typeof ExerciseDocumentSchema>;
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Exercise document schema - the complete exercise structure
|
|
246
|
+
*
|
|
247
|
+
* Structure:
|
|
248
|
+
* 1. Question: What the student should do
|
|
249
|
+
* 2. Lines: Visual rows with inline elements
|
|
250
|
+
* 3. Tools: Standalone interactive elements (optional)
|
|
251
|
+
* 4. Validation: How to check answers
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* {
|
|
255
|
+
* type: "ExerciseDocument",
|
|
256
|
+
* question: {
|
|
257
|
+
* type: "TextBlock",
|
|
258
|
+
* value: "أقارن كل عددين باستعمال الرمر المناسب"
|
|
259
|
+
* },
|
|
260
|
+
* lines: [
|
|
261
|
+
* {
|
|
262
|
+
* type: "LineBlock",
|
|
263
|
+
* inlines: [
|
|
264
|
+
* { type: "NumberText", value: "151 000", highlight: [0, 3] },
|
|
265
|
+
* { type: "InlineInput", name: "x", length: 1 },
|
|
266
|
+
* { type: "NumberText", value: "54 000", highlight: [0, 3] }
|
|
267
|
+
* ]
|
|
268
|
+
* }
|
|
269
|
+
* ],
|
|
270
|
+
* tools: [
|
|
271
|
+
* { type: "DragOptions", options: ["<", ">", "="] }
|
|
272
|
+
* ],
|
|
273
|
+
* validation: {
|
|
274
|
+
* type: "SimpleValidation"
|
|
275
|
+
* }
|
|
276
|
+
* }
|
|
277
|
+
*/
|
|
278
|
+
export declare const ExerciseDocumentSchema: z.ZodObject<{
|
|
279
|
+
type: z.ZodLiteral<"ExerciseDocument">;
|
|
280
|
+
question: z.ZodOptional<z.ZodObject<{
|
|
281
|
+
type: z.ZodLiteral<"TextBlock">;
|
|
282
|
+
value: z.ZodString;
|
|
283
|
+
}, "strip", z.ZodTypeAny, {
|
|
284
|
+
value: string;
|
|
285
|
+
type: "TextBlock";
|
|
286
|
+
}, {
|
|
287
|
+
value: string;
|
|
288
|
+
type: "TextBlock";
|
|
289
|
+
}>>;
|
|
290
|
+
lines: z.ZodArray<z.ZodObject<{
|
|
291
|
+
type: z.ZodLiteral<"LineBlock">;
|
|
292
|
+
inlines: z.ZodArray<z.ZodUnion<[z.ZodObject<{
|
|
293
|
+
type: z.ZodLiteral<"FreeText">;
|
|
294
|
+
value: z.ZodString;
|
|
295
|
+
}, "strip", z.ZodTypeAny, {
|
|
296
|
+
value: string;
|
|
297
|
+
type: "FreeText";
|
|
298
|
+
}, {
|
|
299
|
+
value: string;
|
|
300
|
+
type: "FreeText";
|
|
301
|
+
}>, z.ZodObject<{
|
|
302
|
+
type: z.ZodLiteral<"Space">;
|
|
303
|
+
}, "strip", z.ZodTypeAny, {
|
|
304
|
+
type: "Space";
|
|
305
|
+
}, {
|
|
306
|
+
type: "Space";
|
|
307
|
+
}>, z.ZodObject<{
|
|
308
|
+
type: z.ZodLiteral<"NumberText">;
|
|
309
|
+
value: z.ZodString;
|
|
310
|
+
highlight: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
311
|
+
}, "strip", z.ZodTypeAny, {
|
|
312
|
+
value: string;
|
|
313
|
+
type: "NumberText";
|
|
314
|
+
highlight?: [number, number] | undefined;
|
|
315
|
+
}, {
|
|
316
|
+
value: string;
|
|
317
|
+
type: "NumberText";
|
|
318
|
+
highlight?: [number, number] | undefined;
|
|
319
|
+
}>, z.ZodDiscriminatedUnion<"inputType", [z.ZodObject<{
|
|
320
|
+
type: z.ZodLiteral<"InlineInput">;
|
|
321
|
+
name: z.ZodString;
|
|
322
|
+
inputType: z.ZodLiteral<"string">;
|
|
323
|
+
length: z.ZodNumber;
|
|
324
|
+
answer: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
325
|
+
}, "strip", z.ZodTypeAny, {
|
|
326
|
+
length: number;
|
|
327
|
+
type: "InlineInput";
|
|
328
|
+
inputType: "string";
|
|
329
|
+
name: string;
|
|
330
|
+
answer?: string | number | undefined;
|
|
331
|
+
}, {
|
|
332
|
+
length: number;
|
|
333
|
+
type: "InlineInput";
|
|
334
|
+
inputType: "string";
|
|
335
|
+
name: string;
|
|
336
|
+
answer?: string | number | undefined;
|
|
337
|
+
}>, z.ZodObject<{
|
|
338
|
+
type: z.ZodLiteral<"InlineInput">;
|
|
339
|
+
name: z.ZodString;
|
|
340
|
+
inputType: z.ZodLiteral<"numeric">;
|
|
341
|
+
digits: z.ZodNumber;
|
|
342
|
+
answer: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
343
|
+
}, "strip", z.ZodTypeAny, {
|
|
344
|
+
type: "InlineInput";
|
|
345
|
+
inputType: "numeric";
|
|
346
|
+
name: string;
|
|
347
|
+
digits: number;
|
|
348
|
+
answer?: string | number | undefined;
|
|
349
|
+
}, {
|
|
350
|
+
type: "InlineInput";
|
|
351
|
+
inputType: "numeric";
|
|
352
|
+
name: string;
|
|
353
|
+
digits: number;
|
|
354
|
+
answer?: string | number | undefined;
|
|
355
|
+
}>]>]>, "many">;
|
|
356
|
+
}, "strip", z.ZodTypeAny, {
|
|
357
|
+
type: "LineBlock";
|
|
358
|
+
inlines: ({
|
|
359
|
+
value: string;
|
|
360
|
+
type: "FreeText";
|
|
361
|
+
} | {
|
|
362
|
+
type: "Space";
|
|
363
|
+
} | {
|
|
364
|
+
value: string;
|
|
365
|
+
type: "NumberText";
|
|
366
|
+
highlight?: [number, number] | undefined;
|
|
367
|
+
} | {
|
|
368
|
+
length: number;
|
|
369
|
+
type: "InlineInput";
|
|
370
|
+
inputType: "string";
|
|
371
|
+
name: string;
|
|
372
|
+
answer?: string | number | undefined;
|
|
373
|
+
} | {
|
|
374
|
+
type: "InlineInput";
|
|
375
|
+
inputType: "numeric";
|
|
376
|
+
name: string;
|
|
377
|
+
digits: number;
|
|
378
|
+
answer?: string | number | undefined;
|
|
379
|
+
})[];
|
|
380
|
+
}, {
|
|
381
|
+
type: "LineBlock";
|
|
382
|
+
inlines: ({
|
|
383
|
+
value: string;
|
|
384
|
+
type: "FreeText";
|
|
385
|
+
} | {
|
|
386
|
+
type: "Space";
|
|
387
|
+
} | {
|
|
388
|
+
value: string;
|
|
389
|
+
type: "NumberText";
|
|
390
|
+
highlight?: [number, number] | undefined;
|
|
391
|
+
} | {
|
|
392
|
+
length: number;
|
|
393
|
+
type: "InlineInput";
|
|
394
|
+
inputType: "string";
|
|
395
|
+
name: string;
|
|
396
|
+
answer?: string | number | undefined;
|
|
397
|
+
} | {
|
|
398
|
+
type: "InlineInput";
|
|
399
|
+
inputType: "numeric";
|
|
400
|
+
name: string;
|
|
401
|
+
digits: number;
|
|
402
|
+
answer?: string | number | undefined;
|
|
403
|
+
})[];
|
|
404
|
+
}>, "many">;
|
|
405
|
+
tools: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
406
|
+
type: z.ZodLiteral<"DragOptions">;
|
|
407
|
+
options: z.ZodArray<z.ZodString, "many">;
|
|
408
|
+
}, "strip", z.ZodTypeAny, {
|
|
409
|
+
type: "DragOptions";
|
|
410
|
+
options: string[];
|
|
411
|
+
}, {
|
|
412
|
+
type: "DragOptions";
|
|
413
|
+
options: string[];
|
|
414
|
+
}>, z.ZodObject<{
|
|
415
|
+
type: z.ZodLiteral<"NumericKeypad">;
|
|
416
|
+
includeDecimal: z.ZodDefault<z.ZodBoolean>;
|
|
417
|
+
includeNegative: z.ZodDefault<z.ZodBoolean>;
|
|
418
|
+
}, "strip", z.ZodTypeAny, {
|
|
419
|
+
type: "NumericKeypad";
|
|
420
|
+
includeDecimal: boolean;
|
|
421
|
+
includeNegative: boolean;
|
|
422
|
+
}, {
|
|
423
|
+
type: "NumericKeypad";
|
|
424
|
+
includeDecimal?: boolean | undefined;
|
|
425
|
+
includeNegative?: boolean | undefined;
|
|
426
|
+
}>]>, "many">>;
|
|
427
|
+
validation: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
428
|
+
type: z.ZodLiteral<"SimpleValidation">;
|
|
429
|
+
}, "strip", z.ZodTypeAny, {
|
|
430
|
+
type: "SimpleValidation";
|
|
431
|
+
}, {
|
|
432
|
+
type: "SimpleValidation";
|
|
433
|
+
}>, z.ZodObject<{
|
|
434
|
+
type: z.ZodLiteral<"ExpressionValidation">;
|
|
435
|
+
expression: z.ZodString;
|
|
436
|
+
}, "strip", z.ZodTypeAny, {
|
|
437
|
+
type: "ExpressionValidation";
|
|
438
|
+
expression: string;
|
|
439
|
+
}, {
|
|
440
|
+
type: "ExpressionValidation";
|
|
441
|
+
expression: string;
|
|
442
|
+
}>]>;
|
|
443
|
+
}, "strip", z.ZodTypeAny, {
|
|
444
|
+
validation: {
|
|
445
|
+
type: "SimpleValidation";
|
|
446
|
+
} | {
|
|
447
|
+
type: "ExpressionValidation";
|
|
448
|
+
expression: string;
|
|
449
|
+
};
|
|
450
|
+
type: "ExerciseDocument";
|
|
451
|
+
lines: {
|
|
452
|
+
type: "LineBlock";
|
|
453
|
+
inlines: ({
|
|
454
|
+
value: string;
|
|
455
|
+
type: "FreeText";
|
|
456
|
+
} | {
|
|
457
|
+
type: "Space";
|
|
458
|
+
} | {
|
|
459
|
+
value: string;
|
|
460
|
+
type: "NumberText";
|
|
461
|
+
highlight?: [number, number] | undefined;
|
|
462
|
+
} | {
|
|
463
|
+
length: number;
|
|
464
|
+
type: "InlineInput";
|
|
465
|
+
inputType: "string";
|
|
466
|
+
name: string;
|
|
467
|
+
answer?: string | number | undefined;
|
|
468
|
+
} | {
|
|
469
|
+
type: "InlineInput";
|
|
470
|
+
inputType: "numeric";
|
|
471
|
+
name: string;
|
|
472
|
+
digits: number;
|
|
473
|
+
answer?: string | number | undefined;
|
|
474
|
+
})[];
|
|
475
|
+
}[];
|
|
476
|
+
question?: {
|
|
477
|
+
value: string;
|
|
478
|
+
type: "TextBlock";
|
|
479
|
+
} | undefined;
|
|
480
|
+
tools?: ({
|
|
481
|
+
type: "DragOptions";
|
|
482
|
+
options: string[];
|
|
483
|
+
} | {
|
|
484
|
+
type: "NumericKeypad";
|
|
485
|
+
includeDecimal: boolean;
|
|
486
|
+
includeNegative: boolean;
|
|
487
|
+
})[] | undefined;
|
|
488
|
+
}, {
|
|
489
|
+
validation: {
|
|
490
|
+
type: "SimpleValidation";
|
|
491
|
+
} | {
|
|
492
|
+
type: "ExpressionValidation";
|
|
493
|
+
expression: string;
|
|
494
|
+
};
|
|
495
|
+
type: "ExerciseDocument";
|
|
496
|
+
lines: {
|
|
497
|
+
type: "LineBlock";
|
|
498
|
+
inlines: ({
|
|
499
|
+
value: string;
|
|
500
|
+
type: "FreeText";
|
|
501
|
+
} | {
|
|
502
|
+
type: "Space";
|
|
503
|
+
} | {
|
|
504
|
+
value: string;
|
|
505
|
+
type: "NumberText";
|
|
506
|
+
highlight?: [number, number] | undefined;
|
|
507
|
+
} | {
|
|
508
|
+
length: number;
|
|
509
|
+
type: "InlineInput";
|
|
510
|
+
inputType: "string";
|
|
511
|
+
name: string;
|
|
512
|
+
answer?: string | number | undefined;
|
|
513
|
+
} | {
|
|
514
|
+
type: "InlineInput";
|
|
515
|
+
inputType: "numeric";
|
|
516
|
+
name: string;
|
|
517
|
+
digits: number;
|
|
518
|
+
answer?: string | number | undefined;
|
|
519
|
+
})[];
|
|
520
|
+
}[];
|
|
521
|
+
question?: {
|
|
522
|
+
value: string;
|
|
523
|
+
type: "TextBlock";
|
|
524
|
+
} | undefined;
|
|
525
|
+
tools?: ({
|
|
526
|
+
type: "DragOptions";
|
|
527
|
+
options: string[];
|
|
528
|
+
} | {
|
|
529
|
+
type: "NumericKeypad";
|
|
530
|
+
includeDecimal?: boolean | undefined;
|
|
531
|
+
includeNegative?: boolean | undefined;
|
|
532
|
+
})[] | undefined;
|
|
533
|
+
}>;
|
|
534
|
+
|
|
535
|
+
export declare type ExerciseJSON = z.infer<typeof ExerciseJSONSchema>;
|
|
536
|
+
|
|
537
|
+
export declare const ExerciseJSONSchema: z.ZodObject<{
|
|
538
|
+
version: z.ZodLiteral<"2.0">;
|
|
539
|
+
id: z.ZodOptional<z.ZodString>;
|
|
540
|
+
layout: z.ZodArray<z.ZodType<any, z.ZodTypeDef, any>, "many">;
|
|
541
|
+
widgets: z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodDiscriminatedUnion<"inputType", [z.ZodObject<{
|
|
542
|
+
type: z.ZodLiteral<"inline-input">;
|
|
543
|
+
inputType: z.ZodLiteral<"string">;
|
|
544
|
+
length: z.ZodNumber;
|
|
545
|
+
}, "strip", z.ZodTypeAny, {
|
|
546
|
+
length: number;
|
|
547
|
+
type: "inline-input";
|
|
548
|
+
inputType: "string";
|
|
549
|
+
}, {
|
|
550
|
+
length: number;
|
|
551
|
+
type: "inline-input";
|
|
552
|
+
inputType: "string";
|
|
553
|
+
}>, z.ZodObject<{
|
|
554
|
+
type: z.ZodLiteral<"inline-input">;
|
|
555
|
+
inputType: z.ZodLiteral<"numeric">;
|
|
556
|
+
digits: z.ZodNumber;
|
|
557
|
+
}, "strip", z.ZodTypeAny, {
|
|
558
|
+
type: "inline-input";
|
|
559
|
+
inputType: "numeric";
|
|
560
|
+
digits: number;
|
|
561
|
+
}, {
|
|
562
|
+
type: "inline-input";
|
|
563
|
+
inputType: "numeric";
|
|
564
|
+
digits: number;
|
|
565
|
+
}>]>, z.ZodObject<{
|
|
566
|
+
type: z.ZodLiteral<"drag-options">;
|
|
567
|
+
options: z.ZodArray<z.ZodString, "many">;
|
|
568
|
+
}, "strip", z.ZodTypeAny, {
|
|
569
|
+
type: "drag-options";
|
|
570
|
+
options: string[];
|
|
571
|
+
}, {
|
|
572
|
+
type: "drag-options";
|
|
573
|
+
options: string[];
|
|
574
|
+
}>, z.ZodObject<{
|
|
575
|
+
type: z.ZodLiteral<"numeric-keypad">;
|
|
576
|
+
includeDecimal: z.ZodBoolean;
|
|
577
|
+
}, "strip", z.ZodTypeAny, {
|
|
578
|
+
type: "numeric-keypad";
|
|
579
|
+
includeDecimal: boolean;
|
|
580
|
+
}, {
|
|
581
|
+
type: "numeric-keypad";
|
|
582
|
+
includeDecimal: boolean;
|
|
583
|
+
}>]>>;
|
|
584
|
+
validation: z.ZodObject<{
|
|
585
|
+
mode: z.ZodEnum<["simple", "expression"]>;
|
|
586
|
+
answers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber]>>>;
|
|
587
|
+
expression: z.ZodOptional<z.ZodString>;
|
|
588
|
+
variables: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
589
|
+
}, "strip", z.ZodTypeAny, {
|
|
590
|
+
mode: "expression" | "simple";
|
|
591
|
+
expression?: string | undefined;
|
|
592
|
+
answers?: Record<string, string | number> | undefined;
|
|
593
|
+
variables?: string[] | undefined;
|
|
594
|
+
}, {
|
|
595
|
+
mode: "expression" | "simple";
|
|
596
|
+
expression?: string | undefined;
|
|
597
|
+
answers?: Record<string, string | number> | undefined;
|
|
598
|
+
variables?: string[] | undefined;
|
|
599
|
+
}>;
|
|
600
|
+
meta: z.ZodOptional<z.ZodObject<{
|
|
601
|
+
createdAt: z.ZodOptional<z.ZodString>;
|
|
602
|
+
author: z.ZodOptional<z.ZodString>;
|
|
603
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
604
|
+
difficulty: z.ZodOptional<z.ZodNumber>;
|
|
605
|
+
}, "strip", z.ZodTypeAny, {
|
|
606
|
+
createdAt?: string | undefined;
|
|
607
|
+
author?: string | undefined;
|
|
608
|
+
tags?: string[] | undefined;
|
|
609
|
+
difficulty?: number | undefined;
|
|
610
|
+
}, {
|
|
611
|
+
createdAt?: string | undefined;
|
|
612
|
+
author?: string | undefined;
|
|
613
|
+
tags?: string[] | undefined;
|
|
614
|
+
difficulty?: number | undefined;
|
|
615
|
+
}>>;
|
|
616
|
+
}, "strip", z.ZodTypeAny, {
|
|
617
|
+
validation: {
|
|
618
|
+
mode: "expression" | "simple";
|
|
619
|
+
expression?: string | undefined;
|
|
620
|
+
answers?: Record<string, string | number> | undefined;
|
|
621
|
+
variables?: string[] | undefined;
|
|
622
|
+
};
|
|
623
|
+
version: "2.0";
|
|
624
|
+
layout: any[];
|
|
625
|
+
widgets: Record<string, {
|
|
626
|
+
length: number;
|
|
627
|
+
type: "inline-input";
|
|
628
|
+
inputType: "string";
|
|
629
|
+
} | {
|
|
630
|
+
type: "inline-input";
|
|
631
|
+
inputType: "numeric";
|
|
632
|
+
digits: number;
|
|
633
|
+
} | {
|
|
634
|
+
type: "drag-options";
|
|
635
|
+
options: string[];
|
|
636
|
+
} | {
|
|
637
|
+
type: "numeric-keypad";
|
|
638
|
+
includeDecimal: boolean;
|
|
639
|
+
}>;
|
|
640
|
+
id?: string | undefined;
|
|
641
|
+
meta?: {
|
|
642
|
+
createdAt?: string | undefined;
|
|
643
|
+
author?: string | undefined;
|
|
644
|
+
tags?: string[] | undefined;
|
|
645
|
+
difficulty?: number | undefined;
|
|
646
|
+
} | undefined;
|
|
647
|
+
}, {
|
|
648
|
+
validation: {
|
|
649
|
+
mode: "expression" | "simple";
|
|
650
|
+
expression?: string | undefined;
|
|
651
|
+
answers?: Record<string, string | number> | undefined;
|
|
652
|
+
variables?: string[] | undefined;
|
|
653
|
+
};
|
|
654
|
+
version: "2.0";
|
|
655
|
+
layout: any[];
|
|
656
|
+
widgets: Record<string, {
|
|
657
|
+
length: number;
|
|
658
|
+
type: "inline-input";
|
|
659
|
+
inputType: "string";
|
|
660
|
+
} | {
|
|
661
|
+
type: "inline-input";
|
|
662
|
+
inputType: "numeric";
|
|
663
|
+
digits: number;
|
|
664
|
+
} | {
|
|
665
|
+
type: "drag-options";
|
|
666
|
+
options: string[];
|
|
667
|
+
} | {
|
|
668
|
+
type: "numeric-keypad";
|
|
669
|
+
includeDecimal: boolean;
|
|
670
|
+
}>;
|
|
671
|
+
id?: string | undefined;
|
|
672
|
+
meta?: {
|
|
673
|
+
createdAt?: string | undefined;
|
|
674
|
+
author?: string | undefined;
|
|
675
|
+
tags?: string[] | undefined;
|
|
676
|
+
difficulty?: number | undefined;
|
|
677
|
+
} | undefined;
|
|
678
|
+
}>;
|
|
679
|
+
|
|
680
|
+
export declare type ExerciseMeta = z.infer<typeof ExerciseMetaSchema>;
|
|
681
|
+
|
|
682
|
+
export declare const ExerciseMetaSchema: z.ZodObject<{
|
|
683
|
+
createdAt: z.ZodOptional<z.ZodString>;
|
|
684
|
+
author: z.ZodOptional<z.ZodString>;
|
|
685
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
686
|
+
difficulty: z.ZodOptional<z.ZodNumber>;
|
|
687
|
+
}, "strip", z.ZodTypeAny, {
|
|
688
|
+
createdAt?: string | undefined;
|
|
689
|
+
author?: string | undefined;
|
|
690
|
+
tags?: string[] | undefined;
|
|
691
|
+
difficulty?: number | undefined;
|
|
692
|
+
}, {
|
|
693
|
+
createdAt?: string | undefined;
|
|
694
|
+
author?: string | undefined;
|
|
695
|
+
tags?: string[] | undefined;
|
|
696
|
+
difficulty?: number | undefined;
|
|
697
|
+
}>;
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Main renderer component - the contract for rendering exercises.
|
|
701
|
+
*
|
|
702
|
+
* This component is DUMB - it only collects values and passes them up.
|
|
703
|
+
* The parent decides correctness via validation.
|
|
704
|
+
*/
|
|
705
|
+
export declare const ExerciseRenderer: ForwardRefExoticComponent<ExerciseRendererProps & RefAttributes<ExerciseRendererRef>>;
|
|
706
|
+
|
|
707
|
+
export declare interface ExerciseRendererProps {
|
|
708
|
+
json: ExerciseJSON;
|
|
709
|
+
onSubmit?: (values: Record<string, string>) => void;
|
|
710
|
+
onChange?: (values: Record<string, string>) => void;
|
|
711
|
+
showSubmitButton?: boolean;
|
|
712
|
+
className?: string;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
export declare interface ExerciseRendererRef {
|
|
716
|
+
submit: () => ValidationResult;
|
|
717
|
+
getValues: () => Record<string, string>;
|
|
718
|
+
reset: () => void;
|
|
719
|
+
focusFirstInput: () => void;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
export declare type ExpressionValidation = z.infer<typeof ExpressionValidationSchema>;
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Expression validation schema - validates using a boolean expression
|
|
726
|
+
*
|
|
727
|
+
* The expression can reference widget values by name.
|
|
728
|
+
* Example: "a + b === 10"
|
|
729
|
+
*
|
|
730
|
+
* @example
|
|
731
|
+
* {
|
|
732
|
+
* type: "ExpressionValidation",
|
|
733
|
+
* expression: "a + b === 10"
|
|
734
|
+
* }
|
|
735
|
+
*/
|
|
736
|
+
export declare const ExpressionValidationSchema: z.ZodObject<{
|
|
737
|
+
type: z.ZodLiteral<"ExpressionValidation">;
|
|
738
|
+
expression: z.ZodString;
|
|
739
|
+
}, "strip", z.ZodTypeAny, {
|
|
740
|
+
type: "ExpressionValidation";
|
|
741
|
+
expression: string;
|
|
742
|
+
}, {
|
|
743
|
+
type: "ExpressionValidation";
|
|
744
|
+
expression: string;
|
|
745
|
+
}>;
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Extract variable names from an expression
|
|
749
|
+
*
|
|
750
|
+
* @param expression - The expression to analyze
|
|
751
|
+
* @param validVariables - Optional list of valid variable names to filter by (e.g., from exercise widgets)
|
|
752
|
+
* @returns Array of variable names
|
|
753
|
+
*/
|
|
754
|
+
export declare function extractExpressionVariables(expression: string, validVariables?: string[]): string[];
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Check if any combination of values can satisfy the expression
|
|
758
|
+
* (useful for debugging/testing exercises)
|
|
759
|
+
*
|
|
760
|
+
* @param expression - The expression to check
|
|
761
|
+
* @param ranges - Value ranges for each variable
|
|
762
|
+
* @returns First valid combination found, or null
|
|
763
|
+
*/
|
|
764
|
+
export declare function findValidCombination(expression: string, ranges: Record<string, {
|
|
765
|
+
min: number;
|
|
766
|
+
max: number;
|
|
767
|
+
step?: number;
|
|
768
|
+
}>): Record<string, number> | null;
|
|
769
|
+
|
|
770
|
+
export declare type FreeTextInline = z.infer<typeof FreeTextInlineSchema>;
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Free text inline schema - plain text/numbers WITHOUT special formatting
|
|
774
|
+
*
|
|
775
|
+
* Use this for normal text. Only use NUMBER_TEXT when you need highlighting!
|
|
776
|
+
*
|
|
777
|
+
* @example
|
|
778
|
+
* { type: "FreeText", value: "25 + " }
|
|
779
|
+
* { type: "FreeText", value: " = 30" }
|
|
780
|
+
*/
|
|
781
|
+
export declare const FreeTextInlineSchema: z.ZodObject<{
|
|
782
|
+
type: z.ZodLiteral<"FreeText">;
|
|
783
|
+
value: z.ZodString;
|
|
784
|
+
}, "strip", z.ZodTypeAny, {
|
|
785
|
+
value: string;
|
|
786
|
+
type: "FreeText";
|
|
787
|
+
}, {
|
|
788
|
+
value: string;
|
|
789
|
+
type: "FreeText";
|
|
790
|
+
}>;
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* Check if all required inputs are provided
|
|
794
|
+
*
|
|
795
|
+
* @param exercise - The exercise JSON
|
|
796
|
+
* @param userInputs - User's answers
|
|
797
|
+
* @returns Array of missing widget IDs
|
|
798
|
+
*/
|
|
799
|
+
export declare function getMissingInputs(exercise: ExerciseJSON, userInputs: Record<string, string | number>): string[];
|
|
800
|
+
|
|
801
|
+
export declare type GroupItem = z.infer<typeof GroupItemSchema>;
|
|
802
|
+
|
|
803
|
+
export declare const GroupItemSchema: z.ZodObject<{
|
|
804
|
+
id: z.ZodString;
|
|
805
|
+
type: z.ZodLiteral<"group">;
|
|
806
|
+
items: z.ZodArray<z.ZodType<any, z.ZodTypeDef, any>, "many">;
|
|
807
|
+
}, "strip", z.ZodTypeAny, {
|
|
808
|
+
type: "group";
|
|
809
|
+
id: string;
|
|
810
|
+
items: any[];
|
|
811
|
+
}, {
|
|
812
|
+
type: "group";
|
|
813
|
+
id: string;
|
|
814
|
+
items: any[];
|
|
815
|
+
}>;
|
|
816
|
+
|
|
817
|
+
export declare type InlineInputJSON = z.infer<typeof InlineInputJSONSchema>;
|
|
818
|
+
|
|
819
|
+
export declare const InlineInputJSONSchema: z.ZodDiscriminatedUnion<"inputType", [z.ZodObject<{
|
|
820
|
+
type: z.ZodLiteral<"inline-input">;
|
|
821
|
+
inputType: z.ZodLiteral<"string">;
|
|
822
|
+
length: z.ZodNumber;
|
|
823
|
+
}, "strip", z.ZodTypeAny, {
|
|
824
|
+
length: number;
|
|
825
|
+
type: "inline-input";
|
|
826
|
+
inputType: "string";
|
|
827
|
+
}, {
|
|
828
|
+
length: number;
|
|
829
|
+
type: "inline-input";
|
|
830
|
+
inputType: "string";
|
|
831
|
+
}>, z.ZodObject<{
|
|
832
|
+
type: z.ZodLiteral<"inline-input">;
|
|
833
|
+
inputType: z.ZodLiteral<"numeric">;
|
|
834
|
+
digits: z.ZodNumber;
|
|
835
|
+
}, "strip", z.ZodTypeAny, {
|
|
836
|
+
type: "inline-input";
|
|
837
|
+
inputType: "numeric";
|
|
838
|
+
digits: number;
|
|
839
|
+
}, {
|
|
840
|
+
type: "inline-input";
|
|
841
|
+
inputType: "numeric";
|
|
842
|
+
digits: number;
|
|
843
|
+
}>]>;
|
|
844
|
+
|
|
845
|
+
export declare type InlineInputWidget = z.infer<typeof InlineInputWidgetSchema>;
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* Inline input widget schema - small input that appears within a line
|
|
849
|
+
*
|
|
850
|
+
* This is for SHORT inputs (1-5 characters) that flow with text
|
|
851
|
+
* For longer inputs, consider a standalone tool
|
|
852
|
+
*
|
|
853
|
+
* @example String input (W_S_I):
|
|
854
|
+
* {
|
|
855
|
+
* type: "InlineInput",
|
|
856
|
+
* name: "x",
|
|
857
|
+
* inputType: "string",
|
|
858
|
+
* length: 5, // Visual width in characters
|
|
859
|
+
* answer: "hello"
|
|
860
|
+
* }
|
|
861
|
+
*
|
|
862
|
+
* @example Numeric input (W_N_I):
|
|
863
|
+
* {
|
|
864
|
+
* type: "InlineInput",
|
|
865
|
+
* name: "x",
|
|
866
|
+
* inputType: "numeric",
|
|
867
|
+
* digits: 2, // Maximum number of digits
|
|
868
|
+
* answer: 42
|
|
869
|
+
* }
|
|
870
|
+
*/
|
|
871
|
+
export declare const InlineInputWidgetSchema: z.ZodDiscriminatedUnion<"inputType", [z.ZodObject<{
|
|
872
|
+
type: z.ZodLiteral<"InlineInput">;
|
|
873
|
+
name: z.ZodString;
|
|
874
|
+
inputType: z.ZodLiteral<"string">;
|
|
875
|
+
length: z.ZodNumber;
|
|
876
|
+
answer: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
877
|
+
}, "strip", z.ZodTypeAny, {
|
|
878
|
+
length: number;
|
|
879
|
+
type: "InlineInput";
|
|
880
|
+
inputType: "string";
|
|
881
|
+
name: string;
|
|
882
|
+
answer?: string | number | undefined;
|
|
883
|
+
}, {
|
|
884
|
+
length: number;
|
|
885
|
+
type: "InlineInput";
|
|
886
|
+
inputType: "string";
|
|
887
|
+
name: string;
|
|
888
|
+
answer?: string | number | undefined;
|
|
889
|
+
}>, z.ZodObject<{
|
|
890
|
+
type: z.ZodLiteral<"InlineInput">;
|
|
891
|
+
name: z.ZodString;
|
|
892
|
+
inputType: z.ZodLiteral<"numeric">;
|
|
893
|
+
digits: z.ZodNumber;
|
|
894
|
+
answer: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
895
|
+
}, "strip", z.ZodTypeAny, {
|
|
896
|
+
type: "InlineInput";
|
|
897
|
+
inputType: "numeric";
|
|
898
|
+
name: string;
|
|
899
|
+
digits: number;
|
|
900
|
+
answer?: string | number | undefined;
|
|
901
|
+
}, {
|
|
902
|
+
type: "InlineInput";
|
|
903
|
+
inputType: "numeric";
|
|
904
|
+
name: string;
|
|
905
|
+
digits: number;
|
|
906
|
+
answer?: string | number | undefined;
|
|
907
|
+
}>]>;
|
|
908
|
+
|
|
909
|
+
export declare type InlineNode = z.infer<typeof InlineNodeSchema>;
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Union of all inline element types
|
|
913
|
+
*/
|
|
914
|
+
export declare const InlineNodeSchema: z.ZodUnion<[z.ZodObject<{
|
|
915
|
+
type: z.ZodLiteral<"FreeText">;
|
|
916
|
+
value: z.ZodString;
|
|
917
|
+
}, "strip", z.ZodTypeAny, {
|
|
918
|
+
value: string;
|
|
919
|
+
type: "FreeText";
|
|
920
|
+
}, {
|
|
921
|
+
value: string;
|
|
922
|
+
type: "FreeText";
|
|
923
|
+
}>, z.ZodObject<{
|
|
924
|
+
type: z.ZodLiteral<"Space">;
|
|
925
|
+
}, "strip", z.ZodTypeAny, {
|
|
926
|
+
type: "Space";
|
|
927
|
+
}, {
|
|
928
|
+
type: "Space";
|
|
929
|
+
}>, z.ZodObject<{
|
|
930
|
+
type: z.ZodLiteral<"NumberText">;
|
|
931
|
+
value: z.ZodString;
|
|
932
|
+
highlight: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
933
|
+
}, "strip", z.ZodTypeAny, {
|
|
934
|
+
value: string;
|
|
935
|
+
type: "NumberText";
|
|
936
|
+
highlight?: [number, number] | undefined;
|
|
937
|
+
}, {
|
|
938
|
+
value: string;
|
|
939
|
+
type: "NumberText";
|
|
940
|
+
highlight?: [number, number] | undefined;
|
|
941
|
+
}>, z.ZodDiscriminatedUnion<"inputType", [z.ZodObject<{
|
|
942
|
+
type: z.ZodLiteral<"InlineInput">;
|
|
943
|
+
name: z.ZodString;
|
|
944
|
+
inputType: z.ZodLiteral<"string">;
|
|
945
|
+
length: z.ZodNumber;
|
|
946
|
+
answer: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
947
|
+
}, "strip", z.ZodTypeAny, {
|
|
948
|
+
length: number;
|
|
949
|
+
type: "InlineInput";
|
|
950
|
+
inputType: "string";
|
|
951
|
+
name: string;
|
|
952
|
+
answer?: string | number | undefined;
|
|
953
|
+
}, {
|
|
954
|
+
length: number;
|
|
955
|
+
type: "InlineInput";
|
|
956
|
+
inputType: "string";
|
|
957
|
+
name: string;
|
|
958
|
+
answer?: string | number | undefined;
|
|
959
|
+
}>, z.ZodObject<{
|
|
960
|
+
type: z.ZodLiteral<"InlineInput">;
|
|
961
|
+
name: z.ZodString;
|
|
962
|
+
inputType: z.ZodLiteral<"numeric">;
|
|
963
|
+
digits: z.ZodNumber;
|
|
964
|
+
answer: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
965
|
+
}, "strip", z.ZodTypeAny, {
|
|
966
|
+
type: "InlineInput";
|
|
967
|
+
inputType: "numeric";
|
|
968
|
+
name: string;
|
|
969
|
+
digits: number;
|
|
970
|
+
answer?: string | number | undefined;
|
|
971
|
+
}, {
|
|
972
|
+
type: "InlineInput";
|
|
973
|
+
inputType: "numeric";
|
|
974
|
+
name: string;
|
|
975
|
+
digits: number;
|
|
976
|
+
answer?: string | number | undefined;
|
|
977
|
+
}>]>]>;
|
|
978
|
+
|
|
979
|
+
export declare function isDragOptions(value: unknown): value is DragOptionsTool;
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* Type guard for DragOptionsJSON
|
|
983
|
+
*/
|
|
984
|
+
export declare function isDragOptionsJSON(widget: WidgetJSON): widget is Extract<WidgetJSON, {
|
|
985
|
+
type: 'drag-options';
|
|
986
|
+
}>;
|
|
987
|
+
|
|
988
|
+
export declare function isExerciseDocument(value: unknown): value is ExerciseDocument;
|
|
989
|
+
|
|
990
|
+
export declare function isExpressionValidation(value: unknown): value is ExpressionValidation;
|
|
991
|
+
|
|
992
|
+
export declare function isFreeText(value: unknown): value is FreeTextInline;
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* Type guard for GroupItem
|
|
996
|
+
*/
|
|
997
|
+
export declare function isGroupItem(item: LayoutItem): item is Extract<LayoutItem, {
|
|
998
|
+
type: 'group';
|
|
999
|
+
}>;
|
|
1000
|
+
|
|
1001
|
+
export declare function isInlineInput(value: unknown): value is InlineInputWidget;
|
|
1002
|
+
|
|
1003
|
+
/**
|
|
1004
|
+
* Type guard for InlineInputJSON
|
|
1005
|
+
*/
|
|
1006
|
+
export declare function isInlineInputJSON(widget: WidgetJSON): widget is Extract<WidgetJSON, {
|
|
1007
|
+
type: 'inline-input';
|
|
1008
|
+
}>;
|
|
1009
|
+
|
|
1010
|
+
export declare function isInlineNode(value: unknown): value is InlineNode;
|
|
1011
|
+
|
|
1012
|
+
export declare function isLineBlock(value: unknown): value is LineBlock;
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Type guard for Linebreak
|
|
1016
|
+
*/
|
|
1017
|
+
export declare function isLinebreak(item: LayoutItem): item is Extract<LayoutItem, {
|
|
1018
|
+
type: 'linebreak';
|
|
1019
|
+
}>;
|
|
1020
|
+
|
|
1021
|
+
/**
|
|
1022
|
+
* Type guard for NumberText
|
|
1023
|
+
*/
|
|
1024
|
+
export declare function isNumberText(item: LayoutItem): item is Extract<LayoutItem, {
|
|
1025
|
+
type: 'number-text';
|
|
1026
|
+
}>;
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* @deprecated Use isInlineInputJSON instead
|
|
1030
|
+
*/
|
|
1031
|
+
export declare function isNumericInputJSON(widget: WidgetJSON): widget is Extract<WidgetJSON, {
|
|
1032
|
+
type: 'inline-input';
|
|
1033
|
+
}>;
|
|
1034
|
+
|
|
1035
|
+
export declare function isNumericKeypad(value: unknown): value is NumericKeypadTool;
|
|
1036
|
+
|
|
1037
|
+
/**
|
|
1038
|
+
* Type guard for NumericKeypadJSON
|
|
1039
|
+
*/
|
|
1040
|
+
export declare function isNumericKeypadJSON(widget: WidgetJSON): widget is Extract<WidgetJSON, {
|
|
1041
|
+
type: 'numeric-keypad';
|
|
1042
|
+
}>;
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* Type guard for OperatorItem
|
|
1046
|
+
*/
|
|
1047
|
+
export declare function isOperatorItem(item: LayoutItem): item is Extract<LayoutItem, {
|
|
1048
|
+
type: 'operator';
|
|
1049
|
+
}>;
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* Type guard for QuestionText
|
|
1053
|
+
*/
|
|
1054
|
+
export declare function isQuestionText(item: LayoutItem): item is Extract<LayoutItem, {
|
|
1055
|
+
type: 'question-text';
|
|
1056
|
+
}>;
|
|
1057
|
+
|
|
1058
|
+
export declare function isSimpleValidation(value: unknown): value is SimpleValidation;
|
|
1059
|
+
|
|
1060
|
+
export declare function isSpace(value: unknown): value is SpaceInline;
|
|
1061
|
+
|
|
1062
|
+
export declare function isTextBlock(value: unknown): value is TextBlock;
|
|
1063
|
+
|
|
1064
|
+
/**
|
|
1065
|
+
* Type guard for TextItem
|
|
1066
|
+
*/
|
|
1067
|
+
export declare function isTextItem(item: LayoutItem): item is Extract<LayoutItem, {
|
|
1068
|
+
type: 'text';
|
|
1069
|
+
}>;
|
|
1070
|
+
|
|
1071
|
+
export declare function isToolNode(value: unknown): value is ToolNode;
|
|
1072
|
+
|
|
1073
|
+
export declare function isValidationNode(value: unknown): value is ValidationNode;
|
|
1074
|
+
|
|
1075
|
+
/**
|
|
1076
|
+
* Check if an expression is syntactically valid
|
|
1077
|
+
*
|
|
1078
|
+
* @param expression - The expression to check
|
|
1079
|
+
* @returns true if valid, false otherwise
|
|
1080
|
+
*/
|
|
1081
|
+
export declare function isValidExpression(expression: string): boolean;
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* @deprecated Use isWidgetRef instead
|
|
1085
|
+
*/
|
|
1086
|
+
export declare function isWidgetPlaceholder(item: LayoutItem): item is Extract<LayoutItem, {
|
|
1087
|
+
type: 'widget-ref';
|
|
1088
|
+
}>;
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* Type guard for WidgetRef
|
|
1092
|
+
*/
|
|
1093
|
+
export declare function isWidgetRef(item: LayoutItem): item is Extract<LayoutItem, {
|
|
1094
|
+
type: 'widget-ref';
|
|
1095
|
+
}>;
|
|
1096
|
+
|
|
1097
|
+
export declare type LayoutItem = z.infer<typeof LayoutItemSchema>;
|
|
1098
|
+
|
|
1099
|
+
export declare const LayoutItemSchema: z.ZodType<any>;
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* DUMB layout renderer - no opinions about spacing or layout.
|
|
1103
|
+
*/
|
|
1104
|
+
export declare const LayoutRenderer: default_2.FC<LayoutRendererProps>;
|
|
1105
|
+
|
|
1106
|
+
export declare interface LayoutRendererProps {
|
|
1107
|
+
item: LayoutItem;
|
|
1108
|
+
widgets: Record<string, WidgetJSON>;
|
|
1109
|
+
values: Record<string, string>;
|
|
1110
|
+
droppedInputs: Set<string>;
|
|
1111
|
+
onChange: (widgetId: string, value: string, fromDrop?: boolean) => void;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/**
|
|
1115
|
+
* Error thrown when lexer fails to tokenize input
|
|
1116
|
+
*/
|
|
1117
|
+
export declare class LexerError extends EngineError {
|
|
1118
|
+
readonly lexerErrors: ILexingError[];
|
|
1119
|
+
readonly positions: SourcePosition[];
|
|
1120
|
+
constructor(errors: ILexingError[]);
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
export declare type LineBlock = z.infer<typeof LineBlockSchema>;
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* Line block schema - represents a visual row of inline elements
|
|
1127
|
+
*
|
|
1128
|
+
* One line = one visual row in the UI
|
|
1129
|
+
* Contains an ordered sequence of inline elements
|
|
1130
|
+
*
|
|
1131
|
+
* @example
|
|
1132
|
+
* {
|
|
1133
|
+
* type: "LineBlock",
|
|
1134
|
+
* inlines: [
|
|
1135
|
+
* { type: "NumberText", value: "151 000", highlight: [0, 3] },
|
|
1136
|
+
* { type: "InlineInput", name: "x", length: 1 },
|
|
1137
|
+
* { type: "NumberText", value: "54 000", highlight: [0, 3] }
|
|
1138
|
+
* ]
|
|
1139
|
+
* }
|
|
1140
|
+
*/
|
|
1141
|
+
export declare const LineBlockSchema: z.ZodObject<{
|
|
1142
|
+
type: z.ZodLiteral<"LineBlock">;
|
|
1143
|
+
inlines: z.ZodArray<z.ZodUnion<[z.ZodObject<{
|
|
1144
|
+
type: z.ZodLiteral<"FreeText">;
|
|
1145
|
+
value: z.ZodString;
|
|
1146
|
+
}, "strip", z.ZodTypeAny, {
|
|
1147
|
+
value: string;
|
|
1148
|
+
type: "FreeText";
|
|
1149
|
+
}, {
|
|
1150
|
+
value: string;
|
|
1151
|
+
type: "FreeText";
|
|
1152
|
+
}>, z.ZodObject<{
|
|
1153
|
+
type: z.ZodLiteral<"Space">;
|
|
1154
|
+
}, "strip", z.ZodTypeAny, {
|
|
1155
|
+
type: "Space";
|
|
1156
|
+
}, {
|
|
1157
|
+
type: "Space";
|
|
1158
|
+
}>, z.ZodObject<{
|
|
1159
|
+
type: z.ZodLiteral<"NumberText">;
|
|
1160
|
+
value: z.ZodString;
|
|
1161
|
+
highlight: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
1162
|
+
}, "strip", z.ZodTypeAny, {
|
|
1163
|
+
value: string;
|
|
1164
|
+
type: "NumberText";
|
|
1165
|
+
highlight?: [number, number] | undefined;
|
|
1166
|
+
}, {
|
|
1167
|
+
value: string;
|
|
1168
|
+
type: "NumberText";
|
|
1169
|
+
highlight?: [number, number] | undefined;
|
|
1170
|
+
}>, z.ZodDiscriminatedUnion<"inputType", [z.ZodObject<{
|
|
1171
|
+
type: z.ZodLiteral<"InlineInput">;
|
|
1172
|
+
name: z.ZodString;
|
|
1173
|
+
inputType: z.ZodLiteral<"string">;
|
|
1174
|
+
length: z.ZodNumber;
|
|
1175
|
+
answer: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
1176
|
+
}, "strip", z.ZodTypeAny, {
|
|
1177
|
+
length: number;
|
|
1178
|
+
type: "InlineInput";
|
|
1179
|
+
inputType: "string";
|
|
1180
|
+
name: string;
|
|
1181
|
+
answer?: string | number | undefined;
|
|
1182
|
+
}, {
|
|
1183
|
+
length: number;
|
|
1184
|
+
type: "InlineInput";
|
|
1185
|
+
inputType: "string";
|
|
1186
|
+
name: string;
|
|
1187
|
+
answer?: string | number | undefined;
|
|
1188
|
+
}>, z.ZodObject<{
|
|
1189
|
+
type: z.ZodLiteral<"InlineInput">;
|
|
1190
|
+
name: z.ZodString;
|
|
1191
|
+
inputType: z.ZodLiteral<"numeric">;
|
|
1192
|
+
digits: z.ZodNumber;
|
|
1193
|
+
answer: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
1194
|
+
}, "strip", z.ZodTypeAny, {
|
|
1195
|
+
type: "InlineInput";
|
|
1196
|
+
inputType: "numeric";
|
|
1197
|
+
name: string;
|
|
1198
|
+
digits: number;
|
|
1199
|
+
answer?: string | number | undefined;
|
|
1200
|
+
}, {
|
|
1201
|
+
type: "InlineInput";
|
|
1202
|
+
inputType: "numeric";
|
|
1203
|
+
name: string;
|
|
1204
|
+
digits: number;
|
|
1205
|
+
answer?: string | number | undefined;
|
|
1206
|
+
}>]>]>, "many">;
|
|
1207
|
+
}, "strip", z.ZodTypeAny, {
|
|
1208
|
+
type: "LineBlock";
|
|
1209
|
+
inlines: ({
|
|
1210
|
+
value: string;
|
|
1211
|
+
type: "FreeText";
|
|
1212
|
+
} | {
|
|
1213
|
+
type: "Space";
|
|
1214
|
+
} | {
|
|
1215
|
+
value: string;
|
|
1216
|
+
type: "NumberText";
|
|
1217
|
+
highlight?: [number, number] | undefined;
|
|
1218
|
+
} | {
|
|
1219
|
+
length: number;
|
|
1220
|
+
type: "InlineInput";
|
|
1221
|
+
inputType: "string";
|
|
1222
|
+
name: string;
|
|
1223
|
+
answer?: string | number | undefined;
|
|
1224
|
+
} | {
|
|
1225
|
+
type: "InlineInput";
|
|
1226
|
+
inputType: "numeric";
|
|
1227
|
+
name: string;
|
|
1228
|
+
digits: number;
|
|
1229
|
+
answer?: string | number | undefined;
|
|
1230
|
+
})[];
|
|
1231
|
+
}, {
|
|
1232
|
+
type: "LineBlock";
|
|
1233
|
+
inlines: ({
|
|
1234
|
+
value: string;
|
|
1235
|
+
type: "FreeText";
|
|
1236
|
+
} | {
|
|
1237
|
+
type: "Space";
|
|
1238
|
+
} | {
|
|
1239
|
+
value: string;
|
|
1240
|
+
type: "NumberText";
|
|
1241
|
+
highlight?: [number, number] | undefined;
|
|
1242
|
+
} | {
|
|
1243
|
+
length: number;
|
|
1244
|
+
type: "InlineInput";
|
|
1245
|
+
inputType: "string";
|
|
1246
|
+
name: string;
|
|
1247
|
+
answer?: string | number | undefined;
|
|
1248
|
+
} | {
|
|
1249
|
+
type: "InlineInput";
|
|
1250
|
+
inputType: "numeric";
|
|
1251
|
+
name: string;
|
|
1252
|
+
digits: number;
|
|
1253
|
+
answer?: string | number | undefined;
|
|
1254
|
+
})[];
|
|
1255
|
+
}>;
|
|
1256
|
+
|
|
1257
|
+
export declare type Linebreak = z.infer<typeof LinebreakSchema>;
|
|
1258
|
+
|
|
1259
|
+
export declare const LinebreakSchema: z.ZodObject<{
|
|
1260
|
+
id: z.ZodString;
|
|
1261
|
+
type: z.ZodLiteral<"linebreak">;
|
|
1262
|
+
}, "strip", z.ZodTypeAny, {
|
|
1263
|
+
type: "linebreak";
|
|
1264
|
+
id: string;
|
|
1265
|
+
}, {
|
|
1266
|
+
type: "linebreak";
|
|
1267
|
+
id: string;
|
|
1268
|
+
}>;
|
|
1269
|
+
|
|
1270
|
+
export declare type NumberText = z.infer<typeof NumberTextSchema>;
|
|
1271
|
+
|
|
1272
|
+
export declare type NumberTextInline = z.infer<typeof NumberTextInlineSchema>;
|
|
1273
|
+
|
|
1274
|
+
/**
|
|
1275
|
+
* Number text inline schema - styled numbers with optional highlighting
|
|
1276
|
+
*
|
|
1277
|
+
* highlight: [start, end] character positions for visual emphasis
|
|
1278
|
+
*
|
|
1279
|
+
* @example
|
|
1280
|
+
* {
|
|
1281
|
+
* type: "NumberText",
|
|
1282
|
+
* value: "151 000",
|
|
1283
|
+
* highlight: [0, 3] // Highlights "151"
|
|
1284
|
+
* }
|
|
1285
|
+
*/
|
|
1286
|
+
export declare const NumberTextInlineSchema: z.ZodObject<{
|
|
1287
|
+
type: z.ZodLiteral<"NumberText">;
|
|
1288
|
+
value: z.ZodString;
|
|
1289
|
+
highlight: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
1290
|
+
}, "strip", z.ZodTypeAny, {
|
|
1291
|
+
value: string;
|
|
1292
|
+
type: "NumberText";
|
|
1293
|
+
highlight?: [number, number] | undefined;
|
|
1294
|
+
}, {
|
|
1295
|
+
value: string;
|
|
1296
|
+
type: "NumberText";
|
|
1297
|
+
highlight?: [number, number] | undefined;
|
|
1298
|
+
}>;
|
|
1299
|
+
|
|
1300
|
+
export declare const NumberTextSchema: z.ZodObject<{
|
|
1301
|
+
id: z.ZodString;
|
|
1302
|
+
type: z.ZodLiteral<"number-text">;
|
|
1303
|
+
value: z.ZodString;
|
|
1304
|
+
highlight: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
1305
|
+
}, "strip", z.ZodTypeAny, {
|
|
1306
|
+
value: string;
|
|
1307
|
+
type: "number-text";
|
|
1308
|
+
id: string;
|
|
1309
|
+
highlight?: [number, number] | undefined;
|
|
1310
|
+
}, {
|
|
1311
|
+
value: string;
|
|
1312
|
+
type: "number-text";
|
|
1313
|
+
id: string;
|
|
1314
|
+
highlight?: [number, number] | undefined;
|
|
1315
|
+
}>;
|
|
1316
|
+
|
|
1317
|
+
export declare type NumericKeypadJSON = z.infer<typeof NumericKeypadJSONSchema>;
|
|
1318
|
+
|
|
1319
|
+
export declare const NumericKeypadJSONSchema: z.ZodObject<{
|
|
1320
|
+
type: z.ZodLiteral<"numeric-keypad">;
|
|
1321
|
+
includeDecimal: z.ZodBoolean;
|
|
1322
|
+
}, "strip", z.ZodTypeAny, {
|
|
1323
|
+
type: "numeric-keypad";
|
|
1324
|
+
includeDecimal: boolean;
|
|
1325
|
+
}, {
|
|
1326
|
+
type: "numeric-keypad";
|
|
1327
|
+
includeDecimal: boolean;
|
|
1328
|
+
}>;
|
|
1329
|
+
|
|
1330
|
+
export declare type NumericKeypadTool = z.infer<typeof NumericKeypadToolSchema>;
|
|
1331
|
+
|
|
1332
|
+
/**
|
|
1333
|
+
* Numeric keypad tool schema - on-screen number pad
|
|
1334
|
+
*
|
|
1335
|
+
* Use cases:
|
|
1336
|
+
* - Touch-friendly number entry
|
|
1337
|
+
* - Restricting input to numbers only
|
|
1338
|
+
* - Consistent cross-device experience
|
|
1339
|
+
*
|
|
1340
|
+
* @example
|
|
1341
|
+
* {
|
|
1342
|
+
* type: "NumericKeypad",
|
|
1343
|
+
* includeDecimal: false,
|
|
1344
|
+
* includeNegative: true
|
|
1345
|
+
* }
|
|
1346
|
+
*/
|
|
1347
|
+
export declare const NumericKeypadToolSchema: z.ZodObject<{
|
|
1348
|
+
type: z.ZodLiteral<"NumericKeypad">;
|
|
1349
|
+
includeDecimal: z.ZodDefault<z.ZodBoolean>;
|
|
1350
|
+
includeNegative: z.ZodDefault<z.ZodBoolean>;
|
|
1351
|
+
}, "strip", z.ZodTypeAny, {
|
|
1352
|
+
type: "NumericKeypad";
|
|
1353
|
+
includeDecimal: boolean;
|
|
1354
|
+
includeNegative: boolean;
|
|
1355
|
+
}, {
|
|
1356
|
+
type: "NumericKeypad";
|
|
1357
|
+
includeDecimal?: boolean | undefined;
|
|
1358
|
+
includeNegative?: boolean | undefined;
|
|
1359
|
+
}>;
|
|
1360
|
+
|
|
1361
|
+
export declare type OperatorItem = z.infer<typeof OperatorItemSchema>;
|
|
1362
|
+
|
|
1363
|
+
export declare const OperatorItemSchema: z.ZodObject<{
|
|
1364
|
+
id: z.ZodString;
|
|
1365
|
+
type: z.ZodLiteral<"operator">;
|
|
1366
|
+
operator: z.ZodEnum<["+", "-", "×", "÷", "=", "<", ">", "?"]>;
|
|
1367
|
+
}, "strip", z.ZodTypeAny, {
|
|
1368
|
+
type: "operator";
|
|
1369
|
+
id: string;
|
|
1370
|
+
operator: "+" | "-" | "×" | "÷" | "=" | "<" | ">" | "?";
|
|
1371
|
+
}, {
|
|
1372
|
+
type: "operator";
|
|
1373
|
+
id: string;
|
|
1374
|
+
operator: "+" | "-" | "×" | "÷" | "=" | "<" | ">" | "?";
|
|
1375
|
+
}>;
|
|
1376
|
+
|
|
1377
|
+
export declare const OperatorSchema: z.ZodEnum<["+", "-", "×", "÷", "=", "<", ">", "?"]>;
|
|
1378
|
+
|
|
1379
|
+
/**
|
|
1380
|
+
* Parse DSL tokens into CST
|
|
1381
|
+
*/
|
|
1382
|
+
export declare function parse(tokens: IToken[]): CstNode;
|
|
1383
|
+
|
|
1384
|
+
/**
|
|
1385
|
+
* Error thrown when parser fails to parse tokens
|
|
1386
|
+
*/
|
|
1387
|
+
export declare class ParseError extends EngineError {
|
|
1388
|
+
readonly parseErrors: IRecognitionException[];
|
|
1389
|
+
readonly positions: SourcePosition[];
|
|
1390
|
+
constructor(errors: IRecognitionException[]);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
/**
|
|
1394
|
+
* Parse DSL tokens into CST (safe version - returns errors instead of throwing)
|
|
1395
|
+
*/
|
|
1396
|
+
export declare function parseSafe(tokens: IToken[]): {
|
|
1397
|
+
success: true;
|
|
1398
|
+
cst: CstNode;
|
|
1399
|
+
error?: undefined;
|
|
1400
|
+
} | {
|
|
1401
|
+
success: false;
|
|
1402
|
+
error: unknown;
|
|
1403
|
+
cst?: undefined;
|
|
1404
|
+
};
|
|
1405
|
+
|
|
1406
|
+
export declare type QuestionText = z.infer<typeof QuestionTextSchema>;
|
|
1407
|
+
|
|
1408
|
+
export declare const QuestionTextSchema: z.ZodObject<{
|
|
1409
|
+
id: z.ZodString;
|
|
1410
|
+
type: z.ZodLiteral<"question-text">;
|
|
1411
|
+
value: z.ZodString;
|
|
1412
|
+
}, "strip", z.ZodTypeAny, {
|
|
1413
|
+
value: string;
|
|
1414
|
+
type: "question-text";
|
|
1415
|
+
id: string;
|
|
1416
|
+
}, {
|
|
1417
|
+
value: string;
|
|
1418
|
+
type: "question-text";
|
|
1419
|
+
id: string;
|
|
1420
|
+
}>;
|
|
1421
|
+
|
|
1422
|
+
/**
|
|
1423
|
+
* DOM helper for quick usage / demos.
|
|
1424
|
+
*
|
|
1425
|
+
* This couples the engine to DOM + React root creation.
|
|
1426
|
+
* For production use, prefer <ExerciseRenderer /> directly in your React tree.
|
|
1427
|
+
*
|
|
1428
|
+
* @example
|
|
1429
|
+
* ```typescript
|
|
1430
|
+
* import { compile, renderExercise } from 'math-exercise-engine';
|
|
1431
|
+
*
|
|
1432
|
+
* const json = compile(dsl);
|
|
1433
|
+
* const unmount = renderExercise({
|
|
1434
|
+
* container: '#app',
|
|
1435
|
+
* json,
|
|
1436
|
+
* onSubmit: (values) => {
|
|
1437
|
+
* // Parent decides correctness
|
|
1438
|
+
* const result = validate(json, values);
|
|
1439
|
+
* console.log(result.isCorrect);
|
|
1440
|
+
* }
|
|
1441
|
+
* });
|
|
1442
|
+
*
|
|
1443
|
+
* // Later: unmount()
|
|
1444
|
+
* ```
|
|
1445
|
+
*/
|
|
1446
|
+
export declare function renderExercise(options: RenderOptions): () => void;
|
|
1447
|
+
|
|
1448
|
+
export declare interface RenderOptions {
|
|
1449
|
+
container: HTMLElement | string;
|
|
1450
|
+
json: ExerciseJSON;
|
|
1451
|
+
onSubmit?: (values: Record<string, string>) => void;
|
|
1452
|
+
onChange?: (values: Record<string, string>) => void;
|
|
1453
|
+
showSubmitButton?: boolean;
|
|
1454
|
+
className?: string;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
export declare type SimpleValidation = z.infer<typeof SimpleValidationSchema>;
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
* Simple validation schema - direct answer matching
|
|
1461
|
+
*
|
|
1462
|
+
* Each input has a predetermined correct answer.
|
|
1463
|
+
* No complex expressions or calculations.
|
|
1464
|
+
*
|
|
1465
|
+
* @example
|
|
1466
|
+
* {
|
|
1467
|
+
* type: "SimpleValidation"
|
|
1468
|
+
* }
|
|
1469
|
+
*
|
|
1470
|
+
* Note: Actual answer values are stored separately (in widget definitions)
|
|
1471
|
+
*/
|
|
1472
|
+
export declare const SimpleValidationSchema: z.ZodObject<{
|
|
1473
|
+
type: z.ZodLiteral<"SimpleValidation">;
|
|
1474
|
+
}, "strip", z.ZodTypeAny, {
|
|
1475
|
+
type: "SimpleValidation";
|
|
1476
|
+
}, {
|
|
1477
|
+
type: "SimpleValidation";
|
|
1478
|
+
}>;
|
|
1479
|
+
|
|
1480
|
+
/**
|
|
1481
|
+
* Source position information for error reporting
|
|
1482
|
+
*/
|
|
1483
|
+
export declare interface SourcePosition {
|
|
1484
|
+
startLine: number;
|
|
1485
|
+
startColumn: number;
|
|
1486
|
+
endLine: number;
|
|
1487
|
+
endColumn: number;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
export declare type SpaceInline = z.infer<typeof SpaceInlineSchema>;
|
|
1491
|
+
|
|
1492
|
+
/**
|
|
1493
|
+
* Space inline schema - explicit spacing element
|
|
1494
|
+
*
|
|
1495
|
+
* Represents one or more consecutive spaces as a single space element.
|
|
1496
|
+
* This allows for deterministic and explicit control over spacing in the layout.
|
|
1497
|
+
*
|
|
1498
|
+
* @example
|
|
1499
|
+
* { type: "Space" }
|
|
1500
|
+
*/
|
|
1501
|
+
export declare const SpaceInlineSchema: z.ZodObject<{
|
|
1502
|
+
type: z.ZodLiteral<"Space">;
|
|
1503
|
+
}, "strip", z.ZodTypeAny, {
|
|
1504
|
+
type: "Space";
|
|
1505
|
+
}, {
|
|
1506
|
+
type: "Space";
|
|
1507
|
+
}>;
|
|
1508
|
+
|
|
1509
|
+
export declare type TextBlock = z.infer<typeof TextBlockSchema>;
|
|
1510
|
+
|
|
1511
|
+
/**
|
|
1512
|
+
* Text block schema - represents the question/instruction
|
|
1513
|
+
*
|
|
1514
|
+
* @example
|
|
1515
|
+
* {
|
|
1516
|
+
* type: "TextBlock",
|
|
1517
|
+
* value: "أقارن كل عددين باستعمال الرمر المناسب"
|
|
1518
|
+
* }
|
|
1519
|
+
*/
|
|
1520
|
+
export declare const TextBlockSchema: z.ZodObject<{
|
|
1521
|
+
type: z.ZodLiteral<"TextBlock">;
|
|
1522
|
+
value: z.ZodString;
|
|
1523
|
+
}, "strip", z.ZodTypeAny, {
|
|
1524
|
+
value: string;
|
|
1525
|
+
type: "TextBlock";
|
|
1526
|
+
}, {
|
|
1527
|
+
value: string;
|
|
1528
|
+
type: "TextBlock";
|
|
1529
|
+
}>;
|
|
1530
|
+
|
|
1531
|
+
export declare type TextItem = z.infer<typeof TextItemSchema>;
|
|
1532
|
+
|
|
1533
|
+
export declare const TextItemSchema: z.ZodObject<{
|
|
1534
|
+
id: z.ZodString;
|
|
1535
|
+
type: z.ZodLiteral<"text">;
|
|
1536
|
+
value: z.ZodString;
|
|
1537
|
+
}, "strip", z.ZodTypeAny, {
|
|
1538
|
+
value: string;
|
|
1539
|
+
type: "text";
|
|
1540
|
+
id: string;
|
|
1541
|
+
}, {
|
|
1542
|
+
value: string;
|
|
1543
|
+
type: "text";
|
|
1544
|
+
id: string;
|
|
1545
|
+
}>;
|
|
1546
|
+
|
|
1547
|
+
/**
|
|
1548
|
+
* Transform CST to AST
|
|
1549
|
+
*/
|
|
1550
|
+
export declare function toAST(cst: any): ExerciseDocument;
|
|
1551
|
+
|
|
1552
|
+
/**
|
|
1553
|
+
* Transform AST to JSON
|
|
1554
|
+
*
|
|
1555
|
+
* The JSON format is what gets consumed by renderers and validators
|
|
1556
|
+
*/
|
|
1557
|
+
export declare function toJSON(ast: ExerciseDocument): ExerciseJSON;
|
|
1558
|
+
|
|
1559
|
+
/**
|
|
1560
|
+
* Tokenize a DSL input string
|
|
1561
|
+
*
|
|
1562
|
+
* @param input - The DSL text to tokenize
|
|
1563
|
+
* @returns Array of tokens
|
|
1564
|
+
* @throws LexerError if tokenization fails
|
|
1565
|
+
*/
|
|
1566
|
+
export declare function tokenize(input: string): IToken[];
|
|
1567
|
+
|
|
1568
|
+
/**
|
|
1569
|
+
* Result of tokenization
|
|
1570
|
+
*/
|
|
1571
|
+
declare interface TokenizeResult {
|
|
1572
|
+
tokens: IToken[];
|
|
1573
|
+
errors: ILexingError[];
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
/**
|
|
1577
|
+
* Tokenize without throwing - returns both tokens and errors
|
|
1578
|
+
* Useful for error-tolerant parsing (e.g., in editors)
|
|
1579
|
+
*/
|
|
1580
|
+
export declare function tokenizeSafe(input: string): TokenizeResult;
|
|
1581
|
+
|
|
1582
|
+
export declare type ToolNode = z.infer<typeof ToolNodeSchema>;
|
|
1583
|
+
|
|
1584
|
+
/**
|
|
1585
|
+
* Union of all tool types
|
|
1586
|
+
*/
|
|
1587
|
+
export declare const ToolNodeSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
1588
|
+
type: z.ZodLiteral<"DragOptions">;
|
|
1589
|
+
options: z.ZodArray<z.ZodString, "many">;
|
|
1590
|
+
}, "strip", z.ZodTypeAny, {
|
|
1591
|
+
type: "DragOptions";
|
|
1592
|
+
options: string[];
|
|
1593
|
+
}, {
|
|
1594
|
+
type: "DragOptions";
|
|
1595
|
+
options: string[];
|
|
1596
|
+
}>, z.ZodObject<{
|
|
1597
|
+
type: z.ZodLiteral<"NumericKeypad">;
|
|
1598
|
+
includeDecimal: z.ZodDefault<z.ZodBoolean>;
|
|
1599
|
+
includeNegative: z.ZodDefault<z.ZodBoolean>;
|
|
1600
|
+
}, "strip", z.ZodTypeAny, {
|
|
1601
|
+
type: "NumericKeypad";
|
|
1602
|
+
includeDecimal: boolean;
|
|
1603
|
+
includeNegative: boolean;
|
|
1604
|
+
}, {
|
|
1605
|
+
type: "NumericKeypad";
|
|
1606
|
+
includeDecimal?: boolean | undefined;
|
|
1607
|
+
includeNegative?: boolean | undefined;
|
|
1608
|
+
}>]>;
|
|
1609
|
+
|
|
1610
|
+
/**
|
|
1611
|
+
* Error thrown during AST transformation
|
|
1612
|
+
*/
|
|
1613
|
+
export declare class TransformError extends EngineError {
|
|
1614
|
+
readonly position?: SourcePosition;
|
|
1615
|
+
constructor(message: string, position?: SourcePosition);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
/**
|
|
1619
|
+
* Validate user inputs against an exercise
|
|
1620
|
+
*
|
|
1621
|
+
* This is the main entry point for validation. It automatically
|
|
1622
|
+
* dispatches to the correct validation mode based on the exercise.
|
|
1623
|
+
*
|
|
1624
|
+
* @param exercise - The exercise JSON
|
|
1625
|
+
* @param userInputs - User's answers keyed by widget ID
|
|
1626
|
+
* @returns Validation result
|
|
1627
|
+
*
|
|
1628
|
+
* @example
|
|
1629
|
+
* ```typescript
|
|
1630
|
+
* const result = validate(exercise, { a: 10, b: 20 });
|
|
1631
|
+
* if (result.isCorrect) {
|
|
1632
|
+
* console.log('Correct!');
|
|
1633
|
+
* } else {
|
|
1634
|
+
* console.log('Try again');
|
|
1635
|
+
* }
|
|
1636
|
+
* ```
|
|
1637
|
+
*/
|
|
1638
|
+
export declare function validate(exercise: ExerciseJSON, userInputs: Record<string, string | number>): ValidationResult;
|
|
1639
|
+
|
|
1640
|
+
/**
|
|
1641
|
+
* Validate that an expression will return a boolean
|
|
1642
|
+
*
|
|
1643
|
+
* @param expression - The expression to check
|
|
1644
|
+
* @returns Error message if invalid, null if valid
|
|
1645
|
+
*/
|
|
1646
|
+
export declare function validateBooleanExpression(expression: string): string | null;
|
|
1647
|
+
|
|
1648
|
+
/**
|
|
1649
|
+
* Validate an exercise JSON object at runtime
|
|
1650
|
+
*
|
|
1651
|
+
* @param data - The data to validate
|
|
1652
|
+
* @returns Parsed and validated exercise JSON
|
|
1653
|
+
* @throws ZodError if validation fails
|
|
1654
|
+
*
|
|
1655
|
+
* @example
|
|
1656
|
+
* ```typescript
|
|
1657
|
+
* try {
|
|
1658
|
+
* const validated = validateExerciseJSON(unknownData);
|
|
1659
|
+
* console.log('Valid exercise:', validated);
|
|
1660
|
+
* } catch (error) {
|
|
1661
|
+
* console.error('Validation failed:', error);
|
|
1662
|
+
* }
|
|
1663
|
+
* ```
|
|
1664
|
+
*/
|
|
1665
|
+
export declare function validateExerciseJSON(data: unknown): {
|
|
1666
|
+
validation: {
|
|
1667
|
+
mode: "expression" | "simple";
|
|
1668
|
+
expression?: string | undefined;
|
|
1669
|
+
answers?: Record<string, string | number> | undefined;
|
|
1670
|
+
variables?: string[] | undefined;
|
|
1671
|
+
};
|
|
1672
|
+
version: "2.0";
|
|
1673
|
+
layout: any[];
|
|
1674
|
+
widgets: Record<string, {
|
|
1675
|
+
length: number;
|
|
1676
|
+
type: "inline-input";
|
|
1677
|
+
inputType: "string";
|
|
1678
|
+
} | {
|
|
1679
|
+
type: "inline-input";
|
|
1680
|
+
inputType: "numeric";
|
|
1681
|
+
digits: number;
|
|
1682
|
+
} | {
|
|
1683
|
+
type: "drag-options";
|
|
1684
|
+
options: string[];
|
|
1685
|
+
} | {
|
|
1686
|
+
type: "numeric-keypad";
|
|
1687
|
+
includeDecimal: boolean;
|
|
1688
|
+
}>;
|
|
1689
|
+
id?: string | undefined;
|
|
1690
|
+
meta?: {
|
|
1691
|
+
createdAt?: string | undefined;
|
|
1692
|
+
author?: string | undefined;
|
|
1693
|
+
tags?: string[] | undefined;
|
|
1694
|
+
difficulty?: number | undefined;
|
|
1695
|
+
} | undefined;
|
|
1696
|
+
};
|
|
1697
|
+
|
|
1698
|
+
/**
|
|
1699
|
+
* Safely validate an exercise JSON object at runtime
|
|
1700
|
+
*
|
|
1701
|
+
* @param data - The data to validate
|
|
1702
|
+
* @returns Success result with data or error result
|
|
1703
|
+
*
|
|
1704
|
+
* @example
|
|
1705
|
+
* ```typescript
|
|
1706
|
+
* const result = validateExerciseJSONSafe(unknownData);
|
|
1707
|
+
* if (result.success) {
|
|
1708
|
+
* console.log('Valid exercise:', result.data);
|
|
1709
|
+
* } else {
|
|
1710
|
+
* console.error('Validation errors:', result.error.errors);
|
|
1711
|
+
* }
|
|
1712
|
+
* ```
|
|
1713
|
+
*/
|
|
1714
|
+
export declare function validateExerciseJSONSafe(data: unknown): z.SafeParseReturnType<{
|
|
1715
|
+
validation: {
|
|
1716
|
+
mode: "expression" | "simple";
|
|
1717
|
+
expression?: string | undefined;
|
|
1718
|
+
answers?: Record<string, string | number> | undefined;
|
|
1719
|
+
variables?: string[] | undefined;
|
|
1720
|
+
};
|
|
1721
|
+
version: "2.0";
|
|
1722
|
+
layout: any[];
|
|
1723
|
+
widgets: Record<string, {
|
|
1724
|
+
length: number;
|
|
1725
|
+
type: "inline-input";
|
|
1726
|
+
inputType: "string";
|
|
1727
|
+
} | {
|
|
1728
|
+
type: "inline-input";
|
|
1729
|
+
inputType: "numeric";
|
|
1730
|
+
digits: number;
|
|
1731
|
+
} | {
|
|
1732
|
+
type: "drag-options";
|
|
1733
|
+
options: string[];
|
|
1734
|
+
} | {
|
|
1735
|
+
type: "numeric-keypad";
|
|
1736
|
+
includeDecimal: boolean;
|
|
1737
|
+
}>;
|
|
1738
|
+
id?: string | undefined;
|
|
1739
|
+
meta?: {
|
|
1740
|
+
createdAt?: string | undefined;
|
|
1741
|
+
author?: string | undefined;
|
|
1742
|
+
tags?: string[] | undefined;
|
|
1743
|
+
difficulty?: number | undefined;
|
|
1744
|
+
} | undefined;
|
|
1745
|
+
}, {
|
|
1746
|
+
validation: {
|
|
1747
|
+
mode: "expression" | "simple";
|
|
1748
|
+
expression?: string | undefined;
|
|
1749
|
+
answers?: Record<string, string | number> | undefined;
|
|
1750
|
+
variables?: string[] | undefined;
|
|
1751
|
+
};
|
|
1752
|
+
version: "2.0";
|
|
1753
|
+
layout: any[];
|
|
1754
|
+
widgets: Record<string, {
|
|
1755
|
+
length: number;
|
|
1756
|
+
type: "inline-input";
|
|
1757
|
+
inputType: "string";
|
|
1758
|
+
} | {
|
|
1759
|
+
type: "inline-input";
|
|
1760
|
+
inputType: "numeric";
|
|
1761
|
+
digits: number;
|
|
1762
|
+
} | {
|
|
1763
|
+
type: "drag-options";
|
|
1764
|
+
options: string[];
|
|
1765
|
+
} | {
|
|
1766
|
+
type: "numeric-keypad";
|
|
1767
|
+
includeDecimal: boolean;
|
|
1768
|
+
}>;
|
|
1769
|
+
id?: string | undefined;
|
|
1770
|
+
meta?: {
|
|
1771
|
+
createdAt?: string | undefined;
|
|
1772
|
+
author?: string | undefined;
|
|
1773
|
+
tags?: string[] | undefined;
|
|
1774
|
+
difficulty?: number | undefined;
|
|
1775
|
+
} | undefined;
|
|
1776
|
+
}>;
|
|
1777
|
+
|
|
1778
|
+
/**
|
|
1779
|
+
* Validate using expression mode
|
|
1780
|
+
*
|
|
1781
|
+
* @param exercise - The exercise JSON
|
|
1782
|
+
* @param userInputs - User's answers keyed by widget ID (variable names)
|
|
1783
|
+
* @returns Validation result
|
|
1784
|
+
*/
|
|
1785
|
+
export declare function validateExpression(exercise: ExerciseJSON, userInputs: Record<string, string | number>): ValidationResult;
|
|
1786
|
+
|
|
1787
|
+
/**
|
|
1788
|
+
* Check if user inputs are valid (proper format, etc.)
|
|
1789
|
+
* without checking correctness
|
|
1790
|
+
*
|
|
1791
|
+
* @param exercise - The exercise JSON
|
|
1792
|
+
* @param userInputs - User's answers
|
|
1793
|
+
* @returns Object with widgetId -> error message (empty if all valid)
|
|
1794
|
+
*/
|
|
1795
|
+
export declare function validateInputFormats(exercise: ExerciseJSON, userInputs: Record<string, string | number>): Record<string, string>;
|
|
1796
|
+
|
|
1797
|
+
/**
|
|
1798
|
+
* Validate using simple mode (predetermined answers)
|
|
1799
|
+
*
|
|
1800
|
+
* @param exercise - The exercise JSON
|
|
1801
|
+
* @param userInputs - User's answers keyed by widget ID
|
|
1802
|
+
* @returns Validation result
|
|
1803
|
+
*/
|
|
1804
|
+
export declare function validateSimple(exercise: ExerciseJSON, userInputs: Record<string, string | number>): ValidationResult;
|
|
1805
|
+
|
|
1806
|
+
/**
|
|
1807
|
+
* Validate a widget JSON object at runtime
|
|
1808
|
+
*
|
|
1809
|
+
* @param data - The data to validate
|
|
1810
|
+
* @returns Parsed and validated widget JSON
|
|
1811
|
+
* @throws ZodError if validation fails
|
|
1812
|
+
*/
|
|
1813
|
+
export declare function validateWidgetJSON(data: unknown): {
|
|
1814
|
+
length: number;
|
|
1815
|
+
type: "inline-input";
|
|
1816
|
+
inputType: "string";
|
|
1817
|
+
} | {
|
|
1818
|
+
type: "inline-input";
|
|
1819
|
+
inputType: "numeric";
|
|
1820
|
+
digits: number;
|
|
1821
|
+
} | {
|
|
1822
|
+
type: "drag-options";
|
|
1823
|
+
options: string[];
|
|
1824
|
+
} | {
|
|
1825
|
+
type: "numeric-keypad";
|
|
1826
|
+
includeDecimal: boolean;
|
|
1827
|
+
};
|
|
1828
|
+
|
|
1829
|
+
/**
|
|
1830
|
+
* Safely validate a widget JSON object at runtime
|
|
1831
|
+
*
|
|
1832
|
+
* @param data - The data to validate
|
|
1833
|
+
* @returns Success result with data or error result
|
|
1834
|
+
*/
|
|
1835
|
+
export declare function validateWidgetJSONSafe(data: unknown): z.SafeParseReturnType<{
|
|
1836
|
+
length: number;
|
|
1837
|
+
type: "inline-input";
|
|
1838
|
+
inputType: "string";
|
|
1839
|
+
} | {
|
|
1840
|
+
type: "inline-input";
|
|
1841
|
+
inputType: "numeric";
|
|
1842
|
+
digits: number;
|
|
1843
|
+
} | {
|
|
1844
|
+
type: "drag-options";
|
|
1845
|
+
options: string[];
|
|
1846
|
+
} | {
|
|
1847
|
+
type: "numeric-keypad";
|
|
1848
|
+
includeDecimal: boolean;
|
|
1849
|
+
}, {
|
|
1850
|
+
length: number;
|
|
1851
|
+
type: "inline-input";
|
|
1852
|
+
inputType: "string";
|
|
1853
|
+
} | {
|
|
1854
|
+
type: "inline-input";
|
|
1855
|
+
inputType: "numeric";
|
|
1856
|
+
digits: number;
|
|
1857
|
+
} | {
|
|
1858
|
+
type: "drag-options";
|
|
1859
|
+
options: string[];
|
|
1860
|
+
} | {
|
|
1861
|
+
type: "numeric-keypad";
|
|
1862
|
+
includeDecimal: boolean;
|
|
1863
|
+
}>;
|
|
1864
|
+
|
|
1865
|
+
/**
|
|
1866
|
+
* Error thrown during validation
|
|
1867
|
+
*/
|
|
1868
|
+
export declare class ValidationError extends EngineError {
|
|
1869
|
+
readonly details: Record<string, string>;
|
|
1870
|
+
constructor(message: string, details?: Record<string, string>);
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
export declare type ValidationJSON = z.infer<typeof ValidationJSONSchema>;
|
|
1874
|
+
|
|
1875
|
+
export declare const ValidationJSONSchema: z.ZodObject<{
|
|
1876
|
+
mode: z.ZodEnum<["simple", "expression"]>;
|
|
1877
|
+
answers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber]>>>;
|
|
1878
|
+
expression: z.ZodOptional<z.ZodString>;
|
|
1879
|
+
variables: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1880
|
+
}, "strip", z.ZodTypeAny, {
|
|
1881
|
+
mode: "expression" | "simple";
|
|
1882
|
+
expression?: string | undefined;
|
|
1883
|
+
answers?: Record<string, string | number> | undefined;
|
|
1884
|
+
variables?: string[] | undefined;
|
|
1885
|
+
}, {
|
|
1886
|
+
mode: "expression" | "simple";
|
|
1887
|
+
expression?: string | undefined;
|
|
1888
|
+
answers?: Record<string, string | number> | undefined;
|
|
1889
|
+
variables?: string[] | undefined;
|
|
1890
|
+
}>;
|
|
1891
|
+
|
|
1892
|
+
export declare type ValidationNode = z.infer<typeof ValidationNodeSchema>;
|
|
1893
|
+
|
|
1894
|
+
/**
|
|
1895
|
+
* Union of all validation types
|
|
1896
|
+
*/
|
|
1897
|
+
export declare const ValidationNodeSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
1898
|
+
type: z.ZodLiteral<"SimpleValidation">;
|
|
1899
|
+
}, "strip", z.ZodTypeAny, {
|
|
1900
|
+
type: "SimpleValidation";
|
|
1901
|
+
}, {
|
|
1902
|
+
type: "SimpleValidation";
|
|
1903
|
+
}>, z.ZodObject<{
|
|
1904
|
+
type: z.ZodLiteral<"ExpressionValidation">;
|
|
1905
|
+
expression: z.ZodString;
|
|
1906
|
+
}, "strip", z.ZodTypeAny, {
|
|
1907
|
+
type: "ExpressionValidation";
|
|
1908
|
+
expression: string;
|
|
1909
|
+
}, {
|
|
1910
|
+
type: "ExpressionValidation";
|
|
1911
|
+
expression: string;
|
|
1912
|
+
}>]>;
|
|
1913
|
+
|
|
1914
|
+
/**
|
|
1915
|
+
* Complete validation result
|
|
1916
|
+
*/
|
|
1917
|
+
export declare interface ValidationResult {
|
|
1918
|
+
/** Whether all inputs are correct */
|
|
1919
|
+
isCorrect: boolean;
|
|
1920
|
+
/** Per-widget validation details */
|
|
1921
|
+
details: Record<string, WidgetValidation>;
|
|
1922
|
+
/** Numeric score (0-1) for partial grading */
|
|
1923
|
+
score?: number;
|
|
1924
|
+
/** The expression that was evaluated (expression mode only) */
|
|
1925
|
+
expression?: string;
|
|
1926
|
+
/** The scope used for evaluation (expression mode only, debugging) */
|
|
1927
|
+
scope?: Record<string, number>;
|
|
1928
|
+
/** Error message if validation failed */
|
|
1929
|
+
error?: string;
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
export declare type WidgetJSON = z.infer<typeof WidgetJSONSchema>;
|
|
1933
|
+
|
|
1934
|
+
export declare const WidgetJSONSchema: z.ZodUnion<[z.ZodDiscriminatedUnion<"inputType", [z.ZodObject<{
|
|
1935
|
+
type: z.ZodLiteral<"inline-input">;
|
|
1936
|
+
inputType: z.ZodLiteral<"string">;
|
|
1937
|
+
length: z.ZodNumber;
|
|
1938
|
+
}, "strip", z.ZodTypeAny, {
|
|
1939
|
+
length: number;
|
|
1940
|
+
type: "inline-input";
|
|
1941
|
+
inputType: "string";
|
|
1942
|
+
}, {
|
|
1943
|
+
length: number;
|
|
1944
|
+
type: "inline-input";
|
|
1945
|
+
inputType: "string";
|
|
1946
|
+
}>, z.ZodObject<{
|
|
1947
|
+
type: z.ZodLiteral<"inline-input">;
|
|
1948
|
+
inputType: z.ZodLiteral<"numeric">;
|
|
1949
|
+
digits: z.ZodNumber;
|
|
1950
|
+
}, "strip", z.ZodTypeAny, {
|
|
1951
|
+
type: "inline-input";
|
|
1952
|
+
inputType: "numeric";
|
|
1953
|
+
digits: number;
|
|
1954
|
+
}, {
|
|
1955
|
+
type: "inline-input";
|
|
1956
|
+
inputType: "numeric";
|
|
1957
|
+
digits: number;
|
|
1958
|
+
}>]>, z.ZodObject<{
|
|
1959
|
+
type: z.ZodLiteral<"drag-options">;
|
|
1960
|
+
options: z.ZodArray<z.ZodString, "many">;
|
|
1961
|
+
}, "strip", z.ZodTypeAny, {
|
|
1962
|
+
type: "drag-options";
|
|
1963
|
+
options: string[];
|
|
1964
|
+
}, {
|
|
1965
|
+
type: "drag-options";
|
|
1966
|
+
options: string[];
|
|
1967
|
+
}>, z.ZodObject<{
|
|
1968
|
+
type: z.ZodLiteral<"numeric-keypad">;
|
|
1969
|
+
includeDecimal: z.ZodBoolean;
|
|
1970
|
+
}, "strip", z.ZodTypeAny, {
|
|
1971
|
+
type: "numeric-keypad";
|
|
1972
|
+
includeDecimal: boolean;
|
|
1973
|
+
}, {
|
|
1974
|
+
type: "numeric-keypad";
|
|
1975
|
+
includeDecimal: boolean;
|
|
1976
|
+
}>]>;
|
|
1977
|
+
|
|
1978
|
+
declare type WidgetRef = z.infer<typeof WidgetRefSchema>;
|
|
1979
|
+
export { WidgetRef as WidgetPlaceholder }
|
|
1980
|
+
export { WidgetRef }
|
|
1981
|
+
|
|
1982
|
+
export declare const WidgetRefSchema: z.ZodObject<{
|
|
1983
|
+
id: z.ZodString;
|
|
1984
|
+
type: z.ZodLiteral<"widget-ref">;
|
|
1985
|
+
widgetId: z.ZodString;
|
|
1986
|
+
}, "strip", z.ZodTypeAny, {
|
|
1987
|
+
type: "widget-ref";
|
|
1988
|
+
id: string;
|
|
1989
|
+
widgetId: string;
|
|
1990
|
+
}, {
|
|
1991
|
+
type: "widget-ref";
|
|
1992
|
+
id: string;
|
|
1993
|
+
widgetId: string;
|
|
1994
|
+
}>;
|
|
1995
|
+
|
|
1996
|
+
/**
|
|
1997
|
+
* WidgetRenderer - Router component that delegates to specific widget components
|
|
1998
|
+
* This is a thin layer that just switches between different widget types
|
|
1999
|
+
* Each widget handles its own behavior (DnD, buttons, input, etc.)
|
|
2000
|
+
*/
|
|
2001
|
+
export declare const WidgetRenderer: default_2.FC<WidgetRendererProps>;
|
|
2002
|
+
|
|
2003
|
+
export declare interface WidgetRendererProps {
|
|
2004
|
+
widget: WidgetJSON;
|
|
2005
|
+
widgetId: string;
|
|
2006
|
+
value: string;
|
|
2007
|
+
isDropped?: boolean;
|
|
2008
|
+
onChange: (widgetId: string, value: string, fromDrop?: boolean) => void;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
/**
|
|
2012
|
+
* Validation Result Types
|
|
2013
|
+
*
|
|
2014
|
+
* These define the output of validation operations.
|
|
2015
|
+
*/
|
|
2016
|
+
/**
|
|
2017
|
+
* Result of validating a single widget
|
|
2018
|
+
*/
|
|
2019
|
+
export declare interface WidgetValidation {
|
|
2020
|
+
/** The widget ID */
|
|
2021
|
+
widgetId: string;
|
|
2022
|
+
/** The user's input value */
|
|
2023
|
+
userValue: string | number | undefined;
|
|
2024
|
+
/** Whether the input is correct */
|
|
2025
|
+
isCorrect: boolean;
|
|
2026
|
+
/** Optional error message (for debugging) */
|
|
2027
|
+
error?: string;
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
export { }
|