@scalar/helpers 0.3.0 → 0.4.1
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/CHANGELOG.md +12 -0
- package/dist/general/debounce.d.ts +2 -0
- package/dist/general/debounce.d.ts.map +1 -1
- package/dist/general/debounce.js +13 -1
- package/dist/general/debounce.js.map +2 -2
- package/dist/general/is-mac-os.d.ts +1 -5
- package/dist/general/is-mac-os.d.ts.map +1 -1
- package/dist/general/is-mac-os.js +13 -2
- package/dist/general/is-mac-os.js.map +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @scalar/helpers
|
|
2
2
|
|
|
3
|
+
## 0.4.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#8420](https://github.com/scalar/scalar/pull/8420): fix TypeScript access to navigator.userAgentData in isMacOS without ts-expect-error
|
|
8
|
+
|
|
9
|
+
## 0.4.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#8336](https://github.com/scalar/scalar/pull/8336): feat: support flushing any pending operations
|
|
14
|
+
|
|
3
15
|
## 0.3.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
|
@@ -29,5 +29,7 @@ export type DebounceOptions = {
|
|
|
29
29
|
export declare const debounce: (options?: DebounceOptions) => {
|
|
30
30
|
execute: (key: string, fn: () => unknown | Promise<unknown>) => void;
|
|
31
31
|
cleanup: () => void;
|
|
32
|
+
flush: (key: string) => void;
|
|
33
|
+
flushAll: () => void;
|
|
32
34
|
};
|
|
33
35
|
//# sourceMappingURL=debounce.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../src/general/debounce.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAS,eAAoB;mBA6C9B,MAAM,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAG,IAAI;mBAvCrD,IAAI;
|
|
1
|
+
{"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../src/general/debounce.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAS,eAAoB;mBA6C9B,MAAM,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAG,IAAI;mBAvCrD,IAAI;iBAgEJ,MAAM,KAAG,IAAI;oBAQZ,IAAI;CAQ1B,CAAA"}
|
package/dist/general/debounce.js
CHANGED
|
@@ -47,7 +47,19 @@ const debounce = (options = {}) => {
|
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
|
-
|
|
50
|
+
const flush = (key) => {
|
|
51
|
+
if (!latestFunctions.has(key)) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
executeAndCleanup(key);
|
|
55
|
+
};
|
|
56
|
+
const flushAll = () => {
|
|
57
|
+
const keys = [...latestFunctions.keys()];
|
|
58
|
+
for (const key of keys) {
|
|
59
|
+
executeAndCleanup(key);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
return { execute, cleanup, flush, flushAll };
|
|
51
63
|
};
|
|
52
64
|
export {
|
|
53
65
|
debounce
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/general/debounce.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Options for configuring the debounce behavior.\n */\nexport type DebounceOptions = {\n /** The delay in milliseconds before executing the function. Defaults to 100ms. */\n delay?: number\n /** Maximum time in milliseconds to wait before forcing execution, even with continuous calls. */\n maxWait?: number\n}\n\n/**\n * Creates a debounced function executor that delays execution until after a specified time.\n * Multiple calls with the same key will cancel previous pending executions.\n *\n * This is useful for batching rapid updates (like auto-save or API calls) to avoid\n * unnecessary processing or network requests.\n *\n * @param options - Configuration options for delay, maxWait, and key separator\n * @returns A function that accepts a key array and callback to execute\n *\n * @example\n * const debouncedSave = debounce({ delay: 328 })\n * debouncedSave.execute(['user', '123'], () => saveUser(user))\n *\n * @example\n * // With maxWait to guarantee execution even with continuous calls\n * const debouncedSave = debounce({ delay: 328, maxWait: 2000 })\n * debouncedSave.execute(['user', '123'], () => saveUser(user))\n */\nexport const debounce = (options: DebounceOptions = {}) => {\n const { delay = 328, maxWait } = options\n const timeouts = new Map<string, ReturnType<typeof setTimeout>>()\n const maxWaitTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n const latestFunctions = new Map<string, () => unknown | Promise<unknown>>()\n\n const cleanup = (): void => {\n timeouts.forEach(clearTimeout)\n maxWaitTimeouts.forEach(clearTimeout)\n timeouts.clear()\n maxWaitTimeouts.clear()\n latestFunctions.clear()\n }\n\n /** Executes the function and cleans up all associated timeouts */\n const executeAndCleanup = (key: string): void => {\n // Get the latest function for this key\n const fn = latestFunctions.get(key)\n\n // Clear both timeout types\n const timeout = timeouts.get(key)\n if (timeout !== undefined) {\n clearTimeout(timeout)\n timeouts.delete(key)\n }\n\n const maxWaitTimeout = maxWaitTimeouts.get(key)\n if (maxWaitTimeout !== undefined) {\n clearTimeout(maxWaitTimeout)\n maxWaitTimeouts.delete(key)\n }\n\n // Clear the latest function reference\n latestFunctions.delete(key)\n\n // Execute the function if it exists\n if (fn !== undefined) {\n try {\n fn()\n } catch {\n // Errors are silently caught to prevent the debounce mechanism from breaking\n }\n }\n }\n\n const execute = (key: string, fn: () => unknown | Promise<unknown>): void => {\n // Store the latest function for this key\n latestFunctions.set(key, fn)\n\n // Clear existing debounce timeout\n const existingTimeout = timeouts.get(key)\n if (existingTimeout !== undefined) {\n clearTimeout(existingTimeout)\n }\n\n // Set debounce timeout\n timeouts.set(\n key,\n setTimeout(() => executeAndCleanup(key), delay),\n )\n\n // Set maxWait timeout only if configured and this is a new sequence\n if (maxWait !== undefined && !maxWaitTimeouts.has(key)) {\n maxWaitTimeouts.set(\n key,\n setTimeout(() => executeAndCleanup(key), maxWait),\n )\n }\n }\n\n return { execute, cleanup }\n}\n"],
|
|
5
|
-
"mappings": "AA6BO,MAAM,WAAW,CAAC,UAA2B,CAAC,MAAM;AACzD,QAAM,EAAE,QAAQ,KAAK,QAAQ,IAAI;AACjC,QAAM,WAAW,oBAAI,IAA2C;AAChE,QAAM,kBAAkB,oBAAI,IAA2C;AACvE,QAAM,kBAAkB,oBAAI,IAA8C;AAE1E,QAAM,UAAU,MAAY;AAC1B,aAAS,QAAQ,YAAY;AAC7B,oBAAgB,QAAQ,YAAY;AACpC,aAAS,MAAM;AACf,oBAAgB,MAAM;AACtB,oBAAgB,MAAM;AAAA,EACxB;AAGA,QAAM,oBAAoB,CAAC,QAAsB;AAE/C,UAAM,KAAK,gBAAgB,IAAI,GAAG;AAGlC,UAAM,UAAU,SAAS,IAAI,GAAG;AAChC,QAAI,YAAY,QAAW;AACzB,mBAAa,OAAO;AACpB,eAAS,OAAO,GAAG;AAAA,IACrB;AAEA,UAAM,iBAAiB,gBAAgB,IAAI,GAAG;AAC9C,QAAI,mBAAmB,QAAW;AAChC,mBAAa,cAAc;AAC3B,sBAAgB,OAAO,GAAG;AAAA,IAC5B;AAGA,oBAAgB,OAAO,GAAG;AAG1B,QAAI,OAAO,QAAW;AACpB,UAAI;AACF,WAAG;AAAA,MACL,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,CAAC,KAAa,OAA+C;AAE3E,oBAAgB,IAAI,KAAK,EAAE;AAG3B,UAAM,kBAAkB,SAAS,IAAI,GAAG;AACxC,QAAI,oBAAoB,QAAW;AACjC,mBAAa,eAAe;AAAA,IAC9B;AAGA,aAAS;AAAA,MACP;AAAA,MACA,WAAW,MAAM,kBAAkB,GAAG,GAAG,KAAK;AAAA,IAChD;AAGA,QAAI,YAAY,UAAa,CAAC,gBAAgB,IAAI,GAAG,GAAG;AACtD,sBAAgB;AAAA,QACd;AAAA,QACA,WAAW,MAAM,kBAAkB,GAAG,GAAG,OAAO;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,
|
|
4
|
+
"sourcesContent": ["/**\n * Options for configuring the debounce behavior.\n */\nexport type DebounceOptions = {\n /** The delay in milliseconds before executing the function. Defaults to 100ms. */\n delay?: number\n /** Maximum time in milliseconds to wait before forcing execution, even with continuous calls. */\n maxWait?: number\n}\n\n/**\n * Creates a debounced function executor that delays execution until after a specified time.\n * Multiple calls with the same key will cancel previous pending executions.\n *\n * This is useful for batching rapid updates (like auto-save or API calls) to avoid\n * unnecessary processing or network requests.\n *\n * @param options - Configuration options for delay, maxWait, and key separator\n * @returns A function that accepts a key array and callback to execute\n *\n * @example\n * const debouncedSave = debounce({ delay: 328 })\n * debouncedSave.execute(['user', '123'], () => saveUser(user))\n *\n * @example\n * // With maxWait to guarantee execution even with continuous calls\n * const debouncedSave = debounce({ delay: 328, maxWait: 2000 })\n * debouncedSave.execute(['user', '123'], () => saveUser(user))\n */\nexport const debounce = (options: DebounceOptions = {}) => {\n const { delay = 328, maxWait } = options\n const timeouts = new Map<string, ReturnType<typeof setTimeout>>()\n const maxWaitTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n const latestFunctions = new Map<string, () => unknown | Promise<unknown>>()\n\n const cleanup = (): void => {\n timeouts.forEach(clearTimeout)\n maxWaitTimeouts.forEach(clearTimeout)\n timeouts.clear()\n maxWaitTimeouts.clear()\n latestFunctions.clear()\n }\n\n /** Executes the function and cleans up all associated timeouts */\n const executeAndCleanup = (key: string): void => {\n // Get the latest function for this key\n const fn = latestFunctions.get(key)\n\n // Clear both timeout types\n const timeout = timeouts.get(key)\n if (timeout !== undefined) {\n clearTimeout(timeout)\n timeouts.delete(key)\n }\n\n const maxWaitTimeout = maxWaitTimeouts.get(key)\n if (maxWaitTimeout !== undefined) {\n clearTimeout(maxWaitTimeout)\n maxWaitTimeouts.delete(key)\n }\n\n // Clear the latest function reference\n latestFunctions.delete(key)\n\n // Execute the function if it exists\n if (fn !== undefined) {\n try {\n fn()\n } catch {\n // Errors are silently caught to prevent the debounce mechanism from breaking\n }\n }\n }\n\n const execute = (key: string, fn: () => unknown | Promise<unknown>): void => {\n // Store the latest function for this key\n latestFunctions.set(key, fn)\n\n // Clear existing debounce timeout\n const existingTimeout = timeouts.get(key)\n if (existingTimeout !== undefined) {\n clearTimeout(existingTimeout)\n }\n\n // Set debounce timeout\n timeouts.set(\n key,\n setTimeout(() => executeAndCleanup(key), delay),\n )\n\n // Set maxWait timeout only if configured and this is a new sequence\n if (maxWait !== undefined && !maxWaitTimeouts.has(key)) {\n maxWaitTimeouts.set(\n key,\n setTimeout(() => executeAndCleanup(key), maxWait),\n )\n }\n }\n\n const flush = (key: string): void => {\n if (!latestFunctions.has(key)) {\n return\n }\n\n executeAndCleanup(key)\n }\n\n const flushAll = (): void => {\n const keys = [...latestFunctions.keys()]\n for (const key of keys) {\n executeAndCleanup(key)\n }\n }\n\n return { execute, cleanup, flush, flushAll }\n}\n"],
|
|
5
|
+
"mappings": "AA6BO,MAAM,WAAW,CAAC,UAA2B,CAAC,MAAM;AACzD,QAAM,EAAE,QAAQ,KAAK,QAAQ,IAAI;AACjC,QAAM,WAAW,oBAAI,IAA2C;AAChE,QAAM,kBAAkB,oBAAI,IAA2C;AACvE,QAAM,kBAAkB,oBAAI,IAA8C;AAE1E,QAAM,UAAU,MAAY;AAC1B,aAAS,QAAQ,YAAY;AAC7B,oBAAgB,QAAQ,YAAY;AACpC,aAAS,MAAM;AACf,oBAAgB,MAAM;AACtB,oBAAgB,MAAM;AAAA,EACxB;AAGA,QAAM,oBAAoB,CAAC,QAAsB;AAE/C,UAAM,KAAK,gBAAgB,IAAI,GAAG;AAGlC,UAAM,UAAU,SAAS,IAAI,GAAG;AAChC,QAAI,YAAY,QAAW;AACzB,mBAAa,OAAO;AACpB,eAAS,OAAO,GAAG;AAAA,IACrB;AAEA,UAAM,iBAAiB,gBAAgB,IAAI,GAAG;AAC9C,QAAI,mBAAmB,QAAW;AAChC,mBAAa,cAAc;AAC3B,sBAAgB,OAAO,GAAG;AAAA,IAC5B;AAGA,oBAAgB,OAAO,GAAG;AAG1B,QAAI,OAAO,QAAW;AACpB,UAAI;AACF,WAAG;AAAA,MACL,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,CAAC,KAAa,OAA+C;AAE3E,oBAAgB,IAAI,KAAK,EAAE;AAG3B,UAAM,kBAAkB,SAAS,IAAI,GAAG;AACxC,QAAI,oBAAoB,QAAW;AACjC,mBAAa,eAAe;AAAA,IAC9B;AAGA,aAAS;AAAA,MACP;AAAA,MACA,WAAW,MAAM,kBAAkB,GAAG,GAAG,KAAK;AAAA,IAChD;AAGA,QAAI,YAAY,UAAa,CAAC,gBAAgB,IAAI,GAAG,GAAG;AACtD,sBAAgB;AAAA,QACd;AAAA,QACA,WAAW,MAAM,kBAAkB,GAAG,GAAG,OAAO;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,CAAC,QAAsB;AACnC,QAAI,CAAC,gBAAgB,IAAI,GAAG,GAAG;AAC7B;AAAA,IACF;AAEA,sBAAkB,GAAG;AAAA,EACvB;AAEA,QAAM,WAAW,MAAY;AAC3B,UAAM,OAAO,CAAC,GAAG,gBAAgB,KAAK,CAAC;AACvC,eAAW,OAAO,MAAM;AACtB,wBAAkB,GAAG;AAAA,IACvB;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,SAAS,OAAO,SAAS;AAC7C;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-mac-os.d.ts","sourceRoot":"","sources":["../../src/general/is-mac-os.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"is-mac-os.d.ts","sourceRoot":"","sources":["../../src/general/is-mac-os.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,OAAO,eAanB,CAAA"}
|
|
@@ -1,9 +1,20 @@
|
|
|
1
|
+
const getUserAgentDataPlatform = (nav) => {
|
|
2
|
+
const userAgentData = Reflect.get(nav, "userAgentData");
|
|
3
|
+
if (!userAgentData || typeof userAgentData !== "object") {
|
|
4
|
+
return void 0;
|
|
5
|
+
}
|
|
6
|
+
if (!("platform" in userAgentData) || typeof userAgentData.platform !== "string") {
|
|
7
|
+
return void 0;
|
|
8
|
+
}
|
|
9
|
+
return userAgentData.platform;
|
|
10
|
+
};
|
|
1
11
|
const isMacOS = () => {
|
|
2
12
|
if (typeof navigator === "undefined") {
|
|
3
13
|
return false;
|
|
4
14
|
}
|
|
5
|
-
|
|
6
|
-
|
|
15
|
+
const userAgentDataPlatform = getUserAgentDataPlatform(navigator);
|
|
16
|
+
if (userAgentDataPlatform) {
|
|
17
|
+
return userAgentDataPlatform.toLowerCase().includes("mac");
|
|
7
18
|
}
|
|
8
19
|
return /Mac/.test(navigator.userAgent);
|
|
9
20
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/general/is-mac-os.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Checks whether the user is on macOS\n * Uses the modern navigator.userAgentData API with a fallback to navigator.userAgent\n */\
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * Checks whether the user is on macOS\n * Uses the modern navigator.userAgentData API with a fallback to navigator.userAgent\n */\nconst getUserAgentDataPlatform = (nav: Navigator): string | undefined => {\n const userAgentData: unknown = Reflect.get(nav, 'userAgentData')\n\n if (!userAgentData || typeof userAgentData !== 'object') {\n return undefined\n }\n\n if (!('platform' in userAgentData) || typeof userAgentData.platform !== 'string') {\n return undefined\n }\n\n return userAgentData.platform\n}\n\nexport const isMacOS = () => {\n if (typeof navigator === 'undefined') {\n return false\n }\n\n // Modern approach using navigator.userAgentData\n const userAgentDataPlatform = getUserAgentDataPlatform(navigator)\n if (userAgentDataPlatform) {\n return userAgentDataPlatform.toLowerCase().includes('mac')\n }\n\n // Fallback to userAgent\n return /Mac/.test(navigator.userAgent)\n}\n"],
|
|
5
|
+
"mappings": "AAIA,MAAM,2BAA2B,CAAC,QAAuC;AACvE,QAAM,gBAAyB,QAAQ,IAAI,KAAK,eAAe;AAE/D,MAAI,CAAC,iBAAiB,OAAO,kBAAkB,UAAU;AACvD,WAAO;AAAA,EACT;AAEA,MAAI,EAAE,cAAc,kBAAkB,OAAO,cAAc,aAAa,UAAU;AAChF,WAAO;AAAA,EACT;AAEA,SAAO,cAAc;AACvB;AAEO,MAAM,UAAU,MAAM;AAC3B,MAAI,OAAO,cAAc,aAAa;AACpC,WAAO;AAAA,EACT;AAGA,QAAM,wBAAwB,yBAAyB,SAAS;AAChE,MAAI,uBAAuB;AACzB,WAAO,sBAAsB,YAAY,EAAE,SAAS,KAAK;AAAA,EAC3D;AAGA,SAAO,MAAM,KAAK,UAAU,SAAS;AACvC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|