@ckeditor/ckeditor5-ui 31.0.0 → 31.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.
@@ -0,0 +1,105 @@
1
+ # Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ #
3
+ # !!! IMPORTANT !!!
4
+ #
5
+ # Before you edit this file, please keep in mind that contributing to the project
6
+ # translations is possible ONLY via the Transifex online service.
7
+ #
8
+ # To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
9
+ #
10
+ # To learn more, check out the official contributor's guide:
11
+ # https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
12
+ #
13
+ msgid ""
14
+ msgstr ""
15
+ "Language-Team: Uzbek (https://www.transifex.com/ckeditor/teams/11143/uz/)\n"
16
+ "Language: uz\n"
17
+ "Plural-Forms: nplurals=1; plural=0;\n"
18
+
19
+ msgctxt "Title of the CKEditor5 editor."
20
+ msgid "Rich Text Editor, %0"
21
+ msgstr "Tahrirlovchi, %0"
22
+
23
+ msgctxt "Title of the CKEditor5 editor."
24
+ msgid "Rich Text Editor"
25
+ msgstr "Tahrirlovchi"
26
+
27
+ msgctxt "Label of the block toolbar icon (a block toolbar is displayed next to each paragraph, heading, list item, etc. and contains e.g. block formatting options)"
28
+ msgid "Edit block"
29
+ msgstr "Blokni tahrirlash"
30
+
31
+ msgctxt "Label for a button showing the next thing (tab, page, etc.)."
32
+ msgid "Next"
33
+ msgstr "Keyingi"
34
+
35
+ msgctxt "Label for a button showing the previous thing (tab, page, etc.)."
36
+ msgid "Previous"
37
+ msgstr "Oldingi"
38
+
39
+ msgctxt "Label used by assistive technologies describing a generic editor toolbar."
40
+ msgid "Editor toolbar"
41
+ msgstr "Tahrirlovchi asboblar paneli"
42
+
43
+ msgctxt "Label used by assistive technologies describing a toolbar displayed inside a dropdown."
44
+ msgid "Dropdown toolbar"
45
+ msgstr "Ochiladigan asboblar paneli"
46
+
47
+ msgctxt "Label of a button that applies a black color in color pickers."
48
+ msgid "Black"
49
+ msgstr "Qora"
50
+
51
+ msgctxt "Label of a button that applies a dim grey color in color pickers."
52
+ msgid "Dim grey"
53
+ msgstr "To'q kulrang"
54
+
55
+ msgctxt "Label of a button that applies a grey color in color pickers."
56
+ msgid "Grey"
57
+ msgstr "Kulrang"
58
+
59
+ msgctxt "Label of a button that applies a light grey color in color pickers."
60
+ msgid "Light grey"
61
+ msgstr "Och kulrang"
62
+
63
+ msgctxt "Label of a button that applies a white color in color pickers."
64
+ msgid "White"
65
+ msgstr "Oq"
66
+
67
+ msgctxt "Label of a button that applies a red color in color pickers."
68
+ msgid "Red"
69
+ msgstr "Qizil"
70
+
71
+ msgctxt "Label of a button that applies a orange color in color pickers."
72
+ msgid "Orange"
73
+ msgstr "To'q sariq"
74
+
75
+ msgctxt "Label of a button that applies a yellow color in color pickers."
76
+ msgid "Yellow"
77
+ msgstr "Sariq"
78
+
79
+ msgctxt "Label of a button that applies a light green color in color pickers."
80
+ msgid "Light green"
81
+ msgstr "Och yashil"
82
+
83
+ msgctxt "Label of a button that applies a green color in color pickers."
84
+ msgid "Green"
85
+ msgstr "Yashil"
86
+
87
+ msgctxt "Label of a button that applies a aquamarine color in color pickers."
88
+ msgid "Aquamarine"
89
+ msgstr "Akuamarin"
90
+
91
+ msgctxt "Label of a button that applies a turquoise color in color pickers."
92
+ msgid "Turquoise"
93
+ msgstr "Turkuaz"
94
+
95
+ msgctxt "Label of a button that applies a light blue color in color pickers."
96
+ msgid "Light blue"
97
+ msgstr "Moviy"
98
+
99
+ msgctxt "Label of a button that applies a blue color in color pickers."
100
+ msgid "Blue"
101
+ msgstr "Ko'k"
102
+
103
+ msgctxt "Label of a button that applies a purple color in color pickers."
104
+ msgid "Purple"
105
+ msgstr "Siyohrang"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-ui",
3
- "version": "31.0.0",
3
+ "version": "31.1.0",
4
4
  "description": "The UI framework and standard UI library of CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -11,27 +11,27 @@
11
11
  ],
12
12
  "main": "src/index.js",
13
13
  "dependencies": {
14
- "@ckeditor/ckeditor5-utils": "^31.0.0",
15
- "@ckeditor/ckeditor5-core": "^31.0.0",
14
+ "@ckeditor/ckeditor5-utils": "^31.1.0",
15
+ "@ckeditor/ckeditor5-core": "^31.1.0",
16
16
  "lodash-es": "^4.17.15"
17
17
  },
18
18
  "devDependencies": {
19
- "@ckeditor/ckeditor5-basic-styles": "^31.0.0",
20
- "@ckeditor/ckeditor5-block-quote": "^31.0.0",
21
- "@ckeditor/ckeditor5-editor-balloon": "^31.0.0",
22
- "@ckeditor/ckeditor5-editor-classic": "^31.0.0",
23
- "@ckeditor/ckeditor5-engine": "^31.0.0",
24
- "@ckeditor/ckeditor5-enter": "^31.0.0",
25
- "@ckeditor/ckeditor5-essentials": "^31.0.0",
26
- "@ckeditor/ckeditor5-heading": "^31.0.0",
27
- "@ckeditor/ckeditor5-image": "^31.0.0",
28
- "@ckeditor/ckeditor5-link": "^31.0.0",
29
- "@ckeditor/ckeditor5-list": "^31.0.0",
30
- "@ckeditor/ckeditor5-mention": "^31.0.0",
31
- "@ckeditor/ckeditor5-paragraph": "^31.0.0",
32
- "@ckeditor/ckeditor5-horizontal-line": "^31.0.0",
33
- "@ckeditor/ckeditor5-table": "^31.0.0",
34
- "@ckeditor/ckeditor5-typing": "^31.0.0"
19
+ "@ckeditor/ckeditor5-basic-styles": "^31.1.0",
20
+ "@ckeditor/ckeditor5-block-quote": "^31.1.0",
21
+ "@ckeditor/ckeditor5-editor-balloon": "^31.1.0",
22
+ "@ckeditor/ckeditor5-editor-classic": "^31.1.0",
23
+ "@ckeditor/ckeditor5-engine": "^31.1.0",
24
+ "@ckeditor/ckeditor5-enter": "^31.1.0",
25
+ "@ckeditor/ckeditor5-essentials": "^31.1.0",
26
+ "@ckeditor/ckeditor5-heading": "^31.1.0",
27
+ "@ckeditor/ckeditor5-image": "^31.1.0",
28
+ "@ckeditor/ckeditor5-link": "^31.1.0",
29
+ "@ckeditor/ckeditor5-list": "^31.1.0",
30
+ "@ckeditor/ckeditor5-mention": "^31.1.0",
31
+ "@ckeditor/ckeditor5-paragraph": "^31.1.0",
32
+ "@ckeditor/ckeditor5-horizontal-line": "^31.1.0",
33
+ "@ckeditor/ckeditor5-table": "^31.1.0",
34
+ "@ckeditor/ckeditor5-typing": "^31.1.0"
35
35
  },
36
36
  "engines": {
37
37
  "node": ">=12.0.0",
@@ -176,6 +176,16 @@ export default class ColorGridView extends View {
176
176
  this.keystrokes.listenTo( this.element );
177
177
  }
178
178
 
179
+ /**
180
+ * @inheritDoc
181
+ */
182
+ destroy() {
183
+ super.destroy();
184
+
185
+ this.focusTracker.destroy();
186
+ this.keystrokes.destroy();
187
+ }
188
+
179
189
  /**
180
190
  * Fired when the `ColorTileView` for the picked item is executed.
181
191
  *
@@ -155,6 +155,16 @@ export default class SplitButtonView extends View {
155
155
  } );
156
156
  }
157
157
 
158
+ /**
159
+ * @inheritDoc
160
+ */
161
+ destroy() {
162
+ super.destroy();
163
+
164
+ this.focusTracker.destroy();
165
+ this.keystrokes.destroy();
166
+ }
167
+
158
168
  /**
159
169
  * Focuses the {@link #actionView#element} of the action part of split button.
160
170
  */
@@ -160,6 +160,15 @@ export default class InputTextView extends View {
160
160
  } );
161
161
  }
162
162
 
163
+ /**
164
+ * @inheritDoc
165
+ */
166
+ destroy() {
167
+ super.destroy();
168
+
169
+ this.focusTracker.destroy();
170
+ }
171
+
163
172
  /**
164
173
  * Moves the focus to the input and selects the value.
165
174
  */
@@ -109,6 +109,16 @@ export default class ListView extends View {
109
109
  this.keystrokes.listenTo( this.element );
110
110
  }
111
111
 
112
+ /**
113
+ * @inheritDoc
114
+ */
115
+ destroy() {
116
+ super.destroy();
117
+
118
+ this.focusTracker.destroy();
119
+ this.keystrokes.destroy();
120
+ }
121
+
112
122
  /**
113
123
  * Focuses the first focusable in {@link #items}.
114
124
  */
@@ -750,239 +750,303 @@ BalloonPanelView._getOptimalPosition = getOptimalPosition;
750
750
  *
751
751
  * Positioning functions must be compatible with {@link module:utils/dom/position~Position}.
752
752
  *
753
+ * Default positioning functions with customized offsets can be generated using
754
+ * {@link module:ui/panel/balloon/balloonpanelview~generatePositions}.
755
+ *
753
756
  * The name that the position function returns will be reflected in the balloon panel's class that
754
757
  * controls the placement of the "arrow". See {@link #position} to learn more.
755
758
  *
756
759
  * @member {Object.<String,module:utils/dom/position~positioningFunction>}
757
760
  * module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions
758
761
  */
759
- BalloonPanelView.defaultPositions = {
760
-
761
- // ------- North west
762
-
763
- northWestArrowSouthWest: ( targetRect, balloonRect ) => ( {
764
- top: getNorthTop( targetRect, balloonRect ),
765
- left: targetRect.left - BalloonPanelView.arrowHorizontalOffset,
766
- name: 'arrow_sw'
767
- } ),
768
-
769
- northWestArrowSouthMiddleWest: ( targetRect, balloonRect ) => ( {
770
- top: getNorthTop( targetRect, balloonRect ),
771
- left: targetRect.left - ( balloonRect.width * .25 ) - BalloonPanelView.arrowHorizontalOffset,
772
- name: 'arrow_smw'
773
- } ),
774
-
775
- northWestArrowSouth: ( targetRect, balloonRect ) => ( {
776
- top: getNorthTop( targetRect, balloonRect ),
777
- left: targetRect.left - balloonRect.width / 2,
778
- name: 'arrow_s'
779
- } ),
780
-
781
- northWestArrowSouthMiddleEast: ( targetRect, balloonRect ) => ( {
782
- top: getNorthTop( targetRect, balloonRect ),
783
- left: targetRect.left - ( balloonRect.width * .75 ) + BalloonPanelView.arrowHorizontalOffset,
784
- name: 'arrow_sme'
785
- } ),
786
-
787
- northWestArrowSouthEast: ( targetRect, balloonRect ) => ( {
788
- top: getNorthTop( targetRect, balloonRect ),
789
- left: targetRect.left - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,
790
- name: 'arrow_se'
791
- } ),
792
-
793
- // ------- North
794
-
795
- northArrowSouthWest: ( targetRect, balloonRect ) => ( {
796
- top: getNorthTop( targetRect, balloonRect ),
797
- left: targetRect.left + targetRect.width / 2 - BalloonPanelView.arrowHorizontalOffset,
798
- name: 'arrow_sw'
799
- } ),
800
-
801
- northArrowSouthMiddleWest: ( targetRect, balloonRect ) => ( {
802
- top: getNorthTop( targetRect, balloonRect ),
803
- left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * .25 ) - BalloonPanelView.arrowHorizontalOffset,
804
- name: 'arrow_smw'
805
- } ),
806
-
807
- northArrowSouth: ( targetRect, balloonRect ) => ( {
808
- top: getNorthTop( targetRect, balloonRect ),
809
- left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
810
- name: 'arrow_s'
811
- } ),
812
-
813
- northArrowSouthMiddleEast: ( targetRect, balloonRect ) => ( {
814
- top: getNorthTop( targetRect, balloonRect ),
815
- left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * .75 ) + BalloonPanelView.arrowHorizontalOffset,
816
- name: 'arrow_sme'
817
- } ),
818
-
819
- northArrowSouthEast: ( targetRect, balloonRect ) => ( {
820
- top: getNorthTop( targetRect, balloonRect ),
821
- left: targetRect.left + targetRect.width / 2 - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,
822
- name: 'arrow_se'
823
- } ),
824
-
825
- // ------- North east
826
-
827
- northEastArrowSouthWest: ( targetRect, balloonRect ) => ( {
828
- top: getNorthTop( targetRect, balloonRect ),
829
- left: targetRect.right - BalloonPanelView.arrowHorizontalOffset,
830
- name: 'arrow_sw'
831
- } ),
832
-
833
- northEastArrowSouthMiddleWest: ( targetRect, balloonRect ) => ( {
834
- top: getNorthTop( targetRect, balloonRect ),
835
- left: targetRect.right - ( balloonRect.width * .25 ) - BalloonPanelView.arrowHorizontalOffset,
836
- name: 'arrow_smw'
837
- } ),
838
-
839
- northEastArrowSouth: ( targetRect, balloonRect ) => ( {
840
- top: getNorthTop( targetRect, balloonRect ),
841
- left: targetRect.right - balloonRect.width / 2,
842
- name: 'arrow_s'
843
- } ),
844
-
845
- northEastArrowSouthMiddleEast: ( targetRect, balloonRect ) => ( {
846
- top: getNorthTop( targetRect, balloonRect ),
847
- left: targetRect.right - ( balloonRect.width * .75 ) + BalloonPanelView.arrowHorizontalOffset,
848
- name: 'arrow_sme'
849
- } ),
850
-
851
- northEastArrowSouthEast: ( targetRect, balloonRect ) => ( {
852
- top: getNorthTop( targetRect, balloonRect ),
853
- left: targetRect.right - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,
854
- name: 'arrow_se'
855
- } ),
856
-
857
- // ------- South west
858
-
859
- southWestArrowNorthWest: ( targetRect, balloonRect ) => ( {
860
- top: getSouthTop( targetRect, balloonRect ),
861
- left: targetRect.left - BalloonPanelView.arrowHorizontalOffset,
862
- name: 'arrow_nw'
863
- } ),
864
-
865
- southWestArrowNorthMiddleWest: ( targetRect, balloonRect ) => ( {
866
- top: getSouthTop( targetRect, balloonRect ),
867
- left: targetRect.left - ( balloonRect.width * .25 ) - BalloonPanelView.arrowHorizontalOffset,
868
- name: 'arrow_nmw'
869
- } ),
870
-
871
- southWestArrowNorth: ( targetRect, balloonRect ) => ( {
872
- top: getSouthTop( targetRect, balloonRect ),
873
- left: targetRect.left - balloonRect.width / 2,
874
- name: 'arrow_n'
875
- } ),
876
-
877
- southWestArrowNorthMiddleEast: ( targetRect, balloonRect ) => ( {
878
- top: getSouthTop( targetRect, balloonRect ),
879
- left: targetRect.left - ( balloonRect.width * .75 ) + BalloonPanelView.arrowHorizontalOffset,
880
- name: 'arrow_nme'
881
- } ),
882
-
883
- southWestArrowNorthEast: ( targetRect, balloonRect ) => ( {
884
- top: getSouthTop( targetRect, balloonRect ),
885
- left: targetRect.left - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,
886
- name: 'arrow_ne'
887
- } ),
888
-
889
- // ------- South
890
-
891
- southArrowNorthWest: ( targetRect, balloonRect ) => ( {
892
- top: getSouthTop( targetRect, balloonRect ),
893
- left: targetRect.left + targetRect.width / 2 - BalloonPanelView.arrowHorizontalOffset,
894
- name: 'arrow_nw'
895
- } ),
896
- southArrowNorthMiddleWest: ( targetRect, balloonRect ) => ( {
897
- top: getSouthTop( targetRect, balloonRect ),
898
- left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * 0.25 ) - BalloonPanelView.arrowHorizontalOffset,
899
- name: 'arrow_nmw'
900
- } ),
901
-
902
- southArrowNorth: ( targetRect, balloonRect ) => ( {
903
- top: getSouthTop( targetRect, balloonRect ),
904
- left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
905
- name: 'arrow_n'
906
- } ),
907
-
908
- southArrowNorthMiddleEast: ( targetRect, balloonRect ) => ( {
909
- top: getSouthTop( targetRect, balloonRect ),
910
- left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * 0.75 ) + BalloonPanelView.arrowHorizontalOffset,
911
- name: 'arrow_nme'
912
- } ),
913
-
914
- southArrowNorthEast: ( targetRect, balloonRect ) => ( {
915
- top: getSouthTop( targetRect, balloonRect ),
916
- left: targetRect.left + targetRect.width / 2 - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,
917
- name: 'arrow_ne'
918
- } ),
919
-
920
- // ------- South east
921
-
922
- southEastArrowNorthWest: ( targetRect, balloonRect ) => ( {
923
- top: getSouthTop( targetRect, balloonRect ),
924
- left: targetRect.right - BalloonPanelView.arrowHorizontalOffset,
925
- name: 'arrow_nw'
926
- } ),
927
-
928
- southEastArrowNorthMiddleWest: ( targetRect, balloonRect ) => ( {
929
- top: getSouthTop( targetRect, balloonRect ),
930
- left: targetRect.right - ( balloonRect.width * .25 ) - BalloonPanelView.arrowHorizontalOffset,
931
- name: 'arrow_nmw'
932
- } ),
933
-
934
- southEastArrowNorth: ( targetRect, balloonRect ) => ( {
935
- top: getSouthTop( targetRect, balloonRect ),
936
- left: targetRect.right - balloonRect.width / 2,
937
- name: 'arrow_n'
938
- } ),
939
-
940
- southEastArrowNorthMiddleEast: ( targetRect, balloonRect ) => ( {
941
- top: getSouthTop( targetRect, balloonRect ),
942
- left: targetRect.right - ( balloonRect.width * .75 ) + BalloonPanelView.arrowHorizontalOffset,
943
- name: 'arrow_nme'
944
- } ),
945
-
946
- southEastArrowNorthEast: ( targetRect, balloonRect ) => ( {
947
- top: getSouthTop( targetRect, balloonRect ),
948
- left: targetRect.right - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,
949
- name: 'arrow_ne'
950
- } ),
951
-
952
- // ------- Sticky
953
-
954
- viewportStickyNorth: ( targetRect, balloonRect, viewportRect ) => {
955
- if ( !targetRect.getIntersection( viewportRect ) ) {
956
- return null;
957
- }
762
+ BalloonPanelView.defaultPositions = generatePositions();
958
763
 
959
- return {
960
- top: viewportRect.top + BalloonPanelView.stickyVerticalOffset,
764
+ /**
765
+ * Returns available {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView}
766
+ * {@link module:utils/dom/position~positioningFunction positioning functions} adjusted by the specific offsets.
767
+ *
768
+ * @protected
769
+ * @param {Object} [options] Options to generate positions. If not specified, this helper will simply return
770
+ * {@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}
773
+ * 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}
776
+ * will be used.
777
+ * @param {Number} [options.stickyVerticalOffset] A custom offset (in pixels) of the `viewportStickyNorth` positioning function.
778
+ * If not specified, {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.stickyVerticalOffset the default value}
779
+ * will be used.
780
+ * @param {Object} [options.config] Additional configuration of the balloon balloon panel view.
781
+ * 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>}
784
+ */
785
+ export function generatePositions( {
786
+ horizontalOffset = BalloonPanelView.arrowHorizontalOffset,
787
+ verticalOffset = BalloonPanelView.arrowVerticalOffset,
788
+ stickyVerticalOffset = BalloonPanelView.stickyVerticalOffset,
789
+ config
790
+ } = {} ) {
791
+ return {
792
+ // ------- North west
793
+
794
+ northWestArrowSouthWest: ( targetRect, balloonRect ) => ( {
795
+ top: getNorthTop( targetRect, balloonRect ),
796
+ left: targetRect.left - horizontalOffset,
797
+ name: 'arrow_sw',
798
+ ...( config && { config } )
799
+ } ),
800
+
801
+ northWestArrowSouthMiddleWest: ( targetRect, balloonRect ) => ( {
802
+ top: getNorthTop( targetRect, balloonRect ),
803
+ left: targetRect.left - ( balloonRect.width * .25 ) - horizontalOffset,
804
+ name: 'arrow_smw',
805
+ ...( config && { config } )
806
+ } ),
807
+
808
+ northWestArrowSouth: ( targetRect, balloonRect ) => ( {
809
+ top: getNorthTop( targetRect, balloonRect ),
810
+ left: targetRect.left - balloonRect.width / 2,
811
+ name: 'arrow_s',
812
+ ...( config && { config } )
813
+ } ),
814
+
815
+ northWestArrowSouthMiddleEast: ( targetRect, balloonRect ) => ( {
816
+ top: getNorthTop( targetRect, balloonRect ),
817
+ left: targetRect.left - ( balloonRect.width * .75 ) + horizontalOffset,
818
+ name: 'arrow_sme',
819
+ ...( config && { config } )
820
+ } ),
821
+
822
+ northWestArrowSouthEast: ( targetRect, balloonRect ) => ( {
823
+ top: getNorthTop( targetRect, balloonRect ),
824
+ left: targetRect.left - balloonRect.width + horizontalOffset,
825
+ name: 'arrow_se',
826
+ ...( config && { config } )
827
+ } ),
828
+
829
+ // ------- North
830
+
831
+ northArrowSouthWest: ( targetRect, balloonRect ) => ( {
832
+ top: getNorthTop( targetRect, balloonRect ),
833
+ left: targetRect.left + targetRect.width / 2 - horizontalOffset,
834
+ name: 'arrow_sw',
835
+ ...( config && { config } )
836
+ } ),
837
+
838
+ northArrowSouthMiddleWest: ( targetRect, balloonRect ) => ( {
839
+ top: getNorthTop( targetRect, balloonRect ),
840
+ left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * .25 ) - horizontalOffset,
841
+ name: 'arrow_smw',
842
+ ...( config && { config } )
843
+ } ),
844
+
845
+ northArrowSouth: ( targetRect, balloonRect ) => ( {
846
+ top: getNorthTop( targetRect, balloonRect ),
847
+ left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
848
+ name: 'arrow_s',
849
+ ...( config && { config } )
850
+ } ),
851
+
852
+ northArrowSouthMiddleEast: ( targetRect, balloonRect ) => ( {
853
+ top: getNorthTop( targetRect, balloonRect ),
854
+ left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * .75 ) + horizontalOffset,
855
+ name: 'arrow_sme',
856
+ ...( config && { config } )
857
+ } ),
858
+
859
+ northArrowSouthEast: ( targetRect, balloonRect ) => ( {
860
+ top: getNorthTop( targetRect, balloonRect ),
861
+ left: targetRect.left + targetRect.width / 2 - balloonRect.width + horizontalOffset,
862
+ name: 'arrow_se',
863
+ ...( config && { config } )
864
+ } ),
865
+
866
+ // ------- North east
867
+
868
+ northEastArrowSouthWest: ( targetRect, balloonRect ) => ( {
869
+ top: getNorthTop( targetRect, balloonRect ),
870
+ left: targetRect.right - horizontalOffset,
871
+ name: 'arrow_sw',
872
+ ...( config && { config } )
873
+ } ),
874
+
875
+ northEastArrowSouthMiddleWest: ( targetRect, balloonRect ) => ( {
876
+ top: getNorthTop( targetRect, balloonRect ),
877
+ left: targetRect.right - ( balloonRect.width * .25 ) - horizontalOffset,
878
+ name: 'arrow_smw',
879
+ ...( config && { config } )
880
+ } ),
881
+
882
+ northEastArrowSouth: ( targetRect, balloonRect ) => ( {
883
+ top: getNorthTop( targetRect, balloonRect ),
884
+ left: targetRect.right - balloonRect.width / 2,
885
+ name: 'arrow_s',
886
+ ...( config && { config } )
887
+ } ),
888
+
889
+ northEastArrowSouthMiddleEast: ( targetRect, balloonRect ) => ( {
890
+ top: getNorthTop( targetRect, balloonRect ),
891
+ left: targetRect.right - ( balloonRect.width * .75 ) + horizontalOffset,
892
+ name: 'arrow_sme',
893
+ ...( config && { config } )
894
+ } ),
895
+
896
+ northEastArrowSouthEast: ( targetRect, balloonRect ) => ( {
897
+ top: getNorthTop( targetRect, balloonRect ),
898
+ left: targetRect.right - balloonRect.width + horizontalOffset,
899
+ name: 'arrow_se',
900
+ ...( config && { config } )
901
+ } ),
902
+
903
+ // ------- South west
904
+
905
+ southWestArrowNorthWest: ( targetRect, balloonRect ) => ( {
906
+ top: getSouthTop( targetRect, balloonRect ),
907
+ left: targetRect.left - horizontalOffset,
908
+ name: 'arrow_nw',
909
+ ...( config && { config } )
910
+ } ),
911
+
912
+ southWestArrowNorthMiddleWest: ( targetRect, balloonRect ) => ( {
913
+ top: getSouthTop( targetRect, balloonRect ),
914
+ left: targetRect.left - ( balloonRect.width * .25 ) - horizontalOffset,
915
+ name: 'arrow_nmw',
916
+ ...( config && { config } )
917
+ } ),
918
+
919
+ southWestArrowNorth: ( targetRect, balloonRect ) => ( {
920
+ top: getSouthTop( targetRect, balloonRect ),
921
+ left: targetRect.left - balloonRect.width / 2,
922
+ name: 'arrow_n',
923
+ ...( config && { config } )
924
+ } ),
925
+
926
+ southWestArrowNorthMiddleEast: ( targetRect, balloonRect ) => ( {
927
+ top: getSouthTop( targetRect, balloonRect ),
928
+ left: targetRect.left - ( balloonRect.width * .75 ) + horizontalOffset,
929
+ name: 'arrow_nme',
930
+ ...( config && { config } )
931
+ } ),
932
+
933
+ southWestArrowNorthEast: ( targetRect, balloonRect ) => ( {
934
+ top: getSouthTop( targetRect, balloonRect ),
935
+ left: targetRect.left - balloonRect.width + horizontalOffset,
936
+ name: 'arrow_ne',
937
+ ...( config && { config } )
938
+ } ),
939
+
940
+ // ------- South
941
+
942
+ southArrowNorthWest: ( targetRect, balloonRect ) => ( {
943
+ top: getSouthTop( targetRect, balloonRect ),
944
+ left: targetRect.left + targetRect.width / 2 - horizontalOffset,
945
+ name: 'arrow_nw',
946
+ ...( config && { config } )
947
+ } ),
948
+
949
+ southArrowNorthMiddleWest: ( targetRect, balloonRect ) => ( {
950
+ top: getSouthTop( targetRect, balloonRect ),
951
+ left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * 0.25 ) - horizontalOffset,
952
+ name: 'arrow_nmw',
953
+ ...( config && { config } )
954
+ } ),
955
+
956
+ southArrowNorth: ( targetRect, balloonRect ) => ( {
957
+ top: getSouthTop( targetRect, balloonRect ),
961
958
  left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
962
- name: 'arrowless',
963
- config: {
964
- withArrow: false
959
+ name: 'arrow_n',
960
+ ...( config && { config } )
961
+ } ),
962
+
963
+ southArrowNorthMiddleEast: ( targetRect, balloonRect ) => ( {
964
+ top: getSouthTop( targetRect, balloonRect ),
965
+ left: targetRect.left + targetRect.width / 2 - ( balloonRect.width * 0.75 ) + horizontalOffset,
966
+ name: 'arrow_nme',
967
+ ...( config && { config } )
968
+ } ),
969
+
970
+ southArrowNorthEast: ( targetRect, balloonRect ) => ( {
971
+ top: getSouthTop( targetRect, balloonRect ),
972
+ left: targetRect.left + targetRect.width / 2 - balloonRect.width + horizontalOffset,
973
+ name: 'arrow_ne',
974
+ ...( config && { config } )
975
+ } ),
976
+
977
+ // ------- South east
978
+
979
+ southEastArrowNorthWest: ( targetRect, balloonRect ) => ( {
980
+ top: getSouthTop( targetRect, balloonRect ),
981
+ left: targetRect.right - horizontalOffset,
982
+ name: 'arrow_nw',
983
+ ...( config && { config } )
984
+ } ),
985
+
986
+ southEastArrowNorthMiddleWest: ( targetRect, balloonRect ) => ( {
987
+ top: getSouthTop( targetRect, balloonRect ),
988
+ left: targetRect.right - ( balloonRect.width * .25 ) - horizontalOffset,
989
+ name: 'arrow_nmw',
990
+ ...( config && { config } )
991
+ } ),
992
+
993
+ southEastArrowNorth: ( targetRect, balloonRect ) => ( {
994
+ top: getSouthTop( targetRect, balloonRect ),
995
+ left: targetRect.right - balloonRect.width / 2,
996
+ name: 'arrow_n',
997
+ ...( config && { config } )
998
+ } ),
999
+
1000
+ southEastArrowNorthMiddleEast: ( targetRect, balloonRect ) => ( {
1001
+ top: getSouthTop( targetRect, balloonRect ),
1002
+ left: targetRect.right - ( balloonRect.width * .75 ) + horizontalOffset,
1003
+ name: 'arrow_nme',
1004
+ ...( config && { config } )
1005
+ } ),
1006
+
1007
+ southEastArrowNorthEast: ( targetRect, balloonRect ) => ( {
1008
+ top: getSouthTop( targetRect, balloonRect ),
1009
+ left: targetRect.right - balloonRect.width + horizontalOffset,
1010
+ name: 'arrow_ne',
1011
+ ...( config && { config } )
1012
+ } ),
1013
+
1014
+ // ------- Sticky
1015
+
1016
+ viewportStickyNorth: ( targetRect, balloonRect, viewportRect ) => {
1017
+ if ( !targetRect.getIntersection( viewportRect ) ) {
1018
+ return null;
965
1019
  }
966
- };
967
- }
968
- };
969
1020
 
970
- // Returns the top coordinate for positions starting with `north*`.
971
- //
972
- // @private
973
- // @param {utils/dom/rect~Rect} targetRect A rect of the target.
974
- // @param {utils/dom/rect~Rect} elementRect A rect of the balloon.
975
- // @returns {Number}
976
- function getNorthTop( targetRect, balloonRect ) {
977
- return targetRect.top - balloonRect.height - BalloonPanelView.arrowVerticalOffset;
978
- }
1021
+ return {
1022
+ top: viewportRect.top + stickyVerticalOffset,
1023
+ left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
1024
+ name: 'arrowless',
1025
+ config: {
1026
+ withArrow: false,
1027
+ ...config
1028
+ }
1029
+ };
1030
+ }
1031
+ };
1032
+
1033
+ // Returns the top coordinate for positions starting with `north*`.
1034
+ //
1035
+ // @private
1036
+ // @param {utils/dom/rect~Rect} targetRect A rect of the target.
1037
+ // @param {utils/dom/rect~Rect} elementRect A rect of the balloon.
1038
+ // @returns {Number}
1039
+ function getNorthTop( targetRect, balloonRect ) {
1040
+ return targetRect.top - balloonRect.height - verticalOffset;
1041
+ }
979
1042
 
980
- // Returns the top coordinate for positions starting with `south*`.
981
- //
982
- // @private
983
- // @param {utils/dom/rect~Rect} targetRect A rect of the target.
984
- // @param {utils/dom/rect~Rect} elementRect A rect of the balloon.
985
- // @returns {Number}
986
- function getSouthTop( targetRect ) {
987
- return targetRect.bottom + BalloonPanelView.arrowVerticalOffset;
1043
+ // Returns the top coordinate for positions starting with `south*`.
1044
+ //
1045
+ // @private
1046
+ // @param {utils/dom/rect~Rect} targetRect A rect of the target.
1047
+ // @param {utils/dom/rect~Rect} elementRect A rect of the balloon.
1048
+ // @returns {Number}
1049
+ function getSouthTop( targetRect ) {
1050
+ return targetRect.bottom + verticalOffset;
1051
+ }
988
1052
  }
@@ -170,6 +170,17 @@ export default class ContextualBalloon extends Plugin {
170
170
  this._fakePanelsView = this._createFakePanelsView();
171
171
  }
172
172
 
173
+ /**
174
+ * @inheritDoc
175
+ */
176
+ destroy() {
177
+ super.destroy();
178
+
179
+ this.view.destroy();
180
+ this._rotatorView.destroy();
181
+ this._fakePanelsView.destroy();
182
+ }
183
+
173
184
  /**
174
185
  * Returns `true` when the given view is in one of the stacks. Otherwise returns `false`.
175
186
  *
@@ -628,6 +639,15 @@ class RotatorView extends View {
628
639
  this.focusTracker.add( this.element );
629
640
  }
630
641
 
642
+ /**
643
+ * @inheritDoc
644
+ */
645
+ destroy() {
646
+ super.destroy();
647
+
648
+ this.focusTracker.destroy();
649
+ }
650
+
631
651
  /**
632
652
  * Shows a given view.
633
653
  *
@@ -10,13 +10,14 @@
10
10
  import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
11
11
  import ContextualBalloon from '../../panel/balloon/contextualballoon';
12
12
  import ToolbarView from '../toolbarview';
13
- import BalloonPanelView from '../../panel/balloon/balloonpanelview.js';
13
+ import BalloonPanelView, { generatePositions } from '../../panel/balloon/balloonpanelview.js';
14
14
  import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
15
15
  import Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';
16
16
  import normalizeToolbarConfig from '../normalizetoolbarconfig';
17
17
  import { debounce } from 'lodash-es';
18
18
  import ResizeObserver from '@ckeditor/ckeditor5-utils/src/dom/resizeobserver';
19
19
  import toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit';
20
+ import { env, global } from '@ckeditor/ckeditor5-utils';
20
21
 
21
22
  const toPx = toUnit( 'px' );
22
23
 
@@ -300,7 +301,7 @@ export default class BalloonToolbar extends Plugin {
300
301
  return rangeRects[ rangeRects.length - 1 ];
301
302
  }
302
303
  },
303
- positions: getBalloonPositions( isBackward )
304
+ positions: this._getBalloonPositions( isBackward )
304
305
  };
305
306
  }
306
307
 
@@ -345,39 +346,51 @@ export default class BalloonToolbar extends Plugin {
345
346
  * @protected
346
347
  * @event _selectionChangeDebounced
347
348
  */
348
- }
349
349
 
350
- // Returns toolbar positions for the given direction of the selection.
351
- //
352
- // @private
353
- // @param {Boolean} isBackward
354
- // @returns {Array.<module:utils/dom/position~Position>}
355
- function getBalloonPositions( isBackward ) {
356
- const defaultPositions = BalloonPanelView.defaultPositions;
357
-
358
- return isBackward ? [
359
- defaultPositions.northWestArrowSouth,
360
- defaultPositions.northWestArrowSouthWest,
361
- defaultPositions.northWestArrowSouthEast,
362
- defaultPositions.northWestArrowSouthMiddleEast,
363
- defaultPositions.northWestArrowSouthMiddleWest,
364
- defaultPositions.southWestArrowNorth,
365
- defaultPositions.southWestArrowNorthWest,
366
- defaultPositions.southWestArrowNorthEast,
367
- defaultPositions.southWestArrowNorthMiddleWest,
368
- defaultPositions.southWestArrowNorthMiddleEast
369
- ] : [
370
- defaultPositions.southEastArrowNorth,
371
- defaultPositions.southEastArrowNorthEast,
372
- defaultPositions.southEastArrowNorthWest,
373
- defaultPositions.southEastArrowNorthMiddleEast,
374
- defaultPositions.southEastArrowNorthMiddleWest,
375
- defaultPositions.northEastArrowSouth,
376
- defaultPositions.northEastArrowSouthEast,
377
- defaultPositions.northEastArrowSouthWest,
378
- defaultPositions.northEastArrowSouthMiddleEast,
379
- defaultPositions.northEastArrowSouthMiddleWest
380
- ];
350
+ /**
351
+ * Returns toolbar positions for the given direction of the selection.
352
+ *
353
+ * @private
354
+ * @param {Boolean} isBackward
355
+ * @returns {Array.<module:utils/dom/position~Position>}
356
+ */
357
+ _getBalloonPositions( isBackward ) {
358
+ const isSafariIniOS = env.isSafari && env.isiOS;
359
+
360
+ // https://github.com/ckeditor/ckeditor5/issues/7707
361
+ const positions = isSafariIniOS ? generatePositions( {
362
+ // 20px when zoomed out. Less then 20px when zoomed in; the "radius" of the native selection handle gets
363
+ // smaller as the user zooms in. No less than the default v-offset, though.
364
+ verticalOffset: Math.max(
365
+ BalloonPanelView.arrowVerticalOffset,
366
+ Math.round( 20 / global.window.visualViewport.scale )
367
+ )
368
+ } ) : BalloonPanelView.defaultPositions;
369
+
370
+ return isBackward ? [
371
+ positions.northWestArrowSouth,
372
+ positions.northWestArrowSouthWest,
373
+ positions.northWestArrowSouthEast,
374
+ positions.northWestArrowSouthMiddleEast,
375
+ positions.northWestArrowSouthMiddleWest,
376
+ positions.southWestArrowNorth,
377
+ positions.southWestArrowNorthWest,
378
+ positions.southWestArrowNorthEast,
379
+ positions.southWestArrowNorthMiddleWest,
380
+ positions.southWestArrowNorthMiddleEast
381
+ ] : [
382
+ positions.southEastArrowNorth,
383
+ positions.southEastArrowNorthEast,
384
+ positions.southEastArrowNorthWest,
385
+ positions.southEastArrowNorthMiddleEast,
386
+ positions.southEastArrowNorthMiddleWest,
387
+ positions.northEastArrowSouth,
388
+ positions.northEastArrowSouthEast,
389
+ positions.northEastArrowSouthWest,
390
+ positions.northEastArrowSouthMiddleEast,
391
+ positions.northEastArrowSouthMiddleWest
392
+ ];
393
+ }
381
394
  }
382
395
 
383
396
  // Returns "true" when the selection has multiple ranges and each range contains a selectable element
@@ -259,6 +259,8 @@ export default class ToolbarView extends View {
259
259
  */
260
260
  destroy() {
261
261
  this._behavior.destroy();
262
+ this.focusTracker.destroy();
263
+ this.keystrokes.destroy();
262
264
 
263
265
  return super.destroy();
264
266
  }