>;
7 |
8 | const useAnalytics = () => {
9 | const { pages, tracker, merchantId, ip } = useContext(AnalyticsContext);
10 |
11 | const track = useCallback(
12 | ({ event, type, tag, ...optional }: TrackParams) => {
13 | if (!tag) {
14 | return;
15 | }
16 |
17 | tracker.track({ event, type, tag, pages, merchantId, ip, ...optional });
18 | },
19 | [pages, tracker, merchantId, ip]
20 | );
21 |
22 | const trackCallback = useCallback(
23 | (trackParams: TrackParams) => () => {
24 | track(trackParams);
25 | },
26 | []
27 | );
28 |
29 | return useMemo(() => ({ track, trackCallback }), [track, trackCallback]);
30 | };
31 |
32 | export default useAnalytics;
33 |
--------------------------------------------------------------------------------
/src/assets/images/ip-icon-blue.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
31 |
--------------------------------------------------------------------------------
/src/components/Accordion/Arrow.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled, { css } from 'styled-components';
3 | import { ifProp, switchProp } from 'styled-tools';
4 | import { transparentize } from 'polished';
5 | import colors from '../../theme/colors';
6 |
7 | export const ArrowContainer = styled.div<{ section: string }>`
8 | width: 18px;
9 | margin: 0 1rem 1rem 1rem;
10 | text-align: center;
11 | ${switchProp('section', {
12 | navbar: css`
13 | align-self: flex-end;
14 |
15 | &:hover i {
16 | border-color: ${colors.white};
17 | }
18 | `,
19 | accordion: css`
20 | align-self: flex-start;
21 | `,
22 | })};
23 | `;
24 |
25 | export const AccordionArrow = styled.i<{ open: boolean; section: string }>`
26 | display: inline-block;
27 | transition: all 0.5s ease;
28 | cursor: pointer;
29 | ${switchProp('section', {
30 | navbar: css`
31 | padding: 0.225rem;
32 | border: solid ${transparentize(0.6, colors.white)};
33 | border-width: 1px 0 0 1px;
34 | transform: ${ifProp('open', 'rotate(-45deg)', 'rotate(135deg)')};
35 | `,
36 | accordion: css`
37 | border: solid ${colors.midnightBlue};
38 | border-width: 1px 0 0 1px;
39 | transform: ${ifProp('open', 'rotate(135deg)', 'rotate(-45deg)')};
40 | padding: 0.4rem;
41 | `,
42 | })};
43 | `;
44 |
45 | type Props = {
46 | open: boolean;
47 | section: string;
48 | onClick?: any;
49 | };
50 |
51 | const Arrow = ({ open, section, onClick }: Props) => (
52 |
53 |
54 |
55 | );
56 |
57 | export default Arrow;
58 |
--------------------------------------------------------------------------------
/src/components/Accordion/Usage.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/display-name */
2 | import React from 'react';
3 | import { MdInfo } from 'react-icons/md';
4 | import Accordion from '.';
5 |
6 | const Usage = () => {
7 | const panels = [
8 | {
9 | label: 'Accordion1',
10 | icon: ,
11 | renderContent: () => (
12 |
13 |
Long Content for the accordion1
14 | Long Content for the accordion1
15 | Long Content for the accordion1
16 | Long Content for the accordion1
17 | Long Content for the accordion1
18 | Long Content for the accordion1
19 |
20 | ),
21 | },
22 | {
23 | label: 'Disabled Accordion',
24 | icon: ,
25 | renderContent: () => (
26 |
27 |
Long Content for the accordion
28 | Long Content for the accordion
29 | Long Content for the accordion
30 | Long Content for the accordion
31 | Long Content for the accordion
32 | Long Content for the accordion
33 |
34 | ),
35 | disabled: true,
36 | },
37 | {
38 | label: 'Accordion3',
39 | icon: ,
40 | renderContent: () => (
41 |
42 |
Long Content for the accordion3
43 | Long Content for the accordion3
44 | Long Content for the accordion3
45 | Long Content for the accordion3
46 | Long Content for the accordion3
47 | Long Content for the accordion3
48 |
49 | ),
50 | },
51 | ];
52 |
53 | return (
54 | console.log(index)}
56 | panels={panels}
57 | contentHeight="46vh"
58 | isExtendable
59 | width="80%"
60 | extendWidth="20%"
61 | />
62 | );
63 | };
64 |
65 | export default Usage;
66 |
--------------------------------------------------------------------------------
/src/components/Accordion/accordion.stories.mdx:
--------------------------------------------------------------------------------
1 | import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
2 | import Accordion from './'
3 | import { panels } from './panels.tsx'
4 |
5 | } />
6 |
7 | # Accordion
8 |
9 |
10 | Accordion or expansion panel is a component that generates Accordion component with more accordion panels.
11 | It takes `panels` - array of objects and each object should/could contain:
12 | - `label` (title)
13 | - `renderContent` (action used to render the content)
14 | - `icon` (optional parameter - icon displayed next to the title)
15 | - `iconTooltip` (optional parameter - a tooltip to display on hovering the icon, see Tooltip's prop list) - default null
16 | - `disabled` (optional paremeter - a boolean to disable clicking or opening the panel) - default false
17 |
18 |
19 |
20 | ### Panels example
21 |
22 | ```jsx
23 | import { MdInfo } from 'react-icons/md';
24 |
25 | const panels = [
26 | {
27 | label: 'Accordion1',
28 | icon: ,
29 | renderContent: () => (
30 |
31 |
Long Content for the accordion1
32 | Long Content for the accordion1
33 | Long Content for the accordion1
34 | Long Content for the accordion1
35 | Long Content for the accordion1
36 | Long Content for the accordion1
37 |
38 | ),
39 | },
40 | {
41 | label: 'Disabled Accordion',
42 | icon: ,
43 | renderContent: () => (
44 |
45 |
Long Content for the accordion
46 | Long Content for the accordion
47 | Long Content for the accordion
48 | Long Content for the accordion
49 | Long Content for the accordion
50 | Long Content for the accordion
51 |
52 | ),
53 | disabled: true,
54 | },
55 | {
56 | label: 'Accordion3',
57 | icon: ,
58 | renderContent: () => (
59 |
60 |
Long Content for the accordion3
61 | Long Content for the accordion3
62 | Long Content for the accordion3
63 | Long Content for the accordion3
64 | Long Content for the accordion3
65 | Long Content for the accordion3
66 |
67 | ),
68 | },
69 | ];
70 |
71 | ```
72 |
73 | ```jsx
74 | import { Accordion } from '@inplayer-org/inplayer-ui';
75 |
76 | const Page = () => (
77 |
78 | )
79 | ```
80 |
81 | ### Accordion example
82 |
83 |
84 |
85 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/src/components/Accordion/index.ts:
--------------------------------------------------------------------------------
1 | import Accordion from './Accordion';
2 |
3 | export default Accordion;
4 |
--------------------------------------------------------------------------------
/src/components/Accordion/panels.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/display-name */
2 | import React from 'react';
3 | import { MdInfo } from 'react-icons/md';
4 |
5 | export const panels = [
6 | {
7 | label: 'Accordion1',
8 | icon: ,
9 | renderContent: () => (
10 |
11 |
Long Content for the accordion1
12 | Long Content for the accordion1
13 | Long Content for the accordion1
14 | Long Content for the accordion1
15 | Long Content for the accordion1
16 | Long Content for the accordion1
17 |
18 | ),
19 | tag: 'tag1',
20 | },
21 | {
22 | label: 'Disabled Accordion',
23 | icon: ,
24 | renderContent: () => (
25 |
26 |
Long Content for the accordion
27 | Long Content for the accordion
28 | Long Content for the accordion
29 | Long Content for the accordion
30 | Long Content for the accordion
31 | Long Content for the accordion
32 |
33 | ),
34 | disabled: true,
35 | tag: 'tag2',
36 | },
37 | {
38 | label: 'Accordion3',
39 | icon: ,
40 | renderContent: () => (
41 |
42 |
Long Content for the accordion3
43 | Long Content for the accordion3
44 | Long Content for the accordion3
45 | Long Content for the accordion3
46 | Long Content for the accordion3
47 | Long Content for the accordion3
48 |
49 | ),
50 | tag: 'tag3',
51 | },
52 | ];
53 |
--------------------------------------------------------------------------------
/src/components/Accordion/styled.tsx:
--------------------------------------------------------------------------------
1 | import styled, { css } from 'styled-components';
2 | import colors from '../../theme/colors';
3 |
4 | type AccordionWrapperProps = {
5 | width?: string;
6 | extendWidth?: string;
7 | contentHeight: string;
8 | open: boolean;
9 | };
10 |
11 | export const AccordionWrapper = styled.div`
12 | ${({ width }) => width && `width: ${width}`};
13 | margin-left: 0%;
14 | position: relative;
15 | background: ${colors.white};
16 | border-left: 1px solid ${colors.gray};
17 | box-sizing: border-box;
18 | border-top: 1px solid ${colors.gray};
19 | ${({ contentHeight }) => contentHeight && `height: calc(${contentHeight} - 120px)`};
20 | overflow-y: hidden;
21 | display: flex;
22 | flex-direction: column;
23 | justify-content: space-between;
24 | transition: width 0.3s ease;
25 | ${({ open }) =>
26 | open &&
27 | css`
28 | ${({ width, extendWidth }: AccordionWrapperProps) =>
29 | width && `width: calc(${width} + ${extendWidth})`};
30 | `}
31 | `;
32 |
--------------------------------------------------------------------------------
/src/components/Avatar/Avatar.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled from 'styled-components';
3 | import colors from '../../theme/colors';
4 |
5 | const ImageContainer = styled.div`
6 | width: 100%;
7 | box-sizing: border-box;
8 | position: relative;
9 | text-align: center;
10 | padding: 0.5rem;
11 | `;
12 |
13 | const StyledImage = styled.img`
14 | border-radius: 50%;
15 | width: 140px;
16 | border: 5px solid ${colors.white};
17 | box-shadow: 0 3px 16px rgba(0, 0, 0, 0.4);
18 | `;
19 |
20 | type Props = {
21 | imageUrl?: string;
22 | };
23 |
24 | const Avatar = ({ imageUrl }: Props) => (
25 |
26 |
27 |
28 | );
29 |
30 | Avatar.defaultProps = {
31 | imageUrl: 'https://assets.inplayer.com/images/merchant-default-avatar.png',
32 | };
33 |
34 | export default Avatar;
35 |
--------------------------------------------------------------------------------
/src/components/Avatar/avatar.stories.mdx:
--------------------------------------------------------------------------------
1 | import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
2 | import Avatar from './'
3 |
4 | } />
5 |
6 | # Avatar
7 |
8 | ```jsx
9 | import { Avatar } from '@inplayer-org/inplayer-ui';
10 |
11 | const Page = () => (
12 |
13 | )
14 | ```
15 | ### Props
16 |
17 |
18 | ### Default Avatar
19 |
20 |
21 |
24 |
25 |
26 |
27 | ### Avatar with image provided
28 |
29 |
30 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/components/Avatar/index.ts:
--------------------------------------------------------------------------------
1 | import Avatar from './Avatar';
2 |
3 | export default Avatar;
4 |
--------------------------------------------------------------------------------
/src/components/Button/Button.tsx:
--------------------------------------------------------------------------------
1 | import React, { ButtonHTMLAttributes, ReactElement } from 'react';
2 | import styled, { css } from 'styled-components';
3 | import ButtonWrapper from './ButtonWrapper';
4 | import {
5 | AnalyticsProps,
6 | AnalyticsComponent,
7 | AnalyticsEvents,
8 | AnalyticsComponentType,
9 | } from '../../analytics';
10 |
11 | export type Size = 'xs' | 'sm' | 'md' | 'lg';
12 |
13 | type ContentProps = {
14 | icon?: ReactElement | null;
15 | iconPosition?: string;
16 | children?: any;
17 | };
18 |
19 | export type Props = ButtonHTMLAttributes &
20 | ContentProps & {
21 | buttonModifiers?: Array;
22 | size?: Size;
23 | className?: string;
24 | fullWidth?: boolean;
25 | fullHeight?: boolean;
26 | } & AnalyticsProps;
27 |
28 | const ContentHolder = styled.span`
29 | margin-top: 2px;
30 | `;
31 |
32 | const TextIconWrapper = styled.div<{ center: boolean }>`
33 | padding: 0.2rem;
34 | ${({ center }) =>
35 | center &&
36 | css`
37 | display: grid;
38 | grid-auto-flow: column;
39 | place-items: center;
40 | `}
41 | `;
42 |
43 | const Content = ({ icon = null, iconPosition = 'left', children }: ContentProps) => {
44 | if (iconPosition === 'right') {
45 | return (
46 |
47 | {children && {children}}
48 | {icon}
49 |
50 | );
51 | }
52 |
53 | return (
54 |
55 | {icon}
56 | {children && {children}}
57 |
58 | );
59 | };
60 |
61 | const Button = ({
62 | size = 'md',
63 | tag,
64 | buttonModifiers,
65 | className = '',
66 | icon,
67 | iconPosition,
68 | children,
69 | fullWidth,
70 | fullHeight,
71 | onClick,
72 | ...rest
73 | }: Props) => (
74 |
75 | {({ pages, tracker, merchantId, ip }) => (
76 | {
83 | onClick?.(e);
84 |
85 | if (tag) {
86 | tracker.track({
87 | event: AnalyticsEvents.CLICK,
88 | type: AnalyticsComponentType.BUTTON,
89 | tag,
90 | pages,
91 | merchantId,
92 | ip,
93 | });
94 | }
95 | }}
96 | {...rest}
97 | >
98 |
99 | {children}
100 |
101 |
102 | )}
103 |
104 | );
105 |
106 | export default Button;
107 |
--------------------------------------------------------------------------------
/src/components/Button/Usage.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { MdDelete, MdErrorOutline } from 'react-icons/md';
3 | import Button from '.';
4 |
5 | const Usage = () => (
6 | <>
7 |
8 | } buttonModifiers={['buttonDanger']} />
9 |
10 | } iconPosition="right">
11 | Button with Icon on Right!
12 |
13 |
14 | }>
15 | Button with Icon Color Modifier
16 |
17 |
18 | }>Button with Custom Icon
19 | }>Button with Custom Icon Color
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
Button hover:
30 |
31 |
32 |
33 |
34 |
35 | Button types:
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | >
45 | );
46 |
47 | export default Usage;
48 |
--------------------------------------------------------------------------------
/src/components/Button/button.stories.mdx:
--------------------------------------------------------------------------------
1 | import { Meta, Story, Preview } from "@storybook/addon-docs/blocks";
2 | import { withKnobs, select, boolean } from "@storybook/addon-knobs";
3 | import Button from './'
4 | import { MdDelete, MdErrorOutline } from 'react-icons/md';
5 | import { SeparateElements } from '../DocsStyle'
6 |
7 | } />
8 |
9 | # Button
10 |
11 | Button is a component which supports different kind of types, starting from `color`, `size`, `modifiers` etc.
12 |
13 | ```jsx
14 | import { Button } from '@inplayer-org/inplayer-ui';
15 |
16 | const Page = () => (
17 |
18 | )
19 | ```
20 |
21 | ### Default Button
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | ### Buttons with different sizes
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | ### On hover Buttons
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | ### Different types of Buttons
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | ### Buttons with icons
72 |
73 |
74 |
75 | } buttonModifiers={['buttonDanger']} />
76 |
77 | } iconPosition="right">
78 | Button with Icon on Right!
79 |
80 |
81 | }>
82 | Button with Icon Color Modifier
83 |
84 |
85 | }>Button with Custom Icon
86 | }>Button with Custom Icon Color
87 |
88 |
89 |
--------------------------------------------------------------------------------
/src/components/Button/index.ts:
--------------------------------------------------------------------------------
1 | import Button from './Button';
2 |
3 | export default Button;
4 |
--------------------------------------------------------------------------------
/src/components/Card/Card.tsx:
--------------------------------------------------------------------------------
1 | import React, { ReactChild } from 'react';
2 | import styled from 'styled-components';
3 | import { transparentize } from 'polished';
4 | import colors from '../../theme/colors';
5 | import Typography, { TypographyVariant } from '../Typography/Typography';
6 | import CardContent from './CardContent';
7 | import { AnalyticsProps } from '../../analytics';
8 |
9 | const CardWrapper = styled.div`
10 | display: flex;
11 | flex-direction: column;
12 | justify-content: space-between;
13 | align-items: center;
14 | position: relative;
15 | box-shadow: 0 0 4px 1px ${transparentize(0.87, colors.fontDarkGray)};
16 | border-radius: 3px;
17 | background: ${({ theme }) => theme.palette.background.main};
18 | line-height: 1.5;
19 | box-sizing: border-box;
20 | margin: 0;
21 | padding: 0 1.5rem;
22 | list-style: none;
23 | `;
24 |
25 | const CardTitle = styled(Typography)`
26 | flex: 1;
27 | width: 100%;
28 | margin: 0;
29 | padding: 0.5rem 0;
30 | text-overflow: ellipsis;
31 | overflow: hidden;
32 | white-space: nowrap;
33 | display: inline-block;
34 | `;
35 |
36 | type Props = {
37 | title?: string;
38 | titleVariant?: TypographyVariant;
39 | className?: string;
40 | children: ReactChild;
41 | } & AnalyticsProps;
42 |
43 | const Card = ({ title, titleVariant = 'h1', className = '', children }: Props) => (
44 |
45 | {title && {title}}
46 | {children}
47 |
48 | );
49 |
50 | export default Card;
51 |
--------------------------------------------------------------------------------
/src/components/Card/CardContent.tsx:
--------------------------------------------------------------------------------
1 | import React, { ReactNode } from 'react';
2 | import styled from 'styled-components';
3 |
4 | const ContentWrapper = styled.div`
5 | flex: 3;
6 | padding: 1.2rem 0;
7 | height: 100%;
8 | width: 100%;
9 | `;
10 |
11 | interface Props {
12 | children: ReactNode;
13 | }
14 |
15 | const CardContent = ({ children }: Props) => {children};
16 |
17 | CardContent.defaultProps = {
18 | component: 'div',
19 | };
20 |
21 | export default CardContent;
22 |
--------------------------------------------------------------------------------
/src/components/Card/card.stories.mdx:
--------------------------------------------------------------------------------
1 | import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
2 | import Card from './'
3 | import Typography from '../Typography'
4 |
5 | } />
6 |
7 | # Card
8 |
9 | ```jsx
10 | import { Card } from '@inplayer-org/inplayer-ui';
11 |
12 | const Page = () => (
13 |
14 | )
15 | ```
16 |
17 | ### Props
18 |
19 |
20 | ### Simple Card
21 |
22 |
23 |
24 |
25 | Card content
26 | Card content
27 | Card content
28 |
29 |
30 |
31 |
32 |
33 | ### No title Card
34 |
35 |
36 |
37 |
38 | Card content
39 | Card content
40 | Card content
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/components/Card/index.ts:
--------------------------------------------------------------------------------
1 | import Card from './Card';
2 |
3 | export default Card;
4 |
--------------------------------------------------------------------------------
/src/components/Checkbox/Checkbox.tsx:
--------------------------------------------------------------------------------
1 | import React, { ChangeEvent, RefObject } from 'react';
2 | import Label from '../Label';
3 | import CheckboxWrapper from './CheckboxWrapper';
4 | import {
5 | AnalyticsComponent,
6 | AnalyticsComponentType,
7 | AnalyticsProps,
8 | AnalyticsEvents,
9 | } from '../../analytics';
10 |
11 | type Props = {
12 | label: string;
13 | id: string;
14 | name?: string;
15 | checked: boolean;
16 | onChange: (checked: boolean) => any;
17 | containerRef?: RefObject | null;
18 | disabled?: boolean;
19 | } & AnalyticsProps;
20 |
21 | const Checkbox: React.FC = ({
22 | label,
23 | id,
24 | onChange,
25 | containerRef = null,
26 | disabled = false,
27 | tag = '',
28 | ...rest
29 | }) => {
30 | const onCheckboxChange = (e: ChangeEvent): any => onChange(e.target.checked);
31 |
32 | return (
33 |
34 | {({ pages, tracker, merchantId, ip }) => (
35 |
36 | {
41 | onCheckboxChange(e);
42 |
43 | if (tag) {
44 | if (e.target.checked) {
45 | tracker.track({
46 | event: AnalyticsEvents.CHECKBOX_ON,
47 | type: AnalyticsComponentType.CHECKBOX,
48 | tag,
49 | pages,
50 | merchantId,
51 | ip,
52 | });
53 | } else {
54 | tracker.track({
55 | event: AnalyticsEvents.CHECKBOX_OFF,
56 | type: AnalyticsComponentType.CHECKBOX,
57 | tag,
58 | pages,
59 | merchantId,
60 | ip,
61 | });
62 | }
63 | }
64 | }}
65 | {...rest}
66 | />
67 |
68 |
69 | )}
70 |
71 | );
72 | };
73 |
74 | export default Checkbox;
75 |
--------------------------------------------------------------------------------
/src/components/Checkbox/CheckboxWrapper.ts:
--------------------------------------------------------------------------------
1 | import styled, { DefaultTheme } from 'styled-components';
2 | import colors from '../../theme/colors';
3 |
4 | const CheckboxWrapper = styled.div<{ theme: DefaultTheme }>`
5 | display: flex;
6 |
7 | > input {
8 | display: none;
9 | }
10 |
11 | > input + label {
12 | position: relative;
13 | padding-left: 1.5em;
14 | cursor: pointer;
15 |
16 | &::before {
17 | content: '';
18 | position: absolute;
19 | left: 0;
20 | top: 0;
21 | width: 1em;
22 | height: 1em;
23 | border: 1px solid ${colors.gray};
24 | background: ${colors.white};
25 | border-radius: 2px;
26 | transition: all ease 300ms;
27 | }
28 |
29 | &::after {
30 | content: '';
31 | position: absolute;
32 | top: 5px;
33 | left: 4px;
34 | transition: all ease 300ms;
35 | }
36 | }
37 |
38 | > input:checked + label {
39 | &::before {
40 | border: 1px solid ${colors.skyBlue};
41 | }
42 |
43 | &::after {
44 | border: 2px solid ${colors.skyBlue};
45 | border-top: none;
46 | border-right: none;
47 | width: 0.5em;
48 | height: 0.25em;
49 | opacity: 1;
50 | transform: scale(1) rotate(-45deg);
51 | }
52 | }
53 |
54 | > input:not(:checked) + label {
55 | &::after {
56 | border: 2px solid ${colors.white};
57 | border-top: none;
58 | border-right: none;
59 | width: 0.5em;
60 | height: 0.25em;
61 | opacity: 1;
62 | transform: scale(0);
63 | }
64 | }
65 |
66 | > input:checked + label:hover {
67 | ::before {
68 | border-color: transparent;
69 | background: ${colors.lightSkyBlue};
70 | }
71 |
72 | ::after {
73 | border-color: ${colors.skyBlue};
74 | }
75 | }
76 |
77 | > input:not(:checked) + label:hover {
78 | ::before {
79 | border: 1px solid ${colors.skyBlue};
80 | background-color: ${colors.lightSkyBlue};
81 | }
82 |
83 | ::after {
84 | transform: scale(1) rotate(-45deg);
85 | }
86 | }
87 |
88 | > input:checked:focus + label,
89 | input:not(:checked):focus + label {
90 | &::before {
91 | border: 1px dotted ${colors.lightSkyBlue};
92 | }
93 | }
94 |
95 | > input:disabled:checked + label {
96 | color: ${({ theme }) => theme.palette.text.disabled};
97 |
98 | &::before {
99 | border: 1px solid ${colors.gray};
100 | background: transparent;
101 | }
102 |
103 | &::after {
104 | border-color: ${colors.gray};
105 | background: transparent;
106 | }
107 | }
108 |
109 | > input:disabled:not(:checked) + label {
110 | color: ${({ theme }) => theme.palette.text.disabled};
111 |
112 | &::before {
113 | border: 1px solid ${colors.gray};
114 | background: transparent;
115 | }
116 | }
117 | `;
118 |
119 | export default CheckboxWrapper;
120 |
--------------------------------------------------------------------------------
/src/components/Checkbox/Usage.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import Checkbox from '.';
3 |
4 | const Usage = () => {
5 | const [checkMe, setCheckMe] = useState(false);
6 | const [checkedByDefault, setCheckedByDefault] = useState(true);
7 | return (
8 | <>
9 | setCheckMe(!checkMe)} />
10 | setCheckedByDefault(!checkedByDefault)}
15 | />
16 | console.log(e)}
21 | />
22 | console.log(e)}
27 | disabled
28 | />
29 | console.log(e)}
34 | disabled
35 | />
36 | >
37 | );
38 | };
39 |
40 | export default Usage;
41 |
--------------------------------------------------------------------------------
/src/components/Checkbox/checkbox.stories.mdx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
3 | import Checkbox from './'
4 |
5 | } />
6 |
7 | # Checkbox
8 |
9 | ```jsx
10 | import { Checkbox } from '@inplayer-org/inplayer-ui';
11 |
12 | const Page = () => (
13 |
14 | )
15 | ```
16 |
17 | ### Unchecked - can be changed
18 |
19 |
20 | {() => {
21 | const [checked, setChecked] = useState(false);
22 | return (
23 | setChecked(!checked)}
28 | />
29 | )
30 | }}
31 |
32 |
33 |
34 | ### Checked - can be changed
35 |
36 |
37 | {() => {
38 | const [checkedByDefault, setCheckedByDefault] = useState(true);
39 | return (
40 | setCheckedByDefault(!checkedByDefault)}
45 | />
46 | )
47 | }}
48 |
49 |
50 |
51 | ### Checked - cannot be changed
52 |
53 |
54 | console.log(e)}
59 | />
60 |
61 |
62 |
63 | ### Unchecked - disabled
64 |
65 |
66 | console.log(e)}
71 | />
72 |
73 |
74 |
75 | ### Checked - disabled
76 |
77 |
78 | console.log(e)}
84 | />
85 |
86 |
--------------------------------------------------------------------------------
/src/components/Checkbox/index.ts:
--------------------------------------------------------------------------------
1 | import Checkbox from './Checkbox';
2 |
3 | export default Checkbox;
4 |
--------------------------------------------------------------------------------
/src/components/DatePicker/index.ts:
--------------------------------------------------------------------------------
1 | import DatePicker from './DatePicker';
2 |
3 | export default DatePicker;
4 |
--------------------------------------------------------------------------------
/src/components/DatePicker/periods.ts:
--------------------------------------------------------------------------------
1 | export const PERIODS = {
2 | TODAY: '1D',
3 | ONE_WEEK: '1W',
4 | TWO_WEEKS: '2w',
5 | ONE_MONTH: '1M',
6 | SIX_MONTHS: '6M',
7 | ONE_YEAR: '1Y',
8 | ALL: 'ALL',
9 | };
10 |
11 | export const INNERPERIODS = {
12 | THIS_WEEK: 'this week',
13 | LAST_WEEK: 'last week',
14 | LAST_TWO_WEEKS: 'last 2 weeks',
15 | THIS_MONTH: 'this month',
16 | LAST_MONTH: 'last month',
17 | THIS_YEAR: 'this year',
18 | LAST_SIX_MONTHS: 'last 6 months',
19 | ALL_TIME: 'all time',
20 | CUSTOM: 'custom date preset',
21 | };
22 |
--------------------------------------------------------------------------------
/src/components/DatePicker/styles.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | import colors from '../../theme/colors';
4 | import Label from '../Label';
5 |
6 | const StyledLabel = styled(Label)<{ active: boolean }>`
7 | display: block;
8 | font-size: ${({ theme }) => theme.font.sizes.small};
9 | transition: ease 200ms color;
10 | cursor: pointer;
11 | padding: 0.4375rem;
12 | font-weight: ${({ active, theme: { font } }) =>
13 | active ? font.weights.normal : font.weights.light};
14 | color: ${({ active }) => (active ? colors.navy : colors.fontGray)};
15 | &:hover {
16 | color: ${colors.navy} !important;
17 | }
18 | `;
19 |
20 | const DatePresetWrapper = styled.div`
21 | width: 96px;
22 | text-align: center;
23 | padding: 6.5rem 0 0.625rem 0;
24 | `;
25 |
26 | const CustomMonthContainer = styled.div`
27 | display: flex;
28 | justify-content: center;
29 | `;
30 |
31 | const DropdownContainer = styled.div`
32 | margin: 0 0.1rem;
33 | `;
34 |
35 | export const Styled = {
36 | StyledLabel,
37 | DatePresetWrapper,
38 | CustomMonthContainer,
39 | DropdownContainer,
40 | };
41 |
--------------------------------------------------------------------------------
/src/components/DayPicker/DayPickerWrapper.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | import colors from '../../theme/colors';
4 | import DatePickerWrapper from '../DatePicker/DatePickerWrapper';
5 |
6 | const DayPickerWrapper = styled(DatePickerWrapper)`
7 | .DateInput {
8 | width: 100px !important;
9 | }
10 |
11 | .DateInput_input {
12 | text-align: center;
13 | padding: 0;
14 | }
15 |
16 | .CalendarDay__selected:hover {
17 | background: ${colors.skyBlue};
18 | color: ${colors.white};
19 | }
20 |
21 | .SingleDatePickerInput {
22 | display: inline-block;
23 | background-color: ${colors.white};
24 | }
25 |
26 | .SingleDatePickerInput__withBorder {
27 | border-radius: 2px;
28 | border: 1px solid ${colors.gray};
29 | }
30 |
31 | .SingleDatePickerInput__rtl {
32 | direction: rtl;
33 | }
34 |
35 | .SingleDatePickerInput__disabled {
36 | background-color: ${colors.lightGray};
37 | }
38 |
39 | .SingleDatePickerInput__block {
40 | display: block;
41 | }
42 |
43 | .SingleDatePickerInput__showClearDate {
44 | padding-right: 1.875rem;
45 | }
46 |
47 | .SingleDatePickerInput_calendarIcon {
48 | background: 0 0;
49 | border: 0;
50 | color: inherit;
51 | font: inherit;
52 | line-height: normal;
53 | overflow: visible;
54 | cursor: pointer;
55 | display: inline-block;
56 | vertical-align: middle;
57 | padding: 0.625rem;
58 | margin: 0 0.5rem;
59 | }
60 |
61 | .SingleDatePickerInput_calendarIcon_svg {
62 | fill: ${colors.darkGray};
63 | height: 15px;
64 | width: 14px;
65 | vertical-align: middle;
66 | }
67 |
68 | .SingleDatePicker {
69 | position: relative;
70 | display: inline-block;
71 | }
72 |
73 | .SingleDatePicker__block {
74 | display: block;
75 | }
76 |
77 | .SingleDatePicker_picker {
78 | z-index: 10;
79 | background-color: ${colors.white};
80 | position: absolute;
81 | top: 35px !important;
82 | }
83 |
84 | .SingleDatePicker_picker__rtl {
85 | direction: rtl;
86 | }
87 |
88 | .SingleDatePicker_picker__directionLeft {
89 | left: 0;
90 | }
91 |
92 | .SingleDatePicker_picker__directionRight {
93 | right: 0;
94 | }
95 |
96 | .SingleDatePicker_picker__portal {
97 | background-color: ${colors.lightGray};
98 | position: fixed;
99 | top: 0;
100 | left: 0;
101 | height: 100%;
102 | width: 100%;
103 | }
104 |
105 | .SingleDatePicker_picker__fullScreenPortal {
106 | background-color: #fff;
107 | }
108 | `;
109 |
110 | export default DayPickerWrapper;
111 |
--------------------------------------------------------------------------------
/src/components/DayPicker/Usage.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-shadow */
2 | import React, { useState } from 'react';
3 | import moment, { Moment } from 'moment';
4 | import DayPicker from './DayPicker';
5 |
6 | const DayPickerUsage = () => {
7 | const stringDate = moment();
8 | const [date, setDate] = useState(stringDate);
9 | const [focused, setFocused] = useState(false);
10 |
11 | return (
12 | setFocused(focused)}
14 | onDateChange={(date) => setDate(date)}
15 | id="date picker"
16 | date={date}
17 | focused={focused}
18 | numberOfMonths={1}
19 | isOutsideRange={() => false}
20 | />
21 | );
22 | };
23 |
24 | export default DayPickerUsage;
25 |
--------------------------------------------------------------------------------
/src/components/DayPicker/daypicker.stories.mdx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
3 | import moment from 'moment';
4 | import DayPicker from './'
5 |
6 | } />
7 |
8 | # DayPicker
9 |
10 | ```jsx
11 | import { DayPicker } from '@inplayer-org/inplayer-ui';
12 |
13 | const Page = () => (
14 |
15 | )
16 | ```
17 |
18 | ### Props
19 |
20 |
21 | ### Date provided as a string
22 |
23 |
24 | { ()=> {
25 | const stringDate = '2014-02-27T10:00:00';
26 | const [date, setDate] = useState(stringDate);
27 | const [focused, setFocused] = useState(false);
28 | return (
29 |
30 | setFocused(focused)}
32 | onDateChange={(date) => setDate(date)}
33 | id="date picker"
34 | date={date}
35 | focused={focused}
36 | numberOfMonths={1}
37 | isOutsideRange={() => false}
38 | />
39 |
40 | );
41 | }}
42 |
43 |
44 |
45 | ### Date provided as an object
46 |
47 |
48 | { ()=> {
49 | const momentFormatDate = moment();
50 | const [date, setDate] = useState(momentFormatDate);
51 | const [focused, setFocused] = useState(false);
52 | return (
53 |
54 | setDate(date)}
57 | onFocusChange={({ focused }) => setFocused(focused)}
58 | focused={focused}
59 | date={date}
60 | />
61 |
62 | );
63 | }}
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/src/components/DayPicker/index.ts:
--------------------------------------------------------------------------------
1 | import DayPicker from './DayPicker';
2 |
3 | export default DayPicker;
4 |
--------------------------------------------------------------------------------
/src/components/DocsStyle.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const SeparateElements = styled.div`
4 | width: 90%;
5 | > * {
6 | display: inline;
7 | margin: 10px;
8 | }
9 | `;
10 |
--------------------------------------------------------------------------------
/src/components/Drawer/Drawer.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DrawerContainer from './DrawerContainer';
3 | import { AnalyticsProps } from '../../analytics';
4 |
5 | type Props = {
6 | handleClose: () => void;
7 | isOpen: boolean;
8 | width?: string;
9 | } & AnalyticsProps;
10 |
11 | const Drawer: React.FC = ({ children, handleClose, isOpen, width = '40%' }) => (
12 |
13 | {children}
14 |
15 | );
16 | export default Drawer;
17 |
--------------------------------------------------------------------------------
/src/components/Drawer/DrawerContainer.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef, useEffect } from 'react';
2 | import { CloseSection, StyledIcon, SideDrawer } from './styles';
3 |
4 | interface Props {
5 | shouldShowDrawer: boolean;
6 | closeDrawer: (event: any) => void;
7 | width: string;
8 | }
9 |
10 | const DrawerContainer: React.FC = ({ shouldShowDrawer, children, closeDrawer, width }) => {
11 | const reference = useRef(null);
12 |
13 | useEffect(() => {
14 | const listener = (event: { target: any }) => {
15 | // if inside drawer
16 | if (!reference.current || reference.current.contains(event.target)) {
17 | return;
18 | }
19 |
20 | closeDrawer(event);
21 | };
22 |
23 | document.addEventListener('mousedown', listener);
24 | document.addEventListener('touchstart', listener);
25 |
26 | return () => {
27 | document.removeEventListener('mousedown', listener);
28 | document.removeEventListener('touchstart', listener);
29 | };
30 | }, [reference, closeDrawer]);
31 |
32 | return (
33 | <>
34 |
35 |
36 |
37 |
38 | {children}
39 |
40 | >
41 | );
42 | };
43 |
44 | export default DrawerContainer;
45 |
--------------------------------------------------------------------------------
/src/components/Drawer/drawer.stories.mdx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
3 | import Drawer from './'
4 |
5 | } />
6 |
7 | # Drawer
8 |
9 | A simple Drawer controlled component
10 |
11 | ```jsx
12 | import { Drawer } from '@inplayer-org/inplayer-ui';
13 |
14 | const Page = () => (
15 |
16 | )
17 | ```
18 |
19 |
20 | ### Standard drawer
21 |
22 |
23 | { () => {
24 | const [isOpen, setisOpen] = useState(false);
25 | const handleToggleDrawer = () => {
26 | setisOpen(!isOpen);
27 | };
28 | const handleClose = () => {
29 | setisOpen(false);
30 | };
31 | return (
32 |
33 |
36 | Hi there!
37 |
38 | )
39 | }}
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/components/Drawer/index.ts:
--------------------------------------------------------------------------------
1 | import Drawer from './Drawer';
2 |
3 | export default Drawer;
4 |
--------------------------------------------------------------------------------
/src/components/Drawer/styles.ts:
--------------------------------------------------------------------------------
1 | import { ImCross } from 'react-icons/im';
2 | import styled, { css } from 'styled-components';
3 |
4 | import colors from '../../theme/colors';
5 |
6 | interface SideDrawerProps {
7 | isOpen: boolean;
8 | width: string;
9 | }
10 | export const SideDrawer = styled.div`
11 | height: 100%;
12 | background: ${colors.white};
13 | position: fixed;
14 | top: 0;
15 | right: 0;
16 | width: ${({ width }) => width};
17 | z-index: 1000;
18 |
19 | transform: translateX(100%);
20 | transition: transform 0.4s ease-out;
21 |
22 | ${({ isOpen }) =>
23 | isOpen &&
24 | css`
25 | transform: translateX(0);
26 | box-shadow: 0 20px 25px 10000px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
27 | `}
28 | `;
29 | export const CloseSection = styled.div`
30 | display: flex;
31 | justify-content: flex-end;
32 | margin: 1rem;
33 | `;
34 | export const StyledIcon = styled(ImCross)`
35 | color: ${colors.fontGray};
36 |
37 | :hover {
38 | color: ${colors.fontDarkGray};
39 | cursor: pointer;
40 | }
41 | `;
42 |
--------------------------------------------------------------------------------
/src/components/Dropdown/DocsStyle.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const DropdownWrapperDocs = styled.div`
4 | width: 200px;
5 | > * {
6 | display: inline;
7 | margin: 10px;
8 | }
9 | `;
10 |
--------------------------------------------------------------------------------
/src/components/Dropdown/Dropdown.tsx:
--------------------------------------------------------------------------------
1 | import React, { SelectHTMLAttributes, ChangeEvent } from 'react';
2 | import { snakeCase } from 'lodash';
3 | import DropdownContainer from './DropdownContainer';
4 | import {
5 | AnalyticsEvents,
6 | AnalyticsComponentType,
7 | AnalyticsComponent,
8 | AnalyticsProps,
9 | } from '../../analytics';
10 |
11 | export type Option = {
12 | value: string;
13 | displayName: string;
14 | disabled?: boolean;
15 | } & AnalyticsProps;
16 |
17 | type DefaultOption = {
18 | displayName: string;
19 | disabled?: boolean;
20 | } & AnalyticsProps;
21 |
22 | type SelectHTMLProps = Omit, 'onChange'>;
23 |
24 | type Props = SelectHTMLProps & {
25 | modifiers?: Array;
26 | value: string;
27 | onChange?: (value: string) => void;
28 | color?: string;
29 | options: Array