From f861e6a269ba9f62700776d3cd13b644a9e836d4 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Wed, 20 Sep 2023 16:38:54 +0200 Subject: refactor: use named export for everything except pages Next expect a default export for pages so only those components should use default exports. Everything else should use named exports to reduce the number of import statements. --- src/utils/helpers/author.ts | 3 +- src/utils/helpers/i18n.ts | 49 ------------- src/utils/helpers/images.ts | 3 +- src/utils/helpers/index.ts | 7 ++ src/utils/helpers/pages.ts | 12 +-- src/utils/helpers/projects.ts | 102 -------------------------- src/utils/helpers/rss.ts | 4 +- src/utils/helpers/schema-org.ts | 2 +- src/utils/helpers/server/i18n.ts | 31 ++++++++ src/utils/helpers/server/index.ts | 2 + src/utils/helpers/server/projects.ts | 105 +++++++++++++++++++++++++++ src/utils/hooks/index.ts | 24 ++++++ src/utils/hooks/use-add-classname.tsx | 4 +- src/utils/hooks/use-article.tsx | 24 +++--- src/utils/hooks/use-attributes.tsx | 6 +- src/utils/hooks/use-breadcrumb.tsx | 10 +-- src/utils/hooks/use-comments.tsx | 10 +-- src/utils/hooks/use-data-from-api.tsx | 4 +- src/utils/hooks/use-github-api.tsx | 6 +- src/utils/hooks/use-headings-tree.tsx | 6 +- src/utils/hooks/use-input-autofocus.tsx | 4 +- src/utils/hooks/use-is-mounted.tsx | 4 +- src/utils/hooks/use-local-storage.tsx | 6 +- src/utils/hooks/use-on-click-outside.tsx | 4 +- src/utils/hooks/use-pagination.tsx | 11 +-- src/utils/hooks/use-prism.tsx | 7 +- src/utils/hooks/use-query-selector-all.tsx | 4 +- src/utils/hooks/use-reading-time.tsx | 4 +- src/utils/hooks/use-redirection.tsx | 4 +- src/utils/hooks/use-route-change.tsx | 4 +- src/utils/hooks/use-scroll-position.tsx | 4 +- src/utils/hooks/use-settings.tsx | 6 +- src/utils/hooks/use-state-change.tsx | 4 +- src/utils/hooks/use-styles.tsx | 4 +- src/utils/hooks/use-update-ackee-options.tsx | 6 +- src/utils/providers/index.ts | 2 + src/utils/providers/prism-theme.tsx | 4 +- 37 files changed, 239 insertions(+), 257 deletions(-) delete mode 100644 src/utils/helpers/i18n.ts create mode 100644 src/utils/helpers/index.ts delete mode 100644 src/utils/helpers/projects.ts create mode 100644 src/utils/helpers/server/i18n.ts create mode 100644 src/utils/helpers/server/index.ts create mode 100644 src/utils/helpers/server/projects.ts create mode 100644 src/utils/hooks/index.ts create mode 100644 src/utils/providers/index.ts (limited to 'src/utils') diff --git a/src/utils/helpers/author.ts b/src/utils/helpers/author.ts index 2892524..a5e9bc6 100644 --- a/src/utils/helpers/author.ts +++ b/src/utils/helpers/author.ts @@ -1,5 +1,4 @@ -import { type Author, type ContentKind } from '../../types/app'; -import { type RawAuthor } from '../../types/raw-data'; +import { type Author, type ContentKind, type RawAuthor } from '../../types'; /** * Convert author raw data to regular data. diff --git a/src/utils/helpers/i18n.ts b/src/utils/helpers/i18n.ts deleted file mode 100644 index 35d495e..0000000 --- a/src/utils/helpers/i18n.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { createIntl, createIntlCache, IntlShape } from '@formatjs/intl'; -import { readFile } from 'fs/promises'; -import path from 'path'; -import { settings } from '../config'; - -export type Messages = { [key: string]: string }; - -export const defaultLocale = settings.locales.defaultLocale; - -/** - * Load the translation for the provided locale. - * - * @param currentLocale - The current locale. - * @returns {Promise} The translated strings. - */ -export async function loadTranslation( - currentLocale: string | undefined -): Promise { - const locale: string = currentLocale || defaultLocale; - - const languagePath = path.join(process.cwd(), `lang/${locale}.json`); - - try { - const contents = await readFile(languagePath, 'utf8'); - return JSON.parse(contents); - } catch (error) { - console.error( - 'Error: Could not load compiled language files. Please run `yarn run i18n:compile` first."' - ); - throw error; - } -} - -/** - * Create an Intl object to be used outside components. - * - * @returns {>} The Intl object. - */ -export async function getIntlInstance(): Promise> { - try { - const cache = createIntlCache(); - const messages = await loadTranslation(defaultLocale); - - return createIntl({ locale: defaultLocale, messages }, cache); - } catch (error) { - console.error('Error: Could not create an Intl instance.'); - throw error; - } -} diff --git a/src/utils/helpers/images.ts b/src/utils/helpers/images.ts index bff50c3..6e0c2c5 100644 --- a/src/utils/helpers/images.ts +++ b/src/utils/helpers/images.ts @@ -1,5 +1,4 @@ -import { Image } from '../../types/app'; -import { RawCover } from '../../types/raw-data'; +import { type Image, type RawCover } from '../../types'; /** * Retrieve an Image object from raw data. diff --git a/src/utils/helpers/index.ts b/src/utils/helpers/index.ts new file mode 100644 index 0000000..1a35583 --- /dev/null +++ b/src/utils/helpers/index.ts @@ -0,0 +1,7 @@ +export * from './author'; +export * from './dates'; +export * from './images'; +export * from './pages'; +export * from './rss'; +export * from './schema-org'; +export * from './strings'; diff --git a/src/utils/helpers/pages.ts b/src/utils/helpers/pages.ts index d6d44d2..6b27b6d 100644 --- a/src/utils/helpers/pages.ts +++ b/src/utils/helpers/pages.ts @@ -1,13 +1,13 @@ -import { type Post } from '../../components/organisms/layout/posts-list'; -import { type LinksListItems } from '../../components/organisms/widgets/links-list-widget'; -import { getArticleFromRawData } from '../../services/graphql/articles'; -import { type Article, type PageLink } from '../../types/app'; -import { EdgesResponse } from '../../types/graphql/queries'; +import { type LinksListItems, type Post } from '../../components'; +import { getArticleFromRawData } from '../../services/graphql'; import { + type Article, + type EdgesResponse, + type PageLink, type RawArticle, type RawThematicPreview, type RawTopicPreview, -} from '../../types/raw-data'; +} from '../../types'; import { getImageFromRawData } from './images'; /** diff --git a/src/utils/helpers/projects.ts b/src/utils/helpers/projects.ts deleted file mode 100644 index 0e4de7d..0000000 --- a/src/utils/helpers/projects.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { readdirSync } from 'node:fs'; -import path from 'node:path'; -import { ProjectCard, ProjectPreview } from '../../types/app'; -import { MDXProjectMeta } from '../../types/mdx'; - -/** - * Retrieve all the projects filename. - * - * @returns {string[]} An array of filenames. - */ -export const getProjectFilenames = (): string[] => { - const projectsDirectory = path.join(process.cwd(), 'src/content/projects'); - const filenames = readdirSync(projectsDirectory); - - return filenames.map((filename) => filename.replace(/\.mdx$/, '')); -}; - -/** - * Retrieve the data of a project by filename. - * - * @param {string} filename - The project filename. - * @returns {Promise} - */ -export const getProjectData = async ( - filename: string -): Promise => { - try { - const { - meta, - }: { - meta: MDXProjectMeta; - } = await import(`../../content/projects/${filename}.mdx`); - - const { dates, intro, title, ...projectMeta } = meta; - const { publication, update } = dates; - const cover = await import(`../../../public/projects/${filename}.jpg`); - - return { - id: filename, - intro, - meta: { - ...projectMeta, - dates: { publication, update }, - // Dynamic import source does not work so I use it only to get sizes - cover: { - ...cover.default, - alt: `${title} image`, - src: `/projects/${filename}.jpg`, - title, - }, - }, - slug: filename, - title: title, - }; - } catch (err) { - console.error(err); - throw err; - } -}; - -/** - * Retrieve all the projects data using filenames. - * - * @param {string[]} filenames - The filenames without extension. - * @returns {Promise} - An array of projects data. - */ -export const getProjectsData = async ( - filenames: string[] -): Promise => { - return Promise.all( - filenames.map(async (filename) => { - const { id, meta, slug, title } = await getProjectData(filename); - const { cover, dates, tagline, technologies } = meta; - return { id, meta: { cover, dates, tagline, technologies }, slug, title }; - }) - ); -}; - -/** - * Method to sort an array of projects by publication date. - * - * @param {ProjectCard} a - A single project. - * @param {ProjectCard} b - A single project. - * @returns The result used by Array.sort() method: 1 || -1 || 0. - */ -const sortProjectsByPublicationDate = (a: ProjectCard, b: ProjectCard) => { - if (a.meta.dates.publication < b.meta.dates.publication) return 1; - if (a.meta.dates.publication > b.meta.dates.publication) return -1; - return 0; -}; - -/** - * Retrieve all projects in content folder sorted by publication date. - * - * @returns {Promise} An array of projects. - */ -export const getProjectsCard = async (): Promise => { - const filenames = getProjectFilenames(); - const projects = await getProjectsData(filenames); - - return [...projects].sort(sortProjectsByPublicationDate); -}; diff --git a/src/utils/helpers/rss.ts b/src/utils/helpers/rss.ts index 41a036c..28f3c7b 100644 --- a/src/utils/helpers/rss.ts +++ b/src/utils/helpers/rss.ts @@ -3,8 +3,8 @@ import { getArticleFromRawData, getArticles, getTotalArticles, -} from '../../services/graphql/articles'; -import { Article } from '../../types/app'; +} from '../../services/graphql'; +import { type Article } from '../../types'; import { settings } from '../../utils/config'; /** diff --git a/src/utils/helpers/schema-org.ts b/src/utils/helpers/schema-org.ts index 5d400c8..82f99c2 100644 --- a/src/utils/helpers/schema-org.ts +++ b/src/utils/helpers/schema-org.ts @@ -7,7 +7,7 @@ import { Graph, WebPage, } from 'schema-dts'; -import { Dates } from '../../types/app'; +import { type Dates } from '../../types'; import { settings } from '../../utils/config'; export type GetBlogSchemaProps = { diff --git a/src/utils/helpers/server/i18n.ts b/src/utils/helpers/server/i18n.ts new file mode 100644 index 0000000..dbbc4e5 --- /dev/null +++ b/src/utils/helpers/server/i18n.ts @@ -0,0 +1,31 @@ +import { readFile } from 'fs/promises'; +import path from 'path'; +import { settings } from '../../config'; + +export type Messages = { [key: string]: string }; + +export const defaultLocale = settings.locales.defaultLocale; + +/** + * Load the translation for the provided locale. + * + * @param currentLocale - The current locale. + * @returns {Promise} The translated strings. + */ +export async function loadTranslation( + currentLocale: string | undefined +): Promise { + const locale: string = currentLocale ?? defaultLocale; + + const languagePath = path.join(process.cwd(), `lang/${locale}.json`); + + try { + const contents = await readFile(languagePath, 'utf8'); + return JSON.parse(contents); + } catch (error) { + console.error( + 'Error: Could not load compiled language files. Please run `yarn run i18n:compile` first."' + ); + throw error; + } +} diff --git a/src/utils/helpers/server/index.ts b/src/utils/helpers/server/index.ts new file mode 100644 index 0000000..56ebad5 --- /dev/null +++ b/src/utils/helpers/server/index.ts @@ -0,0 +1,2 @@ +export * from './i18n'; +export * from './projects'; diff --git a/src/utils/helpers/server/projects.ts b/src/utils/helpers/server/projects.ts new file mode 100644 index 0000000..ed73da8 --- /dev/null +++ b/src/utils/helpers/server/projects.ts @@ -0,0 +1,105 @@ +import { readdirSync } from 'fs'; +import path from 'path'; +import { + type MDXProjectMeta, + type ProjectCard, + type ProjectPreview, +} from '../../../types'; + +/** + * Retrieve all the projects filename. + * + * @returns {string[]} An array of filenames. + */ +export const getProjectFilenames = (): string[] => { + const projectsDirectory = path.join(process.cwd(), 'src/content/projects'); + const filenames = readdirSync(projectsDirectory); + + return filenames.map((filename) => filename.replace(/\.mdx$/, '')); +}; + +/** + * Retrieve the data of a project by filename. + * + * @param {string} filename - The project filename. + * @returns {Promise} + */ +export const getProjectData = async ( + filename: string +): Promise => { + try { + const { + meta, + }: { + meta: MDXProjectMeta; + } = await import(`../../../content/projects/${filename}.mdx`); + + const { dates, intro, title, ...projectMeta } = meta; + const { publication, update } = dates; + const cover = await import(`../../../../public/projects/${filename}.jpg`); + + return { + id: filename, + intro, + meta: { + ...projectMeta, + dates: { publication, update }, + // Dynamic import source does not work so I use it only to get sizes + cover: { + ...cover.default, + alt: `${title} image`, + src: `/projects/${filename}.jpg`, + title, + }, + }, + slug: filename, + title: title, + }; + } catch (err) { + console.error(err); + throw err; + } +}; + +/** + * Retrieve all the projects data using filenames. + * + * @param {string[]} filenames - The filenames without extension. + * @returns {Promise} - An array of projects data. + */ +export const getProjectsData = async ( + filenames: string[] +): Promise => { + return Promise.all( + filenames.map(async (filename) => { + const { id, meta, slug, title } = await getProjectData(filename); + const { cover, dates, tagline, technologies } = meta; + return { id, meta: { cover, dates, tagline, technologies }, slug, title }; + }) + ); +}; + +/** + * Method to sort an array of projects by publication date. + * + * @param {ProjectCard} a - A single project. + * @param {ProjectCard} b - A single project. + * @returns The result used by Array.sort() method: 1 || -1 || 0. + */ +const sortProjectsByPublicationDate = (a: ProjectCard, b: ProjectCard) => { + if (a.meta.dates.publication < b.meta.dates.publication) return 1; + if (a.meta.dates.publication > b.meta.dates.publication) return -1; + return 0; +}; + +/** + * Retrieve all projects in content folder sorted by publication date. + * + * @returns {Promise} An array of projects. + */ +export const getProjectsCard = async (): Promise => { + const filenames = getProjectFilenames(); + const projects = await getProjectsData(filenames); + + return [...projects].sort(sortProjectsByPublicationDate); +}; diff --git a/src/utils/hooks/index.ts b/src/utils/hooks/index.ts new file mode 100644 index 0000000..f4357f2 --- /dev/null +++ b/src/utils/hooks/index.ts @@ -0,0 +1,24 @@ +export * from './use-add-classname'; +export * from './use-article'; +export * from './use-attributes'; +export * from './use-breadcrumb'; +export * from './use-comments'; +export * from './use-data-from-api'; +export * from './use-github-api'; +export * from './use-headings-tree'; +export * from './use-input-autofocus'; +export * from './use-is-mounted'; +export * from './use-local-storage'; +export * from './use-mutation-observer'; +export * from './use-on-click-outside'; +export * from './use-pagination'; +export * from './use-prism'; +export * from './use-query-selector-all'; +export * from './use-reading-time'; +export * from './use-redirection'; +export * from './use-route-change'; +export * from './use-scroll-position'; +export * from './use-settings'; +export * from './use-state-change'; +export * from './use-styles'; +export * from './use-update-ackee-options'; diff --git a/src/utils/hooks/use-add-classname.tsx b/src/utils/hooks/use-add-classname.tsx index 0584084..8b0f6d6 100644 --- a/src/utils/hooks/use-add-classname.tsx +++ b/src/utils/hooks/use-add-classname.tsx @@ -11,7 +11,7 @@ export type UseAddClassNameProps = { * * @param {UseAddClassNameProps} props - An object with classnames and one or more elements. */ -const useAddClassName = ({ +export const useAddClassName = ({ className, element, elements, @@ -30,5 +30,3 @@ const useAddClassName = ({ if (elements && elements.length > 0) elements.forEach(setClassName); }, [element, elements, setClassName]); }; - -export default useAddClassName; diff --git a/src/utils/hooks/use-article.tsx b/src/utils/hooks/use-article.tsx index f6512b2..86d8e38 100644 --- a/src/utils/hooks/use-article.tsx +++ b/src/utils/hooks/use-article.tsx @@ -1,23 +1,29 @@ import useSWR from 'swr'; -import { fetchAPI } from '../../services/graphql/api'; -import { getArticleFromRawData } from '../../services/graphql/articles'; -import { articleBySlugQuery } from '../../services/graphql/articles.query'; -import { Article } from '../../types/app'; -import { RawArticle } from '../../types/raw-data'; +import { + articleBySlugQuery, + fetchAPI, + getArticleFromRawData, +} from '../../services/graphql'; +import { type Article, type RawArticle } from '../../types'; export type UseArticleConfig = { + /** + * A fallback article + */ fallback?: Article; + /** + * The article slug + */ slug?: string; }; /** * Retrieve an article by slug. * - * @param {string} slug - The article slug. - * @param {Article} fallback - A fallback article. + * @param {UseArticleConfig} config - The config. * @returns {Article|undefined} The matching article if it exists. */ -const useArticle = ({ +export const useArticle = ({ slug, fallback, }: UseArticleConfig): Article | undefined => { @@ -28,5 +34,3 @@ const useArticle = ({ return data ? getArticleFromRawData(data.post) : fallback; }; - -export default useArticle; diff --git a/src/utils/hooks/use-attributes.tsx b/src/utils/hooks/use-attributes.tsx index 35161ed..20e9947 100644 --- a/src/utils/hooks/use-attributes.tsx +++ b/src/utils/hooks/use-attributes.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect } from 'react'; -import { fromKebabCaseToCamelCase } from '../helpers/strings'; +import { fromKebabCaseToCamelCase } from '../helpers'; export type useAttributesProps = { /** @@ -25,7 +25,7 @@ export type useAttributesProps = { * * @param props - An object with element, attribute name and value. */ -const useAttributes = ({ +export const useAttributes = ({ element, elements, attribute, @@ -48,5 +48,3 @@ const useAttributes = ({ if (elements && elements.length > 0) elements.forEach(setAttribute); }, [element, elements, setAttribute]); }; - -export default useAttributes; diff --git a/src/utils/hooks/use-breadcrumb.tsx b/src/utils/hooks/use-breadcrumb.tsx index dcdf87f..f4506d7 100644 --- a/src/utils/hooks/use-breadcrumb.tsx +++ b/src/utils/hooks/use-breadcrumb.tsx @@ -1,8 +1,8 @@ import { useIntl } from 'react-intl'; import { BreadcrumbList } from 'schema-dts'; -import { BreadcrumbItem } from '../../components/molecules/nav/breadcrumb'; -import { slugify } from '../helpers/strings'; -import useSettings from './use-settings'; +import { BreadcrumbItem } from '../../components'; +import { slugify } from '../helpers'; +import { useSettings } from './use-settings'; export type useBreadcrumbProps = { /** @@ -32,7 +32,7 @@ export type useBreadcrumbReturn = { * @param {useBreadcrumbProps} props - An object (the current page title & url). * @returns {useBreadcrumbReturn} The breadcrumb items and its JSON schema. */ -const useBreadcrumb = ({ +export const useBreadcrumb = ({ title, url, }: useBreadcrumbProps): useBreadcrumbReturn => { @@ -103,5 +103,3 @@ const useBreadcrumb = ({ return { items, schema }; }; - -export default useBreadcrumb; diff --git a/src/utils/hooks/use-comments.tsx b/src/utils/hooks/use-comments.tsx index 8281a86..6ac3d42 100644 --- a/src/utils/hooks/use-comments.tsx +++ b/src/utils/hooks/use-comments.tsx @@ -1,6 +1,6 @@ import useSWR from 'swr'; -import { getAllComments } from '../../services/graphql/comments'; -import { SingleComment } from '../../types/app'; +import { getAllComments } from '../../services/graphql'; +import { SingleComment } from '../../types'; export type UseCommentsConfig = { contentId?: string | number; @@ -13,13 +13,11 @@ export type UseCommentsConfig = { * @param {string | number} contentId - A page/article id. * @returns {SingleComment[]|undefined} */ -const useComments = ({ +export const useComments = ({ contentId, fallback, }: UseCommentsConfig): SingleComment[] | undefined => { const { data } = useSWR(contentId ? { contentId } : null, getAllComments); - return data || fallback; + return data ?? fallback; }; - -export default useComments; diff --git a/src/utils/hooks/use-data-from-api.tsx b/src/utils/hooks/use-data-from-api.tsx index 7082941..5abcf09 100644 --- a/src/utils/hooks/use-data-from-api.tsx +++ b/src/utils/hooks/use-data-from-api.tsx @@ -8,7 +8,7 @@ import { useEffect, useState } from 'react'; * @param fetcher - A function to fetch data from API. * @returns {T | undefined} The requested data. */ -const useDataFromAPI = ( +export const useDataFromAPI = ( fetcher: () => Promise ): T | undefined => { const [data, setData] = useState(); @@ -19,5 +19,3 @@ const useDataFromAPI = ( return data; }; - -export default useDataFromAPI; diff --git a/src/utils/hooks/use-github-api.tsx b/src/utils/hooks/use-github-api.tsx index 56df01f..aa9e3f7 100644 --- a/src/utils/hooks/use-github-api.tsx +++ b/src/utils/hooks/use-github-api.tsx @@ -1,5 +1,5 @@ import useSWR, { Fetcher } from 'swr'; -import { SWRResult } from '../../types/swr'; +import { SWRResult } from '../../types'; export type RepoData = { created_at: string; @@ -16,7 +16,7 @@ const fetcher: Fetcher = (...args) => * @param repo - The Github repo (`owner/repo-name`). * @returns The repository data. */ -const useGithubApi = (repo: string): SWRResult => { +export const useGithubApi = (repo: string): SWRResult => { const apiUrl = repo ? `https://api.github.com/repos/${repo}` : null; const { data, error } = useSWR(apiUrl, fetcher); @@ -26,5 +26,3 @@ const useGithubApi = (repo: string): SWRResult => { isError: error, }; }; - -export default useGithubApi; diff --git a/src/utils/hooks/use-headings-tree.tsx b/src/utils/hooks/use-headings-tree.tsx index 0dc077e..049ab29 100644 --- a/src/utils/hooks/use-headings-tree.tsx +++ b/src/utils/hooks/use-headings-tree.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; -import { slugify } from '../helpers/strings'; +import { slugify } from '../helpers'; import { useMutationObserver } from './use-mutation-observer'; export type Heading = { @@ -27,7 +27,7 @@ export type Heading = { * @param {HTMLElement} wrapper - An HTML element that contains the headings. * @returns {Heading[]} The headings tree. */ -const useHeadingsTree = (wrapper: HTMLElement): Heading[] => { +export const useHeadingsTree = (wrapper: HTMLElement): Heading[] => { const depths = useMemo(() => ['h2', 'h3', 'h4', 'h5', 'h6'], []); const [allHeadings, setAllHeadings] = useState>(); @@ -160,5 +160,3 @@ const useHeadingsTree = (wrapper: HTMLElement): Heading[] => { return headingsTree; }; - -export default useHeadingsTree; diff --git a/src/utils/hooks/use-input-autofocus.tsx b/src/utils/hooks/use-input-autofocus.tsx index c7700e9..d0fcd06 100644 --- a/src/utils/hooks/use-input-autofocus.tsx +++ b/src/utils/hooks/use-input-autofocus.tsx @@ -18,7 +18,7 @@ export type UseInputAutofocusProps = { /** * Set focus on an input with an optional delay. */ -const useInputAutofocus = ({ +export const useInputAutofocus = ({ condition, delay = 0, ref, @@ -35,5 +35,3 @@ const useInputAutofocus = ({ }; }, [condition, delay, ref]); }; - -export default useInputAutofocus; diff --git a/src/utils/hooks/use-is-mounted.tsx b/src/utils/hooks/use-is-mounted.tsx index ca79afb..4d85d45 100644 --- a/src/utils/hooks/use-is-mounted.tsx +++ b/src/utils/hooks/use-is-mounted.tsx @@ -6,7 +6,7 @@ import { RefObject, useEffect, useState } from 'react'; * @param {RefObject} ref - A React reference to an HTML element. * @returns {boolean} True if the HTML element is mounted. */ -const useIsMounted = (ref: RefObject) => { +export const useIsMounted = (ref: RefObject): boolean => { const [isMounted, setIsMounted] = useState(false); useEffect(() => { @@ -15,5 +15,3 @@ const useIsMounted = (ref: RefObject) => { return isMounted; }; - -export default useIsMounted; diff --git a/src/utils/hooks/use-local-storage.tsx b/src/utils/hooks/use-local-storage.tsx index 1809e07..0f9fbb6 100644 --- a/src/utils/hooks/use-local-storage.tsx +++ b/src/utils/hooks/use-local-storage.tsx @@ -13,14 +13,14 @@ export type UseLocalStorageReturn = { * @param {T} [fallbackValue] - A fallback value if local storage is empty. * @returns {UseLocalStorageReturn} An object with value and setValue. */ -const useLocalStorage = ( +export const useLocalStorage = ( key: string, fallbackValue: T ): UseLocalStorageReturn => { const getInitialValue = () => { if (typeof window === 'undefined') return fallbackValue; const storedValue = LocalStorage.get(key); - return storedValue || fallbackValue; + return storedValue ?? fallbackValue; }; const [value, setValue] = useState(getInitialValue); @@ -31,5 +31,3 @@ const useLocalStorage = ( return { value, setValue }; }; - -export default useLocalStorage; diff --git a/src/utils/hooks/use-on-click-outside.tsx b/src/utils/hooks/use-on-click-outside.tsx index 04827b8..b810ddc 100644 --- a/src/utils/hooks/use-on-click-outside.tsx +++ b/src/utils/hooks/use-on-click-outside.tsx @@ -9,7 +9,7 @@ export type UseOnClickOutsideCallback = (target: Node) => void; * @param {boolean} useCapture - Define event propagation method. Default: true. * @returns {RefObject} A React reference object. */ -const useOnClickOutside = ( +export const useOnClickOutside = ( callback: UseOnClickOutsideCallback, useCapture: boolean = true ): RefObject => { @@ -48,5 +48,3 @@ const useOnClickOutside = ( return ref; }; - -export default useOnClickOutside; diff --git a/src/utils/hooks/use-pagination.tsx b/src/utils/hooks/use-pagination.tsx index f47a674..706e656 100644 --- a/src/utils/hooks/use-pagination.tsx +++ b/src/utils/hooks/use-pagination.tsx @@ -1,6 +1,9 @@ import useSWRInfinite, { SWRInfiniteKeyLoader } from 'swr/infinite'; -import { GraphQLEdgesInput } from '../../types/graphql/generics'; -import { EdgesResponse, Search } from '../../types/graphql/queries'; +import { + type EdgesResponse, + type GraphQLEdgesInput, + type Search, +} from '../../types'; export type UsePaginationProps = { /** @@ -66,7 +69,7 @@ export type UsePaginationReturn = { * @param {UsePaginationProps} props - The pagination configuration. * @returns {UsePaginationReturn} An object with pagination data and helpers. */ -const usePagination = ({ +export const usePagination = ({ fallbackData, fetcher, perPage, @@ -114,5 +117,3 @@ const usePagination = ({ setSize, }; }; - -export default usePagination; diff --git a/src/utils/hooks/use-prism.tsx b/src/utils/hooks/use-prism.tsx index 05790a3..429808f 100644 --- a/src/utils/hooks/use-prism.tsx +++ b/src/utils/hooks/use-prism.tsx @@ -111,7 +111,10 @@ const loadPrismPlugins = async (plugins: PrismPlugin[]) => { * @param {UsePrismProps} props - An object of options. * @returns {UsePrismReturn} An object of data. */ -const usePrism = ({ language, plugins }: UsePrismProps): UsePrismReturn => { +export const usePrism = ({ + language, + plugins, +}: UsePrismProps): UsePrismReturn => { /** * The order matter. Toolbar must be loaded before some other plugins. */ @@ -178,5 +181,3 @@ const usePrism = ({ language, plugins }: UsePrismProps): UsePrismReturn => { className, }; }; - -export default usePrism; diff --git a/src/utils/hooks/use-query-selector-all.tsx b/src/utils/hooks/use-query-selector-all.tsx index 6ac8a08..a3650ea 100644 --- a/src/utils/hooks/use-query-selector-all.tsx +++ b/src/utils/hooks/use-query-selector-all.tsx @@ -7,7 +7,7 @@ import { useEffect, useState } from 'react'; * @param {string} query - A query. * @returns {NodeListOf} - The node list. */ -const useQuerySelectorAll = ( +export const useQuerySelectorAll = ( query: string ): NodeListOf | undefined => { const [elements, setElements] = @@ -20,5 +20,3 @@ const useQuerySelectorAll = ( return elements; }; - -export default useQuerySelectorAll; diff --git a/src/utils/hooks/use-reading-time.tsx b/src/utils/hooks/use-reading-time.tsx index fb54135..3a812f6 100644 --- a/src/utils/hooks/use-reading-time.tsx +++ b/src/utils/hooks/use-reading-time.tsx @@ -6,7 +6,7 @@ import { useIntl } from 'react-intl'; * @param {number} wordsCount - The number of words. * @returns {string} The estimated reading time. */ -const useReadingTime = ( +export const useReadingTime = ( wordsCount: number, onlyMinutes: boolean = false ): string => { @@ -54,5 +54,3 @@ const useReadingTime = ( ); } }; - -export default useReadingTime; diff --git a/src/utils/hooks/use-redirection.tsx b/src/utils/hooks/use-redirection.tsx index 9eb26c2..5a677e2 100644 --- a/src/utils/hooks/use-redirection.tsx +++ b/src/utils/hooks/use-redirection.tsx @@ -22,12 +22,10 @@ export type UseRedirectionProps = { * * @param {UseRedirectionProps} props - The redirection parameters. */ -const useRedirection = ({ query, redirectTo }: UseRedirectionProps) => { +export const useRedirection = ({ query, redirectTo }: UseRedirectionProps) => { const router = useRouter(); useEffect(() => { if (router.query[query.param] === query.value) router.push(redirectTo); }, [query, redirectTo, router]); }; - -export default useRedirection; diff --git a/src/utils/hooks/use-route-change.tsx b/src/utils/hooks/use-route-change.tsx index 82e01a1..2eff6e9 100644 --- a/src/utils/hooks/use-route-change.tsx +++ b/src/utils/hooks/use-route-change.tsx @@ -1,12 +1,10 @@ import { useRouter } from 'next/router'; import { useEffect } from 'react'; -const useRouteChange = (callback: () => void) => { +export const useRouteChange = (callback: () => void) => { const { events } = useRouter(); useEffect(() => { events.on('routeChangeStart', callback); }, [events, callback]); }; - -export default useRouteChange; diff --git a/src/utils/hooks/use-scroll-position.tsx b/src/utils/hooks/use-scroll-position.tsx index 47cfdd0..c6ae9fd 100644 --- a/src/utils/hooks/use-scroll-position.tsx +++ b/src/utils/hooks/use-scroll-position.tsx @@ -5,11 +5,9 @@ import { useEffect } from 'react'; * * @param scrollHandler - A callback function. */ -const useScrollPosition = (scrollHandler: () => void) => { +export const useScrollPosition = (scrollHandler: () => void) => { useEffect(() => { window.addEventListener('scroll', scrollHandler); return () => window.removeEventListener('scroll', scrollHandler); }, [scrollHandler]); }; - -export default useScrollPosition; diff --git a/src/utils/hooks/use-settings.tsx b/src/utils/hooks/use-settings.tsx index edb5b5e..968930d 100644 --- a/src/utils/hooks/use-settings.tsx +++ b/src/utils/hooks/use-settings.tsx @@ -67,11 +67,11 @@ export type UseSettingsReturn = { * * @returns {UseSettingsReturn} - An object describing settings. */ -const useSettings = (): UseSettingsReturn => { +export const useSettings = (): UseSettingsReturn => { const { baseline, copyright, email, locales, name, postsPerPage, url } = settings; const router = useRouter(); - const locale = router.locale || locales.defaultLocale; + const locale = router.locale ?? locales.defaultLocale; return { blog: { @@ -93,5 +93,3 @@ const useSettings = (): UseSettingsReturn => { }, }; }; - -export default useSettings; diff --git a/src/utils/hooks/use-state-change.tsx b/src/utils/hooks/use-state-change.tsx index 063fb8e..59ae0df 100644 --- a/src/utils/hooks/use-state-change.tsx +++ b/src/utils/hooks/use-state-change.tsx @@ -6,7 +6,7 @@ import { useEffect, useState } from 'react'; * @param initial - The initial value. * @returns The state and a setter. */ -const useStateChange = (initial: T) => { +export const useStateChange = (initial: T) => { const [state, setState] = useState(initial); useEffect(() => { @@ -15,5 +15,3 @@ const useStateChange = (initial: T) => { return [state, setState] as const; }; - -export default useStateChange; diff --git a/src/utils/hooks/use-styles.tsx b/src/utils/hooks/use-styles.tsx index d47e9fb..a70087b 100644 --- a/src/utils/hooks/use-styles.tsx +++ b/src/utils/hooks/use-styles.tsx @@ -20,10 +20,8 @@ export type UseStylesProps = { * * @param {UseStylesProps} props - An object with property, styles and target. */ -const useStyles = ({ property, styles, target }: UseStylesProps) => { +export const useStyles = ({ property, styles, target }: UseStylesProps) => { useEffect(() => { if (target.current) target.current.style.setProperty(property, styles); }, [property, styles, target]); }; - -export default useStyles; diff --git a/src/utils/hooks/use-update-ackee-options.tsx b/src/utils/hooks/use-update-ackee-options.tsx index 1901588..f6e5c86 100644 --- a/src/utils/hooks/use-update-ackee-options.tsx +++ b/src/utils/hooks/use-update-ackee-options.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { useAckeeTracker } from '../providers/ackee'; +import { useAckeeTracker } from '../providers'; export type AckeeOptions = 'full' | 'partial'; @@ -8,12 +8,10 @@ export type AckeeOptions = 'full' | 'partial'; * * @param {AckeeOptions} value - Either `full` or `partial`. */ -const useUpdateAckeeOptions = (value: AckeeOptions) => { +export const useUpdateAckeeOptions = (value: AckeeOptions) => { const { setDetailed } = useAckeeTracker(); useEffect(() => { setDetailed(value === 'full'); }, [value, setDetailed]); }; - -export default useUpdateAckeeOptions; diff --git a/src/utils/providers/index.ts b/src/utils/providers/index.ts new file mode 100644 index 0000000..43641a1 --- /dev/null +++ b/src/utils/providers/index.ts @@ -0,0 +1,2 @@ +export * from './ackee'; +export * from './prism-theme'; diff --git a/src/utils/providers/prism-theme.tsx b/src/utils/providers/prism-theme.tsx index 6ecbb1d..c063bd5 100644 --- a/src/utils/providers/prism-theme.tsx +++ b/src/utils/providers/prism-theme.tsx @@ -7,9 +7,7 @@ import { useEffect, useState, } from 'react'; -import useAttributes from '../hooks/use-attributes'; -import useLocalStorage from '../hooks/use-local-storage'; -import useQuerySelectorAll from '../hooks/use-query-selector-all'; +import { useAttributes, useLocalStorage, useQuerySelectorAll } from '../hooks'; export type PrismTheme = 'dark' | 'light' | 'system'; export type ResolvedPrismTheme = Exclude; -- cgit v1.2.3