feat(components): checkbox component added, react-aria dependecies were separated

This commit is contained in:
Junior Garcia 2022-10-06 23:08:24 -03:00
parent 00b290060e
commit 3e6673269e
36 changed files with 2217 additions and 1425 deletions

View File

@ -34,19 +34,19 @@
"postpack": "clean-package restore"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-aria": ">=3.18.0"
"react": ">=16.8.0"
},
"dependencies": {
"@nextui-org/system": "workspace:*",
"@nextui-org/shared-utils": "workspace:*",
"@nextui-org/shared-css": "workspace:*",
"@nextui-org/dom-utils": "workspace:*"
"@nextui-org/dom-utils": "workspace:*",
"@react-aria/focus": "^3.9.0",
"@react-aria/utils": "^3.14.0"
},
"devDependencies": {
"@nextui-org/spacer": "workspace:*",
"@nextui-org/icons-utils": "workspace:*",
"react-aria": "3.18.0",
"clean-package": "2.1.1",
"react": "^17.0.2"
}

View File

@ -7,7 +7,8 @@ import type {
} from "@nextui-org/shared-utils";
import {useState, useEffect, useMemo} from "react";
import {useFocusRing, mergeProps} from "react-aria";
import {useFocusRing} from "@react-aria/focus";
import {mergeProps} from "@react-aria/utils";
import {HTMLNextUIProps, forwardRef} from "@nextui-org/system";
import {useDOMRef, IFocusRingAria} from "@nextui-org/dom-utils";
import {clsx, safeText, __DEV__} from "@nextui-org/shared-utils";

View File

@ -0,0 +1,24 @@
# @nextui-org/checkbox
A Quick description of the component
> This is an internal utility, not intended for public usage.
## Installation
```sh
yarn add @nextui-org/checkbox
# or
npm i @nextui-org/checkbox
```
## 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).

View File

@ -0,0 +1,130 @@
import * as React from "react";
import {render} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import {Checkbox} from "../src";
describe("Checkbox.Group", () => {
it("should render correctly", () => {
const wrapper = render(
<Checkbox.Group defaultValue={[]} label="Select cities">
<Checkbox value="sydney">Sydney</Checkbox>
<Checkbox value="buenos-aires">Buenos Aires</Checkbox>
</Checkbox.Group>,
);
expect(() => wrapper.unmount()).not.toThrow();
});
it("ref should be forwarded", () => {
const ref = React.createRef<HTMLDivElement>();
render(
<Checkbox.Group ref={ref} defaultValue={[]} label="Select cities">
<Checkbox value="sydney">Sydney</Checkbox>
<Checkbox value="buenos-aires">Buenos Aires</Checkbox>
</Checkbox.Group>,
);
expect(ref.current).not.toBeNull();
});
it("should work correctly with initial value", () => {
const {container} = render(
<Checkbox.Group defaultValue={["sydney"]} label="Select cities">
<Checkbox data-testid="first-checkbox" value="sydney">
Sydney
</Checkbox>
<Checkbox data-testid="second-checkbox" value="buenos-aires">
Buenos Aires
</Checkbox>
</Checkbox.Group>,
);
// check if the first checkbox is checked
expect(container.querySelector("[data-testid=first-checkbox] input")).toBeChecked();
// second checkbox should not be checked
expect(container.querySelector("[data-testid=second-checkbox] input")).not.toBeChecked();
});
it("should change value after click", () => {
let value = ["sydney"];
const {container} = render(
<Checkbox.Group
defaultValue={["sydney"]}
label="Select cities"
onChange={(val) => (value = val)}
>
<Checkbox data-testid="first-checkbox" value="sydney">
Sydney
</Checkbox>
<Checkbox data-testid="second-checkbox" value="buenos-aires">
Buenos Aires
</Checkbox>
</Checkbox.Group>,
);
const firstCheckbox = container.querySelector("[data-testid=first-checkbox] input");
const secondCheckbox = container.querySelector("[data-testid=second-checkbox] input");
expect(firstCheckbox).toBeChecked();
expect(secondCheckbox).not.toBeChecked();
secondCheckbox && userEvent.click(secondCheckbox);
expect(firstCheckbox).toBeChecked();
expect(secondCheckbox).toBeChecked();
expect(value).toEqual(["sydney", "buenos-aires"]);
});
it("should ignore events when disabled", () => {
const {container} = render(
<Checkbox.Group isDisabled defaultValue={["sydney"]} label="Select cities">
<Checkbox data-testid="first-checkbox" value="sydney">
Sydney
</Checkbox>
<Checkbox data-testid="second-checkbox" value="buenos-aires">
Buenos Aires
</Checkbox>
</Checkbox.Group>,
);
const firstCheckbox = container.querySelector("[data-testid=first-checkbox] input");
const secondCheckbox = container.querySelector("[data-testid=second-checkbox] input");
expect(firstCheckbox).toBeChecked();
expect(secondCheckbox).not.toBeChecked();
secondCheckbox && userEvent.click(secondCheckbox);
expect(firstCheckbox).toBeChecked();
expect(secondCheckbox).not.toBeChecked();
});
it("should work correctly with controlled value", () => {
let checked = ["sydney"];
const onChange = jest.fn((value) => {
checked = value;
});
const {container} = render(
<Checkbox.Group label="Select cities" value={checked} onChange={onChange}>
<Checkbox data-testid="first-checkbox" value="sydney">
Sydney
</Checkbox>
<Checkbox data-testid="second-checkbox" value="buenos-aires">
Buenos Aires
</Checkbox>
</Checkbox.Group>,
);
const secondCheckbox = container.querySelector("[data-testid=second-checkbox] input");
secondCheckbox && userEvent.click(secondCheckbox);
expect(onChange).toHaveBeenCalledTimes(1);
expect(checked).toEqual(["sydney", "buenos-aires"]);
});
});

View File

@ -0,0 +1,103 @@
import * as React from "react";
import {render} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import {Checkbox, CheckboxProps} from "../src";
describe("Checkbox", () => {
it("should render correctly", () => {
const wrapper = render(<Checkbox>Label</Checkbox>);
expect(() => wrapper.unmount()).not.toThrow();
});
it("ref should be forwarded", () => {
const ref = React.createRef<HTMLLabelElement>();
render(<Checkbox ref={ref} label="checkbox-test" />);
expect(ref.current).not.toBeNull();
});
it("should work correctly with initial value", () => {
let {container} = render(<Checkbox isSelected label="checkbox-test" />);
expect(container.querySelector("input")?.checked).toBe(true);
container = render(<Checkbox isSelected={false} label="checkbox-test" />).container;
expect(container.querySelector("input")?.checked).toBe(false);
});
it("should change value after click", () => {
const {container} = render(<Checkbox label="checkbox-test" />);
userEvent.click(container.querySelector("label")!);
expect(container.querySelector("input")?.checked).toBe(true);
});
it("should ignore events when disabled", () => {
const {container} = render(<Checkbox isDisabled label="checkbox-test" />);
userEvent.click(container.querySelector("label")!);
expect(container.querySelector("input")?.checked).toBe(false);
});
it("should work correctly with indeterminate value", () => {
const {container} = render(<Checkbox isIndeterminate label="checkbox-test" />);
expect(container.querySelector("input")?.indeterminate).toBe(true);
});
it('should work correctly with "onChange" prop', () => {
const onChange = jest.fn();
const {container} = render(<Checkbox label="checkbox-test" onChange={onChange} />);
userEvent.click(container.querySelector("label")!);
expect(onChange).toBeCalled();
});
it('should work correctly with "onFocus" prop', () => {
const onFocus = jest.fn();
const {container} = render(<Checkbox label="checkbox-test" onFocus={onFocus} />);
userEvent.click(container.querySelector("label")!);
expect(onFocus).toBeCalled();
});
it('should work correctly with "isRequired" prop', () => {
const {container} = render(<Checkbox isRequired label="checkbox-test" />);
expect(container.querySelector("input")?.required).toBe(true);
});
it("should work correctly with controlled value", () => {
const onChange = jest.fn();
const Component = (props: CheckboxProps) => {
const [value, setValue] = React.useState(false);
return (
<Checkbox
{...props}
isSelected={value}
onChange={(checked) => {
setValue(checked);
onChange(checked);
}}
/>
);
};
const {container} = render(<Component label="checkbox-test" onChange={onChange} />);
userEvent.click(container.querySelector("label")!);
expect(onChange).toBeCalled();
expect(container.querySelector("input")?.getAttribute("aria-checked")).toBe("true");
});
});

View File

@ -0,0 +1,3 @@
{ "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" } } }

View File

@ -0,0 +1,58 @@
{
"name": "@nextui-org/checkbox",
"version": "1.0.0-beta.11",
"description": "Checkboxes allow users to select multiple items from a list of individual items, or to mark one individual item as selected.",
"keywords": [
"checkbox"
],
"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/checkbox"
},
"bugs": {
"url": "https://github.com/nextui-org/nextui/issues"
},
"scripts": {
"build": "tsup src/index.ts --format=esm,cjs --dts",
"dev": "yarn build:fast -- --watch",
"clean": "rimraf dist .turbo",
"typecheck": "tsc --noEmit",
"build:fast": "tsup src/index.ts --format=esm,cjs",
"prepack": "clean-package",
"postpack": "clean-package restore"
},
"peerDependencies": {
"react": ">=16.8.0"
},
"dependencies": {
"@nextui-org/system": "workspace:*",
"@nextui-org/shared-utils": "workspace:*",
"@nextui-org/shared-css": "workspace:*",
"@nextui-org/dom-utils": "workspace:*",
"@react-aria/checkbox": "^3.6.0",
"@react-aria/focus": "^3.9.0",
"@react-aria/interactions": "^3.12.0",
"@react-aria/visually-hidden": "^3.5.0",
"@react-stately/checkbox": "^3.3.0",
"@react-stately/toggle": "^3.4.2",
"@react-aria/utils": "^3.14.0"
},
"devDependencies": {
"@react-types/checkbox": "^3.4.0",
"@react-types/shared": "^3.14.1",
"clean-package": "2.1.1",
"react": "^17.0.2"
}
}

View File

@ -0,0 +1,8 @@
import {createContext} from "@nextui-org/shared-utils";
import {ContextType} from "./use-checkbox-group";
export const [CheckboxGroupProvider, useCheckboxGroupContext] = createContext<ContextType>({
name: "CheckboxGroupContext",
strict: false,
});

View File

@ -0,0 +1,64 @@
import {styled} from "@nextui-org/system";
import {StyledCheckboxLabel} from "./checkbox.styles";
export const StyledCheckboxGroupContainer = styled("div", {
display: "flex",
flexDirection: "column",
variants: {
isRow: {
true: {
flexDirection: "row",
mt: 0,
[`& ${StyledCheckboxLabel}`]: {
mr: "$$checkboxSize",
},
},
false: {
mr: 0,
flexDirection: "column",
[`& ${StyledCheckboxLabel}:not(:first-child)`]: {
mt: "$$checkboxSize",
},
},
},
},
});
export const StyledCheckboxGroup = styled("div", {
display: "flex",
flexDirection: "column",
"& .nextui-checkbox-group-label": {
d: "block",
fontWeight: "$normal",
fontSize: "calc($$checkboxSize * 0.8)",
color: "$accents7",
mb: "$3",
},
variants: {
size: {
xs: {
$$checkboxSize: "$space$7",
},
sm: {
$$checkboxSize: "$space$8",
},
md: {
$$checkboxSize: "$space$9",
},
lg: {
$$checkboxSize: "$space$10",
},
xl: {
$$checkboxSize: "$space$11",
},
},
isDisabled: {
true: {
"& .nextui-checkbox-group-label": {
color: "$accents5",
},
},
},
},
});

View File

@ -0,0 +1,46 @@
import {forwardRef} from "@nextui-org/system";
import {useDOMRef} from "@nextui-org/dom-utils";
import {clsx, __DEV__} from "@nextui-org/shared-utils";
import {mergeProps} from "@react-aria/utils";
import {CheckboxGroupProvider} from "./checkbox-context";
import {StyledCheckboxGroup, StyledCheckboxGroupContainer} from "./checkbox-group.styles";
import {UseCheckboxGroupProps, useCheckboxGroup} from "./use-checkbox-group";
export interface CheckboxGroupProps extends UseCheckboxGroupProps {}
const CheckboxGroup = forwardRef<CheckboxGroupProps, "div">((props, ref) => {
const domRef = useDOMRef(ref);
const {children, orientation, groupProps, labelProps, label, context, className, ...otherProps} =
useCheckboxGroup(props);
return (
<StyledCheckboxGroup
ref={domRef}
className={clsx("nextui-checkbox-group", className)}
{...mergeProps(groupProps, otherProps)}
>
{label && (
<label className="nextui-checkbox-group-label" {...labelProps}>
{label}
</label>
)}
<StyledCheckboxGroupContainer
className="nextui-checkbox-group-items"
isRow={orientation === "horizontal"}
role="presentation"
>
<CheckboxGroupProvider value={context}>{children}</CheckboxGroupProvider>
</StyledCheckboxGroupContainer>
</StyledCheckboxGroup>
);
});
if (__DEV__) {
CheckboxGroup.displayName = "NextUI.CheckboxGroup";
}
CheckboxGroup.toString = () => ".nextui-checkbox-group";
export default CheckboxGroup;

View File

@ -0,0 +1,544 @@
import {styled} from "@nextui-org/system";
import {cssFocusVisible} from "@nextui-org/shared-css";
export const StyledCheckboxLabel = styled("label", {
$$checkboxBorderColor: "$colors$border",
$$checkboxBorderRadius: "$radii$squared",
d: "inline-flex",
jc: "flex-start",
ai: "center",
position: "relative",
w: "auto",
cursor: "pointer",
zIndex: "$1",
opacity: 1,
transition: "opacity 0.25s ease",
"@motion": {
transition: "none",
},
variants: {
size: {
xs: {
$$checkboxSize: "$space$7",
},
sm: {
$$checkboxSize: "$space$8",
},
md: {
$$checkboxSize: "$space$9",
},
lg: {
$$checkboxSize: "$space$10",
},
xl: {
$$checkboxSize: "$space$11",
},
},
isDisabled: {
true: {
opacity: 0.75,
cursor: "not-allowed",
},
},
disableAnimation: {
true: {
transition: "none",
},
},
},
});
export const StyledCheckboxMask = styled("div", {
$$checkboxMaskTransition:
"transform 0.25s ease 0s, opacity 0.25s ease 0s, background 0.25s ease 0s, border-color 0.25s ease 0s",
size: "100%",
position: "absolute",
pe: "none",
boxSizing: "border-box",
dflex: "center",
zIndex: "-$1",
br: "inherit",
color: "$$checkboxBorderColor",
"&:before": {
content: "",
position: "absolute",
top: "0px",
left: "0px",
size: "100%",
br: "inherit",
transition: "$$checkboxMaskTransition",
zIndex: "-$1",
border: "$borderWeights$normal solid currentColor",
boxSizing: "border-box",
},
"&:after": {
content: "",
position: "absolute",
top: "0px",
left: "0px",
size: "100%",
bg: "$$checkboxColor",
scale: 0.5,
br: "inherit",
opacity: 0,
transition: "$$checkboxMaskTransition",
zIndex: "-$1",
},
"@motion": {
"&:before": {
transition: "none",
},
"&:after": {
transition: "none",
},
},
variants: {
isChecked: {
true: {
"&:before": {
opacity: 0,
scale: 1.2,
},
"&:after": {
opacity: 1,
scale: 1,
},
},
},
isIndeterminate: {
true: {
"&:before": {
opacity: 0,
scale: 1.2,
},
"&:after": {
opacity: 1,
scale: 1,
},
},
},
disableAnimation: {
true: {
"&:before": {
transition: "none",
},
"&:after": {
transition: "none",
},
},
},
},
});
export const StyledCheckboxText = styled("span", {
position: "relative",
dflex: "center",
color: "$text",
opacity: 1,
pl: "calc($$checkboxSize * 0.57)",
ln: "$$checkboxSize",
fontSize: "$$checkboxSize",
us: "none",
transition: "opacity 0.25s ease 0s",
"@motion": {
transition: "none",
"&:before": {
transition: "none",
},
},
variants: {
color: {
default: {
color: "$text",
},
primary: {
color: "$primary",
},
secondary: {
color: "$secondary",
},
success: {
color: "$success",
},
warning: {
color: "$warning",
},
error: {
color: "$error",
},
},
lineThrough: {
true: {
"&:before": {
content: "",
position: "absolute",
width: "0px",
height: "2px",
background: "$text",
transition: "width 0.25s ease 0s",
},
},
},
isChecked: {
true: {
"&:before": {
opacity: 0.8,
},
},
},
isDisabled: {
true: {
color: "$accents5",
},
},
disableAnimation: {
true: {
transition: "none",
"&:before": {
transition: "none",
},
},
},
},
compoundVariants: [
{
lineThrough: true,
isChecked: true,
css: {
opacity: 0.6,
"&:before": {
w: "calc(100% - 10px)",
},
},
},
],
});
export const StyledCheckboxContainer = styled(
"div",
{
br: "$$checkboxBorderRadius",
position: "relative",
sizeMin: "$$checkboxSize",
transition: "box-shadow 0.25s ease",
zIndex: "$1",
".nextui-checkbox-input": {
position: "absolute",
width: "100%",
height: "100%",
top: "0px",
left: "0px",
margin: "0px",
padding: "0px",
opacity: 0,
zIndex: "$1",
cursor: "pointer",
"&:disabled": {
cursor: "not-allowed",
},
},
"@motion": {
transition: "none",
},
variants: {
color: {
default: {
$$checkboxColor: "$colors$primary",
$$checkboxColorHover: "$colors$primarySolidHover",
},
primary: {
$$checkboxColor: "$colors$primary",
$$checkboxColorHover: "$colors$primarySolidHover",
},
secondary: {
$$checkboxColor: "$colors$secondary",
$$checkboxColorHover: "$colors$secondarySolidHover",
},
success: {
$$checkboxColor: "$colors$success",
$$checkboxColorHover: "$colors$successSolidHover",
},
warning: {
$$checkboxColor: "$colors$warning",
$$checkboxColorHover: "$colors$warningSolidHover",
},
error: {
$$checkboxColor: "$colors$error",
$$checkboxColorHover: "$colors$errorSolidHover",
},
gradient: {
$$checkboxColor: "$colors$gradient",
$$checkboxColorHover: "$colors$gradient",
},
},
isRounded: {
true: {
$$checkboxBorderRadius: "$radii$pill",
},
},
isDisabled: {
true: {
opacity: 0.4,
cursor: "not-allowed",
},
},
disableAnimation: {
true: {
transition: "none",
},
},
isHovered: {
true: {
[`& ${StyledCheckboxMask}:before`]: {
bg: "$$checkboxBorderColor",
border: "2px solid transparent",
},
[`& ${StyledCheckboxMask}:after`]: {
bg: "$$checkboxColorHover",
},
},
},
},
},
cssFocusVisible,
);
export const StyledIconCheck = styled("i", {
size: "$$checkboxSize",
dflex: "center",
br: "inherit",
opacity: 0,
zIndex: "$2",
transition: "transform 0.35s ease",
"&:after": {
content: "",
opacity: 0,
position: "relative",
width: "10px",
height: "2px",
br: "1px",
background: "$white",
display: "block",
},
"@motion": {
transition: "none",
"&:after": {
transition: "none",
},
},
variants: {
isIndeterminate: {
true: {
opacity: 1,
transform: "rotate(0deg)",
width: "auto",
height: "auto",
margin: "0px",
"&:after": {
opacity: 1,
},
},
false: {
width: "8px",
height: "14px",
display: "block",
position: "relative",
marginTop: "-4px",
},
},
size: {
xs: {
marginTop: "-2px",
transform: "rotate(45deg) scale(0.5)",
},
sm: {
marginTop: "-2px",
transform: "rotate(45deg) scale(0.5)",
},
md: {
transform: "rotate(45deg) scale(0.8)",
},
lg: {
transform: "rotate(45deg)",
},
xl: {
transform: "rotate(45deg)",
},
},
isChecked: {
true: {
opacity: 1,
},
},
disableAnimation: {
true: {
transition: "none",
"&:after": {
transition: "none",
},
},
},
},
compoundVariants: [
// isIndeterminate && xs size
{
isIndeterminate: true,
size: "xs",
css: {
scale: "0.5",
},
},
// isIndeterminate && sm size
{
isIndeterminate: true,
size: "sm",
css: {
scale: "0.5",
},
},
// isIndeterminate && md size
{
isIndeterminate: true,
size: "md",
css: {
scale: "0.8",
},
},
// isIndeterminate && lg size
{
isIndeterminate: true,
size: "lg",
css: {
transform: "none",
},
},
// isIndeterminate && xl size
{
isIndeterminate: true,
size: "lg",
css: {
transform: "none",
},
},
],
});
export const StyledIconCheckFirstLine = styled("div", {
content: "",
background: "transparent",
position: "absolute",
width: "8px",
height: "1px",
br: "5px",
zIndex: "$1",
bottom: "0px",
"&:after": {
content: "",
position: "absolute",
left: "0px",
width: "0%",
height: "2px",
background: "$white",
br: "5px 0px 0px 5px",
},
"@motion": {
"&:after": {
transition: "none",
},
},
variants: {
isIndeterminate: {
true: {
display: "none",
},
},
isChecked: {
true: {
"&:after": {
width: "100%",
transition: "width 0.25s ease 0.1s",
},
},
},
disableAnimation: {
true: {
"&:after": {
transition: "none",
},
},
},
},
compoundVariants: [
// checked && disableAnimation
{
isChecked: true,
disableAnimation: true,
css: {
"&:after": {
transition: "none",
},
},
},
],
});
export const StyledIconCheckSecondLine = styled("div", {
content: "",
position: "absolute",
h: "13px",
br: "5px",
bottom: "0",
right: "0",
zIndex: "$1",
background: "transparent",
width: "2px",
"&:after": {
content: "",
position: "absolute",
width: "2px",
height: "0%",
background: "$white",
left: "0px",
bottom: "0px",
br: "5px 5px 0px 0px",
},
"@motion": {
"&:after": {
transition: "none",
},
},
variants: {
isIndeterminate: {
true: {
display: "none",
},
},
isChecked: {
true: {
"&:after": {
height: "100%",
transition: "height 0.2s ease 0.3s",
},
},
},
disableAnimation: {
true: {
"&:after": {
transition: "none",
},
},
},
},
compoundVariants: [
// checked && disableAnimation
{
isChecked: true,
disableAnimation: true,
css: {
"&:after": {
transition: "none",
},
},
},
],
});

View File

@ -0,0 +1,132 @@
import {forwardRef} from "@nextui-org/system";
import {useFocusableRef} from "@nextui-org/dom-utils";
import {clsx, __DEV__} from "@nextui-org/shared-utils";
import {mergeProps} from "@react-aria/utils";
import {VisuallyHidden} from "@react-aria/visually-hidden";
import {
StyledCheckboxLabel,
StyledCheckboxContainer,
StyledCheckboxMask,
StyledCheckboxText,
StyledIconCheck,
StyledIconCheckFirstLine,
StyledIconCheckSecondLine,
} from "./checkbox.styles";
import {UseCheckboxProps, useCheckbox} from "./use-checkbox";
import CheckboxGroup from "./checkbox-group";
export interface CheckboxProps extends UseCheckboxProps {}
type CompoundCheckbox = {
Group: typeof CheckboxGroup;
};
const Checkbox = forwardRef<CheckboxProps, "label", CompoundCheckbox>((props, ref) => {
const {className, as, css, children, label, ...checkboxProps} = props;
const {
size,
color,
state,
labelColor,
isRounded,
isHovered,
isFocusVisible,
lineThrough,
disableAnimation,
isIndeterminate,
inputRef,
inputProps,
pressProps,
hoverProps,
focusProps,
containerCss,
...otherProps
} = useCheckbox({...checkboxProps, children: children ?? label});
const domRef = useFocusableRef(ref, inputRef);
return (
<StyledCheckboxLabel
ref={domRef}
as={as}
className={clsx("nextui-checkbox", className)}
data-state={state}
{...mergeProps(hoverProps, pressProps, otherProps)}
css={css}
disableAnimation={disableAnimation}
isDisabled={inputProps.disabled}
size={size}
>
<VisuallyHidden>
<input
ref={inputRef}
className="nextui-checkbox-input"
{...mergeProps(inputProps, focusProps)}
/>
</VisuallyHidden>
<StyledCheckboxContainer
className="nextui-checkbox-container"
color={color}
css={containerCss}
disableAnimation={disableAnimation}
isDisabled={inputProps.disabled}
isFocusVisible={isFocusVisible}
isHovered={isHovered}
isRounded={isRounded}
{...focusProps}
>
<StyledCheckboxMask
className="nextui-checkbox-mask"
disableAnimation={disableAnimation}
isChecked={inputProps.checked}
isIndeterminate={isIndeterminate}
>
<StyledIconCheck
className="nextui-icon-check"
disableAnimation={disableAnimation}
isChecked={inputProps.checked}
isIndeterminate={isIndeterminate}
size={size}
>
<StyledIconCheckFirstLine
className="nextui-icon-check-line1"
disableAnimation={disableAnimation}
isChecked={inputProps.checked}
isIndeterminate={isIndeterminate}
/>
<StyledIconCheckSecondLine
className="nextui-icon-check-line2"
disableAnimation={disableAnimation}
isChecked={inputProps.checked}
isIndeterminate={isIndeterminate}
/>
</StyledIconCheck>
</StyledCheckboxMask>
</StyledCheckboxContainer>
{(children || label) && (
<StyledCheckboxText
className="nextui-checkbox-text"
color={labelColor}
disableAnimation={disableAnimation}
isChecked={inputProps.checked}
isDisabled={inputProps.disabled}
lineThrough={lineThrough}
>
{children || label}
</StyledCheckboxText>
)}
</StyledCheckboxLabel>
);
});
Checkbox.Group = CheckboxGroup;
if (__DEV__) {
Checkbox.displayName = "NextUI.Checkbox";
}
Checkbox.toString = () => ".nextui-checkbox";
export default Checkbox;

View File

@ -0,0 +1,6 @@
// export types
export type {CheckboxProps} from "./checkbox";
export type {CheckboxGroupProps} from "./checkbox-group";
// export component
export {default as Checkbox} from "./checkbox";

View File

@ -0,0 +1,69 @@
import type {AriaCheckboxGroupProps} from "@react-types/checkbox";
import type {NormalSizes, NormalColors, SimpleColors} from "@nextui-org/shared-utils";
import type {Orientation} from "@react-types/shared";
import type {HTMLNextUIProps} from "@nextui-org/system";
import {useCheckboxGroup as useReactAriaCheckboxGroup} from "@react-aria/checkbox";
import {CheckboxGroupState, useCheckboxGroupState} from "@react-stately/checkbox";
export interface UseCheckboxGroupProps extends HTMLNextUIProps<"div", AriaCheckboxGroupProps> {
/**
* The color of the checkboxes.
* @default "default"
*/
color?: NormalColors;
/**
* The color of the label.
* @default "default"
*/
labelColor?: SimpleColors;
/**
* The size of the checkboxes.
* @default "md"
*/
size?: NormalSizes;
/**
* The axis the checkbox group items should align with.
* @default "vertical"
*/
orientation?: Orientation;
}
export type ContextType = {
groupState: CheckboxGroupState;
color?: UseCheckboxGroupProps["color"];
labelColor?: UseCheckboxGroupProps["labelColor"];
size?: UseCheckboxGroupProps["size"];
};
export function useCheckboxGroup(props: UseCheckboxGroupProps) {
const {
size = "md",
color = "default",
labelColor = "default",
orientation = "vertical",
...otherProps
} = props;
const groupState = useCheckboxGroupState(otherProps);
const {labelProps, groupProps} = useReactAriaCheckboxGroup(otherProps, groupState);
const context = {
size,
color,
labelColor,
groupState,
};
return {
size,
orientation,
labelProps,
groupProps,
context,
...otherProps,
};
}
export type UseCheckboxGroupReturn = ReturnType<typeof useCheckboxGroup>;

View File

@ -0,0 +1,166 @@
import type {AriaCheckboxProps} from "@react-types/checkbox";
import type {HTMLNextUIProps, CSS} from "@nextui-org/system";
import type {IPressResult, IFocusRingAria} from "@nextui-org/dom-utils";
import {useMemo, useRef} from "react";
import {useToggleState} from "@react-stately/toggle";
import {useHover, usePress} from "@react-aria/interactions";
import {useFocusRing} from "@react-aria/focus";
import {NormalSizes, NormalColors, SimpleColors, __DEV__} from "@nextui-org/shared-utils";
import {
useCheckbox as useReactAriaCheckbox,
useCheckboxGroupItem as useReactAriaCheckboxGroupItem,
} from "@react-aria/checkbox";
import {useCheckboxGroupContext} from "./checkbox-context";
export interface UseCheckboxProps extends HTMLNextUIProps<"label", AriaCheckboxProps> {
/**
* The content to display as the label.
*/
label?: string;
/**
* The color of the checkbox.
* @default "default"
*/
color?: NormalColors;
/**
* The color of the label.
* @default "default"
*/
labelColor?: SimpleColors;
/**
* The size of the checkbox.
* @default "md"
*/
size?: NormalSizes;
/**
* Whether the checkbox is rounded.
* @default false
*/
isRounded?: boolean;
/**
* Line in the middle of the label when the `Checkbox` is checked
* @default false
*/
lineThrough?: boolean;
/**
* Whether the checkbox has animations.
* @default false
*/
disableAnimation?: boolean;
/**
* Override checkbox container CSS style
*/
containerCss?: CSS;
}
export function useCheckbox(props: UseCheckboxProps) {
const groupContext = useCheckboxGroupContext();
const {
size = groupContext?.size ?? "md",
color = groupContext?.color ?? "default",
labelColor = groupContext?.labelColor ?? "default",
lineThrough,
isSelected,
value = "",
isRounded = false,
isRequired = false,
disableAnimation = false,
isIndeterminate = false,
defaultSelected,
onChange,
containerCss,
...otherProps
} = props;
if (groupContext && __DEV__) {
const warningMessage =
"The Checkbox.Group is being used, `%s` will be ignored. Use the `%s` of the Checkbox.Group instead.";
if (isSelected) {
// eslint-disable-next-line no-console
console.warn(warningMessage, "isSelected", "value");
}
if (defaultSelected) {
// eslint-disable-next-line no-console
console.warn(warningMessage, "defaultSelected", "defaultValue");
}
}
const inputRef = useRef<HTMLInputElement>(null);
const ariaCheckboxProps = useMemo(() => {
return {
...otherProps,
value,
defaultSelected,
isSelected,
isIndeterminate,
isRequired,
onChange,
};
}, [isIndeterminate, otherProps]);
const {inputProps} = groupContext
? // eslint-disable-next-line
useReactAriaCheckboxGroupItem(
{
...ariaCheckboxProps,
validationState: otherProps.validationState,
},
groupContext.groupState,
inputRef,
)
: useReactAriaCheckbox(ariaCheckboxProps, useToggleState(ariaCheckboxProps), inputRef); // eslint-disable-line
if (isRequired) {
inputProps.required = true;
}
const {hoverProps, isHovered} = useHover({
isDisabled: inputProps.disabled,
});
// TODO: Event's propagation wasn't stopped https://github.com/adobe/react-spectrum/issues/2383
const {pressProps}: IPressResult<UseCheckboxProps> = usePress({
isDisabled: inputProps.disabled,
});
const {focusProps, isFocusVisible}: IFocusRingAria<UseCheckboxProps> = useFocusRing({
autoFocus: inputProps.autoFocus,
});
const state = useMemo(() => {
if (isHovered) return "hovered";
return isIndeterminate && inputProps.checked
? "mixed"
: inputProps.checked
? "checked"
: "uncheked";
}, [isHovered, isIndeterminate, inputProps.checked]);
return {
size,
color,
state,
labelColor,
isRounded,
lineThrough,
disableAnimation,
isIndeterminate,
isFocusVisible,
isHovered,
inputRef,
inputProps,
pressProps,
hoverProps,
focusProps,
containerCss,
...otherProps,
};
}
export type UseCheckboxReturn = ReturnType<typeof useCheckbox>;

View File

@ -0,0 +1,243 @@
import React from "react";
import {Meta} from "@storybook/react";
import {Checkbox} from "../src";
export default {
title: "Inputs/Checkbox",
component: Checkbox,
} as Meta;
export const Default = () => {
return (
<Checkbox color="default" labelColor="default" size="md">
Option
</Checkbox>
);
};
export const Label = () => {
return <Checkbox color="default" label="Option" labelColor="default" size="md" />;
};
export const Disabled = () => (
<div style={{display: "flex", flexDirection: "column"}}>
<Checkbox defaultSelected size="xl">
Enabled
</Checkbox>
<br />
<Checkbox defaultSelected isDisabled size="xl">
Disabled
</Checkbox>
</div>
);
export const Sizes = () => (
<div style={{display: "flex", flexDirection: "column"}}>
<Checkbox defaultSelected size="xs">
mini
</Checkbox>
<br />
<Checkbox defaultSelected size="sm">
small
</Checkbox>
<br />
<Checkbox defaultSelected size="md">
medium
</Checkbox>
<br />
<Checkbox defaultSelected size="lg">
large
</Checkbox>
<br />
<Checkbox defaultSelected size="xl">
xlarge
</Checkbox>
</div>
);
export const Colors = () => (
<div style={{display: "flex", flexDirection: "column"}}>
<Checkbox defaultSelected color="primary">
Primary
</Checkbox>
<br />
<Checkbox defaultSelected color="secondary">
Secondary
</Checkbox>
<br />
<Checkbox defaultSelected color="success">
Success
</Checkbox>
<br />
<Checkbox defaultSelected color="warning">
Warning
</Checkbox>
<br />
<Checkbox defaultSelected color="error">
Error
</Checkbox>
</div>
);
export const LabelColors = () => (
<div style={{display: "flex", flexDirection: "column"}}>
<Checkbox defaultSelected color="primary" labelColor="primary">
Primary
</Checkbox>
<br />
<Checkbox defaultSelected color="secondary" labelColor="secondary">
Secondary
</Checkbox>
<br />
<Checkbox defaultSelected color="success" labelColor="success">
Success
</Checkbox>
<br />
<Checkbox defaultSelected color="warning" labelColor="warning">
Warning
</Checkbox>
<br />
<Checkbox defaultSelected color="error" labelColor="error">
Error
</Checkbox>
</div>
);
export const Rounded = () => (
<div style={{display: "flex", flexDirection: "column"}}>
<Checkbox defaultSelected isRounded color="primary">
Primary
</Checkbox>
<br />
<Checkbox defaultSelected isRounded color="secondary">
Secondary
</Checkbox>
<br />
<Checkbox defaultSelected isRounded color="success">
Success
</Checkbox>
<br />
<Checkbox defaultSelected isRounded color="warning">
Warning
</Checkbox>
<br />
<Checkbox defaultSelected isRounded color="error">
Error
</Checkbox>
</div>
);
export const Indeterminate = () => {
return (
<Checkbox defaultSelected isIndeterminate color="primary" size="lg">
Option
</Checkbox>
);
};
export const LineThrough = () => {
return (
<Checkbox defaultSelected lineThrough color="primary" size="lg">
Option
</Checkbox>
);
};
export const Controlled = () => {
const [selected, setSelected] = React.useState<boolean>(true);
const [groupSelected, setGroupSelected] = React.useState<string[]>(["buenos-aires", "sydney"]);
React.useEffect(() => {
// eslint-disable-next-line no-console
console.log("Checkbox ", selected);
}, [selected]);
React.useEffect(() => {
// eslint-disable-next-line no-console
console.log("CheckboxGroup ", groupSelected);
}, [groupSelected]);
return (
<div style={{display: "flex", flexDirection: "row", gap: 200}}>
<Checkbox color="success" isSelected={selected} onChange={setSelected}>
Subscribe (controlled)
</Checkbox>
<Checkbox.Group
color="warning"
label="Select cities"
labelColor="primary"
value={groupSelected}
onChange={setGroupSelected}
>
<Checkbox color="primary" value="buenos-aires">
Buenos Aires
</Checkbox>
<Checkbox labelColor="warning" value="sydney">
Sydney
</Checkbox>
<Checkbox labelColor="error" value="london">
London
</Checkbox>
<Checkbox value="tokyo">Tokyo</Checkbox>
</Checkbox.Group>
</div>
);
};
export const NoAnimated = () => {
return (
<div style={{display: "flex", flexDirection: "column"}}>
<Checkbox defaultSelected disableAnimation={true} size="md">
Option
</Checkbox>
<br />
<Checkbox defaultSelected lineThrough disableAnimation={true} size="md">
Option
</Checkbox>
</div>
);
};
export const Group = () => {
// eslint-disable-next-line no-console
const handleGroupChange = (value: string[]) => console.log(value);
return (
<Checkbox.Group
color="warning"
defaultValue={["buenos-aires"]}
label="Select cities"
labelColor="primary"
onChange={handleGroupChange}
>
<Checkbox color="primary" value="buenos-aires">
Buenos Aires
</Checkbox>
<Checkbox labelColor="warning" value="sydney">
Sydney
</Checkbox>
<Checkbox isDisabled labelColor="error" value="london">
London
</Checkbox>
<Checkbox value="tokyo">Tokyo</Checkbox>
</Checkbox.Group>
);
};
export const GroupRow = () => (
<Checkbox.Group
color="warning"
defaultValue={["1"]}
label="Select cities"
orientation="horizontal"
>
<Checkbox color="primary" value="1">
Buenos Aires
</Checkbox>
<Checkbox value="2">Sydney</Checkbox>
<Checkbox value="3">London</Checkbox>
<Checkbox value="4">Tokyo</Checkbox>
</Checkbox.Group>
);

View File

@ -0,0 +1,9 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"paths": {
"@stitches/react": ["../../../node_modules/@stitches/react"]
}
},
"include": ["src", "index.ts"]
}

View File

@ -0,0 +1,13 @@
import {defineConfig} from "tsup";
import {findUpSync} from "find-up";
export default defineConfig({
clean: true,
minify: false,
treeshake: true,
format: ["cjs", "esm"],
outExtension(ctx) {
return {js: `.${ctx.format}.js`};
},
inject: process.env.JSX ? [findUpSync("react-shim.js")!] : undefined,
});

View File

@ -34,14 +34,16 @@
"postpack": "clean-package restore"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-aria": ">=3.18.0"
"react": ">=16.8.0"
},
"dependencies": {
"@nextui-org/dom-utils": "workspace:*",
"@nextui-org/shared-css": "workspace:*",
"@nextui-org/shared-utils": "workspace:*",
"@nextui-org/system": "workspace:*"
"@nextui-org/system": "workspace:*",
"@react-aria/link": "^3.3.4",
"@react-aria/utils": "^3.14.0",
"@react-aria/focus": "^3.9.0"
},
"devDependencies": {
"@react-types/link": "^3.3.3",
@ -49,7 +51,6 @@
"@nextui-org/grid": "workspace:*",
"@nextui-org/text": "workspace:*",
"clean-package": "2.1.1",
"react": "^17.0.2",
"react-aria": "3.18.0"
"react": "^17.0.2"
}
}

View File

@ -1,9 +1,9 @@
import {HTMLAttributes} from "react";
import {useLink as useAriaLink} from "react-aria";
import {useLink as useAriaLink} from "@react-aria/link";
import {mergeProps} from "@react-aria/utils";
import {forwardRef} from "@nextui-org/system";
import {useDOMRef} from "@nextui-org/dom-utils";
import {clsx, __DEV__} from "@nextui-org/shared-utils";
import {mergeProps} from "react-aria";
import {StyledLink} from "./link.styles";
import {UseLinkProps, useLink} from "./use-link";

View File

@ -1,7 +1,7 @@
import type {AriaLinkProps} from "@react-types/link";
import {useMemo} from "react";
import {useFocusRing} from "react-aria";
import {useFocusRing} from "@react-aria/focus";
import {HTMLNextUIProps, CSS, getTokenValue} from "@nextui-org/system";
import {IFocusRingAria} from "@nextui-org/dom-utils";
import {isNormalColor} from "@nextui-org//shared-utils";

View File

@ -34,8 +34,7 @@
"postpack": "clean-package restore"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-aria": ">=3.18.0"
"react": ">=16.8.0"
},
"dependencies": {
"@nextui-org/system": "workspace:*",
@ -43,11 +42,12 @@
"@nextui-org/link": "workspace:*",
"@nextui-org/shared-utils": "workspace:*",
"@nextui-org/shared-css": "workspace:*",
"@nextui-org/dom-utils": "workspace:*"
"@nextui-org/dom-utils": "workspace:*",
"@react-aria/focus": "^3.9.0",
"@react-aria/utils": "^3.14.0"
},
"devDependencies": {
"clean-package": "2.1.1",
"react": "^17.0.2",
"react-aria": "3.18.0"
"react": "^17.0.2"
}
}

View File

@ -1,7 +1,7 @@
import type {AvatarProps} from "@nextui-org/avatar";
import {ReactNode, useMemo} from "react";
import {useFocusRing} from "react-aria";
import {useFocusRing} from "@react-aria/focus";
import {HTMLNextUIProps} from "@nextui-org/system";
import {IFocusRingAria} from "@nextui-org/dom-utils";

View File

@ -1,4 +1,4 @@
import {mergeProps} from "react-aria";
import {mergeProps} from "@react-aria/utils";
import {forwardRef} from "@nextui-org/system";
import {useDOMRef} from "@nextui-org/dom-utils";
import {clsx, __DEV__} from "@nextui-org/shared-utils";

View File

@ -53,15 +53,10 @@
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"react-aria": ">=3.18.0",
"react-stately": ">=3.16.0",
"@stitches/react": ">=1.2.8"
},
"devDependencies": {
"react": "17.0.2",
"react-aria": "3.18.0",
"react-stately": "3.16.0",
"@stitches/react": "1.2.8",
"clean-package": "2.1.1"
}

View File

@ -35,17 +35,17 @@
},
"dependencies": {
"@nextui-org/shared-utils": "workspace:*",
"@nextui-org/use-ssr": "workspace:*"
"@nextui-org/use-ssr": "workspace:*",
"@react-aria/ssr": "^3.3.0",
"@react-aria/overlays": "^3.11.0"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-aria": ">=3.18.0",
"@stitches/react": ">=1.2.8"
},
"devDependencies": {
"react": "^17.0.2",
"@stitches/react": "1.2.8",
"react-aria": "3.18.0",
"clean-package": "2.1.1",
"react": "^17.0.2"
"clean-package": "2.1.1"
}
}

View File

@ -12,7 +12,16 @@ export const getStitchesTheme = (targetTheme: BaseTheme): BaseTheme => {
return deepMerge(targetTheme, commonTheme.theme);
};
const stitches = createStitches({
export const {
styled,
css,
globalCss,
keyframes,
getCssText,
theme,
config,
createTheme: createThemeBase,
} = createStitches({
...commonTheme,
theme: {
...commonTheme.theme,
@ -29,15 +38,6 @@ const stitches = createStitches({
},
});
export const createThemeBase = stitches.createTheme;
export const styled = stitches.styled;
export const css = stitches.css;
export const globalCss = stitches.globalCss;
export const keyframes = stitches.keyframes;
export const getCssText = stitches.getCssText;
export const theme = stitches.theme;
export const config = stitches.config;
export const createTheme = ({type, theme = {}, className}: Theme) => {
if (!type) {
throw new Error("Theme type is required");

View File

@ -1,5 +1,6 @@
import React, {useState, useMemo, useEffect, ReactNode} from "react";
import {SSRProvider, OverlayProvider} from "react-aria";
import {SSRProvider} from "@react-aria/ssr";
import {OverlayProvider} from "@react-aria/overlays";
import {deepMerge, copyObject} from "@nextui-org/shared-utils";
import {useSSR} from "@nextui-org/use-ssr";

View File

@ -34,15 +34,15 @@
"postpack": "clean-package restore"
},
"dependencies": {
"@react-types/shared": "^3.14.1"
"@react-types/shared": "^3.14.1",
"@react-aria/interactions": "^3.12.0",
"@react-aria/focus": "^3.9.0"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-aria": ">=3.18.0"
"react": ">=16.8.0"
},
"devDependencies": {
"clean-package": "2.1.1",
"react-aria": "3.18.0",
"react": "^17.0.2"
}
}

View File

@ -1,7 +1,11 @@
import type {FocusRingAria} from "react-aria";
import {HTMLAttributes} from "react";
import type {FocusRingAria} from "@react-aria/focus";
import type {PressResult} from "@react-aria/interactions";
import type {HTMLAttributes} from "react";
export interface IFocusRingAria<T extends object> extends FocusRingAria {
focusProps: Omit<HTMLAttributes<HTMLElement>, keyof T>;
}
export interface IPressResult<T extends object> extends PressResult {
pressProps: Omit<React.HTMLAttributes<HTMLElement>, keyof T>;
}

View File

@ -1,6 +1,6 @@
import type {CSS} from "@nextui-org/system";
import {css} from "@nextui-org/system";
export const sharedFocus: CSS = {
export const sharedFocus = css({
WebkitTapHighlightColor: "transparent",
"&:focus:not(&:focus-visible)": {
boxShadow: "none",
@ -13,9 +13,9 @@ export const sharedFocus: CSS = {
WebkitTapHighlightColor: "transparent",
outline: "none",
},
};
});
export const cssFocusVisible: CSS = {
export const cssFocusVisible = css({
variants: {
isFocusVisible: {
true: {
@ -28,10 +28,10 @@ export const cssFocusVisible: CSS = {
},
},
},
};
});
export const cssNoBlurriness: CSS = {
export const cssNoBlurriness = css({
/* Avoid blurriness */
transform: "translateZ(0)",
backfaceVisibility: "hidden",
};
});

View File

@ -1,6 +1,6 @@
import type {CSS} from "@nextui-org/system";
import {css} from "@nextui-org/system";
export const sharedVisuallyHidden: CSS = {
export const sharedVisuallyHidden = css({
border: "0px",
clip: "rect(0px, 0px, 0px, 0px)",
height: "1px",
@ -10,9 +10,9 @@ export const sharedVisuallyHidden: CSS = {
overflow: "hidden",
whiteSpace: "nowrap",
position: "absolute",
};
});
export const cssHideIn: CSS = {
export const cssHideIn = css({
variants: {
hideIn: {
xs: {
@ -42,9 +42,9 @@ export const cssHideIn: CSS = {
},
},
},
};
});
export const cssShowIn: CSS = {
export const cssShowIn = css({
variants: {
showIn: {
xs: {
@ -74,6 +74,6 @@ export const cssShowIn: CSS = {
},
},
},
};
});
export const cssHideShowIn: CSS = {...cssHideIn, ...cssShowIn};
export const cssHideShowIn = css(cssHideIn, cssShowIn);

View File

@ -1,4 +1,9 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"paths": {
"@stitches/react": ["../../../node_modules/@stitches/react"],
}
},
"include": ["src", "index.ts"]
}

View File

@ -0,0 +1,52 @@
import * as React from "react";
export interface CreateContextOptions {
/**
* If `true`, React will throw if context is `null` or `undefined`
* In some cases, you might want to support nested context, so you can set it to `false`
*/
strict?: boolean;
/**
* Error message to throw if the context is `undefined`
*/
errorMessage?: string;
/**
* The display name of the context
*/
name?: string;
}
type CreateContextReturn<T> = [React.Provider<T>, () => T, React.Context<T>];
/**
* Creates a named context, provider, and hook.
*
* @param options create context options
*/
export function createContext<ContextType>(options: CreateContextOptions = {}) {
const {
strict = true,
errorMessage = "useContext: `context` is undefined. Seems you forgot to wrap component within the Provider",
name,
} = options;
const Context = React.createContext<ContextType | undefined>(undefined);
Context.displayName = name;
function useContext() {
const context = React.useContext(Context);
if (!context && strict) {
const error = new Error(errorMessage);
error.name = "ContextError";
Error.captureStackTrace?.(error, useContext);
throw error;
}
return context;
}
return [Context.Provider, useContext, Context] as CreateContextReturn<ContextType>;
}

View File

@ -10,3 +10,4 @@ export * from "./text";
export * from "./dimensions";
export * from "./css-transition";
export * from "./functions";
export * from "./context";

1838
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff