diff --git a/package.json b/package.json
index 5d8fff5e..a483362e 100644
--- a/package.json
+++ b/package.json
@@ -98,7 +98,7 @@
"npm-run-all": "^4.1.5",
"prisma": "5.4.2",
"react": "^18.2.0",
- "react-basics": "^0.106.0",
+ "react-basics": "^0.107.0",
"react-beautiful-dnd": "^13.1.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.4",
diff --git a/src/components/common/HamburgerButton.js b/src/components/common/HamburgerButton.tsx
similarity index 89%
rename from src/components/common/HamburgerButton.js
rename to src/components/common/HamburgerButton.tsx
index 0eddad0f..380392c8 100644
--- a/src/components/common/HamburgerButton.js
+++ b/src/components/common/HamburgerButton.tsx
@@ -3,7 +3,7 @@ import { useState } from 'react';
import MobileMenu from './MobileMenu';
import Icons from 'components/icons';
-export function HamburgerButton({ menuItems }) {
+export function HamburgerButton({ menuItems }: { menuItems: any[] }) {
const [active, setActive] = useState(false);
const handleClick = () => setActive(state => !state);
diff --git a/src/components/common/HoverTooltip.js b/src/components/common/HoverTooltip.tsx
similarity index 82%
rename from src/components/common/HoverTooltip.js
rename to src/components/common/HoverTooltip.tsx
index 614841df..e5e31219 100644
--- a/src/components/common/HoverTooltip.js
+++ b/src/components/common/HoverTooltip.tsx
@@ -1,8 +1,8 @@
-import { useEffect, useState } from 'react';
+import { ReactNode, useEffect, useState } from 'react';
import { Tooltip } from 'react-basics';
import styles from './HoverTooltip.module.css';
-export function HoverTooltip({ children }) {
+export function HoverTooltip({ children }: { children: ReactNode }) {
const [position, setPosition] = useState({ x: -1000, y: -1000 });
useEffect(() => {
diff --git a/src/components/common/LinkButton.tsx b/src/components/common/LinkButton.tsx
index c9366e5c..83d95151 100644
--- a/src/components/common/LinkButton.tsx
+++ b/src/components/common/LinkButton.tsx
@@ -6,7 +6,7 @@ import { ReactNode } from 'react';
export interface LinkButtonProps {
href: string;
- className: string;
+ className?: string;
variant?: string;
scroll?: boolean;
children?: ReactNode;
diff --git a/src/components/common/MobileMenu.js b/src/components/common/MobileMenu.tsx
similarity index 74%
rename from src/components/common/MobileMenu.js
rename to src/components/common/MobileMenu.tsx
index 83a05dff..251085a4 100644
--- a/src/components/common/MobileMenu.js
+++ b/src/components/common/MobileMenu.tsx
@@ -4,12 +4,19 @@ import { usePathname } from 'next/navigation';
import Link from 'next/link';
import styles from './MobileMenu.module.css';
-export function MobileMenu({ items = [], onClose }) {
+export function MobileMenu({
+ items = [],
+ onClose,
+}: {
+ items: any[];
+ className?: string;
+ onClose: () => void;
+}) {
const pathname = usePathname();
- const Items = ({ items, className }) => (
+ const Items = ({ items, className }: { items: any[]; className?: string }) => (
- {items.map(({ label, url, children }) => {
+ {items.map(({ label, url, children }: { label: string; url: string; children: any[] }) => {
const selected = pathname.startsWith(url);
return (
diff --git a/src/components/common/Pager.js b/src/components/common/Pager.tsx
similarity index 86%
rename from src/components/common/Pager.js
rename to src/components/common/Pager.tsx
index a21d35d9..2fe7c6db 100644
--- a/src/components/common/Pager.js
+++ b/src/components/common/Pager.tsx
@@ -3,7 +3,15 @@ import { Button, Icon, Icons } from 'react-basics';
import useMessages from 'components/hooks/useMessages';
import styles from './Pager.module.css';
-export function Pager({ page, pageSize, count, onPageChange, className }) {
+export interface PagerProps {
+ page: number;
+ pageSize: number;
+ count: number;
+ onPageChange: (nextPage: number) => void;
+ className?: string;
+}
+
+export function Pager({ page, pageSize, count, onPageChange, className }: PagerProps) {
const { formatMessage, labels } = useMessages();
const maxPage = pageSize && count ? Math.ceil(count / pageSize) : 0;
const lastPage = page === maxPage;
@@ -13,7 +21,7 @@ export function Pager({ page, pageSize, count, onPageChange, className }) {
return null;
}
- const handlePageChange = value => {
+ const handlePageChange = (value: number) => {
const nextPage = page + value;
if (nextPage > 0 && nextPage <= maxPage) {
onPageChange(nextPage);
diff --git a/src/components/declarations.d.ts b/src/components/declarations.d.ts
index 31e44ff3..81533301 100644
--- a/src/components/declarations.d.ts
+++ b/src/components/declarations.d.ts
@@ -1,2 +1,3 @@
declare module '*.css';
declare module '*.svg';
+declare module '*.json';
diff --git a/src/components/hooks/useConfig.js b/src/components/hooks/useConfig.ts
similarity index 100%
rename from src/components/hooks/useConfig.js
rename to src/components/hooks/useConfig.ts
diff --git a/src/components/hooks/useCountryNames.js b/src/components/hooks/useCountryNames.ts
similarity index 87%
rename from src/components/hooks/useCountryNames.js
rename to src/components/hooks/useCountryNames.ts
index 40611865..22f20666 100644
--- a/src/components/hooks/useCountryNames.js
+++ b/src/components/hooks/useCountryNames.ts
@@ -6,10 +6,10 @@ const countryNames = {
'en-US': enUS,
};
-export function useCountryNames(locale) {
+export function useCountryNames(locale: string) {
const [list, setList] = useState(countryNames[locale] || enUS);
- async function loadData(locale) {
+ async function loadData(locale: string) {
const { data } = await httpGet(`${process.env.basePath}/intl/country/${locale}.json`);
if (data) {
diff --git a/src/components/hooks/useDateRange.js b/src/components/hooks/useDateRange.ts
similarity index 91%
rename from src/components/hooks/useDateRange.js
rename to src/components/hooks/useDateRange.ts
index 1e1b0616..6e70a368 100644
--- a/src/components/hooks/useDateRange.js
+++ b/src/components/hooks/useDateRange.ts
@@ -6,7 +6,7 @@ import websiteStore, { setWebsiteDateRange } from 'store/websites';
import appStore, { setDateRange } from 'store/app';
import useApi from './useApi';
-export function useDateRange(websiteId) {
+export function useDateRange(websiteId: string) {
const { get } = useApi();
const { locale } = useLocale();
const websiteConfig = websiteStore(state => state[websiteId]?.dateRange);
@@ -20,7 +20,7 @@ export function useDateRange(websiteId) {
if (typeof value === 'string') {
if (value === 'all') {
- const result = await get(`/websites/${websiteId}/daterange`);
+ const result: any = await get(`/websites/${websiteId}/daterange`);
const { mindate, maxdate } = result;
const startDate = new Date(mindate);
diff --git a/src/components/hooks/useDocumentClick.js b/src/components/hooks/useDocumentClick.ts
similarity index 77%
rename from src/components/hooks/useDocumentClick.js
rename to src/components/hooks/useDocumentClick.ts
index be3d09be..eefd9366 100644
--- a/src/components/hooks/useDocumentClick.js
+++ b/src/components/hooks/useDocumentClick.ts
@@ -1,6 +1,6 @@
import { useEffect } from 'react';
-export function useDocumentClick(handler) {
+export function useDocumentClick(handler: (event: MouseEvent) => any) {
useEffect(() => {
document.addEventListener('click', handler);
diff --git a/src/components/hooks/useEscapeKey.js b/src/components/hooks/useEscapeKey.js
deleted file mode 100644
index 1a17f18f..00000000
--- a/src/components/hooks/useEscapeKey.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { useEffect, useCallback } from 'react';
-
-export function useEscapeKey(handler) {
- const escFunction = useCallback(event => {
- if (event.keyCode === 27) {
- handler(event);
- }
- }, []);
-
- useEffect(() => {
- document.addEventListener('keydown', escFunction, false);
-
- return () => {
- document.removeEventListener('keydown', escFunction, false);
- };
- }, [escFunction]);
-
- return null;
-}
-
-export default useEscapeKey;
diff --git a/src/components/hooks/useEscapeKey.ts b/src/components/hooks/useEscapeKey.ts
new file mode 100644
index 00000000..5c3350e7
--- /dev/null
+++ b/src/components/hooks/useEscapeKey.ts
@@ -0,0 +1,21 @@
+import { useEffect, useCallback, KeyboardEvent } from 'react';
+
+export function useEscapeKey(handler: (event: KeyboardEvent) => void) {
+ const escFunction = useCallback((event: KeyboardEvent) => {
+ if (event.key === 'Escape') {
+ handler(event);
+ }
+ }, []);
+
+ useEffect(() => {
+ document.addEventListener('keydown', escFunction as any, false);
+
+ return () => {
+ document.removeEventListener('keydown', escFunction as any, false);
+ };
+ }, [escFunction]);
+
+ return null;
+}
+
+export default useEscapeKey;
diff --git a/src/components/hooks/useFilters.js b/src/components/hooks/useFilters.ts
similarity index 100%
rename from src/components/hooks/useFilters.js
rename to src/components/hooks/useFilters.ts
diff --git a/src/components/hooks/useForceUpdate.js b/src/components/hooks/useForceUpdate.ts
similarity index 100%
rename from src/components/hooks/useForceUpdate.js
rename to src/components/hooks/useForceUpdate.ts
diff --git a/src/components/hooks/useFormat.js b/src/components/hooks/useFormat.ts
similarity index 81%
rename from src/components/hooks/useFormat.js
rename to src/components/hooks/useFormat.ts
index 0e609c48..c1160162 100644
--- a/src/components/hooks/useFormat.js
+++ b/src/components/hooks/useFormat.ts
@@ -9,23 +9,23 @@ export function useFormat() {
const { locale } = useLocale();
const countryNames = useCountryNames(locale);
- const formatBrowser = value => {
+ const formatBrowser = (value: string) => {
return BROWSERS[value] || value;
};
- const formatCountry = value => {
+ const formatCountry = (value: string) => {
return countryNames[value] || value;
};
- const formatRegion = value => {
+ const formatRegion = (value: string) => {
return regions[value] ? regions[value] : value;
};
- const formatDevice = value => {
+ const formatDevice = (value: string) => {
return formatMessage(labels[value] || labels.unknown);
};
- const formatValue = (value, type) => {
+ const formatValue = (value: string, type: string) => {
switch (type) {
case 'browser':
return formatBrowser(value);
diff --git a/src/components/hooks/useLanguageNames.js b/src/components/hooks/useLanguageNames.ts
similarity index 100%
rename from src/components/hooks/useLanguageNames.js
rename to src/components/hooks/useLanguageNames.ts
diff --git a/src/components/hooks/useLocale.js b/src/components/hooks/useLocale.ts
similarity index 100%
rename from src/components/hooks/useLocale.js
rename to src/components/hooks/useLocale.ts
diff --git a/src/components/hooks/useMessages.js b/src/components/hooks/useMessages.ts
similarity index 81%
rename from src/components/hooks/useMessages.js
rename to src/components/hooks/useMessages.ts
index e3a6c20b..0801c7d9 100644
--- a/src/components/hooks/useMessages.js
+++ b/src/components/hooks/useMessages.ts
@@ -4,13 +4,13 @@ import { messages, labels } from 'components/messages';
export function useMessages() {
const intl = useIntl();
- const getMessage = id => {
+ const getMessage = (id: string) => {
const message = Object.values(messages).find(value => value.id === id);
return message ? formatMessage(message) : id;
};
- const formatMessage = (descriptor, values, opts) => {
+ const formatMessage = (descriptor: any, values?: any, opts?: any) => {
return descriptor ? intl.formatMessage(descriptor, values, opts) : null;
};
diff --git a/src/components/hooks/useNavigation.js b/src/components/hooks/useNavigation.ts
similarity index 100%
rename from src/components/hooks/useNavigation.js
rename to src/components/hooks/useNavigation.ts
diff --git a/src/components/hooks/useReport.js b/src/components/hooks/useReport.ts
similarity index 94%
rename from src/components/hooks/useReport.js
rename to src/components/hooks/useReport.ts
index 7c698b4e..1686e222 100644
--- a/src/components/hooks/useReport.js
+++ b/src/components/hooks/useReport.ts
@@ -18,7 +18,7 @@ export function useReport(reportId, defaultParameters) {
};
const loadReport = async id => {
- const data = await get(`/reports/${id}`);
+ const data: any = await get(`/reports/${id}`);
const { dateRange } = data?.parameters || {};
const { startDate, endDate } = dateRange || {};
@@ -40,7 +40,7 @@ export function useReport(reportId, defaultParameters) {
const data = await post(`/reports/${type}`, { ...parameters, timezone });
setReport(
- produce(state => {
+ produce((state: any) => {
state.parameters = parameters;
state.data = data;
@@ -56,7 +56,7 @@ export function useReport(reportId, defaultParameters) {
const updateReport = useCallback(
async data => {
setReport(
- produce(state => {
+ produce((state: any) => {
const { parameters, ...rest } = data;
if (parameters) {
diff --git a/src/components/hooks/useReports.js b/src/components/hooks/useReports.ts
similarity index 100%
rename from src/components/hooks/useReports.js
rename to src/components/hooks/useReports.ts
diff --git a/src/components/hooks/useShareToken.js b/src/components/hooks/useShareToken.ts
similarity index 77%
rename from src/components/hooks/useShareToken.js
rename to src/components/hooks/useShareToken.ts
index 5062c73e..088f643e 100644
--- a/src/components/hooks/useShareToken.js
+++ b/src/components/hooks/useShareToken.ts
@@ -1,9 +1,9 @@
import useStore, { setShareToken } from 'store/app';
import useApi from './useApi';
-const selector = state => state.shareToken;
+const selector = (state: { shareToken: string }) => state.shareToken;
-export function useShareToken(shareId) {
+export function useShareToken(shareId: string) {
const shareToken = useStore(selector);
const { get, useQuery } = useApi();
const { isLoading, error } = useQuery(['share', shareId], async () => {
diff --git a/src/components/hooks/useSticky.js b/src/components/hooks/useSticky.ts
similarity index 76%
rename from src/components/hooks/useSticky.js
rename to src/components/hooks/useSticky.ts
index be33f6ed..459c489a 100644
--- a/src/components/hooks/useSticky.js
+++ b/src/components/hooks/useSticky.ts
@@ -5,8 +5,9 @@ export function useSticky({ enabled = true, threshold = 1 }) {
const ref = useRef(null);
useEffect(() => {
- let observer;
- const handler = ([entry]) => setIsSticky(entry.intersectionRatio < threshold);
+ let observer: IntersectionObserver | undefined;
+ const handler: IntersectionObserverCallback = ([entry]) =>
+ setIsSticky(entry.intersectionRatio < threshold);
if (enabled && ref.current) {
observer = new IntersectionObserver(handler, { threshold: [threshold] });
diff --git a/src/components/hooks/useTheme.js b/src/components/hooks/useTheme.ts
similarity index 97%
rename from src/components/hooks/useTheme.js
rename to src/components/hooks/useTheme.ts
index 7e40f601..099bf962 100644
--- a/src/components/hooks/useTheme.js
+++ b/src/components/hooks/useTheme.ts
@@ -4,7 +4,7 @@ import { getItem, setItem } from 'next-basics';
import { THEME_COLORS, THEME_CONFIG } from 'lib/constants';
import { colord } from 'colord';
-const selector = state => state.theme;
+const selector = (state: { theme: string }) => state.theme;
export function useTheme() {
const defaultTheme =
diff --git a/src/components/hooks/useTimezone.js b/src/components/hooks/useTimezone.ts
similarity index 100%
rename from src/components/hooks/useTimezone.js
rename to src/components/hooks/useTimezone.ts
diff --git a/src/components/hooks/useWebsite.js b/src/components/hooks/useWebsite.ts
similarity index 81%
rename from src/components/hooks/useWebsite.js
rename to src/components/hooks/useWebsite.ts
index 5315f0dc..7b68335a 100644
--- a/src/components/hooks/useWebsite.js
+++ b/src/components/hooks/useWebsite.ts
@@ -1,6 +1,6 @@
import useApi from './useApi';
-export function useWebsite(websiteId) {
+export function useWebsite(websiteId: string) {
const { get, useQuery } = useApi();
return useQuery(['websites', websiteId], () => get(`/websites/${websiteId}`), {
enabled: !!websiteId,
diff --git a/tsconfig.json b/tsconfig.json
index 9b8b6033..1807e947 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "target": "es5",
+ "target": "es2021",
"outDir": "./build",
"module": "esnext",
"moduleResolution": "node",
diff --git a/yarn.lock b/yarn.lock
index da4ce1ca..f2ed9264 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7466,10 +7466,10 @@ rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
-react-basics@^0.106.0:
- version "0.106.0"
- resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.106.0.tgz#28ba95a06e6d36adcdb303e1556e6c731b505991"
- integrity sha512-CD1qxFu4wrBeNubNo/SkBfWH0BuTErBueNJCCk04IC3qM9poUr3evYfs2S4sfql7dlorcOJ2GflKC1NJ8qPvmw==
+react-basics@^0.107.0:
+ version "0.107.0"
+ resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.107.0.tgz#e5615792cbb3e4707ba5c8f438b29d6a88cf38b3"
+ integrity sha512-jYnP1z2LTotxXWYwxOBvF26vXxSUBJB0x62YPKkEr1vmJGeg8iOLr8JGF8KE3R6E+NTqzRt6Bmdtt93mjaog4A==
dependencies:
"@react-spring/web" "^9.7.3"
classnames "^2.3.1"