@khanacademy/perseus 53.1.0 → 54.0.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 +603 -1867
- 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 +678 -691
- 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 +3 -12
- package/dist/util/graphie.d.ts +1 -1
- 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 -4
- 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) {
|
|
@@ -16010,12 +16069,17 @@ class ImageLoader extends React__namespace.Component {
|
|
|
16010
16069
|
};
|
|
16011
16070
|
}
|
|
16012
16071
|
const staticUrl = getDependencies().staticUrl;
|
|
16013
|
-
return
|
|
16014
|
-
|
|
16015
|
-
|
|
16016
|
-
|
|
16017
|
-
|
|
16018
|
-
|
|
16072
|
+
return (
|
|
16073
|
+
/*#__PURE__*/
|
|
16074
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- TODO(LEMS-2871): Address a11y error
|
|
16075
|
+
React__namespace.createElement("img", _extends({
|
|
16076
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- TODO(LEMS-2871): Address a11y error
|
|
16077
|
+
tabIndex: 0,
|
|
16078
|
+
src: staticUrl(src),
|
|
16079
|
+
onKeyUp: onKeyUp,
|
|
16080
|
+
onKeyDown: onKeyDown
|
|
16081
|
+
}, imgProps))
|
|
16082
|
+
);
|
|
16019
16083
|
};
|
|
16020
16084
|
render() {
|
|
16021
16085
|
switch (this.state.status) {
|
|
@@ -16689,16 +16753,20 @@ class Zoomable extends React__namespace.Component {
|
|
|
16689
16753
|
WebkitTapHighlightColor: "transparent",
|
|
16690
16754
|
...transitionStyle
|
|
16691
16755
|
};
|
|
16692
|
-
return
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16756
|
+
return (
|
|
16757
|
+
/*#__PURE__*/
|
|
16758
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events -- TODO(LEMS-2871): Address a11y error
|
|
16759
|
+
React__namespace.createElement("span", {
|
|
16760
|
+
onClick: this.handleClick,
|
|
16761
|
+
onClickCapture: this.handleClickIfZoomed,
|
|
16762
|
+
onTouchCancelCapture: this.stopPropagationIfZoomed,
|
|
16763
|
+
onTouchEndCapture: this.stopPropagationIfZoomed,
|
|
16764
|
+
onTouchStartCapture: this.stopPropagationIfZoomed
|
|
16765
|
+
// @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'.
|
|
16766
|
+
,
|
|
16767
|
+
style: style
|
|
16768
|
+
}, this.props.children)
|
|
16769
|
+
);
|
|
16702
16770
|
}
|
|
16703
16771
|
}
|
|
16704
16772
|
|
|
@@ -17921,9 +17989,6 @@ const getWidget = name => {
|
|
|
17921
17989
|
const getWidgetExport = name => {
|
|
17922
17990
|
return widgets[name] ?? null;
|
|
17923
17991
|
};
|
|
17924
|
-
const getPublicWidgetOptionsFunction = name => {
|
|
17925
|
-
return widgets[name]?.getPublicWidgetOptions ?? (i => i);
|
|
17926
|
-
};
|
|
17927
17992
|
const getEditor = name => {
|
|
17928
17993
|
return ___default["default"].has(editors, name) ? editors[name] : null;
|
|
17929
17994
|
};
|
|
@@ -18060,7 +18125,6 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
18060
18125
|
replaceDeprecatedEditors: replaceDeprecatedEditors,
|
|
18061
18126
|
getWidget: getWidget,
|
|
18062
18127
|
getWidgetExport: getWidgetExport,
|
|
18063
|
-
getPublicWidgetOptionsFunction: getPublicWidgetOptionsFunction,
|
|
18064
18128
|
getEditor: getEditor,
|
|
18065
18129
|
getTransform: getTransform,
|
|
18066
18130
|
getVersion: getVersion,
|
|
@@ -18136,6 +18200,7 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18136
18200
|
"perseus-widget__definition": this.props.type === "definition"
|
|
18137
18201
|
});
|
|
18138
18202
|
const type = this.props.type;
|
|
18203
|
+
const userAgent = navigator.userAgent;
|
|
18139
18204
|
const WidgetType = getWidget(type);
|
|
18140
18205
|
if (WidgetType == null) {
|
|
18141
18206
|
// This is for the good of all people!!
|
|
@@ -18146,6 +18211,11 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18146
18211
|
className: className
|
|
18147
18212
|
});
|
|
18148
18213
|
}
|
|
18214
|
+
let subType = "null";
|
|
18215
|
+
if (type === "interactive-graph") {
|
|
18216
|
+
const props = this.state.widgetProps;
|
|
18217
|
+
subType = props.graph?.type ?? "null";
|
|
18218
|
+
}
|
|
18149
18219
|
let alignment = this.state.widgetProps.alignment;
|
|
18150
18220
|
if (alignment === "default") {
|
|
18151
18221
|
alignment = perseusCore.CoreWidgetRegistry.getDefaultAlignment(type);
|
|
@@ -18202,12 +18272,26 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18202
18272
|
widget_type: type,
|
|
18203
18273
|
widget_id: this.props.id
|
|
18204
18274
|
},
|
|
18205
|
-
onError:
|
|
18275
|
+
onError: error => {
|
|
18276
|
+
// TODO(LEMS-2826): Remove analytics event in LEMS-2826 in favor of ti below.
|
|
18206
18277
|
analytics.onAnalyticsEvent({
|
|
18207
18278
|
type: "perseus:widget-rendering-error",
|
|
18208
18279
|
payload: {
|
|
18280
|
+
widgetSubType: subType,
|
|
18209
18281
|
widgetType: type,
|
|
18210
|
-
widgetId: this.props.id
|
|
18282
|
+
widgetId: this.props.id,
|
|
18283
|
+
message: error.message,
|
|
18284
|
+
userAgent: userAgent
|
|
18285
|
+
}
|
|
18286
|
+
});
|
|
18287
|
+
analytics.onAnalyticsEvent({
|
|
18288
|
+
type: "perseus:widget-rendering-error:ti",
|
|
18289
|
+
payload: {
|
|
18290
|
+
widgetSubType: subType,
|
|
18291
|
+
widgetType: type,
|
|
18292
|
+
widgetId: this.props.id,
|
|
18293
|
+
message: error.message,
|
|
18294
|
+
userAgent: userAgent
|
|
18211
18295
|
}
|
|
18212
18296
|
});
|
|
18213
18297
|
}
|
|
@@ -20650,7 +20734,6 @@ var NumericInput$1 = {
|
|
|
20650
20734
|
widget: NumericInput,
|
|
20651
20735
|
transform: propsTransform,
|
|
20652
20736
|
isLintable: true,
|
|
20653
|
-
getPublicWidgetOptions: perseusCore.getNumericInputPublicWidgetOptions,
|
|
20654
20737
|
// TODO(LEMS-2656): remove TS suppression
|
|
20655
20738
|
// @ts-expect-error: Type 'Rubric' is not assignable to type 'PerseusNumericInputRubric'
|
|
20656
20739
|
getOneCorrectAnswerFromRubric(rubric) {
|
|
@@ -21457,7 +21540,10 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
21457
21540
|
// using div instead of TooltipContent because
|
|
21458
21541
|
// TooltipContent wouldn't let me overwrite
|
|
21459
21542
|
// user-select and onClick
|
|
21460
|
-
const content =
|
|
21543
|
+
const content =
|
|
21544
|
+
/*#__PURE__*/
|
|
21545
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events -- TODO(LEMS-2871): Address a11y error
|
|
21546
|
+
React__namespace.createElement("div", {
|
|
21461
21547
|
className: aphrodite.css(styles$x.tooltipLabel),
|
|
21462
21548
|
onClick: this.props.onClick
|
|
21463
21549
|
}, this.props.label);
|
|
@@ -21468,14 +21554,18 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
21468
21554
|
top: `calc(${Math.round(focusRect.top)}px + 0.95em)`,
|
|
21469
21555
|
height: 0
|
|
21470
21556
|
};
|
|
21471
|
-
return
|
|
21472
|
-
|
|
21473
|
-
|
|
21474
|
-
|
|
21475
|
-
|
|
21476
|
-
|
|
21477
|
-
|
|
21478
|
-
|
|
21557
|
+
return (
|
|
21558
|
+
/*#__PURE__*/
|
|
21559
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions -- TODO(LEMS-2871): Address a11y error
|
|
21560
|
+
React__namespace.createElement("div", {
|
|
21561
|
+
style: style,
|
|
21562
|
+
onMouseEnter: this.props.onMouseEnter,
|
|
21563
|
+
onMouseLeave: this.props.onMouseLeave
|
|
21564
|
+
}, /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
21565
|
+
content: content,
|
|
21566
|
+
opened: true
|
|
21567
|
+
}, /*#__PURE__*/React__namespace.createElement("div", null)))
|
|
21568
|
+
);
|
|
21479
21569
|
}
|
|
21480
21570
|
}
|
|
21481
21571
|
const styles$x = aphrodite.StyleSheet.create({
|
|
@@ -24192,15 +24282,19 @@ const BaseRadio = function (_ref) {
|
|
|
24192
24282
|
// content somehow? Would changing our choice of key
|
|
24193
24283
|
// somehow break something happening inside a choice's
|
|
24194
24284
|
// child Renderers, by changing when we mount/unmount?
|
|
24195
|
-
return
|
|
24196
|
-
|
|
24197
|
-
|
|
24198
|
-
|
|
24199
|
-
|
|
24200
|
-
|
|
24201
|
-
|
|
24202
|
-
|
|
24203
|
-
|
|
24285
|
+
return (
|
|
24286
|
+
/*#__PURE__*/
|
|
24287
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions -- TODO(LEMS-2871): Address a11y error
|
|
24288
|
+
React__namespace.createElement("li", {
|
|
24289
|
+
key: i,
|
|
24290
|
+
ref: e => listElem = e,
|
|
24291
|
+
className: className,
|
|
24292
|
+
onClick: clickHandler,
|
|
24293
|
+
onTouchStart: labelWrap ? undefined : captureScratchpadTouchStart$1
|
|
24294
|
+
}, /*#__PURE__*/React__namespace.createElement(Element, _extends({}, elementProps, {
|
|
24295
|
+
ref: ref
|
|
24296
|
+
})))
|
|
24297
|
+
);
|
|
24204
24298
|
})));
|
|
24205
24299
|
|
|
24206
24300
|
// Allow for horizontal scrolling if content is too wide, which may be
|
|
@@ -24745,8 +24839,7 @@ var Radio = {
|
|
|
24745
24839
|
staticTransform: transform,
|
|
24746
24840
|
version: perseusCore.radioLogic.version,
|
|
24747
24841
|
propUpgrades: perseusCore.radioLogic.widgetOptionsUpgrades,
|
|
24748
|
-
isLintable: true
|
|
24749
|
-
getPublicWidgetOptions: perseusCore.getRadioPublicWidgetOptions
|
|
24842
|
+
isLintable: true
|
|
24750
24843
|
};
|
|
24751
24844
|
|
|
24752
24845
|
/* eslint-disable import/no-named-as-default */
|
|
@@ -25035,8 +25128,7 @@ var Categorizer$1 = {
|
|
|
25035
25128
|
staticTransform: editorProps => {
|
|
25036
25129
|
return ___default["default"].pick(editorProps, "items", "categories", "values", "randomizeItems");
|
|
25037
25130
|
},
|
|
25038
|
-
isLintable: true
|
|
25039
|
-
getPublicWidgetOptions: perseusCore.getCategorizerPublicWidgetOptions
|
|
25131
|
+
isLintable: true
|
|
25040
25132
|
};
|
|
25041
25133
|
|
|
25042
25134
|
/**
|
|
@@ -25246,8 +25338,7 @@ var CSProgram$1 = {
|
|
|
25246
25338
|
name: "cs-program",
|
|
25247
25339
|
displayName: "CS Program",
|
|
25248
25340
|
widget: CSProgram,
|
|
25249
|
-
hidden: true
|
|
25250
|
-
getPublicWidgetOptions: perseusCore.getCSProgramPublicWidgetOptions
|
|
25341
|
+
hidden: true
|
|
25251
25342
|
};
|
|
25252
25343
|
|
|
25253
25344
|
const getPromptJSON$l = renderProps => {
|
|
@@ -25463,8 +25554,7 @@ var Dropdown$1 = {
|
|
|
25463
25554
|
displayName: "Drop down",
|
|
25464
25555
|
accessible: true,
|
|
25465
25556
|
widget: Dropdown,
|
|
25466
|
-
transform: optionsTransform
|
|
25467
|
-
getPublicWidgetOptions: perseusCore.getDropdownPublicWidgetOptions
|
|
25557
|
+
transform: optionsTransform
|
|
25468
25558
|
};
|
|
25469
25559
|
|
|
25470
25560
|
const getPromptJSON$j = renderProps => {
|
|
@@ -26956,8 +27046,7 @@ var Grapher$1 = {
|
|
|
26956
27046
|
hidden: true,
|
|
26957
27047
|
widget: Grapher,
|
|
26958
27048
|
transform: propTransform$2,
|
|
26959
|
-
staticTransform: staticTransform$4
|
|
26960
|
-
getPublicWidgetOptions: perseusCore.getGrapherPublicWidgetOptions
|
|
27049
|
+
staticTransform: staticTransform$4
|
|
26961
27050
|
};
|
|
26962
27051
|
|
|
26963
27052
|
const getPromptJSON$f = rendererJSON => {
|
|
@@ -27251,12 +27340,16 @@ class Iframe extends React__namespace.Component {
|
|
|
27251
27340
|
// that we need. This makes it a bit safer in case some content
|
|
27252
27341
|
// creator "went wild".
|
|
27253
27342
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
27254
|
-
return
|
|
27255
|
-
|
|
27256
|
-
|
|
27257
|
-
|
|
27258
|
-
|
|
27259
|
-
|
|
27343
|
+
return (
|
|
27344
|
+
/*#__PURE__*/
|
|
27345
|
+
// eslint-disable-next-line jsx-a11y/iframe-has-title -- TODO(LEMS-2871): Address a11y error
|
|
27346
|
+
React__namespace.createElement("iframe", {
|
|
27347
|
+
sandbox: sandboxProperties,
|
|
27348
|
+
style: style,
|
|
27349
|
+
src: url,
|
|
27350
|
+
allowFullScreen: this.props.allowFullScreen
|
|
27351
|
+
})
|
|
27352
|
+
);
|
|
27260
27353
|
}
|
|
27261
27354
|
}
|
|
27262
27355
|
var Iframe$1 = {
|
|
@@ -27264,8 +27357,7 @@ var Iframe$1 = {
|
|
|
27264
27357
|
displayName: "Iframe (deprecated)",
|
|
27265
27358
|
widget: Iframe,
|
|
27266
27359
|
// Let's not expose it to all content creators yet
|
|
27267
|
-
hidden: true
|
|
27268
|
-
getPublicWidgetOptions: perseusCore.getIFramePublicWidgetOptions
|
|
27360
|
+
hidden: true
|
|
27269
27361
|
};
|
|
27270
27362
|
|
|
27271
27363
|
const getPromptJSON$d = renderProps => {
|
|
@@ -27282,7 +27374,7 @@ const getPromptJSON$d = renderProps => {
|
|
|
27282
27374
|
|
|
27283
27375
|
const defaultBoxSize = 400;
|
|
27284
27376
|
const defaultRange = [0, 10];
|
|
27285
|
-
const defaultBackgroundImage$
|
|
27377
|
+
const defaultBackgroundImage$1 = {
|
|
27286
27378
|
url: null,
|
|
27287
27379
|
width: 0,
|
|
27288
27380
|
height: 0
|
|
@@ -27297,7 +27389,7 @@ class ImageWidget extends React__namespace.Component {
|
|
|
27297
27389
|
title: "",
|
|
27298
27390
|
range: [defaultRange, defaultRange],
|
|
27299
27391
|
box: [defaultBoxSize, defaultBoxSize],
|
|
27300
|
-
backgroundImage: defaultBackgroundImage$
|
|
27392
|
+
backgroundImage: defaultBackgroundImage$1,
|
|
27301
27393
|
labels: [],
|
|
27302
27394
|
alt: "",
|
|
27303
27395
|
caption: "",
|
|
@@ -28068,306 +28160,6 @@ var Interactive = {
|
|
|
28068
28160
|
hidden: true
|
|
28069
28161
|
};
|
|
28070
28162
|
|
|
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
28163
|
const getPromptJSON$b = (props, userInput) => {
|
|
28372
28164
|
return {
|
|
28373
28165
|
type: "interactive-graph",
|
|
@@ -28932,13 +28724,19 @@ function escapeIfUnescaped(character) {
|
|
|
28932
28724
|
}
|
|
28933
28725
|
}
|
|
28934
28726
|
|
|
28935
|
-
function AxisLabels() {
|
|
28727
|
+
function AxisLabels(_ref) {
|
|
28728
|
+
let {
|
|
28729
|
+
i18n
|
|
28730
|
+
} = _ref;
|
|
28936
28731
|
const {
|
|
28937
28732
|
range,
|
|
28938
28733
|
labels,
|
|
28939
28734
|
width,
|
|
28940
28735
|
height
|
|
28941
28736
|
} = useGraphConfig();
|
|
28737
|
+
const {
|
|
28738
|
+
strings
|
|
28739
|
+
} = i18n;
|
|
28942
28740
|
const yAxisLabelLocation = [0, range[Y][MAX]];
|
|
28943
28741
|
const xAxisLabelLocation = [range[X][MAX], 0];
|
|
28944
28742
|
const [xAxisLabelText, yAxisLabelText] = labels;
|
|
@@ -28956,6 +28754,7 @@ function AxisLabels() {
|
|
|
28956
28754
|
TeX
|
|
28957
28755
|
} = getDependencies();
|
|
28958
28756
|
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("span", {
|
|
28757
|
+
"aria-label": strings.xAxis,
|
|
28959
28758
|
style: {
|
|
28960
28759
|
position: "absolute",
|
|
28961
28760
|
left: x1,
|
|
@@ -28964,6 +28763,7 @@ function AxisLabels() {
|
|
|
28964
28763
|
transform: "translate(7px, -50%)"
|
|
28965
28764
|
}
|
|
28966
28765
|
}, /*#__PURE__*/React__default["default"].createElement(TeX, null, replaceOutsideTeX(xAxisLabelText))), /*#__PURE__*/React__default["default"].createElement("span", {
|
|
28766
|
+
"aria-label": strings.yAxis,
|
|
28967
28767
|
style: {
|
|
28968
28768
|
position: "absolute",
|
|
28969
28769
|
left: x2,
|
|
@@ -29772,7 +29572,6 @@ class RangeInput extends React__namespace.Component {
|
|
|
29772
29572
|
var components = /*#__PURE__*/Object.freeze({
|
|
29773
29573
|
__proto__: null,
|
|
29774
29574
|
ButtonGroup: ButtonGroup,
|
|
29775
|
-
Graph: Graph,
|
|
29776
29575
|
Graphie: Graphie,
|
|
29777
29576
|
HUD: HUD,
|
|
29778
29577
|
Icon: Icon,
|
|
@@ -29916,9 +29715,9 @@ const LockedFunction = props => {
|
|
|
29916
29715
|
const {
|
|
29917
29716
|
color,
|
|
29918
29717
|
strokeStyle,
|
|
29919
|
-
directionalAxis
|
|
29920
|
-
domain
|
|
29718
|
+
directionalAxis
|
|
29921
29719
|
} = props;
|
|
29720
|
+
const domain = props.domain ? [Number.isFinite(props.domain[0]) ? props.domain[0] : -Infinity, Number.isFinite(props.domain[1]) ? props.domain[1] : Infinity] : undefined;
|
|
29922
29721
|
const plotProps = {
|
|
29923
29722
|
color: perseusCore.lockedFigureColors[color],
|
|
29924
29723
|
style: strokeStyle,
|
|
@@ -29998,6 +29797,11 @@ function Vector(props) {
|
|
|
29998
29797
|
}
|
|
29999
29798
|
|
|
30000
29799
|
function srFormatNumber(a, locale, maximumFractionDigits) {
|
|
29800
|
+
const piBasedNumber = getPiMultiple(a);
|
|
29801
|
+
if (piBasedNumber) {
|
|
29802
|
+
return piBasedNumber;
|
|
29803
|
+
}
|
|
29804
|
+
|
|
30001
29805
|
// adding zero here converts negative zero to positive zero.
|
|
30002
29806
|
return (0 + a).toLocaleString(locale, {
|
|
30003
29807
|
maximumFractionDigits: maximumFractionDigits ?? 3,
|
|
@@ -30005,6 +29809,77 @@ function srFormatNumber(a, locale, maximumFractionDigits) {
|
|
|
30005
29809
|
});
|
|
30006
29810
|
}
|
|
30007
29811
|
|
|
29812
|
+
// Exported for testing
|
|
29813
|
+
function getPiMultiple(a) {
|
|
29814
|
+
// - Save some calculations by checking if this is an integer first.
|
|
29815
|
+
// If a is an integer, it's definitely not a multiple of π.
|
|
29816
|
+
// - 0 should not be presented as a multiple of π.
|
|
29817
|
+
// - If a is greater than 1e12, then it thinks that it's always a
|
|
29818
|
+
// multiple of π even when it's not, due to rounding errors.
|
|
29819
|
+
if (Number.isInteger(a) || a === 0 || a > 1e12) {
|
|
29820
|
+
return null;
|
|
29821
|
+
}
|
|
29822
|
+
|
|
29823
|
+
// Figure out the coefficient before the π.
|
|
29824
|
+
// Example: If a = π/2, then piCoefficient = 0.5
|
|
29825
|
+
// Example: If a = 2π, then piCoefficient = 2
|
|
29826
|
+
const piCoefficient = a / Math.PI;
|
|
29827
|
+
// Truncate the coefficient to account for floating point errors.
|
|
29828
|
+
// π calculations are only accurate up to precision of 1e-12.
|
|
29829
|
+
const truncatedCoefficient = parseFloat(piCoefficient.toFixed(12));
|
|
29830
|
+
|
|
29831
|
+
// If the coefficient is already an integer, then the number
|
|
29832
|
+
// is a multiple of π. Return it here.
|
|
29833
|
+
// Example: If a = 2π, then truncatedCoefficient = 2, so return "2π"
|
|
29834
|
+
if (Number.isInteger(truncatedCoefficient)) {
|
|
29835
|
+
// Return "π" rather than "1π".
|
|
29836
|
+
if (truncatedCoefficient === 1) {
|
|
29837
|
+
return "π";
|
|
29838
|
+
}
|
|
29839
|
+
|
|
29840
|
+
// Return "-π" rather than "-1π".
|
|
29841
|
+
if (truncatedCoefficient === -1) {
|
|
29842
|
+
return "-π";
|
|
29843
|
+
}
|
|
29844
|
+
return truncatedCoefficient + "π";
|
|
29845
|
+
}
|
|
29846
|
+
|
|
29847
|
+
// If the coefficient is not an integer, then we need to
|
|
29848
|
+
// check if it's a multiple of π/2, π/3, π/4, or π/6.
|
|
29849
|
+
// These are π-based values on a unit circle.
|
|
29850
|
+
const acceptableDivisors = [2, 3, 4, 6];
|
|
29851
|
+
|
|
29852
|
+
// Loop through the acceptable divisors and check if the
|
|
29853
|
+
// coefficient is a multiple of (1/divisor).
|
|
29854
|
+
// Example: If a = 5π/6, the coeff is 5/6, which is a multiple of 1/6.
|
|
29855
|
+
// So we return "5π/6".
|
|
29856
|
+
for (const divisor of acceptableDivisors) {
|
|
29857
|
+
// Check if the coefficient is a multiple of (1/divisor) by
|
|
29858
|
+
// multiplying the coefficient by the divisor and checking if
|
|
29859
|
+
// the result is an integer.
|
|
29860
|
+
// Example: If a = 5π/6, then piCoefficient = 5/6. We multiply
|
|
29861
|
+
// by 6 (divisor) to get 5, which is an integer.
|
|
29862
|
+
const coefficientNumerator = parseFloat(
|
|
29863
|
+
// π calculations are only accurate up to precision of 1e-12.
|
|
29864
|
+
(piCoefficient * divisor).toFixed(12));
|
|
29865
|
+
if (Number.isInteger(coefficientNumerator)) {
|
|
29866
|
+
// Handle the case where the coefficient numberator is just 1.
|
|
29867
|
+
// We don't want to write "π/6" as "1π/6"
|
|
29868
|
+
if (coefficientNumerator === 1) {
|
|
29869
|
+
return "π/" + divisor;
|
|
29870
|
+
}
|
|
29871
|
+
|
|
29872
|
+
// Handle the case where the coefficient numberator is just -1.
|
|
29873
|
+
// We don't want to write "π/6" as "-1π/6"
|
|
29874
|
+
if (coefficientNumerator === -1) {
|
|
29875
|
+
return "-π/" + divisor;
|
|
29876
|
+
}
|
|
29877
|
+
return coefficientNumerator + "π/" + divisor;
|
|
29878
|
+
}
|
|
29879
|
+
}
|
|
29880
|
+
return null;
|
|
29881
|
+
}
|
|
29882
|
+
|
|
30008
29883
|
/**
|
|
30009
29884
|
* Given a ray and a rectangular box, find the point where the ray intersects
|
|
30010
29885
|
* the edge of the box. Assumes the `initialPoint` is inside the box.
|
|
@@ -31172,6 +31047,34 @@ function range(min, max) {
|
|
|
31172
31047
|
return result;
|
|
31173
31048
|
}
|
|
31174
31049
|
|
|
31050
|
+
function Hairlines(props) {
|
|
31051
|
+
const {
|
|
31052
|
+
point
|
|
31053
|
+
} = props;
|
|
31054
|
+
const {
|
|
31055
|
+
range
|
|
31056
|
+
} = useGraphConfig();
|
|
31057
|
+
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
31058
|
+
const [[x, y]] = useTransformVectorsToPixels(point);
|
|
31059
|
+
const [[verticalStartX]] = useTransformVectorsToPixels([xMin, 0]);
|
|
31060
|
+
const [[verticalEndX]] = useTransformVectorsToPixels([xMax, 0]);
|
|
31061
|
+
const [[_, horizontalStartY]] = useTransformVectorsToPixels([0, yMin]);
|
|
31062
|
+
const [[__, horizontalEndY]] = useTransformVectorsToPixels([0, yMax]);
|
|
31063
|
+
return /*#__PURE__*/React__namespace.createElement("g", null, /*#__PURE__*/React__namespace.createElement("line", {
|
|
31064
|
+
x1: verticalStartX,
|
|
31065
|
+
y1: y,
|
|
31066
|
+
x2: verticalEndX,
|
|
31067
|
+
y2: y,
|
|
31068
|
+
stroke: wonderBlocksTokens.color.blue
|
|
31069
|
+
}), /*#__PURE__*/React__namespace.createElement("line", {
|
|
31070
|
+
x1: x,
|
|
31071
|
+
y1: horizontalStartY,
|
|
31072
|
+
x2: x,
|
|
31073
|
+
y2: horizontalEndY,
|
|
31074
|
+
stroke: wonderBlocksTokens.color.blue
|
|
31075
|
+
}));
|
|
31076
|
+
}
|
|
31077
|
+
|
|
31175
31078
|
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
31176
31079
|
// graph.
|
|
31177
31080
|
const hitboxSizePx = 48;
|
|
@@ -31181,7 +31084,6 @@ const hitboxSizePx = 48;
|
|
|
31181
31084
|
// on an interactive graph.
|
|
31182
31085
|
const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
31183
31086
|
const {
|
|
31184
|
-
range,
|
|
31185
31087
|
markings,
|
|
31186
31088
|
showTooltips
|
|
31187
31089
|
} = useGraphConfig();
|
|
@@ -31189,6 +31091,7 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
31189
31091
|
point,
|
|
31190
31092
|
color = wonderBlocksTokens.color.blue,
|
|
31191
31093
|
dragging,
|
|
31094
|
+
focused,
|
|
31192
31095
|
cursor,
|
|
31193
31096
|
showFocusRing,
|
|
31194
31097
|
onClick = () => {}
|
|
@@ -31202,25 +31105,7 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
31202
31105
|
})?.[0] ?? "blue";
|
|
31203
31106
|
const pointClasses = classNames("movable-point", dragging && "movable-point--dragging", showFocusRing && "movable-point--focus");
|
|
31204
31107
|
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
|
-
}));
|
|
31108
|
+
const showHairlines = (dragging || focused) && markings !== "none";
|
|
31224
31109
|
const svgForPoint = /*#__PURE__*/React__namespace.createElement("g", {
|
|
31225
31110
|
ref: hitboxRef,
|
|
31226
31111
|
className: pointClasses,
|
|
@@ -31256,7 +31141,9 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
31256
31141
|
},
|
|
31257
31142
|
"data-testid": "movable-point__center"
|
|
31258
31143
|
}));
|
|
31259
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, showHairlines &&
|
|
31144
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, showHairlines && /*#__PURE__*/React__namespace.createElement(Hairlines, {
|
|
31145
|
+
point: point
|
|
31146
|
+
}), showTooltips ? /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
31260
31147
|
autoUpdate: true,
|
|
31261
31148
|
backgroundColor: wbColorName,
|
|
31262
31149
|
content: `(${point[X]}, ${point[Y]})`,
|
|
@@ -31352,6 +31239,7 @@ function useControlPoint(params) {
|
|
|
31352
31239
|
},
|
|
31353
31240
|
point: point,
|
|
31354
31241
|
dragging: dragging,
|
|
31242
|
+
focused: focused,
|
|
31355
31243
|
color: color,
|
|
31356
31244
|
ref: visiblePointRef,
|
|
31357
31245
|
showFocusRing: focused
|
|
@@ -31569,13 +31457,13 @@ const {
|
|
|
31569
31457
|
getClockwiseAngle: getClockwiseAngle$2,
|
|
31570
31458
|
polar: polar$1
|
|
31571
31459
|
} = kmath.angles;
|
|
31572
|
-
function renderAngleGraph(state, dispatch) {
|
|
31460
|
+
function renderAngleGraph(state, dispatch, i18n) {
|
|
31573
31461
|
return {
|
|
31574
31462
|
graph: /*#__PURE__*/React__namespace.createElement(AngleGraph, {
|
|
31575
31463
|
graphState: state,
|
|
31576
31464
|
dispatch: dispatch
|
|
31577
31465
|
}),
|
|
31578
|
-
interactiveElementsDescription:
|
|
31466
|
+
interactiveElementsDescription: getAngleGraphDescription(state, i18n)
|
|
31579
31467
|
};
|
|
31580
31468
|
}
|
|
31581
31469
|
function AngleGraph(props) {
|
|
@@ -31586,6 +31474,9 @@ function AngleGraph(props) {
|
|
|
31586
31474
|
const {
|
|
31587
31475
|
graphDimensionsInPixels
|
|
31588
31476
|
} = useGraphConfig();
|
|
31477
|
+
const i18n = usePerseusI18n();
|
|
31478
|
+
const id = React__namespace.useId();
|
|
31479
|
+
const descriptionId = id + "-description";
|
|
31589
31480
|
const {
|
|
31590
31481
|
coords,
|
|
31591
31482
|
showAngles,
|
|
@@ -31635,80 +31526,106 @@ function AngleGraph(props) {
|
|
|
31635
31526
|
showAngles: showAngles || false // Whether to show the angle or not
|
|
31636
31527
|
};
|
|
31637
31528
|
|
|
31529
|
+
// Aria strings
|
|
31638
31530
|
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]);
|
|
31531
|
+
srAngleGraphAriaLabel,
|
|
31532
|
+
srAngleGraphAriaDescription,
|
|
31533
|
+
srAngleStartingSide,
|
|
31534
|
+
srAngleEndingSide,
|
|
31535
|
+
srAngleVertex
|
|
31536
|
+
} = describeAngleGraph(graphState, i18n);
|
|
31685
31537
|
|
|
31686
31538
|
// Render the lines, angle, and then movable points
|
|
31687
31539
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
31688
|
-
"aria-label":
|
|
31689
|
-
"aria-describedby":
|
|
31540
|
+
"aria-label": srAngleGraphAriaLabel,
|
|
31541
|
+
"aria-describedby": descriptionId
|
|
31690
31542
|
}, svgLines, /*#__PURE__*/React__namespace.createElement(Angle, angleParams), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31691
31543
|
point: coords[1],
|
|
31692
31544
|
sequenceNumber: 1,
|
|
31693
31545
|
constrain: p => p,
|
|
31694
31546
|
onMove: destination => dispatch(actions.angle.movePoint(1, destination)),
|
|
31695
|
-
ariaLabel:
|
|
31547
|
+
ariaLabel: srAngleVertex
|
|
31696
31548
|
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31697
31549
|
point: coords[0],
|
|
31698
31550
|
sequenceNumber: 2,
|
|
31699
31551
|
constrain: getAngleSideConstraint(coords[0], coords[1], snapDegrees || 1),
|
|
31700
31552
|
onMove: destination => dispatch(actions.angle.movePoint(0, destination)),
|
|
31701
|
-
ariaLabel:
|
|
31553
|
+
ariaLabel: srAngleEndingSide
|
|
31702
31554
|
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31703
31555
|
point: coords[2],
|
|
31704
31556
|
sequenceNumber: 3,
|
|
31705
31557
|
constrain: getAngleSideConstraint(coords[2], coords[1], snapDegrees || 1),
|
|
31706
31558
|
onMove: destination => dispatch(actions.angle.movePoint(2, destination)),
|
|
31707
|
-
ariaLabel:
|
|
31559
|
+
ariaLabel: srAngleStartingSide
|
|
31708
31560
|
}), /*#__PURE__*/React__namespace.createElement("g", {
|
|
31709
|
-
id:
|
|
31561
|
+
id: descriptionId,
|
|
31710
31562
|
style: a11y.srOnly
|
|
31711
|
-
},
|
|
31563
|
+
}, srAngleGraphAriaDescription));
|
|
31564
|
+
}
|
|
31565
|
+
function getAngleGraphDescription(state, i18n) {
|
|
31566
|
+
const {
|
|
31567
|
+
strings,
|
|
31568
|
+
locale
|
|
31569
|
+
} = i18n;
|
|
31570
|
+
const {
|
|
31571
|
+
coords
|
|
31572
|
+
} = state;
|
|
31573
|
+
return strings.srInteractiveElements({
|
|
31574
|
+
elements: strings.srAngleInteractiveElements({
|
|
31575
|
+
vertexX: srFormatNumber(coords[1][X], locale),
|
|
31576
|
+
vertexY: srFormatNumber(coords[1][Y], locale),
|
|
31577
|
+
startingSideX: srFormatNumber(coords[2][X], locale),
|
|
31578
|
+
startingSideY: srFormatNumber(coords[2][Y], locale),
|
|
31579
|
+
endingSideX: srFormatNumber(coords[0][X], locale),
|
|
31580
|
+
endingSideY: srFormatNumber(coords[0][Y], locale)
|
|
31581
|
+
})
|
|
31582
|
+
});
|
|
31583
|
+
}
|
|
31584
|
+
function describeAngleGraph(state, i18n) {
|
|
31585
|
+
const {
|
|
31586
|
+
strings,
|
|
31587
|
+
locale
|
|
31588
|
+
} = i18n;
|
|
31589
|
+
const {
|
|
31590
|
+
coords,
|
|
31591
|
+
allowReflexAngles,
|
|
31592
|
+
showAngles
|
|
31593
|
+
} = state;
|
|
31594
|
+
const [endingSide, vertex, startingSide] = coords;
|
|
31595
|
+
const angleMeasure = srFormatNumber(getClockwiseAngle$2(coords, allowReflexAngles), locale);
|
|
31596
|
+
const srAngleGraphAriaLabel = strings.srAngleGraphAriaLabel;
|
|
31597
|
+
const srAngleGraphAriaDescription = strings.srAngleGraphAriaDescription({
|
|
31598
|
+
angleMeasure,
|
|
31599
|
+
vertexX: srFormatNumber(vertex[X], locale),
|
|
31600
|
+
vertexY: srFormatNumber(vertex[Y], locale),
|
|
31601
|
+
startingSideX: srFormatNumber(startingSide[X], locale),
|
|
31602
|
+
startingSideY: srFormatNumber(startingSide[Y], locale),
|
|
31603
|
+
endingSideX: srFormatNumber(endingSide[X], locale),
|
|
31604
|
+
endingSideY: srFormatNumber(endingSide[Y], locale)
|
|
31605
|
+
});
|
|
31606
|
+
const srAngleStartingSide = strings.srAngleStartingSide({
|
|
31607
|
+
x: srFormatNumber(startingSide[X], locale),
|
|
31608
|
+
y: srFormatNumber(startingSide[Y], locale)
|
|
31609
|
+
});
|
|
31610
|
+
const srAngleEndingSide = strings.srAngleEndingSide({
|
|
31611
|
+
x: srFormatNumber(endingSide[X], locale),
|
|
31612
|
+
y: srFormatNumber(endingSide[Y], locale)
|
|
31613
|
+
});
|
|
31614
|
+
const srAngleVertex = showAngles ? strings.srAngleVertexWithAngleMeasure({
|
|
31615
|
+
x: srFormatNumber(vertex[X], locale),
|
|
31616
|
+
y: srFormatNumber(vertex[Y], locale),
|
|
31617
|
+
angleMeasure
|
|
31618
|
+
}) : strings.srAngleVertex({
|
|
31619
|
+
x: srFormatNumber(vertex[X], locale),
|
|
31620
|
+
y: srFormatNumber(vertex[Y], locale)
|
|
31621
|
+
});
|
|
31622
|
+
return {
|
|
31623
|
+
srAngleGraphAriaLabel,
|
|
31624
|
+
srAngleGraphAriaDescription,
|
|
31625
|
+
srAngleStartingSide,
|
|
31626
|
+
srAngleEndingSide,
|
|
31627
|
+
srAngleVertex
|
|
31628
|
+
};
|
|
31712
31629
|
}
|
|
31713
31630
|
const positiveX = [1, 0];
|
|
31714
31631
|
const negativeX = [-1, 0];
|
|
@@ -31852,17 +31769,16 @@ function getRadius(graph) {
|
|
|
31852
31769
|
return Math.sqrt(Math.pow(edgeX - centerX, 2) + Math.pow(edgeY - centerY, 2));
|
|
31853
31770
|
}
|
|
31854
31771
|
|
|
31855
|
-
function renderCircleGraph(state, dispatch) {
|
|
31772
|
+
function renderCircleGraph(state, dispatch, i18n) {
|
|
31856
31773
|
return {
|
|
31857
31774
|
graph: /*#__PURE__*/React__namespace.createElement(CircleGraph, {
|
|
31858
31775
|
graphState: state,
|
|
31859
31776
|
dispatch: dispatch
|
|
31860
31777
|
}),
|
|
31861
|
-
interactiveElementsDescription:
|
|
31862
|
-
state: state
|
|
31863
|
-
})
|
|
31778
|
+
interactiveElementsDescription: getCircleGraphDescription(state, i18n)
|
|
31864
31779
|
};
|
|
31865
31780
|
}
|
|
31781
|
+
// Exported for testing
|
|
31866
31782
|
function CircleGraph(props) {
|
|
31867
31783
|
const {
|
|
31868
31784
|
dispatch,
|
|
@@ -31955,6 +31871,7 @@ function MovableCircle(props) {
|
|
|
31955
31871
|
snapStep,
|
|
31956
31872
|
disableKeyboardInteraction
|
|
31957
31873
|
} = useGraphConfig();
|
|
31874
|
+
const [focused, setFocused] = React__namespace.useState(false);
|
|
31958
31875
|
const draggableRef = React.useRef(null);
|
|
31959
31876
|
const {
|
|
31960
31877
|
dragging
|
|
@@ -31973,7 +31890,9 @@ function MovableCircle(props) {
|
|
|
31973
31890
|
ref: draggableRef,
|
|
31974
31891
|
role: "button",
|
|
31975
31892
|
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
31976
|
-
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}
|
|
31893
|
+
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`,
|
|
31894
|
+
onFocus: () => setFocused(true),
|
|
31895
|
+
onBlur: () => setFocused(false)
|
|
31977
31896
|
}, /*#__PURE__*/React__namespace.createElement("ellipse", {
|
|
31978
31897
|
className: "focus-ring",
|
|
31979
31898
|
cx: centerPx[X],
|
|
@@ -31988,19 +31907,29 @@ function MovableCircle(props) {
|
|
|
31988
31907
|
rx: radiiPx[X],
|
|
31989
31908
|
ry: radiiPx[Y]
|
|
31990
31909
|
}), /*#__PURE__*/React__namespace.createElement(DragHandle, {
|
|
31991
|
-
center: center
|
|
31910
|
+
center: center,
|
|
31911
|
+
dragging: dragging,
|
|
31912
|
+
focused: focused
|
|
31992
31913
|
}));
|
|
31993
31914
|
}
|
|
31994
31915
|
const dragHandleDimensions = [24, 14];
|
|
31995
31916
|
const dragHandleDotPositions = crossProduct([-4.4, 0, 4.4], [-2.1, 2.1]);
|
|
31996
31917
|
function DragHandle(props) {
|
|
31997
31918
|
const {
|
|
31998
|
-
center
|
|
31919
|
+
center,
|
|
31920
|
+
dragging,
|
|
31921
|
+
focused
|
|
31999
31922
|
} = props;
|
|
32000
|
-
const cornerRadius = Math.min(...dragHandleDimensions) / 2;
|
|
32001
31923
|
const [centerPx] = useTransformVectorsToPixels(center);
|
|
31924
|
+
const {
|
|
31925
|
+
markings
|
|
31926
|
+
} = useGraphConfig();
|
|
31927
|
+
const cornerRadius = Math.min(...dragHandleDimensions) / 2;
|
|
32002
31928
|
const topLeft = mafs.vec.sub(centerPx, mafs.vec.scale(dragHandleDimensions, 0.5));
|
|
32003
|
-
|
|
31929
|
+
const showHairlines = (dragging || focused) && markings !== "none";
|
|
31930
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, showHairlines && /*#__PURE__*/React__namespace.createElement(Hairlines, {
|
|
31931
|
+
point: center
|
|
31932
|
+
}), /*#__PURE__*/React__namespace.createElement("rect", {
|
|
32004
31933
|
className: "movable-circle-handle",
|
|
32005
31934
|
x: topLeft[X],
|
|
32006
31935
|
y: topLeft[Y],
|
|
@@ -32027,14 +31956,7 @@ function crossProduct(as, bs) {
|
|
|
32027
31956
|
}
|
|
32028
31957
|
return result;
|
|
32029
31958
|
}
|
|
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();
|
|
31959
|
+
function getCircleGraphDescription(state, i18n) {
|
|
32038
31960
|
const strings = describeCircleGraph(state, i18n);
|
|
32039
31961
|
return strings.srCircleInteractiveElement;
|
|
32040
31962
|
}
|
|
@@ -32087,15 +32009,13 @@ function describeCircleGraph(state, i18n) {
|
|
|
32087
32009
|
};
|
|
32088
32010
|
}
|
|
32089
32011
|
|
|
32090
|
-
function renderLinearGraph(state, dispatch) {
|
|
32012
|
+
function renderLinearGraph(state, dispatch, i18n) {
|
|
32091
32013
|
return {
|
|
32092
32014
|
graph: /*#__PURE__*/React__namespace.createElement(LinearGraph, {
|
|
32093
32015
|
graphState: state,
|
|
32094
32016
|
dispatch: dispatch
|
|
32095
32017
|
}),
|
|
32096
|
-
interactiveElementsDescription:
|
|
32097
|
-
state: state
|
|
32098
|
-
})
|
|
32018
|
+
interactiveElementsDescription: getLinearGraphDescription(state, i18n)
|
|
32099
32019
|
};
|
|
32100
32020
|
}
|
|
32101
32021
|
const LinearGraph = (props, key) => {
|
|
@@ -32160,14 +32080,7 @@ const LinearGraph = (props, key) => {
|
|
|
32160
32080
|
style: a11y.srOnly
|
|
32161
32081
|
}, slopeString));
|
|
32162
32082
|
};
|
|
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();
|
|
32083
|
+
function getLinearGraphDescription(state, i18n) {
|
|
32171
32084
|
const strings = describeLinearGraph(state, i18n);
|
|
32172
32085
|
return strings.srLinearInteractiveElement;
|
|
32173
32086
|
}
|
|
@@ -32211,15 +32124,13 @@ function describeLinearGraph(state, i18n) {
|
|
|
32211
32124
|
};
|
|
32212
32125
|
}
|
|
32213
32126
|
|
|
32214
|
-
function renderLinearSystemGraph(state, dispatch) {
|
|
32127
|
+
function renderLinearSystemGraph(state, dispatch, i18n) {
|
|
32215
32128
|
return {
|
|
32216
32129
|
graph: /*#__PURE__*/React__namespace.createElement(LinearSystemGraph, {
|
|
32217
32130
|
graphState: state,
|
|
32218
32131
|
dispatch: dispatch
|
|
32219
32132
|
}),
|
|
32220
|
-
interactiveElementsDescription:
|
|
32221
|
-
state: state
|
|
32222
|
-
})
|
|
32133
|
+
interactiveElementsDescription: getLinearSystemGraphDescription(state, i18n)
|
|
32223
32134
|
};
|
|
32224
32135
|
}
|
|
32225
32136
|
const LinearSystemGraph = props => {
|
|
@@ -32312,19 +32223,9 @@ const LinearSystemGraph = props => {
|
|
|
32312
32223
|
}, slopeDescription));
|
|
32313
32224
|
}));
|
|
32314
32225
|
};
|
|
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
32226
|
|
|
32326
32227
|
// Exported for testing
|
|
32327
|
-
function
|
|
32228
|
+
function getLinearSystemGraphDescription(state, i18n) {
|
|
32328
32229
|
const {
|
|
32329
32230
|
strings,
|
|
32330
32231
|
locale
|
|
@@ -32350,15 +32251,13 @@ function describeLinearSystemGraph(state, i18n) {
|
|
|
32350
32251
|
});
|
|
32351
32252
|
}
|
|
32352
32253
|
|
|
32353
|
-
function renderPointGraph(state, dispatch) {
|
|
32254
|
+
function renderPointGraph(state, dispatch, i18n) {
|
|
32354
32255
|
return {
|
|
32355
32256
|
graph: /*#__PURE__*/React__namespace.createElement(PointGraph, {
|
|
32356
32257
|
graphState: state,
|
|
32357
32258
|
dispatch: dispatch
|
|
32358
32259
|
}),
|
|
32359
|
-
interactiveElementsDescription:
|
|
32360
|
-
state: state
|
|
32361
|
-
})
|
|
32260
|
+
interactiveElementsDescription: getPointGraphDescription(state, i18n)
|
|
32362
32261
|
};
|
|
32363
32262
|
}
|
|
32364
32263
|
function PointGraph(props) {
|
|
@@ -32380,7 +32279,9 @@ function PointGraph(props) {
|
|
|
32380
32279
|
if (focusedIndex != null) {
|
|
32381
32280
|
pointsRef.current[focusedIndex]?.focus();
|
|
32382
32281
|
}
|
|
32383
|
-
}, [props.graphState.focusedPointIndex,
|
|
32282
|
+
}, [props.graphState.focusedPointIndex,
|
|
32283
|
+
// Ensure that we re-focus if a point is deleted.
|
|
32284
|
+
props.graphState.coords.length, pointsRef]);
|
|
32384
32285
|
const statefulProps = {
|
|
32385
32286
|
...props,
|
|
32386
32287
|
graphConfig,
|
|
@@ -32452,18 +32353,9 @@ function UnlimitedPointGraph(statefulProps) {
|
|
|
32452
32353
|
}
|
|
32453
32354
|
})));
|
|
32454
32355
|
}
|
|
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
32356
|
|
|
32465
32357
|
// Exported for testing
|
|
32466
|
-
function
|
|
32358
|
+
function getPointGraphDescription(state, i18n) {
|
|
32467
32359
|
const {
|
|
32468
32360
|
strings,
|
|
32469
32361
|
locale
|
|
@@ -32471,8 +32363,8 @@ function describePointGraph(state, i18n) {
|
|
|
32471
32363
|
if (state.coords.length === 0) {
|
|
32472
32364
|
return strings.srNoInteractiveElements;
|
|
32473
32365
|
}
|
|
32474
|
-
const pointDescriptions = state.coords.map((
|
|
32475
|
-
let [x, y] =
|
|
32366
|
+
const pointDescriptions = state.coords.map((_ref, index) => {
|
|
32367
|
+
let [x, y] = _ref;
|
|
32476
32368
|
return strings.srPointAtCoordinates({
|
|
32477
32369
|
num: index + 1,
|
|
32478
32370
|
x: srFormatNumber(x, locale),
|
|
@@ -32552,7 +32444,9 @@ const PolygonGraph = props => {
|
|
|
32552
32444
|
if (focusedIndex != null) {
|
|
32553
32445
|
pointsRef.current[focusedIndex]?.focus();
|
|
32554
32446
|
}
|
|
32555
|
-
}, [props.graphState.focusedPointIndex,
|
|
32447
|
+
}, [props.graphState.focusedPointIndex,
|
|
32448
|
+
// Ensure that we re-focus if a point is deleted.
|
|
32449
|
+
props.graphState.coords.length, pointsRef]);
|
|
32556
32450
|
|
|
32557
32451
|
// If the unlimited polygon is rendered with 3 or more coordinates
|
|
32558
32452
|
// Close the polygon, but only on first render.
|
|
@@ -33135,15 +33029,13 @@ function describeQuadraticGraph(state, i18n) {
|
|
|
33135
33029
|
};
|
|
33136
33030
|
}
|
|
33137
33031
|
|
|
33138
|
-
function renderRayGraph(state, dispatch) {
|
|
33032
|
+
function renderRayGraph(state, dispatch, i18n) {
|
|
33139
33033
|
return {
|
|
33140
33034
|
graph: /*#__PURE__*/React__namespace.createElement(RayGraph, {
|
|
33141
33035
|
graphState: state,
|
|
33142
33036
|
dispatch: dispatch
|
|
33143
33037
|
}),
|
|
33144
|
-
interactiveElementsDescription:
|
|
33145
|
-
state: state
|
|
33146
|
-
})
|
|
33038
|
+
interactiveElementsDescription: getRayGraphDescription(state, i18n)
|
|
33147
33039
|
};
|
|
33148
33040
|
}
|
|
33149
33041
|
const RayGraph = props => {
|
|
@@ -33197,14 +33089,7 @@ const RayGraph = props => {
|
|
|
33197
33089
|
style: a11y.srOnly
|
|
33198
33090
|
}, srRayPoints));
|
|
33199
33091
|
};
|
|
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();
|
|
33092
|
+
function getRayGraphDescription(state, i18n) {
|
|
33208
33093
|
const strings = describeRayGraph(state, i18n);
|
|
33209
33094
|
return strings.srRayInteractiveElement;
|
|
33210
33095
|
}
|
|
@@ -33254,15 +33139,13 @@ function describeRayGraph(state, i18n) {
|
|
|
33254
33139
|
};
|
|
33255
33140
|
}
|
|
33256
33141
|
|
|
33257
|
-
function renderSegmentGraph(state, dispatch) {
|
|
33142
|
+
function renderSegmentGraph(state, dispatch, i18n) {
|
|
33258
33143
|
return {
|
|
33259
33144
|
graph: /*#__PURE__*/React__namespace.createElement(SegmentGraph, {
|
|
33260
33145
|
graphState: state,
|
|
33261
33146
|
dispatch: dispatch
|
|
33262
33147
|
}),
|
|
33263
|
-
interactiveElementsDescription:
|
|
33264
|
-
state: state
|
|
33265
|
-
})
|
|
33148
|
+
interactiveElementsDescription: getSegmentGraphDescription(state, i18n)
|
|
33266
33149
|
};
|
|
33267
33150
|
}
|
|
33268
33151
|
const SegmentGraph = _ref => {
|
|
@@ -33356,25 +33239,15 @@ const SegmentGraph = _ref => {
|
|
|
33356
33239
|
function getLengthOfSegment(segment) {
|
|
33357
33240
|
return kmath.point.distanceToPoint(...segment);
|
|
33358
33241
|
}
|
|
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
33242
|
|
|
33370
33243
|
// Exported for testing
|
|
33371
|
-
function
|
|
33244
|
+
function getSegmentGraphDescription(state, i18n) {
|
|
33372
33245
|
const {
|
|
33373
33246
|
strings,
|
|
33374
33247
|
locale
|
|
33375
33248
|
} = i18n;
|
|
33376
|
-
const segmentDescriptions = state.coords.map((
|
|
33377
|
-
let [point1, point2] =
|
|
33249
|
+
const segmentDescriptions = state.coords.map((_ref2, index) => {
|
|
33250
|
+
let [point1, point2] = _ref2;
|
|
33378
33251
|
return strings.srMultipleSegmentIndividualLabel({
|
|
33379
33252
|
point1X: srFormatNumber(point1[X], locale),
|
|
33380
33253
|
point1Y: srFormatNumber(point1[Y], locale),
|
|
@@ -33388,13 +33261,13 @@ function describeSegmentGraph(state, i18n) {
|
|
|
33388
33261
|
});
|
|
33389
33262
|
}
|
|
33390
33263
|
|
|
33391
|
-
function renderSinusoidGraph(state, dispatch) {
|
|
33264
|
+
function renderSinusoidGraph(state, dispatch, i18n) {
|
|
33392
33265
|
return {
|
|
33393
33266
|
graph: /*#__PURE__*/React__namespace.createElement(SinusoidGraph, {
|
|
33394
33267
|
graphState: state,
|
|
33395
33268
|
dispatch: dispatch
|
|
33396
33269
|
}),
|
|
33397
|
-
interactiveElementsDescription:
|
|
33270
|
+
interactiveElementsDescription: getSinusoidDescription(state, i18n)
|
|
33398
33271
|
};
|
|
33399
33272
|
}
|
|
33400
33273
|
function SinusoidGraph(props) {
|
|
@@ -33402,6 +33275,9 @@ function SinusoidGraph(props) {
|
|
|
33402
33275
|
dispatch,
|
|
33403
33276
|
graphState
|
|
33404
33277
|
} = props;
|
|
33278
|
+
const i18n = usePerseusI18n();
|
|
33279
|
+
const id = React__namespace.useId();
|
|
33280
|
+
const descriptionId = id + "-description";
|
|
33405
33281
|
|
|
33406
33282
|
// Destructure the coordinates from the graph state
|
|
33407
33283
|
// Note: The order of the coordinates is important:
|
|
@@ -33426,15 +33302,30 @@ function SinusoidGraph(props) {
|
|
|
33426
33302
|
if (coeffs !== undefined) {
|
|
33427
33303
|
coeffRef.current = coeffs;
|
|
33428
33304
|
}
|
|
33429
|
-
|
|
33305
|
+
|
|
33306
|
+
// Aria strings
|
|
33307
|
+
const {
|
|
33308
|
+
srSinusoidGraph,
|
|
33309
|
+
srSinusoidDescription,
|
|
33310
|
+
srSinusoidRootPoint,
|
|
33311
|
+
srSinusoidPeakPoint
|
|
33312
|
+
} = describeSinusoidGraph(graphState, i18n);
|
|
33313
|
+
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
33314
|
+
// Outer graph minimal description
|
|
33315
|
+
"aria-label": srSinusoidGraph,
|
|
33316
|
+
"aria-describedby": descriptionId
|
|
33317
|
+
}, /*#__PURE__*/React__namespace.createElement(mafs.Plot.OfX, {
|
|
33430
33318
|
y: x => computeSine(x, coeffRef.current),
|
|
33431
33319
|
color: wonderBlocksTokens.color.blue
|
|
33432
33320
|
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
33321
|
+
ariaLabel: i === 0 ? srSinusoidRootPoint : srSinusoidPeakPoint,
|
|
33433
33322
|
key: "point-" + i,
|
|
33434
33323
|
point: coord,
|
|
33435
33324
|
sequenceNumber: i + 1,
|
|
33436
33325
|
onMove: destination => dispatch(actions.sinusoid.movePoint(i, destination))
|
|
33437
|
-
}))
|
|
33326
|
+
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
33327
|
+
id: descriptionId
|
|
33328
|
+
}, srSinusoidDescription));
|
|
33438
33329
|
}
|
|
33439
33330
|
|
|
33440
33331
|
// Plot a sinusoid of the form: f(x) = a * sin(b * x - c) + d
|
|
@@ -33472,6 +33363,52 @@ const getSinusoidCoefficients$1 = coords => {
|
|
|
33472
33363
|
verticalOffset
|
|
33473
33364
|
};
|
|
33474
33365
|
};
|
|
33366
|
+
function getSinusoidDescription(state, i18n) {
|
|
33367
|
+
const strings = describeSinusoidGraph(state, i18n);
|
|
33368
|
+
return strings.srSinusoidInteractiveElements;
|
|
33369
|
+
}
|
|
33370
|
+
function describeSinusoidGraph(state, i18n) {
|
|
33371
|
+
const {
|
|
33372
|
+
strings,
|
|
33373
|
+
locale
|
|
33374
|
+
} = i18n;
|
|
33375
|
+
const {
|
|
33376
|
+
coords
|
|
33377
|
+
} = state;
|
|
33378
|
+
const [root, peak] = coords;
|
|
33379
|
+
const diffX = Math.abs(peak[X] - root[X]);
|
|
33380
|
+
const diffY = Math.abs(peak[Y] - root[Y]);
|
|
33381
|
+
const srSinusoidGraph = strings.srSinusoidGraph;
|
|
33382
|
+
const srSinusoidDescription = strings.srSinusoidDescription({
|
|
33383
|
+
minValue: srFormatNumber(root[Y] - diffY, locale),
|
|
33384
|
+
maxValue: srFormatNumber(root[Y] + diffY, locale),
|
|
33385
|
+
cycleStart: srFormatNumber(root[X] - 2 * diffX, locale),
|
|
33386
|
+
cycleEnd: srFormatNumber(root[X] + 2 * diffX, locale)
|
|
33387
|
+
});
|
|
33388
|
+
const srSinusoidRootPoint = strings.srSinusoidRootPoint({
|
|
33389
|
+
x: srFormatNumber(root[X], locale),
|
|
33390
|
+
y: srFormatNumber(root[Y], locale)
|
|
33391
|
+
});
|
|
33392
|
+
const srSinusoidPeakPoint = strings.srSinusoidPeakPoint({
|
|
33393
|
+
x: srFormatNumber(peak[X], locale),
|
|
33394
|
+
y: srFormatNumber(peak[Y], locale)
|
|
33395
|
+
});
|
|
33396
|
+
const srSinusoidInteractiveElements = strings.srInteractiveElements({
|
|
33397
|
+
elements: strings.srSinusoidInteractiveElements({
|
|
33398
|
+
point1X: srFormatNumber(root[X], locale),
|
|
33399
|
+
point1Y: srFormatNumber(root[Y], locale),
|
|
33400
|
+
point2X: srFormatNumber(peak[X], locale),
|
|
33401
|
+
point2Y: srFormatNumber(peak[Y], locale)
|
|
33402
|
+
})
|
|
33403
|
+
});
|
|
33404
|
+
return {
|
|
33405
|
+
srSinusoidGraph,
|
|
33406
|
+
srSinusoidDescription,
|
|
33407
|
+
srSinusoidRootPoint,
|
|
33408
|
+
srSinusoidPeakPoint,
|
|
33409
|
+
srSinusoidInteractiveElements
|
|
33410
|
+
};
|
|
33411
|
+
}
|
|
33475
33412
|
|
|
33476
33413
|
const {
|
|
33477
33414
|
calculateAngleInDegrees,
|
|
@@ -33642,6 +33579,7 @@ const MafsGraph = props => {
|
|
|
33642
33579
|
const descriptionId = `interactive-graph-description-${uniqueId}`;
|
|
33643
33580
|
const interactiveElementsDescriptionId = `interactive-graph-interactive-elements-description-${uniqueId}`;
|
|
33644
33581
|
const unlimitedGraphKeyboardPromptId = `unlimited-graph-keyboard-prompt-${uniqueId}`;
|
|
33582
|
+
const instructionsId = `instructions-${uniqueId}`;
|
|
33645
33583
|
const graphRef = React__namespace.useRef(null);
|
|
33646
33584
|
const {
|
|
33647
33585
|
analytics
|
|
@@ -33669,6 +33607,7 @@ const MafsGraph = props => {
|
|
|
33669
33607
|
const interactionPrompt = isUnlimitedGraphState(state) && state.showKeyboardInteractionInvitation;
|
|
33670
33608
|
wonderBlocksCore.useOnMountEffect(() => {
|
|
33671
33609
|
analytics.onAnalyticsEvent({
|
|
33610
|
+
// TODO(LEMS-2827): Remove analytics event in LEMS-2827 in favor of ti below.
|
|
33672
33611
|
type: "perseus:interactive-graph-widget:rendered",
|
|
33673
33612
|
payload: {
|
|
33674
33613
|
type,
|
|
@@ -33676,6 +33615,14 @@ const MafsGraph = props => {
|
|
|
33676
33615
|
widgetId: "interactive-graph"
|
|
33677
33616
|
}
|
|
33678
33617
|
});
|
|
33618
|
+
analytics.onAnalyticsEvent({
|
|
33619
|
+
type: "perseus:widget:rendered:ti",
|
|
33620
|
+
payload: {
|
|
33621
|
+
widgetSubType: type,
|
|
33622
|
+
widgetType: "INTERACTIVE_GRAPH",
|
|
33623
|
+
widgetId: "interactive-graph"
|
|
33624
|
+
}
|
|
33625
|
+
});
|
|
33679
33626
|
});
|
|
33680
33627
|
const {
|
|
33681
33628
|
graph,
|
|
@@ -33719,7 +33666,7 @@ const MafsGraph = props => {
|
|
|
33719
33666
|
handleKeyboardEvent(event, state, dispatch);
|
|
33720
33667
|
},
|
|
33721
33668
|
"aria-label": fullGraphAriaLabel,
|
|
33722
|
-
"aria-describedby": describedByIds(fullGraphAriaDescription && descriptionId, interactiveElementsDescription && interactiveElementsDescriptionId, isUnlimitedGraphState(state) && unlimitedGraphKeyboardPromptId),
|
|
33669
|
+
"aria-describedby": describedByIds(fullGraphAriaDescription && descriptionId, interactiveElementsDescription && interactiveElementsDescriptionId, isUnlimitedGraphState(state) && unlimitedGraphKeyboardPromptId, state.type !== "none" && instructionsId),
|
|
33723
33670
|
ref: graphRef,
|
|
33724
33671
|
tabIndex: 0,
|
|
33725
33672
|
onFocus: event => {
|
|
@@ -33736,7 +33683,11 @@ const MafsGraph = props => {
|
|
|
33736
33683
|
id: interactiveElementsDescriptionId,
|
|
33737
33684
|
tabIndex: -1,
|
|
33738
33685
|
className: "mafs-sr-only"
|
|
33739
|
-
}, interactiveElementsDescription), /*#__PURE__*/React__namespace.createElement(
|
|
33686
|
+
}, interactiveElementsDescription), state.type !== "none" && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
33687
|
+
id: instructionsId,
|
|
33688
|
+
tabIndex: -1,
|
|
33689
|
+
className: "mafs-sr-only"
|
|
33690
|
+
}, isUnlimitedGraphState(state) ? strings.srUnlimitedGraphInstructions : strings.srGraphInstructions), /*#__PURE__*/React__namespace.createElement(LegacyGrid, {
|
|
33740
33691
|
box: props.box,
|
|
33741
33692
|
backgroundImage: props.backgroundImage
|
|
33742
33693
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
@@ -33745,7 +33696,9 @@ const MafsGraph = props => {
|
|
|
33745
33696
|
bottom: 0,
|
|
33746
33697
|
left: 0
|
|
33747
33698
|
}
|
|
33748
|
-
}, (props.markings === "graph" || props.markings === "axes") && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(AxisLabels,
|
|
33699
|
+
}, (props.markings === "graph" || props.markings === "axes") && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(AxisLabels, {
|
|
33700
|
+
i18n: i18n
|
|
33701
|
+
})), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View
|
|
33749
33702
|
// If we have locked figures, we set aria-hidden
|
|
33750
33703
|
// to false so that screen readers can read the
|
|
33751
33704
|
// locked figures. If we don't have any locked
|
|
@@ -34082,25 +34035,25 @@ const renderGraphElements = props => {
|
|
|
34082
34035
|
} = state;
|
|
34083
34036
|
switch (type) {
|
|
34084
34037
|
case "angle":
|
|
34085
|
-
return renderAngleGraph(state, dispatch);
|
|
34038
|
+
return renderAngleGraph(state, dispatch, i18n);
|
|
34086
34039
|
case "segment":
|
|
34087
|
-
return renderSegmentGraph(state, dispatch);
|
|
34040
|
+
return renderSegmentGraph(state, dispatch, i18n);
|
|
34088
34041
|
case "linear-system":
|
|
34089
|
-
return renderLinearSystemGraph(state, dispatch);
|
|
34042
|
+
return renderLinearSystemGraph(state, dispatch, i18n);
|
|
34090
34043
|
case "linear":
|
|
34091
|
-
return renderLinearGraph(state, dispatch);
|
|
34044
|
+
return renderLinearGraph(state, dispatch, i18n);
|
|
34092
34045
|
case "ray":
|
|
34093
|
-
return renderRayGraph(state, dispatch);
|
|
34046
|
+
return renderRayGraph(state, dispatch, i18n);
|
|
34094
34047
|
case "polygon":
|
|
34095
34048
|
return renderPolygonGraph(state, dispatch, i18n, markings);
|
|
34096
34049
|
case "point":
|
|
34097
|
-
return renderPointGraph(state, dispatch);
|
|
34050
|
+
return renderPointGraph(state, dispatch, i18n);
|
|
34098
34051
|
case "circle":
|
|
34099
|
-
return renderCircleGraph(state, dispatch);
|
|
34052
|
+
return renderCircleGraph(state, dispatch, i18n);
|
|
34100
34053
|
case "quadratic":
|
|
34101
34054
|
return renderQuadraticGraph(state, dispatch, i18n);
|
|
34102
34055
|
case "sinusoid":
|
|
34103
|
-
return renderSinusoidGraph(state, dispatch);
|
|
34056
|
+
return renderSinusoidGraph(state, dispatch, i18n);
|
|
34104
34057
|
case "none":
|
|
34105
34058
|
return {
|
|
34106
34059
|
graph: null,
|
|
@@ -34520,13 +34473,13 @@ const {
|
|
|
34520
34473
|
polar
|
|
34521
34474
|
} = kmath.angles;
|
|
34522
34475
|
const {
|
|
34523
|
-
angleMeasures
|
|
34524
|
-
ccw
|
|
34525
|
-
lawOfCosines
|
|
34476
|
+
angleMeasures,
|
|
34477
|
+
ccw,
|
|
34478
|
+
lawOfCosines,
|
|
34526
34479
|
magnitude: magnitude$1,
|
|
34527
34480
|
polygonSidesIntersect,
|
|
34528
34481
|
reverseVector,
|
|
34529
|
-
sign
|
|
34482
|
+
sign,
|
|
34530
34483
|
vector: vector$1
|
|
34531
34484
|
} = kmath.geometry;
|
|
34532
34485
|
const {
|
|
@@ -35033,7 +34986,7 @@ function doAddPoint(state, action) {
|
|
|
35033
34986
|
...state,
|
|
35034
34987
|
hasBeenInteractedWith: true,
|
|
35035
34988
|
coords: newCoords,
|
|
35036
|
-
showRemovePointButton:
|
|
34989
|
+
showRemovePointButton: true,
|
|
35037
34990
|
focusedPointIndex: newCoords.length - 1
|
|
35038
34991
|
};
|
|
35039
34992
|
}
|
|
@@ -35041,17 +34994,12 @@ function doRemovePoint(state, action) {
|
|
|
35041
34994
|
if (!isUnlimitedGraphState(state)) {
|
|
35042
34995
|
return state;
|
|
35043
34996
|
}
|
|
35044
|
-
|
|
35045
|
-
if (state.interactionMode === "mouse") {
|
|
35046
|
-
nextFocusedPointIndex = null;
|
|
35047
|
-
} else {
|
|
35048
|
-
nextFocusedPointIndex = state.coords.length > 1 ? state.coords.length - 2 : null;
|
|
35049
|
-
}
|
|
34997
|
+
const nextFocusedPointIndex = state.coords.length > 1 ? state.coords.length - 2 : null;
|
|
35050
34998
|
return {
|
|
35051
34999
|
...state,
|
|
35052
35000
|
coords: state.coords.filter((_, i) => i !== action.index),
|
|
35053
35001
|
focusedPointIndex: nextFocusedPointIndex,
|
|
35054
|
-
showRemovePointButton: false
|
|
35002
|
+
showRemovePointButton: nextFocusedPointIndex !== null ? true : false
|
|
35055
35003
|
};
|
|
35056
35004
|
}
|
|
35057
35005
|
const getDeltaVertex = (maxMoves, minMoves, delta) => {
|
|
@@ -35228,7 +35176,7 @@ function boundAndSnapToPolygonAngle(destinationPoint, _ref6, index) {
|
|
|
35228
35176
|
});
|
|
35229
35177
|
|
|
35230
35178
|
// Gets the radian angles between the coords and maps them to degrees
|
|
35231
|
-
const angles = angleMeasures
|
|
35179
|
+
const angles = angleMeasures(coordsCopy).map(angle => angle * 180 / Math.PI);
|
|
35232
35180
|
|
|
35233
35181
|
// Gets the relative index of a point
|
|
35234
35182
|
const rel = j => {
|
|
@@ -35262,7 +35210,7 @@ function boundAndSnapToPolygonAngle(destinationPoint, _ref6, index) {
|
|
|
35262
35210
|
// we want to add the inner angle to the outer angle, and if it's on the right,
|
|
35263
35211
|
// we want to subtract the inner angle from the outer angle. The angle solved
|
|
35264
35212
|
// for is then used in the polar function to determine the new point.
|
|
35265
|
-
const onLeft = sign
|
|
35213
|
+
const onLeft = sign(ccw(coordsCopy[rel(-1)], coordsCopy[rel(1)], coordsCopy[index])) === 1;
|
|
35266
35214
|
|
|
35267
35215
|
// Solve for side by using the law of sines
|
|
35268
35216
|
const side = Math.sin(innerAngles[1] * Math.PI / 180) / Math.sin(innerAngles[2] * Math.PI / 180) * knownSide;
|
|
@@ -35316,7 +35264,7 @@ function boundAndSnapToSides(destinationPoint, _ref7, index) {
|
|
|
35316
35264
|
|
|
35317
35265
|
// Solve for angle by using the law of cosines
|
|
35318
35266
|
// Angle at the first vertex of the polygon
|
|
35319
|
-
const innerAngle = lawOfCosines
|
|
35267
|
+
const innerAngle = lawOfCosines(sides[0], sides[2], sides[1]);
|
|
35320
35268
|
|
|
35321
35269
|
// Angle at the second vertex of the polygon
|
|
35322
35270
|
const outerAngle = getAngleFromVertex(coordsCopy[rel(1)], coordsCopy[rel(-1)]);
|
|
@@ -35327,7 +35275,7 @@ function boundAndSnapToSides(destinationPoint, _ref7, index) {
|
|
|
35327
35275
|
// we want to add the inner angle to the outer angle, and if it's on the right,
|
|
35328
35276
|
// we want to subtract the inner angle from the outer angle. The angle solved
|
|
35329
35277
|
// for is then used in the polar function to determine the new point.
|
|
35330
|
-
const onLeft = sign
|
|
35278
|
+
const onLeft = sign(ccw(coordsCopy[rel(-1)], coordsCopy[rel(1)], coordsCopy[index])) === 1;
|
|
35331
35279
|
|
|
35332
35280
|
// Uses the length of the first side of the polygon (radial coordinate)
|
|
35333
35281
|
// and the angle between the first and second sides of the
|
|
@@ -35465,27 +35413,19 @@ const {
|
|
|
35465
35413
|
getClockwiseAngle
|
|
35466
35414
|
} = kmath.angles;
|
|
35467
35415
|
const {
|
|
35468
|
-
angleMeasures,
|
|
35469
|
-
ccw,
|
|
35470
|
-
collinear,
|
|
35471
35416
|
getLineEquation,
|
|
35472
35417
|
getLineIntersection,
|
|
35473
|
-
intersects,
|
|
35474
|
-
lawOfCosines,
|
|
35475
35418
|
magnitude,
|
|
35476
|
-
rotate,
|
|
35477
|
-
sign,
|
|
35478
35419
|
vector
|
|
35479
35420
|
} = kmath.geometry;
|
|
35480
35421
|
const defaultBackgroundImage = {
|
|
35481
35422
|
url: null
|
|
35482
35423
|
};
|
|
35483
35424
|
const UNLIMITED = "unlimited";
|
|
35484
|
-
|
|
35485
|
-
|
|
35486
|
-
|
|
35487
|
-
|
|
35488
|
-
}
|
|
35425
|
+
|
|
35426
|
+
// Sample background image:
|
|
35427
|
+
// https://ka-perseus-graphie.s3.amazonaws.com/29c1b0fcd17fe63df0f148fe357044d5d5c7d0bb.png
|
|
35428
|
+
|
|
35489
35429
|
function numSteps(range, step) {
|
|
35490
35430
|
return Math.floor((range[1] - range[0]) / step);
|
|
35491
35431
|
}
|
|
@@ -35530,7 +35470,6 @@ function getQuadraticCoefficients(coords) {
|
|
|
35530
35470
|
return [a, b, c];
|
|
35531
35471
|
}
|
|
35532
35472
|
class InteractiveGraph extends React__namespace.Component {
|
|
35533
|
-
legacyGraphRef = /*#__PURE__*/React__namespace.createRef();
|
|
35534
35473
|
mafsRef = /*#__PURE__*/React__namespace.createRef();
|
|
35535
35474
|
static defaultProps = {
|
|
35536
35475
|
labels: ["x", "y"],
|
|
@@ -35548,9 +35487,6 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
35548
35487
|
if (this.mafsRef.current?.getUserInput) {
|
|
35549
35488
|
return this.mafsRef.current.getUserInput();
|
|
35550
35489
|
}
|
|
35551
|
-
if (this.legacyGraphRef.current?.getUserInput) {
|
|
35552
|
-
return this.legacyGraphRef.current.getUserInput();
|
|
35553
|
-
}
|
|
35554
35490
|
throw new perseusCore.PerseusError("Cannot getUserInput from a graph that has never rendered", perseusCore.Errors.NotAllowed);
|
|
35555
35491
|
}
|
|
35556
35492
|
getPromptJSON() {
|
|
@@ -35744,8 +35680,32 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
35744
35680
|
}
|
|
35745
35681
|
static getEquationString(props) {
|
|
35746
35682
|
const type = props.graph.type;
|
|
35747
|
-
|
|
35748
|
-
|
|
35683
|
+
switch (type) {
|
|
35684
|
+
case "none":
|
|
35685
|
+
return InteractiveGraph.getNoneEquationString();
|
|
35686
|
+
case "linear":
|
|
35687
|
+
return InteractiveGraph.getLinearEquationString(props);
|
|
35688
|
+
case "quadratic":
|
|
35689
|
+
return InteractiveGraph.getQuadraticEquationString(props);
|
|
35690
|
+
case "sinusoid":
|
|
35691
|
+
return InteractiveGraph.getSinusoidEquationString(props);
|
|
35692
|
+
case "circle":
|
|
35693
|
+
return InteractiveGraph.getCircleEquationString(props);
|
|
35694
|
+
case "linear-system":
|
|
35695
|
+
return InteractiveGraph.getLinearSystemEquationString(props);
|
|
35696
|
+
case "point":
|
|
35697
|
+
return InteractiveGraph.getPointEquationString(props);
|
|
35698
|
+
case "segment":
|
|
35699
|
+
return InteractiveGraph.getSegmentEquationString(props);
|
|
35700
|
+
case "ray":
|
|
35701
|
+
return InteractiveGraph.getRayEquationString(props);
|
|
35702
|
+
case "polygon":
|
|
35703
|
+
return InteractiveGraph.getPolygonEquationString(props);
|
|
35704
|
+
case "angle":
|
|
35705
|
+
return InteractiveGraph.getAngleEquationString(props);
|
|
35706
|
+
default:
|
|
35707
|
+
throw new wonderStuffCore.UnreachableCaseError(type);
|
|
35708
|
+
}
|
|
35749
35709
|
}
|
|
35750
35710
|
static pointsFromNormalized(props, coordsList, noSnap) {
|
|
35751
35711
|
// @ts-expect-error - TS2322 - Type 'number[][]' is not assignable to type 'readonly Coord[]'.
|
|
@@ -35889,8 +35849,7 @@ var InteractiveGraph$1 = {
|
|
|
35889
35849
|
name: "interactive-graph",
|
|
35890
35850
|
displayName: "Interactive graph (Assessments only)",
|
|
35891
35851
|
widget: InteractiveGraph,
|
|
35892
|
-
staticTransform: staticTransform$3
|
|
35893
|
-
getPublicWidgetOptions: perseusCore.getInteractiveGraphPublicWidgetOptions
|
|
35852
|
+
staticTransform: staticTransform$3
|
|
35894
35853
|
};
|
|
35895
35854
|
|
|
35896
35855
|
// TODO: can we use WB typography?
|
|
@@ -36526,10 +36485,15 @@ class LabelImage extends React__namespace.Component {
|
|
|
36526
36485
|
});
|
|
36527
36486
|
}
|
|
36528
36487
|
activateMarker(index, opened) {
|
|
36488
|
+
// TODO(LEMS-2830): Remove analytics event in LEMS-2830 in favor of ti below.
|
|
36529
36489
|
this.props.analytics?.onAnalyticsEvent({
|
|
36530
36490
|
type: "perseus:label-image:marker-interacted-with",
|
|
36531
36491
|
payload: null
|
|
36532
36492
|
});
|
|
36493
|
+
this.props.analytics?.onAnalyticsEvent({
|
|
36494
|
+
type: "perseus:label-image:marker-interacted-with:ti",
|
|
36495
|
+
payload: null
|
|
36496
|
+
});
|
|
36533
36497
|
const {
|
|
36534
36498
|
activeMarkerIndex
|
|
36535
36499
|
} = this.state;
|
|
@@ -36673,10 +36637,15 @@ class LabelImage extends React__namespace.Component {
|
|
|
36673
36637
|
})),
|
|
36674
36638
|
multipleSelect: this.props.multipleAnswers,
|
|
36675
36639
|
onChange: selection => {
|
|
36640
|
+
// TODO(LEMS-2829): Remove analytics event in LEMS-2829 in favor of ti below.
|
|
36676
36641
|
this.props.analytics?.onAnalyticsEvent({
|
|
36677
36642
|
type: "perseus:label-image:choiced-interacted-with",
|
|
36678
36643
|
payload: null
|
|
36679
36644
|
});
|
|
36645
|
+
this.props.analytics?.onAnalyticsEvent({
|
|
36646
|
+
type: "perseus:label-image:choiced-interacted-with:ti",
|
|
36647
|
+
payload: null
|
|
36648
|
+
});
|
|
36680
36649
|
this.handleAnswerChoicesChangeForMarker(index, selection);
|
|
36681
36650
|
},
|
|
36682
36651
|
onToggle: opened => this.activateMarker(index, opened)
|
|
@@ -36781,10 +36750,15 @@ class LabelImage extends React__namespace.Component {
|
|
|
36781
36750
|
})), this.renderMarkers()), /*#__PURE__*/React__namespace.createElement(HideAnswersToggle, {
|
|
36782
36751
|
areAnswersHidden: this.state.hideAnswers,
|
|
36783
36752
|
onChange: hideAnswers => {
|
|
36753
|
+
// TODO(LEMS-2831): Remove analytics event in LEMS-2831 in favor of ti below.
|
|
36784
36754
|
this.props.analytics?.onAnalyticsEvent({
|
|
36785
36755
|
type: "perseus:label-image:toggle-answers-hidden",
|
|
36786
36756
|
payload: null
|
|
36787
36757
|
});
|
|
36758
|
+
this.props.analytics?.onAnalyticsEvent({
|
|
36759
|
+
type: "perseus:label-image:toggle-answers-hidden:ti",
|
|
36760
|
+
payload: null
|
|
36761
|
+
});
|
|
36788
36762
|
this.setState({
|
|
36789
36763
|
hideAnswers
|
|
36790
36764
|
});
|
|
@@ -36847,8 +36821,7 @@ var LabelImage$1 = {
|
|
|
36847
36821
|
displayName: "Label Image",
|
|
36848
36822
|
widget: LabelImageWithDependencies,
|
|
36849
36823
|
accessible: true,
|
|
36850
|
-
isLintable: true
|
|
36851
|
-
getPublicWidgetOptions: perseusCore.getLabelImagePublicWidgetOptions
|
|
36824
|
+
isLintable: true
|
|
36852
36825
|
};
|
|
36853
36826
|
|
|
36854
36827
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -37107,20 +37080,24 @@ class Draggable extends React__namespace.Component {
|
|
|
37107
37080
|
if (this.props.margin != null) {
|
|
37108
37081
|
style.margin = this.props.margin;
|
|
37109
37082
|
}
|
|
37110
|
-
return
|
|
37111
|
-
|
|
37112
|
-
|
|
37113
|
-
|
|
37114
|
-
|
|
37115
|
-
|
|
37116
|
-
|
|
37117
|
-
|
|
37118
|
-
|
|
37119
|
-
|
|
37120
|
-
|
|
37121
|
-
|
|
37122
|
-
|
|
37123
|
-
|
|
37083
|
+
return (
|
|
37084
|
+
/*#__PURE__*/
|
|
37085
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- TODO(LEMS-2871): Address a11y error
|
|
37086
|
+
React__namespace.createElement("li", {
|
|
37087
|
+
className: className,
|
|
37088
|
+
style: style,
|
|
37089
|
+
onMouseDown: this.onMouseDown,
|
|
37090
|
+
onTouchStart: this.onMouseDown,
|
|
37091
|
+
onTouchMove: this.onMouseMove,
|
|
37092
|
+
onTouchEnd: this.onMouseUp,
|
|
37093
|
+
onTouchCancel: this.onMouseUp
|
|
37094
|
+
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
37095
|
+
content: this.props.content,
|
|
37096
|
+
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "draggable"),
|
|
37097
|
+
onRender: this.props.onRender,
|
|
37098
|
+
strings: this.context.strings
|
|
37099
|
+
}))
|
|
37100
|
+
);
|
|
37124
37101
|
}
|
|
37125
37102
|
}
|
|
37126
37103
|
class Sortable extends React__namespace.Component {
|
|
@@ -38179,8 +38156,7 @@ var Matrix$1 = {
|
|
|
38179
38156
|
widget: Matrix,
|
|
38180
38157
|
transform: propTransform$1,
|
|
38181
38158
|
staticTransform: staticTransform$2,
|
|
38182
|
-
isLintable: true
|
|
38183
|
-
getPublicWidgetOptions: perseusCore.getMatrixPublicWidgetOptions
|
|
38159
|
+
isLintable: true
|
|
38184
38160
|
};
|
|
38185
38161
|
|
|
38186
38162
|
const getPromptJSON$7 = () => {
|
|
@@ -39757,8 +39733,7 @@ var NumberLine$1 = {
|
|
|
39757
39733
|
displayName: "Number line",
|
|
39758
39734
|
widget: NumberLine,
|
|
39759
39735
|
transform: numberLineTransform,
|
|
39760
|
-
staticTransform: staticTransform$1
|
|
39761
|
-
getPublicWidgetOptions: perseusCore.getNumberLinePublicWidgetOptions
|
|
39736
|
+
staticTransform: staticTransform$1
|
|
39762
39737
|
};
|
|
39763
39738
|
|
|
39764
39739
|
const getPromptJSON$5 = (renderProps, userInput) => {
|
|
@@ -39925,19 +39900,23 @@ class Card extends React__namespace.Component {
|
|
|
39925
39900
|
// Pull out the content to get rendered
|
|
39926
39901
|
const rendererProps = ___default["default"].pick(this.props, "content");
|
|
39927
39902
|
const onMouseDown = this.props.animating ? $__default["default"].noop : this.onMouseDown;
|
|
39928
|
-
return
|
|
39929
|
-
|
|
39930
|
-
|
|
39931
|
-
|
|
39932
|
-
|
|
39933
|
-
|
|
39934
|
-
|
|
39935
|
-
|
|
39936
|
-
|
|
39937
|
-
|
|
39938
|
-
|
|
39939
|
-
|
|
39940
|
-
|
|
39903
|
+
return (
|
|
39904
|
+
/*#__PURE__*/
|
|
39905
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions -- TODO(LEMS-2871): Address a11y error
|
|
39906
|
+
React__namespace.createElement("div", {
|
|
39907
|
+
className: "card-wrap",
|
|
39908
|
+
style: style,
|
|
39909
|
+
onMouseDown: onMouseDown,
|
|
39910
|
+
onTouchStart: onMouseDown,
|
|
39911
|
+
onTouchEnd: this.onMouseUp,
|
|
39912
|
+
onTouchCancel: this.onMouseUp
|
|
39913
|
+
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
39914
|
+
className: className.join(" ")
|
|
39915
|
+
}, /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, rendererProps, {
|
|
39916
|
+
linterContext: this.props.linterContext,
|
|
39917
|
+
strings: this.context.strings
|
|
39918
|
+
}))))
|
|
39919
|
+
);
|
|
39941
39920
|
}
|
|
39942
39921
|
}
|
|
39943
39922
|
class Orderer extends React__namespace.Component {
|
|
@@ -40309,8 +40288,7 @@ var Orderer$1 = {
|
|
|
40309
40288
|
displayName: "Orderer",
|
|
40310
40289
|
hidden: true,
|
|
40311
40290
|
widget: Orderer,
|
|
40312
|
-
isLintable: true
|
|
40313
|
-
getPublicWidgetOptions: perseusCore.getOrdererPublicWidgetOptions
|
|
40291
|
+
isLintable: true
|
|
40314
40292
|
};
|
|
40315
40293
|
|
|
40316
40294
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -41376,8 +41354,7 @@ var Plotter$1 = {
|
|
|
41376
41354
|
displayName: "Plotter",
|
|
41377
41355
|
hidden: true,
|
|
41378
41356
|
widget: Plotter,
|
|
41379
|
-
staticTransform: staticTransform
|
|
41380
|
-
getPublicWidgetOptions: perseusCore.getPlotterPublicWidgetOptions
|
|
41357
|
+
staticTransform: staticTransform
|
|
41381
41358
|
};
|
|
41382
41359
|
|
|
41383
41360
|
const getPromptJSON$2 = () => {
|
|
@@ -41537,8 +41514,7 @@ var Sorter$1 = {
|
|
|
41537
41514
|
name: "sorter",
|
|
41538
41515
|
displayName: "Sorter",
|
|
41539
41516
|
widget: Sorter,
|
|
41540
|
-
isLintable: true
|
|
41541
|
-
getPublicWidgetOptions: perseusCore.getSorterPublicWidgetOptions
|
|
41517
|
+
isLintable: true
|
|
41542
41518
|
};
|
|
41543
41519
|
|
|
41544
41520
|
const {
|
|
@@ -41754,8 +41730,7 @@ var Table$1 = {
|
|
|
41754
41730
|
widget: Table,
|
|
41755
41731
|
transform: propTransform,
|
|
41756
41732
|
hidden: true,
|
|
41757
|
-
isLintable: true
|
|
41758
|
-
getPublicWidgetOptions: perseusCore.getTablePublicWidgetOptions
|
|
41733
|
+
isLintable: true
|
|
41759
41734
|
};
|
|
41760
41735
|
|
|
41761
41736
|
const getPromptJSON = () => {
|
|
@@ -41936,7 +41911,7 @@ const init = function () {
|
|
|
41936
41911
|
|
|
41937
41912
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
41938
41913
|
const libName = "@khanacademy/perseus";
|
|
41939
|
-
const libVersion = "
|
|
41914
|
+
const libVersion = "54.0.0";
|
|
41940
41915
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
41941
41916
|
|
|
41942
41917
|
const apiVersion = {
|
|
@@ -43430,6 +43405,17 @@ function getWidgetTypeByWidgetId(WidgetId, widgetMap) {
|
|
|
43430
43405
|
const widget = widgetMap[WidgetId];
|
|
43431
43406
|
return widget?.type ?? null;
|
|
43432
43407
|
}
|
|
43408
|
+
function getWidgetSubTypeByWidgetId(widgetId, widgetMap) {
|
|
43409
|
+
const widget = widgetMap[widgetId];
|
|
43410
|
+
const widgetType = widget?.type ?? null;
|
|
43411
|
+
switch (widgetType) {
|
|
43412
|
+
case "interactive-graph":
|
|
43413
|
+
const graph = widget.options.graph;
|
|
43414
|
+
return graph?.type ?? null;
|
|
43415
|
+
default:
|
|
43416
|
+
return null;
|
|
43417
|
+
}
|
|
43418
|
+
}
|
|
43433
43419
|
|
|
43434
43420
|
/**
|
|
43435
43421
|
* Does the content have a specific type of widget?
|
|
@@ -44308,6 +44294,7 @@ exports.getSegmentCoords = getSegmentCoords;
|
|
|
44308
44294
|
exports.getSinusoidCoords = getSinusoidCoords;
|
|
44309
44295
|
exports.getValidWidgetIds = getValidWidgetIds;
|
|
44310
44296
|
exports.getWidgetFromWidgetMap = getWidgetFromWidgetMap;
|
|
44297
|
+
exports.getWidgetSubTypeByWidgetId = getWidgetSubTypeByWidgetId;
|
|
44311
44298
|
exports.getWidgetTypeByWidgetId = getWidgetTypeByWidgetId;
|
|
44312
44299
|
exports.getWidgetsFromWidgetMap = getWidgetsFromWidgetMap;
|
|
44313
44300
|
exports.getWidgetsMapFromItemData = getWidgetsMapFromItemData;
|