From 58a77cb6b9aa6cf41c811c389656dfabffc6206a Mon Sep 17 00:00:00 2001 From: Junior Garcia Date: Mon, 4 Nov 2024 17:20:46 -0300 Subject: [PATCH] feat: added drawer component (#3986) Signed-off-by: The1111mp Co-authored-by: The1111mp --- apps/docs/config/routes.json | 7 + .../content/components/drawer/backdrop.ts | 132 ++++++++ .../components/drawer/custom-motion.ts | 63 ++++ apps/docs/content/components/drawer/form.ts | 115 +++++++ apps/docs/content/components/drawer/index.ts | 17 + .../components/drawer/non-dismissable.ts | 52 +++ .../content/components/drawer/placement.ts | 68 ++++ apps/docs/content/components/drawer/sizes.ts | 64 ++++ apps/docs/content/components/drawer/usage.ts | 55 ++++ apps/docs/content/components/index.ts | 1 + apps/docs/content/docs/components/drawer.mdx | 186 +++++++++++ packages/components/drawer/README.md | 24 ++ .../drawer/__tests__/drawer.test.tsx | 110 +++++++ packages/components/drawer/package.json | 64 ++++ packages/components/drawer/src/drawer.tsx | 22 ++ packages/components/drawer/src/index.ts | 20 ++ packages/components/drawer/src/use-drawer.ts | 99 ++++++ .../drawer/stories/drawer.stories.tsx | 218 +++++++++++++ packages/components/drawer/tsconfig.json | 10 + packages/components/drawer/tsup.config.ts | 8 + .../components/modal/__tests__/modal.test.tsx | 1 + packages/core/react/package.json | 1 + packages/core/react/src/index.ts | 1 + packages/core/theme/src/components/alert.ts | 171 +++------- packages/core/theme/src/components/drawer.ts | 76 +++++ packages/core/theme/src/components/index.ts | 1 + packages/core/theme/src/utils/variants.ts | 10 +- pnpm-lock.yaml | 308 ++++++++++-------- 28 files changed, 1626 insertions(+), 278 deletions(-) create mode 100644 apps/docs/content/components/drawer/backdrop.ts create mode 100644 apps/docs/content/components/drawer/custom-motion.ts create mode 100644 apps/docs/content/components/drawer/form.ts create mode 100644 apps/docs/content/components/drawer/index.ts create mode 100644 apps/docs/content/components/drawer/non-dismissable.ts create mode 100644 apps/docs/content/components/drawer/placement.ts create mode 100644 apps/docs/content/components/drawer/sizes.ts create mode 100644 apps/docs/content/components/drawer/usage.ts create mode 100644 apps/docs/content/docs/components/drawer.mdx create mode 100644 packages/components/drawer/README.md create mode 100644 packages/components/drawer/__tests__/drawer.test.tsx create mode 100644 packages/components/drawer/package.json create mode 100644 packages/components/drawer/src/drawer.tsx create mode 100644 packages/components/drawer/src/index.ts create mode 100644 packages/components/drawer/src/use-drawer.ts create mode 100644 packages/components/drawer/stories/drawer.stories.tsx create mode 100644 packages/components/drawer/tsconfig.json create mode 100644 packages/components/drawer/tsup.config.ts create mode 100644 packages/core/theme/src/components/drawer.ts diff --git a/apps/docs/config/routes.json b/apps/docs/config/routes.json index 080bee747..d62238ce3 100644 --- a/apps/docs/config/routes.json +++ b/apps/docs/config/routes.json @@ -253,6 +253,13 @@ "keywords": "dropdown, menu, selection, option list", "path": "/docs/components/dropdown.mdx" }, + { + "key": "drawer", + "title": "Drawer", + "keywords": "drawer, panel, slide, overlay", + "path": "/docs/components/drawer.mdx", + "newPost": true + }, { "key": "image", "title": "Image", diff --git a/apps/docs/content/components/drawer/backdrop.ts b/apps/docs/content/components/drawer/backdrop.ts new file mode 100644 index 000000000..83f53e0f7 --- /dev/null +++ b/apps/docs/content/components/drawer/backdrop.ts @@ -0,0 +1,132 @@ +const MailIcon = `export const MailIcon = (props) => ( + +);`; + +const LockIcon = `export const LockIcon = (props) => ( + +);`; + +const App = `import {Drawer, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, Button, useDisclosure, Input, Checkbox, Link} from "@nextui-org/react"; +import {MailIcon} from "./MailIcon"; +import {LockIcon} from "./LockIcon"; + +export default function App() { + const {isOpen, onOpen, onOpenChange} = useDisclosure(); + const [backdrop, setBackdrop] = React.useState("opaque"); + + const backdrops = ["opaque", "blur", "transparent"]; + + const handleBackdropChange = (backdrop) => { + setBackdrop(backdrop); + onOpen(); + }; + + return ( + <> +
+ {backdrops.map((backdrop) => ( + + ))} +
+ + + {(onClose) => ( + <> + Log in + + + } + label="Email" + placeholder="Enter your email" + variant="bordered" + /> + + } + label="Password" + placeholder="Enter your password" + type="password" + variant="bordered" + /> +
+ + Remember me + + + Forgot password? + +
+
+ + + + + + )} +
+
+ + ); +}`; + +const react = { + "/App.jsx": App, + "/MailIcon.jsx": MailIcon, + "/LockIcon.jsx": LockIcon, +}; + +export default { + ...react, +}; diff --git a/apps/docs/content/components/drawer/custom-motion.ts b/apps/docs/content/components/drawer/custom-motion.ts new file mode 100644 index 000000000..62140e8e5 --- /dev/null +++ b/apps/docs/content/components/drawer/custom-motion.ts @@ -0,0 +1,63 @@ +const App = `import {Drawer, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, Button, useDisclosure} from "@nextui-org/react"; + +export default function App() { + const {isOpen, onOpen, onOpenChange} = useDisclosure(); + + return ( + <> + + + + {(onClose) => ( + <> + Custom Motion Drawer + +

+ This drawer has custom enter/exit animations. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Nullam pulvinar risus non risus hendrerit venenatis. + Pellentesque sit amet hendrerit risus, sed porttitor quam. +

+
+ + + + + + )} +
+
+ + ); +}`; + +const react = { + "/App.jsx": App, +}; + +export default { + ...react, +}; diff --git a/apps/docs/content/components/drawer/form.ts b/apps/docs/content/components/drawer/form.ts new file mode 100644 index 000000000..f087d8de0 --- /dev/null +++ b/apps/docs/content/components/drawer/form.ts @@ -0,0 +1,115 @@ +const MailIcon = `export const MailIcon = (props) => ( + +); +`; + +const LockIcon = `export const LockIcon = (props) => ( + +);`; + +const App = `import {Drawer, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, Button, useDisclosure, Input, Checkbox, Link} from "@nextui-org/react"; +import {MailIcon} from "./MailIcon"; +import {LockIcon} from "./LockIcon"; + +export default function App() { + const {isOpen, onOpen, onOpenChange} = useDisclosure(); + + return ( + <> + + + + {(onClose) => ( + <> + Log in + + + } + label="Email" + placeholder="Enter your email" + variant="bordered" + /> + + } + label="Password" + placeholder="Enter your password" + type="password" + variant="bordered" + /> +
+ + Remember me + + + Forgot password? + +
+
+ + + + + + )} +
+
+ + ); +}`; + +const react = { + "/App.jsx": App, + "/MailIcon.jsx": MailIcon, + "/LockIcon.jsx": LockIcon, +}; + +export default { + ...react, +}; diff --git a/apps/docs/content/components/drawer/index.ts b/apps/docs/content/components/drawer/index.ts new file mode 100644 index 000000000..e9fa1947c --- /dev/null +++ b/apps/docs/content/components/drawer/index.ts @@ -0,0 +1,17 @@ +import usage from "./usage"; +import sizes from "./sizes"; +import nonDismissable from "./non-dismissable"; +import placement from "./placement"; +import form from "./form"; +import backdrop from "./backdrop"; +import customMotion from "./custom-motion"; + +export const drawerContent = { + usage, + sizes, + nonDismissable, + placement, + form, + backdrop, + customMotion, +}; diff --git a/apps/docs/content/components/drawer/non-dismissable.ts b/apps/docs/content/components/drawer/non-dismissable.ts new file mode 100644 index 000000000..fc9f1ded2 --- /dev/null +++ b/apps/docs/content/components/drawer/non-dismissable.ts @@ -0,0 +1,52 @@ +const App = `import {Drawer, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, Button, useDisclosure} from "@nextui-org/react"; + +export default function App() { + const {isOpen, onOpen, onOpenChange} = useDisclosure(); + + return ( + <> + + + + {(onClose) => ( + <> + Non Dismissable Drawer + +

+ Click the close button or action button to close the drawer. + Clicking outside or pressing the escape key won't close it. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Nullam pulvinar risus non risus hendrerit venenatis. + Pellentesque sit amet hendrerit risus, sed porttitor quam. +

+
+ + + + + + )} +
+
+ + ); +}`; + +const react = { + "/App.jsx": App, +}; + +export default { + ...react, +}; diff --git a/apps/docs/content/components/drawer/placement.ts b/apps/docs/content/components/drawer/placement.ts new file mode 100644 index 000000000..bd66a29ba --- /dev/null +++ b/apps/docs/content/components/drawer/placement.ts @@ -0,0 +1,68 @@ +const App = `import {Drawer, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, Button, useDisclosure} from "@nextui-org/react"; + +export default function App() { + const {isOpen, onOpen, onOpenChange} = useDisclosure(); + const [placement, setPlacement] = React.useState("left") + + const handleOpen = (placement) => { + setPlacement(placement) + onOpen(); + } + + return ( + <> +
+ {["left", "right", "top", "bottom"].map((placement) => ( + + ))} +
+ + + {(onClose) => ( + <> + Drawer Title + +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Nullam pulvinar risus non risus hendrerit venenatis. + Pellentesque sit amet hendrerit risus, sed porttitor quam. +

+

+ Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit + dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. + Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. +

+
+ + + + + + )} +
+
+ + ); +}`; + +const react = { + "/App.jsx": App, +}; + +export default { + ...react, +}; diff --git a/apps/docs/content/components/drawer/sizes.ts b/apps/docs/content/components/drawer/sizes.ts new file mode 100644 index 000000000..6fa5d5589 --- /dev/null +++ b/apps/docs/content/components/drawer/sizes.ts @@ -0,0 +1,64 @@ +const App = `import {Drawer, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, Button, useDisclosure} from "@nextui-org/react"; + +export default function App() { + const {isOpen, onOpen, onClose} = useDisclosure(); + const [size, setSize] = React.useState('md') + + const sizes = ["xs", "sm", "md", "lg", "xl", "2xl", "3xl", "4xl", "5xl", "full"]; + + const handleOpen = (size) => { + setSize(size) + onOpen(); + } + + return ( + <> +
+ {sizes.map((size) => ( + + ))} +
+ + + {(onClose) => ( + <> + Drawer Title + +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Nullam pulvinar risus non risus hendrerit venenatis. + Pellentesque sit amet hendrerit risus, sed porttitor quam. +

+

+ Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit + dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. + Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. +

+
+ + + + + + )} +
+
+ + ); +}`; + +const react = { + "/App.jsx": App, +}; + +export default { + ...react, +}; diff --git a/apps/docs/content/components/drawer/usage.ts b/apps/docs/content/components/drawer/usage.ts new file mode 100644 index 000000000..e4de7c5f5 --- /dev/null +++ b/apps/docs/content/components/drawer/usage.ts @@ -0,0 +1,55 @@ +const App = `import {Drawer, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, Button, useDisclosure} from "@nextui-org/react"; + +export default function App() { + const {isOpen, onOpen, onOpenChange} = useDisclosure(); + + return ( + <> + + + + {(onClose) => ( + <> + Drawer Title + +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Nullam pulvinar risus non risus hendrerit venenatis. + Pellentesque sit amet hendrerit risus, sed porttitor quam. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Nullam pulvinar risus non risus hendrerit venenatis. + Pellentesque sit amet hendrerit risus, sed porttitor quam. +

+

+ Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit + dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. + Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. + Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur + proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam. +

+
+ + + + + + )} +
+
+ + ); +}`; + +const react = { + "/App.jsx": App, +}; + +export default { + ...react, +}; diff --git a/apps/docs/content/components/index.ts b/apps/docs/content/components/index.ts index 2641e4c40..45cfacb81 100644 --- a/apps/docs/content/components/index.ts +++ b/apps/docs/content/components/index.ts @@ -32,3 +32,4 @@ export * from "./navbar"; export * from "./table"; export * from "./autocomplete"; export * from "./alert"; +export * from "./drawer"; diff --git a/apps/docs/content/docs/components/drawer.mdx b/apps/docs/content/docs/components/drawer.mdx new file mode 100644 index 000000000..464f05758 --- /dev/null +++ b/apps/docs/content/docs/components/drawer.mdx @@ -0,0 +1,186 @@ +--- +title: "Drawer" +description: "Display a panel that slides in from the edge of the screen, containing supplementary content." +--- + +import {drawerContent} from "@/content/components/drawer"; + +# Drawer + +Displays a panel that slides in from the edge of the screen, containing supplementary content. + + + +--- + + + +## Installation + + + +## Import + +NextUI exports 5 drawer-related components: + +- **Drawer**: The main component to display a drawer. +- **DrawerContent**: The wrapper of the other drawer components. +- **DrawerHeader**: The header of the drawer. +- **DrawerBody**: The body of the drawer. +- **DrawerFooter**: The footer of the drawer. + + + +## Usage + +When the drawer opens: + +- Focus is bounded within the drawer and set to the first tabbable element. +- Content behind a drawer is inert, meaning that users cannot interact with it. + + + +### Sizes + + + +### Non-dismissible + +By default, the drawer can be closed by clicking on the overlay or pressing the Esc key. +You can disable this behavior by setting the following properties: + +- Set the `isDismissable` property to `false` to prevent the drawer from closing when clicking on the overlay. +- Set the `isKeyboardDismissDisabled` property to `true` to prevent the drawer from closing when pressing the Esc key. + + + +### Drawer placement + +The drawer can be placed on any edge of the screen using the `placement` prop: +- `left` (default) +- `right` +- `top` +- `bottom` + + + +### With Form + +The `Drawer` handles the focus within the drawer content. It means that you can use the drawer with +form elements without any problem. The focus returns to the trigger when the drawer closes. + + + +> **Note**: You can add the `autoFocus` prop to the first `Input` component to focus it when the drawer opens. + +### Backdrop + +The `Drawer` component has a `backdrop` prop to show a backdrop behind the drawer. The backdrop can be +either `transparent`, `opaque` or `blur`. The default value is `opaque`. + + + +### Custom Motion + +Drawer offers a `motionProps` property to customize the `enter` / `exit` animation. + + + +> Learn more about Framer motion variants [here](https://www.framer.com/motion/animation/#variants). + +## Slots + +- **wrapper**: The wrapper slot of the drawer. It wraps the `base` and the `backdrop` slots. +- **base**: The main slot of the drawer content. +- **backdrop**: The backdrop slot, it is displayed behind the drawer. +- **header**: The header of the drawer, it is displayed at the top of the drawer. +- **body**: The body of the drawer, it is displayed in the middle of the drawer. +- **footer**: The footer of the drawer, it is displayed at the bottom of the drawer. +- **closeButton**: The close button of the drawer. + +## Data Attributes + +`Drawer` has the following attributes on the `base` element: + +- **data-open**: + When the drawer is open. Based on drawer state. +- **data-dismissable**: + When the drawer is dismissable. Based on `isDismissable` prop. + + + +## Accessibility + +- Content outside the drawer is hidden from assistive technologies while it is open. +- The drawer optionally closes when interacting outside, or pressing the Esc key. +- Focus is moved into the drawer on mount, and restored to the trigger element on unmount. +- While open, focus is contained within the drawer, preventing the user from tabbing outside. +- Scrolling the page behind the drawer is prevented while it is open, including in mobile browsers. + + + +## API + +### Drawer Props + +| Attribute | Type | Description | Default | +| ------------------------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | --------------- | +| children\* | `ReactNode` | The content of the drawer. It's usually the `DrawerContent`. | - | +| size | `xs` \| `sm` \| `md` \| `lg` \| `xl` \| `2xl` \| `3xl` \| `4xl` \| `5xl` \| `full` | The drawer size. | `md` | +| radius | `none` \| `sm` \| `md` \| `lg` | The drawer border radius. | `lg` | +| placement | `left` \| `right` \| `top` \| `bottom` | The drawer position. | `right` | +| isOpen | `boolean` | Whether the drawer is open by default (controlled). | - | +| defaultOpen | `boolean` | Whether the drawer is open by default (uncontrolled). | - | +| isDismissable | `boolean` | Whether the drawer can be closed by clicking on the overlay or pressing the Esc key. | `true` | +| isKeyboardDismissDisabled | `boolean` | Whether pressing the Esc key to close the drawer should be disabled. | `false` | +| shouldBlockScroll | `boolean` | Whether the drawer should block the scroll of the page on open. | `true` | +| hideCloseButton | `boolean` | Whether to hide the drawer close button. | `false` | +| closeButton | `ReactNode` | Custom close button to display on top right corner. | - | +| motionProps | [MotionProps](#motion-props) | The props to modify the framer motion animation. Use the `variants` API to create your own animation. | | +| portalContainer | `HTMLElement` | The container element in which the overlay portal will be placed. | `document.body` | +| disableAnimation | `boolean` | Whether the drawer should not have animations. | `false` | +| classNames | `Record<"wrapper"| "base"| "backdrop"| "header" | "body" | "footer" | "closeButton", string>` | Allows to set custom class names for the drawer slots. | - | + +### Drawer Events + +| Attribute | Type | Description | +| ------------ | --------------------------- | ----------------------------------------------------------- | +| onOpenChange | `(isOpen: boolean) => void` | Handler that is called when the drawer's open state changes. | +| onClose | `() => void` | Handler that is called when the drawer is closed. | + + + +### Drawer types + +#### Motion Props + +```ts +export type MotionProps = HTMLMotionProps<"div">; // @see https://www.framer.com/motion/ +``` diff --git a/packages/components/drawer/README.md b/packages/components/drawer/README.md new file mode 100644 index 000000000..881c5193b --- /dev/null +++ b/packages/components/drawer/README.md @@ -0,0 +1,24 @@ +# @nextui-org/drawer + +A Quick description of the component + +> This is an internal utility, not intended for public usage. + +## Installation + +```sh +yarn add @nextui-org/drawer +# or +npm i @nextui-org/drawer +``` + +## Contribution + +Yes please! See the +[contributing guidelines](https://github.com/nextui-org/nextui/blob/master/CONTRIBUTING.md) +for details. + +## License + +This project is licensed under the terms of the +[MIT license](https://github.com/nextui-org/nextui/blob/master/LICENSE). diff --git a/packages/components/drawer/__tests__/drawer.test.tsx b/packages/components/drawer/__tests__/drawer.test.tsx new file mode 100644 index 000000000..85178372c --- /dev/null +++ b/packages/components/drawer/__tests__/drawer.test.tsx @@ -0,0 +1,110 @@ +import "@testing-library/jest-dom"; +import * as React from "react"; +import {render, fireEvent} from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; + +import {Drawer, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter} from "../src"; +// e.g. console.error Warning: Function components cannot be given refs. +// Attempts to access this ref will fail. Did you mean to use React.forwardRef()? +const spy = jest.spyOn(console, "error").mockImplementation(() => {}); + +describe("Drawer", () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it("should render correctly", () => { + const wrapper = render( + + + Drawer header + Drawer body + Drawer footer + + , + ); + + expect(() => wrapper.unmount()).not.toThrow(); + expect(spy).toHaveBeenCalledTimes(0); + }); + + it("ref should be forwarded", () => { + const ref = React.createRef(); + + render( + + + Drawer header + Drawer body + Drawer footer + + , + ); + expect(ref.current).not.toBeNull(); + }); + + it("should have the proper 'aria' attributes", () => { + const {getByRole, getByText} = render( + + + Drawer header + Drawer body + Drawer footer + + , + ); + + const drawer = getByRole("dialog"); + + expect(drawer).toHaveAttribute("aria-modal", "true"); + expect(drawer).toHaveAttribute("role", "dialog"); + + const drawerHeader = getByText("Drawer header"); + + expect(drawer).toHaveAttribute("aria-labelledby", drawerHeader.id); + + const drawerBody = getByText("Drawer body"); + + expect(drawer).toHaveAttribute("aria-describedby", drawerBody.id); + }); + + test("should fire 'onOpenChange' callback when close button is clicked", async () => { + const onClose = jest.fn(); + + const {getByLabelText} = render( + + + Drawer header + Drawer body + Drawer footer + + , + ); + + const closeButton = getByLabelText("Close"); + const user = userEvent.setup(); + + await user.click(closeButton); + + expect(onClose).toHaveBeenCalled(); + }); + + it("should hide the drawer when pressing the escape key", () => { + const onClose = jest.fn(); + + const wrapper = render( + + + Drawer header + Drawer body + Drawer footer + + , + ); + + const drawer = wrapper.getByRole("dialog"); + + fireEvent.keyDown(drawer, {key: "Escape"}); + expect(onClose).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/components/drawer/package.json b/packages/components/drawer/package.json new file mode 100644 index 000000000..96559ab14 --- /dev/null +++ b/packages/components/drawer/package.json @@ -0,0 +1,64 @@ +{ + "name": "@nextui-org/drawer", + "version": "2.0.0", + "description": "Used to render a content that slides in from the side of the screen.", + "keywords": [ + "drawer" + ], + "author": "Junior Garcia ", + "homepage": "https://nextui.org", + "license": "MIT", + "main": "src/index.ts", + "sideEffects": false, + "files": [ + "dist" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/nextui-org/nextui.git", + "directory": "packages/components/drawer" + }, + "bugs": { + "url": "https://github.com/nextui-org/nextui/issues" + }, + "scripts": { + "build": "tsup src --dts", + "build:fast": "tsup src", + "dev": "pnpm build:fast --watch", + "clean": "rimraf dist .turbo", + "typecheck": "tsc --noEmit", + "prepack": "clean-package", + "postpack": "clean-package restore" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18", + "@nextui-org/theme": ">=2.0.0", + "@nextui-org/system": ">=2.0.0" + }, + "dependencies": { + "@nextui-org/shared-utils": "workspace:*", + "@nextui-org/react-utils": "workspace:*", + "@nextui-org/framer-utils": "workspace:*", + "@nextui-org/modal": "workspace:*" + }, + "devDependencies": { + "@nextui-org/theme": "workspace:*", + "@nextui-org/system": "workspace:*", + "@nextui-org/input": "workspace:*", + "@nextui-org/checkbox": "workspace:*", + "@nextui-org/button": "workspace:*", + "@nextui-org/link": "workspace:*", + "@nextui-org/switch": "workspace:*", + "@nextui-org/shared-icons": "workspace:*", + "@nextui-org/use-disclosure": "workspace:*", + "react-lorem-component": "0.13.0", + "clean-package": "2.2.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "clean-package": "../../../clean-package.config.json" +} diff --git a/packages/components/drawer/src/drawer.tsx b/packages/components/drawer/src/drawer.tsx new file mode 100644 index 000000000..e362911cc --- /dev/null +++ b/packages/components/drawer/src/drawer.tsx @@ -0,0 +1,22 @@ +import {forwardRef} from "@nextui-org/system"; +import {Modal} from "@nextui-org/modal"; + +import {useDrawer, UseDrawerProps} from "./use-drawer"; + +export interface DrawerProps extends UseDrawerProps { + children: React.ReactNode; +} + +const Drawer = forwardRef<"div", DrawerProps>(({children, ...props}, ref) => { + const {domRef, getModalProps} = useDrawer({...props, ref}); + + return ( + + {children} + + ); +}); + +Drawer.displayName = "NextUI.Drawer"; + +export default Drawer; diff --git a/packages/components/drawer/src/index.ts b/packages/components/drawer/src/index.ts new file mode 100644 index 000000000..d171778a5 --- /dev/null +++ b/packages/components/drawer/src/index.ts @@ -0,0 +1,20 @@ +import {ModalHeader, ModalBody, ModalFooter, ModalContent} from "@nextui-org/modal"; + +import Drawer from "./drawer"; + +// export types +export type {DrawerProps} from "./drawer"; + +// export hooks +export {useDrawer} from "./use-drawer"; + +// export component +export {Drawer}; + +// export subcomponents +export { + ModalHeader as DrawerHeader, + ModalBody as DrawerBody, + ModalFooter as DrawerFooter, + ModalContent as DrawerContent, +}; diff --git a/packages/components/drawer/src/use-drawer.ts b/packages/components/drawer/src/use-drawer.ts new file mode 100644 index 000000000..b7d047881 --- /dev/null +++ b/packages/components/drawer/src/use-drawer.ts @@ -0,0 +1,99 @@ +import type {ModalProps} from "@nextui-org/modal"; + +import {drawer} from "@nextui-org/theme"; +import {ReactRef, useDOMRef} from "@nextui-org/react-utils"; +import {useCallback, useMemo} from "react"; +import {TRANSITION_EASINGS} from "@nextui-org/framer-utils"; +import {clsx} from "@nextui-org/shared-utils"; +import {PropGetter} from "@nextui-org/system"; + +interface Props extends Omit { + /** + * Ref to the DOM node. + */ + ref?: ReactRef; + /** + * The placement of the drawer. + */ + placement?: "top" | "right" | "bottom" | "left"; + /** + * The scroll behavior of the drawer. + */ + scrollBehavior?: "inside" | "outside"; +} + +export type UseDrawerProps = Props; + +export function useDrawer(originalProps: UseDrawerProps) { + const { + ref, + className, + classNames, + placement = "right", + scrollBehavior = "inside", + size = "md", + motionProps: drawerMotionProps, + ...otherProps + } = originalProps; + + const domRef = useDOMRef(ref); + + const motionProps = useMemo(() => { + if (drawerMotionProps !== void 0) return drawerMotionProps; + + const key = placement === "left" || placement === "right" ? "x" : "y"; + + return { + variants: { + enter: { + [key]: 0, + transition: { + [key]: { + bounce: 0, + duration: 0.3, + ease: TRANSITION_EASINGS.ease, + }, + }, + }, + exit: { + [key]: placement === "top" || placement === "left" ? "-100%" : "100%", + transition: { + [key]: { + bounce: 0, + duration: 0.6, + ease: TRANSITION_EASINGS.ease, + }, + }, + }, + }, + }; + }, [placement, drawerMotionProps]); + + const baseStyles = clsx(classNames?.base, className); + + const slots = useMemo( + () => + drawer({ + size, + placement, + }), + [size, placement], + ); + + const getModalProps = useCallback(() => { + return { + classNames: { + ...classNames, + base: slots.base({class: baseStyles}), + }, + motionProps, + scrollBehavior, + size, + ...otherProps, + }; + }, [baseStyles, classNames, motionProps, scrollBehavior, size, otherProps]); + + return {domRef, getModalProps}; +} + +export type UseDrawerReturn = ReturnType; diff --git a/packages/components/drawer/stories/drawer.stories.tsx b/packages/components/drawer/stories/drawer.stories.tsx new file mode 100644 index 000000000..259c2449f --- /dev/null +++ b/packages/components/drawer/stories/drawer.stories.tsx @@ -0,0 +1,218 @@ +/* eslint-disable jsx-a11y/no-autofocus */ +import React from "react"; +import {Meta} from "@storybook/react"; +import {drawer} from "@nextui-org/theme"; +import {Button} from "@nextui-org/button"; +import {Input} from "@nextui-org/input"; +import {Checkbox} from "@nextui-org/checkbox"; +import {Link} from "@nextui-org/link"; +import {MailFilledIcon, LockFilledIcon} from "@nextui-org/shared-icons"; +import {useDisclosure} from "@nextui-org/use-disclosure"; + +import {Drawer, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, DrawerProps} from "../src"; + +export default { + title: "Components/Drawer", + component: Drawer, + argTypes: { + size: { + control: { + type: "select", + }, + options: ["xs", "sm", "md", "lg", "xl", "2xl", "3xl", "4xl", "5xl", "6xl", "full"], + }, + placement: { + control: { + type: "select", + }, + options: ["left", "right", "top", "bottom"], + }, + radius: { + control: { + type: "select", + }, + options: ["none", "sm", "md", "lg"], + }, + backdrop: { + control: { + type: "select", + }, + options: ["transparent", "blur", "opaque"], + }, + disableAnimation: { + control: { + type: "boolean", + }, + }, + isDismissable: { + control: { + type: "boolean", + }, + }, + isKeyboardDismissDisabled: { + control: { + type: "boolean", + }, + }, + }, + decorators: [ + (Story) => ( +
+ +
+ ), + ], +} as Meta; + +const defaultProps = { + ...drawer.defaultVariants, + isDismissable: true, + isKeyboardDismissDisabled: false, +}; + +const content = ( + + {(onClose) => ( + <> + Log in + + + } + label="Email" + placeholder="Enter your email" + variant="bordered" + /> + + } + label="Password" + placeholder="Enter your password" + type="password" + variant="bordered" + /> +
+ + Remember me + + + Forgot password? + +
+
+ + + + + + )} +
+); + +const Template = (args: DrawerProps) => { + const {isOpen, onOpen, onOpenChange} = useDisclosure({defaultOpen: args.defaultOpen}); + + return ( + <> + + + {content} + + + ); +}; + +const PlacementTemplate = (args: DrawerProps) => { + const [placement, setPlacement] = React.useState("right"); + const {isOpen, onOpen, onOpenChange} = useDisclosure({defaultOpen: args.defaultOpen}); + + const handlePress = (placement: DrawerProps["placement"]) => { + setPlacement(placement); + onOpen(); + }; + + const placements = ["right", "left", "top", "bottom"] as DrawerProps["placement"][]; + + return ( + <> +
+ {placements.map((placement) => ( + + ))} +
+ + {content} + + + ); +}; + +export const Default = { + render: Template, + args: { + ...defaultProps, + }, +}; + +export const DefaultOpen = { + render: Template, + args: { + ...defaultProps, + defaultOpen: true, + }, +}; + +export const Placement = { + render: PlacementTemplate, + args: { + ...defaultProps, + placement: "right", + }, +}; + +export const DisableAnimation = { + render: Template, + args: { + ...defaultProps, + disableAnimation: true, + }, +}; + +export const CustomMotion = { + render: Template, + args: { + ...defaultProps, + motionProps: { + variants: { + enter: { + opacity: 1, + x: 0, + duration: 0.3, + }, + exit: { + x: 100, + opacity: 0, + duration: 0.3, + }, + }, + }, + }, +}; diff --git a/packages/components/drawer/tsconfig.json b/packages/components/drawer/tsconfig.json new file mode 100644 index 000000000..5d012f6e6 --- /dev/null +++ b/packages/components/drawer/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "tailwind-variants": ["../../../node_modules/tailwind-variants"] + }, + }, + "include": ["src", "index.ts"] +} diff --git a/packages/components/drawer/tsup.config.ts b/packages/components/drawer/tsup.config.ts new file mode 100644 index 000000000..3e2bcff6c --- /dev/null +++ b/packages/components/drawer/tsup.config.ts @@ -0,0 +1,8 @@ +import {defineConfig} from "tsup"; + +export default defineConfig({ + clean: true, + target: "es2019", + format: ["cjs", "esm"], + banner: {js: '"use client";'}, +}); diff --git a/packages/components/modal/__tests__/modal.test.tsx b/packages/components/modal/__tests__/modal.test.tsx index 13173bebf..3e73ec156 100644 --- a/packages/components/modal/__tests__/modal.test.tsx +++ b/packages/components/modal/__tests__/modal.test.tsx @@ -1,3 +1,4 @@ +import "@testing-library/jest-dom"; import * as React from "react"; import {render, fireEvent} from "@testing-library/react"; import userEvent from "@testing-library/user-event"; diff --git a/packages/core/react/package.json b/packages/core/react/package.json index 6b4f16c38..6b1fca8f2 100644 --- a/packages/core/react/package.json +++ b/packages/core/react/package.json @@ -85,6 +85,7 @@ "@nextui-org/date-picker": "workspace:*", "@nextui-org/alert": "workspace:*", "@nextui-org/framer-utils": "workspace:*", + "@nextui-org/drawer": "workspace:*", "@react-aria/visually-hidden": "3.8.15" }, "peerDependencies": { diff --git a/packages/core/react/src/index.ts b/packages/core/react/src/index.ts index 96c5475f6..cdaab4d34 100644 --- a/packages/core/react/src/index.ts +++ b/packages/core/react/src/index.ts @@ -44,6 +44,7 @@ export * from "@nextui-org/calendar"; export * from "@nextui-org/date-input"; export * from "@nextui-org/date-picker"; export * from "@nextui-org/alert"; +export * from "@nextui-org/drawer"; /** * React Aria - Exports diff --git a/packages/core/theme/src/components/alert.ts b/packages/core/theme/src/components/alert.ts index 451746c5a..c7713f972 100644 --- a/packages/core/theme/src/components/alert.ts +++ b/packages/core/theme/src/components/alert.ts @@ -1,6 +1,7 @@ import type {VariantProps} from "tailwind-variants"; import {tv} from "../utils/tv"; +import {colorVariants} from "../utils"; /** * Alert wrapper **Tailwind Variants** component * @@ -23,57 +24,23 @@ import {tv} from "../utils/tv"; */ const alert = tv({ slots: { - base: ["flex flex-row w-full flex-grow min-h-17 max-h-full py-3 px-4"], - mainWrapper: ["flex-grow min-h-11 max-h-full ms-2 flex flex-col box-border items-start"], - title: ["w-full text-medium font-normal block min-h-6 max-h-full"], - description: ["text-small font-normal min-h-5 max-h-full"], - closeButton: ["relative fill-current"], - alertIcon: ["fill-current"], + base: "flex flex-row w-full flex-grow min-h-17 max-h-full py-3 px-4", + mainWrapper: [ + "flex-grow min-h-11 max-h-full ms-2 flex flex-col box-border items-start text-inherit", + ], + title: "w-full text-medium font-normal block min-h-6 max-h-full text-inherit", + description: "text-small font-normal min-h-5 max-h-full text-inherit", + closeButton: "relative text-inherit", + alertIcon: "fill-current w-6", }, variants: { color: { - default: { - base: ["bg-default-100"], - title: ["text-foreground"], - description: ["text-default-600"], - closeButton: ["text-default-400"], - alertIcon: ["text-default-foreground"], - }, - primary: { - base: ["bg-primary-50"], - title: ["text-primary"], - description: ["text-primary"], - closeButton: ["text-primary-200"], - alertIcon: ["text-primary"], - }, - secondary: { - base: ["bg-secondary-50"], - title: ["text-secondary"], - description: ["text-secondary-200"], - closeButton: ["text-secondary-200"], - alertIcon: ["text-secondary"], - }, - success: { - base: ["bg-success-50"], - title: ["text-success"], - description: ["text-success-800 dark:text-success"], - closeButton: ["text-success-200"], - alertIcon: ["text-success"], - }, - warning: { - base: ["bg-warning-50"], - title: ["text-warning"], - description: ["text-warning-800 dark:text-warning"], - closeButton: ["text-warning-200"], - alertIcon: ["text-warning"], - }, - danger: { - base: ["bg-danger-50"], - title: ["text-danger"], - description: ["text-danger-800 dark:text-danger"], - closeButton: ["text-danger-200"], - alertIcon: ["text-danger"], - }, + default: {}, + primary: {}, + secondary: {}, + success: {}, + warning: {}, + danger: {}, }, variant: { solid: {}, @@ -104,8 +71,8 @@ const alert = tv({ alertIcon: "mt-0.5", }, false: { - base: ["items-center"], - mainWrapper: ["justify-center"], + base: "items-center", + mainWrapper: "justify-center", }, }, }, @@ -120,10 +87,8 @@ const alert = tv({ variant: "solid", color: "default", class: { - base: "bg-default", - title: "text-default-foreground", - description: "text-default-foreground", - closeButton: "text-default-foreground data-[hover]:bg-default-100", + base: colorVariants.solid.default, + closeButton: "data-[hover]:bg-default-100", alertIcon: "text-default-foreground", }, }, @@ -131,55 +96,35 @@ const alert = tv({ variant: "solid", color: "primary", class: { - base: "bg-primary", - title: "text-primary-foreground", - description: "text-primary-foreground", - closeButton: "text-primary-foreground", - alertIcon: "text-primary-foreground", + base: colorVariants.solid.primary, }, }, { variant: "solid", color: "secondary", class: { - base: "bg-secondary", - title: "text-secondary-foreground", - description: "text-secondary-foreground", - closeButton: "text-secondary-foreground", - alertIcon: "text-secondary-foreground", + base: colorVariants.solid.secondary, }, }, { variant: "solid", color: "success", class: { - base: "bg-success", - title: "text-success-foreground", - description: "text-success-foreground", - closeButton: "text-success-foreground", - alertIcon: "text-success-foreground", + base: colorVariants.solid.success, }, }, { variant: "solid", color: "warning", class: { - base: "bg-warning", - title: "text-warning-foreground", - description: "text-warning-foreground", - closeButton: "text-warning-foreground", - alertIcon: "text-warning-foreground", + base: colorVariants.solid.warning, }, }, { variant: "solid", color: "danger", class: { - base: "bg-danger", - title: "text-danger-foreground", - description: "text-danger-foreground", - closeButton: "text-danger-foreground", - alertIcon: "text-danger-foreground", + base: colorVariants.solid.danger, }, }, @@ -188,66 +133,49 @@ const alert = tv({ variant: "flat", color: "default", class: { - base: "bg-default-100", - title: "text-default-foreground", + base: [colorVariants.flat.default, "text-default-foreground"], description: "text-default-600", closeButton: "text-default-400", - alertIcon: "text-default-foreground", }, }, { variant: "flat", color: "primary", class: { - base: "bg-primary-50", - title: "text-primary", - description: "text-primary-600", + base: colorVariants.flat.primary, closeButton: "text-primary-400 data-[hover]:bg-primary-100", - alertIcon: "text-primary", }, }, { variant: "flat", color: "secondary", class: { - base: "bg-secondary-50", - title: "text-secondary", - description: "text-secondary-600", + base: colorVariants.flat.secondary, closeButton: "text-secondary-400 data-[hover]:bg-secondary-100", - alertIcon: "text-secondary", }, }, { variant: "flat", color: "success", class: { - base: "bg-success-50", - title: "text-success", - description: "text-success-800 dark:text-success", + base: colorVariants.flat.success, closeButton: "text-success-400 data-[hover]:bg-success-100", - alertIcon: "text-success", }, }, { variant: "flat", color: "warning", class: { - base: "bg-warning-50", - title: "text-warning", - description: "text-warning-800 dark:text-warning", + base: colorVariants.flat.warning, closeButton: "text-warning-500 data-[hover]:bg-warning-200", - alertIcon: "text-warning", }, }, { variant: "flat", color: "danger", class: { - base: "bg-danger-50", - title: "text-danger", - description: "text-danger-800 dark:text-danger", + base: colorVariants.flat.danger, closeButton: "text-danger-400 data-[hover]:bg-danger-100", - alertIcon: "text-danger", }, }, @@ -256,66 +184,49 @@ const alert = tv({ variant: "bordered", color: "default", class: { - base: "border-default-200", - title: "text-default-foreground", + base: [colorVariants.bordered.default], description: "text-default-600", closeButton: "text-default-400", - alertIcon: "text-default-foreground", }, }, { variant: "bordered", color: "primary", class: { - base: "border-primary", - title: "text-primary", - description: "text-primary-600", - closeButton: "text-primary-400 data-[hover]:bg-primary-50", - alertIcon: "text-primary", + base: [colorVariants.bordered.primary], + closeButton: "data-[hover]:bg-primary-50", }, }, { variant: "bordered", color: "secondary", class: { - base: "border-secondary", - title: "text-secondary", - description: "text-secondary-600", - closeButton: "text-secondary-400 data-[hover]:bg-secondary-50", - alertIcon: "text-secondary", + base: [colorVariants.bordered.secondary], + closeButton: "data-[hover]:bg-secondary-50", }, }, { variant: "bordered", color: "success", class: { - base: "border-success", - title: "text-success", - description: "text-success-600", - closeButton: "text-success-400 data-[hover]:bg-success-50", - alertIcon: "text-success", + base: [colorVariants.bordered.success], + closeButton: "data-[hover]:bg-success-50", }, }, { variant: "bordered", color: "warning", class: { - base: "border-warning", - title: "text-warning", - description: "text-warning-600", - closeButton: "text-warning-500 data-[hover]:bg-warning-100", - alertIcon: "text-warning", + base: [colorVariants.bordered.warning], + closeButton: "data-[hover]:bg-warning-100", }, }, { variant: "bordered", color: "danger", class: { - base: "border-danger", - title: "text-danger", - description: "text-danger-600", - closeButton: "text-danger-400 data-[hover]:bg-danger-50", - alertIcon: "text-danger", + base: [colorVariants.bordered.danger], + closeButton: "data-[hover]:bg-danger-50", }, }, ], diff --git a/packages/core/theme/src/components/drawer.ts b/packages/core/theme/src/components/drawer.ts new file mode 100644 index 000000000..3bd749f03 --- /dev/null +++ b/packages/core/theme/src/components/drawer.ts @@ -0,0 +1,76 @@ +import {VariantProps} from "tailwind-variants"; + +import {tv} from "../utils/tv"; + +/** + * Modal **Tailwind Variants** component + * + * @example + * ```js + * const {base} = drawer({...}) + * + *
+ * + *
+ * Drawer Content + *
+ *
+ * ``` + */ +const drawer = tv({ + slots: { + base: ["absolute", "m-0", "sm:m-0", "overflow-y-auto"], + }, + variants: { + size: { + xs: { + base: "max-w-xs max-h-[20rem]", + }, + sm: { + base: "max-w-sm max-h-[24rem]", + }, + md: { + base: "max-w-md max-h-[28rem]", + }, + lg: { + base: "max-w-lg max-h-[32rem]", + }, + xl: { + base: "max-w-xl max-h-[36rem]", + }, + "2xl": { + base: "max-w-2xl max-h-[42rem]", + }, + "3xl": { + base: "max-w-3xl max-h-[48rem]", + }, + "4xl": { + base: "max-w-4xl max-h-[56rem]", + }, + "5xl": { + base: "max-w-5xl max-h-[64rem]", + }, + full: { + base: "max-w-full max-h-full h-[100dvh] !rounded-none", + }, + }, + placement: { + top: { + base: "inset-x-0 top-0 max-w-[none] rounded-t-none", + }, + right: { + base: "inset-y-0 right-0 max-h-[none] rounded-r-none", + }, + bottom: { + base: "inset-x-0 bottom-0 max-w-[none] rounded-b-none", + }, + left: { + base: "inset-y-0 left-0 max-h-[none] rounded-l-none", + }, + }, + }, +}); + +export type DrawerVariants = VariantProps; + +export {drawer}; diff --git a/packages/core/theme/src/components/index.ts b/packages/core/theme/src/components/index.ts index c5ed21c03..bd7aa182b 100644 --- a/packages/core/theme/src/components/index.ts +++ b/packages/core/theme/src/components/index.ts @@ -39,3 +39,4 @@ export * from "./calendar"; export * from "./date-input"; export * from "./date-picker"; export * from "./alert"; +export * from "./drawer"; diff --git a/packages/core/theme/src/utils/variants.ts b/packages/core/theme/src/utils/variants.ts index 084bf1de5..9a4ad2d67 100644 --- a/packages/core/theme/src/utils/variants.ts +++ b/packages/core/theme/src/utils/variants.ts @@ -30,11 +30,11 @@ const bordered = { const flat = { default: "bg-default/40 text-default-700", - primary: "bg-primary/20 text-primary-700", - secondary: "bg-secondary/20 text-secondary-700", - success: "bg-success/20 text-success-800 dark:text-success", - warning: "bg-warning/20 text-warning-800 dark:text-warning", - danger: "bg-danger/20 text-danger-800 dark:text-danger-500", + primary: "bg-primary/20 text-primary-600", + secondary: "bg-secondary/20 text-secondary-600", + success: "bg-success/20 text-success-700 dark:text-success", + warning: "bg-warning/20 text-warning-700 dark:text-warning", + danger: "bg-danger/20 text-danger-600 dark:text-danger-500", foreground: "bg-foreground/10 text-foreground", }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 653149079..a0662f279 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1454,6 +1454,61 @@ importers: specifier: ^18.2.0 version: 18.3.1(react@18.3.1) + packages/components/drawer: + dependencies: + '@nextui-org/framer-utils': + specifier: workspace:* + version: link:../../utilities/framer-utils + '@nextui-org/modal': + specifier: workspace:* + version: link:../modal + '@nextui-org/react-utils': + specifier: workspace:* + version: link:../../utilities/react-utils + '@nextui-org/shared-utils': + specifier: workspace:* + version: link:../../utilities/shared-utils + devDependencies: + '@nextui-org/button': + specifier: workspace:* + version: link:../button + '@nextui-org/checkbox': + specifier: workspace:* + version: link:../checkbox + '@nextui-org/input': + specifier: workspace:* + version: link:../input + '@nextui-org/link': + specifier: workspace:* + version: link:../link + '@nextui-org/shared-icons': + specifier: workspace:* + version: link:../../utilities/shared-icons + '@nextui-org/switch': + specifier: workspace:* + version: link:../switch + '@nextui-org/system': + specifier: workspace:* + version: link:../../core/system + '@nextui-org/theme': + specifier: workspace:* + version: link:../../core/theme + '@nextui-org/use-disclosure': + specifier: workspace:* + version: link:../../hooks/use-disclosure + clean-package: + specifier: 2.2.0 + version: 2.2.0 + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + react-lorem-component: + specifier: 0.13.0 + version: 0.13.0(react@18.3.1) + packages/components/dropdown: dependencies: '@nextui-org/aria-utils': @@ -2913,6 +2968,9 @@ importers: '@nextui-org/divider': specifier: workspace:* version: link:../../components/divider + '@nextui-org/drawer': + specifier: workspace:* + version: link:../../components/drawer '@nextui-org/dropdown': specifier: workspace:* version: link:../../components/dropdown @@ -7931,7 +7989,7 @@ packages: resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - eslint: 8.57.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 '@typescript-eslint/visitor-keys@3.10.1': resolution: {integrity: sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==} @@ -18187,17 +18245,16 @@ snapshots: '@opentelemetry/semantic-conventions@1.27.0': {} - '@parcel/bundler-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/bundler-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 '@parcel/graph': 3.2.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 '@parcel/utils': 2.12.0 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/cache@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': dependencies: @@ -18213,47 +18270,46 @@ snapshots: dependencies: chalk: 4.1.2 - '@parcel/compressor-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/compressor-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/config-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)(postcss@8.4.47)(terser@5.36.0)(typescript@4.9.5)': dependencies: - '@parcel/bundler-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/compressor-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/bundler-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/compressor-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/core': 2.12.0(@swc/helpers@0.5.13) - '@parcel/namer-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/optimizer-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/optimizer-htmlnano': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)(postcss@8.4.47)(terser@5.36.0)(typescript@4.9.5) - '@parcel/optimizer-image': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/optimizer-svgo': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/namer-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/optimizer-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/optimizer-htmlnano': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(postcss@8.4.47)(terser@5.36.0)(typescript@4.9.5) + '@parcel/optimizer-image': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/optimizer-svgo': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/optimizer-swc': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-html': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-js': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-svg': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-wasm': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/reporter-dev-server': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/resolver-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/runtime-browser-hmr': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/runtime-js': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/runtime-react-refresh': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/runtime-service-worker': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-babel': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-html': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-image': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/packager-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/packager-html': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/packager-js': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/packager-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/packager-svg': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/packager-wasm': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/reporter-dev-server': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/resolver-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/runtime-browser-hmr': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/runtime-js': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/runtime-react-refresh': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/runtime-service-worker': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-babel': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-html': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-image': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/transformer-js': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) - '@parcel/transformer-json': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-postcss': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-posthtml': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-react-refresh-wrap': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-svg': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/transformer-json': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-postcss': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-posthtml': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-react-refresh-wrap': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-svg': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@swc/helpers' - cssnano @@ -18275,13 +18331,13 @@ snapshots: '@parcel/graph': 3.2.0 '@parcel/logger': 2.12.0 '@parcel/package-manager': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/profiler': 2.12.0 '@parcel/rust': 2.12.0 '@parcel/source-map': 2.1.1 '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) abortcontroller-polyfill: 1.7.5 base-x: 3.0.10 browserslist: 4.24.2 @@ -18309,7 +18365,7 @@ snapshots: '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 '@parcel/watcher': 2.5.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@swc/helpers' @@ -18326,14 +18382,13 @@ snapshots: dependencies: chalk: 4.1.2 - '@parcel/namer-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/namer-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/node-resolver-core@3.3.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: @@ -18347,10 +18402,10 @@ snapshots: transitivePeerDependencies: - '@parcel/core' - '@parcel/optimizer-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/optimizer-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 browserslist: 4.24.2 @@ -18358,18 +18413,16 @@ snapshots: nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/optimizer-htmlnano@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)(postcss@8.4.47)(terser@5.36.0)(typescript@4.9.5)': + '@parcel/optimizer-htmlnano@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(postcss@8.4.47)(terser@5.36.0)(typescript@4.9.5)': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) htmlnano: 2.1.1(postcss@8.4.47)(svgo@2.8.0)(terser@5.36.0)(typescript@4.9.5) nullthrows: 1.1.1 posthtml: 0.16.6 svgo: 2.8.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - cssnano - postcss - purgecss @@ -18379,31 +18432,28 @@ snapshots: - typescript - uncss - '@parcel/optimizer-image@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/optimizer-image@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/core': 2.12.0(@swc/helpers@0.5.13) '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 '@parcel/utils': 2.12.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - transitivePeerDependencies: - - '@swc/helpers' + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) - '@parcel/optimizer-svgo@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/optimizer-svgo@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 svgo: 2.8.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/optimizer-swc@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 '@swc/core': 1.8.0(@swc/helpers@0.5.13) @@ -18421,39 +18471,37 @@ snapshots: '@parcel/node-resolver-core': 3.3.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@swc/core': 1.8.0(@swc/helpers@0.5.13) semver: 7.6.3 transitivePeerDependencies: - '@swc/helpers' - '@parcel/packager-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 lightningcss: 1.28.1 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/packager-html@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-html@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 nullthrows: 1.1.1 posthtml: 0.16.6 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/packager-js@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-js@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 '@parcel/source-map': 2.1.1 '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) @@ -18462,38 +18510,33 @@ snapshots: nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/packager-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/packager-svg@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-svg@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 posthtml: 0.16.6 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/packager-wasm@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-wasm@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/plugin@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/plugin@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/profiler@2.12.0': dependencies: @@ -18501,79 +18544,71 @@ snapshots: '@parcel/events': 2.12.0 chrome-trace-event: 1.0.4 - '@parcel/reporter-cli@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/reporter-cli@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 chalk: 4.1.2 term-size: 2.2.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/reporter-dev-server@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/reporter-dev-server@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/reporter-tracer@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/reporter-tracer@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 chrome-trace-event: 1.0.4 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/resolver-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/resolver-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/node-resolver-core': 3.3.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/runtime-browser-hmr@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/runtime-browser-hmr@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/runtime-js@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/runtime-js@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/runtime-react-refresh@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/runtime-react-refresh@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 react-error-overlay: 6.0.9 react-refresh: 0.9.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/runtime-service-worker@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/runtime-service-worker@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/rust@2.12.0': {} @@ -18581,10 +18616,10 @@ snapshots: dependencies: detect-libc: 1.0.3 - '@parcel/transformer-babel@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-babel@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 browserslist: 4.24.2 @@ -18593,12 +18628,11 @@ snapshots: semver: 7.6.3 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 browserslist: 4.24.2 @@ -18606,12 +18640,11 @@ snapshots: nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-html@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-html@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 nullthrows: 1.1.1 posthtml: 0.16.6 @@ -18621,45 +18654,41 @@ snapshots: srcset: 4.0.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-image@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-image@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/core': 2.12.0(@swc/helpers@0.5.13) - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) nullthrows: 1.1.1 - transitivePeerDependencies: - - '@swc/helpers' '@parcel/transformer-js@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/core': 2.12.0(@swc/helpers@0.5.13) '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@swc/helpers': 0.5.13 browserslist: 4.24.2 nullthrows: 1.1.1 regenerator-runtime: 0.13.11 semver: 7.6.3 - '@parcel/transformer-json@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-json@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) json5: 2.2.3 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-postcss@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-postcss@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 '@parcel/utils': 2.12.0 clone: 2.1.2 @@ -18668,11 +18697,10 @@ snapshots: semver: 7.6.3 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-posthtml@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-posthtml@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 nullthrows: 1.1.1 posthtml: 0.16.6 @@ -18681,28 +18709,25 @@ snapshots: semver: 7.6.3 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-react-refresh-wrap@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-react-refresh-wrap@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 react-refresh: 0.9.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-svg@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-svg@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 nullthrows: 1.1.1 posthtml: 0.16.6 @@ -18711,7 +18736,6 @@ snapshots: semver: 7.6.3 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/types@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': dependencies: @@ -18720,7 +18744,7 @@ snapshots: '@parcel/fs': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/package-manager': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/source-map': 2.1.1 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) utility-types: 3.11.0 transitivePeerDependencies: - '@parcel/core' @@ -18797,7 +18821,7 @@ snapshots: '@parcel/watcher-win32-ia32': 2.5.0 '@parcel/watcher-win32-x64': 2.5.0 - '@parcel/workers@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/workers@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/core': 2.12.0(@swc/helpers@0.5.13) '@parcel/diagnostic': 2.12.0 @@ -18806,8 +18830,6 @@ snapshots: '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 nullthrows: 1.1.1 - transitivePeerDependencies: - - '@swc/helpers' '@pkgjs/parseargs@0.11.0': optional: true @@ -28265,9 +28287,9 @@ snapshots: '@parcel/fs': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/logger': 2.12.0 '@parcel/package-manager': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/reporter-cli': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/reporter-dev-server': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/reporter-tracer': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/reporter-cli': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/reporter-dev-server': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/reporter-tracer': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 chalk: 4.1.2 commander: 7.2.0