@iress-oss/ids-components 0.0.1-dev.1 → 0.0.1-dev.3
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/patterns/Loading/LoadingSuspense.js +53 -0
- package/dist/patterns/Loading/hooks/useShouldRenderLoading.js +19 -15
- package/dist/patterns/Loading/hooks/useSuspenseResource.js +27 -0
- package/dist/src/patterns/Loading/Loading.d.ts +1 -1
- package/dist/src/patterns/Loading/LoadingSuspense.d.ts +73 -0
- package/dist/src/patterns/Loading/hooks/useShouldRenderLoading.d.ts +2 -1
- package/dist/src/patterns/Loading/hooks/useSuspenseResource.d.ts +17 -0
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsxs as d, Fragment as a, jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo as S, useRef as F, useState as g, useEffect as b, Suspense as R } from "react";
|
|
3
|
+
import { Q as i } from "../../Loading-rKDsRTjZ.js";
|
|
4
|
+
import { useSuspenseResource as I, uncacheSuspenseResource as E } from "./hooks/useSuspenseResource.js";
|
|
5
|
+
const k = ({
|
|
6
|
+
children: s,
|
|
7
|
+
delay: r,
|
|
8
|
+
onLoaded: l,
|
|
9
|
+
pattern: e,
|
|
10
|
+
startFrom: c,
|
|
11
|
+
...t
|
|
12
|
+
}) => {
|
|
13
|
+
const w = S(() => r || (e === "component" || e === "default" || e === "validate" ? 0 : e === "long" ? 1300 : 500), [r, e]), x = S(() => c || (e === "component" || e === "default" || e === "long" ? 0 : 250), [c, e]), m = F(!1), [u, j] = g(!1), o = i.shouldRender(u, w, x), [f, C] = g(!1);
|
|
14
|
+
b(() => {
|
|
15
|
+
u && !o && (C(!0), l == null || l());
|
|
16
|
+
}, [u, l, o]);
|
|
17
|
+
const h = () => {
|
|
18
|
+
m.current || (m.current = !0, j(() => !0));
|
|
19
|
+
};
|
|
20
|
+
return e === "component" || e === "validate" ? /* @__PURE__ */ d(a, { children: [
|
|
21
|
+
/* @__PURE__ */ n(
|
|
22
|
+
i,
|
|
23
|
+
{
|
|
24
|
+
pattern: e,
|
|
25
|
+
loaded: u,
|
|
26
|
+
...t,
|
|
27
|
+
children: f && s
|
|
28
|
+
}
|
|
29
|
+
),
|
|
30
|
+
/* @__PURE__ */ n(R, { fallback: null, children: !f && /* @__PURE__ */ n(v, { onResolved: h, children: !u && s }) })
|
|
31
|
+
] }) : /* @__PURE__ */ d(a, { children: [
|
|
32
|
+
o && /* @__PURE__ */ n(
|
|
33
|
+
i,
|
|
34
|
+
{
|
|
35
|
+
pattern: e,
|
|
36
|
+
loaded: u,
|
|
37
|
+
...t
|
|
38
|
+
}
|
|
39
|
+
),
|
|
40
|
+
/* @__PURE__ */ n(R, { fallback: null, children: f ? s : /* @__PURE__ */ n(v, { onResolved: h, children: !u && s }) })
|
|
41
|
+
] });
|
|
42
|
+
};
|
|
43
|
+
k.use = I;
|
|
44
|
+
k.uncache = E;
|
|
45
|
+
const v = ({
|
|
46
|
+
onResolved: s,
|
|
47
|
+
children: r
|
|
48
|
+
}) => (b(() => {
|
|
49
|
+
s();
|
|
50
|
+
}, [s]), r);
|
|
51
|
+
export {
|
|
52
|
+
k as IressLoadingSuspense
|
|
53
|
+
};
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
import { useState as
|
|
2
|
-
const
|
|
3
|
-
const [i, n
|
|
4
|
-
return
|
|
5
|
-
const
|
|
6
|
-
e ||
|
|
7
|
-
},
|
|
8
|
-
return () => clearTimeout(
|
|
9
|
-
}, [
|
|
1
|
+
import { useState as i, useRef as m, useEffect as f } from "react";
|
|
2
|
+
const p = (e, o = 500, r = 250, c = 250) => {
|
|
3
|
+
const [s, t] = i(r === 0), n = m(0);
|
|
4
|
+
return f(() => {
|
|
5
|
+
const u = setTimeout(() => {
|
|
6
|
+
e || (t(!0), n.current = performance.now());
|
|
7
|
+
}, r);
|
|
8
|
+
return () => clearTimeout(u);
|
|
9
|
+
}, [r, e]), f(() => {
|
|
10
10
|
if (e !== !0)
|
|
11
11
|
return;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
if (!n.current || performance.now() - n.current < c) {
|
|
13
|
+
t(!1);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const u = setTimeout(() => {
|
|
17
|
+
t(!1);
|
|
18
|
+
}, o);
|
|
19
|
+
return () => clearTimeout(u);
|
|
20
|
+
}, [e, o, c]), e !== !0 || s;
|
|
17
21
|
};
|
|
18
22
|
export {
|
|
19
|
-
|
|
23
|
+
p as useShouldRenderLoading
|
|
20
24
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useMemo as c } from "react";
|
|
2
|
+
const a = (e) => {
|
|
3
|
+
let r = "pending", n, o;
|
|
4
|
+
const u = e.then(
|
|
5
|
+
(t) => {
|
|
6
|
+
r = "success", n = t;
|
|
7
|
+
},
|
|
8
|
+
(t) => {
|
|
9
|
+
r = "error", o = t;
|
|
10
|
+
}
|
|
11
|
+
);
|
|
12
|
+
return {
|
|
13
|
+
read() {
|
|
14
|
+
if (r === "pending") throw u;
|
|
15
|
+
if (r === "error") throw o;
|
|
16
|
+
return n;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}, s = /* @__PURE__ */ new WeakMap(), d = (e) => c(() => (s.has(e) || s.set(e, a(e())), s.get(e)), [e]).read(), i = (e, r = 1e3) => {
|
|
20
|
+
setTimeout(() => {
|
|
21
|
+
s.delete(e);
|
|
22
|
+
}, r);
|
|
23
|
+
};
|
|
24
|
+
export {
|
|
25
|
+
i as uncacheSuspenseResource,
|
|
26
|
+
d as useSuspenseResource
|
|
27
|
+
};
|
|
@@ -43,5 +43,5 @@ export declare const IressLoading: {
|
|
|
43
43
|
* @param delay - Once a component has loaded, how long should the loading indicator be displayed for.
|
|
44
44
|
* @returns A boolean value that determines whether the `IressLoading` component is safe to be removed.
|
|
45
45
|
*/
|
|
46
|
-
shouldRender: (isLoaded: boolean, delay?: number, startFrom?: number) => boolean;
|
|
46
|
+
shouldRender: (isLoaded: boolean, delay?: number, startFrom?: number, avoidDelayTimeout?: number) => boolean;
|
|
47
47
|
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { StartUpLoadingProps } from './components/StartUpLoading';
|
|
3
|
+
import { ValidateLoadingProps } from './components/ValidateLoading';
|
|
4
|
+
import { PageLoadingProps } from './components/PageLoading';
|
|
5
|
+
import { ComponentLoadingProps } from './components/ComponentLoading';
|
|
6
|
+
import { LongLoadingProps } from './components/LongLoading';
|
|
7
|
+
import { DefaultLoadingProps } from './components/DefaultLoading';
|
|
8
|
+
export type IressLoadingSuspenseProps = (Omit<StartUpLoadingProps, 'loaded'> | ValidateLoadingProps | Omit<PageLoadingProps, 'loaded'> | Omit<ComponentLoadingProps, 'loaded'> | Omit<LongLoadingProps, 'loaded'> | DefaultLoadingProps) & {
|
|
9
|
+
/**
|
|
10
|
+
* The content that will be rendered inside the Suspense boundary.
|
|
11
|
+
* Typically includes lazy-loaded components and components that use the `use` or `IressLoadingSuspense.use` hook.
|
|
12
|
+
*/
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* Duration (in milliseconds) to delay unmounting the fallback
|
|
16
|
+
* to allow the fade-out animation to complete.
|
|
17
|
+
* By default it uses the default delay of the pattern.
|
|
18
|
+
*/
|
|
19
|
+
delay?: number;
|
|
20
|
+
/**
|
|
21
|
+
* By default it uses the default delay of the pattern.
|
|
22
|
+
*/
|
|
23
|
+
onLoaded?: () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Duration (in milliseconds) before showing the loading pattern.
|
|
26
|
+
* Default is 500ms, meaning a user will not even see the loading indicator if the page loads before this time.
|
|
27
|
+
*/
|
|
28
|
+
startFrom?: number;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* A pattern component that has in-built loading states for different contexts, designed to provide a consistent user experience across Iress applications.
|
|
32
|
+
*
|
|
33
|
+
* The `pattern` prop is used to determine the type of loading state to display. The following patterns are available:
|
|
34
|
+
*
|
|
35
|
+
* - `component`: Loading pattern for a component that is expected to take some time to load, but has content around it that can be loaded before it (hence not part of page pattern). It also supports updating the state of the component via a slightly different UI. Examples:
|
|
36
|
+
* - Charts that can be updated in real-time
|
|
37
|
+
* - Tables that load many records and may update in real-time
|
|
38
|
+
* - `long`: Loading pattern for a component that is expected to take longer than 10 seconds to load. It displays a checklist of items that are being loaded. Examples:
|
|
39
|
+
* - Calling multiple slow APIs to load data
|
|
40
|
+
* - Loading results from AI
|
|
41
|
+
* - Processing a large amount of data as a queue (eg. bulk uploading or large media file uploads)
|
|
42
|
+
* - `page`: Loading pattern for a page, with out-of-the-box skeleton templates. Examples:
|
|
43
|
+
* - Dashboard page with multiple filters/panels
|
|
44
|
+
* - Search page with multiple filters and search results
|
|
45
|
+
* - Detail page for a record
|
|
46
|
+
* - Form page
|
|
47
|
+
* - Article page
|
|
48
|
+
* - `start-up`: Loading pattern when the application is first loaded. Examples:
|
|
49
|
+
* - Loading an application for the first time
|
|
50
|
+
* - Switching from a different application to a new application
|
|
51
|
+
* - Switching from a client's website to an Iress application
|
|
52
|
+
* - Switching themes
|
|
53
|
+
* - `validate`: Loading pattern when validating user input. Examples:
|
|
54
|
+
* - Submitting a form
|
|
55
|
+
* - Saving a record
|
|
56
|
+
*
|
|
57
|
+
* If no `pattern` is provided, it will use the default experience, which only displays a message after a certain amount of time to help stop drop-offs due to uncommon loading times.
|
|
58
|
+
*/
|
|
59
|
+
export declare const IressLoadingSuspense: {
|
|
60
|
+
({ children, delay: delayProp, onLoaded, pattern, startFrom: startFromProp, ...restProps }: IressLoadingSuspenseProps): import("react/jsx-runtime").JSX.Element;
|
|
61
|
+
/**
|
|
62
|
+
* A polyfill for the `use` hook in React 19. It allows you to suspend a component until the resource (Promise) is resolved.
|
|
63
|
+
* **Note:** For those using React 19, import the `use` hook from React instead of using this polyfill.
|
|
64
|
+
* @see https://react.dev/reference/react/use
|
|
65
|
+
*/
|
|
66
|
+
use: <T>(fetcher: () => Promise<T>) => T;
|
|
67
|
+
/**
|
|
68
|
+
* Uncache the resource (Promise) that is being used in the `use` hook.
|
|
69
|
+
* **Note:** For those using React 19, import the `use` hook from React instead of using this method.
|
|
70
|
+
* @see https://react.dev/reference/react/use
|
|
71
|
+
*/
|
|
72
|
+
uncache: (fetcher: () => Promise<unknown>, timeout?: number) => void;
|
|
73
|
+
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @param isLoaded - A boolean value that determines if the component waiting to be loaded has finished loading.
|
|
5
5
|
* @param delay - Once a component has loaded, how long should the loading indicator be displayed for. This is useful to allow the loading indicator to animate out.
|
|
6
6
|
* @param startFrom - If a component is still loading after this time in milliseconds, you should show the loading message. Default is 500ms, meaning a user will not even see the loading indicator if the page loads before this time.
|
|
7
|
+
* @param avoidDelayTimeout - If the component has a start up animation, this is the time in milliseconds that we will avoid the delay timeout for. This is useful to speed up the loading indicator removal if the component loaded before the first half of an animation finishes.
|
|
7
8
|
* @returns A boolean value that determines whether the `IressLoading` component should be rendered.
|
|
8
9
|
*/
|
|
9
|
-
export declare const useShouldRenderLoading: (isLoaded: boolean, delay?: number, startFrom?: number) => boolean;
|
|
10
|
+
export declare const useShouldRenderLoading: (isLoaded: boolean, delay?: number, startFrom?: number, avoidDelayTimeout?: number) => boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is a polyfill for the `use` hook in React 19, allowing you to suspend a component until the resource (Promise) is resolved.
|
|
3
|
+
* **Note:** For those using React 19, import the `use` hook from React instead of using this polyfill.
|
|
4
|
+
* @param promise The promise to suspend on. Once it resolves, the component will re-render with the resolved value.
|
|
5
|
+
* @returns {T | Error | Promise<void>} If the promise has not resolved, it will throw the promise, causing the component to suspend. If it has resolved successfully, it will return the result. If it has errored, it will throw the error.
|
|
6
|
+
* @see https://react.dev/reference/react/use
|
|
7
|
+
*/
|
|
8
|
+
export declare const useSuspenseResource: <T>(fetcher: () => Promise<T>) => T;
|
|
9
|
+
/**
|
|
10
|
+
* Our polyfill is not as smart as React's `use` hook, so we need to manually uncache the resource after a certain timeout.
|
|
11
|
+
* You usually need this if you are calling parameters with your `useSuspenseResource` hook (eg. `useSuspenseResource(() => fetch('/api/data'))`).
|
|
12
|
+
* **Note:** For those using React 19, import the `use` hook from React instead of using this polyfill.
|
|
13
|
+
* @param fetcher The function that returns a promise to suspend on (usually an API call).
|
|
14
|
+
* @param timeout The time in milliseconds after which the resource will be uncached. Default is 1000ms, usually enough to avoid flickering.
|
|
15
|
+
* @see https://react.dev/reference/react/use
|
|
16
|
+
*/
|
|
17
|
+
export declare const uncacheSuspenseResource: (fetcher: () => Promise<unknown>, timeout?: number) => void;
|