@uiw/react-codemirror 4.23.13 → 4.23.14

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,22 @@
1
+ export declare class TimeoutLatch {
2
+ private timeLeftMS;
3
+ private timeoutMS;
4
+ private isCancelled;
5
+ private isTimeExhausted;
6
+ private callbacks;
7
+ constructor(callback: Function, timeoutMS: number);
8
+ tick(): void;
9
+ cancel(): void;
10
+ reset(): void;
11
+ get isDone(): boolean;
12
+ }
13
+ declare class Scheduler {
14
+ private interval;
15
+ private latches;
16
+ add(latch: TimeoutLatch): void;
17
+ remove(latch: TimeoutLatch): void;
18
+ private start;
19
+ private stop;
20
+ }
21
+ export declare const getScheduler: () => Scheduler;
22
+ export {};
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.getScheduler = exports.TimeoutLatch = void 0;
8
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
+ // Setting / Unsetting timeouts for every keystroke was a significant overhead
12
+ // Inspired from https://github.com/iostreamer-X/timeout-latch
13
+ var TimeoutLatch = exports.TimeoutLatch = /*#__PURE__*/function () {
14
+ function TimeoutLatch(callback, timeoutMS) {
15
+ (0, _classCallCheck2["default"])(this, TimeoutLatch);
16
+ (0, _defineProperty2["default"])(this, "timeLeftMS", void 0);
17
+ (0, _defineProperty2["default"])(this, "timeoutMS", void 0);
18
+ (0, _defineProperty2["default"])(this, "isCancelled", false);
19
+ (0, _defineProperty2["default"])(this, "isTimeExhausted", false);
20
+ (0, _defineProperty2["default"])(this, "callbacks", []);
21
+ this.timeLeftMS = timeoutMS;
22
+ this.timeoutMS = timeoutMS;
23
+ this.callbacks.push(callback);
24
+ }
25
+ return (0, _createClass2["default"])(TimeoutLatch, [{
26
+ key: "tick",
27
+ value: function tick() {
28
+ if (!this.isCancelled && !this.isTimeExhausted) {
29
+ this.timeLeftMS--;
30
+ if (this.timeLeftMS <= 0) {
31
+ this.isTimeExhausted = true;
32
+ var callbacks = this.callbacks.slice();
33
+ this.callbacks.length = 0;
34
+ callbacks.forEach(function (callback) {
35
+ try {
36
+ callback();
37
+ } catch (error) {
38
+ console.error('TimeoutLatch callback error:', error);
39
+ }
40
+ });
41
+ }
42
+ }
43
+ }
44
+ }, {
45
+ key: "cancel",
46
+ value: function cancel() {
47
+ this.isCancelled = true;
48
+ this.callbacks.length = 0;
49
+ }
50
+ }, {
51
+ key: "reset",
52
+ value: function reset() {
53
+ this.timeLeftMS = this.timeoutMS;
54
+ this.isCancelled = false;
55
+ this.isTimeExhausted = false;
56
+ }
57
+ }, {
58
+ key: "isDone",
59
+ get: function get() {
60
+ return this.isCancelled || this.isTimeExhausted;
61
+ }
62
+ }]);
63
+ }();
64
+ var Scheduler = /*#__PURE__*/function () {
65
+ function Scheduler() {
66
+ (0, _classCallCheck2["default"])(this, Scheduler);
67
+ (0, _defineProperty2["default"])(this, "interval", null);
68
+ (0, _defineProperty2["default"])(this, "latches", new Set());
69
+ }
70
+ return (0, _createClass2["default"])(Scheduler, [{
71
+ key: "add",
72
+ value: function add(latch) {
73
+ this.latches.add(latch);
74
+ this.start();
75
+ }
76
+ }, {
77
+ key: "remove",
78
+ value: function remove(latch) {
79
+ this.latches["delete"](latch);
80
+ if (this.latches.size === 0) {
81
+ this.stop();
82
+ }
83
+ }
84
+ }, {
85
+ key: "start",
86
+ value: function start() {
87
+ var _this = this;
88
+ if (this.interval === null) {
89
+ this.interval = setInterval(function () {
90
+ _this.latches.forEach(function (latch) {
91
+ latch.tick();
92
+ if (latch.isDone) {
93
+ _this.remove(latch);
94
+ }
95
+ });
96
+ }, 1);
97
+ }
98
+ }
99
+ }, {
100
+ key: "stop",
101
+ value: function stop() {
102
+ if (this.interval !== null) {
103
+ clearInterval(this.interval);
104
+ this.interval = null;
105
+ }
106
+ }
107
+ }]);
108
+ }();
109
+ var globalScheduler = null;
110
+ var getScheduler = exports.getScheduler = function getScheduler() {
111
+ if (typeof window === 'undefined') {
112
+ return new Scheduler();
113
+ }
114
+ if (!globalScheduler) {
115
+ globalScheduler = new Scheduler();
116
+ }
117
+ return globalScheduler;
118
+ };
@@ -12,7 +12,10 @@ var _state = require("@codemirror/state");
12
12
  var _view = require("@codemirror/view");
13
13
  var _getDefaultExtensions = require("./getDefaultExtensions");
14
14
  var _utils = require("./utils");
15
+ var _timeoutLatch = require("./timeoutLatch");
15
16
  var External = _state.Annotation.define();
17
+ var TYPING_TIMOUT = 200; // ms
18
+
16
19
  var emptyExtensions = [];
17
20
  function useCodeMirror(props) {
18
21
  var value = props.value,
@@ -62,6 +65,16 @@ function useCodeMirror(props) {
62
65
  _useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
63
66
  state = _useState6[0],
64
67
  setState = _useState6[1];
68
+ var typingLatch = (0, _react.useState)(function () {
69
+ return {
70
+ current: null
71
+ };
72
+ })[0];
73
+ var pendingUpdate = (0, _react.useState)(function () {
74
+ return {
75
+ current: null
76
+ };
77
+ })[0];
65
78
  var defaultThemeOption = _view.EditorView.theme({
66
79
  '&': {
67
80
  height: height,
@@ -82,6 +95,19 @@ function useCodeMirror(props) {
82
95
  !vu.transactions.some(function (tr) {
83
96
  return tr.annotation(External);
84
97
  })) {
98
+ if (typingLatch.current) {
99
+ typingLatch.current.reset();
100
+ } else {
101
+ typingLatch.current = new _timeoutLatch.TimeoutLatch(function () {
102
+ if (pendingUpdate.current) {
103
+ var forceUpdate = pendingUpdate.current;
104
+ pendingUpdate.current = null;
105
+ forceUpdate();
106
+ }
107
+ typingLatch.current = null;
108
+ }, TYPING_TIMOUT);
109
+ (0, _timeoutLatch.getScheduler)().add(typingLatch.current);
110
+ }
85
111
  var doc = vu.state.doc;
86
112
  var _value = doc.toString();
87
113
  onChange(_value, vu);
@@ -138,6 +164,10 @@ function useCodeMirror(props) {
138
164
  view.destroy();
139
165
  setView(undefined);
140
166
  }
167
+ if (typingLatch.current) {
168
+ typingLatch.current.cancel();
169
+ typingLatch.current = null;
170
+ }
141
171
  };
142
172
  }, [view]);
143
173
  (0, _react.useEffect)(function () {
@@ -159,14 +189,24 @@ function useCodeMirror(props) {
159
189
  }
160
190
  var currentValue = view ? view.state.doc.toString() : '';
161
191
  if (view && value !== currentValue) {
162
- view.dispatch({
163
- changes: {
164
- from: 0,
165
- to: currentValue.length,
166
- insert: value || ''
167
- },
168
- annotations: [External.of(true)]
169
- });
192
+ var isTyping = typingLatch.current && !typingLatch.current.isDone;
193
+ var forceUpdate = function forceUpdate() {
194
+ if (view && value !== view.state.doc.toString()) {
195
+ view.dispatch({
196
+ changes: {
197
+ from: 0,
198
+ to: view.state.doc.toString().length,
199
+ insert: value || ''
200
+ },
201
+ annotations: [External.of(true)]
202
+ });
203
+ }
204
+ };
205
+ if (!isTyping) {
206
+ forceUpdate();
207
+ } else {
208
+ pendingUpdate.current = forceUpdate;
209
+ }
170
210
  }
171
211
  }, [value, view]);
172
212
  return {