@wordpress/compose
Version:
WordPress higher-order components (HOCs).
8 lines (7 loc) • 10.9 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../src/utils/debounce/index.ts"],
"sourcesContent": ["/**\n * Parts of this source were derived and modified from lodash,\n * released under the MIT license.\n *\n * https://github.com/lodash/lodash\n *\n * Copyright JS Foundation and other contributors <https://js.foundation/>\n *\n * Based on Underscore.js, copyright Jeremy Ashkenas,\n * DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>\n *\n * This software consists of voluntary contributions made by many\n * individuals. For exact contribution history, see the revision history\n * available at https://github.com/lodash/lodash\n *\n * The following license applies to all parts of this software except as\n * documented below:\n *\n * ====\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nexport interface DebounceOptions {\n\tleading: boolean;\n\tmaxWait: number;\n\ttrailing: boolean;\n}\n\nexport interface DebouncedFunc< T extends ( ...args: any[] ) => any > {\n\t/**\n\t * Call the original function, but applying the debounce rules.\n\t *\n\t * If the debounced function can be run immediately, this calls it and returns its return\n\t * value.\n\t *\n\t * Otherwise, it returns the return value of the last invocation, or undefined if the debounced\n\t * function was not invoked yet.\n\t */\n\t( ...args: Parameters< T > ): ReturnType< T > | undefined;\n\n\t/**\n\t * Throw away any pending invocation of the debounced function.\n\t */\n\tcancel: () => void;\n\n\t/**\n\t * If there is a pending invocation of the debounced function, invoke it immediately and return\n\t * its return value.\n\t *\n\t * Otherwise, return the value from the last invocation, or undefined if the debounced function\n\t * was never invoked.\n\t */\n\tflush: () => ReturnType< T > | undefined;\n}\n\n/**\n * A simplified and properly typed version of lodash's `debounce`, that\n * always uses timers instead of sometimes using rAF.\n *\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel delayed\n * `func` invocations and a `flush` method to immediately invoke them. Provide\n * `options` to indicate whether `func` should be invoked on the leading and/or\n * trailing edge of the `wait` timeout. The `func` is invoked with the last\n * arguments provided to the debounced function. Subsequent calls to the debounced\n * function return the result of the last `func` invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * @param {Function} func The function to debounce.\n * @param {number} wait The number of milliseconds to delay.\n * @param {Partial< DebounceOptions >} options The options object.\n * @param {boolean} options.leading Specify invoking on the leading edge of the timeout.\n * @param {number} options.maxWait The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} options.trailing Specify invoking on the trailing edge of the timeout.\n *\n * @return Returns the new debounced function.\n */\nexport const debounce = < FunctionT extends ( ...args: unknown[] ) => unknown >(\n\tfunc: FunctionT,\n\twait: number,\n\toptions?: Partial< DebounceOptions >\n) => {\n\tlet lastArgs: Parameters< FunctionT > | undefined;\n\tlet lastThis: unknown | undefined;\n\tlet maxWait = 0;\n\tlet result: ReturnType< FunctionT >;\n\tlet timerId: ReturnType< typeof setTimeout > | undefined;\n\tlet lastCallTime: number | undefined;\n\n\tlet lastInvokeTime = 0;\n\tlet leading = false;\n\tlet maxing = false;\n\tlet trailing = true;\n\n\tif ( options ) {\n\t\tleading = !! options.leading;\n\t\tmaxing = 'maxWait' in options;\n\t\tif ( options.maxWait !== undefined ) {\n\t\t\tmaxWait = Math.max( options.maxWait, wait );\n\t\t}\n\t\ttrailing = 'trailing' in options ? !! options.trailing : trailing;\n\t}\n\n\tfunction invokeFunc( time: number ) {\n\t\tconst args = lastArgs;\n\t\tconst thisArg = lastThis;\n\n\t\tlastArgs = undefined;\n\t\tlastThis = undefined;\n\t\tlastInvokeTime = time;\n\n\t\tresult = func.apply( thisArg, args! ) as ReturnType< FunctionT >;\n\t\treturn result;\n\t}\n\n\tfunction startTimer(\n\t\tpendingFunc: () => void,\n\t\twaitTime: number | undefined\n\t) {\n\t\ttimerId = setTimeout( pendingFunc, waitTime );\n\t}\n\n\tfunction cancelTimer() {\n\t\tif ( timerId !== undefined ) {\n\t\t\tclearTimeout( timerId );\n\t\t}\n\t}\n\n\tfunction leadingEdge( time: number ) {\n\t\t// Reset any `maxWait` timer.\n\t\tlastInvokeTime = time;\n\t\t// Start the timer for the trailing edge.\n\t\tstartTimer( timerExpired, wait );\n\t\t// Invoke the leading edge.\n\t\treturn leading ? invokeFunc( time ) : result;\n\t}\n\n\tfunction getTimeSinceLastCall( time: number ) {\n\t\treturn time - ( lastCallTime || 0 );\n\t}\n\n\tfunction remainingWait( time: number ) {\n\t\tconst timeSinceLastCall = getTimeSinceLastCall( time );\n\t\tconst timeSinceLastInvoke = time - lastInvokeTime;\n\t\tconst timeWaiting = wait - timeSinceLastCall;\n\n\t\treturn maxing\n\t\t\t? Math.min( timeWaiting, maxWait - timeSinceLastInvoke )\n\t\t\t: timeWaiting;\n\t}\n\n\tfunction shouldInvoke( time: number ) {\n\t\tconst timeSinceLastCall = getTimeSinceLastCall( time );\n\t\tconst timeSinceLastInvoke = time - lastInvokeTime;\n\n\t\t// Either this is the first call, activity has stopped and we're at the\n\t\t// trailing edge, the system time has gone backwards and we're treating\n\t\t// it as the trailing edge, or we've hit the `maxWait` limit.\n\t\treturn (\n\t\t\tlastCallTime === undefined ||\n\t\t\ttimeSinceLastCall >= wait ||\n\t\t\ttimeSinceLastCall < 0 ||\n\t\t\t( maxing && timeSinceLastInvoke >= maxWait )\n\t\t);\n\t}\n\n\tfunction timerExpired() {\n\t\tconst time = Date.now();\n\t\tif ( shouldInvoke( time ) ) {\n\t\t\treturn trailingEdge( time );\n\t\t}\n\t\t// Restart the timer.\n\t\tstartTimer( timerExpired, remainingWait( time ) );\n\t\treturn undefined;\n\t}\n\n\tfunction clearTimer() {\n\t\ttimerId = undefined;\n\t}\n\n\tfunction trailingEdge( time: number ) {\n\t\tclearTimer();\n\n\t\t// Only invoke if we have `lastArgs` which means `func` has been\n\t\t// debounced at least once.\n\t\tif ( trailing && lastArgs ) {\n\t\t\treturn invokeFunc( time );\n\t\t}\n\t\tlastArgs = lastThis = undefined;\n\t\treturn result;\n\t}\n\n\tfunction cancel() {\n\t\tcancelTimer();\n\t\tlastInvokeTime = 0;\n\t\tclearTimer();\n\t\tlastArgs = lastCallTime = lastThis = undefined;\n\t}\n\n\tfunction flush() {\n\t\treturn pending() ? trailingEdge( Date.now() ) : result;\n\t}\n\n\tfunction pending() {\n\t\treturn timerId !== undefined;\n\t}\n\n\tfunction debounced( this: unknown, ...args: Parameters< FunctionT > ) {\n\t\tconst time = Date.now();\n\t\tconst isInvoking = shouldInvoke( time );\n\n\t\tlastArgs = args;\n\t\tlastThis = this;\n\t\tlastCallTime = time;\n\n\t\tif ( isInvoking ) {\n\t\t\tif ( ! pending() ) {\n\t\t\t\treturn leadingEdge( lastCallTime );\n\t\t\t}\n\t\t\tif ( maxing ) {\n\t\t\t\t// Handle invocations in a tight loop.\n\t\t\t\tstartTimer( timerExpired, wait );\n\t\t\t\treturn invokeFunc( lastCallTime );\n\t\t\t}\n\t\t}\n\t\tif ( ! pending() ) {\n\t\t\tstartTimer( timerExpired, wait );\n\t\t}\n\t\treturn result;\n\t}\n\tdebounced.cancel = cancel;\n\tdebounced.flush = flush;\n\tdebounced.pending = pending;\n\treturn debounced;\n};\n"],
"mappings": ";AAsGO,IAAM,WAAW,CACvB,MACA,MACA,YACI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,UAAU;AACd,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,iBAAiB;AACrB,MAAI,UAAU;AACd,MAAI,SAAS;AACb,MAAI,WAAW;AAEf,MAAK,SAAU;AACd,cAAU,CAAC,CAAE,QAAQ;AACrB,aAAS,aAAa;AACtB,QAAK,QAAQ,YAAY,QAAY;AACpC,gBAAU,KAAK,IAAK,QAAQ,SAAS,IAAK;AAAA,IAC3C;AACA,eAAW,cAAc,UAAU,CAAC,CAAE,QAAQ,WAAW;AAAA,EAC1D;AAEA,WAAS,WAAY,MAAe;AACnC,UAAM,OAAO;AACb,UAAM,UAAU;AAEhB,eAAW;AACX,eAAW;AACX,qBAAiB;AAEjB,aAAS,KAAK,MAAO,SAAS,IAAM;AACpC,WAAO;AAAA,EACR;AAEA,WAAS,WACR,aACA,UACC;AACD,cAAU,WAAY,aAAa,QAAS;AAAA,EAC7C;AAEA,WAAS,cAAc;AACtB,QAAK,YAAY,QAAY;AAC5B,mBAAc,OAAQ;AAAA,IACvB;AAAA,EACD;AAEA,WAAS,YAAa,MAAe;AAEpC,qBAAiB;AAEjB,eAAY,cAAc,IAAK;AAE/B,WAAO,UAAU,WAAY,IAAK,IAAI;AAAA,EACvC;AAEA,WAAS,qBAAsB,MAAe;AAC7C,WAAO,QAAS,gBAAgB;AAAA,EACjC;AAEA,WAAS,cAAe,MAAe;AACtC,UAAM,oBAAoB,qBAAsB,IAAK;AACrD,UAAM,sBAAsB,OAAO;AACnC,UAAM,cAAc,OAAO;AAE3B,WAAO,SACJ,KAAK,IAAK,aAAa,UAAU,mBAAoB,IACrD;AAAA,EACJ;AAEA,WAAS,aAAc,MAAe;AACrC,UAAM,oBAAoB,qBAAsB,IAAK;AACrD,UAAM,sBAAsB,OAAO;AAKnC,WACC,iBAAiB,UACjB,qBAAqB,QACrB,oBAAoB,KAClB,UAAU,uBAAuB;AAAA,EAErC;AAEA,WAAS,eAAe;AACvB,UAAM,OAAO,KAAK,IAAI;AACtB,QAAK,aAAc,IAAK,GAAI;AAC3B,aAAO,aAAc,IAAK;AAAA,IAC3B;AAEA,eAAY,cAAc,cAAe,IAAK,CAAE;AAChD,WAAO;AAAA,EACR;AAEA,WAAS,aAAa;AACrB,cAAU;AAAA,EACX;AAEA,WAAS,aAAc,MAAe;AACrC,eAAW;AAIX,QAAK,YAAY,UAAW;AAC3B,aAAO,WAAY,IAAK;AAAA,IACzB;AACA,eAAW,WAAW;AACtB,WAAO;AAAA,EACR;AAEA,WAAS,SAAS;AACjB,gBAAY;AACZ,qBAAiB;AACjB,eAAW;AACX,eAAW,eAAe,WAAW;AAAA,EACtC;AAEA,WAAS,QAAQ;AAChB,WAAO,QAAQ,IAAI,aAAc,KAAK,IAAI,CAAE,IAAI;AAAA,EACjD;AAEA,WAAS,UAAU;AAClB,WAAO,YAAY;AAAA,EACpB;AAEA,WAAS,aAA6B,MAAgC;AACrE,UAAM,OAAO,KAAK,IAAI;AACtB,UAAM,aAAa,aAAc,IAAK;AAEtC,eAAW;AACX,eAAW;AACX,mBAAe;AAEf,QAAK,YAAa;AACjB,UAAK,CAAE,QAAQ,GAAI;AAClB,eAAO,YAAa,YAAa;AAAA,MAClC;AACA,UAAK,QAAS;AAEb,mBAAY,cAAc,IAAK;AAC/B,eAAO,WAAY,YAAa;AAAA,MACjC;AAAA,IACD;AACA,QAAK,CAAE,QAAQ,GAAI;AAClB,iBAAY,cAAc,IAAK;AAAA,IAChC;AACA,WAAO;AAAA,EACR;AACA,YAAU,SAAS;AACnB,YAAU,QAAQ;AAClB,YAAU,UAAU;AACpB,SAAO;AACR;",
"names": []
}