@oneblink/apps-react 5.1.1 → 5.1.2-beta.2
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/components/messages/ErrorMessage.js +1 -1
- package/dist/components/messages/ErrorMessage.js.map +1 -1
- package/dist/hooks/useLoadDataState.d.ts +2 -2
- package/dist/hooks/useLoadDataState.js +11 -4
- package/dist/hooks/useLoadDataState.js.map +1 -1
- package/dist/hooks/useLoadResourcesState.d.ts +2 -2
- package/dist/hooks/useLoadResourcesState.js.map +1 -1
- package/package.json +1 -1
@@ -7,7 +7,7 @@ function ErrorMessage({ title, children, gutterTop, gutterBottom, IconComponent,
|
|
7
7
|
IconComponent = ErrorIcon;
|
8
8
|
}
|
9
9
|
return (React.createElement(React.Fragment, null,
|
10
|
-
React.createElement(LargeIconMessage, { IconComponent: IconComponent, title: title, variant: "error", gutterTop: gutterTop, gutterBottom: gutterBottom, action: onTryAgain && (React.createElement(Button, { variant: "outlined", color: "primary", onClick: () => onTryAgain() }, "Try Again")), className: "ob-error-snackbar" }, children)));
|
10
|
+
React.createElement(LargeIconMessage, { IconComponent: IconComponent, title: title, variant: "error", gutterTop: gutterTop, gutterBottom: gutterBottom, action: onTryAgain && (React.createElement(Button, { variant: "outlined", color: "primary", onClick: () => onTryAgain(), "data-cypress": "error-try-again-button" }, "Try Again")), className: "ob-error-snackbar" }, children)));
|
11
11
|
}
|
12
12
|
export default React.memo(ErrorMessage);
|
13
13
|
//# sourceMappingURL=ErrorMessage.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ErrorMessage.js","sourceRoot":"","sources":["../../../src/components/messages/ErrorMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,SAAS,MAAM,2BAA2B,CAAA;AACjD,OAAO,gBAEN,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAUtC,SAAS,YAAY,CAAC,EACpB,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,aAAa,EACb,UAAU,GACJ;IACN,IAAI,CAAC,aAAa,EAAE;QAClB,aAAa,GAAG,SAAS,CAAA;KAC1B;IAED,OAAO,CACL;QACE,oBAAC,gBAAgB,IACf,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAC,OAAO,EACf,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,EAC1B,MAAM,EACJ,UAAU,IAAI,CACZ,oBAAC,MAAM,IACL,OAAO,EAAC,UAAU,EAClB,KAAK,EAAC,SAAS,EACf,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,
|
1
|
+
{"version":3,"file":"ErrorMessage.js","sourceRoot":"","sources":["../../../src/components/messages/ErrorMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,SAAS,MAAM,2BAA2B,CAAA;AACjD,OAAO,gBAEN,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAUtC,SAAS,YAAY,CAAC,EACpB,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,aAAa,EACb,UAAU,GACJ;IACN,IAAI,CAAC,aAAa,EAAE;QAClB,aAAa,GAAG,SAAS,CAAA;KAC1B;IAED,OAAO,CACL;QACE,oBAAC,gBAAgB,IACf,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAC,OAAO,EACf,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,EAC1B,MAAM,EACJ,UAAU,IAAI,CACZ,oBAAC,MAAM,IACL,OAAO,EAAC,UAAU,EAClB,KAAK,EAAC,SAAS,EACf,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,kBACd,wBAAwB,gBAG9B,CACV,EAEH,SAAS,EAAC,mBAAmB,IAE5B,QAAQ,CACQ,CAClB,CACJ,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAQ,YAAY,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport ErrorIcon from '@mui/icons-material/Error'\nimport LargeIconMessage, {\n Props as LargeIconMessageProps,\n} from './LargeIconMessage'\nimport { Button } from '@mui/material'\ntype Props = {\n IconComponent?: LargeIconMessageProps['IconComponent']\n title: string\n gutterTop?: boolean\n gutterBottom?: boolean\n children?: React.ReactNode\n onTryAgain?: () => void\n}\n\nfunction ErrorMessage({\n title,\n children,\n gutterTop,\n gutterBottom,\n IconComponent,\n onTryAgain,\n}: Props) {\n if (!IconComponent) {\n IconComponent = ErrorIcon\n }\n\n return (\n <>\n <LargeIconMessage\n IconComponent={IconComponent}\n title={title}\n variant=\"error\"\n gutterTop={gutterTop}\n gutterBottom={gutterBottom}\n action={\n onTryAgain && (\n <Button\n variant=\"outlined\"\n color=\"primary\"\n onClick={() => onTryAgain()}\n data-cypress=\"error-try-again-button\"\n >\n Try Again\n </Button>\n )\n }\n className=\"ob-error-snackbar\"\n >\n {children}\n </LargeIconMessage>\n </>\n )\n}\n\nexport default React.memo<Props>(ErrorMessage)\n"]}
|
@@ -51,8 +51,8 @@ export type LoadDataState<T> = {
|
|
51
51
|
* @returns
|
52
52
|
* @group Hooks
|
53
53
|
*/
|
54
|
-
export default function useLoadDataState<T>(onLoad: (abortSignal
|
54
|
+
export default function useLoadDataState<T>(onLoad: (abortSignal: AbortSignal) => Promise<T>): [
|
55
55
|
state: LoadDataState<T>,
|
56
|
-
|
56
|
+
handleRefresh: () => void,
|
57
57
|
setResult: React.Dispatch<React.SetStateAction<T>>
|
58
58
|
];
|
@@ -52,7 +52,7 @@ export default function useLoadDataState(onLoad) {
|
|
52
52
|
});
|
53
53
|
try {
|
54
54
|
const result = await onLoad(abortSignal);
|
55
|
-
if (isMounted.current && !
|
55
|
+
if (isMounted.current && !abortSignal.aborted) {
|
56
56
|
setState({
|
57
57
|
status: 'SUCCESS',
|
58
58
|
result,
|
@@ -60,7 +60,7 @@ export default function useLoadDataState(onLoad) {
|
|
60
60
|
}
|
61
61
|
}
|
62
62
|
catch (err) {
|
63
|
-
if (isMounted.current && !
|
63
|
+
if (isMounted.current && !abortSignal.aborted) {
|
64
64
|
setState({
|
65
65
|
status: 'ERROR',
|
66
66
|
error: err,
|
@@ -84,13 +84,20 @@ export default function useLoadDataState(onLoad) {
|
|
84
84
|
}
|
85
85
|
});
|
86
86
|
}, []);
|
87
|
+
// We use a number to trigger the refresh function so that
|
88
|
+
// we can pass an abort controller using a useEffect and
|
89
|
+
// have it aborted if the refresh function is triggered again.
|
90
|
+
const [loadCount, setLoadCount] = React.useState(0);
|
91
|
+
const handleRefresh = React.useCallback(() => {
|
92
|
+
setLoadCount((currentLoadCount) => currentLoadCount + 1);
|
93
|
+
}, []);
|
87
94
|
React.useEffect(() => {
|
88
95
|
const abortController = new AbortController();
|
89
96
|
handleLoad(abortController.signal);
|
90
97
|
return () => {
|
91
98
|
abortController.abort();
|
92
99
|
};
|
93
|
-
}, [handleLoad]);
|
94
|
-
return [state,
|
100
|
+
}, [handleLoad, loadCount]);
|
101
|
+
return [state, handleRefresh, setResult];
|
95
102
|
}
|
96
103
|
//# sourceMappingURL=useLoadDataState.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useLoadDataState.js","sourceRoot":"","sources":["../../src/hooks/useLoadDataState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAiBzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,
|
1
|
+
{"version":3,"file":"useLoadDataState.js","sourceRoot":"","sources":["../../src/hooks/useLoadDataState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAiBzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,MAAgD;IAMhD,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAmB;QACzD,MAAM,EAAE,SAAS;KAClB,CAAC,CAAA;IAEF,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAClC,KAAK,EAAE,WAAwB,EAAE,EAAE;QACjC,QAAQ,CAAC;YACP,MAAM,EAAE,SAAS;SAClB,CAAC,CAAA;QACF,IAAI;YACF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;YACxC,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;gBAC7C,QAAQ,CAAC;oBACP,MAAM,EAAE,SAAS;oBACjB,MAAM;iBACP,CAAC,CAAA;aACH;SACF;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;gBAC7C,QAAQ,CAAC;oBACP,MAAM,EAAE,OAAO;oBACf,KAAK,EAAE,GAAY;iBACpB,CAAC,CAAA;aACH;SACF;IACH,CAAC,EACD,CAAC,SAAS,EAAE,MAAM,CAAC,CACpB,CAAA;IAED,MAAM,SAAS,GAA4C,KAAK,CAAC,WAAW,CAC1E,CAAC,MAAM,EAAE,EAAE;QACT,QAAQ,CAAC,CAAC,YAA8B,EAAE,EAAE;YAC1C,IAAI,YAAY,CAAC,MAAM,KAAK,SAAS,EAAE;gBACrC,OAAO;oBACL,GAAG,YAAY;oBACf,MAAM,EACJ,OAAO,MAAM,KAAK,UAAU;wBAC1B,CAAC,CAAC,oFAAoF;4BACpF,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;wBAC7B,CAAC,CAAC,MAAM;iBACb,CAAA;aACF;iBAAM;gBACL,OAAO,YAAY,CAAA;aACpB;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,EACD,EAAE,CACH,CAAA;IAED,0DAA0D;IAC1D,wDAAwD;IACxD,8DAA8D;IAC9D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAEnD,MAAM,aAAa,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAC3C,YAAY,CAAC,CAAC,gBAAgB,EAAE,EAAE,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAA;IAC1D,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA;QAC7C,UAAU,CAAC,eAAe,CAAC,MAAM,CAAC,CAAA;QAClC,OAAO,GAAG,EAAE;YACV,eAAe,CAAC,KAAK,EAAE,CAAA;QACzB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAA;IAE3B,OAAO,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,CAAA;AAC1C,CAAC","sourcesContent":["import * as React from 'react'\nimport useIsMounted from './useIsMounted'\n\nexport type LoadDataState<T> =\n | {\n status: 'SUCCESS'\n /** Your data. */\n result: T\n }\n | {\n status: 'ERROR'\n /** A JavaScript `Error` object. */\n error: Error\n }\n | {\n status: 'LOADING'\n }\n\n/**\n * This function is a react hook for managing the state involved with loading\n * data.\n *\n * ## Example\n *\n * ```js\n * import { useLoadDataState } from '@oneblink/apps-react'\n * const fetchData = async () => {\n * const response = await fetch(`https://some-website.com/api?data=data`)\n *\n * if (!response.ok) {\n * const text = await response.text()\n * throw new Error(text)\n * }\n *\n * return await response.json()\n * }\n *\n * const MyComponent = () => {\n * const [state, refresh, setResult] = useLoadDataState(fetchData)\n *\n * switch (state.status) {\n * case 'LOADING':\n * return <Loading />\n * case 'ERROR':\n * return <Error message={state.error} />\n * case 'SUCCESS':\n * // RENDER UI\n * }\n * }\n *\n * export default MyComponent\n * ```\n *\n * @typeParam T The type of the data returned by your `onLoad` function\n * @param onLoad The function that fetches your data. Should be a Promise that\n * returns your data\n * @returns\n * @group Hooks\n */\nexport default function useLoadDataState<T>(\n onLoad: (abortSignal: AbortSignal) => Promise<T>,\n): [\n state: LoadDataState<T>,\n handleRefresh: () => void,\n setResult: React.Dispatch<React.SetStateAction<T>>,\n] {\n const isMounted = useIsMounted()\n const [state, setState] = React.useState<LoadDataState<T>>({\n status: 'LOADING',\n })\n\n const handleLoad = React.useCallback(\n async (abortSignal: AbortSignal) => {\n setState({\n status: 'LOADING',\n })\n try {\n const result = await onLoad(abortSignal)\n if (isMounted.current && !abortSignal.aborted) {\n setState({\n status: 'SUCCESS',\n result,\n })\n }\n } catch (err) {\n if (isMounted.current && !abortSignal.aborted) {\n setState({\n status: 'ERROR',\n error: err as Error,\n })\n }\n }\n },\n [isMounted, onLoad],\n )\n\n const setResult: React.Dispatch<React.SetStateAction<T>> = React.useCallback(\n (setter) => {\n setState((currentState: LoadDataState<T>) => {\n if (currentState.status === 'SUCCESS') {\n return {\n ...currentState,\n result:\n typeof setter === 'function'\n ? // @ts-expect-error Typescript cannot tell between a generic type (T) and a function\n setter(currentState.result)\n : setter,\n }\n } else {\n return currentState\n }\n })\n },\n [],\n )\n\n // We use a number to trigger the refresh function so that\n // we can pass an abort controller using a useEffect and\n // have it aborted if the refresh function is triggered again.\n const [loadCount, setLoadCount] = React.useState(0)\n\n const handleRefresh = React.useCallback(() => {\n setLoadCount((currentLoadCount) => currentLoadCount + 1)\n }, [])\n\n React.useEffect(() => {\n const abortController = new AbortController()\n handleLoad(abortController.signal)\n return () => {\n abortController.abort()\n }\n }, [handleLoad, loadCount])\n\n return [state, handleRefresh, setResult]\n}\n"]}
|
@@ -52,10 +52,10 @@ import * as React from 'react';
|
|
52
52
|
* that returns your array of resources
|
53
53
|
* @returns
|
54
54
|
*/
|
55
|
-
export default function useLoadResourcesState<T>(onLoad: (abortSignal
|
55
|
+
export default function useLoadResourcesState<T>(onLoad: (abortSignal: AbortSignal) => Promise<T[]>): [
|
56
56
|
resources: T[],
|
57
57
|
isLoading: boolean,
|
58
58
|
loadError: Error | null,
|
59
|
-
|
59
|
+
handleRefresh: () => void,
|
60
60
|
setResult: React.Dispatch<React.SetStateAction<T[]>>
|
61
61
|
];
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useLoadResourcesState.js","sourceRoot":"","sources":["../../src/hooks/useLoadResourcesState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,gBAAgB,MAAM,oBAAoB,CAAA;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAC3C,
|
1
|
+
{"version":3,"file":"useLoadResourcesState.js","sourceRoot":"","sources":["../../src/hooks/useLoadResourcesState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,gBAAgB,MAAM,oBAAoB,CAAA;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAC3C,MAAkD;IAQlD,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAM,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACvD,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACjD,OAAO;QACL,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc;QAC1D,KAAK,CAAC,MAAM,KAAK,SAAS;QAC1B,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QAC7C,GAAG,IAAI;KACR,CAAA;AACH,CAAC","sourcesContent":["import * as React from 'react'\nimport useLoadDataState from './useLoadDataState'\n\n/**\n * This function is a react hook for managing the state involved with loading\n * resources.\n *\n * ## Example\n *\n * ```js\n * import { useLoadResourcesState } from '@oneblink/apps-react'\n * const fetchResources = async () => {\n * const response = await fetch(`https://some-website.com/api?data=data`)\n *\n * if (!response.ok) {\n * const text = await response.text()\n * throw new Error(text)\n * }\n *\n * return await response.json()\n * }\n *\n * const MyComponent = () => {\n * const [resources, isLoading, loadError, refresh, setResult] =\n * useLoadResourcesState(fetchResources)\n *\n * if (isLoading) {\n * return <Loading />\n * }\n *\n * if (loadError) {\n * return (\n * <>\n * <Error message={state.error} />\n * <button onClick={refresh}>Try Again</button>\n * </>\n * )\n * }\n *\n * return (\n * <>\n * {resources.map((resource) => {\n * // RENDER UI\n * return <></>\n * })}\n * </>\n * )\n * }\n *\n * export default MyComponent\n * ```\n *\n * @param onLoad The function that fetches your resources. Should be a Promise\n * that returns your array of resources\n * @returns\n */\nexport default function useLoadResourcesState<T>(\n onLoad: (abortSignal: AbortSignal) => Promise<T[]>,\n): [\n resources: T[],\n isLoading: boolean,\n loadError: Error | null,\n handleRefresh: () => void,\n setResult: React.Dispatch<React.SetStateAction<T[]>>,\n] {\n const emptyResources = React.useMemo<T[]>(() => [], [])\n const [state, ...rest] = useLoadDataState(onLoad)\n return [\n state.status === 'SUCCESS' ? state.result : emptyResources,\n state.status === 'LOADING',\n state.status === 'ERROR' ? state.error : null,\n ...rest,\n ]\n}\n"]}
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@oneblink/apps-react",
|
3
3
|
"description": "Helper functions for OneBlink apps in ReactJS.",
|
4
|
-
"version": "5.1.
|
4
|
+
"version": "5.1.2-beta.2",
|
5
5
|
"author": "OneBlink <developers@oneblink.io> (https://oneblink.io)",
|
6
6
|
"bugs": {
|
7
7
|
"url": "https://github.com/oneblink/apps-react/issues"
|