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