@saleor/macaw-ui 0.2.4
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/README.md +40 -0
- package/dist/ActionBar/ActionBar.d.ts +8 -0
- package/dist/ActionBar/context.d.ts +9 -0
- package/dist/ActionBar/index.d.ts +2 -0
- package/dist/ActionBar/styles.d.ts +2 -0
- package/dist/Alert/Alert.d.ts +9 -0
- package/dist/Alert/index.d.ts +1 -0
- package/dist/Alert/styles.d.ts +2 -0
- package/dist/Backlink/Backlink.d.ts +6 -0
- package/dist/Backlink/context.d.ts +5 -0
- package/dist/Backlink/index.d.ts +2 -0
- package/dist/Backlink/styles.d.ts +2 -0
- package/dist/ConfirmButton/ConfirmButton.d.ts +11 -0
- package/dist/ConfirmButton/index.d.ts +1 -0
- package/dist/ConfirmButton/styles.d.ts +2 -0
- package/dist/Notification/Notification.d.ts +3 -0
- package/dist/Notification/index.d.ts +2 -0
- package/dist/Notification/styles.d.ts +2 -0
- package/dist/Notification/types.d.ts +16 -0
- package/dist/ResponsiveTable/ResponsiveTable.d.ts +8 -0
- package/dist/ResponsiveTable/index.d.ts +1 -0
- package/dist/ResponsiveTable/styles.d.ts +2 -0
- package/dist/Savebar/ButtonTooltipDecorator.d.ts +6 -0
- package/dist/Savebar/Savebar.d.ts +14 -0
- package/dist/Savebar/index.d.ts +1 -0
- package/dist/Savebar/styles.d.ts +2 -0
- package/dist/Sidebar/ExpandButton.d.ts +6 -0
- package/dist/Sidebar/MenuItem.d.ts +11 -0
- package/dist/Sidebar/Sidebar.d.ts +6 -0
- package/dist/Sidebar/fixtures.d.ts +2 -0
- package/dist/Sidebar/index.d.ts +4 -0
- package/dist/Sidebar/types.d.ts +16 -0
- package/dist/SidebarDrawer/MenuItemBtn.d.ts +7 -0
- package/dist/SidebarDrawer/SidebarDrawer.d.ts +4 -0
- package/dist/SidebarDrawer/index.d.ts +2 -0
- package/dist/SidebarDrawer/styles.d.ts +2 -0
- package/dist/SquareButton/SquareButton.d.ts +3 -0
- package/dist/SquareButton/index.d.ts +1 -0
- package/dist/Tooltip/Tooltip.d.ts +6 -0
- package/dist/Tooltip/index.d.ts +1 -0
- package/dist/Tooltip/styles.d.ts +3 -0
- package/dist/UserChipMenu/UserChipMenu.d.ts +8 -0
- package/dist/UserChipMenu/UserChipMenuItem.d.ts +6 -0
- package/dist/UserChipMenu/context.d.ts +4 -0
- package/dist/UserChipMenu/index.d.ts +2 -0
- package/dist/UserChipMenu/styles.d.ts +2 -0
- package/dist/extensions/index.d.ts +3 -0
- package/dist/extensions/sendMessage.d.ts +3 -0
- package/dist/extensions/types.d.ts +22 -0
- package/dist/extensions/useExtensionMessage.d.ts +2 -0
- package/dist/icons/ArrowDropdownIcon.d.ts +2 -0
- package/dist/icons/CheckboxCheckedIcon.d.ts +1 -0
- package/dist/icons/CheckboxIcon.d.ts +1 -0
- package/dist/icons/CheckboxIndeterminateIcon.d.ts +1 -0
- package/dist/icons/CompleteIcon.d.ts +2 -0
- package/dist/icons/InfoIcon.d.ts +2 -0
- package/dist/icons/Logo.d.ts +2 -0
- package/dist/icons/NotAllowedIcon.d.ts +2 -0
- package/dist/icons/NotAllowedInvertedIcon.d.ts +2 -0
- package/dist/icons/WarningIcon.d.ts +2 -0
- package/dist/icons/index.d.ts +9 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +8 -0
- package/dist/localStorageKeys.d.ts +4 -0
- package/dist/macaw-ui.cjs.development.js +2582 -0
- package/dist/macaw-ui.cjs.development.js.map +1 -0
- package/dist/macaw-ui.cjs.production.min.js +2 -0
- package/dist/macaw-ui.cjs.production.min.js.map +1 -0
- package/dist/macaw-ui.esm.js +2536 -0
- package/dist/macaw-ui.esm.js.map +1 -0
- package/dist/theme/Baseline.d.ts +2 -0
- package/dist/theme/ThemeProvider.d.ts +17 -0
- package/dist/theme/context.d.ts +3 -0
- package/dist/theme/createSaleorTheme/createSaleorTheme.d.ts +3 -0
- package/dist/theme/createSaleorTheme/index.d.ts +2 -0
- package/dist/theme/createSaleorTheme/overrides/buttons.d.ts +3 -0
- package/dist/theme/createSaleorTheme/overrides/index.d.ts +3 -0
- package/dist/theme/createSaleorTheme/overrides/inputs.d.ts +3 -0
- package/dist/theme/createSaleorTheme/overrides/tables.d.ts +3 -0
- package/dist/theme/createSaleorTheme/palette.d.ts +2 -0
- package/dist/theme/createSaleorTheme/shadows.d.ts +2 -0
- package/dist/theme/createSaleorTheme/types.d.ts +53 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/styles.d.ts +5 -0
- package/dist/theme/themes.d.ts +3 -0
- package/dist/theme/types.d.ts +6 -0
- package/dist/theme/utils.d.ts +1 -0
- package/dist/tools/useLocalStorage.d.ts +5 -0
- package/dist/tools/useWindowScroll.d.ts +5 -0
- package/dist/utils/Decorator.d.ts +4 -0
- package/package.json +117 -0
- package/src/ActionBar/ActionBar.stories.tsx +34 -0
- package/src/ActionBar/ActionBar.tsx +58 -0
- package/src/ActionBar/context.tsx +32 -0
- package/src/ActionBar/index.ts +2 -0
- package/src/ActionBar/styles.ts +27 -0
- package/src/Alert/Alert.stories.tsx +30 -0
- package/src/Alert/Alert.tsx +86 -0
- package/src/Alert/index.ts +1 -0
- package/src/Alert/styles.ts +46 -0
- package/src/Backlink/Backlink.stories.tsx +51 -0
- package/src/Backlink/Backlink.tsx +40 -0
- package/src/Backlink/context.tsx +27 -0
- package/src/Backlink/index.ts +2 -0
- package/src/Backlink/styles.ts +41 -0
- package/src/ConfirmButton/ConfirmButton.stories.tsx +72 -0
- package/src/ConfirmButton/ConfirmButton.tsx +119 -0
- package/src/ConfirmButton/index.ts +1 -0
- package/src/ConfirmButton/styles.ts +44 -0
- package/src/Notification/Notification.stories.tsx +42 -0
- package/src/Notification/Notification.tsx +98 -0
- package/src/Notification/index.ts +2 -0
- package/src/Notification/styles.ts +74 -0
- package/src/Notification/types.ts +18 -0
- package/src/ResponsiveTable/ResponsiveTable.tsx +24 -0
- package/src/ResponsiveTable/index.ts +1 -0
- package/src/ResponsiveTable/styles.ts +23 -0
- package/src/Savebar/ButtonTooltipDecorator.tsx +22 -0
- package/src/Savebar/Savebar.stories.tsx +57 -0
- package/src/Savebar/Savebar.tsx +79 -0
- package/src/Savebar/index.ts +1 -0
- package/src/Savebar/styles.ts +25 -0
- package/src/Sidebar/ExpandButton.tsx +44 -0
- package/src/Sidebar/MenuItem.tsx +217 -0
- package/src/Sidebar/Sidebar.stories.tsx +21 -0
- package/src/Sidebar/Sidebar.tsx +88 -0
- package/src/Sidebar/fixtures.ts +39 -0
- package/src/Sidebar/index.ts +4 -0
- package/src/Sidebar/types.ts +18 -0
- package/src/SidebarDrawer/MenuItemBtn.tsx +40 -0
- package/src/SidebarDrawer/SidebarDrawer.stories.tsx +13 -0
- package/src/SidebarDrawer/SidebarDrawer.tsx +113 -0
- package/src/SidebarDrawer/index.ts +2 -0
- package/src/SidebarDrawer/styles.ts +69 -0
- package/src/SquareButton/SquareButton.stories.tsx +15 -0
- package/src/SquareButton/SquareButton.tsx +35 -0
- package/src/SquareButton/index.ts +1 -0
- package/src/Tooltip/Tooltip.stories.tsx +19 -0
- package/src/Tooltip/Tooltip.tsx +25 -0
- package/src/Tooltip/index.ts +1 -0
- package/src/Tooltip/styles.ts +28 -0
- package/src/UserChipMenu/UserChipMenu.stories.tsx +40 -0
- package/src/UserChipMenu/UserChipMenu.tsx +113 -0
- package/src/UserChipMenu/UserChipMenuItem.tsx +33 -0
- package/src/UserChipMenu/context.ts +19 -0
- package/src/UserChipMenu/index.ts +2 -0
- package/src/UserChipMenu/styles.ts +65 -0
- package/src/assets/placeholder_64x64.png +0 -0
- package/src/extensions/index.ts +3 -0
- package/src/extensions/sendMessage.ts +23 -0
- package/src/extensions/types.ts +26 -0
- package/src/extensions/useExtensionMessage.ts +13 -0
- package/src/icons/ArrowDropdownIcon.tsx +11 -0
- package/src/icons/CheckboxCheckedIcon.tsx +15 -0
- package/src/icons/CheckboxIcon.tsx +7 -0
- package/src/icons/CheckboxIndeterminateIcon.tsx +17 -0
- package/src/icons/CompleteIcon.tsx +25 -0
- package/src/icons/InfoIcon.tsx +23 -0
- package/src/icons/Logo.tsx +32 -0
- package/src/icons/NotAllowedIcon.tsx +25 -0
- package/src/icons/NotAllowedInvertedIcon.tsx +25 -0
- package/src/icons/WarningIcon.tsx +23 -0
- package/src/icons/index.ts +9 -0
- package/src/index.tsx +15 -0
- package/src/localStorageKeys.ts +4 -0
- package/src/theme/Baseline.tsx +30 -0
- package/src/theme/ThemeProvider.tsx +84 -0
- package/src/theme/context.ts +8 -0
- package/src/theme/createSaleorTheme/createSaleorTheme.ts +267 -0
- package/src/theme/createSaleorTheme/index.ts +2 -0
- package/src/theme/createSaleorTheme/overrides/buttons.ts +94 -0
- package/src/theme/createSaleorTheme/overrides/index.ts +15 -0
- package/src/theme/createSaleorTheme/overrides/inputs.ts +149 -0
- package/src/theme/createSaleorTheme/overrides/tables.ts +74 -0
- package/src/theme/createSaleorTheme/palette.ts +38 -0
- package/src/theme/createSaleorTheme/shadows.ts +46 -0
- package/src/theme/createSaleorTheme/types.ts +84 -0
- package/src/theme/index.ts +4 -0
- package/src/theme/styles.ts +40 -0
- package/src/theme/themes.ts +113 -0
- package/src/theme/types.ts +7 -0
- package/src/theme/utils.test.ts +43 -0
- package/src/theme/utils.ts +13 -0
- package/src/tools/useLocalStorage.ts +56 -0
- package/src/tools/useWindowScroll.ts +26 -0
- package/src/utils/Decorator.tsx +23 -0
package/package.json
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.4",
|
|
3
|
+
"license": "CC-BY-4.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"homepage": "https://macaw-ui.vercel.app/",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git://github.com/mirumee/macaw-ui.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/mirumee/macaw-ui/issues"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"saleor",
|
|
15
|
+
"macaw",
|
|
16
|
+
"macaw-ui",
|
|
17
|
+
"react",
|
|
18
|
+
"ui components"
|
|
19
|
+
],
|
|
20
|
+
"typings": "dist/index.d.ts",
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"src"
|
|
24
|
+
],
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=10"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"start": "tsdx watch",
|
|
30
|
+
"build": "tsdx build --tsconfig ./tsconfig.prod.json",
|
|
31
|
+
"test": "tsdx test --passWithNoTests",
|
|
32
|
+
"lint": "tsdx lint src",
|
|
33
|
+
"prepare": "npm run build",
|
|
34
|
+
"size": "size-limit",
|
|
35
|
+
"analyze": "size-limit --why",
|
|
36
|
+
"storybook": "start-storybook -p 6006",
|
|
37
|
+
"build-storybook": "build-storybook",
|
|
38
|
+
"release": "np"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@material-ui/core": "^4.11.2",
|
|
42
|
+
"@material-ui/icons": "^4.11.2",
|
|
43
|
+
"@material-ui/lab": "^4.0.0-alpha.58",
|
|
44
|
+
"react": "^16.8.0 || ^17.0.0",
|
|
45
|
+
"react-helmet": "^6.1.0"
|
|
46
|
+
},
|
|
47
|
+
"husky": {
|
|
48
|
+
"hooks": {
|
|
49
|
+
"pre-commit": "tsdx lint",
|
|
50
|
+
"pre-push": "tsdx lint"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"np": {
|
|
54
|
+
"yarn": false
|
|
55
|
+
},
|
|
56
|
+
"prettier": {
|
|
57
|
+
"printWidth": 80,
|
|
58
|
+
"semi": true,
|
|
59
|
+
"singleQuote": false,
|
|
60
|
+
"trailingComma": "es5"
|
|
61
|
+
},
|
|
62
|
+
"name": "@saleor/macaw-ui",
|
|
63
|
+
"description": "Saleor's UI component library",
|
|
64
|
+
"author": "Saleor Commerce",
|
|
65
|
+
"module": "dist/macaw-ui.esm.js",
|
|
66
|
+
"private": false,
|
|
67
|
+
"publishConfig": {
|
|
68
|
+
"access": "public"
|
|
69
|
+
},
|
|
70
|
+
"sideEffects": false,
|
|
71
|
+
"size-limit": [
|
|
72
|
+
{
|
|
73
|
+
"path": "dist/macaw-ui.cjs.production.min.js",
|
|
74
|
+
"limit": "45 KB"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"path": "dist/macaw-ui.esm.js",
|
|
78
|
+
"limit": "25 KB"
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"devDependencies": {
|
|
82
|
+
"@babel/core": "^7.14.0",
|
|
83
|
+
"@material-ui/core": "^4.11.2",
|
|
84
|
+
"@material-ui/icons": "^4.11.2",
|
|
85
|
+
"@material-ui/lab": "^4.0.0-alpha.58",
|
|
86
|
+
"@size-limit/preset-small-lib": "^4.10.2",
|
|
87
|
+
"@storybook/addon-essentials": "^6.2.9",
|
|
88
|
+
"@storybook/addon-info": "^5.3.21",
|
|
89
|
+
"@storybook/addon-links": "^6.2.9",
|
|
90
|
+
"@storybook/addons": "^6.2.9",
|
|
91
|
+
"@storybook/react": "^6.2.9",
|
|
92
|
+
"@types/lodash": "^4.14.170",
|
|
93
|
+
"@types/react": "^17.0.5",
|
|
94
|
+
"@types/react-dom": "^17.0.4",
|
|
95
|
+
"@types/react-helmet": "^6.1.1",
|
|
96
|
+
"@types/react-inlinesvg": "^1.0.0",
|
|
97
|
+
"babel-loader": "^8.2.2",
|
|
98
|
+
"babel-plugin-import": "^1.13.3",
|
|
99
|
+
"eslint-plugin-simple-import-sort": "^5.0.3",
|
|
100
|
+
"husky": "^6.0.0",
|
|
101
|
+
"np": "^7.5.0",
|
|
102
|
+
"react": "^16.8.0 || ^17.0.0",
|
|
103
|
+
"react-dom": "^16.8.0 || ^17.0.0",
|
|
104
|
+
"react-is": "^17.0.2",
|
|
105
|
+
"rollup-plugin-svg": "^2.0.0",
|
|
106
|
+
"size-limit": "^4.10.2",
|
|
107
|
+
"tsdx": "^0.14.1",
|
|
108
|
+
"tslib": "^2.2.0",
|
|
109
|
+
"typescript": "^4.2.4"
|
|
110
|
+
},
|
|
111
|
+
"dependencies": {
|
|
112
|
+
"clsx": "^1.1.1",
|
|
113
|
+
"lodash": "^4.17.21",
|
|
114
|
+
"lodash-es": "^4.17.21",
|
|
115
|
+
"react-inlinesvg": "^2.3.0"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Meta, Story } from "@storybook/react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
import { ConfirmButton, ConfirmButtonLabels } from "../ConfirmButton";
|
|
5
|
+
import { ActionBar } from "./ActionBar";
|
|
6
|
+
import { useActionBar } from "./context";
|
|
7
|
+
|
|
8
|
+
const Wrapper: React.FC = ({ children }) => {
|
|
9
|
+
const { anchor } = useActionBar();
|
|
10
|
+
|
|
11
|
+
return <div ref={anchor}>{children}</div>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const labels: ConfirmButtonLabels = {
|
|
15
|
+
confirm: "Confirm",
|
|
16
|
+
error: "Error",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const WithContent: Story = () => (
|
|
20
|
+
<ActionBar disabled={false} state="default">
|
|
21
|
+
<ConfirmButton labels={labels} transitionState="default" />
|
|
22
|
+
</ActionBar>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export default {
|
|
26
|
+
title: "ActionBar",
|
|
27
|
+
decorators: [
|
|
28
|
+
(Story) => (
|
|
29
|
+
<Wrapper>
|
|
30
|
+
<Story />
|
|
31
|
+
</Wrapper>
|
|
32
|
+
),
|
|
33
|
+
],
|
|
34
|
+
} as Meta;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import Card from "@material-ui/core/Card";
|
|
2
|
+
import CardContent from "@material-ui/core/CardContent";
|
|
3
|
+
import Container from "@material-ui/core/Container";
|
|
4
|
+
import Portal from "@material-ui/core/Portal";
|
|
5
|
+
import React from "react";
|
|
6
|
+
|
|
7
|
+
import { ConfirmButtonTransitionState } from "../ConfirmButton";
|
|
8
|
+
import useWindowScroll from "../tools/useWindowScroll";
|
|
9
|
+
import { useActionBar } from "./context";
|
|
10
|
+
import useStyles from "./styles";
|
|
11
|
+
|
|
12
|
+
export interface ActionBarProps {
|
|
13
|
+
disabled: boolean;
|
|
14
|
+
state: ConfirmButtonTransitionState;
|
|
15
|
+
children: React.ReactNode[] | React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const ActionBar: React.FC<ActionBarProps> = ({
|
|
19
|
+
disabled,
|
|
20
|
+
children,
|
|
21
|
+
state,
|
|
22
|
+
...rest
|
|
23
|
+
}) => {
|
|
24
|
+
const classes = useStyles();
|
|
25
|
+
|
|
26
|
+
const { anchor, docked, setDocked } = useActionBar();
|
|
27
|
+
const scrollPosition = useWindowScroll();
|
|
28
|
+
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
if (!disabled && state !== "loading") {
|
|
31
|
+
setDocked(false);
|
|
32
|
+
}
|
|
33
|
+
}, [disabled, state, setDocked]);
|
|
34
|
+
React.useEffect(() => () => setDocked(true), [setDocked]);
|
|
35
|
+
|
|
36
|
+
const scrolledToBottom =
|
|
37
|
+
scrollPosition.y + window.innerHeight >= document.body.scrollHeight;
|
|
38
|
+
|
|
39
|
+
if (!anchor.current) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Portal container={anchor.current}>
|
|
45
|
+
<div className={classes.root} {...rest}>
|
|
46
|
+
<Container maxWidth="lg">
|
|
47
|
+
<Card
|
|
48
|
+
className={classes.paper}
|
|
49
|
+
elevation={!(docked || scrolledToBottom) ? 16 : 0}
|
|
50
|
+
>
|
|
51
|
+
<CardContent className={classes.content}>{children}</CardContent>
|
|
52
|
+
</Card>
|
|
53
|
+
</Container>
|
|
54
|
+
</div>
|
|
55
|
+
</Portal>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
ActionBar.displayName = "ActionBar";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export interface ActionBarContextType {
|
|
4
|
+
anchor: React.RefObject<HTMLDivElement>;
|
|
5
|
+
docked: boolean;
|
|
6
|
+
setDocked: (docked: boolean) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const ActionBarContext = React.createContext<
|
|
10
|
+
ActionBarContextType | undefined
|
|
11
|
+
>(undefined);
|
|
12
|
+
ActionBarContext.displayName = "ActionBarContext";
|
|
13
|
+
|
|
14
|
+
export const useActionBar = () => {
|
|
15
|
+
const ctx = React.useContext(ActionBarContext);
|
|
16
|
+
if (ctx === undefined) {
|
|
17
|
+
throw new Error("useActionBar must be used within a ActionBarContext");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return ctx;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const ActionBarProvider: React.FC = ({ children }) => {
|
|
24
|
+
const [docked, setDocked] = React.useState(true);
|
|
25
|
+
const anchor = React.useRef<HTMLDivElement | null>(null);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<ActionBarContext.Provider value={{ anchor, docked, setDocked }}>
|
|
29
|
+
{children}
|
|
30
|
+
</ActionBarContext.Provider>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { makeStyles } from "../theme";
|
|
2
|
+
|
|
3
|
+
const useStyles = makeStyles(
|
|
4
|
+
(theme) => ({
|
|
5
|
+
content: {
|
|
6
|
+
"&:last-child": {
|
|
7
|
+
paddingBottom: theme.spacing(2),
|
|
8
|
+
},
|
|
9
|
+
display: "flex",
|
|
10
|
+
paddingBottom: theme.spacing(2),
|
|
11
|
+
paddingTop: theme.spacing(2),
|
|
12
|
+
[theme.breakpoints.down("sm")]: {
|
|
13
|
+
marginTop: theme.spacing(1),
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
paper: {
|
|
17
|
+
borderBottomLeftRadius: 0,
|
|
18
|
+
borderBottomRightRadius: 0,
|
|
19
|
+
},
|
|
20
|
+
root: {
|
|
21
|
+
height: 70,
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
{ name: "Savebar" }
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
export default useStyles;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Meta, Story } from "@storybook/react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
import { Alert, AlertProps } from "./Alert";
|
|
5
|
+
|
|
6
|
+
const props: AlertProps = {
|
|
7
|
+
close: false,
|
|
8
|
+
title: "Title",
|
|
9
|
+
variant: "info",
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const Info: Story = () => <Alert {...props} />;
|
|
13
|
+
export const Warn: Story = () => <Alert {...props} variant="warning" />;
|
|
14
|
+
export const Success: Story = () => <Alert {...props} variant="success" />;
|
|
15
|
+
export const Error: Story = () => <Alert {...props} variant="error" />;
|
|
16
|
+
export const WithClose: Story = () => <Alert {...props} close />;
|
|
17
|
+
export const WithContent: Story = () => (
|
|
18
|
+
<Alert {...props}>
|
|
19
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
20
|
+
</Alert>
|
|
21
|
+
);
|
|
22
|
+
export const WithContentAndClose: Story = () => (
|
|
23
|
+
<Alert {...props} close>
|
|
24
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
25
|
+
</Alert>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export default {
|
|
29
|
+
title: "Alert",
|
|
30
|
+
} as Meta;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import Card from "@material-ui/core/Card";
|
|
2
|
+
import CardContent from "@material-ui/core/CardContent";
|
|
3
|
+
import IconButton from "@material-ui/core/IconButton";
|
|
4
|
+
import Typography from "@material-ui/core/Typography";
|
|
5
|
+
import CloseIcon from "@material-ui/icons/Close";
|
|
6
|
+
import clsx from "clsx";
|
|
7
|
+
import React from "react";
|
|
8
|
+
|
|
9
|
+
import { CompleteIcon, InfoIcon, NotAllowedIcon, WarningIcon } from "../icons";
|
|
10
|
+
import useStyles from "./styles";
|
|
11
|
+
|
|
12
|
+
export type AlertVariant = "error" | "warning" | "success" | "info";
|
|
13
|
+
export interface AlertProps {
|
|
14
|
+
className?: string;
|
|
15
|
+
close?: boolean;
|
|
16
|
+
variant: AlertVariant;
|
|
17
|
+
title: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getIcon(variant: AlertVariant): React.ReactElement {
|
|
21
|
+
switch (variant) {
|
|
22
|
+
case "error":
|
|
23
|
+
return <NotAllowedIcon />;
|
|
24
|
+
case "success":
|
|
25
|
+
return <CompleteIcon />;
|
|
26
|
+
case "warning":
|
|
27
|
+
return <WarningIcon />;
|
|
28
|
+
}
|
|
29
|
+
return <InfoIcon />;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const Alert: React.FC<AlertProps> = ({
|
|
33
|
+
className,
|
|
34
|
+
close = true,
|
|
35
|
+
variant = "info",
|
|
36
|
+
title,
|
|
37
|
+
children,
|
|
38
|
+
}) => {
|
|
39
|
+
const classes = useStyles();
|
|
40
|
+
const [visible, setVisible] = React.useState(true);
|
|
41
|
+
|
|
42
|
+
if (!visible) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Card
|
|
48
|
+
elevation={0}
|
|
49
|
+
className={clsx(className, classes.root, {
|
|
50
|
+
[classes.error]: variant === "error",
|
|
51
|
+
[classes.warning]: variant === "warning",
|
|
52
|
+
[classes.success]: variant === "success",
|
|
53
|
+
})}
|
|
54
|
+
data-test="alert"
|
|
55
|
+
>
|
|
56
|
+
<CardContent>
|
|
57
|
+
<div className={classes.container}>
|
|
58
|
+
<div>{getIcon(variant)}</div>
|
|
59
|
+
<div className={classes.content}>
|
|
60
|
+
<div className={classes.titleBar}>
|
|
61
|
+
<Typography variant="h5">{title}</Typography>
|
|
62
|
+
{close && (
|
|
63
|
+
<IconButton
|
|
64
|
+
className={clsx(classes.close, {
|
|
65
|
+
[classes.closeNoContent]: !!children,
|
|
66
|
+
})}
|
|
67
|
+
onClick={() => setVisible(false)}
|
|
68
|
+
data-test="close"
|
|
69
|
+
>
|
|
70
|
+
<CloseIcon />
|
|
71
|
+
</IconButton>
|
|
72
|
+
)}
|
|
73
|
+
</div>
|
|
74
|
+
{typeof children === "string" ? (
|
|
75
|
+
<Typography variant="body1">{children}</Typography>
|
|
76
|
+
) : (
|
|
77
|
+
children
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</CardContent>
|
|
82
|
+
</Card>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
Alert.displayName = "Alert";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Alert";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { makeStyles } from "../theme";
|
|
2
|
+
|
|
3
|
+
const useStyles = makeStyles(
|
|
4
|
+
(theme) => ({
|
|
5
|
+
close: {
|
|
6
|
+
color: theme.palette.common.black,
|
|
7
|
+
position: "absolute",
|
|
8
|
+
right: theme.spacing(-2),
|
|
9
|
+
top: theme.spacing(-1),
|
|
10
|
+
},
|
|
11
|
+
closeNoContent: {
|
|
12
|
+
"&$close": {
|
|
13
|
+
right: theme.spacing(-3),
|
|
14
|
+
top: theme.spacing(-3),
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
container: {
|
|
18
|
+
columnGap: theme.spacing(2),
|
|
19
|
+
display: "grid",
|
|
20
|
+
gridTemplateColumns: "40px 1fr",
|
|
21
|
+
},
|
|
22
|
+
content: {
|
|
23
|
+
padding: theme.spacing(0, 1),
|
|
24
|
+
},
|
|
25
|
+
root: {},
|
|
26
|
+
titleBar: {
|
|
27
|
+
marginTop: 6,
|
|
28
|
+
marginBottom: theme.spacing(1),
|
|
29
|
+
position: "relative",
|
|
30
|
+
},
|
|
31
|
+
error: {
|
|
32
|
+
background: theme.palette.alert.paper.error,
|
|
33
|
+
},
|
|
34
|
+
warning: {
|
|
35
|
+
background: theme.palette.alert.paper.warning,
|
|
36
|
+
},
|
|
37
|
+
success: {
|
|
38
|
+
background: theme.palette.alert.paper.success,
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
{
|
|
42
|
+
name: "Alert",
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
export default useStyles;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Meta, Story } from "@storybook/react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
import { Decorator } from "../utils/Decorator";
|
|
5
|
+
import { Backlink } from "./Backlink";
|
|
6
|
+
import { useBacklink } from "./context";
|
|
7
|
+
|
|
8
|
+
// Normally some other component would rerender and force Backlink to recheck
|
|
9
|
+
// anchor too, but since it's static view we need to hack it a bit
|
|
10
|
+
const Wrapper: React.FC = ({ children }) => {
|
|
11
|
+
const anchor = useBacklink();
|
|
12
|
+
const [initialized, setInitialized] = React.useState(false);
|
|
13
|
+
const timer = React.useRef<number>();
|
|
14
|
+
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
timer.current = setInterval(() => {
|
|
17
|
+
if (!initialized && anchor.current) {
|
|
18
|
+
setInitialized(true);
|
|
19
|
+
clearInterval(timer.current);
|
|
20
|
+
}
|
|
21
|
+
}, 50) as any;
|
|
22
|
+
|
|
23
|
+
return () => clearInterval(timer.current);
|
|
24
|
+
}, []);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div>
|
|
28
|
+
<div ref={anchor} />
|
|
29
|
+
{initialized && children}
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const Default: Story = () => (
|
|
35
|
+
<Backlink onClick={() => undefined}>Go back</Backlink>
|
|
36
|
+
);
|
|
37
|
+
export const Loading: Story = () => (
|
|
38
|
+
<Backlink onClick={() => undefined}>{undefined}</Backlink>
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
export default {
|
|
42
|
+
title: "Backlink",
|
|
43
|
+
decorators: [
|
|
44
|
+
(Story) => (
|
|
45
|
+
<Wrapper>
|
|
46
|
+
<Story />
|
|
47
|
+
</Wrapper>
|
|
48
|
+
),
|
|
49
|
+
Decorator,
|
|
50
|
+
],
|
|
51
|
+
} as Meta;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import Portal from "@material-ui/core/Portal";
|
|
2
|
+
import Typography from "@material-ui/core/Typography";
|
|
3
|
+
import ArrowBackIcon from "@material-ui/icons/ArrowBack";
|
|
4
|
+
import Skeleton from "@material-ui/lab/Skeleton";
|
|
5
|
+
import React from "react";
|
|
6
|
+
|
|
7
|
+
import { useBacklink } from "./context";
|
|
8
|
+
import useStyles from "./styles";
|
|
9
|
+
|
|
10
|
+
export interface AppHeaderProps {
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
onClick: () => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const Backlink: React.FC<AppHeaderProps> = ({ children, onClick }) => {
|
|
16
|
+
const classes = useStyles();
|
|
17
|
+
const anchor = useBacklink();
|
|
18
|
+
|
|
19
|
+
if (!anchor.current) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Portal container={anchor.current}>
|
|
25
|
+
<div
|
|
26
|
+
className={classes.root}
|
|
27
|
+
onClick={onClick}
|
|
28
|
+
data-test-id="app-header-back-button"
|
|
29
|
+
>
|
|
30
|
+
<ArrowBackIcon className={classes.backArrow} />
|
|
31
|
+
{children ? (
|
|
32
|
+
<Typography className={classes.title}>{children}</Typography>
|
|
33
|
+
) : (
|
|
34
|
+
<Skeleton className={classes.skeleton} />
|
|
35
|
+
)}
|
|
36
|
+
</div>
|
|
37
|
+
</Portal>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
Backlink.displayName = "Backlink";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export type BacklinkContextType = React.RefObject<HTMLDivElement>;
|
|
4
|
+
|
|
5
|
+
export const BacklinkContext = React.createContext<
|
|
6
|
+
BacklinkContextType | undefined
|
|
7
|
+
>(undefined);
|
|
8
|
+
BacklinkContext.displayName = "BacklinkContext";
|
|
9
|
+
|
|
10
|
+
export const useBacklink = () => {
|
|
11
|
+
const ctx = React.useContext(BacklinkContext);
|
|
12
|
+
if (ctx === undefined) {
|
|
13
|
+
throw new Error("useBacklink must be used within a BacklinkContext");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return ctx;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const BacklinkProvider: React.FC = ({ children }) => {
|
|
20
|
+
const anchor = React.useRef<HTMLDivElement | null>(null);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<BacklinkContext.Provider value={anchor}>
|
|
24
|
+
{children}
|
|
25
|
+
</BacklinkContext.Provider>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { makeStyles } from "../theme";
|
|
2
|
+
|
|
3
|
+
const useStyles = makeStyles(
|
|
4
|
+
(theme) => ({
|
|
5
|
+
backArrow: {
|
|
6
|
+
fontSize: 30,
|
|
7
|
+
},
|
|
8
|
+
menuButton: {
|
|
9
|
+
flex: "0 0 auto",
|
|
10
|
+
marginLeft: theme.spacing(-2),
|
|
11
|
+
marginRight: theme.spacing(),
|
|
12
|
+
marginTop: theme.spacing(-2),
|
|
13
|
+
},
|
|
14
|
+
root: {
|
|
15
|
+
"&:hover": {
|
|
16
|
+
color: theme.typography.body1.color,
|
|
17
|
+
},
|
|
18
|
+
alignItems: "center",
|
|
19
|
+
color: theme.palette.grey[500],
|
|
20
|
+
cursor: "pointer",
|
|
21
|
+
display: "flex",
|
|
22
|
+
marginTop: theme.spacing(0.5),
|
|
23
|
+
transition: theme.transitions.duration.standard + "ms",
|
|
24
|
+
[theme.breakpoints.down("sm")]: {
|
|
25
|
+
margin: theme.spacing(4, 0, 0, 0),
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
skeleton: {
|
|
29
|
+
width: "10rem",
|
|
30
|
+
},
|
|
31
|
+
title: {
|
|
32
|
+
color: "inherit",
|
|
33
|
+
flex: 1,
|
|
34
|
+
marginLeft: theme.spacing(),
|
|
35
|
+
textTransform: "uppercase",
|
|
36
|
+
},
|
|
37
|
+
}),
|
|
38
|
+
{ name: "AppHeader" }
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
export default useStyles;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Meta, Story } from "@storybook/react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
ConfirmButton,
|
|
6
|
+
ConfirmButtonLabels,
|
|
7
|
+
ConfirmButtonTransitionState,
|
|
8
|
+
} from "./ConfirmButton";
|
|
9
|
+
|
|
10
|
+
const labels: ConfirmButtonLabels = {
|
|
11
|
+
confirm: "Confirm",
|
|
12
|
+
error: "Error",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const Interactive: Story = () => {
|
|
16
|
+
const [
|
|
17
|
+
transitionState,
|
|
18
|
+
setTransitionState,
|
|
19
|
+
] = React.useState<ConfirmButtonTransitionState>("default");
|
|
20
|
+
const timer = React.useRef<number>();
|
|
21
|
+
React.useEffect(
|
|
22
|
+
() => () => {
|
|
23
|
+
if (timer.current) {
|
|
24
|
+
clearTimeout(timer.current);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
[]
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const handleClick = () => {
|
|
31
|
+
if (!timer.current) {
|
|
32
|
+
setTransitionState("loading");
|
|
33
|
+
timer.current = (setTimeout(
|
|
34
|
+
() => setTransitionState("success"),
|
|
35
|
+
2000
|
|
36
|
+
) as unknown) as number;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<ConfirmButton
|
|
42
|
+
labels={labels}
|
|
43
|
+
transitionState={transitionState}
|
|
44
|
+
onClick={handleClick}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const Default: Story = () => (
|
|
50
|
+
<ConfirmButton labels={labels} transitionState="default" />
|
|
51
|
+
);
|
|
52
|
+
export const Loading: Story = () => (
|
|
53
|
+
<ConfirmButton
|
|
54
|
+
labels={labels}
|
|
55
|
+
transitionState="loading"
|
|
56
|
+
noTransition={true}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
export const Error: Story = () => (
|
|
60
|
+
<ConfirmButton labels={labels} transitionState="error" noTransition={true} />
|
|
61
|
+
);
|
|
62
|
+
export const Success: Story = () => (
|
|
63
|
+
<ConfirmButton
|
|
64
|
+
labels={labels}
|
|
65
|
+
transitionState="success"
|
|
66
|
+
noTransition={true}
|
|
67
|
+
/>
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
export default {
|
|
71
|
+
title: "Confirm Button",
|
|
72
|
+
} as Meta;
|