@mathscan/math-exercise-engine 1.0.11 → 1.0.13
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/index.d.ts +2343 -25
- package/dist/index.js +981 -280
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +982 -281
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +396 -32
- package/package.json +1 -1
package/dist/style.css
CHANGED
|
@@ -49,6 +49,8 @@
|
|
|
49
49
|
--exercise-border: #ddd;
|
|
50
50
|
--exercise-border-focus: var(--exercise-primary);
|
|
51
51
|
--exercise-highlight-color: #aef59d;
|
|
52
|
+
--exercise-correct: #22c55e;
|
|
53
|
+
--exercise-incorrect: #ef4444;
|
|
52
54
|
|
|
53
55
|
/* ========================================
|
|
54
56
|
SPACING VARIABLES
|
|
@@ -100,6 +102,17 @@
|
|
|
100
102
|
|
|
101
103
|
/** Border width for inputs and buttons */
|
|
102
104
|
--exercise-border-width: 2px;
|
|
105
|
+
|
|
106
|
+
/* ========================================
|
|
107
|
+
NUMBER LINE — HIGHLIGHT COLORS
|
|
108
|
+
======================================== */
|
|
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);
|
|
103
116
|
}
|
|
104
117
|
|
|
105
118
|
/* Layout & Structure */
|
|
@@ -170,7 +183,6 @@
|
|
|
170
183
|
flex-wrap: wrap;
|
|
171
184
|
align-items: center;
|
|
172
185
|
justify-content: center;
|
|
173
|
-
align-items: baseline;
|
|
174
186
|
gap: var(--exercise-element-margin);
|
|
175
187
|
padding-bottom: calc(var(--exercise-line-gap) * 0.5);
|
|
176
188
|
}
|
|
@@ -360,6 +372,30 @@ mark {
|
|
|
360
372
|
border-color: var(--exercise-border-focus);
|
|
361
373
|
}
|
|
362
374
|
|
|
375
|
+
/* ========================================
|
|
376
|
+
VALIDATION STATUS
|
|
377
|
+
======================================== */
|
|
378
|
+
|
|
379
|
+
.inline-input.widget--correct {
|
|
380
|
+
border-color: var(--exercise-correct, #22c55e);
|
|
381
|
+
box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.15);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.inline-input.widget--incorrect {
|
|
385
|
+
border-color: var(--exercise-incorrect, #ef4444);
|
|
386
|
+
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.inline-input-chip.widget--correct {
|
|
390
|
+
border-color: var(--exercise-correct, #22c55e);
|
|
391
|
+
box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.15);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.inline-input-chip.widget--incorrect {
|
|
395
|
+
border-color: var(--exercise-incorrect, #ef4444);
|
|
396
|
+
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);
|
|
397
|
+
}
|
|
398
|
+
|
|
363
399
|
/**
|
|
364
400
|
* Widget Styles
|
|
365
401
|
*
|
|
@@ -468,6 +504,24 @@ button.drag-option {
|
|
|
468
504
|
box-shadow: 0 2px 4px rgba(0, 122, 204, 0.2);
|
|
469
505
|
}
|
|
470
506
|
|
|
507
|
+
/* ========================================
|
|
508
|
+
VALIDATION STATUS
|
|
509
|
+
======================================== */
|
|
510
|
+
|
|
511
|
+
.radio-option.widget--correct {
|
|
512
|
+
background: var(--exercise-correct, #22c55e);
|
|
513
|
+
border-color: var(--exercise-correct, #22c55e);
|
|
514
|
+
color: white;
|
|
515
|
+
box-shadow: 0 2px 4px rgba(34, 197, 94, 0.25);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
.radio-option.widget--incorrect {
|
|
519
|
+
background: var(--exercise-incorrect, #ef4444);
|
|
520
|
+
border-color: var(--exercise-incorrect, #ef4444);
|
|
521
|
+
color: white;
|
|
522
|
+
box-shadow: 0 2px 4px rgba(239, 68, 68, 0.25);
|
|
523
|
+
}
|
|
524
|
+
|
|
471
525
|
/* ========================================
|
|
472
526
|
NUMERIC KEYPAD
|
|
473
527
|
======================================== */
|
|
@@ -556,6 +610,64 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
556
610
|
border: 2px solid #7c6cf2;
|
|
557
611
|
}
|
|
558
612
|
|
|
613
|
+
/* ========================================
|
|
614
|
+
FRACTION WIDGET
|
|
615
|
+
======================================== */
|
|
616
|
+
|
|
617
|
+
.fraction {
|
|
618
|
+
display: inline-flex;
|
|
619
|
+
flex-direction: column;
|
|
620
|
+
align-items: center;
|
|
621
|
+
vertical-align: -0.15em;
|
|
622
|
+
margin: 0 0.2em;
|
|
623
|
+
line-height: 1;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
.fraction-numerator {
|
|
627
|
+
margin-bottom: 3px;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
.fraction-numerator,
|
|
631
|
+
.fraction-denominator {
|
|
632
|
+
display: flex;
|
|
633
|
+
align-items: center;
|
|
634
|
+
justify-content: center;
|
|
635
|
+
min-width: 1.5em;
|
|
636
|
+
padding: 0.05em 0.1em;
|
|
637
|
+
line-height: 2.2;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
.fraction-bar {
|
|
641
|
+
width: 100%;
|
|
642
|
+
min-width: 2em;
|
|
643
|
+
height: 3px;
|
|
644
|
+
background-color: var(--exercise-accent);
|
|
645
|
+
border-radius: 1px;
|
|
646
|
+
margin: 1px 0;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
.fraction-fixed {
|
|
650
|
+
color: var(--exercise-text);
|
|
651
|
+
min-width: 1ch;
|
|
652
|
+
text-align: center;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.fraction-input {
|
|
656
|
+
width: 3.2em !important;
|
|
657
|
+
padding: 0.15em 0.2em;
|
|
658
|
+
font-size: 0.9em;
|
|
659
|
+
text-align: center;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
.fraction-chip {
|
|
663
|
+
font-size: 0.9em;
|
|
664
|
+
padding: 0.1em 0.3em;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
.fraction-slot-droppable {
|
|
668
|
+
display: inline-flex;
|
|
669
|
+
}
|
|
670
|
+
|
|
559
671
|
/**
|
|
560
672
|
* Number Line Styles
|
|
561
673
|
*
|
|
@@ -574,6 +686,8 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
574
686
|
margin-bottom: var(--exercise-margin-bottom);
|
|
575
687
|
user-select: none;
|
|
576
688
|
--nl-chip-zone-height: 3rem;
|
|
689
|
+
/* Visual gap between end ticks and arrowheads — pure CSS, no effect on calculations */
|
|
690
|
+
--nl-arrow-gap: 8px;
|
|
577
691
|
}
|
|
578
692
|
|
|
579
693
|
/* Chip zone: push the axis row down so chips overflowing upward
|
|
@@ -615,7 +729,7 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
615
729
|
|
|
616
730
|
/* In drag mode, chip zone is handled by .number-line--drag-mode padding-top on root */
|
|
617
731
|
|
|
618
|
-
/* Horizontal track line — spans [--nl-side-pad, 100% - --nl-side-pad] */
|
|
732
|
+
/* Horizontal track line — spans [--nl-side-pad, 100% - --nl-side-pad] by default */
|
|
619
733
|
|
|
620
734
|
.number-line-track {
|
|
621
735
|
position: absolute;
|
|
@@ -629,6 +743,25 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
629
743
|
transition: all 0.2s ease;
|
|
630
744
|
}
|
|
631
745
|
|
|
746
|
+
/* Extend the track toward the arrow only when the arrow is present —
|
|
747
|
+
keeps the track flush with the last tick when no arrow exists on that side */
|
|
748
|
+
|
|
749
|
+
.number-line-axis-row:has(.number-line-arrow-left) .number-line-track {
|
|
750
|
+
left: calc(var(--nl-side-pad, 7%) - var(--nl-arrow-gap, 8px));
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
.number-line-axis-row:has(.number-line-arrow-right) .number-line-track {
|
|
754
|
+
right: calc(var(--nl-side-pad, 7%) - var(--nl-arrow-gap, 8px));
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/* Geometric line style — track extends to the full container edges
|
|
758
|
+
so the axis looks like an infinite line, not a closed segment */
|
|
759
|
+
|
|
760
|
+
.number-line--style-line .number-line-track {
|
|
761
|
+
left: 0;
|
|
762
|
+
right: 0;
|
|
763
|
+
}
|
|
764
|
+
|
|
632
765
|
/* ── Arrowheads (CSS border-triangle technique) ── */
|
|
633
766
|
|
|
634
767
|
.number-line-arrow {
|
|
@@ -638,26 +771,36 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
638
771
|
height: 0;
|
|
639
772
|
}
|
|
640
773
|
|
|
641
|
-
/* Right-pointing arrow — base sits at the right end of the track */
|
|
774
|
+
/* Right-pointing arrow — base sits at the right end of the track, offset outward by --nl-arrow-gap */
|
|
642
775
|
|
|
643
776
|
.number-line-arrow-right {
|
|
644
|
-
left: calc(100% - var(--nl-side-pad, 7%));
|
|
777
|
+
left: calc(100% - var(--nl-side-pad, 7%) + var(--nl-arrow-gap, 8px));
|
|
645
778
|
transform: translateY(-50%);
|
|
646
779
|
border-top: 5px solid transparent;
|
|
647
780
|
border-bottom: 5px solid transparent;
|
|
648
781
|
border-left: 8px solid var(--exercise-text, #333);
|
|
649
782
|
}
|
|
650
783
|
|
|
651
|
-
/* Left-pointing arrow — tip extends just past the left end of the track */
|
|
784
|
+
/* Left-pointing arrow — tip extends just past the left end of the track, offset outward by --nl-arrow-gap */
|
|
652
785
|
|
|
653
786
|
.number-line-arrow-left {
|
|
654
|
-
left: var(--nl-side-pad, 7%);
|
|
787
|
+
left: calc(var(--nl-side-pad, 7%) - var(--nl-arrow-gap, 8px));
|
|
655
788
|
transform: translate(-100%, -50%);
|
|
656
789
|
border-top: 5px solid transparent;
|
|
657
790
|
border-bottom: 5px solid transparent;
|
|
658
791
|
border-right: 8px solid var(--exercise-text, #333);
|
|
659
792
|
}
|
|
660
793
|
|
|
794
|
+
/* Geometric line style — arrows reach the full container edges */
|
|
795
|
+
|
|
796
|
+
.number-line--style-line .number-line-arrow-right {
|
|
797
|
+
left: calc(100%);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
.number-line--style-line .number-line-arrow-left {
|
|
801
|
+
left: 0;
|
|
802
|
+
}
|
|
803
|
+
|
|
661
804
|
/* ── Major ticks ── */
|
|
662
805
|
|
|
663
806
|
.number-line-major-tick {
|
|
@@ -667,6 +810,7 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
667
810
|
width: 2px;
|
|
668
811
|
height: 14px;
|
|
669
812
|
background-color: var(--exercise-text, #333);
|
|
813
|
+
transition: transform 0.1s ease, background-color 0.1s ease, width 0.1s ease;
|
|
670
814
|
}
|
|
671
815
|
|
|
672
816
|
/* ── Minor ticks ── */
|
|
@@ -678,6 +822,7 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
678
822
|
width: 1px;
|
|
679
823
|
height: 8px;
|
|
680
824
|
background-color: var(--exercise-text-light, #555);
|
|
825
|
+
transition: transform 0.1s ease, background-color 0.1s ease, width 0.1s ease;
|
|
681
826
|
}
|
|
682
827
|
|
|
683
828
|
/* ── Position marker dots ── */
|
|
@@ -686,12 +831,11 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
686
831
|
position: absolute;
|
|
687
832
|
top: 50%;
|
|
688
833
|
transform: translate(-50%, -50%);
|
|
689
|
-
width:
|
|
690
|
-
height:
|
|
834
|
+
width: 10px;
|
|
835
|
+
height: 10px;
|
|
691
836
|
border-radius: 50%;
|
|
692
|
-
background-color: var(--exercise-
|
|
693
|
-
|
|
694
|
-
box-shadow: 0 2px 4px rgba(0, 122, 204, 0.2);
|
|
837
|
+
background-color: var(--exercise-accent, #705DC0);
|
|
838
|
+
box-shadow: 0 1px 3px rgba(112, 93, 192, 0.25);
|
|
695
839
|
z-index: 2;
|
|
696
840
|
}
|
|
697
841
|
|
|
@@ -705,10 +849,20 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
705
849
|
*
|
|
706
850
|
* Structure:
|
|
707
851
|
* .number-line-placed-chip — absolute wrapper, positioned by left%
|
|
708
|
-
* .number-line-placed-chip-
|
|
852
|
+
* .number-line-placed-chip-inner — flex row holding btn + X button
|
|
853
|
+
* .number-line-placed-chip-btn — the visible chip button (draggable)
|
|
854
|
+
* .number-line-placed-chip-remove — ✕ badge (always visible)
|
|
709
855
|
* ::after pseudo — thin connector line down to the axis
|
|
710
856
|
*/
|
|
711
857
|
|
|
858
|
+
/* Drop landing animation — subtle scale for professional feel */
|
|
859
|
+
|
|
860
|
+
@keyframes nl-chip-land {
|
|
861
|
+
0% { transform: translateX(-50%) scale(0.75); opacity: 0.6; }
|
|
862
|
+
60% { transform: translateX(-50%) scale(1.06); opacity: 1; }
|
|
863
|
+
100% { transform: translateX(-50%) scale(1); opacity: 1; }
|
|
864
|
+
}
|
|
865
|
+
|
|
712
866
|
.number-line-placed-chip {
|
|
713
867
|
position: absolute;
|
|
714
868
|
bottom: calc(50% + 2px);
|
|
@@ -721,48 +875,134 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
721
875
|
pointer-events: none;
|
|
722
876
|
}
|
|
723
877
|
|
|
878
|
+
/* Play landing animation when class is toggled on by React */
|
|
879
|
+
|
|
880
|
+
.nl-chip-landing {
|
|
881
|
+
animation: nl-chip-land 0.28s ease-out forwards;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/* Hide original chip while DragOverlay clone follows cursor — no ghost double */
|
|
885
|
+
|
|
886
|
+
.nl-chip-dragging {
|
|
887
|
+
opacity: 0 !important;
|
|
888
|
+
pointer-events: none;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
.nl-chip-dragging::after {
|
|
892
|
+
display: none;
|
|
893
|
+
}
|
|
894
|
+
|
|
724
895
|
/* Thin connector between chip and axis */
|
|
725
896
|
|
|
726
897
|
.number-line-placed-chip::after {
|
|
727
898
|
content: '';
|
|
728
899
|
display: block;
|
|
729
|
-
width:
|
|
730
|
-
height:
|
|
731
|
-
background-color: var(--exercise-
|
|
732
|
-
|
|
900
|
+
width: 1.5px;
|
|
901
|
+
height: 10px;
|
|
902
|
+
background-color: var(--exercise-accent, #705DC0);
|
|
903
|
+
opacity: 0.5;
|
|
904
|
+
margin-top: 1px;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/* Item 3 — Inner flex row: position: relative so ✕ badge can be anchored inside */
|
|
908
|
+
|
|
909
|
+
.number-line-placed-chip-inner {
|
|
910
|
+
position: relative;
|
|
911
|
+
display: inline-flex;
|
|
912
|
+
align-items: center;
|
|
913
|
+
pointer-events: all;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/* ✕ badge: hidden by default, revealed on chip hover — clean, non-distracting */
|
|
917
|
+
|
|
918
|
+
.number-line-placed-chip-remove {
|
|
919
|
+
position: absolute;
|
|
920
|
+
top: -6px;
|
|
921
|
+
right: -6px;
|
|
922
|
+
display: flex;
|
|
923
|
+
align-items: center;
|
|
924
|
+
justify-content: center;
|
|
925
|
+
width: 16px;
|
|
926
|
+
height: 16px;
|
|
927
|
+
border-radius: 50%;
|
|
928
|
+
border: 1.5px solid white;
|
|
929
|
+
background-color: var(--exercise-text-light, #555);
|
|
930
|
+
color: white;
|
|
931
|
+
font-size: 0.5rem;
|
|
932
|
+
font-weight: bold;
|
|
933
|
+
line-height: 1;
|
|
934
|
+
cursor: pointer;
|
|
935
|
+
transition: opacity 0.15s ease, transform 0.12s ease, background-color 0.12s ease;
|
|
936
|
+
pointer-events: all;
|
|
937
|
+
z-index: 1;
|
|
938
|
+
opacity: 0;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/* Show ✕ on chip hover or when badge itself has focus */
|
|
942
|
+
|
|
943
|
+
.number-line-placed-chip-inner:hover .number-line-placed-chip-remove,
|
|
944
|
+
.number-line-placed-chip-remove:focus-visible {
|
|
945
|
+
opacity: 1;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
.number-line-placed-chip-remove:hover {
|
|
949
|
+
opacity: 1;
|
|
950
|
+
transform: scale(1.15);
|
|
951
|
+
background-color: var(--exercise-danger, #ef4444);
|
|
733
952
|
}
|
|
734
953
|
|
|
735
954
|
.number-line-placed-chip-btn {
|
|
736
955
|
pointer-events: all;
|
|
737
|
-
background-color: var(--exercise-
|
|
956
|
+
background-color: var(--exercise-accent, #705DC0);
|
|
738
957
|
color: white;
|
|
739
|
-
|
|
740
|
-
border:
|
|
741
|
-
|
|
742
|
-
padding: var(--exercise-input-padding, 0.375rem 0.625rem);
|
|
958
|
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
|
959
|
+
border-radius: 8px;
|
|
960
|
+
padding: 6px 14px;
|
|
743
961
|
font-size: var(--exercise-font-size, 0.875rem);
|
|
744
962
|
font-weight: var(--exercise-font-weight-bold, 600);
|
|
745
963
|
cursor: pointer;
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
transition: all 0.2s ease;
|
|
964
|
+
box-shadow: 0 2px 8px rgba(112, 93, 192, 0.25);
|
|
965
|
+
transition: all 0.15s ease;
|
|
749
966
|
white-space: nowrap;
|
|
750
967
|
}
|
|
751
968
|
|
|
752
969
|
.number-line-placed-chip-btn:hover {
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
970
|
+
filter: brightness(1.08);
|
|
971
|
+
box-shadow: 0 3px 10px rgba(112, 93, 192, 0.35);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
/* Nearest snap tick highlights during drag — scaleY keeps layout intact */
|
|
975
|
+
|
|
976
|
+
.number-line-major-tick.nl-tick-hover {
|
|
977
|
+
transform: translate(-50%, -50%) scaleY(1.5);
|
|
978
|
+
width: 2.5px;
|
|
979
|
+
background-color: var(--exercise-accent, #705DC0);
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.number-line-minor-tick.nl-tick-hover {
|
|
983
|
+
transform: translate(-50%, -50%) scaleY(1.8);
|
|
984
|
+
width: 1.5px;
|
|
985
|
+
background-color: var(--exercise-accent, #705DC0);
|
|
756
986
|
}
|
|
757
987
|
|
|
758
|
-
/*
|
|
988
|
+
/* Snap preview — static subtle dot at landing position */
|
|
759
989
|
|
|
760
|
-
.nl-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
990
|
+
.nl-snap-preview {
|
|
991
|
+
position: absolute;
|
|
992
|
+
top: 50%;
|
|
993
|
+
transform: translate(-50%, -50%);
|
|
994
|
+
width: 12px;
|
|
995
|
+
height: 12px;
|
|
996
|
+
border-radius: 50%;
|
|
997
|
+
background-color: var(--exercise-accent, #705DC0);
|
|
998
|
+
opacity: 0.3;
|
|
999
|
+
pointer-events: none;
|
|
1000
|
+
z-index: 2;
|
|
1001
|
+
transition: left 0.06s ease;
|
|
764
1002
|
}
|
|
765
1003
|
|
|
1004
|
+
/* Axis glow on drag-over intentionally disabled — axis stays neutral */
|
|
1005
|
+
|
|
766
1006
|
/* ========================================
|
|
767
1007
|
ROW 3 — NUMERIC TICK LABELS
|
|
768
1008
|
======================================== */
|
|
@@ -783,6 +1023,130 @@ td.exercise-table-cell, th.exercise-table-cell {
|
|
|
783
1023
|
white-space: nowrap;
|
|
784
1024
|
}
|
|
785
1025
|
|
|
1026
|
+
/* ========================================
|
|
1027
|
+
HIGHLIGHT BANDS
|
|
1028
|
+
======================================== */
|
|
1029
|
+
|
|
1030
|
+
/* A coloured band spanning [from%, to%] on the axis row */
|
|
1031
|
+
|
|
1032
|
+
.number-line-highlight-band {
|
|
1033
|
+
position: absolute;
|
|
1034
|
+
top: 0;
|
|
1035
|
+
height: 100%;
|
|
1036
|
+
background-color: var(--nl-highlight-color, var(--nl-highlight-blue, rgba(0, 122, 204, 0.25)));
|
|
1037
|
+
border-radius: 2px;
|
|
1038
|
+
z-index: 0;
|
|
1039
|
+
pointer-events: none;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/* Highlight label row — sits below tick labels, never overlaps inputs */
|
|
1043
|
+
|
|
1044
|
+
.number-line-highlight-labels-row {
|
|
1045
|
+
position: relative;
|
|
1046
|
+
width: 100%;
|
|
1047
|
+
height: 1.2rem;
|
|
1048
|
+
margin-top: 0.1rem;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
.number-line-highlight-label {
|
|
1052
|
+
position: absolute;
|
|
1053
|
+
transform: translateX(-50%);
|
|
1054
|
+
font-size: calc(var(--exercise-font-size) * 0.75);
|
|
1055
|
+
font-weight: var(--exercise-font-weight-bold, 600);
|
|
1056
|
+
color: var(--exercise-text-light, #555);
|
|
1057
|
+
white-space: nowrap;
|
|
1058
|
+
pointer-events: none;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/* ========================================
|
|
1062
|
+
COUNTER UI
|
|
1063
|
+
======================================== */
|
|
1064
|
+
|
|
1065
|
+
.number-line-counter {
|
|
1066
|
+
display: flex;
|
|
1067
|
+
flex-direction: column;
|
|
1068
|
+
align-items: center;
|
|
1069
|
+
gap: 0.25rem;
|
|
1070
|
+
margin-top: 0.5rem;
|
|
1071
|
+
padding: 0.4rem 0.75rem;
|
|
1072
|
+
width: fit-content;
|
|
1073
|
+
margin-left: auto;
|
|
1074
|
+
margin-right: auto;
|
|
1075
|
+
background: var(--exercise-bg, white);
|
|
1076
|
+
border: 1px solid var(--exercise-border, #ddd);
|
|
1077
|
+
border-radius: 8px;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/* Inner row: − value + buttons as a cohesive stepper */
|
|
1081
|
+
|
|
1082
|
+
.number-line-counter-controls {
|
|
1083
|
+
display: flex;
|
|
1084
|
+
align-items: center;
|
|
1085
|
+
justify-content: center;
|
|
1086
|
+
gap: 0.5rem;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
.number-line-counter-label {
|
|
1090
|
+
font-size: calc(var(--exercise-font-size) * 0.85);
|
|
1091
|
+
color: var(--exercise-text-light, #555);
|
|
1092
|
+
text-align: center;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
.number-line-counter-value {
|
|
1096
|
+
font-size: calc(var(--exercise-font-size) * 1.15);
|
|
1097
|
+
font-weight: 600;
|
|
1098
|
+
font-variant-numeric: tabular-nums;
|
|
1099
|
+
color: var(--exercise-text, #333);
|
|
1100
|
+
min-width: 2ch;
|
|
1101
|
+
text-align: center;
|
|
1102
|
+
line-height: 1;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
.number-line-counter-btn {
|
|
1106
|
+
display: inline-flex;
|
|
1107
|
+
align-items: center;
|
|
1108
|
+
justify-content: center;
|
|
1109
|
+
min-width: 36px;
|
|
1110
|
+
min-height: 36px;
|
|
1111
|
+
width: 36px;
|
|
1112
|
+
height: 36px;
|
|
1113
|
+
border: 1.5px solid var(--exercise-accent, #705DC0);
|
|
1114
|
+
border-radius: 50%;
|
|
1115
|
+
background: transparent;
|
|
1116
|
+
color: var(--exercise-accent, #705DC0);
|
|
1117
|
+
font-size: 1.1rem;
|
|
1118
|
+
font-weight: 500;
|
|
1119
|
+
line-height: 1;
|
|
1120
|
+
cursor: pointer;
|
|
1121
|
+
transition: all 0.12s ease;
|
|
1122
|
+
-webkit-tap-highlight-color: transparent;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
.number-line-counter-btn:hover:not(:disabled) {
|
|
1126
|
+
background: var(--exercise-accent, #705DC0);
|
|
1127
|
+
color: white;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
.number-line-counter-btn:active:not(:disabled) {
|
|
1131
|
+
transform: scale(0.93);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
.number-line-counter-btn:disabled {
|
|
1135
|
+
opacity: 0.35;
|
|
1136
|
+
cursor: not-allowed;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/* ========================================
|
|
1140
|
+
ACCESSIBILITY — FOCUS-VISIBLE RINGS (item 6)
|
|
1141
|
+
======================================== */
|
|
1142
|
+
|
|
1143
|
+
.number-line-placed-chip-btn:focus-visible,
|
|
1144
|
+
.number-line-placed-chip-remove:focus-visible,
|
|
1145
|
+
.number-line-counter-btn:focus-visible {
|
|
1146
|
+
outline: 2px solid var(--exercise-accent, #705DC0);
|
|
1147
|
+
outline-offset: 2px;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
786
1150
|
/**
|
|
787
1151
|
* Button & Action Styles
|
|
788
1152
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mathscan/math-exercise-engine",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
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",
|