feat(accordion): tests added

This commit is contained in:
Junior Garcia 2023-03-19 15:33:42 -03:00
parent 976a3d52aa
commit 28229dc0ae
11 changed files with 424 additions and 115 deletions

View File

@ -1,5 +1,7 @@
import * as React from "react";
import {render} from "@testing-library/react";
import {act, render} from "@testing-library/react";
import {focus} from "@nextui-org/test-utils";
import userEvent from "@testing-library/user-event";
import {Accordion, AccordionItem} from "../src";
@ -24,4 +26,221 @@ describe("Accordion", () => {
);
expect(ref.current).not.toBeNull();
});
it("should display the correct number of items", () => {
const wrapper = render(
<Accordion>
<AccordionItem key="1">Accordion Item</AccordionItem>
<AccordionItem key="2">Accordion Item</AccordionItem>
</Accordion>,
);
expect(wrapper.getAllByRole("button")).toHaveLength(2);
});
it("should be opened when defaultExpandedKeys is set", () => {
const wrapper = render(
<Accordion defaultExpandedKeys={["1"]}>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
<AccordionItem key="2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);
expect(wrapper.getByTestId("item-1")).toHaveAttribute("data-open", "true");
});
it("should be disabled when disabledKeys is set", () => {
const wrapper = render(
<Accordion disabledKeys={["1"]}>
<AccordionItem key="1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
<AccordionItem key="2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);
expect(wrapper.getAllByRole("button")[0]).toBeDisabled();
});
it("should expand the accordion item when clicked", () => {
const wrapper = render(
<Accordion disableAnimation>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
<AccordionItem key="2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);
const base = wrapper.getByTestId("item-1");
const button = base.querySelector("button");
expect(button).toHaveAttribute("aria-expanded", "false");
act(() => {
button?.click();
});
expect(button).toHaveAttribute("aria-expanded", "true");
});
it("should support leftIndicator", () => {
const wrapper = render(
<Accordion>
<AccordionItem
key="1"
data-testid="item-1"
leftIndicator={<div data-testid="left-content" />}
title="Accordion Item 1"
>
Accordion Item 1 description
</AccordionItem>
</Accordion>,
);
expect(wrapper.getByTestId("left-content")).toBeInTheDocument();
});
it("arrow up & down moves focus to next/previous accordion item", async () => {
const wrapper = render(
<Accordion>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
<AccordionItem key="2" data-testid="item-2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);
const first = wrapper.getByTestId("item-1");
const firstButton = first.querySelector("button") as HTMLElement;
const second = wrapper.getByTestId("item-2");
const secondButton = second.querySelector("button") as HTMLElement;
act(() => {
focus(firstButton);
});
await act(async () => {
await userEvent.keyboard("[ArrowDown]");
});
expect(secondButton).toHaveFocus();
await act(async () => {
await userEvent.keyboard("[ArrowUp]");
});
expect(firstButton).toHaveFocus();
});
it("home & end keys moves focus to first/last accordion", async () => {
const wrapper = render(
<Accordion>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
<AccordionItem key="2" data-testid="item-2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);
const first = wrapper.getByTestId("item-1");
const firstButton = first.querySelector("button") as HTMLElement;
const second = wrapper.getByTestId("item-2");
const secondButton = second.querySelector("button") as HTMLElement;
act(() => {
focus(secondButton);
});
await act(async () => {
await userEvent.keyboard("[Home]");
});
expect(firstButton).toHaveFocus();
await act(async () => {
await userEvent.keyboard("[End]");
});
expect(secondButton).toHaveFocus();
});
it("tab moves focus to the next focusable element", async () => {
const wrapper = render(
<Accordion>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
<AccordionItem key="2" data-testid="item-2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);
const first = wrapper.getByTestId("item-1");
const firstButton = first.querySelector("button") as HTMLElement;
const second = wrapper.getByTestId("item-2");
const secondButton = second.querySelector("button") as HTMLElement;
act(() => {
focus(firstButton);
});
await act(async () => {
await userEvent.keyboard("[Tab]");
});
expect(secondButton).toHaveFocus();
});
it("aria-controls for button is same as id for region", async () => {
const wrapper = render(
<Accordion defaultExpandedKeys={["1"]}>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
<AccordionItem key="2" data-testid="item-2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);
const base = wrapper.getByTestId("item-1");
const button = base.querySelector("button") as HTMLElement;
const region = base.querySelector("[role='region']") as HTMLElement;
expect(button).toHaveAttribute("aria-controls", region.id);
});
it("aria-expanded is true/false when accordion is open/closed", async () => {
const wrapper = render(
<Accordion disableAnimation>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
</Accordion>,
);
const base = wrapper.getByTestId("item-1");
const button = base.querySelector("button") as HTMLElement;
expect(button).toHaveAttribute("aria-expanded", "false");
act(() => {
button?.click();
});
expect(button).toHaveAttribute("aria-expanded", "true");
});
});

View File

@ -58,6 +58,7 @@
},
"devDependencies": {
"@nextui-org/avatar": "workspace:*",
"@nextui-org/test-utils": "workspace:*",
"@react-types/accordion": "3.0.0-alpha.12",
"@react-types/shared": "^3.17.0",
"clean-package": "2.2.0",

View File

@ -10,9 +10,13 @@ export interface AccordionItemProps extends Omit<UseAccordionItemProps, "ref"> {
const Accordion = forwardRef<AccordionItemProps, "div">((props, ref) => {
const {
Component,
item,
styles,
slots,
indicator,
children,
title,
subtitle,
leftIndicator,
isOpen,
isDisabled,
disableAnimation,
@ -26,42 +30,42 @@ const Accordion = forwardRef<AccordionItemProps, "div">((props, ref) => {
getIndicatorProps,
} = useAccordionItem({ref, ...props});
const indicator = useMemo<ReactNode | null>(() => {
if (typeof item.props?.indicator === "function") {
return item.props?.indicator({indicator: <ChevronIcon />, isOpen, isDisabled});
const indicatorContent = useMemo<ReactNode | null>(() => {
if (typeof indicator === "function") {
return indicator({indicator: <ChevronIcon />, isOpen, isDisabled});
}
if (item.props?.indicator) return item.props?.indicator;
if (indicator) return indicator;
return <ChevronIcon />;
}, [item.props?.indicator, isOpen, isDisabled]);
}, [indicator, isOpen, isDisabled]);
const content = useMemo(() => {
if (disableAnimation) {
return <div {...getContentProps()}>{item.props?.children}</div>;
return <div {...getContentProps()}>{children}</div>;
}
return (
<Collapse in={isOpen} {...motionProps}>
<div {...getContentProps()}>{item.props?.children}</div>
<div {...getContentProps()}>{children}</div>
</Collapse>
);
}, [isOpen, disableAnimation, item.props?.children, motionProps]);
}, [isOpen, disableAnimation, children, motionProps]);
return (
<Component {...getBaseProps()}>
<h2 {...getHeadingProps()}>
<button {...getButtonProps()}>
{item.props?.leftIndicator && (
{leftIndicator && (
<div className={slots.leftIndicator({class: styles?.leftIndicator})}>
{item.props?.leftIndicator}
{leftIndicator}
</div>
)}
<div className={slots.titleWrapper({class: styles?.titleWrapper})}>
{item.props?.title && <span {...getTitleProps()}>{item.props?.title}</span>}
{item.props?.subtitle && <span {...getSubtitleProps()}>{item.props?.subtitle}</span>}
{title && <span {...getTitleProps()}>{title}</span>}
{subtitle && <span {...getSubtitleProps()}>{subtitle}</span>}
</div>
{indicator && <span {...getIndicatorProps()}>{indicator}</span>}
{indicatorContent && <span {...getIndicatorProps()}>{indicatorContent}</span>}
</button>
</h2>
{content}

View File

@ -2,7 +2,7 @@ import {HTMLNextUIProps, PropGetter} from "@nextui-org/system";
import {useFocusRing} from "@react-aria/focus";
import {accordionItem} from "@nextui-org/theme";
import {useDOMRef} from "@nextui-org/dom-utils";
import {clsx, ReactRef, callAllHandlers, dataAttr, extractProperty} from "@nextui-org/shared-utils";
import {clsx, ReactRef, callAllHandlers, dataAttr} from "@nextui-org/shared-utils";
import {NodeWithProps, useAccordionItem as useBaseAccordion} from "@nextui-org/aria-utils";
import {useCallback, useMemo} from "react";
import {mergeProps} from "@react-aria/utils";
@ -26,52 +26,25 @@ export type UseAccordionItemProps<T extends object = {}> = Props<T> & AccordionI
export function useAccordionItem<T extends object = {}>(props: UseAccordionItemProps<T>) {
const groupContext = useAccordionContext();
const {ref, as, item, onFocusChange} = props;
const {
ref,
as,
item,
styles = item.props?.styles,
className = item.props?.className,
isCompact = extractProperty(
"isCompact",
false,
groupContext,
item.props,
) as AccordionItemBaseProps["isCompact"],
isDisabled: isDisabledProp = extractProperty(
"isDisabled",
false,
groupContext,
item.props,
) as AccordionItemBaseProps["isDisabled"],
hideDivider = extractProperty(
"hideDivider",
false,
groupContext,
item.props,
) as AccordionItemBaseProps["hideDivider"],
hideIndicator = extractProperty(
"hideIndicator",
false,
groupContext,
item.props,
) as AccordionItemBaseProps["hideIndicator"],
disableAnimation = extractProperty(
"disableAnimation",
false,
groupContext,
item.props,
) as AccordionItemBaseProps["disableAnimation"],
disableIndicatorAnimation = extractProperty(
"disableIndicatorAnimation",
false,
groupContext,
item.props,
) as AccordionItemBaseProps["disableIndicatorAnimation"],
onFocusChange,
motionProps = item.props?.motionProps ?? groupContext?.motionProps,
styles,
className,
indicator,
children,
title,
subtitle,
leftIndicator,
motionProps = groupContext?.motionProps,
isCompact = groupContext?.isCompact ?? false,
isDisabled: isDisabledProp = groupContext?.isDisabled ?? false,
hideDivider = groupContext.hideDivider ?? false,
hideIndicator = groupContext.hideIndicator ?? false,
disableAnimation = groupContext.disableAnimation ?? false,
disableIndicatorAnimation = groupContext.disableIndicatorAnimation ?? false,
...otherProps
} = props;
} = item.props as AccordionItemBaseProps<T>;
const Component = as || "div";
@ -134,7 +107,7 @@ export function useAccordionItem<T extends object = {}>(props: UseAccordionItemP
...mergeProps(otherProps, props),
};
},
[baseStyles, otherProps, slots, isOpen, isDisabled],
[baseStyles, otherProps, slots, item.props, isOpen, isDisabled],
);
const getButtonProps = useCallback<PropGetter>(
@ -233,6 +206,11 @@ export function useAccordionItem<T extends object = {}>(props: UseAccordionItemP
slots,
styles,
domRef,
indicator,
children,
title,
subtitle,
leftIndicator,
isOpen,
isDisabled,
disableAnimation,

View File

@ -78,7 +78,6 @@ export function useAccordion<T extends object>(props: UseAccordionProps<T>) {
hideIndicator = false,
disableAnimation = false,
disableIndicatorAnimation = false,
...otherProps
} = props;

View File

@ -54,13 +54,13 @@ const defaultContent =
const Template: ComponentStory<typeof Accordion> = (args: AccordionProps) => (
<Accordion {...args}>
<AccordionItem key="1" title="Accordion 1">
<AccordionItem key="1" aria-label="Accordion 1" title="Accordion 1">
{defaultContent}
</AccordionItem>
<AccordionItem key="2" title="Accordion 2">
<AccordionItem key="2" aria-label="Accordion 2" title="Accordion 2">
{defaultContent}
</AccordionItem>
<AccordionItem key="3" title="Accordion 3">
<AccordionItem key="3" aria-label="Accordion 3" title="Accordion 3">
{defaultContent}
</AccordionItem>
</Accordion>
@ -68,11 +68,12 @@ const Template: ComponentStory<typeof Accordion> = (args: AccordionProps) => (
const TemplateWithSubtitle: ComponentStory<typeof Accordion> = (args: AccordionProps) => (
<Accordion {...args}>
<AccordionItem key="1" subtitle="Press to expand" title="Accordion 1">
<AccordionItem key="1" aria-label="Accordion 1" subtitle="Press to expand" title="Accordion 1">
{defaultContent}
</AccordionItem>
<AccordionItem
key="2"
aria-label="Accordion 2"
subtitle={
<span>
Press to expand <strong>key 2</strong>
@ -82,7 +83,7 @@ const TemplateWithSubtitle: ComponentStory<typeof Accordion> = (args: AccordionP
>
{defaultContent}
</AccordionItem>
<AccordionItem key="3" subtitle="Press to expand" title="Accordion 3">
<AccordionItem key="3" aria-label="Accordion 3" subtitle="Press to expand" title="Accordion 3">
{defaultContent}
</AccordionItem>
</Accordion>
@ -92,6 +93,7 @@ const TemplateWithLeftIndicator: ComponentStory<typeof Accordion> = (args: Accor
<Accordion {...args} variant="shadow">
<AccordionItem
key="1"
aria-label="Chung Miller"
leftIndicator={
<Avatar
isBordered
@ -107,6 +109,7 @@ const TemplateWithLeftIndicator: ComponentStory<typeof Accordion> = (args: Accor
</AccordionItem>
<AccordionItem
key="2"
aria-label="Janelle Lenard"
leftIndicator={
<Avatar
isBordered
@ -122,6 +125,7 @@ const TemplateWithLeftIndicator: ComponentStory<typeof Accordion> = (args: Accor
</AccordionItem>
<AccordionItem
key="3"
aria-label="Zoey Lang"
leftIndicator={
<Avatar
isBordered
@ -167,13 +171,13 @@ const VariantsTemplate: ComponentStory<typeof Accordion> = (args: AccordionProps
<div className="flex flex-col gap-4">
<h3>Shadow</h3>
<Accordion {...args} variant="shadow">
<AccordionItem key="1" title="Accordion 1">
<AccordionItem key="1" aria-label="Accordion 1" title="Accordion 1">
{defaultContent}
</AccordionItem>
<AccordionItem key="2" title="Accordion 2">
<AccordionItem key="2" aria-label="Accordion 2" title="Accordion 2">
{defaultContent}
</AccordionItem>
<AccordionItem key="3" title="Accordion 3">
<AccordionItem key="3" aria-label="Accordion 3" title="Accordion 3">
{defaultContent}
</AccordionItem>
</Accordion>
@ -181,13 +185,13 @@ const VariantsTemplate: ComponentStory<typeof Accordion> = (args: AccordionProps
<div className="flex flex-col gap-4">
<h3>Bordered</h3>
<Accordion {...args} variant="bordered">
<AccordionItem key="1" title="Accordion 1">
<AccordionItem key="1" aria-label="Accordion 1" title="Accordion 1">
{defaultContent}
</AccordionItem>
<AccordionItem key="2" title="Accordion 2">
<AccordionItem key="2" aria-label="Accordion 2" title="Accordion 2">
{defaultContent}
</AccordionItem>
<AccordionItem key="3" title="Accordion 3">
<AccordionItem key="3" aria-label="Accordion 3" title="Accordion 3">
{defaultContent}
</AccordionItem>
</Accordion>
@ -195,13 +199,13 @@ const VariantsTemplate: ComponentStory<typeof Accordion> = (args: AccordionProps
<div className="flex flex-col gap-4">
<h3>Splitted</h3>
<Accordion {...args} variant="splitted">
<AccordionItem key="1" title="Accordion 1">
<AccordionItem key="1" aria-label="Accordion 1" title="Accordion 1">
{defaultContent}
</AccordionItem>
<AccordionItem key="2" title="Accordion 2">
<AccordionItem key="2" aria-label="Accordion 2" title="Accordion 2">
{defaultContent}
</AccordionItem>
<AccordionItem key="3" title="Accordion 3">
<AccordionItem key="3" aria-label="Accordion 3" title="Accordion 3">
{defaultContent}
</AccordionItem>
</Accordion>
@ -211,13 +215,13 @@ const VariantsTemplate: ComponentStory<typeof Accordion> = (args: AccordionProps
const CustomInidicatorTemplate: ComponentStory<typeof Accordion> = (args: AccordionProps) => (
<Accordion {...args}>
<AccordionItem key="anchor" indicator={<AnchorIcon />} title="Anchor">
<AccordionItem key="anchor" aria-label="Anchor" indicator={<AnchorIcon />} title="Anchor">
{defaultContent}
</AccordionItem>
<AccordionItem key="moon" indicator={<MoonIcon />} title="Moon">
<AccordionItem key="moon" aria-label="Moon" indicator={<MoonIcon />} title="Moon">
{defaultContent}
</AccordionItem>
<AccordionItem key="sun" indicator={<SunIcon />} title="Sun">
<AccordionItem key="sun" aria-label="Sun" indicator={<SunIcon />} title="Sun">
{defaultContent}
</AccordionItem>
</Accordion>
@ -231,13 +235,13 @@ const ControlledTemplate: ComponentStory<typeof Accordion> = (args: AccordionPro
return (
<Accordion {...args} selectedKeys={selectedKeys} onSelectionChange={setSelectedKeys}>
<AccordionItem key="1" title="Accordion 1">
<AccordionItem key="1" aria-label="Accordion 1" title="Accordion 1">
{defaultContent}
</AccordionItem>
<AccordionItem key="2" title="Accordion 2">
<AccordionItem key="2" aria-label="Accordion 2" title="Accordion 2">
{defaultContent}
</AccordionItem>
<AccordionItem key="3" title="Accordion 3">
<AccordionItem key="3" aria-label="Accordion 3" title="Accordion 3">
{defaultContent}
</AccordionItem>
</Accordion>
@ -262,6 +266,7 @@ const CustomWithStylesTemplate: ComponentStory<typeof Accordion> = (args: Accord
>
<AccordionItem
key="1"
aria-label="Connected devices"
leftIndicator={<MonitorMobileIcon className="text-primary" />}
styles={itemStyles}
subtitle={
@ -281,6 +286,7 @@ const CustomWithStylesTemplate: ComponentStory<typeof Accordion> = (args: Accord
</AccordionItem>
<AccordionItem
key="2"
aria-label="Apps Permissions"
leftIndicator={<ShieldSecurityIcon />}
styles={itemStyles}
subtitle="3 apps have read permissions"
@ -290,6 +296,7 @@ const CustomWithStylesTemplate: ComponentStory<typeof Accordion> = (args: Accord
</AccordionItem>
<AccordionItem
key="3"
aria-label="Pending tasks"
leftIndicator={<InfoIcon className="text-warning" />}
styles={{...itemStyles, subtitle: "text-warning"}}
subtitle="Complete your profile"
@ -299,6 +306,7 @@ const CustomWithStylesTemplate: ComponentStory<typeof Accordion> = (args: Accord
</AccordionItem>
<AccordionItem
key="4"
aria-label="Card expired"
leftIndicator={<InvalidCardIcon className="text-danger" />}
styles={{...itemStyles, subtitle: "text-danger"}}
subtitle="Please, update now"

View File

@ -0,0 +1,25 @@
export function isElement(el: any): el is Element {
return (
el != null && typeof el == "object" && "nodeType" in el && el.nodeType === Node.ELEMENT_NODE
);
}
export function isHTMLElement(el: any): el is HTMLElement {
if (!isElement(el)) {
return false;
}
const win = el.ownerDocument.defaultView ?? window;
return el instanceof win.HTMLElement;
}
export function getOwnerDocument(node?: Element | null): Document {
return isElement(node) ? node.ownerDocument ?? document : document;
}
export function getActiveElement(node?: HTMLElement) {
const doc = getOwnerDocument(node);
return doc?.activeElement as HTMLElement;
}

View File

@ -0,0 +1,21 @@
import {act} from "@testing-library/react";
import {isFocusable} from "./tabbable";
import {getActiveElement} from "./dom";
export function focus(el: HTMLElement) {
if (getActiveElement(el) === el) return;
if (!isFocusable(el)) return;
act(() => {
el.focus();
});
}
export function blur(el?: HTMLElement | null) {
if (el == null) el = document.activeElement as HTMLElement;
if (el.tagName === "BODY") return;
if (getActiveElement(el) !== el) return;
act(() => {
if (el && "blur" in el) el.blur();
});
}

View File

@ -1 +1,4 @@
export * from "./mocks";
export * from "./focus";
export * from "./tabbable";
export * from "./dom";

View File

@ -0,0 +1,82 @@
// Really great work done by Diego Haz on this one
// https://github.com/reakit/reakit/blob/master/packages/reakit-utils/src/tabbable.ts
import {getOwnerDocument, isHTMLElement} from "./dom";
export const hasDisplayNone = (element: HTMLElement) =>
window.getComputedStyle(element).display === "none";
export const hasTabIndex = (element: HTMLElement) => element.hasAttribute("tabindex");
export const hasNegativeTabIndex = (element: HTMLElement) =>
hasTabIndex(element) && element.tabIndex === -1;
export function isDisabled(element: HTMLElement) {
return (
Boolean(element.getAttribute("disabled")) === true ||
Boolean(element.getAttribute("aria-disabled")) === true
);
}
export interface FocusableElement {
focus(options?: FocusOptions): void;
}
export function isInputElement(element: FocusableElement): element is HTMLInputElement {
return isHTMLElement(element) && element.localName === "input" && "select" in element;
}
export function isActiveElement(element: FocusableElement) {
const doc = isHTMLElement(element) ? getOwnerDocument(element) : document;
return doc.activeElement === (element as HTMLElement);
}
export function hasFocusWithin(element: HTMLElement) {
if (!document.activeElement) return false;
return element.contains(document.activeElement);
}
export function isHidden(element: HTMLElement) {
if (element.parentElement && isHidden(element.parentElement)) return true;
return element.hidden;
}
export function isContentEditable(element: HTMLElement) {
const value = element.getAttribute("contenteditable");
return value !== "false" && value != null;
}
export function isFocusable(element: HTMLElement) {
if (!isHTMLElement(element) || isHidden(element) || isDisabled(element)) {
return false;
}
const {localName} = element;
const focusableTags = ["input", "select", "textarea", "button"];
if (focusableTags.indexOf(localName) >= 0) return true;
const others = {
a: () => element.hasAttribute("href"),
audio: () => element.hasAttribute("controls"),
video: () => element.hasAttribute("controls"),
};
if (localName in others) {
return others[localName as keyof typeof others]();
}
if (isContentEditable(element)) return true;
return hasTabIndex(element);
}
export function isTabbable(element?: HTMLElement | null) {
if (!element) return false;
return isHTMLElement(element) && isFocusable(element) && !hasNegativeTabIndex(element);
}

35
pnpm-lock.yaml generated
View File

@ -312,6 +312,7 @@ importers:
'@nextui-org/shared-icons': workspace:*
'@nextui-org/shared-utils': workspace:*
'@nextui-org/system': workspace:*
'@nextui-org/test-utils': workspace:*
'@nextui-org/theme': workspace:*
'@react-aria/accordion': 3.0.0-alpha.15
'@react-aria/focus': ^3.11.0
@ -337,6 +338,7 @@ importers:
framer-motion: 10.6.0_react@18.2.0
devDependencies:
'@nextui-org/avatar': link:../avatar
'@nextui-org/test-utils': link:../../utilities/test-utils
'@react-types/accordion': 3.0.0-alpha.12_react@18.2.0
'@react-types/shared': 3.17.0_react@18.2.0
clean-package: 2.2.0
@ -545,39 +547,6 @@ importers:
clean-package: 2.2.0
react: 18.2.0
packages/components/collapse:
specifiers:
'@nextui-org/aria-utils': workspace:*
'@nextui-org/dom-utils': workspace:*
'@nextui-org/react-utils': workspace:*
'@nextui-org/shared-css': workspace:*
'@nextui-org/shared-utils': workspace:*
'@nextui-org/system': workspace:*
'@react-aria/accordion': 3.0.0-alpha.15
'@react-aria/focus': ^3.11.0
'@react-aria/utils': ^3.15.0
'@react-stately/tree': ^3.5.0
'@react-types/accordion': 3.0.0-alpha.12
'@react-types/shared': ^3.15.0
clean-package: 2.2.0
react: ^18.2.0
dependencies:
'@nextui-org/aria-utils': link:../../utilities/aria-utils
'@nextui-org/dom-utils': link:../../utilities/dom-utils
'@nextui-org/react-utils': link:../../utilities/react-utils
'@nextui-org/shared-css': link:../../utilities/shared-css
'@nextui-org/shared-utils': link:../../utilities/shared-utils
'@nextui-org/system': link:../../core/system
'@react-aria/accordion': 3.0.0-alpha.15_react@18.2.0
'@react-aria/focus': 3.11.0_react@18.2.0
'@react-aria/utils': 3.15.0_react@18.2.0
'@react-stately/tree': 3.5.0_react@18.2.0
devDependencies:
'@react-types/accordion': 3.0.0-alpha.12_react@18.2.0
'@react-types/shared': 3.17.0_react@18.2.0
clean-package: 2.2.0
react: 18.2.0
packages/components/drip:
specifiers:
'@nextui-org/dom-utils': workspace:*