@ckeditor/ckeditor5-widget 0.0.0-internal-20241017.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.
Potentially problematic release.
This version of @ckeditor/ckeditor5-widget might be problematic. Click here for more details.
- package/CHANGELOG.md +4 -0
- package/LICENSE.md +21 -0
- package/README.md +22 -0
- package/dist/augmentation.d.ts +17 -0
- package/dist/highlightstack.d.ts +78 -0
- package/dist/index-content.css +4 -0
- package/dist/index-editor.css +183 -0
- package/dist/index.css +257 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +3054 -0
- package/dist/index.js.map +1 -0
- package/dist/translations/ar.d.ts +8 -0
- package/dist/translations/ar.js +5 -0
- package/dist/translations/ar.umd.js +11 -0
- package/dist/translations/az.d.ts +8 -0
- package/dist/translations/az.js +5 -0
- package/dist/translations/az.umd.js +11 -0
- package/dist/translations/bg.d.ts +8 -0
- package/dist/translations/bg.js +5 -0
- package/dist/translations/bg.umd.js +11 -0
- package/dist/translations/bn.d.ts +8 -0
- package/dist/translations/bn.js +5 -0
- package/dist/translations/bn.umd.js +11 -0
- package/dist/translations/ca.d.ts +8 -0
- package/dist/translations/ca.js +5 -0
- package/dist/translations/ca.umd.js +11 -0
- package/dist/translations/cs.d.ts +8 -0
- package/dist/translations/cs.js +5 -0
- package/dist/translations/cs.umd.js +11 -0
- package/dist/translations/da.d.ts +8 -0
- package/dist/translations/da.js +5 -0
- package/dist/translations/da.umd.js +11 -0
- package/dist/translations/de-ch.d.ts +8 -0
- package/dist/translations/de-ch.js +5 -0
- package/dist/translations/de-ch.umd.js +11 -0
- package/dist/translations/de.d.ts +8 -0
- package/dist/translations/de.js +5 -0
- package/dist/translations/de.umd.js +11 -0
- package/dist/translations/el.d.ts +8 -0
- package/dist/translations/el.js +5 -0
- package/dist/translations/el.umd.js +11 -0
- package/dist/translations/en-au.d.ts +8 -0
- package/dist/translations/en-au.js +5 -0
- package/dist/translations/en-au.umd.js +11 -0
- package/dist/translations/en.d.ts +8 -0
- package/dist/translations/en.js +5 -0
- package/dist/translations/en.umd.js +11 -0
- package/dist/translations/es.d.ts +8 -0
- package/dist/translations/es.js +5 -0
- package/dist/translations/es.umd.js +11 -0
- package/dist/translations/et.d.ts +8 -0
- package/dist/translations/et.js +5 -0
- package/dist/translations/et.umd.js +11 -0
- package/dist/translations/fa.d.ts +8 -0
- package/dist/translations/fa.js +5 -0
- package/dist/translations/fa.umd.js +11 -0
- package/dist/translations/fi.d.ts +8 -0
- package/dist/translations/fi.js +5 -0
- package/dist/translations/fi.umd.js +11 -0
- package/dist/translations/fr.d.ts +8 -0
- package/dist/translations/fr.js +5 -0
- package/dist/translations/fr.umd.js +11 -0
- package/dist/translations/gl.d.ts +8 -0
- package/dist/translations/gl.js +5 -0
- package/dist/translations/gl.umd.js +11 -0
- package/dist/translations/he.d.ts +8 -0
- package/dist/translations/he.js +5 -0
- package/dist/translations/he.umd.js +11 -0
- package/dist/translations/hi.d.ts +8 -0
- package/dist/translations/hi.js +5 -0
- package/dist/translations/hi.umd.js +11 -0
- package/dist/translations/hr.d.ts +8 -0
- package/dist/translations/hr.js +5 -0
- package/dist/translations/hr.umd.js +11 -0
- package/dist/translations/hu.d.ts +8 -0
- package/dist/translations/hu.js +5 -0
- package/dist/translations/hu.umd.js +11 -0
- package/dist/translations/id.d.ts +8 -0
- package/dist/translations/id.js +5 -0
- package/dist/translations/id.umd.js +11 -0
- package/dist/translations/it.d.ts +8 -0
- package/dist/translations/it.js +5 -0
- package/dist/translations/it.umd.js +11 -0
- package/dist/translations/ja.d.ts +8 -0
- package/dist/translations/ja.js +5 -0
- package/dist/translations/ja.umd.js +11 -0
- package/dist/translations/ko.d.ts +8 -0
- package/dist/translations/ko.js +5 -0
- package/dist/translations/ko.umd.js +11 -0
- package/dist/translations/ku.d.ts +8 -0
- package/dist/translations/ku.js +5 -0
- package/dist/translations/ku.umd.js +11 -0
- package/dist/translations/lt.d.ts +8 -0
- package/dist/translations/lt.js +5 -0
- package/dist/translations/lt.umd.js +11 -0
- package/dist/translations/lv.d.ts +8 -0
- package/dist/translations/lv.js +5 -0
- package/dist/translations/lv.umd.js +11 -0
- package/dist/translations/ms.d.ts +8 -0
- package/dist/translations/ms.js +5 -0
- package/dist/translations/ms.umd.js +11 -0
- package/dist/translations/nl.d.ts +8 -0
- package/dist/translations/nl.js +5 -0
- package/dist/translations/nl.umd.js +11 -0
- package/dist/translations/no.d.ts +8 -0
- package/dist/translations/no.js +5 -0
- package/dist/translations/no.umd.js +11 -0
- package/dist/translations/pl.d.ts +8 -0
- package/dist/translations/pl.js +5 -0
- package/dist/translations/pl.umd.js +11 -0
- package/dist/translations/pt-br.d.ts +8 -0
- package/dist/translations/pt-br.js +5 -0
- package/dist/translations/pt-br.umd.js +11 -0
- package/dist/translations/pt.d.ts +8 -0
- package/dist/translations/pt.js +5 -0
- package/dist/translations/pt.umd.js +11 -0
- package/dist/translations/ro.d.ts +8 -0
- package/dist/translations/ro.js +5 -0
- package/dist/translations/ro.umd.js +11 -0
- package/dist/translations/ru.d.ts +8 -0
- package/dist/translations/ru.js +5 -0
- package/dist/translations/ru.umd.js +11 -0
- package/dist/translations/sk.d.ts +8 -0
- package/dist/translations/sk.js +5 -0
- package/dist/translations/sk.umd.js +11 -0
- package/dist/translations/sq.d.ts +8 -0
- package/dist/translations/sq.js +5 -0
- package/dist/translations/sq.umd.js +11 -0
- package/dist/translations/sr-latn.d.ts +8 -0
- package/dist/translations/sr-latn.js +5 -0
- package/dist/translations/sr-latn.umd.js +11 -0
- package/dist/translations/sr.d.ts +8 -0
- package/dist/translations/sr.js +5 -0
- package/dist/translations/sr.umd.js +11 -0
- package/dist/translations/sv.d.ts +8 -0
- package/dist/translations/sv.js +5 -0
- package/dist/translations/sv.umd.js +11 -0
- package/dist/translations/th.d.ts +8 -0
- package/dist/translations/th.js +5 -0
- package/dist/translations/th.umd.js +11 -0
- package/dist/translations/tk.d.ts +8 -0
- package/dist/translations/tk.js +5 -0
- package/dist/translations/tk.umd.js +11 -0
- package/dist/translations/tr.d.ts +8 -0
- package/dist/translations/tr.js +5 -0
- package/dist/translations/tr.umd.js +11 -0
- package/dist/translations/uk.d.ts +8 -0
- package/dist/translations/uk.js +5 -0
- package/dist/translations/uk.umd.js +11 -0
- package/dist/translations/ur.d.ts +8 -0
- package/dist/translations/ur.js +5 -0
- package/dist/translations/ur.umd.js +11 -0
- package/dist/translations/uz.d.ts +8 -0
- package/dist/translations/uz.js +5 -0
- package/dist/translations/uz.umd.js +11 -0
- package/dist/translations/vi.d.ts +8 -0
- package/dist/translations/vi.js +5 -0
- package/dist/translations/vi.umd.js +11 -0
- package/dist/translations/zh-cn.d.ts +8 -0
- package/dist/translations/zh-cn.js +5 -0
- package/dist/translations/zh-cn.umd.js +11 -0
- package/dist/translations/zh.d.ts +8 -0
- package/dist/translations/zh.js +5 -0
- package/dist/translations/zh.umd.js +11 -0
- package/dist/utils.d.ts +219 -0
- package/dist/verticalnavigation.d.ts +19 -0
- package/dist/widget.d.ts +111 -0
- package/dist/widgetresize/resizer.d.ts +181 -0
- package/dist/widgetresize/resizerstate.d.ts +129 -0
- package/dist/widgetresize/sizeview.d.ts +59 -0
- package/dist/widgetresize.d.ts +133 -0
- package/dist/widgettoolbarrepository.d.ts +102 -0
- package/dist/widgettypearound/utils.d.ts +42 -0
- package/dist/widgettypearound/widgettypearound.d.ts +237 -0
- package/lang/contexts.json +12 -0
- package/lang/translations/ar.po +58 -0
- package/lang/translations/az.po +58 -0
- package/lang/translations/bg.po +58 -0
- package/lang/translations/bn.po +58 -0
- package/lang/translations/ca.po +58 -0
- package/lang/translations/cs.po +58 -0
- package/lang/translations/da.po +58 -0
- package/lang/translations/de-ch.po +58 -0
- package/lang/translations/de.po +58 -0
- package/lang/translations/el.po +58 -0
- package/lang/translations/en-au.po +58 -0
- package/lang/translations/en.po +58 -0
- package/lang/translations/es.po +58 -0
- package/lang/translations/et.po +58 -0
- package/lang/translations/fa.po +58 -0
- package/lang/translations/fi.po +58 -0
- package/lang/translations/fr.po +58 -0
- package/lang/translations/gl.po +58 -0
- package/lang/translations/he.po +58 -0
- package/lang/translations/hi.po +58 -0
- package/lang/translations/hr.po +58 -0
- package/lang/translations/hu.po +58 -0
- package/lang/translations/id.po +58 -0
- package/lang/translations/it.po +58 -0
- package/lang/translations/ja.po +58 -0
- package/lang/translations/ko.po +58 -0
- package/lang/translations/ku.po +58 -0
- package/lang/translations/lt.po +58 -0
- package/lang/translations/lv.po +58 -0
- package/lang/translations/ms.po +58 -0
- package/lang/translations/nl.po +58 -0
- package/lang/translations/no.po +58 -0
- package/lang/translations/pl.po +58 -0
- package/lang/translations/pt-br.po +58 -0
- package/lang/translations/pt.po +58 -0
- package/lang/translations/ro.po +58 -0
- package/lang/translations/ru.po +58 -0
- package/lang/translations/sk.po +58 -0
- package/lang/translations/sq.po +58 -0
- package/lang/translations/sr-latn.po +58 -0
- package/lang/translations/sr.po +58 -0
- package/lang/translations/sv.po +58 -0
- package/lang/translations/th.po +58 -0
- package/lang/translations/tk.po +58 -0
- package/lang/translations/tr.po +58 -0
- package/lang/translations/uk.po +58 -0
- package/lang/translations/ur.po +58 -0
- package/lang/translations/uz.po +58 -0
- package/lang/translations/vi.po +58 -0
- package/lang/translations/zh-cn.po +58 -0
- package/lang/translations/zh.po +58 -0
- package/package.json +42 -0
- package/src/augmentation.d.ts +13 -0
- package/src/augmentation.js +5 -0
- package/src/highlightstack.d.ts +74 -0
- package/src/highlightstack.js +129 -0
- package/src/index.d.ts +13 -0
- package/src/index.js +13 -0
- package/src/utils.d.ts +215 -0
- package/src/utils.js +396 -0
- package/src/verticalnavigation.d.ts +15 -0
- package/src/verticalnavigation.js +196 -0
- package/src/widget.d.ts +107 -0
- package/src/widget.js +603 -0
- package/src/widgetresize/resizer.d.ts +177 -0
- package/src/widgetresize/resizer.js +372 -0
- package/src/widgetresize/resizerstate.d.ts +125 -0
- package/src/widgetresize/resizerstate.js +129 -0
- package/src/widgetresize/sizeview.d.ts +55 -0
- package/src/widgetresize/sizeview.js +63 -0
- package/src/widgetresize.d.ts +129 -0
- package/src/widgetresize.js +194 -0
- package/src/widgettoolbarrepository.d.ts +98 -0
- package/src/widgettoolbarrepository.js +274 -0
- package/src/widgettypearound/utils.d.ts +38 -0
- package/src/widgettypearound/utils.js +52 -0
- package/src/widgettypearound/widgettypearound.d.ts +233 -0
- package/src/widgettypearound/widgettypearound.js +779 -0
- package/theme/icons/drag-handle.svg +1 -0
- package/theme/icons/return-arrow.svg +1 -0
- package/theme/widget.css +91 -0
- package/theme/widgetresize.css +43 -0
- package/theme/widgettypearound.css +113 -0
package/src/utils.d.ts
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module widget/utils
|
7
|
+
*/
|
8
|
+
import { Rect, type GetCallback } from '@ckeditor/ckeditor5-utils';
|
9
|
+
import { type HighlightDescriptor, type MapperViewToModelPositionEvent, type DocumentSelection, type DowncastWriter, type Model, type Range, type Selection, type ViewEditableElement, type ViewElement, type ViewTypeCheckable } from '@ckeditor/ckeditor5-engine';
|
10
|
+
/**
|
11
|
+
* CSS class added to each widget element.
|
12
|
+
*/
|
13
|
+
export declare const WIDGET_CLASS_NAME = "ck-widget";
|
14
|
+
/**
|
15
|
+
* CSS class added to currently selected widget element.
|
16
|
+
*/
|
17
|
+
export declare const WIDGET_SELECTED_CLASS_NAME = "ck-widget_selected";
|
18
|
+
/**
|
19
|
+
* Returns `true` if given {@link module:engine/view/node~Node} is an {@link module:engine/view/element~Element} and a widget.
|
20
|
+
*/
|
21
|
+
export declare function isWidget(node: ViewTypeCheckable): boolean;
|
22
|
+
/**
|
23
|
+
* Converts the given {@link module:engine/view/element~Element} to a widget in the following way:
|
24
|
+
*
|
25
|
+
* * sets the `contenteditable` attribute to `"false"`,
|
26
|
+
* * adds the `ck-widget` CSS class,
|
27
|
+
* * adds a custom {@link module:engine/view/element~Element#getFillerOffset `getFillerOffset()`} method returning `null`,
|
28
|
+
* * adds a custom property allowing to recognize widget elements by using {@link ~isWidget `isWidget()`},
|
29
|
+
* * implements the {@link ~setHighlightHandling view highlight on widgets}.
|
30
|
+
*
|
31
|
+
* This function needs to be used in conjunction with
|
32
|
+
* {@link module:engine/conversion/downcasthelpers~DowncastHelpers downcast conversion helpers}
|
33
|
+
* like {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`}.
|
34
|
+
* Moreover, typically you will want to use `toWidget()` only for `editingDowncast`, while keeping the `dataDowncast` clean.
|
35
|
+
*
|
36
|
+
* For example, in order to convert a `<widget>` model element to `<div class="widget">` in the view, you can define
|
37
|
+
* such converters:
|
38
|
+
*
|
39
|
+
* ```ts
|
40
|
+
* editor.conversion.for( 'editingDowncast' )
|
41
|
+
* .elementToElement( {
|
42
|
+
* model: 'widget',
|
43
|
+
* view: ( modelItem, { writer } ) => {
|
44
|
+
* const div = writer.createContainerElement( 'div', { class: 'widget' } );
|
45
|
+
*
|
46
|
+
* return toWidget( div, writer, { label: 'some widget' } );
|
47
|
+
* }
|
48
|
+
* } );
|
49
|
+
*
|
50
|
+
* editor.conversion.for( 'dataDowncast' )
|
51
|
+
* .elementToElement( {
|
52
|
+
* model: 'widget',
|
53
|
+
* view: ( modelItem, { writer } ) => {
|
54
|
+
* return writer.createContainerElement( 'div', { class: 'widget' } );
|
55
|
+
* }
|
56
|
+
* } );
|
57
|
+
* ```
|
58
|
+
*
|
59
|
+
* See the full source code of the widget (with a nested editable) schema definition and converters in
|
60
|
+
* [this sample](https://github.com/ckeditor/ckeditor5-widget/blob/master/tests/manual/widget-with-nestededitable.js).
|
61
|
+
*
|
62
|
+
* @param options Additional options.
|
63
|
+
* @param options.label Element's label provided to the {@link ~setLabel} function. It can be passed as
|
64
|
+
* a plain string or a function returning a string. It represents the widget for assistive technologies (like screen readers).
|
65
|
+
* @param options.hasSelectionHandle If `true`, the widget will have a selection handle added.
|
66
|
+
* @returns Returns the same element.
|
67
|
+
*/
|
68
|
+
export declare function toWidget(element: ViewElement, writer: DowncastWriter, options?: {
|
69
|
+
label?: string | (() => string);
|
70
|
+
hasSelectionHandle?: boolean;
|
71
|
+
}): ViewElement;
|
72
|
+
/**
|
73
|
+
* Sets highlight handling methods. Uses {@link module:widget/highlightstack~HighlightStack} to
|
74
|
+
* properly determine which highlight descriptor should be used at given time.
|
75
|
+
*/
|
76
|
+
export declare function setHighlightHandling(element: ViewElement, writer: DowncastWriter, add?: (element: ViewElement, descriptor: HighlightDescriptor, writer: DowncastWriter) => void, remove?: (element: ViewElement, descriptor: HighlightDescriptor, writer: DowncastWriter) => void): void;
|
77
|
+
/**
|
78
|
+
* Sets label for given element.
|
79
|
+
* It can be passed as a plain string or a function returning a string. Function will be called each time label is retrieved by
|
80
|
+
* {@link ~getLabel `getLabel()`}.
|
81
|
+
*/
|
82
|
+
export declare function setLabel(element: ViewElement, labelOrCreator: string | (() => string)): void;
|
83
|
+
/**
|
84
|
+
* Returns the label of the provided element.
|
85
|
+
*/
|
86
|
+
export declare function getLabel(element: ViewElement): string;
|
87
|
+
/**
|
88
|
+
* Adds functionality to the provided {@link module:engine/view/editableelement~EditableElement} to act as a widget's editable:
|
89
|
+
*
|
90
|
+
* * sets the `contenteditable` attribute to `true` when {@link module:engine/view/editableelement~EditableElement#isReadOnly} is `false`,
|
91
|
+
* otherwise sets it to `false`,
|
92
|
+
* * adds the `ck-editor__editable` and `ck-editor__nested-editable` CSS classes,
|
93
|
+
* * adds the `ck-editor__nested-editable_focused` CSS class when the editable is focused and removes it when it is blurred.
|
94
|
+
* * implements the {@link ~setHighlightHandling view highlight on widget's editable}.
|
95
|
+
*
|
96
|
+
* Similarly to {@link ~toWidget `toWidget()`} this function should be used in `editingDowncast` only and it is usually
|
97
|
+
* used together with {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`}.
|
98
|
+
*
|
99
|
+
* For example, in order to convert a `<nested>` model element to `<div class="nested">` in the view, you can define
|
100
|
+
* such converters:
|
101
|
+
*
|
102
|
+
* ```ts
|
103
|
+
* editor.conversion.for( 'editingDowncast' )
|
104
|
+
* .elementToElement( {
|
105
|
+
* model: 'nested',
|
106
|
+
* view: ( modelItem, { writer } ) => {
|
107
|
+
* const div = writer.createEditableElement( 'div', { class: 'nested' } );
|
108
|
+
*
|
109
|
+
* return toWidgetEditable( nested, writer, { label: 'label for editable' } );
|
110
|
+
* }
|
111
|
+
* } );
|
112
|
+
*
|
113
|
+
* editor.conversion.for( 'dataDowncast' )
|
114
|
+
* .elementToElement( {
|
115
|
+
* model: 'nested',
|
116
|
+
* view: ( modelItem, { writer } ) => {
|
117
|
+
* return writer.createContainerElement( 'div', { class: 'nested' } );
|
118
|
+
* }
|
119
|
+
* } );
|
120
|
+
* ```
|
121
|
+
*
|
122
|
+
* See the full source code of the widget (with nested editable) schema definition and converters in
|
123
|
+
* [this sample](https://github.com/ckeditor/ckeditor5-widget/blob/master/tests/manual/widget-with-nestededitable.js).
|
124
|
+
*
|
125
|
+
* @param options Additional options.
|
126
|
+
* @param options.label Editable's label used by assistive technologies (e.g. screen readers).
|
127
|
+
* @returns Returns the same element that was provided in the `editable` parameter
|
128
|
+
*/
|
129
|
+
export declare function toWidgetEditable(editable: ViewEditableElement, writer: DowncastWriter, options?: {
|
130
|
+
label?: string;
|
131
|
+
}): ViewEditableElement;
|
132
|
+
/**
|
133
|
+
* Returns a model range which is optimal (in terms of UX) for inserting a widget block.
|
134
|
+
*
|
135
|
+
* For instance, if a selection is in the middle of a paragraph, the collapsed range before this paragraph
|
136
|
+
* will be returned so that it is not split. If the selection is at the end of a paragraph,
|
137
|
+
* the collapsed range after this paragraph will be returned.
|
138
|
+
*
|
139
|
+
* Note: If the selection is placed in an empty block, the range in that block will be returned. If that range
|
140
|
+
* is then passed to {@link module:engine/model/model~Model#insertContent}, the block will be fully replaced
|
141
|
+
* by the inserted widget block.
|
142
|
+
*
|
143
|
+
* @param selection The selection based on which the insertion position should be calculated.
|
144
|
+
* @param model Model instance.
|
145
|
+
* @returns The optimal range.
|
146
|
+
*/
|
147
|
+
export declare function findOptimalInsertionRange(selection: Selection | DocumentSelection, model: Model): Range;
|
148
|
+
/**
|
149
|
+
* A util to be used in order to map view positions to correct model positions when implementing a widget
|
150
|
+
* which renders non-empty view element for an empty model element.
|
151
|
+
*
|
152
|
+
* For example:
|
153
|
+
*
|
154
|
+
* ```
|
155
|
+
* // Model:
|
156
|
+
* <placeholder type="name"></placeholder>
|
157
|
+
*
|
158
|
+
* // View:
|
159
|
+
* <span class="placeholder">name</span>
|
160
|
+
* ```
|
161
|
+
*
|
162
|
+
* In such case, view positions inside `<span>` cannot be correctly mapped to the model (because the model element is empty).
|
163
|
+
* To handle mapping positions inside `<span class="placeholder">` to the model use this util as follows:
|
164
|
+
*
|
165
|
+
* ```ts
|
166
|
+
* editor.editing.mapper.on(
|
167
|
+
* 'viewToModelPosition',
|
168
|
+
* viewToModelPositionOutsideModelElement( model, viewElement => viewElement.hasClass( 'placeholder' ) )
|
169
|
+
* );
|
170
|
+
* ```
|
171
|
+
*
|
172
|
+
* The callback will try to map the view offset of selection to an expected model position.
|
173
|
+
*
|
174
|
+
* 1. When the position is at the end (or in the middle) of the inline widget:
|
175
|
+
*
|
176
|
+
* ```
|
177
|
+
* // View:
|
178
|
+
* <p>foo <span class="placeholder">name|</span> bar</p>
|
179
|
+
*
|
180
|
+
* // Model:
|
181
|
+
* <paragraph>foo <placeholder type="name"></placeholder>| bar</paragraph>
|
182
|
+
* ```
|
183
|
+
*
|
184
|
+
* 2. When the position is at the beginning of the inline widget:
|
185
|
+
*
|
186
|
+
* ```
|
187
|
+
* // View:
|
188
|
+
* <p>foo <span class="placeholder">|name</span> bar</p>
|
189
|
+
*
|
190
|
+
* // Model:
|
191
|
+
* <paragraph>foo |<placeholder type="name"></placeholder> bar</paragraph>
|
192
|
+
* ```
|
193
|
+
*
|
194
|
+
* @param model Model instance on which the callback operates.
|
195
|
+
* @param viewElementMatcher Function that is passed a view element and should return `true` if the custom mapping
|
196
|
+
* should be applied to the given view element.
|
197
|
+
*/
|
198
|
+
export declare function viewToModelPositionOutsideModelElement(model: Model, viewElementMatcher: (element: ViewElement) => boolean): GetCallback<MapperViewToModelPositionEvent>;
|
199
|
+
/**
|
200
|
+
* Starting from a DOM resize host element (an element that receives dimensions as a result of resizing),
|
201
|
+
* this helper returns the width of the found ancestor element.
|
202
|
+
*
|
203
|
+
* * It searches up to 5 levels of ancestors only.
|
204
|
+
*
|
205
|
+
* @param domResizeHost Resize host DOM element that receives dimensions as a result of resizing.
|
206
|
+
* @returns Width of ancestor element in pixels or 0 if no ancestor with a computed width has been found.
|
207
|
+
*/
|
208
|
+
export declare function calculateResizeHostAncestorWidth(domResizeHost: HTMLElement): number;
|
209
|
+
/**
|
210
|
+
* Calculates a relative width of a `domResizeHost` compared to its ancestor in percents.
|
211
|
+
*
|
212
|
+
* @param domResizeHost Resize host DOM element.
|
213
|
+
* @returns Percentage value between 0 and 100.
|
214
|
+
*/
|
215
|
+
export declare function calculateResizeHostPercentageWidth(domResizeHost: HTMLElement, resizeHostRect?: Rect): number;
|
package/src/utils.js
ADDED
@@ -0,0 +1,396 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module widget/utils
|
7
|
+
*/
|
8
|
+
import { Rect, CKEditorError, toArray } from '@ckeditor/ckeditor5-utils';
|
9
|
+
import { IconView } from '@ckeditor/ckeditor5-ui';
|
10
|
+
import HighlightStack from './highlightstack.js';
|
11
|
+
import { getTypeAroundFakeCaretPosition } from './widgettypearound/utils.js';
|
12
|
+
import dragHandleIcon from '../theme/icons/drag-handle.svg';
|
13
|
+
/**
|
14
|
+
* CSS class added to each widget element.
|
15
|
+
*/
|
16
|
+
export const WIDGET_CLASS_NAME = 'ck-widget';
|
17
|
+
/**
|
18
|
+
* CSS class added to currently selected widget element.
|
19
|
+
*/
|
20
|
+
export const WIDGET_SELECTED_CLASS_NAME = 'ck-widget_selected';
|
21
|
+
/**
|
22
|
+
* Returns `true` if given {@link module:engine/view/node~Node} is an {@link module:engine/view/element~Element} and a widget.
|
23
|
+
*/
|
24
|
+
export function isWidget(node) {
|
25
|
+
if (!node.is('element')) {
|
26
|
+
return false;
|
27
|
+
}
|
28
|
+
return !!node.getCustomProperty('widget');
|
29
|
+
}
|
30
|
+
/**
|
31
|
+
* Converts the given {@link module:engine/view/element~Element} to a widget in the following way:
|
32
|
+
*
|
33
|
+
* * sets the `contenteditable` attribute to `"false"`,
|
34
|
+
* * adds the `ck-widget` CSS class,
|
35
|
+
* * adds a custom {@link module:engine/view/element~Element#getFillerOffset `getFillerOffset()`} method returning `null`,
|
36
|
+
* * adds a custom property allowing to recognize widget elements by using {@link ~isWidget `isWidget()`},
|
37
|
+
* * implements the {@link ~setHighlightHandling view highlight on widgets}.
|
38
|
+
*
|
39
|
+
* This function needs to be used in conjunction with
|
40
|
+
* {@link module:engine/conversion/downcasthelpers~DowncastHelpers downcast conversion helpers}
|
41
|
+
* like {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`}.
|
42
|
+
* Moreover, typically you will want to use `toWidget()` only for `editingDowncast`, while keeping the `dataDowncast` clean.
|
43
|
+
*
|
44
|
+
* For example, in order to convert a `<widget>` model element to `<div class="widget">` in the view, you can define
|
45
|
+
* such converters:
|
46
|
+
*
|
47
|
+
* ```ts
|
48
|
+
* editor.conversion.for( 'editingDowncast' )
|
49
|
+
* .elementToElement( {
|
50
|
+
* model: 'widget',
|
51
|
+
* view: ( modelItem, { writer } ) => {
|
52
|
+
* const div = writer.createContainerElement( 'div', { class: 'widget' } );
|
53
|
+
*
|
54
|
+
* return toWidget( div, writer, { label: 'some widget' } );
|
55
|
+
* }
|
56
|
+
* } );
|
57
|
+
*
|
58
|
+
* editor.conversion.for( 'dataDowncast' )
|
59
|
+
* .elementToElement( {
|
60
|
+
* model: 'widget',
|
61
|
+
* view: ( modelItem, { writer } ) => {
|
62
|
+
* return writer.createContainerElement( 'div', { class: 'widget' } );
|
63
|
+
* }
|
64
|
+
* } );
|
65
|
+
* ```
|
66
|
+
*
|
67
|
+
* See the full source code of the widget (with a nested editable) schema definition and converters in
|
68
|
+
* [this sample](https://github.com/ckeditor/ckeditor5-widget/blob/master/tests/manual/widget-with-nestededitable.js).
|
69
|
+
*
|
70
|
+
* @param options Additional options.
|
71
|
+
* @param options.label Element's label provided to the {@link ~setLabel} function. It can be passed as
|
72
|
+
* a plain string or a function returning a string. It represents the widget for assistive technologies (like screen readers).
|
73
|
+
* @param options.hasSelectionHandle If `true`, the widget will have a selection handle added.
|
74
|
+
* @returns Returns the same element.
|
75
|
+
*/
|
76
|
+
export function toWidget(element, writer, options = {}) {
|
77
|
+
if (!element.is('containerElement')) {
|
78
|
+
/**
|
79
|
+
* The element passed to `toWidget()` must be a {@link module:engine/view/containerelement~ContainerElement}
|
80
|
+
* instance.
|
81
|
+
*
|
82
|
+
* @error widget-to-widget-wrong-element-type
|
83
|
+
* @param element The view element passed to `toWidget()`.
|
84
|
+
*/
|
85
|
+
throw new CKEditorError('widget-to-widget-wrong-element-type', null, { element });
|
86
|
+
}
|
87
|
+
writer.setAttribute('contenteditable', 'false', element);
|
88
|
+
writer.addClass(WIDGET_CLASS_NAME, element);
|
89
|
+
writer.setCustomProperty('widget', true, element);
|
90
|
+
element.getFillerOffset = getFillerOffset;
|
91
|
+
writer.setCustomProperty('widgetLabel', [], element);
|
92
|
+
if (options.label) {
|
93
|
+
setLabel(element, options.label);
|
94
|
+
}
|
95
|
+
if (options.hasSelectionHandle) {
|
96
|
+
addSelectionHandle(element, writer);
|
97
|
+
}
|
98
|
+
setHighlightHandling(element, writer);
|
99
|
+
return element;
|
100
|
+
}
|
101
|
+
/**
|
102
|
+
* Default handler for adding a highlight on a widget.
|
103
|
+
* It adds CSS class and attributes basing on the given highlight descriptor.
|
104
|
+
*/
|
105
|
+
function addHighlight(element, descriptor, writer) {
|
106
|
+
if (descriptor.classes) {
|
107
|
+
writer.addClass(toArray(descriptor.classes), element);
|
108
|
+
}
|
109
|
+
if (descriptor.attributes) {
|
110
|
+
for (const key in descriptor.attributes) {
|
111
|
+
writer.setAttribute(key, descriptor.attributes[key], element);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
/**
|
116
|
+
* Default handler for removing a highlight from a widget.
|
117
|
+
* It removes CSS class and attributes basing on the given highlight descriptor.
|
118
|
+
*/
|
119
|
+
function removeHighlight(element, descriptor, writer) {
|
120
|
+
if (descriptor.classes) {
|
121
|
+
writer.removeClass(toArray(descriptor.classes), element);
|
122
|
+
}
|
123
|
+
if (descriptor.attributes) {
|
124
|
+
for (const key in descriptor.attributes) {
|
125
|
+
writer.removeAttribute(key, element);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
129
|
+
/**
|
130
|
+
* Sets highlight handling methods. Uses {@link module:widget/highlightstack~HighlightStack} to
|
131
|
+
* properly determine which highlight descriptor should be used at given time.
|
132
|
+
*/
|
133
|
+
export function setHighlightHandling(element, writer, add = addHighlight, remove = removeHighlight) {
|
134
|
+
const stack = new HighlightStack();
|
135
|
+
stack.on('change:top', (evt, data) => {
|
136
|
+
if (data.oldDescriptor) {
|
137
|
+
remove(element, data.oldDescriptor, data.writer);
|
138
|
+
}
|
139
|
+
if (data.newDescriptor) {
|
140
|
+
add(element, data.newDescriptor, data.writer);
|
141
|
+
}
|
142
|
+
});
|
143
|
+
const addHighlightCallback = (element, descriptor, writer) => stack.add(descriptor, writer);
|
144
|
+
const removeHighlightCallback = (element, id, writer) => stack.remove(id, writer);
|
145
|
+
writer.setCustomProperty('addHighlight', addHighlightCallback, element);
|
146
|
+
writer.setCustomProperty('removeHighlight', removeHighlightCallback, element);
|
147
|
+
}
|
148
|
+
/**
|
149
|
+
* Sets label for given element.
|
150
|
+
* It can be passed as a plain string or a function returning a string. Function will be called each time label is retrieved by
|
151
|
+
* {@link ~getLabel `getLabel()`}.
|
152
|
+
*/
|
153
|
+
export function setLabel(element, labelOrCreator) {
|
154
|
+
const widgetLabel = element.getCustomProperty('widgetLabel');
|
155
|
+
widgetLabel.push(labelOrCreator);
|
156
|
+
}
|
157
|
+
/**
|
158
|
+
* Returns the label of the provided element.
|
159
|
+
*/
|
160
|
+
export function getLabel(element) {
|
161
|
+
const widgetLabel = element.getCustomProperty('widgetLabel');
|
162
|
+
return widgetLabel.reduce((prev, current) => {
|
163
|
+
if (typeof current === 'function') {
|
164
|
+
return prev ? prev + '. ' + current() : current();
|
165
|
+
}
|
166
|
+
else {
|
167
|
+
return prev ? prev + '. ' + current : current;
|
168
|
+
}
|
169
|
+
}, '');
|
170
|
+
}
|
171
|
+
/**
|
172
|
+
* Adds functionality to the provided {@link module:engine/view/editableelement~EditableElement} to act as a widget's editable:
|
173
|
+
*
|
174
|
+
* * sets the `contenteditable` attribute to `true` when {@link module:engine/view/editableelement~EditableElement#isReadOnly} is `false`,
|
175
|
+
* otherwise sets it to `false`,
|
176
|
+
* * adds the `ck-editor__editable` and `ck-editor__nested-editable` CSS classes,
|
177
|
+
* * adds the `ck-editor__nested-editable_focused` CSS class when the editable is focused and removes it when it is blurred.
|
178
|
+
* * implements the {@link ~setHighlightHandling view highlight on widget's editable}.
|
179
|
+
*
|
180
|
+
* Similarly to {@link ~toWidget `toWidget()`} this function should be used in `editingDowncast` only and it is usually
|
181
|
+
* used together with {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`}.
|
182
|
+
*
|
183
|
+
* For example, in order to convert a `<nested>` model element to `<div class="nested">` in the view, you can define
|
184
|
+
* such converters:
|
185
|
+
*
|
186
|
+
* ```ts
|
187
|
+
* editor.conversion.for( 'editingDowncast' )
|
188
|
+
* .elementToElement( {
|
189
|
+
* model: 'nested',
|
190
|
+
* view: ( modelItem, { writer } ) => {
|
191
|
+
* const div = writer.createEditableElement( 'div', { class: 'nested' } );
|
192
|
+
*
|
193
|
+
* return toWidgetEditable( nested, writer, { label: 'label for editable' } );
|
194
|
+
* }
|
195
|
+
* } );
|
196
|
+
*
|
197
|
+
* editor.conversion.for( 'dataDowncast' )
|
198
|
+
* .elementToElement( {
|
199
|
+
* model: 'nested',
|
200
|
+
* view: ( modelItem, { writer } ) => {
|
201
|
+
* return writer.createContainerElement( 'div', { class: 'nested' } );
|
202
|
+
* }
|
203
|
+
* } );
|
204
|
+
* ```
|
205
|
+
*
|
206
|
+
* See the full source code of the widget (with nested editable) schema definition and converters in
|
207
|
+
* [this sample](https://github.com/ckeditor/ckeditor5-widget/blob/master/tests/manual/widget-with-nestededitable.js).
|
208
|
+
*
|
209
|
+
* @param options Additional options.
|
210
|
+
* @param options.label Editable's label used by assistive technologies (e.g. screen readers).
|
211
|
+
* @returns Returns the same element that was provided in the `editable` parameter
|
212
|
+
*/
|
213
|
+
export function toWidgetEditable(editable, writer, options = {}) {
|
214
|
+
writer.addClass(['ck-editor__editable', 'ck-editor__nested-editable'], editable);
|
215
|
+
writer.setAttribute('role', 'textbox', editable);
|
216
|
+
writer.setAttribute('tabindex', '-1', editable);
|
217
|
+
if (options.label) {
|
218
|
+
writer.setAttribute('aria-label', options.label, editable);
|
219
|
+
}
|
220
|
+
// Set initial contenteditable value.
|
221
|
+
writer.setAttribute('contenteditable', editable.isReadOnly ? 'false' : 'true', editable);
|
222
|
+
// Bind the contenteditable property to element#isReadOnly.
|
223
|
+
editable.on('change:isReadOnly', (evt, property, is) => {
|
224
|
+
writer.setAttribute('contenteditable', is ? 'false' : 'true', editable);
|
225
|
+
});
|
226
|
+
editable.on('change:isFocused', (evt, property, is) => {
|
227
|
+
if (is) {
|
228
|
+
writer.addClass('ck-editor__nested-editable_focused', editable);
|
229
|
+
}
|
230
|
+
else {
|
231
|
+
writer.removeClass('ck-editor__nested-editable_focused', editable);
|
232
|
+
}
|
233
|
+
});
|
234
|
+
setHighlightHandling(editable, writer);
|
235
|
+
return editable;
|
236
|
+
}
|
237
|
+
/**
|
238
|
+
* Returns a model range which is optimal (in terms of UX) for inserting a widget block.
|
239
|
+
*
|
240
|
+
* For instance, if a selection is in the middle of a paragraph, the collapsed range before this paragraph
|
241
|
+
* will be returned so that it is not split. If the selection is at the end of a paragraph,
|
242
|
+
* the collapsed range after this paragraph will be returned.
|
243
|
+
*
|
244
|
+
* Note: If the selection is placed in an empty block, the range in that block will be returned. If that range
|
245
|
+
* is then passed to {@link module:engine/model/model~Model#insertContent}, the block will be fully replaced
|
246
|
+
* by the inserted widget block.
|
247
|
+
*
|
248
|
+
* @param selection The selection based on which the insertion position should be calculated.
|
249
|
+
* @param model Model instance.
|
250
|
+
* @returns The optimal range.
|
251
|
+
*/
|
252
|
+
export function findOptimalInsertionRange(selection, model) {
|
253
|
+
const selectedElement = selection.getSelectedElement();
|
254
|
+
if (selectedElement) {
|
255
|
+
const typeAroundFakeCaretPosition = getTypeAroundFakeCaretPosition(selection);
|
256
|
+
// If the WidgetTypeAround "fake caret" is displayed, use its position for the insertion
|
257
|
+
// to provide the most predictable UX (https://github.com/ckeditor/ckeditor5/issues/7438).
|
258
|
+
if (typeAroundFakeCaretPosition) {
|
259
|
+
return model.createRange(model.createPositionAt(selectedElement, typeAroundFakeCaretPosition));
|
260
|
+
}
|
261
|
+
}
|
262
|
+
return model.schema.findOptimalInsertionRange(selection);
|
263
|
+
}
|
264
|
+
/**
|
265
|
+
* A util to be used in order to map view positions to correct model positions when implementing a widget
|
266
|
+
* which renders non-empty view element for an empty model element.
|
267
|
+
*
|
268
|
+
* For example:
|
269
|
+
*
|
270
|
+
* ```
|
271
|
+
* // Model:
|
272
|
+
* <placeholder type="name"></placeholder>
|
273
|
+
*
|
274
|
+
* // View:
|
275
|
+
* <span class="placeholder">name</span>
|
276
|
+
* ```
|
277
|
+
*
|
278
|
+
* In such case, view positions inside `<span>` cannot be correctly mapped to the model (because the model element is empty).
|
279
|
+
* To handle mapping positions inside `<span class="placeholder">` to the model use this util as follows:
|
280
|
+
*
|
281
|
+
* ```ts
|
282
|
+
* editor.editing.mapper.on(
|
283
|
+
* 'viewToModelPosition',
|
284
|
+
* viewToModelPositionOutsideModelElement( model, viewElement => viewElement.hasClass( 'placeholder' ) )
|
285
|
+
* );
|
286
|
+
* ```
|
287
|
+
*
|
288
|
+
* The callback will try to map the view offset of selection to an expected model position.
|
289
|
+
*
|
290
|
+
* 1. When the position is at the end (or in the middle) of the inline widget:
|
291
|
+
*
|
292
|
+
* ```
|
293
|
+
* // View:
|
294
|
+
* <p>foo <span class="placeholder">name|</span> bar</p>
|
295
|
+
*
|
296
|
+
* // Model:
|
297
|
+
* <paragraph>foo <placeholder type="name"></placeholder>| bar</paragraph>
|
298
|
+
* ```
|
299
|
+
*
|
300
|
+
* 2. When the position is at the beginning of the inline widget:
|
301
|
+
*
|
302
|
+
* ```
|
303
|
+
* // View:
|
304
|
+
* <p>foo <span class="placeholder">|name</span> bar</p>
|
305
|
+
*
|
306
|
+
* // Model:
|
307
|
+
* <paragraph>foo |<placeholder type="name"></placeholder> bar</paragraph>
|
308
|
+
* ```
|
309
|
+
*
|
310
|
+
* @param model Model instance on which the callback operates.
|
311
|
+
* @param viewElementMatcher Function that is passed a view element and should return `true` if the custom mapping
|
312
|
+
* should be applied to the given view element.
|
313
|
+
*/
|
314
|
+
export function viewToModelPositionOutsideModelElement(model, viewElementMatcher) {
|
315
|
+
return (evt, data) => {
|
316
|
+
const { mapper, viewPosition } = data;
|
317
|
+
const viewParent = mapper.findMappedViewAncestor(viewPosition);
|
318
|
+
if (!viewElementMatcher(viewParent)) {
|
319
|
+
return;
|
320
|
+
}
|
321
|
+
const modelParent = mapper.toModelElement(viewParent);
|
322
|
+
data.modelPosition = model.createPositionAt(modelParent, viewPosition.isAtStart ? 'before' : 'after');
|
323
|
+
};
|
324
|
+
}
|
325
|
+
/**
|
326
|
+
* Default filler offset function applied to all widget elements.
|
327
|
+
*/
|
328
|
+
function getFillerOffset() {
|
329
|
+
return null;
|
330
|
+
}
|
331
|
+
/**
|
332
|
+
* Adds a drag handle to the widget.
|
333
|
+
*/
|
334
|
+
function addSelectionHandle(widgetElement, writer) {
|
335
|
+
const selectionHandle = writer.createUIElement('div', { class: 'ck ck-widget__selection-handle' }, function (domDocument) {
|
336
|
+
const domElement = this.toDomElement(domDocument);
|
337
|
+
// Use the IconView from the ui library.
|
338
|
+
const icon = new IconView();
|
339
|
+
icon.set('content', dragHandleIcon);
|
340
|
+
// Render the icon view right away to append its #element to the selectionHandle DOM element.
|
341
|
+
icon.render();
|
342
|
+
domElement.appendChild(icon.element);
|
343
|
+
return domElement;
|
344
|
+
});
|
345
|
+
// Append the selection handle into the widget wrapper.
|
346
|
+
writer.insert(writer.createPositionAt(widgetElement, 0), selectionHandle);
|
347
|
+
writer.addClass(['ck-widget_with-selection-handle'], widgetElement);
|
348
|
+
}
|
349
|
+
/**
|
350
|
+
* Starting from a DOM resize host element (an element that receives dimensions as a result of resizing),
|
351
|
+
* this helper returns the width of the found ancestor element.
|
352
|
+
*
|
353
|
+
* * It searches up to 5 levels of ancestors only.
|
354
|
+
*
|
355
|
+
* @param domResizeHost Resize host DOM element that receives dimensions as a result of resizing.
|
356
|
+
* @returns Width of ancestor element in pixels or 0 if no ancestor with a computed width has been found.
|
357
|
+
*/
|
358
|
+
export function calculateResizeHostAncestorWidth(domResizeHost) {
|
359
|
+
const getElementComputedWidth = (element) => {
|
360
|
+
const { width, paddingLeft, paddingRight } = element.ownerDocument.defaultView.getComputedStyle(element);
|
361
|
+
return parseFloat(width) - (parseFloat(paddingLeft) || 0) - (parseFloat(paddingRight) || 0);
|
362
|
+
};
|
363
|
+
const domResizeHostParent = domResizeHost.parentElement;
|
364
|
+
if (!domResizeHostParent) {
|
365
|
+
return 0;
|
366
|
+
}
|
367
|
+
// Need to use computed style as it properly excludes parent's paddings from the returned value.
|
368
|
+
let parentWidth = getElementComputedWidth(domResizeHostParent);
|
369
|
+
// Sometimes parent width cannot be accessed. If that happens we should go up in the elements tree
|
370
|
+
// and try to get width from next ancestor.
|
371
|
+
// https://github.com/ckeditor/ckeditor5/issues/10776
|
372
|
+
const ancestorLevelLimit = 5;
|
373
|
+
let currentLevel = 0;
|
374
|
+
let checkedElement = domResizeHostParent;
|
375
|
+
while (isNaN(parentWidth)) {
|
376
|
+
checkedElement = checkedElement.parentElement;
|
377
|
+
if (++currentLevel > ancestorLevelLimit) {
|
378
|
+
return 0;
|
379
|
+
}
|
380
|
+
parentWidth = getElementComputedWidth(checkedElement);
|
381
|
+
}
|
382
|
+
return parentWidth;
|
383
|
+
}
|
384
|
+
/**
|
385
|
+
* Calculates a relative width of a `domResizeHost` compared to its ancestor in percents.
|
386
|
+
*
|
387
|
+
* @param domResizeHost Resize host DOM element.
|
388
|
+
* @returns Percentage value between 0 and 100.
|
389
|
+
*/
|
390
|
+
export function calculateResizeHostPercentageWidth(domResizeHost, resizeHostRect = new Rect(domResizeHost)) {
|
391
|
+
const parentWidth = calculateResizeHostAncestorWidth(domResizeHost);
|
392
|
+
if (!parentWidth) {
|
393
|
+
return 0;
|
394
|
+
}
|
395
|
+
return resizeHostRect.width / parentWidth * 100;
|
396
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module widget/verticalnavigation
|
7
|
+
*/
|
8
|
+
import { type GetCallback } from '@ckeditor/ckeditor5-utils';
|
9
|
+
import type { EditingController, ViewDocumentArrowKeyEvent } from '@ckeditor/ckeditor5-engine';
|
10
|
+
/**
|
11
|
+
* Returns 'keydown' handler for up/down arrow keys that modifies the caret movement if it's in a text line next to an object.
|
12
|
+
*
|
13
|
+
* @param editing The editing controller.
|
14
|
+
*/
|
15
|
+
export default function verticalNavigationHandler(editing: EditingController): GetCallback<ViewDocumentArrowKeyEvent>;
|