@alextheman/components 6.26.0 → 7.0.1
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 +1 -1
- package/dist/DropdownMenu/index.d.ts +126 -0
- package/dist/DropdownMenu/index.js +2 -0
- package/dist/DropdownMenu/index.js.map +1 -0
- package/dist/QueryBoundary/index.d.ts +288 -0
- package/dist/QueryBoundary/index.js +2 -0
- package/dist/QueryBoundary/index.js.map +1 -0
- package/dist/Tab/index.d.ts +103 -0
- package/dist/Tab/index.js +2 -0
- package/dist/Tab/index.js.map +1 -0
- package/dist/audio/index.d.ts +40 -0
- package/dist/audio/index.js +2 -0
- package/dist/audio/index.js.map +1 -0
- package/dist/file/index.d.ts +56 -0
- package/dist/file/index.js +2 -0
- package/dist/file/index.js.map +1 -0
- package/dist/index.d.ts +34 -876
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/routing/index.d.ts +170 -0
- package/dist/routing/index.js +2 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/snackbar/index.d.ts +55 -0
- package/dist/snackbar/index.js +2 -0
- package/dist/snackbar/index.js.map +1 -0
- package/dist/theme/index.d.ts +36 -0
- package/dist/theme/index.js +2 -0
- package/dist/theme/index.js.map +1 -0
- package/package.json +38 -13
- package/dist/index.cjs +0 -3
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -1026
- package/dist/v7/index.cjs +0 -2
- package/dist/v7/index.cjs.map +0 -1
- package/dist/v7/index.d.cts +0 -381
- package/dist/v7/index.d.ts +0 -381
- package/dist/v7/index.js +0 -2
- package/dist/v7/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://github.com/alextheman231/components/actions/workflows/ci.yml)
|
|
8
8
|
[](https://github.com/alextheman231/components/actions/workflows/publish.yml)
|
|
9
9
|
|
|
10
|
-
This is a React component library used across my projects. It is built with React and Material UI, and integrates with tools such as
|
|
10
|
+
This is a React component library used across my projects. It is built with React and Material UI, and integrates with tools such as Wouter and Tanstack Form.
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { MenuProps } from "@mui/material/Menu";
|
|
2
|
+
import { ComponentProps, ComponentPropsWithRef, ComponentPropsWithoutRef, ElementType, MouseEvent, ReactNode } from "react";
|
|
3
|
+
import { MenuItemOwnProps } from "@mui/material/MenuItem";
|
|
4
|
+
import Button, { ButtonOwnProps } from "@mui/material/Button";
|
|
5
|
+
import { OptionalOnCondition } from "@alextheman/utility";
|
|
6
|
+
|
|
7
|
+
//#region src/DropdownMenu/DropdownMenu.d.ts
|
|
8
|
+
interface DropdownMenuProps extends Omit<MenuProps, "anchorEl" | "open"> {
|
|
9
|
+
/** The children to render inside of the dropdown. */
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Renders a menu component that can be used alongside the `DropdownMenuProvider`.
|
|
14
|
+
*
|
|
15
|
+
* This component's open state would be controlled by the `DropdownMenuTrigger`.
|
|
16
|
+
*/
|
|
17
|
+
declare function DropdownMenu({
|
|
18
|
+
children,
|
|
19
|
+
onClose,
|
|
20
|
+
...menuProps
|
|
21
|
+
}: DropdownMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/DropdownMenu/DropdownMenuItem.d.ts
|
|
24
|
+
type DropdownMenuItemProps<RootComponent extends ElementType = typeof Button> = {
|
|
25
|
+
/**
|
|
26
|
+
* An optional component to provide to override the current component.
|
|
27
|
+
*
|
|
28
|
+
* Note that the provided component must:
|
|
29
|
+
* - accept a `to` prop.
|
|
30
|
+
* - correctly handle the forwarded `ref`.
|
|
31
|
+
* - render a valid anchor element (or equivalent) for proper accessibility.
|
|
32
|
+
*/
|
|
33
|
+
component?: RootComponent; /** The children to be rendered within the menu item. */
|
|
34
|
+
children?: ReactNode; /** The ref to forward to allow it to be used with polymorphic components */
|
|
35
|
+
ref?: ComponentPropsWithRef<RootComponent>["ref"]; /** A function to execute after clicking the item. */
|
|
36
|
+
onClick?: ComponentProps<RootComponent>["onClick"];
|
|
37
|
+
} & Omit<ComponentPropsWithoutRef<RootComponent>, "children" | "ref"> & MenuItemOwnProps;
|
|
38
|
+
/** Represents a menu item to be used inside the `DropdownMenu`. It must be used as children of the `DropdownMenu` component. */
|
|
39
|
+
declare function DropdownMenuItem<RootComponent extends ElementType = typeof Button>({
|
|
40
|
+
component,
|
|
41
|
+
children,
|
|
42
|
+
ref,
|
|
43
|
+
onClick,
|
|
44
|
+
...menuItemProps
|
|
45
|
+
}: DropdownMenuItemProps<RootComponent>): import("react/jsx-runtime").JSX.Element;
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/root/types/ContextHookOptions.d.ts
|
|
48
|
+
interface ContextHookOptions<Strict extends boolean = true> {
|
|
49
|
+
/** Error if the context is missing if this is set to true. */
|
|
50
|
+
strict?: Strict;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/DropdownMenu/DropdownMenuProvider.d.ts
|
|
54
|
+
interface DropdownMenuContextValue {
|
|
55
|
+
/** A function responsible for closing the dropdown menu. */
|
|
56
|
+
closeMenu: () => void;
|
|
57
|
+
/** Represents whether or not the dropdown is open. */
|
|
58
|
+
isDropdownOpen: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
Access the DropdownMenu context directly.
|
|
62
|
+
*/
|
|
63
|
+
declare function useDropdownMenuContext<Strict extends boolean = true>({
|
|
64
|
+
strict
|
|
65
|
+
}?: ContextHookOptions<Strict>): OptionalOnCondition<Strict, DropdownMenuContextValue>;
|
|
66
|
+
interface DropdownMenuProviderProps {
|
|
67
|
+
/** The children to render inside of the dropdown. */
|
|
68
|
+
children: ReactNode;
|
|
69
|
+
}
|
|
70
|
+
/** Provides shared context for the `DropdownMenu` related components. */
|
|
71
|
+
declare function DropdownMenuProvider({
|
|
72
|
+
children
|
|
73
|
+
}: DropdownMenuProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/DropdownMenu/DropdownMenuTrigger.d.ts
|
|
76
|
+
type DropdownMenuTriggerProps<RootComponent extends ElementType> = {
|
|
77
|
+
/**
|
|
78
|
+
* An optional component to provide to override the current component.
|
|
79
|
+
*
|
|
80
|
+
* Note that the provided component must:
|
|
81
|
+
* - accept a `to` prop.
|
|
82
|
+
* - correctly handle the forwarded `ref`.
|
|
83
|
+
* - render a valid anchor element (or equivalent) for proper accessibility.
|
|
84
|
+
*/
|
|
85
|
+
component?: RootComponent; /** A function to call whenever the trigger is clicked. */
|
|
86
|
+
onClick?: (event: MouseEvent<HTMLElement>) => void; /** The ref to forward to allow it to be used with polymorphic components */
|
|
87
|
+
ref?: ComponentPropsWithRef<RootComponent>["ref"]; /** The icon to display on the button when it is open. */
|
|
88
|
+
openIcon?: ElementType; /** The icon to display on the button when it is closed. */
|
|
89
|
+
closedIcon?: ElementType;
|
|
90
|
+
} & ComponentPropsWithoutRef<RootComponent> & Omit<ButtonOwnProps, "endIcon">;
|
|
91
|
+
/**
|
|
92
|
+
* Renders a component which, when clicked, opens the `DropdownMenu` in the current `DropdownMenuProvider`.
|
|
93
|
+
*
|
|
94
|
+
* Note that this component must be used in a `DropdownMenuProvider`. It will error in any other context.
|
|
95
|
+
*/
|
|
96
|
+
declare function DropdownMenuTrigger<RootComponent extends ElementType>({
|
|
97
|
+
component,
|
|
98
|
+
onClick,
|
|
99
|
+
openIcon: OpenIcon,
|
|
100
|
+
closedIcon: ClosedIcon,
|
|
101
|
+
variant,
|
|
102
|
+
...buttonProps
|
|
103
|
+
}: DropdownMenuTriggerProps<RootComponent>): import("react/jsx-runtime").JSX.Element;
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/DropdownMenu/DropdownMenuWrapper.d.ts
|
|
106
|
+
interface DropdownMenuWrapperProps {
|
|
107
|
+
/** The children to render inside of the dropdown. */
|
|
108
|
+
children: ReactNode;
|
|
109
|
+
/** The button component to be used as the dropdown toggle (defaults to a Material UI Button) */
|
|
110
|
+
trigger?: ElementType;
|
|
111
|
+
/** Props to pass to the Button. */
|
|
112
|
+
triggerProps?: Omit<DropdownMenuTriggerProps<ElementType>, "component">;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* An in-line component that manages the `DropdownMenuProvider` internally. You can just pass in the `DropdownMenuItem` components and it will work as is.
|
|
116
|
+
*
|
|
117
|
+
* This may be used over DropdownMenuProvider if you don't require as much control over the placement of each individual part of the dropdown.
|
|
118
|
+
*/
|
|
119
|
+
declare function DropdownMenuWrapper({
|
|
120
|
+
children,
|
|
121
|
+
trigger,
|
|
122
|
+
triggerProps
|
|
123
|
+
}: DropdownMenuWrapperProps): import("react/jsx-runtime").JSX.Element;
|
|
124
|
+
//#endregion
|
|
125
|
+
export { DropdownMenu, type DropdownMenuContextValue, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuProps, DropdownMenuProvider, type DropdownMenuProviderProps, DropdownMenuTrigger, type DropdownMenuTriggerProps, DropdownMenuWrapper, type DropdownMenuWrapperProps, useDropdownMenuContext };
|
|
126
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"@mui/material/Menu";import{DataError as t}from"@alextheman/utility/v6";import{createContext as n,use as r,useId as i,useState as a}from"react";import{jsx as o,jsxs as s}from"react/jsx-runtime";import c from"@mui/material/MenuItem";import l from"@mui/material/Button";import{MdArrowDropDown as u,MdArrowDropUp as d}from"react-icons/md";const f=n(void 0);function p({strict:e=!0}={}){let n=r(f);if(e&&!n)throw new t({strict:e,context:n},`DROPDOWN_MENU_NOT_FOUND`,`Could not find the DropdownMenu context. Please double-check that it is present.`);return n}function m({strict:e=!0}={}){return p({strict:e})}function h({children:e}){let[t,n]=a(null),r=i(),s=!!t;function c(){n(null)}return o(f,{value:{closeMenu:c,isDropdownOpen:s,anchorElement:t,setAnchorElement:n,menuId:r},children:e})}function g({children:t,onClose:n,...r}){let{anchorElement:i,isDropdownOpen:a,closeMenu:s,menuId:c}=m();return o(e,{id:c,anchorEl:i,open:a,onClose:(e,t)=>{e.defaultPrevented||s(),n&&n(e,t)},...r,children:t})}function _({component:e,children:t,ref:n,onClick:r,...i}){let{closeMenu:a}=p();return o(c,{component:e,ref:n,...i,onClick:e=>{r&&r(e),!e.defaultPrevented&&a()},children:t})}function v({component:e,onClick:t,openIcon:n=d,closedIcon:r=u,variant:i=`contained`,...a}){let{isDropdownOpen:s,setAnchorElement:c,menuId:f}=m();return o(l,{...e?{component:e}:{},"aria-controls":s?f:void 0,"aria-haspopup":`true`,"aria-expanded":s,endIcon:o(s?n:r,{}),variant:i,...a,onClick:e=>{t&&t(e),!e.defaultPrevented&&c(e.currentTarget)}})}function y({children:e,trigger:t,triggerProps:n}){return s(h,{children:[o(v,{component:t,...n,children:n?.children??`Menu`}),o(g,{children:e})]})}export{g as DropdownMenu,_ as DropdownMenuItem,h as DropdownMenuProvider,v as DropdownMenuTrigger,y as DropdownMenuWrapper,p as useDropdownMenuContext};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/DropdownMenu/DropdownMenuProvider.tsx","../../src/DropdownMenu/DropdownMenu.tsx","../../src/DropdownMenu/DropdownMenuItem.tsx","../../src/DropdownMenu/DropdownMenuTrigger.tsx","../../src/DropdownMenu/DropdownMenuWrapper.tsx"],"sourcesContent":["import type { OptionalOnCondition } from \"@alextheman/utility\";\nimport type { Dispatch, ReactNode, SetStateAction } from \"react\";\n\nimport type { ContextHookOptions } from \"src/root/types\";\n\nimport { DataError } from \"@alextheman/utility/v6\";\nimport { createContext, use, useId, useState } from \"react\";\n\nexport interface DropdownMenuContextValue {\n /** A function responsible for closing the dropdown menu. */\n closeMenu: () => void;\n /** Represents whether or not the dropdown is open. */\n isDropdownOpen: boolean;\n}\n\nexport type DropdownMenuInternalContextValue = DropdownMenuContextValue & {\n anchorElement: HTMLElement | null;\n setAnchorElement: Dispatch<SetStateAction<HTMLElement | null>>;\n menuId: string;\n};\nconst DropdownMenuContext = createContext<DropdownMenuInternalContextValue | undefined>(undefined);\n\n/**\n Access the DropdownMenu context directly.\n */\nexport function useDropdownMenuContext<Strict extends boolean = true>({\n strict = true as Strict,\n}: ContextHookOptions<Strict> = {}): OptionalOnCondition<Strict, DropdownMenuContextValue> {\n const context = use(DropdownMenuContext);\n if (strict && !context) {\n throw new DataError(\n { strict, context },\n \"DROPDOWN_MENU_NOT_FOUND\",\n \"Could not find the DropdownMenu context. Please double-check that it is present.\",\n );\n }\n return context as OptionalOnCondition<Strict, DropdownMenuContextValue>;\n}\n\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport function useDropdownMenuContextInternal<Strict extends boolean = true>({\n strict = true as Strict,\n}: ContextHookOptions<Strict> = {}): OptionalOnCondition<Strict, DropdownMenuInternalContextValue> {\n return useDropdownMenuContext({ strict }) as OptionalOnCondition<\n Strict,\n DropdownMenuInternalContextValue\n >;\n}\n\nexport interface DropdownMenuProviderProps {\n /** The children to render inside of the dropdown. */\n children: ReactNode;\n}\n\n/** Provides shared context for the `DropdownMenu` related components. */\nfunction DropdownMenuProvider({ children }: DropdownMenuProviderProps) {\n const [anchorElement, setAnchorElement] = useState<HTMLElement | null>(null);\n const menuId = useId();\n const isDropdownOpen = Boolean(anchorElement);\n\n function closeMenu() {\n setAnchorElement(null);\n }\n\n return (\n <DropdownMenuContext\n value={{ closeMenu, isDropdownOpen, anchorElement, setAnchorElement, menuId }}\n >\n {children}\n </DropdownMenuContext>\n );\n}\n\nexport default DropdownMenuProvider;\n","import type { MenuProps } from \"@mui/material/Menu\";\nimport type { MouseEvent, ReactNode } from \"react\";\n\nimport Menu from \"@mui/material/Menu\";\n\nimport { useDropdownMenuContextInternal } from \"src/DropdownMenu/DropdownMenuProvider\";\n\nexport interface DropdownMenuProps extends Omit<MenuProps, \"anchorEl\" | \"open\"> {\n /** The children to render inside of the dropdown. */\n children: ReactNode;\n}\n\n/**\n * Renders a menu component that can be used alongside the `DropdownMenuProvider`.\n *\n * This component's open state would be controlled by the `DropdownMenuTrigger`.\n */\nfunction DropdownMenu({ children, onClose, ...menuProps }: DropdownMenuProps) {\n const { anchorElement, isDropdownOpen, closeMenu, menuId } = useDropdownMenuContextInternal();\n\n return (\n <Menu\n id={menuId}\n anchorEl={anchorElement}\n open={isDropdownOpen}\n onClose={(event: MouseEvent, reason) => {\n if (!event.defaultPrevented) {\n closeMenu();\n }\n if (onClose) {\n onClose(event, reason);\n }\n }}\n {...menuProps}\n >\n {children}\n </Menu>\n );\n}\n\nexport default DropdownMenu;\n","import type Button from \"@mui/material/Button\";\nimport type { MenuItemOwnProps } from \"@mui/material/MenuItem\";\nimport type {\n ComponentProps,\n ComponentPropsWithoutRef,\n ComponentPropsWithRef,\n ElementType,\n ReactNode,\n} from \"react\";\n\nimport MenuItem from \"@mui/material/MenuItem\";\n\nimport { useDropdownMenuContext } from \"src/DropdownMenu/DropdownMenuProvider\";\n\nexport type DropdownMenuItemProps<RootComponent extends ElementType = typeof Button> = {\n /**\n * An optional component to provide to override the current component.\n *\n * Note that the provided component must:\n * - accept a `to` prop.\n * - correctly handle the forwarded `ref`.\n * - render a valid anchor element (or equivalent) for proper accessibility.\n */\n component?: RootComponent;\n /** The children to be rendered within the menu item. */\n children?: ReactNode;\n /** The ref to forward to allow it to be used with polymorphic components */\n ref?: ComponentPropsWithRef<RootComponent>[\"ref\"];\n /** A function to execute after clicking the item. */\n onClick?: ComponentProps<RootComponent>[\"onClick\"];\n} & Omit<ComponentPropsWithoutRef<RootComponent>, \"children\" | \"ref\"> &\n MenuItemOwnProps;\n\n/** Represents a menu item to be used inside the `DropdownMenu`. It must be used as children of the `DropdownMenu` component. */\nfunction DropdownMenuItem<RootComponent extends ElementType = typeof Button>({\n component,\n children,\n ref,\n onClick,\n ...menuItemProps\n}: DropdownMenuItemProps<RootComponent>) {\n const { closeMenu } = useDropdownMenuContext();\n\n return (\n <MenuItem\n component={component}\n ref={ref}\n {...menuItemProps}\n onClick={(event) => {\n if (onClick) {\n onClick(event);\n }\n if (event.defaultPrevented) {\n return;\n }\n closeMenu();\n }}\n >\n {children}\n </MenuItem>\n );\n}\n\nexport default DropdownMenuItem;\n","import type { ButtonOwnProps } from \"@mui/material/Button\";\nimport type {\n ComponentPropsWithoutRef,\n ComponentPropsWithRef,\n ElementType,\n MouseEvent,\n} from \"react\";\n\nimport Button from \"@mui/material/Button\";\nimport { MdArrowDropDown, MdArrowDropUp } from \"react-icons/md\";\n\nimport { useDropdownMenuContextInternal } from \"src/DropdownMenu/DropdownMenuProvider\";\n\nexport type DropdownMenuTriggerProps<RootComponent extends ElementType> = {\n /**\n * An optional component to provide to override the current component.\n *\n * Note that the provided component must:\n * - accept a `to` prop.\n * - correctly handle the forwarded `ref`.\n * - render a valid anchor element (or equivalent) for proper accessibility.\n */\n component?: RootComponent;\n /** A function to call whenever the trigger is clicked. */\n onClick?: (event: MouseEvent<HTMLElement>) => void;\n /** The ref to forward to allow it to be used with polymorphic components */\n ref?: ComponentPropsWithRef<RootComponent>[\"ref\"];\n /** The icon to display on the button when it is open. */\n openIcon?: ElementType;\n /** The icon to display on the button when it is closed. */\n closedIcon?: ElementType;\n} & ComponentPropsWithoutRef<RootComponent> &\n Omit<ButtonOwnProps, \"endIcon\">;\n\n/**\n * Renders a component which, when clicked, opens the `DropdownMenu` in the current `DropdownMenuProvider`.\n *\n * Note that this component must be used in a `DropdownMenuProvider`. It will error in any other context.\n */\nfunction DropdownMenuTrigger<RootComponent extends ElementType>({\n component,\n onClick,\n openIcon: OpenIcon = MdArrowDropUp,\n closedIcon: ClosedIcon = MdArrowDropDown,\n variant = \"contained\",\n ...buttonProps\n}: DropdownMenuTriggerProps<RootComponent>) {\n const { isDropdownOpen, setAnchorElement, menuId } = useDropdownMenuContextInternal();\n\n return (\n <Button\n {...(component ? { component } : {})}\n aria-controls={isDropdownOpen ? menuId : undefined}\n aria-haspopup=\"true\"\n aria-expanded={isDropdownOpen}\n endIcon={isDropdownOpen ? <OpenIcon /> : <ClosedIcon />}\n variant={variant}\n {...buttonProps}\n onClick={(event: MouseEvent<HTMLElement>) => {\n if (onClick) {\n onClick(event);\n }\n if (event.defaultPrevented) {\n return;\n }\n setAnchorElement(event.currentTarget);\n }}\n />\n );\n}\n\nexport default DropdownMenuTrigger;\n","import type { ElementType, ReactNode } from \"react\";\n\nimport type { DropdownMenuTriggerProps } from \"src/DropdownMenu/DropdownMenuTrigger\";\n\nimport DropdownMenu from \"src/DropdownMenu/DropdownMenu\";\nimport DropdownMenuProvider from \"src/DropdownMenu/DropdownMenuProvider\";\nimport DropdownMenuTrigger from \"src/DropdownMenu/DropdownMenuTrigger\";\n\nexport interface DropdownMenuWrapperProps {\n /** The children to render inside of the dropdown. */\n children: ReactNode;\n /** The button component to be used as the dropdown toggle (defaults to a Material UI Button) */\n trigger?: ElementType;\n /** Props to pass to the Button. */\n triggerProps?: Omit<DropdownMenuTriggerProps<ElementType>, \"component\">;\n}\n\n/**\n * An in-line component that manages the `DropdownMenuProvider` internally. You can just pass in the `DropdownMenuItem` components and it will work as is.\n *\n * This may be used over DropdownMenuProvider if you don't require as much control over the placement of each individual part of the dropdown.\n */\nfunction DropdownMenuWrapper({ children, trigger, triggerProps }: DropdownMenuWrapperProps) {\n return (\n <DropdownMenuProvider>\n <DropdownMenuTrigger component={trigger} {...triggerProps}>\n {triggerProps?.children ?? \"Menu\"}\n </DropdownMenuTrigger>\n <DropdownMenu>{children}</DropdownMenu>\n </DropdownMenuProvider>\n );\n}\n\nexport default DropdownMenuWrapper;\n"],"mappings":"6VAoBA,MAAM,EAAsB,EAA4D,IAAA,EAAS,EAKjG,SAAgB,EAAsD,CACpE,SAAS,IACqB,CAAC,EAA0D,CACzF,IAAM,EAAU,EAAI,CAAmB,EACvC,GAAI,GAAU,CAAC,EACb,MAAM,IAAI,EACR,CAAE,SAAQ,SAAQ,EAClB,0BACA,kFACF,EAEF,OAAO,CACT,CAGA,SAAgB,EAA8D,CAC5E,SAAS,IACqB,CAAC,EAAkE,CACjG,OAAO,EAAuB,CAAE,QAAO,CAAC,CAI1C,CAQA,SAAS,EAAqB,CAAE,YAAuC,CACrE,GAAM,CAAC,EAAe,GAAoB,EAA6B,IAAI,EACrE,EAAS,EAAM,EACf,EAAiB,EAAQ,EAE/B,SAAS,GAAY,CACnB,EAAiB,IAAI,CACvB,CAEA,OACE,EAAC,EAAD,CACE,MAAO,CAAE,YAAW,iBAAgB,gBAAe,mBAAkB,QAAO,EAE3E,UACkB,CAAA,CAEzB,CCtDA,SAAS,EAAa,CAAE,WAAU,UAAS,GAAG,GAAgC,CAC5E,GAAM,CAAE,gBAAe,iBAAgB,YAAW,UAAW,EAA+B,EAE5F,OACE,EAAC,EAAD,CACE,GAAI,EACJ,SAAU,EACV,KAAM,EACN,SAAU,EAAmB,IAAW,CACjC,EAAM,kBACT,EAAU,EAER,GACF,EAAQ,EAAO,CAAM,CAEzB,EACA,GAAI,EAEH,UACG,CAAA,CAEV,CCJA,SAAS,EAAoE,CAC3E,YACA,WACA,MACA,UACA,GAAG,GACoC,CACvC,GAAM,CAAE,aAAc,EAAuB,EAE7C,OACE,EAAC,EAAD,CACa,YACN,MACL,GAAI,EACJ,QAAU,GAAU,CACd,GACF,EAAQ,CAAK,EAEX,GAAM,kBAGV,EAAU,CACZ,EAEC,UACO,CAAA,CAEd,CCtBA,SAAS,EAAuD,CAC9D,YACA,UACA,SAAU,EAAW,EACrB,WAAY,EAAa,EACzB,UAAU,YACV,GAAG,GACuC,CAC1C,GAAM,CAAE,iBAAgB,mBAAkB,UAAW,EAA+B,EAEpF,OACE,EAAC,EAAD,CACE,GAAK,EAAY,CAAE,WAAU,EAAI,CAAC,EAClC,gBAAe,EAAiB,EAAS,IAAA,GACzC,gBAAc,OACd,gBAAe,EACf,QAA0B,EAAjB,EAAkB,EAAe,EAAhB,CAAW,CAAiB,EAC7C,UACT,GAAI,EACJ,QAAU,GAAmC,CACvC,GACF,EAAQ,CAAK,EAEX,GAAM,kBAGV,EAAiB,EAAM,aAAa,CACtC,CACD,CAAA,CAEL,CC/CA,SAAS,EAAoB,CAAE,WAAU,UAAS,gBAA0C,CAC1F,OACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAqB,UAAW,EAAS,GAAI,WAC1C,GAAc,UAAY,MACR,CAAA,EACrB,EAAC,EAAD,CAAe,UAAuB,CAAA,CAClB,CAAA,CAAA,CAE1B"}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { JSX, Key, ReactNode } from "react";
|
|
2
|
+
import { OptionalOnCondition } from "@alextheman/utility";
|
|
3
|
+
|
|
4
|
+
//#region src/QueryBoundary/QueryBoundaryData.d.ts
|
|
5
|
+
interface QueryBoundaryDataProps<DataType> {
|
|
6
|
+
/**
|
|
7
|
+
* The elements to show after data has been loaded.
|
|
8
|
+
* This is best provided as a function with a data argument that guarantees the data will not be undefined by the time you receive it here.
|
|
9
|
+
*/
|
|
10
|
+
children: ReactNode | ((data: NonNullable<DataType>) => ReactNode);
|
|
11
|
+
/** A parser for the data. */
|
|
12
|
+
dataParser?: (data: unknown) => NonNullable<DataType>;
|
|
13
|
+
/** The component to show when the data is being fetched. */
|
|
14
|
+
loadingFallback?: ReactNode;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The component responsible for showing the data provided by QueryBoundaryProvider.
|
|
18
|
+
*
|
|
19
|
+
* @template DataType - The type of data being loaded.
|
|
20
|
+
*/
|
|
21
|
+
declare function QueryBoundaryData<DataType>({
|
|
22
|
+
children,
|
|
23
|
+
dataParser,
|
|
24
|
+
loadingFallback
|
|
25
|
+
}: QueryBoundaryDataProps<DataType>): import("react/jsx-runtime").JSX.Element | null;
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/QueryBoundary/QueryBoundaryDataMap.d.ts
|
|
28
|
+
interface QueryBoundaryDataMapBaseProps<ItemType> {
|
|
29
|
+
/**
|
|
30
|
+
* The elements to show after data has been loaded.
|
|
31
|
+
*
|
|
32
|
+
* This is best provided as a function with a data argument that guarantees the data will not be undefined by the time you receive it here.
|
|
33
|
+
*/
|
|
34
|
+
children: ReactNode | ((data: ItemType) => ReactNode);
|
|
35
|
+
/** The component to show when the data is being fetched. */
|
|
36
|
+
loadingFallback?: ReactNode;
|
|
37
|
+
/** The component to show if the array is empty. */
|
|
38
|
+
emptyFallback?: ReactNode;
|
|
39
|
+
/** Throw an error if the provided data is not an array. (defaults to `true`) */
|
|
40
|
+
strictlyRequireArray?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* A function that takes a data item and returns the key to be used for the item.
|
|
43
|
+
*
|
|
44
|
+
* If not provided, it will fall back to using the index.
|
|
45
|
+
*/
|
|
46
|
+
itemKey?: (item: ItemType, index: number) => Key;
|
|
47
|
+
}
|
|
48
|
+
interface QueryBoundaryDataMapPropsWithItemParser<ItemType> extends QueryBoundaryDataMapBaseProps<ItemType> {
|
|
49
|
+
/** A parser for each data item. */
|
|
50
|
+
itemParser: (data: unknown) => ItemType;
|
|
51
|
+
dataParser?: never;
|
|
52
|
+
}
|
|
53
|
+
interface QueryBoundaryDataMapPropsWithDataParser<ItemType> extends QueryBoundaryDataMapBaseProps<ItemType> {
|
|
54
|
+
/** A parser for each data item. */
|
|
55
|
+
dataParser: (data: unknown) => Array<ItemType>;
|
|
56
|
+
itemParser?: never;
|
|
57
|
+
}
|
|
58
|
+
interface QueryBoundaryDataMapPropsWithNoParser<ItemType> extends QueryBoundaryDataMapBaseProps<ItemType> {
|
|
59
|
+
dataParser?: never;
|
|
60
|
+
itemParser?: never;
|
|
61
|
+
}
|
|
62
|
+
type QueryBoundaryDataMapProps<ItemType> = QueryBoundaryDataMapPropsWithItemParser<ItemType> | QueryBoundaryDataMapPropsWithDataParser<ItemType> | QueryBoundaryDataMapPropsWithNoParser<ItemType>;
|
|
63
|
+
/**
|
|
64
|
+
* The component responsible for handling an array of data provided by `QueryBoundaryProvider`.
|
|
65
|
+
*
|
|
66
|
+
* It will map through the data array, rendering the result of the children function in a fragment with a key of its index in the list, unless overridden by the `itemKey` prop.
|
|
67
|
+
*
|
|
68
|
+
* @template ItemType - The type of data being loaded.
|
|
69
|
+
*
|
|
70
|
+
* @throws {DataError} If the data provided by `QueryBoundaryProvider` is not an array, and the `strictlyRequireArray` prop is `true` (it is by default).
|
|
71
|
+
*/
|
|
72
|
+
declare function QueryBoundaryDataMap<ItemType>({
|
|
73
|
+
children,
|
|
74
|
+
loadingFallback,
|
|
75
|
+
itemKey,
|
|
76
|
+
itemParser,
|
|
77
|
+
dataParser,
|
|
78
|
+
emptyFallback,
|
|
79
|
+
strictlyRequireArray
|
|
80
|
+
}: QueryBoundaryDataMapProps<ItemType>): import("react/jsx-runtime").JSX.Element | null;
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/QueryBoundary/QueryBoundaryError.d.ts
|
|
83
|
+
interface QueryBoundaryErrorProps {
|
|
84
|
+
/** The component to show if an error has been thrown. */
|
|
85
|
+
children?: ReactNode | ((error: unknown) => ReactNode);
|
|
86
|
+
/** An option to log the error to the console. */
|
|
87
|
+
logError?: boolean;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The component responsible for showing any errors provided by QueryBoundaryProvider.
|
|
91
|
+
*/
|
|
92
|
+
declare function QueryBoundaryError({
|
|
93
|
+
children,
|
|
94
|
+
logError
|
|
95
|
+
}: QueryBoundaryErrorProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/QueryBoundary/QueryBoundaryNullable.d.ts
|
|
98
|
+
interface QueryBoundaryNullablePropsWithUndefinedOrNull {
|
|
99
|
+
/** The component to show if no error was thrown but data is undefined */
|
|
100
|
+
undefinedFallback?: ReactNode;
|
|
101
|
+
/** The component to show if no error was thrown but data is null */
|
|
102
|
+
nullFallback?: ReactNode;
|
|
103
|
+
nullableFallback?: never;
|
|
104
|
+
}
|
|
105
|
+
interface QueryBoundaryNullablePropsWithNullable {
|
|
106
|
+
undefinedFallback?: never;
|
|
107
|
+
nullFallback?: never;
|
|
108
|
+
/** The component to show if no error was thrown but data is undefined or null */
|
|
109
|
+
nullableFallback?: ReactNode;
|
|
110
|
+
}
|
|
111
|
+
type QueryBoundaryNullableProps = QueryBoundaryNullablePropsWithUndefinedOrNull | QueryBoundaryNullablePropsWithNullable;
|
|
112
|
+
/** The component responsible for handling cases when the data provided by `QueryBoundaryProvider` may be missing. */
|
|
113
|
+
declare function QueryBoundaryNullable({
|
|
114
|
+
undefinedFallback,
|
|
115
|
+
nullFallback,
|
|
116
|
+
nullableFallback
|
|
117
|
+
}: QueryBoundaryNullableProps): import("react/jsx-runtime").JSX.Element | null;
|
|
118
|
+
//#endregion
|
|
119
|
+
//#region src/QueryBoundary/QueryBoundaryFallback.d.ts
|
|
120
|
+
type QueryBoundaryFallbackProps = Omit<QueryBoundaryErrorProps, "children"> & {
|
|
121
|
+
/** The component to show if an error has been thrown. */errorFallback?: ReactNode | ((error: unknown) => ReactNode);
|
|
122
|
+
} & QueryBoundaryNullableProps;
|
|
123
|
+
/**
|
|
124
|
+
* The component responsible for handling both errors and nullable data from `QueryBoundaryProvider`
|
|
125
|
+
*/
|
|
126
|
+
declare function QueryBoundaryFallback({
|
|
127
|
+
errorFallback,
|
|
128
|
+
logError,
|
|
129
|
+
...queryBoundaryNullableProps
|
|
130
|
+
}: QueryBoundaryFallbackProps): import("react/jsx-runtime").JSX.Element;
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/root/types/ContextHookOptions.d.ts
|
|
133
|
+
interface ContextHookOptions<Strict extends boolean = true> {
|
|
134
|
+
/** Error if the context is missing if this is set to true. */
|
|
135
|
+
strict?: Strict;
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/QueryBoundary/QueryBoundaryProvider.d.ts
|
|
139
|
+
interface QueryBoundaryContextValue<DataType> {
|
|
140
|
+
/** The current loading status (true if loading, false if not) */
|
|
141
|
+
isLoading?: boolean;
|
|
142
|
+
/** The data being loaded. */
|
|
143
|
+
data?: DataType | null | undefined;
|
|
144
|
+
/** The error given if the request gave an error. */
|
|
145
|
+
error: unknown;
|
|
146
|
+
}
|
|
147
|
+
type QueryBoundaryProviderProps<DataType> = QueryBoundaryContextValue<DataType> & {
|
|
148
|
+
children: ReactNode;
|
|
149
|
+
};
|
|
150
|
+
/** Access the QueryBoundary context directly. */
|
|
151
|
+
declare function useQueryBoundaryContext<DataType, Strict extends boolean = true>({
|
|
152
|
+
strict
|
|
153
|
+
}?: ContextHookOptions<Strict>): OptionalOnCondition<Strict, QueryBoundaryContextValue<DataType>>;
|
|
154
|
+
/**
|
|
155
|
+
* A provider for a context that deals with state management when fetching data from an API.
|
|
156
|
+
* This may be used over QueryBoundary if you require more control over the placement of the error message and data display.
|
|
157
|
+
*
|
|
158
|
+
* @template DataType - The type of data being loaded.
|
|
159
|
+
*/
|
|
160
|
+
declare function QueryBoundaryProvider<DataType>({
|
|
161
|
+
children,
|
|
162
|
+
...contextProps
|
|
163
|
+
}: QueryBoundaryProviderProps<DataType>): import("react/jsx-runtime").JSX.Element;
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/QueryBoundary/QueryBoundaryItemWrapper.d.ts
|
|
166
|
+
type QueryBoundaryItemWrapperProps<DataType> = QueryBoundaryContextValue<DataType> & QueryBoundaryFallbackProps & QueryBoundaryDataProps<DataType>;
|
|
167
|
+
/**
|
|
168
|
+
* An in-line component that deals with state management when fetching data from an API.
|
|
169
|
+
* This may be used over QueryBoundaryProvider if you don't require as much control over the placement of the error message and data display.
|
|
170
|
+
*
|
|
171
|
+
* @template DataType - The type of data being loaded.
|
|
172
|
+
*/
|
|
173
|
+
declare function QueryBoundaryItemWrapper<DataType>({
|
|
174
|
+
children,
|
|
175
|
+
errorFallback,
|
|
176
|
+
undefinedFallback,
|
|
177
|
+
nullFallback,
|
|
178
|
+
nullableFallback,
|
|
179
|
+
logError,
|
|
180
|
+
loadingFallback,
|
|
181
|
+
isLoading,
|
|
182
|
+
error,
|
|
183
|
+
data,
|
|
184
|
+
dataParser
|
|
185
|
+
}: QueryBoundaryItemWrapperProps<DataType>): import("react/jsx-runtime").JSX.Element;
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region src/QueryBoundary/QueryBoundaryListWrapper.d.ts
|
|
188
|
+
type QueryBoundaryListWrapperProps<ItemType> = QueryBoundaryContextValue<Array<ItemType>> & QueryBoundaryFallbackProps & QueryBoundaryDataMapProps<ItemType>;
|
|
189
|
+
/**
|
|
190
|
+
* An in-line component that handles an array of data provided by `QueryBoundaryProvider`.
|
|
191
|
+
*
|
|
192
|
+
* This may be used over QueryBoundaryProvider/QueryBoundaryDataMap if you don't require as much control over the placement of the error message and data display.
|
|
193
|
+
*
|
|
194
|
+
* @template DataType - The type of data being loaded.
|
|
195
|
+
*/
|
|
196
|
+
declare function QueryBoundaryListWrapper<ItemType>({
|
|
197
|
+
loadingFallback,
|
|
198
|
+
undefinedFallback,
|
|
199
|
+
nullFallback,
|
|
200
|
+
nullableFallback,
|
|
201
|
+
logError,
|
|
202
|
+
errorFallback,
|
|
203
|
+
children,
|
|
204
|
+
isLoading,
|
|
205
|
+
error,
|
|
206
|
+
data,
|
|
207
|
+
dataParser,
|
|
208
|
+
itemParser,
|
|
209
|
+
itemKey
|
|
210
|
+
}: QueryBoundaryListWrapperProps<ItemType>): import("react/jsx-runtime").JSX.Element;
|
|
211
|
+
//#endregion
|
|
212
|
+
//#region src/QueryBoundary/creators/createBaseQueryBoundary.d.ts
|
|
213
|
+
interface QueryBase<DataType> {
|
|
214
|
+
/** The current loading status (true if loading, false if not) */
|
|
215
|
+
isLoading?: boolean;
|
|
216
|
+
/** The error given if the response gave an error. */
|
|
217
|
+
error?: unknown;
|
|
218
|
+
/** The data being loaded. */
|
|
219
|
+
data: DataType;
|
|
220
|
+
}
|
|
221
|
+
interface CreateBaseQueryBoundaryParameters<DataType> {
|
|
222
|
+
query: QueryBase<DataType>;
|
|
223
|
+
}
|
|
224
|
+
interface DefaultQueryBoundaryComponentsBase {
|
|
225
|
+
/** Provides the context for the query boundary. */
|
|
226
|
+
Context: (props: {
|
|
227
|
+
children: ReactNode;
|
|
228
|
+
}) => JSX.Element;
|
|
229
|
+
/** The component responsible for showing any errors provided by `QueryBoundary.Context`. */
|
|
230
|
+
Error: typeof QueryBoundaryError;
|
|
231
|
+
/** The component responsible for handling cases when the data provided by `QueryBoundary.Context` may be missing. */
|
|
232
|
+
Fallback: typeof QueryBoundaryFallback;
|
|
233
|
+
/** The component responsible for handling both errors and nullable data from `QueryBoundary.Context`*/
|
|
234
|
+
Nullable: typeof QueryBoundaryNullable;
|
|
235
|
+
}
|
|
236
|
+
/** A creator function to create the base system of QueryBoundary components with the data fully typed throughout. */
|
|
237
|
+
declare function createBaseQueryBoundary<DataType>({
|
|
238
|
+
query
|
|
239
|
+
}: CreateBaseQueryBoundaryParameters<DataType>): DefaultQueryBoundaryComponentsBase;
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region src/QueryBoundary/creators/createItemQueryBoundary.d.ts
|
|
242
|
+
interface QueryItem<DataType> extends Omit<QueryBase<DataType>, "data"> {
|
|
243
|
+
/** The data being loaded. */
|
|
244
|
+
data: DataType | null | undefined;
|
|
245
|
+
}
|
|
246
|
+
interface CreateItemQueryBoundaryParameters<DataType> {
|
|
247
|
+
query: QueryItem<DataType>;
|
|
248
|
+
}
|
|
249
|
+
interface DefaultQueryBoundaryItemComponents<DataType> extends DefaultQueryBoundaryComponentsBase {
|
|
250
|
+
/**
|
|
251
|
+
* The component responsible for showing the data provided by `QueryBoundary.Context`.
|
|
252
|
+
*
|
|
253
|
+
* @template DataType - The type of data being loaded.
|
|
254
|
+
*/
|
|
255
|
+
Data: typeof QueryBoundaryData<DataType>;
|
|
256
|
+
}
|
|
257
|
+
/** A creator function to create the system of QueryBoundary components with the data treated as a single data item, fully typed throughout. */
|
|
258
|
+
declare function createItemQueryBoundary<DataType>({
|
|
259
|
+
query
|
|
260
|
+
}: CreateItemQueryBoundaryParameters<DataType>): DefaultQueryBoundaryItemComponents<DataType>;
|
|
261
|
+
//#endregion
|
|
262
|
+
//#region src/QueryBoundary/creators/createListQueryBoundary.d.ts
|
|
263
|
+
interface QueryList<DataType> extends Omit<QueryBase<DataType>, "data"> {
|
|
264
|
+
/** The data being loaded. */
|
|
265
|
+
data: Array<DataType> | null | undefined;
|
|
266
|
+
}
|
|
267
|
+
interface CreateListQueryBoundaryParameters<DataType> {
|
|
268
|
+
query: QueryList<DataType>;
|
|
269
|
+
}
|
|
270
|
+
interface DefaultQueryBoundaryListComponents<DataType> extends DefaultQueryBoundaryComponentsBase {
|
|
271
|
+
/**
|
|
272
|
+
* The component responsible for handling an array of data provided by `QueryBoundary.Context`.
|
|
273
|
+
*
|
|
274
|
+
* It will map through the data array, rendering the result of the children function in a fragment with a key of its index in the list, unless overridden by the `itemKey` prop.
|
|
275
|
+
*
|
|
276
|
+
* @template ItemType - The type of data being loaded.
|
|
277
|
+
*
|
|
278
|
+
* @throws {DataError} If the data provided by `QueryBoundary.Context` is not an array, and the `strictlyRequireArray` prop is `true` (it is by default).
|
|
279
|
+
*/
|
|
280
|
+
DataMap: typeof QueryBoundaryDataMap<DataType>;
|
|
281
|
+
}
|
|
282
|
+
/** A creator function to create the system of QueryBoundary components with the data treated as an array of data items, fully typed throughout. */
|
|
283
|
+
declare function createListQueryBoundary<DataType>({
|
|
284
|
+
query
|
|
285
|
+
}: CreateListQueryBoundaryParameters<DataType>): DefaultQueryBoundaryListComponents<DataType>;
|
|
286
|
+
//#endregion
|
|
287
|
+
export { type CreateBaseQueryBoundaryParameters, type CreateItemQueryBoundaryParameters, type CreateListQueryBoundaryParameters, type DefaultQueryBoundaryComponentsBase, type DefaultQueryBoundaryItemComponents, type DefaultQueryBoundaryListComponents, type QueryBase, type QueryBoundaryContextValue, QueryBoundaryData, QueryBoundaryDataMap, type QueryBoundaryDataMapBaseProps, type QueryBoundaryDataMapProps, type QueryBoundaryDataMapPropsWithDataParser, type QueryBoundaryDataMapPropsWithItemParser, type QueryBoundaryDataMapPropsWithNoParser, type QueryBoundaryDataProps, QueryBoundaryError, type QueryBoundaryErrorProps, QueryBoundaryFallback, type QueryBoundaryFallbackProps, QueryBoundaryItemWrapper, type QueryBoundaryItemWrapperProps, QueryBoundaryListWrapper, type QueryBoundaryListWrapperProps, QueryBoundaryNullable, type QueryBoundaryNullableProps, type QueryBoundaryNullablePropsWithNullable, type QueryBoundaryNullablePropsWithUndefinedOrNull, QueryBoundaryProvider, type QueryBoundaryProviderProps, type QueryItem, type QueryList, createBaseQueryBoundary, createItemQueryBoundary, createListQueryBoundary, useQueryBoundaryContext };
|
|
288
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"@mui/material/CircularProgress";import{DataError as t}from"@alextheman/utility/v6";import{Fragment as n,createContext as r,use as i,useRef as a}from"react";import{Fragment as o,jsx as s,jsxs as c}from"react/jsx-runtime";import l from"@mui/material/Typography";import u from"@mui/material/Alert";const d=r(void 0);function f({strict:e=!0}={}){let n=i(d);if(e&&!n)throw new t({strict:e,context:n},`QUERY_BOUNDARY_PROVIDER_NOT_FOUND`,`Could not find the QueryBoundaryProvider context. Please double-check that it is present.`);return n}function p({children:e,...t}){return s(d,{value:t,children:e})}function m({children:t,dataParser:n,loadingFallback:r=s(e,{})}){let{isLoading:i,data:a,error:c}=f();return c?null:i?s(o,{children:r}):a==null?null:s(o,{children:typeof t==`function`?t(n?n(a):a):t})}function h({children:r,loadingFallback:i=s(e,{}),itemKey:a,itemParser:c,dataParser:u,emptyFallback:d=s(l,{children:`No data present`}),strictlyRequireArray:p=!0}){let{isLoading:m,data:h,error:g}=f();if(m)return s(o,{children:i});if(g||h==null)return null;if(!Array.isArray(h)){if(p)throw new t({data:h,strictlyRequireArray:p},`NOT_AN_ARRAY`,`Expected the data to be an array but it was not an array.`);return null}if(h.length===0)return s(o,{children:d});let _;return _=u?u(h):c?h.map(c):h,s(o,{children:_.map((e,t)=>s(n,{children:typeof r==`function`?r(e):r},a?a(e,t):t))})}function g({children:e,logError:t}){let{data:n,error:r}=f(),i=a(!1);return r?(t&&!i.current&&(n==null?console.error(r):console.error(`An error has occurred but data is still present. This may indicate an invalid query state.`,{data:n,error:r}),i.current=!0),typeof e==`function`?e(r):e===void 0?s(u,{severity:`error`,children:typeof r==`object`&&`message`in r&&typeof r.message==`string`?r.message:`An unknown error has occured.`}):s(o,{children:e})):null}function _({undefinedFallback:e,nullFallback:t,nullableFallback:n}){let{isLoading:r,data:i,error:a}=f();if(r||a)return null;if(i==null){if(n!==void 0)return s(o,{children:n});if(i===void 0)return e===void 0?s(l,{children:`No data available.`}):s(o,{children:e});if(i===null)return t===void 0?s(l,{children:`No data found.`}):s(o,{children:t})}return null}function v({errorFallback:e,logError:t,...n}){return c(o,{children:[s(g,{logError:t,children:e}),s(_,{...n})]})}function y({query:e}){return{Context:({children:t})=>s(p,{isLoading:e.isLoading,error:e.error,data:e.data,children:t}),Error:g,Fallback:v,Nullable:_}}function b({query:e}){return{...y({query:e}),Data:m}}function x({children:t,errorFallback:n,undefinedFallback:r,nullFallback:i,nullableFallback:a,logError:o,loadingFallback:l=s(e,{}),isLoading:u,error:d,data:f,dataParser:p}){let m=b({query:{isLoading:u,error:d,data:f}}),h=s(m.Fallback,{logError:o,errorFallback:n});return a===void 0?(r!==void 0||i!==void 0)&&(h=s(m.Fallback,{undefinedFallback:r,nullFallback:i,logError:o,errorFallback:n})):h=s(m.Fallback,{nullableFallback:a,logError:o,errorFallback:n}),c(m.Context,{children:[h,s(m.Data,{loadingFallback:l,dataParser:p,children:t})]})}function S({query:e}){return{...y({query:e}),DataMap:h}}function C({loadingFallback:e,undefinedFallback:t,nullFallback:n,nullableFallback:r,logError:i,errorFallback:a,children:o,isLoading:l,error:u,data:d,dataParser:f,itemParser:p,itemKey:m}){let h=S({query:{isLoading:l,error:u,data:d}}),g=s(h.Fallback,{logError:i,errorFallback:a});r===void 0?(t!==void 0||n!==void 0)&&(g=s(h.Fallback,{undefinedFallback:t,nullFallback:n,logError:i,errorFallback:a})):g=s(h.Fallback,{nullableFallback:r,logError:i,errorFallback:a});let _=s(h.DataMap,{loadingFallback:e,itemKey:m,children:o});return f?_=s(h.DataMap,{loadingFallback:e,itemKey:m,dataParser:f,children:o}):p&&(_=s(h.DataMap,{loadingFallback:e,itemKey:m,itemParser:p,children:o})),c(h.Context,{children:[g,_]})}export{m as QueryBoundaryData,h as QueryBoundaryDataMap,g as QueryBoundaryError,v as QueryBoundaryFallback,x as QueryBoundaryItemWrapper,C as QueryBoundaryListWrapper,_ as QueryBoundaryNullable,p as QueryBoundaryProvider,y as createBaseQueryBoundary,b as createItemQueryBoundary,S as createListQueryBoundary,f as useQueryBoundaryContext};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/QueryBoundary/QueryBoundaryProvider.tsx","../../src/QueryBoundary/QueryBoundaryData.tsx","../../src/QueryBoundary/QueryBoundaryDataMap.tsx","../../src/QueryBoundary/QueryBoundaryError.tsx","../../src/QueryBoundary/QueryBoundaryNullable.tsx","../../src/QueryBoundary/QueryBoundaryFallback.tsx","../../src/QueryBoundary/creators/createBaseQueryBoundary.tsx","../../src/QueryBoundary/creators/createItemQueryBoundary.tsx","../../src/QueryBoundary/QueryBoundaryItemWrapper.tsx","../../src/QueryBoundary/creators/createListQueryBoundary.tsx","../../src/QueryBoundary/QueryBoundaryListWrapper.tsx"],"sourcesContent":["import type { OptionalOnCondition } from \"@alextheman/utility\";\nimport type { ReactNode } from \"react\";\n\nimport type { ContextHookOptions } from \"src/root/types\";\n\nimport { DataError } from \"@alextheman/utility/v6\";\nimport { createContext, use } from \"react\";\n\nexport interface QueryBoundaryContextValue<DataType> {\n /** The current loading status (true if loading, false if not) */\n isLoading?: boolean;\n /** The data being loaded. */\n data?: DataType | null | undefined;\n /** The error given if the request gave an error. */\n error: unknown;\n}\n\nexport type QueryBoundaryProviderProps<DataType> = QueryBoundaryContextValue<DataType> & {\n children: ReactNode;\n};\n\nconst QueryBoundaryContext = createContext<QueryBoundaryContextValue<unknown> | undefined>(\n undefined,\n);\n\n/** Access the QueryBoundary context directly. */\nexport function useQueryBoundaryContext<DataType, Strict extends boolean = true>({\n strict = true as Strict,\n}: ContextHookOptions<Strict> = {}): OptionalOnCondition<\n Strict,\n QueryBoundaryContextValue<DataType>\n> {\n const context = use(QueryBoundaryContext);\n if (strict && !context) {\n throw new DataError(\n { strict, context },\n \"QUERY_BOUNDARY_PROVIDER_NOT_FOUND\",\n \"Could not find the QueryBoundaryProvider context. Please double-check that it is present.\",\n );\n }\n return context as OptionalOnCondition<Strict, QueryBoundaryContextValue<DataType>>;\n}\n\n/**\n * A provider for a context that deals with state management when fetching data from an API.\n * This may be used over QueryBoundary if you require more control over the placement of the error message and data display.\n *\n * @template DataType - The type of data being loaded.\n */\nfunction QueryBoundaryProvider<DataType>({\n children,\n ...contextProps\n}: QueryBoundaryProviderProps<DataType>) {\n return <QueryBoundaryContext value={contextProps}>{children}</QueryBoundaryContext>;\n}\n\nexport default QueryBoundaryProvider;\n","import type { ReactNode } from \"react\";\n\nimport CircularProgress from \"@mui/material/CircularProgress\";\n\nimport { useQueryBoundaryContext } from \"src/QueryBoundary/QueryBoundaryProvider\";\n\nexport interface QueryBoundaryDataProps<DataType> {\n /**\n * The elements to show after data has been loaded.\n * This is best provided as a function with a data argument that guarantees the data will not be undefined by the time you receive it here.\n */\n children: ReactNode | ((data: NonNullable<DataType>) => ReactNode);\n /** A parser for the data. */\n dataParser?: (data: unknown) => NonNullable<DataType>;\n /** The component to show when the data is being fetched. */\n loadingFallback?: ReactNode;\n}\n\n/**\n * The component responsible for showing the data provided by QueryBoundaryProvider.\n *\n * @template DataType - The type of data being loaded.\n */\nfunction QueryBoundaryData<DataType>({\n children,\n dataParser,\n loadingFallback = <CircularProgress />,\n}: QueryBoundaryDataProps<DataType>) {\n const { isLoading, data, error } = useQueryBoundaryContext<DataType>();\n\n if (error) {\n return null;\n }\n\n if (isLoading) {\n return <>{loadingFallback}</>;\n }\n\n if (data === null || data === undefined) {\n return null;\n }\n\n return (\n <>\n {typeof children === \"function\" ? children(dataParser ? dataParser(data) : data) : children}\n </>\n );\n}\n\nexport default QueryBoundaryData;\n","import type { Key, ReactNode } from \"react\";\n\nimport { DataError } from \"@alextheman/utility/v6\";\nimport CircularProgress from \"@mui/material/CircularProgress\";\nimport Typography from \"@mui/material/Typography\";\nimport { Fragment } from \"react\";\n\nimport { useQueryBoundaryContext } from \"src/QueryBoundary/QueryBoundaryProvider\";\n\nexport interface QueryBoundaryDataMapBaseProps<ItemType> {\n /**\n * The elements to show after data has been loaded.\n *\n * This is best provided as a function with a data argument that guarantees the data will not be undefined by the time you receive it here.\n */\n children: ReactNode | ((data: ItemType) => ReactNode);\n /** The component to show when the data is being fetched. */\n loadingFallback?: ReactNode;\n /** The component to show if the array is empty. */\n emptyFallback?: ReactNode;\n /** Throw an error if the provided data is not an array. (defaults to `true`) */\n strictlyRequireArray?: boolean;\n /**\n * A function that takes a data item and returns the key to be used for the item.\n *\n * If not provided, it will fall back to using the index.\n */\n itemKey?: (item: ItemType, index: number) => Key;\n}\n\nexport interface QueryBoundaryDataMapPropsWithItemParser<\n ItemType,\n> extends QueryBoundaryDataMapBaseProps<ItemType> {\n /** A parser for each data item. */\n itemParser: (data: unknown) => ItemType;\n dataParser?: never;\n}\n\nexport interface QueryBoundaryDataMapPropsWithDataParser<\n ItemType,\n> extends QueryBoundaryDataMapBaseProps<ItemType> {\n /** A parser for each data item. */\n dataParser: (data: unknown) => Array<ItemType>;\n itemParser?: never;\n}\n\nexport interface QueryBoundaryDataMapPropsWithNoParser<\n ItemType,\n> extends QueryBoundaryDataMapBaseProps<ItemType> {\n dataParser?: never;\n itemParser?: never;\n}\n\nexport type QueryBoundaryDataMapProps<ItemType> =\n | QueryBoundaryDataMapPropsWithItemParser<ItemType>\n | QueryBoundaryDataMapPropsWithDataParser<ItemType>\n | QueryBoundaryDataMapPropsWithNoParser<ItemType>;\n\n/**\n * The component responsible for handling an array of data provided by `QueryBoundaryProvider`.\n *\n * It will map through the data array, rendering the result of the children function in a fragment with a key of its index in the list, unless overridden by the `itemKey` prop.\n *\n * @template ItemType - The type of data being loaded.\n *\n * @throws {DataError} If the data provided by `QueryBoundaryProvider` is not an array, and the `strictlyRequireArray` prop is `true` (it is by default).\n */\nfunction QueryBoundaryDataMap<ItemType>({\n children,\n loadingFallback = <CircularProgress />,\n itemKey,\n itemParser,\n dataParser,\n emptyFallback = <Typography>No data present</Typography>,\n strictlyRequireArray = true,\n}: QueryBoundaryDataMapProps<ItemType>) {\n const { isLoading, data, error } = useQueryBoundaryContext<Array<ItemType>>();\n\n if (isLoading) {\n return <>{loadingFallback}</>;\n }\n\n if (error) {\n return null;\n }\n\n if (data === null || data === undefined) {\n return null;\n }\n\n if (!Array.isArray(data)) {\n if (strictlyRequireArray) {\n throw new DataError(\n { data, strictlyRequireArray },\n \"NOT_AN_ARRAY\",\n \"Expected the data to be an array but it was not an array.\",\n );\n }\n return null;\n }\n\n if (data.length === 0) {\n return <>{emptyFallback}</>;\n }\n\n let items: Array<ItemType>;\n\n if (dataParser) {\n items = dataParser(data);\n } else if (itemParser) {\n items = data.map(itemParser);\n } else {\n items = data;\n }\n\n return (\n <>\n {items.map((item, index) => {\n return (\n <Fragment key={itemKey ? itemKey(item, index) : index}>\n {typeof children === \"function\" ? children(item) : children}\n </Fragment>\n );\n })}\n </>\n );\n}\n\nexport default QueryBoundaryDataMap;\n","import type { ReactNode } from \"react\";\n\nimport Alert from \"@mui/material/Alert\";\nimport { useRef } from \"react\";\n\nimport { useQueryBoundaryContext } from \"src/QueryBoundary/QueryBoundaryProvider\";\n\nexport interface QueryBoundaryErrorProps {\n /** The component to show if an error has been thrown. */\n children?: ReactNode | ((error: unknown) => ReactNode);\n /** An option to log the error to the console. */\n logError?: boolean;\n}\n\n/**\n * The component responsible for showing any errors provided by QueryBoundaryProvider.\n */\nfunction QueryBoundaryError({ children, logError }: QueryBoundaryErrorProps) {\n const { data, error } = useQueryBoundaryContext();\n const warnedOnceRef = useRef(false);\n\n if (error) {\n if (logError && !warnedOnceRef.current) {\n if (data !== null && data !== undefined) {\n console.error(\n \"An error has occurred but data is still present. This may indicate an invalid query state.\",\n { data, error },\n );\n } else {\n console.error(error);\n }\n warnedOnceRef.current = true;\n }\n if (typeof children === \"function\") {\n return children(error);\n }\n if (children !== undefined) {\n return <>{children}</>;\n }\n\n return (\n <Alert severity=\"error\">\n {typeof error === \"object\" && \"message\" in error && typeof error.message === \"string\"\n ? error.message\n : \"An unknown error has occured.\"}\n </Alert>\n );\n }\n\n return null;\n}\n\nexport default QueryBoundaryError;\n","import type { ReactNode } from \"react\";\n\nimport Typography from \"@mui/material/Typography\";\n\nimport { useQueryBoundaryContext } from \"src/QueryBoundary/QueryBoundaryProvider\";\n\nexport interface QueryBoundaryNullablePropsWithUndefinedOrNull {\n /** The component to show if no error was thrown but data is undefined */\n undefinedFallback?: ReactNode;\n /** The component to show if no error was thrown but data is null */\n nullFallback?: ReactNode;\n nullableFallback?: never;\n}\n\nexport interface QueryBoundaryNullablePropsWithNullable {\n undefinedFallback?: never;\n nullFallback?: never;\n /** The component to show if no error was thrown but data is undefined or null */\n nullableFallback?: ReactNode;\n}\n\nexport type QueryBoundaryNullableProps =\n | QueryBoundaryNullablePropsWithUndefinedOrNull\n | QueryBoundaryNullablePropsWithNullable;\n\n/** The component responsible for handling cases when the data provided by `QueryBoundaryProvider` may be missing. */\nfunction QueryBoundaryNullable({\n undefinedFallback,\n nullFallback,\n nullableFallback,\n}: QueryBoundaryNullableProps) {\n const { isLoading, data, error } = useQueryBoundaryContext();\n\n if (isLoading) {\n return null;\n }\n\n if (error) {\n return null;\n }\n\n if (data === null || data === undefined) {\n if (nullableFallback !== undefined) {\n return <>{nullableFallback}</>;\n }\n\n if (data === undefined) {\n if (undefinedFallback !== undefined) {\n return <>{undefinedFallback}</>;\n }\n return <Typography>No data available.</Typography>;\n }\n\n if (data === null) {\n if (nullFallback !== undefined) {\n return <>{nullFallback}</>;\n }\n return <Typography>No data found.</Typography>;\n }\n }\n\n return null;\n}\n\nexport default QueryBoundaryNullable;\n","import type { ReactNode } from \"react\";\n\nimport type { QueryBoundaryErrorProps } from \"src/QueryBoundary/QueryBoundaryError\";\nimport type { QueryBoundaryNullableProps } from \"src/QueryBoundary/QueryBoundaryNullable\";\n\nimport QueryBoundaryError from \"src/QueryBoundary/QueryBoundaryError\";\nimport QueryBoundaryNullable from \"src/QueryBoundary/QueryBoundaryNullable\";\n\nexport type QueryBoundaryFallbackProps = Omit<QueryBoundaryErrorProps, \"children\"> & {\n /** The component to show if an error has been thrown. */\n errorFallback?: ReactNode | ((error: unknown) => ReactNode);\n} & QueryBoundaryNullableProps;\n\n/**\n * The component responsible for handling both errors and nullable data from `QueryBoundaryProvider`\n */\nfunction QueryBoundaryFallback({\n errorFallback,\n logError,\n ...queryBoundaryNullableProps\n}: QueryBoundaryFallbackProps) {\n return (\n <>\n <QueryBoundaryError logError={logError}>{errorFallback}</QueryBoundaryError>\n <QueryBoundaryNullable {...queryBoundaryNullableProps} />\n </>\n );\n}\n\nexport default QueryBoundaryFallback;\n","import type { JSX, ReactNode } from \"react\";\n\nimport QueryBoundaryError from \"src/QueryBoundary/QueryBoundaryError\";\nimport QueryBoundaryFallback from \"src/QueryBoundary/QueryBoundaryFallback\";\nimport QueryBoundaryNullable from \"src/QueryBoundary/QueryBoundaryNullable\";\nimport QueryBoundaryProvider from \"src/QueryBoundary/QueryBoundaryProvider\";\n\nexport interface QueryBase<DataType> {\n /** The current loading status (true if loading, false if not) */\n isLoading?: boolean;\n /** The error given if the response gave an error. */\n error?: unknown;\n /** The data being loaded. */\n data: DataType;\n}\n\nexport interface CreateBaseQueryBoundaryParameters<DataType> {\n query: QueryBase<DataType>;\n}\n\nexport interface DefaultQueryBoundaryComponentsBase {\n /** Provides the context for the query boundary. */\n Context: (props: { children: ReactNode }) => JSX.Element;\n /** The component responsible for showing any errors provided by `QueryBoundary.Context`. */\n Error: typeof QueryBoundaryError;\n /** The component responsible for handling cases when the data provided by `QueryBoundary.Context` may be missing. */\n Fallback: typeof QueryBoundaryFallback;\n /** The component responsible for handling both errors and nullable data from `QueryBoundary.Context`*/\n Nullable: typeof QueryBoundaryNullable;\n}\n\n/** A creator function to create the base system of QueryBoundary components with the data fully typed throughout. */\nfunction createBaseQueryBoundary<DataType>({\n query,\n}: CreateBaseQueryBoundaryParameters<DataType>): DefaultQueryBoundaryComponentsBase {\n return {\n Context: ({ children }) => {\n return (\n <QueryBoundaryProvider isLoading={query.isLoading} error={query.error} data={query.data}>\n {children}\n </QueryBoundaryProvider>\n );\n },\n Error: QueryBoundaryError,\n Fallback: QueryBoundaryFallback,\n Nullable: QueryBoundaryNullable,\n };\n}\n\nexport default createBaseQueryBoundary;\n","import type {\n DefaultQueryBoundaryComponentsBase,\n QueryBase,\n} from \"src/QueryBoundary/creators/createBaseQueryBoundary\";\n\nimport createBaseQueryBoundary from \"src/QueryBoundary/creators/createBaseQueryBoundary\";\nimport QueryBoundaryData from \"src/QueryBoundary/QueryBoundaryData\";\n\nexport interface QueryItem<DataType> extends Omit<QueryBase<DataType>, \"data\"> {\n /** The data being loaded. */\n data: DataType | null | undefined;\n}\n\nexport interface CreateItemQueryBoundaryParameters<DataType> {\n query: QueryItem<DataType>;\n}\n\nexport interface DefaultQueryBoundaryItemComponents<\n DataType,\n> extends DefaultQueryBoundaryComponentsBase {\n /**\n * The component responsible for showing the data provided by `QueryBoundary.Context`.\n *\n * @template DataType - The type of data being loaded.\n */\n Data: typeof QueryBoundaryData<DataType>;\n}\n\n/** A creator function to create the system of QueryBoundary components with the data treated as a single data item, fully typed throughout. */\nfunction createItemQueryBoundary<DataType>({\n query,\n}: CreateItemQueryBoundaryParameters<DataType>): DefaultQueryBoundaryItemComponents<DataType> {\n const baseComponents = createBaseQueryBoundary({ query });\n\n return {\n ...baseComponents,\n Data: QueryBoundaryData,\n };\n}\n\nexport default createItemQueryBoundary;\n","import type { ReactNode } from \"react\";\n\nimport type { QueryBoundaryDataProps } from \"src/QueryBoundary/QueryBoundaryData\";\nimport type { QueryBoundaryFallbackProps } from \"src/QueryBoundary/QueryBoundaryFallback\";\nimport type { QueryBoundaryContextValue } from \"src/QueryBoundary/QueryBoundaryProvider\";\n\nimport CircularProgress from \"@mui/material/CircularProgress\";\n\nimport createItemQueryBoundary from \"src/QueryBoundary/creators/createItemQueryBoundary\";\n\nexport type QueryBoundaryItemWrapperProps<DataType> = QueryBoundaryContextValue<DataType> &\n QueryBoundaryFallbackProps &\n QueryBoundaryDataProps<DataType>;\n\n/**\n * An in-line component that deals with state management when fetching data from an API.\n * This may be used over QueryBoundaryProvider if you don't require as much control over the placement of the error message and data display.\n *\n * @template DataType - The type of data being loaded.\n */\nfunction QueryBoundaryItemWrapper<DataType>({\n children,\n errorFallback,\n undefinedFallback,\n nullFallback,\n nullableFallback,\n logError,\n loadingFallback = <CircularProgress />,\n isLoading,\n error,\n data,\n dataParser,\n}: QueryBoundaryItemWrapperProps<DataType>) {\n const QueryBoundary = createItemQueryBoundary({ query: { isLoading, error, data } });\n\n let boundaryFallbackComponent: ReactNode = (\n <QueryBoundary.Fallback logError={logError} errorFallback={errorFallback} />\n );\n\n if (nullableFallback !== undefined) {\n boundaryFallbackComponent = (\n <QueryBoundary.Fallback\n nullableFallback={nullableFallback}\n logError={logError}\n errorFallback={errorFallback}\n />\n );\n } else if (undefinedFallback !== undefined || nullFallback !== undefined) {\n boundaryFallbackComponent = (\n <QueryBoundary.Fallback\n undefinedFallback={undefinedFallback}\n nullFallback={nullFallback}\n logError={logError}\n errorFallback={errorFallback}\n />\n );\n }\n\n return (\n <QueryBoundary.Context>\n {boundaryFallbackComponent}\n <QueryBoundary.Data loadingFallback={loadingFallback} dataParser={dataParser}>\n {children}\n </QueryBoundary.Data>\n </QueryBoundary.Context>\n );\n}\n\nexport default QueryBoundaryItemWrapper;\n","import type {\n DefaultQueryBoundaryComponentsBase,\n QueryBase,\n} from \"src/QueryBoundary/creators/createBaseQueryBoundary\";\n\nimport createBaseQueryBoundary from \"src/QueryBoundary/creators/createBaseQueryBoundary\";\nimport QueryBoundaryDataMap from \"src/QueryBoundary/QueryBoundaryDataMap\";\n\nexport interface QueryList<DataType> extends Omit<QueryBase<DataType>, \"data\"> {\n /** The data being loaded. */\n data: Array<DataType> | null | undefined;\n}\n\nexport interface CreateListQueryBoundaryParameters<DataType> {\n query: QueryList<DataType>;\n}\n\nexport interface DefaultQueryBoundaryListComponents<\n DataType,\n> extends DefaultQueryBoundaryComponentsBase {\n /**\n * The component responsible for handling an array of data provided by `QueryBoundary.Context`.\n *\n * It will map through the data array, rendering the result of the children function in a fragment with a key of its index in the list, unless overridden by the `itemKey` prop.\n *\n * @template ItemType - The type of data being loaded.\n *\n * @throws {DataError} If the data provided by `QueryBoundary.Context` is not an array, and the `strictlyRequireArray` prop is `true` (it is by default).\n */\n DataMap: typeof QueryBoundaryDataMap<DataType>;\n}\n\n/** A creator function to create the system of QueryBoundary components with the data treated as an array of data items, fully typed throughout. */\nfunction createListQueryBoundary<DataType>({\n query,\n}: CreateListQueryBoundaryParameters<DataType>): DefaultQueryBoundaryListComponents<DataType> {\n const baseComponents = createBaseQueryBoundary({ query });\n\n return {\n ...baseComponents,\n DataMap: QueryBoundaryDataMap,\n };\n}\n\nexport default createListQueryBoundary;\n","import type { ReactNode } from \"react\";\n\nimport type { QueryBoundaryDataMapProps } from \"src/QueryBoundary/QueryBoundaryDataMap\";\nimport type { QueryBoundaryFallbackProps } from \"src/QueryBoundary/QueryBoundaryFallback\";\nimport type { QueryBoundaryContextValue } from \"src/QueryBoundary/QueryBoundaryProvider\";\n\nimport createListQueryBoundary from \"src/QueryBoundary/creators/createListQueryBoundary\";\n\nexport type QueryBoundaryListWrapperProps<ItemType> = QueryBoundaryContextValue<Array<ItemType>> &\n QueryBoundaryFallbackProps &\n QueryBoundaryDataMapProps<ItemType>;\n\n/**\n * An in-line component that handles an array of data provided by `QueryBoundaryProvider`.\n *\n * This may be used over QueryBoundaryProvider/QueryBoundaryDataMap if you don't require as much control over the placement of the error message and data display.\n *\n * @template DataType - The type of data being loaded.\n */\nfunction QueryBoundaryListWrapper<ItemType>({\n loadingFallback,\n undefinedFallback,\n nullFallback,\n nullableFallback,\n logError,\n errorFallback,\n children,\n isLoading,\n error,\n data,\n dataParser,\n itemParser,\n itemKey,\n}: QueryBoundaryListWrapperProps<ItemType>) {\n const QueryBoundary = createListQueryBoundary({ query: { isLoading, error, data } });\n\n let boundaryErrorFallback: ReactNode = (\n <QueryBoundary.Fallback logError={logError} errorFallback={errorFallback} />\n );\n\n if (nullableFallback !== undefined) {\n boundaryErrorFallback = (\n <QueryBoundary.Fallback\n nullableFallback={nullableFallback}\n logError={logError}\n errorFallback={errorFallback}\n />\n );\n } else if (undefinedFallback !== undefined || nullFallback !== undefined) {\n boundaryErrorFallback = (\n <QueryBoundary.Fallback\n undefinedFallback={undefinedFallback}\n nullFallback={nullFallback}\n logError={logError}\n errorFallback={errorFallback}\n />\n );\n }\n\n let boundaryDataMapComponent: ReactNode = (\n <QueryBoundary.DataMap loadingFallback={loadingFallback} itemKey={itemKey}>\n {children}\n </QueryBoundary.DataMap>\n );\n\n if (dataParser) {\n boundaryDataMapComponent = (\n <QueryBoundary.DataMap\n loadingFallback={loadingFallback}\n itemKey={itemKey}\n dataParser={dataParser}\n >\n {children}\n </QueryBoundary.DataMap>\n );\n } else if (itemParser) {\n boundaryDataMapComponent = (\n <QueryBoundary.DataMap\n loadingFallback={loadingFallback}\n itemKey={itemKey}\n itemParser={itemParser}\n >\n {children}\n </QueryBoundary.DataMap>\n );\n }\n\n return (\n <QueryBoundary.Context>\n {boundaryErrorFallback}\n {boundaryDataMapComponent}\n </QueryBoundary.Context>\n );\n}\n\nexport default QueryBoundaryListWrapper;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { TabProps } from "@mui/material/Tab";
|
|
2
|
+
import { TabsProps } from "@mui/material/Tabs";
|
|
3
|
+
import { Dispatch, JSX, ReactNode, SetStateAction } from "react";
|
|
4
|
+
import { OptionalOnCondition } from "@alextheman/utility";
|
|
5
|
+
//#region src/root/types/ContextHookOptions.d.ts
|
|
6
|
+
interface ContextHookOptions<Strict extends boolean = true> {
|
|
7
|
+
/** Error if the context is missing if this is set to true. */
|
|
8
|
+
strict?: Strict;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/Tab/TabProvider.d.ts
|
|
12
|
+
interface TabContextValue<TabState extends string = string> {
|
|
13
|
+
tab: TabState;
|
|
14
|
+
setTab: Dispatch<SetStateAction<TabState>>;
|
|
15
|
+
}
|
|
16
|
+
interface TabProviderProps<TabState extends string = string> extends TabContextValue<TabState> {
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
/** Access the TabContext directly. */
|
|
20
|
+
declare function useTabContext<TabState extends string = string, Strict extends boolean = true>({
|
|
21
|
+
strict
|
|
22
|
+
}?: ContextHookOptions<Strict>): OptionalOnCondition<Strict, TabContextValue<TabState>>;
|
|
23
|
+
/**
|
|
24
|
+
* A provider for a context that manages tab grouping.
|
|
25
|
+
*
|
|
26
|
+
* @template TabState The possible values for the tab.
|
|
27
|
+
*/
|
|
28
|
+
declare function TabProvider<TabState extends string = string>({
|
|
29
|
+
children,
|
|
30
|
+
tab,
|
|
31
|
+
setTab
|
|
32
|
+
}: TabProviderProps<TabState>): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/Tab/TabItem.d.ts
|
|
35
|
+
interface TabItemProps<TabState extends string = string> extends Omit<TabProps, "value"> {
|
|
36
|
+
value: TabState;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Renders a tab to be used within a `TabProvider`
|
|
40
|
+
*
|
|
41
|
+
* @template TabState The possible values for the tab.
|
|
42
|
+
*/
|
|
43
|
+
declare function TabItem<TabState extends string = string>({
|
|
44
|
+
label,
|
|
45
|
+
value,
|
|
46
|
+
...tabProps
|
|
47
|
+
}: TabItemProps<TabState>): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/Tab/TabList.d.ts
|
|
50
|
+
interface TabListProps extends Omit<TabsProps, "value"> {
|
|
51
|
+
children: ReactNode;
|
|
52
|
+
}
|
|
53
|
+
/** Takes the tabs provided as the children and renders them in a list. Should be used with `TabProvider`. */
|
|
54
|
+
declare function TabList({
|
|
55
|
+
children,
|
|
56
|
+
onChange,
|
|
57
|
+
...tabListProps
|
|
58
|
+
}: TabListProps): import("react/jsx-runtime").JSX.Element;
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/Tab/TabPanel.d.ts
|
|
61
|
+
interface TabPanelProps<TabState extends string = string> {
|
|
62
|
+
value: TabState;
|
|
63
|
+
children: ReactNode;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Displays the children if the current tab matches the value prop.
|
|
67
|
+
*
|
|
68
|
+
* @template TabState The possible values for the tab.
|
|
69
|
+
*/
|
|
70
|
+
declare function TabPanel<TabState extends string = string>({
|
|
71
|
+
value,
|
|
72
|
+
children
|
|
73
|
+
}: TabPanelProps<TabState>): ReactNode;
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/Tab/createTabGroup.d.ts
|
|
76
|
+
interface TabComponents<TabState extends string = string> {
|
|
77
|
+
/** Provides the context for the tab grouping. */
|
|
78
|
+
Context: (props: {
|
|
79
|
+
children: ReactNode;
|
|
80
|
+
}) => JSX.Element;
|
|
81
|
+
/** Takes the tabs provided as the children and renders them in a list. Should be used with the tab context. */
|
|
82
|
+
List: typeof TabList;
|
|
83
|
+
/**
|
|
84
|
+
* Renders a tab to be used within the context.
|
|
85
|
+
*
|
|
86
|
+
* @template TabState The possible values for the tab.
|
|
87
|
+
*/
|
|
88
|
+
Item: typeof TabItem<TabState>;
|
|
89
|
+
/**
|
|
90
|
+
* Displays the children if the current tab in the `Tab.Context` matches the value prop.
|
|
91
|
+
*
|
|
92
|
+
* @template TabState The possible values for the tab.
|
|
93
|
+
*/
|
|
94
|
+
Panel: typeof TabPanel<TabState>;
|
|
95
|
+
}
|
|
96
|
+
/** A creator function to create the tab group with the tab state fully typed throughout. */
|
|
97
|
+
declare function createTabGroup<TabState extends string = string>({
|
|
98
|
+
tab,
|
|
99
|
+
setTab
|
|
100
|
+
}: TabContextValue<TabState>): TabComponents<TabState>;
|
|
101
|
+
//#endregion
|
|
102
|
+
export { type TabContextValue, TabItem, type TabItemProps, TabList, type TabListProps, TabPanel, type TabPanelProps, TabProvider, type TabProviderProps, createTabGroup, useTabContext };
|
|
103
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"@mui/material/Tab";import{jsx as t}from"react/jsx-runtime";import n from"@mui/material/Tabs";import{DataError as r}from"@alextheman/utility/v6";import{createContext as i,use as a}from"react";function o({label:n,value:r,...i}){return t(e,{label:n??r,value:r,...i})}const s=i(void 0);function c({strict:e=!0}={}){let t=a(s);if(e&&!t)throw new r({strict:e,context:t},`TAB_PROVIDER_NOT_FOUND`,`Could not find the TabProvider. Please double-check that it is present.`);return t}function l({children:e,tab:n,setTab:r}){return t(s,{value:{tab:n,setTab:r},children:e})}function u({children:e,onChange:r,...i}){let{tab:a,setTab:o}=c();return t(n,{value:a,onChange:(e,t)=>{r&&r(e,t),!e.defaultPrevented&&o(t)},...i,children:e})}function d({value:e,children:t}){let{tab:n}=c();return e===n?t:null}function f({tab:e,setTab:n}){return{Context:({children:r})=>t(l,{tab:e,setTab:n,children:r}),List:u,Item:o,Panel:d}}export{o as TabItem,u as TabList,d as TabPanel,l as TabProvider,f as createTabGroup,c as useTabContext};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|