@ttoss/react-hooks 1.21.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.
- package/README.md +41 -0
- package/dist/esm/index.js +52 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +97 -0
- package/package.json +39 -0
- package/src/index.ts +1 -0
- package/src/useScript.ts +107 -0
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @ttoss/hooks
|
|
2
|
+
|
|
3
|
+
## 📚 About
|
|
4
|
+
|
|
5
|
+
<strong> @ttoss/hooks</strong> is a easiest way to use Util Hooks in your React application.
|
|
6
|
+
|
|
7
|
+
## 🚀 Getting Started
|
|
8
|
+
|
|
9
|
+
### Install @ttoss/hooks
|
|
10
|
+
|
|
11
|
+
```shell
|
|
12
|
+
$ yarn add @ttoss/hooks
|
|
13
|
+
# or
|
|
14
|
+
$ npm install @ttoss/hooks
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 📄 Examples of use
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import React from 'react';
|
|
21
|
+
|
|
22
|
+
import { useScript } from '@ttoss/hooks';
|
|
23
|
+
|
|
24
|
+
export const Component = () => {
|
|
25
|
+
const url = 'https://your-domain.com/bundle-api.js';
|
|
26
|
+
|
|
27
|
+
const { status } = useScript(url);
|
|
28
|
+
|
|
29
|
+
return <div>{status === 'ready' ? 'Ok' : 'Loading'}</div>;
|
|
30
|
+
};
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 📘 Types
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
type ScriptStatus = 'idle' | 'loading' | 'ready' | 'error';
|
|
37
|
+
|
|
38
|
+
const useScript: (src: string) => {
|
|
39
|
+
status: ScriptStatus;
|
|
40
|
+
};
|
|
41
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
|
|
3
|
+
// tsup.inject.js
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
|
|
6
|
+
// src/useScript.ts
|
|
7
|
+
import * as React2 from "react";
|
|
8
|
+
var useScript = src => {
|
|
9
|
+
const [status, setStatus] = React2.useState(src ? "loading" : "idle");
|
|
10
|
+
React2.useEffect(() => {
|
|
11
|
+
if (!src) {
|
|
12
|
+
setStatus("idle");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
let script = document.querySelector(`script[src="${src}"]`);
|
|
16
|
+
if (!script) {
|
|
17
|
+
script = document.createElement("script");
|
|
18
|
+
script.src = src;
|
|
19
|
+
script.async = true;
|
|
20
|
+
script.setAttribute("data-status", "loading");
|
|
21
|
+
document.body.appendChild(script);
|
|
22
|
+
const setAttributeFromEvent = event => {
|
|
23
|
+
if (script) {
|
|
24
|
+
script.setAttribute("data-status", event.type === "load" ? "ready" : "error");
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
script.addEventListener("load", setAttributeFromEvent);
|
|
28
|
+
script.addEventListener("error", setAttributeFromEvent);
|
|
29
|
+
} else {
|
|
30
|
+
setStatus(script.getAttribute("data-status") || "error");
|
|
31
|
+
}
|
|
32
|
+
const setStateFromEvent = event => {
|
|
33
|
+
setStatus(event.type === "load" ? "ready" : "error");
|
|
34
|
+
};
|
|
35
|
+
script.addEventListener("load", setStateFromEvent);
|
|
36
|
+
script.addEventListener("error", setStateFromEvent);
|
|
37
|
+
return () => {
|
|
38
|
+
if (script) {
|
|
39
|
+
script.removeEventListener("load", setStateFromEvent);
|
|
40
|
+
script.removeEventListener("error", setStateFromEvent);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
/**
|
|
45
|
+
* Only re-run effect if script src changes.
|
|
46
|
+
*/
|
|
47
|
+
[src]);
|
|
48
|
+
return {
|
|
49
|
+
status
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
export { useScript };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type ScriptStatus = 'idle' | 'loading' | 'ready' | 'error';
|
|
2
|
+
/**
|
|
3
|
+
* https://usehooks.com/useScript/
|
|
4
|
+
*
|
|
5
|
+
* @param src: string - the url of the script to load.
|
|
6
|
+
* @returns status: Status
|
|
7
|
+
*/
|
|
8
|
+
declare const useScript: (src: string) => {
|
|
9
|
+
status: ScriptStatus;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export { ScriptStatus, useScript };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
var __create = Object.create;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __export = (target, all) => {
|
|
11
|
+
for (var name in all) __defProp(target, name, {
|
|
12
|
+
get: all[name],
|
|
13
|
+
enumerable: true
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
19
|
+
get: () => from[key],
|
|
20
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return to;
|
|
24
|
+
};
|
|
25
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
26
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
27
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
28
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
29
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
30
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
31
|
+
value: mod,
|
|
32
|
+
enumerable: true
|
|
33
|
+
}) : target, mod));
|
|
34
|
+
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
35
|
+
value: true
|
|
36
|
+
}), mod);
|
|
37
|
+
|
|
38
|
+
// src/index.ts
|
|
39
|
+
var src_exports = {};
|
|
40
|
+
__export(src_exports, {
|
|
41
|
+
useScript: () => useScript
|
|
42
|
+
});
|
|
43
|
+
module.exports = __toCommonJS(src_exports);
|
|
44
|
+
|
|
45
|
+
// tsup.inject.js
|
|
46
|
+
var React = __toESM(require("react"));
|
|
47
|
+
|
|
48
|
+
// src/useScript.ts
|
|
49
|
+
var React2 = __toESM(require("react"));
|
|
50
|
+
var useScript = src => {
|
|
51
|
+
const [status, setStatus] = React2.useState(src ? "loading" : "idle");
|
|
52
|
+
React2.useEffect(() => {
|
|
53
|
+
if (!src) {
|
|
54
|
+
setStatus("idle");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
let script = document.querySelector(`script[src="${src}"]`);
|
|
58
|
+
if (!script) {
|
|
59
|
+
script = document.createElement("script");
|
|
60
|
+
script.src = src;
|
|
61
|
+
script.async = true;
|
|
62
|
+
script.setAttribute("data-status", "loading");
|
|
63
|
+
document.body.appendChild(script);
|
|
64
|
+
const setAttributeFromEvent = event => {
|
|
65
|
+
if (script) {
|
|
66
|
+
script.setAttribute("data-status", event.type === "load" ? "ready" : "error");
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
script.addEventListener("load", setAttributeFromEvent);
|
|
70
|
+
script.addEventListener("error", setAttributeFromEvent);
|
|
71
|
+
} else {
|
|
72
|
+
setStatus(script.getAttribute("data-status") || "error");
|
|
73
|
+
}
|
|
74
|
+
const setStateFromEvent = event => {
|
|
75
|
+
setStatus(event.type === "load" ? "ready" : "error");
|
|
76
|
+
};
|
|
77
|
+
script.addEventListener("load", setStateFromEvent);
|
|
78
|
+
script.addEventListener("error", setStateFromEvent);
|
|
79
|
+
return () => {
|
|
80
|
+
if (script) {
|
|
81
|
+
script.removeEventListener("load", setStateFromEvent);
|
|
82
|
+
script.removeEventListener("error", setStateFromEvent);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
/**
|
|
87
|
+
* Only re-run effect if script src changes.
|
|
88
|
+
*/
|
|
89
|
+
[src]);
|
|
90
|
+
return {
|
|
91
|
+
status
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
95
|
+
0 && (module.exports = {
|
|
96
|
+
useScript
|
|
97
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ttoss/react-hooks",
|
|
3
|
+
"version": "1.21.14",
|
|
4
|
+
"description": "React hooks.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"author": "ttoss",
|
|
7
|
+
"contributors": [
|
|
8
|
+
"Pedro Arantes <pedro@arantespp.com> (https://arantespp.com/contact)"
|
|
9
|
+
],
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"module": "dist/esm/index.js",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"src"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup",
|
|
18
|
+
"test": "jest"
|
|
19
|
+
},
|
|
20
|
+
"typings": "dist/index.d.ts",
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"react": ">=16.8.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@ttoss/config": "^1.29.4",
|
|
26
|
+
"@ttoss/test-utils": "^1.21.3",
|
|
27
|
+
"@types/react": "^18.0.35",
|
|
28
|
+
"jest": "^29.5.0",
|
|
29
|
+
"tsup": "^6.7.0"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"React",
|
|
33
|
+
"hooks"
|
|
34
|
+
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"gitHead": "81c9da91988b338a6449d84b4dfc183ccf9ed941"
|
|
39
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useScript, ScriptStatus } from './useScript';
|
package/src/useScript.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
export type ScriptStatus = 'idle' | 'loading' | 'ready' | 'error';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* https://usehooks.com/useScript/
|
|
7
|
+
*
|
|
8
|
+
* @param src: string - the url of the script to load.
|
|
9
|
+
* @returns status: Status
|
|
10
|
+
*/
|
|
11
|
+
export const useScript = (src: string) => {
|
|
12
|
+
/**
|
|
13
|
+
* Keep track of script status ("idle", "loading", "ready", "error")
|
|
14
|
+
*/
|
|
15
|
+
const [status, setStatus] = React.useState<ScriptStatus>(
|
|
16
|
+
src ? 'loading' : 'idle'
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
React.useEffect(
|
|
20
|
+
() => {
|
|
21
|
+
/**
|
|
22
|
+
* Allow falsy src value if waiting on other data needed for
|
|
23
|
+
* constructing the script URL passed to this hook.
|
|
24
|
+
*/
|
|
25
|
+
if (!src) {
|
|
26
|
+
setStatus('idle');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Fetch existing script element by src.
|
|
32
|
+
* It may have been added by another instance of this hook.
|
|
33
|
+
*/
|
|
34
|
+
let script: HTMLScriptElement | null = document.querySelector(
|
|
35
|
+
`script[src="${src}"]`
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
if (!script) {
|
|
39
|
+
/**
|
|
40
|
+
* Create script element and set its src.
|
|
41
|
+
*/
|
|
42
|
+
script = document.createElement('script');
|
|
43
|
+
script.src = src;
|
|
44
|
+
script.async = true;
|
|
45
|
+
script.setAttribute('data-status', 'loading');
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Add script to document body
|
|
49
|
+
*/
|
|
50
|
+
document.body.appendChild(script);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Store status in attribute on script.
|
|
54
|
+
* This can be read by other instances of this hook.
|
|
55
|
+
*/
|
|
56
|
+
const setAttributeFromEvent = (event: any) => {
|
|
57
|
+
if (script) {
|
|
58
|
+
script.setAttribute(
|
|
59
|
+
'data-status',
|
|
60
|
+
event.type === 'load' ? 'ready' : 'error'
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
script.addEventListener('load', setAttributeFromEvent);
|
|
65
|
+
script.addEventListener('error', setAttributeFromEvent);
|
|
66
|
+
} else {
|
|
67
|
+
/**
|
|
68
|
+
* Grab existing script status from attribute and set to state.
|
|
69
|
+
*/
|
|
70
|
+
setStatus(
|
|
71
|
+
(script.getAttribute('data-status') as ScriptStatus) || 'error'
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Script event handler to update status in state
|
|
77
|
+
* Note: Even if the script already exists we still need to add
|
|
78
|
+
* event handlers to update the state for *this* hook instance.
|
|
79
|
+
*/
|
|
80
|
+
const setStateFromEvent = (event: any) => {
|
|
81
|
+
setStatus(event.type === 'load' ? 'ready' : 'error');
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Add event listeners.
|
|
86
|
+
*/
|
|
87
|
+
script.addEventListener('load', setStateFromEvent);
|
|
88
|
+
script.addEventListener('error', setStateFromEvent);
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Remove event listeners on cleanup.
|
|
92
|
+
*/
|
|
93
|
+
return () => {
|
|
94
|
+
if (script) {
|
|
95
|
+
script.removeEventListener('load', setStateFromEvent);
|
|
96
|
+
script.removeEventListener('error', setStateFromEvent);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
/**
|
|
101
|
+
* Only re-run effect if script src changes.
|
|
102
|
+
*/
|
|
103
|
+
[src]
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
return { status };
|
|
107
|
+
};
|