@oneblink/apps-react 4.0.0-beta.5 → 4.0.0-beta.6
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 +2 -8
- package/dist/OneBlinkAutoSaveForm.d.ts +24 -5
- package/dist/OneBlinkAutoSaveForm.js +11 -0
- package/dist/OneBlinkAutoSaveForm.js.map +1 -1
- package/dist/OneBlinkForm.d.ts +556 -8
- package/dist/OneBlinkForm.js +544 -0
- package/dist/OneBlinkForm.js.map +1 -1
- package/dist/OneBlinkFormBase.d.ts +51 -6
- package/dist/OneBlinkFormBase.js.map +1 -1
- package/dist/OneBlinkReadOnlyForm.d.ts +82 -6
- package/dist/OneBlinkReadOnlyForm.js +78 -0
- package/dist/OneBlinkReadOnlyForm.js.map +1 -1
- package/dist/PaymentReceipt.d.ts +55 -0
- package/dist/PaymentReceipt.js +45 -0
- package/dist/PaymentReceipt.js.map +1 -1
- package/dist/components/formStore/FormStoreTableProvider.js +23 -1
- package/dist/components/formStore/FormStoreTableProvider.js.map +1 -1
- package/dist/components/renderer/LookupNotification.js +11 -2
- package/dist/components/renderer/LookupNotification.js.map +1 -1
- package/dist/components/renderer/OneBlinkFormElements.d.ts +3 -3
- package/dist/components/renderer/OneBlinkFormElements.js.map +1 -1
- package/dist/components/renderer/PageFormElements.d.ts +3 -3
- package/dist/components/renderer/PageFormElements.js.map +1 -1
- package/dist/components/renderer/ProgressBar.d.ts +2 -3
- package/dist/components/renderer/ProgressBar.js.map +1 -1
- package/dist/form-elements/FormElementCalculation.js.map +1 -1
- package/dist/form-elements/FormElementForm.d.ts +4 -4
- package/dist/form-elements/FormElementForm.js.map +1 -1
- package/dist/form-elements/FormElementRepeatableSet.d.ts +4 -4
- package/dist/form-elements/FormElementRepeatableSet.js.map +1 -1
- package/dist/form-elements/FormElementSummary.js.map +1 -1
- package/dist/hooks/useAuth.d.ts +79 -6
- package/dist/hooks/useAuth.js +52 -0
- package/dist/hooks/useAuth.js.map +1 -1
- package/dist/hooks/useBooleanState.d.ts +41 -5
- package/dist/hooks/useBooleanState.js +35 -0
- package/dist/hooks/useBooleanState.js.map +1 -1
- package/dist/hooks/useClickOutsideElement.d.ts +39 -0
- package/dist/hooks/useClickOutsideElement.js +39 -0
- package/dist/hooks/useClickOutsideElement.js.map +1 -1
- package/dist/hooks/useConditionalLogic.d.ts +2 -3
- package/dist/hooks/useConditionalLogic.js.map +1 -1
- package/dist/hooks/useDrafts.d.ts +61 -1
- package/dist/hooks/useDrafts.js +56 -11
- package/dist/hooks/useDrafts.js.map +1 -1
- package/dist/hooks/useFormSubmissionAutoSaveState.d.ts +17 -5
- package/dist/hooks/useFormSubmissionAutoSaveState.js +9 -0
- package/dist/hooks/useFormSubmissionAutoSaveState.js.map +1 -1
- package/dist/hooks/useFormSubmissionModelContext.d.ts +4 -4
- package/dist/hooks/useFormSubmissionModelContext.js.map +1 -1
- package/dist/hooks/useFormSubmissionState.d.ts +44 -5
- package/dist/hooks/useFormSubmissionState.js +36 -0
- package/dist/hooks/useFormSubmissionState.js.map +1 -1
- package/dist/hooks/useFormValidation.d.ts +3 -3
- package/dist/hooks/useFormValidation.js.map +1 -1
- package/dist/hooks/useInjectPages.d.ts +2 -3
- package/dist/hooks/useInjectPages.js.map +1 -1
- package/dist/hooks/useIsMounted.d.ts +19 -0
- package/dist/hooks/useIsMounted.js +18 -0
- package/dist/hooks/useIsMounted.js.map +1 -1
- package/dist/hooks/useIsOffline.d.ts +49 -0
- package/dist/hooks/useIsOffline.js +49 -0
- package/dist/hooks/useIsOffline.js.map +1 -1
- package/dist/hooks/useLoadDataState.d.ts +44 -3
- package/dist/hooks/useLoadDataState.js +39 -0
- package/dist/hooks/useLoadDataState.js.map +1 -1
- package/dist/hooks/useLogin.d.ts +396 -11
- package/dist/hooks/useLogin.js +299 -0
- package/dist/hooks/useLogin.js.map +1 -1
- package/dist/hooks/useLookups.d.ts +3 -3
- package/dist/hooks/useLookups.js.map +1 -1
- package/dist/hooks/useNullableState.d.ts +44 -1
- package/dist/hooks/useNullableState.js +40 -1
- package/dist/hooks/useNullableState.js.map +1 -1
- package/dist/hooks/usePendingSubmissions.d.ts +95 -0
- package/dist/hooks/usePendingSubmissions.js +192 -0
- package/dist/hooks/usePendingSubmissions.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/services/checkBsbsAreInvalid.d.ts +2 -3
- package/dist/services/checkBsbsAreInvalid.js.map +1 -1
- package/dist/services/checkIfAttachmentsExist.d.ts +2 -3
- package/dist/services/checkIfAttachmentsExist.js.map +1 -1
- package/dist/services/checkIfBsbsAreValidating.d.ts +2 -3
- package/dist/services/checkIfBsbsAreValidating.js.map +1 -1
- package/dist/services/cleanFormSubmissionModel.d.ts +4 -4
- package/dist/services/cleanFormSubmissionModel.js +2 -1
- package/dist/services/cleanFormSubmissionModel.js.map +1 -1
- package/dist/services/form-validation.d.ts +3 -3
- package/dist/services/form-validation.js.map +1 -1
- package/dist/services/generate-default-data.d.ts +2 -3
- package/dist/services/generate-default-data.js +3 -1
- package/dist/services/generate-default-data.js.map +1 -1
- package/dist/services/generateFreshdeskDependentFieldElements.js.map +1 -1
- package/dist/services/getDateRangeConfiguration.d.ts +2 -3
- package/dist/services/getDateRangeConfiguration.js.map +1 -1
- package/dist/services/getRepeatableSetEntriesConfiguration.d.ts +2 -3
- package/dist/services/getRepeatableSetEntriesConfiguration.js.map +1 -1
- package/dist/styles/receipt.scss +1 -1
- package/dist/styles/repeatable-set.scss +2 -2
- package/dist/typedoc.d.ts +2 -0
- package/dist/typedoc.js +3 -0
- package/dist/typedoc.js.map +1 -0
- package/dist/types/form.d.ts +5 -6
- package/dist/types/form.js.map +1 -1
- package/package.json +9 -3
@@ -1,6 +1,42 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import _cloneDeep from 'lodash.clonedeep';
|
3
3
|
import generateDefaultData from '../services/generate-default-data';
|
4
|
+
/**
|
5
|
+
* This function is a simple wrapper around the react hook `useState()`. The
|
6
|
+
* results can be passed to the [`<OneBlinkForm
|
7
|
+
* />`](https://oneblink.github.io/apps-react/somewhere) //TODO: Fix link
|
8
|
+
* component.
|
9
|
+
*
|
10
|
+
* ## Example
|
11
|
+
*
|
12
|
+
* ```js
|
13
|
+
* import {
|
14
|
+
* useFormSubmissionState,
|
15
|
+
* OneBlinkFormControlled,
|
16
|
+
* } from '@oneblink/apps-react'
|
17
|
+
*
|
18
|
+
* function Uncontrolled({ form, initialSubmission, ...props }) {
|
19
|
+
* const [{ definition, submission }, setFormSubmission] =
|
20
|
+
* useFormSubmissionState(form, initialSubmission)
|
21
|
+
*
|
22
|
+
* return (
|
23
|
+
* <OneBlinkFormControlled
|
24
|
+
* {...props}
|
25
|
+
* definition={definition}
|
26
|
+
* submission={submission}
|
27
|
+
* setFormSubmission={setFormSubmission}
|
28
|
+
* lastElementUpdated={lastElementUpdated}
|
29
|
+
* />
|
30
|
+
* )
|
31
|
+
* }
|
32
|
+
* ```
|
33
|
+
*
|
34
|
+
* @param form The OneBlink Form to render
|
35
|
+
* @param initialSubmission The initial submission data to populate the form
|
36
|
+
* with
|
37
|
+
* @param lastElementUpdated
|
38
|
+
* @returns
|
39
|
+
*/
|
4
40
|
export default function useFormSubmissionState(form, initialSubmission, lastElementUpdated) {
|
5
41
|
return React.useState(() => {
|
6
42
|
const definition = _cloneDeep(form);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useFormSubmissionState.js","sourceRoot":"","sources":["../../src/hooks/useFormSubmissionState.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,UAAU,MAAM,kBAAkB,CAAA;AAEzC,OAAO,mBAAmB,MAAM,mCAAmC,CAAA;
|
1
|
+
{"version":3,"file":"useFormSubmissionState.js","sourceRoot":"","sources":["../../src/hooks/useFormSubmissionState.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,UAAU,MAAM,kBAAkB,CAAA;AAEzC,OAAO,mBAAmB,MAAM,mCAAmC,CAAA;AACnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAC5C,IAAoB,EACpB,iBAAkE,EAClE,kBAA0C;IAE1C,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE;QACzB,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;QACnC,MAAM,WAAW,GAAG,mBAAmB,CACrC,UAAU,CAAC,QAAQ,EACnB,iBAAiB,IAAI,EAAE,CACxB,CAAA;QACD,OAAO;YACL,UAAU;YACV,UAAU,EAAE,WAAW;YACvB,kBAAkB;SACnB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import * as React from 'react'\nimport _cloneDeep from 'lodash.clonedeep'\nimport { FormTypes, SubmissionTypes } from '@oneblink/types'\nimport generateDefaultData from '../services/generate-default-data'\n/**\n * This function is a simple wrapper around the react hook `useState()`. The\n * results can be passed to the [`<OneBlinkForm\n * />`](https://oneblink.github.io/apps-react/somewhere) //TODO: Fix link\n * component.\n *\n * ## Example\n *\n * ```js\n * import {\n * useFormSubmissionState,\n * OneBlinkFormControlled,\n * } from '@oneblink/apps-react'\n *\n * function Uncontrolled({ form, initialSubmission, ...props }) {\n * const [{ definition, submission }, setFormSubmission] =\n * useFormSubmissionState(form, initialSubmission)\n *\n * return (\n * <OneBlinkFormControlled\n * {...props}\n * definition={definition}\n * submission={submission}\n * setFormSubmission={setFormSubmission}\n * lastElementUpdated={lastElementUpdated}\n * />\n * )\n * }\n * ```\n *\n * @param form The OneBlink Form to render\n * @param initialSubmission The initial submission data to populate the form\n * with\n * @param lastElementUpdated\n * @returns\n */\nexport default function useFormSubmissionState(\n form: FormTypes.Form,\n initialSubmission?: SubmissionTypes.S3SubmissionData['submission'],\n lastElementUpdated?: FormTypes.FormElement,\n) {\n return React.useState(() => {\n const definition = _cloneDeep(form)\n const defaultData = generateDefaultData(\n definition.elements,\n initialSubmission || {},\n )\n return {\n definition,\n submission: defaultData,\n lastElementUpdated,\n }\n })\n}\n"]}
|
@@ -1,7 +1,7 @@
|
|
1
|
-
import { FormTypes } from '@oneblink/types';
|
2
|
-
import { FormElementsConditionallyShown
|
1
|
+
import { FormTypes, SubmissionTypes } from '@oneblink/types';
|
2
|
+
import { FormElementsConditionallyShown } from '../types/form';
|
3
3
|
export default function useFormValidation(pages: FormTypes.PageElement[]): {
|
4
4
|
executedLookup: (element: FormTypes.LookupFormElement) => void;
|
5
5
|
executeLookupFailed: (element: FormTypes.LookupFormElement) => void;
|
6
|
-
validate: (submission:
|
6
|
+
validate: (submission: SubmissionTypes.S3SubmissionData['submission'], formElementsConditionallyShown: FormElementsConditionallyShown) => import("../types/form").FormElementsValidation | undefined;
|
7
7
|
};
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useFormValidation.js","sourceRoot":"","sources":["../../src/hooks/useFormValidation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,6BAA6B,CAAA;
|
1
|
+
{"version":3,"file":"useFormValidation.js","sourceRoot":"","sources":["../../src/hooks/useFormValidation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,6BAA6B,CAAA;AAGpC,SAAS,4BAA4B,CACnC,YAAqC;IAErC,OAAO,YAAY,CAAC,MAAM,CACxB,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE;QACpB,QAAQ,WAAW,CAAC,IAAI,EAAE;YACxB,KAAK,MAAM,CAAC;YACZ,KAAK,SAAS,CAAC,CAAC;gBACd,OAAO;oBACL,GAAG,IAAI;oBACP,GAAG,4BAA4B,CAAC,WAAW,CAAC,QAAQ,CAAC;iBACtD,CAAA;aACF;YACD,KAAK,UAAU,CAAC;YAChB,KAAK,MAAM,CAAC;YACZ,KAAK,eAAe,CAAC,CAAC;gBACpB,OAAO;oBACL,GAAG,IAAI;oBACP;wBACE,GAAG,WAAW;wBACd,QAAQ,EAAE,4BAA4B,CACpC,WAAW,CAAC,QAAQ,IAAI,EAAE,CAC3B;qBACF;iBACF,CAAA;aACF;YACD,OAAO,CAAC,CAAC;gBACP,OAAO,CAAC,GAAG,IAAI,EAAE,WAAW,CAAC,CAAA;aAC9B;SACF;IACH,CAAC,EACD,EAAE,CACH,CAAA;AACH,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,KAA8B;IACtE,MAAM,CAAC,6BAA6B,EAAE,gCAAgC,CAAC,GACrE,KAAK,CAAC,QAAQ,CAAW,EAAE,CAAC,CAAA;IAE9B,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,CACtC,CAAC,OAAoC,EAAE,EAAE;QACvC,gCAAgC,CAC9B,CAAC,oCAA8C,EAAE,EAAE;YACjD,IAAI,oCAAoC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;gBAC7D,OAAO,oCAAoC,CAAA;aAC5C;YACD,OAAO,CAAC,GAAG,oCAAoC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;QAC9D,CAAC,CACF,CAAA;IACH,CAAC,EACD,EAAE,CACH,CAAA;IACD,MAAM,mBAAmB,GAAG,KAAK,CAAC,WAAW,CAC3C,CAAC,OAAoC,EAAE,EAAE;QACvC,gCAAgC,CAC9B,CAAC,oCAAoC,EAAE,EAAE;YACvC,OAAO,oCAAoC,CAAC,MAAM,CAChD,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,CACxC,CAAA;QACH,CAAC,CACF,CAAA;IACH,CAAC,EACD,EAAE,CACH,CAAA;IAED,MAAM,uBAAuB,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACjD,OAAO,4BAA4B,CAAC,KAAK,CAAC,CAAA;IAC5C,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QAC1C,OAAO,wBAAwB,CAC7B,uBAAuB,EACvB,6BAA6B,CAC9B,CAAA;IACH,CAAC,EAAE,CAAC,uBAAuB,EAAE,6BAA6B,CAAC,CAAC,CAAA;IAE5D,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,CACtC,CACE,UAA0D,EAC1D,8BAA8D,EAC9D,EAAE;QACF,OAAO,kBAAkB,CACvB,gBAAgB,EAChB,UAAU,EACV,8BAA8B,CAC/B,CAAA;IACH,CAAC,EACD,CAAC,gBAAgB,CAAC,CACnB,CAAA;IAED,OAAO;QACL,cAAc;QACd,mBAAmB;QACnB,QAAQ,EAAE,cAAc;KACzB,CAAA;AACH,CAAC","sourcesContent":["import { FormTypes, SubmissionTypes } from '@oneblink/types'\nimport * as React from 'react'\n\nimport {\n validateSubmission,\n generateValidationSchema,\n} from '../services/form-validation'\nimport { FormElementsConditionallyShown } from '../types/form'\n\nfunction stripFormElementsWithoutName(\n formElements: FormTypes.FormElement[],\n): FormTypes.FormElementWithName[] {\n return formElements.reduce<FormTypes.FormElementWithName[]>(\n (memo, formElement) => {\n switch (formElement.type) {\n case 'page':\n case 'section': {\n return [\n ...memo,\n ...stripFormElementsWithoutName(formElement.elements),\n ]\n }\n case 'infoPage':\n case 'form':\n case 'repeatableSet': {\n return [\n ...memo,\n {\n ...formElement,\n elements: stripFormElementsWithoutName(\n formElement.elements || [],\n ),\n },\n ]\n }\n default: {\n return [...memo, formElement]\n }\n }\n },\n [],\n )\n}\n\nexport default function useFormValidation(pages: FormTypes.PageElement[]) {\n const [elementIdsWithLookupsExecuted, setElementIdsWithLookupsExecuted] =\n React.useState<string[]>([])\n\n const executedLookup = React.useCallback(\n (element: FormTypes.LookupFormElement) => {\n setElementIdsWithLookupsExecuted(\n (currentElementIdsWithLookupsExecuted: string[]) => {\n if (currentElementIdsWithLookupsExecuted.includes(element.id)) {\n return currentElementIdsWithLookupsExecuted\n }\n return [...currentElementIdsWithLookupsExecuted, element.id]\n },\n )\n },\n [],\n )\n const executeLookupFailed = React.useCallback(\n (element: FormTypes.LookupFormElement) => {\n setElementIdsWithLookupsExecuted(\n (currentElementIdsWithLookupsExecuted) => {\n return currentElementIdsWithLookupsExecuted.filter(\n (elementId) => elementId !== element.id,\n )\n },\n )\n },\n [],\n )\n\n const formElementsWithoutName = React.useMemo(() => {\n return stripFormElementsWithoutName(pages)\n }, [pages])\n\n const validationSchema = React.useMemo(() => {\n return generateValidationSchema(\n formElementsWithoutName,\n elementIdsWithLookupsExecuted,\n )\n }, [formElementsWithoutName, elementIdsWithLookupsExecuted])\n\n const handleValidate = React.useCallback(\n (\n submission: SubmissionTypes.S3SubmissionData['submission'],\n formElementsConditionallyShown: FormElementsConditionallyShown,\n ) => {\n return validateSubmission(\n validationSchema,\n submission,\n formElementsConditionallyShown,\n )\n },\n [validationSchema],\n )\n\n return {\n executedLookup,\n executeLookupFailed,\n validate: handleValidate,\n }\n}\n"]}
|
@@ -1,7 +1,6 @@
|
|
1
|
-
import { FormTypes } from '@oneblink/types';
|
1
|
+
import { FormTypes, SubmissionTypes } from '@oneblink/types';
|
2
2
|
import * as React from 'react';
|
3
|
-
|
4
|
-
type InjectPagesContextValue = (lookupFormElement: FormTypes.LookupFormElement, pageElements: FormTypes.PageElement[], data?: FormSubmissionModel) => void;
|
3
|
+
type InjectPagesContextValue = (lookupFormElement: FormTypes.LookupFormElement, pageElements: FormTypes.PageElement[], data?: SubmissionTypes.S3SubmissionData['submission']) => void;
|
5
4
|
export declare const InjectPagesContext: React.Context<InjectPagesContextValue>;
|
6
5
|
export default function useInjectPages(): InjectPagesContextValue;
|
7
6
|
export {};
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useInjectPages.js","sourceRoot":"","sources":["../../src/hooks/useInjectPages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
1
|
+
{"version":3,"file":"useInjectPages.js","sourceRoot":"","sources":["../../src/hooks/useInjectPages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC,aAAa,CACnD,GAAG,EAAE,GAAE,CAAC,CACT,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,cAAc;IACpC,OAAO,KAAK,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAA;AAC7C,CAAC","sourcesContent":["import { FormTypes, SubmissionTypes } from '@oneblink/types'\nimport * as React from 'react'\n\ntype InjectPagesContextValue = (\n lookupFormElement: FormTypes.LookupFormElement,\n pageElements: FormTypes.PageElement[],\n data?: SubmissionTypes.S3SubmissionData['submission'],\n) => void\n\nexport const InjectPagesContext = React.createContext<InjectPagesContextValue>(\n () => {},\n)\n\nexport default function useInjectPages() {\n return React.useContext(InjectPagesContext)\n}\n"]}
|
@@ -1,3 +1,22 @@
|
|
1
|
+
/**
|
2
|
+
* This function is a react hook for determining whether the consuming component
|
3
|
+
* is currently mounted on the DOM.
|
4
|
+
*
|
5
|
+
* ## Example
|
6
|
+
*
|
7
|
+
* ```js
|
8
|
+
* import { useIsMounted } from '@oneblink/apps-react'
|
9
|
+
*
|
10
|
+
* const isMounted = useIsMounted()
|
11
|
+
*
|
12
|
+
* if (isMounted.current) {
|
13
|
+
* // DO SOMETHING HERE
|
14
|
+
* }
|
15
|
+
* ```
|
16
|
+
*
|
17
|
+
* @returns
|
18
|
+
*/
|
1
19
|
export default function useIsMounted(): {
|
20
|
+
/** Whether the current component is mounted. */
|
2
21
|
current: boolean;
|
3
22
|
};
|
@@ -1,4 +1,22 @@
|
|
1
1
|
import * as React from 'react';
|
2
|
+
/**
|
3
|
+
* This function is a react hook for determining whether the consuming component
|
4
|
+
* is currently mounted on the DOM.
|
5
|
+
*
|
6
|
+
* ## Example
|
7
|
+
*
|
8
|
+
* ```js
|
9
|
+
* import { useIsMounted } from '@oneblink/apps-react'
|
10
|
+
*
|
11
|
+
* const isMounted = useIsMounted()
|
12
|
+
*
|
13
|
+
* if (isMounted.current) {
|
14
|
+
* // DO SOMETHING HERE
|
15
|
+
* }
|
16
|
+
* ```
|
17
|
+
*
|
18
|
+
* @returns
|
19
|
+
*/
|
2
20
|
export default function useIsMounted() {
|
3
21
|
const isMounted = React.useRef(false);
|
4
22
|
React.useEffect(() => {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useIsMounted.js","sourceRoot":"","sources":["../../src/hooks/useIsMounted.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,MAAM,CAAC,OAAO,UAAU,YAAY;
|
1
|
+
{"version":3,"file":"useIsMounted.js","sourceRoot":"","sources":["../../src/hooks/useIsMounted.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY;IAIlC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACrC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,SAAS,CAAC,OAAO,GAAG,IAAI,CAAA;QACxB,OAAO,GAAG,EAAE;YACV,SAAS,CAAC,OAAO,GAAG,KAAK,CAAA;QAC3B,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IACN,OAAO,SAAS,CAAA;AAClB,CAAC","sourcesContent":["import * as React from 'react'\n\n/**\n * This function is a react hook for determining whether the consuming component\n * is currently mounted on the DOM.\n *\n * ## Example\n *\n * ```js\n * import { useIsMounted } from '@oneblink/apps-react'\n *\n * const isMounted = useIsMounted()\n *\n * if (isMounted.current) {\n * // DO SOMETHING HERE\n * }\n * ```\n *\n * @returns\n */\nexport default function useIsMounted(): {\n /** Whether the current component is mounted. */\n current: boolean\n} {\n const isMounted = React.useRef(false)\n React.useEffect(() => {\n isMounted.current = true\n return () => {\n isMounted.current = false\n }\n }, [])\n return isMounted\n}\n"]}
|
@@ -1,6 +1,55 @@
|
|
1
1
|
import * as React from 'react';
|
2
|
+
/**
|
3
|
+
* @param type
|
4
|
+
* @param listener
|
5
|
+
*/
|
2
6
|
export declare const useNetworkChangeEffect: (type: 'online' | 'offline', listener: () => unknown) => void;
|
7
|
+
/**
|
8
|
+
* IsOfflineContextProvider is a React Component that provides the `isOffline`
|
9
|
+
* state for components further down your component tree to consume. It should
|
10
|
+
* be used to wrap the components requiring the state.
|
11
|
+
*
|
12
|
+
* - **This component is required in your component tree to be able to consume the
|
13
|
+
* [`useIsOffline`](./useIsOffline.html) hook.**
|
14
|
+
*
|
15
|
+
* ### Usage
|
16
|
+
*
|
17
|
+
* ```jsx
|
18
|
+
* import { IsOfflineContextProvider } from '@oneblink/apps-react'
|
19
|
+
*
|
20
|
+
* const TopLevelComponent = () => {
|
21
|
+
* return (
|
22
|
+
* <IsOfflineContextProvider>
|
23
|
+
* <div>
|
24
|
+
* <ComponentThatRequiresOfflineState />
|
25
|
+
* </div>
|
26
|
+
* </IsOfflineContextProvider>
|
27
|
+
* )
|
28
|
+
* }
|
29
|
+
*
|
30
|
+
* export default TopLevelComponent
|
31
|
+
* ```
|
32
|
+
*
|
33
|
+
* @param props
|
34
|
+
* @returns
|
35
|
+
*/
|
3
36
|
export declare function IsOfflineContextProvider({ children, }: {
|
4
37
|
children: React.ReactNode;
|
5
38
|
}): JSX.Element;
|
39
|
+
/**
|
40
|
+
* This function is a react hook for determining whether an application is in an
|
41
|
+
* offline state.
|
42
|
+
*
|
43
|
+
* - **This component requires
|
44
|
+
* [`<IsOfflineContextProvider/>`](./IsOfflineContextProvider.html) to be
|
45
|
+
* present in your component tree.**
|
46
|
+
*
|
47
|
+
* ## Example
|
48
|
+
*
|
49
|
+
* ```js
|
50
|
+
* import { useIsOffline } from '@oneblink/apps-react'
|
51
|
+
*
|
52
|
+
* const isOffline = useIsOffline()
|
53
|
+
* ```
|
54
|
+
*/
|
6
55
|
export default function useIsOffline(): boolean;
|
@@ -3,6 +3,10 @@ import { offlineService } from '@oneblink/apps';
|
|
3
3
|
import useBooleanState from '../hooks/useBooleanState';
|
4
4
|
const defaultValue = offlineService.isOffline();
|
5
5
|
const IsOfflineContext = React.createContext(defaultValue);
|
6
|
+
/**
|
7
|
+
* @param type
|
8
|
+
* @param listener
|
9
|
+
*/
|
6
10
|
export const useNetworkChangeEffect = (type, listener) => {
|
7
11
|
React.useEffect(() => {
|
8
12
|
// Stupid cordova seems to require that offline/online
|
@@ -15,12 +19,57 @@ export const useNetworkChangeEffect = (type, listener) => {
|
|
15
19
|
};
|
16
20
|
}, [type, listener]);
|
17
21
|
};
|
22
|
+
/**
|
23
|
+
* IsOfflineContextProvider is a React Component that provides the `isOffline`
|
24
|
+
* state for components further down your component tree to consume. It should
|
25
|
+
* be used to wrap the components requiring the state.
|
26
|
+
*
|
27
|
+
* - **This component is required in your component tree to be able to consume the
|
28
|
+
* [`useIsOffline`](./useIsOffline.html) hook.**
|
29
|
+
*
|
30
|
+
* ### Usage
|
31
|
+
*
|
32
|
+
* ```jsx
|
33
|
+
* import { IsOfflineContextProvider } from '@oneblink/apps-react'
|
34
|
+
*
|
35
|
+
* const TopLevelComponent = () => {
|
36
|
+
* return (
|
37
|
+
* <IsOfflineContextProvider>
|
38
|
+
* <div>
|
39
|
+
* <ComponentThatRequiresOfflineState />
|
40
|
+
* </div>
|
41
|
+
* </IsOfflineContextProvider>
|
42
|
+
* )
|
43
|
+
* }
|
44
|
+
*
|
45
|
+
* export default TopLevelComponent
|
46
|
+
* ```
|
47
|
+
*
|
48
|
+
* @param props
|
49
|
+
* @returns
|
50
|
+
*/
|
18
51
|
export function IsOfflineContextProvider({ children, }) {
|
19
52
|
const [isOffline, goOffline, goOnline] = useBooleanState(defaultValue);
|
20
53
|
useNetworkChangeEffect('online', goOnline);
|
21
54
|
useNetworkChangeEffect('offline', goOffline);
|
22
55
|
return (React.createElement(IsOfflineContext.Provider, { value: isOffline }, children));
|
23
56
|
}
|
57
|
+
/**
|
58
|
+
* This function is a react hook for determining whether an application is in an
|
59
|
+
* offline state.
|
60
|
+
*
|
61
|
+
* - **This component requires
|
62
|
+
* [`<IsOfflineContextProvider/>`](./IsOfflineContextProvider.html) to be
|
63
|
+
* present in your component tree.**
|
64
|
+
*
|
65
|
+
* ## Example
|
66
|
+
*
|
67
|
+
* ```js
|
68
|
+
* import { useIsOffline } from '@oneblink/apps-react'
|
69
|
+
*
|
70
|
+
* const isOffline = useIsOffline()
|
71
|
+
* ```
|
72
|
+
*/
|
24
73
|
export default function useIsOffline() {
|
25
74
|
return React.useContext(IsOfflineContext);
|
26
75
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useIsOffline.js","sourceRoot":"","sources":["../../src/hooks/useIsOffline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,eAAe,MAAM,0BAA0B,CAAA;AAEtD,MAAM,YAAY,GAAG,cAAc,CAAC,SAAS,EAAE,CAAA;AAE/C,MAAM,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAAU,YAAY,CAAC,CAAA;AAEnE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,IAA0B,EAC1B,QAAuB,EACvB,EAAE;IACF,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,sDAAsD;QACtD,sDAAsD;QACtD,qBAAqB;QACrB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAA;QAClD,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QAExC,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QAC7C,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;AACtB,CAAC,CAAA;AAED,MAAM,UAAU,wBAAwB,CAAC,EACvC,QAAQ,GAGT;IACC,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,GAAG,eAAe,CAAC,YAAY,CAAC,CAAA;IAEtE,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC1C,sBAAsB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IAE5C,OAAO,CACL,oBAAC,gBAAgB,CAAC,QAAQ,IAAC,KAAK,EAAE,SAAS,IACxC,QAAQ,CACiB,CAC7B,CAAA;AACH,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,YAAY;IAClC,OAAO,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAA;AAC3C,CAAC","sourcesContent":["import * as React from 'react'\n\nimport { offlineService } from '@oneblink/apps'\nimport useBooleanState from '../hooks/useBooleanState'\n\nconst defaultValue = offlineService.isOffline()\n\nconst IsOfflineContext = React.createContext<boolean>(defaultValue)\n\nexport const useNetworkChangeEffect = (\n type: 'online' | 'offline',\n listener: () => unknown,\n) => {\n React.useEffect(() => {\n // Stupid cordova seems to require that offline/online\n // listeners are set on the document and browsers seem\n // to require window.\n const element = window.cordova ? document : window\n element.addEventListener(type, listener)\n\n return () => {\n element.removeEventListener(type, listener)\n }\n }, [type, listener])\n}\n\nexport function IsOfflineContextProvider({\n children,\n}: {\n children: React.ReactNode\n}) {\n const [isOffline, goOffline, goOnline] = useBooleanState(defaultValue)\n\n useNetworkChangeEffect('online', goOnline)\n useNetworkChangeEffect('offline', goOffline)\n\n return (\n <IsOfflineContext.Provider value={isOffline}>\n {children}\n </IsOfflineContext.Provider>\n )\n}\n\nexport default function useIsOffline() {\n return React.useContext(IsOfflineContext)\n}\n"]}
|
1
|
+
{"version":3,"file":"useIsOffline.js","sourceRoot":"","sources":["../../src/hooks/useIsOffline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,eAAe,MAAM,0BAA0B,CAAA;AAEtD,MAAM,YAAY,GAAG,cAAc,CAAC,SAAS,EAAE,CAAA;AAE/C,MAAM,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAAU,YAAY,CAAC,CAAA;AAEnE;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,IAA0B,EAC1B,QAAuB,EACvB,EAAE;IACF,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,sDAAsD;QACtD,sDAAsD;QACtD,qBAAqB;QACrB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAA;QAClD,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QAExC,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QAC7C,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;AACtB,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,wBAAwB,CAAC,EACvC,QAAQ,GAGT;IACC,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,GAAG,eAAe,CAAC,YAAY,CAAC,CAAA;IAEtE,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC1C,sBAAsB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IAE5C,OAAO,CACL,oBAAC,gBAAgB,CAAC,QAAQ,IAAC,KAAK,EAAE,SAAS,IACxC,QAAQ,CACiB,CAC7B,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY;IAClC,OAAO,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAA;AAC3C,CAAC","sourcesContent":["import * as React from 'react'\n\nimport { offlineService } from '@oneblink/apps'\nimport useBooleanState from '../hooks/useBooleanState'\n\nconst defaultValue = offlineService.isOffline()\n\nconst IsOfflineContext = React.createContext<boolean>(defaultValue)\n\n/**\n * @param type\n * @param listener\n */\nexport const useNetworkChangeEffect = (\n type: 'online' | 'offline',\n listener: () => unknown,\n) => {\n React.useEffect(() => {\n // Stupid cordova seems to require that offline/online\n // listeners are set on the document and browsers seem\n // to require window.\n const element = window.cordova ? document : window\n element.addEventListener(type, listener)\n\n return () => {\n element.removeEventListener(type, listener)\n }\n }, [type, listener])\n}\n\n/**\n * IsOfflineContextProvider is a React Component that provides the `isOffline`\n * state for components further down your component tree to consume. It should\n * be used to wrap the components requiring the state.\n *\n * - **This component is required in your component tree to be able to consume the\n * [`useIsOffline`](./useIsOffline.html) hook.**\n *\n * ### Usage\n *\n * ```jsx\n * import { IsOfflineContextProvider } from '@oneblink/apps-react'\n *\n * const TopLevelComponent = () => {\n * return (\n * <IsOfflineContextProvider>\n * <div>\n * <ComponentThatRequiresOfflineState />\n * </div>\n * </IsOfflineContextProvider>\n * )\n * }\n *\n * export default TopLevelComponent\n * ```\n *\n * @param props\n * @returns\n */\nexport function IsOfflineContextProvider({\n children,\n}: {\n children: React.ReactNode\n}) {\n const [isOffline, goOffline, goOnline] = useBooleanState(defaultValue)\n\n useNetworkChangeEffect('online', goOnline)\n useNetworkChangeEffect('offline', goOffline)\n\n return (\n <IsOfflineContext.Provider value={isOffline}>\n {children}\n </IsOfflineContext.Provider>\n )\n}\n\n/**\n * This function is a react hook for determining whether an application is in an\n * offline state.\n *\n * - **This component requires\n * [`<IsOfflineContextProvider/>`](./IsOfflineContextProvider.html) to be\n * present in your component tree.**\n *\n * ## Example\n *\n * ```js\n * import { useIsOffline } from '@oneblink/apps-react'\n *\n * const isOffline = useIsOffline()\n * ```\n */\nexport default function useIsOffline() {\n return React.useContext(IsOfflineContext)\n}\n"]}
|
@@ -1,15 +1,56 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
export type LoadDataState<T> = {
|
3
3
|
status: 'SUCCESS';
|
4
|
+
/** Your data. */
|
4
5
|
result: T;
|
5
6
|
} | {
|
6
7
|
status: 'ERROR';
|
8
|
+
/** A JavaScript `Error` object. */
|
7
9
|
error: Error;
|
8
10
|
} | {
|
9
11
|
status: 'LOADING';
|
10
12
|
};
|
13
|
+
/**
|
14
|
+
* This function is a react hook for managing the state involved with loading
|
15
|
+
* data.
|
16
|
+
*
|
17
|
+
* ## Example
|
18
|
+
*
|
19
|
+
* ```js
|
20
|
+
* import { useLoadDataState } from '@oneblink/apps-react'
|
21
|
+
* const fetchData = async () => {
|
22
|
+
* const response = await fetch(`https://some-website.com/api?data=data`)
|
23
|
+
*
|
24
|
+
* if (!response.ok) {
|
25
|
+
* const text = await response.text()
|
26
|
+
* throw new Error(text)
|
27
|
+
* }
|
28
|
+
*
|
29
|
+
* return await response.json()
|
30
|
+
* }
|
31
|
+
*
|
32
|
+
* const MyComponent = () => {
|
33
|
+
* const [state, refresh, setResult] = useLoadDataState(fetchData)
|
34
|
+
*
|
35
|
+
* switch (state.status) {
|
36
|
+
* case 'LOADING':
|
37
|
+
* return <Loading />
|
38
|
+
* case 'ERROR':
|
39
|
+
* return <Error message={state.error} />
|
40
|
+
* case 'SUCCESS':
|
41
|
+
* // RENDER UI
|
42
|
+
* }
|
43
|
+
* }
|
44
|
+
*
|
45
|
+
* export default MyComponent
|
46
|
+
* ```
|
47
|
+
*
|
48
|
+
* @param onLoad The function that fetches your data. Should be a Promise that
|
49
|
+
* returns your data
|
50
|
+
* @returns
|
51
|
+
*/
|
11
52
|
export default function useLoadDataState<T>(onLoad: (abortSignal?: AbortSignal) => Promise<T>): [
|
12
|
-
LoadDataState<T>,
|
13
|
-
(abortSignal?: AbortSignal) => void,
|
14
|
-
React.Dispatch<React.SetStateAction<T>>
|
53
|
+
state: LoadDataState<T>,
|
54
|
+
handleLoad: (abortSignal?: AbortSignal) => void,
|
55
|
+
setResult: React.Dispatch<React.SetStateAction<T>>
|
15
56
|
];
|
@@ -1,5 +1,44 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import useIsMounted from './useIsMounted';
|
3
|
+
/**
|
4
|
+
* This function is a react hook for managing the state involved with loading
|
5
|
+
* data.
|
6
|
+
*
|
7
|
+
* ## Example
|
8
|
+
*
|
9
|
+
* ```js
|
10
|
+
* import { useLoadDataState } from '@oneblink/apps-react'
|
11
|
+
* const fetchData = async () => {
|
12
|
+
* const response = await fetch(`https://some-website.com/api?data=data`)
|
13
|
+
*
|
14
|
+
* if (!response.ok) {
|
15
|
+
* const text = await response.text()
|
16
|
+
* throw new Error(text)
|
17
|
+
* }
|
18
|
+
*
|
19
|
+
* return await response.json()
|
20
|
+
* }
|
21
|
+
*
|
22
|
+
* const MyComponent = () => {
|
23
|
+
* const [state, refresh, setResult] = useLoadDataState(fetchData)
|
24
|
+
*
|
25
|
+
* switch (state.status) {
|
26
|
+
* case 'LOADING':
|
27
|
+
* return <Loading />
|
28
|
+
* case 'ERROR':
|
29
|
+
* return <Error message={state.error} />
|
30
|
+
* case 'SUCCESS':
|
31
|
+
* // RENDER UI
|
32
|
+
* }
|
33
|
+
* }
|
34
|
+
*
|
35
|
+
* export default MyComponent
|
36
|
+
* ```
|
37
|
+
*
|
38
|
+
* @param onLoad The function that fetches your data. Should be a Promise that
|
39
|
+
* returns your data
|
40
|
+
* @returns
|
41
|
+
*/
|
3
42
|
export default function useLoadDataState(onLoad) {
|
4
43
|
const isMounted = useIsMounted();
|
5
44
|
const [state, setState] = React.useState({
|
@@ -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;
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,MAAiD;IAMjD,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,WAAyB,EAAE,EAAE;QAClC,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,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,OAAO,CAAA,EAAE;gBAC9C,QAAQ,CAAC;oBACP,MAAM,EAAE,SAAS;oBACjB,MAAM;iBACP,CAAC,CAAA;aACH;SACF;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,OAAO,CAAA,EAAE;gBAC9C,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,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,CAAC,CAAC,CAAA;IAEhB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,CAAC,CAAA;AACvC,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 * @param onLoad The function that fetches your data. Should be a Promise that\n * returns your data\n * @returns\n */\nexport default function useLoadDataState<T>(\n onLoad: (abortSignal?: AbortSignal) => Promise<T>,\n): [\n state: LoadDataState<T>,\n handleLoad: (abortSignal?: AbortSignal) => 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 React.useEffect(() => {\n const abortController = new AbortController()\n handleLoad(abortController.signal)\n return () => {\n abortController.abort()\n }\n }, [handleLoad])\n\n return [state, handleLoad, setResult]\n}\n"]}
|