@mathscan/math-exercise-engine 1.2.13 → 1.2.15
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/README.md +6 -3
- package/dist/{GeometryWidget-CMJTNSAG.js → GeometryWidget-CTTLw871.js} +2 -2
- package/dist/{GeometryWidget-CMJTNSAG.js.map → GeometryWidget-CTTLw871.js.map} +1 -1
- package/dist/{GeometryWidget-h2yNZsas.mjs → GeometryWidget-DZWM4LcD.mjs} +2 -2
- package/dist/{GeometryWidget-h2yNZsas.mjs.map → GeometryWidget-DZWM4LcD.mjs.map} +1 -1
- package/dist/{index-CAvdtiDQ.mjs → index-BLrnKegW.mjs} +2012 -1051
- package/dist/index-BLrnKegW.mjs.map +1 -0
- package/dist/{index-CbKXPRsS.js → index-C9OHpy2h.js} +1747 -786
- package/dist/index-C9OHpy2h.js.map +1 -0
- package/dist/index.d.ts +7574 -1766
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +282 -266
- package/dist/style.css +200 -23
- package/package.json +1 -1
- package/dist/index-CAvdtiDQ.mjs.map +0 -1
- package/dist/index-CbKXPRsS.js.map +0 -1
package/dist/style.css
CHANGED
|
@@ -515,6 +515,87 @@ mark {
|
|
|
515
515
|
opacity: 1;
|
|
516
516
|
}
|
|
517
517
|
|
|
518
|
+
/* ========================================
|
|
519
|
+
DROP INPUT
|
|
520
|
+
======================================== */
|
|
521
|
+
|
|
522
|
+
.drop-input {
|
|
523
|
+
direction: ltr;
|
|
524
|
+
text-align: center;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/* Border, color and padding come from .inline-input. 5em is InlineInput's default
|
|
528
|
+
box. Low specificity on purpose, so a host's .inline-input size wins. */
|
|
529
|
+
|
|
530
|
+
.drop-input.inline-input,
|
|
531
|
+
.drop-input-sizer.inline-input {
|
|
532
|
+
display: inline-flex;
|
|
533
|
+
align-items: center;
|
|
534
|
+
justify-content: center;
|
|
535
|
+
width: 5em;
|
|
536
|
+
/* A placeholder longer than the box grows it, on one line. Not fit-content: its
|
|
537
|
+
shrink-wrapped parent gets its width from this box, so that would wrap the text. */
|
|
538
|
+
min-width: max-content;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/* Keeps a line box when the box has no text, so it has the input's height. Only
|
|
542
|
+
when empty: beside a placeholder it is a flex item that a host's gap pushes apart. */
|
|
543
|
+
|
|
544
|
+
.drop-input--empty:empty::before,
|
|
545
|
+
.drop-input-sizer:empty::before {
|
|
546
|
+
content: '\200b';
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/* Not a real <input>, so ::placeholder can't style it and it would read as an
|
|
550
|
+
answer. Faded from the input's own color, so it suits any host without an override.
|
|
551
|
+
Padding is here because hosts set .inline-input padding to 0 for a centered short
|
|
552
|
+
value, which leaves a box-sized placeholder touching the border. */
|
|
553
|
+
|
|
554
|
+
.drop-input-placeholder {
|
|
555
|
+
padding: 0 0.25em;
|
|
556
|
+
color: var(--exercise-placeholder, color-mix(in srgb, currentColor 50%, transparent));
|
|
557
|
+
font-weight: normal;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/* Sizer and chip share one grid cell, so the cell fits whichever is bigger. */
|
|
561
|
+
|
|
562
|
+
.drop-input.drop-input--filled {
|
|
563
|
+
display: inline-grid;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
.drop-input--filled > * {
|
|
567
|
+
grid-area: 1 / 1;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
.drop-input-sizer {
|
|
571
|
+
visibility: hidden;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.drop-input--locked {
|
|
575
|
+
cursor: default;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/* Unresolved stored value (no matching bank option) — plain text, still clickable to clear. */
|
|
579
|
+
|
|
580
|
+
.drop-input-unresolved {
|
|
581
|
+
padding: 0;
|
|
582
|
+
border: 0;
|
|
583
|
+
background: transparent;
|
|
584
|
+
color: inherit;
|
|
585
|
+
font: inherit;
|
|
586
|
+
cursor: pointer;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.drop-input.widget--correct {
|
|
590
|
+
border-color: var(--exercise-correct, #22c55e);
|
|
591
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--exercise-correct, #22c55e) 15%, transparent);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.drop-input.widget--incorrect {
|
|
595
|
+
border-color: var(--exercise-incorrect, #ef4444);
|
|
596
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--exercise-incorrect, #ef4444) 15%, transparent);
|
|
597
|
+
}
|
|
598
|
+
|
|
518
599
|
/* ========================================
|
|
519
600
|
VALIDATION STATUS
|
|
520
601
|
======================================== */
|
|
@@ -636,19 +717,23 @@ mark {
|
|
|
636
717
|
box-shadow: 0 2px 4px rgba(0, 122, 204, 0.2);
|
|
637
718
|
}
|
|
638
719
|
|
|
639
|
-
/*
|
|
720
|
+
/* A gentle lift and soft halo invite the student to pick up a chip. */
|
|
640
721
|
|
|
641
722
|
@keyframes drag-option-hint {
|
|
642
|
-
0%, 100% {
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
723
|
+
0%, 100% {
|
|
724
|
+
transform: translateY(0);
|
|
725
|
+
box-shadow: 0 0 0 0 transparent, 0 0 0 transparent;
|
|
726
|
+
}
|
|
727
|
+
40%, 55% {
|
|
728
|
+
transform: translateY(-5px);
|
|
729
|
+
box-shadow:
|
|
730
|
+
0 0 0 5px color-mix(in srgb, var(--exercise-accent) 16%, transparent),
|
|
731
|
+
0 6px 12px color-mix(in srgb, var(--exercise-accent) 22%, transparent);
|
|
732
|
+
}
|
|
647
733
|
}
|
|
648
734
|
|
|
649
735
|
.drag-option.drag-option--hint {
|
|
650
|
-
|
|
651
|
-
animation: drag-option-hint 0.8s ease-in-out 0.4s 2 both;
|
|
736
|
+
animation: drag-option-hint 1.8s ease-in-out 0.65s 1 both;
|
|
652
737
|
}
|
|
653
738
|
|
|
654
739
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -669,6 +754,35 @@ button.drag-option {
|
|
|
669
754
|
font-weight: var(--exercise-font-weight);
|
|
670
755
|
}
|
|
671
756
|
|
|
757
|
+
/* Cards holding images or colored text: on the accent surface they could become
|
|
758
|
+
unreadable, so only the surface changes. Text-only cards stay plain chips.
|
|
759
|
+
Same specificity as button.drag-option, so a host's restyle of that rule wins
|
|
760
|
+
here too and all cards in a bank match. */
|
|
761
|
+
|
|
762
|
+
button.drag-option--rich {
|
|
763
|
+
background: var(--exercise-bg);
|
|
764
|
+
color: var(--exercise-text);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/* The mobile fixed chip width would clip an image. */
|
|
768
|
+
|
|
769
|
+
.rich-drag-option-slot button.drag-option {
|
|
770
|
+
width: auto;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
.rich-option-content {
|
|
774
|
+
display: inline-flex;
|
|
775
|
+
align-items: center;
|
|
776
|
+
white-space: nowrap;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
/* Text takes its color from the card it sits on. COLOR_TEXT keeps its own. */
|
|
780
|
+
|
|
781
|
+
.rich-option-content .text-item,
|
|
782
|
+
.rich-option-content .bold-text {
|
|
783
|
+
color: inherit;
|
|
784
|
+
}
|
|
785
|
+
|
|
672
786
|
/* ========================================
|
|
673
787
|
RADIO OPTIONS
|
|
674
788
|
======================================== */
|
|
@@ -3672,6 +3786,7 @@ button.drag-option {
|
|
|
3672
3786
|
--met-tutorial-next-text: #2e2463;
|
|
3673
3787
|
--met-tutorial-text: #2e2463;
|
|
3674
3788
|
--met-tutorial-bubble-border: #e0d9ff;
|
|
3789
|
+
--met-tutorial-fill-bg: #fff;
|
|
3675
3790
|
|
|
3676
3791
|
position: fixed;
|
|
3677
3792
|
inset: 0;
|
|
@@ -3799,12 +3914,24 @@ button.drag-option {
|
|
|
3799
3914
|
animation: met-tutorial-hop 550ms ease-in-out both;
|
|
3800
3915
|
}
|
|
3801
3916
|
|
|
3917
|
+
.met-tutorial-hop--digit {
|
|
3918
|
+
display: flex;
|
|
3919
|
+
align-items: center;
|
|
3920
|
+
justify-content: center;
|
|
3921
|
+
width: 24px;
|
|
3922
|
+
height: 24px;
|
|
3923
|
+
margin: -12px 0 0 -12px;
|
|
3924
|
+
color: white;
|
|
3925
|
+
font-size: 18px;
|
|
3926
|
+
font-weight: 700;
|
|
3927
|
+
}
|
|
3928
|
+
|
|
3802
3929
|
@keyframes met-tutorial-hop {
|
|
3803
3930
|
from { offset-distance: 0%; }
|
|
3804
3931
|
to { offset-distance: 100%; opacity: 0.2; }
|
|
3805
3932
|
}
|
|
3806
3933
|
|
|
3807
|
-
/*
|
|
3934
|
+
/* Guided digits (or generic dots) over the real answer box. */
|
|
3808
3935
|
|
|
3809
3936
|
.met-tutorial-fill {
|
|
3810
3937
|
display: flex;
|
|
@@ -3812,6 +3939,8 @@ button.drag-option {
|
|
|
3812
3939
|
justify-content: center;
|
|
3813
3940
|
gap: 0.35em;
|
|
3814
3941
|
border-radius: 10px;
|
|
3942
|
+
/* Opaque: a prefill or typed value in the real box must not show through. */
|
|
3943
|
+
background: var(--met-tutorial-fill-bg);
|
|
3815
3944
|
pointer-events: none;
|
|
3816
3945
|
font-size: 18px;
|
|
3817
3946
|
font-weight: 700;
|
|
@@ -4079,12 +4208,6 @@ button.drag-option {
|
|
|
4079
4208
|
user-select: none;
|
|
4080
4209
|
}
|
|
4081
4210
|
|
|
4082
|
-
.draggable.dragging {
|
|
4083
|
-
/* Hide original while drag overlay follows cursor to avoid duplicate render.
|
|
4084
|
-
visibility:hidden preserves layout space so neighbors don't shift. */
|
|
4085
|
-
visibility: hidden;
|
|
4086
|
-
}
|
|
4087
|
-
|
|
4088
4211
|
/* Droppable base */
|
|
4089
4212
|
.droppable {
|
|
4090
4213
|
display: inline-block;
|
|
@@ -4120,6 +4243,35 @@ button.drag-option {
|
|
|
4120
4243
|
cursor: grabbing;
|
|
4121
4244
|
}
|
|
4122
4245
|
|
|
4246
|
+
/* Carries the theme variables to the overlay; drops the root's own card look. */
|
|
4247
|
+
.math-exercise-renderer.rich-drag-overlay-root {
|
|
4248
|
+
padding: 0;
|
|
4249
|
+
background: transparent;
|
|
4250
|
+
border-radius: 0;
|
|
4251
|
+
box-shadow: none;
|
|
4252
|
+
}
|
|
4253
|
+
|
|
4254
|
+
.rich-drag-overlay-option {
|
|
4255
|
+
display: inline-flex;
|
|
4256
|
+
align-items: center;
|
|
4257
|
+
justify-content: center;
|
|
4258
|
+
}
|
|
4259
|
+
|
|
4260
|
+
/* Same light surface as .drag-option--rich in the bank. */
|
|
4261
|
+
.drag-overlay-option--rich {
|
|
4262
|
+
background: var(--exercise-bg);
|
|
4263
|
+
color: var(--exercise-text);
|
|
4264
|
+
}
|
|
4265
|
+
|
|
4266
|
+
/* The droppable wrapper carries the inline flow (its child .drop-input keeps
|
|
4267
|
+
.inline-widget for the no-dnd path). drop-active styling is shared with
|
|
4268
|
+
.inline-input-droppable below. */
|
|
4269
|
+
.drop-input-droppable {
|
|
4270
|
+
display: inline-flex;
|
|
4271
|
+
align-items: center;
|
|
4272
|
+
vertical-align: middle;
|
|
4273
|
+
}
|
|
4274
|
+
|
|
4123
4275
|
/* Note: .drag-options and .drag-option base styles live in styles/widgets.css
|
|
4124
4276
|
(themed via CSS vars). Don't duplicate them here. */
|
|
4125
4277
|
|
|
@@ -4127,20 +4279,34 @@ button.drag-option {
|
|
|
4127
4279
|
display: inline-block;
|
|
4128
4280
|
}
|
|
4129
4281
|
|
|
4130
|
-
/* Slot container - maintains space when item is dragged out
|
|
4282
|
+
/* Slot container - maintains space when item is dragged out.
|
|
4283
|
+
Shared by the legacy chip bank and the rich DRAGGABLE_OPTIONS bank. */
|
|
4131
4284
|
.drag-option-slot {
|
|
4132
4285
|
display: inline-flex;
|
|
4133
4286
|
min-width: 60px;
|
|
4134
4287
|
min-height: 44px;
|
|
4135
4288
|
}
|
|
4136
4289
|
|
|
4137
|
-
/* Empty slot - shows where
|
|
4290
|
+
/* Empty slot - shows where a chip came from, from pick-up on. It is sized by an
|
|
4291
|
+
invisible copy of the chip; the outline draws inside so the size stays exact.
|
|
4292
|
+
Solid, not dashed: dashed is the look of the inputs it must not be mistaken for. */
|
|
4138
4293
|
.drag-option-empty {
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
border: 2px dashed #d4c5a9;
|
|
4294
|
+
outline: 1px solid color-mix(in srgb, var(--exercise-accent) 30%, transparent);
|
|
4295
|
+
outline-offset: -1px;
|
|
4142
4296
|
border-radius: 8px;
|
|
4143
|
-
background:
|
|
4297
|
+
background: #FFEECA;
|
|
4298
|
+
}
|
|
4299
|
+
|
|
4300
|
+
.drag-option-empty .drag-option {
|
|
4301
|
+
visibility: hidden;
|
|
4302
|
+
}
|
|
4303
|
+
|
|
4304
|
+
/* Rich cards vary in size, so the slot always matches its hidden copy, even if a
|
|
4305
|
+
host gives .drag-option-empty a fixed width or a border that adds to the size.
|
|
4306
|
+
The outline above still draws the edge. */
|
|
4307
|
+
.rich-drag-option-slot .drag-option-empty {
|
|
4308
|
+
width: auto;
|
|
4309
|
+
border: 0;
|
|
4144
4310
|
}
|
|
4145
4311
|
|
|
4146
4312
|
/* Inline input droppable */
|
|
@@ -4203,8 +4369,19 @@ button.drag-option {
|
|
|
4203
4369
|
opacity: 0.4;
|
|
4204
4370
|
}
|
|
4205
4371
|
|
|
4206
|
-
/*
|
|
4207
|
-
.
|
|
4372
|
+
/* A chip in a DROP_INPUT stacks with its sizer instead of overlaying it, so a
|
|
4373
|
+
large card can grow the slot. See .drop-input--filled. */
|
|
4374
|
+
.inline-input-chip.placed-rich-option {
|
|
4375
|
+
display: inline-flex;
|
|
4376
|
+
align-items: center;
|
|
4377
|
+
justify-content: center;
|
|
4378
|
+
padding: 4px 8px;
|
|
4379
|
+
}
|
|
4380
|
+
|
|
4381
|
+
/* When droppable is active, style the input inside.
|
|
4382
|
+
DROP_INPUT shares the inline-input affordance. */
|
|
4383
|
+
.inline-input-droppable.drop-active .inline-input,
|
|
4384
|
+
.drop-input-droppable.drop-active .drop-input {
|
|
4208
4385
|
border-color: #4a90d9;
|
|
4209
4386
|
background-color: rgba(74, 144, 217, 0.05);
|
|
4210
4387
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mathscan/math-exercise-engine",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.15",
|
|
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",
|