x-star-editor 0.3.4 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/FileInput.d.ts +2 -1
- package/dist/components/FileInput.js +3 -1
- package/dist/components/Toolbar.js +2 -1
- package/dist/styles/index.css +4 -4
- package/dist/utils/container.d.ts +1 -0
- package/dist/utils/container.js +35 -38
- package/dist/utils/history.d.ts +1 -1
- package/dist/utils/history.js +9 -3
- package/dist/x-star-editor/index.d.ts +5 -1
- package/dist/x-star-editor/index.js +31 -7
- package/dist/x-star-md-editor/index.d.ts +4 -0
- package/dist/x-star-md-editor/index.js +8 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
interface FileInputProps {
|
|
3
|
+
image?: boolean;
|
|
3
4
|
onCancel: () => void;
|
|
4
5
|
onOk: (data: ({
|
|
5
6
|
type: 'file';
|
|
@@ -11,5 +12,5 @@ interface FileInputProps {
|
|
|
11
12
|
description: string;
|
|
12
13
|
}) => void;
|
|
13
14
|
}
|
|
14
|
-
declare const FileInput: ({ onCancel, onOk }: FileInputProps) => React.JSX.Element;
|
|
15
|
+
declare const FileInput: ({ image, onCancel, onOk }: FileInputProps) => React.JSX.Element;
|
|
15
16
|
export default FileInput;
|
|
@@ -6,7 +6,8 @@ import { useLocale } from "../locales";
|
|
|
6
6
|
import { prefix } from "../utils/global";
|
|
7
7
|
var FileInput = function FileInput(_ref) {
|
|
8
8
|
var _file$name;
|
|
9
|
-
var
|
|
9
|
+
var image = _ref.image,
|
|
10
|
+
onCancel = _ref.onCancel,
|
|
10
11
|
onOk = _ref.onOk;
|
|
11
12
|
var _useState = useState('file'),
|
|
12
13
|
_useState2 = _slicedToArray(_useState, 2),
|
|
@@ -47,6 +48,7 @@ var FileInput = function FileInput(_ref) {
|
|
|
47
48
|
}, /*#__PURE__*/React.createElement("input", {
|
|
48
49
|
className: classNames("".concat(prefix, "hidden")),
|
|
49
50
|
type: "file",
|
|
51
|
+
accept: image ? 'image/*' : undefined,
|
|
50
52
|
onChange: function onChange(e) {
|
|
51
53
|
var _e$target$files;
|
|
52
54
|
return setFile((_e$target$files = e.target.files) === null || _e$target$files === void 0 ? void 0 : _e$target$files[0]);
|
|
@@ -78,7 +78,7 @@ var Item = function Item(_ref) {
|
|
|
78
78
|
return /*#__PURE__*/React.createElement("div", {
|
|
79
79
|
className: classNames("".concat(prefix, "item-container"))
|
|
80
80
|
}, /*#__PURE__*/React.createElement("div", {
|
|
81
|
-
className: classNames("".concat(prefix, "item"), (_classNames = {}, _defineProperty(_classNames, "".concat(prefix, "disabled"), disabled), _defineProperty(_classNames, "".concat(prefix, "active"),
|
|
81
|
+
className: classNames("".concat(prefix, "item"), (_classNames = {}, _defineProperty(_classNames, "".concat(prefix, "disabled"), disabled), _defineProperty(_classNames, "".concat(prefix, "active"), popoverMount), _classNames)),
|
|
82
82
|
onClick: function onClick() {
|
|
83
83
|
if (!disabled) {
|
|
84
84
|
setTooltipOpen(false);
|
|
@@ -315,6 +315,7 @@ export var getDefaultToolbarItemMap = function getDefaultToolbarItemMap(locale,
|
|
|
315
315
|
tooltip: t('image'),
|
|
316
316
|
popoverRender: function popoverRender(exec, close) {
|
|
317
317
|
return /*#__PURE__*/React.createElement(FileInput, {
|
|
318
|
+
image: true,
|
|
318
319
|
onCancel: close,
|
|
319
320
|
onOk: function onOk(data) {
|
|
320
321
|
if (data.type === 'file') {
|
package/dist/styles/index.css
CHANGED
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
background-color: rgba(230, 247, 255, 0.7);
|
|
115
115
|
cursor: not-allowed;
|
|
116
116
|
}
|
|
117
|
-
.x-star-editor-toolbar .x-star-editor-item-container .x-star-editor-item.x-star-editor-active {
|
|
117
|
+
.x-star-editor-toolbar .x-star-editor-item-container .x-star-editor-item:hover, .x-star-editor-toolbar .x-star-editor-item-container .x-star-editor-item.x-star-editor-active {
|
|
118
118
|
background-color: #cbedfd;
|
|
119
119
|
}
|
|
120
120
|
.x-star-editor-toolbar .x-star-editor-item-container .x-star-editor-item .x-star-editor-icon {
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
.x-star-editor-editor.x-star-editor-fullscreen {
|
|
180
180
|
position: fixed;
|
|
181
181
|
inset: 0;
|
|
182
|
-
z-index:
|
|
182
|
+
z-index: 9999;
|
|
183
183
|
}
|
|
184
184
|
.x-star-editor-editor.x-star-editor-fullscreen > .x-star-editor-md-editor,
|
|
185
185
|
.x-star-editor-editor.x-star-editor-fullscreen > .x-star-editor-md-viewer {
|
|
@@ -237,10 +237,10 @@
|
|
|
237
237
|
background-color: #c1def1;
|
|
238
238
|
}
|
|
239
239
|
.x-star-editor-md-editor > :first-child {
|
|
240
|
-
margin-top:
|
|
240
|
+
margin-top: 0.5em;
|
|
241
241
|
}
|
|
242
242
|
.x-star-editor-md-editor > :last-child {
|
|
243
|
-
margin-bottom:
|
|
243
|
+
margin-bottom: 0.5em;
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
.x-star-editor-md-viewer {
|
|
@@ -41,4 +41,5 @@ export declare const useContainer: (ref: React.RefObject<HTMLDivElement>) => {
|
|
|
41
41
|
getOffset: (root: Node, targetNode: Node, targetOffset: number) => number;
|
|
42
42
|
getSelection: () => ContainerSelection;
|
|
43
43
|
setSelection: ({ anchorOffset, focusOffset }: ContainerSelection) => void;
|
|
44
|
+
normalizeSelection: () => void;
|
|
44
45
|
};
|
package/dist/utils/container.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
|
|
2
|
-
import {
|
|
2
|
+
import { useRef } from 'react';
|
|
3
3
|
import { editorRender } from "./markdown";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -294,52 +294,49 @@ export var useContainer = function useContainer(ref) {
|
|
|
294
294
|
range.setEnd(focus.node, focus.offset);
|
|
295
295
|
var rangeRect = range.getBoundingClientRect();
|
|
296
296
|
var containerRect = ref.current.getBoundingClientRect();
|
|
297
|
-
var topOffset = rangeRect.top - containerRect.top;
|
|
298
|
-
var bottomOffset = rangeRect.bottom - containerRect.bottom;
|
|
297
|
+
var topOffset = Math.round(rangeRect.top - containerRect.top);
|
|
298
|
+
var bottomOffset = Math.round(rangeRect.bottom - containerRect.bottom);
|
|
299
299
|
|
|
300
300
|
// 将光标滚动到视口内
|
|
301
|
-
if (topOffset <
|
|
302
|
-
ref.current.scrollTop += topOffset;
|
|
303
|
-
} else if (bottomOffset >
|
|
304
|
-
ref.current.scrollTop += bottomOffset;
|
|
301
|
+
if (topOffset < 1) {
|
|
302
|
+
ref.current.scrollTop += topOffset - 1;
|
|
303
|
+
} else if (bottomOffset > -1) {
|
|
304
|
+
ref.current.scrollTop += bottomOffset + 1;
|
|
305
305
|
}
|
|
306
306
|
};
|
|
307
307
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
return function () {
|
|
335
|
-
return document.removeEventListener('selectionchange', listener);
|
|
336
|
-
};
|
|
337
|
-
}, []);
|
|
308
|
+
/**
|
|
309
|
+
* 标准化容器选区,确保光标不在零宽空格后
|
|
310
|
+
*/
|
|
311
|
+
var normalizeSelection = function normalizeSelection() {
|
|
312
|
+
var _anchorNode$nodeValue, _focusNode$nodeValue;
|
|
313
|
+
var selection = window.getSelection();
|
|
314
|
+
if (!selection || !selection.anchorNode || !selection.focusNode || !ref.current) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
var update = false;
|
|
318
|
+
var anchorNode = selection.anchorNode,
|
|
319
|
+
anchorOffset = selection.anchorOffset,
|
|
320
|
+
focusNode = selection.focusNode,
|
|
321
|
+
focusOffset = selection.focusOffset;
|
|
322
|
+
if (anchorNode.nodeType === Node.TEXT_NODE && ((_anchorNode$nodeValue = anchorNode.nodeValue) === null || _anchorNode$nodeValue === void 0 ? void 0 : _anchorNode$nodeValue[anchorOffset - 1]) === "\u200B") {
|
|
323
|
+
update = true;
|
|
324
|
+
anchorOffset--;
|
|
325
|
+
}
|
|
326
|
+
if (focusNode.nodeType === Node.TEXT_NODE && ((_focusNode$nodeValue = focusNode.nodeValue) === null || _focusNode$nodeValue === void 0 ? void 0 : _focusNode$nodeValue[focusOffset - 1]) === "\u200B") {
|
|
327
|
+
update = true;
|
|
328
|
+
focusOffset--;
|
|
329
|
+
}
|
|
330
|
+
if (update) {
|
|
331
|
+
selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
338
334
|
return useRef({
|
|
339
335
|
getText: getText,
|
|
340
336
|
setText: setText,
|
|
341
337
|
getOffset: getOffset,
|
|
342
338
|
getSelection: getSelection,
|
|
343
|
-
setSelection: setSelection
|
|
339
|
+
setSelection: setSelection,
|
|
340
|
+
normalizeSelection: normalizeSelection
|
|
344
341
|
}).current;
|
|
345
342
|
};
|
package/dist/utils/history.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export interface SelectAction {
|
|
|
66
66
|
selection: ContainerSelection;
|
|
67
67
|
}
|
|
68
68
|
type HistoryAction = UndoAction | RedoAction | BatchAction | SelectAction;
|
|
69
|
-
export declare const useHistory: (initialSourceCode: string) => {
|
|
69
|
+
export declare const useHistory: (initialSourceCode: string, readOnly?: boolean) => {
|
|
70
70
|
history: History;
|
|
71
71
|
sourceCode: string;
|
|
72
72
|
selection: ContainerSelection;
|
package/dist/utils/history.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
2
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
3
3
|
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
4
|
-
import { useReducer } from 'react';
|
|
4
|
+
import { useReducer, useRef } from 'react';
|
|
5
5
|
import { createSelection, getRange } from "./container";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -268,7 +268,7 @@ var historyReducer = function historyReducer(_ref2, action) {
|
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
270
|
};
|
|
271
|
-
export var useHistory = function useHistory(initialSourceCode) {
|
|
271
|
+
export var useHistory = function useHistory(initialSourceCode, readOnly) {
|
|
272
272
|
var _useReducer = useReducer(historyReducer, initialSourceCode, function (text) {
|
|
273
273
|
var action = {
|
|
274
274
|
type: 'insert',
|
|
@@ -292,10 +292,16 @@ export var useHistory = function useHistory(initialSourceCode) {
|
|
|
292
292
|
_useReducer2 = _slicedToArray(_useReducer, 2),
|
|
293
293
|
history = _useReducer2[0],
|
|
294
294
|
dispatch = _useReducer2[1];
|
|
295
|
+
var readOnlyLatest = useRef(readOnly);
|
|
296
|
+
readOnlyLatest.current = readOnly;
|
|
295
297
|
return {
|
|
296
298
|
history: history,
|
|
297
299
|
sourceCode: history.states[history.index].sourceCode,
|
|
298
300
|
selection: history.selection,
|
|
299
|
-
dispatch:
|
|
301
|
+
dispatch: useRef(function (action) {
|
|
302
|
+
if (!readOnlyLatest.current) {
|
|
303
|
+
dispatch(action);
|
|
304
|
+
}
|
|
305
|
+
}).current
|
|
300
306
|
};
|
|
301
307
|
};
|
|
@@ -25,6 +25,10 @@ export interface XStarEditorProps {
|
|
|
25
25
|
* 初始文本
|
|
26
26
|
*/
|
|
27
27
|
initialValue?: string;
|
|
28
|
+
/**
|
|
29
|
+
* 是否只读
|
|
30
|
+
*/
|
|
31
|
+
readOnly?: XStarMdEditorProps['readOnly'];
|
|
28
32
|
/**
|
|
29
33
|
* 是否启用 Web Worker
|
|
30
34
|
*/
|
|
@@ -32,7 +36,7 @@ export interface XStarEditorProps {
|
|
|
32
36
|
/**
|
|
33
37
|
* 编辑器属性
|
|
34
38
|
*/
|
|
35
|
-
editorProps?: Omit<XStarMdEditorProps, 'height' | 'locale' | 'initialValue' | 'onChange' | 'onInsertFile'>;
|
|
39
|
+
editorProps?: Omit<XStarMdEditorProps, 'height' | 'locale' | 'initialValue' | 'readOnly' | 'onChange' | 'onInsertFile'>;
|
|
36
40
|
/**
|
|
37
41
|
* 查看器属性
|
|
38
42
|
*/
|
|
@@ -5,6 +5,7 @@ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
|
5
5
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
6
6
|
import classNames from 'classnames';
|
|
7
7
|
import React, { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
8
|
+
import { createKeybindingsHandler } from 'tinykeys';
|
|
8
9
|
import SvgEditOnly from "../icons/EditOnly";
|
|
9
10
|
import SvgEnterFullscreen from "../icons/EnterFullscreen";
|
|
10
11
|
import SvgExitFullscreen from "../icons/ExitFullscreen";
|
|
@@ -42,6 +43,7 @@ var XStarEditor = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
42
43
|
locale = _ref2.locale,
|
|
43
44
|
_ref2$initialValue = _ref2.initialValue,
|
|
44
45
|
initialValue = _ref2$initialValue === void 0 ? '' : _ref2$initialValue,
|
|
46
|
+
readOnly = _ref2.readOnly,
|
|
45
47
|
enableWebWorker = _ref2.enableWebWorker,
|
|
46
48
|
editorProps = _ref2.editorProps,
|
|
47
49
|
viewerProps = _ref2.viewerProps,
|
|
@@ -64,6 +66,9 @@ var XStarEditor = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
64
66
|
var _editorRef$current, _viewerRef$current;
|
|
65
67
|
var editor = (_editorRef$current = editorRef.current) === null || _editorRef$current === void 0 ? void 0 : _editorRef$current.getEditorContainer();
|
|
66
68
|
var viewer = (_viewerRef$current = viewerRef.current) === null || _viewerRef$current === void 0 ? void 0 : _viewerRef$current.getViewerContainer();
|
|
69
|
+
if (!editor || !viewer) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
67
72
|
|
|
68
73
|
/**
|
|
69
74
|
* 获取两个父元素的子元素到各自父元素顶部的距离
|
|
@@ -122,7 +127,7 @@ var XStarEditor = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
122
127
|
var listener = function listener(e) {
|
|
123
128
|
var ignore = ignoreNext;
|
|
124
129
|
ignoreNext = false;
|
|
125
|
-
if (ignore
|
|
130
|
+
if (ignore) {
|
|
126
131
|
return;
|
|
127
132
|
}
|
|
128
133
|
var _ref3 = e.currentTarget === editor ? [editor, viewer] : [viewer, editor],
|
|
@@ -135,7 +140,7 @@ var XStarEditor = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
135
140
|
toOffsetTops = _getOffsetTops2[1];
|
|
136
141
|
for (var i = 0; i < fromOffsetTops.length - 1; i++) {
|
|
137
142
|
if (fromOffsetTops[i] <= fromElement.scrollTop && fromElement.scrollTop < fromOffsetTops[i + 1]) {
|
|
138
|
-
var scrollTop = (fromElement.scrollTop - fromOffsetTops[i]) / (fromOffsetTops[i + 1] - fromOffsetTops[i]) * (toOffsetTops[i + 1] - toOffsetTops[i]) + toOffsetTops[i];
|
|
143
|
+
var scrollTop = Math.round((fromElement.scrollTop - fromOffsetTops[i]) / (fromOffsetTops[i + 1] - fromOffsetTops[i]) * (toOffsetTops[i + 1] - toOffsetTops[i]) + toOffsetTops[i]);
|
|
139
144
|
if (toElement.scrollTop !== scrollTop) {
|
|
140
145
|
ignoreNext = true;
|
|
141
146
|
toElement.scrollTop = scrollTop;
|
|
@@ -144,11 +149,21 @@ var XStarEditor = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
144
149
|
}
|
|
145
150
|
}
|
|
146
151
|
};
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
var observer = new MutationObserver(function () {
|
|
153
|
+
return listener({
|
|
154
|
+
currentTarget: editor
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
editor.addEventListener('scroll', listener);
|
|
158
|
+
viewer.addEventListener('scroll', listener);
|
|
159
|
+
observer.observe(viewer, {
|
|
160
|
+
subtree: true,
|
|
161
|
+
childList: true
|
|
162
|
+
});
|
|
149
163
|
return function () {
|
|
150
|
-
editor
|
|
151
|
-
viewer
|
|
164
|
+
editor.removeEventListener('scroll', listener);
|
|
165
|
+
viewer.removeEventListener('scroll', listener);
|
|
166
|
+
observer.disconnect();
|
|
152
167
|
};
|
|
153
168
|
}, []);
|
|
154
169
|
var _useState = useState(initialValue),
|
|
@@ -202,13 +217,21 @@ var XStarEditor = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
202
217
|
}].concat(_toConsumableArray((_editorProps$plugins = editorProps === null || editorProps === void 0 ? void 0 : editorProps.plugins) !== null && _editorProps$plugins !== void 0 ? _editorProps$plugins : []));
|
|
203
218
|
}, [locale, editOnly, viewOnly, fullscreen, editorProps === null || editorProps === void 0 ? void 0 : editorProps.plugins]);
|
|
204
219
|
|
|
205
|
-
//
|
|
220
|
+
// 防止出现两个滚动条,按下 Esc 退出全屏
|
|
206
221
|
useEffect(function () {
|
|
207
222
|
if (fullscreen) {
|
|
208
223
|
var overflow = document.body.style.overflow;
|
|
224
|
+
var listener = createKeybindingsHandler({
|
|
225
|
+
Escape: function Escape(e) {
|
|
226
|
+
e.stopPropagation();
|
|
227
|
+
setFullscreen(false);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
209
230
|
document.body.style.overflow = 'hidden';
|
|
231
|
+
document.addEventListener('keydown', listener);
|
|
210
232
|
return function () {
|
|
211
233
|
document.body.style.overflow = overflow;
|
|
234
|
+
document.removeEventListener('keydown', listener);
|
|
212
235
|
};
|
|
213
236
|
}
|
|
214
237
|
}, [fullscreen]);
|
|
@@ -223,6 +246,7 @@ var XStarEditor = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
223
246
|
height: height,
|
|
224
247
|
locale: locale,
|
|
225
248
|
initialValue: initialValue,
|
|
249
|
+
readOnly: viewOnly || readOnly,
|
|
226
250
|
plugins: editorPlugins,
|
|
227
251
|
onChange: function onChange(value) {
|
|
228
252
|
setValue(value);
|
|
@@ -16,12 +16,13 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
16
16
|
locale = _ref.locale,
|
|
17
17
|
_ref$initialValue = _ref.initialValue,
|
|
18
18
|
initialValue = _ref$initialValue === void 0 ? '' : _ref$initialValue,
|
|
19
|
+
readOnly = _ref.readOnly,
|
|
19
20
|
plugins = _ref.plugins,
|
|
20
21
|
onChange = _ref.onChange,
|
|
21
22
|
onInsertFile = _ref.onInsertFile;
|
|
22
23
|
var containerRef = useRef(null);
|
|
23
24
|
var container = useContainer(containerRef);
|
|
24
|
-
var _useHistory = useHistory(initialValue),
|
|
25
|
+
var _useHistory = useHistory(initialValue, readOnly),
|
|
25
26
|
history = _useHistory.history,
|
|
26
27
|
sourceCode = _useHistory.sourceCode,
|
|
27
28
|
selection = _useHistory.selection,
|
|
@@ -124,6 +125,11 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
124
125
|
});
|
|
125
126
|
break;
|
|
126
127
|
}
|
|
128
|
+
case 'compositionstart':
|
|
129
|
+
{
|
|
130
|
+
container.normalizeSelection();
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
127
133
|
}
|
|
128
134
|
};
|
|
129
135
|
var dragEventHandler = function dragEventHandler(e) {
|
|
@@ -369,6 +375,7 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
369
375
|
contentEditable: true,
|
|
370
376
|
onBlur: focusEventHandler,
|
|
371
377
|
onCompositionEnd: compositionEventHandler,
|
|
378
|
+
onCompositionStart: compositionEventHandler,
|
|
372
379
|
onCopy: clipboardEventHandler,
|
|
373
380
|
onCut: clipboardEventHandler,
|
|
374
381
|
onDragStart: dragEventHandler,
|