@usefy/use-click-any-where 0.0.8
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/dist/index.d.mts +70 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +26 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +59 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for useClickAnyWhere hook
|
|
3
|
+
*/
|
|
4
|
+
interface UseClickAnyWhereOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Whether the event listener is enabled
|
|
7
|
+
* @default true
|
|
8
|
+
*/
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Whether to use event capture phase
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
capture?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Whether to use passive event listener
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
passive?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Handler type for click events
|
|
23
|
+
*/
|
|
24
|
+
type ClickAnyWhereHandler = (event: MouseEvent) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Detects document-wide click events and calls the provided handler.
|
|
27
|
+
* Useful for closing dropdowns, modals, or any component when clicking outside.
|
|
28
|
+
*
|
|
29
|
+
* @param handler - Callback function called when a click is detected anywhere on the document
|
|
30
|
+
* @param options - Configuration options for the event listener
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* function ClickTracker() {
|
|
35
|
+
* const [lastClick, setLastClick] = useState({ x: 0, y: 0 });
|
|
36
|
+
*
|
|
37
|
+
* useClickAnyWhere((event) => {
|
|
38
|
+
* setLastClick({ x: event.clientX, y: event.clientY });
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* return (
|
|
42
|
+
* <div>
|
|
43
|
+
* Last click: ({lastClick.x}, {lastClick.y})
|
|
44
|
+
* </div>
|
|
45
|
+
* );
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```tsx
|
|
51
|
+
* // Conditional activation
|
|
52
|
+
* function Dropdown({ isOpen, onClose }) {
|
|
53
|
+
* useClickAnyWhere(
|
|
54
|
+
* () => onClose(),
|
|
55
|
+
* { enabled: isOpen }
|
|
56
|
+
* );
|
|
57
|
+
*
|
|
58
|
+
* return isOpen ? <div>Dropdown content</div> : null;
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* // With capture phase
|
|
65
|
+
* useClickAnyWhere(handleClick, { capture: true });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
declare function useClickAnyWhere(handler: ClickAnyWhereHandler, options?: UseClickAnyWhereOptions): void;
|
|
69
|
+
|
|
70
|
+
export { type ClickAnyWhereHandler, type UseClickAnyWhereOptions, useClickAnyWhere };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for useClickAnyWhere hook
|
|
3
|
+
*/
|
|
4
|
+
interface UseClickAnyWhereOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Whether the event listener is enabled
|
|
7
|
+
* @default true
|
|
8
|
+
*/
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Whether to use event capture phase
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
capture?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Whether to use passive event listener
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
passive?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Handler type for click events
|
|
23
|
+
*/
|
|
24
|
+
type ClickAnyWhereHandler = (event: MouseEvent) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Detects document-wide click events and calls the provided handler.
|
|
27
|
+
* Useful for closing dropdowns, modals, or any component when clicking outside.
|
|
28
|
+
*
|
|
29
|
+
* @param handler - Callback function called when a click is detected anywhere on the document
|
|
30
|
+
* @param options - Configuration options for the event listener
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* function ClickTracker() {
|
|
35
|
+
* const [lastClick, setLastClick] = useState({ x: 0, y: 0 });
|
|
36
|
+
*
|
|
37
|
+
* useClickAnyWhere((event) => {
|
|
38
|
+
* setLastClick({ x: event.clientX, y: event.clientY });
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* return (
|
|
42
|
+
* <div>
|
|
43
|
+
* Last click: ({lastClick.x}, {lastClick.y})
|
|
44
|
+
* </div>
|
|
45
|
+
* );
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```tsx
|
|
51
|
+
* // Conditional activation
|
|
52
|
+
* function Dropdown({ isOpen, onClose }) {
|
|
53
|
+
* useClickAnyWhere(
|
|
54
|
+
* () => onClose(),
|
|
55
|
+
* { enabled: isOpen }
|
|
56
|
+
* );
|
|
57
|
+
*
|
|
58
|
+
* return isOpen ? <div>Dropdown content</div> : null;
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* // With capture phase
|
|
65
|
+
* useClickAnyWhere(handleClick, { capture: true });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
declare function useClickAnyWhere(handler: ClickAnyWhereHandler, options?: UseClickAnyWhereOptions): void;
|
|
69
|
+
|
|
70
|
+
export { type ClickAnyWhereHandler, type UseClickAnyWhereOptions, useClickAnyWhere };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
useClickAnyWhere: () => useClickAnyWhere
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/useClickAnyWhere.ts
|
|
28
|
+
var import_react = require("react");
|
|
29
|
+
function useClickAnyWhere(handler, options = {}) {
|
|
30
|
+
const { enabled = true, capture = false, passive = true } = options;
|
|
31
|
+
const handlerRef = (0, import_react.useRef)(handler);
|
|
32
|
+
handlerRef.current = handler;
|
|
33
|
+
(0, import_react.useEffect)(() => {
|
|
34
|
+
if (typeof document === "undefined") {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (!enabled) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const internalHandler = (event) => {
|
|
41
|
+
handlerRef.current(event);
|
|
42
|
+
};
|
|
43
|
+
document.addEventListener("click", internalHandler, { capture, passive });
|
|
44
|
+
return () => {
|
|
45
|
+
document.removeEventListener("click", internalHandler, { capture });
|
|
46
|
+
};
|
|
47
|
+
}, [enabled, capture, passive]);
|
|
48
|
+
}
|
|
49
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
50
|
+
0 && (module.exports = {
|
|
51
|
+
useClickAnyWhere
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/useClickAnyWhere.ts"],"sourcesContent":["export {\n useClickAnyWhere,\n type UseClickAnyWhereOptions,\n type ClickAnyWhereHandler,\n} from \"./useClickAnyWhere\";\n","import { useEffect, useRef } from \"react\";\n\n/**\n * Options for useClickAnyWhere hook\n */\nexport interface UseClickAnyWhereOptions {\n /**\n * Whether the event listener is enabled\n * @default true\n */\n enabled?: boolean;\n /**\n * Whether to use event capture phase\n * @default false\n */\n capture?: boolean;\n /**\n * Whether to use passive event listener\n * @default true\n */\n passive?: boolean;\n}\n\n/**\n * Handler type for click events\n */\nexport type ClickAnyWhereHandler = (event: MouseEvent) => void;\n\n/**\n * Detects document-wide click events and calls the provided handler.\n * Useful for closing dropdowns, modals, or any component when clicking outside.\n *\n * @param handler - Callback function called when a click is detected anywhere on the document\n * @param options - Configuration options for the event listener\n *\n * @example\n * ```tsx\n * function ClickTracker() {\n * const [lastClick, setLastClick] = useState({ x: 0, y: 0 });\n *\n * useClickAnyWhere((event) => {\n * setLastClick({ x: event.clientX, y: event.clientY });\n * });\n *\n * return (\n * <div>\n * Last click: ({lastClick.x}, {lastClick.y})\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Conditional activation\n * function Dropdown({ isOpen, onClose }) {\n * useClickAnyWhere(\n * () => onClose(),\n * { enabled: isOpen }\n * );\n *\n * return isOpen ? <div>Dropdown content</div> : null;\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With capture phase\n * useClickAnyWhere(handleClick, { capture: true });\n * ```\n */\nexport function useClickAnyWhere(\n handler: ClickAnyWhereHandler,\n options: UseClickAnyWhereOptions = {}\n): void {\n const { enabled = true, capture = false, passive = true } = options;\n\n // Store handler in ref to avoid re-registering event listener\n const handlerRef = useRef<ClickAnyWhereHandler>(handler);\n\n // Update ref when handler changes\n handlerRef.current = handler;\n\n useEffect(() => {\n // SSR check\n if (typeof document === \"undefined\") {\n return;\n }\n\n // Don't add listener if disabled\n if (!enabled) {\n return;\n }\n\n // Internal handler that calls the latest handler ref\n const internalHandler = (event: MouseEvent) => {\n handlerRef.current(event);\n };\n\n // Add event listener\n document.addEventListener(\"click\", internalHandler, { capture, passive });\n\n // Cleanup\n return () => {\n document.removeEventListener(\"click\", internalHandler, { capture });\n };\n }, [enabled, capture, passive]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAkC;AAuE3B,SAAS,iBACd,SACA,UAAmC,CAAC,GAC9B;AACN,QAAM,EAAE,UAAU,MAAM,UAAU,OAAO,UAAU,KAAK,IAAI;AAG5D,QAAM,iBAAa,qBAA6B,OAAO;AAGvD,aAAW,UAAU;AAErB,8BAAU,MAAM;AAEd,QAAI,OAAO,aAAa,aAAa;AACnC;AAAA,IACF;AAGA,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAGA,UAAM,kBAAkB,CAAC,UAAsB;AAC7C,iBAAW,QAAQ,KAAK;AAAA,IAC1B;AAGA,aAAS,iBAAiB,SAAS,iBAAiB,EAAE,SAAS,QAAQ,CAAC;AAGxE,WAAO,MAAM;AACX,eAAS,oBAAoB,SAAS,iBAAiB,EAAE,QAAQ,CAAC;AAAA,IACpE;AAAA,EACF,GAAG,CAAC,SAAS,SAAS,OAAO,CAAC;AAChC;","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/useClickAnyWhere.ts
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
function useClickAnyWhere(handler, options = {}) {
|
|
4
|
+
const { enabled = true, capture = false, passive = true } = options;
|
|
5
|
+
const handlerRef = useRef(handler);
|
|
6
|
+
handlerRef.current = handler;
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
if (typeof document === "undefined") {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (!enabled) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const internalHandler = (event) => {
|
|
15
|
+
handlerRef.current(event);
|
|
16
|
+
};
|
|
17
|
+
document.addEventListener("click", internalHandler, { capture, passive });
|
|
18
|
+
return () => {
|
|
19
|
+
document.removeEventListener("click", internalHandler, { capture });
|
|
20
|
+
};
|
|
21
|
+
}, [enabled, capture, passive]);
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
useClickAnyWhere
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/useClickAnyWhere.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\n\n/**\n * Options for useClickAnyWhere hook\n */\nexport interface UseClickAnyWhereOptions {\n /**\n * Whether the event listener is enabled\n * @default true\n */\n enabled?: boolean;\n /**\n * Whether to use event capture phase\n * @default false\n */\n capture?: boolean;\n /**\n * Whether to use passive event listener\n * @default true\n */\n passive?: boolean;\n}\n\n/**\n * Handler type for click events\n */\nexport type ClickAnyWhereHandler = (event: MouseEvent) => void;\n\n/**\n * Detects document-wide click events and calls the provided handler.\n * Useful for closing dropdowns, modals, or any component when clicking outside.\n *\n * @param handler - Callback function called when a click is detected anywhere on the document\n * @param options - Configuration options for the event listener\n *\n * @example\n * ```tsx\n * function ClickTracker() {\n * const [lastClick, setLastClick] = useState({ x: 0, y: 0 });\n *\n * useClickAnyWhere((event) => {\n * setLastClick({ x: event.clientX, y: event.clientY });\n * });\n *\n * return (\n * <div>\n * Last click: ({lastClick.x}, {lastClick.y})\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Conditional activation\n * function Dropdown({ isOpen, onClose }) {\n * useClickAnyWhere(\n * () => onClose(),\n * { enabled: isOpen }\n * );\n *\n * return isOpen ? <div>Dropdown content</div> : null;\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With capture phase\n * useClickAnyWhere(handleClick, { capture: true });\n * ```\n */\nexport function useClickAnyWhere(\n handler: ClickAnyWhereHandler,\n options: UseClickAnyWhereOptions = {}\n): void {\n const { enabled = true, capture = false, passive = true } = options;\n\n // Store handler in ref to avoid re-registering event listener\n const handlerRef = useRef<ClickAnyWhereHandler>(handler);\n\n // Update ref when handler changes\n handlerRef.current = handler;\n\n useEffect(() => {\n // SSR check\n if (typeof document === \"undefined\") {\n return;\n }\n\n // Don't add listener if disabled\n if (!enabled) {\n return;\n }\n\n // Internal handler that calls the latest handler ref\n const internalHandler = (event: MouseEvent) => {\n handlerRef.current(event);\n };\n\n // Add event listener\n document.addEventListener(\"click\", internalHandler, { capture, passive });\n\n // Cleanup\n return () => {\n document.removeEventListener(\"click\", internalHandler, { capture });\n };\n }, [enabled, capture, passive]);\n}\n"],"mappings":";AAAA,SAAS,WAAW,cAAc;AAuE3B,SAAS,iBACd,SACA,UAAmC,CAAC,GAC9B;AACN,QAAM,EAAE,UAAU,MAAM,UAAU,OAAO,UAAU,KAAK,IAAI;AAG5D,QAAM,aAAa,OAA6B,OAAO;AAGvD,aAAW,UAAU;AAErB,YAAU,MAAM;AAEd,QAAI,OAAO,aAAa,aAAa;AACnC;AAAA,IACF;AAGA,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAGA,UAAM,kBAAkB,CAAC,UAAsB;AAC7C,iBAAW,QAAQ,KAAK;AAAA,IAC1B;AAGA,aAAS,iBAAiB,SAAS,iBAAiB,EAAE,SAAS,QAAQ,CAAC;AAGxE,WAAO,MAAM;AACX,eAAS,oBAAoB,SAAS,iBAAiB,EAAE,QAAQ,CAAC;AAAA,IACpE;AAAA,EACF,GAAG,CAAC,SAAS,SAAS,OAAO,CAAC;AAChC;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@usefy/use-click-any-where",
|
|
3
|
+
"version": "0.0.8",
|
|
4
|
+
"description": "A React hook for detecting document-wide click events",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
24
|
+
"@testing-library/react": "^16.3.1",
|
|
25
|
+
"@testing-library/user-event": "^14.6.1",
|
|
26
|
+
"@types/react": "^19.0.0",
|
|
27
|
+
"jsdom": "^27.3.0",
|
|
28
|
+
"react": "^19.0.0",
|
|
29
|
+
"rimraf": "^6.0.1",
|
|
30
|
+
"tsup": "^8.0.0",
|
|
31
|
+
"typescript": "^5.0.0",
|
|
32
|
+
"vitest": "^4.0.16"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/geon0529/usefy.git",
|
|
40
|
+
"directory": "packages/use-click-any-where"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"keywords": [
|
|
44
|
+
"react",
|
|
45
|
+
"hooks",
|
|
46
|
+
"click",
|
|
47
|
+
"document",
|
|
48
|
+
"event-listener",
|
|
49
|
+
"click-anywhere"
|
|
50
|
+
],
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsup",
|
|
53
|
+
"dev": "tsup --watch",
|
|
54
|
+
"test": "vitest run",
|
|
55
|
+
"test:watch": "vitest",
|
|
56
|
+
"typecheck": "tsc --noEmit",
|
|
57
|
+
"clean": "rimraf dist"
|
|
58
|
+
}
|
|
59
|
+
}
|