@mathscan/math-exercise-engine 1.2.3 → 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
  /* ========================================
@@ -794,8 +806,14 @@ button.drag-option {
794
806
  color: var(--exercise-text);
795
807
  }
796
808
 
809
+ /*
810
+ * --exercise-table-border-color is always set inline by LayoutRenderer, which
811
+ * falls back to DEFAULT_TABLE_BORDER_COLOR. No literal default here: the color
812
+ * has one source of truth in src/constants/table-constants.ts.
813
+ */
814
+
797
815
  .exercise-table-container {
798
- border: 2px solid #7c6cf2;
816
+ border: 2px solid var(--exercise-table-border-color);
799
817
  border-radius: 8px;
800
818
  overflow: hidden;
801
819
  }
@@ -807,19 +825,19 @@ table.exercise-table {
807
825
 
808
826
  td.exercise-table-cell,
809
827
  th.exercise-table-cell {
810
- box-shadow: inset -2px -2px 0 0 #7c6cf2;
828
+ box-shadow: inset -2px -2px 0 0 var(--exercise-table-border-color);
811
829
  }
812
830
 
813
831
  td.exercise-table-cell:last-child,
814
832
  th.exercise-table-cell:last-child {
815
- box-shadow: inset 0 -2px 0 0 #7c6cf2;
833
+ box-shadow: inset 0 -2px 0 0 var(--exercise-table-border-color);
816
834
  }
817
835
 
818
836
  tr.exercise-table-row:last-child td.exercise-table-cell,
819
837
  tr.exercise-table-row:last-child th.exercise-table-cell,
820
838
  td.exercise-table-cell.exercise-table-cell--last-row,
821
839
  th.exercise-table-cell.exercise-table-cell--last-row {
822
- box-shadow: inset -2px 0 0 0 #7c6cf2;
840
+ box-shadow: inset -2px 0 0 0 var(--exercise-table-border-color);
823
841
  }
824
842
 
825
843
  tr.exercise-table-row:last-child td.exercise-table-cell:last-child,
@@ -1099,15 +1117,15 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
1099
1117
  }
1100
1118
 
1101
1119
  .widget--correct .matcher-card--selected {
1102
- border-color: #43b925;
1103
- background: #f2ffee;
1104
- 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);
1105
1123
  }
1106
1124
 
1107
1125
  .widget--incorrect .matcher-card--selected {
1108
- border-color: #d6234d;
1109
- background: #fff0f7;
1110
- 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);
1111
1129
  }
1112
1130
 
1113
1131
  /* Intentionally dropped — kept for reference if unselected-card validation feedback is restored.
@@ -1137,8 +1155,8 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
1137
1155
  --pm-dot-size: 17px;
1138
1156
  --pm-dot-border-width: 2px;
1139
1157
  --pm-line-color: var(--pm-orange);
1140
- --pm-line-color-correct: #43b925;
1141
- --pm-line-color-incorrect: #d6234d;
1158
+ --pm-line-color-correct: var(--exercise-correct, #22c55e);
1159
+ --pm-line-color-incorrect: var(--exercise-incorrect, #ef4444);
1142
1160
  --pm-line-width: 4px;
1143
1161
  position: relative;
1144
1162
  display: flex;
@@ -1215,15 +1233,15 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
1215
1233
  }
1216
1234
 
1217
1235
  .pair-matcher-card--correct {
1218
- border-color: #43b925;
1219
- background: #f2ffee;
1220
- 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);
1221
1239
  }
1222
1240
 
1223
1241
  .pair-matcher-card--incorrect {
1224
- border-color: #d6234d;
1225
- background: #fff0f7;
1226
- 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);
1227
1245
  }
1228
1246
 
1229
1247
  .pair-matcher-dot {
@@ -1255,13 +1273,13 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
1255
1273
  }
1256
1274
 
1257
1275
  .pair-matcher-dot--correct {
1258
- border-color: #43b925;
1259
- background: #43b925;
1276
+ border-color: var(--exercise-correct, #22c55e);
1277
+ background: var(--exercise-correct, #22c55e);
1260
1278
  }
1261
1279
 
1262
1280
  .pair-matcher-dot--incorrect {
1263
- border-color: #d6234d;
1264
- background: #d6234d;
1281
+ border-color: var(--exercise-incorrect, #ef4444);
1282
+ background: var(--exercise-incorrect, #ef4444);
1265
1283
  }
1266
1284
 
1267
1285
  .pair-matcher-lines {
@@ -1620,9 +1638,9 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
1620
1638
 
1621
1639
  /* Axis colour: overriding --nl-axis-color on root propagates to track, ticks, arrows and labels. */
1622
1640
 
1623
- .number-line--correct { --nl-axis-color: #43B925; }
1641
+ .number-line--correct { --nl-axis-color: var(--exercise-correct, #22c55e); }
1624
1642
 
1625
- .number-line--incorrect { --nl-axis-color: #D6234D; }
1643
+ .number-line--incorrect { --nl-axis-color: var(--exercise-incorrect, #ef4444); }
1626
1644
 
1627
1645
  /* Disable track transition for instant colour on submit. */
1628
1646
 
@@ -2181,13 +2199,13 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
2181
2199
  .number-line-cursor-ball--correct,
2182
2200
  .number-line-cursor-fill--correct,
2183
2201
  .number-line-cursor-label--correct {
2184
- --nl-cursor-color: #43B925;
2202
+ --nl-cursor-color: var(--exercise-correct, #22c55e);
2185
2203
  }
2186
2204
 
2187
2205
  .number-line-cursor-ball--incorrect,
2188
2206
  .number-line-cursor-fill--incorrect,
2189
2207
  .number-line-cursor-label--incorrect {
2190
- --nl-cursor-color: #D6234D;
2208
+ --nl-cursor-color: var(--exercise-incorrect, #ef4444);
2191
2209
  }
2192
2210
 
2193
2211
  .number-line-cursor-ball:focus-visible {
@@ -2459,33 +2477,33 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
2459
2477
  }
2460
2478
 
2461
2479
  .clock-correct .clock-arrow {
2462
- fill: #16a34a;
2463
- stroke: #16a34a;
2480
+ fill: var(--exercise-correct, #22c55e);
2481
+ stroke: var(--exercise-correct, #22c55e);
2464
2482
  }
2465
2483
 
2466
2484
  .clock-correct .clock-arrow-hour {
2467
- fill: #f2ffee;
2468
- 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);
2469
2487
  }
2470
2488
 
2471
2489
  .clock-incorrect .clock-arrow {
2472
- fill: #dc2626;
2473
- stroke: #dc2626;
2490
+ fill: var(--exercise-incorrect, #ef4444);
2491
+ stroke: var(--exercise-incorrect, #ef4444);
2474
2492
  }
2475
2493
 
2476
2494
  .clock-incorrect .clock-arrow-hour {
2477
- fill: #fff0f7;
2478
- 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);
2479
2497
  }
2480
2498
 
2481
2499
  .clock-correct .clock-digital-display {
2482
- border-color: #16a34a;
2483
- 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)));
2484
2502
  }
2485
2503
 
2486
2504
  .clock-incorrect .clock-digital-display {
2487
- border-color: #dc2626;
2488
- 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)));
2489
2507
  }
2490
2508
 
2491
2509
  .grid-symmetry {
@@ -2495,8 +2513,8 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
2495
2513
  --grid-symmetry-reference-color: #705dc0;
2496
2514
  --grid-symmetry-prefilled-color: #4f86d9;
2497
2515
  --grid-symmetry-answer-color: #291a64;
2498
- --grid-symmetry-correct-color: #43b925;
2499
- --grid-symmetry-incorrect-color: #d6234d;
2516
+ --grid-symmetry-correct-color: var(--exercise-correct, #22c55e);
2517
+ --grid-symmetry-incorrect-color: var(--exercise-incorrect, #ef4444);
2500
2518
  --grid-symmetry-line-color: #ffca76;
2501
2519
  --grid-symmetry-axis-color: #291a64;
2502
2520
  max-width: 100%;
@@ -2635,12 +2653,13 @@ th.exercise-table-cell.exercise-table-cell--last-row:last-child {
2635
2653
  *
2636
2654
  * All colours and sizes are driven by CSS custom properties defined inside
2637
2655
  * `.math-exercise-renderer` (variables.css). Consumer apps can override any
2638
- * of these variables on a parent selector to theme the chart without touching
2639
- * 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.
2640
2659
  *
2641
- * Override surface example (student app):
2660
+ * Override surface example (student app, `className="my-exercise"`):
2642
2661
  *
2643
- * .my-exercise-wrapper {
2662
+ * .math-exercise-renderer.my-exercise {
2644
2663
  * --chart-bar-color: #4f46e5;
2645
2664
  * --chart-bar-correct-color: #22c55e;
2646
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.3",
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",