diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml index 3a9f5d0aad..a3e648e5fe 100644 --- a/.github/workflows/ci-release.yml +++ b/.github/workflows/ci-release.yml @@ -12,7 +12,6 @@ concurrency: ${{ github.workflow }}-${{ github.ref }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} permissions: {} @@ -24,6 +23,7 @@ jobs: contents: write # to create release (changesets/action) issues: write # to post issue comments (changesets/action) pull-requests: write # to create pull request (changesets/action) + id-token: write # to request OIDC token for npm Trusted Publishing name: Release runs-on: ubuntu-latest steps: @@ -38,6 +38,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 24 + registry-url: 'https://registry.npmjs.org' - name: Install Dependencies id: install-dependencies run: yarn install @@ -57,4 +58,4 @@ jobs: publish: yarn ci-publish env: GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }} - NPM_TOKEN: ${{ env.NPM_TOKEN }} + NPM_CONFIG_PROVENANCE: true diff --git a/codecov.yml b/codecov.yml index c0384270be..380acef1d2 100644 --- a/codecov.yml +++ b/codecov.yml @@ -3,9 +3,13 @@ coverage: status: project: default: - target: auto - threshold: 2% + target: auto + threshold: 1% + removed_code_behavior: adjust_base + if_ci_failed: error + if_not_found: success patch: default: - target: auto - threshold: 2% + target: auto + threshold: 5% + informational: true diff --git a/examples/react-template/package.json b/examples/react-template/package.json index 520ba25d03..8aaa5e374d 100644 --- a/examples/react-template/package.json +++ b/examples/react-template/package.json @@ -7,15 +7,15 @@ "react-dom": "^18.0.0" }, "devDependencies": { - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^15.0.0", "del-cli": "^5.0.0", - "eslint": "^8.25.0", - "eslint-config-trendmicro": "^3.0.0", - "eslint-plugin-import": "latest", - "eslint-plugin-jsx-a11y": "latest", - "eslint-plugin-react": "latest", - "eslint-plugin-react-hooks": "latest", + "eslint": "^9.26.0", + "eslint-config-trendmicro": "^4.1.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsx-a11y": "^6.10.2", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^7.0.1", "jest-watch-typeahead": "^2.2.1", "react-scripts": "^5.0.1", "web-vitals": "^2.1.4" diff --git a/packages/changelog-github/package.json b/packages/changelog-github/package.json index fe5b8e7b0a..bc9ceee4a2 100644 --- a/packages/changelog-github/package.json +++ b/packages/changelog-github/package.json @@ -33,7 +33,7 @@ "cross-env": "^7.0.3", "del-cli": "^5.0.0", "eslint": "^9.26.0", - "eslint-config-trendmicro": "^4.0.0", + "eslint-config-trendmicro": "^4.4.1", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-react": "^7.37.5", diff --git a/packages/codemod/eslint.config.mjs b/packages/codemod/eslint.config.mjs index 4bb25af094..fb77ed6996 100644 --- a/packages/codemod/eslint.config.mjs +++ b/packages/codemod/eslint.config.mjs @@ -25,7 +25,7 @@ export default defineConfig([ 'build', 'dist', 'node_modules', - '__fixtures__', + '**/__fixtures__/**', ], }, ]); diff --git a/packages/codemod/package.json b/packages/codemod/package.json index 952b03b2f5..ce5fb3d3b6 100644 --- a/packages/codemod/package.json +++ b/packages/codemod/package.json @@ -35,7 +35,7 @@ "@trendmicro/babel-config": "^1.0.2", "del-cli": "^5.0.0", "eslint": "^9.26.0", - "eslint-config-trendmicro": "^4.0.0", + "eslint-config-trendmicro": "^4.4.1", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-react": "^7.37.5", diff --git a/packages/mcp/package.json b/packages/mcp/package.json index 5675be54fa..5b9420dec0 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -65,7 +65,7 @@ "cross-env": "^7.0.3", "del-cli": "^5.0.0", "eslint": "^9.26.0", - "eslint-config-trendmicro": "^4.0.0", + "eslint-config-trendmicro": "^4.4.1", "eslint-import-resolver-typescript": "3.6.3", "eslint-plugin-import": "^2.32.0", "globals": "^15.0.0", diff --git a/packages/mcp/src/__tests__/server.test.ts b/packages/mcp/src/__tests__/server.test.ts index 903e9537f2..cd6dbe7630 100644 --- a/packages/mcp/src/__tests__/server.test.ts +++ b/packages/mcp/src/__tests__/server.test.ts @@ -68,7 +68,7 @@ describe('createMcpServer', () => { The description of the tool contains the available packages, as listed below: - @tonic-ui/react@2.0.0 -1. Pick the most suitable package from the above list, and use that as the \"packages\" argument for this tool's execution, to get the docs content. If it's just one, let it be an array with one package. +1. Pick the most suitable package from the above list, and use that as the "packages" argument for this tool's execution, to get the docs content. If it's just one, let it be an array with one package. 2. Analyze the URLs listed in the content. 3. Then use "fetch-pages" tool to fetch specific documentation pages relevant to the user's question with the subsequent tool call.`); diff --git a/packages/mcp/src/utils.ts b/packages/mcp/src/utils.ts index c252f07f84..d4e4721ae6 100644 --- a/packages/mcp/src/utils.ts +++ b/packages/mcp/src/utils.ts @@ -33,7 +33,7 @@ async function fetchFromUrl(urlString: string): Promise { return content; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - throw new Error(`Failed to fetch ${urlString}: ${errorMessage}`); + throw new Error(`Failed to fetch ${urlString}: ${errorMessage}`, { cause: error }); } } @@ -89,9 +89,7 @@ async function loadFromFilePath( } for (const ext of extensions) { const candidate = filePath + ext; - // eslint-disable-next-line no-await-in-loop if (await exists(candidate)) { - // eslint-disable-next-line no-await-in-loop return await fs.readFile(candidate, 'utf-8'); } } @@ -110,7 +108,7 @@ export function trimTrailingSlashAndWhitespace(url: string | undefined): string if (typeof url !== 'string') { return ''; } - return url.replace(/[\/\s]+$/, ''); + return url.replace(/[\/\s]+$/, ''); // eslint-disable-line no-useless-escape } /** @@ -176,7 +174,6 @@ export async function processUrls( let error; try { - // eslint-disable-next-line no-await-in-loop content = await _processUrl(url); } catch (err) { error = err; diff --git a/packages/react-base/babel.config.js b/packages/react-base/babel.config.js index adb10d5ff6..fec50ba5a1 100644 --- a/packages/react-base/babel.config.js +++ b/packages/react-base/babel.config.js @@ -12,6 +12,23 @@ module.exports = { ], presets: [ '@babel/preset-env', + /** + * @babel/preset-react + * + * - `runtime: 'automatic'` + * Babel auto-injects the JSX runtime import, so JSX files no longer need + * `import React from 'react'`. Named imports are still required for React APIs: + * - `import { useState, useRef, forwardRef, memo } from 'react'` ✅ still needed + * - `import React from 'react'` ❌ not needed + * + * - `importSource: '@emotion/react'` + * Selects which JSX runtime to use: + * - `@emotion/react/jsx-runtime` (with importSource) — enables Emotion's `css` prop + * - `react/jsx-runtime` (default) + * + * These two options are independent. `runtime` removes the need for `import React`; + * `importSource` controls which runtime handles the JSX transform. + */ ['@babel/preset-react', { 'runtime': 'automatic', 'importSource': '@emotion/react', diff --git a/packages/react-base/package.json b/packages/react-base/package.json index ef3369c454..23cfb956fb 100644 --- a/packages/react-base/package.json +++ b/packages/react-base/package.json @@ -46,7 +46,7 @@ "cross-env": "^7.0.3", "del-cli": "^5.0.0", "eslint": "^9.26.0", - "eslint-config-trendmicro": "^4.0.0", + "eslint-config-trendmicro": "^4.4.1", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-react": "^7.37.5", diff --git a/packages/react-base/src/box/__tests__/Box.test.js b/packages/react-base/src/box/__tests__/Box.test.js index c0a6e844bd..2da3eddbc7 100644 --- a/packages/react-base/src/box/__tests__/Box.test.js +++ b/packages/react-base/src/box/__tests__/Box.test.js @@ -1,7 +1,6 @@ import { testA11y } from '@tonic-ui/react-base/test-utils/accessibility'; import { render } from '@tonic-ui/react-base/test-utils/render'; import { Box } from '@tonic-ui/react-base/src'; -import React from 'react'; describe('Box', () => { it('should render correctly', async () => { diff --git a/packages/react-docs/babel.config.js b/packages/react-docs/babel.config.js index adb10d5ff6..fec50ba5a1 100644 --- a/packages/react-docs/babel.config.js +++ b/packages/react-docs/babel.config.js @@ -12,6 +12,23 @@ module.exports = { ], presets: [ '@babel/preset-env', + /** + * @babel/preset-react + * + * - `runtime: 'automatic'` + * Babel auto-injects the JSX runtime import, so JSX files no longer need + * `import React from 'react'`. Named imports are still required for React APIs: + * - `import { useState, useRef, forwardRef, memo } from 'react'` ✅ still needed + * - `import React from 'react'` ❌ not needed + * + * - `importSource: '@emotion/react'` + * Selects which JSX runtime to use: + * - `@emotion/react/jsx-runtime` (with importSource) — enables Emotion's `css` prop + * - `react/jsx-runtime` (default) + * + * These two options are independent. `runtime` removes the need for `import React`; + * `importSource` controls which runtime handles the JSX transform. + */ ['@babel/preset-react', { 'runtime': 'automatic', 'importSource': '@emotion/react', diff --git a/packages/react-docs/components/BaseTable.js b/packages/react-docs/components/BaseTable.js index c6a84c931c..d2473e9e3c 100644 --- a/packages/react-docs/components/BaseTable.js +++ b/packages/react-docs/components/BaseTable.js @@ -20,7 +20,7 @@ import { useTheme, } from '@tonic-ui/react'; import { dataAttr } from '@tonic-ui/utils'; -import React, { Fragment, forwardRef, useEffect, useState } from 'react'; +import { Fragment, forwardRef, useEffect, useState } from 'react'; import AutoSizer from 'react-virtualized-auto-sizer'; /** @@ -148,7 +148,6 @@ const BaseTable = forwardRef(( ); }; - // eslint-disable-next-line react-hooks/incompatible-library const table = useReactTable({ data, columns, @@ -317,8 +316,7 @@ const BaseTable = forwardRef(( > {header.isPlaceholder ? null - : flexRender(header.column.columnDef.header, header.getContext()) - } + : flexRender(header.column.columnDef.header, header.getContext())} ); })} diff --git a/packages/react-docs/components/BorderedBox.js b/packages/react-docs/components/BorderedBox.js index aa4ecf8dd9..98b7971c60 100644 --- a/packages/react-docs/components/BorderedBox.js +++ b/packages/react-docs/components/BorderedBox.js @@ -1,4 +1,3 @@ -import React from 'react'; import { Box, useColorMode } from '@tonic-ui/react'; const BorderedBox = (props) => { diff --git a/packages/react-docs/components/CodeBlock.js b/packages/react-docs/components/CodeBlock.js index b5a7031384..96b43228a9 100644 --- a/packages/react-docs/components/CodeBlock.js +++ b/packages/react-docs/components/CodeBlock.js @@ -9,9 +9,8 @@ import { } from '@tonic-ui/utils'; import useClipboard from '../hooks/useClipboard'; import { ensureString } from 'ensure-type'; -import React from 'react'; import { LiveProvider, LiveEditor } from 'react-live'; -import { themes } from "prism-react-renderer" +import { themes } from 'prism-react-renderer'; const CodeBlock = ({ code: codeProp, language, ...rest }) => { const theme = useTheme(); diff --git a/packages/react-docs/components/ColorPalette.js b/packages/react-docs/components/ColorPalette.js index aaeb995bd4..72bf738eaf 100644 --- a/packages/react-docs/components/ColorPalette.js +++ b/packages/react-docs/components/ColorPalette.js @@ -2,7 +2,6 @@ import { Box, Flex, Stack, useTheme } from '@tonic-ui/react'; import { ensureString, } from 'ensure-type'; -import React from 'react'; const ColorPalette = ({ hue }) => { const theme = useTheme(); diff --git a/packages/react-docs/components/ColorStyleBlock.js b/packages/react-docs/components/ColorStyleBlock.js index 2040433626..ab418d4fbe 100644 --- a/packages/react-docs/components/ColorStyleBlock.js +++ b/packages/react-docs/components/ColorStyleBlock.js @@ -6,7 +6,6 @@ import { useColorMode, useColorStyle, } from '@tonic-ui/react'; -import React from 'react'; const baseWidth = 120; const baseHeight = 120; @@ -69,7 +68,7 @@ const ColorStyleBlock = ({ - {colorLabel && ( + {colorLabel ? ( {colorLabel} - )} + ) : null} {colorTokens.length > 0 && ( <> diff --git a/packages/react-docs/components/ColorStyleBody.js b/packages/react-docs/components/ColorStyleBody.js index e02f497a62..57349e184b 100644 --- a/packages/react-docs/components/ColorStyleBody.js +++ b/packages/react-docs/components/ColorStyleBody.js @@ -9,7 +9,6 @@ import { } from 'ensure-type'; import _get from 'lodash/get'; import _has from 'lodash/has'; -import React from 'react'; import ColorStyleBlock from './ColorStyleBlock'; const baseWidth = 180; diff --git a/packages/react-docs/components/ColorStyleContent.js b/packages/react-docs/components/ColorStyleContent.js index 0806229fc0..aa3ccf77f0 100644 --- a/packages/react-docs/components/ColorStyleContent.js +++ b/packages/react-docs/components/ColorStyleContent.js @@ -2,7 +2,6 @@ import { Box, useColorMode, } from '@tonic-ui/react'; -import React from 'react'; const ColorStyleContent = (props) => { const [colorMode] = useColorMode(); diff --git a/packages/react-docs/components/ColorStyleHeader.js b/packages/react-docs/components/ColorStyleHeader.js index 3303ad1e72..d99bd89190 100644 --- a/packages/react-docs/components/ColorStyleHeader.js +++ b/packages/react-docs/components/ColorStyleHeader.js @@ -3,7 +3,6 @@ import { useColorMode, useColorStyle, } from '@tonic-ui/react'; -import React from 'react'; const ColorStyleHeader = (props) => { const [colorMode] = useColorMode(); diff --git a/packages/react-docs/components/Demo.js b/packages/react-docs/components/Demo.js index 5336e44f58..c8f894580f 100644 --- a/packages/react-docs/components/Demo.js +++ b/packages/react-docs/components/Demo.js @@ -20,8 +20,8 @@ import { merge, } from '@tonic-ui/utils'; import { useRouter } from 'next/router'; -import { themes } from "prism-react-renderer" -import React, { Fragment, useEffect, useCallback, useReducer } from 'react'; +import { themes } from 'prism-react-renderer' +import { Fragment, useEffect, useCallback, useReducer } from 'react'; import { LiveProvider, LiveEditor } from 'react-live'; import useClipboard from '../hooks/useClipboard'; import CodeSandboxIcon from '../icons/CodeSandboxIcon'; @@ -125,8 +125,7 @@ const Demo = ({ diff --git a/packages/react-docs/components/FormGroup.js b/packages/react-docs/components/FormGroup.js index 3071bf9d19..d27e76a169 100644 --- a/packages/react-docs/components/FormGroup.js +++ b/packages/react-docs/components/FormGroup.js @@ -1,5 +1,4 @@ import { Box } from '@tonic-ui/react'; -import React from 'react'; const FormGroup = (props) => ( diff --git a/packages/react-docs/components/GlobalStyles.js b/packages/react-docs/components/GlobalStyles.js index 290cad2173..2e149246b3 100644 --- a/packages/react-docs/components/GlobalStyles.js +++ b/packages/react-docs/components/GlobalStyles.js @@ -4,7 +4,6 @@ import { useColorStyle, useTheme, } from '@tonic-ui/react'; -import React from 'react'; const GlobalStyles = () => { const [colorMode] = useColorMode(); diff --git a/packages/react-docs/components/Header.js b/packages/react-docs/components/Header.js index 78a761c7ec..9400e16a70 100644 --- a/packages/react-docs/components/Header.js +++ b/packages/react-docs/components/Header.js @@ -23,7 +23,7 @@ import { } from '@tonic-ui/react-icons'; import { ensureString } from 'ensure-type'; import NextLink from 'next/link'; -import React, { forwardRef, useCallback, useEffect } from 'react'; +import { forwardRef, useCallback, useEffect } from 'react'; import useTrack from '../hooks/useTrack'; import CodeSandboxIcon from '../icons/CodeSandboxIcon'; import GitHubIcon from '../icons/GitHubIcon'; @@ -158,7 +158,7 @@ const Header = forwardRef(( lg: 'block', }} > - + {(key === version) ? <>{value?.label}✓ - : value?.label - } + : value?.label} ))} @@ -251,7 +250,7 @@ const Header = forwardRef(( handleClickOpenInCodeSandbox()} title="Open in CodeSandbox" sx={{ diff --git a/packages/react-docs/components/IconButton.js b/packages/react-docs/components/IconButton.js index 9b464d3555..9d1da9143f 100644 --- a/packages/react-docs/components/IconButton.js +++ b/packages/react-docs/components/IconButton.js @@ -2,7 +2,7 @@ import { ButtonBase, useColorMode, } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const IconButton = forwardRef((props, ref) => { const [colorMode] = useColorMode(); diff --git a/packages/react-docs/components/InstantSearchInput.js b/packages/react-docs/components/InstantSearchInput.js index 9b14460eea..3038d398b8 100644 --- a/packages/react-docs/components/InstantSearchInput.js +++ b/packages/react-docs/components/InstantSearchInput.js @@ -4,7 +4,7 @@ import { import { callEventHandlers, } from '@tonic-ui/utils'; -import React, { forwardRef, useCallback, useState } from 'react'; +import { forwardRef, useCallback, useState } from 'react'; import { useSearchBox, } from 'react-instantsearch-core'; diff --git a/packages/react-docs/components/InstantSearchModal.js b/packages/react-docs/components/InstantSearchModal.js index c86f7901a2..8808091269 100644 --- a/packages/react-docs/components/InstantSearchModal.js +++ b/packages/react-docs/components/InstantSearchModal.js @@ -7,7 +7,7 @@ import { ModalContent, useTheme, } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; import useTrack from '../hooks/useTrack'; import x from '../utils/json-stringify'; import InstantSearchInput from './InstantSearchInput'; diff --git a/packages/react-docs/components/InstantSearchPagination.js b/packages/react-docs/components/InstantSearchPagination.js index e9af3558d2..d109eab098 100644 --- a/packages/react-docs/components/InstantSearchPagination.js +++ b/packages/react-docs/components/InstantSearchPagination.js @@ -1,7 +1,7 @@ import { Pagination, } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; import { usePagination, } from 'react-instantsearch-core'; diff --git a/packages/react-docs/components/InstantSearchRefinementLink.js b/packages/react-docs/components/InstantSearchRefinementLink.js index 83ea1b74ed..6b09fe2b81 100644 --- a/packages/react-docs/components/InstantSearchRefinementLink.js +++ b/packages/react-docs/components/InstantSearchRefinementLink.js @@ -4,7 +4,7 @@ import { useColorStyle, } from '@tonic-ui/react'; import NextLink from 'next/link'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const InstantSearchRefinementLink = forwardRef((props, ref) => { const [colorMode] = useColorMode(); diff --git a/packages/react-docs/components/InstantSearchRefinementList.js b/packages/react-docs/components/InstantSearchRefinementList.js index bb75cf8227..4d632264f5 100644 --- a/packages/react-docs/components/InstantSearchRefinementList.js +++ b/packages/react-docs/components/InstantSearchRefinementList.js @@ -2,6 +2,7 @@ import { Box, Divider, Flex, + Highlight, Spinner, Stack, Text, @@ -13,8 +14,6 @@ import { } from '@tonic-ui/react-icons'; import { ensureArray, ensureString } from 'ensure-type' import _ from 'lodash'; -import React from 'react'; -import Highlight from 'react-highlight-words'; import { useInstantSearch, } from 'react-instantsearch-core'; @@ -70,11 +69,11 @@ const InstantSearchRefinementList = ( The search is currently unable to proceed. Please resolve the error and try again. - {error && ( + {error ? ( Error: {error.message} - )} + ) : null} ); @@ -137,16 +136,10 @@ const InstantSearchRefinementList = ( href={`/${hit.data.path}`} onClick={handleClickRefinementLinkBy(hit)} > - {Icon && } - + {Icon ? : null} + + {textToHighlight} + diff --git a/packages/react-docs/components/Lorem.js b/packages/react-docs/components/Lorem.js index bd095cc676..62c6dc2891 100644 --- a/packages/react-docs/components/Lorem.js +++ b/packages/react-docs/components/Lorem.js @@ -3,7 +3,7 @@ import { useColorMode, } from '@tonic-ui/react'; import { loremIpsum } from 'lorem-ipsum'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const Lorem = forwardRef(( { diff --git a/packages/react-docs/components/MDXComponents.js b/packages/react-docs/components/MDXComponents.js index 991e7103e0..58b5ff6f44 100644 --- a/packages/react-docs/components/MDXComponents.js +++ b/packages/react-docs/components/MDXComponents.js @@ -7,7 +7,7 @@ import { useColorStyle, } from '@tonic-ui/react'; import { ensureString } from 'ensure-type'; -import React, { isValidElement } from 'react'; +import { isValidElement } from 'react'; import CodeBlock from './CodeBlock'; const ParagraphComponent = props => ( diff --git a/packages/react-docs/components/Main.js b/packages/react-docs/components/Main.js index 2f140c1c9d..5355ba862e 100644 --- a/packages/react-docs/components/Main.js +++ b/packages/react-docs/components/Main.js @@ -1,5 +1,5 @@ import { Box, useColorMode } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const Main = forwardRef(({ children, ...props }, ref) => { const [colorMode] = useColorMode(); diff --git a/packages/react-docs/components/NavLink.js b/packages/react-docs/components/NavLink.js index a93a5ca791..09712c4c29 100644 --- a/packages/react-docs/components/NavLink.js +++ b/packages/react-docs/components/NavLink.js @@ -4,7 +4,7 @@ import { useColorStyle, } from '@tonic-ui/react'; import NextLink from 'next/link'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const NavLink = forwardRef(( { diff --git a/packages/react-docs/components/PreformattedText.js b/packages/react-docs/components/PreformattedText.js index f5e0753730..4a36b1352b 100644 --- a/packages/react-docs/components/PreformattedText.js +++ b/packages/react-docs/components/PreformattedText.js @@ -2,7 +2,6 @@ import { Text, useColorStyle, } from '@tonic-ui/react'; -import React from 'react'; const PreformattedText = (props) => { const [colorStyle] = useColorStyle(); diff --git a/packages/react-docs/components/SearchButton.js b/packages/react-docs/components/SearchButton.js index 64451f4de9..fcac65880b 100644 --- a/packages/react-docs/components/SearchButton.js +++ b/packages/react-docs/components/SearchButton.js @@ -8,7 +8,7 @@ import { import { SearchOIcon, } from '@tonic-ui/react-icons'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const SearchButton = forwardRef(( { diff --git a/packages/react-docs/components/Sidebar.js b/packages/react-docs/components/Sidebar.js index 012109c032..5154bb8987 100644 --- a/packages/react-docs/components/Sidebar.js +++ b/packages/react-docs/components/Sidebar.js @@ -22,7 +22,7 @@ import { import { ensureString } from 'ensure-type'; import NextLink from 'next/link'; import { useRouter } from 'next/router'; -import React, { forwardRef, useEffect, useRef } from 'react'; +import { forwardRef, useEffect, useRef } from 'react'; import { routes } from '../config/sidebar-routes'; import x from '../utils/json-stringify'; import IconButton from './IconButton'; @@ -105,7 +105,7 @@ const Sidebar = forwardRef(( justifyContent="space-between" mb="4x" > - + - Tonic UI + marginRight="2x" + /> + Tonic UI @@ -164,8 +164,7 @@ const Sidebar = forwardRef(( ( diff --git a/packages/react-docs/components/SkeletonContent.js b/packages/react-docs/components/SkeletonContent.js index 4a02931de1..192aa9f72e 100644 --- a/packages/react-docs/components/SkeletonContent.js +++ b/packages/react-docs/components/SkeletonContent.js @@ -3,7 +3,6 @@ import { useColorMode, useColorStyle, } from '@tonic-ui/react'; -import React from 'react'; const SkeletonContent = (props) => { const [colorMode] = useColorMode(); diff --git a/packages/react-docs/components/SourceCode.js b/packages/react-docs/components/SourceCode.js index b9c42dbcd8..852af2e812 100644 --- a/packages/react-docs/components/SourceCode.js +++ b/packages/react-docs/components/SourceCode.js @@ -1,6 +1,5 @@ import { Box, Collapse, LinkButton } from '@tonic-ui/react'; import { useToggle } from '@tonic-ui/react-hooks'; -import React from 'react'; import CodeBlock from '@/components/CodeBlock'; const SourceCode = ({ name, code }) => { diff --git a/packages/react-docs/components/TableOfContents.js b/packages/react-docs/components/TableOfContents.js index 9f77493cd4..a6b8f4086e 100644 --- a/packages/react-docs/components/TableOfContents.js +++ b/packages/react-docs/components/TableOfContents.js @@ -4,10 +4,47 @@ import { } from '@tonic-ui/react'; import { canUseDOM } from '@tonic-ui/utils'; import { useRouter } from 'next/router'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import useThrottledCallbackOnScroll from '../hooks/useThrottledCallbackOnScroll'; import x from '../utils/json-stringify'; - + +const NavList = ({ nodes, activeIndex, handleClick }) => { + return ( + + {nodes.map(node => { + return ( + + + {node.textContent} + + + ); + })} + + ); +}; + +const NavItem = ({ children, nodes, activeIndex, handleClick }) => { + return ( + + {children} + {(nodes.length > 0) && ( + + )} + + ); +}; + const TableOfContents = (props) => { const router = useRouter(); const [nodes, setNodes] = useState([]); @@ -46,7 +83,7 @@ const TableOfContents = (props) => { useEffect(() => { if (!canUseDOM()) { - return null; + return; } setActiveIndex(null); @@ -66,7 +103,6 @@ const TableOfContents = (props) => { }, 200); } } - }, [router.pathname]); // update nodes on routing change const [activeIndex, setActiveIndex] = useState(null); @@ -136,47 +172,12 @@ const TableOfContents = (props) => { }; }, []); - const NavList = ({ nodes }) => { - return ( - - {nodes.map(node => { - return ( - - - {node.textContent} - - - ); - })} - - ); - }; - - const NavItem = ({ children, nodes }) => { - return ( - - {children} - {(nodes.length > 0) && ( - - )} - - ); - }; - return ( Contents - + ); }; diff --git a/packages/react-docs/components/TablePagination.js b/packages/react-docs/components/TablePagination.js index c0ca016ca3..ff7e7a0767 100644 --- a/packages/react-docs/components/TablePagination.js +++ b/packages/react-docs/components/TablePagination.js @@ -1,4 +1,3 @@ -/* eslint-disable react-hooks/set-state-in-effect */ import { Button, ButtonGroup, @@ -19,7 +18,7 @@ import { AngleRightIcon, } from '@tonic-ui/react-icons'; import { ensureArray, ensureFiniteNumber } from 'ensure-type'; -import React, { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; const TablePagination = ({ count, diff --git a/packages/react-docs/components/ThemeParser.js b/packages/react-docs/components/ThemeParser.js index 6a4dd82f35..5468960b4b 100644 --- a/packages/react-docs/components/ThemeParser.js +++ b/packages/react-docs/components/ThemeParser.js @@ -4,7 +4,6 @@ import { useColorStyle, useTheme, } from '@tonic-ui/react'; -import React from 'react'; import PreformattedText from './PreformattedText'; import jsonPrettify from '../utils/json-prettify'; diff --git a/packages/react-docs/components/Toolbar.js b/packages/react-docs/components/Toolbar.js index e9bad3f390..66720257b4 100644 --- a/packages/react-docs/components/Toolbar.js +++ b/packages/react-docs/components/Toolbar.js @@ -1,7 +1,7 @@ import { Flex, } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const Toolbar = forwardRef((props, ref) => { const styleProps = { diff --git a/packages/react-docs/components/ToolbarItem.js b/packages/react-docs/components/ToolbarItem.js index 5d41cd8c98..6f850fb3ae 100644 --- a/packages/react-docs/components/ToolbarItem.js +++ b/packages/react-docs/components/ToolbarItem.js @@ -1,7 +1,7 @@ import { Flex, } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const ToolbarItem = forwardRef((props, ref) => { const styleProps = { @@ -22,4 +22,3 @@ const ToolbarItem = forwardRef((props, ref) => { ToolbarItem.displayName = 'ToolbarItem'; export default ToolbarItem; - diff --git a/packages/react-docs/config/sidebar-routes.js b/packages/react-docs/config/sidebar-routes.js index fd837de584..a8e1a0588f 100644 --- a/packages/react-docs/config/sidebar-routes.js +++ b/packages/react-docs/config/sidebar-routes.js @@ -17,7 +17,6 @@ import { WidgetsIcon, WorkspaceIcon, } from '@tonic-ui/react-icons'; -import React from 'react'; import { MutedText } from '../experiments/muted-text'; export const routes = [ @@ -130,7 +129,7 @@ export const routes = [ ), routes: [ { title: 'Notification', path: 'patterns/notification' }, - { title: 'Table display', path: 'patterns/table-display', }, + { title: 'Table display', path: 'patterns/table-display' }, ], }, { @@ -191,7 +190,7 @@ export const routes = [ path: 'components/button', render: () => { return ( - {`tag: button`}}> + tag: button}> ); @@ -202,7 +201,7 @@ export const routes = [ path: 'components/button-base', render: () => { return ( - {`tag: button`}}> + tag: button}> ); @@ -214,7 +213,7 @@ export const routes = [ path: 'components/checkbox', render: () => { return ( - {`tag: input`}}> + tag: input}> ); @@ -227,7 +226,7 @@ export const routes = [ path: 'components/input', render: () => { return ( - {`tag: input`}}> + tag: input}> ); @@ -238,7 +237,7 @@ export const routes = [ path: 'components/input-base', render: () => { return ( - {`tag: input`}}> + tag: input}> ); @@ -249,7 +248,7 @@ export const routes = [ path: 'components/input-control', render: () => { return ( - {`tag: input`}}> + tag: input}> ); @@ -261,7 +260,7 @@ export const routes = [ path: 'components/link-button', render: () => { return ( - {`tag: button`}}> + tag: button}> ); @@ -272,7 +271,7 @@ export const routes = [ path: 'components/radio', render: () => { return ( - {`tag: input`}}> + tag: input}> ); @@ -284,7 +283,7 @@ export const routes = [ path: 'components/search-input', render: () => { return ( - {`tag: input`}}> + tag: input}> ); @@ -295,7 +294,7 @@ export const routes = [ path: 'components/select', render: () => { return ( - {`tag: select`}}> + tag: select}> ); @@ -306,7 +305,7 @@ export const routes = [ path: 'components/switch', render: () => { return ( - {`tag: input`}}> + tag: input}> ); @@ -317,7 +316,7 @@ export const routes = [ path: 'components/textarea', render: () => { return ( - {`tag: textarea`}}> + tag: textarea}> ); @@ -330,7 +329,7 @@ export const routes = [ path: 'components/icon', render: () => { return ( - {`tag: svg`}}> + tag: svg}> ); @@ -341,7 +340,7 @@ export const routes = [ path: 'components/image', render: () => { return ( - {`tag: img`}}> + tag: img}> ); @@ -352,7 +351,7 @@ export const routes = [ path: 'components/svg-icon', render: () => { return ( - {`tag: svg`}}> + tag: svg}> ); @@ -364,7 +363,7 @@ export const routes = [ path: 'components/link', render: () => { return ( - {`tag: a`}}> + tag: a}> ); @@ -375,7 +374,7 @@ export const routes = [ path: 'components/button-link', render: () => { return ( - {`tag: a`}}> + tag: a}> ); @@ -402,7 +401,7 @@ export const routes = [ path: 'components/code', render: () => { return ( - {`tag: code`}}> + tag: code}> ); @@ -414,7 +413,7 @@ export const routes = [ path: 'components/mark', render: () => { return ( - {`tag: mark`}}> + tag: mark}> ); @@ -426,7 +425,7 @@ export const routes = [ path: 'components/text-label', render: () => { return ( - {`tag: label`}}> + tag: label}> ); @@ -531,7 +530,8 @@ export const routes = [ viewBox="0 0 512.001 512.001" {...props} > - { }); it('uses provided tabIndex when not disabled', () => { + // eslint-disable-next-line jsx-a11y/tabindex-no-positive render(Custom Tab); const button = screen.getByRole('button'); expect(button).toHaveAttribute('tabindex', '2'); diff --git a/packages/react-docs/experiments/dropdown/Dropdown.js b/packages/react-docs/experiments/dropdown/Dropdown.js index 759f763a15..0ea6bc826f 100644 --- a/packages/react-docs/experiments/dropdown/Dropdown.js +++ b/packages/react-docs/experiments/dropdown/Dropdown.js @@ -1,4 +1,4 @@ -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; import DropdownBase from './DropdownBase'; import MenuButtonToggle from './MenuButtonToggle'; diff --git a/packages/react-docs/experiments/dropdown/DropdownBase.js b/packages/react-docs/experiments/dropdown/DropdownBase.js index 790dcc07d5..8467faf27f 100644 --- a/packages/react-docs/experiments/dropdown/DropdownBase.js +++ b/packages/react-docs/experiments/dropdown/DropdownBase.js @@ -8,11 +8,11 @@ import { Submenu, SubmenuTrigger, SubmenuList, - useTheme, } from '@tonic-ui/react'; import { callEventHandlers, isPlainObject, runIfFn } from '@tonic-ui/utils'; -import { ensureArray } from 'ensure-type'; -import React, { Fragment, forwardRef, useCallback } from 'react'; +import { ensureArray, ensureFunction } from 'ensure-type'; +import { Fragment, forwardRef, useCallback } from 'react'; +import { getMenuListStyle } from './styles'; const isValidElementType = (type) => { return ( @@ -22,7 +22,7 @@ const isValidElementType = (type) => { ); }; -const defaultRenderItem = (item, context) => isPlainObject(item) ? item.label : item; +const defaultRenderItem = (item) => (isPlainObject(item) ? item.label : item); const DropdownBase = forwardRef(( { @@ -38,7 +38,6 @@ const DropdownBase = forwardRef(( }, ref, ) => { - const theme = useTheme(); const handleClickBy = useCallback((item) => (event) => { if (event.defaultPrevented) { return; @@ -54,75 +53,79 @@ const DropdownBase = forwardRef(( } }, [onSelect]); - const renderItem = (item) => (typeof renderItemProp === 'function') ? renderItemProp(item) : null; + const renderItem = ensureFunction(renderItemProp); // Recursively render items including groups, dividers, and items - const renderItems = (items, prefix) => { - return ensureArray(items).map((item, index) => { - const key = [prefix, index].filter(x => (x !== null && x !== undefined)).join('_'); + const renderItems = useCallback((items) => { + const _renderItems = (items, { prefix } = {}) => { + return ensureArray(items).map((item, index) => { + const key = [prefix, index].filter(x => (x !== null && x !== undefined)).join('_'); + + if (!isPlainObject(item)) { + return ( + + {renderItem(item)} + + ); + } + + if (item.type === 'custom') { + return ( + + {renderItem(item)} + + ); + } + + if (item.type === 'group') { + return ( + + {_renderItems(item.children, { prefix: key })} + + ); + } + + if (item.type === 'divider') { + return ( + + ); + } + + if (item.type === 'submenu') { + return ( + + + {renderItem(item)} + + + {_renderItems(item.children, { prefix: key })} + + + ); + } + + const { onClick: onClickProp, onKeyDown: onKeyDownProp, ...restItemProps } = { ...item.props }; - if (!isPlainObject(item)) { return ( - + {renderItem(item)} - + ); - } + }); + }; - if (item.type === 'custom') { - return ( - - {renderItem(item)} - - ); - } - - if (item.type === 'group') { - return ( - - {renderItems(item.children, key)} - - ); - } - - if (item.type === 'divider') { - return ( - - ); - } - - if (item.type === 'submenu') { - return ( - - - {renderItem?.(item)} - - - {renderItems(item.children, key)} - - - ); - } - - const { onClick: onClickProp, onKeyDown: onKeyDownProp, ...restItemProps } = { ...item.props }; - - return ( - - {renderItem?.(item)} - - ); - }); - }; + return _renderItems(items); + }, [renderItem, handleClickBy, handleKeyDownBy]); return ( {({ menuToggleRef }) => { - const { fitToggleWidth, ...restContentProps } = { ...slotProps?.content }; - const toggleWidth = menuToggleRef.current?.offsetWidth; - const menuListStyle = { - ...(fitToggleWidth - ? { width: toggleWidth } - : { minWidth: toggleWidth, width: 'max-content', maxWidth: 640 } - ), - ...(portalled && { zIndex: theme?.zIndices?.modal + 1 }), - }; + const toggleWidth = menuToggleRef?.current?.offsetWidth; + const { width: contentWidth, ...contentProps } = { ...slotProps?.content }; + const menuListStyle = getMenuListStyle({ portalled, toggleWidth, contentWidth }); return ( <> @@ -160,16 +157,15 @@ const DropdownBase = forwardRef(( {(typeof renderContent === 'function') ? renderContent({ items, renderItem, renderItems }) - : renderItems(items) - } + : renderItems(items)} ); diff --git a/packages/react-docs/experiments/dropdown/MenuButtonToggle.js b/packages/react-docs/experiments/dropdown/MenuButtonToggle.js index 3f83520e27..dadb7b7f5a 100644 --- a/packages/react-docs/experiments/dropdown/MenuButtonToggle.js +++ b/packages/react-docs/experiments/dropdown/MenuButtonToggle.js @@ -1,5 +1,5 @@ import { MenuButton } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const MenuButtonToggle = forwardRef((props, ref) => { const { children, sx, ...rest } = props; diff --git a/packages/react-docs/experiments/dropdown/TagToggle.js b/packages/react-docs/experiments/dropdown/TagToggle.js index c91cff190f..be0a5eb589 100644 --- a/packages/react-docs/experiments/dropdown/TagToggle.js +++ b/packages/react-docs/experiments/dropdown/TagToggle.js @@ -1,5 +1,5 @@ import { Tag } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const TagToggle = forwardRef((props, ref) => { const { children, sx, ...rest } = props; diff --git a/packages/react-docs/experiments/dropdown/styles.js b/packages/react-docs/experiments/dropdown/styles.js new file mode 100644 index 0000000000..81b2428669 --- /dev/null +++ b/packages/react-docs/experiments/dropdown/styles.js @@ -0,0 +1,38 @@ +// Cap the popup at `40vh` so a long list doesn't extend beyond the viewport. +// Override via `slotProps.content.maxHeight`. +// +// Behavior | minWidth | width | maxWidth | maxHeight | zIndex +// -----------|-------------|-------------------------------|----------|-----------|--------- +// portalled | toggleWidth | contentWidth (passthrough) | 640px | 40vh | popover +// fit-toggle | — | toggleWidth | 640px | 40vh | — +// default | toggleWidth | contentWidth ?? 'max-content' | 640px | 40vh | — +const getMenuListStyle = ({ portalled, contentWidth, toggleWidth }) => { + const base = { + maxHeight: '40vh', + overflowY: 'auto', + maxWidth: 640, + }; + if (portalled) { + return { + ...base, + zIndex: 'popover', + minWidth: toggleWidth, + width: contentWidth, + }; + } + if (contentWidth === 'fit-toggle') { + return { + ...base, + width: toggleWidth, + }; + } + return { + ...base, + minWidth: toggleWidth, + width: contentWidth ?? 'max-content', + }; +}; + +export { + getMenuListStyle, +}; diff --git a/packages/react-docs/experiments/flex-item/FlexItem.js b/packages/react-docs/experiments/flex-item/FlexItem.js index dd462c6591..16eaca1aed 100644 --- a/packages/react-docs/experiments/flex-item/FlexItem.js +++ b/packages/react-docs/experiments/flex-item/FlexItem.js @@ -1,5 +1,5 @@ import { Box, OverflowTooltip } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; import { useFlexItemStyle } from './styles'; const FlexItem = forwardRef(( diff --git a/packages/react-docs/experiments/flex-item/styles.js b/packages/react-docs/experiments/flex-item/styles.js index d4acf3257f..901b1960a4 100644 --- a/packages/react-docs/experiments/flex-item/styles.js +++ b/packages/react-docs/experiments/flex-item/styles.js @@ -2,7 +2,7 @@ const useFlexItemStyle = ({ fixed }) => { return { display: 'block', // Use block display to allow text truncation with ellipsis flex: fixed ? 'none' : 'auto', - maxWidth: fixed ? '100%': undefined, + maxWidth: fixed ? '100%' : undefined, }; }; diff --git a/packages/react-docs/experiments/list/List.js b/packages/react-docs/experiments/list/List.js index 6169e4619a..c26b7cb168 100644 --- a/packages/react-docs/experiments/list/List.js +++ b/packages/react-docs/experiments/list/List.js @@ -1,5 +1,5 @@ import { Box } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const defaultVariant = 'unordered'; diff --git a/packages/react-docs/experiments/list/ListItem.js b/packages/react-docs/experiments/list/ListItem.js index eafcdf1952..f763f72b02 100644 --- a/packages/react-docs/experiments/list/ListItem.js +++ b/packages/react-docs/experiments/list/ListItem.js @@ -1,5 +1,5 @@ import { Box } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const ListItem = forwardRef((props, ref) => { return ( diff --git a/packages/react-docs/experiments/muted-text/MutedText.js b/packages/react-docs/experiments/muted-text/MutedText.js index 28b7ba4107..54f32146e7 100644 --- a/packages/react-docs/experiments/muted-text/MutedText.js +++ b/packages/react-docs/experiments/muted-text/MutedText.js @@ -1,5 +1,5 @@ import { Text, useColorStyle } from '@tonic-ui/react'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; const MutedText = forwardRef((props, ref) => { const [colorStyle] = useColorStyle(); diff --git a/packages/react-docs/experiments/render/Render.js b/packages/react-docs/experiments/render/Render.js index fd19e10ee6..a399b60988 100644 --- a/packages/react-docs/experiments/render/Render.js +++ b/packages/react-docs/experiments/render/Render.js @@ -1,5 +1,5 @@ import { runIfFn } from '@tonic-ui/utils'; -import React, { forwardRef, isValidElement } from 'react'; +import { forwardRef, isValidElement } from 'react'; const Render = forwardRef(( { diff --git a/packages/react-docs/experiments/search-dropdown/SearchDropdown.js b/packages/react-docs/experiments/search-dropdown/SearchDropdown.js index d07cf8c28d..24edcc122d 100644 --- a/packages/react-docs/experiments/search-dropdown/SearchDropdown.js +++ b/packages/react-docs/experiments/search-dropdown/SearchDropdown.js @@ -1,7 +1,7 @@ import { Box, SearchInput } from '@tonic-ui/react'; import { callEventHandlers } from '@tonic-ui/utils'; import { ensureString } from 'ensure-type'; -import React, { forwardRef, useState } from 'react'; +import { forwardRef, useState } from 'react'; import { Dropdown } from '../dropdown'; const SearchDropdown = forwardRef(( diff --git a/packages/react-docs/icons/CodeSandboxIcon.js b/packages/react-docs/icons/CodeSandboxIcon.js index 6a14d31573..669b31619d 100644 --- a/packages/react-docs/icons/CodeSandboxIcon.js +++ b/packages/react-docs/icons/CodeSandboxIcon.js @@ -1,5 +1,4 @@ import { createSVGIcon } from '@tonic-ui/react-icons'; -import React from 'react'; export default createSVGIcon( diff --git a/packages/react-docs/icons/GitHubIcon.js b/packages/react-docs/icons/GitHubIcon.js index 6190711306..d4f8e6aadd 100644 --- a/packages/react-docs/icons/GitHubIcon.js +++ b/packages/react-docs/icons/GitHubIcon.js @@ -1,5 +1,4 @@ import { createSVGIcon } from '@tonic-ui/react-icons'; -import React from 'react'; export default createSVGIcon( diff --git a/packages/react-docs/next.config.mjs b/packages/react-docs/next.config.mjs index 79fb9df8e8..222c225359 100644 --- a/packages/react-docs/next.config.mjs +++ b/packages/react-docs/next.config.mjs @@ -219,10 +219,10 @@ const withMDX = mdxPlugin({ if (renderExpressionCount > 0) { // Insert `import Demo from '../../components/Demo';` to the top of the MDX document - //const relativePath = path.relative(path.dirname(file.path), rootdir); + // const relativePath = path.relative(path.dirname(file.path), rootdir); const newNode = { type: 'mdxjsEsm', - value: `import Demo from "@/components/Demo";`, + value: 'import Demo from "@/components/Demo";', }; newNode.data = { estree: acorn.parse(newNode.value, { diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index e2c178a8ba..f573eac757 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -51,6 +51,7 @@ "ensure-type": "^1.5.1", "eslint": "^9.26.0", "eslint-config-next": "^15.0.0", + "eslint-config-trendmicro": "^4.4.1", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-react": "^7.37.5", diff --git a/packages/react-docs/pages/404.page.js b/packages/react-docs/pages/404.page.js index 68cd84f682..279a672e80 100644 --- a/packages/react-docs/pages/404.page.js +++ b/packages/react-docs/pages/404.page.js @@ -1,5 +1,4 @@ import { Divider, Flex, Text } from '@tonic-ui/react'; -import React from 'react'; export default function Custom404() { return ( diff --git a/packages/react-docs/pages/_app.page.js b/packages/react-docs/pages/_app.page.js index 33c41e390a..5c220ffb3b 100644 --- a/packages/react-docs/pages/_app.page.js +++ b/packages/react-docs/pages/_app.page.js @@ -19,7 +19,7 @@ import algoliasearch from 'algoliasearch/lite'; import { ensureString } from 'ensure-type'; import NextApp from 'next/app'; import { useRouter } from 'next/router'; -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { InstantSearch, Configure } from 'react-instantsearch-core'; import GlobalStyles from '../components/GlobalStyles'; import Header from '../components/Header'; @@ -68,7 +68,7 @@ const App = (props) => { // ``` }, })); - const [initialColorMode, setColorMode] = useState(null); + const [initialColorMode, setInitialColorMode] = useState(null); const router = useRouter(); useEffect(() => { @@ -79,9 +79,8 @@ const App = (props) => { const colorScheme = root.style.getPropertyValue('color-scheme'); root.setAttribute('data-color-scheme', colorScheme); if ((colorScheme === 'dark' || colorScheme === 'light') && (initialColorMode !== colorScheme)) { - setColorMode(colorScheme); + setInitialColorMode(colorScheme); } - // eslint-disable-next-line react-hooks/exhaustive-deps }, []); if (!initialColorMode) { @@ -242,7 +241,7 @@ const DocsPage = (props) => { if (isSidebarVisible) { toggleSidebarVisible(false); } - }, [isMediaQueryMatched]); // eslint-disable-line react-hooks/exhaustive-deps + }, [isMediaQueryMatched]); return ( { const csp = [ - `default-src 'self'`, - `connect-src 'self' http: https:`, + 'default-src \'self\'', + 'connect-src \'self\' http: https:', `script-src 'self' 'unsafe-eval' 'nonce-${nonce}' 'strict-dynamic'`, process.env.NODE_ENV === 'development' - ? `style-src 'self' 'unsafe-inline'` // required for the `dev-build-watcher.js` script + ? 'style-src \'self\' \'unsafe-inline\'' // required for the `dev-build-watcher.js` script : `style-src 'self' 'nonce-${nonce}'`, - `style-src-attr 'self' 'unsafe-inline'`, // required for the color mode script to set the `color-scheme` property on the root element + 'style-src-attr \'self\' \'unsafe-inline\'', // required for the color mode script to set the `color-scheme` property on the root element 'img-src http: https: data:' ].join('; '); @@ -72,23 +71,25 @@ class CustomDocument extends Document { - {(MATOMO_URL && MATOMO_CONTAINER_ID) && ( + {(MATOMO_URL && MATOMO_CONTAINER_ID) ? (