From 17e07df91a3d3f39ec22f803b99f7685228bf437 Mon Sep 17 00:00:00 2001 From: oneao Date: Tue, 6 Jan 2026 21:49:19 +0800 Subject: [PATCH] u --- code/docs/docusaurus.config.ts | 6 - code/docs/eslint.config.mjs | 3 + code/docs/package.json | 1 + code/docs/pnpm-lock.yaml | 107 ++++++++++++ .../src/components/HomepageFeatures/index.tsx | 44 ++--- .../DropdownNavbarItem/Desktop/index.js | 68 ++++++++ .../DropdownNavbarItem/Desktop/index.tsx | 82 +++++++++ .../DropdownNavbarItem/Mobile/index.js | 136 +++++++++++++++ .../DropdownNavbarItem/Mobile/index.tsx | 159 ++++++++++++++++++ .../Mobile/styles.module.css | 3 + .../NavbarItem/DropdownNavbarItem/index.js | 8 + .../NavbarItem/DropdownNavbarItem/index.tsx | 13 ++ 12 files changed, 604 insertions(+), 26 deletions(-) create mode 100644 code/docs/src/theme/NavbarItem/DropdownNavbarItem/Desktop/index.js create mode 100644 code/docs/src/theme/NavbarItem/DropdownNavbarItem/Desktop/index.tsx create mode 100644 code/docs/src/theme/NavbarItem/DropdownNavbarItem/Mobile/index.js create mode 100644 code/docs/src/theme/NavbarItem/DropdownNavbarItem/Mobile/index.tsx create mode 100644 code/docs/src/theme/NavbarItem/DropdownNavbarItem/Mobile/styles.module.css create mode 100644 code/docs/src/theme/NavbarItem/DropdownNavbarItem/index.js create mode 100644 code/docs/src/theme/NavbarItem/DropdownNavbarItem/index.tsx diff --git a/code/docs/docusaurus.config.ts b/code/docs/docusaurus.config.ts index e545cd6c..5890f2bb 100644 --- a/code/docs/docusaurus.config.ts +++ b/code/docs/docusaurus.config.ts @@ -138,9 +138,3 @@ const config: Config = { } export default config - -/** - * - * - * - */ diff --git a/code/docs/eslint.config.mjs b/code/docs/eslint.config.mjs index bb955f07..956f53da 100644 --- a/code/docs/eslint.config.mjs +++ b/code/docs/eslint.config.mjs @@ -7,4 +7,7 @@ export default antfu({ html: true, markdown: 'prettier', }, + extends: [ + 'plugin:@docusaurus/recommended', + ], }) diff --git a/code/docs/package.json b/code/docs/package.json index 20ed853f..19d20c10 100644 --- a/code/docs/package.json +++ b/code/docs/package.json @@ -28,6 +28,7 @@ }, "devDependencies": { "@antfu/eslint-config": "^6.7.3", + "@docusaurus/eslint-plugin": "^3.9.2", "@docusaurus/module-type-aliases": "3.9.2", "@docusaurus/tsconfig": "3.9.2", "@docusaurus/types": "3.9.2", diff --git a/code/docs/pnpm-lock.yaml b/code/docs/pnpm-lock.yaml index de498cf1..6e2a15db 100644 --- a/code/docs/pnpm-lock.yaml +++ b/code/docs/pnpm-lock.yaml @@ -33,6 +33,9 @@ importers: '@antfu/eslint-config': specifier: ^6.7.3 version: 6.7.3(@eslint-react/eslint-plugin@2.5.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.6.3))(@vue/compiler-sfc@3.5.26)(eslint-plugin-format@1.2.0(eslint@9.39.2(jiti@1.21.7)))(eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@1.21.7)))(eslint-plugin-react-refresh@0.4.26(eslint@9.39.2(jiti@1.21.7)))(eslint@9.39.2(jiti@1.21.7))(typescript@5.6.3) + '@docusaurus/eslint-plugin': + specifier: ^3.9.2 + version: 3.9.2(eslint@9.39.2(jiti@1.21.7))(typescript@5.6.3) '@docusaurus/module-type-aliases': specifier: 3.9.2 version: 3.9.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -1164,6 +1167,12 @@ packages: resolution: {integrity: sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==} engines: {node: '>=20.0'} + '@docusaurus/eslint-plugin@3.9.2': + resolution: {integrity: sha512-LnCrmrR4EtzpSiq6aoSfiY0Lf8P0WslGbBFZJ0olKXJIMxey8dpKevT1K/+tN87Lbn2H/VrdGGSPGlfVKmihAQ==} + engines: {node: '>=20.0'} + peerDependencies: + eslint: '>=6' + '@docusaurus/logger@3.9.2': resolution: {integrity: sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA==} engines: {node: '>=20.0'} @@ -1799,6 +1808,9 @@ packages: '@types/sax@1.2.7': resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + '@types/send@0.17.6': resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} @@ -1850,6 +1862,10 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/scope-manager@5.62.0': + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/scope-manager@8.52.0': resolution: {integrity: sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1867,16 +1883,35 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/types@5.62.0': + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/types@8.52.0': resolution: {integrity: sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@5.62.0': + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/typescript-estree@8.52.0': resolution: {integrity: sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/utils@5.62.0': + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@typescript-eslint/utils@8.52.0': resolution: {integrity: sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1884,6 +1919,10 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/visitor-keys@5.62.0': + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/visitor-keys@8.52.0': resolution: {integrity: sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5588,9 +5627,18 @@ packages: ts-pattern@5.9.0: resolution: {integrity: sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg==} + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsutils@3.21.0: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -7354,6 +7402,15 @@ snapshots: postcss-sort-media-queries: 5.2.0(postcss@8.5.6) tslib: 2.8.1 + '@docusaurus/eslint-plugin@3.9.2(eslint@9.39.2(jiti@1.21.7))(typescript@5.6.3)': + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.6.3) + eslint: 9.39.2(jiti@1.21.7) + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + - typescript + '@docusaurus/logger@3.9.2': dependencies: chalk: 4.1.2 @@ -8572,6 +8629,8 @@ snapshots: dependencies: '@types/node': 17.0.45 + '@types/semver@7.7.1': {} + '@types/send@0.17.6': dependencies: '@types/mime': 1.3.5 @@ -8646,6 +8705,11 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/scope-manager@5.62.0': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + '@typescript-eslint/scope-manager@8.52.0': dependencies: '@typescript-eslint/types': 8.52.0 @@ -8667,8 +8731,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/types@5.62.0': {} + '@typescript-eslint/types@8.52.0': {} + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.6.3)': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.4.3 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.7.3 + tsutils: 3.21.0(typescript@5.6.3) + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/typescript-estree@8.52.0(typescript@5.6.3)': dependencies: '@typescript-eslint/project-service': 8.52.0(typescript@5.6.3) @@ -8684,6 +8764,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@5.62.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) + '@types/json-schema': 7.0.15 + '@types/semver': 7.7.1 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.6.3) + eslint: 9.39.2(jiti@1.21.7) + eslint-scope: 5.1.1 + semver: 7.7.3 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/utils@8.52.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.6.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) @@ -8695,6 +8790,11 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/visitor-keys@5.62.0': + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.52.0': dependencies: '@typescript-eslint/types': 8.52.0 @@ -13052,8 +13152,15 @@ snapshots: ts-pattern@5.9.0: {} + tslib@1.14.1: {} + tslib@2.8.1: {} + tsutils@3.21.0(typescript@5.6.3): + dependencies: + tslib: 1.14.1 + typescript: 5.6.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 diff --git a/code/docs/src/components/HomepageFeatures/index.tsx b/code/docs/src/components/HomepageFeatures/index.tsx index 81178655..85523f45 100644 --- a/code/docs/src/components/HomepageFeatures/index.tsx +++ b/code/docs/src/components/HomepageFeatures/index.tsx @@ -1,18 +1,18 @@ -import type { ReactNode } from "react"; -import clsx from "clsx"; -import Heading from "@theme/Heading"; -import styles from "./styles.module.css"; +import type { ReactNode } from 'react' +import Heading from '@theme/Heading' +import clsx from 'clsx' +import styles from './styles.module.css' -type FeatureItem = { - title: string; - Svg: React.ComponentType>; - description: ReactNode; -}; +interface FeatureItem { + title: string + Svg: React.ComponentType> + description: ReactNode +} const FeatureList: FeatureItem[] = [ { - title: "Easy to Use", - Svg: require("@site/static/img/undraw_docusaurus_mountain.svg").default, + title: 'Easy to Use', + Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, description: ( <> Docusaurus was designed from the ground up to be easily installed and used to get your @@ -21,18 +21,22 @@ const FeatureList: FeatureItem[] = [ ), }, { - title: "Focus on What Matters", - Svg: require("@site/static/img/undraw_docusaurus_tree.svg").default, + title: 'Focus on What Matters', + Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default, description: ( <> Docusaurus lets you focus on your docs, and we'll do the chores. Go ahead and move your - docs into the docs directory. + docs into the + {' '} + docs + {' '} + directory. ), }, { - title: "Powered by React", - Svg: require("@site/static/img/undraw_docusaurus_react.svg").default, + title: 'Powered by React', + Svg: require('@site/static/img/undraw_docusaurus_react.svg').default, description: ( <> Extend or customize your website layout by reusing React. Docusaurus can be extended while @@ -40,11 +44,11 @@ const FeatureList: FeatureItem[] = [ ), }, -]; +] function Feature({ title, Svg, description }: FeatureItem) { return ( -
+
@@ -53,7 +57,7 @@ function Feature({ title, Svg, description }: FeatureItem) {

{description}

- ); + ) } export default function HomepageFeatures(): ReactNode { @@ -67,5 +71,5 @@ export default function HomepageFeatures(): ReactNode { - ); + ) } diff --git a/code/docs/src/theme/NavbarItem/DropdownNavbarItem/Desktop/index.js b/code/docs/src/theme/NavbarItem/DropdownNavbarItem/Desktop/index.js new file mode 100644 index 00000000..bed38861 --- /dev/null +++ b/code/docs/src/theme/NavbarItem/DropdownNavbarItem/Desktop/index.js @@ -0,0 +1,68 @@ +import React, {useState, useRef, useEffect} from 'react'; +import clsx from 'clsx'; +import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink'; +import NavbarItem from '@theme/NavbarItem'; +export default function DropdownNavbarItemDesktop({ + items, + position, + className, + onClick, + ...props +}) { + const dropdownRef = useRef(null); + const [showDropdown, setShowDropdown] = useState(false); + useEffect(() => { + const handleClickOutside = (event) => { + if (!dropdownRef.current || dropdownRef.current.contains(event.target)) { + return; + } + setShowDropdown(false); + }; + document.addEventListener('mousedown', handleClickOutside); + document.addEventListener('touchstart', handleClickOutside); + document.addEventListener('focusin', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener('touchstart', handleClickOutside); + document.removeEventListener('focusin', handleClickOutside); + }; + }, [dropdownRef]); + return ( +
+ tag focusable in case no link target + // See https://github.com/facebook/docusaurus/pull/6003 + // There's probably a better solution though... + href={props.to ? undefined : '#'} + className={clsx('navbar__link', className)} + {...props} + onClick={props.to ? undefined : (e) => e.preventDefault()} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); + setShowDropdown(!showDropdown); + } + }}> + {props.children ?? props.label} + +
    + {items.map((childItemProps, i) => ( + + ))} +
+
+ ); +} diff --git a/code/docs/src/theme/NavbarItem/DropdownNavbarItem/Desktop/index.tsx b/code/docs/src/theme/NavbarItem/DropdownNavbarItem/Desktop/index.tsx new file mode 100644 index 00000000..8e87642f --- /dev/null +++ b/code/docs/src/theme/NavbarItem/DropdownNavbarItem/Desktop/index.tsx @@ -0,0 +1,82 @@ +import type { Props } from '@theme/NavbarItem/DropdownNavbarItem/Desktop' +import type { ReactNode } from 'react' +import NavbarItem from '@theme/NavbarItem' +import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink' +import clsx from 'clsx' +import React, { useEffect, useRef, useState } from 'react' + +export default function DropdownNavbarItemDesktop({ + items, + position, + className, + onClick, + ...props +}: Props): ReactNode { + const dropdownRef = useRef(null) + const [showDropdown, setShowDropdown] = useState(false) + + useEffect(() => { + const handleClickOutside = ( + event: MouseEvent | TouchEvent | FocusEvent, + ) => { + if ( + !dropdownRef.current + || dropdownRef.current.contains(event.target as Node) + ) { + return + } + setShowDropdown(false) + } + + document.addEventListener('mousedown', handleClickOutside) + document.addEventListener('touchstart', handleClickOutside) + document.addEventListener('focusin', handleClickOutside) + + return () => { + document.removeEventListener('mousedown', handleClickOutside) + document.removeEventListener('touchstart', handleClickOutside) + document.removeEventListener('focusin', handleClickOutside) + } + }, [dropdownRef]) + + return ( +
+ tag focusable in case no link target + // See https://github.com/facebook/docusaurus/pull/6003 + // There's probably a better solution though... + href={props.to ? undefined : '#'} + className={clsx('navbar__link', className)} + {...props} + onClick={props.to ? undefined : e => e.preventDefault()} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault() + setShowDropdown(!showDropdown) + } + }} + > + {props.children ?? props.label} + +
    + {items.map((childItemProps, i) => ( + + ))} +
+
+ ) +} diff --git a/code/docs/src/theme/NavbarItem/DropdownNavbarItem/Mobile/index.js b/code/docs/src/theme/NavbarItem/DropdownNavbarItem/Mobile/index.js new file mode 100644 index 00000000..092860e6 --- /dev/null +++ b/code/docs/src/theme/NavbarItem/DropdownNavbarItem/Mobile/index.js @@ -0,0 +1,136 @@ +import React, {useEffect} from 'react'; +import clsx from 'clsx'; +import { + isRegexpStringMatch, + useCollapsible, + Collapsible, +} from '@docusaurus/theme-common'; +import {isSamePath, useLocalPathname} from '@docusaurus/theme-common/internal'; +import {translate} from '@docusaurus/Translate'; +import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink'; +import NavbarItem from '@theme/NavbarItem'; +import styles from './styles.module.css'; +function isItemActive(item, localPathname) { + if (isSamePath(item.to, localPathname)) { + return true; + } + if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) { + return true; + } + if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) { + return true; + } + return false; +} +function containsActiveItems(items, localPathname) { + return items.some((item) => isItemActive(item, localPathname)); +} +function CollapseButton({collapsed, onClick}) { + return ( +