@unbxd-ui/unbxd-react-components 0.2.105 → 0.2.107-beta.2
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/.babelrc +4 -0
- package/.eslintrc.js +38 -0
- package/CONTRIBUTE.md +105 -0
- package/components/Accordian/Accordian.js +45 -13
- package/components/Accordian/Accordian.stories.js +25 -6
- package/components/Accordian/index.js +3 -0
- package/components/Button/Button.js +26 -9
- package/components/Button/Button.stories.js +14 -1
- package/components/Button/DropdownButton.js +31 -9
- package/components/Button/DropdownButton.stories.js +23 -6
- package/components/Button/index.js +8 -1
- package/components/DataLoader/DataLoader.js +40 -10
- package/components/DataLoader/DataLoader.stories.js +30 -5
- package/components/DataLoader/index.js +3 -0
- package/components/Form/Checkbox.js +42 -14
- package/components/Form/DragDropFileUploader.js +42 -12
- package/components/Form/Dropdown.js +181 -104
- package/components/Form/FileUploader.js +32 -10
- package/components/Form/Form.js +45 -15
- package/components/Form/FormElementWrapper.js +7 -2
- package/components/Form/Input.js +72 -27
- package/components/Form/RadioList.js +48 -17
- package/components/Form/RangeSlider.js +73 -37
- package/components/Form/ServerPaginatedDDList.js +130 -86
- package/components/Form/Textarea.js +43 -18
- package/components/Form/Toggle.js +48 -16
- package/components/Form/index.js +30 -18
- package/components/Form/stories/Checkbox.stories.js +12 -1
- package/components/Form/stories/DragDropFileUploader.stories.js +8 -0
- package/components/Form/stories/Dropdown.stories.js +24 -6
- package/components/Form/stories/FileUploader.stories.js +8 -0
- package/components/Form/stories/FormDefault.stories.js +21 -1
- package/components/Form/stories/RadioList.stories.js +12 -1
- package/components/Form/stories/RangeSlider.stories.js +15 -1
- package/components/Form/stories/TextInput.stories.js +19 -3
- package/components/Form/stories/Textarea.stories.js +12 -1
- package/components/Form/stories/Toggle.stories.js +7 -0
- package/components/Form/stories/form.stories.js +40 -3
- package/components/InlineModal/InlineModal.js +51 -14
- package/components/InlineModal/InlineModal.stories.js +14 -2
- package/components/InlineModal/index.js +6 -1
- package/components/List/List.js +24 -9
- package/components/List/index.js +3 -0
- package/components/List/list.stories.js +10 -0
- package/components/Modal/Modal.js +49 -17
- package/components/Modal/Modal.stories.js +15 -1
- package/components/Modal/index.js +3 -0
- package/components/NotificationComponent/NotificationComponent.js +34 -11
- package/components/NotificationComponent/NotificationComponent.stories.js +6 -0
- package/components/NotificationComponent/index.js +3 -0
- package/components/ProgressBar/ProgressBar.js +11 -2
- package/components/ProgressBar/ProgressBar.stories.js +6 -0
- package/components/ProgressBar/index.js +3 -0
- package/components/Table/BaseTable.js +134 -69
- package/components/Table/PaginationComponent.js +23 -11
- package/components/Table/Table.js +149 -68
- package/components/Table/Table.stories.js +67 -22
- package/components/Table/index.js +4 -0
- package/components/TabsComponent/TabsComponent.js +57 -20
- package/components/TabsComponent/TabsComponent.stories.js +16 -0
- package/components/TabsComponent/index.js +3 -0
- package/components/Tooltip/Tooltip.js +47 -25
- package/components/Tooltip/Tooltip.stories.js +6 -0
- package/components/Tooltip/index.js +3 -0
- package/components/core.css +1 -3
- package/components/index.js +17 -1
- package/components/theme.css +0 -2
- package/lib/Readme.md +82 -0
- package/lib/components/Accordian/Accordian.js +117 -0
- package/lib/components/Accordian/Accordian.stories.js +137 -0
- package/lib/components/Accordian/index.js +10 -0
- package/lib/components/Button/Button.js +84 -0
- package/lib/components/Button/Button.stories.js +89 -0
- package/lib/components/Button/DropdownButton.js +77 -0
- package/lib/components/Button/DropdownButton.stories.js +51 -0
- package/lib/components/Button/index.js +32 -0
- package/lib/components/DataLoader/DataLoader.js +88 -0
- package/lib/components/DataLoader/DataLoader.stories.js +77 -0
- package/lib/components/DataLoader/index.js +10 -0
- package/lib/components/Form/Checkbox.js +93 -0
- package/lib/components/Form/DragDropFileUploader.js +85 -0
- package/lib/components/Form/Dropdown.js +478 -0
- package/lib/components/Form/FileUploader.js +81 -0
- package/lib/components/Form/Form.js +106 -0
- package/lib/components/Form/FormElementWrapper.js +27 -0
- package/lib/components/Form/Input.js +140 -0
- package/lib/components/Form/RadioList.js +111 -0
- package/lib/components/Form/RangeSlider.js +142 -0
- package/lib/components/Form/ServerPaginatedDDList.js +267 -0
- package/lib/components/Form/Textarea.js +95 -0
- package/lib/components/Form/Toggle.js +117 -0
- package/lib/components/Form/index.js +73 -0
- package/lib/components/Form/stories/Checkbox.stories.js +54 -0
- package/lib/components/Form/stories/DragDropFileUploader.stories.js +27 -0
- package/lib/components/Form/stories/Dropdown.stories.js +114 -0
- package/lib/components/Form/stories/FileUploader.stories.js +31 -0
- package/lib/components/Form/stories/FormDefault.stories.js +117 -0
- package/lib/components/Form/stories/RadioList.stories.js +55 -0
- package/lib/components/Form/stories/RangeSlider.stories.js +82 -0
- package/lib/components/Form/stories/TextInput.stories.js +79 -0
- package/lib/components/Form/stories/Textarea.stories.js +48 -0
- package/lib/components/Form/stories/Toggle.stories.js +25 -0
- package/lib/components/Form/stories/form.stories.js +240 -0
- package/lib/components/InlineModal/InlineModal.js +146 -0
- package/lib/components/InlineModal/InlineModal.stories.js +61 -0
- package/lib/components/InlineModal/index.js +24 -0
- package/lib/components/List/List.js +76 -0
- package/lib/components/List/index.js +10 -0
- package/lib/components/List/list.stories.js +38 -0
- package/lib/components/Modal/Modal.js +117 -0
- package/lib/components/Modal/Modal.stories.js +55 -0
- package/lib/components/Modal/index.js +10 -0
- package/lib/components/NotificationComponent/NotificationComponent.js +76 -0
- package/lib/components/NotificationComponent/NotificationComponent.stories.js +29 -0
- package/lib/components/NotificationComponent/index.js +10 -0
- package/lib/components/ProgressBar/ProgressBar.js +49 -0
- package/lib/components/ProgressBar/ProgressBar.stories.js +21 -0
- package/lib/components/ProgressBar/index.js +10 -0
- package/lib/components/Table/BaseTable.js +352 -0
- package/lib/components/Table/PaginationComponent.js +87 -0
- package/lib/components/Table/Table.js +333 -0
- package/lib/components/Table/Table.stories.js +204 -0
- package/lib/components/Table/index.js +17 -0
- package/lib/components/TabsComponent/TabsComponent.js +134 -0
- package/lib/components/TabsComponent/TabsComponent.stories.js +65 -0
- package/lib/components/TabsComponent/index.js +10 -0
- package/lib/components/Tooltip/Tooltip.js +102 -0
- package/lib/components/Tooltip/Tooltip.stories.js +25 -0
- package/lib/components/Tooltip/index.js +10 -0
- package/lib/components/core.css +3 -0
- package/lib/components/core.scss +29 -0
- package/lib/components/index.js +159 -0
- package/lib/components/theme.css +3 -0
- package/lib/components/theme.scss +11 -0
- package/lib/package-lock.json +20607 -0
- package/lib/package.json +94 -0
- package/package.json +1 -1
- package/src/Intro.stories.mdx +119 -0
- package/src/components/Accordian/Accordian.js +89 -0
- package/src/components/Accordian/Accordian.stories.js +92 -0
- package/src/components/Accordian/accordianCore.css +1 -0
- package/src/components/Accordian/accordianCore.scss +8 -0
- package/src/components/Accordian/accordianTheme.css +1 -0
- package/src/components/Accordian/accordianTheme.scss +6 -0
- package/src/components/Accordian/index.js +3 -0
- package/src/components/Button/Button.js +67 -0
- package/src/components/Button/Button.stories.js +103 -0
- package/src/components/Button/DropdownButton.js +60 -0
- package/src/components/Button/DropdownButton.stories.js +38 -0
- package/src/components/Button/button.css +1 -0
- package/src/components/Button/buttonTheme.css +1 -0
- package/src/components/Button/buttonTheme.scss +45 -0
- package/src/components/Button/index.js +5 -0
- package/src/components/DataLoader/DataLoader.js +86 -0
- package/src/components/DataLoader/DataLoader.stories.js +72 -0
- package/src/components/DataLoader/index.js +3 -0
- package/src/components/Form/Checkbox.js +73 -0
- package/src/components/Form/DragDropFileUploader.js +67 -0
- package/src/components/Form/Dropdown.js +430 -0
- package/src/components/Form/FileUploader.js +64 -0
- package/src/components/Form/Form.js +83 -0
- package/src/components/Form/FormElementWrapper.js +22 -0
- package/src/components/Form/Input.js +121 -0
- package/src/components/Form/RadioList.js +86 -0
- package/src/components/Form/RangeSlider.js +100 -0
- package/src/components/Form/ServerPaginatedDDList.js +231 -0
- package/src/components/Form/Textarea.js +76 -0
- package/src/components/Form/Toggle.js +96 -0
- package/src/components/Form/form.css +1 -0
- package/src/components/Form/formCore.css +1 -0
- package/src/components/Form/formCore.scss +142 -0
- package/src/components/Form/formTheme.css +1 -0
- package/src/components/Form/formTheme.scss +27 -0
- package/src/components/Form/index.js +13 -0
- package/src/components/Form/stories/Checkbox.stories.js +41 -0
- package/src/components/Form/stories/DragDropFileUploader.stories.js +21 -0
- package/src/components/Form/stories/Dropdown.stories.js +124 -0
- package/src/components/Form/stories/FileUploader.stories.js +21 -0
- package/src/components/Form/stories/FormDefault.stories.js +87 -0
- package/src/components/Form/stories/RadioList.stories.js +48 -0
- package/src/components/Form/stories/RangeSlider.stories.js +84 -0
- package/src/components/Form/stories/TextInput.stories.js +77 -0
- package/src/components/Form/stories/Textarea.stories.js +43 -0
- package/src/components/Form/stories/Toggle.stories.js +14 -0
- package/src/components/Form/stories/form.stories.js +216 -0
- package/src/components/InlineModal/InlineModal.js +135 -0
- package/src/components/InlineModal/InlineModal.stories.js +54 -0
- package/src/components/InlineModal/index.js +4 -0
- package/src/components/InlineModal/inlineModal.css +1 -0
- package/src/components/InlineModal/inlineModalCore.css +1 -0
- package/src/components/InlineModal/inlineModalCore.scss +31 -0
- package/src/components/InlineModal/inlineModalTheme.css +1 -0
- package/src/components/InlineModal/inlineModalTheme.scss +16 -0
- package/src/components/List/List.js +72 -0
- package/src/components/List/index.js +3 -0
- package/src/components/List/list.css +1 -0
- package/src/components/List/list.stories.js +28 -0
- package/src/components/List/listCore.css +1 -0
- package/src/components/List/listCore.scss +6 -0
- package/src/components/List/listTheme.css +0 -0
- package/src/components/List/listTheme.scss +0 -0
- package/src/components/Modal/Modal.js +99 -0
- package/src/components/Modal/Modal.stories.js +54 -0
- package/src/components/Modal/index.js +3 -0
- package/src/components/Modal/modal.css +1 -0
- package/src/components/Modal/modalCore.css +1 -0
- package/src/components/Modal/modalCore.scss +34 -0
- package/src/components/Modal/modalTheme.css +0 -0
- package/src/components/Modal/modalTheme.scss +0 -0
- package/src/components/NotificationComponent/NotificationComponent.js +58 -0
- package/src/components/NotificationComponent/NotificationComponent.stories.js +28 -0
- package/src/components/NotificationComponent/index.js +3 -0
- package/src/components/NotificationComponent/notificationComponent.css +1 -0
- package/src/components/NotificationComponent/notificationTheme.css +1 -0
- package/src/components/NotificationComponent/notificationTheme.scss +30 -0
- package/src/components/ProgressBar/ProgressBar.js +45 -0
- package/src/components/ProgressBar/ProgressBar.stories.js +14 -0
- package/src/components/ProgressBar/index.js +3 -0
- package/src/components/ProgressBar/progressBar.css +1 -0
- package/src/components/ProgressBar/progressBarCore.css +1 -0
- package/src/components/ProgressBar/progressBarCore.scss +14 -0
- package/src/components/ProgressBar/progressBarTheme.css +0 -0
- package/src/components/ProgressBar/progressBarTheme.scss +0 -0
- package/src/components/Table/BaseTable.js +306 -0
- package/src/components/Table/PaginationComponent.js +73 -0
- package/src/components/Table/Table.js +295 -0
- package/src/components/Table/Table.stories.js +198 -0
- package/src/components/Table/index.js +8 -0
- package/src/components/Table/table.css +1 -0
- package/src/components/Table/tableCore.css +1 -0
- package/src/components/Table/tableCore.scss +94 -0
- package/src/components/Table/tableTheme.css +1 -0
- package/src/components/Table/tableTheme.scss +34 -0
- package/src/components/TabsComponent/TabsComponent.js +99 -0
- package/src/components/TabsComponent/TabsComponent.stories.js +69 -0
- package/src/components/TabsComponent/index.js +3 -0
- package/src/components/TabsComponent/tabs.css +1 -0
- package/src/components/TabsComponent/tabsCore.css +1 -0
- package/src/components/TabsComponent/tabsCore.scss +59 -0
- package/src/components/TabsComponent/tabsTheme.css +0 -0
- package/src/components/TabsComponent/tabsTheme.scss +0 -0
- package/src/components/Tooltip/Tooltip.js +87 -0
- package/src/components/Tooltip/Tooltip.stories.js +16 -0
- package/src/components/Tooltip/index.js +3 -0
- package/src/components/Tooltip/tooltipCore.css +1 -0
- package/src/components/Tooltip/tooltipCore.scss +22 -0
- package/src/components/Tooltip/tooltipTheme.css +1 -0
- package/src/components/Tooltip/tooltipTheme.scss +21 -0
- package/src/components/core.css +1 -0
- package/src/components/core.scss +29 -0
- package/src/components/index.js +38 -0
- package/src/components/theme.css +1 -0
- package/src/components/theme.scss +11 -0
- package/src/core/Validators.js +34 -0
- package/src/core/customHooks.js +20 -0
- package/src/core/dataLoader.js +143 -0
- package/src/core/dataLoader.stories.js +123 -0
- package/src/core/index.js +3 -0
- package/src/core/utils.js +95 -0
- package/src/index.js +68 -0
- package/vscode-templates/NewStoryTemplate.stories.js +8 -0
- /package/{Readme.md → README.md} +0 -0
- /package/{components → lib/components}/Accordian/accordianCore.css +0 -0
- /package/{components → lib/components}/Accordian/accordianTheme.css +0 -0
- /package/{components → lib/components}/Button/buttonTheme.css +0 -0
- /package/{components → lib/components}/Form/formCore.css +0 -0
- /package/{components → lib/components}/Form/formTheme.css +0 -0
- /package/{components → lib/components}/InlineModal/inlineModalCore.css +0 -0
- /package/{components → lib/components}/InlineModal/inlineModalTheme.css +0 -0
- /package/{components → lib/components}/List/listCore.css +0 -0
- /package/{components → lib/components}/List/listTheme.css +0 -0
- /package/{components → lib/components}/Modal/modalCore.css +0 -0
- /package/{components → lib/components}/Modal/modalTheme.css +0 -0
- /package/{components → lib/components}/NotificationComponent/notificationTheme.css +0 -0
- /package/{components → lib/components}/ProgressBar/progressBarCore.css +0 -0
- /package/{components → lib/components}/ProgressBar/progressBarTheme.css +0 -0
- /package/{components → lib/components}/Table/tableCore.css +0 -0
- /package/{components → lib/components}/Table/tableTheme.css +0 -0
- /package/{components → lib/components}/TabsComponent/tabsCore.css +0 -0
- /package/{components → lib/components}/TabsComponent/tabsTheme.css +0 -0
- /package/{components → lib/components}/Tooltip/tooltipCore.css +0 -0
- /package/{components → lib/components}/Tooltip/tooltipTheme.css +0 -0
- /package/{core → lib/core}/Validators.js +0 -0
- /package/{core → lib/core}/customHooks.js +0 -0
- /package/{core → lib/core}/dataLoader.js +0 -0
- /package/{core → lib/core}/dataLoader.stories.js +0 -0
- /package/{core → lib/core}/index.js +0 -0
- /package/{core → lib/core}/utils.js +0 -0
- /package/{index.js → lib/index.js} +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Form from "../Form";
|
|
3
|
+
import RangeSlider from "../RangeSlider";
|
|
4
|
+
import Button, { ButtonAppearance } from "../../Button";
|
|
5
|
+
|
|
6
|
+
export const _RangeSlider = () => {
|
|
7
|
+
const onSubmit = formData => {
|
|
8
|
+
const { data } = formData;
|
|
9
|
+
const { price } = data;
|
|
10
|
+
|
|
11
|
+
console.log("Selected price: ", price);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Form onSubmit={onSubmit}>
|
|
16
|
+
<RangeSlider
|
|
17
|
+
name="price"
|
|
18
|
+
label="Select price range"
|
|
19
|
+
min="10"
|
|
20
|
+
max="100"
|
|
21
|
+
appearance="block"
|
|
22
|
+
defaultValue="10"
|
|
23
|
+
/>
|
|
24
|
+
<Button appearance={ButtonAppearance.PRIMARY} className="full-width-btn">
|
|
25
|
+
Submit
|
|
26
|
+
</Button>
|
|
27
|
+
</Form>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
_RangeSlider.story = {
|
|
32
|
+
name: "Range Slider ",
|
|
33
|
+
|
|
34
|
+
parameters: {
|
|
35
|
+
info: {
|
|
36
|
+
propTables: [RangeSlider]
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const BubbleRangeSlider = () => {
|
|
42
|
+
const onSubmit = formData => {
|
|
43
|
+
const { data } = formData;
|
|
44
|
+
const { price } = data;
|
|
45
|
+
|
|
46
|
+
console.log("Selected price: ", price);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Form onSubmit={onSubmit}>
|
|
51
|
+
<RangeSlider
|
|
52
|
+
name="price"
|
|
53
|
+
label="Select price range"
|
|
54
|
+
min="10"
|
|
55
|
+
max="100"
|
|
56
|
+
appearance="block"
|
|
57
|
+
defaultValue="10"
|
|
58
|
+
showBubble={true}
|
|
59
|
+
/>
|
|
60
|
+
<Button appearance={ButtonAppearance.PRIMARY} className="full-width-btn">
|
|
61
|
+
Submit
|
|
62
|
+
</Button>
|
|
63
|
+
</Form>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
BubbleRangeSlider.story = {
|
|
68
|
+
name: "Range Slider with Bubble",
|
|
69
|
+
|
|
70
|
+
parameters: {
|
|
71
|
+
info: {
|
|
72
|
+
propTables: [RangeSlider]
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export default {
|
|
78
|
+
title: "Form|RangeSlider",
|
|
79
|
+
parameters: {
|
|
80
|
+
info: {
|
|
81
|
+
propTables: [RangeSlider],
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React, { Fragment, useRef } from "react";
|
|
2
|
+
import Form from "../Form";
|
|
3
|
+
import Input from "../Input";
|
|
4
|
+
import Button, { ButtonAppearance } from "../../Button";
|
|
5
|
+
|
|
6
|
+
export const TextInput = () => {
|
|
7
|
+
const onSubmit = formData => {
|
|
8
|
+
const { data, errors = {} } = formData;
|
|
9
|
+
|
|
10
|
+
if (Object.keys(errors).length) {
|
|
11
|
+
console.log("ERRORS FOUND : ");
|
|
12
|
+
console.log(errors);
|
|
13
|
+
} else {
|
|
14
|
+
console.log("Submitted data: ", data);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Form onSubmit={onSubmit}>
|
|
20
|
+
<Input
|
|
21
|
+
type="text"
|
|
22
|
+
name="email"
|
|
23
|
+
label="Name"
|
|
24
|
+
placeholder="Enter your email"
|
|
25
|
+
appearance="block"
|
|
26
|
+
validations={[
|
|
27
|
+
{
|
|
28
|
+
type: "EMAIL",
|
|
29
|
+
message: "Please enter a valid email address",
|
|
30
|
+
},
|
|
31
|
+
]}
|
|
32
|
+
/>
|
|
33
|
+
<Button appearance={ButtonAppearance.PRIMARY} className="full-width-btn">
|
|
34
|
+
Submit
|
|
35
|
+
</Button>
|
|
36
|
+
</Form>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
TextInput.story = {
|
|
41
|
+
parameters: {
|
|
42
|
+
info: {
|
|
43
|
+
propTables: [Input]
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const RefUsage = () => {
|
|
49
|
+
const inputRef = useRef();
|
|
50
|
+
|
|
51
|
+
const focusInput = () => {
|
|
52
|
+
inputRef.current.focus();
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<Fragment>
|
|
57
|
+
<Button appearance={ButtonAppearance.SECONDARY} className="full-width-btn" onClick={focusInput}>Focus input</Button>
|
|
58
|
+
<Input
|
|
59
|
+
ref={inputRef}
|
|
60
|
+
type="text"
|
|
61
|
+
name="email"
|
|
62
|
+
label="Name"
|
|
63
|
+
placeholder="Enter your email"
|
|
64
|
+
appearance="block"
|
|
65
|
+
/>
|
|
66
|
+
</Fragment>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export default {
|
|
71
|
+
title: "Form|Text Input",
|
|
72
|
+
parameters: {
|
|
73
|
+
info: {
|
|
74
|
+
propTables: [TextInput]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Form from "../Form";
|
|
3
|
+
import Textarea from "../Textarea";
|
|
4
|
+
import Button, { ButtonAppearance } from "../../Button";
|
|
5
|
+
|
|
6
|
+
export const _Textarea = () => {
|
|
7
|
+
const onSubmit = formData => {
|
|
8
|
+
const { data } = formData;
|
|
9
|
+
|
|
10
|
+
console.log("Submitted data: ", data);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<Form onSubmit={onSubmit}>
|
|
15
|
+
<Textarea
|
|
16
|
+
name="description"
|
|
17
|
+
label="Description"
|
|
18
|
+
placeholder="Enter your description"
|
|
19
|
+
appearance="block"
|
|
20
|
+
/>
|
|
21
|
+
<Button appearance={ButtonAppearance.PRIMARY} className="full-width-btn">
|
|
22
|
+
Submit
|
|
23
|
+
</Button>
|
|
24
|
+
</Form>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
_Textarea.story = {
|
|
29
|
+
parameters: {
|
|
30
|
+
info: {
|
|
31
|
+
propTables: [Textarea],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default {
|
|
37
|
+
title: "Form|Textarea",
|
|
38
|
+
parameters: {
|
|
39
|
+
info: {
|
|
40
|
+
propTables: [Textarea]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Toggle from "../Toggle";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: "Toggle",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const SimpleUsage = () => {
|
|
9
|
+
const onChange = isActive => {
|
|
10
|
+
console.log("isActive: ", isActive);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
return <Toggle label="Is Active?" name="isActive" appearance="block" onChange={onChange} />;
|
|
14
|
+
};
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import React, { Fragment, useRef } from "react";
|
|
2
|
+
import Form from "../Form";
|
|
3
|
+
import Dropdown from "../Dropdown";
|
|
4
|
+
import Input from "../Input";
|
|
5
|
+
import Textarea from "../Textarea";
|
|
6
|
+
import RadioList from "../RadioList";
|
|
7
|
+
import Checkbox from "../Checkbox";
|
|
8
|
+
import FileUploader from "../FileUploader";
|
|
9
|
+
import DragDropFileUploader from "../DragDropFileUploader";
|
|
10
|
+
import Toggle from "../Toggle";
|
|
11
|
+
import RangeSlider from "../RangeSlider";
|
|
12
|
+
import Button, { ButtonAppearance } from "../../Button";
|
|
13
|
+
import { FRUITS_LIST } from "../../../../public/Constants";
|
|
14
|
+
|
|
15
|
+
export const FormExample = () => {
|
|
16
|
+
const onSubmit = formData => {
|
|
17
|
+
const { data, errors = {} } = formData;
|
|
18
|
+
|
|
19
|
+
if (Object.keys(errors).length) {
|
|
20
|
+
console.log("ERRORS FOUND : ");
|
|
21
|
+
console.log(errors);
|
|
22
|
+
} else {
|
|
23
|
+
console.log("Submitted data: ", data);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return (<Form onSubmit={onSubmit}>
|
|
28
|
+
<Input
|
|
29
|
+
type="text"
|
|
30
|
+
name="email"
|
|
31
|
+
label="Name"
|
|
32
|
+
placeholder="Enter your email"
|
|
33
|
+
appearance="block"
|
|
34
|
+
/>
|
|
35
|
+
<Textarea
|
|
36
|
+
name="description"
|
|
37
|
+
label="Description"
|
|
38
|
+
placeholder="Enter your description"
|
|
39
|
+
appearance="block"
|
|
40
|
+
/>
|
|
41
|
+
<RadioList
|
|
42
|
+
name="yesNoOption"
|
|
43
|
+
label="Are you sure?"
|
|
44
|
+
options={[
|
|
45
|
+
{ id: "YES", name: "Yes" },
|
|
46
|
+
{ id: "NO", name: "No" },
|
|
47
|
+
]}
|
|
48
|
+
appearance="block"
|
|
49
|
+
/>
|
|
50
|
+
<Checkbox name="orange" label="Orange" />
|
|
51
|
+
<Checkbox name="pineapple" label="Pineapple" value={true} onChange={()=>{}} />
|
|
52
|
+
<Checkbox name="grapes" label="Grapes" />
|
|
53
|
+
<br />
|
|
54
|
+
<Dropdown name="fruit" label="Select fruit"
|
|
55
|
+
options={FRUITS_LIST} appearance="block"
|
|
56
|
+
validations={[{ type: "REQUIRED", message: "Please select a fruit" }]} />
|
|
57
|
+
<Toggle label="Is Active?" name="isActive" appearance="block" />
|
|
58
|
+
<RangeSlider
|
|
59
|
+
name="price"
|
|
60
|
+
label="Select price range"
|
|
61
|
+
min="10"
|
|
62
|
+
max="100"
|
|
63
|
+
appearance="block"
|
|
64
|
+
defaultValue="10"
|
|
65
|
+
/>
|
|
66
|
+
<Button appearance={ButtonAppearance.PRIMARY} className="full-width-btn">Submit</Button>
|
|
67
|
+
</Form>);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
FormExample.story = {
|
|
71
|
+
name: "Form"
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const _Dropdown = () => {
|
|
75
|
+
const onSubmit = formData => {
|
|
76
|
+
const { data } = formData;
|
|
77
|
+
const { fruit } = data;
|
|
78
|
+
|
|
79
|
+
console.log("Selected Fruit: ", fruit);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<Form onSubmit={onSubmit}>
|
|
84
|
+
<Dropdown name="fruit" label="Select fruit" options={FRUITS_LIST} appearance="block" />
|
|
85
|
+
<Button appearance={ButtonAppearance.PRIMARY} className="full-width-btn">
|
|
86
|
+
Submit
|
|
87
|
+
</Button>
|
|
88
|
+
</Form>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
_Dropdown.story = {
|
|
93
|
+
name: "Dropdown ",
|
|
94
|
+
|
|
95
|
+
parameters: {
|
|
96
|
+
info: {
|
|
97
|
+
propTables: [Dropdown],
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export const _FileUploader = () => {
|
|
103
|
+
const onSubmit = formData => {
|
|
104
|
+
const { data } = formData;
|
|
105
|
+
const { file } = data;
|
|
106
|
+
|
|
107
|
+
console.log("Selected file: ", file[0].name);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<Form onSubmit={onSubmit}>
|
|
112
|
+
<FileUploader name="file" appearance="block">
|
|
113
|
+
<a href="javascript:void(0)">Upload File</a>
|
|
114
|
+
</FileUploader>
|
|
115
|
+
<Button appearance={ButtonAppearance.PRIMARY} className="full-width-btn">
|
|
116
|
+
Submit
|
|
117
|
+
</Button>
|
|
118
|
+
</Form>
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
_FileUploader.story = {
|
|
123
|
+
name: "File Uploader ",
|
|
124
|
+
|
|
125
|
+
parameters: {
|
|
126
|
+
info: {
|
|
127
|
+
propTables: [FileUploader],
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export const _DragDropFileUploader = () => {
|
|
133
|
+
const onSubmit = formData => {
|
|
134
|
+
const { data } = formData;
|
|
135
|
+
const { filesList } = data;
|
|
136
|
+
|
|
137
|
+
console.log("Selected file: ", filesList[0].name);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<Form onSubmit={onSubmit}>
|
|
142
|
+
<DragDropFileUploader name="filesList" appearance="block">
|
|
143
|
+
<div>Drag & drop files into this area</div>
|
|
144
|
+
</DragDropFileUploader>
|
|
145
|
+
<Button appearance={ButtonAppearance.PRIMARY} className="full-width-btn">
|
|
146
|
+
Submit
|
|
147
|
+
</Button>
|
|
148
|
+
</Form>
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
_DragDropFileUploader.story = {
|
|
153
|
+
name: "DragDrop File Uploader ",
|
|
154
|
+
|
|
155
|
+
parameters: {
|
|
156
|
+
info: {
|
|
157
|
+
propTables: [DragDropFileUploader],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export const _Toggle = () => {
|
|
163
|
+
const onSubmit = formData => {
|
|
164
|
+
const { data } = formData;
|
|
165
|
+
const { isActive } = data;
|
|
166
|
+
|
|
167
|
+
console.log("isActive: ", isActive);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<Form onSubmit={onSubmit}>
|
|
172
|
+
<Toggle label="Is Active?" name="isActive" appearance="block" />
|
|
173
|
+
<Button appearance={ButtonAppearance.PRIMARY} className="full-width-btn">
|
|
174
|
+
Submit
|
|
175
|
+
</Button>
|
|
176
|
+
</Form>
|
|
177
|
+
);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
_Toggle.story = {
|
|
181
|
+
name: "Toggle ",
|
|
182
|
+
|
|
183
|
+
parameters: {
|
|
184
|
+
info: {
|
|
185
|
+
propTables: [Toggle],
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
export const GetFormData = () => {
|
|
191
|
+
const formRef = useRef();
|
|
192
|
+
const submitFormData = () => {
|
|
193
|
+
const formData = formRef.current.getFormData();
|
|
194
|
+
const { data } = formData;
|
|
195
|
+
|
|
196
|
+
console.log("Got data", data);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
return (<Fragment>
|
|
200
|
+
<Form ref={formRef}>
|
|
201
|
+
<Input name="name" label="Enter name" />
|
|
202
|
+
<Input name="email" label="Enter Email ID" />
|
|
203
|
+
<Dropdown name="fruit" label="Select fruit" options={FRUITS_LIST} appearance="block" />
|
|
204
|
+
</Form>
|
|
205
|
+
<Button appearance={ButtonAppearance.PRIMARY} className="full-width-btn" onClick={submitFormData}>Click to submit</Button>
|
|
206
|
+
</Fragment>);
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
export default {
|
|
210
|
+
title: "Form|Miscellanious",
|
|
211
|
+
parameters: {
|
|
212
|
+
info: {
|
|
213
|
+
propTables: [Form],
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import React, { forwardRef, useState, useRef, useEffect, useImperativeHandle } from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
|
|
4
|
+
export const InlineModalActivator = (props) => {
|
|
5
|
+
return props.children;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const InlineModalBody = (props) => {
|
|
9
|
+
return props.children;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let InlineModal = (props, ref) => {
|
|
13
|
+
const { children, activatorAction, className, isModalOpen:propIsOpen, halign, onModalStateChange } = props;
|
|
14
|
+
let [ isModalOpen, setIsModalOpen ] = useState(propIsOpen);
|
|
15
|
+
let activatorProps = {};
|
|
16
|
+
let inlineModalClassName = `RCB-inline-modal ${className}`;
|
|
17
|
+
let showModalBody = isModalOpen;
|
|
18
|
+
const inlineModalRef = useRef();
|
|
19
|
+
const isFirstRun = useRef(true);
|
|
20
|
+
|
|
21
|
+
const changeModalState = (newState) => {
|
|
22
|
+
setIsModalOpen(newState);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const onActivatorClick = (e) => {
|
|
26
|
+
e.stopPropagation();
|
|
27
|
+
changeModalState(!isModalOpen);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const onBodyClick = (e) => {
|
|
31
|
+
const eventTarget = e.target;
|
|
32
|
+
const inlineModalNode = inlineModalRef.current;
|
|
33
|
+
let eventPathNodes = e.composedPath();
|
|
34
|
+
let isWithinModal = false;
|
|
35
|
+
|
|
36
|
+
if (inlineModalNode.contains(eventTarget)) {
|
|
37
|
+
isWithinModal = true;
|
|
38
|
+
} else {
|
|
39
|
+
for (let i = 0; i < eventPathNodes.length; i++) {
|
|
40
|
+
const node = eventPathNodes[i];
|
|
41
|
+
if (node!== window && inlineModalNode.contains(node)) {
|
|
42
|
+
isWithinModal = true;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!isWithinModal) {
|
|
49
|
+
/* outside click -> close modal */
|
|
50
|
+
changeModalState(false);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
/* add when mounted */
|
|
56
|
+
document.addEventListener("click", onBodyClick);
|
|
57
|
+
|
|
58
|
+
/* return function to be called when unmounted */
|
|
59
|
+
return () => {
|
|
60
|
+
document.removeEventListener("click", onBodyClick);
|
|
61
|
+
};
|
|
62
|
+
}, []);
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (isFirstRun.current) {
|
|
66
|
+
/* skip first run */
|
|
67
|
+
isFirstRun.current = false;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
typeof(onModalStateChange) === "function" && onModalStateChange(isModalOpen);
|
|
71
|
+
}, [isModalOpen]);
|
|
72
|
+
|
|
73
|
+
if (activatorAction === "click") {
|
|
74
|
+
activatorProps = {
|
|
75
|
+
onClick: onActivatorClick
|
|
76
|
+
};
|
|
77
|
+
} else if (activatorAction === "hover") {
|
|
78
|
+
inlineModalClassName += " hover-open";
|
|
79
|
+
showModalBody = true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* add methods that can be accessed via this component's ref */
|
|
83
|
+
useImperativeHandle(ref, () => ({
|
|
84
|
+
hideModal: () => {
|
|
85
|
+
changeModalState(false);
|
|
86
|
+
}
|
|
87
|
+
}));
|
|
88
|
+
|
|
89
|
+
return (<div className={inlineModalClassName} ref={inlineModalRef}>
|
|
90
|
+
<div {...activatorProps} className="RCB-inline-modal-btn">{children[0]}</div>
|
|
91
|
+
{showModalBody && <div className={`RCB-inline-modal-body RCB-align-${halign}`}>{children[1]}</div>}
|
|
92
|
+
</div>);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
InlineModal = forwardRef(InlineModal);
|
|
96
|
+
|
|
97
|
+
InlineModal.propTypes = {
|
|
98
|
+
/** Pass any additional classNames to InlineModal component */
|
|
99
|
+
className: PropTypes.string,
|
|
100
|
+
/** Horizontal alignment of the inline modal body */
|
|
101
|
+
halign: PropTypes.oneOf(["left", "right"]),
|
|
102
|
+
/** Event on which the modal should be opened */
|
|
103
|
+
activatorAction: PropTypes.oneOf(["click", "hover"]),
|
|
104
|
+
children: (props, propName, componentName) => {
|
|
105
|
+
const children = props[propName];
|
|
106
|
+
|
|
107
|
+
if (React.Children.count(children) !== 2) {
|
|
108
|
+
return new Error(
|
|
109
|
+
`${componentName} should have 2 children`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (children[0].type !== InlineModalActivator ||
|
|
114
|
+
children[1].type !== InlineModalBody) {
|
|
115
|
+
return new Error(
|
|
116
|
+
`${componentName} should have an InlineModalActivator & InlineModalBody components as children`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
/** Boolean prop to have the modal open or close */
|
|
121
|
+
isModalOpen: PropTypes.bool,
|
|
122
|
+
/** callback function that gets called when the modal state changes (either opens or closes) */
|
|
123
|
+
onModalStateChange: PropTypes.func
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
InlineModal.defaultProps = {
|
|
127
|
+
className: "",
|
|
128
|
+
halign: "left",
|
|
129
|
+
activatorAction: "click", // or "hover"
|
|
130
|
+
isModalOpen: false
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
InlineModal.displayName = "InlineModal";
|
|
134
|
+
|
|
135
|
+
export default InlineModal;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React, { Fragment, useState } from "react";
|
|
2
|
+
import { linkTo } from "@storybook/addon-links";
|
|
3
|
+
|
|
4
|
+
import { FRUITS_LIST } from "../../../public/Constants";
|
|
5
|
+
import InlineModal, { InlineModalActivator, InlineModalBody } from "./InlineModal";
|
|
6
|
+
import { List } from "../";
|
|
7
|
+
|
|
8
|
+
/* eslint-disable react/prop-types */
|
|
9
|
+
const CustomListItem = (props) => {
|
|
10
|
+
const { itemData } = props;
|
|
11
|
+
const { id, name } = itemData;
|
|
12
|
+
|
|
13
|
+
return (<li>
|
|
14
|
+
<input type="checkbox" id={id}></input>
|
|
15
|
+
<label htmlFor={id}>{name}</label>
|
|
16
|
+
</li>)
|
|
17
|
+
};
|
|
18
|
+
/* eslint-enable react/prop-types */
|
|
19
|
+
|
|
20
|
+
export const SimpleUsage = () => {
|
|
21
|
+
const onModalStateChange = (isModalOpen) => {
|
|
22
|
+
console.log("Modal state change 1");
|
|
23
|
+
console.log({isModalOpen});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return (<Fragment>
|
|
27
|
+
<InlineModal onModalStateChange={onModalStateChange}>
|
|
28
|
+
<InlineModalActivator>
|
|
29
|
+
<div>Select a fruit</div>
|
|
30
|
+
</InlineModalActivator>
|
|
31
|
+
<InlineModalBody>
|
|
32
|
+
<List items={FRUITS_LIST} showApp={linkTo("List")} ListItem={CustomListItem} />
|
|
33
|
+
</InlineModalBody>
|
|
34
|
+
</InlineModal>
|
|
35
|
+
</Fragment>);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
SimpleUsage.story = {
|
|
39
|
+
parameters: {
|
|
40
|
+
info: {
|
|
41
|
+
text: "Displaying a dropdown list of items",
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default {
|
|
47
|
+
title: "Modals|Inline modal",
|
|
48
|
+
parameters: {
|
|
49
|
+
info: {
|
|
50
|
+
propTables: [InlineModal, InlineModalActivator, InlineModalBody],
|
|
51
|
+
propTablesExclude: [List],
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.RCB-inline-modal{position:relative;display:inline-block}.RCB-inline-modal.hover-open .RCB-inline-modal-body{display:none}.RCB-inline-modal.hover-open:hover .RCB-inline-modal-body{display:block}.RCB-inline-modal-btn{display:inline-block;background:#FFF;border:1px solid #eee;padding:10px;border-radius:3px;cursor:pointer}.RCB-inline-modal-body{position:absolute;background:#FFF;border:1px solid #efeeee;box-shadow:0 9px 12px 0 rgba(0,0,0,0.15);z-index:1}.RCB-inline-modal-body.RCB-align-left{left:0}.RCB-inline-modal-body.RCB-align-right{right:0}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.RCB-inline-modal{position:relative;display:inline-block}.RCB-inline-modal.hover-open .RCB-inline-modal-body{display:none}.RCB-inline-modal.hover-open:hover .RCB-inline-modal-body{display:block}.RCB-inline-modal-body{position:absolute;z-index:1}.RCB-inline-modal-body.RCB-align-left{left:0}.RCB-inline-modal-body.RCB-align-right{right:0}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
.RCB {
|
|
2
|
+
&-inline-modal {
|
|
3
|
+
position: relative;
|
|
4
|
+
display: inline-block;
|
|
5
|
+
|
|
6
|
+
&.hover-open {
|
|
7
|
+
.RCB-inline-modal-body {
|
|
8
|
+
display: none;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&:hover {
|
|
12
|
+
.RCB-inline-modal-body {
|
|
13
|
+
display: block;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&-inline-modal-body {
|
|
20
|
+
position: absolute;
|
|
21
|
+
z-index: 1;
|
|
22
|
+
|
|
23
|
+
&.RCB-align-left {
|
|
24
|
+
left: 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&.RCB-align-right {
|
|
28
|
+
right: 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.RCB-inline-modal-btn{display:inline-block;background:#FFF;border:1px solid #eee;padding:10px;border-radius:3px;cursor:pointer}.RCB-inline-modal-body{background:#FFF;border:1px solid #efeeee;box-shadow:0 9px 12px 0 rgba(0,0,0,0.15)}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.RCB {
|
|
2
|
+
&-inline-modal-btn {
|
|
3
|
+
display: inline-block;
|
|
4
|
+
background: #FFF;
|
|
5
|
+
border: 1px solid #eee;
|
|
6
|
+
padding: 10px;
|
|
7
|
+
border-radius: 3px;
|
|
8
|
+
cursor: pointer;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&-inline-modal-body {
|
|
12
|
+
background: #FFF;
|
|
13
|
+
border: 1px solid #efeeee;
|
|
14
|
+
box-shadow: 0 9px 12px 0 rgba(0,0,0,0.15);
|
|
15
|
+
}
|
|
16
|
+
}
|