@redsift/popovers 9.2.3-patch → 9.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/coverage/clover.xml +763 -0
- package/coverage/coverage-final.json +53 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/dialog/Dialog.tsx.html +271 -0
- package/coverage/lcov-report/dialog/context.ts.html +97 -0
- package/coverage/lcov-report/dialog/index.html +191 -0
- package/coverage/lcov-report/dialog/index.ts.html +100 -0
- package/coverage/lcov-report/dialog/types.ts.html +241 -0
- package/coverage/lcov-report/dialog/useDialog.tsx.html +346 -0
- package/coverage/lcov-report/dialog/useDialogContext.tsx.html +121 -0
- package/coverage/lcov-report/dialog-content/DialogContent.tsx.html +484 -0
- package/coverage/lcov-report/dialog-content/index.html +146 -0
- package/coverage/lcov-report/dialog-content/index.ts.html +91 -0
- package/coverage/lcov-report/dialog-content/intl/index.html +116 -0
- package/coverage/lcov-report/dialog-content/intl/index.ts.html +106 -0
- package/coverage/lcov-report/dialog-content/styles.ts.html +256 -0
- package/coverage/lcov-report/dialog-content-actions/DialogContentActions.tsx.html +205 -0
- package/coverage/lcov-report/dialog-content-actions/index.html +146 -0
- package/coverage/lcov-report/dialog-content-actions/index.ts.html +91 -0
- package/coverage/lcov-report/dialog-content-actions/styles.ts.html +139 -0
- package/coverage/lcov-report/dialog-content-body/DialogContentBody.tsx.html +232 -0
- package/coverage/lcov-report/dialog-content-body/index.html +146 -0
- package/coverage/lcov-report/dialog-content-body/index.ts.html +91 -0
- package/coverage/lcov-report/dialog-content-body/styles.ts.html +259 -0
- package/coverage/lcov-report/dialog-content-header/DialogContentHeader.tsx.html +280 -0
- package/coverage/lcov-report/dialog-content-header/index.html +146 -0
- package/coverage/lcov-report/dialog-content-header/index.ts.html +91 -0
- package/coverage/lcov-report/dialog-content-header/styles.ts.html +193 -0
- package/coverage/lcov-report/dialog-trigger/DialogTrigger.tsx.html +217 -0
- package/coverage/lcov-report/dialog-trigger/index.html +131 -0
- package/coverage/lcov-report/dialog-trigger/index.ts.html +91 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +341 -0
- package/coverage/lcov-report/popover/Popover.tsx.html +295 -0
- package/coverage/lcov-report/popover/context.ts.html +97 -0
- package/coverage/lcov-report/popover/index.html +191 -0
- package/coverage/lcov-report/popover/index.ts.html +100 -0
- package/coverage/lcov-report/popover/types.ts.html +283 -0
- package/coverage/lcov-report/popover/usePopover.tsx.html +415 -0
- package/coverage/lcov-report/popover/usePopoverContext.tsx.html +121 -0
- package/coverage/lcov-report/popover-content/PopoverContent.tsx.html +229 -0
- package/coverage/lcov-report/popover-content/index.html +146 -0
- package/coverage/lcov-report/popover-content/index.ts.html +94 -0
- package/coverage/lcov-report/popover-content/styles.ts.html +370 -0
- package/coverage/lcov-report/popover-trigger/PopoverTrigger.tsx.html +202 -0
- package/coverage/lcov-report/popover-trigger/index.html +131 -0
- package/coverage/lcov-report/popover-trigger/index.ts.html +91 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov-report/toast/Toast.tsx.html +373 -0
- package/coverage/lcov-report/toast/index.html +161 -0
- package/coverage/lcov-report/toast/index.ts.html +91 -0
- package/coverage/lcov-report/toast/intl/index.html +116 -0
- package/coverage/lcov-report/toast/intl/index.ts.html +106 -0
- package/coverage/lcov-report/toast/styles.ts.html +193 -0
- package/coverage/lcov-report/toast/types.ts.html +217 -0
- package/coverage/lcov-report/toast-container/ToastContainer.tsx.html +217 -0
- package/coverage/lcov-report/toast-container/index.html +161 -0
- package/coverage/lcov-report/toast-container/index.ts.html +94 -0
- package/coverage/lcov-report/toast-container/styles.ts.html +2284 -0
- package/coverage/lcov-report/toast-container/useToast.tsx.html +469 -0
- package/coverage/lcov-report/tooltip/Tooltip.tsx.html +250 -0
- package/coverage/lcov-report/tooltip/context.ts.html +97 -0
- package/coverage/lcov-report/tooltip/index.html +191 -0
- package/coverage/lcov-report/tooltip/index.ts.html +100 -0
- package/coverage/lcov-report/tooltip/types.ts.html +250 -0
- package/coverage/lcov-report/tooltip/useTooltip.tsx.html +358 -0
- package/coverage/lcov-report/tooltip/useTooltipContext.tsx.html +121 -0
- package/coverage/lcov-report/tooltip-content/TooltipContent.tsx.html +313 -0
- package/coverage/lcov-report/tooltip-content/index.html +146 -0
- package/coverage/lcov-report/tooltip-content/index.ts.html +91 -0
- package/coverage/lcov-report/tooltip-content/styles.ts.html +337 -0
- package/coverage/lcov-report/tooltip-trigger/TooltipTrigger.tsx.html +211 -0
- package/coverage/lcov-report/tooltip-trigger/index.html +131 -0
- package/coverage/lcov-report/tooltip-trigger/index.ts.html +91 -0
- package/coverage/lcov.info +1510 -0
- package/coverage/storybook/coverage-storybook.json +58724 -0
- package/dist/package.json +96 -0
- package/index.ts +1 -0
- package/jest.config.js +3 -0
- package/package.json +2 -3
- package/rollup.config.js +13 -0
- package/src/components/dialog/Dialog.stories.tsx +264 -0
- package/src/components/dialog/Dialog.test.tsx +116 -0
- package/src/components/dialog/Dialog.tsx +62 -0
- package/src/components/dialog/context.ts +4 -0
- package/src/components/dialog/index.ts +5 -0
- package/src/components/dialog/types.ts +52 -0
- package/src/components/dialog/useDialog.tsx +87 -0
- package/src/components/dialog/useDialogContext.tsx +12 -0
- package/src/components/dialog-content/DialogContent.stories.tsx +348 -0
- package/src/components/dialog-content/DialogContent.tsx +133 -0
- package/src/components/dialog-content/index.ts +2 -0
- package/src/components/dialog-content/intl/en-US.json +3 -0
- package/src/components/dialog-content/intl/fr-FR.json +3 -0
- package/src/components/dialog-content/intl/index.ts +7 -0
- package/src/components/dialog-content/styles.ts +57 -0
- package/src/components/dialog-content/types.ts +10 -0
- package/src/components/dialog-content-actions/DialogContentActions.test.tsx +68 -0
- package/src/components/dialog-content-actions/DialogContentActions.tsx +40 -0
- package/src/components/dialog-content-actions/index.ts +2 -0
- package/src/components/dialog-content-actions/styles.ts +18 -0
- package/src/components/dialog-content-actions/types.ts +11 -0
- package/src/components/dialog-content-body/DialogContentBody.test.tsx +63 -0
- package/src/components/dialog-content-body/DialogContentBody.tsx +49 -0
- package/src/components/dialog-content-body/index.ts +2 -0
- package/src/components/dialog-content-body/styles.ts +58 -0
- package/src/components/dialog-content-body/types.ts +14 -0
- package/src/components/dialog-content-header/DialogContentHeader.test.tsx +63 -0
- package/src/components/dialog-content-header/DialogContentHeader.tsx +65 -0
- package/src/components/dialog-content-header/index.ts +2 -0
- package/src/components/dialog-content-header/styles.ts +36 -0
- package/src/components/dialog-content-header/types.ts +21 -0
- package/src/components/dialog-trigger/DialogTrigger.tsx +44 -0
- package/src/components/dialog-trigger/index.ts +2 -0
- package/src/components/dialog-trigger/types.ts +9 -0
- package/src/components/popover/Popover.stories.tsx +129 -0
- package/src/components/popover/Popover.test.tsx +102 -0
- package/src/components/popover/Popover.tsx +70 -0
- package/src/components/popover/context.ts +4 -0
- package/src/components/popover/index.ts +5 -0
- package/src/components/popover/types.ts +66 -0
- package/src/components/popover/usePopover.tsx +110 -0
- package/src/components/popover/usePopoverContext.tsx +12 -0
- package/src/components/popover-content/PopoverContent.tsx +48 -0
- package/src/components/popover-content/index.ts +3 -0
- package/src/components/popover-content/styles.ts +95 -0
- package/src/components/popover-content/types.ts +11 -0
- package/src/components/popover-trigger/PopoverTrigger.tsx +39 -0
- package/src/components/popover-trigger/index.ts +2 -0
- package/src/components/popover-trigger/types.ts +9 -0
- package/src/components/toast/Toast.stories.tsx +68 -0
- package/src/components/toast/Toast.test.tsx +63 -0
- package/src/components/toast/Toast.tsx +96 -0
- package/src/components/toast/index.ts +2 -0
- package/src/components/toast/intl/en-US.json +3 -0
- package/src/components/toast/intl/fr-FR.json +3 -0
- package/src/components/toast/intl/index.ts +7 -0
- package/src/components/toast/styles.ts +36 -0
- package/src/components/toast/types.ts +44 -0
- package/src/components/toast-container/ToastContainer.stories.tsx +349 -0
- package/src/components/toast-container/ToastContainer.tsx +44 -0
- package/src/components/toast-container/index.ts +3 -0
- package/src/components/toast-container/styles.ts +733 -0
- package/src/components/toast-container/types.ts +110 -0
- package/src/components/toast-container/useToast.test.tsx +111 -0
- package/src/components/toast-container/useToast.tsx +128 -0
- package/src/components/tooltip/Tooltip.stories.tsx +196 -0
- package/src/components/tooltip/Tooltip.test.tsx +119 -0
- package/src/components/tooltip/Tooltip.tsx +55 -0
- package/src/components/tooltip/context.ts +4 -0
- package/src/components/tooltip/index.ts +5 -0
- package/src/components/tooltip/types.ts +55 -0
- package/src/components/tooltip/useTooltip.tsx +93 -0
- package/src/components/tooltip/useTooltipContext.tsx +12 -0
- package/src/components/tooltip-content/TooltipContent.tsx +76 -0
- package/src/components/tooltip-content/index.ts +2 -0
- package/src/components/tooltip-content/styles.ts +84 -0
- package/src/components/tooltip-content/types.ts +14 -0
- package/src/components/tooltip-trigger/TooltipTrigger.tsx +42 -0
- package/src/components/tooltip-trigger/index.ts +2 -0
- package/src/components/tooltip-trigger/types.ts +9 -0
- package/src/index.ts +16 -0
- package/tsconfig.json +3 -0
- /package/{CONTRIBUTING.md → dist/CONTRIBUTING.md} +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{index.js → dist/index.js} +0 -0
- /package/{index.js.map → dist/index.js.map} +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": {
|
|
3
|
+
"name": "Red Sift"
|
|
4
|
+
},
|
|
5
|
+
"bugs": {
|
|
6
|
+
"url": "https://github.com/redsift/design-system/issues"
|
|
7
|
+
},
|
|
8
|
+
"description": "Popover component library as part of Red Sift's Design System. This package is based on @floating-ui/react and react-toastify.",
|
|
9
|
+
"homepage": "https://github.com/redsift/design-system",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"main": "index.js",
|
|
12
|
+
"module": "index.js",
|
|
13
|
+
"name": "@redsift/popovers",
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"directory": "dist"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/redsift/design-system"
|
|
20
|
+
},
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "rollup -c",
|
|
24
|
+
"check-types": "tsc && tsc-strict",
|
|
25
|
+
"lint": "eslint --ext .js,.jsx,.ts,.tsx src/",
|
|
26
|
+
"prepare": "install-peers || exit 0",
|
|
27
|
+
"prepublishOnly": "yarn build",
|
|
28
|
+
"test:unit": "NODE_ENV=test jest --verbose",
|
|
29
|
+
"test:storybook": "test-storybook -c ../../.storybook --url http://localhost:9000/ --coverage",
|
|
30
|
+
"test": "yarn test:unit && yarn test:storybook"
|
|
31
|
+
},
|
|
32
|
+
"types": "index.d.ts",
|
|
33
|
+
"version": "9.2.3",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@floating-ui/react": "^0.19.2",
|
|
36
|
+
"@react-aria/i18n": "3.7.2",
|
|
37
|
+
"classnames": "^2.3.1",
|
|
38
|
+
"react-toastify": "^9.1.1"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@babel/core": "^7.8.3",
|
|
42
|
+
"@babel/plugin-proposal-class-properties": "^7.16.7",
|
|
43
|
+
"@babel/plugin-proposal-export-default-from": "^7.16.7",
|
|
44
|
+
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7",
|
|
45
|
+
"@babel/plugin-proposal-object-rest-spread": "^7.17.3",
|
|
46
|
+
"@babel/plugin-proposal-optional-chaining": "^7.16.7",
|
|
47
|
+
"@babel/plugin-proposal-private-methods": "^7.16.11",
|
|
48
|
+
"@babel/plugin-proposal-private-property-in-object": "^7.16.7",
|
|
49
|
+
"@babel/preset-env": "^7.17.10",
|
|
50
|
+
"@babel/preset-react": "^7.17.12",
|
|
51
|
+
"@babel/preset-typescript": "^7.16.7",
|
|
52
|
+
"@rollup/plugin-babel": "^6.0.2",
|
|
53
|
+
"@rollup/plugin-commonjs": "^24.0.0",
|
|
54
|
+
"@rollup/plugin-json": "^6.0.0",
|
|
55
|
+
"@rollup/plugin-node-resolve": "^13.3.0",
|
|
56
|
+
"@svgr/rollup": "^6.2.1",
|
|
57
|
+
"@testing-library/dom": "^8.5.0",
|
|
58
|
+
"@testing-library/jest-dom": "^5.16.4",
|
|
59
|
+
"@testing-library/react": "^13.4.0",
|
|
60
|
+
"@testing-library/user-event": "14.2.1",
|
|
61
|
+
"@types/jest": "^27.5.1",
|
|
62
|
+
"@types/react": "18.0.12",
|
|
63
|
+
"@types/react-dom": "18.0.5",
|
|
64
|
+
"@types/react-transition-group": "^4.4.5",
|
|
65
|
+
"@types/styled-components": "^5.1.25",
|
|
66
|
+
"@typescript-eslint/eslint-plugin": "^5.48.0",
|
|
67
|
+
"@typescript-eslint/parser": "^5.26.0",
|
|
68
|
+
"autoprefixer": "^9.7.4",
|
|
69
|
+
"babel-plugin-require-context-hook": "^1.0.0",
|
|
70
|
+
"changelog-verify": "^1.1.2",
|
|
71
|
+
"identity-obj-proxy": "^3.0.0",
|
|
72
|
+
"install-peers-cli": "^2.2.0",
|
|
73
|
+
"jest": "^28.1.0",
|
|
74
|
+
"jest-environment-jsdom": "^29.3.0",
|
|
75
|
+
"react": "18.2.0",
|
|
76
|
+
"react-dom": "18.2.0",
|
|
77
|
+
"rollup": "^2.72.1",
|
|
78
|
+
"rollup-plugin-analyzer": "^4.0.0",
|
|
79
|
+
"rollup-plugin-auto-external": "^2.0.0",
|
|
80
|
+
"rollup-plugin-cleaner": "^1.0.0",
|
|
81
|
+
"rollup-plugin-copy": "^3.4.0",
|
|
82
|
+
"rollup-plugin-dts": "^5.0.0",
|
|
83
|
+
"rollup-plugin-execute": "^1.1.0",
|
|
84
|
+
"rollup-plugin-svg": "^2.0.0",
|
|
85
|
+
"rollup-plugin-ts-paths-resolve": "^1.7.1",
|
|
86
|
+
"rollup-plugin-typescript-paths": "^1.3.1",
|
|
87
|
+
"ts-jest": "^28.0.3"
|
|
88
|
+
},
|
|
89
|
+
"peerDependencies": {
|
|
90
|
+
"@redsift/design-system": ">=9.0.0-alpha.0",
|
|
91
|
+
"@redsift/icons": ">=9.0.0-alpha.0",
|
|
92
|
+
"react": ">=17",
|
|
93
|
+
"react-dom": ">=17",
|
|
94
|
+
"styled-components": "^5.3.5"
|
|
95
|
+
}
|
|
96
|
+
}
|
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src';
|
package/jest.config.js
ADDED
package/package.json
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"test": "yarn test:unit && yarn test:storybook"
|
|
31
31
|
},
|
|
32
32
|
"types": "index.d.ts",
|
|
33
|
-
"version": "9.2.3
|
|
33
|
+
"version": "9.2.3",
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@floating-ui/react": "^0.19.2",
|
|
36
36
|
"@react-aria/i18n": "3.7.2",
|
|
@@ -92,6 +92,5 @@
|
|
|
92
92
|
"react": ">=17",
|
|
93
93
|
"react-dom": ">=17",
|
|
94
94
|
"styled-components": "^5.3.5"
|
|
95
|
-
}
|
|
96
|
-
"gitHead": "44635b1b3181bd68befd7efc0c3519a81342ad7b"
|
|
95
|
+
}
|
|
97
96
|
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { rollupConfig } from '../../configs/rollup.base.config';
|
|
2
|
+
|
|
3
|
+
import pkg from './package.json';
|
|
4
|
+
|
|
5
|
+
const baseRollupConfig = rollupConfig(__dirname, pkg);
|
|
6
|
+
|
|
7
|
+
// Bundle JS code
|
|
8
|
+
const bundleJS = { ...baseRollupConfig.bundleJS };
|
|
9
|
+
|
|
10
|
+
// Bundle TS types in D.TS files
|
|
11
|
+
const bundleType = { ...baseRollupConfig.bundleType };
|
|
12
|
+
|
|
13
|
+
export default [bundleJS, bundleType];
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import React, { RefObject, useRef, useState } from 'react';
|
|
2
|
+
import { Flexbox, Button, Number, Text, Checkbox } from '@redsift/design-system';
|
|
3
|
+
import { Dialog, DialogProps } from '.';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'Popovers/Dialog',
|
|
7
|
+
component: Dialog,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const Uncontrolled = () => {
|
|
11
|
+
const nextButtonRef = useRef<HTMLButtonElement>(null);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<Dialog initialFocus={nextButtonRef} defaultOpen={false}>
|
|
15
|
+
<Dialog.Trigger>
|
|
16
|
+
<Button variant="secondary">Button</Button>
|
|
17
|
+
</Dialog.Trigger>
|
|
18
|
+
<Dialog.Content>
|
|
19
|
+
<Dialog.Content.Header header="Dialog Header">
|
|
20
|
+
<Text>
|
|
21
|
+
<Number value={102} as="b" /> mails have been detected from this domain.
|
|
22
|
+
</Text>
|
|
23
|
+
</Dialog.Content.Header>
|
|
24
|
+
<Dialog.Content.Body>
|
|
25
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
|
|
26
|
+
magna aliqua.
|
|
27
|
+
</Dialog.Content.Body>
|
|
28
|
+
<Dialog.Content.Actions justifyContent="space-between">
|
|
29
|
+
<Button variant="unstyled">Previous</Button>
|
|
30
|
+
<Flexbox>
|
|
31
|
+
<Button variant="secondary">Cancel</Button>
|
|
32
|
+
<Button ref={nextButtonRef as RefObject<HTMLButtonElement>}>Next</Button>
|
|
33
|
+
</Flexbox>
|
|
34
|
+
</Dialog.Content.Actions>
|
|
35
|
+
</Dialog.Content>
|
|
36
|
+
</Dialog>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const Controlled = () => {
|
|
41
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
42
|
+
const nextButtonRef = useRef<HTMLButtonElement>(null);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<>
|
|
46
|
+
<Button variant="secondary" onClick={() => setIsOpen(!isOpen)}>
|
|
47
|
+
External trigger
|
|
48
|
+
</Button>
|
|
49
|
+
<Dialog isOpen={isOpen} onOpen={setIsOpen} initialFocus={nextButtonRef}>
|
|
50
|
+
<Dialog.Trigger>
|
|
51
|
+
<Button variant="secondary">Trigger</Button>
|
|
52
|
+
</Dialog.Trigger>
|
|
53
|
+
<Dialog.Content>
|
|
54
|
+
<Dialog.Content.Header header="Dialog Header">
|
|
55
|
+
<Text>
|
|
56
|
+
<Number value={102} as="b" /> mails have been detected from this domain.
|
|
57
|
+
</Text>
|
|
58
|
+
</Dialog.Content.Header>
|
|
59
|
+
<Dialog.Content.Body>
|
|
60
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
|
|
61
|
+
dolore magna aliqua.
|
|
62
|
+
</Dialog.Content.Body>
|
|
63
|
+
<Dialog.Content.Actions justifyContent="space-between">
|
|
64
|
+
<Button variant="unstyled">Previous</Button>
|
|
65
|
+
<Flexbox>
|
|
66
|
+
<Button variant="secondary">Cancel</Button>
|
|
67
|
+
<Button ref={nextButtonRef as RefObject<HTMLButtonElement>}>Next</Button>
|
|
68
|
+
</Flexbox>
|
|
69
|
+
</Dialog.Content.Actions>
|
|
70
|
+
</Dialog.Content>
|
|
71
|
+
</Dialog>
|
|
72
|
+
</>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const CheckboxAsTrigger = () => {
|
|
77
|
+
const nextButtonRef = useRef<HTMLButtonElement>(null);
|
|
78
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
79
|
+
const [selected, setSelected] = useState(false);
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<Dialog isOpen={isOpen} onOpen={setIsOpen} initialFocus={nextButtonRef} defaultOpen={false}>
|
|
83
|
+
<Dialog.Trigger>
|
|
84
|
+
<Checkbox isSelected={selected} onChange={() => {}}>
|
|
85
|
+
I accept the terms and conditions
|
|
86
|
+
</Checkbox>
|
|
87
|
+
</Dialog.Trigger>
|
|
88
|
+
<Dialog.Content>
|
|
89
|
+
<Dialog.Content.Header header="Terms and conditions" />
|
|
90
|
+
<Dialog.Content.Body display="flex" flexDirection="column" gap="8px">
|
|
91
|
+
<p>
|
|
92
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent ligula est, volutpat sit amet lectus
|
|
93
|
+
condimentum, laoreet imperdiet dolor. Sed eu enim vitae orci egestas blandit id non orci. Mauris blandit
|
|
94
|
+
quis erat sit amet suscipit. Proin congue, leo vitae rutrum accumsan, leo diam consectetur sapien, fermentum
|
|
95
|
+
vestibulum elit turpis et metus. Nulla id magna a enim pulvinar accumsan sit amet sit amet dui. Fusce
|
|
96
|
+
fermentum accumsan odio molestie convallis. Mauris faucibus ex bibendum, condimentum risus eget, ullamcorper
|
|
97
|
+
diam. Nullam at ullamcorper felis. Donec diam ante, gravida a ex non, semper interdum orci.
|
|
98
|
+
</p>
|
|
99
|
+
<p>
|
|
100
|
+
Aliquam rhoncus dui ut odio accumsan, a suscipit ex posuere. Quisque faucibus, justo at consequat malesuada,
|
|
101
|
+
tellus nunc tempus mi, in consequat justo metus ac urna. Suspendisse ut augue at arcu aliquam porttitor. Nam
|
|
102
|
+
vestibulum sit amet nulla quis lobortis. Aenean id odio ut ex ultrices egestas. Nulla luctus fringilla nibh,
|
|
103
|
+
eu accumsan massa mollis eget. Pellentesque eleifend sit amet ante ut lobortis. Curabitur imperdiet ex
|
|
104
|
+
gravida lacus fringilla mollis. Phasellus quis metus elit. Praesent lobortis nec ipsum suscipit congue.
|
|
105
|
+
Aliquam in congue felis.
|
|
106
|
+
</p>
|
|
107
|
+
<p>
|
|
108
|
+
Donec a ante eget leo aliquet congue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices
|
|
109
|
+
posuere cubilia curae; Nunc id libero vitae ante interdum pharetra. Phasellus ipsum diam, sagittis eget
|
|
110
|
+
feugiat in, faucibus ut quam. Sed ac urna interdum, convallis libero vel, fringilla ipsum. Suspendisse
|
|
111
|
+
blandit fringilla augue, in fringilla nulla. Quisque aliquet mi in fermentum sagittis. Vestibulum eu feugiat
|
|
112
|
+
est. Proin tristique, turpis commodo elementum ultricies, elit ipsum lobortis ex, sed porta orci dolor at
|
|
113
|
+
mi.
|
|
114
|
+
</p>
|
|
115
|
+
<p>
|
|
116
|
+
Donec in dolor blandit, egestas nunc sed, mollis ligula. Class aptent taciti sociosqu ad litora torquent per
|
|
117
|
+
conubia nostra, per inceptos himenaeos. Etiam tempor ipsum id tincidunt pharetra. Nulla orci tortor,
|
|
118
|
+
tristique semper vulputate nec, pharetra sit amet quam. Pellentesque habitant morbi tristique senectus et
|
|
119
|
+
netus et malesuada fames ac turpis egestas. Nam suscipit lacus odio, at vestibulum orci viverra in.
|
|
120
|
+
Phasellus interdum dictum congue. Nulla erat turpis, fermentum sit amet placerat eu, condimentum nec augue.
|
|
121
|
+
Donec eget tortor in massa vehicula ultrices.
|
|
122
|
+
</p>
|
|
123
|
+
<p>
|
|
124
|
+
Sed quis turpis turpis. Ut tincidunt justo ligula, a fermentum nisl venenatis vitae. Vestibulum sodales
|
|
125
|
+
consequat diam, venenatis placerat libero dignissim ac. Vestibulum placerat venenatis pretium. Suspendisse
|
|
126
|
+
potenti. Etiam at pretium magna, non pulvinar risus. Nulla in enim felis. Proin at luctus ipsum. Nunc a
|
|
127
|
+
tristique odio, et dictum quam. Donec a commodo ante, eget fringilla augue. Proin luctus neque vitae est
|
|
128
|
+
congue, et volutpat libero luctus. Nulla luctus placerat accumsan. Aliquam tristique urna est, nec volutpat
|
|
129
|
+
nisl varius at.
|
|
130
|
+
</p>
|
|
131
|
+
</Dialog.Content.Body>
|
|
132
|
+
<Dialog.Content.Actions justifyContent="space-between">
|
|
133
|
+
<Button
|
|
134
|
+
variant="secondary"
|
|
135
|
+
onClick={() => {
|
|
136
|
+
setSelected(false);
|
|
137
|
+
setIsOpen(false);
|
|
138
|
+
}}
|
|
139
|
+
>
|
|
140
|
+
Decline
|
|
141
|
+
</Button>
|
|
142
|
+
<Button
|
|
143
|
+
ref={nextButtonRef as RefObject<HTMLButtonElement>}
|
|
144
|
+
onClick={() => {
|
|
145
|
+
setSelected(true);
|
|
146
|
+
setIsOpen(false);
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
Accept
|
|
150
|
+
</Button>
|
|
151
|
+
</Dialog.Content.Actions>
|
|
152
|
+
</Dialog.Content>
|
|
153
|
+
</Dialog>
|
|
154
|
+
);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export const TriggerIsInvalid = () => (
|
|
158
|
+
<Dialog>
|
|
159
|
+
<Dialog.Trigger>
|
|
160
|
+
This text has a dialog but this will never be displayed because the trigger is not a button.
|
|
161
|
+
</Dialog.Trigger>
|
|
162
|
+
<Dialog.Content>
|
|
163
|
+
<Text margin="16px">
|
|
164
|
+
Cupcake ipsum dolor sit amet blueie jujubes topping sesame snaps. Liquorice marzipan jelly-o carrot cake icing
|
|
165
|
+
croissant carrot cake. Tart soufflé sweet roll halvah croissant wafer cotton candy. Candy halvah marzipan bear
|
|
166
|
+
claw donut.
|
|
167
|
+
</Text>
|
|
168
|
+
</Dialog.Content>
|
|
169
|
+
</Dialog>
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
export const EmptyDialog = () => (
|
|
173
|
+
<Flexbox
|
|
174
|
+
flexDirection="row"
|
|
175
|
+
flexWrap="wrap"
|
|
176
|
+
justifyContent="center"
|
|
177
|
+
alignItems="center"
|
|
178
|
+
padding="32px"
|
|
179
|
+
style={{ backgroundColor: '#EFEFEF' }}
|
|
180
|
+
>
|
|
181
|
+
<Dialog>
|
|
182
|
+
<Dialog.Trigger>
|
|
183
|
+
<Button variant="secondary">Button</Button>
|
|
184
|
+
</Dialog.Trigger>
|
|
185
|
+
</Dialog>
|
|
186
|
+
</Flexbox>
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
export const DialogOnDisabledButton = () => (
|
|
190
|
+
<Flexbox
|
|
191
|
+
flexDirection="row"
|
|
192
|
+
flexWrap="wrap"
|
|
193
|
+
justifyContent="center"
|
|
194
|
+
alignItems="center"
|
|
195
|
+
padding="32px"
|
|
196
|
+
style={{ backgroundColor: '#EFEFEF' }}
|
|
197
|
+
>
|
|
198
|
+
<Dialog>
|
|
199
|
+
<Dialog.Trigger>
|
|
200
|
+
<Button variant="secondary" isDisabled>
|
|
201
|
+
Disabled
|
|
202
|
+
</Button>
|
|
203
|
+
</Dialog.Trigger>
|
|
204
|
+
<Dialog.Content>
|
|
205
|
+
<Text margin="16px">
|
|
206
|
+
Cupcake ipsum dolor sit amet blueie jujubes topping sesame snaps. Liquorice marzipan jelly-o carrot cake icing
|
|
207
|
+
croissant carrot cake. Tart soufflé sweet roll halvah croissant wafer cotton candy. Candy halvah marzipan bear
|
|
208
|
+
claw donut.
|
|
209
|
+
</Text>
|
|
210
|
+
</Dialog.Content>
|
|
211
|
+
</Dialog>
|
|
212
|
+
</Flexbox>
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
export const InitialFocus = () => {
|
|
216
|
+
const nextButtonRef = useRef<HTMLButtonElement>(null);
|
|
217
|
+
|
|
218
|
+
const renderDialog = ({ title, initialFocus }: { title: string; initialFocus?: DialogProps['initialFocus'] }) => (
|
|
219
|
+
<Dialog initialFocus={initialFocus}>
|
|
220
|
+
<Dialog.Trigger>
|
|
221
|
+
<Button variant="secondary">{title}</Button>
|
|
222
|
+
</Dialog.Trigger>
|
|
223
|
+
<Dialog.Content>
|
|
224
|
+
<Dialog.Content.Header header="Dialog Header">
|
|
225
|
+
<Text>
|
|
226
|
+
<Number value={102} as="b" /> mails have been detected from this domain.
|
|
227
|
+
</Text>
|
|
228
|
+
</Dialog.Content.Header>
|
|
229
|
+
<Dialog.Content.Body>
|
|
230
|
+
{Array.from({ length: 100 }).map((e, i) => (
|
|
231
|
+
<p key={i}>
|
|
232
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
|
|
233
|
+
dolore magna aliqua.
|
|
234
|
+
</p>
|
|
235
|
+
))}
|
|
236
|
+
</Dialog.Content.Body>
|
|
237
|
+
<Dialog.Content.Actions justifyContent="space-between">
|
|
238
|
+
<Button variant="unstyled">Previous</Button>
|
|
239
|
+
<Flexbox>
|
|
240
|
+
<Button variant="secondary">Cancel</Button>
|
|
241
|
+
<Button ref={nextButtonRef as RefObject<HTMLButtonElement>}>Next</Button>
|
|
242
|
+
</Flexbox>
|
|
243
|
+
</Dialog.Content.Actions>
|
|
244
|
+
</Dialog.Content>
|
|
245
|
+
</Dialog>
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
return (
|
|
249
|
+
<Flexbox
|
|
250
|
+
flexDirection="row"
|
|
251
|
+
flexWrap="wrap"
|
|
252
|
+
justifyContent="center"
|
|
253
|
+
alignItems="center"
|
|
254
|
+
padding="32px"
|
|
255
|
+
style={{ backgroundColor: '#EFEFEF' }}
|
|
256
|
+
>
|
|
257
|
+
{renderDialog({ title: 'Default' })}
|
|
258
|
+
{renderDialog({ title: 'Next', initialFocus: nextButtonRef })}
|
|
259
|
+
{renderDialog({ title: 'Header', initialFocus: 'header' })}
|
|
260
|
+
{renderDialog({ title: 'Body', initialFocus: 'body' })}
|
|
261
|
+
{renderDialog({ title: 'Actions', initialFocus: 'actions' })}
|
|
262
|
+
</Flexbox>
|
|
263
|
+
);
|
|
264
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
act,
|
|
4
|
+
fireEvent,
|
|
5
|
+
render,
|
|
6
|
+
screen,
|
|
7
|
+
waitFor,
|
|
8
|
+
} from '@testing-library/react';
|
|
9
|
+
|
|
10
|
+
import { Button } from '@redsift/design-system';
|
|
11
|
+
import { DialogContent } from '../dialog-content';
|
|
12
|
+
import { DialogTrigger } from '../dialog-trigger';
|
|
13
|
+
import { DialogContentHeader } from '../dialog-content-header';
|
|
14
|
+
import { DialogContentBody } from '../dialog-content-body';
|
|
15
|
+
import { Dialog } from '.';
|
|
16
|
+
|
|
17
|
+
describe('Dialog', () => {
|
|
18
|
+
const onOpenSpy = jest.fn();
|
|
19
|
+
const realError = console.error;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
console.error = jest.fn();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
onOpenSpy.mockClear();
|
|
27
|
+
console.error = realError;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it.each`
|
|
31
|
+
Name | Component | props
|
|
32
|
+
${'DialogTrigger'} | ${DialogTrigger} | ${{}}
|
|
33
|
+
${'DialogContent'} | ${DialogContent} | ${{}}
|
|
34
|
+
${'DialogContentHeader'} | ${DialogContentHeader} | ${{}}
|
|
35
|
+
`(
|
|
36
|
+
'$Name should throw error when not wrapped inside `Dialog`',
|
|
37
|
+
function ({ Component, props }) {
|
|
38
|
+
expect(() => render(<Component {...props} />)).toThrow(
|
|
39
|
+
'Dialog components must be wrapped in <Dialog />'
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
it.each`
|
|
45
|
+
Name | Component | props
|
|
46
|
+
${'Controlled Dialog'} | ${Dialog} | ${{ onOpen: onOpenSpy, isOpen: false }}
|
|
47
|
+
${'Uncontrolled Dialog'} | ${Dialog} | ${{ onOpen: onOpenSpy, defaultOpen: false }}
|
|
48
|
+
`(
|
|
49
|
+
'$Name can be closed by default and then open',
|
|
50
|
+
async function ({ Name, Component, props }) {
|
|
51
|
+
const { getByText } = render(
|
|
52
|
+
<Component {...props}>
|
|
53
|
+
<DialogTrigger>
|
|
54
|
+
<Button variant="secondary">Trigger</Button>
|
|
55
|
+
</DialogTrigger>
|
|
56
|
+
<DialogContent>
|
|
57
|
+
<DialogContentBody>Content</DialogContentBody>
|
|
58
|
+
</DialogContent>
|
|
59
|
+
</Component>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
expect(screen.queryByText('Content')).not.toBeInTheDocument();
|
|
63
|
+
expect(onOpenSpy).not.toHaveBeenCalled();
|
|
64
|
+
|
|
65
|
+
const triggerButton = getByText('Trigger');
|
|
66
|
+
fireEvent.click(triggerButton);
|
|
67
|
+
|
|
68
|
+
expect(onOpenSpy).toHaveBeenCalled();
|
|
69
|
+
if (Name.includes('Uncontrolled')) {
|
|
70
|
+
await act(async () => {});
|
|
71
|
+
await waitFor(() => {
|
|
72
|
+
expect(screen.queryByText('Content')).toBeInTheDocument();
|
|
73
|
+
});
|
|
74
|
+
expect(getByText('Content')).toBeVisible();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
it.each`
|
|
80
|
+
Name | Component | props
|
|
81
|
+
${'Controlled Dialog'} | ${Dialog} | ${{ onOpen: onOpenSpy, isOpen: true }}
|
|
82
|
+
${'Uncontrolled Dialog'} | ${Dialog} | ${{ onOpen: onOpenSpy, defaultOpen: true }}
|
|
83
|
+
`(
|
|
84
|
+
'$Name can be open by default and then closed',
|
|
85
|
+
async function ({ Name, Component, props }) {
|
|
86
|
+
render(
|
|
87
|
+
<Component {...props}>
|
|
88
|
+
<DialogTrigger>
|
|
89
|
+
<Button variant="secondary">Trigger</Button>
|
|
90
|
+
</DialogTrigger>
|
|
91
|
+
<DialogContent>
|
|
92
|
+
<DialogContentBody>Content</DialogContentBody>
|
|
93
|
+
</DialogContent>
|
|
94
|
+
</Component>
|
|
95
|
+
);
|
|
96
|
+
await act(async () => {});
|
|
97
|
+
await waitFor(() => {
|
|
98
|
+
expect(screen.queryByText('Content')).toBeInTheDocument();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
expect(screen.queryByText('Content')).toBeVisible();
|
|
102
|
+
expect(onOpenSpy).not.toHaveBeenCalled();
|
|
103
|
+
|
|
104
|
+
const closeButton = screen.getByLabelText('Close');
|
|
105
|
+
fireEvent.click(closeButton);
|
|
106
|
+
|
|
107
|
+
expect(onOpenSpy).toHaveBeenCalled();
|
|
108
|
+
if (Name.includes('Uncontrolled')) {
|
|
109
|
+
await act(async () => {});
|
|
110
|
+
await waitFor(() => {
|
|
111
|
+
expect(screen.queryByText('Content')).not.toBeInTheDocument();
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { partitionComponents, isComponent } from '@redsift/design-system';
|
|
3
|
+
import { DialogContent } from '../dialog-content';
|
|
4
|
+
import { DialogTrigger } from '../dialog-trigger';
|
|
5
|
+
|
|
6
|
+
import { DialogContext } from './context';
|
|
7
|
+
import { DialogProps, DialogSize } from './types';
|
|
8
|
+
import { useDialog } from './useDialog';
|
|
9
|
+
|
|
10
|
+
const COMPONENT_NAME = 'Dialog';
|
|
11
|
+
const CLASSNAME = 'redsift-dialog';
|
|
12
|
+
const DEFAULT_PROPS: Partial<DialogProps> = {
|
|
13
|
+
hasCloseButton: true,
|
|
14
|
+
size: DialogSize.medium,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The Dialog component.
|
|
19
|
+
*/
|
|
20
|
+
export const BaseDialog: React.FC<DialogProps> & {
|
|
21
|
+
displayName?: string;
|
|
22
|
+
className?: string;
|
|
23
|
+
} = (props) => {
|
|
24
|
+
const {
|
|
25
|
+
children,
|
|
26
|
+
defaultOpen,
|
|
27
|
+
hasCloseButton = DEFAULT_PROPS.hasCloseButton,
|
|
28
|
+
initialFocus,
|
|
29
|
+
isOpen,
|
|
30
|
+
onOpen,
|
|
31
|
+
size,
|
|
32
|
+
} = props;
|
|
33
|
+
|
|
34
|
+
const dialog = useDialog({
|
|
35
|
+
defaultOpen,
|
|
36
|
+
hasCloseButton,
|
|
37
|
+
initialFocus,
|
|
38
|
+
isOpen,
|
|
39
|
+
onOpen,
|
|
40
|
+
size,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const [[trigger], [content]] = partitionComponents(
|
|
44
|
+
React.Children.toArray(children),
|
|
45
|
+
[isComponent('DialogTrigger'), isComponent('DialogContent')]
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<DialogContext.Provider value={dialog}>
|
|
50
|
+
{trigger}
|
|
51
|
+
{content}
|
|
52
|
+
</DialogContext.Provider>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
BaseDialog.className = CLASSNAME;
|
|
56
|
+
BaseDialog.defaultProps = DEFAULT_PROPS;
|
|
57
|
+
BaseDialog.displayName = COMPONENT_NAME;
|
|
58
|
+
|
|
59
|
+
export const Dialog = Object.assign(BaseDialog, {
|
|
60
|
+
Trigger: DialogTrigger,
|
|
61
|
+
Content: DialogContent,
|
|
62
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Dispatch, ReactNode, SetStateAction } from 'react';
|
|
2
|
+
import { ValueOf } from '@redsift/design-system';
|
|
3
|
+
import { useDialog } from './useDialog';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Context props.
|
|
7
|
+
*/
|
|
8
|
+
export type DialogState =
|
|
9
|
+
| (ReturnType<typeof useDialog> & {
|
|
10
|
+
setLabelId: Dispatch<SetStateAction<string | undefined>>;
|
|
11
|
+
setDescriptionId: Dispatch<SetStateAction<string | undefined>>;
|
|
12
|
+
})
|
|
13
|
+
| null;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Component variant.
|
|
17
|
+
*/
|
|
18
|
+
export const DialogSize = {
|
|
19
|
+
small: 'small',
|
|
20
|
+
medium: 'medium',
|
|
21
|
+
large: 'large',
|
|
22
|
+
xlarge: 'xlarge',
|
|
23
|
+
} as const;
|
|
24
|
+
export type DialogSize = ValueOf<typeof DialogSize>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Component props.
|
|
28
|
+
*/
|
|
29
|
+
export interface DialogProps {
|
|
30
|
+
/** Children. Can only be DialogTrigger and DialogContent. */
|
|
31
|
+
children: ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* Default open status.
|
|
34
|
+
* Used for uncontrolled version.
|
|
35
|
+
*/
|
|
36
|
+
defaultOpen?: boolean;
|
|
37
|
+
/** Whether the Close icon button is displayed or not. */
|
|
38
|
+
hasCloseButton?: boolean;
|
|
39
|
+
/** Which element to initially focus. Can be either a number (tabbable index), a ref to en element, or a shortcut pointing towards a section of the dialog. See the accessibility section in the documentation to know which one to use. */
|
|
40
|
+
initialFocus?: number | React.MutableRefObject<HTMLElement | null> | 'header' | 'body' | 'actions';
|
|
41
|
+
/**
|
|
42
|
+
* Whether the component is opened or not.
|
|
43
|
+
* Used for controlled version.
|
|
44
|
+
*/
|
|
45
|
+
isOpen?: boolean;
|
|
46
|
+
/** Method to handle component change. */
|
|
47
|
+
onOpen?: (open: boolean) => void;
|
|
48
|
+
/** Dialog size. */
|
|
49
|
+
size?: DialogSize | { width: string };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type StyledDialogProps = DialogProps;
|