@mathscan/math-exercise-engine 1.0.15 → 1.0.17
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 +3031 -81
- package/dist/index.js +1047 -104
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1047 -104
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +240 -64
- package/package.json +1 -1
package/dist/style.css
CHANGED
|
@@ -238,6 +238,10 @@
|
|
|
238
238
|
unicode-bidi: plaintext;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
+
.text-item-number {
|
|
242
|
+
font-variant-numeric: tabular-nums;
|
|
243
|
+
}
|
|
244
|
+
|
|
241
245
|
.text-item-arabic {
|
|
242
246
|
/* Direction is handled by parent text-group with unicode-bidi: plaintext */
|
|
243
247
|
}
|
|
@@ -586,6 +590,49 @@ button.drag-option {
|
|
|
586
590
|
color: white;
|
|
587
591
|
}
|
|
588
592
|
|
|
593
|
+
/* ========================================
|
|
594
|
+
NUMERIC KEYPAD V2 (diamond / 45-degree style)
|
|
595
|
+
======================================== */
|
|
596
|
+
|
|
597
|
+
.diamond-keypad {
|
|
598
|
+
display: flex;
|
|
599
|
+
flex-direction: column;
|
|
600
|
+
align-items: center;
|
|
601
|
+
gap: 0;
|
|
602
|
+
padding: 0;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
.diamond-keypad-row {
|
|
606
|
+
display: flex;
|
|
607
|
+
gap: 20px;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
.diamond-keypad .keypad-btn {
|
|
611
|
+
transform: rotate(45deg);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
.diamond-keypad .keypad-btn span {
|
|
615
|
+
transform: rotate(-45deg);
|
|
616
|
+
display: inline-flex;
|
|
617
|
+
align-items: center;
|
|
618
|
+
justify-content: center;
|
|
619
|
+
pointer-events: none;
|
|
620
|
+
line-height: 1;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
.diamond-keypad .keypad-btn:hover {
|
|
624
|
+
box-shadow: 0 4px 12px rgba(0, 122, 204, 0.18);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
.diamond-keypad .keypad-btn:active {
|
|
628
|
+
transform: rotate(45deg) scale(0.92);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
.diamond-keypad .keypad-btn-backspace {
|
|
632
|
+
border-color: var(--exercise-accent, #705dc0);
|
|
633
|
+
color: var(--exercise-accent, #705dc0);
|
|
634
|
+
}
|
|
635
|
+
|
|
589
636
|
/* ========================================
|
|
590
637
|
TABLE LAYOUT
|
|
591
638
|
======================================== */
|
|
@@ -664,7 +711,6 @@ th.exercise-table-cell {
|
|
|
664
711
|
}
|
|
665
712
|
|
|
666
713
|
.fraction-input {
|
|
667
|
-
width: 3.2em !important;
|
|
668
714
|
padding: 0.15em 0.2em;
|
|
669
715
|
font-size: 0.9em;
|
|
670
716
|
text-align: center;
|
|
@@ -679,6 +725,152 @@ th.exercise-table-cell {
|
|
|
679
725
|
display: inline-flex;
|
|
680
726
|
}
|
|
681
727
|
|
|
728
|
+
/* ========================================
|
|
729
|
+
VISUAL FRACTION WIDGET
|
|
730
|
+
======================================== */
|
|
731
|
+
|
|
732
|
+
.visual-fraction-widget {
|
|
733
|
+
--visual-fraction-size: clamp(7rem, 24vw, 12rem);
|
|
734
|
+
--visual-fraction-part-size: 1.35rem;
|
|
735
|
+
--visual-fraction-line-width: 1px;
|
|
736
|
+
--visual-fraction-svg-line-width: 0.5px;
|
|
737
|
+
--visual-fraction-gap: var(--visual-fraction-line-width);
|
|
738
|
+
--visual-fraction-border-radius: 0;
|
|
739
|
+
--visual-fraction-border-color: #705DC0;
|
|
740
|
+
--visual-fraction-empty-bg: var(--exercise-bg, #fff);
|
|
741
|
+
--visual-fraction-hover-color: #E6E0FF;
|
|
742
|
+
--visual-fraction-part-color: #AE9CFF;
|
|
743
|
+
--visual-fraction-part-text-color: #fff;
|
|
744
|
+
--visual-fraction-label-color: var(--exercise-text-light, #555);
|
|
745
|
+
display: inline-flex;
|
|
746
|
+
flex-direction: column;
|
|
747
|
+
align-items: center;
|
|
748
|
+
gap: 0.35rem;
|
|
749
|
+
max-width: 100%;
|
|
750
|
+
vertical-align: middle;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
.visual-fraction-widget__parts {
|
|
754
|
+
display: grid;
|
|
755
|
+
gap: var(--visual-fraction-gap);
|
|
756
|
+
border: var(--visual-fraction-line-width) solid var(--visual-fraction-border-color);
|
|
757
|
+
border-radius: var(--visual-fraction-border-radius);
|
|
758
|
+
background: var(--visual-fraction-border-color);
|
|
759
|
+
max-width: 100%;
|
|
760
|
+
overflow: hidden;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
.visual-fraction-widget__parts--horizontal {
|
|
764
|
+
grid-template-columns: repeat(var(--visual-fraction-divisions, 1), 1fr);
|
|
765
|
+
grid-template-rows: var(--visual-fraction-part-size);
|
|
766
|
+
width: var(--visual-fraction-size);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
.visual-fraction-widget__parts--vertical {
|
|
770
|
+
grid-template-columns: var(--visual-fraction-part-size);
|
|
771
|
+
grid-template-rows: repeat(var(--visual-fraction-divisions, 1), 1fr);
|
|
772
|
+
height: var(--visual-fraction-size);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
.visual-fraction-widget__part {
|
|
776
|
+
min-width: 0;
|
|
777
|
+
min-height: 0;
|
|
778
|
+
background: var(--visual-fraction-empty-bg);
|
|
779
|
+
color: var(--exercise-text, #333);
|
|
780
|
+
transition: background 0.2s ease, border-color 0.2s ease, filter 0.2s ease;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
.visual-fraction-widget__part[role="button"] {
|
|
784
|
+
cursor: pointer;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
.visual-fraction-widget__part[role="button"]:hover {
|
|
788
|
+
background: var(--visual-fraction-hover-color);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
.visual-fraction-widget__part[role="button"]:focus-visible {
|
|
792
|
+
outline: 2px solid var(--exercise-border-focus, var(--exercise-primary, #007acc));
|
|
793
|
+
outline-offset: -2px;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
.visual-fraction-widget__part--filled,
|
|
797
|
+
.visual-fraction-widget__part--answer {
|
|
798
|
+
background: var(--visual-fraction-part-color);
|
|
799
|
+
color: var(--visual-fraction-part-text-color);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
.visual-fraction-widget__part--filled[role="button"]:hover,
|
|
803
|
+
.visual-fraction-widget__part--answer[role="button"]:hover {
|
|
804
|
+
background: var(--visual-fraction-part-color);
|
|
805
|
+
color: var(--visual-fraction-part-text-color);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
.visual-fraction-widget__sector {
|
|
809
|
+
fill: var(--visual-fraction-empty-bg);
|
|
810
|
+
stroke: var(--visual-fraction-border-color);
|
|
811
|
+
stroke-width: var(--visual-fraction-svg-line-width);
|
|
812
|
+
stroke-linejoin: round;
|
|
813
|
+
stroke-linecap: round;
|
|
814
|
+
transition: fill 0.2s ease, filter 0.2s ease;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
.visual-fraction-widget__sector[role="button"] {
|
|
818
|
+
cursor: pointer;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
.visual-fraction-widget__sector[role="button"]:hover {
|
|
822
|
+
fill: var(--visual-fraction-hover-color);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
.visual-fraction-widget__sector[role="button"]:focus-visible {
|
|
826
|
+
outline: none;
|
|
827
|
+
filter: drop-shadow(0 0 0.18rem var(--exercise-border-focus, var(--exercise-primary, #007acc)));
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
.visual-fraction-widget__sector.visual-fraction-widget__part--filled,
|
|
831
|
+
.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
|
+
fill: var(--visual-fraction-part-color);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
.visual-fraction-widget.widget--correct .visual-fraction-widget__parts {
|
|
838
|
+
border-color: var(--exercise-correct, #22c55e);
|
|
839
|
+
background: var(--exercise-correct, #22c55e);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
.visual-fraction-widget.widget--incorrect .visual-fraction-widget__parts {
|
|
843
|
+
border-color: var(--exercise-incorrect, #ef4444);
|
|
844
|
+
background: var(--exercise-incorrect, #ef4444);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
.visual-fraction-widget.widget--correct .visual-fraction-widget__sector {
|
|
848
|
+
stroke: var(--exercise-correct, #22c55e);
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
.visual-fraction-widget.widget--incorrect .visual-fraction-widget__sector {
|
|
852
|
+
stroke: var(--exercise-incorrect, #ef4444);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
.visual-fraction-widget__shape {
|
|
856
|
+
width: var(--visual-fraction-size);
|
|
857
|
+
height: var(--visual-fraction-size);
|
|
858
|
+
overflow: visible;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
.visual-fraction-widget--grid .visual-fraction-widget__parts {
|
|
862
|
+
grid-template-columns: repeat(var(--visual-fraction-grid-cols, 3), 1fr);
|
|
863
|
+
grid-template-rows: repeat(var(--visual-fraction-grid-rows, 3), 1fr);
|
|
864
|
+
width: var(--visual-fraction-size);
|
|
865
|
+
height: var(--visual-fraction-size);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
.visual-fraction-widget__label {
|
|
869
|
+
color: var(--visual-fraction-label-color);
|
|
870
|
+
font-size: 0.9em;
|
|
871
|
+
font-weight: var(--exercise-font-weight, 500);
|
|
872
|
+
}
|
|
873
|
+
|
|
682
874
|
/* ========================================
|
|
683
875
|
MATCHER WIDGET
|
|
684
876
|
======================================== */
|
|
@@ -686,101 +878,76 @@ th.exercise-table-cell {
|
|
|
686
878
|
.matcher-widget {
|
|
687
879
|
display: flex;
|
|
688
880
|
flex-direction: column;
|
|
689
|
-
gap:
|
|
690
|
-
|
|
881
|
+
gap: clamp(10px, 2.5vw, 16px);
|
|
882
|
+
width: min(100%, 580px);
|
|
883
|
+
margin-inline: auto;
|
|
691
884
|
}
|
|
692
885
|
|
|
693
886
|
.matcher-row {
|
|
694
887
|
display: grid;
|
|
695
|
-
grid-template-columns: repeat(var(--matcher-cols, 3), 1fr);
|
|
696
|
-
gap:
|
|
888
|
+
grid-template-columns: repeat(var(--matcher-cols, 3), minmax(0, 1fr));
|
|
889
|
+
gap: clamp(10px, 2.5vw, 16px);
|
|
697
890
|
}
|
|
698
891
|
|
|
699
892
|
.matcher-card {
|
|
700
893
|
display: flex;
|
|
701
|
-
flex-wrap: wrap;
|
|
702
894
|
align-items: center;
|
|
703
895
|
justify-content: center;
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
border:
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
color: var(--exercise-text, #333);
|
|
711
|
-
font-size: var(--exercise-font-size, 1rem);
|
|
712
|
-
font-weight: var(--exercise-font-weight, 400);
|
|
713
|
-
line-height: 1.4;
|
|
896
|
+
min-height: clamp(72px, 14vw, 96px);
|
|
897
|
+
padding: clamp(8px, 2vw, 12px);
|
|
898
|
+
border: 2px solid #FFCA76;
|
|
899
|
+
border-radius: clamp(12px, 3vw, 17px);
|
|
900
|
+
background: #FFFFFF;
|
|
901
|
+
color: #333333;
|
|
714
902
|
text-align: center;
|
|
715
|
-
overflow-wrap: break-word;
|
|
716
|
-
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
|
|
717
903
|
cursor: pointer;
|
|
718
|
-
|
|
904
|
+
box-shadow: 0 4px 0 rgba(255, 202, 118, 0.22);
|
|
719
905
|
transition:
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
box-shadow
|
|
724
|
-
transform 0.2s ease,
|
|
725
|
-
filter 0.2s ease;
|
|
906
|
+
background 280ms cubic-bezier(0.34, 1.56, 0.64, 1),
|
|
907
|
+
border-color 280ms cubic-bezier(0.34, 1.56, 0.64, 1),
|
|
908
|
+
transform 220ms cubic-bezier(0.34, 1.56, 0.64, 1),
|
|
909
|
+
box-shadow 280ms ease;
|
|
726
910
|
}
|
|
727
911
|
|
|
912
|
+
.matcher-card:active {
|
|
913
|
+
transform: scale(0.95);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/* Intentionally dropped — kept for reference if hover feedback is restored.
|
|
728
917
|
.matcher-card:hover {
|
|
729
918
|
border-color: var(--exercise-accent, #705dc0);
|
|
730
919
|
box-shadow: 0 4px 10px rgba(112, 93, 192, 0.22);
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
.matcher-card:active {
|
|
734
|
-
transform: scale(0.96);
|
|
735
|
-
}
|
|
920
|
+
} */
|
|
736
921
|
|
|
737
922
|
.matcher-card--selected {
|
|
738
|
-
background: var(--matcher-card-color);
|
|
923
|
+
background: color-mix(in srgb, var(--matcher-card-color) 12%, #FFFFFF);
|
|
739
924
|
border-color: var(--matcher-card-color);
|
|
740
|
-
|
|
741
|
-
transform:
|
|
742
|
-
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.18);
|
|
925
|
+
box-shadow: 0 4px 0 color-mix(in srgb, var(--matcher-card-color) 30%, transparent);
|
|
926
|
+
transform: scale(1.04);
|
|
743
927
|
}
|
|
744
928
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
color: inherit;
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
.matcher-card--selected:hover {
|
|
753
|
-
border-color: var(--exercise-accent, #705dc0);
|
|
754
|
-
filter: brightness(1.07);
|
|
929
|
+
.widget--correct .matcher-card--selected {
|
|
930
|
+
border-color: #43B925;
|
|
931
|
+
background: #F2FFEE;
|
|
932
|
+
box-shadow: 0 4px 0 rgba(67, 185, 37, 0.30);
|
|
755
933
|
}
|
|
756
934
|
|
|
757
|
-
.matcher-card--selected
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
.matcher-widget.widget--correct .matcher-card--selected {
|
|
764
|
-
background: var(--exercise-correct, #22c55e);
|
|
765
|
-
border-color: var(--exercise-correct, #22c55e);
|
|
766
|
-
color: #fff;
|
|
935
|
+
.widget--incorrect .matcher-card--selected {
|
|
936
|
+
border-color: #D6234D;
|
|
937
|
+
background: #FFF0F7;
|
|
938
|
+
box-shadow: 0 4px 0 rgba(214, 35, 77, 0.25);
|
|
767
939
|
}
|
|
768
940
|
|
|
769
|
-
|
|
941
|
+
/* Intentionally dropped — kept for reference if unselected-card validation feedback is restored.
|
|
942
|
+
.widget--correct .matcher-card:not(.matcher-card--selected) {
|
|
770
943
|
border-color: var(--exercise-correct, #22c55e);
|
|
771
944
|
opacity: 0.5;
|
|
772
945
|
}
|
|
773
946
|
|
|
774
|
-
.
|
|
775
|
-
background: var(--exercise-incorrect, #ef4444);
|
|
776
|
-
border-color: var(--exercise-incorrect, #ef4444);
|
|
777
|
-
color: #fff;
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
.matcher-widget.widget--incorrect .matcher-card:not(.matcher-card--selected) {
|
|
947
|
+
.widget--incorrect .matcher-card:not(.matcher-card--selected) {
|
|
781
948
|
border-color: var(--exercise-incorrect, #ef4444);
|
|
782
949
|
opacity: 0.5;
|
|
783
|
-
}
|
|
950
|
+
} */
|
|
784
951
|
|
|
785
952
|
/**
|
|
786
953
|
* Number Line Styles
|
|
@@ -800,6 +967,10 @@ th.exercise-table-cell {
|
|
|
800
967
|
margin-bottom: var(--exercise-margin-bottom);
|
|
801
968
|
user-select: none;
|
|
802
969
|
--nl-chip-zone-height: 3rem;
|
|
970
|
+
--nl-position-content-height: 0px;
|
|
971
|
+
--nl-position-content-min-height: 2.8rem;
|
|
972
|
+
--nl-visual-fraction-part-size: clamp(0.8rem, 2vw, 1rem);
|
|
973
|
+
--nl-visual-fraction-size: clamp(5.5rem, 18vw, 8rem);
|
|
803
974
|
/* Visual gap between end ticks and arrowheads — pure CSS, no effect on calculations */
|
|
804
975
|
--nl-arrow-gap: 8px;
|
|
805
976
|
}
|
|
@@ -818,7 +989,7 @@ th.exercise-table-cell {
|
|
|
818
989
|
.number-line-content-row {
|
|
819
990
|
position: relative;
|
|
820
991
|
width: 100%;
|
|
821
|
-
min-height:
|
|
992
|
+
min-height: max(var(--nl-position-content-min-height), var(--nl-position-content-height));
|
|
822
993
|
}
|
|
823
994
|
|
|
824
995
|
.number-line-position-content {
|
|
@@ -831,6 +1002,11 @@ th.exercise-table-cell {
|
|
|
831
1002
|
z-index: 1;
|
|
832
1003
|
}
|
|
833
1004
|
|
|
1005
|
+
.number-line-position-content .visual-fraction-widget {
|
|
1006
|
+
--visual-fraction-part-size: var(--nl-visual-fraction-part-size);
|
|
1007
|
+
--visual-fraction-size: var(--nl-visual-fraction-size);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
834
1010
|
/* ========================================
|
|
835
1011
|
ROW 2 — AXIS (track + ticks + arrows + dots)
|
|
836
1012
|
======================================== */
|
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.17",
|
|
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",
|