From b6faafd6650ad5bee4b62013c2911cd20455b6bb Mon Sep 17 00:00:00 2001 From: Junior Garcia Date: Sun, 2 Oct 2022 16:59:13 -0300 Subject: [PATCH] feat(components): divider component added --- packages/components/divider/README.md | 24 ++++++ .../divider/__tests__/divider.test.tsx | 36 +++++++++ .../divider/clean-package.config.json | 3 + packages/components/divider/package.json | 49 ++++++++++++ .../components/divider/src/divider.styles.ts | 7 ++ packages/components/divider/src/divider.tsx | 49 ++++++++++++ packages/components/divider/src/index.ts | 5 ++ .../components/divider/src/use-divider.ts | 76 +++++++++++++++++++ .../divider/stories/divider.stories.tsx | 11 +++ packages/components/divider/tsconfig.json | 9 +++ packages/components/divider/tsup.config.ts | 13 ++++ packages/components/spacer/src/use-spacer.ts | 5 +- packages/components/text/src/text-child.tsx | 2 +- packages/core/system/src/system.ts | 2 +- .../utilities/shared-utils/src/dimensions.ts | 3 + packages/utilities/shared-utils/src/index.ts | 1 + .../__tests__/{{componentName}}.test.tsx.hbs | 7 ++ pnpm-lock.yaml | 17 +++++ 18 files changed, 313 insertions(+), 6 deletions(-) create mode 100644 packages/components/divider/README.md create mode 100644 packages/components/divider/__tests__/divider.test.tsx create mode 100644 packages/components/divider/clean-package.config.json create mode 100644 packages/components/divider/package.json create mode 100644 packages/components/divider/src/divider.styles.ts create mode 100644 packages/components/divider/src/divider.tsx create mode 100644 packages/components/divider/src/index.ts create mode 100644 packages/components/divider/src/use-divider.ts create mode 100644 packages/components/divider/stories/divider.stories.tsx create mode 100644 packages/components/divider/tsconfig.json create mode 100644 packages/components/divider/tsup.config.ts create mode 100644 packages/utilities/shared-utils/src/dimensions.ts diff --git a/packages/components/divider/README.md b/packages/components/divider/README.md new file mode 100644 index 000000000..9c2a68aeb --- /dev/null +++ b/packages/components/divider/README.md @@ -0,0 +1,24 @@ +# @nextui-org/divider + +A Quick description of the component + +> This is an internal utility, not intended for public usage. + +## Installation + +```sh +yarn add @nextui-org/divider +# or +npm i @nextui-org/divider +``` + +## 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). \ No newline at end of file diff --git a/packages/components/divider/__tests__/divider.test.tsx b/packages/components/divider/__tests__/divider.test.tsx new file mode 100644 index 000000000..bc50b2320 --- /dev/null +++ b/packages/components/divider/__tests__/divider.test.tsx @@ -0,0 +1,36 @@ +import * as React from "react"; +import {render} from "@testing-library/react"; +import {getMargin} from "@nextui-org/shared-utils"; + +import {Divider} from "../src"; + +describe("Divider", () => { + it("should render correctly", () => { + const wrapper = render(); + + expect(() => wrapper.unmount()).not.toThrow(); + }); + + it("ref should be forwarded", () => { + const ref = React.createRef(); + + render(); + expect(ref.current).not.toBeNull(); + }); + + it("should work with x and y", () => { + let x = 2; + let y = 4; + const {container} = render(); + + expect(container.firstChild).toHaveStyle(`margin: ${getMargin(x / 2)} ${getMargin(y / 2)}`); + }); + + it("should support float x & y", () => { + let x = 2.5; + let y = 4.5; + const {container} = render(); + + expect(container.firstChild).toHaveStyle(`margin: ${getMargin(x / 2)} ${getMargin(y / 2)}`); + }); +}); diff --git a/packages/components/divider/clean-package.config.json b/packages/components/divider/clean-package.config.json new file mode 100644 index 000000000..ea9967219 --- /dev/null +++ b/packages/components/divider/clean-package.config.json @@ -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" } } } \ No newline at end of file diff --git a/packages/components/divider/package.json b/packages/components/divider/package.json new file mode 100644 index 000000000..e27d678ba --- /dev/null +++ b/packages/components/divider/package.json @@ -0,0 +1,49 @@ +{ + "name": "@nextui-org/divider", + "version": "1.0.0-beta.11", + "description": "Dividers are used to visually separate content in a list or group.", + "keywords": [ + "divider" + ], + "author": "Junior Garcia ", + "homepage": "https://nextui.org", + "license": "MIT", + "main": "src/index.ts", + "sideEffects": false, + "files": [ + "dist" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/nextui-org/nextui.git", + "directory": "packages/components/divider" + }, + "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/text": "workspace:*", + "@nextui-org/system": "workspace:*", + "@nextui-org/shared-utils": "workspace:*", + "@nextui-org/dom-utils": "workspace:*" + }, + "devDependencies": { + "clean-package": "2.1.1", + "react": "^17.0.2" + } +} diff --git a/packages/components/divider/src/divider.styles.ts b/packages/components/divider/src/divider.styles.ts new file mode 100644 index 000000000..870cf21b8 --- /dev/null +++ b/packages/components/divider/src/divider.styles.ts @@ -0,0 +1,7 @@ +import {styled} from "@nextui-org/system"; + +export const StyledDivider = styled("div", { + width: "100%", + maxWidth: "100%", + position: "relative", +}); diff --git a/packages/components/divider/src/divider.tsx b/packages/components/divider/src/divider.tsx new file mode 100644 index 000000000..2577a4842 --- /dev/null +++ b/packages/components/divider/src/divider.tsx @@ -0,0 +1,49 @@ +import {forwardRef} from "@nextui-org/system"; +import {useDOMRef} from "@nextui-org/dom-utils"; +import {clsx, __DEV__} from "@nextui-org/shared-utils"; +import {Text} from "@nextui-org/text"; + +import {StyledDivider} from "./divider.styles"; +import {UseDividerProps, useDivider} from "./use-divider"; + +export interface DividerProps extends UseDividerProps {} + +const Divider = forwardRef((props, ref) => { + const {css, children, dividerCss, alignCss, textProps, className, ...otherProps} = + useDivider(props); + + const domRef = useDOMRef(ref); + + const {css: textCss, ...otherTextProps} = textProps; + + return ( + + {children && ( + + )} + + ); +}); + +if (__DEV__) { + Divider.displayName = "NextUI.Divider"; +} + +Divider.toString = () => ".nextui-divider"; + +export default Divider; diff --git a/packages/components/divider/src/index.ts b/packages/components/divider/src/index.ts new file mode 100644 index 000000000..a6c518110 --- /dev/null +++ b/packages/components/divider/src/index.ts @@ -0,0 +1,5 @@ +// export types +export type {DividerProps} from "./divider"; + +// export component +export {default as Divider} from "./divider"; diff --git a/packages/components/divider/src/use-divider.ts b/packages/components/divider/src/use-divider.ts new file mode 100644 index 000000000..6ec3088a7 --- /dev/null +++ b/packages/components/divider/src/use-divider.ts @@ -0,0 +1,76 @@ +import {useMemo} from "react"; +import {HTMLNextUIProps, CSS} from "@nextui-org/system"; +import {TextProps} from "@nextui-org/text"; +import {DividerAlign, getMargin} from "@nextui-org/shared-utils"; + +export interface UseDividerProps extends HTMLNextUIProps<"div"> { + /** + * x-axis spacing + * @default 0 + */ + x?: number; + /** + * y-axis spacing + * @default 0 + */ + y?: number; + /** + * Divider height in pixels + * @default 1 + */ + height?: CSS["height"]; + /** + * Divider background color + * @default "border" + */ + color?: CSS["color"]; + /** + * Divider text children color + */ + textProps?: TextProps; + /** + * Divider alignment + * @default center + */ + align?: DividerAlign; +} + +export function useDivider(props: UseDividerProps) { + const { + x = 0, + y = 0, + align = "center", + height = 1, + color = "$border", + textProps = {}, + ...otherProps + } = props; + + const alignCss = useMemo(() => { + if (!align || align === "center") return {}; + if (align === "left" || align === "start") { + return {transform: "translateY(-50%)", left: "7%"}; + } + + return { + transform: "translateY(-50%)", + left: "auto", + right: "7%", + }; + }, [align]); + + const dividerCss = useMemo(() => { + const top = y ? getMargin(y / 2) : 0; + const left = x ? getMargin(x / 2) : 0; + + return { + backgroundColor: color, + margin: `${top} ${left}`, + height: `calc(${height} * 1px)`, + }; + }, [x, y, color]); + + return {dividerCss, alignCss, textProps, ...otherProps}; +} + +export type UseDividerReturn = ReturnType; diff --git a/packages/components/divider/stories/divider.stories.tsx b/packages/components/divider/stories/divider.stories.tsx new file mode 100644 index 000000000..673df2c99 --- /dev/null +++ b/packages/components/divider/stories/divider.stories.tsx @@ -0,0 +1,11 @@ +import React from "react"; +import {Meta} from "@storybook/react"; + +import {Divider} from "../src"; + +export default { + title: "Layout/Divider", + component: Divider, +} as Meta; + +export const Default = () => ; diff --git a/packages/components/divider/tsconfig.json b/packages/components/divider/tsconfig.json new file mode 100644 index 000000000..80a8d5de0 --- /dev/null +++ b/packages/components/divider/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "paths": { + "@stitches/react": ["../../../node_modules/@stitches/react"] + } + }, + "include": ["src", "index.ts"] +} diff --git a/packages/components/divider/tsup.config.ts b/packages/components/divider/tsup.config.ts new file mode 100644 index 000000000..ac7f42d48 --- /dev/null +++ b/packages/components/divider/tsup.config.ts @@ -0,0 +1,13 @@ +import {defineConfig} from "tsup"; +import {findUpSync} from "find-up"; + +export default defineConfig({ + clean: true, + minify: false, + treeshake: false, + format: ["cjs", "esm"], + outExtension(ctx) { + return {js: `.${ctx.format}.js`}; + }, + inject: process.env.JSX ? [findUpSync("react-shim.js")!] : undefined, +}); diff --git a/packages/components/spacer/src/use-spacer.ts b/packages/components/spacer/src/use-spacer.ts index 9b05a5708..a2ae8b18f 100644 --- a/packages/components/spacer/src/use-spacer.ts +++ b/packages/components/spacer/src/use-spacer.ts @@ -1,5 +1,6 @@ import type {HTMLNextUIProps} from "@nextui-org/system"; +import {getMargin} from "@nextui-org/shared-utils"; import {useMemo} from "react"; export interface UseSpacerProps extends HTMLNextUIProps<"span"> { @@ -17,10 +18,6 @@ export interface UseSpacerProps extends HTMLNextUIProps<"span"> { inline?: boolean; } -const getMargin = (num: number): string => { - return `calc(${num * 15.25}pt + 1px * ${num - 1})`; -}; - export function useSpacer(props: UseSpacerProps) { const {x, y, inline = false, ...otherProps} = props; diff --git a/packages/components/text/src/text-child.tsx b/packages/components/text/src/text-child.tsx index 649c502a8..83d2cb937 100644 --- a/packages/components/text/src/text-child.tsx +++ b/packages/components/text/src/text-child.tsx @@ -5,7 +5,7 @@ import {clsx, __DEV__, isNormalColor} from "@nextui-org/shared-utils"; import {StyledText} from "./text.styles"; -export interface TextChildProps extends Omit, "color"> { +export interface TextChildProps extends HTMLNextUIProps<"p"> { tag: keyof JSX.IntrinsicElements; /** * Text color. diff --git a/packages/core/system/src/system.ts b/packages/core/system/src/system.ts index 330e19fe6..77d8a93b0 100644 --- a/packages/core/system/src/system.ts +++ b/packages/core/system/src/system.ts @@ -53,7 +53,7 @@ export type PropsOf = React.ComponentPropsWithoutRef & { }; export type HTMLNextUIProps = Omit< - Omit, "ref"> & { + Omit, "ref" | "color"> & { as?: As; css?: CSS; }, diff --git a/packages/utilities/shared-utils/src/dimensions.ts b/packages/utilities/shared-utils/src/dimensions.ts new file mode 100644 index 000000000..f49121e75 --- /dev/null +++ b/packages/utilities/shared-utils/src/dimensions.ts @@ -0,0 +1,3 @@ +export const getMargin = (num: number): string => { + return `calc(${num * 15.25}pt + 1px * ${num - 1})`; +}; diff --git a/packages/utilities/shared-utils/src/index.ts b/packages/utilities/shared-utils/src/index.ts index 680e518df..94c343a2f 100644 --- a/packages/utilities/shared-utils/src/index.ts +++ b/packages/utilities/shared-utils/src/index.ts @@ -7,3 +7,4 @@ export * from "./prop-types"; export * from "./color"; export * from "./object"; export * from "./text"; +export * from "./dimensions"; diff --git a/plop/component/__tests__/{{componentName}}.test.tsx.hbs b/plop/component/__tests__/{{componentName}}.test.tsx.hbs index 42cdbb958..c684be451 100644 --- a/plop/component/__tests__/{{componentName}}.test.tsx.hbs +++ b/plop/component/__tests__/{{componentName}}.test.tsx.hbs @@ -9,4 +9,11 @@ describe("{{capitalize componentName}}", () => { expect(() => wrapper.unmount()).not.toThrow(); }); + + it("ref should be forwarded", () => { + const ref = React.createRef(); + + render(<{capitalize componentName}} ref={ref} />); + expect(ref.current).not.toBeNull(); + }); }); \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 71ad4abe1..2ec04adc9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -365,6 +365,23 @@ importers: clean-package: 2.1.1 react: 17.0.2 + packages/components/divider: + specifiers: + '@nextui-org/dom-utils': workspace:* + '@nextui-org/shared-utils': workspace:* + '@nextui-org/system': workspace:* + '@nextui-org/text': workspace:* + clean-package: 2.1.1 + react: ^17.0.2 + dependencies: + '@nextui-org/dom-utils': link:../../utilities/dom-utils + '@nextui-org/shared-utils': link:../../utilities/shared-utils + '@nextui-org/system': link:../../core/system + '@nextui-org/text': link:../text + devDependencies: + clean-package: 2.1.1 + react: 17.0.2 + packages/components/grid: specifiers: '@nextui-org/dom-utils': workspace:*