@mathscan/math-exercise-engine 1.0.17 → 1.1.1

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
@@ -107,12 +107,13 @@
107
107
  NUMBER LINE — HIGHLIGHT COLORS
108
108
  ======================================== */
109
109
 
110
- --nl-highlight-blue: rgba(0, 122, 204, 0.25);
111
- --nl-highlight-red: rgba(239, 68, 68, 0.25);
112
- --nl-highlight-green: rgba(34, 197, 94, 0.25);
113
- --nl-highlight-orange: rgba(249, 115, 22, 0.25);
114
- --nl-highlight-purple: rgba(112, 93, 192, 0.25);
115
- --nl-highlight-yellow: rgba(255, 215, 0, 0.35);
110
+ --nl-axis-color: #705DC0;
111
+ --nl-highlight-blue: #007ACC;
112
+ --nl-highlight-red: #EF4444;
113
+ --nl-highlight-green: #22C55E;
114
+ --nl-highlight-orange: #F97316;
115
+ --nl-highlight-purple: #705DC0;
116
+ --nl-highlight-yellow: #FFD700;
116
117
  }
117
118
 
118
119
  /* Layout & Structure */
@@ -420,10 +421,6 @@ mark {
420
421
  DRAG OPTIONS
421
422
  ======================================== */
422
423
 
423
- .drag-options-container {
424
- /* Container for drag options widget */
425
- }
426
-
427
424
  .drag-options {
428
425
  display: flex;
429
426
  justify-content: center;
@@ -736,10 +733,10 @@ th.exercise-table-cell {
736
733
  --visual-fraction-svg-line-width: 0.5px;
737
734
  --visual-fraction-gap: var(--visual-fraction-line-width);
738
735
  --visual-fraction-border-radius: 0;
739
- --visual-fraction-border-color: #705DC0;
736
+ --visual-fraction-border-color: #705dc0;
740
737
  --visual-fraction-empty-bg: var(--exercise-bg, #fff);
741
- --visual-fraction-hover-color: #E6E0FF;
742
- --visual-fraction-part-color: #AE9CFF;
738
+ --visual-fraction-hover-color: #e6e0ff;
739
+ --visual-fraction-part-color: #ae9cff;
743
740
  --visual-fraction-part-text-color: #fff;
744
741
  --visual-fraction-label-color: var(--exercise-text-light, #555);
745
742
  display: inline-flex;
@@ -777,18 +774,21 @@ th.exercise-table-cell {
777
774
  min-height: 0;
778
775
  background: var(--visual-fraction-empty-bg);
779
776
  color: var(--exercise-text, #333);
780
- transition: background 0.2s ease, border-color 0.2s ease, filter 0.2s ease;
777
+ transition:
778
+ background 0.2s ease,
779
+ border-color 0.2s ease,
780
+ filter 0.2s ease;
781
781
  }
782
782
 
783
- .visual-fraction-widget__part[role="button"] {
783
+ .visual-fraction-widget__part[role='button'] {
784
784
  cursor: pointer;
785
785
  }
786
786
 
787
- .visual-fraction-widget__part[role="button"]:hover {
787
+ .visual-fraction-widget__part[role='button']:hover {
788
788
  background: var(--visual-fraction-hover-color);
789
789
  }
790
790
 
791
- .visual-fraction-widget__part[role="button"]:focus-visible {
791
+ .visual-fraction-widget__part[role='button']:focus-visible {
792
792
  outline: 2px solid var(--exercise-border-focus, var(--exercise-primary, #007acc));
793
793
  outline-offset: -2px;
794
794
  }
@@ -799,8 +799,8 @@ th.exercise-table-cell {
799
799
  color: var(--visual-fraction-part-text-color);
800
800
  }
801
801
 
802
- .visual-fraction-widget__part--filled[role="button"]:hover,
803
- .visual-fraction-widget__part--answer[role="button"]:hover {
802
+ .visual-fraction-widget__part--filled[role='button']:hover,
803
+ .visual-fraction-widget__part--answer[role='button']:hover {
804
804
  background: var(--visual-fraction-part-color);
805
805
  color: var(--visual-fraction-part-text-color);
806
806
  }
@@ -811,26 +811,28 @@ th.exercise-table-cell {
811
811
  stroke-width: var(--visual-fraction-svg-line-width);
812
812
  stroke-linejoin: round;
813
813
  stroke-linecap: round;
814
- transition: fill 0.2s ease, filter 0.2s ease;
814
+ transition:
815
+ fill 0.2s ease,
816
+ filter 0.2s ease;
815
817
  }
816
818
 
817
- .visual-fraction-widget__sector[role="button"] {
819
+ .visual-fraction-widget__sector[role='button'] {
818
820
  cursor: pointer;
819
821
  }
820
822
 
821
- .visual-fraction-widget__sector[role="button"]:hover {
823
+ .visual-fraction-widget__sector[role='button']:hover {
822
824
  fill: var(--visual-fraction-hover-color);
823
825
  }
824
826
 
825
- .visual-fraction-widget__sector[role="button"]:focus-visible {
827
+ .visual-fraction-widget__sector[role='button']:focus-visible {
826
828
  outline: none;
827
829
  filter: drop-shadow(0 0 0.18rem var(--exercise-border-focus, var(--exercise-primary, #007acc)));
828
830
  }
829
831
 
830
832
  .visual-fraction-widget__sector.visual-fraction-widget__part--filled,
831
833
  .visual-fraction-widget__sector.visual-fraction-widget__part--answer,
832
- .visual-fraction-widget__sector.visual-fraction-widget__part--filled[role="button"]:hover,
833
- .visual-fraction-widget__sector.visual-fraction-widget__part--answer[role="button"]:hover {
834
+ .visual-fraction-widget__sector.visual-fraction-widget__part--filled[role='button']:hover,
835
+ .visual-fraction-widget__sector.visual-fraction-widget__part--answer[role='button']:hover {
834
836
  fill: var(--visual-fraction-part-color);
835
837
  }
836
838
 
@@ -895,9 +897,9 @@ th.exercise-table-cell {
895
897
  justify-content: center;
896
898
  min-height: clamp(72px, 14vw, 96px);
897
899
  padding: clamp(8px, 2vw, 12px);
898
- border: 2px solid #FFCA76;
900
+ border: 2px solid #ffca76;
899
901
  border-radius: clamp(12px, 3vw, 17px);
900
- background: #FFFFFF;
902
+ background: #ffffff;
901
903
  color: #333333;
902
904
  text-align: center;
903
905
  cursor: pointer;
@@ -920,21 +922,21 @@ th.exercise-table-cell {
920
922
  } */
921
923
 
922
924
  .matcher-card--selected {
923
- background: color-mix(in srgb, var(--matcher-card-color) 12%, #FFFFFF);
925
+ background: color-mix(in srgb, var(--matcher-card-color) 12%, #ffffff);
924
926
  border-color: var(--matcher-card-color);
925
927
  box-shadow: 0 4px 0 color-mix(in srgb, var(--matcher-card-color) 30%, transparent);
926
928
  transform: scale(1.04);
927
929
  }
928
930
 
929
931
  .widget--correct .matcher-card--selected {
930
- border-color: #43B925;
931
- background: #F2FFEE;
932
- box-shadow: 0 4px 0 rgba(67, 185, 37, 0.30);
932
+ border-color: #43b925;
933
+ background: #f2ffee;
934
+ box-shadow: 0 4px 0 rgba(67, 185, 37, 0.3);
933
935
  }
934
936
 
935
937
  .widget--incorrect .matcher-card--selected {
936
- border-color: #D6234D;
937
- background: #FFF0F7;
938
+ border-color: #d6234d;
939
+ background: #fff0f7;
938
940
  box-shadow: 0 4px 0 rgba(214, 35, 77, 0.25);
939
941
  }
940
942
 
@@ -1027,7 +1029,7 @@ th.exercise-table-cell {
1027
1029
  right: var(--nl-side-pad, 7%);
1028
1030
  top: 50%;
1029
1031
  height: 2px;
1030
- background-color: var(--exercise-text, #333);
1032
+ background-color: var(--nl-axis-color);
1031
1033
  transform: translateY(-50%);
1032
1034
  /* transition on base state so both enter and exit are smooth */
1033
1035
  transition: all 0.2s ease;
@@ -1068,7 +1070,7 @@ th.exercise-table-cell {
1068
1070
  transform: translateY(-50%);
1069
1071
  border-top: 5px solid transparent;
1070
1072
  border-bottom: 5px solid transparent;
1071
- border-left: 8px solid var(--exercise-text, #333);
1073
+ border-left: 8px solid var(--nl-axis-color);
1072
1074
  }
1073
1075
 
1074
1076
  /* Left-pointing arrow — tip extends just past the left end of the track, offset outward by --nl-arrow-gap */
@@ -1078,7 +1080,7 @@ th.exercise-table-cell {
1078
1080
  transform: translate(-100%, -50%);
1079
1081
  border-top: 5px solid transparent;
1080
1082
  border-bottom: 5px solid transparent;
1081
- border-right: 8px solid var(--exercise-text, #333);
1083
+ border-right: 8px solid var(--nl-axis-color);
1082
1084
  }
1083
1085
 
1084
1086
  /* Geometric line style — arrows reach the full container edges */
@@ -1099,7 +1101,8 @@ th.exercise-table-cell {
1099
1101
  transform: translate(-50%, -50%);
1100
1102
  width: 2px;
1101
1103
  height: 14px;
1102
- background-color: var(--exercise-text, #333);
1104
+ background-color: var(--nl-axis-color);
1105
+ z-index: 2;
1103
1106
  transition: transform 0.1s ease, background-color 0.1s ease, width 0.1s ease;
1104
1107
  }
1105
1108
 
@@ -1111,7 +1114,8 @@ th.exercise-table-cell {
1111
1114
  transform: translate(-50%, -50%);
1112
1115
  width: 1px;
1113
1116
  height: 8px;
1114
- background-color: var(--exercise-text-light, #555);
1117
+ background-color: var(--nl-axis-color);
1118
+ z-index: 2;
1115
1119
  transition: transform 0.1s ease, background-color 0.1s ease, width 0.1s ease;
1116
1120
  }
1117
1121
 
@@ -1309,7 +1313,7 @@ th.exercise-table-cell {
1309
1313
  transform: translateX(-50%);
1310
1314
  /** Slightly smaller than base font — same pattern as secondary text in the app */
1311
1315
  font-size: calc(var(--exercise-font-size) * 0.8);
1312
- color: var(--exercise-text-light, #555);
1316
+ color: var(--nl-axis-color);
1313
1317
  white-space: nowrap;
1314
1318
  }
1315
1319
 
@@ -1321,11 +1325,12 @@ th.exercise-table-cell {
1321
1325
 
1322
1326
  .number-line-highlight-band {
1323
1327
  position: absolute;
1324
- top: 0;
1325
- height: 100%;
1326
- background-color: var(--nl-highlight-color, var(--nl-highlight-blue, rgba(0, 122, 204, 0.25)));
1327
- border-radius: 2px;
1328
- z-index: 0;
1328
+ top: 50%;
1329
+ height: 6px;
1330
+ transform: translateY(-50%);
1331
+ background-color: var(--nl-highlight-color, var(--nl-highlight-purple, #705DC0));
1332
+ border-radius: 0;
1333
+ z-index: 1;
1329
1334
  pointer-events: none;
1330
1335
  }
1331
1336
 
@@ -1540,7 +1545,9 @@ th.exercise-table-cell {
1540
1545
  }
1541
1546
 
1542
1547
  .draggable.dragging {
1543
- opacity: 0.5;
1548
+ /* Hide original while drag overlay follows cursor to avoid duplicate render.
1549
+ visibility:hidden preserves layout space so neighbors don't shift. */
1550
+ visibility: hidden;
1544
1551
  }
1545
1552
 
1546
1553
  /* Droppable base */
@@ -1560,53 +1567,31 @@ th.exercise-table-cell {
1560
1567
  outline-offset: 2px;
1561
1568
  }
1562
1569
 
1563
- /* Drag overlay - the item following cursor */
1570
+ /* Drag overlay - the item following cursor. Matches the rendered button look,
1571
+ which is the `button.drag-option` legacy rule in styles/widgets.css
1572
+ (accent background + white text, no border).
1573
+ NOTE: @dnd-kit DragOverlay renders in a portal at document.body, outside
1574
+ the .math-exercise-renderer scope — so CSS vars must include fallbacks. */
1564
1575
  .drag-overlay-option {
1565
- padding: 8px 16px;
1566
- background: #4a90d9;
1576
+ padding: 10px 16px;
1577
+ border: none;
1578
+ border-radius: var(--exercise-border-radius, 0.25rem);
1579
+ background: var(--exercise-accent, #705DC0);
1567
1580
  color: white;
1568
- border-radius: 6px;
1569
- font-weight: 500;
1570
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1581
+ font-size: var(--exercise-font-size, clamp(0.875rem, 2vw, 1.1rem));
1582
+ font-weight: var(--exercise-font-weight, 500);
1583
+ min-width: var(--exercise-button-width, clamp(3rem, 6vw, 4rem));
1584
+ text-align: center;
1571
1585
  cursor: grabbing;
1572
1586
  }
1573
1587
 
1574
- /* Drag options container */
1575
- .drag-options {
1576
- display: flex;
1577
- flex-wrap: wrap;
1578
- gap: 8px;
1579
- /* padding: 12px; */
1580
- /* background: #f5f5f5; */
1581
- border-radius: 8px;
1582
- justify-content: center;
1583
- }
1588
+ /* Note: .drag-options and .drag-option base styles live in styles/widgets.css
1589
+ (themed via CSS vars). Don't duplicate them here. */
1584
1590
 
1585
1591
  .drag-option-wrapper {
1586
1592
  display: inline-block;
1587
1593
  }
1588
1594
 
1589
- .drag-option {
1590
- padding: 10px 20px;
1591
- border: 2px solid #ddd;
1592
- border-radius: 8px;
1593
- background: white;
1594
- font-size: 16px;
1595
- font-weight: 500;
1596
- cursor: grab;
1597
- transition: all 0.15s ease;
1598
- }
1599
-
1600
- .drag-option:hover {
1601
- border-color: #4a90d9;
1602
- background: #f0f7ff;
1603
- }
1604
-
1605
- .drag-option.selected {
1606
- border-color: #4a90d9;
1607
- background: #e3f0ff;
1608
- }
1609
-
1610
1595
  /* Slot container - maintains space when item is dragged out */
1611
1596
  .drag-option-slot {
1612
1597
  display: inline-flex;
@@ -1672,17 +1657,6 @@ th.exercise-table-cell {
1672
1657
  background-color: rgba(74, 144, 217, 0.05);
1673
1658
  }
1674
1659
 
1675
- /* Drag options container at bottom */
1676
- .drag-options-container {
1677
- /* margin-top: 20px;
1678
- padding-top: 16px;
1679
- border-top: 1px solid #eee; */
1680
- }
1681
-
1682
- /* ============================================
1683
- FUTURE WIDGETS - Placeholder styles
1684
- ============================================ */
1685
-
1686
1660
  /* ============================================
1687
1661
  DRAGGABLE TOOLS (Ruler, Protractor, etc.)
1688
1662
  ============================================ */
@@ -1743,4 +1717,4 @@ th.exercise-table-cell {
1743
1717
  .math-exercise-renderer {
1744
1718
  position: relative;
1745
1719
  min-height: 200px;
1746
- }
1720
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mathscan/math-exercise-engine",
3
- "version": "1.0.17",
3
+ "version": "1.1.1",
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",