diff --git a/components/common/Button.js b/components/common/Button.js
index 5e92d0d8..0cdb5fbc 100644
--- a/components/common/Button.js
+++ b/components/common/Button.js
@@ -1,10 +1,11 @@
import React from 'react';
+import PropTypes from 'prop-types';
import ReactTooltip from 'react-tooltip';
import classNames from 'classnames';
import Icon from './Icon';
import styles from './Button.module.css';
-export default function Button({
+function Button({
type = 'button',
icon,
size,
@@ -43,3 +44,19 @@ export default function Button({
);
}
+
+Button.propTypes = {
+ type: PropTypes.oneOf(['button', 'submit', 'reset']),
+ icon: PropTypes.node,
+ size: PropTypes.oneOf(['xlarge', 'large', 'medium', 'small', 'xsmall']),
+ variant: PropTypes.oneOf(['action', 'danger', 'light']),
+ children: PropTypes.node,
+ className: PropTypes.string,
+ tooltip: PropTypes.node,
+ tooltipId: PropTypes.string,
+ disabled: PropTypes.bool,
+ iconRight: PropTypes.bool,
+ onClick: PropTypes.func,
+};
+
+export default Button;
diff --git a/components/common/ButtonGroup.js b/components/common/ButtonGroup.js
index c91bb743..353ce690 100644
--- a/components/common/ButtonGroup.js
+++ b/components/common/ButtonGroup.js
@@ -1,16 +1,10 @@
import React from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import Button from './Button';
import styles from './ButtonGroup.module.css';
-export default function ButtonGroup({
- items = [],
- selectedItem,
- className,
- size,
- icon,
- onClick = () => {},
-}) {
+function ButtonGroup({ items = [], selectedItem, className, size, icon, onClick = () => {} }) {
return (
{items.map(item => {
@@ -30,3 +24,19 @@ export default function ButtonGroup({
);
}
+
+ButtonGroup.propTypes = {
+ items: PropTypes.arrayOf(
+ PropTypes.shape({
+ label: PropTypes.node,
+ value: PropTypes.any.isRequired,
+ }),
+ ),
+ selectedItem: PropTypes.any,
+ className: PropTypes.string,
+ size: PropTypes.oneOf(['xlarge', 'large', 'medium', 'small', 'xsmall']),
+ icon: PropTypes.node,
+ onClick: PropTypes.func,
+};
+
+export default ButtonGroup;
diff --git a/components/common/Checkbox.js b/components/common/Checkbox.js
index 1a66a258..67eea80d 100644
--- a/components/common/Checkbox.js
+++ b/components/common/Checkbox.js
@@ -1,9 +1,10 @@
import React, { useRef } from 'react';
+import PropTypes from 'prop-types';
import Icon from 'components/common/Icon';
import Check from 'assets/check.svg';
import styles from './Checkbox.module.css';
-export default function Checkbox({ name, value, label, onChange }) {
+function Checkbox({ name, value, label, onChange }) {
const ref = useRef();
return (
@@ -25,3 +26,12 @@ export default function Checkbox({ name, value, label, onChange }) {
);
}
+
+Checkbox.propTypes = {
+ name: PropTypes.string,
+ value: PropTypes.any,
+ label: PropTypes.node,
+ onChange: PropTypes.func,
+};
+
+export default Checkbox;
diff --git a/components/common/CopyButton.js b/components/common/CopyButton.js
index 460c68ac..b300ef31 100644
--- a/components/common/CopyButton.js
+++ b/components/common/CopyButton.js
@@ -1,4 +1,5 @@
import React, { useState } from 'react';
+import PropTypes from 'prop-types';
import Button from './Button';
import { FormattedMessage } from 'react-intl';
@@ -6,7 +7,7 @@ const defaultText = (
);
-export default function CopyButton({ element, ...props }) {
+function CopyButton({ element, ...props }) {
const [text, setText] = useState(defaultText);
function handleClick() {
@@ -24,3 +25,13 @@ export default function CopyButton({ element, ...props }) {
);
}
+
+CopyButton.propTypes = {
+ element: PropTypes.shape({
+ current: PropTypes.shape({
+ select: PropTypes.func.isRequired,
+ }),
+ }),
+};
+
+export default CopyButton;
diff --git a/components/common/DateFilter.js b/components/common/DateFilter.js
index fb76a081..6279d338 100644
--- a/components/common/DateFilter.js
+++ b/components/common/DateFilter.js
@@ -1,4 +1,5 @@
import React, { useState } from 'react';
+import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { endOfYear, isSameDay } from 'date-fns';
import Modal from './Modal';
@@ -54,7 +55,7 @@ const filterOptions = [
},
];
-export default function DateFilter({ value, startDate, endDate, onChange, className }) {
+function DateFilter({ value, startDate, endDate, onChange, className }) {
const [showPicker, setShowPicker] = useState(false);
const displayValue =
value === 'custom' ? (
@@ -117,3 +118,13 @@ const CustomRange = ({ startDate, endDate, onClick }) => {
>
);
};
+
+DateFilter.propTypes = {
+ value: PropTypes.string,
+ startDate: PropTypes.instanceOf(Date),
+ endDate: PropTypes.instanceOf(Date),
+ onChange: PropTypes.func,
+ className: PropTypes.string,
+};
+
+export default DateFilter;
diff --git a/components/common/Dot.js b/components/common/Dot.js
index d5dcf914..81454c48 100644
--- a/components/common/Dot.js
+++ b/components/common/Dot.js
@@ -1,8 +1,9 @@
import React from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import styles from './Dot.module.css';
-export default function Dot({ color, size, className }) {
+function Dot({ color, size, className }) {
return (
);
}
+
+Dot.propTypes = {
+ color: PropTypes.string,
+ size: PropTypes.oneOf(['small', 'large']),
+ className: PropTypes.string,
+};
+
+export default Dot;
diff --git a/components/common/DropDown.js b/components/common/DropDown.js
index 3b3be39e..00d20e34 100644
--- a/components/common/DropDown.js
+++ b/components/common/DropDown.js
@@ -1,4 +1,5 @@
import React, { useState, useRef } from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import Menu from './Menu';
import useDocumentClick from 'hooks/useDocumentClick';
@@ -6,13 +7,7 @@ import Chevron from 'assets/chevron-down.svg';
import styles from './Dropdown.module.css';
import Icon from './Icon';
-export default function DropDown({
- value,
- className,
- menuClassName,
- options = [],
- onChange = () => {},
-}) {
+function DropDown({ value, className, menuClassName, options = [], onChange = () => {} }) {
const [showMenu, setShowMenu] = useState(false);
const ref = useRef();
const selectedOption = options.find(e => e.value === value);
@@ -52,3 +47,18 @@ export default function DropDown({
);
}
+
+DropDown.propTypes = {
+ value: PropTypes.any,
+ className: PropTypes.string,
+ menuClassName: PropTypes.string,
+ options: PropTypes.arrayOf(
+ PropTypes.shape({
+ value: PropTypes.any.isRequired,
+ label: PropTypes.node,
+ }),
+ ),
+ onChange: PropTypes.func,
+};
+
+export default DropDown;
diff --git a/components/common/EmptyPlaceholder.js b/components/common/EmptyPlaceholder.js
index 26a9fcbf..a223814d 100644
--- a/components/common/EmptyPlaceholder.js
+++ b/components/common/EmptyPlaceholder.js
@@ -1,9 +1,10 @@
import React from 'react';
+import PropTypes from 'prop-types';
import Icon from 'components/common/Icon';
import Logo from 'assets/logo.svg';
import styles from './EmptyPlaceholder.module.css';
-export default function EmptyPlaceholder({ msg, children }) {
+function EmptyPlaceholder({ msg, children }) {
return (
} size="xlarge" />
@@ -12,3 +13,10 @@ export default function EmptyPlaceholder({ msg, children }) {
);
}
+
+EmptyPlaceholder.propTypes = {
+ msg: PropTypes.node,
+ children: PropTypes.node,
+};
+
+export default EmptyPlaceholder;
diff --git a/components/common/Favicon.js b/components/common/Favicon.js
index 07ec696c..d72cd3c7 100644
--- a/components/common/Favicon.js
+++ b/components/common/Favicon.js
@@ -1,4 +1,5 @@
import React from 'react';
+import PropTypes from 'prop-types';
import styles from './Favicon.module.css';
function getHostName(url) {
@@ -6,7 +7,7 @@ function getHostName(url) {
return match && match.length > 1 ? match[1] : null;
}
-export default function Favicon({ domain, ...props }) {
+function Favicon({ domain, ...props }) {
const hostName = domain ? getHostName(domain) : null;
return hostName ? (
@@ -19,3 +20,9 @@ export default function Favicon({ domain, ...props }) {
/>
) : null;
}
+
+Favicon.propTypes = {
+ domain: PropTypes.string,
+};
+
+export default Favicon;
diff --git a/components/common/FilterButtons.js b/components/common/FilterButtons.js
index 5b898bf4..ea811216 100644
--- a/components/common/FilterButtons.js
+++ b/components/common/FilterButtons.js
@@ -1,11 +1,25 @@
import React from 'react';
+import PropTypes from 'prop-types';
import ButtonLayout from 'components/layout/ButtonLayout';
import ButtonGroup from './ButtonGroup';
-export default function FilterButtons({ buttons, selected, onClick }) {
+function FilterButtons({ buttons, selected, onClick }) {
return (
);
}
+
+FilterButtons.propTypes = {
+ buttons: PropTypes.arrayOf(
+ PropTypes.shape({
+ label: PropTypes.node,
+ value: PropTypes.any.isRequired,
+ }),
+ ),
+ selected: PropTypes.any,
+ onClick: PropTypes.func,
+};
+
+export default FilterButtons;
diff --git a/components/common/Icon.js b/components/common/Icon.js
index 8a794f61..e9d96eb5 100644
--- a/components/common/Icon.js
+++ b/components/common/Icon.js
@@ -1,8 +1,9 @@
import React from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import styles from './Icon.module.css';
-export default function Icon({ icon, className, size = 'medium', ...props }) {
+function Icon({ icon, className, size = 'medium', ...props }) {
return (
);
}
+
+Icon.propTypes = {
+ className: PropTypes.string,
+ icon: PropTypes.node.isRequired,
+ size: PropTypes.oneOf(['xlarge', 'large', 'medium', 'small', 'xsmall']),
+};
+
+export default Icon;
diff --git a/components/common/Link.js b/components/common/Link.js
index 466e018c..f0fad731 100644
--- a/components/common/Link.js
+++ b/components/common/Link.js
@@ -1,10 +1,11 @@
import React from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import NextLink from 'next/link';
import Icon from './Icon';
import styles from './Link.module.css';
-export default function Link({ className, icon, children, size, iconRight, ...props }) {
+function Link({ className, icon, children, size, iconRight, ...props }) {
return (
);
}
+
+Link.propTypes = {
+ className: PropTypes.string,
+ icon: PropTypes.node,
+ children: PropTypes.node,
+ size: PropTypes.oneOf(['large', 'small', 'xsmall']),
+ iconRight: PropTypes.bool,
+};
+
+export default Link;
diff --git a/components/common/Loading.js b/components/common/Loading.js
index 46e72f17..16d8bb8a 100644
--- a/components/common/Loading.js
+++ b/components/common/Loading.js
@@ -1,8 +1,9 @@
import React from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import styles from './Loading.module.css';
-export default function Loading({ className }) {
+function Loading({ className }) {
return (
@@ -11,3 +12,9 @@ export default function Loading({ className }) {
);
}
+
+Loading.propTypes = {
+ className: PropTypes.string,
+};
+
+export default Loading;
diff --git a/components/common/Menu.js b/components/common/Menu.js
index 6421ba55..91eeee97 100644
--- a/components/common/Menu.js
+++ b/components/common/Menu.js
@@ -1,8 +1,9 @@
import React from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import styles from './Menu.module.css';
-export default function Menu({
+function Menu({
options = [],
selectedOption,
className,
@@ -46,3 +47,24 @@ export default function Menu({
);
}
+
+Menu.propTypes = {
+ options: PropTypes.arrayOf(
+ PropTypes.shape({
+ label: PropTypes.node,
+ value: PropTypes.any,
+ className: PropTypes.string,
+ render: PropTypes.func,
+ divider: PropTypes.bool,
+ }),
+ ),
+ selectedOption: PropTypes.any,
+ className: PropTypes.string,
+ float: PropTypes.oneOf(['top', 'bottom']),
+ align: PropTypes.oneOf(['left', 'right']),
+ optionClassName: PropTypes.string,
+ selectedClassName: PropTypes.string,
+ onSelect: PropTypes.func,
+};
+
+export default Menu;
diff --git a/components/common/MenuButton.js b/components/common/MenuButton.js
index c3e2b0ec..40df2e0c 100644
--- a/components/common/MenuButton.js
+++ b/components/common/MenuButton.js
@@ -1,11 +1,12 @@
import React, { useState, useRef } from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import Menu from 'components/common/Menu';
import Button from 'components/common/Button';
import useDocumentClick from 'hooks/useDocumentClick';
import styles from './MenuButton.module.css';
-export default function MenuButton({
+function MenuButton({
icon,
value,
options,
@@ -58,3 +59,25 @@ export default function MenuButton({
);
}
+
+MenuButton.propTypes = {
+ icon: PropTypes.node,
+ value: PropTypes.any,
+ options: PropTypes.arrayOf(
+ PropTypes.shape({
+ label: PropTypes.node,
+ value: PropTypes.any,
+ className: PropTypes.string,
+ render: PropTypes.func,
+ divider: PropTypes.bool,
+ }),
+ ),
+ buttonClassName: PropTypes.string,
+ menuClassName: PropTypes.string,
+ menuPosition: PropTypes.oneOf(['top', 'bottom']),
+ menuAlign: PropTypes.oneOf(['left', 'right']),
+ onSelect: PropTypes.func,
+ renderValue: PropTypes.func,
+};
+
+export default MenuButton;
diff --git a/components/common/Modal.js b/components/common/Modal.js
index 42df57e2..694fba60 100644
--- a/components/common/Modal.js
+++ b/components/common/Modal.js
@@ -1,9 +1,10 @@
import React from 'react';
+import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { useSpring, animated } from 'react-spring';
import styles from './Modal.module.css';
-export default function Modal({ title, children }) {
+function Modal({ title, children }) {
const props = useSpring({ opacity: 1, from: { opacity: 0 } });
return ReactDOM.createPortal(
@@ -16,3 +17,10 @@ export default function Modal({ title, children }) {
document.getElementById('__modals'),
);
}
+
+Modal.propTypes = {
+ title: PropTypes.node,
+ children: PropTypes.node,
+};
+
+export default Modal;
diff --git a/components/common/NavMenu.js b/components/common/NavMenu.js
index 6cbe7559..82d97fff 100644
--- a/components/common/NavMenu.js
+++ b/components/common/NavMenu.js
@@ -1,9 +1,10 @@
import React from 'react';
+import PropTypes from 'prop-types';
import { useRouter } from 'next/router';
import classNames from 'classnames';
import styles from './NavMenu.module.css';
-export default function NavMenu({ options = [], className, onSelect = () => {} }) {
+function NavMenu({ options = [], className, onSelect = () => {} }) {
const router = useRouter();
return (
@@ -30,3 +31,17 @@ export default function NavMenu({ options = [], className, onSelect = () => {} }
);
}
+
+NavMenu.propTypes = {
+ options: PropTypes.arrayOf(
+ PropTypes.shape({
+ label: PropTypes.node,
+ value: PropTypes.any,
+ className: PropTypes.string,
+ render: PropTypes.func,
+ }),
+ ),
+ className: PropTypes.string,
+ onSelect: PropTypes.func,
+};
+export default NavMenu;
diff --git a/components/common/NoData.js b/components/common/NoData.js
index bb27c18f..9d523437 100644
--- a/components/common/NoData.js
+++ b/components/common/NoData.js
@@ -1,12 +1,19 @@
import React from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import { FormattedMessage } from 'react-intl';
import styles from './NoData.module.css';
-export default function NoData({ className }) {
+function NoData({ className }) {
return (
);
}
+
+NoData.propTypes = {
+ className: PropTypes.string,
+};
+
+export default NoData;
diff --git a/components/common/RefreshButton.js b/components/common/RefreshButton.js
index b1b80a83..a2857522 100644
--- a/components/common/RefreshButton.js
+++ b/components/common/RefreshButton.js
@@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { setDateRange } from 'redux/actions/websites';
@@ -8,7 +9,7 @@ import Dots from 'assets/ellipsis-h.svg';
import useDateRange from 'hooks/useDateRange';
import { getDateRange } from '../../lib/date';
-export default function RefreshButton({ websiteId }) {
+function RefreshButton({ websiteId }) {
const dispatch = useDispatch();
const [dateRange] = useDateRange(websiteId);
const [loading, setLoading] = useState(false);
@@ -35,3 +36,9 @@ export default function RefreshButton({ websiteId }) {
/>
);
}
+
+RefreshButton.propTypes = {
+ websiteId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+};
+
+export default RefreshButton;
diff --git a/components/common/Table.js b/components/common/Table.js
index f0989903..004b5af6 100644
--- a/components/common/Table.js
+++ b/components/common/Table.js
@@ -1,9 +1,10 @@
import React from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import NoData from 'components/common/NoData';
import styles from './Table.module.css';
-export default function Table({
+function Table({
columns,
rows,
empty,
@@ -45,6 +46,34 @@ export default function Table({
);
}
+const styledObject = PropTypes.shape({
+ className: PropTypes.string,
+ style: PropTypes.object,
+});
+
+Table.propTypes = {
+ columns: PropTypes.arrayOf(
+ PropTypes.shape({
+ cell: styledObject,
+ className: PropTypes.string,
+ header: styledObject,
+ key: PropTypes.string,
+ label: PropTypes.node,
+ render: PropTypes.func,
+ style: PropTypes.object,
+ }),
+ ),
+ rows: PropTypes.arrayOf(PropTypes.object),
+ empty: PropTypes.node,
+ className: PropTypes.string,
+ bodyClassName: PropTypes.string,
+ rowKey: PropTypes.func,
+ showHeader: PropTypes.bool,
+ children: PropTypes.node,
+};
+
+export default Table;
+
export const TableRow = ({ columns, row }) => (
{columns.map(({ key, render, className, style, cell }, index) => (
diff --git a/components/common/Tag.js b/components/common/Tag.js
index 29612dca..08589c36 100644
--- a/components/common/Tag.js
+++ b/components/common/Tag.js
@@ -1,7 +1,15 @@
import React from 'react';
+import PropTypes from 'prop-types';
import classNames from 'classnames';
import styles from './Tag.module.css';
-export default function Tag({ className, children }) {
+function Tag({ className, children }) {
return {children};
}
+
+Tag.propTypes = {
+ className: PropTypes.string,
+ children: PropTypes.node,
+};
+
+export default Tag;
diff --git a/components/common/Toast.js b/components/common/Toast.js
index 12787985..e8218766 100644
--- a/components/common/Toast.js
+++ b/components/common/Toast.js
@@ -1,11 +1,12 @@
import React, { useEffect } from 'react';
+import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { useSpring, animated } from 'react-spring';
import styles from './Toast.module.css';
import Icon from 'components/common/Icon';
import Close from 'assets/times.svg';
-export default function Toast({ message, timeout = 3000, onClose }) {
+function Toast({ message, timeout = 3000, onClose }) {
const props = useSpring({
opacity: 1,
transform: 'translate3d(0,0px,0)',
@@ -24,3 +25,11 @@ export default function Toast({ message, timeout = 3000, onClose }) {
document.getElementById('__modals'),
);
}
+
+Toast.propTypes = {
+ message: PropTypes.node,
+ timeout: PropTypes.number,
+ onClose: PropTypes.func,
+};
+
+export default Toast;
diff --git a/components/common/WorldMap.js b/components/common/WorldMap.js
index 7a4a0fda..ee3a0a00 100644
--- a/components/common/WorldMap.js
+++ b/components/common/WorldMap.js
@@ -1,4 +1,5 @@
import React, { useState, useMemo } from 'react';
+import PropTypes from 'prop-types';
import ReactTooltip from 'react-tooltip';
import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps';
import classNames from 'classnames';
@@ -12,7 +13,7 @@ import { useRouter } from 'next/router';
const geoUrl = '/world-110m.json';
-export default function WorldMap({ data, className }) {
+function WorldMap({ data, className }) {
const { basePath } = useRouter();
const [tooltip, setTooltip] = useState();
const [theme] = useTheme();
@@ -89,3 +90,16 @@ export default function WorldMap({ data, className }) {
);
}
+
+WorldMap.propTypes = {
+ data: PropTypes.arrayOf(
+ PropTypes.shape({
+ x: PropTypes.string,
+ y: PropTypes.number,
+ z: PropTypes.number,
+ }),
+ ),
+ className: PropTypes.string,
+};
+
+export default WorldMap;