@mathscan/math-exercise-engine 1.1.0 → 1.1.2
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 +6581 -2558
- package/dist/index.js +874 -79
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +874 -79
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +150 -77
- package/package.json +1 -1
package/dist/style.css
CHANGED
|
@@ -421,10 +421,6 @@ mark {
|
|
|
421
421
|
DRAG OPTIONS
|
|
422
422
|
======================================== */
|
|
423
423
|
|
|
424
|
-
.drag-options-container {
|
|
425
|
-
/* Container for drag options widget */
|
|
426
|
-
}
|
|
427
|
-
|
|
428
424
|
.drag-options {
|
|
429
425
|
display: flex;
|
|
430
426
|
justify-content: center;
|
|
@@ -737,10 +733,10 @@ th.exercise-table-cell {
|
|
|
737
733
|
--visual-fraction-svg-line-width: 0.5px;
|
|
738
734
|
--visual-fraction-gap: var(--visual-fraction-line-width);
|
|
739
735
|
--visual-fraction-border-radius: 0;
|
|
740
|
-
--visual-fraction-border-color: #
|
|
736
|
+
--visual-fraction-border-color: #705dc0;
|
|
741
737
|
--visual-fraction-empty-bg: var(--exercise-bg, #fff);
|
|
742
|
-
--visual-fraction-hover-color: #
|
|
743
|
-
--visual-fraction-part-color: #
|
|
738
|
+
--visual-fraction-hover-color: #e6e0ff;
|
|
739
|
+
--visual-fraction-part-color: #ae9cff;
|
|
744
740
|
--visual-fraction-part-text-color: #fff;
|
|
745
741
|
--visual-fraction-label-color: var(--exercise-text-light, #555);
|
|
746
742
|
display: inline-flex;
|
|
@@ -778,18 +774,21 @@ th.exercise-table-cell {
|
|
|
778
774
|
min-height: 0;
|
|
779
775
|
background: var(--visual-fraction-empty-bg);
|
|
780
776
|
color: var(--exercise-text, #333);
|
|
781
|
-
transition:
|
|
777
|
+
transition:
|
|
778
|
+
background 0.2s ease,
|
|
779
|
+
border-color 0.2s ease,
|
|
780
|
+
filter 0.2s ease;
|
|
782
781
|
}
|
|
783
782
|
|
|
784
|
-
.visual-fraction-widget__part[role=
|
|
783
|
+
.visual-fraction-widget__part[role='button'] {
|
|
785
784
|
cursor: pointer;
|
|
786
785
|
}
|
|
787
786
|
|
|
788
|
-
.visual-fraction-widget__part[role=
|
|
787
|
+
.visual-fraction-widget__part[role='button']:hover {
|
|
789
788
|
background: var(--visual-fraction-hover-color);
|
|
790
789
|
}
|
|
791
790
|
|
|
792
|
-
.visual-fraction-widget__part[role=
|
|
791
|
+
.visual-fraction-widget__part[role='button']:focus-visible {
|
|
793
792
|
outline: 2px solid var(--exercise-border-focus, var(--exercise-primary, #007acc));
|
|
794
793
|
outline-offset: -2px;
|
|
795
794
|
}
|
|
@@ -800,8 +799,8 @@ th.exercise-table-cell {
|
|
|
800
799
|
color: var(--visual-fraction-part-text-color);
|
|
801
800
|
}
|
|
802
801
|
|
|
803
|
-
.visual-fraction-widget__part--filled[role=
|
|
804
|
-
.visual-fraction-widget__part--answer[role=
|
|
802
|
+
.visual-fraction-widget__part--filled[role='button']:hover,
|
|
803
|
+
.visual-fraction-widget__part--answer[role='button']:hover {
|
|
805
804
|
background: var(--visual-fraction-part-color);
|
|
806
805
|
color: var(--visual-fraction-part-text-color);
|
|
807
806
|
}
|
|
@@ -812,26 +811,28 @@ th.exercise-table-cell {
|
|
|
812
811
|
stroke-width: var(--visual-fraction-svg-line-width);
|
|
813
812
|
stroke-linejoin: round;
|
|
814
813
|
stroke-linecap: round;
|
|
815
|
-
transition:
|
|
814
|
+
transition:
|
|
815
|
+
fill 0.2s ease,
|
|
816
|
+
filter 0.2s ease;
|
|
816
817
|
}
|
|
817
818
|
|
|
818
|
-
.visual-fraction-widget__sector[role=
|
|
819
|
+
.visual-fraction-widget__sector[role='button'] {
|
|
819
820
|
cursor: pointer;
|
|
820
821
|
}
|
|
821
822
|
|
|
822
|
-
.visual-fraction-widget__sector[role=
|
|
823
|
+
.visual-fraction-widget__sector[role='button']:hover {
|
|
823
824
|
fill: var(--visual-fraction-hover-color);
|
|
824
825
|
}
|
|
825
826
|
|
|
826
|
-
.visual-fraction-widget__sector[role=
|
|
827
|
+
.visual-fraction-widget__sector[role='button']:focus-visible {
|
|
827
828
|
outline: none;
|
|
828
829
|
filter: drop-shadow(0 0 0.18rem var(--exercise-border-focus, var(--exercise-primary, #007acc)));
|
|
829
830
|
}
|
|
830
831
|
|
|
831
832
|
.visual-fraction-widget__sector.visual-fraction-widget__part--filled,
|
|
832
833
|
.visual-fraction-widget__sector.visual-fraction-widget__part--answer,
|
|
833
|
-
.visual-fraction-widget__sector.visual-fraction-widget__part--filled[role=
|
|
834
|
-
.visual-fraction-widget__sector.visual-fraction-widget__part--answer[role=
|
|
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 {
|
|
835
836
|
fill: var(--visual-fraction-part-color);
|
|
836
837
|
}
|
|
837
838
|
|
|
@@ -896,9 +897,9 @@ th.exercise-table-cell {
|
|
|
896
897
|
justify-content: center;
|
|
897
898
|
min-height: clamp(72px, 14vw, 96px);
|
|
898
899
|
padding: clamp(8px, 2vw, 12px);
|
|
899
|
-
border: 2px solid #
|
|
900
|
+
border: 2px solid #ffca76;
|
|
900
901
|
border-radius: clamp(12px, 3vw, 17px);
|
|
901
|
-
background: #
|
|
902
|
+
background: #ffffff;
|
|
902
903
|
color: #333333;
|
|
903
904
|
text-align: center;
|
|
904
905
|
cursor: pointer;
|
|
@@ -921,21 +922,21 @@ th.exercise-table-cell {
|
|
|
921
922
|
} */
|
|
922
923
|
|
|
923
924
|
.matcher-card--selected {
|
|
924
|
-
background: color-mix(in srgb, var(--matcher-card-color) 12%, #
|
|
925
|
+
background: color-mix(in srgb, var(--matcher-card-color) 12%, #ffffff);
|
|
925
926
|
border-color: var(--matcher-card-color);
|
|
926
927
|
box-shadow: 0 4px 0 color-mix(in srgb, var(--matcher-card-color) 30%, transparent);
|
|
927
928
|
transform: scale(1.04);
|
|
928
929
|
}
|
|
929
930
|
|
|
930
931
|
.widget--correct .matcher-card--selected {
|
|
931
|
-
border-color: #
|
|
932
|
-
background: #
|
|
933
|
-
box-shadow: 0 4px 0 rgba(67, 185, 37, 0.
|
|
932
|
+
border-color: #43b925;
|
|
933
|
+
background: #f2ffee;
|
|
934
|
+
box-shadow: 0 4px 0 rgba(67, 185, 37, 0.3);
|
|
934
935
|
}
|
|
935
936
|
|
|
936
937
|
.widget--incorrect .matcher-card--selected {
|
|
937
|
-
border-color: #
|
|
938
|
-
background: #
|
|
938
|
+
border-color: #d6234d;
|
|
939
|
+
background: #fff0f7;
|
|
939
940
|
box-shadow: 0 4px 0 rgba(214, 35, 77, 0.25);
|
|
940
941
|
}
|
|
941
942
|
|
|
@@ -950,6 +951,109 @@ th.exercise-table-cell {
|
|
|
950
951
|
opacity: 0.5;
|
|
951
952
|
} */
|
|
952
953
|
|
|
954
|
+
/* ========================================
|
|
955
|
+
PAIR MATCHER WIDGET
|
|
956
|
+
======================================== */
|
|
957
|
+
|
|
958
|
+
.pair-matcher-widget {
|
|
959
|
+
--pm-orange: #FFCA76; --pm-purple: #705DC0;
|
|
960
|
+
--pm-selected-bg: #E7E2FF; --pm-selected-border: #AE9CFF;
|
|
961
|
+
--pm-card-width: 163px; --pm-card-height: 82px; --pm-card-radius: 12px; --pm-card-border-width: 1px;
|
|
962
|
+
--pm-dot-size: 17px; --pm-dot-border-width: 2px;
|
|
963
|
+
--pm-line-color: var(--pm-orange); --pm-line-color-correct: #43B925; --pm-line-color-incorrect: #D6234D; --pm-line-width: 4px;
|
|
964
|
+
position: relative; display: flex; flex-direction: column;
|
|
965
|
+
gap: 52px; width: max-content; max-width: 100%; margin-inline: auto; padding: 0;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.pair-matcher-row {
|
|
969
|
+
position: relative; z-index: 2; display: grid;
|
|
970
|
+
grid-template-columns: repeat(var(--pm-cols, 3), minmax(0, var(--pm-card-width)));
|
|
971
|
+
justify-content: center; gap: 18px; align-items: stretch; min-width: 0;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
.pair-matcher-cell { display: flex; flex-direction: column; align-items: center; min-width: 0; }
|
|
975
|
+
|
|
976
|
+
.pair-matcher-card {
|
|
977
|
+
box-sizing: border-box; display: flex; align-items: center; justify-content: center;
|
|
978
|
+
width: 100%; min-width: 0; max-width: 100%; align-self: stretch; flex: 1 1 auto;
|
|
979
|
+
min-height: var(--pm-card-height); height: auto; padding: 6px 8px;
|
|
980
|
+
border: var(--pm-card-border-width) solid var(--pm-orange); border-radius: var(--pm-card-radius);
|
|
981
|
+
background: #fff; color: var(--pm-purple);
|
|
982
|
+
font: 500 1rem / 1.2 var(--exercise-font-family, inherit); letter-spacing: 0;
|
|
983
|
+
text-align: center; word-break: normal; overflow-wrap: break-word;
|
|
984
|
+
white-space: normal; hyphens: auto; overflow: visible; cursor: pointer;
|
|
985
|
+
transition: background 0.35s ease, border-color 0.35s ease, transform 0.2s ease;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
.pair-matcher-card:not([aria-disabled="true"]):active { transform: scale(0.98); }
|
|
989
|
+
|
|
990
|
+
.pair-matcher-card[aria-disabled="true"] { cursor: default; }
|
|
991
|
+
|
|
992
|
+
.pair-matcher-card--pending, .pair-matcher-card--flash { border-color: var(--pm-selected-border); background: var(--pm-selected-bg); }
|
|
993
|
+
|
|
994
|
+
.pair-matcher-card--correct { border-color: #43B925; background: #F2FFEE; color: #43B925; }
|
|
995
|
+
|
|
996
|
+
.pair-matcher-card--incorrect { border-color: #D6234D; background: #FFF0F7; color: #D6234D; }
|
|
997
|
+
|
|
998
|
+
.pair-matcher-dot {
|
|
999
|
+
position: relative; z-index: 3; flex-shrink: 0;
|
|
1000
|
+
width: var(--pm-dot-size); height: var(--pm-dot-size);
|
|
1001
|
+
border: var(--pm-dot-border-width) solid var(--pm-orange); border-radius: 50%; background: #fff;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
.pair-matcher-dot--south { margin-top: calc(var(--pm-dot-size) / -2); }
|
|
1005
|
+
|
|
1006
|
+
.pair-matcher-dot--north { margin-bottom: calc(var(--pm-dot-size) / -2); }
|
|
1007
|
+
|
|
1008
|
+
.pair-matcher-dot--active { background: var(--pm-orange); }
|
|
1009
|
+
|
|
1010
|
+
.pair-matcher-dot--pending { border-color: var(--pm-selected-border); background: #fff; }
|
|
1011
|
+
|
|
1012
|
+
.pair-matcher-dot--correct { border-color: #43B925; background: #43B925; }
|
|
1013
|
+
|
|
1014
|
+
.pair-matcher-dot--incorrect { border-color: #D6234D; background: #D6234D; }
|
|
1015
|
+
|
|
1016
|
+
.pair-matcher-lines {
|
|
1017
|
+
position: absolute; inset: 0; z-index: 1;
|
|
1018
|
+
width: 100%; height: 100%; overflow: visible; pointer-events: none;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
.pair-matcher-line { stroke-dasharray: 1; animation: pair-matcher-line-draw 0.5s ease both; }
|
|
1022
|
+
|
|
1023
|
+
@keyframes pair-matcher-line-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
|
|
1024
|
+
|
|
1025
|
+
.pair-matcher-card .text-item,
|
|
1026
|
+
.pair-matcher-card .question-text,
|
|
1027
|
+
.pair-matcher-card .group {
|
|
1028
|
+
margin: 0; min-width: 0; max-width: 100%;
|
|
1029
|
+
color: inherit; font: inherit;
|
|
1030
|
+
overflow-wrap: break-word; word-break: normal; white-space: normal;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
.pair-matcher-card:not(.pair-matcher-card--rtl) .text-item,
|
|
1034
|
+
.pair-matcher-card:not(.pair-matcher-card--rtl) .question-text,
|
|
1035
|
+
.pair-matcher-card:not(.pair-matcher-card--rtl) .group { overflow-wrap: break-word; }
|
|
1036
|
+
|
|
1037
|
+
.pair-matcher-card--rtl { direction: rtl; unicode-bidi: plaintext; }
|
|
1038
|
+
|
|
1039
|
+
.pair-matcher-card-content {
|
|
1040
|
+
display: block; width: 100%; min-width: 0; max-width: 100%; text-align: inherit; white-space: normal;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
.pair-matcher-card-content .space { display: inline; width: auto; }
|
|
1044
|
+
|
|
1045
|
+
.pair-matcher-card .text-item-arabic,
|
|
1046
|
+
.pair-matcher-card .question-text-arabic {
|
|
1047
|
+
direction: rtl; font-size: 0.72rem; line-height: 1.15;
|
|
1048
|
+
overflow-wrap: normal; word-break: normal; hyphens: manual;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
@media (max-width: 420px) {
|
|
1052
|
+
.pair-matcher-widget { gap: 46px; }
|
|
1053
|
+
.pair-matcher-row { grid-template-columns: repeat(var(--pm-cols, 3), minmax(0, 1fr)); gap: 12px; }
|
|
1054
|
+
.pair-matcher-card { min-height: 58px; padding: 6px 7px; font-size: 0.92rem; }
|
|
1055
|
+
}
|
|
1056
|
+
|
|
953
1057
|
/**
|
|
954
1058
|
* Number Line Styles
|
|
955
1059
|
*
|
|
@@ -1544,7 +1648,9 @@ th.exercise-table-cell {
|
|
|
1544
1648
|
}
|
|
1545
1649
|
|
|
1546
1650
|
.draggable.dragging {
|
|
1547
|
-
|
|
1651
|
+
/* Hide original while drag overlay follows cursor to avoid duplicate render.
|
|
1652
|
+
visibility:hidden preserves layout space so neighbors don't shift. */
|
|
1653
|
+
visibility: hidden;
|
|
1548
1654
|
}
|
|
1549
1655
|
|
|
1550
1656
|
/* Droppable base */
|
|
@@ -1564,53 +1670,31 @@ th.exercise-table-cell {
|
|
|
1564
1670
|
outline-offset: 2px;
|
|
1565
1671
|
}
|
|
1566
1672
|
|
|
1567
|
-
/* Drag overlay - the item following cursor
|
|
1673
|
+
/* Drag overlay - the item following cursor. Matches the rendered button look,
|
|
1674
|
+
which is the `button.drag-option` legacy rule in styles/widgets.css
|
|
1675
|
+
(accent background + white text, no border).
|
|
1676
|
+
NOTE: @dnd-kit DragOverlay renders in a portal at document.body, outside
|
|
1677
|
+
the .math-exercise-renderer scope — so CSS vars must include fallbacks. */
|
|
1568
1678
|
.drag-overlay-option {
|
|
1569
|
-
padding:
|
|
1570
|
-
|
|
1679
|
+
padding: 10px 16px;
|
|
1680
|
+
border: none;
|
|
1681
|
+
border-radius: var(--exercise-border-radius, 0.25rem);
|
|
1682
|
+
background: var(--exercise-accent, #705DC0);
|
|
1571
1683
|
color: white;
|
|
1572
|
-
|
|
1573
|
-
font-weight: 500;
|
|
1574
|
-
|
|
1684
|
+
font-size: var(--exercise-font-size, clamp(0.875rem, 2vw, 1.1rem));
|
|
1685
|
+
font-weight: var(--exercise-font-weight, 500);
|
|
1686
|
+
min-width: var(--exercise-button-width, clamp(3rem, 6vw, 4rem));
|
|
1687
|
+
text-align: center;
|
|
1575
1688
|
cursor: grabbing;
|
|
1576
1689
|
}
|
|
1577
1690
|
|
|
1578
|
-
/*
|
|
1579
|
-
.
|
|
1580
|
-
display: flex;
|
|
1581
|
-
flex-wrap: wrap;
|
|
1582
|
-
gap: 8px;
|
|
1583
|
-
/* padding: 12px; */
|
|
1584
|
-
/* background: #f5f5f5; */
|
|
1585
|
-
border-radius: 8px;
|
|
1586
|
-
justify-content: center;
|
|
1587
|
-
}
|
|
1691
|
+
/* Note: .drag-options and .drag-option base styles live in styles/widgets.css
|
|
1692
|
+
(themed via CSS vars). Don't duplicate them here. */
|
|
1588
1693
|
|
|
1589
1694
|
.drag-option-wrapper {
|
|
1590
1695
|
display: inline-block;
|
|
1591
1696
|
}
|
|
1592
1697
|
|
|
1593
|
-
.drag-option {
|
|
1594
|
-
padding: 10px 20px;
|
|
1595
|
-
border: 2px solid #ddd;
|
|
1596
|
-
border-radius: 8px;
|
|
1597
|
-
background: white;
|
|
1598
|
-
font-size: 16px;
|
|
1599
|
-
font-weight: 500;
|
|
1600
|
-
cursor: grab;
|
|
1601
|
-
transition: all 0.15s ease;
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
|
-
.drag-option:hover {
|
|
1605
|
-
border-color: #4a90d9;
|
|
1606
|
-
background: #f0f7ff;
|
|
1607
|
-
}
|
|
1608
|
-
|
|
1609
|
-
.drag-option.selected {
|
|
1610
|
-
border-color: #4a90d9;
|
|
1611
|
-
background: #e3f0ff;
|
|
1612
|
-
}
|
|
1613
|
-
|
|
1614
1698
|
/* Slot container - maintains space when item is dragged out */
|
|
1615
1699
|
.drag-option-slot {
|
|
1616
1700
|
display: inline-flex;
|
|
@@ -1676,17 +1760,6 @@ th.exercise-table-cell {
|
|
|
1676
1760
|
background-color: rgba(74, 144, 217, 0.05);
|
|
1677
1761
|
}
|
|
1678
1762
|
|
|
1679
|
-
/* Drag options container at bottom */
|
|
1680
|
-
.drag-options-container {
|
|
1681
|
-
/* margin-top: 20px;
|
|
1682
|
-
padding-top: 16px;
|
|
1683
|
-
border-top: 1px solid #eee; */
|
|
1684
|
-
}
|
|
1685
|
-
|
|
1686
|
-
/* ============================================
|
|
1687
|
-
FUTURE WIDGETS - Placeholder styles
|
|
1688
|
-
============================================ */
|
|
1689
|
-
|
|
1690
1763
|
/* ============================================
|
|
1691
1764
|
DRAGGABLE TOOLS (Ruler, Protractor, etc.)
|
|
1692
1765
|
============================================ */
|
|
@@ -1747,4 +1820,4 @@ th.exercise-table-cell {
|
|
|
1747
1820
|
.math-exercise-renderer {
|
|
1748
1821
|
position: relative;
|
|
1749
1822
|
min-height: 200px;
|
|
1750
|
-
}
|
|
1823
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mathscan/math-exercise-engine",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
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",
|