@iress-oss/ids-components 0.0.1-dev.1 → 0.0.1-dev.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.
@@ -0,0 +1,51 @@
1
+ import { jsxs as R, Fragment as v, jsx as r } from "react/jsx-runtime";
2
+ import { useMemo as a, useRef as C, useState as b, Suspense as k, useEffect as F } from "react";
3
+ import { Q as f } from "../../Loading-rKDsRTjZ.js";
4
+ import { useSuspenseResource as I, uncacheSuspenseResource as E } from "./hooks/useSuspenseResource.js";
5
+ const x = ({
6
+ children: s,
7
+ delay: l,
8
+ onLoaded: u,
9
+ pattern: e,
10
+ startFrom: c,
11
+ ...t
12
+ }) => {
13
+ const o = a(() => l || (e === "component" || e === "default" || e === "validate" ? 0 : e === "long" ? 1300 : 250), [l, e]), d = a(() => c || (e === "component" || e === "default" || e === "long" ? 0 : 250), [c, e]), m = C(!1), [n, j] = b(!1), h = f.shouldRender(n, o, d, 0), [i, S] = b(!1), g = () => {
14
+ m.current || (m.current = !0, j(() => !0), h ? setTimeout(() => {
15
+ S(!0), u == null || u();
16
+ }, o) : (S(!0), u == null || u()));
17
+ };
18
+ return e === "component" || e === "validate" ? /* @__PURE__ */ R(v, { children: [
19
+ /* @__PURE__ */ r(
20
+ f,
21
+ {
22
+ pattern: e,
23
+ loaded: n,
24
+ ...t,
25
+ children: i && s
26
+ }
27
+ ),
28
+ /* @__PURE__ */ r(k, { fallback: null, children: !i && /* @__PURE__ */ r(w, { onResolved: g, children: !n && s }) })
29
+ ] }) : /* @__PURE__ */ R(v, { children: [
30
+ h && /* @__PURE__ */ r(
31
+ f,
32
+ {
33
+ pattern: e,
34
+ loaded: n,
35
+ ...t
36
+ }
37
+ ),
38
+ /* @__PURE__ */ r(k, { fallback: null, children: i ? s : /* @__PURE__ */ r(w, { onResolved: g, children: !n && s }) })
39
+ ] });
40
+ };
41
+ x.use = I;
42
+ x.uncache = E;
43
+ const w = ({
44
+ onResolved: s,
45
+ children: l
46
+ }) => (F(() => {
47
+ s();
48
+ }, [s]), l);
49
+ export {
50
+ x as IressLoadingSuspense
51
+ };
@@ -1,20 +1,24 @@
1
- import { useState as c, useEffect as o } from "react";
2
- const m = (e, r = 500, u = 500) => {
3
- const [i, n] = c(!1);
4
- return o(() => {
5
- const t = setTimeout(() => {
6
- e || n(!0);
7
- }, u);
8
- return () => clearTimeout(t);
9
- }, [u, e]), o(() => {
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
- const t = setTimeout(() => {
13
- n(!1);
14
- }, r);
15
- return () => clearTimeout(t);
16
- }, [e, r]), e !== !0 || i;
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
- m as useShouldRenderLoading
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,74 @@
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
+ 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
+ };
74
+ export {};
@@ -6,4 +6,4 @@
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
7
  * @returns A boolean value that determines whether the `IressLoading` component should be rendered.
8
8
  */
9
- export declare const useShouldRenderLoading: (isLoaded: boolean, delay?: number, startFrom?: number) => boolean;
9
+ 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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iress-oss/ids-components",
3
- "version": "0.0.1-dev.1",
3
+ "version": "0.0.1-dev.2",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/"
6
6
  },