| | |
| | | 'use client' |
| | | |
| | | import { useEffect, useMemo, useState } from 'react' |
| | | import { useEffect, useState } from 'react' |
| | | import { useContext } from 'use-context-selector' |
| | | import { useTranslation } from 'react-i18next' |
| | | import { RiListUnordered } from '@remixicon/react' |
| | | import TemplateEn from './template/template.en.mdx' |
| | | import TemplateZh from './template/template.zh.mdx' |
| | | import TemplateJa from './template/template.ja.mdx' |
| | | import I18n from '@/context/i18n' |
| | | import { LanguagesSupported } from '@/i18n/language' |
| | | import useTheme from '@/hooks/use-theme' |
| | | import { Theme } from '@/types/app' |
| | | import cn from '@/utils/classnames' |
| | | |
| | | type DocProps = { |
| | | apiBaseUrl: string |
| | |
| | | const { t } = useTranslation() |
| | | const [toc, setToc] = useState<Array<{ href: string; text: string }>>([]) |
| | | const [isTocExpanded, setIsTocExpanded] = useState(false) |
| | | const { theme } = useTheme() |
| | | |
| | | // Set initial TOC expanded state based on screen width |
| | | useEffect(() => { |
| | |
| | | } |
| | | } |
| | | |
| | | const Template = useMemo(() => { |
| | | switch (locale) { |
| | | case LanguagesSupported[1]: |
| | | return <TemplateZh apiBaseUrl={apiBaseUrl} /> |
| | | case LanguagesSupported[7]: |
| | | return <TemplateJa apiBaseUrl={apiBaseUrl} /> |
| | | default: |
| | | return <TemplateEn apiBaseUrl={apiBaseUrl} /> |
| | | } |
| | | }, [apiBaseUrl, locale]) |
| | | |
| | | return ( |
| | | <div className="flex"> |
| | | <div className={`fixed right-20 top-32 z-10 transition-all ${isTocExpanded ? 'w-64' : 'w-10'}`}> |
| | | <div className={`fixed right-16 top-32 z-10 transition-all ${isTocExpanded ? 'w-64' : 'w-10'}`}> |
| | | {isTocExpanded |
| | | ? ( |
| | | <nav className="toc max-h-[calc(100vh-150px)] w-full overflow-y-auto rounded-lg bg-components-panel-bg p-4 shadow-md"> |
| | | <div className="mb-4 flex items-center justify-between"> |
| | | <h3 className="text-lg font-semibold text-text-primary">{t('appApi.develop.toc')}</h3> |
| | | <nav className="toc w-full bg-gray-50 p-4 rounded-lg shadow-md max-h-[calc(100vh-150px)] overflow-y-auto"> |
| | | <div className="flex justify-between items-center mb-4"> |
| | | <h3 className="text-lg font-semibold">{t('appApi.develop.toc')}</h3> |
| | | <button |
| | | onClick={() => setIsTocExpanded(false)} |
| | | className="text-text-tertiary hover:text-text-secondary" |
| | | className="text-gray-500 hover:text-gray-700" |
| | | > |
| | | ✕ |
| | | ✕ |
| | | </button> |
| | | </div> |
| | | <ul className="space-y-2"> |
| | |
| | | <li key={index}> |
| | | <a |
| | | href={item.href} |
| | | className="text-text-secondary transition-colors duration-200 hover:text-text-primary hover:underline" |
| | | className="text-gray-600 hover:text-gray-900 hover:underline transition-colors duration-200" |
| | | onClick={e => handleTocClick(e, item)} |
| | | > |
| | | {item.text} |
| | |
| | | : ( |
| | | <button |
| | | onClick={() => setIsTocExpanded(true)} |
| | | className="flex h-10 w-10 items-center justify-center rounded-full bg-components-button-secondary-bg shadow-md transition-colors duration-200 hover:bg-components-button-secondary-bg-hover" |
| | | className="w-10 h-10 bg-gray-50 rounded-full shadow-md flex items-center justify-center hover:bg-gray-100 transition-colors duration-200" |
| | | > |
| | | <RiListUnordered className="h-6 w-6 text-components-button-secondary-text" /> |
| | | <RiListUnordered className="w-6 h-6" /> |
| | | </button> |
| | | )} |
| | | </div> |
| | | <article className={cn('prose-xl prose mx-1 rounded-t-xl bg-background-default px-4 pt-16 sm:mx-12', theme === Theme.dark && 'prose-invert')}> |
| | | {Template} |
| | | <article className='mx-1 px-4 sm:mx-12 pt-16 bg-white rounded-t-xl prose prose-xl'> |
| | | {locale !== LanguagesSupported[1] |
| | | ? <TemplateEn apiBaseUrl={apiBaseUrl} /> |
| | | : <TemplateZh apiBaseUrl={apiBaseUrl} /> |
| | | } |
| | | </article> |
| | | </div> |
| | | ) |