@mathscan/math-exercise-engine 1.2.4 → 1.2.5

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/dist/style.css CHANGED
@@ -49,8 +49,20 @@
49
49
  --exercise-border: #ddd;
50
50
  --exercise-border-focus: var(--exercise-primary);
51
51
  --exercise-highlight-color: #aef59d;
52
+ /* Validation state colors. Declared on this element, so an override on a
53
+ host *wrapper* is shadowed — use the renderer's `theme` prop (inline
54
+ style), or override on the root itself via the `className` prop.
55
+ The -bg tints derive from the base tokens so a host that only swaps
56
+ --exercise-incorrect (orange → red across attempts) gets matching tints.
57
+ The tints are computed HERE, so override the base tokens on the root
58
+ only — an override on a nested element leaves its tint unchanged. */
52
59
  --exercise-correct: #22c55e;
53
60
  --exercise-incorrect: #ef4444;
61
+ --exercise-correct-bg: color-mix(in srgb, var(--exercise-correct) 6%, var(--exercise-bg));
62
+ --exercise-incorrect-bg: color-mix(in srgb, var(--exercise-incorrect) 6%, var(--exercise-bg));
63
+ /* Authoring/engine errors — kept apart from --exercise-incorrect so they
64
+ don't follow the student's attempt state. */
65
+ --exercise-error: #ef4444;
54
66
 
55
67
  /* ========================================
56
68
  SPACING VARIABLES
@@ -490,22 +502,22 @@ mark {
490
502
 
491
503
  .inline-input.widget--correct {
492
504
  border-color: var(--exercise-correct, #22c55e);
493
- box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.15);
505
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--exercise-correct, #22c55e) 15%, transparent);
494
506
  }
495
507
 
496
508
  .inline-input.widget--incorrect {
497
509
  border-color: var(--exercise-incorrect, #ef4444);
498
- box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);
510
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--exercise-incorrect, #ef4444) 15%, transparent);
499
511
  }
500
512
 
501
513
  .inline-input-chip.widget--correct {
502
514
  border-color: var(--exercise-correct, #22c55e);
503
- box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.15);
515
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--exercise-correct, #22c55e) 15%, transparent);
504
516
  }
505
517
 
506
518
  .inline-input-chip.widget--incorrect {
507
519
  border-color: var(--exercise-incorrect, #ef4444);
508
- box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);
520
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--exercise-incorrect, #ef4444) 15%, transparent);
509
521
  }
510
522
 
511
523
  /* ========================================
@@ -666,14 +678,14 @@ button.drag-option {
666
678
  background: var(--exercise-correct, #22c55e);
667
679
  border-color: var(--exercise-correct, #22c55e);
668
680
  color: white;
669
- box-shadow: 0 2px 4px rgba(34, 197, 94, 0.25);
681
+ box-shadow: 0 2px 4px color-mix(in srgb, var(--exercise-correct, #22c55e) 25%, transparent);
670
682
  }
671
683
 
672
684
  .radio-option.widget--incorrect {
673
685
  background: var(--exercise-incorrect, #ef4444);
674
686
  border-color: var(--exercise-incorrect, #ef4444);
675
687
  color: white;
676
- box-shadow: 0 2px 4px rgba(239, 68, 68, 0.25);
688
+ box-shadow: 0 2px 4px color-mix(in srgb, var(--exercise-incorrect, #ef4444) 25%, transparent);
677
689
  }
678
690
 
679
691
  /* ========================================
@@ -1105,15 +1117,15 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
1105
1117
  }
1106
1118
 
1107
1119
  .widget--correct .matcher-card--selected {
1108
- border-color: #43b925;
1109
- background: #f2ffee;
1110
- box-shadow: 0 4px 0 rgba(67, 185, 37, 0.3);
1120
+ border-color: var(--exercise-correct, #22c55e);
1121
+ background: var(--exercise-correct-bg, color-mix(in srgb, var(--exercise-correct, #22c55e) 6%, var(--exercise-bg, white)));
1122
+ box-shadow: 0 4px 0 color-mix(in srgb, var(--exercise-correct, #22c55e) 30%, transparent);
1111
1123
  }
1112
1124
 
1113
1125
  .widget--incorrect .matcher-card--selected {
1114
- border-color: #d6234d;
1115
- background: #fff0f7;
1116
- box-shadow: 0 4px 0 rgba(214, 35, 77, 0.25);
1126
+ border-color: var(--exercise-incorrect, #ef4444);
1127
+ background: var(--exercise-incorrect-bg, color-mix(in srgb, var(--exercise-incorrect, #ef4444) 6%, var(--exercise-bg, white)));
1128
+ box-shadow: 0 4px 0 color-mix(in srgb, var(--exercise-incorrect, #ef4444) 25%, transparent);
1117
1129
  }
1118
1130
 
1119
1131
  /* Intentionally dropped — kept for reference if unselected-card validation feedback is restored.
@@ -1143,8 +1155,8 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
1143
1155
  --pm-dot-size: 17px;
1144
1156
  --pm-dot-border-width: 2px;
1145
1157
  --pm-line-color: var(--pm-orange);
1146
- --pm-line-color-correct: #43b925;
1147
- --pm-line-color-incorrect: #d6234d;
1158
+ --pm-line-color-correct: var(--exercise-correct, #22c55e);
1159
+ --pm-line-color-incorrect: var(--exercise-incorrect, #ef4444);
1148
1160
  --pm-line-width: 4px;
1149
1161
  position: relative;
1150
1162
  display: flex;
@@ -1221,15 +1233,15 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
1221
1233
  }
1222
1234
 
1223
1235
  .pair-matcher-card--correct {
1224
- border-color: #43b925;
1225
- background: #f2ffee;
1226
- color: #43b925;
1236
+ border-color: var(--exercise-correct, #22c55e);
1237
+ background: var(--exercise-correct-bg, color-mix(in srgb, var(--exercise-correct, #22c55e) 6%, var(--exercise-bg, white)));
1238
+ color: var(--exercise-correct, #22c55e);
1227
1239
  }
1228
1240
 
1229
1241
  .pair-matcher-card--incorrect {
1230
- border-color: #d6234d;
1231
- background: #fff0f7;
1232
- color: #d6234d;
1242
+ border-color: var(--exercise-incorrect, #ef4444);
1243
+ background: var(--exercise-incorrect-bg, color-mix(in srgb, var(--exercise-incorrect, #ef4444) 6%, var(--exercise-bg, white)));
1244
+ color: var(--exercise-incorrect, #ef4444);
1233
1245
  }
1234
1246
 
1235
1247
  .pair-matcher-dot {
@@ -1261,13 +1273,13 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
1261
1273
  }
1262
1274
 
1263
1275
  .pair-matcher-dot--correct {
1264
- border-color: #43b925;
1265
- background: #43b925;
1276
+ border-color: var(--exercise-correct, #22c55e);
1277
+ background: var(--exercise-correct, #22c55e);
1266
1278
  }
1267
1279
 
1268
1280
  .pair-matcher-dot--incorrect {
1269
- border-color: #d6234d;
1270
- background: #d6234d;
1281
+ border-color: var(--exercise-incorrect, #ef4444);
1282
+ background: var(--exercise-incorrect, #ef4444);
1271
1283
  }
1272
1284
 
1273
1285
  .pair-matcher-lines {
@@ -1626,9 +1638,9 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
1626
1638
 
1627
1639
  /* Axis colour: overriding --nl-axis-color on root propagates to track, ticks, arrows and labels. */
1628
1640
 
1629
- .number-line--correct { --nl-axis-color: #43B925; }
1641
+ .number-line--correct { --nl-axis-color: var(--exercise-correct, #22c55e); }
1630
1642
 
1631
- .number-line--incorrect { --nl-axis-color: #D6234D; }
1643
+ .number-line--incorrect { --nl-axis-color: var(--exercise-incorrect, #ef4444); }
1632
1644
 
1633
1645
  /* Disable track transition for instant colour on submit. */
1634
1646
 
@@ -2187,13 +2199,13 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
2187
2199
  .number-line-cursor-ball--correct,
2188
2200
  .number-line-cursor-fill--correct,
2189
2201
  .number-line-cursor-label--correct {
2190
- --nl-cursor-color: #43B925;
2202
+ --nl-cursor-color: var(--exercise-correct, #22c55e);
2191
2203
  }
2192
2204
 
2193
2205
  .number-line-cursor-ball--incorrect,
2194
2206
  .number-line-cursor-fill--incorrect,
2195
2207
  .number-line-cursor-label--incorrect {
2196
- --nl-cursor-color: #D6234D;
2208
+ --nl-cursor-color: var(--exercise-incorrect, #ef4444);
2197
2209
  }
2198
2210
 
2199
2211
  .number-line-cursor-ball:focus-visible {
@@ -2465,33 +2477,33 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
2465
2477
  }
2466
2478
 
2467
2479
  .clock-correct .clock-arrow {
2468
- fill: #16a34a;
2469
- stroke: #16a34a;
2480
+ fill: var(--exercise-correct, #22c55e);
2481
+ stroke: var(--exercise-correct, #22c55e);
2470
2482
  }
2471
2483
 
2472
2484
  .clock-correct .clock-arrow-hour {
2473
- fill: #f2ffee;
2474
- stroke: #16a34a;
2485
+ fill: var(--exercise-correct-bg, color-mix(in srgb, var(--exercise-correct, #22c55e) 6%, var(--exercise-bg, white)));
2486
+ stroke: var(--exercise-correct, #22c55e);
2475
2487
  }
2476
2488
 
2477
2489
  .clock-incorrect .clock-arrow {
2478
- fill: #dc2626;
2479
- stroke: #dc2626;
2490
+ fill: var(--exercise-incorrect, #ef4444);
2491
+ stroke: var(--exercise-incorrect, #ef4444);
2480
2492
  }
2481
2493
 
2482
2494
  .clock-incorrect .clock-arrow-hour {
2483
- fill: #fff0f7;
2484
- stroke: #dc2626;
2495
+ fill: var(--exercise-incorrect-bg, color-mix(in srgb, var(--exercise-incorrect, #ef4444) 6%, var(--exercise-bg, white)));
2496
+ stroke: var(--exercise-incorrect, #ef4444);
2485
2497
  }
2486
2498
 
2487
2499
  .clock-correct .clock-digital-display {
2488
- border-color: #16a34a;
2489
- background: #f0fdf4;
2500
+ border-color: var(--exercise-correct, #22c55e);
2501
+ background: var(--exercise-correct-bg, color-mix(in srgb, var(--exercise-correct, #22c55e) 6%, var(--exercise-bg, white)));
2490
2502
  }
2491
2503
 
2492
2504
  .clock-incorrect .clock-digital-display {
2493
- border-color: #dc2626;
2494
- background: #fef2f2;
2505
+ border-color: var(--exercise-incorrect, #ef4444);
2506
+ background: var(--exercise-incorrect-bg, color-mix(in srgb, var(--exercise-incorrect, #ef4444) 6%, var(--exercise-bg, white)));
2495
2507
  }
2496
2508
 
2497
2509
  .grid-symmetry {
@@ -2501,8 +2513,8 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
2501
2513
  --grid-symmetry-reference-color: #705dc0;
2502
2514
  --grid-symmetry-prefilled-color: #4f86d9;
2503
2515
  --grid-symmetry-answer-color: #291a64;
2504
- --grid-symmetry-correct-color: #43b925;
2505
- --grid-symmetry-incorrect-color: #d6234d;
2516
+ --grid-symmetry-correct-color: var(--exercise-correct, #22c55e);
2517
+ --grid-symmetry-incorrect-color: var(--exercise-incorrect, #ef4444);
2506
2518
  --grid-symmetry-line-color: #ffca76;
2507
2519
  --grid-symmetry-axis-color: #291a64;
2508
2520
  max-width: 100%;
@@ -2641,12 +2653,13 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
2641
2653
  *
2642
2654
  * All colours and sizes are driven by CSS custom properties defined inside
2643
2655
  * `.math-exercise-renderer` (variables.css). Consumer apps can override any
2644
- * of these variables on a parent selector to theme the chart without touching
2645
- * engine code.
2656
+ * of these variables to theme the chart without touching engine code — but on
2657
+ * the renderer root itself (via its `className` prop), not on a parent: tokens
2658
+ * declared on the root shadow anything inherited from a wrapper.
2646
2659
  *
2647
- * Override surface example (student app):
2660
+ * Override surface example (student app, `className="my-exercise"`):
2648
2661
  *
2649
- * .my-exercise-wrapper {
2662
+ * .math-exercise-renderer.my-exercise {
2650
2663
  * --chart-bar-color: #4f46e5;
2651
2664
  * --chart-bar-correct-color: #22c55e;
2652
2665
  * --chart-bar-wrong-color: #ef4444;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mathscan/math-exercise-engine",
3
- "version": "1.2.4",
3
+ "version": "1.2.5",
4
4
  "description": "A DSL parser and validator for math exercises - transforms text-based exercise definitions into structured AST and JSON",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",