mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
feat(tooltip): migrated to react-aria and tw
This commit is contained in:
parent
93eafd7738
commit
27f2ae1fab
@ -38,6 +38,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@nextui-org/system": "workspace:*",
|
||||
"@nextui-org/theme": "workspace:*",
|
||||
"@nextui-org/shared-utils": "workspace:*",
|
||||
"@nextui-org/shared-css": "workspace:*",
|
||||
"@nextui-org/dom-utils": "workspace:*"
|
||||
|
||||
@ -6,6 +6,7 @@ module.exports = {
|
||||
"../../button/stories/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../../spinner/stories/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../../code/stories/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../../tooltip/stories/*.stories.@(js|jsx|ts|tsx)",
|
||||
],
|
||||
staticDirs: ["../public"],
|
||||
addons: [
|
||||
|
||||
24
packages/components/tooltip/README.md
Normal file
24
packages/components/tooltip/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# @nextui-org/tooltip
|
||||
|
||||
A Quick description of the component
|
||||
|
||||
> This is an internal utility, not intended for public usage.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
yarn add @nextui-org/tooltip
|
||||
# or
|
||||
npm i @nextui-org/tooltip
|
||||
```
|
||||
|
||||
## Contribution
|
||||
|
||||
Yes please! See the
|
||||
[contributing guidelines](https://github.com/nextui-org/nextui/blob/master/CONTRIBUTING.md)
|
||||
for details.
|
||||
|
||||
## Licence
|
||||
|
||||
This project is licensed under the terms of the
|
||||
[MIT license](https://github.com/nextui-org/nextui/blob/master/LICENSE).
|
||||
72
packages/components/tooltip/__tests__/tooltip.test.tsx
Normal file
72
packages/components/tooltip/__tests__/tooltip.test.tsx
Normal file
@ -0,0 +1,72 @@
|
||||
import * as React from "react";
|
||||
import {render, fireEvent} from "@testing-library/react";
|
||||
import {Button} from "@nextui-org/button";
|
||||
|
||||
import {Tooltip} from "../src";
|
||||
|
||||
describe("Tooltip", () => {
|
||||
it("should throw error if no children is passed", () => {
|
||||
const spy = jest.spyOn(console, "warn").mockImplementation(() => {});
|
||||
|
||||
render(<Tooltip content="tooltip" />);
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should render correctly", () => {
|
||||
const wrapper = render(
|
||||
<Tooltip content="tooltip">
|
||||
<Button>Trigger</Button>
|
||||
</Tooltip>,
|
||||
);
|
||||
|
||||
expect(() => wrapper.unmount()).not.toThrow();
|
||||
});
|
||||
|
||||
it("ref should be forwarded", () => {
|
||||
const ref = React.createRef<HTMLDivElement>();
|
||||
|
||||
render(
|
||||
<Tooltip ref={ref} defaultOpen content="tooltip">
|
||||
<Button>Trigger</Button>
|
||||
</Tooltip>,
|
||||
);
|
||||
|
||||
expect(ref.current).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should hide the tooltip when pressing the escape key", () => {
|
||||
const onClose = jest.fn();
|
||||
|
||||
const wrapper = render(
|
||||
<Tooltip defaultOpen content={<p data-testid="content-test">tooltip</p>} onClose={onClose}>
|
||||
<Button>Trigger</Button>
|
||||
</Tooltip>,
|
||||
);
|
||||
|
||||
const content = wrapper.getByTestId("content-test");
|
||||
|
||||
fireEvent.keyDown(content, {key: "Escape"});
|
||||
expect(onClose).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("should still hide the tooltip when pressing the escape key if isDismissable is false", () => {
|
||||
const onClose = jest.fn();
|
||||
|
||||
const wrapper = render(
|
||||
<Tooltip
|
||||
defaultOpen
|
||||
content={<p data-testid="content-test">tooltip</p>}
|
||||
isDismissable={false}
|
||||
onClose={onClose}
|
||||
>
|
||||
<Button>Trigger</Button>
|
||||
</Tooltip>,
|
||||
);
|
||||
|
||||
const content = wrapper.getByTestId("content-test");
|
||||
|
||||
fireEvent.keyDown(content, {key: "Escape"});
|
||||
expect(onClose).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
11
packages/components/tooltip/clean-package.config.json
Normal file
11
packages/components/tooltip/clean-package.config.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"replace": {
|
||||
"main": "dist/index.cjs.js",
|
||||
"module": "dist/index.esm.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {"import": "./dist/index.esm.js", "require": "./dist/index.cjs.js"},
|
||||
"./package.json": "./package.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
67
packages/components/tooltip/package.json
Normal file
67
packages/components/tooltip/package.json
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "@nextui-org/tooltip",
|
||||
"version": "2.0.0-beta.1",
|
||||
"description": "A React Component for rendering dynamically positioned Tooltips",
|
||||
"keywords": [
|
||||
"tooltip"
|
||||
],
|
||||
"author": "Junior Garcia <jrgarciadev@gmail.com>",
|
||||
"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/tooltip"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/nextui-org/nextui/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsup src --dts",
|
||||
"build:fast": "tsup src",
|
||||
"dev": "yarn build:fast -- --watch",
|
||||
"clean": "rimraf dist .turbo",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"prepack": "clean-package",
|
||||
"postpack": "clean-package restore"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nextui-org/dom-utils": "workspace:*",
|
||||
"@nextui-org/shared-utils": "workspace:*",
|
||||
"@nextui-org/react-utils": "workspace:*",
|
||||
"@nextui-org/system": "workspace:*",
|
||||
"@nextui-org/theme": "workspace:*",
|
||||
"@nextui-org/aria-utils": "workspace:*",
|
||||
"@react-aria/focus": "^3.9.0",
|
||||
"@react-aria/overlays": "^3.11.0",
|
||||
"@react-aria/tooltip": "^3.3.4",
|
||||
"@react-stately/tooltip": "^3.2.4",
|
||||
"@react-aria/utils": "^3.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-types/overlays": "^3.6.5",
|
||||
"@react-types/tooltip": "^3.2.5",
|
||||
"@nextui-org/button": "workspace:*",
|
||||
"clean-package": "2.1.1",
|
||||
"react": "^17.0.2"
|
||||
},
|
||||
"tsup": {
|
||||
"clean": true,
|
||||
"target": "es2019",
|
||||
"format": [
|
||||
"cjs",
|
||||
"esm"
|
||||
]
|
||||
}
|
||||
}
|
||||
10
packages/components/tooltip/src/index.ts
Normal file
10
packages/components/tooltip/src/index.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import Tooltip from "./tooltip";
|
||||
|
||||
// export types
|
||||
export type {TooltipProps} from "./tooltip";
|
||||
|
||||
// export hooks
|
||||
export {useTooltip} from "./use-tooltip";
|
||||
|
||||
// export component
|
||||
export {Tooltip};
|
||||
59
packages/components/tooltip/src/tooltip.tsx
Normal file
59
packages/components/tooltip/src/tooltip.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import {forwardRef} from "@nextui-org/system";
|
||||
import {warn, __DEV__} from "@nextui-org/shared-utils";
|
||||
import {cloneElement, Children} from "react";
|
||||
import {OverlayContainer} from "@react-aria/overlays";
|
||||
import {CSSTransition} from "@nextui-org/react-utils";
|
||||
|
||||
import {UseTooltipProps, useTooltip} from "./use-tooltip";
|
||||
|
||||
export interface TooltipProps extends Omit<UseTooltipProps, "ref"> {}
|
||||
|
||||
const Tooltip = forwardRef<TooltipProps, "div">((props, ref) => {
|
||||
const {
|
||||
Component,
|
||||
children,
|
||||
content,
|
||||
mountOverlay,
|
||||
transitionProps,
|
||||
getTriggerProps,
|
||||
getTooltipProps,
|
||||
} = useTooltip({
|
||||
ref,
|
||||
...props,
|
||||
});
|
||||
|
||||
let trigger: React.ReactElement;
|
||||
|
||||
try {
|
||||
/**
|
||||
* Ensure tooltip has only one child node
|
||||
*/
|
||||
const child = Children.only(children) as React.ReactElement & {
|
||||
ref?: React.Ref<any>;
|
||||
};
|
||||
|
||||
trigger = cloneElement(child, getTriggerProps(child.props, child.ref));
|
||||
} catch (error) {
|
||||
trigger = <span />;
|
||||
warn("Tooltip must have only one child node. Please, check your code.");
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{trigger}
|
||||
{mountOverlay && (
|
||||
<OverlayContainer>
|
||||
<CSSTransition {...transitionProps}>
|
||||
<Component {...getTooltipProps()}>{content}</Component>
|
||||
</CSSTransition>
|
||||
</OverlayContainer>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
if (__DEV__) {
|
||||
Tooltip.displayName = "NextUI.Tooltip";
|
||||
}
|
||||
|
||||
export default Tooltip;
|
||||
211
packages/components/tooltip/src/use-tooltip.ts
Normal file
211
packages/components/tooltip/src/use-tooltip.ts
Normal file
@ -0,0 +1,211 @@
|
||||
import type {TooltipVariantProps} from "@nextui-org/theme";
|
||||
import type {AriaTooltipProps} from "@react-types/tooltip";
|
||||
import type {OverlayTriggerProps} from "@react-types/overlays";
|
||||
import type {CSSTransitionProps} from "@nextui-org/react-utils";
|
||||
import type {ReactNode} from "react";
|
||||
|
||||
import {useTooltipTriggerState} from "@react-stately/tooltip";
|
||||
import {mergeProps} from "@react-aria/utils";
|
||||
import {useTooltip as useReactAriaTooltip, useTooltipTrigger} from "@react-aria/tooltip";
|
||||
import {useOverlayPosition, useOverlay, AriaOverlayProps} from "@react-aria/overlays";
|
||||
import {HTMLNextUIProps, mapPropsVariants} from "@nextui-org/system";
|
||||
import {tooltip} from "@nextui-org/theme";
|
||||
import {ReactRef, mergeRefs} from "@nextui-org/shared-utils";
|
||||
import {useMemo, useRef, useState, useCallback} from "react";
|
||||
|
||||
export interface UseTooltipProps
|
||||
extends HTMLNextUIProps<"div", TooltipVariantProps>,
|
||||
AriaTooltipProps,
|
||||
AriaOverlayProps,
|
||||
OverlayTriggerProps {
|
||||
/**
|
||||
* Ref to the DOM node.
|
||||
*/
|
||||
ref?: ReactRef<HTMLElement | null>;
|
||||
children?: ReactNode;
|
||||
/**
|
||||
* The content of the tooltip.
|
||||
*/
|
||||
content?: string | React.ReactNode;
|
||||
/**
|
||||
* Whether the tooltip should be disabled, independent from the trigger.
|
||||
*/
|
||||
isDisabled?: boolean;
|
||||
/**
|
||||
* The delay time for the tooltip to show up.
|
||||
* @default 0
|
||||
*/
|
||||
delay?: number;
|
||||
/**
|
||||
* The additional offset applied along the main axis between the element and its
|
||||
* anchor element.
|
||||
* @default 7 (px)
|
||||
*/
|
||||
offset?: number;
|
||||
/**
|
||||
* Whether the element should flip its orientation (e.g. top to bottom or left to right) when
|
||||
* there is insufficient room for it to render completely.
|
||||
* @default true
|
||||
*/
|
||||
shouldFlip?: boolean;
|
||||
/**
|
||||
* By default, opens for both focus and hover. Can be made to open only for focus.
|
||||
*/
|
||||
trigger?: "focus";
|
||||
/**
|
||||
* The placement of the element with respect to its anchor element.
|
||||
* @default 'top'
|
||||
*/
|
||||
placement?: "start" | "end" | "right" | "left" | "top" | "bottom";
|
||||
/**
|
||||
* The placement padding that should be applied between the element and its
|
||||
* surrounding container.
|
||||
* @default 12
|
||||
*/
|
||||
containerPadding?: number;
|
||||
/** Handler that is called when the overlay should close. */
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
export function useTooltip(originalProps: UseTooltipProps) {
|
||||
const [props, variantProps] = mapPropsVariants(originalProps, tooltip.variantKeys);
|
||||
|
||||
const {
|
||||
ref,
|
||||
as,
|
||||
isOpen,
|
||||
content,
|
||||
children,
|
||||
defaultOpen,
|
||||
onOpenChange,
|
||||
isDisabled,
|
||||
trigger: triggerAction = "focus",
|
||||
shouldFlip = true,
|
||||
containerPadding = 12,
|
||||
placement: placementProp = "top",
|
||||
delay = 0,
|
||||
offset = 7,
|
||||
isDismissable = true,
|
||||
shouldCloseOnBlur = false,
|
||||
isKeyboardDismissDisabled = false,
|
||||
shouldCloseOnInteractOutside,
|
||||
className,
|
||||
onClose,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const Component = as || "div";
|
||||
|
||||
const state = useTooltipTriggerState({delay, isDisabled, isOpen, defaultOpen, onOpenChange});
|
||||
|
||||
const [exited, setExited] = useState(!state.isOpen);
|
||||
|
||||
const triggerRef = useRef<HTMLElement>(null);
|
||||
const overlayRef = useRef<HTMLElement>(null);
|
||||
const domRef = mergeRefs(overlayRef, ref);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
onClose?.();
|
||||
state.close();
|
||||
}, [state, onClose]);
|
||||
|
||||
const onEntered = useCallback(() => {
|
||||
setExited(false);
|
||||
}, []);
|
||||
|
||||
const onExited = useCallback(() => {
|
||||
setExited(true);
|
||||
}, []);
|
||||
|
||||
const {triggerProps, tooltipProps: triggerTooltipProps} = useTooltipTrigger(
|
||||
{
|
||||
delay,
|
||||
isDisabled,
|
||||
trigger: triggerAction,
|
||||
},
|
||||
state,
|
||||
triggerRef,
|
||||
);
|
||||
|
||||
const {tooltipProps} = useReactAriaTooltip(mergeProps(props, triggerTooltipProps), state);
|
||||
|
||||
const {
|
||||
overlayProps: positionProps,
|
||||
// arrowProps,
|
||||
// placement,
|
||||
} = useOverlayPosition({
|
||||
isOpen: state.isOpen,
|
||||
targetRef: triggerRef,
|
||||
placement: placementProp,
|
||||
overlayRef,
|
||||
offset,
|
||||
shouldFlip,
|
||||
containerPadding,
|
||||
});
|
||||
|
||||
const mountOverlay = (state.isOpen || !exited) && !isDisabled;
|
||||
|
||||
const {overlayProps} = useOverlay(
|
||||
{
|
||||
isOpen: state.isOpen,
|
||||
isDismissable: isDismissable && state.isOpen,
|
||||
onClose: handleClose,
|
||||
shouldCloseOnBlur,
|
||||
isKeyboardDismissDisabled,
|
||||
shouldCloseOnInteractOutside,
|
||||
},
|
||||
overlayRef,
|
||||
);
|
||||
|
||||
const transitionProps = useMemo<CSSTransitionProps>(
|
||||
() => ({
|
||||
clearTime: originalProps?.disableAnimation ? 0 : 100,
|
||||
enterTime: originalProps?.disableAnimation ? 0 : 250,
|
||||
leaveTime: originalProps?.disableAnimation ? 0 : 60,
|
||||
isVisible: state.isOpen,
|
||||
onEntered: onEntered,
|
||||
onExited: onExited,
|
||||
}),
|
||||
[originalProps?.disableAnimation, state.isOpen],
|
||||
);
|
||||
|
||||
const styles = useMemo(
|
||||
() =>
|
||||
tooltip({
|
||||
...variantProps,
|
||||
className,
|
||||
}),
|
||||
[variantProps, className],
|
||||
);
|
||||
|
||||
const getTriggerProps = useCallback(
|
||||
(props = {}, _ref = null) => ({
|
||||
...mergeProps(triggerProps, props),
|
||||
ref: mergeRefs(triggerRef, _ref),
|
||||
onPointerEnter: () => state.open(),
|
||||
onPointerLeave: () => !isDismissable && state.close(),
|
||||
}),
|
||||
[isDismissable, triggerRef, triggerProps],
|
||||
);
|
||||
|
||||
const getTooltipProps = useCallback(
|
||||
() => ({
|
||||
ref: domRef,
|
||||
className: styles,
|
||||
...mergeProps(tooltipProps, positionProps, overlayProps, otherProps),
|
||||
}),
|
||||
[domRef, styles, tooltipProps, positionProps, overlayProps, otherProps],
|
||||
);
|
||||
|
||||
return {
|
||||
Component,
|
||||
content,
|
||||
children,
|
||||
mountOverlay,
|
||||
transitionProps,
|
||||
getTriggerProps,
|
||||
getTooltipProps,
|
||||
};
|
||||
}
|
||||
|
||||
export type UseTooltipReturn = ReturnType<typeof useTooltip>;
|
||||
98
packages/components/tooltip/stories/tooltip.stories.tsx
Normal file
98
packages/components/tooltip/stories/tooltip.stories.tsx
Normal file
@ -0,0 +1,98 @@
|
||||
import React from "react";
|
||||
import {ComponentStory, ComponentMeta} from "@storybook/react";
|
||||
import {tooltip} from "@nextui-org/theme";
|
||||
import {Button} from "@nextui-org/button";
|
||||
|
||||
import {Tooltip, TooltipProps} from "../src";
|
||||
|
||||
export default {
|
||||
title: "Display/Tooltip",
|
||||
component: Tooltip,
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: {
|
||||
type: "select",
|
||||
options: ["solid", "bordered", "light", "flat", "shadow", "ghost"],
|
||||
},
|
||||
},
|
||||
color: {
|
||||
control: {
|
||||
type: "select",
|
||||
options: ["neutral", "foreground", "primary", "secondary", "success", "warning", "danger"],
|
||||
},
|
||||
},
|
||||
size: {
|
||||
control: {
|
||||
type: "select",
|
||||
options: ["xs", "sm", "md", "lg", "xl"],
|
||||
},
|
||||
},
|
||||
radius: {
|
||||
control: {
|
||||
type: "select",
|
||||
options: ["none", "base", "sm", "md", "lg", "xl", "full"],
|
||||
},
|
||||
},
|
||||
placement: {
|
||||
control: {
|
||||
type: "select",
|
||||
options: ["start", "end", "right", "left", "top", "bottom"],
|
||||
},
|
||||
},
|
||||
delay: {
|
||||
control: {
|
||||
type: "number",
|
||||
},
|
||||
},
|
||||
offset: {
|
||||
control: {
|
||||
type: "number",
|
||||
},
|
||||
},
|
||||
defaultOpen: {
|
||||
control: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
isDisabled: {
|
||||
control: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
disableAnimation: {
|
||||
control: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
children: {
|
||||
control: {
|
||||
disable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="flex items-center justify-center w-screen h-screen">
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
} as ComponentMeta<typeof Tooltip>;
|
||||
|
||||
const defaultProps = {
|
||||
...tooltip.defaultVariants,
|
||||
delay: 0,
|
||||
offset: 7,
|
||||
defaultOpen: false,
|
||||
isDisabled: false,
|
||||
disableAnimation: false,
|
||||
content: "I am a tooltip",
|
||||
};
|
||||
|
||||
const Template: ComponentStory<typeof Tooltip> = (args: TooltipProps) => <Tooltip {...args} />;
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
...defaultProps,
|
||||
children: <Button>Hover me</Button>,
|
||||
};
|
||||
9
packages/components/tooltip/tsconfig.json
Normal file
9
packages/components/tooltip/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@stitches/react": ["../../../node_modules/@stitches/react"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "index.ts"]
|
||||
}
|
||||
@ -7,3 +7,4 @@ export * from "./button-group";
|
||||
export * from "./drip";
|
||||
export * from "./spinner";
|
||||
export * from "./code";
|
||||
export * from "./tooltip";
|
||||
|
||||
25
packages/core/theme/src/components/snippet/index.ts
Normal file
25
packages/core/theme/src/components/snippet/index.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import {tv, type VariantProps} from "tailwind-variants";
|
||||
|
||||
/**
|
||||
* Snippet wrapper **Tailwind Variants** component
|
||||
*
|
||||
* const {base, svg} = snippet({...})
|
||||
*
|
||||
* @example
|
||||
* <div className={base())}>
|
||||
* <svg className={svg()}>
|
||||
* // drip svg content
|
||||
* </svg>
|
||||
* </div>
|
||||
*/
|
||||
const snippet = tv({
|
||||
slots: {
|
||||
base: "",
|
||||
svg: "",
|
||||
},
|
||||
});
|
||||
|
||||
export type SnippetVariantProps = VariantProps<typeof snippet>;
|
||||
export type SnippetSlots = keyof ReturnType<typeof snippet>;
|
||||
|
||||
export {snippet};
|
||||
221
packages/core/theme/src/components/tooltip/index.ts
Normal file
221
packages/core/theme/src/components/tooltip/index.ts
Normal file
@ -0,0 +1,221 @@
|
||||
import {tv, type VariantProps} from "tailwind-variants";
|
||||
|
||||
/**
|
||||
* Tooltip wrapper **Tailwind Variants** component
|
||||
*
|
||||
* const styles = tooltip({...})
|
||||
*
|
||||
* @example
|
||||
* <div>
|
||||
* <button>your trigger</button>
|
||||
* <div role="tooltip" className={styles} data-transition='enter/leave'>
|
||||
* // tooltip content
|
||||
* </div>
|
||||
* </div>
|
||||
*/
|
||||
const tooltip = tv({
|
||||
base: [
|
||||
"inline-flex",
|
||||
"flex-col",
|
||||
"items-center",
|
||||
"justify-center",
|
||||
"box-border",
|
||||
"animate-appearance-in",
|
||||
"data-[transition=leave]:animate-appearance-out",
|
||||
],
|
||||
variants: {
|
||||
variant: {
|
||||
solid: "",
|
||||
bordered: "border-2 !bg-transparent",
|
||||
light: "!bg-transparent",
|
||||
flat: "",
|
||||
shadow: "",
|
||||
},
|
||||
color: {
|
||||
neutral: "bg-neutral-300 dark:bg-neutral-700 text-neutral-800 dark:text-neutral-100",
|
||||
foreground: "bg-foreground text-foreground-dark dark:text-foreground-light",
|
||||
primary: "bg-primary text-white",
|
||||
secondary: "bg-secondary text-white",
|
||||
success: "bg-success text-success-800",
|
||||
warning: "bg-warning text-warning-800",
|
||||
danger: "bg-danger text-white",
|
||||
},
|
||||
size: {
|
||||
xs: "px-2 h-4 text-xs",
|
||||
sm: "px-3 h-6 text-sm",
|
||||
md: "px-4 h-8 text-base",
|
||||
lg: "px-6 h-10 text-lg",
|
||||
xl: "px-8 h-12 text-xl",
|
||||
},
|
||||
radius: {
|
||||
none: "rounded-none",
|
||||
base: "rounded",
|
||||
sm: "rounded-sm",
|
||||
md: "rounded-md",
|
||||
lg: "rounded-lg",
|
||||
xl: "rounded-xl",
|
||||
full: "rounded-full",
|
||||
},
|
||||
disableAnimation: {
|
||||
true: "animate-none",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "solid",
|
||||
color: "neutral",
|
||||
size: "sm",
|
||||
radius: "lg",
|
||||
},
|
||||
compoundVariants: [
|
||||
// shadow / color
|
||||
{
|
||||
variant: "shadow",
|
||||
color: "neutral",
|
||||
class: "shadow-lg shadow-neutral/40",
|
||||
},
|
||||
{
|
||||
variant: "shadow",
|
||||
color: "foreground",
|
||||
class: "shadow-lg shadow-foreground/40",
|
||||
},
|
||||
{
|
||||
variant: "shadow",
|
||||
color: "primary",
|
||||
class: "shadow-lg shadow-primary/40",
|
||||
},
|
||||
{
|
||||
variant: "shadow",
|
||||
color: "secondary",
|
||||
class: "shadow-lg shadow-secondary/40",
|
||||
},
|
||||
{
|
||||
variant: "shadow",
|
||||
color: "success",
|
||||
class: "shadow-lg shadow-success/40",
|
||||
},
|
||||
{
|
||||
variant: "shadow",
|
||||
color: "warning",
|
||||
class: "shadow-lg shadow-warning/40",
|
||||
},
|
||||
{
|
||||
variant: "shadow",
|
||||
color: "danger",
|
||||
class: "shadow-lg shadow-danger/40",
|
||||
},
|
||||
// bordered / color
|
||||
{
|
||||
variant: "bordered",
|
||||
color: "neutral",
|
||||
class: "border-neutral-300 dark:border-neutral-700 text-neutral-700 dark:text-neutral-100",
|
||||
},
|
||||
{
|
||||
variant: "bordered",
|
||||
color: "foreground",
|
||||
class: "border-foreground text-foreground dark:text-foreground-dark",
|
||||
},
|
||||
{
|
||||
variant: "bordered",
|
||||
color: "primary",
|
||||
class: "border-primary text-primary",
|
||||
},
|
||||
{
|
||||
variant: "bordered",
|
||||
color: "secondary",
|
||||
class: "border-secondary text-secondary",
|
||||
},
|
||||
{
|
||||
variant: "bordered",
|
||||
color: "success",
|
||||
class: "border-success text-success",
|
||||
},
|
||||
{
|
||||
variant: "bordered",
|
||||
color: "warning",
|
||||
class: "border-warning text-warning",
|
||||
},
|
||||
{
|
||||
variant: "bordered",
|
||||
color: "danger",
|
||||
class: "border-danger text-danger",
|
||||
},
|
||||
// flat / color
|
||||
{
|
||||
variant: "flat",
|
||||
color: "neutral",
|
||||
class: "bg-neutral-100 dark:bg-neutral-800 text-neutral-700 dark:text-neutral-100",
|
||||
},
|
||||
{
|
||||
variant: "flat",
|
||||
color: "foreground",
|
||||
class:
|
||||
"bg-foreground/20 text-foreground dark:bg-foreground-dark/20 dark:text-foreground-dark",
|
||||
},
|
||||
{
|
||||
variant: "flat",
|
||||
color: "primary",
|
||||
class: "bg-primary-50 dark:bg-primary-900 text-primary",
|
||||
},
|
||||
{
|
||||
variant: "flat",
|
||||
color: "secondary",
|
||||
class: "bg-secondary-50 dark:bg-secondary-900 text-secondary dark:text-secondary-400",
|
||||
},
|
||||
{
|
||||
variant: "flat",
|
||||
color: "success",
|
||||
class: "bg-success-50 dark:bg-success-900 text-success-600 dark:text-success",
|
||||
},
|
||||
{
|
||||
variant: "flat",
|
||||
color: "warning",
|
||||
class: "bg-warning-50 dark:bg-warning-900 text-warning-600 dark:text-warning",
|
||||
},
|
||||
{
|
||||
variant: "flat",
|
||||
color: "danger",
|
||||
class: "bg-danger-50 dark:bg-danger-900 text-danger dark:text-danger-400",
|
||||
},
|
||||
// light / color
|
||||
{
|
||||
variant: "light",
|
||||
color: "neutral",
|
||||
class: "text-neutral-700 dark:text-neutral-100",
|
||||
},
|
||||
{
|
||||
variant: "light",
|
||||
color: "foreground",
|
||||
class: "text-foreground dark:text-foreground-dark",
|
||||
},
|
||||
{
|
||||
variant: "light",
|
||||
color: "primary",
|
||||
class: "text-primary",
|
||||
},
|
||||
{
|
||||
variant: "light",
|
||||
color: "secondary",
|
||||
class: "text-secondary",
|
||||
},
|
||||
{
|
||||
variant: "light",
|
||||
color: "success",
|
||||
class: "text-success",
|
||||
},
|
||||
{
|
||||
variant: "light",
|
||||
color: "warning",
|
||||
class: "text-warning",
|
||||
},
|
||||
{
|
||||
variant: "light",
|
||||
color: "danger",
|
||||
class: "text-danger",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export type TooltipVariantProps = VariantProps<typeof tooltip>;
|
||||
export type TooltipSlots = keyof ReturnType<typeof tooltip>;
|
||||
|
||||
export {tooltip};
|
||||
@ -155,6 +155,8 @@ module.exports = plugin(
|
||||
"drip-expand": "drip-expand 350ms linear",
|
||||
"spinner-ease-spin": "spinner-spin 0.8s ease infinite",
|
||||
"spinner-linear-spin": "spinner-spin 0.8s linear infinite",
|
||||
"appearance-in": "appearance-in 250ms ease-out normal both",
|
||||
"appearance-out": "appearance-out 60ms ease-in normal both",
|
||||
},
|
||||
keyframes: {
|
||||
"spinner-spin": {
|
||||
@ -181,6 +183,33 @@ module.exports = plugin(
|
||||
opacity: 0,
|
||||
},
|
||||
},
|
||||
"appearance-in": {
|
||||
"0%": {
|
||||
opacity: 0,
|
||||
transform: "translateZ(0) scale(0.95)",
|
||||
},
|
||||
"60%": {
|
||||
opacity: 0.75,
|
||||
/* Avoid blurriness */
|
||||
backfaceVisibility: "hidden",
|
||||
webkitFontSmoothing: "antialiased",
|
||||
transform: "translateZ(0) scale(1.05)",
|
||||
},
|
||||
"100%": {
|
||||
opacity: 1,
|
||||
transform: "translateZ(0) scale(1)",
|
||||
},
|
||||
},
|
||||
"appearance-out": {
|
||||
"0%": {
|
||||
opacity: 1,
|
||||
transform: "scale(1)",
|
||||
},
|
||||
"100%": {
|
||||
opacity: 0,
|
||||
transform: "scale(0.5)",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -39,18 +39,19 @@
|
||||
"dependencies": {
|
||||
"@nextui-org/system": "workspace:*",
|
||||
"@react-aria/button": "^3.6.2",
|
||||
"@react-aria/focus": "^3.9.0",
|
||||
"@react-aria/interactions": "^3.12.0",
|
||||
"@react-aria/selection": "^3.11.0",
|
||||
"@react-aria/utils": "^3.14.0",
|
||||
"@react-stately/collections": "^3.4.4",
|
||||
"@react-aria/interactions": "^3.12.0",
|
||||
"@react-aria/focus": "^3.9.0",
|
||||
"@react-stately/tree": "^3.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-types/button": "^3.6.2",
|
||||
"@react-types/overlays": "^3.6.5",
|
||||
"@react-types/shared": "^3.15.0",
|
||||
"react": "^17.0.2",
|
||||
"clean-package": "2.1.1"
|
||||
"clean-package": "2.1.1",
|
||||
"react": "^17.0.2"
|
||||
},
|
||||
"tsup": {
|
||||
"clean": true,
|
||||
|
||||
@ -3,3 +3,4 @@ export * from "./collections";
|
||||
export * from "./utils";
|
||||
export * from "./interactions";
|
||||
export * from "./type-utils";
|
||||
export * from "./overlays";
|
||||
|
||||
73
packages/utilities/aria-utils/src/overlays/index.ts
Normal file
73
packages/utilities/aria-utils/src/overlays/index.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import {Placement, PlacementAxis} from "@react-types/overlays";
|
||||
|
||||
export type PopoverPlacement =
|
||||
| "bottom"
|
||||
| "bottom-left"
|
||||
| "bottom-right"
|
||||
| "top"
|
||||
| "top-left"
|
||||
| "top-right"
|
||||
| "left"
|
||||
| "left-top"
|
||||
| "left-bottom"
|
||||
| "right"
|
||||
| "right-top"
|
||||
| "right-bottom";
|
||||
|
||||
export const getAriaPlacement = (placement?: PopoverPlacement) => {
|
||||
if (!placement) {
|
||||
return "bottom" as Placement;
|
||||
}
|
||||
|
||||
return placement.replace("-", " ") as Placement;
|
||||
};
|
||||
|
||||
export const getPopoverPlacementFromAxis = (placementAxis?: PlacementAxis) => {
|
||||
if (!placementAxis) {
|
||||
return "bottom";
|
||||
}
|
||||
|
||||
return placementAxis.replace("-", " ") as PopoverPlacement;
|
||||
};
|
||||
|
||||
export const getPopoverPlacement = (ariaPlacement?: Placement) => {
|
||||
if (!ariaPlacement) {
|
||||
return "bottom" as Placement;
|
||||
}
|
||||
|
||||
return ariaPlacement.replace(" ", "-") as PopoverPlacement;
|
||||
};
|
||||
|
||||
export const getTransformOrigin = (placement?: PopoverPlacement) => {
|
||||
if (!placement) {
|
||||
return "bottom" as Placement;
|
||||
}
|
||||
switch (placement) {
|
||||
case "bottom":
|
||||
return "top center";
|
||||
case "top":
|
||||
return "bottom center";
|
||||
case "left":
|
||||
return "right center";
|
||||
case "right":
|
||||
return "left center";
|
||||
case "bottom-left":
|
||||
return "top left";
|
||||
case "bottom-right":
|
||||
return "top right";
|
||||
case "top-left":
|
||||
return "bottom left";
|
||||
case "top-right":
|
||||
return "bottom right";
|
||||
case "left-top":
|
||||
return "right top";
|
||||
case "left-bottom":
|
||||
return "right bottom";
|
||||
case "right-top":
|
||||
return "left top";
|
||||
case "right-bottom":
|
||||
return "left bottom";
|
||||
default:
|
||||
return "top center";
|
||||
}
|
||||
};
|
||||
@ -1,86 +1,97 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import type {FC, ReactNode, RefObject} from "react";
|
||||
|
||||
import React, {useEffect, useLayoutEffect, useState} from "react";
|
||||
import {clsx} from "@nextui-org/shared-utils";
|
||||
|
||||
interface CSSTransitionProps {
|
||||
visible?: boolean;
|
||||
childrenRef?: React.RefObject<HTMLElement>;
|
||||
export interface CSSTransitionProps {
|
||||
name?: string;
|
||||
isVisible?: boolean;
|
||||
enterTime?: number;
|
||||
leaveTime?: number;
|
||||
clearTime?: number;
|
||||
className?: string;
|
||||
name?: string;
|
||||
onExited?: () => void;
|
||||
onEntered?: () => void;
|
||||
children?: ReactNode;
|
||||
childrenRef?: RefObject<HTMLElement>;
|
||||
}
|
||||
|
||||
export const CSSTransition: React.FC<React.PropsWithChildren<CSSTransitionProps>> = ({
|
||||
children,
|
||||
childrenRef,
|
||||
visible = false,
|
||||
enterTime = 60,
|
||||
leaveTime = 60,
|
||||
clearTime = 60,
|
||||
className = "",
|
||||
name = "transition",
|
||||
onExited,
|
||||
onEntered,
|
||||
...props
|
||||
}) => {
|
||||
const [classes, setClasses] = useState<string>("");
|
||||
const [renderable, setRenderable] = useState<boolean>(visible);
|
||||
const CSSTransition: FC<CSSTransitionProps> = React.memo(
|
||||
({
|
||||
children,
|
||||
onExited,
|
||||
onEntered,
|
||||
className,
|
||||
childrenRef,
|
||||
enterTime = 60,
|
||||
leaveTime = 60,
|
||||
clearTime = 60,
|
||||
isVisible = false,
|
||||
name = "transition",
|
||||
...otherProps
|
||||
}) => {
|
||||
const [classes, setClasses] = useState<string>("");
|
||||
const [statusClassName, setStatusClassName] = useState("");
|
||||
const [renderable, setRenderable] = useState<boolean>(isVisible);
|
||||
|
||||
useEffect(() => {
|
||||
const statusClassName = visible ? "enter" : "leave";
|
||||
const time = visible ? enterTime : leaveTime;
|
||||
useLayoutEffect(() => {
|
||||
const statusClassName = isVisible ? "enter" : "leave";
|
||||
|
||||
if (visible && !renderable) {
|
||||
setRenderable(true);
|
||||
}
|
||||
if (isVisible && !renderable) setRenderable(true);
|
||||
|
||||
setClasses(`${name}-${statusClassName}`);
|
||||
setClasses(`${name}-${statusClassName}`);
|
||||
setStatusClassName(statusClassName);
|
||||
|
||||
// set class to active
|
||||
const timer = setTimeout(() => {
|
||||
setClasses(`${name}-${statusClassName} ${name}-${statusClassName}-active`);
|
||||
if (statusClassName === "leave") {
|
||||
onExited?.();
|
||||
} else {
|
||||
onEntered?.();
|
||||
}
|
||||
clearTimeout(timer);
|
||||
}, time);
|
||||
const time = isVisible ? enterTime : leaveTime;
|
||||
|
||||
// remove classess when animation over
|
||||
const clearClassesTimer = setTimeout(() => {
|
||||
if (!visible) {
|
||||
setClasses("");
|
||||
setRenderable(false);
|
||||
}
|
||||
clearTimeout(clearClassesTimer);
|
||||
}, time + clearTime);
|
||||
// set class to active
|
||||
const timer = setTimeout(() => {
|
||||
setClasses(`${name}-${statusClassName} ${name}-${statusClassName}-active`);
|
||||
setStatusClassName(`${statusClassName}-active`);
|
||||
if (statusClassName === "leave") {
|
||||
onExited?.();
|
||||
} else {
|
||||
onEntered?.();
|
||||
}
|
||||
clearTimeout(timer);
|
||||
}, time);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
clearTimeout(clearClassesTimer);
|
||||
};
|
||||
}, [visible, renderable]);
|
||||
// remove classess when animation over
|
||||
const clearClassesTimer = setTimeout(() => {
|
||||
if (!isVisible) {
|
||||
setClasses("");
|
||||
setRenderable(false);
|
||||
}
|
||||
clearTimeout(clearClassesTimer);
|
||||
}, time + clearTime);
|
||||
|
||||
// update children ref classes
|
||||
useEffect(() => {
|
||||
if (!childrenRef?.current) {
|
||||
return;
|
||||
}
|
||||
const classesArr = classes.split(" ");
|
||||
const refClassesArr = childrenRef.current.className.split(" ");
|
||||
const newRefClassesArr = refClassesArr.filter((item) => !item.includes(name));
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
clearTimeout(clearClassesTimer);
|
||||
};
|
||||
}, [isVisible, renderable]);
|
||||
|
||||
childrenRef.current.className = clsx(newRefClassesArr, classesArr);
|
||||
}, [childrenRef, classes]);
|
||||
// update children ref classes
|
||||
useEffect(() => {
|
||||
if (!childrenRef?.current) return;
|
||||
|
||||
if (!React.isValidElement(children) || !renderable) return null;
|
||||
const classesArr = classes.split(" ");
|
||||
const refClassesArr = childrenRef.current.className.split(" ");
|
||||
const newRefClassesArr = refClassesArr.filter((item) => !item.includes(name));
|
||||
|
||||
return React.cloneElement(children, {
|
||||
...props,
|
||||
className: clsx(children.props.className, className, !childrenRef?.current ? classes : ""),
|
||||
});
|
||||
};
|
||||
childrenRef.current.className = clsx(newRefClassesArr, classesArr);
|
||||
}, [childrenRef, classes]);
|
||||
|
||||
if (!React.isValidElement(children) || !renderable) return null;
|
||||
|
||||
return React.cloneElement(children, {
|
||||
...otherProps,
|
||||
"data-transition": statusClassName,
|
||||
className: clsx(children.props.className, className, !childrenRef?.current && classes),
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
CSSTransition.displayName = "NextUI.CSSTransition";
|
||||
|
||||
export {CSSTransition};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { {{capitalize componentName}} } from "./{{componentName}}";
|
||||
import {{capitalize componentName}} from "./{{componentName}}";
|
||||
|
||||
// export types
|
||||
export type { {{capitalize componentName}}Props } from "./{{componentName}}";
|
||||
|
||||
@ -32,7 +32,7 @@ export function use{{capitalize componentName}}(originalProps: Use{{capitalize c
|
||||
[variantProps, className],
|
||||
);
|
||||
|
||||
return {Component, as, styles, domRef, ...otherProps};
|
||||
return {Component, styles, domRef, ...otherProps};
|
||||
}
|
||||
|
||||
export type Use{{capitalize componentName}}Return = ReturnType<typeof use{{capitalize componentName}}>;
|
||||
|
||||
@ -35,7 +35,7 @@ export default {
|
||||
} as ComponentMeta<typeof {{capitalize componentName}}>;
|
||||
|
||||
const defaultProps = {
|
||||
...code.defaultVariants,
|
||||
...{{componentName}}.defaultVariants,
|
||||
};
|
||||
|
||||
const Template: ComponentStory<typeof {{capitalize componentName}}> = (args: {{capitalize componentName}}Props) => <{{capitalize componentName}} {...args} />;
|
||||
|
||||
78
pnpm-lock.yaml
generated
78
pnpm-lock.yaml
generated
@ -657,6 +657,7 @@ importers:
|
||||
'@nextui-org/shared-css': workspace:*
|
||||
'@nextui-org/shared-utils': workspace:*
|
||||
'@nextui-org/system': workspace:*
|
||||
'@nextui-org/theme': workspace:*
|
||||
clean-package: 2.1.1
|
||||
react: ^17.0.2
|
||||
dependencies:
|
||||
@ -664,6 +665,7 @@ importers:
|
||||
'@nextui-org/shared-css': link:../../utilities/shared-css
|
||||
'@nextui-org/shared-utils': link:../../utilities/shared-utils
|
||||
'@nextui-org/system': link:../../core/system
|
||||
'@nextui-org/theme': link:../../core/theme
|
||||
devDependencies:
|
||||
clean-package: 2.1.1
|
||||
react: 17.0.2
|
||||
@ -738,6 +740,43 @@ importers:
|
||||
storybook-dark-mode: 1.1.2
|
||||
tailwindcss: 3.2.6_postcss@8.4.21
|
||||
|
||||
packages/components/tooltip:
|
||||
specifiers:
|
||||
'@nextui-org/aria-utils': workspace:*
|
||||
'@nextui-org/button': workspace:*
|
||||
'@nextui-org/dom-utils': workspace:*
|
||||
'@nextui-org/react-utils': workspace:*
|
||||
'@nextui-org/shared-utils': workspace:*
|
||||
'@nextui-org/system': workspace:*
|
||||
'@nextui-org/theme': workspace:*
|
||||
'@react-aria/focus': ^3.9.0
|
||||
'@react-aria/overlays': ^3.11.0
|
||||
'@react-aria/tooltip': ^3.3.4
|
||||
'@react-aria/utils': ^3.14.0
|
||||
'@react-stately/tooltip': ^3.2.4
|
||||
'@react-types/overlays': ^3.6.5
|
||||
'@react-types/tooltip': ^3.2.5
|
||||
clean-package: 2.1.1
|
||||
react: ^17.0.2
|
||||
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-utils': link:../../utilities/shared-utils
|
||||
'@nextui-org/system': link:../../core/system
|
||||
'@nextui-org/theme': link:../../core/theme
|
||||
'@react-aria/focus': 3.10.1_react@17.0.2
|
||||
'@react-aria/overlays': 3.12.1_react@17.0.2
|
||||
'@react-aria/tooltip': 3.3.4_react@17.0.2
|
||||
'@react-aria/utils': 3.14.2_react@17.0.2
|
||||
'@react-stately/tooltip': 3.2.4_react@17.0.2
|
||||
devDependencies:
|
||||
'@nextui-org/button': link:../button
|
||||
'@react-types/overlays': 3.6.5_react@17.0.2
|
||||
'@react-types/tooltip': 3.2.5_react@17.0.2
|
||||
clean-package: 2.1.1
|
||||
react: 17.0.2
|
||||
|
||||
packages/components/user:
|
||||
specifiers:
|
||||
'@nextui-org/avatar': workspace:*
|
||||
@ -932,6 +971,7 @@ importers:
|
||||
'@react-stately/collections': ^3.4.4
|
||||
'@react-stately/tree': ^3.3.4
|
||||
'@react-types/button': ^3.6.2
|
||||
'@react-types/overlays': ^3.6.5
|
||||
'@react-types/shared': ^3.15.0
|
||||
clean-package: 2.1.1
|
||||
react: ^17.0.2
|
||||
@ -946,6 +986,7 @@ importers:
|
||||
'@react-stately/tree': 3.4.1_react@17.0.2
|
||||
devDependencies:
|
||||
'@react-types/button': 3.7.0_react@17.0.2
|
||||
'@react-types/overlays': 3.6.5_react@17.0.2
|
||||
'@react-types/shared': 3.16.0_react@17.0.2
|
||||
clean-package: 2.1.1
|
||||
react: 17.0.2
|
||||
@ -5745,6 +5786,21 @@ packages:
|
||||
react: 17.0.2
|
||||
dev: false
|
||||
|
||||
/@react-aria/tooltip/3.3.4_react@17.0.2:
|
||||
resolution: {integrity: sha512-KPDkDu7fquuUOOnNh9S7KfhPMwB1w9K+yLIFrYaj4iYSOLk/HH5TDkyiUQ7j5+B963D1fWlQjYFEGQ9o2KwO/Q==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
|
||||
dependencies:
|
||||
'@react-aria/focus': 3.10.1_react@17.0.2
|
||||
'@react-aria/interactions': 3.13.1_react@17.0.2
|
||||
'@react-aria/utils': 3.14.2_react@17.0.2
|
||||
'@react-stately/tooltip': 3.2.4_react@17.0.2
|
||||
'@react-types/shared': 3.16.0_react@17.0.2
|
||||
'@react-types/tooltip': 3.2.5_react@17.0.2
|
||||
'@swc/helpers': 0.4.14
|
||||
react: 17.0.2
|
||||
dev: false
|
||||
|
||||
/@react-aria/utils/3.14.0_react@17.0.2:
|
||||
resolution: {integrity: sha512-DHgmwNBNEhnb6DEYYAfbt99wprBqJJOBBeIpQ2g3+pxwlw4BZ+v4Qr+rDD0ZibWV0mYzt8zOhZ9StpId7iTF0Q==}
|
||||
peerDependencies:
|
||||
@ -6011,6 +6067,18 @@ packages:
|
||||
react: 17.0.2
|
||||
dev: false
|
||||
|
||||
/@react-stately/tooltip/3.2.4_react@17.0.2:
|
||||
resolution: {integrity: sha512-t7ksDRs9jKcOS25BVLM5cNCyzSCnzrin8OZ3AEmgeNxfiS58HhHbNxYk725hyGrbdpugQ03cRcJG70EZ6VgwDQ==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
|
||||
dependencies:
|
||||
'@react-stately/overlays': 3.4.4_react@17.0.2
|
||||
'@react-stately/utils': 3.5.2_react@17.0.2
|
||||
'@react-types/tooltip': 3.2.5_react@17.0.2
|
||||
'@swc/helpers': 0.4.14
|
||||
react: 17.0.2
|
||||
dev: false
|
||||
|
||||
/@react-stately/tree/3.3.4_react@17.0.2:
|
||||
resolution: {integrity: sha512-CBgXvwa9qYBsJuxrAiVgGnm48eSxLe/6OjPMwH1pWf4s383Mx73MbbN4fS0oWDeXBVgdqz5/Xg/p8nvPIvl3WQ==}
|
||||
peerDependencies:
|
||||
@ -6161,7 +6229,6 @@ packages:
|
||||
dependencies:
|
||||
'@react-types/shared': 3.16.0_react@17.0.2
|
||||
react: 17.0.2
|
||||
dev: false
|
||||
|
||||
/@react-types/radio/3.3.1_react@17.0.2:
|
||||
resolution: {integrity: sha512-q/x0kMvBsu6mH4bIkp/Jjrm9ff5y/p3UR0V4CmQFI7604gQd2Dt1dZMU/2HV9x70r1JfWRrDeRrVjUHVfFL5Vg==}
|
||||
@ -6206,6 +6273,15 @@ packages:
|
||||
react: 17.0.2
|
||||
dev: false
|
||||
|
||||
/@react-types/tooltip/3.2.5_react@17.0.2:
|
||||
resolution: {integrity: sha512-D4lN32JwQuA3JbCgcI26mgCkLHIj1WE8MTzf1McaasPkx7gVaqW+wfPyFwt99/Oo52TLvA/1oin78qePP67PSw==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
|
||||
dependencies:
|
||||
'@react-types/overlays': 3.6.5_react@17.0.2
|
||||
'@react-types/shared': 3.16.0_react@17.0.2
|
||||
react: 17.0.2
|
||||
|
||||
/@rushstack/eslint-patch/1.2.0:
|
||||
resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==}
|
||||
dev: true
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user