@khanacademy/perseus 53.1.0 → 54.1.0
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/components/highlighting/types.d.ts +2 -1
- package/dist/components.d.ts +0 -1
- package/dist/es/index.js +621 -1948
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +61 -10
- package/dist/es/strings.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +698 -775
- package/dist/index.js.map +1 -1
- package/dist/interactive2/movable.d.ts +2 -1
- package/dist/strings.d.ts +57 -6
- package/dist/strings.js +139 -67
- package/dist/strings.js.map +1 -1
- package/dist/types.d.ts +6 -13
- package/dist/util/graphie.d.ts +1 -1
- package/dist/util.d.ts +0 -5
- package/dist/widget-ai-utils/radio/radio-ai-utils.d.ts +2 -1
- package/dist/widget-type-utils.d.ts +1 -0
- package/dist/widgets/categorizer/categorizer.d.ts +1 -2
- package/dist/widgets/cs-program/cs-program.d.ts +0 -2
- package/dist/widgets/dropdown/dropdown.d.ts +0 -2
- package/dist/widgets/expression/expression.d.ts +3 -6
- package/dist/widgets/grapher/grapher.d.ts +0 -2
- package/dist/widgets/iframe/iframe.d.ts +1 -2
- package/dist/widgets/interactive-graph.d.ts +2 -87
- package/dist/widgets/interactive-graphs/backgrounds/axis-labels.d.ts +4 -1
- package/dist/widgets/interactive-graphs/graphs/angle.d.ts +2 -1
- package/dist/widgets/interactive-graphs/graphs/circle.d.ts +6 -2
- package/dist/widgets/interactive-graphs/graphs/components/hairlines.d.ts +7 -0
- package/dist/widgets/interactive-graphs/graphs/components/movable-point-view.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/components/svg-line.d.ts +2 -1
- package/dist/widgets/interactive-graphs/graphs/linear-system.d.ts +2 -2
- package/dist/widgets/interactive-graphs/graphs/linear.d.ts +1 -1
- package/dist/widgets/interactive-graphs/graphs/point.d.ts +3 -2
- package/dist/widgets/interactive-graphs/graphs/ray.d.ts +1 -1
- package/dist/widgets/interactive-graphs/graphs/screenreader-text.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/segment.d.ts +2 -2
- package/dist/widgets/interactive-graphs/graphs/sinusoid.d.ts +2 -1
- package/dist/widgets/interactive-graphs/graphs/utils.d.ts +0 -3
- package/dist/widgets/interactive-graphs/interactive-graph-question-builder.d.ts +1 -2
- package/dist/widgets/interactive-graphs/reducer/interactive-graph-action.d.ts +3 -3
- package/dist/widgets/label-image/label-image.d.ts +1 -3
- package/dist/widgets/matrix/matrix.d.ts +1 -2
- package/dist/widgets/number-line/number-line.d.ts +0 -2
- package/dist/widgets/numeric-input/numeric-input.d.ts +0 -2
- package/dist/widgets/orderer/orderer.d.ts +0 -2
- package/dist/widgets/plotter/plotter.d.ts +0 -2
- package/dist/widgets/radio/radio.d.ts +1 -2
- package/dist/widgets/sorter/sorter.d.ts +1 -2
- package/dist/widgets/table/table.d.ts +0 -2
- package/dist/widgets.d.ts +1 -2
- package/package.json +10 -10
- package/dist/components/graph.d.ts +0 -61
package/dist/index.js
CHANGED
|
@@ -33,7 +33,6 @@ var Banner = require('@khanacademy/wonder-blocks-banner');
|
|
|
33
33
|
var wonderBlocksDropdown = require('@khanacademy/wonder-blocks-dropdown');
|
|
34
34
|
var caretDown = require('@phosphor-icons/core/regular/caret-down.svg');
|
|
35
35
|
var caretUp = require('@phosphor-icons/core/regular/caret-up.svg');
|
|
36
|
-
require('lodash.debounce');
|
|
37
36
|
var mafs = require('mafs');
|
|
38
37
|
var wonderBlocksIcon = require('@khanacademy/wonder-blocks-icon');
|
|
39
38
|
var questionIcon = require('@phosphor-icons/core/regular/question.svg');
|
|
@@ -367,6 +366,10 @@ const mockStrings = {
|
|
|
367
366
|
simulationLocaleWarning: "Sorry, this simulation isn't available in your language.",
|
|
368
367
|
selectAnAnswer: "Select an answer",
|
|
369
368
|
// The following strings are used for interactive graph SR descriptions.
|
|
369
|
+
srGraphInstructions: "Use the Tab key to move through the interactive elements in the graph. When an interactive element has focus, use the Arrow keys to move it.",
|
|
370
|
+
srUnlimitedGraphInstructions: "Press Shift + Enter to interact with the graph. Use the Tab key to move through the interactive elements in the graph and access the graph Action Bar. When an interactive element has focus, use the Arrow keys to move it or use the Delete key to remove it from the graph. Use the buttons in the Action Bar to add or adjust elements within the graph.",
|
|
371
|
+
xAxis: "X-axis",
|
|
372
|
+
yAxis: "Y-axis",
|
|
370
373
|
graphKeyboardPrompt: "Press Shift + Enter to interact with the graph",
|
|
371
374
|
addPoint: "Add Point",
|
|
372
375
|
removePoint: "Remove Point",
|
|
@@ -464,25 +467,37 @@ const mockStrings = {
|
|
|
464
467
|
} = _ref37;
|
|
465
468
|
return `Line from ${point1X} comma ${point1Y} to ${point2X} comma ${point2Y}.`;
|
|
466
469
|
},
|
|
467
|
-
|
|
470
|
+
srAngleStartingSide: _ref38 => {
|
|
468
471
|
let {
|
|
469
|
-
point,
|
|
470
|
-
side,
|
|
471
472
|
x,
|
|
472
473
|
y
|
|
473
474
|
} = _ref38;
|
|
474
|
-
return `Point
|
|
475
|
+
return `Point 3, starting side at ${x} comma ${y}.`;
|
|
475
476
|
},
|
|
476
|
-
|
|
477
|
+
srAngleEndingSide: _ref39 => {
|
|
478
|
+
let {
|
|
479
|
+
x,
|
|
480
|
+
y
|
|
481
|
+
} = _ref39;
|
|
482
|
+
return `Point 2, ending side at ${x} comma ${y}.`;
|
|
483
|
+
},
|
|
484
|
+
srAngleVertex: _ref40 => {
|
|
485
|
+
let {
|
|
486
|
+
x,
|
|
487
|
+
y
|
|
488
|
+
} = _ref40;
|
|
489
|
+
return `Point 1, vertex at ${x} comma ${y}.`;
|
|
490
|
+
},
|
|
491
|
+
srAngleVertexWithAngleMeasure: _ref41 => {
|
|
477
492
|
let {
|
|
478
493
|
x,
|
|
479
494
|
y,
|
|
480
495
|
angleMeasure
|
|
481
|
-
} =
|
|
482
|
-
return `Point
|
|
496
|
+
} = _ref41;
|
|
497
|
+
return `Point 1, vertex at ${x} comma ${y}. Angle ${angleMeasure} degrees.`;
|
|
483
498
|
},
|
|
484
499
|
srAngleGraphAriaLabel: "An angle on a coordinate plane.",
|
|
485
|
-
srAngleGraphAriaDescription:
|
|
500
|
+
srAngleGraphAriaDescription: _ref42 => {
|
|
486
501
|
let {
|
|
487
502
|
angleMeasure,
|
|
488
503
|
vertexX,
|
|
@@ -491,118 +506,129 @@ const mockStrings = {
|
|
|
491
506
|
startingSideY,
|
|
492
507
|
endingSideX,
|
|
493
508
|
endingSideY
|
|
494
|
-
} =
|
|
509
|
+
} = _ref42;
|
|
495
510
|
return `The angle measure is ${angleMeasure} degrees with a vertex at ${vertexX} comma ${vertexY}, a point on the starting side at ${startingSideX} comma ${startingSideY} and a point on the ending side at ${endingSideX} comma ${endingSideY}.`;
|
|
496
511
|
},
|
|
512
|
+
srAngleInteractiveElements: _ref43 => {
|
|
513
|
+
let {
|
|
514
|
+
vertexX,
|
|
515
|
+
vertexY,
|
|
516
|
+
startingSideX,
|
|
517
|
+
startingSideY,
|
|
518
|
+
endingSideX,
|
|
519
|
+
endingSideY
|
|
520
|
+
} = _ref43;
|
|
521
|
+
return `An angle formed by 3 points. The vertex is at ${vertexX} comma ${vertexY}. The starting side point is at ${startingSideX} comma ${startingSideY}. The ending side point is at ${endingSideX} comma ${endingSideY}.`;
|
|
522
|
+
},
|
|
497
523
|
srSingleSegmentGraphAriaLabel: "A line segment on a coordinate plane.",
|
|
498
|
-
srMultipleSegmentGraphAriaLabel:
|
|
524
|
+
srMultipleSegmentGraphAriaLabel: _ref44 => {
|
|
499
525
|
let {
|
|
500
526
|
countOfSegments
|
|
501
|
-
} =
|
|
527
|
+
} = _ref44;
|
|
502
528
|
return `${countOfSegments} segments on a coordinate plane.`;
|
|
503
529
|
},
|
|
504
|
-
srMultipleSegmentIndividualLabel:
|
|
530
|
+
srMultipleSegmentIndividualLabel: _ref45 => {
|
|
505
531
|
let {
|
|
506
532
|
point1X,
|
|
507
533
|
point1Y,
|
|
508
534
|
point2X,
|
|
509
535
|
point2Y,
|
|
510
536
|
indexOfSegment
|
|
511
|
-
} =
|
|
537
|
+
} = _ref45;
|
|
512
538
|
return `Segment ${indexOfSegment}: Endpoint 1 at ${point1X} comma ${point1Y}. Endpoint 2 at ${point2X} comma ${point2Y}.`;
|
|
513
539
|
},
|
|
514
|
-
srSingleSegmentLabel:
|
|
540
|
+
srSingleSegmentLabel: _ref46 => {
|
|
515
541
|
let {
|
|
516
542
|
point1X,
|
|
517
543
|
point1Y,
|
|
518
544
|
point2X,
|
|
519
545
|
point2Y
|
|
520
|
-
} =
|
|
546
|
+
} = _ref46;
|
|
521
547
|
return `Endpoint 1 at ${point1X} comma ${point1Y}. Endpoint 2 at ${point2X} comma ${point2Y}.`;
|
|
522
548
|
},
|
|
523
|
-
srSegmentLength:
|
|
549
|
+
srSegmentLength: _ref47 => {
|
|
524
550
|
let {
|
|
525
551
|
length
|
|
526
|
-
} =
|
|
552
|
+
} = _ref47;
|
|
527
553
|
return `Segment length ${length} units.`;
|
|
528
554
|
},
|
|
529
|
-
srSingleSegmentGraphEndpointAriaLabel:
|
|
555
|
+
srSingleSegmentGraphEndpointAriaLabel: _ref48 => {
|
|
530
556
|
let {
|
|
531
557
|
endpointNumber,
|
|
532
558
|
x,
|
|
533
559
|
y
|
|
534
|
-
} =
|
|
560
|
+
} = _ref48;
|
|
535
561
|
return `Endpoint ${endpointNumber} at ${x} comma ${y}.`;
|
|
536
562
|
},
|
|
537
|
-
srMultipleSegmentGraphEndpointAriaLabel:
|
|
563
|
+
srMultipleSegmentGraphEndpointAriaLabel: _ref49 => {
|
|
538
564
|
let {
|
|
539
565
|
endpointNumber,
|
|
540
566
|
x,
|
|
541
567
|
y,
|
|
542
568
|
indexOfSegment
|
|
543
|
-
} =
|
|
569
|
+
} = _ref49;
|
|
544
570
|
return `Endpoint ${endpointNumber} on segment ${indexOfSegment} at ${x} comma ${y}.`;
|
|
545
571
|
},
|
|
546
|
-
srSegmentGrabHandle:
|
|
572
|
+
srSegmentGrabHandle: _ref50 => {
|
|
547
573
|
let {
|
|
548
574
|
point1X,
|
|
549
575
|
point1Y,
|
|
550
576
|
point2X,
|
|
551
577
|
point2Y
|
|
552
|
-
} =
|
|
578
|
+
} = _ref50;
|
|
553
579
|
return `Segment from ${point1X} comma ${point1Y} to ${point2X} comma ${point2Y}.`;
|
|
554
580
|
},
|
|
555
581
|
srLinearSystemGraph: "Two lines on a coordinate plane.",
|
|
556
|
-
srLinearSystemPoints:
|
|
582
|
+
srLinearSystemPoints: _ref51 => {
|
|
557
583
|
let {
|
|
558
584
|
lineNumber,
|
|
559
585
|
point1X,
|
|
560
586
|
point1Y,
|
|
561
587
|
point2X,
|
|
562
588
|
point2Y
|
|
563
|
-
} =
|
|
589
|
+
} = _ref51;
|
|
564
590
|
return `Line ${lineNumber} has two points, point 1 at ${point1X} comma ${point1Y} and point 2 at ${point2X} comma ${point2Y}.`;
|
|
565
591
|
},
|
|
566
|
-
srLinearSystemPoint:
|
|
592
|
+
srLinearSystemPoint: _ref52 => {
|
|
567
593
|
let {
|
|
568
594
|
lineNumber,
|
|
569
595
|
pointSequence,
|
|
570
596
|
x,
|
|
571
597
|
y
|
|
572
|
-
} =
|
|
598
|
+
} = _ref52;
|
|
573
599
|
return `Point ${pointSequence} on line ${lineNumber} at ${x} comma ${y}.`;
|
|
574
600
|
},
|
|
575
601
|
srRayGraph: "A ray on a coordinate plane.",
|
|
576
|
-
srRayPoints:
|
|
602
|
+
srRayPoints: _ref53 => {
|
|
577
603
|
let {
|
|
578
604
|
point1X,
|
|
579
605
|
point1Y,
|
|
580
606
|
point2X,
|
|
581
607
|
point2Y
|
|
582
|
-
} =
|
|
608
|
+
} = _ref53;
|
|
583
609
|
return `The endpoint is at ${point1X} comma ${point1Y} and the ray goes through point ${point2X} comma ${point2Y}.`;
|
|
584
610
|
},
|
|
585
|
-
srRayGrabHandle:
|
|
611
|
+
srRayGrabHandle: _ref54 => {
|
|
586
612
|
let {
|
|
587
613
|
point1X,
|
|
588
614
|
point1Y,
|
|
589
615
|
point2X,
|
|
590
616
|
point2Y
|
|
591
|
-
} =
|
|
617
|
+
} = _ref54;
|
|
592
618
|
return `Ray with endpoint ${point1X} comma ${point1Y} going through point ${point2X} comma ${point2Y}.`;
|
|
593
619
|
},
|
|
594
|
-
srRayEndpoint:
|
|
620
|
+
srRayEndpoint: _ref55 => {
|
|
595
621
|
let {
|
|
596
622
|
x,
|
|
597
623
|
y
|
|
598
|
-
} =
|
|
624
|
+
} = _ref55;
|
|
599
625
|
return `Endpoint at ${x} comma ${y}.`;
|
|
600
626
|
},
|
|
601
|
-
srRayTerminalPoint:
|
|
627
|
+
srRayTerminalPoint: _ref56 => {
|
|
602
628
|
let {
|
|
603
629
|
x,
|
|
604
630
|
y
|
|
605
|
-
} =
|
|
631
|
+
} = _ref56;
|
|
606
632
|
return `Through point at ${x} comma ${y}.`;
|
|
607
633
|
},
|
|
608
634
|
srQuadraticGraph: "A parabola on a 4-quadrant coordinate plane.",
|
|
@@ -611,55 +637,55 @@ const mockStrings = {
|
|
|
611
637
|
srQuadraticGraphVertexOrigin: "Vertex is at the origin.",
|
|
612
638
|
srQuadraticGraphVertexXAxis: "Vertex is on the X-axis.",
|
|
613
639
|
srQuadraticGraphVertexYAxis: "Vertex is on the Y-axis.",
|
|
614
|
-
srQuadraticGraphVertexQuadrant:
|
|
640
|
+
srQuadraticGraphVertexQuadrant: _ref57 => {
|
|
615
641
|
let {
|
|
616
642
|
quadrant
|
|
617
|
-
} =
|
|
643
|
+
} = _ref57;
|
|
618
644
|
return `Vertex is in quadrant ${quadrant}.`;
|
|
619
645
|
},
|
|
620
|
-
srQuadraticTwoXIntercepts:
|
|
646
|
+
srQuadraticTwoXIntercepts: _ref58 => {
|
|
621
647
|
let {
|
|
622
648
|
intercept1,
|
|
623
649
|
intercept2
|
|
624
|
-
} =
|
|
650
|
+
} = _ref58;
|
|
625
651
|
return `The X-intercepts are at ${intercept1} comma 0 and ${intercept2} comma 0.`;
|
|
626
652
|
},
|
|
627
|
-
srQuadraticOneXIntercept:
|
|
653
|
+
srQuadraticOneXIntercept: _ref59 => {
|
|
628
654
|
let {
|
|
629
655
|
intercept
|
|
630
|
-
} =
|
|
656
|
+
} = _ref59;
|
|
631
657
|
return `The X-intercept is at ${intercept} comma 0.`;
|
|
632
658
|
},
|
|
633
|
-
srQuadraticYIntercept:
|
|
659
|
+
srQuadraticYIntercept: _ref60 => {
|
|
634
660
|
let {
|
|
635
661
|
intercept
|
|
636
|
-
} =
|
|
662
|
+
} = _ref60;
|
|
637
663
|
return `The Y-intercept is at 0 comma ${intercept}.`;
|
|
638
664
|
},
|
|
639
|
-
srQuadraticPointOrigin:
|
|
665
|
+
srQuadraticPointOrigin: _ref61 => {
|
|
640
666
|
let {
|
|
641
667
|
pointNumber
|
|
642
|
-
} =
|
|
668
|
+
} = _ref61;
|
|
643
669
|
return `Point ${pointNumber} on parabola at the origin.`;
|
|
644
670
|
},
|
|
645
|
-
srQuadraticPointAxis:
|
|
671
|
+
srQuadraticPointAxis: _ref62 => {
|
|
646
672
|
let {
|
|
647
673
|
pointNumber,
|
|
648
674
|
x,
|
|
649
675
|
y
|
|
650
|
-
} =
|
|
676
|
+
} = _ref62;
|
|
651
677
|
return `Point ${pointNumber} on parabola at ${x} comma ${y}.`;
|
|
652
678
|
},
|
|
653
|
-
srQuadraticPointQuadrant:
|
|
679
|
+
srQuadraticPointQuadrant: _ref63 => {
|
|
654
680
|
let {
|
|
655
681
|
pointNumber,
|
|
656
682
|
x,
|
|
657
683
|
y,
|
|
658
684
|
quadrant
|
|
659
|
-
} =
|
|
685
|
+
} = _ref63;
|
|
660
686
|
return `Point ${pointNumber} on parabola in quadrant ${quadrant} at ${x} comma ${y}.`;
|
|
661
687
|
},
|
|
662
|
-
srQuadraticInteractiveElements:
|
|
688
|
+
srQuadraticInteractiveElements: _ref64 => {
|
|
663
689
|
let {
|
|
664
690
|
point1X,
|
|
665
691
|
point1Y,
|
|
@@ -667,52 +693,85 @@ const mockStrings = {
|
|
|
667
693
|
point2Y,
|
|
668
694
|
point3X,
|
|
669
695
|
point3Y
|
|
670
|
-
} =
|
|
696
|
+
} = _ref64;
|
|
671
697
|
return `Parabola with points at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, and ${point3X} comma ${point3Y}.`;
|
|
672
698
|
},
|
|
673
699
|
srPolygonGraph: "A polygon.",
|
|
674
700
|
srPolygonGraphCoordinatePlane: "A polygon on a coordinate plane.",
|
|
675
|
-
srPolygonGraphPointsNum:
|
|
701
|
+
srPolygonGraphPointsNum: _ref65 => {
|
|
676
702
|
let {
|
|
677
703
|
num
|
|
678
|
-
} =
|
|
704
|
+
} = _ref65;
|
|
679
705
|
return `The polygon has ${num} points.`;
|
|
680
706
|
},
|
|
681
707
|
srPolygonGraphPointsOne: "The polygon has 1 point.",
|
|
682
|
-
srPolygonElementsNum:
|
|
708
|
+
srPolygonElementsNum: _ref66 => {
|
|
683
709
|
let {
|
|
684
710
|
num
|
|
685
|
-
} =
|
|
711
|
+
} = _ref66;
|
|
686
712
|
return `A polygon with ${num} points.`;
|
|
687
713
|
},
|
|
688
714
|
srPolygonElementsOne: "A polygon with 1 point.",
|
|
689
|
-
srPolygonPointAngleApprox:
|
|
715
|
+
srPolygonPointAngleApprox: _ref67 => {
|
|
690
716
|
let {
|
|
691
717
|
angle
|
|
692
|
-
} =
|
|
718
|
+
} = _ref67;
|
|
693
719
|
return `Angle approximately equal to ${angle} degrees.`;
|
|
694
720
|
},
|
|
695
|
-
srPolygonPointAngle:
|
|
721
|
+
srPolygonPointAngle: _ref68 => {
|
|
696
722
|
let {
|
|
697
723
|
angle
|
|
698
|
-
} =
|
|
724
|
+
} = _ref68;
|
|
699
725
|
return `Angle equal to ${angle} degrees.`;
|
|
700
726
|
},
|
|
701
|
-
srPolygonSideLength:
|
|
727
|
+
srPolygonSideLength: _ref69 => {
|
|
702
728
|
let {
|
|
703
729
|
pointNum,
|
|
704
730
|
length
|
|
705
|
-
} =
|
|
731
|
+
} = _ref69;
|
|
706
732
|
return `A line segment, length equal to ${length} units, connects to point ${pointNum}.`;
|
|
707
733
|
},
|
|
708
|
-
srPolygonSideLengthApprox:
|
|
734
|
+
srPolygonSideLengthApprox: _ref70 => {
|
|
709
735
|
let {
|
|
710
736
|
pointNum,
|
|
711
737
|
length
|
|
712
|
-
} =
|
|
738
|
+
} = _ref70;
|
|
713
739
|
return `A line segment, length approximately equal to ${length} units, connects to point ${pointNum}.`;
|
|
714
740
|
},
|
|
715
|
-
srUnlimitedPolygonEmpty: "An empty coordinate plane."
|
|
741
|
+
srUnlimitedPolygonEmpty: "An empty coordinate plane.",
|
|
742
|
+
srSinusoidGraph: "A sinusoid function on a coordinate plane.",
|
|
743
|
+
srSinusoidRootPoint: _ref71 => {
|
|
744
|
+
let {
|
|
745
|
+
x,
|
|
746
|
+
y
|
|
747
|
+
} = _ref71;
|
|
748
|
+
return `Midline intersection at ${x} comma ${y}.`;
|
|
749
|
+
},
|
|
750
|
+
srSinusoidPeakPoint: _ref72 => {
|
|
751
|
+
let {
|
|
752
|
+
x,
|
|
753
|
+
y
|
|
754
|
+
} = _ref72;
|
|
755
|
+
return `Extremum point at ${x} comma ${y}.`;
|
|
756
|
+
},
|
|
757
|
+
srSinusoidDescription: _ref73 => {
|
|
758
|
+
let {
|
|
759
|
+
minValue,
|
|
760
|
+
maxValue,
|
|
761
|
+
cycleStart,
|
|
762
|
+
cycleEnd
|
|
763
|
+
} = _ref73;
|
|
764
|
+
return `The graph shows a wave with a minimum value of ${minValue} and a maximum value of ${maxValue}. The wave completes a full cycle from ${cycleStart} to ${cycleEnd}.`;
|
|
765
|
+
},
|
|
766
|
+
srSinusoidInteractiveElements: _ref74 => {
|
|
767
|
+
let {
|
|
768
|
+
point1X,
|
|
769
|
+
point1Y,
|
|
770
|
+
point2X,
|
|
771
|
+
point2Y
|
|
772
|
+
} = _ref74;
|
|
773
|
+
return `Sinusoid graph with midline intersection point at ${point1X} comma ${point1Y} and extremum point at ${point2X} comma ${point2Y}.`;
|
|
774
|
+
}
|
|
716
775
|
// The above strings are used for interactive graph SR descriptions.
|
|
717
776
|
};
|
|
718
777
|
|
|
@@ -1634,6 +1693,7 @@ const ApiOptions = {
|
|
|
1634
1693
|
},
|
|
1635
1694
|
baseElements: {
|
|
1636
1695
|
Link: props => {
|
|
1696
|
+
// eslint-disable-next-line jsx-a11y/anchor-has-content -- TODO(LEMS-2871): Address a11y error
|
|
1637
1697
|
return /*#__PURE__*/React__namespace.createElement("a", props);
|
|
1638
1698
|
}
|
|
1639
1699
|
},
|
|
@@ -2034,7 +2094,6 @@ var Expression$1 = {
|
|
|
2034
2094
|
propUpgrades: perseusCore.expressionLogic.widgetOptionsUpgrades,
|
|
2035
2095
|
// For use by the editor
|
|
2036
2096
|
isLintable: true,
|
|
2037
|
-
getPublicWidgetOptions: perseusCore.getExpressionPublicWidgetOptions,
|
|
2038
2097
|
// TODO(LEMS-2656): remove TS suppression
|
|
2039
2098
|
// @ts-expect-error: Type 'Rubric' is not assignable to type 'PerseusExpressionRubric'.
|
|
2040
2099
|
getOneCorrectAnswerFromRubric(rubric) {
|
|
@@ -2138,55 +2197,6 @@ const rWidgetRule = /^\[\[\u2603 (([a-z-]+) ([0-9]+))\]\]/;
|
|
|
2138
2197
|
const rTypeFromWidgetId = /^([a-z-]+) ([0-9]+)$/;
|
|
2139
2198
|
const rWidgetParts = new RegExp(rWidgetRule.source + "$");
|
|
2140
2199
|
const snowman = "\u2603";
|
|
2141
|
-
const seededRNG$1 = function (seed) {
|
|
2142
|
-
let randomSeed = seed;
|
|
2143
|
-
return function () {
|
|
2144
|
-
// Robert Jenkins' 32 bit integer hash function.
|
|
2145
|
-
let seed = randomSeed;
|
|
2146
|
-
seed = seed + 0x7ed55d16 + (seed << 12) & 0xffffffff;
|
|
2147
|
-
seed = (seed ^ 0xc761c23c ^ seed >>> 19) & 0xffffffff;
|
|
2148
|
-
seed = seed + 0x165667b1 + (seed << 5) & 0xffffffff;
|
|
2149
|
-
seed = (seed + 0xd3a2646c ^ seed << 9) & 0xffffffff;
|
|
2150
|
-
seed = seed + 0xfd7046c5 + (seed << 3) & 0xffffffff;
|
|
2151
|
-
seed = (seed ^ 0xb55a4f09 ^ seed >>> 16) & 0xffffffff;
|
|
2152
|
-
return (randomSeed = seed & 0xfffffff) / 0x10000000;
|
|
2153
|
-
};
|
|
2154
|
-
};
|
|
2155
|
-
|
|
2156
|
-
// Shuffle an array using a given random seed or function.
|
|
2157
|
-
// If `ensurePermuted` is true, the input and ouput are guaranteed to be
|
|
2158
|
-
// distinct permutations.
|
|
2159
|
-
function shuffle$3(array, randomSeed) {
|
|
2160
|
-
let ensurePermuted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
2161
|
-
// Always return a copy of the input array
|
|
2162
|
-
const shuffled = ___default["default"].clone(array);
|
|
2163
|
-
|
|
2164
|
-
// Handle edge cases (input array is empty or uniform)
|
|
2165
|
-
if (!shuffled.length || ___default["default"].all(shuffled, function (value) {
|
|
2166
|
-
return ___default["default"].isEqual(value, shuffled[0]);
|
|
2167
|
-
})) {
|
|
2168
|
-
return shuffled;
|
|
2169
|
-
}
|
|
2170
|
-
let random;
|
|
2171
|
-
if (typeof randomSeed === "function") {
|
|
2172
|
-
random = randomSeed;
|
|
2173
|
-
} else {
|
|
2174
|
-
random = seededRNG$1(randomSeed);
|
|
2175
|
-
}
|
|
2176
|
-
do {
|
|
2177
|
-
// Fischer-Yates shuffle
|
|
2178
|
-
for (let top = shuffled.length; top > 0; top--) {
|
|
2179
|
-
const newEnd = Math.floor(random() * top);
|
|
2180
|
-
const temp = shuffled[newEnd];
|
|
2181
|
-
|
|
2182
|
-
// @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
|
|
2183
|
-
shuffled[newEnd] = shuffled[top - 1];
|
|
2184
|
-
// @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
|
|
2185
|
-
shuffled[top - 1] = temp;
|
|
2186
|
-
}
|
|
2187
|
-
} while (ensurePermuted && ___default["default"].isEqual(array, shuffled));
|
|
2188
|
-
return shuffled;
|
|
2189
|
-
}
|
|
2190
2200
|
|
|
2191
2201
|
/**
|
|
2192
2202
|
* TODO(somewhatabstract, FEI-3463):
|
|
@@ -2617,7 +2627,6 @@ const textarea = {
|
|
|
2617
2627
|
* to translate it but don't need the extra dollar signs.
|
|
2618
2628
|
*/
|
|
2619
2629
|
const unescapeMathMode$1 = label => label.startsWith("$") && label.endsWith("$") ? label.slice(1, -1) : label;
|
|
2620
|
-
const random$1 = seededRNG$1(new Date().getTime() & 0xffffffff);
|
|
2621
2630
|
const Util = {
|
|
2622
2631
|
inputPathsEqual,
|
|
2623
2632
|
nestedMap: nestedMap$2,
|
|
@@ -2625,8 +2634,6 @@ const Util = {
|
|
|
2625
2634
|
rTypeFromWidgetId,
|
|
2626
2635
|
rWidgetParts,
|
|
2627
2636
|
snowman,
|
|
2628
|
-
seededRNG: seededRNG$1,
|
|
2629
|
-
shuffle: shuffle$3,
|
|
2630
2637
|
split,
|
|
2631
2638
|
firstNumericalParse: firstNumericalParse$1,
|
|
2632
2639
|
stringArrayOfSize: stringArrayOfSize$1,
|
|
@@ -2654,8 +2661,7 @@ const Util = {
|
|
|
2654
2661
|
getSvgUrl: getSvgUrl,
|
|
2655
2662
|
getDataUrl: getDataUrl,
|
|
2656
2663
|
textarea,
|
|
2657
|
-
unescapeMathMode: unescapeMathMode$1
|
|
2658
|
-
random: random$1
|
|
2664
|
+
unescapeMathMode: unescapeMathMode$1
|
|
2659
2665
|
};
|
|
2660
2666
|
|
|
2661
2667
|
// TODO(LP-11481): Change the primary API we use for logging in Perseus to use
|
|
@@ -16010,12 +16016,17 @@ class ImageLoader extends React__namespace.Component {
|
|
|
16010
16016
|
};
|
|
16011
16017
|
}
|
|
16012
16018
|
const staticUrl = getDependencies().staticUrl;
|
|
16013
|
-
return
|
|
16014
|
-
|
|
16015
|
-
|
|
16016
|
-
|
|
16017
|
-
|
|
16018
|
-
|
|
16019
|
+
return (
|
|
16020
|
+
/*#__PURE__*/
|
|
16021
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- TODO(LEMS-2871): Address a11y error
|
|
16022
|
+
React__namespace.createElement("img", _extends({
|
|
16023
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- TODO(LEMS-2871): Address a11y error
|
|
16024
|
+
tabIndex: 0,
|
|
16025
|
+
src: staticUrl(src),
|
|
16026
|
+
onKeyUp: onKeyUp,
|
|
16027
|
+
onKeyDown: onKeyDown
|
|
16028
|
+
}, imgProps))
|
|
16029
|
+
);
|
|
16019
16030
|
};
|
|
16020
16031
|
render() {
|
|
16021
16032
|
switch (this.state.status) {
|
|
@@ -16689,16 +16700,20 @@ class Zoomable extends React__namespace.Component {
|
|
|
16689
16700
|
WebkitTapHighlightColor: "transparent",
|
|
16690
16701
|
...transitionStyle
|
|
16691
16702
|
};
|
|
16692
|
-
return
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16703
|
+
return (
|
|
16704
|
+
/*#__PURE__*/
|
|
16705
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events -- TODO(LEMS-2871): Address a11y error
|
|
16706
|
+
React__namespace.createElement("span", {
|
|
16707
|
+
onClick: this.handleClick,
|
|
16708
|
+
onClickCapture: this.handleClickIfZoomed,
|
|
16709
|
+
onTouchCancelCapture: this.stopPropagationIfZoomed,
|
|
16710
|
+
onTouchEndCapture: this.stopPropagationIfZoomed,
|
|
16711
|
+
onTouchStartCapture: this.stopPropagationIfZoomed
|
|
16712
|
+
// @ts-expect-error - TS2322 - Type '{ readonly transitionProperty: string; readonly transitionDuration: string; readonly transitionTimingFunction: string; readonly display: "block"; readonly width: "100%"; readonly height: number | ... 1 more ... | undefined; readonly transform: string; readonly transformOrigin: "0 0"; readonly opacity: 0 | 1; readonl...' is not assignable to type 'CSSProperties | undefined'.
|
|
16713
|
+
,
|
|
16714
|
+
style: style
|
|
16715
|
+
}, this.props.children)
|
|
16716
|
+
);
|
|
16702
16717
|
}
|
|
16703
16718
|
}
|
|
16704
16719
|
|
|
@@ -17921,9 +17936,6 @@ const getWidget = name => {
|
|
|
17921
17936
|
const getWidgetExport = name => {
|
|
17922
17937
|
return widgets[name] ?? null;
|
|
17923
17938
|
};
|
|
17924
|
-
const getPublicWidgetOptionsFunction = name => {
|
|
17925
|
-
return widgets[name]?.getPublicWidgetOptions ?? (i => i);
|
|
17926
|
-
};
|
|
17927
17939
|
const getEditor = name => {
|
|
17928
17940
|
return ___default["default"].has(editors, name) ? editors[name] : null;
|
|
17929
17941
|
};
|
|
@@ -18060,7 +18072,6 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
18060
18072
|
replaceDeprecatedEditors: replaceDeprecatedEditors,
|
|
18061
18073
|
getWidget: getWidget,
|
|
18062
18074
|
getWidgetExport: getWidgetExport,
|
|
18063
|
-
getPublicWidgetOptionsFunction: getPublicWidgetOptionsFunction,
|
|
18064
18075
|
getEditor: getEditor,
|
|
18065
18076
|
getTransform: getTransform,
|
|
18066
18077
|
getVersion: getVersion,
|
|
@@ -18136,6 +18147,7 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18136
18147
|
"perseus-widget__definition": this.props.type === "definition"
|
|
18137
18148
|
});
|
|
18138
18149
|
const type = this.props.type;
|
|
18150
|
+
const userAgent = navigator.userAgent;
|
|
18139
18151
|
const WidgetType = getWidget(type);
|
|
18140
18152
|
if (WidgetType == null) {
|
|
18141
18153
|
// This is for the good of all people!!
|
|
@@ -18146,6 +18158,11 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18146
18158
|
className: className
|
|
18147
18159
|
});
|
|
18148
18160
|
}
|
|
18161
|
+
let subType = "null";
|
|
18162
|
+
if (type === "interactive-graph") {
|
|
18163
|
+
const props = this.state.widgetProps;
|
|
18164
|
+
subType = props.graph?.type ?? "null";
|
|
18165
|
+
}
|
|
18149
18166
|
let alignment = this.state.widgetProps.alignment;
|
|
18150
18167
|
if (alignment === "default") {
|
|
18151
18168
|
alignment = perseusCore.CoreWidgetRegistry.getDefaultAlignment(type);
|
|
@@ -18202,12 +18219,26 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18202
18219
|
widget_type: type,
|
|
18203
18220
|
widget_id: this.props.id
|
|
18204
18221
|
},
|
|
18205
|
-
onError:
|
|
18222
|
+
onError: error => {
|
|
18223
|
+
// TODO(LEMS-2826): Remove analytics event in LEMS-2826 in favor of ti below.
|
|
18206
18224
|
analytics.onAnalyticsEvent({
|
|
18207
18225
|
type: "perseus:widget-rendering-error",
|
|
18208
18226
|
payload: {
|
|
18227
|
+
widgetSubType: subType,
|
|
18228
|
+
widgetType: type,
|
|
18229
|
+
widgetId: this.props.id,
|
|
18230
|
+
message: error.message,
|
|
18231
|
+
userAgent: userAgent
|
|
18232
|
+
}
|
|
18233
|
+
});
|
|
18234
|
+
analytics.onAnalyticsEvent({
|
|
18235
|
+
type: "perseus:widget-rendering-error:ti",
|
|
18236
|
+
payload: {
|
|
18237
|
+
widgetSubType: subType,
|
|
18209
18238
|
widgetType: type,
|
|
18210
|
-
widgetId: this.props.id
|
|
18239
|
+
widgetId: this.props.id,
|
|
18240
|
+
message: error.message,
|
|
18241
|
+
userAgent: userAgent
|
|
18211
18242
|
}
|
|
18212
18243
|
});
|
|
18213
18244
|
}
|
|
@@ -20650,7 +20681,6 @@ var NumericInput$1 = {
|
|
|
20650
20681
|
widget: NumericInput,
|
|
20651
20682
|
transform: propsTransform,
|
|
20652
20683
|
isLintable: true,
|
|
20653
|
-
getPublicWidgetOptions: perseusCore.getNumericInputPublicWidgetOptions,
|
|
20654
20684
|
// TODO(LEMS-2656): remove TS suppression
|
|
20655
20685
|
// @ts-expect-error: Type 'Rubric' is not assignable to type 'PerseusNumericInputRubric'
|
|
20656
20686
|
getOneCorrectAnswerFromRubric(rubric) {
|
|
@@ -21457,7 +21487,10 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
21457
21487
|
// using div instead of TooltipContent because
|
|
21458
21488
|
// TooltipContent wouldn't let me overwrite
|
|
21459
21489
|
// user-select and onClick
|
|
21460
|
-
const content =
|
|
21490
|
+
const content =
|
|
21491
|
+
/*#__PURE__*/
|
|
21492
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events -- TODO(LEMS-2871): Address a11y error
|
|
21493
|
+
React__namespace.createElement("div", {
|
|
21461
21494
|
className: aphrodite.css(styles$x.tooltipLabel),
|
|
21462
21495
|
onClick: this.props.onClick
|
|
21463
21496
|
}, this.props.label);
|
|
@@ -21468,14 +21501,18 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
21468
21501
|
top: `calc(${Math.round(focusRect.top)}px + 0.95em)`,
|
|
21469
21502
|
height: 0
|
|
21470
21503
|
};
|
|
21471
|
-
return
|
|
21472
|
-
|
|
21473
|
-
|
|
21474
|
-
|
|
21475
|
-
|
|
21476
|
-
|
|
21477
|
-
|
|
21478
|
-
|
|
21504
|
+
return (
|
|
21505
|
+
/*#__PURE__*/
|
|
21506
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions -- TODO(LEMS-2871): Address a11y error
|
|
21507
|
+
React__namespace.createElement("div", {
|
|
21508
|
+
style: style,
|
|
21509
|
+
onMouseEnter: this.props.onMouseEnter,
|
|
21510
|
+
onMouseLeave: this.props.onMouseLeave
|
|
21511
|
+
}, /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
21512
|
+
content: content,
|
|
21513
|
+
opened: true
|
|
21514
|
+
}, /*#__PURE__*/React__namespace.createElement("div", null)))
|
|
21515
|
+
);
|
|
21479
21516
|
}
|
|
21480
21517
|
}
|
|
21481
21518
|
const styles$x = aphrodite.StyleSheet.create({
|
|
@@ -24192,15 +24229,19 @@ const BaseRadio = function (_ref) {
|
|
|
24192
24229
|
// content somehow? Would changing our choice of key
|
|
24193
24230
|
// somehow break something happening inside a choice's
|
|
24194
24231
|
// child Renderers, by changing when we mount/unmount?
|
|
24195
|
-
return
|
|
24196
|
-
|
|
24197
|
-
|
|
24198
|
-
|
|
24199
|
-
|
|
24200
|
-
|
|
24201
|
-
|
|
24202
|
-
|
|
24203
|
-
|
|
24232
|
+
return (
|
|
24233
|
+
/*#__PURE__*/
|
|
24234
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions -- TODO(LEMS-2871): Address a11y error
|
|
24235
|
+
React__namespace.createElement("li", {
|
|
24236
|
+
key: i,
|
|
24237
|
+
ref: e => listElem = e,
|
|
24238
|
+
className: className,
|
|
24239
|
+
onClick: clickHandler,
|
|
24240
|
+
onTouchStart: labelWrap ? undefined : captureScratchpadTouchStart$1
|
|
24241
|
+
}, /*#__PURE__*/React__namespace.createElement(Element, _extends({}, elementProps, {
|
|
24242
|
+
ref: ref
|
|
24243
|
+
})))
|
|
24244
|
+
);
|
|
24204
24245
|
})));
|
|
24205
24246
|
|
|
24206
24247
|
// Allow for horizontal scrolling if content is too wide, which may be
|
|
@@ -24649,22 +24690,17 @@ class Radio$1 extends React__namespace.Component {
|
|
|
24649
24690
|
}
|
|
24650
24691
|
}
|
|
24651
24692
|
|
|
24652
|
-
const {
|
|
24653
|
-
shuffle: shuffle$2,
|
|
24654
|
-
random
|
|
24655
|
-
} = Util;
|
|
24656
|
-
|
|
24657
24693
|
// Transforms the choices for display.
|
|
24658
24694
|
const _choiceTransform = (widgetOptions, strings, problemNum) => {
|
|
24659
24695
|
const _maybeRandomize = function (array) {
|
|
24660
|
-
const randomSeed = problemNum === undefined ? random : problemNum;
|
|
24696
|
+
const randomSeed = problemNum === undefined ? perseusCore.random : problemNum;
|
|
24661
24697
|
// NOTE: `problemNum` will only be set when the radio widget is
|
|
24662
24698
|
// rendered at the root of an exercise question. It will be `undefined`
|
|
24663
24699
|
// if it's rendered embedded in another widget, such as `graded-group`,
|
|
24664
24700
|
// or if rendered within an article. This results in a predictable
|
|
24665
24701
|
// shuffle order. To avoid this we use a random seed when `problemNum`
|
|
24666
24702
|
// is `undefined`.
|
|
24667
|
-
return widgetOptions.randomize ? shuffle
|
|
24703
|
+
return widgetOptions.randomize ? perseusCore.shuffle(array, randomSeed ?? 0) : array;
|
|
24668
24704
|
};
|
|
24669
24705
|
const _addNoneOfAbove = function (choices) {
|
|
24670
24706
|
let noneOfTheAbove = null;
|
|
@@ -24745,8 +24781,7 @@ var Radio = {
|
|
|
24745
24781
|
staticTransform: transform,
|
|
24746
24782
|
version: perseusCore.radioLogic.version,
|
|
24747
24783
|
propUpgrades: perseusCore.radioLogic.widgetOptionsUpgrades,
|
|
24748
|
-
isLintable: true
|
|
24749
|
-
getPublicWidgetOptions: perseusCore.getRadioPublicWidgetOptions
|
|
24784
|
+
isLintable: true
|
|
24750
24785
|
};
|
|
24751
24786
|
|
|
24752
24787
|
/* eslint-disable import/no-named-as-default */
|
|
@@ -24906,8 +24941,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24906
24941
|
const isMobile = this.props.apiOptions.isMobile;
|
|
24907
24942
|
let indexedItems = this.props.items.map((item, n) => [item, n]);
|
|
24908
24943
|
if (this.props.randomizeItems) {
|
|
24909
|
-
|
|
24910
|
-
indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
|
|
24944
|
+
indexedItems = perseusCore.shuffle(indexedItems, this.props.problemNum);
|
|
24911
24945
|
}
|
|
24912
24946
|
const table = /*#__PURE__*/React__namespace.createElement("table", {
|
|
24913
24947
|
className: "categorizer-table " + aphrodite.css(styles$n.mobileTable)
|
|
@@ -24933,9 +24967,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24933
24967
|
const uniqueId = self.state.uniqueId + "_" + itemNum;
|
|
24934
24968
|
return /*#__PURE__*/React__namespace.createElement("tr", {
|
|
24935
24969
|
key: itemNum
|
|
24936
|
-
}, /*#__PURE__*/React__namespace.createElement("td", null, /*#__PURE__*/React__namespace.createElement(Renderer
|
|
24937
|
-
// @ts-expect-error - TS2322 - Type 'string | number' is not assignable to type 'string | undefined'.
|
|
24938
|
-
, {
|
|
24970
|
+
}, /*#__PURE__*/React__namespace.createElement("td", null, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
24939
24971
|
content: item,
|
|
24940
24972
|
linterContext: this.props.linterContext,
|
|
24941
24973
|
strings: this.context.strings
|
|
@@ -25035,8 +25067,7 @@ var Categorizer$1 = {
|
|
|
25035
25067
|
staticTransform: editorProps => {
|
|
25036
25068
|
return ___default["default"].pick(editorProps, "items", "categories", "values", "randomizeItems");
|
|
25037
25069
|
},
|
|
25038
|
-
isLintable: true
|
|
25039
|
-
getPublicWidgetOptions: perseusCore.getCategorizerPublicWidgetOptions
|
|
25070
|
+
isLintable: true
|
|
25040
25071
|
};
|
|
25041
25072
|
|
|
25042
25073
|
/**
|
|
@@ -25246,8 +25277,7 @@ var CSProgram$1 = {
|
|
|
25246
25277
|
name: "cs-program",
|
|
25247
25278
|
displayName: "CS Program",
|
|
25248
25279
|
widget: CSProgram,
|
|
25249
|
-
hidden: true
|
|
25250
|
-
getPublicWidgetOptions: perseusCore.getCSProgramPublicWidgetOptions
|
|
25280
|
+
hidden: true
|
|
25251
25281
|
};
|
|
25252
25282
|
|
|
25253
25283
|
const getPromptJSON$l = renderProps => {
|
|
@@ -25463,8 +25493,7 @@ var Dropdown$1 = {
|
|
|
25463
25493
|
displayName: "Drop down",
|
|
25464
25494
|
accessible: true,
|
|
25465
25495
|
widget: Dropdown,
|
|
25466
|
-
transform: optionsTransform
|
|
25467
|
-
getPublicWidgetOptions: perseusCore.getDropdownPublicWidgetOptions
|
|
25496
|
+
transform: optionsTransform
|
|
25468
25497
|
};
|
|
25469
25498
|
|
|
25470
25499
|
const getPromptJSON$j = renderProps => {
|
|
@@ -26956,8 +26985,7 @@ var Grapher$1 = {
|
|
|
26956
26985
|
hidden: true,
|
|
26957
26986
|
widget: Grapher,
|
|
26958
26987
|
transform: propTransform$2,
|
|
26959
|
-
staticTransform: staticTransform$4
|
|
26960
|
-
getPublicWidgetOptions: perseusCore.getGrapherPublicWidgetOptions
|
|
26988
|
+
staticTransform: staticTransform$4
|
|
26961
26989
|
};
|
|
26962
26990
|
|
|
26963
26991
|
const getPromptJSON$f = rendererJSON => {
|
|
@@ -27251,12 +27279,16 @@ class Iframe extends React__namespace.Component {
|
|
|
27251
27279
|
// that we need. This makes it a bit safer in case some content
|
|
27252
27280
|
// creator "went wild".
|
|
27253
27281
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
27254
|
-
return
|
|
27255
|
-
|
|
27256
|
-
|
|
27257
|
-
|
|
27258
|
-
|
|
27259
|
-
|
|
27282
|
+
return (
|
|
27283
|
+
/*#__PURE__*/
|
|
27284
|
+
// eslint-disable-next-line jsx-a11y/iframe-has-title -- TODO(LEMS-2871): Address a11y error
|
|
27285
|
+
React__namespace.createElement("iframe", {
|
|
27286
|
+
sandbox: sandboxProperties,
|
|
27287
|
+
style: style,
|
|
27288
|
+
src: url,
|
|
27289
|
+
allowFullScreen: this.props.allowFullScreen
|
|
27290
|
+
})
|
|
27291
|
+
);
|
|
27260
27292
|
}
|
|
27261
27293
|
}
|
|
27262
27294
|
var Iframe$1 = {
|
|
@@ -27264,8 +27296,7 @@ var Iframe$1 = {
|
|
|
27264
27296
|
displayName: "Iframe (deprecated)",
|
|
27265
27297
|
widget: Iframe,
|
|
27266
27298
|
// Let's not expose it to all content creators yet
|
|
27267
|
-
hidden: true
|
|
27268
|
-
getPublicWidgetOptions: perseusCore.getIFramePublicWidgetOptions
|
|
27299
|
+
hidden: true
|
|
27269
27300
|
};
|
|
27270
27301
|
|
|
27271
27302
|
const getPromptJSON$d = renderProps => {
|
|
@@ -27282,7 +27313,7 @@ const getPromptJSON$d = renderProps => {
|
|
|
27282
27313
|
|
|
27283
27314
|
const defaultBoxSize = 400;
|
|
27284
27315
|
const defaultRange = [0, 10];
|
|
27285
|
-
const defaultBackgroundImage$
|
|
27316
|
+
const defaultBackgroundImage$1 = {
|
|
27286
27317
|
url: null,
|
|
27287
27318
|
width: 0,
|
|
27288
27319
|
height: 0
|
|
@@ -27297,7 +27328,7 @@ class ImageWidget extends React__namespace.Component {
|
|
|
27297
27328
|
title: "",
|
|
27298
27329
|
range: [defaultRange, defaultRange],
|
|
27299
27330
|
box: [defaultBoxSize, defaultBoxSize],
|
|
27300
|
-
backgroundImage: defaultBackgroundImage$
|
|
27331
|
+
backgroundImage: defaultBackgroundImage$1,
|
|
27301
27332
|
labels: [],
|
|
27302
27333
|
alt: "",
|
|
27303
27334
|
caption: "",
|
|
@@ -28068,306 +28099,6 @@ var Interactive = {
|
|
|
28068
28099
|
hidden: true
|
|
28069
28100
|
};
|
|
28070
28101
|
|
|
28071
|
-
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
28072
|
-
const defaultBackgroundImage$1 = {
|
|
28073
|
-
url: null
|
|
28074
|
-
};
|
|
28075
|
-
|
|
28076
|
-
/* Style objects */
|
|
28077
|
-
const defaultInstructionsStyle = {
|
|
28078
|
-
fontStyle: "italic",
|
|
28079
|
-
fontWeight: "bold",
|
|
28080
|
-
fontSize: "32px",
|
|
28081
|
-
width: "100%",
|
|
28082
|
-
height: "100%",
|
|
28083
|
-
textAlign: "center",
|
|
28084
|
-
backgroundColor: "white",
|
|
28085
|
-
position: "absolute",
|
|
28086
|
-
zIndex: 1,
|
|
28087
|
-
transition: "opacity .25s ease-in-out"
|
|
28088
|
-
};
|
|
28089
|
-
const instructionsTextStyle = {
|
|
28090
|
-
position: "relative",
|
|
28091
|
-
top: "25%"
|
|
28092
|
-
};
|
|
28093
|
-
function numSteps$1(range, step) {
|
|
28094
|
-
return Math.floor((range[1] - range[0]) / step);
|
|
28095
|
-
}
|
|
28096
|
-
class Graph extends React__namespace.Component {
|
|
28097
|
-
graphieDivRef = /*#__PURE__*/React__namespace.createRef();
|
|
28098
|
-
protractor;
|
|
28099
|
-
ruler;
|
|
28100
|
-
_graphie;
|
|
28101
|
-
// @ts-expect-error - TS2564 - Property '_hasSetupGraphieThisUpdate' has no initializer and is not definitely assigned in the constructor.
|
|
28102
|
-
_hasSetupGraphieThisUpdate;
|
|
28103
|
-
// @ts-expect-error - TS2564 - Property '_shouldSetupGraphie' has no initializer and is not definitely assigned in the constructor.
|
|
28104
|
-
_shouldSetupGraphie;
|
|
28105
|
-
static defaultProps = {
|
|
28106
|
-
labels: ["x", "y"],
|
|
28107
|
-
range: [[-10, 10], [-10, 10]],
|
|
28108
|
-
step: [1, 1],
|
|
28109
|
-
gridStep: [1, 1],
|
|
28110
|
-
snapStep: [0.5, 0.5],
|
|
28111
|
-
markings: "graph",
|
|
28112
|
-
backgroundImage: defaultBackgroundImage$1,
|
|
28113
|
-
showProtractor: false,
|
|
28114
|
-
showRuler: false,
|
|
28115
|
-
rulerLabel: "",
|
|
28116
|
-
rulerTicks: 10,
|
|
28117
|
-
isMobile: false
|
|
28118
|
-
};
|
|
28119
|
-
componentDidMount() {
|
|
28120
|
-
this._setupGraphie(true);
|
|
28121
|
-
}
|
|
28122
|
-
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
28123
|
-
const potentialChanges = ["labels", "range", "step", "markings", "showProtractor", "showRuler", "rulerLabel", "rulerTicks", "gridStep", "snapStep"];
|
|
28124
|
-
const self = this;
|
|
28125
|
-
___default["default"].each(potentialChanges, function (prop) {
|
|
28126
|
-
if (!___default["default"].isEqual(self.props[prop], nextProps[prop])) {
|
|
28127
|
-
self._shouldSetupGraphie = true;
|
|
28128
|
-
}
|
|
28129
|
-
});
|
|
28130
|
-
}
|
|
28131
|
-
componentDidUpdate() {
|
|
28132
|
-
// Only setupGraphie once per componentDidUpdate().
|
|
28133
|
-
// See explanation in setupGraphie().
|
|
28134
|
-
this._hasSetupGraphieThisUpdate = false;
|
|
28135
|
-
if (this._shouldSetupGraphie) {
|
|
28136
|
-
this._setupGraphie(false);
|
|
28137
|
-
this._shouldSetupGraphie = false;
|
|
28138
|
-
}
|
|
28139
|
-
}
|
|
28140
|
-
|
|
28141
|
-
/* Reset the graphie canvas to its initial state
|
|
28142
|
-
*
|
|
28143
|
-
* Use when re-rendering the parent component and you need a blank
|
|
28144
|
-
* graphie.
|
|
28145
|
-
*/
|
|
28146
|
-
reset = () => {
|
|
28147
|
-
this._setupGraphie(false);
|
|
28148
|
-
};
|
|
28149
|
-
graphie = () => {
|
|
28150
|
-
return this._graphie;
|
|
28151
|
-
};
|
|
28152
|
-
pointsFromNormalized = (coordsList, noSnap) => {
|
|
28153
|
-
const self = this;
|
|
28154
|
-
return ___default["default"].map(coordsList, function (coords) {
|
|
28155
|
-
return ___default["default"].map(coords, function (coord, i) {
|
|
28156
|
-
const range = self.props.range[i];
|
|
28157
|
-
if (noSnap) {
|
|
28158
|
-
return range[0] + (range[1] - range[0]) * coord;
|
|
28159
|
-
}
|
|
28160
|
-
const step = self.props.step[i];
|
|
28161
|
-
const nSteps = numSteps$1(range, step);
|
|
28162
|
-
const tick = Math.round(coord * nSteps);
|
|
28163
|
-
return range[0] + step * tick;
|
|
28164
|
-
});
|
|
28165
|
-
});
|
|
28166
|
-
};
|
|
28167
|
-
_setupGraphie = initialMount => {
|
|
28168
|
-
// Only setupGraphie once per componentDidUpdate().
|
|
28169
|
-
// This prevents this component from rendering graphie
|
|
28170
|
-
// and then immediately re-render graphie because its
|
|
28171
|
-
// parent component asked it to. This will happen when
|
|
28172
|
-
// props on the parent and props on this component both
|
|
28173
|
-
// require graphie to be re-rendered.
|
|
28174
|
-
if (this._hasSetupGraphieThisUpdate) {
|
|
28175
|
-
return;
|
|
28176
|
-
}
|
|
28177
|
-
const graphieDiv = this.graphieDivRef.current;
|
|
28178
|
-
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'empty' does not exist on type 'JQueryStatic'.
|
|
28179
|
-
$__default["default"](graphieDiv).empty();
|
|
28180
|
-
|
|
28181
|
-
// Content creators may need to explicitly add the dollar signs so the
|
|
28182
|
-
// strings are picked up by our translation tools. However, these math
|
|
28183
|
-
// annotations are redundant because we already render all graph labels
|
|
28184
|
-
// in math mode. For example, a label value of `$\text{Dollars}$` will
|
|
28185
|
-
// be translatable, but we only want to pass the string
|
|
28186
|
-
// `\text{Dollars}` to the Graph widget.
|
|
28187
|
-
const labels = this.props.labels.map(label => Util.unescapeMathMode(label));
|
|
28188
|
-
const range = this.props.range;
|
|
28189
|
-
// @ts-expect-error - TS2345: Argument of type 'Element | Text | null' is not assignable to parameter of type 'HTMLElement'.
|
|
28190
|
-
const graphie = this._graphie = GraphUtils.createGraphie(graphieDiv);
|
|
28191
|
-
const gridConfig = this._getGridConfig();
|
|
28192
|
-
// @ts-expect-error - TS2339: Property 'snap' does not exist on type 'Graphie'.
|
|
28193
|
-
graphie.snap = this.props.snapStep;
|
|
28194
|
-
if (this.props.markings === "graph") {
|
|
28195
|
-
graphie.graphInit({
|
|
28196
|
-
range: range,
|
|
28197
|
-
scale: kmath.vector.map(gridConfig, g => g.scale),
|
|
28198
|
-
axisArrows: "<->",
|
|
28199
|
-
labelFormat: function (s) {
|
|
28200
|
-
return "\\small{" + s + "}";
|
|
28201
|
-
},
|
|
28202
|
-
gridStep: this.props.gridStep,
|
|
28203
|
-
tickStep: kmath.vector.map(gridConfig, g => g.tickStep),
|
|
28204
|
-
labelStep: 1,
|
|
28205
|
-
unityLabels: kmath.vector.map(gridConfig, g => g.unityLabel),
|
|
28206
|
-
isMobile: this.props.isMobile
|
|
28207
|
-
});
|
|
28208
|
-
graphie.label([0, range[1][1]], labels[1], this.props.isMobile ? "below right" : "above");
|
|
28209
|
-
graphie.label([range[0][1], 0], labels[0], this.props.isMobile ? "above left" : "right");
|
|
28210
|
-
} else if (this.props.markings === "grid") {
|
|
28211
|
-
graphie.graphInit({
|
|
28212
|
-
range: range,
|
|
28213
|
-
scale: kmath.vector.map(gridConfig, g => g.scale),
|
|
28214
|
-
gridStep: this.props.gridStep,
|
|
28215
|
-
axes: false,
|
|
28216
|
-
ticks: false,
|
|
28217
|
-
labels: false,
|
|
28218
|
-
isMobile: this.props.isMobile
|
|
28219
|
-
});
|
|
28220
|
-
} else if (this.props.markings === "none") {
|
|
28221
|
-
graphie.init({
|
|
28222
|
-
range: range,
|
|
28223
|
-
scale: kmath.vector.map(gridConfig, g => g.scale),
|
|
28224
|
-
isMobile: this.props.isMobile
|
|
28225
|
-
});
|
|
28226
|
-
}
|
|
28227
|
-
|
|
28228
|
-
// Add instructions just before mouse layer
|
|
28229
|
-
const visible = 0.5;
|
|
28230
|
-
const invisible = 0.0;
|
|
28231
|
-
let $instructionsWrapper;
|
|
28232
|
-
if (this.props.instructions) {
|
|
28233
|
-
$instructionsWrapper = $__default["default"]("<div/>");
|
|
28234
|
-
___default["default"].each(defaultInstructionsStyle, function (value, key) {
|
|
28235
|
-
$instructionsWrapper.css(key, value);
|
|
28236
|
-
});
|
|
28237
|
-
$instructionsWrapper.css("opacity", visible);
|
|
28238
|
-
const $instructions = $__default["default"]("<span/>", {
|
|
28239
|
-
text: this.props.instructions
|
|
28240
|
-
});
|
|
28241
|
-
___default["default"].each(instructionsTextStyle, function (value, key) {
|
|
28242
|
-
$instructions.css(key, value);
|
|
28243
|
-
});
|
|
28244
|
-
$instructionsWrapper.append($instructions);
|
|
28245
|
-
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'append' does not exist on type 'JQueryStatic'.
|
|
28246
|
-
$__default["default"](graphieDiv).append($instructionsWrapper);
|
|
28247
|
-
} else {
|
|
28248
|
-
$instructionsWrapper = undefined;
|
|
28249
|
-
}
|
|
28250
|
-
|
|
28251
|
-
// Add some handlers for instructions text (if necessary)
|
|
28252
|
-
const onMouseDown = $instructionsWrapper || this.props.onMouseDown ? ___default["default"].bind(function (coord) {
|
|
28253
|
-
if ($instructionsWrapper) {
|
|
28254
|
-
$instructionsWrapper.remove();
|
|
28255
|
-
$instructionsWrapper = null;
|
|
28256
|
-
}
|
|
28257
|
-
// eslint-disable-next-line @babel/no-invalid-this
|
|
28258
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
28259
|
-
// eslint-disable-next-line @babel/no-invalid-this
|
|
28260
|
-
this.props.onMouseDown(coord);
|
|
28261
|
-
}, this) : undefined;
|
|
28262
|
-
const onMouseOver = $instructionsWrapper ? function () {
|
|
28263
|
-
$instructionsWrapper?.css("opacity", invisible);
|
|
28264
|
-
} : undefined;
|
|
28265
|
-
const onMouseOut = $instructionsWrapper ? function () {
|
|
28266
|
-
$instructionsWrapper?.css("opacity", visible);
|
|
28267
|
-
} : undefined;
|
|
28268
|
-
/* eslint-enable indent */
|
|
28269
|
-
|
|
28270
|
-
graphie.addMouseLayer({
|
|
28271
|
-
onClick: this.props.onClick,
|
|
28272
|
-
onMouseDown: onMouseDown,
|
|
28273
|
-
onMouseOver: onMouseOver,
|
|
28274
|
-
onMouseOut: onMouseOut,
|
|
28275
|
-
onMouseMove: this.props.onMouseMove,
|
|
28276
|
-
allowScratchpad: true,
|
|
28277
|
-
setDrawingAreaAvailable: this.props.setDrawingAreaAvailable
|
|
28278
|
-
});
|
|
28279
|
-
this._updateProtractor();
|
|
28280
|
-
this._updateRuler();
|
|
28281
|
-
|
|
28282
|
-
// We set this flag before jumping into our callback
|
|
28283
|
-
// to avoid recursing if our callback calls reset() itself
|
|
28284
|
-
this._hasSetupGraphieThisUpdate = true;
|
|
28285
|
-
if (!initialMount && this.props.onGraphieUpdated) {
|
|
28286
|
-
// Calling a parent callback in componentDidMount is bad and
|
|
28287
|
-
// results in hard-to-reason-about lifecycle problems (esp. with
|
|
28288
|
-
// refs), so we do it only on update and rely on the parent to
|
|
28289
|
-
// query for the graphie object on initial mount
|
|
28290
|
-
this.props.onGraphieUpdated(graphie);
|
|
28291
|
-
}
|
|
28292
|
-
};
|
|
28293
|
-
_getGridConfig = () => {
|
|
28294
|
-
return kmath.vector.map(this.props.step, (step, i) => Util.gridDimensionConfig(step, this.props.range[i], this.props.box[i], this.props.gridStep[i]));
|
|
28295
|
-
};
|
|
28296
|
-
_updateProtractor = () => {
|
|
28297
|
-
if (this.protractor) {
|
|
28298
|
-
this.protractor.remove();
|
|
28299
|
-
}
|
|
28300
|
-
if (this.props.showProtractor) {
|
|
28301
|
-
// @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
|
|
28302
|
-
const coord = this.pointsFromNormalized([[0.5, 0.05]])[0];
|
|
28303
|
-
this.protractor = this._graphie.protractor(coord);
|
|
28304
|
-
}
|
|
28305
|
-
};
|
|
28306
|
-
_updateRuler = () => {
|
|
28307
|
-
if (this.ruler) {
|
|
28308
|
-
this.ruler.remove();
|
|
28309
|
-
}
|
|
28310
|
-
if (this.props.showRuler) {
|
|
28311
|
-
// @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
|
|
28312
|
-
const coord = this.pointsFromNormalized([[0.5, 0.25]])[0];
|
|
28313
|
-
const extent = this._graphie.range[0][1] - this._graphie.range[0][0];
|
|
28314
|
-
this.ruler = this._graphie.ruler({
|
|
28315
|
-
center: coord,
|
|
28316
|
-
label: this.props.rulerLabel,
|
|
28317
|
-
pixelsPerUnit: this._graphie.scale[0],
|
|
28318
|
-
ticksPerUnit: this.props.rulerTicks,
|
|
28319
|
-
units: Math.round(0.8 * extent)
|
|
28320
|
-
});
|
|
28321
|
-
}
|
|
28322
|
-
};
|
|
28323
|
-
toJSON = () => {
|
|
28324
|
-
return ___default["default"].pick(this.props, "range", "step", "markings", "labels", "backgroundImage", "showProtractor", "showRuler", "rulerLabel", "rulerTicks", "gridStep", "snapStep");
|
|
28325
|
-
};
|
|
28326
|
-
render() {
|
|
28327
|
-
let image;
|
|
28328
|
-
const imageData = this.props.backgroundImage;
|
|
28329
|
-
if (imageData.url) {
|
|
28330
|
-
const scale = this.props.box[0] / interactiveSizes$1.defaultBoxSize;
|
|
28331
|
-
image = /*#__PURE__*/React__namespace.createElement(context$1.Consumer, null, _ref => {
|
|
28332
|
-
let {
|
|
28333
|
-
setAssetStatus
|
|
28334
|
-
} = _ref;
|
|
28335
|
-
return /*#__PURE__*/React__namespace.createElement(SvgImage
|
|
28336
|
-
// @ts-expect-error - TS2741 - Property 'alt' is missing in type '{ src: any; width: any; height: any; scale: number; responsive: false; }' but required in type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "children" | "height" | "width" | "title" | "alt" | "trackInteraction" | "preloader" | "allowFullBleed" | "extraGraphie" | "overrideAriaHidden">'.
|
|
28337
|
-
, {
|
|
28338
|
-
src: imageData.url,
|
|
28339
|
-
width: imageData.width,
|
|
28340
|
-
height: imageData.height,
|
|
28341
|
-
scale: scale,
|
|
28342
|
-
responsive: false,
|
|
28343
|
-
setAssetStatus: setAssetStatus
|
|
28344
|
-
});
|
|
28345
|
-
});
|
|
28346
|
-
} else {
|
|
28347
|
-
image = null;
|
|
28348
|
-
}
|
|
28349
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
28350
|
-
className: "graphie-container blank-background",
|
|
28351
|
-
style: {
|
|
28352
|
-
width: this.props.box[0],
|
|
28353
|
-
height: this.props.box[1]
|
|
28354
|
-
}
|
|
28355
|
-
// @ts-expect-error - TS2339 - Property 'onMouseOut' does not exist on type 'Graph'.
|
|
28356
|
-
,
|
|
28357
|
-
onMouseOut: this.onMouseOut
|
|
28358
|
-
// @ts-expect-error - TS2339 - Property 'onMouseOver' does not exist on type 'Graph'.
|
|
28359
|
-
,
|
|
28360
|
-
onMouseOver: this.onMouseOver
|
|
28361
|
-
// @ts-expect-error - TS2339 - Property 'onClick' does not exist on type 'Graph'.
|
|
28362
|
-
,
|
|
28363
|
-
onClick: this.onClick
|
|
28364
|
-
}, image, /*#__PURE__*/React__namespace.createElement("div", {
|
|
28365
|
-
className: "graphie",
|
|
28366
|
-
ref: this.graphieDivRef
|
|
28367
|
-
}));
|
|
28368
|
-
}
|
|
28369
|
-
}
|
|
28370
|
-
|
|
28371
28102
|
const getPromptJSON$b = (props, userInput) => {
|
|
28372
28103
|
return {
|
|
28373
28104
|
type: "interactive-graph",
|
|
@@ -28932,13 +28663,19 @@ function escapeIfUnescaped(character) {
|
|
|
28932
28663
|
}
|
|
28933
28664
|
}
|
|
28934
28665
|
|
|
28935
|
-
function AxisLabels() {
|
|
28666
|
+
function AxisLabels(_ref) {
|
|
28667
|
+
let {
|
|
28668
|
+
i18n
|
|
28669
|
+
} = _ref;
|
|
28936
28670
|
const {
|
|
28937
28671
|
range,
|
|
28938
28672
|
labels,
|
|
28939
28673
|
width,
|
|
28940
28674
|
height
|
|
28941
28675
|
} = useGraphConfig();
|
|
28676
|
+
const {
|
|
28677
|
+
strings
|
|
28678
|
+
} = i18n;
|
|
28942
28679
|
const yAxisLabelLocation = [0, range[Y][MAX]];
|
|
28943
28680
|
const xAxisLabelLocation = [range[X][MAX], 0];
|
|
28944
28681
|
const [xAxisLabelText, yAxisLabelText] = labels;
|
|
@@ -28956,6 +28693,7 @@ function AxisLabels() {
|
|
|
28956
28693
|
TeX
|
|
28957
28694
|
} = getDependencies();
|
|
28958
28695
|
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("span", {
|
|
28696
|
+
"aria-label": strings.xAxis,
|
|
28959
28697
|
style: {
|
|
28960
28698
|
position: "absolute",
|
|
28961
28699
|
left: x1,
|
|
@@ -28964,6 +28702,7 @@ function AxisLabels() {
|
|
|
28964
28702
|
transform: "translate(7px, -50%)"
|
|
28965
28703
|
}
|
|
28966
28704
|
}, /*#__PURE__*/React__default["default"].createElement(TeX, null, replaceOutsideTeX(xAxisLabelText))), /*#__PURE__*/React__default["default"].createElement("span", {
|
|
28705
|
+
"aria-label": strings.yAxis,
|
|
28967
28706
|
style: {
|
|
28968
28707
|
position: "absolute",
|
|
28969
28708
|
left: x2,
|
|
@@ -29772,7 +29511,6 @@ class RangeInput extends React__namespace.Component {
|
|
|
29772
29511
|
var components = /*#__PURE__*/Object.freeze({
|
|
29773
29512
|
__proto__: null,
|
|
29774
29513
|
ButtonGroup: ButtonGroup,
|
|
29775
|
-
Graph: Graph,
|
|
29776
29514
|
Graphie: Graphie,
|
|
29777
29515
|
HUD: HUD,
|
|
29778
29516
|
Icon: Icon,
|
|
@@ -29916,9 +29654,9 @@ const LockedFunction = props => {
|
|
|
29916
29654
|
const {
|
|
29917
29655
|
color,
|
|
29918
29656
|
strokeStyle,
|
|
29919
|
-
directionalAxis
|
|
29920
|
-
domain
|
|
29657
|
+
directionalAxis
|
|
29921
29658
|
} = props;
|
|
29659
|
+
const domain = props.domain ? [Number.isFinite(props.domain[0]) ? props.domain[0] : -Infinity, Number.isFinite(props.domain[1]) ? props.domain[1] : Infinity] : undefined;
|
|
29922
29660
|
const plotProps = {
|
|
29923
29661
|
color: perseusCore.lockedFigureColors[color],
|
|
29924
29662
|
style: strokeStyle,
|
|
@@ -29998,6 +29736,11 @@ function Vector(props) {
|
|
|
29998
29736
|
}
|
|
29999
29737
|
|
|
30000
29738
|
function srFormatNumber(a, locale, maximumFractionDigits) {
|
|
29739
|
+
const piBasedNumber = getPiMultiple(a);
|
|
29740
|
+
if (piBasedNumber) {
|
|
29741
|
+
return piBasedNumber;
|
|
29742
|
+
}
|
|
29743
|
+
|
|
30001
29744
|
// adding zero here converts negative zero to positive zero.
|
|
30002
29745
|
return (0 + a).toLocaleString(locale, {
|
|
30003
29746
|
maximumFractionDigits: maximumFractionDigits ?? 3,
|
|
@@ -30005,6 +29748,77 @@ function srFormatNumber(a, locale, maximumFractionDigits) {
|
|
|
30005
29748
|
});
|
|
30006
29749
|
}
|
|
30007
29750
|
|
|
29751
|
+
// Exported for testing
|
|
29752
|
+
function getPiMultiple(a) {
|
|
29753
|
+
// - Save some calculations by checking if this is an integer first.
|
|
29754
|
+
// If a is an integer, it's definitely not a multiple of π.
|
|
29755
|
+
// - 0 should not be presented as a multiple of π.
|
|
29756
|
+
// - If a is greater than 1e12, then it thinks that it's always a
|
|
29757
|
+
// multiple of π even when it's not, due to rounding errors.
|
|
29758
|
+
if (Number.isInteger(a) || a === 0 || a > 1e12) {
|
|
29759
|
+
return null;
|
|
29760
|
+
}
|
|
29761
|
+
|
|
29762
|
+
// Figure out the coefficient before the π.
|
|
29763
|
+
// Example: If a = π/2, then piCoefficient = 0.5
|
|
29764
|
+
// Example: If a = 2π, then piCoefficient = 2
|
|
29765
|
+
const piCoefficient = a / Math.PI;
|
|
29766
|
+
// Truncate the coefficient to account for floating point errors.
|
|
29767
|
+
// π calculations are only accurate up to precision of 1e-12.
|
|
29768
|
+
const truncatedCoefficient = parseFloat(piCoefficient.toFixed(12));
|
|
29769
|
+
|
|
29770
|
+
// If the coefficient is already an integer, then the number
|
|
29771
|
+
// is a multiple of π. Return it here.
|
|
29772
|
+
// Example: If a = 2π, then truncatedCoefficient = 2, so return "2π"
|
|
29773
|
+
if (Number.isInteger(truncatedCoefficient)) {
|
|
29774
|
+
// Return "π" rather than "1π".
|
|
29775
|
+
if (truncatedCoefficient === 1) {
|
|
29776
|
+
return "π";
|
|
29777
|
+
}
|
|
29778
|
+
|
|
29779
|
+
// Return "-π" rather than "-1π".
|
|
29780
|
+
if (truncatedCoefficient === -1) {
|
|
29781
|
+
return "-π";
|
|
29782
|
+
}
|
|
29783
|
+
return truncatedCoefficient + "π";
|
|
29784
|
+
}
|
|
29785
|
+
|
|
29786
|
+
// If the coefficient is not an integer, then we need to
|
|
29787
|
+
// check if it's a multiple of π/2, π/3, π/4, or π/6.
|
|
29788
|
+
// These are π-based values on a unit circle.
|
|
29789
|
+
const acceptableDivisors = [2, 3, 4, 6];
|
|
29790
|
+
|
|
29791
|
+
// Loop through the acceptable divisors and check if the
|
|
29792
|
+
// coefficient is a multiple of (1/divisor).
|
|
29793
|
+
// Example: If a = 5π/6, the coeff is 5/6, which is a multiple of 1/6.
|
|
29794
|
+
// So we return "5π/6".
|
|
29795
|
+
for (const divisor of acceptableDivisors) {
|
|
29796
|
+
// Check if the coefficient is a multiple of (1/divisor) by
|
|
29797
|
+
// multiplying the coefficient by the divisor and checking if
|
|
29798
|
+
// the result is an integer.
|
|
29799
|
+
// Example: If a = 5π/6, then piCoefficient = 5/6. We multiply
|
|
29800
|
+
// by 6 (divisor) to get 5, which is an integer.
|
|
29801
|
+
const coefficientNumerator = parseFloat(
|
|
29802
|
+
// π calculations are only accurate up to precision of 1e-12.
|
|
29803
|
+
(piCoefficient * divisor).toFixed(12));
|
|
29804
|
+
if (Number.isInteger(coefficientNumerator)) {
|
|
29805
|
+
// Handle the case where the coefficient numberator is just 1.
|
|
29806
|
+
// We don't want to write "π/6" as "1π/6"
|
|
29807
|
+
if (coefficientNumerator === 1) {
|
|
29808
|
+
return "π/" + divisor;
|
|
29809
|
+
}
|
|
29810
|
+
|
|
29811
|
+
// Handle the case where the coefficient numberator is just -1.
|
|
29812
|
+
// We don't want to write "π/6" as "-1π/6"
|
|
29813
|
+
if (coefficientNumerator === -1) {
|
|
29814
|
+
return "-π/" + divisor;
|
|
29815
|
+
}
|
|
29816
|
+
return coefficientNumerator + "π/" + divisor;
|
|
29817
|
+
}
|
|
29818
|
+
}
|
|
29819
|
+
return null;
|
|
29820
|
+
}
|
|
29821
|
+
|
|
30008
29822
|
/**
|
|
30009
29823
|
* Given a ray and a rectangular box, find the point where the ray intersects
|
|
30010
29824
|
* the edge of the box. Assumes the `initialPoint` is inside the box.
|
|
@@ -31172,6 +30986,34 @@ function range(min, max) {
|
|
|
31172
30986
|
return result;
|
|
31173
30987
|
}
|
|
31174
30988
|
|
|
30989
|
+
function Hairlines(props) {
|
|
30990
|
+
const {
|
|
30991
|
+
point
|
|
30992
|
+
} = props;
|
|
30993
|
+
const {
|
|
30994
|
+
range
|
|
30995
|
+
} = useGraphConfig();
|
|
30996
|
+
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
30997
|
+
const [[x, y]] = useTransformVectorsToPixels(point);
|
|
30998
|
+
const [[verticalStartX]] = useTransformVectorsToPixels([xMin, 0]);
|
|
30999
|
+
const [[verticalEndX]] = useTransformVectorsToPixels([xMax, 0]);
|
|
31000
|
+
const [[_, horizontalStartY]] = useTransformVectorsToPixels([0, yMin]);
|
|
31001
|
+
const [[__, horizontalEndY]] = useTransformVectorsToPixels([0, yMax]);
|
|
31002
|
+
return /*#__PURE__*/React__namespace.createElement("g", null, /*#__PURE__*/React__namespace.createElement("line", {
|
|
31003
|
+
x1: verticalStartX,
|
|
31004
|
+
y1: y,
|
|
31005
|
+
x2: verticalEndX,
|
|
31006
|
+
y2: y,
|
|
31007
|
+
stroke: wonderBlocksTokens.color.blue
|
|
31008
|
+
}), /*#__PURE__*/React__namespace.createElement("line", {
|
|
31009
|
+
x1: x,
|
|
31010
|
+
y1: horizontalStartY,
|
|
31011
|
+
x2: x,
|
|
31012
|
+
y2: horizontalEndY,
|
|
31013
|
+
stroke: wonderBlocksTokens.color.blue
|
|
31014
|
+
}));
|
|
31015
|
+
}
|
|
31016
|
+
|
|
31175
31017
|
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
31176
31018
|
// graph.
|
|
31177
31019
|
const hitboxSizePx = 48;
|
|
@@ -31181,7 +31023,6 @@ const hitboxSizePx = 48;
|
|
|
31181
31023
|
// on an interactive graph.
|
|
31182
31024
|
const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
31183
31025
|
const {
|
|
31184
|
-
range,
|
|
31185
31026
|
markings,
|
|
31186
31027
|
showTooltips
|
|
31187
31028
|
} = useGraphConfig();
|
|
@@ -31189,6 +31030,7 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
31189
31030
|
point,
|
|
31190
31031
|
color = wonderBlocksTokens.color.blue,
|
|
31191
31032
|
dragging,
|
|
31033
|
+
focused,
|
|
31192
31034
|
cursor,
|
|
31193
31035
|
showFocusRing,
|
|
31194
31036
|
onClick = () => {}
|
|
@@ -31202,25 +31044,7 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
31202
31044
|
})?.[0] ?? "blue";
|
|
31203
31045
|
const pointClasses = classNames("movable-point", dragging && "movable-point--dragging", showFocusRing && "movable-point--focus");
|
|
31204
31046
|
const [[x, y]] = useTransformVectorsToPixels(point);
|
|
31205
|
-
const
|
|
31206
|
-
const [[verticalStartX]] = useTransformVectorsToPixels([xMin, 0]);
|
|
31207
|
-
const [[verticalEndX]] = useTransformVectorsToPixels([xMax, 0]);
|
|
31208
|
-
const [[_, horizontalStartY]] = useTransformVectorsToPixels([0, yMin]);
|
|
31209
|
-
const [[__, horizontalEndY]] = useTransformVectorsToPixels([0, yMax]);
|
|
31210
|
-
const showHairlines = dragging && markings !== "none";
|
|
31211
|
-
const hairlines = /*#__PURE__*/React__namespace.createElement("g", null, /*#__PURE__*/React__namespace.createElement("line", {
|
|
31212
|
-
x1: verticalStartX,
|
|
31213
|
-
y1: y,
|
|
31214
|
-
x2: verticalEndX,
|
|
31215
|
-
y2: y,
|
|
31216
|
-
stroke: color
|
|
31217
|
-
}), /*#__PURE__*/React__namespace.createElement("line", {
|
|
31218
|
-
x1: x,
|
|
31219
|
-
y1: horizontalStartY,
|
|
31220
|
-
x2: x,
|
|
31221
|
-
y2: horizontalEndY,
|
|
31222
|
-
stroke: color
|
|
31223
|
-
}));
|
|
31047
|
+
const showHairlines = (dragging || focused) && markings !== "none";
|
|
31224
31048
|
const svgForPoint = /*#__PURE__*/React__namespace.createElement("g", {
|
|
31225
31049
|
ref: hitboxRef,
|
|
31226
31050
|
className: pointClasses,
|
|
@@ -31256,7 +31080,9 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
31256
31080
|
},
|
|
31257
31081
|
"data-testid": "movable-point__center"
|
|
31258
31082
|
}));
|
|
31259
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, showHairlines &&
|
|
31083
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, showHairlines && /*#__PURE__*/React__namespace.createElement(Hairlines, {
|
|
31084
|
+
point: point
|
|
31085
|
+
}), showTooltips ? /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
31260
31086
|
autoUpdate: true,
|
|
31261
31087
|
backgroundColor: wbColorName,
|
|
31262
31088
|
content: `(${point[X]}, ${point[Y]})`,
|
|
@@ -31352,6 +31178,7 @@ function useControlPoint(params) {
|
|
|
31352
31178
|
},
|
|
31353
31179
|
point: point,
|
|
31354
31180
|
dragging: dragging,
|
|
31181
|
+
focused: focused,
|
|
31355
31182
|
color: color,
|
|
31356
31183
|
ref: visiblePointRef,
|
|
31357
31184
|
showFocusRing: focused
|
|
@@ -31569,13 +31396,13 @@ const {
|
|
|
31569
31396
|
getClockwiseAngle: getClockwiseAngle$2,
|
|
31570
31397
|
polar: polar$1
|
|
31571
31398
|
} = kmath.angles;
|
|
31572
|
-
function renderAngleGraph(state, dispatch) {
|
|
31399
|
+
function renderAngleGraph(state, dispatch, i18n) {
|
|
31573
31400
|
return {
|
|
31574
31401
|
graph: /*#__PURE__*/React__namespace.createElement(AngleGraph, {
|
|
31575
31402
|
graphState: state,
|
|
31576
31403
|
dispatch: dispatch
|
|
31577
31404
|
}),
|
|
31578
|
-
interactiveElementsDescription:
|
|
31405
|
+
interactiveElementsDescription: getAngleGraphDescription(state, i18n)
|
|
31579
31406
|
};
|
|
31580
31407
|
}
|
|
31581
31408
|
function AngleGraph(props) {
|
|
@@ -31586,6 +31413,9 @@ function AngleGraph(props) {
|
|
|
31586
31413
|
const {
|
|
31587
31414
|
graphDimensionsInPixels
|
|
31588
31415
|
} = useGraphConfig();
|
|
31416
|
+
const i18n = usePerseusI18n();
|
|
31417
|
+
const id = React__namespace.useId();
|
|
31418
|
+
const descriptionId = id + "-description";
|
|
31589
31419
|
const {
|
|
31590
31420
|
coords,
|
|
31591
31421
|
showAngles,
|
|
@@ -31635,80 +31465,106 @@ function AngleGraph(props) {
|
|
|
31635
31465
|
showAngles: showAngles || false // Whether to show the angle or not
|
|
31636
31466
|
};
|
|
31637
31467
|
|
|
31468
|
+
// Aria strings
|
|
31638
31469
|
const {
|
|
31639
|
-
|
|
31640
|
-
|
|
31641
|
-
|
|
31642
|
-
|
|
31643
|
-
|
|
31644
|
-
|
|
31645
|
-
angleMeasure,
|
|
31646
|
-
vertexX: srFormatNumber(coords[1][X], locale),
|
|
31647
|
-
vertexY: srFormatNumber(coords[1][Y], locale),
|
|
31648
|
-
startingSideX: srFormatNumber(coords[2][X], locale),
|
|
31649
|
-
startingSideY: srFormatNumber(coords[2][Y], locale),
|
|
31650
|
-
endingSideX: srFormatNumber(coords[0][X], locale),
|
|
31651
|
-
endingSideY: srFormatNumber(coords[0][Y], locale)
|
|
31652
|
-
});
|
|
31653
|
-
const formatCoordinates = (x, y) => ({
|
|
31654
|
-
x: srFormatNumber(x, locale),
|
|
31655
|
-
y: srFormatNumber(y, locale)
|
|
31656
|
-
});
|
|
31657
|
-
const formatSideAriaLabel = (side, newPoint) => {
|
|
31658
|
-
const formattedCoordinates = formatCoordinates(newPoint[X], newPoint[Y]);
|
|
31659
|
-
const label = side === "terminal" ? strings.srAngleSideAtCoordinates({
|
|
31660
|
-
point: 1,
|
|
31661
|
-
side: "terminal side",
|
|
31662
|
-
...formattedCoordinates
|
|
31663
|
-
}) : strings.srAngleSideAtCoordinates({
|
|
31664
|
-
point: 3,
|
|
31665
|
-
side: "initial side",
|
|
31666
|
-
...formattedCoordinates
|
|
31667
|
-
});
|
|
31668
|
-
return label;
|
|
31669
|
-
};
|
|
31670
|
-
const formatVertexAriaLabel = newPoint => {
|
|
31671
|
-
const formattedVertexCoordinates = formatCoordinates(newPoint[X], newPoint[Y]);
|
|
31672
|
-
const label = showAngles ? strings.srAngleVertexAtCoordinatesWithAngleMeasure({
|
|
31673
|
-
...formattedVertexCoordinates,
|
|
31674
|
-
angleMeasure: angleMeasure
|
|
31675
|
-
}) : strings.srAngleSideAtCoordinates({
|
|
31676
|
-
point: 2,
|
|
31677
|
-
side: "vertex",
|
|
31678
|
-
...formattedVertexCoordinates
|
|
31679
|
-
});
|
|
31680
|
-
return label;
|
|
31681
|
-
};
|
|
31682
|
-
const initialSideAriaLabel = formatSideAriaLabel("initial", coords[2]);
|
|
31683
|
-
const terminalSideAriaLabel = formatSideAriaLabel("terminal", coords[0]);
|
|
31684
|
-
const vertexAriaLabel = formatVertexAriaLabel(coords[1]);
|
|
31470
|
+
srAngleGraphAriaLabel,
|
|
31471
|
+
srAngleGraphAriaDescription,
|
|
31472
|
+
srAngleStartingSide,
|
|
31473
|
+
srAngleEndingSide,
|
|
31474
|
+
srAngleVertex
|
|
31475
|
+
} = describeAngleGraph(graphState, i18n);
|
|
31685
31476
|
|
|
31686
31477
|
// Render the lines, angle, and then movable points
|
|
31687
31478
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
31688
|
-
"aria-label":
|
|
31689
|
-
"aria-describedby":
|
|
31479
|
+
"aria-label": srAngleGraphAriaLabel,
|
|
31480
|
+
"aria-describedby": descriptionId
|
|
31690
31481
|
}, svgLines, /*#__PURE__*/React__namespace.createElement(Angle, angleParams), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31691
31482
|
point: coords[1],
|
|
31692
31483
|
sequenceNumber: 1,
|
|
31693
31484
|
constrain: p => p,
|
|
31694
31485
|
onMove: destination => dispatch(actions.angle.movePoint(1, destination)),
|
|
31695
|
-
ariaLabel:
|
|
31486
|
+
ariaLabel: srAngleVertex
|
|
31696
31487
|
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31697
31488
|
point: coords[0],
|
|
31698
31489
|
sequenceNumber: 2,
|
|
31699
31490
|
constrain: getAngleSideConstraint(coords[0], coords[1], snapDegrees || 1),
|
|
31700
31491
|
onMove: destination => dispatch(actions.angle.movePoint(0, destination)),
|
|
31701
|
-
ariaLabel:
|
|
31492
|
+
ariaLabel: srAngleEndingSide
|
|
31702
31493
|
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31703
31494
|
point: coords[2],
|
|
31704
31495
|
sequenceNumber: 3,
|
|
31705
31496
|
constrain: getAngleSideConstraint(coords[2], coords[1], snapDegrees || 1),
|
|
31706
31497
|
onMove: destination => dispatch(actions.angle.movePoint(2, destination)),
|
|
31707
|
-
ariaLabel:
|
|
31498
|
+
ariaLabel: srAngleStartingSide
|
|
31708
31499
|
}), /*#__PURE__*/React__namespace.createElement("g", {
|
|
31709
|
-
id:
|
|
31500
|
+
id: descriptionId,
|
|
31710
31501
|
style: a11y.srOnly
|
|
31711
|
-
},
|
|
31502
|
+
}, srAngleGraphAriaDescription));
|
|
31503
|
+
}
|
|
31504
|
+
function getAngleGraphDescription(state, i18n) {
|
|
31505
|
+
const {
|
|
31506
|
+
strings,
|
|
31507
|
+
locale
|
|
31508
|
+
} = i18n;
|
|
31509
|
+
const {
|
|
31510
|
+
coords
|
|
31511
|
+
} = state;
|
|
31512
|
+
return strings.srInteractiveElements({
|
|
31513
|
+
elements: strings.srAngleInteractiveElements({
|
|
31514
|
+
vertexX: srFormatNumber(coords[1][X], locale),
|
|
31515
|
+
vertexY: srFormatNumber(coords[1][Y], locale),
|
|
31516
|
+
startingSideX: srFormatNumber(coords[2][X], locale),
|
|
31517
|
+
startingSideY: srFormatNumber(coords[2][Y], locale),
|
|
31518
|
+
endingSideX: srFormatNumber(coords[0][X], locale),
|
|
31519
|
+
endingSideY: srFormatNumber(coords[0][Y], locale)
|
|
31520
|
+
})
|
|
31521
|
+
});
|
|
31522
|
+
}
|
|
31523
|
+
function describeAngleGraph(state, i18n) {
|
|
31524
|
+
const {
|
|
31525
|
+
strings,
|
|
31526
|
+
locale
|
|
31527
|
+
} = i18n;
|
|
31528
|
+
const {
|
|
31529
|
+
coords,
|
|
31530
|
+
allowReflexAngles,
|
|
31531
|
+
showAngles
|
|
31532
|
+
} = state;
|
|
31533
|
+
const [endingSide, vertex, startingSide] = coords;
|
|
31534
|
+
const angleMeasure = srFormatNumber(getClockwiseAngle$2(coords, allowReflexAngles), locale);
|
|
31535
|
+
const srAngleGraphAriaLabel = strings.srAngleGraphAriaLabel;
|
|
31536
|
+
const srAngleGraphAriaDescription = strings.srAngleGraphAriaDescription({
|
|
31537
|
+
angleMeasure,
|
|
31538
|
+
vertexX: srFormatNumber(vertex[X], locale),
|
|
31539
|
+
vertexY: srFormatNumber(vertex[Y], locale),
|
|
31540
|
+
startingSideX: srFormatNumber(startingSide[X], locale),
|
|
31541
|
+
startingSideY: srFormatNumber(startingSide[Y], locale),
|
|
31542
|
+
endingSideX: srFormatNumber(endingSide[X], locale),
|
|
31543
|
+
endingSideY: srFormatNumber(endingSide[Y], locale)
|
|
31544
|
+
});
|
|
31545
|
+
const srAngleStartingSide = strings.srAngleStartingSide({
|
|
31546
|
+
x: srFormatNumber(startingSide[X], locale),
|
|
31547
|
+
y: srFormatNumber(startingSide[Y], locale)
|
|
31548
|
+
});
|
|
31549
|
+
const srAngleEndingSide = strings.srAngleEndingSide({
|
|
31550
|
+
x: srFormatNumber(endingSide[X], locale),
|
|
31551
|
+
y: srFormatNumber(endingSide[Y], locale)
|
|
31552
|
+
});
|
|
31553
|
+
const srAngleVertex = showAngles ? strings.srAngleVertexWithAngleMeasure({
|
|
31554
|
+
x: srFormatNumber(vertex[X], locale),
|
|
31555
|
+
y: srFormatNumber(vertex[Y], locale),
|
|
31556
|
+
angleMeasure
|
|
31557
|
+
}) : strings.srAngleVertex({
|
|
31558
|
+
x: srFormatNumber(vertex[X], locale),
|
|
31559
|
+
y: srFormatNumber(vertex[Y], locale)
|
|
31560
|
+
});
|
|
31561
|
+
return {
|
|
31562
|
+
srAngleGraphAriaLabel,
|
|
31563
|
+
srAngleGraphAriaDescription,
|
|
31564
|
+
srAngleStartingSide,
|
|
31565
|
+
srAngleEndingSide,
|
|
31566
|
+
srAngleVertex
|
|
31567
|
+
};
|
|
31712
31568
|
}
|
|
31713
31569
|
const positiveX = [1, 0];
|
|
31714
31570
|
const negativeX = [-1, 0];
|
|
@@ -31852,17 +31708,16 @@ function getRadius(graph) {
|
|
|
31852
31708
|
return Math.sqrt(Math.pow(edgeX - centerX, 2) + Math.pow(edgeY - centerY, 2));
|
|
31853
31709
|
}
|
|
31854
31710
|
|
|
31855
|
-
function renderCircleGraph(state, dispatch) {
|
|
31711
|
+
function renderCircleGraph(state, dispatch, i18n) {
|
|
31856
31712
|
return {
|
|
31857
31713
|
graph: /*#__PURE__*/React__namespace.createElement(CircleGraph, {
|
|
31858
31714
|
graphState: state,
|
|
31859
31715
|
dispatch: dispatch
|
|
31860
31716
|
}),
|
|
31861
|
-
interactiveElementsDescription:
|
|
31862
|
-
state: state
|
|
31863
|
-
})
|
|
31717
|
+
interactiveElementsDescription: getCircleGraphDescription(state, i18n)
|
|
31864
31718
|
};
|
|
31865
31719
|
}
|
|
31720
|
+
// Exported for testing
|
|
31866
31721
|
function CircleGraph(props) {
|
|
31867
31722
|
const {
|
|
31868
31723
|
dispatch,
|
|
@@ -31955,6 +31810,7 @@ function MovableCircle(props) {
|
|
|
31955
31810
|
snapStep,
|
|
31956
31811
|
disableKeyboardInteraction
|
|
31957
31812
|
} = useGraphConfig();
|
|
31813
|
+
const [focused, setFocused] = React__namespace.useState(false);
|
|
31958
31814
|
const draggableRef = React.useRef(null);
|
|
31959
31815
|
const {
|
|
31960
31816
|
dragging
|
|
@@ -31973,7 +31829,9 @@ function MovableCircle(props) {
|
|
|
31973
31829
|
ref: draggableRef,
|
|
31974
31830
|
role: "button",
|
|
31975
31831
|
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
31976
|
-
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}
|
|
31832
|
+
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`,
|
|
31833
|
+
onFocus: () => setFocused(true),
|
|
31834
|
+
onBlur: () => setFocused(false)
|
|
31977
31835
|
}, /*#__PURE__*/React__namespace.createElement("ellipse", {
|
|
31978
31836
|
className: "focus-ring",
|
|
31979
31837
|
cx: centerPx[X],
|
|
@@ -31988,19 +31846,29 @@ function MovableCircle(props) {
|
|
|
31988
31846
|
rx: radiiPx[X],
|
|
31989
31847
|
ry: radiiPx[Y]
|
|
31990
31848
|
}), /*#__PURE__*/React__namespace.createElement(DragHandle, {
|
|
31991
|
-
center: center
|
|
31849
|
+
center: center,
|
|
31850
|
+
dragging: dragging,
|
|
31851
|
+
focused: focused
|
|
31992
31852
|
}));
|
|
31993
31853
|
}
|
|
31994
31854
|
const dragHandleDimensions = [24, 14];
|
|
31995
31855
|
const dragHandleDotPositions = crossProduct([-4.4, 0, 4.4], [-2.1, 2.1]);
|
|
31996
31856
|
function DragHandle(props) {
|
|
31997
31857
|
const {
|
|
31998
|
-
center
|
|
31858
|
+
center,
|
|
31859
|
+
dragging,
|
|
31860
|
+
focused
|
|
31999
31861
|
} = props;
|
|
32000
|
-
const cornerRadius = Math.min(...dragHandleDimensions) / 2;
|
|
32001
31862
|
const [centerPx] = useTransformVectorsToPixels(center);
|
|
31863
|
+
const {
|
|
31864
|
+
markings
|
|
31865
|
+
} = useGraphConfig();
|
|
31866
|
+
const cornerRadius = Math.min(...dragHandleDimensions) / 2;
|
|
32002
31867
|
const topLeft = mafs.vec.sub(centerPx, mafs.vec.scale(dragHandleDimensions, 0.5));
|
|
32003
|
-
|
|
31868
|
+
const showHairlines = (dragging || focused) && markings !== "none";
|
|
31869
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, showHairlines && /*#__PURE__*/React__namespace.createElement(Hairlines, {
|
|
31870
|
+
point: center
|
|
31871
|
+
}), /*#__PURE__*/React__namespace.createElement("rect", {
|
|
32004
31872
|
className: "movable-circle-handle",
|
|
32005
31873
|
x: topLeft[X],
|
|
32006
31874
|
y: topLeft[Y],
|
|
@@ -32027,14 +31895,7 @@ function crossProduct(as, bs) {
|
|
|
32027
31895
|
}
|
|
32028
31896
|
return result;
|
|
32029
31897
|
}
|
|
32030
|
-
function
|
|
32031
|
-
let {
|
|
32032
|
-
state
|
|
32033
|
-
} = _ref;
|
|
32034
|
-
// The reason that CircleGraphDescription is a component (rather than a
|
|
32035
|
-
// function that returns a string) is because it needs to use a
|
|
32036
|
-
// hook: `usePerseusI18n`.
|
|
32037
|
-
const i18n = usePerseusI18n();
|
|
31898
|
+
function getCircleGraphDescription(state, i18n) {
|
|
32038
31899
|
const strings = describeCircleGraph(state, i18n);
|
|
32039
31900
|
return strings.srCircleInteractiveElement;
|
|
32040
31901
|
}
|
|
@@ -32087,15 +31948,13 @@ function describeCircleGraph(state, i18n) {
|
|
|
32087
31948
|
};
|
|
32088
31949
|
}
|
|
32089
31950
|
|
|
32090
|
-
function renderLinearGraph(state, dispatch) {
|
|
31951
|
+
function renderLinearGraph(state, dispatch, i18n) {
|
|
32091
31952
|
return {
|
|
32092
31953
|
graph: /*#__PURE__*/React__namespace.createElement(LinearGraph, {
|
|
32093
31954
|
graphState: state,
|
|
32094
31955
|
dispatch: dispatch
|
|
32095
31956
|
}),
|
|
32096
|
-
interactiveElementsDescription:
|
|
32097
|
-
state: state
|
|
32098
|
-
})
|
|
31957
|
+
interactiveElementsDescription: getLinearGraphDescription(state, i18n)
|
|
32099
31958
|
};
|
|
32100
31959
|
}
|
|
32101
31960
|
const LinearGraph = (props, key) => {
|
|
@@ -32160,14 +32019,7 @@ const LinearGraph = (props, key) => {
|
|
|
32160
32019
|
style: a11y.srOnly
|
|
32161
32020
|
}, slopeString));
|
|
32162
32021
|
};
|
|
32163
|
-
function
|
|
32164
|
-
let {
|
|
32165
|
-
state
|
|
32166
|
-
} = _ref;
|
|
32167
|
-
// The reason that LinearGraphDescription is a component (rather than a
|
|
32168
|
-
// function that returns a string) is because it needs to use a
|
|
32169
|
-
// hook: `usePerseusI18n`.
|
|
32170
|
-
const i18n = usePerseusI18n();
|
|
32022
|
+
function getLinearGraphDescription(state, i18n) {
|
|
32171
32023
|
const strings = describeLinearGraph(state, i18n);
|
|
32172
32024
|
return strings.srLinearInteractiveElement;
|
|
32173
32025
|
}
|
|
@@ -32211,15 +32063,13 @@ function describeLinearGraph(state, i18n) {
|
|
|
32211
32063
|
};
|
|
32212
32064
|
}
|
|
32213
32065
|
|
|
32214
|
-
function renderLinearSystemGraph(state, dispatch) {
|
|
32066
|
+
function renderLinearSystemGraph(state, dispatch, i18n) {
|
|
32215
32067
|
return {
|
|
32216
32068
|
graph: /*#__PURE__*/React__namespace.createElement(LinearSystemGraph, {
|
|
32217
32069
|
graphState: state,
|
|
32218
32070
|
dispatch: dispatch
|
|
32219
32071
|
}),
|
|
32220
|
-
interactiveElementsDescription:
|
|
32221
|
-
state: state
|
|
32222
|
-
})
|
|
32072
|
+
interactiveElementsDescription: getLinearSystemGraphDescription(state, i18n)
|
|
32223
32073
|
};
|
|
32224
32074
|
}
|
|
32225
32075
|
const LinearSystemGraph = props => {
|
|
@@ -32312,19 +32162,9 @@ const LinearSystemGraph = props => {
|
|
|
32312
32162
|
}, slopeDescription));
|
|
32313
32163
|
}));
|
|
32314
32164
|
};
|
|
32315
|
-
function LinearSystemGraphDescription(_ref3) {
|
|
32316
|
-
let {
|
|
32317
|
-
state
|
|
32318
|
-
} = _ref3;
|
|
32319
|
-
// The reason that LinearSystemGraphDescription is a component (rather
|
|
32320
|
-
// than a function that returns a string) is because it needs to use a
|
|
32321
|
-
// hook: `usePerseusI18n`.
|
|
32322
|
-
const i18n = usePerseusI18n();
|
|
32323
|
-
return describeLinearSystemGraph(state, i18n);
|
|
32324
|
-
}
|
|
32325
32165
|
|
|
32326
32166
|
// Exported for testing
|
|
32327
|
-
function
|
|
32167
|
+
function getLinearSystemGraphDescription(state, i18n) {
|
|
32328
32168
|
const {
|
|
32329
32169
|
strings,
|
|
32330
32170
|
locale
|
|
@@ -32350,15 +32190,13 @@ function describeLinearSystemGraph(state, i18n) {
|
|
|
32350
32190
|
});
|
|
32351
32191
|
}
|
|
32352
32192
|
|
|
32353
|
-
function renderPointGraph(state, dispatch) {
|
|
32193
|
+
function renderPointGraph(state, dispatch, i18n) {
|
|
32354
32194
|
return {
|
|
32355
32195
|
graph: /*#__PURE__*/React__namespace.createElement(PointGraph, {
|
|
32356
32196
|
graphState: state,
|
|
32357
32197
|
dispatch: dispatch
|
|
32358
32198
|
}),
|
|
32359
|
-
interactiveElementsDescription:
|
|
32360
|
-
state: state
|
|
32361
|
-
})
|
|
32199
|
+
interactiveElementsDescription: getPointGraphDescription(state, i18n)
|
|
32362
32200
|
};
|
|
32363
32201
|
}
|
|
32364
32202
|
function PointGraph(props) {
|
|
@@ -32380,7 +32218,9 @@ function PointGraph(props) {
|
|
|
32380
32218
|
if (focusedIndex != null) {
|
|
32381
32219
|
pointsRef.current[focusedIndex]?.focus();
|
|
32382
32220
|
}
|
|
32383
|
-
}, [props.graphState.focusedPointIndex,
|
|
32221
|
+
}, [props.graphState.focusedPointIndex,
|
|
32222
|
+
// Ensure that we re-focus if a point is deleted.
|
|
32223
|
+
props.graphState.coords.length, pointsRef]);
|
|
32384
32224
|
const statefulProps = {
|
|
32385
32225
|
...props,
|
|
32386
32226
|
graphConfig,
|
|
@@ -32452,18 +32292,9 @@ function UnlimitedPointGraph(statefulProps) {
|
|
|
32452
32292
|
}
|
|
32453
32293
|
})));
|
|
32454
32294
|
}
|
|
32455
|
-
function PointGraphDescription(_ref) {
|
|
32456
|
-
let {
|
|
32457
|
-
state
|
|
32458
|
-
} = _ref;
|
|
32459
|
-
// PointGraphDescription needs to `usePerseusI18n`, so it has to be a
|
|
32460
|
-
// component rather than a function that simply returns a string.
|
|
32461
|
-
const i18n = usePerseusI18n();
|
|
32462
|
-
return describePointGraph(state, i18n);
|
|
32463
|
-
}
|
|
32464
32295
|
|
|
32465
32296
|
// Exported for testing
|
|
32466
|
-
function
|
|
32297
|
+
function getPointGraphDescription(state, i18n) {
|
|
32467
32298
|
const {
|
|
32468
32299
|
strings,
|
|
32469
32300
|
locale
|
|
@@ -32471,8 +32302,8 @@ function describePointGraph(state, i18n) {
|
|
|
32471
32302
|
if (state.coords.length === 0) {
|
|
32472
32303
|
return strings.srNoInteractiveElements;
|
|
32473
32304
|
}
|
|
32474
|
-
const pointDescriptions = state.coords.map((
|
|
32475
|
-
let [x, y] =
|
|
32305
|
+
const pointDescriptions = state.coords.map((_ref, index) => {
|
|
32306
|
+
let [x, y] = _ref;
|
|
32476
32307
|
return strings.srPointAtCoordinates({
|
|
32477
32308
|
num: index + 1,
|
|
32478
32309
|
x: srFormatNumber(x, locale),
|
|
@@ -32552,7 +32383,9 @@ const PolygonGraph = props => {
|
|
|
32552
32383
|
if (focusedIndex != null) {
|
|
32553
32384
|
pointsRef.current[focusedIndex]?.focus();
|
|
32554
32385
|
}
|
|
32555
|
-
}, [props.graphState.focusedPointIndex,
|
|
32386
|
+
}, [props.graphState.focusedPointIndex,
|
|
32387
|
+
// Ensure that we re-focus if a point is deleted.
|
|
32388
|
+
props.graphState.coords.length, pointsRef]);
|
|
32556
32389
|
|
|
32557
32390
|
// If the unlimited polygon is rendered with 3 or more coordinates
|
|
32558
32391
|
// Close the polygon, but only on first render.
|
|
@@ -33135,15 +32968,13 @@ function describeQuadraticGraph(state, i18n) {
|
|
|
33135
32968
|
};
|
|
33136
32969
|
}
|
|
33137
32970
|
|
|
33138
|
-
function renderRayGraph(state, dispatch) {
|
|
32971
|
+
function renderRayGraph(state, dispatch, i18n) {
|
|
33139
32972
|
return {
|
|
33140
32973
|
graph: /*#__PURE__*/React__namespace.createElement(RayGraph, {
|
|
33141
32974
|
graphState: state,
|
|
33142
32975
|
dispatch: dispatch
|
|
33143
32976
|
}),
|
|
33144
|
-
interactiveElementsDescription:
|
|
33145
|
-
state: state
|
|
33146
|
-
})
|
|
32977
|
+
interactiveElementsDescription: getRayGraphDescription(state, i18n)
|
|
33147
32978
|
};
|
|
33148
32979
|
}
|
|
33149
32980
|
const RayGraph = props => {
|
|
@@ -33197,14 +33028,7 @@ const RayGraph = props => {
|
|
|
33197
33028
|
style: a11y.srOnly
|
|
33198
33029
|
}, srRayPoints));
|
|
33199
33030
|
};
|
|
33200
|
-
function
|
|
33201
|
-
let {
|
|
33202
|
-
state
|
|
33203
|
-
} = _ref;
|
|
33204
|
-
// The reason that RayGraphDescription is a component (rather than a
|
|
33205
|
-
// function that returns a string) is because it needs to use a
|
|
33206
|
-
// hook: `usePerseusI18n`.
|
|
33207
|
-
const i18n = usePerseusI18n();
|
|
33031
|
+
function getRayGraphDescription(state, i18n) {
|
|
33208
33032
|
const strings = describeRayGraph(state, i18n);
|
|
33209
33033
|
return strings.srRayInteractiveElement;
|
|
33210
33034
|
}
|
|
@@ -33254,15 +33078,13 @@ function describeRayGraph(state, i18n) {
|
|
|
33254
33078
|
};
|
|
33255
33079
|
}
|
|
33256
33080
|
|
|
33257
|
-
function renderSegmentGraph(state, dispatch) {
|
|
33081
|
+
function renderSegmentGraph(state, dispatch, i18n) {
|
|
33258
33082
|
return {
|
|
33259
33083
|
graph: /*#__PURE__*/React__namespace.createElement(SegmentGraph, {
|
|
33260
33084
|
graphState: state,
|
|
33261
33085
|
dispatch: dispatch
|
|
33262
33086
|
}),
|
|
33263
|
-
interactiveElementsDescription:
|
|
33264
|
-
state: state
|
|
33265
|
-
})
|
|
33087
|
+
interactiveElementsDescription: getSegmentGraphDescription(state, i18n)
|
|
33266
33088
|
};
|
|
33267
33089
|
}
|
|
33268
33090
|
const SegmentGraph = _ref => {
|
|
@@ -33356,25 +33178,15 @@ const SegmentGraph = _ref => {
|
|
|
33356
33178
|
function getLengthOfSegment(segment) {
|
|
33357
33179
|
return kmath.point.distanceToPoint(...segment);
|
|
33358
33180
|
}
|
|
33359
|
-
function SegmentGraphDescription(_ref2) {
|
|
33360
|
-
let {
|
|
33361
|
-
state
|
|
33362
|
-
} = _ref2;
|
|
33363
|
-
// The reason that SegmentGraphDescription is a component (rather than a
|
|
33364
|
-
// function that returns a string) is because it needs to use a
|
|
33365
|
-
// hook: `usePerseusI18n`.
|
|
33366
|
-
const i18n = usePerseusI18n();
|
|
33367
|
-
return describeSegmentGraph(state, i18n);
|
|
33368
|
-
}
|
|
33369
33181
|
|
|
33370
33182
|
// Exported for testing
|
|
33371
|
-
function
|
|
33183
|
+
function getSegmentGraphDescription(state, i18n) {
|
|
33372
33184
|
const {
|
|
33373
33185
|
strings,
|
|
33374
33186
|
locale
|
|
33375
33187
|
} = i18n;
|
|
33376
|
-
const segmentDescriptions = state.coords.map((
|
|
33377
|
-
let [point1, point2] =
|
|
33188
|
+
const segmentDescriptions = state.coords.map((_ref2, index) => {
|
|
33189
|
+
let [point1, point2] = _ref2;
|
|
33378
33190
|
return strings.srMultipleSegmentIndividualLabel({
|
|
33379
33191
|
point1X: srFormatNumber(point1[X], locale),
|
|
33380
33192
|
point1Y: srFormatNumber(point1[Y], locale),
|
|
@@ -33388,13 +33200,13 @@ function describeSegmentGraph(state, i18n) {
|
|
|
33388
33200
|
});
|
|
33389
33201
|
}
|
|
33390
33202
|
|
|
33391
|
-
function renderSinusoidGraph(state, dispatch) {
|
|
33203
|
+
function renderSinusoidGraph(state, dispatch, i18n) {
|
|
33392
33204
|
return {
|
|
33393
33205
|
graph: /*#__PURE__*/React__namespace.createElement(SinusoidGraph, {
|
|
33394
33206
|
graphState: state,
|
|
33395
33207
|
dispatch: dispatch
|
|
33396
33208
|
}),
|
|
33397
|
-
interactiveElementsDescription:
|
|
33209
|
+
interactiveElementsDescription: getSinusoidDescription(state, i18n)
|
|
33398
33210
|
};
|
|
33399
33211
|
}
|
|
33400
33212
|
function SinusoidGraph(props) {
|
|
@@ -33402,6 +33214,9 @@ function SinusoidGraph(props) {
|
|
|
33402
33214
|
dispatch,
|
|
33403
33215
|
graphState
|
|
33404
33216
|
} = props;
|
|
33217
|
+
const i18n = usePerseusI18n();
|
|
33218
|
+
const id = React__namespace.useId();
|
|
33219
|
+
const descriptionId = id + "-description";
|
|
33405
33220
|
|
|
33406
33221
|
// Destructure the coordinates from the graph state
|
|
33407
33222
|
// Note: The order of the coordinates is important:
|
|
@@ -33426,15 +33241,30 @@ function SinusoidGraph(props) {
|
|
|
33426
33241
|
if (coeffs !== undefined) {
|
|
33427
33242
|
coeffRef.current = coeffs;
|
|
33428
33243
|
}
|
|
33429
|
-
|
|
33244
|
+
|
|
33245
|
+
// Aria strings
|
|
33246
|
+
const {
|
|
33247
|
+
srSinusoidGraph,
|
|
33248
|
+
srSinusoidDescription,
|
|
33249
|
+
srSinusoidRootPoint,
|
|
33250
|
+
srSinusoidPeakPoint
|
|
33251
|
+
} = describeSinusoidGraph(graphState, i18n);
|
|
33252
|
+
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
33253
|
+
// Outer graph minimal description
|
|
33254
|
+
"aria-label": srSinusoidGraph,
|
|
33255
|
+
"aria-describedby": descriptionId
|
|
33256
|
+
}, /*#__PURE__*/React__namespace.createElement(mafs.Plot.OfX, {
|
|
33430
33257
|
y: x => computeSine(x, coeffRef.current),
|
|
33431
33258
|
color: wonderBlocksTokens.color.blue
|
|
33432
33259
|
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
33260
|
+
ariaLabel: i === 0 ? srSinusoidRootPoint : srSinusoidPeakPoint,
|
|
33433
33261
|
key: "point-" + i,
|
|
33434
33262
|
point: coord,
|
|
33435
33263
|
sequenceNumber: i + 1,
|
|
33436
33264
|
onMove: destination => dispatch(actions.sinusoid.movePoint(i, destination))
|
|
33437
|
-
}))
|
|
33265
|
+
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
33266
|
+
id: descriptionId
|
|
33267
|
+
}, srSinusoidDescription));
|
|
33438
33268
|
}
|
|
33439
33269
|
|
|
33440
33270
|
// Plot a sinusoid of the form: f(x) = a * sin(b * x - c) + d
|
|
@@ -33472,6 +33302,52 @@ const getSinusoidCoefficients$1 = coords => {
|
|
|
33472
33302
|
verticalOffset
|
|
33473
33303
|
};
|
|
33474
33304
|
};
|
|
33305
|
+
function getSinusoidDescription(state, i18n) {
|
|
33306
|
+
const strings = describeSinusoidGraph(state, i18n);
|
|
33307
|
+
return strings.srSinusoidInteractiveElements;
|
|
33308
|
+
}
|
|
33309
|
+
function describeSinusoidGraph(state, i18n) {
|
|
33310
|
+
const {
|
|
33311
|
+
strings,
|
|
33312
|
+
locale
|
|
33313
|
+
} = i18n;
|
|
33314
|
+
const {
|
|
33315
|
+
coords
|
|
33316
|
+
} = state;
|
|
33317
|
+
const [root, peak] = coords;
|
|
33318
|
+
const diffX = Math.abs(peak[X] - root[X]);
|
|
33319
|
+
const diffY = Math.abs(peak[Y] - root[Y]);
|
|
33320
|
+
const srSinusoidGraph = strings.srSinusoidGraph;
|
|
33321
|
+
const srSinusoidDescription = strings.srSinusoidDescription({
|
|
33322
|
+
minValue: srFormatNumber(root[Y] - diffY, locale),
|
|
33323
|
+
maxValue: srFormatNumber(root[Y] + diffY, locale),
|
|
33324
|
+
cycleStart: srFormatNumber(root[X] - 2 * diffX, locale),
|
|
33325
|
+
cycleEnd: srFormatNumber(root[X] + 2 * diffX, locale)
|
|
33326
|
+
});
|
|
33327
|
+
const srSinusoidRootPoint = strings.srSinusoidRootPoint({
|
|
33328
|
+
x: srFormatNumber(root[X], locale),
|
|
33329
|
+
y: srFormatNumber(root[Y], locale)
|
|
33330
|
+
});
|
|
33331
|
+
const srSinusoidPeakPoint = strings.srSinusoidPeakPoint({
|
|
33332
|
+
x: srFormatNumber(peak[X], locale),
|
|
33333
|
+
y: srFormatNumber(peak[Y], locale)
|
|
33334
|
+
});
|
|
33335
|
+
const srSinusoidInteractiveElements = strings.srInteractiveElements({
|
|
33336
|
+
elements: strings.srSinusoidInteractiveElements({
|
|
33337
|
+
point1X: srFormatNumber(root[X], locale),
|
|
33338
|
+
point1Y: srFormatNumber(root[Y], locale),
|
|
33339
|
+
point2X: srFormatNumber(peak[X], locale),
|
|
33340
|
+
point2Y: srFormatNumber(peak[Y], locale)
|
|
33341
|
+
})
|
|
33342
|
+
});
|
|
33343
|
+
return {
|
|
33344
|
+
srSinusoidGraph,
|
|
33345
|
+
srSinusoidDescription,
|
|
33346
|
+
srSinusoidRootPoint,
|
|
33347
|
+
srSinusoidPeakPoint,
|
|
33348
|
+
srSinusoidInteractiveElements
|
|
33349
|
+
};
|
|
33350
|
+
}
|
|
33475
33351
|
|
|
33476
33352
|
const {
|
|
33477
33353
|
calculateAngleInDegrees,
|
|
@@ -33642,6 +33518,7 @@ const MafsGraph = props => {
|
|
|
33642
33518
|
const descriptionId = `interactive-graph-description-${uniqueId}`;
|
|
33643
33519
|
const interactiveElementsDescriptionId = `interactive-graph-interactive-elements-description-${uniqueId}`;
|
|
33644
33520
|
const unlimitedGraphKeyboardPromptId = `unlimited-graph-keyboard-prompt-${uniqueId}`;
|
|
33521
|
+
const instructionsId = `instructions-${uniqueId}`;
|
|
33645
33522
|
const graphRef = React__namespace.useRef(null);
|
|
33646
33523
|
const {
|
|
33647
33524
|
analytics
|
|
@@ -33669,6 +33546,7 @@ const MafsGraph = props => {
|
|
|
33669
33546
|
const interactionPrompt = isUnlimitedGraphState(state) && state.showKeyboardInteractionInvitation;
|
|
33670
33547
|
wonderBlocksCore.useOnMountEffect(() => {
|
|
33671
33548
|
analytics.onAnalyticsEvent({
|
|
33549
|
+
// TODO(LEMS-2827): Remove analytics event in LEMS-2827 in favor of ti below.
|
|
33672
33550
|
type: "perseus:interactive-graph-widget:rendered",
|
|
33673
33551
|
payload: {
|
|
33674
33552
|
type,
|
|
@@ -33676,6 +33554,14 @@ const MafsGraph = props => {
|
|
|
33676
33554
|
widgetId: "interactive-graph"
|
|
33677
33555
|
}
|
|
33678
33556
|
});
|
|
33557
|
+
analytics.onAnalyticsEvent({
|
|
33558
|
+
type: "perseus:widget:rendered:ti",
|
|
33559
|
+
payload: {
|
|
33560
|
+
widgetSubType: type,
|
|
33561
|
+
widgetType: "INTERACTIVE_GRAPH",
|
|
33562
|
+
widgetId: "interactive-graph"
|
|
33563
|
+
}
|
|
33564
|
+
});
|
|
33679
33565
|
});
|
|
33680
33566
|
const {
|
|
33681
33567
|
graph,
|
|
@@ -33719,7 +33605,7 @@ const MafsGraph = props => {
|
|
|
33719
33605
|
handleKeyboardEvent(event, state, dispatch);
|
|
33720
33606
|
},
|
|
33721
33607
|
"aria-label": fullGraphAriaLabel,
|
|
33722
|
-
"aria-describedby": describedByIds(fullGraphAriaDescription && descriptionId, interactiveElementsDescription && interactiveElementsDescriptionId, isUnlimitedGraphState(state) && unlimitedGraphKeyboardPromptId),
|
|
33608
|
+
"aria-describedby": describedByIds(fullGraphAriaDescription && descriptionId, interactiveElementsDescription && interactiveElementsDescriptionId, isUnlimitedGraphState(state) && unlimitedGraphKeyboardPromptId, state.type !== "none" && instructionsId),
|
|
33723
33609
|
ref: graphRef,
|
|
33724
33610
|
tabIndex: 0,
|
|
33725
33611
|
onFocus: event => {
|
|
@@ -33736,7 +33622,11 @@ const MafsGraph = props => {
|
|
|
33736
33622
|
id: interactiveElementsDescriptionId,
|
|
33737
33623
|
tabIndex: -1,
|
|
33738
33624
|
className: "mafs-sr-only"
|
|
33739
|
-
}, interactiveElementsDescription), /*#__PURE__*/React__namespace.createElement(
|
|
33625
|
+
}, interactiveElementsDescription), state.type !== "none" && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
33626
|
+
id: instructionsId,
|
|
33627
|
+
tabIndex: -1,
|
|
33628
|
+
className: "mafs-sr-only"
|
|
33629
|
+
}, isUnlimitedGraphState(state) ? strings.srUnlimitedGraphInstructions : strings.srGraphInstructions), /*#__PURE__*/React__namespace.createElement(LegacyGrid, {
|
|
33740
33630
|
box: props.box,
|
|
33741
33631
|
backgroundImage: props.backgroundImage
|
|
33742
33632
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
@@ -33745,7 +33635,9 @@ const MafsGraph = props => {
|
|
|
33745
33635
|
bottom: 0,
|
|
33746
33636
|
left: 0
|
|
33747
33637
|
}
|
|
33748
|
-
}, (props.markings === "graph" || props.markings === "axes") && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(AxisLabels,
|
|
33638
|
+
}, (props.markings === "graph" || props.markings === "axes") && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(AxisLabels, {
|
|
33639
|
+
i18n: i18n
|
|
33640
|
+
})), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View
|
|
33749
33641
|
// If we have locked figures, we set aria-hidden
|
|
33750
33642
|
// to false so that screen readers can read the
|
|
33751
33643
|
// locked figures. If we don't have any locked
|
|
@@ -34082,25 +33974,25 @@ const renderGraphElements = props => {
|
|
|
34082
33974
|
} = state;
|
|
34083
33975
|
switch (type) {
|
|
34084
33976
|
case "angle":
|
|
34085
|
-
return renderAngleGraph(state, dispatch);
|
|
33977
|
+
return renderAngleGraph(state, dispatch, i18n);
|
|
34086
33978
|
case "segment":
|
|
34087
|
-
return renderSegmentGraph(state, dispatch);
|
|
33979
|
+
return renderSegmentGraph(state, dispatch, i18n);
|
|
34088
33980
|
case "linear-system":
|
|
34089
|
-
return renderLinearSystemGraph(state, dispatch);
|
|
33981
|
+
return renderLinearSystemGraph(state, dispatch, i18n);
|
|
34090
33982
|
case "linear":
|
|
34091
|
-
return renderLinearGraph(state, dispatch);
|
|
33983
|
+
return renderLinearGraph(state, dispatch, i18n);
|
|
34092
33984
|
case "ray":
|
|
34093
|
-
return renderRayGraph(state, dispatch);
|
|
33985
|
+
return renderRayGraph(state, dispatch, i18n);
|
|
34094
33986
|
case "polygon":
|
|
34095
33987
|
return renderPolygonGraph(state, dispatch, i18n, markings);
|
|
34096
33988
|
case "point":
|
|
34097
|
-
return renderPointGraph(state, dispatch);
|
|
33989
|
+
return renderPointGraph(state, dispatch, i18n);
|
|
34098
33990
|
case "circle":
|
|
34099
|
-
return renderCircleGraph(state, dispatch);
|
|
33991
|
+
return renderCircleGraph(state, dispatch, i18n);
|
|
34100
33992
|
case "quadratic":
|
|
34101
33993
|
return renderQuadraticGraph(state, dispatch, i18n);
|
|
34102
33994
|
case "sinusoid":
|
|
34103
|
-
return renderSinusoidGraph(state, dispatch);
|
|
33995
|
+
return renderSinusoidGraph(state, dispatch, i18n);
|
|
34104
33996
|
case "none":
|
|
34105
33997
|
return {
|
|
34106
33998
|
graph: null,
|
|
@@ -34520,13 +34412,13 @@ const {
|
|
|
34520
34412
|
polar
|
|
34521
34413
|
} = kmath.angles;
|
|
34522
34414
|
const {
|
|
34523
|
-
angleMeasures
|
|
34524
|
-
ccw
|
|
34525
|
-
lawOfCosines
|
|
34415
|
+
angleMeasures,
|
|
34416
|
+
ccw,
|
|
34417
|
+
lawOfCosines,
|
|
34526
34418
|
magnitude: magnitude$1,
|
|
34527
34419
|
polygonSidesIntersect,
|
|
34528
34420
|
reverseVector,
|
|
34529
|
-
sign
|
|
34421
|
+
sign,
|
|
34530
34422
|
vector: vector$1
|
|
34531
34423
|
} = kmath.geometry;
|
|
34532
34424
|
const {
|
|
@@ -35033,7 +34925,7 @@ function doAddPoint(state, action) {
|
|
|
35033
34925
|
...state,
|
|
35034
34926
|
hasBeenInteractedWith: true,
|
|
35035
34927
|
coords: newCoords,
|
|
35036
|
-
showRemovePointButton:
|
|
34928
|
+
showRemovePointButton: true,
|
|
35037
34929
|
focusedPointIndex: newCoords.length - 1
|
|
35038
34930
|
};
|
|
35039
34931
|
}
|
|
@@ -35041,17 +34933,12 @@ function doRemovePoint(state, action) {
|
|
|
35041
34933
|
if (!isUnlimitedGraphState(state)) {
|
|
35042
34934
|
return state;
|
|
35043
34935
|
}
|
|
35044
|
-
|
|
35045
|
-
if (state.interactionMode === "mouse") {
|
|
35046
|
-
nextFocusedPointIndex = null;
|
|
35047
|
-
} else {
|
|
35048
|
-
nextFocusedPointIndex = state.coords.length > 1 ? state.coords.length - 2 : null;
|
|
35049
|
-
}
|
|
34936
|
+
const nextFocusedPointIndex = state.coords.length > 1 ? state.coords.length - 2 : null;
|
|
35050
34937
|
return {
|
|
35051
34938
|
...state,
|
|
35052
34939
|
coords: state.coords.filter((_, i) => i !== action.index),
|
|
35053
34940
|
focusedPointIndex: nextFocusedPointIndex,
|
|
35054
|
-
showRemovePointButton: false
|
|
34941
|
+
showRemovePointButton: nextFocusedPointIndex !== null ? true : false
|
|
35055
34942
|
};
|
|
35056
34943
|
}
|
|
35057
34944
|
const getDeltaVertex = (maxMoves, minMoves, delta) => {
|
|
@@ -35228,7 +35115,7 @@ function boundAndSnapToPolygonAngle(destinationPoint, _ref6, index) {
|
|
|
35228
35115
|
});
|
|
35229
35116
|
|
|
35230
35117
|
// Gets the radian angles between the coords and maps them to degrees
|
|
35231
|
-
const angles = angleMeasures
|
|
35118
|
+
const angles = angleMeasures(coordsCopy).map(angle => angle * 180 / Math.PI);
|
|
35232
35119
|
|
|
35233
35120
|
// Gets the relative index of a point
|
|
35234
35121
|
const rel = j => {
|
|
@@ -35262,7 +35149,7 @@ function boundAndSnapToPolygonAngle(destinationPoint, _ref6, index) {
|
|
|
35262
35149
|
// we want to add the inner angle to the outer angle, and if it's on the right,
|
|
35263
35150
|
// we want to subtract the inner angle from the outer angle. The angle solved
|
|
35264
35151
|
// for is then used in the polar function to determine the new point.
|
|
35265
|
-
const onLeft = sign
|
|
35152
|
+
const onLeft = sign(ccw(coordsCopy[rel(-1)], coordsCopy[rel(1)], coordsCopy[index])) === 1;
|
|
35266
35153
|
|
|
35267
35154
|
// Solve for side by using the law of sines
|
|
35268
35155
|
const side = Math.sin(innerAngles[1] * Math.PI / 180) / Math.sin(innerAngles[2] * Math.PI / 180) * knownSide;
|
|
@@ -35316,7 +35203,7 @@ function boundAndSnapToSides(destinationPoint, _ref7, index) {
|
|
|
35316
35203
|
|
|
35317
35204
|
// Solve for angle by using the law of cosines
|
|
35318
35205
|
// Angle at the first vertex of the polygon
|
|
35319
|
-
const innerAngle = lawOfCosines
|
|
35206
|
+
const innerAngle = lawOfCosines(sides[0], sides[2], sides[1]);
|
|
35320
35207
|
|
|
35321
35208
|
// Angle at the second vertex of the polygon
|
|
35322
35209
|
const outerAngle = getAngleFromVertex(coordsCopy[rel(1)], coordsCopy[rel(-1)]);
|
|
@@ -35327,7 +35214,7 @@ function boundAndSnapToSides(destinationPoint, _ref7, index) {
|
|
|
35327
35214
|
// we want to add the inner angle to the outer angle, and if it's on the right,
|
|
35328
35215
|
// we want to subtract the inner angle from the outer angle. The angle solved
|
|
35329
35216
|
// for is then used in the polar function to determine the new point.
|
|
35330
|
-
const onLeft = sign
|
|
35217
|
+
const onLeft = sign(ccw(coordsCopy[rel(-1)], coordsCopy[rel(1)], coordsCopy[index])) === 1;
|
|
35331
35218
|
|
|
35332
35219
|
// Uses the length of the first side of the polygon (radial coordinate)
|
|
35333
35220
|
// and the angle between the first and second sides of the
|
|
@@ -35465,27 +35352,19 @@ const {
|
|
|
35465
35352
|
getClockwiseAngle
|
|
35466
35353
|
} = kmath.angles;
|
|
35467
35354
|
const {
|
|
35468
|
-
angleMeasures,
|
|
35469
|
-
ccw,
|
|
35470
|
-
collinear,
|
|
35471
35355
|
getLineEquation,
|
|
35472
35356
|
getLineIntersection,
|
|
35473
|
-
intersects,
|
|
35474
|
-
lawOfCosines,
|
|
35475
35357
|
magnitude,
|
|
35476
|
-
rotate,
|
|
35477
|
-
sign,
|
|
35478
35358
|
vector
|
|
35479
35359
|
} = kmath.geometry;
|
|
35480
35360
|
const defaultBackgroundImage = {
|
|
35481
35361
|
url: null
|
|
35482
35362
|
};
|
|
35483
35363
|
const UNLIMITED = "unlimited";
|
|
35484
|
-
|
|
35485
|
-
|
|
35486
|
-
|
|
35487
|
-
|
|
35488
|
-
}
|
|
35364
|
+
|
|
35365
|
+
// Sample background image:
|
|
35366
|
+
// https://ka-perseus-graphie.s3.amazonaws.com/29c1b0fcd17fe63df0f148fe357044d5d5c7d0bb.png
|
|
35367
|
+
|
|
35489
35368
|
function numSteps(range, step) {
|
|
35490
35369
|
return Math.floor((range[1] - range[0]) / step);
|
|
35491
35370
|
}
|
|
@@ -35530,7 +35409,6 @@ function getQuadraticCoefficients(coords) {
|
|
|
35530
35409
|
return [a, b, c];
|
|
35531
35410
|
}
|
|
35532
35411
|
class InteractiveGraph extends React__namespace.Component {
|
|
35533
|
-
legacyGraphRef = /*#__PURE__*/React__namespace.createRef();
|
|
35534
35412
|
mafsRef = /*#__PURE__*/React__namespace.createRef();
|
|
35535
35413
|
static defaultProps = {
|
|
35536
35414
|
labels: ["x", "y"],
|
|
@@ -35548,9 +35426,6 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
35548
35426
|
if (this.mafsRef.current?.getUserInput) {
|
|
35549
35427
|
return this.mafsRef.current.getUserInput();
|
|
35550
35428
|
}
|
|
35551
|
-
if (this.legacyGraphRef.current?.getUserInput) {
|
|
35552
|
-
return this.legacyGraphRef.current.getUserInput();
|
|
35553
|
-
}
|
|
35554
35429
|
throw new perseusCore.PerseusError("Cannot getUserInput from a graph that has never rendered", perseusCore.Errors.NotAllowed);
|
|
35555
35430
|
}
|
|
35556
35431
|
getPromptJSON() {
|
|
@@ -35744,8 +35619,32 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
35744
35619
|
}
|
|
35745
35620
|
static getEquationString(props) {
|
|
35746
35621
|
const type = props.graph.type;
|
|
35747
|
-
|
|
35748
|
-
|
|
35622
|
+
switch (type) {
|
|
35623
|
+
case "none":
|
|
35624
|
+
return InteractiveGraph.getNoneEquationString();
|
|
35625
|
+
case "linear":
|
|
35626
|
+
return InteractiveGraph.getLinearEquationString(props);
|
|
35627
|
+
case "quadratic":
|
|
35628
|
+
return InteractiveGraph.getQuadraticEquationString(props);
|
|
35629
|
+
case "sinusoid":
|
|
35630
|
+
return InteractiveGraph.getSinusoidEquationString(props);
|
|
35631
|
+
case "circle":
|
|
35632
|
+
return InteractiveGraph.getCircleEquationString(props);
|
|
35633
|
+
case "linear-system":
|
|
35634
|
+
return InteractiveGraph.getLinearSystemEquationString(props);
|
|
35635
|
+
case "point":
|
|
35636
|
+
return InteractiveGraph.getPointEquationString(props);
|
|
35637
|
+
case "segment":
|
|
35638
|
+
return InteractiveGraph.getSegmentEquationString(props);
|
|
35639
|
+
case "ray":
|
|
35640
|
+
return InteractiveGraph.getRayEquationString(props);
|
|
35641
|
+
case "polygon":
|
|
35642
|
+
return InteractiveGraph.getPolygonEquationString(props);
|
|
35643
|
+
case "angle":
|
|
35644
|
+
return InteractiveGraph.getAngleEquationString(props);
|
|
35645
|
+
default:
|
|
35646
|
+
throw new wonderStuffCore.UnreachableCaseError(type);
|
|
35647
|
+
}
|
|
35749
35648
|
}
|
|
35750
35649
|
static pointsFromNormalized(props, coordsList, noSnap) {
|
|
35751
35650
|
// @ts-expect-error - TS2322 - Type 'number[][]' is not assignable to type 'readonly Coord[]'.
|
|
@@ -35889,8 +35788,7 @@ var InteractiveGraph$1 = {
|
|
|
35889
35788
|
name: "interactive-graph",
|
|
35890
35789
|
displayName: "Interactive graph (Assessments only)",
|
|
35891
35790
|
widget: InteractiveGraph,
|
|
35892
|
-
staticTransform: staticTransform$3
|
|
35893
|
-
getPublicWidgetOptions: perseusCore.getInteractiveGraphPublicWidgetOptions
|
|
35791
|
+
staticTransform: staticTransform$3
|
|
35894
35792
|
};
|
|
35895
35793
|
|
|
35896
35794
|
// TODO: can we use WB typography?
|
|
@@ -36526,10 +36424,15 @@ class LabelImage extends React__namespace.Component {
|
|
|
36526
36424
|
});
|
|
36527
36425
|
}
|
|
36528
36426
|
activateMarker(index, opened) {
|
|
36427
|
+
// TODO(LEMS-2830): Remove analytics event in LEMS-2830 in favor of ti below.
|
|
36529
36428
|
this.props.analytics?.onAnalyticsEvent({
|
|
36530
36429
|
type: "perseus:label-image:marker-interacted-with",
|
|
36531
36430
|
payload: null
|
|
36532
36431
|
});
|
|
36432
|
+
this.props.analytics?.onAnalyticsEvent({
|
|
36433
|
+
type: "perseus:label-image:marker-interacted-with:ti",
|
|
36434
|
+
payload: null
|
|
36435
|
+
});
|
|
36533
36436
|
const {
|
|
36534
36437
|
activeMarkerIndex
|
|
36535
36438
|
} = this.state;
|
|
@@ -36673,10 +36576,15 @@ class LabelImage extends React__namespace.Component {
|
|
|
36673
36576
|
})),
|
|
36674
36577
|
multipleSelect: this.props.multipleAnswers,
|
|
36675
36578
|
onChange: selection => {
|
|
36579
|
+
// TODO(LEMS-2829): Remove analytics event in LEMS-2829 in favor of ti below.
|
|
36676
36580
|
this.props.analytics?.onAnalyticsEvent({
|
|
36677
36581
|
type: "perseus:label-image:choiced-interacted-with",
|
|
36678
36582
|
payload: null
|
|
36679
36583
|
});
|
|
36584
|
+
this.props.analytics?.onAnalyticsEvent({
|
|
36585
|
+
type: "perseus:label-image:choiced-interacted-with:ti",
|
|
36586
|
+
payload: null
|
|
36587
|
+
});
|
|
36680
36588
|
this.handleAnswerChoicesChangeForMarker(index, selection);
|
|
36681
36589
|
},
|
|
36682
36590
|
onToggle: opened => this.activateMarker(index, opened)
|
|
@@ -36781,10 +36689,15 @@ class LabelImage extends React__namespace.Component {
|
|
|
36781
36689
|
})), this.renderMarkers()), /*#__PURE__*/React__namespace.createElement(HideAnswersToggle, {
|
|
36782
36690
|
areAnswersHidden: this.state.hideAnswers,
|
|
36783
36691
|
onChange: hideAnswers => {
|
|
36692
|
+
// TODO(LEMS-2831): Remove analytics event in LEMS-2831 in favor of ti below.
|
|
36784
36693
|
this.props.analytics?.onAnalyticsEvent({
|
|
36785
36694
|
type: "perseus:label-image:toggle-answers-hidden",
|
|
36786
36695
|
payload: null
|
|
36787
36696
|
});
|
|
36697
|
+
this.props.analytics?.onAnalyticsEvent({
|
|
36698
|
+
type: "perseus:label-image:toggle-answers-hidden:ti",
|
|
36699
|
+
payload: null
|
|
36700
|
+
});
|
|
36788
36701
|
this.setState({
|
|
36789
36702
|
hideAnswers
|
|
36790
36703
|
});
|
|
@@ -36847,8 +36760,7 @@ var LabelImage$1 = {
|
|
|
36847
36760
|
displayName: "Label Image",
|
|
36848
36761
|
widget: LabelImageWithDependencies,
|
|
36849
36762
|
accessible: true,
|
|
36850
|
-
isLintable: true
|
|
36851
|
-
getPublicWidgetOptions: perseusCore.getLabelImagePublicWidgetOptions
|
|
36763
|
+
isLintable: true
|
|
36852
36764
|
};
|
|
36853
36765
|
|
|
36854
36766
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -37107,20 +37019,24 @@ class Draggable extends React__namespace.Component {
|
|
|
37107
37019
|
if (this.props.margin != null) {
|
|
37108
37020
|
style.margin = this.props.margin;
|
|
37109
37021
|
}
|
|
37110
|
-
return
|
|
37111
|
-
|
|
37112
|
-
|
|
37113
|
-
|
|
37114
|
-
|
|
37115
|
-
|
|
37116
|
-
|
|
37117
|
-
|
|
37118
|
-
|
|
37119
|
-
|
|
37120
|
-
|
|
37121
|
-
|
|
37122
|
-
|
|
37123
|
-
|
|
37022
|
+
return (
|
|
37023
|
+
/*#__PURE__*/
|
|
37024
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- TODO(LEMS-2871): Address a11y error
|
|
37025
|
+
React__namespace.createElement("li", {
|
|
37026
|
+
className: className,
|
|
37027
|
+
style: style,
|
|
37028
|
+
onMouseDown: this.onMouseDown,
|
|
37029
|
+
onTouchStart: this.onMouseDown,
|
|
37030
|
+
onTouchMove: this.onMouseMove,
|
|
37031
|
+
onTouchEnd: this.onMouseUp,
|
|
37032
|
+
onTouchCancel: this.onMouseUp
|
|
37033
|
+
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
37034
|
+
content: this.props.content,
|
|
37035
|
+
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "draggable"),
|
|
37036
|
+
onRender: this.props.onRender,
|
|
37037
|
+
strings: this.context.strings
|
|
37038
|
+
}))
|
|
37039
|
+
);
|
|
37124
37040
|
}
|
|
37125
37041
|
}
|
|
37126
37042
|
class Sortable extends React__namespace.Component {
|
|
@@ -37574,10 +37490,6 @@ const getPromptJSON$9 = (renderProps, userInput) => {
|
|
|
37574
37490
|
};
|
|
37575
37491
|
};
|
|
37576
37492
|
|
|
37577
|
-
const {
|
|
37578
|
-
shuffle: shuffle$1,
|
|
37579
|
-
seededRNG
|
|
37580
|
-
} = Util;
|
|
37581
37493
|
const HACKY_CSS_CLASSNAME = "perseus-widget-matcher";
|
|
37582
37494
|
class Matcher extends React__namespace.Component {
|
|
37583
37495
|
static contextType = PerseusI18nContext;
|
|
@@ -37679,16 +37591,16 @@ class Matcher extends React__namespace.Component {
|
|
|
37679
37591
|
}, "1")));
|
|
37680
37592
|
}
|
|
37681
37593
|
|
|
37682
|
-
|
|
37683
|
-
|
|
37684
|
-
|
|
37685
|
-
|
|
37686
|
-
|
|
37687
|
-
|
|
37688
|
-
|
|
37689
|
-
left
|
|
37690
|
-
|
|
37691
|
-
|
|
37594
|
+
/* TODO(LEMS-2841):
|
|
37595
|
+
Once the getMatcherPublicWidgetOptions function gets connected to the
|
|
37596
|
+
widget, we'll need to update this to the line below to only shuffle
|
|
37597
|
+
on the server.
|
|
37598
|
+
const {left, right} = this.props;
|
|
37599
|
+
*/
|
|
37600
|
+
const {
|
|
37601
|
+
left,
|
|
37602
|
+
right
|
|
37603
|
+
} = perseusCore.shuffleMatcher(this.props);
|
|
37692
37604
|
const showLabels = ___default["default"].any(this.props.labels);
|
|
37693
37605
|
const constraints = {
|
|
37694
37606
|
height: ___default["default"].max([this.state.leftHeight, this.state.rightHeight])
|
|
@@ -38179,8 +38091,7 @@ var Matrix$1 = {
|
|
|
38179
38091
|
widget: Matrix,
|
|
38180
38092
|
transform: propTransform$1,
|
|
38181
38093
|
staticTransform: staticTransform$2,
|
|
38182
|
-
isLintable: true
|
|
38183
|
-
getPublicWidgetOptions: perseusCore.getMatrixPublicWidgetOptions
|
|
38094
|
+
isLintable: true
|
|
38184
38095
|
};
|
|
38185
38096
|
|
|
38186
38097
|
const getPromptJSON$7 = () => {
|
|
@@ -39757,8 +39668,7 @@ var NumberLine$1 = {
|
|
|
39757
39668
|
displayName: "Number line",
|
|
39758
39669
|
widget: NumberLine,
|
|
39759
39670
|
transform: numberLineTransform,
|
|
39760
|
-
staticTransform: staticTransform$1
|
|
39761
|
-
getPublicWidgetOptions: perseusCore.getNumberLinePublicWidgetOptions
|
|
39671
|
+
staticTransform: staticTransform$1
|
|
39762
39672
|
};
|
|
39763
39673
|
|
|
39764
39674
|
const getPromptJSON$5 = (renderProps, userInput) => {
|
|
@@ -39925,19 +39835,23 @@ class Card extends React__namespace.Component {
|
|
|
39925
39835
|
// Pull out the content to get rendered
|
|
39926
39836
|
const rendererProps = ___default["default"].pick(this.props, "content");
|
|
39927
39837
|
const onMouseDown = this.props.animating ? $__default["default"].noop : this.onMouseDown;
|
|
39928
|
-
return
|
|
39929
|
-
|
|
39930
|
-
|
|
39931
|
-
|
|
39932
|
-
|
|
39933
|
-
|
|
39934
|
-
|
|
39935
|
-
|
|
39936
|
-
|
|
39937
|
-
|
|
39938
|
-
|
|
39939
|
-
|
|
39940
|
-
|
|
39838
|
+
return (
|
|
39839
|
+
/*#__PURE__*/
|
|
39840
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions -- TODO(LEMS-2871): Address a11y error
|
|
39841
|
+
React__namespace.createElement("div", {
|
|
39842
|
+
className: "card-wrap",
|
|
39843
|
+
style: style,
|
|
39844
|
+
onMouseDown: onMouseDown,
|
|
39845
|
+
onTouchStart: onMouseDown,
|
|
39846
|
+
onTouchEnd: this.onMouseUp,
|
|
39847
|
+
onTouchCancel: this.onMouseUp
|
|
39848
|
+
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
39849
|
+
className: className.join(" ")
|
|
39850
|
+
}, /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, rendererProps, {
|
|
39851
|
+
linterContext: this.props.linterContext,
|
|
39852
|
+
strings: this.context.strings
|
|
39853
|
+
}))))
|
|
39854
|
+
);
|
|
39941
39855
|
}
|
|
39942
39856
|
}
|
|
39943
39857
|
class Orderer extends React__namespace.Component {
|
|
@@ -40309,8 +40223,7 @@ var Orderer$1 = {
|
|
|
40309
40223
|
displayName: "Orderer",
|
|
40310
40224
|
hidden: true,
|
|
40311
40225
|
widget: Orderer,
|
|
40312
|
-
isLintable: true
|
|
40313
|
-
getPublicWidgetOptions: perseusCore.getOrdererPublicWidgetOptions
|
|
40226
|
+
isLintable: true
|
|
40314
40227
|
};
|
|
40315
40228
|
|
|
40316
40229
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -41376,8 +41289,7 @@ var Plotter$1 = {
|
|
|
41376
41289
|
displayName: "Plotter",
|
|
41377
41290
|
hidden: true,
|
|
41378
41291
|
widget: Plotter,
|
|
41379
|
-
staticTransform: staticTransform
|
|
41380
|
-
getPublicWidgetOptions: perseusCore.getPlotterPublicWidgetOptions
|
|
41292
|
+
staticTransform: staticTransform
|
|
41381
41293
|
};
|
|
41382
41294
|
|
|
41383
41295
|
const getPromptJSON$2 = () => {
|
|
@@ -41454,9 +41366,6 @@ const getPromptJSON$1 = userInput => {
|
|
|
41454
41366
|
};
|
|
41455
41367
|
};
|
|
41456
41368
|
|
|
41457
|
-
const {
|
|
41458
|
-
shuffle
|
|
41459
|
-
} = Util;
|
|
41460
41369
|
class Sorter extends React__namespace.Component {
|
|
41461
41370
|
_isMounted = false;
|
|
41462
41371
|
static defaultProps = {
|
|
@@ -41513,7 +41422,11 @@ class Sorter extends React__namespace.Component {
|
|
|
41513
41422
|
this.refs.sortable.moveOptionToIndex(option, index);
|
|
41514
41423
|
};
|
|
41515
41424
|
render() {
|
|
41516
|
-
|
|
41425
|
+
// TODO(LEMS-2841): Remove client-side shuffle once receiving public
|
|
41426
|
+
// options. The correct field will already be shuffled.
|
|
41427
|
+
// Probably easiest to replace "options" with "this.props.correct" when
|
|
41428
|
+
// setting up Sortable below. Or use the assignment to rename for clarity.
|
|
41429
|
+
const options = perseusCore.shuffle(this.props.correct, this.props.problemNum, /* ensurePermuted */true);
|
|
41517
41430
|
const {
|
|
41518
41431
|
apiOptions
|
|
41519
41432
|
} = this.props;
|
|
@@ -41537,8 +41450,7 @@ var Sorter$1 = {
|
|
|
41537
41450
|
name: "sorter",
|
|
41538
41451
|
displayName: "Sorter",
|
|
41539
41452
|
widget: Sorter,
|
|
41540
|
-
isLintable: true
|
|
41541
|
-
getPublicWidgetOptions: perseusCore.getSorterPublicWidgetOptions
|
|
41453
|
+
isLintable: true
|
|
41542
41454
|
};
|
|
41543
41455
|
|
|
41544
41456
|
const {
|
|
@@ -41754,8 +41666,7 @@ var Table$1 = {
|
|
|
41754
41666
|
widget: Table,
|
|
41755
41667
|
transform: propTransform,
|
|
41756
41668
|
hidden: true,
|
|
41757
|
-
isLintable: true
|
|
41758
|
-
getPublicWidgetOptions: perseusCore.getTablePublicWidgetOptions
|
|
41669
|
+
isLintable: true
|
|
41759
41670
|
};
|
|
41760
41671
|
|
|
41761
41672
|
const getPromptJSON = () => {
|
|
@@ -41936,7 +41847,7 @@ const init = function () {
|
|
|
41936
41847
|
|
|
41937
41848
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
41938
41849
|
const libName = "@khanacademy/perseus";
|
|
41939
|
-
const libVersion = "
|
|
41850
|
+
const libVersion = "54.1.0";
|
|
41940
41851
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
41941
41852
|
|
|
41942
41853
|
const apiVersion = {
|
|
@@ -43430,6 +43341,17 @@ function getWidgetTypeByWidgetId(WidgetId, widgetMap) {
|
|
|
43430
43341
|
const widget = widgetMap[WidgetId];
|
|
43431
43342
|
return widget?.type ?? null;
|
|
43432
43343
|
}
|
|
43344
|
+
function getWidgetSubTypeByWidgetId(widgetId, widgetMap) {
|
|
43345
|
+
const widget = widgetMap[widgetId];
|
|
43346
|
+
const widgetType = widget?.type ?? null;
|
|
43347
|
+
switch (widgetType) {
|
|
43348
|
+
case "interactive-graph":
|
|
43349
|
+
const graph = widget.options.graph;
|
|
43350
|
+
return graph?.type ?? null;
|
|
43351
|
+
default:
|
|
43352
|
+
return null;
|
|
43353
|
+
}
|
|
43354
|
+
}
|
|
43433
43355
|
|
|
43434
43356
|
/**
|
|
43435
43357
|
* Does the content have a specific type of widget?
|
|
@@ -44308,6 +44230,7 @@ exports.getSegmentCoords = getSegmentCoords;
|
|
|
44308
44230
|
exports.getSinusoidCoords = getSinusoidCoords;
|
|
44309
44231
|
exports.getValidWidgetIds = getValidWidgetIds;
|
|
44310
44232
|
exports.getWidgetFromWidgetMap = getWidgetFromWidgetMap;
|
|
44233
|
+
exports.getWidgetSubTypeByWidgetId = getWidgetSubTypeByWidgetId;
|
|
44311
44234
|
exports.getWidgetTypeByWidgetId = getWidgetTypeByWidgetId;
|
|
44312
44235
|
exports.getWidgetsFromWidgetMap = getWidgetsFromWidgetMap;
|
|
44313
44236
|
exports.getWidgetsMapFromItemData = getWidgetsMapFromItemData;
|