@ckeditor/ckeditor5-ui 34.2.0 → 35.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +542 -0
  2. package/LICENSE.md +4 -0
  3. package/lang/contexts.json +4 -2
  4. package/lang/translations/ar.po +31 -23
  5. package/lang/translations/ast.po +12 -4
  6. package/lang/translations/az.po +12 -4
  7. package/lang/translations/bg.po +113 -0
  8. package/lang/translations/bn.po +113 -0
  9. package/lang/translations/ca.po +113 -0
  10. package/lang/translations/cs.po +12 -4
  11. package/lang/translations/da.po +12 -4
  12. package/lang/translations/de-ch.po +12 -4
  13. package/lang/translations/de.po +12 -4
  14. package/lang/translations/el.po +12 -4
  15. package/lang/translations/en-au.po +12 -4
  16. package/lang/translations/en-gb.po +12 -4
  17. package/lang/translations/en.po +12 -4
  18. package/lang/translations/eo.po +12 -4
  19. package/lang/translations/es.po +12 -4
  20. package/lang/translations/et.po +12 -4
  21. package/lang/translations/eu.po +12 -4
  22. package/lang/translations/fa.po +12 -4
  23. package/lang/translations/fi.po +14 -6
  24. package/lang/translations/fr.po +12 -4
  25. package/lang/translations/gl.po +12 -4
  26. package/lang/translations/he.po +26 -18
  27. package/lang/translations/hi.po +12 -4
  28. package/lang/translations/hr.po +12 -4
  29. package/lang/translations/hu.po +12 -4
  30. package/lang/translations/id.po +12 -4
  31. package/lang/translations/it.po +12 -4
  32. package/lang/translations/ja.po +17 -9
  33. package/lang/translations/km.po +12 -4
  34. package/lang/translations/kn.po +12 -4
  35. package/lang/translations/ko.po +12 -4
  36. package/lang/translations/ku.po +12 -4
  37. package/lang/translations/lt.po +16 -8
  38. package/lang/translations/lv.po +12 -4
  39. package/lang/translations/ms.po +113 -0
  40. package/lang/translations/nb.po +12 -4
  41. package/lang/translations/ne.po +12 -4
  42. package/lang/translations/nl.po +12 -4
  43. package/lang/translations/no.po +12 -4
  44. package/lang/translations/pl.po +12 -4
  45. package/lang/translations/pt-br.po +12 -4
  46. package/lang/translations/pt.po +29 -21
  47. package/lang/translations/ro.po +12 -4
  48. package/lang/translations/ru.po +12 -4
  49. package/lang/translations/sk.po +12 -4
  50. package/lang/translations/sl.po +11 -3
  51. package/lang/translations/sq.po +12 -4
  52. package/lang/translations/sr-latn.po +12 -4
  53. package/lang/translations/sr.po +12 -4
  54. package/lang/translations/sv.po +31 -23
  55. package/lang/translations/th.po +18 -10
  56. package/lang/translations/tk.po +12 -4
  57. package/lang/translations/tr.po +12 -4
  58. package/lang/translations/tt.po +113 -0
  59. package/lang/translations/ug.po +12 -4
  60. package/lang/translations/uk.po +12 -4
  61. package/lang/translations/ur.po +29 -21
  62. package/lang/translations/uz.po +12 -4
  63. package/lang/translations/vi.po +12 -4
  64. package/lang/translations/zh-cn.po +12 -4
  65. package/lang/translations/zh.po +12 -4
  66. package/package.json +23 -20
  67. package/src/bindings/addkeyboardhandlingforgrid.js +76 -0
  68. package/src/button/button.jsdoc +2 -2
  69. package/src/button/buttonview.js +19 -35
  70. package/src/colorgrid/colorgridview.js +19 -25
  71. package/src/dropdown/button/dropdownbuttonview.js +2 -1
  72. package/src/dropdown/button/splitbuttonview.js +4 -1
  73. package/src/dropdown/dropdownpanelview.js +22 -2
  74. package/src/dropdown/dropdownview.js +12 -2
  75. package/src/dropdown/utils.js +71 -1
  76. package/src/editableui/inline/inlineeditableuiview.js +18 -3
  77. package/src/icon/iconview.js +3 -1
  78. package/src/index.js +2 -2
  79. package/src/list/listitemview.js +14 -1
  80. package/src/panel/balloon/balloonpanelview.js +132 -78
  81. package/src/toolbar/balloon/balloontoolbar.js +17 -5
  82. package/src/toolbar/block/blocktoolbar.js +17 -0
  83. package/src/tooltipmanager.js +430 -0
  84. package/theme/components/button/button.css +0 -8
  85. package/theme/components/dropdown/dropdown.css +0 -12
  86. package/theme/components/dropdown/splitbutton.css +0 -7
  87. package/theme/components/responsive-form/responsiveform.css +28 -16
  88. package/theme/components/tooltip/tooltip.css +3 -26
  89. package/src/toolbar/enabletoolbarkeyboardfocus.js +0 -64
  90. package/src/tooltip/tooltipview.js +0 -107
  91. package/theme/components/tooltip/mixins/_tooltip.css +0 -54
@@ -392,60 +392,74 @@ function getDomElement( object ) {
392
392
  }
393
393
 
394
394
  /**
395
- * A horizontal offset of the arrow tip from the edge of the balloon. Controlled by CSS.
396
- *
397
- * +-----|---------...
398
- * | |
399
- * | |
400
- * | |
401
- * | |
402
- * +--+ | +------...
403
- * \ | /
404
- * \|/
405
- * >|-----|<---------------- horizontal offset
395
+ * A side offset of the arrow tip from the edge of the balloon. Controlled by CSS.
396
+ *
397
+ * ┌───────────────────────┐
398
+ * │ │
399
+ * │ Balloon │
400
+ * │ Content │
401
+ * │ │
402
+ * └──+ +───────────────┘
403
+ * | \ /
404
+ * | \/
405
+ * >┼─────┼< ─────────────────────── side offset
406
+ *
406
407
  *
407
408
  * @default 25
408
- * @member {Number} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowHorizontalOffset
409
+ * @member {Number} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowSideOffset
409
410
  */
410
- BalloonPanelView.arrowHorizontalOffset = 25;
411
+ BalloonPanelView.arrowSideOffset = 25;
411
412
 
412
413
  /**
413
- * A vertical offset of the arrow from the edge of the balloon. Controlled by CSS.
414
- *
415
- * +-------------...
416
- * |
417
- * |
418
- * | /-- vertical offset
419
- * | V
420
- * +--+ +-----... ---------
421
- * \ / |
422
- * \/ |
423
- * -------------------------------
424
- * ^
414
+ * A height offset of the arrow from the edge of the balloon. Controlled by CSS.
415
+ *
416
+ * ┌───────────────────────┐
417
+ * │ │
418
+ * │ Balloon │
419
+ * │ Content │ ╱-- arrow height offset
420
+ * │ │ V
421
+ * └──+ +───────────────┘ --- ─┼───────
422
+ * \ /
423
+ * \/
424
+ * ────────────────────────────────┼───────
425
+ * ^
426
+ *
427
+ *
428
+ * >┼────┼< arrow height offset
429
+ * │ │
430
+ * │ ┌────────────────────────┐
431
+ * │ │ │
432
+ * │ ╱ │
433
+ * │ ╱ Balloon │
434
+ * │ ╲ Content │
435
+ * │ ╲ │
436
+ * │ │ │
437
+ * │ └────────────────────────┘
438
+ *
425
439
  *
426
440
  * @default 10
427
- * @member {Number} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowVerticalOffset
441
+ * @member {Number} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowHeightOffset
428
442
  */
429
- BalloonPanelView.arrowVerticalOffset = 10;
443
+ BalloonPanelView.arrowHeightOffset = 10;
430
444
 
431
445
  /**
432
446
  * A vertical offset of the balloon panel from the edge of the viewport if sticky.
433
447
  * It helps in accessing toolbar buttons underneath the balloon panel.
434
448
  *
435
- * +---------------------------------------------------+
436
- * | Target |
437
- * | |
438
- * | /-- vertical offset |
439
- * +-----------------------------V-------------------------+
440
- * | Toolbar +-------------+ |
441
- * +--------------------| Balloon |--------------------+
442
- * | | +-------------+ | |
443
- * | | | |
444
- * | | | |
445
- * | | | |
446
- * | +---------------------------------------------------+ |
447
- * | Viewport |
448
- * +-------------------------------------------------------+
449
+ * ┌───────────────────────────────────────────────────┐
450
+ * Target
451
+ *
452
+ * /── vertical offset
453
+ * ┌─────────────────────────────V─────────────────────────┐
454
+ * Toolbar ┌─────────────┐
455
+ * ├────────────────────│ Balloon │────────────────────┤
456
+ * └─────────────┘
457
+ *
458
+ *
459
+ *
460
+ * └───────────────────────────────────────────────────┘
461
+ * Viewport
462
+ * └───────────────────────────────────────────────────────┘
449
463
  *
450
464
  * @default 20
451
465
  * @member {Number} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.stickyVerticalOffset
@@ -697,7 +711,7 @@ BalloonPanelView._getOptimalPosition = getOptimalPosition;
697
711
  * +-----------------+
698
712
  * | Balloon |
699
713
  * +-----------------+
700
- * * `southEastArrowNorthMiddleWest`
714
+ * * `southEastArrowNorthMiddleWest`
701
715
  *
702
716
  * [ Target ]
703
717
  * ^
@@ -729,6 +743,28 @@ BalloonPanelView._getOptimalPosition = getOptimalPosition;
729
743
  * | Balloon |
730
744
  * +-----------------+
731
745
  *
746
+ *
747
+ *
748
+ * **West**
749
+ *
750
+ * * `westArrowEast`
751
+ *
752
+ * +-----------------+
753
+ * | Balloon |>[ Target ]
754
+ * +-----------------+
755
+ *
756
+ * **East**
757
+ *
758
+ * * `eastArrowWest`
759
+ *
760
+ * +-----------------+
761
+ * [ Target ]<| Balloon |
762
+ * +-----------------+
763
+ *
764
+ *
765
+ *
766
+ * **Sticky**
767
+ *
732
768
  * * `viewportStickyNorth`
733
769
  *
734
770
  * +---------------------------+
@@ -756,35 +792,35 @@ BalloonPanelView._getOptimalPosition = getOptimalPosition;
756
792
  * The name that the position function returns will be reflected in the balloon panel's class that
757
793
  * controls the placement of the "arrow". See {@link #position} to learn more.
758
794
  *
759
- * @member {Object.<String,module:utils/dom/position~positioningFunction>}
795
+ * @member {Object.<String,module:utils/dom/position~PositioningFunction>}
760
796
  * module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions
761
797
  */
762
798
  BalloonPanelView.defaultPositions = generatePositions();
763
799
 
764
800
  /**
765
801
  * Returns available {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView}
766
- * {@link module:utils/dom/position~positioningFunction positioning functions} adjusted by the specific offsets.
802
+ * {@link module:utils/dom/position~PositioningFunction positioning functions} adjusted by the specific offsets.
767
803
  *
768
804
  * @protected
769
805
  * @param {Object} [options] Options to generate positions. If not specified, this helper will simply return
770
806
  * {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.
771
- * @param {Number} [options.horizontalOffset] A custom horizontal offset (in pixels) of each position. If
772
- * not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowHorizontalOffset the default value}
807
+ * @param {Number} [options.sideOffset] A custom side offset (in pixels) of each position. If
808
+ * not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowSideOffset the default value}
773
809
  * will be used.
774
- * @param {Number} [options.verticalOffset] A custom vertical offset (in pixels) of each position. If
775
- * not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowVerticalOffset the default value}
810
+ * @param {Number} [options.heightOffset] A custom height offset (in pixels) of each position. If
811
+ * not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowHeightOffset the default value}
776
812
  * will be used.
777
813
  * @param {Number} [options.stickyVerticalOffset] A custom offset (in pixels) of the `viewportStickyNorth` positioning function.
778
814
  * If not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.stickyVerticalOffset the default value}
779
815
  * will be used.
780
816
  * @param {Object} [options.config] Additional configuration of the balloon balloon panel view.
781
817
  * Currently only {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#withArrow} is supported. Learn more
782
- * about {@link module:utils/dom/position~positioningFunction positioning functions}.
783
- * @returns {Object.<String,module:utils/dom/position~positioningFunction>}
818
+ * about {@link module:utils/dom/position~PositioningFunction positioning functions}.
819
+ * @returns {Object.<String,module:utils/dom/position~PositioningFunction>}
784
820
  */
785
821
  export function generatePositions( {
786
- horizontalOffset = BalloonPanelView.arrowHorizontalOffset,
787
- verticalOffset = BalloonPanelView.arrowVerticalOffset,
822
+ sideOffset = BalloonPanelView.arrowSideOffset,
823
+ heightOffset = BalloonPanelView.arrowHeightOffset,
788
824
  stickyVerticalOffset = BalloonPanelView.stickyVerticalOffset,
789
825
  config
790
826
  } = {} ) {
@@ -793,14 +829,14 @@ export function generatePositions( {
793
829
 
794
830
  northWestArrowSouthWest: ( targetRect, balloonRect ) => ( {
795
831
  top: getNorthTop( targetRect, balloonRect ),
796
- left: targetRect.left - horizontalOffset,
832
+ left: targetRect.left - sideOffset,
797
833
  name: 'arrow_sw',
798
834
  ...( config && { config } )
799
835
  } ),
800
836
 
801
837
  northWestArrowSouthMiddleWest: ( targetRect, balloonRect ) => ( {
802
838
  top: getNorthTop( targetRect, balloonRect ),
803
- left: targetRect.left - ( balloonRect.width * .25 ) - horizontalOffset,
839
+ left: targetRect.left - ( balloonRect.width * .25 ) - sideOffset,
804
840
  name: 'arrow_smw',
805
841
  ...( config && { config } )
806
842
  } ),
@@ -814,14 +850,14 @@ export function generatePositions( {
814
850
 
815
851
  northWestArrowSouthMiddleEast: ( targetRect, balloonRect ) => ( {
816
852
  top: getNorthTop( targetRect, balloonRect ),
817
- left: targetRect.left - ( balloonRect.width * .75 ) + horizontalOffset,
853
+ left: targetRect.left - ( balloonRect.width * .75 ) + sideOffset,
818
854
  name: 'arrow_sme',
819
855
  ...( config && { config } )
820
856
  } ),
821
857
 
822
858
  northWestArrowSouthEast: ( targetRect, balloonRect ) => ( {
823
859
  top: getNorthTop( targetRect, balloonRect ),
824
- left: targetRect.left - balloonRect.width + horizontalOffset,
860
+ left: targetRect.left - balloonRect.width + sideOffset,
825
861
  name: 'arrow_se',
826
862
  ...( config && { config } )
827
863
  } ),
@@ -830,14 +866,14 @@ export function generatePositions( {
830
866
 
831
867
  northArrowSouthWest: ( targetRect, balloonRect ) => ( {
832
868
  top: getNorthTop( targetRect, balloonRect ),
833
- left: targetRect.left + targetRect.width / 2 - horizontalOffset,
869
+ left: targetRect.left + targetRect.width / 2 - sideOffset,
834
870
  name: 'arrow_sw',
835
871
  ...( config && { config } )
836
872
  } ),
837
873
 
838
874
  northArrowSouthMiddleWest: ( targetRect, balloonRect ) => ( {
839
875
  top: getNorthTop( targetRect, balloonRect ),
840
- left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * .25 ) - horizontalOffset,
876
+ left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * .25 ) - sideOffset,
841
877
  name: 'arrow_smw',
842
878
  ...( config && { config } )
843
879
  } ),
@@ -851,14 +887,14 @@ export function generatePositions( {
851
887
 
852
888
  northArrowSouthMiddleEast: ( targetRect, balloonRect ) => ( {
853
889
  top: getNorthTop( targetRect, balloonRect ),
854
- left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * .75 ) + horizontalOffset,
890
+ left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * .75 ) + sideOffset,
855
891
  name: 'arrow_sme',
856
892
  ...( config && { config } )
857
893
  } ),
858
894
 
859
895
  northArrowSouthEast: ( targetRect, balloonRect ) => ( {
860
896
  top: getNorthTop( targetRect, balloonRect ),
861
- left: targetRect.left + targetRect.width / 2 - balloonRect.width + horizontalOffset,
897
+ left: targetRect.left + targetRect.width / 2 - balloonRect.width + sideOffset,
862
898
  name: 'arrow_se',
863
899
  ...( config && { config } )
864
900
  } ),
@@ -867,14 +903,14 @@ export function generatePositions( {
867
903
 
868
904
  northEastArrowSouthWest: ( targetRect, balloonRect ) => ( {
869
905
  top: getNorthTop( targetRect, balloonRect ),
870
- left: targetRect.right - horizontalOffset,
906
+ left: targetRect.right - sideOffset,
871
907
  name: 'arrow_sw',
872
908
  ...( config && { config } )
873
909
  } ),
874
910
 
875
911
  northEastArrowSouthMiddleWest: ( targetRect, balloonRect ) => ( {
876
912
  top: getNorthTop( targetRect, balloonRect ),
877
- left: targetRect.right - ( balloonRect.width * .25 ) - horizontalOffset,
913
+ left: targetRect.right - ( balloonRect.width * .25 ) - sideOffset,
878
914
  name: 'arrow_smw',
879
915
  ...( config && { config } )
880
916
  } ),
@@ -888,14 +924,14 @@ export function generatePositions( {
888
924
 
889
925
  northEastArrowSouthMiddleEast: ( targetRect, balloonRect ) => ( {
890
926
  top: getNorthTop( targetRect, balloonRect ),
891
- left: targetRect.right - ( balloonRect.width * .75 ) + horizontalOffset,
927
+ left: targetRect.right - ( balloonRect.width * .75 ) + sideOffset,
892
928
  name: 'arrow_sme',
893
929
  ...( config && { config } )
894
930
  } ),
895
931
 
896
932
  northEastArrowSouthEast: ( targetRect, balloonRect ) => ( {
897
933
  top: getNorthTop( targetRect, balloonRect ),
898
- left: targetRect.right - balloonRect.width + horizontalOffset,
934
+ left: targetRect.right - balloonRect.width + sideOffset,
899
935
  name: 'arrow_se',
900
936
  ...( config && { config } )
901
937
  } ),
@@ -904,14 +940,14 @@ export function generatePositions( {
904
940
 
905
941
  southWestArrowNorthWest: ( targetRect, balloonRect ) => ( {
906
942
  top: getSouthTop( targetRect, balloonRect ),
907
- left: targetRect.left - horizontalOffset,
943
+ left: targetRect.left - sideOffset,
908
944
  name: 'arrow_nw',
909
945
  ...( config && { config } )
910
946
  } ),
911
947
 
912
948
  southWestArrowNorthMiddleWest: ( targetRect, balloonRect ) => ( {
913
949
  top: getSouthTop( targetRect, balloonRect ),
914
- left: targetRect.left - ( balloonRect.width * .25 ) - horizontalOffset,
950
+ left: targetRect.left - ( balloonRect.width * .25 ) - sideOffset,
915
951
  name: 'arrow_nmw',
916
952
  ...( config && { config } )
917
953
  } ),
@@ -925,14 +961,14 @@ export function generatePositions( {
925
961
 
926
962
  southWestArrowNorthMiddleEast: ( targetRect, balloonRect ) => ( {
927
963
  top: getSouthTop( targetRect, balloonRect ),
928
- left: targetRect.left - ( balloonRect.width * .75 ) + horizontalOffset,
964
+ left: targetRect.left - ( balloonRect.width * .75 ) + sideOffset,
929
965
  name: 'arrow_nme',
930
966
  ...( config && { config } )
931
967
  } ),
932
968
 
933
969
  southWestArrowNorthEast: ( targetRect, balloonRect ) => ( {
934
970
  top: getSouthTop( targetRect, balloonRect ),
935
- left: targetRect.left - balloonRect.width + horizontalOffset,
971
+ left: targetRect.left - balloonRect.width + sideOffset,
936
972
  name: 'arrow_ne',
937
973
  ...( config && { config } )
938
974
  } ),
@@ -941,14 +977,14 @@ export function generatePositions( {
941
977
 
942
978
  southArrowNorthWest: ( targetRect, balloonRect ) => ( {
943
979
  top: getSouthTop( targetRect, balloonRect ),
944
- left: targetRect.left + targetRect.width / 2 - horizontalOffset,
980
+ left: targetRect.left + targetRect.width / 2 - sideOffset,
945
981
  name: 'arrow_nw',
946
982
  ...( config && { config } )
947
983
  } ),
948
984
 
949
985
  southArrowNorthMiddleWest: ( targetRect, balloonRect ) => ( {
950
986
  top: getSouthTop( targetRect, balloonRect ),
951
- left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * 0.25 ) - horizontalOffset,
987
+ left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * 0.25 ) - sideOffset,
952
988
  name: 'arrow_nmw',
953
989
  ...( config && { config } )
954
990
  } ),
@@ -962,14 +998,14 @@ export function generatePositions( {
962
998
 
963
999
  southArrowNorthMiddleEast: ( targetRect, balloonRect ) => ( {
964
1000
  top: getSouthTop( targetRect, balloonRect ),
965
- left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * 0.75 ) + horizontalOffset,
1001
+ left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * 0.75 ) + sideOffset,
966
1002
  name: 'arrow_nme',
967
1003
  ...( config && { config } )
968
1004
  } ),
969
1005
 
970
1006
  southArrowNorthEast: ( targetRect, balloonRect ) => ( {
971
1007
  top: getSouthTop( targetRect, balloonRect ),
972
- left: targetRect.left + targetRect.width / 2 - balloonRect.width + horizontalOffset,
1008
+ left: targetRect.left + targetRect.width / 2 - balloonRect.width + sideOffset,
973
1009
  name: 'arrow_ne',
974
1010
  ...( config && { config } )
975
1011
  } ),
@@ -978,14 +1014,14 @@ export function generatePositions( {
978
1014
 
979
1015
  southEastArrowNorthWest: ( targetRect, balloonRect ) => ( {
980
1016
  top: getSouthTop( targetRect, balloonRect ),
981
- left: targetRect.right - horizontalOffset,
1017
+ left: targetRect.right - sideOffset,
982
1018
  name: 'arrow_nw',
983
1019
  ...( config && { config } )
984
1020
  } ),
985
1021
 
986
1022
  southEastArrowNorthMiddleWest: ( targetRect, balloonRect ) => ( {
987
1023
  top: getSouthTop( targetRect, balloonRect ),
988
- left: targetRect.right - ( balloonRect.width * .25 ) - horizontalOffset,
1024
+ left: targetRect.right - ( balloonRect.width * .25 ) - sideOffset,
989
1025
  name: 'arrow_nmw',
990
1026
  ...( config && { config } )
991
1027
  } ),
@@ -999,18 +1035,36 @@ export function generatePositions( {
999
1035
 
1000
1036
  southEastArrowNorthMiddleEast: ( targetRect, balloonRect ) => ( {
1001
1037
  top: getSouthTop( targetRect, balloonRect ),
1002
- left: targetRect.right - ( balloonRect.width * .75 ) + horizontalOffset,
1038
+ left: targetRect.right - ( balloonRect.width * .75 ) + sideOffset,
1003
1039
  name: 'arrow_nme',
1004
1040
  ...( config && { config } )
1005
1041
  } ),
1006
1042
 
1007
1043
  southEastArrowNorthEast: ( targetRect, balloonRect ) => ( {
1008
1044
  top: getSouthTop( targetRect, balloonRect ),
1009
- left: targetRect.right - balloonRect.width + horizontalOffset,
1045
+ left: targetRect.right - balloonRect.width + sideOffset,
1010
1046
  name: 'arrow_ne',
1011
1047
  ...( config && { config } )
1012
1048
  } ),
1013
1049
 
1050
+ // ------- West
1051
+
1052
+ westArrowEast: ( targetRect, balloonRect ) => ( {
1053
+ top: targetRect.top + targetRect.height / 2 - balloonRect.height / 2,
1054
+ left: targetRect.left - balloonRect.width - heightOffset,
1055
+ name: 'arrow_e',
1056
+ ...( config && { config } )
1057
+ } ),
1058
+
1059
+ // ------- East
1060
+
1061
+ eastArrowWest: ( targetRect, balloonRect ) => ( {
1062
+ top: targetRect.top + targetRect.height / 2 - balloonRect.height / 2,
1063
+ left: targetRect.right + heightOffset,
1064
+ name: 'arrow_w',
1065
+ ...( config && { config } )
1066
+ } ),
1067
+
1014
1068
  // ------- Sticky
1015
1069
 
1016
1070
  viewportStickyNorth: ( targetRect, balloonRect, viewportRect ) => {
@@ -1037,7 +1091,7 @@ export function generatePositions( {
1037
1091
  // @param {utils/dom/rect~Rect} elementRect A rect of the balloon.
1038
1092
  // @returns {Number}
1039
1093
  function getNorthTop( targetRect, balloonRect ) {
1040
- return targetRect.top - balloonRect.height - verticalOffset;
1094
+ return targetRect.top - balloonRect.height - heightOffset;
1041
1095
  }
1042
1096
 
1043
1097
  // Returns the top coordinate for positions starting with `south*`.
@@ -1047,6 +1101,6 @@ export function generatePositions( {
1047
1101
  // @param {utils/dom/rect~Rect} elementRect A rect of the balloon.
1048
1102
  // @returns {Number}
1049
1103
  function getSouthTop( targetRect ) {
1050
- return targetRect.bottom + verticalOffset;
1104
+ return targetRect.bottom + heightOffset;
1051
1105
  }
1052
1106
  }
@@ -79,6 +79,13 @@ export default class BalloonToolbar extends Plugin {
79
79
  this.focusTracker.add( this.toolbarView.element );
80
80
  } );
81
81
 
82
+ // Register the toolbar so it becomes available for Alt+F10 and Esc navigation.
83
+ editor.ui.addToolbar( this.toolbarView, {
84
+ beforeFocus: () => this.show( true ),
85
+ afterBlur: () => this.hide(),
86
+ isContextual: true
87
+ } );
88
+
82
89
  /**
83
90
  * An instance of the resize observer that allows to respond to changes in editable's geometry
84
91
  * so the toolbar can stay within its boundaries (and group toolbar items that do not fit).
@@ -196,12 +203,14 @@ export default class BalloonToolbar extends Plugin {
196
203
  * @returns {module:ui/toolbar/toolbarview~ToolbarView}
197
204
  */
198
205
  _createToolbarView() {
206
+ const t = this.editor.locale.t;
199
207
  const shouldGroupWhenFull = !this._balloonConfig.shouldNotGroupWhenFull;
200
208
  const toolbarView = new ToolbarView( this.editor.locale, {
201
209
  shouldGroupWhenFull,
202
210
  isFloating: true
203
211
  } );
204
212
 
213
+ toolbarView.ariaLabel = t( 'Editor contextual toolbar' );
205
214
  toolbarView.render();
206
215
 
207
216
  return toolbarView;
@@ -211,8 +220,11 @@ export default class BalloonToolbar extends Plugin {
211
220
  * Shows the toolbar and attaches it to the selection.
212
221
  *
213
222
  * Fires {@link #event:show} event which can be stopped to prevent the toolbar from showing up.
223
+ *
224
+ * @param {Boolean} [showForCollapsedSelection=false] When set `true`, the toolbar will show despite collapsed selection in the
225
+ * editing view.
214
226
  */
215
- show() {
227
+ show( showForCollapsedSelection = false ) {
216
228
  const editor = this.editor;
217
229
  const selection = editor.model.document.selection;
218
230
  const schema = editor.model.schema;
@@ -223,7 +235,7 @@ export default class BalloonToolbar extends Plugin {
223
235
  }
224
236
 
225
237
  // Do not show the toolbar when the selection is collapsed.
226
- if ( selection.isCollapsed ) {
238
+ if ( selection.isCollapsed && !showForCollapsedSelection ) {
227
239
  return;
228
240
  }
229
241
 
@@ -361,8 +373,8 @@ export default class BalloonToolbar extends Plugin {
361
373
  const positions = isSafariIniOS ? generatePositions( {
362
374
  // 20px when zoomed out. Less then 20px when zoomed in; the "radius" of the native selection handle gets
363
375
  // smaller as the user zooms in. No less than the default v-offset, though.
364
- verticalOffset: Math.max(
365
- BalloonPanelView.arrowVerticalOffset,
376
+ heightOffset: Math.max(
377
+ BalloonPanelView.arrowHeightOffset,
366
378
  Math.round( 20 / global.window.visualViewport.scale )
367
379
  )
368
380
  } ) : BalloonPanelView.defaultPositions;
@@ -426,7 +438,7 @@ function selectionContainsOnlyMultipleSelectables( selection, schema ) {
426
438
  * You can also use `'|'` to create a separator between groups of items:
427
439
  *
428
440
  * const config = {
429
- * balloonToolbar: [ 'bold', 'italic', | 'undo', 'redo' ]
441
+ * balloonToolbar: [ 'bold', 'italic', '|', 'undo', 'redo' ]
430
442
  * };
431
443
  *
432
444
  * Read also about configuring the main editor toolbar in {@link module:core/editor/editorconfig~EditorConfig#toolbar}.
@@ -166,6 +166,12 @@ export default class BlockToolbar extends Plugin {
166
166
  this._hidePanel();
167
167
  }
168
168
  } );
169
+
170
+ // Register the toolbar so it becomes available for Alt+F10 and Esc navigation.
171
+ editor.ui.addToolbar( this.toolbarView, {
172
+ beforeFocus: () => this._showPanel(),
173
+ afterBlur: () => this._hidePanel()
174
+ } );
169
175
  }
170
176
 
171
177
  /**
@@ -221,12 +227,15 @@ export default class BlockToolbar extends Plugin {
221
227
  * @returns {module:ui/toolbar/toolbarview~ToolbarView}
222
228
  */
223
229
  _createToolbarView() {
230
+ const t = this.editor.locale.t;
224
231
  const shouldGroupWhenFull = !this._blockToolbarConfig.shouldNotGroupWhenFull;
225
232
  const toolbarView = new ToolbarView( this.editor.locale, {
226
233
  shouldGroupWhenFull,
227
234
  isFloating: true
228
235
  } );
229
236
 
237
+ toolbarView.ariaLabel = t( 'Editor block content toolbar' );
238
+
230
239
  // When toolbar lost focus then panel should hide.
231
240
  toolbarView.focusTracker.on( 'change:isFocused', ( evt, name, is ) => {
232
241
  if ( !is ) {
@@ -363,6 +372,14 @@ export default class BlockToolbar extends Plugin {
363
372
  * @private
364
373
  */
365
374
  _showPanel() {
375
+ // Usually, the only way to show the toolbar is by pressing the block button. It makes it impossible for
376
+ // the toolbar to show up when the button is invisible (feature does not make sense for the selection then).
377
+ // The toolbar navigation using Alt+F10 does not access the button but shows the panel directly using this method.
378
+ // So we need to check whether this is possible first.
379
+ if ( !this.buttonView.isVisible ) {
380
+ return;
381
+ }
382
+
366
383
  const wasVisible = this.panelView.isVisible;
367
384
 
368
385
  // So here's the thing: If there was no initial panelView#show() or these two were in different order, the toolbar