diff --git a/next.config.js b/next.config.js
index 03c30c55..a1e30c36 100644
--- a/next.config.js
+++ b/next.config.js
@@ -11,24 +11,36 @@ const contentSecurityPolicy = [
`connect-src 'self' api.umami.is`,
];
+const cspHeader = (values = []) => ({
+ key: 'Content-Security-Policy',
+ value: values
+ .join(';')
+ .replace(/\s{2,}/g, ' ')
+ .trim(),
+});
+
const headers = [
{
key: 'X-DNS-Prefetch-Control',
value: 'on',
},
- !process.env.ALLOWED_FRAME_URLS && {
+ {
key: 'X-Frame-Options',
value: 'SAMEORIGIN',
},
-].filter(n => n);
+ cspHeader(contentSecurityPolicy),
+];
-const cspHeader = (values = []) => ({
- key: 'Content-Security-Policy',
- value: [...contentSecurityPolicy, ...values]
- .join(';')
- .replace(/\s{2,}/g, ' ')
- .trim(),
-});
+const shareHeaders = [
+ {
+ key: 'X-DNS-Prefetch-Control',
+ value: 'on',
+ },
+ cspHeader([
+ ...contentSecurityPolicy,
+ `frame-ancestors 'self' ${process.env.ALLOWED_FRAME_URLS || ''}`,
+ ]),
+];
if (process.env.FORCE_SSL) {
headers.push({
@@ -127,14 +139,11 @@ const config = {
return [
{
source: '/:path*',
- headers: [
- ...headers,
- cspHeader([`frame-ancestors 'self' ${process.env.ALLOWED_FRAME_URLS || ''}`]),
- ],
+ headers,
},
{
source: '/share/:path*',
- headers: [...headers, cspHeader()],
+ headers: shareHeaders,
},
];
},
diff --git a/package.json b/package.json
index 08038ed7..5d8fff5e 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.105.0",
+ "react-basics": "^0.106.0",
"react-beautiful-dnd": "^13.1.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.4",
@@ -125,9 +125,9 @@
"@rollup/plugin-replace": "^5.0.2",
"@svgr/rollup": "^8.1.0",
"@svgr/webpack": "^8.1.0",
- "@types/node": "^18.11.9",
- "@types/react": "^18.0.25",
- "@types/react-dom": "^18.0.8",
+ "@types/node": "^20.9.0",
+ "@types/react": "^18.2.37",
+ "@types/react-dom": "^18.2.15",
"@typescript-eslint/eslint-plugin": "^6.7.3",
"@typescript-eslint/parser": "^6.7.3",
"cross-env": "^7.0.3",
diff --git a/src/app/(main)/settings/websites/WebsiteAddForm.js b/src/app/(main)/settings/websites/WebsiteAddForm.tsx
similarity index 76%
rename from src/app/(main)/settings/websites/WebsiteAddForm.js
rename to src/app/(main)/settings/websites/WebsiteAddForm.tsx
index 371343ba..99624103 100644
--- a/src/app/(main)/settings/websites/WebsiteAddForm.js
+++ b/src/app/(main)/settings/websites/WebsiteAddForm.tsx
@@ -11,22 +11,22 @@ import useApi from 'components/hooks/useApi';
import { DOMAIN_REGEX } from 'lib/constants';
import useMessages from 'components/hooks/useMessages';
-export function WebsiteAddForm({ onSave, onClose }) {
+export function WebsiteAddForm({ onSave, onClose }: { onSave?: () => void; onClose?: () => void }) {
const { formatMessage, labels, messages } = useMessages();
const { post, useMutation } = useApi();
const { mutate, error, isLoading } = useMutation(data => post('/websites', data));
- const handleSubmit = async data => {
+ const handleSubmit = async (data: any) => {
mutate(data, {
onSuccess: async () => {
- onSave();
- onClose();
+ onSave?.();
+ onClose?.();
},
});
};
return (
-
);
diff --git a/src/components/common/ConfirmDeleteForm.js b/src/components/common/ConfirmDeleteForm.tsx
similarity index 80%
rename from src/components/common/ConfirmDeleteForm.js
rename to src/components/common/ConfirmDeleteForm.tsx
index 3d2c383d..d4cbf203 100644
--- a/src/components/common/ConfirmDeleteForm.js
+++ b/src/components/common/ConfirmDeleteForm.tsx
@@ -2,7 +2,13 @@ import { useState } from 'react';
import { Button, LoadingButton, Form, FormButtons } from 'react-basics';
import useMessages from 'components/hooks/useMessages';
-export function ConfirmDeleteForm({ name, onConfirm, onClose }) {
+export interface ConfirmDeleteFormProps {
+ name: string;
+ onConfirm?: () => void;
+ onClose?: () => void;
+}
+
+export function ConfirmDeleteForm({ name, onConfirm, onClose }: ConfirmDeleteFormProps) {
const [loading, setLoading] = useState(false);
const { formatMessage, labels, messages, FormattedMessage } = useMessages();
diff --git a/src/components/common/Empty.tsx b/src/components/common/Empty.tsx
index 2c7fcd4a..4e2677f8 100644
--- a/src/components/common/Empty.tsx
+++ b/src/components/common/Empty.tsx
@@ -1,6 +1,6 @@
import classNames from 'classnames';
-import styles from './Empty.module.css';
import useMessages from 'components/hooks/useMessages';
+import styles from './Empty.module.css';
export interface EmptyProps {
message?: string;
diff --git a/src/components/common/EmptyPlaceholder.js b/src/components/common/EmptyPlaceholder.tsx
similarity index 78%
rename from src/components/common/EmptyPlaceholder.js
rename to src/components/common/EmptyPlaceholder.tsx
index 8834a1db..27282edc 100644
--- a/src/components/common/EmptyPlaceholder.js
+++ b/src/components/common/EmptyPlaceholder.tsx
@@ -1,6 +1,12 @@
+import { ReactNode } from 'react';
import { Icon, Text, Flexbox } from 'react-basics';
import Logo from 'assets/logo.svg';
+export interface EmptyPlaceholderProps {
+ message: string;
+ children?: ReactNode;
+}
+
export function EmptyPlaceholder({ message, children }) {
return (
diff --git a/src/components/common/ErrorBoundary.js b/src/components/common/ErrorBoundary.tsx
similarity index 78%
rename from src/components/common/ErrorBoundary.js
rename to src/components/common/ErrorBoundary.tsx
index 32cedb39..4eb2700f 100644
--- a/src/components/common/ErrorBoundary.js
+++ b/src/components/common/ErrorBoundary.tsx
@@ -1,14 +1,19 @@
/* eslint-disable no-console */
+import { ErrorInfo, ReactNode } from 'react';
import { ErrorBoundary as Boundary } from 'react-error-boundary';
import { Button } from 'react-basics';
import useMessages from 'components/hooks/useMessages';
import styles from './ErrorBoundry.module.css';
-const logError = (error, info) => {
+const logError = (error: Error, info: ErrorInfo) => {
console.error(error, info.componentStack);
};
-export function ErrorBoundary({ children }) {
+export interface ErrorBoundaryProps {
+ children: ReactNode;
+}
+
+export function ErrorBoundary({ children }: ErrorBoundaryProps) {
const { formatMessage, messages } = useMessages();
const fallbackRender = ({ error, resetErrorBoundary }) => {
diff --git a/src/components/common/ErrorMessage.js b/src/components/common/ErrorMessage.tsx
similarity index 100%
rename from src/components/common/ErrorMessage.js
rename to src/components/common/ErrorMessage.tsx
diff --git a/src/components/common/Favicon.js b/src/components/common/Favicon.tsx
similarity index 93%
rename from src/components/common/Favicon.js
rename to src/components/common/Favicon.tsx
index 55059cc0..2bf43c77 100644
--- a/src/components/common/Favicon.js
+++ b/src/components/common/Favicon.tsx
@@ -1,6 +1,6 @@
import styles from './Favicon.module.css';
-function getHostName(url) {
+function getHostName(url: string) {
const match = url.match(/^(?:https?:\/\/)?(?:[^@\n]+@)?(?:www\.)?([^:/\n?=]+)/im);
return match && match.length > 1 ? match[1] : null;
}
diff --git a/src/components/common/FilterButtons.js b/src/components/common/FilterButtons.js
deleted file mode 100644
index f5a54fb6..00000000
--- a/src/components/common/FilterButtons.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import { ButtonGroup, Button, Flexbox } from 'react-basics';
-
-export function FilterButtons({ items, selectedKey, onSelect }) {
- return (
-
-
- {({ key, label }) => }
-
-
- );
-}
-
-export default FilterButtons;
diff --git a/src/components/common/FilterButtons.tsx b/src/components/common/FilterButtons.tsx
new file mode 100644
index 00000000..e1860c78
--- /dev/null
+++ b/src/components/common/FilterButtons.tsx
@@ -0,0 +1,20 @@
+import { Key } from 'react';
+import { ButtonGroup, Button, Flexbox } from 'react-basics';
+
+export interface FilterButtonsProps {
+ items: any[];
+ selectedKey?: Key;
+ onSelect: () => void;
+}
+
+export function FilterButtons({ items, selectedKey, onSelect }: FilterButtonsProps) {
+ return (
+
+
+ {({ key, label }) => }
+
+
+ );
+}
+
+export default FilterButtons;
diff --git a/src/components/common/FilterLink.js b/src/components/common/FilterLink.tsx
similarity index 79%
rename from src/components/common/FilterLink.js
rename to src/components/common/FilterLink.tsx
index 89648255..f91e1459 100644
--- a/src/components/common/FilterLink.js
+++ b/src/components/common/FilterLink.tsx
@@ -1,3 +1,4 @@
+import { ReactNode } from 'react';
import { Icon, Icons } from 'react-basics';
import classNames from 'classnames';
import Link from 'next/link';
@@ -6,7 +7,23 @@ import useNavigation from 'components/hooks/useNavigation';
import useMessages from 'components/hooks/useMessages';
import styles from './FilterLink.module.css';
-export function FilterLink({ id, value, label, externalUrl, children, className }) {
+export interface FilterLinkProps {
+ id: string;
+ value: string;
+ label: string;
+ externalUrl: string;
+ className: string;
+ children: ReactNode;
+}
+
+export function FilterLink({
+ id,
+ value,
+ label,
+ externalUrl,
+ children,
+ className,
+}: FilterLinkProps) {
const { formatMessage, labels } = useMessages();
const { makeUrl, query } = useNavigation();
const active = query[id] !== undefined;
diff --git a/src/components/common/LinkButton.js b/src/components/common/LinkButton.tsx
similarity index 69%
rename from src/components/common/LinkButton.js
rename to src/components/common/LinkButton.tsx
index a9a8562d..c9366e5c 100644
--- a/src/components/common/LinkButton.js
+++ b/src/components/common/LinkButton.tsx
@@ -2,8 +2,17 @@ import classNames from 'classnames';
import Link from 'next/link';
import { useLocale } from 'components/hooks';
import styles from './LinkButton.module.css';
+import { ReactNode } from 'react';
-export function LinkButton({ href, className, variant, scroll = true, children }) {
+export interface LinkButtonProps {
+ href: string;
+ className: string;
+ variant?: string;
+ scroll?: boolean;
+ children?: ReactNode;
+}
+
+export function LinkButton({ href, className, variant, scroll = true, children }: LinkButtonProps) {
const { dir } = useLocale();
return (
diff --git a/yarn.lock b/yarn.lock
index 6dd8b93b..da4ce1ca 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2393,10 +2393,12 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
-"@types/node@^18.11.9":
- version "18.18.6"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-18.18.6.tgz#26da694f75cdb057750f49d099da5e3f3824cb3e"
- integrity sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==
+"@types/node@^20.9.0":
+ version "20.9.0"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.0.tgz#bfcdc230583aeb891cf51e73cfdaacdd8deae298"
+ integrity sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==
+ dependencies:
+ undici-types "~5.26.4"
"@types/normalize-package-data@^2.4.0":
version "2.4.3"
@@ -2408,10 +2410,10 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.9.tgz#b6f785caa7ea1fe4414d9df42ee0ab67f23d8a6d"
integrity sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==
-"@types/react-dom@^18.0.8":
- version "18.2.14"
- resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.14.tgz#c01ba40e5bb57fc1dc41569bb3ccdb19eab1c539"
- integrity sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==
+"@types/react-dom@^18.2.15":
+ version "18.2.15"
+ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.15.tgz#921af67f9ee023ac37ea84b1bc0cc40b898ea522"
+ integrity sha512-HWMdW+7r7MR5+PZqJF6YFNSCtjz1T0dsvo/f1BV6HkV+6erD/nA7wd9NM00KVG83zf2nJ7uATPO9ttdIPvi3gg==
dependencies:
"@types/react" "*"
@@ -2425,7 +2427,7 @@
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
-"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@^18.0.25":
+"@types/react@*", "@types/react@16 || 17 || 18":
version "18.2.30"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.30.tgz#b84f786864fc46f18545364a54d5e1316308e59b"
integrity sha512-OfqdJnDsSo4UNw0bqAjFCuBpLYQM7wvZidz0hVxHRjrEkzRlvZL1pJVyOSY55HMiKvRNEo9DUBRuEl7FNlJ/Vg==
@@ -2434,6 +2436,15 @@
"@types/scheduler" "*"
csstype "^3.0.2"
+"@types/react@^18.2.37":
+ version "18.2.37"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.37.tgz#0f03af69e463c0f19a356c2660dbca5d19c44cae"
+ integrity sha512-RGAYMi2bhRgEXT3f4B92WTohopH6bIXw05FuGlmJEnv/omEn190+QYEIYxIAuIBdKgboYYdVved2p1AxZVQnaw==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
"@types/resolve@1.20.2":
version "1.20.2"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975"
@@ -7455,10 +7466,10 @@ rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
-react-basics@^0.105.0:
- version "0.105.0"
- resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.105.0.tgz#94eda703b3c0728e817b6e9d086e5d1c6c68f25c"
- integrity sha512-iKYtfB0A2vsmO+X4jaX64XdmHE836w8TG2jFQ0pi5Qp0ktL0lAL9/q0IrWUjNr86hi0apg46aeJWxY+qQO+T1g==
+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==
dependencies:
"@react-spring/web" "^9.7.3"
classnames "^2.3.1"
@@ -8893,6 +8904,11 @@ undici-types@~5.25.1:
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.25.3.tgz#e044115914c85f0bcbb229f346ab739f064998c3"
integrity sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==
+undici-types@~5.26.4:
+ version "5.26.5"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
+ integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
+
unenv@^1.7.4:
version "1.7.4"
resolved "https://registry.yarnpkg.com/unenv/-/unenv-1.7.4.tgz#a0e5a78de2c7c3c4563c06ba9763c96c59db3333"