feat(modal): implementation done

This commit is contained in:
Junior Garcia 2023-04-14 23:08:53 -03:00
parent 2da9d4a8c9
commit 93e7bd5105
14 changed files with 485 additions and 71 deletions

View File

@ -43,6 +43,7 @@
"@nextui-org/framer-transitions": "workspace:*",
"@nextui-org/use-aria-button": "workspace:*",
"@nextui-org/shared-utils": "workspace:*",
"@nextui-org/shared-icons": "workspace:*",
"@nextui-org/dom-utils": "workspace:*",
"@react-aria/dialog": "^3.5.1",
"@react-aria/interactions": "^3.15.0",
@ -53,6 +54,8 @@
},
"devDependencies": {
"@nextui-org/input": "workspace:*",
"@nextui-org/checkbox": "workspace:*",
"react-lorem-component": "0.13.0",
"framer-motion": "^10.11.2",
"@react-types/overlays": "^3.7.1",
"clean-package": "2.2.0",

View File

@ -1,11 +1,17 @@
import Modal from "./modal";
import ModalTrigger from "./modal-trigger";
import ModalContent from "./modal-content";
import ModalHeader from "./modal-header";
import ModalBody from "./modal-body";
import ModalFooter from "./modal-footer";
// export types
export type {ModalProps} from "./modal";
export type {ModalTriggerProps} from "./modal-trigger";
export type {ModalContentProps} from "./modal-content";
export type {ModalHeaderProps} from "./modal-header";
export type {ModalBodyProps} from "./modal-body";
export type {ModalFooterProps} from "./modal-footer";
// export hooks
export {useModal} from "./use-modal";
@ -14,4 +20,4 @@ export {useModal} from "./use-modal";
export * from "./modal-context";
// export components
export {Modal, ModalTrigger, ModalContent};
export {Modal, ModalTrigger, ModalContent, ModalHeader, ModalBody, ModalFooter};

View File

@ -0,0 +1,43 @@
import {useEffect} from "react";
import {forwardRef, HTMLNextUIProps} from "@nextui-org/system";
import {useDOMRef} from "@nextui-org/dom-utils";
import {clsx} from "@nextui-org/shared-utils";
import {useModalContext} from "./modal-context";
export interface ModalBodyProps extends HTMLNextUIProps<"div"> {}
const ModalBody = forwardRef<ModalBodyProps, "div">((props, ref) => {
const {as, children, className, ...otherProps} = props;
const {slots, classNames, bodyId, setBodyMounted} = useModalContext();
const domRef = useDOMRef(ref);
const Component = as || "div";
/**
* Notify us if this component was rendered or used,
* so we can append `aria-labelledby` automatically
*/
useEffect(() => {
setBodyMounted(true);
return () => setBodyMounted(false);
}, [setBodyMounted]);
return (
<Component
ref={domRef}
className={slots.body({class: clsx(classNames?.body, className)})}
id={bodyId}
{...otherProps}
>
{children}
</Component>
);
});
ModalBody.displayName = "NextUI.ModalBody";
export default ModalBody;

View File

@ -1,20 +1,19 @@
import type {AriaDialogProps} from "@react-aria/dialog";
import type {HTMLMotionProps} from "framer-motion";
import {DOMAttributes, ReactNode, useMemo} from "react";
import {ReactNode, useMemo} from "react";
import {forwardRef} from "@nextui-org/system";
import {DismissButton} from "@react-aria/overlays";
import {FocusScope} from "@react-aria/focus";
import {TRANSITION_VARIANTS} from "@nextui-org/framer-transitions";
import {CloseIcon} from "@nextui-org/shared-icons";
import {motion} from "framer-motion";
import {useDialog} from "@react-aria/dialog";
import {mergeProps} from "@react-aria/utils";
import {FocusableElement} from "@react-types/shared";
import {useModalContext} from "./modal-context";
export interface ModalContentProps extends AriaDialogProps {
children: ReactNode | ((titleProps: DOMAttributes<FocusableElement>) => ReactNode);
children: ReactNode | ((onClose: () => void) => ReactNode);
}
const ModalContent = forwardRef<ModalContentProps, "section">((props, _) => {
@ -27,15 +26,17 @@ const ModalContent = forwardRef<ModalContentProps, "section">((props, _) => {
classNames,
motionProps,
backdropVariant,
showCloseButton,
disableAnimation,
getDialogProps,
getBackdropProps,
getCloseButtonProps,
onClose,
} = useModalContext();
const Component = as || DialogComponent || "section";
const {dialogProps, titleProps} = useDialog(
const {dialogProps} = useDialog(
{
role: "dialog",
},
@ -46,9 +47,12 @@ const ModalContent = forwardRef<ModalContentProps, "section">((props, _) => {
<>
<DismissButton onDismiss={onClose} />
<Component {...getDialogProps(mergeProps(dialogProps, otherProps))}>
<FocusScope contain restoreFocus>
{typeof children === "function" ? children(titleProps) : children}
</FocusScope>
{showCloseButton && (
<button {...getCloseButtonProps()}>
<CloseIcon />
</button>
)}
{typeof children === "function" ? children(onClose) : children}
</Component>
<DismissButton onDismiss={onClose} />
</>

View File

@ -0,0 +1,31 @@
import {forwardRef, HTMLNextUIProps} from "@nextui-org/system";
import {useDOMRef} from "@nextui-org/dom-utils";
import {clsx} from "@nextui-org/shared-utils";
import {useModalContext} from "./modal-context";
export interface ModalFooterProps extends HTMLNextUIProps<"footer"> {}
const ModalFooter = forwardRef<ModalFooterProps, "footer">((props, ref) => {
const {as, children, className, ...otherProps} = props;
const {slots, classNames} = useModalContext();
const domRef = useDOMRef(ref);
const Component = as || "footer";
return (
<Component
ref={domRef}
className={slots.footer({class: clsx(classNames?.footer, className)})}
{...otherProps}
>
{children}
</Component>
);
});
ModalFooter.displayName = "NextUI.ModalFooter";
export default ModalFooter;

View File

@ -0,0 +1,43 @@
import {useEffect} from "react";
import {forwardRef, HTMLNextUIProps} from "@nextui-org/system";
import {useDOMRef} from "@nextui-org/dom-utils";
import {clsx} from "@nextui-org/shared-utils";
import {useModalContext} from "./modal-context";
export interface ModalHeaderProps extends HTMLNextUIProps<"header"> {}
const ModalHeader = forwardRef<ModalHeaderProps, "header">((props, ref) => {
const {as, children, className, ...otherProps} = props;
const {slots, classNames, headerId, setHeaderMounted} = useModalContext();
const domRef = useDOMRef(ref);
const Component = as || "header";
/**
* Notify us if this component was rendered or used,
* so we can append `aria-labelledby` automatically
*/
useEffect(() => {
setHeaderMounted(true);
return () => setHeaderMounted(false);
}, [setHeaderMounted]);
return (
<Component
ref={domRef}
className={slots.header({class: clsx(classNames?.header, className)})}
id={headerId}
{...otherProps}
>
{children}
</Component>
);
});
ModalHeader.displayName = "NextUI.ModalHeader";
export default ModalHeader;

View File

@ -12,8 +12,10 @@ import {
useMemo,
useImperativeHandle,
} from "react";
import {HTMLNextUIProps, mapPropsVariants, PropGetter} from "@nextui-org/system";
import {modal} from "@nextui-org/theme";
import {HTMLNextUIProps, mapPropsVariants, PropGetter} from "@nextui-org/system";
import {useAriaButton} from "@nextui-org/use-aria-button";
import {useFocusRing} from "@react-aria/focus";
import {clsx, ReactRef} from "@nextui-org/shared-utils";
import {useOverlayTrigger} from "@react-aria/overlays";
import {createDOMRef} from "@nextui-org/dom-utils";
@ -34,7 +36,11 @@ interface Props extends HTMLNextUIProps<"div"> {
* The props to modify the framer motion animation. Use the `variants` API to create your own animation.
*/
motionProps?: HTMLMotionProps<"div">;
/**
* Determines if the modal should have a close button in the top right corner.
* @default true
*/
showCloseButton?: boolean;
/**
* Whether the animation should be disabled.
* @default false
@ -47,10 +53,13 @@ interface Props extends HTMLNextUIProps<"div"> {
* @example
* ```ts
* <Modal classNames={{
* wrapper: "wrapper-classes", // main wrapper
* backdrop: "backdrop-classes",
* base:"base-classes",
* header: "header-classes",
* body: "body-classes",
* footer: "footer-classes",
* closeButton: "close-button-classes",
* }} />
* ```
*/
@ -73,6 +82,9 @@ export function useModal(originalProps: UseModalProps) {
defaultOpen,
onOpenChange,
motionProps,
isDismissable = true,
showCloseButton = true,
isKeyboardDismissDisabled = false,
...otherProps
} = props;
@ -80,6 +92,7 @@ export function useModal(originalProps: UseModalProps) {
const dialogRef = useRef<HTMLElement>(null);
const domTriggerRef = useRef<HTMLElement>(null);
const closeButtonRef = useRef<HTMLElement>(null);
const [headerMounted, setHeaderMounted] = useState(false);
const [bodyMounted, setBodyMounted] = useState(false);
@ -104,7 +117,20 @@ export function useModal(originalProps: UseModalProps) {
const {triggerProps} = useOverlayTrigger({type: "dialog"}, state, triggerRef);
const {modalProps, underlayProps} = useModalOverlay(originalProps, state, dialogRef);
const {modalProps, underlayProps} = useModalOverlay(
{
isDismissable,
isKeyboardDismissDisabled,
},
state,
dialogRef,
);
const {buttonProps: closeButtonProps} = useAriaButton({onPress: state.close}, closeButtonRef);
const {
isFocusVisible: isCloseButtonFocusVisible,
focusProps: closeButtonFocusProps,
} = useFocusRing();
const baseStyles = clsx(classNames?.base, className);
@ -112,35 +138,28 @@ export function useModal(originalProps: UseModalProps) {
() =>
modal({
...variantProps,
isCloseButtonFocusVisible,
}),
[...Object.values(variantProps)],
[...Object.values(variantProps), isCloseButtonFocusVisible],
);
const getDialogProps: PropGetter = useCallback(
(props = {}, ref = null) => ({
ref: mergeRefs(ref, dialogRef),
...mergeProps(modalProps, otherProps, props),
className: slots.base({class: clsx(baseStyles, props.className)}),
id: dialogId,
"aria-modal": true,
"aria-labelledby": headerMounted ? headerId : undefined,
"aria-describedby": bodyMounted ? bodyId : undefined,
}),
[],
);
const getDialogProps: PropGetter = (props = {}, ref = null) => ({
ref: mergeRefs(ref, dialogRef),
...mergeProps(modalProps, otherProps, props),
className: slots.base({class: clsx(baseStyles, props.className)}),
id: dialogId,
"aria-modal": true,
"aria-labelledby": headerMounted ? headerId : undefined,
"aria-describedby": bodyMounted ? bodyId : undefined,
});
const getTriggerProps = useCallback<PropGetter>(
(props = {}, _ref: Ref<any> | null | undefined = null) => {
return {
...mergeProps(triggerProps, props),
className: slots.trigger({class: clsx(classNames?.trigger, props.className)}),
ref: mergeRefs(_ref, triggerRef),
"aria-controls": dialogId,
"aria-haspopup": "dialog",
};
},
[isOpen, dialogId, state, triggerProps, triggerRef],
);
const getTriggerProps: PropGetter = (props = {}, _ref: Ref<any> | null | undefined = null) => ({
...mergeProps(triggerProps, props),
className: slots.trigger({class: clsx(classNames?.trigger, props.className)}),
ref: mergeRefs(_ref, triggerRef),
"aria-controls": dialogId,
"aria-haspopup": "dialog",
});
const getBackdropProps = useCallback<PropGetter>(
(props = {}) => ({
@ -152,6 +171,15 @@ export function useModal(originalProps: UseModalProps) {
[slots, classNames, underlayProps],
);
const getCloseButtonProps: PropGetter = () => {
return {
role: "button",
tabIndex: 0,
className: slots.closeButton({class: classNames?.closeButton}),
...mergeProps(closeButtonProps, closeButtonFocusProps),
};
};
return {
Component,
slots,
@ -161,6 +189,8 @@ export function useModal(originalProps: UseModalProps) {
triggerRef,
motionProps,
classNames,
isDismissable,
showCloseButton,
backdropVariant: originalProps.backdropVariant ?? "opaque",
isOpen: state.isOpen,
onClose: state.close,
@ -170,6 +200,7 @@ export function useModal(originalProps: UseModalProps) {
getDialogProps,
getTriggerProps,
getBackdropProps,
getCloseButtonProps,
};
}

View File

@ -1,9 +1,23 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
/* eslint-disable jsx-a11y/no-autofocus */
import React from "react";
import {ComponentStory, ComponentMeta} from "@storybook/react";
import {modal} from "@nextui-org/theme";
import {link, modal} from "@nextui-org/theme";
import {Button} from "@nextui-org/button";
import {Input} from "@nextui-org/input";
import {Checkbox} from "@nextui-org/checkbox";
import {MailFilledIcon, LockFilledIcon} from "@nextui-org/shared-icons";
import Lorem from "react-lorem-component";
import {Modal, ModalContent, ModalTrigger, ModalProps} from "../src";
import {
Modal,
ModalContent,
ModalTrigger,
ModalHeader,
ModalBody,
ModalFooter,
ModalProps,
} from "../src";
export default {
title: "Components/Modal",
@ -32,6 +46,16 @@ export default {
type: "boolean",
},
},
isDismissable: {
control: {
type: "boolean",
},
},
isKeyboardDismissDisabled: {
control: {
type: "boolean",
},
},
children: {
control: {
disable: true,
@ -49,25 +73,146 @@ export default {
const defaultProps = {
...modal.defaultVariants,
disableAnimation: false,
isDismissable: true,
isKeyboardDismissDisabled: false,
};
const Template: ComponentStory<typeof Modal> = (args: ModalProps) => {
return (
<Modal {...args}>
<ModalTrigger>
<Button disableAnimation={!!args.disableAnimation}>Open popover</Button>
</ModalTrigger>
<ModalContent>
<div className="px-1 py-2">
<div className="text-sm font-bold">Modal Content</div>
<div className="text-xs">This is a content of the modal</div>
</div>
</ModalContent>
</Modal>
);
};
const content = (
<ModalContent>
{(onClose) => (
<>
<ModalHeader className="flex flex-col gap-1">Log in</ModalHeader>
<ModalBody>
<Input
autoFocus
endContent={
<MailFilledIcon className="text-2xl text-neutral-400 pointer-events-none flex-shrink-0" />
}
label="Email"
placeholder="Enter your email"
variant="bordered"
/>
<Input
endContent={
<LockFilledIcon className="text-2xl text-neutral-400 pointer-events-none flex-shrink-0" />
}
label="Password"
placeholder="Enter your password"
type="password"
variant="bordered"
/>
<div className="flex py-2 px-1 justify-between">
<Checkbox
classNames={{
label: "text-sm",
}}
>
Remember me
</Checkbox>
<a className={link({size: "sm"})} href="#">
Forgot password?
</a>
</div>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="flat" onClick={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
Sign in
</Button>
</ModalFooter>
</>
)}
</ModalContent>
);
const Template: ComponentStory<typeof Modal> = (args: ModalProps) => (
<Modal {...args}>
<ModalTrigger>
<Button disableAnimation={!!args.disableAnimation}>Open Modal</Button>
</ModalTrigger>
{content}
</Modal>
);
const InsideScrollTemplate: ComponentStory<typeof Modal> = (args: ModalProps) => (
<Modal {...args}>
<ModalTrigger>
<Button disableAnimation={!!args.disableAnimation}>Open Modal</Button>
</ModalTrigger>
<ModalContent>
{(onClose) => (
<>
<ModalHeader>Modal Title</ModalHeader>
<ModalBody>
<Lorem size={5} />
</ModalBody>
<ModalFooter>
<Button onPress={onClose}>Close</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
);
const OutsideScrollTemplate: ComponentStory<typeof Modal> = (args: ModalProps) => (
<Modal {...args} scrollBehavior="outside">
<ModalTrigger>
<Button disableAnimation={!!args.disableAnimation}>Open Modal</Button>
</ModalTrigger>
<ModalContent>
{(onClose) => (
<>
<ModalHeader>Modal Title</ModalHeader>
<ModalBody>
<Lorem size={5} />
</ModalBody>
<ModalFooter>
<Button onPress={onClose}>Close</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
);
export const Default = Template.bind({});
Default.args = {
...defaultProps,
};
export const InsideScroll = InsideScrollTemplate.bind({});
InsideScroll.args = {
...defaultProps,
};
export const OutsideScroll = OutsideScrollTemplate.bind({});
OutsideScroll.args = {
...defaultProps,
};
export const DisableAnimation = Template.bind({});
DisableAnimation.args = {
...defaultProps,
disableAnimation: true,
};
export const CustomMotion = Template.bind({});
CustomMotion.args = {
...defaultProps,
motionProps: {
variants: {
enter: {
opacity: 1,
duration: 0.3,
},
exit: {
opacity: 0,
duration: 0.3,
},
},
},
};

View File

@ -10,12 +10,11 @@ import {motion} from "framer-motion";
import {getTransformOrigins} from "@nextui-org/aria-utils";
import {useDialog} from "@react-aria/dialog";
import {mergeProps} from "@react-aria/utils";
import {FocusableElement} from "@react-types/shared";
import {usePopoverContext} from "./popover-context";
export interface PopoverContentProps extends AriaDialogProps {
children: ReactNode | ((titleProps: DOMAttributes<FocusableElement>) => ReactNode);
children: ReactNode | ((titleProps: DOMAttributes<HTMLElement>) => ReactNode);
}
const PopoverContent = forwardRef<PopoverContentProps, "section">((props, _) => {

View File

@ -110,7 +110,7 @@ const Template: ComponentStory<typeof Popover> = (args: PopoverProps) => {
return (
<Popover {...args}>
<PopoverTrigger>
<Button disableAnimation={!!args.disableAnimation}>Open popover</Button>
<Button disableAnimation={!!args.disableAnimation}>Open Popover</Button>
</PopoverTrigger>
{content}
</Popover>
@ -121,7 +121,7 @@ const WithTitlePropsTemplate: ComponentStory<typeof Popover> = (args: PopoverPro
return (
<Popover {...args}>
<PopoverTrigger>
<Button disableAnimation={!!args.disableAnimation}>Open popover</Button>
<Button disableAnimation={!!args.disableAnimation}>Open Popover</Button>
</PopoverTrigger>
<PopoverContent>
{(titleProps) => (
@ -144,7 +144,7 @@ const OpenChangeTemplate: ComponentStory<typeof Popover> = (args: PopoverProps)
<div className="flex flex-col gap-2">
<Popover {...args} onOpenChange={(open) => setIsOpen(open)}>
<PopoverTrigger>
<Button>Open popover</Button>
<Button>Open Popover</Button>
</PopoverTrigger>
<PopoverContent>
<div className="px-1 py-2">
@ -370,7 +370,7 @@ const OffsetTemplate: ComponentStory<typeof Popover> = (args: PopoverProps) => (
const WithFormTemplate: ComponentStory<typeof Popover> = (args: PopoverProps) => (
<Popover {...args}>
<PopoverTrigger>
<Button color="primary">Open popover</Button>
<Button color="primary">Open Popover</Button>
</PopoverTrigger>
<PopoverContent>
{(titleProps) => (
@ -416,7 +416,7 @@ const WithBackdropTemplate: ComponentStory<typeof Popover> = (args: PopoverProps
<Popover {...args}>
<PopoverTrigger>
<Button color="primary" radius="full">
Open popover
Open Popover
</Button>
</PopoverTrigger>
<PopoverContent>
@ -510,3 +510,21 @@ WithBackdrop.args = {
backdropVariant: "blur",
className: "bg-white dark:bg-content1",
};
export const CustomMotion = Template.bind({});
CustomMotion.args = {
...defaultProps,
placement: "bottom",
motionProps: {
variants: {
enter: {
opacity: 1,
duration: 0.2,
},
exit: {
opacity: 0,
duration: 0.1,
},
},
},
};

View File

@ -2,7 +2,7 @@ import type {VariantProps} from "tailwind-variants";
import {tv} from "tailwind-variants";
// import {ringClasses} from "../utils";
import {ringClasses} from "../utils";
/**
* Card **Tailwind Variants** component
@ -35,9 +35,10 @@ const modal = tv({
"overflow-y-hidden",
"justify-center",
"items-center",
"outline-none",
],
base: [
"flex",
"flex-col",
"relative",
"bg-white",
"z-50",
@ -46,12 +47,26 @@ const modal = tv({
"box-border",
"dark:bg-content1",
"border border-neutral-100",
"outline-none",
],
trigger: [],
backdrop: ["hidden"],
header: [],
body: [],
footer: [],
header: "flex py-4 px-6 flex-initial text-lg font-semibold",
body: "flex flex-1 flex-col gap-3 px-6 py-2",
footer: "flex flex-row gap-2 px-6 py-4 justify-end",
closeButton: [
"absolute",
"appearance-none",
"outline-none",
"select-none",
"top-1",
"right-1",
"p-2",
"text-neutral-500",
"rounded-full",
"hover:bg-neutral-100",
"active:bg-neutral-200",
],
},
variants: {
size: {
@ -83,10 +98,7 @@ const modal = tv({
base: "max-w-5xl",
},
full: {
base: "max-w-full",
},
prose: {
base: "max-w-prose",
base: "max-w-full rounded-none min-h-screen",
},
},
radius: {
@ -108,11 +120,27 @@ const modal = tv({
backdrop: "backdrop-blur-sm backdrop-saturate-150 bg-black/20",
},
},
scrollBehavior: {
inside: {
base: "max-h-[calc(100%_-_7.5rem)]",
body: "overflow-y-auto",
},
outside: {
wrapper: "items-start overflow-y-auto",
base: "my-16",
},
},
isCloseButtonFocusVisible: {
true: {
closeButton: [...ringClasses],
},
},
},
defaultVariants: {
size: "md",
radius: "lg",
backdropVariant: "opaque",
backdropVariant: "blur",
scrollBehavior: "inside",
},
compoundVariants: [
// backdropVariant (opaque/blur)

View File

@ -23,3 +23,4 @@ export * from "./eye-filled";
export * from "./eye-slash-filled";
export * from "./search";
export * from "./bulk";
export * from "./lock-filled";

View File

@ -0,0 +1,23 @@
import {IconSvgProps} from "./types";
export const LockFilledIcon = (props: IconSvgProps) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M12.0011 17.3498C12.9013 17.3498 13.6311 16.6201 13.6311 15.7198C13.6311 14.8196 12.9013 14.0898 12.0011 14.0898C11.1009 14.0898 10.3711 14.8196 10.3711 15.7198C10.3711 16.6201 11.1009 17.3498 12.0011 17.3498Z"
fill="currentColor"
/>
<path
d="M18.28 9.53V8.28C18.28 5.58 17.63 2 12 2C6.37 2 5.72 5.58 5.72 8.28V9.53C2.92 9.88 2 11.3 2 14.79V16.65C2 20.75 3.25 22 7.35 22H16.65C20.75 22 22 20.75 22 16.65V14.79C22 11.3 21.08 9.88 18.28 9.53ZM12 18.74C10.33 18.74 8.98 17.38 8.98 15.72C8.98 14.05 10.34 12.7 12 12.7C13.66 12.7 15.02 14.06 15.02 15.72C15.02 17.39 13.67 18.74 12 18.74ZM7.35 9.44C7.27 9.44 7.2 9.44 7.12 9.44V8.28C7.12 5.35 7.95 3.4 12 3.4C16.05 3.4 16.88 5.35 16.88 8.28V9.45C16.8 9.45 16.73 9.45 16.65 9.45H7.35V9.44Z"
fill="currentColor"
/>
</svg>
);

39
pnpm-lock.yaml generated
View File

@ -1015,6 +1015,9 @@ importers:
'@nextui-org/framer-transitions':
specifier: workspace:*
version: link:../../utilities/framer-transitions
'@nextui-org/shared-icons':
specifier: workspace:*
version: link:../../utilities/shared-icons
'@nextui-org/shared-utils':
specifier: workspace:*
version: link:../../utilities/shared-utils
@ -1046,6 +1049,9 @@ importers:
specifier: ^3.5.1
version: 3.5.1(react@18.2.0)
devDependencies:
'@nextui-org/checkbox':
specifier: workspace:*
version: link:../checkbox
'@nextui-org/input':
specifier: workspace:*
version: link:../input
@ -1061,6 +1067,9 @@ importers:
react:
specifier: ^18.2.0
version: 18.2.0
react-lorem-component:
specifier: 0.13.0
version: 0.13.0(react@18.2.0)
packages/components/pagination:
dependencies:
@ -11652,6 +11661,13 @@ packages:
sha.js: 2.4.11
dev: true
/create-react-class@15.7.0:
resolution: {integrity: sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==}
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
dev: true
/create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
@ -17170,6 +17186,13 @@ packages:
dependencies:
js-tokens: 4.0.0
/lorem-ipsum@1.0.6:
resolution: {integrity: sha512-Rx4XH8X4KSDCKAVvWGYlhAfNqdUP5ZdT4rRyf0jjrvWgtViZimDIlopWNfn/y3lGM5K4uuiAoY28TaD+7YKFrQ==}
hasBin: true
dependencies:
minimist: 1.2.8
dev: true
/loud-rejection@1.6.0:
resolution: {integrity: sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==}
engines: {node: '>=0.10.0'}
@ -20073,6 +20096,18 @@ packages:
unescape: 1.0.1
dev: false
/react-lorem-component@0.13.0(react@18.2.0):
resolution: {integrity: sha512-4mWjxmcG/DJJwdxdKwXWyP2N9zohbJg/yYaC+7JffQNrKj3LYDpA/A4u/Dju1v1ZF6Jew2gbFKGb5Z6CL+UNTw==}
peerDependencies:
react: 16.x
dependencies:
create-react-class: 15.7.0
lorem-ipsum: 1.0.6
object-assign: 4.1.1
react: 18.2.0
seedable-random: 0.0.1
dev: true
/react-markdown@6.0.2(@types/react@17.0.11)(react@18.2.0):
resolution: {integrity: sha512-Et2AjXAsbmPP1nLQQRqmVgcqzfwcz8uQJ8VAdADs8Nk/aaUA0YeU9RDLuCtD+GwajCnm/+Iiu2KPmXzmD/M3vA==}
peerDependencies:
@ -20894,6 +20929,10 @@ packages:
extend-shallow: 2.0.1
kind-of: 6.0.3
/seedable-random@0.0.1:
resolution: {integrity: sha512-uZWbEfz3BQdBl4QlUPELPqhInGEO1Q6zjzqrTDkd3j7mHaWWJo7h4ydr2g24a2WtTLk3imTLc8mPbBdQqdsbGw==}
dev: true
/select@1.1.2:
resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==}
dev: false