x-star-editor 0.1.1 → 0.2.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.
@@ -1,5 +1,6 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
1
2
  import classNames from 'classnames';
2
- import React, { useEffect, useImperativeHandle, useRef } from 'react';
3
+ import React, { useEffect, useImperativeHandle, useMemo, useRef } from 'react';
3
4
  import Toolbar, { getDefaultToolbarItemMap, getDefaultToolbarItems } from "../components/Toolbar";
4
5
  import { LocaleProvider } from "../locales";
5
6
  import { getRange, useContainer } from "../utils/container";
@@ -9,6 +10,7 @@ import { useHistory } from "../utils/history";
9
10
  var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
10
11
  var className = _ref.className,
11
12
  style = _ref.style,
13
+ height = _ref.height,
12
14
  toolbarClassName = _ref.toolbarClassName,
13
15
  toolbarStyle = _ref.toolbarStyle,
14
16
  locale = _ref.locale,
@@ -24,17 +26,12 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
24
26
  selection = _useHistory.selection,
25
27
  dispatch = _useHistory.dispatch;
26
28
  var initialized = useRef(false);
27
- var onChangeLatest = useRef(onChange);
28
- onChangeLatest.current = onChange;
29
- var onInsertFileLatest = useRef(onInsertFile);
30
- onInsertFileLatest.current = onInsertFile;
31
29
 
32
30
  // 将文本同步到容器
33
31
  useEffect(function () {
34
32
  container.setText(sourceCode);
35
33
  if (initialized.current) {
36
- var _onChangeLatest$curre;
37
- (_onChangeLatest$curre = onChangeLatest.current) === null || _onChangeLatest$curre === void 0 ? void 0 : _onChangeLatest$curre.call(onChangeLatest, sourceCode);
34
+ onChange === null || onChange === void 0 ? void 0 : onChange(sourceCode);
38
35
  }
39
36
  }, [sourceCode]);
40
37
 
@@ -80,7 +77,7 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
80
77
  useImperativeHandle(ref, function () {
81
78
  return {
82
79
  exec: exec,
83
- getContainer: function getContainer() {
80
+ getEditorContainer: function getEditorContainer() {
84
81
  return container.ref.current;
85
82
  }
86
83
  };
@@ -96,7 +93,7 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
96
93
  {
97
94
  e.preventDefault();
98
95
  if (startOffset < endOffset) {
99
- e.clipboardData.setData('text/plain', sourceCodeLatest.current.slice(startOffset, endOffset));
96
+ e.clipboardData.setData('text/plain', sourceCode.slice(startOffset, endOffset));
100
97
  if (e.type === 'cut') {
101
98
  dispatch({
102
99
  type: 'delete',
@@ -118,9 +115,8 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
118
115
  selection: selection
119
116
  });
120
117
  } else if (e.clipboardData.types.includes('Files')) {
121
- var _onInsertFileLatest$c;
122
118
  var _file = e.clipboardData.files[0];
123
- (_onInsertFileLatest$c = onInsertFileLatest.current) === null || _onInsertFileLatest$c === void 0 ? void 0 : _onInsertFileLatest$c.call(onInsertFileLatest, _file, {
119
+ onInsertFile === null || onInsertFile === void 0 ? void 0 : onInsertFile(_file, {
124
120
  description: _file.name,
125
121
  image: _file.type.startsWith('image/')
126
122
  });
@@ -134,27 +130,55 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
134
130
  * 开始组合时的选区
135
131
  */
136
132
  var compositionStartSelection = useRef();
133
+
134
+ /**
135
+ * 容器同步控制器
136
+ */
137
+ var syncController = useMemo(function () {
138
+ var timer = 0;
139
+
140
+ /**
141
+ * 将最新的文本和选区同步到容器
142
+ */
143
+ var sync = function sync() {
144
+ if (compositionStartSelection.current) {
145
+ var _selection = getSelection();
146
+ container.setText(sourceCodeLatest.current);
147
+ container.setSelection(_selection);
148
+ compositionStartSelection.current = undefined;
149
+ }
150
+ timer = 0;
151
+ };
152
+ return {
153
+ /**
154
+ * 在下个事件循环中同步
155
+ */
156
+ start: function start() {
157
+ if (!timer) {
158
+ timer = window.setTimeout(sync);
159
+ }
160
+ },
161
+ /**
162
+ * 立即执行下个事件循环中的同步
163
+ */
164
+ flush: function flush() {
165
+ if (timer) {
166
+ window.clearTimeout(timer);
167
+ sync();
168
+ }
169
+ }
170
+ };
171
+ }, []);
137
172
  var compositionEventHandler = function compositionEventHandler(e) {
138
173
  switch (e.type) {
139
174
  case 'compositionend':
140
175
  {
141
- if (compositionStartSelection.current) {
142
- dispatch({
143
- type: 'insert',
144
- payload: {
145
- text: e.data
146
- },
147
- selection: compositionStartSelection.current
148
- });
149
- // 确保组合事件屏蔽表单和键盘事件
150
- window.setTimeout(function () {
151
- return compositionStartSelection.current = undefined;
152
- });
153
- }
176
+ syncController.start();
154
177
  break;
155
178
  }
156
179
  case 'compositionstart':
157
180
  {
181
+ syncController.flush();
158
182
  compositionStartSelection.current = getSelection();
159
183
  break;
160
184
  }
@@ -164,7 +188,7 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
164
188
  switch (e.type) {
165
189
  case 'drop':
166
190
  {
167
- var _selection = getSelection();
191
+ var _selection2 = getSelection();
168
192
  window.setTimeout(function () {
169
193
  container.normalize();
170
194
  dispatch({
@@ -173,7 +197,7 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
173
197
  sourceCode: container.getText(),
174
198
  selection: getSelection()
175
199
  },
176
- selection: _selection
200
+ selection: _selection2
177
201
  });
178
202
  });
179
203
  break;
@@ -185,57 +209,60 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
185
209
  case 'blur':
186
210
  {
187
211
  blurSelection.current = getSelection();
188
- window.setTimeout(function () {
189
- compositionStartSelection.current = undefined;
190
- container.setText(sourceCodeLatest.current);
191
- });
192
212
  break;
193
213
  }
194
214
  }
195
215
  };
196
216
  var formEventHandler = function formEventHandler(e) {
197
- if (compositionStartSelection.current) {
198
- return;
199
- }
200
217
  switch (e.type) {
201
218
  case 'beforeinput':
202
219
  {
203
220
  e.preventDefault();
204
221
  if ('data' in e && typeof e.data === 'string') {
222
+ var _compositionStartSele;
205
223
  dispatch({
206
224
  type: 'insert',
207
225
  payload: {
208
226
  text: e.data
209
227
  },
210
- selection: getSelection()
228
+ selection: (_compositionStartSele = compositionStartSelection.current) !== null && _compositionStartSele !== void 0 ? _compositionStartSele : getSelection()
211
229
  });
230
+ compositionStartSelection.current = undefined;
212
231
  }
213
232
  break;
214
233
  }
215
234
  }
216
235
  };
217
- var _composeHandlers = composeHandlers(plugins)({
218
- toolbarItemMap: getDefaultToolbarItemMap(locale, onInsertFileLatest.current),
236
+ var onInsertFileLatest = useRef(onInsertFile);
237
+ onInsertFileLatest.current = onInsertFile;
238
+ var options = useMemo(function () {
239
+ return composeHandlers(plugins)({
240
+ toolbarItemMap: getDefaultToolbarItemMap(locale, function () {
241
+ var _onInsertFileLatest$c;
242
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
243
+ args[_key] = arguments[_key];
244
+ }
245
+ return (_onInsertFileLatest$c = onInsertFileLatest.current) === null || _onInsertFileLatest$c === void 0 ? void 0 : _onInsertFileLatest$c.call.apply(_onInsertFileLatest$c, [onInsertFileLatest].concat(args));
246
+ }),
219
247
  toolbarItems: getDefaultToolbarItems(),
220
248
  keyboardEventHandlers: getDefaultKeyboardEventHandlers()
221
- }),
222
- toolbarItemMap = _composeHandlers.toolbarItemMap,
223
- toolbarItems = _composeHandlers.toolbarItems,
224
- keyboardEventHandlers = _composeHandlers.keyboardEventHandlers;
249
+ });
250
+ }, [locale, plugins]);
225
251
  var keyboardEventHandler = function keyboardEventHandler(e) {
226
- if (compositionStartSelection.current) {
227
- return;
228
- }
229
252
  switch (e.type) {
230
253
  case 'keydown':
231
254
  {
232
- composeHandlers(keyboardEventHandlers)({
233
- history: historyLatest.current,
234
- sourceCode: sourceCodeLatest.current,
235
- selection: getSelection(),
236
- dispatch: dispatch,
237
- e: e
238
- });
255
+ if (compositionStartSelection.current) {
256
+ e.preventDefault();
257
+ } else {
258
+ composeHandlers(options.keyboardEventHandlers)({
259
+ history: history,
260
+ sourceCode: sourceCode,
261
+ selection: getSelection(),
262
+ dispatch: dispatch,
263
+ e: e
264
+ });
265
+ }
239
266
  break;
240
267
  }
241
268
  }
@@ -245,13 +272,15 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
245
272
  }, /*#__PURE__*/React.createElement(Toolbar, {
246
273
  className: classNames(toolbarClassName),
247
274
  style: toolbarStyle,
248
- itemMap: toolbarItemMap,
249
- items: toolbarItems,
275
+ itemMap: options.toolbarItemMap,
276
+ items: options.toolbarItems,
250
277
  exec: exec
251
278
  }), /*#__PURE__*/React.createElement("div", {
252
279
  ref: container.ref,
253
280
  className: classNames("".concat(prefix, "md-editor"), className),
254
- style: style,
281
+ style: _objectSpread(_objectSpread({}, style), {}, {
282
+ height: height
283
+ }),
255
284
  contentEditable: true,
256
285
  onBeforeInput: formEventHandler,
257
286
  onBlur: focusEventHandler,
@@ -1,10 +1,27 @@
1
+ import type { Components } from 'hast-util-to-jsx-runtime';
1
2
  import React from 'react';
2
- import type { ViewerOptions } from '../utils/markdown';
3
+ import type { Schema } from '../utils/markdown';
4
+ export interface ViewerOptions {
5
+ /**
6
+ * 自定义过滤模式
7
+ */
8
+ customSchema: Schema;
9
+ /**
10
+ * 自定义 HTML 元素
11
+ */
12
+ customHTMLElements: Partial<Components>;
13
+ /**
14
+ * 自定义块
15
+ */
16
+ customBlocks: Partial<Record<string, React.ComponentType<{
17
+ children: string;
18
+ }>>>;
19
+ }
3
20
  export interface XStarMdViewerPlugin {
4
21
  (ctx: ViewerOptions): void;
5
22
  }
6
23
  export interface XStarMdViewerHandle {
7
- getContainer: () => HTMLDivElement | null;
24
+ getViewerContainer: () => HTMLDivElement;
8
25
  }
9
26
  export interface XStarMdViewerProps {
10
27
  /**
@@ -15,6 +32,10 @@ export interface XStarMdViewerProps {
15
32
  * CSS 样式
16
33
  */
17
34
  style?: React.CSSProperties;
35
+ /**
36
+ * 浏览器的高度
37
+ */
38
+ height?: React.CSSProperties['height'];
18
39
  /**
19
40
  * 文本
20
41
  */
@@ -23,6 +44,10 @@ export interface XStarMdViewerProps {
23
44
  * 插件
24
45
  */
25
46
  plugins?: XStarMdViewerPlugin[];
47
+ /**
48
+ * 是否启用 Web Worker
49
+ */
50
+ enableWebWorker?: boolean;
26
51
  }
27
52
  declare const XStarMdViewer: React.ForwardRefExoticComponent<XStarMdViewerProps & React.RefAttributes<XStarMdViewerHandle>>;
28
53
  export default XStarMdViewer;