Skip to content

Commit 078146d

Browse files
authored
Merge pull request #4 from devfolioco/pro-595-add-lodash-to-peer-dependencies-in-react
Pro 595 add lodash to peer dependencies in react
2 parents a13abf0 + c3dae2f commit 078146d

File tree

8 files changed

+295
-22
lines changed

8 files changed

+295
-22
lines changed

docs/bundle-prod.js

Lines changed: 7 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devfolioco/react-mde",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"description": "React Markdown Editor",
55
"main": "./lib/js/index.js",
66
"types": "./lib/definitions/index.d.ts",
@@ -64,7 +64,6 @@
6464
"gulp-sass": "^4.0.2",
6565
"gulp-typescript": "^6.0.0-alpha.1",
6666
"jest": "^24.9.0",
67-
"lodash": "4.17.21",
6867
"merge2": "^1.2.1",
6968
"normalize.css": "^8.0.0",
7069
"prettier": "^1.19.1",

src/components/TextArea.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from "react";
2-
import { debounce } from "lodash";
2+
import debounce from "../util/debounce/index";
33
import { classNames, ClassValue } from "../util/ClassNames";
44
import {
55
CaretCoordinates,
@@ -167,7 +167,8 @@ export class TextArea extends React.Component<TextAreaProps, TextAreaState> {
167167

168168
debouncedStartLoadingSuggestions = debounce(
169169
this.startLoadingSuggestions,
170-
this.props.debounceSuggestions ?? DEFAULT_WAIT_TIME
170+
this.props.debounceSuggestions ?? DEFAULT_WAIT_TIME,
171+
{}
171172
);
172173

173174
loadEmptySuggestion = (target: HTMLTextAreaElement, key: string) => {

src/util/debounce/freeGlobal.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* @reference https://github.com/lodash/lodash/blob/master/.internal/freeGlobal.js
3+
*/
4+
/** Detect free variable `global` from Node.js. */
5+
const freeGlobal =
6+
typeof global === "object" &&
7+
global !== null &&
8+
global.Object === Object &&
9+
global;
10+
11+
export default freeGlobal;

src/util/debounce/index.ts

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/**
2+
* @reference https://github.com/lodash/lodash/blob/master/debounce.js
3+
*/
4+
5+
import isObject from "./isObject";
6+
import root from "./root";
7+
8+
/**
9+
* Creates a debounced function that delays invoking `func` until after `wait`
10+
* milliseconds have elapsed since the last time the debounced function was
11+
* invoked, or until the next browser frame is drawn. The debounced function
12+
* comes with a `cancel` method to cancel delayed `func` invocations and a
13+
* `flush` method to immediately invoke them. Provide `options` to indicate
14+
* whether `func` should be invoked on the leading and/or trailing edge of the
15+
* `wait` timeout. The `func` is invoked with the last arguments provided to the
16+
* debounced function. Subsequent calls to the debounced function return the
17+
* result of the last `func` invocation.
18+
*
19+
* **Note:** If `leading` and `trailing` options are `true`, `func` is
20+
* invoked on the trailing edge of the timeout only if the debounced function
21+
* is invoked more than once during the `wait` timeout.
22+
*
23+
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
24+
* until the next tick, similar to `setTimeout` with a timeout of `0`.
25+
*
26+
* If `wait` is omitted in an environment with `requestAnimationFrame`, `func`
27+
* invocation will be deferred until the next frame is drawn (typically about
28+
* 16ms).
29+
*
30+
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
31+
* for details over the differences between `debounce` and `throttle`.
32+
*
33+
* @since 0.1.0
34+
* @category Function
35+
* @param {Function} func The function to debounce.
36+
* @param {number} [wait=0]
37+
* The number of milliseconds to delay; if omitted, `requestAnimationFrame` is
38+
* used (if available).
39+
* @param {Object} [options={}] The options object.
40+
* @param {boolean} [options.leading=false]
41+
* Specify invoking on the leading edge of the timeout.
42+
* @param {number} [options.maxWait]
43+
* The maximum time `func` is allowed to be delayed before it's invoked.
44+
* @param {boolean} [options.trailing=true]
45+
* Specify invoking on the trailing edge of the timeout.
46+
* @returns {Function} Returns the new debounced function.
47+
* @example
48+
*
49+
* // Avoid costly calculations while the window size is in flux.
50+
* jQuery(window).on('resize', debounce(calculateLayout, 150))
51+
*
52+
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
53+
* jQuery(element).on('click', debounce(sendMail, 300, {
54+
* 'leading': true,
55+
* 'trailing': false
56+
* }))
57+
*
58+
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
59+
* const debounced = debounce(batchLog, 250, { 'maxWait': 1000 })
60+
* const source = new EventSource('/stream')
61+
* jQuery(source).on('message', debounced)
62+
*
63+
* // Cancel the trailing debounced invocation.
64+
* jQuery(window).on('popstate', debounced.cancel)
65+
*
66+
* // Check for pending invocations.
67+
* const status = debounced.pending() ? "Pending..." : "Ready"
68+
*/
69+
function debounce(func, wait, options) {
70+
let lastArgs, lastThis, maxWait, result, timerId, lastCallTime;
71+
72+
let lastInvokeTime = 0;
73+
let leading = false;
74+
let maxing = false;
75+
let trailing = true;
76+
77+
// Bypass `requestAnimationFrame` by explicitly setting `wait=0`.
78+
const useRAF =
79+
!wait && wait !== 0 && typeof root.requestAnimationFrame === "function";
80+
81+
if (typeof func !== "function") {
82+
throw new TypeError("Expected a function");
83+
}
84+
wait = +wait || 0;
85+
if (isObject(options)) {
86+
leading = !!options.leading;
87+
maxing = "maxWait" in options;
88+
maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait;
89+
trailing = "trailing" in options ? !!options.trailing : trailing;
90+
}
91+
92+
function invokeFunc(time) {
93+
const args = lastArgs;
94+
const thisArg = lastThis;
95+
96+
lastArgs = lastThis = undefined;
97+
lastInvokeTime = time;
98+
result = func.apply(thisArg, args);
99+
return result;
100+
}
101+
102+
function startTimer(pendingFunc, wait) {
103+
if (useRAF) {
104+
root.cancelAnimationFrame(timerId);
105+
return root.requestAnimationFrame(pendingFunc);
106+
}
107+
return setTimeout(pendingFunc, wait);
108+
}
109+
110+
function cancelTimer(id) {
111+
if (useRAF) {
112+
return root.cancelAnimationFrame(id);
113+
}
114+
clearTimeout(id);
115+
}
116+
117+
function leadingEdge(time) {
118+
// Reset any `maxWait` timer.
119+
lastInvokeTime = time;
120+
// Start the timer for the trailing edge.
121+
timerId = startTimer(timerExpired, wait);
122+
// Invoke the leading edge.
123+
return leading ? invokeFunc(time) : result;
124+
}
125+
126+
function remainingWait(time) {
127+
const timeSinceLastCall = time - lastCallTime;
128+
const timeSinceLastInvoke = time - lastInvokeTime;
129+
const timeWaiting = wait - timeSinceLastCall;
130+
131+
return maxing
132+
? Math.min(timeWaiting, maxWait - timeSinceLastInvoke)
133+
: timeWaiting;
134+
}
135+
136+
function shouldInvoke(time) {
137+
const timeSinceLastCall = time - lastCallTime;
138+
const timeSinceLastInvoke = time - lastInvokeTime;
139+
140+
// Either this is the first call, activity has stopped and we're at the
141+
// trailing edge, the system time has gone backwards and we're treating
142+
// it as the trailing edge, or we've hit the `maxWait` limit.
143+
return (
144+
lastCallTime === undefined ||
145+
timeSinceLastCall >= wait ||
146+
timeSinceLastCall < 0 ||
147+
(maxing && timeSinceLastInvoke >= maxWait)
148+
);
149+
}
150+
151+
function timerExpired() {
152+
const time = Date.now();
153+
if (shouldInvoke(time)) {
154+
return trailingEdge(time);
155+
}
156+
// Restart the timer.
157+
timerId = startTimer(timerExpired, remainingWait(time));
158+
}
159+
160+
function trailingEdge(time) {
161+
timerId = undefined;
162+
163+
// Only invoke if we have `lastArgs` which means `func` has been
164+
// debounced at least once.
165+
if (trailing && lastArgs) {
166+
return invokeFunc(time);
167+
}
168+
lastArgs = lastThis = undefined;
169+
return result;
170+
}
171+
172+
function cancel() {
173+
if (timerId !== undefined) {
174+
cancelTimer(timerId);
175+
}
176+
lastInvokeTime = 0;
177+
lastArgs = lastCallTime = lastThis = timerId = undefined;
178+
}
179+
180+
function flush() {
181+
return timerId === undefined ? result : trailingEdge(Date.now());
182+
}
183+
184+
function pending() {
185+
return timerId !== undefined;
186+
}
187+
188+
function debounced(...args) {
189+
const time = Date.now();
190+
const isInvoking = shouldInvoke(time);
191+
192+
lastArgs = args;
193+
lastThis = this;
194+
lastCallTime = time;
195+
196+
if (isInvoking) {
197+
if (timerId === undefined) {
198+
return leadingEdge(lastCallTime);
199+
}
200+
if (maxing) {
201+
// Handle invocations in a tight loop.
202+
timerId = startTimer(timerExpired, wait);
203+
return invokeFunc(lastCallTime);
204+
}
205+
}
206+
if (timerId === undefined) {
207+
timerId = startTimer(timerExpired, wait);
208+
}
209+
return result;
210+
}
211+
debounced.cancel = cancel;
212+
debounced.flush = flush;
213+
debounced.pending = pending;
214+
return debounced;
215+
}
216+
217+
export default debounce;

src/util/debounce/isObject.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* @reference https://github.com/lodash/lodash/blob/master/isObject.js
3+
*/
4+
/**
5+
* Checks if `value` is the
6+
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
7+
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
8+
*
9+
* @since 0.1.0
10+
* @category Lang
11+
* @param {*} value The value to check.
12+
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
13+
* @example
14+
*
15+
* isObject({})
16+
* // => true
17+
*
18+
* isObject([1, 2, 3])
19+
* // => true
20+
*
21+
* isObject(Function)
22+
* // => true
23+
*
24+
* isObject(null)
25+
* // => false
26+
*/
27+
function isObject(value) {
28+
const type = typeof value;
29+
return value != null && (type === "object" || type === "function");
30+
}
31+
32+
export default isObject;

src/util/debounce/root.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* @reference https://github.com/lodash/lodash/blob/master/.internal/root.js
3+
*/
4+
/* global globalThis, self */
5+
import freeGlobal from "./freeGlobal";
6+
7+
/** Detect free variable `globalThis` */
8+
const freeGlobalThis =
9+
typeof globalThis === "object" &&
10+
globalThis !== null &&
11+
globalThis.Object == Object &&
12+
globalThis;
13+
14+
/** Detect free variable `self`. */
15+
const freeSelf =
16+
typeof self === "object" && self !== null && self.Object === Object && self;
17+
18+
/** Used as a reference to the global object. */
19+
const root =
20+
freeGlobalThis || freeGlobal || freeSelf || Function("return this")();
21+
22+
export default root;

0 commit comments

Comments
 (0)