@doenet/doenetml 0.7.23-dev.475 → 0.7.23-dev.476

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.
Files changed (105) hide show
  1. package/{AnswerResponseButton-B53k5lrk.js → AnswerResponseButton-CYTvrt3I.js} +2 -2
  2. package/{Description-DyPYa_ME.js → Description-CZuMXIjw.js} +1 -1
  3. package/{GraphFrame-CUDmX-f_.js → GraphFrame-DI6EMJc3.js} +2 -2
  4. package/{JSXGraphRenderer-C9Ylgb9D.js → JSXGraphRenderer-xzvpcvgx.js} +1 -1
  5. package/{NonInlineMediaWrapper-CCHEfwyI.js → NonInlineMediaWrapper-BNQCzge3.js} +1 -1
  6. package/{_error-JHz1wAdS.js → _error-DWqjMYij.js} +2 -2
  7. package/{alert-SyXPOCiR.js → alert-COmp6XLs.js} +3 -3
  8. package/{angle-a9FibBTs.js → angle-CKLjzXuL.js} +6 -6
  9. package/{answer-CfOMtUek.js → answer-BkN2MwQa.js} +5 -5
  10. package/{asList-kpPO54xo.js → asList-CZXZF0cP.js} +2 -2
  11. package/{blockQuote-DjlUe3Ad.js → blockQuote-DZVOLGax.js} +3 -3
  12. package/{boolean-5tZlmd10.js → boolean-DPp5xzWB.js} +2 -2
  13. package/{booleanInput-D3ABOXZ5.js → booleanInput-CtIwyp82.js} +6 -6
  14. package/{br-B8uJFeYF.js → br-BFdYJFVu.js} +2 -2
  15. package/{button-CiXRrAzU.js → button-DWbHCnQm.js} +4 -4
  16. package/{c-BYGwzMlI.js → c-CKYSF3cp.js} +3 -3
  17. package/{cell-DmO_qY76.js → cell-DUbUmtOI.js} +3 -3
  18. package/{choiceInput-Crr3C-HF.js → choiceInput-BrH7MTB7.js} +4 -4
  19. package/{circle-CkT4Sx0b.js → circle-BgnBqcZF.js} +6 -6
  20. package/{cobwebPolyline-BgqcgR6k.js → cobwebPolyline-DK6ozrJy.js} +4 -4
  21. package/{codeEditor-CYUacYHR.js → codeEditor-B7w6xwE2.js} +2 -2
  22. package/{composites-A35T_1Yt.js → composites-BfMuYvvj.js} +1 -1
  23. package/{containerBlock-CZ-Vjvyr.js → containerBlock-B22E5Fqp.js} +4 -4
  24. package/{containerInline-DQG6Ndtb.js → containerInline-q1XBOIT2.js} +4 -4
  25. package/{curve-jOhpc5P-.js → curve-DcsspUTe.js} +4 -4
  26. package/{doenetml-Is045YXP.js → doenetml-Ta2HxqsQ.js} +12 -6
  27. package/doenetml-external-worker.js +2 -2
  28. package/doenetml-inline-worker.js +2 -2
  29. package/{ellipsis-887PvGfJ.js → ellipsis-BuI1kGgH.js} +2 -2
  30. package/{em-POA-G3kM.js → em-ijhxC4d-.js} +3 -3
  31. package/{embed-DGtaXhYN.js → embed-DGFgA5gz.js} +2 -2
  32. package/{feedback-kl4at098.js → feedback-XY2Pa2wD.js} +4 -4
  33. package/{figure-uPE0-EzM.js → figure-Blq7ssOc.js} +3 -3
  34. package/{fillPatterns-Dpx4zEgt.js → fillPatterns-rlbUUF5x.js} +1 -1
  35. package/{footnote-Cj_vgNcD.js → footnote-o0sfw77X.js} +3 -3
  36. package/{fractionInput-DffR1vEy.js → fractionInput-DkinWrhq.js} +4 -4
  37. package/{graph-B-r2M3bu.js → graph-GEbrtd5f.js} +6 -6
  38. package/{hint-BuGcmvCm.js → hint-DWxHJhOc.js} +4 -4
  39. package/{hr-D1FuH1Co.js → hr-Ca8Nt9sM.js} +2 -2
  40. package/{image-Du0KyDrQ.js → image-DwfH7o0u.js} +7 -7
  41. package/{index-BpKbPHhJ.js → index-Blxt578R.js} +1 -1
  42. package/{index.es-qqfsiLTM.js → index.es-DCLnH1LF.js} +1 -1
  43. package/index.js +1 -1
  44. package/{label-CmHTpfkm.js → label-CWhMa2ox.js} +6 -6
  45. package/{labelWithLatex-B0DnOp07.js → labelWithLatex-kFAjdoWk.js} +1 -1
  46. package/{legend-DhdQx3Im.js → legend-DYmNIl5C.js} +4 -4
  47. package/{line-IXKV26LF.js → line-BCg0MYPj.js} +6 -6
  48. package/{lineFamilyDragHandlers-9OE6rl44.js → lineFamilyDragHandlers-CcFnhoeH.js} +1 -1
  49. package/{lineSegment-CH21alDi.js → lineSegment-B4jo9Gh6.js} +5 -5
  50. package/{list-C0qTR_fm.js → list-U0L6Qo0x.js} +4 -4
  51. package/{lq-B9PN1YWM.js → lq-7Cx7qr85.js} +2 -2
  52. package/{lsq-BjrnYUAf.js → lsq-B37UFeNR.js} +2 -2
  53. package/{markupRenderer-Bsih1FJC.js → markupRenderer-CGSpuHTy.js} +1 -1
  54. package/{math-DdjB4yyo.js → math-B0VFfoIF.js} +6 -6
  55. package/{mathInput-yleORQIq.js → mathInput-BhgkCTIt.js} +7 -7
  56. package/{matrixInput-CKdtgj-_.js → matrixInput-Dw7267GU.js} +4 -4
  57. package/{mdash-ChuhJuKV.js → mdash-3Q7GGLQk.js} +2 -2
  58. package/{nbsp-BPGzxqC4.js → nbsp-CeJzsfHa.js} +2 -2
  59. package/{ndash-BNpP-sZ8.js → ndash-BmJgJGxw.js} +2 -2
  60. package/{number-ZXlS15R1.js → number-BCPnqkr8.js} +6 -6
  61. package/{orbitalDiagram-CFmDTRMv.js → orbitalDiagram-O6Li7jYh.js} +2 -2
  62. package/{orbitalDiagramInput-B89K_onN.js → orbitalDiagramInput-Ctl1Io7-.js} +2 -2
  63. package/{p-19NXXtal.js → p-By0tU6_l.js} +4 -4
  64. package/package.json +1 -1
  65. package/{paginatorControls-Bkg-bqeu.js → paginatorControls-B2bmHCN2.js} +2 -2
  66. package/{pegboard-Cm2YaNPP.js → pegboard-TqWsYbep.js} +4 -4
  67. package/{point-CkDaAbIF.js → point-DAiiNV-_.js} +6 -6
  68. package/{polygon-Ck58FXfd.js → polygon-WG_3sbSk.js} +6 -6
  69. package/{polyline-byfNHn5G.js → polyline-XWpJ_EKT.js} +5 -5
  70. package/{pre-WrLnWomg.js → pre-o9N0xYIH.js} +3 -3
  71. package/{prefigure-Dpo5IkQr.js → prefigure-CbWDTSpX.js} +1 -1
  72. package/{pretzel-CSunCYFI.js → pretzel-KQha_rJP.js} +4 -4
  73. package/{q-aIbWeFJ9.js → q-Ci8WOpJz.js} +3 -3
  74. package/{ray-BfIu2L44.js → ray-C1-E1Yrm.js} +5 -5
  75. package/{ref-hkY9PkFc.js → ref-DTIn1fgE.js} +2 -2
  76. package/{regionBetweenCurveXAxis-BNrJmaN_.js → regionBetweenCurveXAxis-DA7L4yJO.js} +5 -5
  77. package/{regionBetweenCurves-_mank897.js → regionBetweenCurves-C_Z3Q1iM.js} +5 -5
  78. package/{row-DoE-evrD.js → row-yChJHcHK.js} +2 -2
  79. package/{rq-DOgwFs8F.js → rq-D1qwK9HE.js} +2 -2
  80. package/{rsq-BTClqbcx.js → rsq-CAgaVpfV.js} +2 -2
  81. package/{section-CwC-4nsu.js → section-Cepja3lw.js} +5 -5
  82. package/{sha256-DT5xJ2Hv-CRdVGzK1.js → sha256-DT5xJ2Hv-C-nlv62I.js} +1 -1
  83. package/{sideBySide-B0nRa1ar.js → sideBySide-BydWyjXl.js} +2 -2
  84. package/{slider-DuJpCojl.js → slider-BFX5dAzy.js} +3 -3
  85. package/{slopeField-CE6bOGcj.js → slopeField-CP5cnvHP.js} +2 -2
  86. package/{solution-DYsp2e1H.js → solution-s8aIRGE7.js} +4 -4
  87. package/{spreadsheet-3r43ikiX.js → spreadsheet-DQL0rlwm.js} +2 -2
  88. package/{sq-O5MAfNXY.js → sq-BpvXWV4N.js} +3 -3
  89. package/style.css +246 -28
  90. package/{subsetOfRealsInput-06o90Y8L.js → subsetOfRealsInput-Dfiyjer-.js} +2 -2
  91. package/{summaryStatistics-ZjPiWxiR.js → summaryStatistics-VZu2PPMM.js} +2 -2
  92. package/{table-Dvta9OER.js → table-j-qeVf4M.js} +2 -2
  93. package/{tabular-DGmtbX6-.js → tabular-3pY_y78e.js} +2 -2
  94. package/{tag-CgVQ_Rl3.js → tag-CFFs_NOJ.js} +2 -2
  95. package/{text-DsHz-aqh.js → text-RO26-xQ8.js} +6 -6
  96. package/{textInput-CDlSZFsO.js → textInput-DAewn1p7.js} +6 -6
  97. package/{tooltip-provider-Djh7M4xU.js → tooltip-provider-BEbG7ksq.js} +1 -1
  98. package/{useAnchoredGraphDragHandler-AXWt5rFu.js → useAnchoredGraphDragHandler-CnL8PGob.js} +1 -1
  99. package/useDoenetRenderer-BfN6AEqX.js +114 -0
  100. package/{useFieldCurve-DxaUkcbk.js → useFieldCurve-C-rjP7c2.js} +2 -2
  101. package/{useSubmitActionWithDelay-CrrIiCmf.js → useSubmitActionWithDelay-Dq7IwApa.js} +2 -2
  102. package/{vector-WS37N22n.js → vector-BTtmLhiF.js} +6 -6
  103. package/{vectorField-BVXdWVy6.js → vectorField-CMkWuOjx.js} +2 -2
  104. package/{video-SMUAMtg-.js → video-DwRSSoHX.js} +4 -4
  105. package/useDoenetRenderer-CdAHG5_i.js +0 -114
package/style.css CHANGED
@@ -477,26 +477,55 @@ div.jxgbox input[type="checkbox"] {
477
477
  /**************************************************
478
478
  End JSXGraph styles
479
479
  **************************************************/
480
+ .container {
481
+ width: 100%;
482
+ }
483
+ @media (min-width: 640px) {
484
+ .container {
485
+ max-width: 640px;
486
+ }
487
+ }
488
+ @media (min-width: 768px) {
489
+ .container {
490
+ max-width: 768px;
491
+ }
492
+ }
493
+ @media (min-width: 1024px) {
494
+ .container {
495
+ max-width: 1024px;
496
+ }
497
+ }
498
+ @media (min-width: 1280px) {
499
+ .container {
500
+ max-width: 1280px;
501
+ }
502
+ }
503
+ @media (min-width: 1536px) {
504
+ .container {
505
+ max-width: 1536px;
506
+ }
507
+ }
480
508
  .fixed {
481
509
  position: fixed;
482
510
  }
483
-
484
511
  .inline {
485
512
  display: inline;
486
513
  }
487
-
488
514
  .overline {
489
515
  text-decoration-line: overline;
490
516
  }
491
-
492
517
  .blur {
493
518
  --tw-blur: blur(8px);
494
519
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
495
520
  }
496
-
497
521
  .filter {
498
522
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
499
523
  }
524
+ .transition {
525
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
526
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
527
+ transition-duration: 150ms;
528
+ }
500
529
 
501
530
  .keyboard-button {
502
531
  display: inline-flex;
@@ -565,8 +594,13 @@ div.jxgbox input[type="checkbox"] {
565
594
  }
566
595
 
567
596
  .virtual-keyboard {
597
+ /*
598
+ * How wide the keyboard may spread. A variable because the sub-keyboard
599
+ * has to agree with it, and because the touch-device block below raises
600
+ * it — two literals that must match are two literals that can drift.
601
+ */
602
+ --keyboard-max-width: 42rem;
568
603
  display: flex;
569
- max-width: 42rem;
570
604
  justify-content: center;
571
605
  row-gap: 0.25rem;
572
606
  -moz-column-gap: 0.75rem;
@@ -574,7 +608,6 @@ div.jxgbox input[type="checkbox"] {
574
608
  }
575
609
 
576
610
  @media (min-width: 640px) {
577
-
578
611
  .virtual-keyboard {
579
612
  row-gap: 0.5rem;
580
613
  }
@@ -585,12 +618,15 @@ div.jxgbox input[type="checkbox"] {
585
618
  }
586
619
 
587
620
  @media (min-width: 640px) {
588
-
589
621
  .virtual-keyboard {
590
622
  flex-wrap: nowrap;
591
623
  }
592
624
  }
593
625
 
626
+ .virtual-keyboard {
627
+ max-width: var(--keyboard-max-width);
628
+ }
629
+
594
630
  .virtual-keyboard .row {
595
631
  display: flex;
596
632
  flex-basis: 100%;
@@ -600,7 +636,6 @@ div.jxgbox input[type="checkbox"] {
600
636
  }
601
637
 
602
638
  @media (min-width: 640px) {
603
-
604
639
  .virtual-keyboard .row {
605
640
  -moz-column-gap: 0.5rem;
606
641
  column-gap: 0.5rem;
@@ -616,7 +651,6 @@ div.jxgbox input[type="checkbox"] {
616
651
  }
617
652
 
618
653
  @media (min-width: 640px) {
619
-
620
654
  .virtual-keyboard .keyboard-region {
621
655
  -moz-column-gap: 0.5rem;
622
656
  column-gap: 0.5rem;
@@ -630,7 +664,6 @@ div.jxgbox input[type="checkbox"] {
630
664
  }
631
665
 
632
666
  @media (min-width: 640px) {
633
-
634
667
  .virtual-keyboard .keyboard-region .key {
635
668
  padding-left: 1rem;
636
669
  padding-right: 1rem;
@@ -639,14 +672,12 @@ div.jxgbox input[type="checkbox"] {
639
672
 
640
673
  .virtual-keyboard .sub-keyboard {
641
674
  display: flex;
642
- max-width: 42rem;
643
675
  flex-wrap: wrap;
644
676
  justify-content: center;
645
677
  row-gap: 0.25rem;
646
678
  }
647
679
 
648
680
  @media (min-width: 640px) {
649
-
650
681
  .virtual-keyboard .sub-keyboard {
651
682
  row-gap: 0.5rem;
652
683
  }
@@ -654,6 +685,7 @@ div.jxgbox input[type="checkbox"] {
654
685
 
655
686
  .virtual-keyboard .sub-keyboard {
656
687
  height: 100%;
688
+ max-width: var(--keyboard-max-width);
657
689
  }
658
690
 
659
691
  .virtual-keyboard button {
@@ -774,7 +806,6 @@ div.jxgbox input[type="checkbox"] {
774
806
  }
775
807
 
776
808
  @media (min-width: 640px) {
777
-
778
809
  .virtual-keyboard-tab-list button {
779
810
  padding: 0.5rem;
780
811
  padding-left: 0.75rem;
@@ -796,10 +827,87 @@ div.jxgbox input[type="checkbox"] {
796
827
  --tw-text-opacity: 1;
797
828
  color: rgb(37 99 235 / var(--tw-text-opacity, 1));
798
829
  }
830
+
831
+ /*
832
+ * Touch devices — see the note beside the matching block in
833
+ * `keyboard-tray.css`. A key was 39x40 on a phone and a layout tab 30x25;
834
+ * both are below the 44px a fingertip needs (issue #449).
835
+ *
836
+ * Height is raised outright, since it costs only tray height. Width is left
837
+ * to the flex layout, which already gives each key an equal share of the row:
838
+ * a phone cannot fit twelve 44px-wide keys across, and forcing it would push
839
+ * the row into an overflow or a wrap that helps no one. What helps the other
840
+ * end — a tablet, where the row had room to spare and the keys stayed small
841
+ * in the middle of it — is room for the row to grow, so the even share each
842
+ * key gets is a larger one, and a ceiling raised to match.
843
+ *
844
+ * Both halves are needed. `--keyboard-max-width` alone would hand the extra
845
+ * room to shift, backspace and space, the only keys with no ceiling of their
846
+ * own; the per-key `max-width` alone has nothing extra to hand out. Note that
847
+ * the ceiling is in `em`, and a key is a `button`, which this package's
848
+ * partial copy of Tailwind's preflight leaves at the UA font size of
849
+ * 13.33px — so `4em` is 53px and `4.5em` is 60px, not 64 and 72.
850
+ *
851
+ * Last in the file because every rule here raises one above it and each pair
852
+ * has equal specificity, so source order is all that separates them — a media
853
+ * query adds none. Shift, backspace and space are the exception: their
854
+ * `max-width: none` is set on `.virtual-keyboard .key-*`, two classes, which
855
+ * already outranks the one-class-one-type `button` selector here, so they
856
+ * stay unbounded without being named again. Backspace on the numeric layout
857
+ * is the exception to that exception — a rule above puts its ceiling back at
858
+ * `4em`, and outranks this block for the same reason — so it is the one key
859
+ * that has to be raised by name.
860
+ */
861
+ @media (pointer: coarse) {
862
+ .virtual-keyboard {
863
+ --keyboard-max-width: 48rem;
864
+ }
865
+
866
+ .virtual-keyboard button {
867
+ min-height: 2.75rem;
868
+ max-width: 4.5em;
869
+ }
870
+ .virtual-keyboard.numeric .key-backspace {
871
+ max-width: 4.5em;
872
+ }
873
+ .virtual-keyboard-tab-list button {
874
+ min-height: 2.75rem;
875
+ padding-left: 0.75rem;
876
+ padding-right: 0.75rem;
877
+ }
878
+ }
799
879
  /*
800
880
  Tailwind base is purposely not included because we want all styles to be prefixed. We manually copy in whatever is needed from tailwind preflight.
801
881
  @tailwind base;
802
882
  */
883
+ .container {
884
+ width: 100%;
885
+ }
886
+ @media (min-width: 640px) {
887
+ .container {
888
+ max-width: 640px;
889
+ }
890
+ }
891
+ @media (min-width: 768px) {
892
+ .container {
893
+ max-width: 768px;
894
+ }
895
+ }
896
+ @media (min-width: 1024px) {
897
+ .container {
898
+ max-width: 1024px;
899
+ }
900
+ }
901
+ @media (min-width: 1280px) {
902
+ .container {
903
+ max-width: 1280px;
904
+ }
905
+ }
906
+ @media (min-width: 1536px) {
907
+ .container {
908
+ max-width: 1536px;
909
+ }
910
+ }
803
911
  .fixed {
804
912
  position: fixed;
805
913
  }
@@ -816,6 +924,11 @@ Tailwind base is purposely not included because we want all styles to be prefixe
816
924
  .filter {
817
925
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
818
926
  }
927
+ .transition {
928
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
929
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
930
+ transition-duration: 150ms;
931
+ }
819
932
 
820
933
  /*
821
934
  * Some styles from tailwind preflight need to be included here
@@ -860,6 +973,15 @@ Tailwind base is purposely not included because we want all styles to be prefixe
860
973
 
861
974
  --keyboard-tray-height: 280px;
862
975
 
976
+ /*
977
+ * The tab that peeks above a closed tray. Its height and the distance it
978
+ * is raised by are the same measurement — it sits exactly its own height
979
+ * above the tray's top edge — so they are one value, not two that have to
980
+ * be kept equal.
981
+ */
982
+ --keyboard-tab-height: 1.5rem;
983
+ --keyboard-tab-width: 3rem;
984
+
863
985
  border-top: 1px solid var(--kb-tray-border-top);
864
986
 
865
987
  position: fixed;
@@ -885,12 +1007,67 @@ Tailwind base is purposely not included because we want all styles to be prefixe
885
1007
  transition-duration: 300ms;
886
1008
 
887
1009
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
888
- min-height: var(--keyboard-tray-height);
889
- max-height: calc(100vh - 1.5rem);
1010
+ /* A column, so `.keyboard-container` is bound by the height set below. */
1011
+ display: flex;
1012
+ flex-direction: column;
1013
+ /*
1014
+ * The tray may never be so tall that it carries its own tab off the top of
1015
+ * the screen: the tab hangs exactly `--keyboard-tab-height` above the
1016
+ * tray's top edge, so that much has to stay clear. Both bounds are held to
1017
+ * it — the floor as well as the ceiling, because a `min-height` outranks a
1018
+ * `max-height` and would otherwise reinstate the overshoot on a viewport
1019
+ * shorter than the floor. Written against the variable rather than
1020
+ * repeating its value: widening the tab for a fingertip is exactly the
1021
+ * change that a literal here would have missed.
1022
+ */
1023
+ --keyboard-tray-max-height: calc(100vh - var(--keyboard-tab-height));
1024
+ min-height: min(
1025
+ var(--keyboard-tray-height),
1026
+ var(--keyboard-tray-max-height)
1027
+ );
1028
+ max-height: var(--keyboard-tray-max-height);
890
1029
  z-index: 10000;
891
1030
  background-color: var(--kb-tray-bg);
892
1031
  }
893
1032
 
1033
+ /*
1034
+ * The layout tabs and the keyboard under them, and the only part of the
1035
+ * tray that scrolls. A viewport too short for the keyboard — a phone held
1036
+ * sideways, or any short window — used to cut the bottom rows off, which
1037
+ * on the numeric layout is the number pad; taller keys for a fingertip
1038
+ * would have cut off more. `min-height: 0` is what lets it shrink: a flex
1039
+ * item's automatic minimum is its own content, which would otherwise push
1040
+ * the overflow straight back out to the tray.
1041
+ *
1042
+ * The layout tabs scroll with the keys rather than staying pinned, so a
1043
+ * tray reopened at the position it was left at would be missing them.
1044
+ * `keyboard-tray.tsx` scrolls this back to the top as the tray opens.
1045
+ *
1046
+ * A finger can pan it even though the tray cancels the default action of
1047
+ * `pointerdown` across its whole subtree (see `keyboard-tray.tsx`): what
1048
+ * suppresses a pan is `touch-action` or a cancelled `touchstart` /
1049
+ * `touchmove`, and the tray does neither. Confirmed in Chromium with a
1050
+ * real coarse pointer, and asserted in
1051
+ * `cypress/e2e/accessibility/virtualKeyboardTouchTargets.cy.js`; iOS
1052
+ * Safari has not been tried. `overscroll-behavior` keeps a pan that runs
1053
+ * off the end of it from scrolling the document behind the tray.
1054
+ */
1055
+
1056
+ #virtual-keyboard-tray .keyboard-container {
1057
+ min-height: 0;
1058
+ overflow-y: auto;
1059
+ overscroll-behavior: contain;
1060
+ }
1061
+
1062
+ /*
1063
+ * Outside `.keyboard-container`'s scroll for positioning purposes even
1064
+ * though it is inside it in the markup: its containing block is the tray,
1065
+ * so it neither scrolls away nor is clipped, and stays in the corner
1066
+ * where it can be reached. That holds only while nothing between the two
1067
+ * is positioned — give `.keyboard-container` a `position` and the button
1068
+ * starts scrolling away with the keys.
1069
+ */
1070
+
894
1071
  #virtual-keyboard-tray .close-keyboard-button {
895
1072
  position: absolute;
896
1073
  top: 0px;
@@ -920,19 +1097,19 @@ Tailwind base is purposely not included because we want all styles to be prefixe
920
1097
  }
921
1098
 
922
1099
  /*
923
- * Inline-end footprint of this button (w-12 + me-4 = 4rem) is mirrored
924
- * by `--keyboard-tab-reserve-width` in
1100
+ * Inline-end footprint of this button (`--keyboard-tab-width` + me-4) is
1101
+ * mirrored by `--keyboard-tab-reserve-width` in
925
1102
  * `packages/doenetml/src/EditorViewer/editor-viewer.css` so the editor
926
1103
  * footer can shift its last element inward to clear it. Keep the two
927
- * values in sync — and keep both on the *same* axis. `end-0` here pairs
928
- * with `margin-inline-end` there; making one logical and leaving the
929
- * other physical would send the tab and the space reserved for it to
930
- * opposite edges under `rtl`, which is worse than either alone.
1104
+ * values in sync — including the touch-device widening below and keep
1105
+ * both on the *same* axis. `end-0` here pairs with `margin-inline-end`
1106
+ * there; making one logical and leaving the other physical would send the
1107
+ * tab and the space reserved for it to opposite edges under `rtl`, which
1108
+ * is worse than either alone.
931
1109
  */
932
1110
 
933
1111
  #virtual-keyboard-tray .open-keyboard-button {
934
1112
  position: absolute;
935
- top: -1.5rem;
936
1113
  inset-inline-end: 0px;
937
1114
  margin-inline-end: 1rem;
938
1115
  border-top-left-radius: 0.25rem;
@@ -954,13 +1131,14 @@ Tailwind base is purposely not included because we want all styles to be prefixe
954
1131
 
955
1132
  #virtual-keyboard-tray .open-keyboard-button {
956
1133
  display: flex;
957
- height: 1.5rem;
958
- width: 3rem;
959
1134
  align-items: center;
960
1135
  justify-content: center;
961
1136
  border-width: 1px;
962
1137
  --tw-bg-opacity: 1;
963
1138
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
1139
+ top: calc(-1 * var(--keyboard-tab-height));
1140
+ width: var(--keyboard-tab-width);
1141
+ height: var(--keyboard-tab-height);
964
1142
  }
965
1143
 
966
1144
  #virtual-keyboard-tray .virtual-keyboard-tab-list {
@@ -980,6 +1158,38 @@ Tailwind base is purposely not included because we want all styles to be prefixe
980
1158
  margin-right: auto;
981
1159
  }
982
1160
 
1161
+ /*
1162
+ * Touch devices: everything here is tapped with a fingertip rather than
1163
+ * pointed at, so every control needs a target a fingertip can land on. 44px is
1164
+ * the minimum in Apple's HIG and in WCAG 2.5.5. The tray shipped with a 48x24
1165
+ * tab to open it, a 24x24 button to close it, and layout tabs measuring 30x25
1166
+ * on a phone — issue #449.
1167
+ *
1168
+ * Keyed on the reader's primary pointer being coarse rather than on how wide
1169
+ * the viewport is: a narrow window on a desktop is still driven by a mouse,
1170
+ * and a tablet held in two hands is not, however much room it has. This is the
1171
+ * same test the viewer uses to decide whether to suppress the device's own
1172
+ * on-screen keyboard, so the two stay consistent about what a touch device is.
1173
+ */
1174
+ @media (pointer: coarse) {
1175
+ #virtual-keyboard-tray {
1176
+ --keyboard-tab-height: 2.75rem;
1177
+ --keyboard-tab-width: 4rem;
1178
+ }
1179
+
1180
+ #virtual-keyboard-tray .open-keyboard-button {
1181
+ /* The icon is drawn at 1em, so it grows with the tab. */
1182
+ font-size: 1.25rem;
1183
+ line-height: 1.75rem;
1184
+ }
1185
+
1186
+ #virtual-keyboard-tray .close-keyboard-button {
1187
+ margin: 0.25rem;
1188
+ height: 2.75rem;
1189
+ width: 2.75rem;
1190
+ }
1191
+ }
1192
+
983
1193
  /* Dark-mode overrides — applied when data-theme="dark" is written to #virtual-keyboard-tray */
984
1194
  #virtual-keyboard-tray[data-theme="dark"] {
985
1195
  --kb-tray-bg: #1e1e1e;
@@ -2108,18 +2318,26 @@ Tailwind base is purposely not included because we want all styles to be prefixe
2108
2318
  * tab (showViewer={false} or viewerLocation in {"start","top"} with the
2109
2319
  * keyboard enabled), push the last footer element inward so the icons stay
2110
2320
  * clickable. The reservation must match the keyboard tab's inline-end
2111
- * footprint (`w-12` + `me-4` = 3rem + 1rem) defined in
2112
- * `packages/virtual-keyboard/src/virtual-keyboard/keyboard-tray.css`. Keep
2113
- * this value in sync if that footprint changes. Very narrow viewports may
2114
- * still let the tab and the icons collide; that's accepted.
2321
+ * footprint (`--keyboard-tab-width` + `me-4`) defined in
2322
+ * `packages/virtual-keyboard/src/virtual-keyboard/keyboard-tray.css`, which
2323
+ * widens the tab on touch devices to give it a target a fingertip can hit.
2324
+ * Keep both values in sync if that footprint changes. Very narrow viewports
2325
+ * may still let the tab and the icons collide; that's accepted.
2115
2326
  *
2116
2327
  * Logical, and it has to stay paired with the tab's own `end-0`: the tab is
2117
2328
  * portaled to `document.body`, so nothing but this axis agreement keeps the
2118
2329
  * space and the thing it is reserved for on the same side of the screen.
2119
2330
  */
2120
2331
  .editor-panel .editor-footer.reserve-keyboard-button-space {
2332
+ /* 3rem tab + 1rem margin */
2121
2333
  --keyboard-tab-reserve-width: 4rem;
2122
2334
  }
2335
+ @media (pointer: coarse) {
2336
+ .editor-panel .editor-footer.reserve-keyboard-button-space {
2337
+ /* 4rem tab + 1rem margin */
2338
+ --keyboard-tab-reserve-width: 5rem;
2339
+ }
2340
+ }
2123
2341
  .editor-panel .editor-footer.reserve-keyboard-button-space .footer-menu-button {
2124
2342
  margin-inline-end: var(--keyboard-tab-reserve-width);
2125
2343
  }
@@ -1,6 +1,6 @@
1
- import { u as useT, G as useRecordVisibilityChanges, p as jsxRuntimeExports, W as ToggleButtonGroup, U as ToggleButton, R as ActionButtonGroup, S as ActionButton } from "./doenetml-Is045YXP.js";
1
+ import { u as useT, G as useRecordVisibilityChanges, p as jsxRuntimeExports, W as ToggleButtonGroup, U as ToggleButton, R as ActionButtonGroup, S as ActionButton } from "./doenetml-Ta2HxqsQ.js";
2
2
  import React__default, { useState, useRef } from "react";
3
- import { u as useDoenetRenderer } from "./useDoenetRenderer-CdAHG5_i.js";
3
+ import { u as useDoenetRenderer } from "./useDoenetRenderer-BfN6AEqX.js";
4
4
  import { l as ltrIslandProps } from "./direction-BwrU7jHk.js";
5
5
  const subsetOfRealsInput = React__default.memo(function subsetOfReals(props) {
6
6
  let { id, SVs, actions, callAction } = useDoenetRenderer(props, false);
@@ -1,6 +1,6 @@
1
- import { u as useT, t as useChromeLangDir, G as useRecordVisibilityChanges, p as jsxRuntimeExports } from "./doenetml-Is045YXP.js";
1
+ import { u as useT, t as useChromeLangDir, G as useRecordVisibilityChanges, p as jsxRuntimeExports } from "./doenetml-Ta2HxqsQ.js";
2
2
  import React__default, { useRef } from "react";
3
- import { u as useDoenetRenderer } from "./useDoenetRenderer-CdAHG5_i.js";
3
+ import { u as useDoenetRenderer } from "./useDoenetRenderer-BfN6AEqX.js";
4
4
  import { s as sizeToCSS } from "./css-BJLDLYRJ.js";
5
5
  const summaryStatistics = React__default.memo(function SummaryStatistics(props) {
6
6
  let { id, SVs, actions, callAction } = useDoenetRenderer(props);
@@ -1,6 +1,6 @@
1
- import { G as useRecordVisibilityChanges, p as jsxRuntimeExports } from "./doenetml-Is045YXP.js";
1
+ import { G as useRecordVisibilityChanges, p as jsxRuntimeExports } from "./doenetml-Ta2HxqsQ.js";
2
2
  import React__default, { useRef } from "react";
3
- import { u as useDoenetRenderer } from "./useDoenetRenderer-CdAHG5_i.js";
3
+ import { u as useDoenetRenderer } from "./useDoenetRenderer-BfN6AEqX.js";
4
4
  const table = React__default.memo(function Table(props) {
5
5
  let { id, SVs, children, actions, callAction } = useDoenetRenderer(props);
6
6
  const ref = useRef(null);
@@ -1,6 +1,6 @@
1
- import { G as useRecordVisibilityChanges, p as jsxRuntimeExports } from "./doenetml-Is045YXP.js";
1
+ import { G as useRecordVisibilityChanges, p as jsxRuntimeExports } from "./doenetml-Ta2HxqsQ.js";
2
2
  import React__default, { useRef } from "react";
3
- import { u as useDoenetRenderer } from "./useDoenetRenderer-CdAHG5_i.js";
3
+ import { u as useDoenetRenderer } from "./useDoenetRenderer-BfN6AEqX.js";
4
4
  import { s as sizeToCSS } from "./css-BJLDLYRJ.js";
5
5
  import { a as getBlockMarginWithOptionalTopSuppression } from "./nonInlineMediaLayout-CkXHaqzo.js";
6
6
  const tabular = React__default.memo(function Tabular(props) {
@@ -1,6 +1,6 @@
1
- import { p as jsxRuntimeExports } from "./doenetml-Is045YXP.js";
1
+ import { p as jsxRuntimeExports } from "./doenetml-Ta2HxqsQ.js";
2
2
  import React__default from "react";
3
- import { u as useDoenetRenderer } from "./useDoenetRenderer-CdAHG5_i.js";
3
+ import { u as useDoenetRenderer } from "./useDoenetRenderer-BfN6AEqX.js";
4
4
  const tag = React__default.memo(function Tag(props) {
5
5
  let { id, SVs, children } = useDoenetRenderer(props);
6
6
  if (SVs.hidden) {
@@ -1,13 +1,13 @@
1
- import { z as DocContext, H as Context, p as jsxRuntimeExports, A as textRendererStyle } from "./doenetml-Is045YXP.js";
1
+ import { z as DocContext, H as Context, p as jsxRuntimeExports, A as textRendererStyle } from "./doenetml-Ta2HxqsQ.js";
2
2
  import React__default, { useRef, useContext } from "react";
3
- import { j as jxg } from "./JSXGraphRenderer-C9Ylgb9D.js";
4
- import { BoardContext, TEXT_LAYER_OFFSET } from "./graph-B-r2M3bu.js";
5
- import { u as useDoenetRenderer } from "./useDoenetRenderer-CdAHG5_i.js";
3
+ import { j as jxg } from "./JSXGraphRenderer-xzvpcvgx.js";
4
+ import { BoardContext, TEXT_LAYER_OFFSET } from "./graph-GEbrtd5f.js";
5
+ import { u as useDoenetRenderer } from "./useDoenetRenderer-BfN6AEqX.js";
6
6
  import { g as getPositionFromAnchorByCoordinate } from "./graph-W6vrFcBu.js";
7
- import { ChoiceInputInlineContext } from "./choiceInput-Crr3C-HF.js";
7
+ import { ChoiceInputInlineContext } from "./choiceInput-BrH7MTB7.js";
8
8
  import { u as usePointerDragState, a as useBoardPointerTracking } from "./useBoardPointerTracking-DV6a8Wvg.js";
9
9
  import { u as useDraggableRefs } from "./useDraggableRefs-QaTfkVuD.js";
10
- import { d as detachAnchoredGraphElement, a as attachAnchoredGraphDragHandlers } from "./useAnchoredGraphDragHandler-AXWt5rFu.js";
10
+ import { d as detachAnchoredGraphElement, a as attachAnchoredGraphDragHandlers } from "./useAnchoredGraphDragHandler-CnL8PGob.js";
11
11
  import { u as useJSXGraphCleanup } from "./useJSXGraphCleanup-BNk4sn6x.js";
12
12
  const text = React__default.memo(function Text(props) {
13
13
  let { componentIdx, id, SVs, actions, callAction } = useDoenetRenderer(props);
@@ -1,12 +1,12 @@
1
- import { F as useContentT, H as Context, p as jsxRuntimeExports, T as MathJax } from "./doenetml-Is045YXP.js";
1
+ import { F as useContentT, H as Context, p as jsxRuntimeExports, T as MathJax } from "./doenetml-Ta2HxqsQ.js";
2
2
  import { useState, useRef, useContext, useEffect } from "react";
3
- import { j as jxg } from "./JSXGraphRenderer-C9Ylgb9D.js";
4
- import { u as useDoenetRenderer } from "./useDoenetRenderer-CdAHG5_i.js";
3
+ import { j as jxg } from "./JSXGraphRenderer-xzvpcvgx.js";
4
+ import { u as useDoenetRenderer } from "./useDoenetRenderer-BfN6AEqX.js";
5
5
  import { s as sizeToCSS } from "./css-BJLDLYRJ.js";
6
- import { BoardContext } from "./graph-B-r2M3bu.js";
6
+ import { BoardContext } from "./graph-GEbrtd5f.js";
7
7
  import { g as getPositionFromAnchorByCoordinate, P as POINTER_DRAG_THRESHOLD } from "./graph-W6vrFcBu.js";
8
- import { c as calculateValidationState, u as useSubmitActionWithDelay, a as createCheckWorkComponent } from "./useSubmitActionWithDelay-CrrIiCmf.js";
9
- import { D as DescriptionPopover } from "./Description-DyPYa_ME.js";
8
+ import { c as calculateValidationState, u as useSubmitActionWithDelay, a as createCheckWorkComponent } from "./useSubmitActionWithDelay-Dq7IwApa.js";
9
+ import { D as DescriptionPopover } from "./Description-CZuMXIjw.js";
10
10
  import { a as addValidationStateToShortDescription } from "./validationState-DI_lxk1a.js";
11
11
  function TextInput(props) {
12
12
  let { id, SVs, children, actions, ignoreUpdate, callAction } = useDoenetRenderer(props);
@@ -1,4 +1,4 @@
1
- import { ae as createStoreContext, af as HovercardScopedContextProvider, ag as HovercardContextProvider, ah as createDialogComponent, Y as forwardRef, Z as createElement, $ as createHook, a1 as invariant, ai as useWrapElement, p as jsxRuntimeExports, a2 as useStoreState, aj as useHovercard, ak as isFalsyBooleanCallback, al as contains, am as sync, an as chain, ao as useEvent, ap as useHovercardAnchor, aq as createStore, ar as createHovercardStore, as as defaultValue, at as useStore, au as useStoreProps, av as useHovercardStoreProps } from "./doenetml-Is045YXP.js";
1
+ import { ae as createStoreContext, af as HovercardScopedContextProvider, ag as HovercardContextProvider, ah as createDialogComponent, Y as forwardRef, Z as createElement, $ as createHook, a1 as invariant, ai as useWrapElement, p as jsxRuntimeExports, a2 as useStoreState, aj as useHovercard, ak as isFalsyBooleanCallback, al as contains, am as sync, an as chain, ao as useEvent, ap as useHovercardAnchor, aq as createStore, ar as createHovercardStore, as as defaultValue, at as useStore, au as useStoreProps, av as useHovercardStoreProps } from "./doenetml-Ta2HxqsQ.js";
2
2
  import { useRef, useEffect } from "react";
3
3
  const ctx = createStoreContext([HovercardContextProvider], [HovercardScopedContextProvider]);
4
4
  const useTooltipProviderContext = ctx.useProviderContext;
@@ -1,4 +1,4 @@
1
- import { r as removeJXGEventHandlers, L as LINE_FAMILY_EVENTS, j as jxg } from "./JSXGraphRenderer-C9Ylgb9D.js";
1
+ import { r as removeJXGEventHandlers, L as LINE_FAMILY_EVENTS, j as jxg } from "./JSXGraphRenderer-xzvpcvgx.js";
2
2
  import { e as exceededDragThreshold, p as pointerEventToUserCoords } from "./dragThreshold-DuSSFrIU.js";
3
3
  function attachAnchoredGraphDragHandlers(params) {
4
4
  const {