Skip to content

Commit

Permalink
feat(ui): add notification component
Browse files Browse the repository at this point in the history
  • Loading branch information
xiejay97 committed Dec 31, 2021
1 parent 3305f22 commit 9abbaa6
Show file tree
Hide file tree
Showing 58 changed files with 1,821 additions and 695 deletions.
65 changes: 33 additions & 32 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,82 +23,83 @@
"build:executors": "tsc --project tools/tsconfig.json",
"release": "standard-version",
"prepare": "husky install && chmod ug+x .husky/*",
"prepublishOnly": "nx build ui"
"prepublishOnly": "nx build ui",
"check-update": "yarn upgrade-interactive --latest"
},
"dependencies": {
"core-js": "^3.19.1",
"i18next": "^21.5.3",
"core-js": "^3.20.1",
"i18next": "^21.6.4",
"immer": "^9.0.7",
"lodash": "^4.17.21",
"react": "18.0.0-rc.0",
"react-dom": "18.0.0-rc.0",
"react-i18next": "^11.14.3",
"react-router-dom": "^6.0.2",
"react-i18next": "^11.15.2",
"react-router-dom": "^6.2.1",
"regenerator-runtime": "^0.13.9",
"rfs": "^9.0.6",
"rxjs": "^7.4.0",
"rxjs": "^7.5.1",
"tslib": "^2.3.1"
},
"devDependencies": {
"@commitlint/cli": "^15.0.0",
"@commitlint/config-conventional": "^15.0.0",
"@nrwl/cli": "^13.3.1",
"@nrwl/cypress": "^13.3.1",
"@nrwl/eslint-plugin-nx": "^13.3.1",
"@nrwl/jest": "^13.3.1",
"@nrwl/linter": "^13.3.1",
"@nrwl/nx-cloud": "latest",
"@nrwl/react": "^13.3.1",
"@nrwl/tao": "^13.3.1",
"@nrwl/web": "^13.3.1",
"@nrwl/workspace": "^13.3.1",
"@commitlint/cli": "^16.0.1",
"@commitlint/config-conventional": "^16.0.0",
"@nrwl/cli": "^13.4.1",
"@nrwl/cypress": "^13.4.1",
"@nrwl/eslint-plugin-nx": "^13.4.1",
"@nrwl/jest": "^13.4.1",
"@nrwl/linter": "^13.4.1",
"@nrwl/nx-cloud": "13.0.1",
"@nrwl/react": "^13.4.1",
"@nrwl/tao": "^13.4.1",
"@nrwl/web": "^13.4.1",
"@nrwl/workspace": "^13.4.1",
"@testing-library/jest-dom": "^5.16.1",
"@testing-library/react": "13.0.0-alpha.5",
"@testing-library/react-hooks": "^7.0.2",
"@types/enzyme": "^3.10.10",
"@types/fs-extra": "^9.0.13",
"@types/jest": "^27.0.3",
"@types/jest": "^27.4.0",
"@types/lodash": "^4.14.177",
"@types/marked": "^3.0.1",
"@types/node": "^16.11.10",
"@types/react": "^17.0.37",
"@types/node": "^17.0.5",
"@types/react": "^17.0.38",
"@types/react-dom": "^17.0.11",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"babel-jest": "^27.3.1",
"cypress": "^9.1.0",
"@typescript-eslint/eslint-plugin": "^5.8.1",
"@typescript-eslint/parser": "^5.8.1",
"babel-jest": "^27.4.5",
"cypress": "^9.2.0",
"dotenv": "^10.0.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6",
"eslint": "^8.2.0",
"eslint": "^8.5.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-markdown": "^2.2.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.27.1",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
"fs-extra": "^10.0.0",
"highlight.js": "^11.3.1",
"husky": "^7.0.4",
"jest": "^27.3.1",
"jest": "^27.4.5",
"marked": "^3.0.4",
"postcss-html": "^1.3.0",
"postcss-markdown": "^1.2.0",
"prettier": "^2.5.0",
"react-test-renderer": "^17.0.2",
"rxjs-for-await": "^1.0.0",
"sass": "^1.43.5",
"sass": "^1.45.2",
"standard-version": "^9.3.2",
"stylelint": "^14.1.0",
"stylelint": "^14.2.0",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-config-recommended-scss": "^5.0.2",
"stylelint-config-standard": "^24.0.0",
"stylelint-order": "^5.0.0",
"stylelint-scss": "^4.0.0",
"ts-jest": "^27.0.7",
"stylelint-scss": "^4.1.0",
"ts-jest": "^27.1.2",
"ts-node": "^10.4.0",
"typescript": "~4.5.2",
"yaml-front-matter": "^4.1.1"
Expand Down
1 change: 1 addition & 0 deletions packages/site/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": {
"compiler": "babel",
"deployUrl": "/",
"outputPath": "dist/packages/site",
"index": "packages/site/src/index.html",
Expand Down
16 changes: 11 additions & 5 deletions packages/site/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router-dom';

import { DConfigRoot } from '@react-devui/ui';
import { DRoot, NotificationService } from '@react-devui/ui';
import { useAsync } from '@react-devui/ui/hooks';

import { environment } from '../environments/environment';
Expand Down Expand Up @@ -55,6 +56,11 @@ export function App() {
}
}, [asyncCapture, mainEl]);

const location = useLocation();
useEffect(() => {
NotificationService.closeAll(false);
}, [location]);

const contextValue = useMemo<AppContextData>(
() => ({
menuOpen,
Expand All @@ -79,15 +85,15 @@ export function App() {
);

return (
<AppContext.Provider value={contextValue}>
<DConfigRoot content="main .app-route-article" i18n={{ lang: i18n.language as 'en-US' | 'zh-Hant' }} icons={icons}>
<DRoot i18n={{ lang: i18n.language as 'en-US' | 'zh-Hant' }} icons={icons} contentSelector="main .app-route-article">
<AppContext.Provider value={contextValue}>
<AppHeader />
<AppSidebar />
<main ref={mainRef} className="app-main">
<AppRoutes />
</main>
</DConfigRoot>
</AppContext.Provider>
</AppContext.Provider>
</DRoot>
);
}

Expand Down
4 changes: 0 additions & 4 deletions packages/site/src/app/components/route/RouteArticle.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
z-index: 910;

width: 168px;

.d-anchor-link__link {
padding: 4px 0;
}
}

.app-route-article__anchor-conatiner {
Expand Down
3 changes: 2 additions & 1 deletion packages/site/src/app/routes/components/Interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ Extend `React.HTMLAttributes<HTMLDivElement>`.
<!-- prettier-ignore-start -->
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| dCloseIcon | Set the icon of the close button, `null` means hide the button | React.ReactNode | - |
| dClosable | Can be closed | boolean | false |
| dCloseIcon | Custom close icon | React.ReactNode | - |
| dExtraIcons | Add some extra action buttons | React.ReactNode[] | - |
| onClose | Callback when the close button is clicked | `() => void` | - |
<!-- prettier-ignore-end -->
Expand Down
3 changes: 2 additions & 1 deletion packages/site/src/app/routes/components/Interface.zh-Hant.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ interface DTransitionStateList {
<!-- prettier-ignore-start -->
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| dCloseIcon | 设置关闭按钮的图标, `null` 表示隐藏按钮 | React.ReactNode | - |
| dClosable | 是否可关闭 | boolean | false |
| dCloseIcon | 设置关闭按钮的图标 | React.ReactNode | - |
| dExtraIcons | 添加一些额外的操作按钮 | React.ReactNode[] | - |
| onClose | 点击关闭按钮的回调 | `() => void` | - |
<!-- prettier-ignore-end -->
Expand Down
9 changes: 6 additions & 3 deletions packages/site/src/app/styles/_app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,15 @@ h3 {
.app-component-route-article__demos {
section[id^='Button'],
section[id^='Dropdown'],
section[id^='Tooltip'] {
section[id^='Tooltip'],
section[id^='Notification'] {
.d-button {
margin-right: 8px;
margin-bottom: 12px;

&.d-button--block {
margin-right: 0;
}
}

.d-button-group {
Expand Down Expand Up @@ -232,8 +237,6 @@ h3 {

background-color: var(--d-color-primary);

@include font-size(0.8rem);

& + &,
& + .app-demo-drag-placeholder,
.app-demo-drag-placeholder + & {
Expand Down
84 changes: 84 additions & 0 deletions packages/ui/src/components/_alert-dialog/AlertDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { useCallback, useEffect, useRef } from 'react';

import { useAsync } from '../../hooks';

export interface DAlertDialogProps extends React.HTMLAttributes<HTMLDivElement> {
dHidden: boolean;
dDuration: number;
dDialogRef?: React.LegacyRef<HTMLDivElement>;
onClose?: () => void;
}

export function DAlertDialog(props: DAlertDialogProps) {
const { dHidden, dDuration, dDialogRef, onClose, children, onKeyDown, onMouseEnter, onMouseLeave, ...restProps } = props;

const dataRef = useRef<{ clearTid: (() => void) | null }>({
clearTid: null,
});

const asyncCapture = useAsync();

const handleKeyDown = useCallback<React.KeyboardEventHandler<HTMLDivElement>>(
(e) => {
onKeyDown?.(e);

if (e.code === 'Escape') {
dataRef.current.clearTid && dataRef.current.clearTid();
onClose?.();
}
},
[onClose, onKeyDown]
);

const handleMouseEnter = useCallback<React.MouseEventHandler<HTMLDivElement>>(
(e) => {
onMouseEnter?.(e);

dataRef.current.clearTid && dataRef.current.clearTid();
},
[onMouseEnter]
);

const handleMouseLeave = useCallback<React.MouseEventHandler<HTMLDivElement>>(
(e) => {
onMouseLeave?.(e);

if (dDuration > 0) {
dataRef.current.clearTid && dataRef.current.clearTid();
dataRef.current.clearTid = asyncCapture.setTimeout(() => {
onClose?.();
}, dDuration * 1000);
}
},
[asyncCapture, dDuration, onClose, onMouseLeave]
);

useEffect(() => {
if (dDuration > 0) {
dataRef.current.clearTid && dataRef.current.clearTid();
dataRef.current.clearTid = asyncCapture.setTimeout(() => {
onClose?.();
}, dDuration * 1000);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
// eslint-disable-next-line react/jsx-no-useless-fragment
<>
{!dHidden && (
<div
{...restProps}
ref={dDialogRef}
role="alertdialog"
aria-modal="true"
onKeyDown={handleKeyDown}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
{children}
</div>
)}
</>
);
}
1 change: 1 addition & 0 deletions packages/ui/src/components/_alert-dialog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './AlertDialog';
17 changes: 1 addition & 16 deletions packages/ui/src/components/_dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,23 @@ import { getClassName, mergeStyle } from '../../utils';
import { DMask } from './Mask';

export interface DDialogProps extends React.HTMLAttributes<HTMLDivElement> {
dId: string;
dVisible: boolean;
dHidden: boolean;
dContentProps?: React.HTMLAttributes<HTMLDivElement>;
dMask?: boolean;
dMaskClosable?: boolean;
dDestroy?: boolean;
dDialogRef?: React.LegacyRef<HTMLDivElement>;
dDialogContentRef?: React.LegacyRef<HTMLDivElement>;
onClose?: () => void;
}

export function DDialog(props: DDialogProps) {
const {
dId,
dVisible,
dHidden,
dContentProps,
dMask = true,
dMaskClosable = true,
dDestroy = false,
dDialogRef,
dDialogContentRef,
onClose,
className,
style,
Expand Down Expand Up @@ -70,18 +64,9 @@ export function DDialog(props: DDialogProps) {
style={mergeStyle(style, { display: dHidden ? 'none' : undefined })}
role="dialog"
aria-modal="true"
aria-describedby={`${dPrefix}dialog-content-${dId}`}
>
{dMask && <DMask dVisible={dVisible} onClose={handleMaskClose} />}
<div
{...dContentProps}
ref={dDialogContentRef}
id={`${dPrefix}dialog-content-${dId}`}
className={getClassName(dContentProps?.className, `${dPrefix}dialog__content`)}
tabIndex={-1}
>
{children}
</div>
{children}
</div>
)}
</>
Expand Down
12 changes: 6 additions & 6 deletions packages/ui/src/components/_header/Header.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import { DHeader } from './Header';
const icon = <DIcon data-testid="custom-icon"></DIcon>;

describe('DHeader', () => {
it('should `dClosable` work', () => {
render(<DHeader dClosable={false} />);
expect(screen.queryAllByRole('button').length).toBe(0);
});

it('should `dCloseIcon` work', () => {
render(<DHeader />);
expect(screen.getAllByRole('button').length).toBe(1);
Expand All @@ -16,13 +21,8 @@ describe('DHeader', () => {
expect(screen.getAllByTestId('custom-icon').length).toBe(1);
});

it('should `dCloseIcon` null work', () => {
render(<DHeader dCloseIcon={null} />);
expect(screen.queryAllByRole('button').length).toBe(0);
});

it('should `dExtraIcons` work', () => {
render(<DHeader dExtraIcons={[icon, icon]} dCloseIcon={null} />);
render(<DHeader dExtraIcons={[icon, icon]} dClosable={false} />);
expect(screen.getAllByRole('button').length).toBe(2);
});

Expand Down

0 comments on commit 9abbaa6

Please sign in to comment.