diff --git a/.changeset/calm-baboons-speak.md b/.changeset/calm-baboons-speak.md new file mode 100644 index 000000000..54da9dd2d --- /dev/null +++ b/.changeset/calm-baboons-speak.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/divider": minor +--- + +feat(divider):新增 Divider 组件 diff --git a/.changeset/shiny-cooks-bathe.md b/.changeset/shiny-cooks-bathe.md new file mode 100644 index 000000000..5e86e31e9 --- /dev/null +++ b/.changeset/shiny-cooks-bathe.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/hiui": minor +--- + +feat(divider):新增 Divider 组件 diff --git a/packages/ui/divider/README.md b/packages/ui/divider/README.md new file mode 100644 index 000000000..135db74ad --- /dev/null +++ b/packages/ui/divider/README.md @@ -0,0 +1,11 @@ +# `@hi-ui/divider` + +> TODO: description + +## Usage + +``` +const Divider = require('@hi-ui/divider'); + +// TODO: DEMONSTRATE API +``` diff --git a/packages/ui/divider/__tests__/divider.test.js b/packages/ui/divider/__tests__/divider.test.js new file mode 100644 index 000000000..9f145111a --- /dev/null +++ b/packages/ui/divider/__tests__/divider.test.js @@ -0,0 +1,5 @@ +const Divider = require('../src') + +describe('@hi-ui/divider', () => { + it('needs tests', () => {}) +}) diff --git a/packages/ui/divider/jest.config.js b/packages/ui/divider/jest.config.js new file mode 100644 index 000000000..e33c14b5d --- /dev/null +++ b/packages/ui/divider/jest.config.js @@ -0,0 +1 @@ +module.exports = require('../../../jest.config') diff --git a/packages/ui/divider/package.json b/packages/ui/divider/package.json new file mode 100644 index 000000000..5594d18d5 --- /dev/null +++ b/packages/ui/divider/package.json @@ -0,0 +1,61 @@ +{ + "name": "@hi-ui/divider", + "version": "4.0.0-alpha.0", + "description": "A sub-package for @hi-ui/hiui.", + "keywords": [], + "author": "HiUI ", + "homepage": "https://github.com/XiaoMi/hiui/tree/master/packages/ui/divider#readme", + "license": "MIT", + "directories": { + "lib": "lib", + "test": "__tests__" + }, + "files": [ + "lib" + ], + "main": "lib/cjs/index.js", + "module": "lib/esm/index.js", + "types": "lib/types/index.d.ts", + "typings": "lib/types/index.d.ts", + "exports": { + ".": { + "require": "./lib/cjs/index.js", + "default": "./lib/esm/index.js" + } + }, + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/XiaoMi/hiui.git" + }, + "scripts": { + "test": "jest", + "clean": "rimraf lib", + "prebuild": "yarn clean", + "build:esm": "hi-build ./src/index.ts --format esm -d ./lib/esm", + "build:cjs": "hi-build ./src/index.ts --format cjs -d ./lib/cjs", + "build:types": "tsc --emitDeclarationOnly --declaration --declarationDir lib/types", + "build": "concurrently yarn:build:*" + }, + "bugs": { + "url": "https://github.com/XiaoMi/hiui/issues" + }, + "dependencies": { + "@hi-ui/classname": "^4.0.0", + "@hi-ui/env": "^4.0.0" + }, + "peerDependencies": { + "@hi-ui/core": ">=4.0.0", + "react": ">=16.8.6", + "react-dom": ">=16.8.6" + }, + "devDependencies": { + "@hi-ui/core": "^4.0.0", + "@hi-ui/core-css": "^4.0.0", + + "react": "^17.0.1", + "react-dom": "^17.0.1" + } +} diff --git a/packages/ui/divider/src/Divider.tsx b/packages/ui/divider/src/Divider.tsx new file mode 100644 index 000000000..223ffde94 --- /dev/null +++ b/packages/ui/divider/src/Divider.tsx @@ -0,0 +1,111 @@ +import React, { forwardRef, useMemo } from 'react' +import { cx, getPrefixCls } from '@hi-ui/classname' +import { __DEV__ } from '@hi-ui/env' +import { HiBaseHTMLProps } from '@hi-ui/core' + +const DIVIDER_PREFIX = getPrefixCls('divider') +const DEFAULT_ORIENTATION_MARGIN = 0.05 +const DEFAULT_VERTICAL_MARGIN_INLINE = 8 +/** + * TODO: What is Divider + */ +export const Divider = forwardRef( + ( + { + prefixCls = DIVIDER_PREFIX, + role = 'divider', + className, + children, + type = 'horizontal', + dashed = false, + color = 'rgba(5, 5, 5, 0.06)', + lineWidth = 1, + orientation = 'center', + orientationMargin = DEFAULT_ORIENTATION_MARGIN, + verticalMarginInline = DEFAULT_VERTICAL_MARGIN_INLINE, + wrapperStyle = {}, + ...rest + }, + ref + ) => { + const withContent = children && type !== 'vertical' + + const customOrientationMargin = useMemo(() => { + const number = Number(orientationMargin) + if (!isNaN(number) && number >= 0 && number <= 1) return number + return DEFAULT_ORIENTATION_MARGIN + }, [orientationMargin]) + + const customVerticalMarginInline = useMemo(() => { + const number = Number(verticalMarginInline) + if (!isNaN(number) && number >= 0) return number + return DEFAULT_VERTICAL_MARGIN_INLINE + }, [verticalMarginInline]) + + const cls = cx( + prefixCls, + className, + `${prefixCls}--type-${type}`, + `${prefixCls}--orientation-${orientation}`, + dashed && `${prefixCls}--dashed`, + withContent && `${prefixCls}--with-content` + ) + + const dividerStyle = useMemo(() => { + return { + '--line-color': color, + '--line-width': `${lineWidth}px`, + '--orientation-margin': customOrientationMargin, + '--vertical-margin-inline': `${customVerticalMarginInline}px`, + ...wrapperStyle, + } as React.CSSProperties + }, [color, lineWidth, customOrientationMargin, customVerticalMarginInline, wrapperStyle]) + + return ( +
+ {children && type !== 'vertical' && ( + {children} + )} +
+ ) + } +) + +export interface DividerProps extends HiBaseHTMLProps<'div'> { + /** + * 设置分割线类型 + */ + type?: 'horizontal' | 'vertical' + /** + * 设置是否虚线 + */ + dashed?: boolean + /** + * 线条颜色 + */ + color?: string + /** + * 线条宽度(px) + */ + lineWidth?: number + /** + * 设置分割线子节点位置 + */ + orientation?: 'left' | 'center' | 'right' + /** + * 设置orientation非center下分割线子节点与最近边距离占全长比例 + */ + orientationMargin?: string | number + /** + * 设置垂直模式下分割线左右margin(px) + */ + verticalMarginInline?: number + /** + * 设置分割线样式 + */ + wrapperStyle?: React.CSSProperties +} + +if (__DEV__) { + Divider.displayName = 'Divider' +} diff --git a/packages/ui/divider/src/index.ts b/packages/ui/divider/src/index.ts new file mode 100644 index 000000000..6383e44aa --- /dev/null +++ b/packages/ui/divider/src/index.ts @@ -0,0 +1,4 @@ +import './styles/index.scss' + +export * from './Divider' +export { Divider as default } from './Divider' diff --git a/packages/ui/divider/src/styles/divider.scss b/packages/ui/divider/src/styles/divider.scss new file mode 100644 index 000000000..dc9c8cda1 --- /dev/null +++ b/packages/ui/divider/src/styles/divider.scss @@ -0,0 +1,87 @@ +@import '~@hi-ui/core-css/lib/index.scss'; + +$prefix: '#{$component-prefix}-divider' !default; + +.#{$prefix} { + box-sizing: border-box; + + &--type-horizontal { + display: flex; + clear: both; + width: 100%; + min-width: 100%; + margin-block: 24px; + border-block-start: var(--line-width) solid var(--line-color); + } + + &--type-vertical { + position: relative; + display: inline-block; + top: -0.06em; + height: 0.9em; + vertical-align: middle; + border-top: 0; + border-inline-start: var(--line-width) solid var(--line-color); + margin-inline: var(--vertical-margin-inline); + } + + &--dashed { + background: none; + border-color: var(--line-color); + border-style: dashed; + border-width: var(--line-width) 0 0; + } + + &--with-content { + display: flex; + align-items: center; + border-block-start: 0 var(--line-color); + white-space: nowrap; + text-align: center; + + &::before, + &::after { + position: relative; + width: 50%; + border-block-start: var(--line-width) solid transparent; + border-block-start-color: inherit; + border-block-end: 0; + transform: translateY(50%); + content: ''; + } + &.#{$prefix} { + &--dashed { + &::before, + &::after { + border-style: dashed none none; + } + } + + &--orientation-left { + &::before { + width: calc(var(--orientation-margin) * 100%); + } + + &::after { + width: calc(100% - var(--orientation-margin) * 100%); + } + } + + &--orientation-right { + &::before { + width: calc(100% - var(--orientation-margin) * 100%); + } + + &::after { + width: calc(var(--orientation-margin) * 100%); + } + } + } + } + + &--inner-content { + display: inline-block; + padding-block: 0; + padding-inline: 1em; + } +} diff --git a/packages/ui/divider/src/styles/index.scss b/packages/ui/divider/src/styles/index.scss new file mode 100644 index 000000000..c7a6b324a --- /dev/null +++ b/packages/ui/divider/src/styles/index.scss @@ -0,0 +1 @@ +@import './divider.scss'; diff --git a/packages/ui/divider/src/types.ts b/packages/ui/divider/src/types.ts new file mode 100644 index 000000000..6b0287f83 --- /dev/null +++ b/packages/ui/divider/src/types.ts @@ -0,0 +1,12 @@ +import React from 'react' + +export interface DividerDataItem { + /** + * 节点唯一 id + */ + id: React.ReactText + /** + * 节点标题 + */ + title: React.ReactNode +} diff --git a/packages/ui/divider/stories/basic.stories.tsx b/packages/ui/divider/stories/basic.stories.tsx new file mode 100644 index 000000000..633c44735 --- /dev/null +++ b/packages/ui/divider/stories/basic.stories.tsx @@ -0,0 +1,15 @@ +import React from 'react' +import Divider from '../src' + +export const Basic = () => { + return ( + <> +

Basic

+
+ 分割线上方文本 + + 分割线下方文本 +
+ + ) +} diff --git a/packages/ui/divider/stories/children.stories.tsx b/packages/ui/divider/stories/children.stories.tsx new file mode 100644 index 000000000..383052110 --- /dev/null +++ b/packages/ui/divider/stories/children.stories.tsx @@ -0,0 +1,29 @@ +import React from 'react' +import Divider from '../src' + +export const children = () => { + return ( + <> +

带子节点

+
+ 分割线上方文本 + 分割线 文字 + 分割线下方文本 +
分割线上方文本 + 分割线文字 + 分割线下方文本 +
分割线上方文本 + 分割线靠左内容 + 分割线下方文本 +
分割线上方文本 + 分割线靠右内容 + 分割线下方文本 +
分割线上方文本 + + 分割线左侧距离占比30% + + 分割线下方文本 +
+ + ) +} diff --git a/packages/ui/divider/stories/color.stories.tsx b/packages/ui/divider/stories/color.stories.tsx new file mode 100644 index 000000000..ddd03fe8a --- /dev/null +++ b/packages/ui/divider/stories/color.stories.tsx @@ -0,0 +1,15 @@ +import React from 'react' +import Divider from '../src' + +export const Color = () => { + return ( + <> +

分割线颜色

+
+ 分割线上方文本 + + 分割线下方文本 +
+ + ) +} diff --git a/packages/ui/divider/stories/dashed.stories.tsx b/packages/ui/divider/stories/dashed.stories.tsx new file mode 100644 index 000000000..5a579244d --- /dev/null +++ b/packages/ui/divider/stories/dashed.stories.tsx @@ -0,0 +1,15 @@ +import React from 'react' +import Divider from '../src' + +export const Dashed = () => { + return ( + <> +

虚线

+
+ 虚线上方文本 + + 虚线下方文本 +
+ + ) +} diff --git a/packages/ui/divider/stories/index.stories.tsx b/packages/ui/divider/stories/index.stories.tsx new file mode 100644 index 000000000..c0b7317bd --- /dev/null +++ b/packages/ui/divider/stories/index.stories.tsx @@ -0,0 +1,14 @@ +import React from 'react' +import Divider from '../src' + +export * from './basic.stories' +export * from './color.stories' +export * from './style.stories' +export * from './dashed.stories' +export * from './vertical.stories' +export * from './children.stories' +export default { + title: 'Basic/Divider', + component: Divider, + decorators: [(story: Function) =>
{story()}
], +} diff --git a/packages/ui/divider/stories/style.stories.tsx b/packages/ui/divider/stories/style.stories.tsx new file mode 100644 index 000000000..11e4ff29b --- /dev/null +++ b/packages/ui/divider/stories/style.stories.tsx @@ -0,0 +1,15 @@ +import React from 'react' +import Divider from '../src' + +export const Style = () => { + return ( + <> +

自定义样式

+
+ 分割线上方文本 + + 分割线下方文本 +
+ + ) +} diff --git a/packages/ui/divider/stories/vertical.stories.tsx b/packages/ui/divider/stories/vertical.stories.tsx new file mode 100644 index 000000000..c3e75f4ab --- /dev/null +++ b/packages/ui/divider/stories/vertical.stories.tsx @@ -0,0 +1,19 @@ +import React from 'react' +import Divider from '../src' + +export const Vertical = () => { + return ( + <> +

垂直分割线

+
+ 分割线左侧文本 + + 分割线右侧文本 +
+ 分割线左侧文本 + + 分割线右侧文本 +
+ + ) +} diff --git a/packages/ui/divider/tsconfig.json b/packages/ui/divider/tsconfig.json new file mode 100644 index 000000000..f7bbdb2fe --- /dev/null +++ b/packages/ui/divider/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../../tsconfig.json", + "include": ["./src"] +}