From de42c8ff7867fa24e88b9927074158e13c717af0 Mon Sep 17 00:00:00 2001 From: Hossein Mehrabi Date: Sun, 9 Oct 2022 04:38:54 +0330 Subject: [PATCH] feat: search components. --- .gitignore | 5 +- docusaurus.config.js | 16 +- package.json | 6 +- src/deps.ts | 4 + src/lib/settle.ts | 18 + src/lib/useEventListener.ts | 28 ++ src/lib/useOS.ts | 12 + src/lib/useWindowEventListener.ts | 20 ++ src/theme/Layout/index.tsx | 1 + src/theme/Layout/styles.scss | 13 + src/theme/Navbar/Content/index.tsx | 2 +- src/theme/Navbar/Content/styles.module.scss | 4 + src/theme/SearchBar/SearchBar.module.scss | 3 + src/theme/SearchBar/SearchBar.tsx | 82 +++++ .../SearchInput/SearchInput.module.scss | 74 ++++ .../SearchBar/SearchInput/SearchInput.tsx | 84 +++++ src/theme/SearchBar/SearchInput/index.ts | 1 + .../SearchResultGroup.module.scss | 17 + .../SearchResultGroup/SearchResultGroup.tsx | 23 ++ .../SearchBar/SearchResultGroup/index.ts | 1 + .../SearchResultItem.module.scss | 38 ++ .../SearchResultItem/SearchResultItem.tsx | 55 +++ src/theme/SearchBar/SearchResultItem/index.ts | 1 + .../SearchResultItemBase.module.scss | 37 ++ .../SearchResultItemBase.tsx | 27 ++ .../SearchBar/SearchResultItemBase/index.ts | 1 + .../SearchResults/SearchResults.module.scss | 68 ++++ .../SearchBar/SearchResults/SearchResults.tsx | 65 ++++ src/theme/SearchBar/SearchResults/index.ts | 1 + .../SearchResultsContainer.module.scss | 21 ++ .../SearchResultsContainer.tsx | 34 ++ .../SearchBar/SearchResultsContainer/index.ts | 1 + .../hooks/useProxiedGeneratedData.ts | 5 + src/theme/SearchBar/hooks/useSearch.ts | 33 ++ src/theme/SearchBar/hooks/useVersionUrl.ts | 27 ++ src/theme/SearchBar/index.tsx | 8 + src/theme/SearchBar/types.ts | 61 ++++ .../SearchBar/utils/groupSearchResult.ts | 102 ++++++ static/icons/document.svg | 3 + static/icons/hashtag.svg | 3 + yarn.lock | 337 +++++++++++++++++- 41 files changed, 1325 insertions(+), 17 deletions(-) create mode 100644 src/lib/settle.ts create mode 100644 src/lib/useEventListener.ts create mode 100644 src/lib/useOS.ts create mode 100644 src/lib/useWindowEventListener.ts create mode 100644 src/theme/Layout/styles.scss create mode 100644 src/theme/SearchBar/SearchBar.module.scss create mode 100644 src/theme/SearchBar/SearchBar.tsx create mode 100644 src/theme/SearchBar/SearchInput/SearchInput.module.scss create mode 100644 src/theme/SearchBar/SearchInput/SearchInput.tsx create mode 100644 src/theme/SearchBar/SearchInput/index.ts create mode 100644 src/theme/SearchBar/SearchResultGroup/SearchResultGroup.module.scss create mode 100644 src/theme/SearchBar/SearchResultGroup/SearchResultGroup.tsx create mode 100644 src/theme/SearchBar/SearchResultGroup/index.ts create mode 100644 src/theme/SearchBar/SearchResultItem/SearchResultItem.module.scss create mode 100644 src/theme/SearchBar/SearchResultItem/SearchResultItem.tsx create mode 100644 src/theme/SearchBar/SearchResultItem/index.ts create mode 100644 src/theme/SearchBar/SearchResultItemBase/SearchResultItemBase.module.scss create mode 100644 src/theme/SearchBar/SearchResultItemBase/SearchResultItemBase.tsx create mode 100644 src/theme/SearchBar/SearchResultItemBase/index.ts create mode 100644 src/theme/SearchBar/SearchResults/SearchResults.module.scss create mode 100644 src/theme/SearchBar/SearchResults/SearchResults.tsx create mode 100644 src/theme/SearchBar/SearchResults/index.ts create mode 100644 src/theme/SearchBar/SearchResultsContainer/SearchResultsContainer.module.scss create mode 100644 src/theme/SearchBar/SearchResultsContainer/SearchResultsContainer.tsx create mode 100644 src/theme/SearchBar/SearchResultsContainer/index.ts create mode 100644 src/theme/SearchBar/hooks/useProxiedGeneratedData.ts create mode 100644 src/theme/SearchBar/hooks/useSearch.ts create mode 100644 src/theme/SearchBar/hooks/useVersionUrl.ts create mode 100644 src/theme/SearchBar/index.tsx create mode 100644 src/theme/SearchBar/types.ts create mode 100644 src/theme/SearchBar/utils/groupSearchResult.ts create mode 100644 static/icons/document.svg create mode 100644 static/icons/hashtag.svg diff --git a/.gitignore b/.gitignore index 3ced74e..9e155eb 100644 --- a/.gitignore +++ b/.gitignore @@ -18,5 +18,8 @@ npm-debug.log* yarn-debug.log* yarn-error.log* - +.yalc +yalc.lock .idea + +static/search-index.json diff --git a/docusaurus.config.js b/docusaurus.config.js index 9eb1801..24a3d48 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -10,7 +10,7 @@ const config = { tagline: 'Dinosaurs are cool', url: 'https://your-docusaurus-test-site.com', baseUrl: '/', - onBrokenLinks: 'throw', + onBrokenLinks: 'warn', onBrokenMarkdownLinks: 'warn', favicon: 'img/favicon.ico', @@ -127,7 +127,19 @@ const config = { darkTheme: darkCodeTheme, }, }), - plugins: ['docusaurus-plugin-sass'], + plugins: [ + 'docusaurus-plugin-sass', + [ + '@acid-info/docusaurus-search-local', + { + hashed: true, + indexDocs: true, + indexBlog: false, + indexPages: true, + docsRouteBasePath: '/', + }, + ], + ], } module.exports = config diff --git a/package.json b/package.json index 575fbbc..d094ea3 100644 --- a/package.json +++ b/package.json @@ -18,18 +18,22 @@ "prettier:staged": "pretty-quick --staged" }, "dependencies": { + "@acid-info/docusaurus-search-local": "^0.32.1", "@docusaurus/core": "2.1.0", "@docusaurus/preset-classic": "2.1.0", "@mdx-js/react": "^1.6.22", "clsx": "^1.2.1", "copy-to-clipboard": "^3.3.2", + "lodash": "^4.17.21", "prism-react-renderer": "^1.3.5", "react": "^17.0.2", - "react-dom": "^17.0.2" + "react-dom": "^17.0.2", + "react-use": "^17.4.0" }, "devDependencies": { "@docusaurus/module-type-aliases": "2.1.0", "@tsconfig/docusaurus": "^1.0.5", + "@types/lodash": "^4.14.186", "docusaurus-plugin-sass": "^0.2.2", "husky": "^8.0.1", "prettier": "^2.7.1", diff --git a/src/deps.ts b/src/deps.ts index 25f6997..e5e343c 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -1,3 +1,7 @@ declare module '@docusaurus/theme-common/internal' { export * from '@docusaurus/theme-common/lib/internal' } + +declare module '@docusaurus/plugin-content-docs/client' { + export * from '@docusaurus/plugin-content-docs/lib/client' +} diff --git a/src/lib/settle.ts b/src/lib/settle.ts new file mode 100644 index 0000000..d0934ad --- /dev/null +++ b/src/lib/settle.ts @@ -0,0 +1,18 @@ +export const settle = async ( + promise: Promise, +): Promise<[R, undefined] | [undefined, E]> => { + try { + const result: R = await promise + return [result, undefined] + } catch (error) { + return [undefined, error as E] + } +} + +export const settleSync = (func: () => R): [R, E] => { + try { + return [func(), null] + } catch (error) { + return [undefined, error] + } +} diff --git a/src/lib/useEventListener.ts b/src/lib/useEventListener.ts new file mode 100644 index 0000000..7115e06 --- /dev/null +++ b/src/lib/useEventListener.ts @@ -0,0 +1,28 @@ +import { useEffect, useMemo } from 'react' + +export const useEventListener = < + T = any, + E extends { addEventListener: any; removeEventListener: any } = any, +>( + key: string | (() => string), + element: E | (() => E), + listener: (event: T) => void, + options?: boolean | AddEventListenerOptions, + deps?: any[], +) => { + const _key = useMemo(() => (typeof key === 'string' ? key : key()), []) + const _element = useMemo( + () => (typeof element === 'function' ? element() : element), + [element], + ) + + useEffect(() => { + if (!_element?.addEventListener || !_element?.removeEventListener) return + + _element.addEventListener(_key, listener, options) + + return () => { + _element.removeEventListener(_key, listener, options) + } + }, [_key, _element]) +} diff --git a/src/lib/useOS.ts b/src/lib/useOS.ts new file mode 100644 index 0000000..c6a4377 --- /dev/null +++ b/src/lib/useOS.ts @@ -0,0 +1,12 @@ +export const useOS = (): 'windows' | 'linux' | 'mac' | 'unknown' => { + const str = + navigator?.appVersion ?? navigator?.platform ?? navigator?.userAgent + + return /mac/gi.test(str) + ? 'mac' + : /win/gi.test(str) + ? 'windows' + : /linux/gi.test(str) + ? 'linux' + : 'unknown' +} diff --git a/src/lib/useWindowEventListener.ts b/src/lib/useWindowEventListener.ts new file mode 100644 index 0000000..417c3e9 --- /dev/null +++ b/src/lib/useWindowEventListener.ts @@ -0,0 +1,20 @@ +import { useEventListener } from './useEventListener' + +export const useWindowEventListener = ( + key: K | string, + listener: ( + ev: Record extends Record + ? WindowEventMap[K] + : T, + ) => void, + options?: boolean | AddEventListenerOptions, + deps: any[] = [], +) => { + useEventListener( + key, + () => typeof window !== 'undefined' && window, + listener, + options, + deps, + ) +} diff --git a/src/theme/Layout/index.tsx b/src/theme/Layout/index.tsx index 37d1647..71f51a0 100644 --- a/src/theme/Layout/index.tsx +++ b/src/theme/Layout/index.tsx @@ -1,6 +1,7 @@ import { globalStore } from '@site/src/containers/GlobalStore' import Layout from '@theme-original/Layout' import React from 'react' +import './styles.scss' export default function LayoutWrapper(props) { const store = globalStore.useCreateStore({ hiddenSidebar: false }) diff --git a/src/theme/Layout/styles.scss b/src/theme/Layout/styles.scss new file mode 100644 index 0000000..42fc9b7 --- /dev/null +++ b/src/theme/Layout/styles.scss @@ -0,0 +1,13 @@ +// TODO: move styles to css/custom.scss file. + +.hidden-scrollbar { + /* Chrome, Safari and Opera */ + &::-webkit-scrollbar { + width: 0; + display: none; + } + + /* Firefox, Edge and IE */ + -ms-overflow-style: none; + scrollbar-width: none; +} diff --git a/src/theme/Navbar/Content/index.tsx b/src/theme/Navbar/Content/index.tsx index 0757600..866ba9f 100644 --- a/src/theme/Navbar/Content/index.tsx +++ b/src/theme/Navbar/Content/index.tsx @@ -69,7 +69,7 @@ export default function NavbarContent(): JSX.Element {
-
+
diff --git a/src/theme/Navbar/Content/styles.module.scss b/src/theme/Navbar/Content/styles.module.scss index d048eae..d3e3af2 100644 --- a/src/theme/Navbar/Content/styles.module.scss +++ b/src/theme/Navbar/Content/styles.module.scss @@ -105,6 +105,10 @@ } } +.searchContainer > div { + padding: 0; +} + @include utils.responsive('lg', 'down') { .root { padding: 0 var(--ifm-spacing-horizontal); diff --git a/src/theme/SearchBar/SearchBar.module.scss b/src/theme/SearchBar/SearchBar.module.scss new file mode 100644 index 0000000..6e91c9f --- /dev/null +++ b/src/theme/SearchBar/SearchBar.module.scss @@ -0,0 +1,3 @@ +.root { + position: relative; +} diff --git a/src/theme/SearchBar/SearchBar.tsx b/src/theme/SearchBar/SearchBar.tsx new file mode 100644 index 0000000..09ba3a5 --- /dev/null +++ b/src/theme/SearchBar/SearchBar.tsx @@ -0,0 +1,82 @@ +import { useLocation } from '@docusaurus/router' +import clsx from 'clsx' +import React, { useEffect, useRef, useState } from 'react' +import { useSearch } from './hooks/useSearch' +import styles from './SearchBar.module.scss' +import { SearchInput } from './SearchInput' +import { SearchResults } from './SearchResults' +import { SearchResultsContainer } from './SearchResultsContainer' +import { SearchResult } from './types' + +export const SearchBar: React.FC<{}> = ({}) => { + const search = useSearch() + const ref = useRef(null) + const inputRef = useRef(null) + + const location = useLocation() + + const [input, setInput] = useState('') + const [results, setResults] = useState([]) + const [showResultsContainer, setShowResultsContainer] = useState(false) + + const onInputChange = (e: React.ChangeEvent) => { + setInput(e.target.value) + } + + const onInputFocus = () => { + setShowResultsContainer(true) + } + + const onInputCancel = () => { + setShowResultsContainer(false) + } + + const onClickOutsideResultsContainer = (event: Event) => { + if (!event.composedPath().find((el) => el === ref.current)) onInputCancel() + } + + const onClear = () => { + setInput('') + inputRef.current.focus() + } + + const query = async (input: string) => { + const { results } = await search.query(input) + setResults(results) + setShowResultsContainer(true) + } + + useEffect(() => { + if (input.length > 0) query(input) + else setResults([]) + }, [input]) + + useEffect(() => { + if (showResultsContainer) { + setShowResultsContainer(false) + } + }, [location.key]) + + return ( +
+ + 0} + inputRef={inputRef} + onClickOutside={onClickOutsideResultsContainer} + > + + +
+ ) +} diff --git a/src/theme/SearchBar/SearchInput/SearchInput.module.scss b/src/theme/SearchBar/SearchInput/SearchInput.module.scss new file mode 100644 index 0000000..8a3f8b3 --- /dev/null +++ b/src/theme/SearchBar/SearchInput/SearchInput.module.scss @@ -0,0 +1,74 @@ +// TODO: use ifm variables + +.root { + width: auto; + position: relative; +} + +.root input { + width: 134px; + + border: 0; + border-radius: 8px; + background: var(--ifm-background-surface-color); + + padding: 9px 48px 9px 16px; + + transition: 0.2s; + + &:focus { + outline: none; + } +} + +.root.expanded input { + background: #eeeef0; + width: 334px; +} + +.root.expanded .label { + display: none; +} + +.label { + position: absolute; + left: 16px; + top: 50%; + transform: translateY(-50%); + + color: #747475; + font-size: 0.875rem; + pointer-events: none; +} + +.shortcuts { + position: absolute; + right: 16px; + top: 50%; + transform: translateY(-50%); + line-height: 0; + pointer-events: none; + + & > kbd { + margin-left: 0.375rem; + } + + kbd { + background: none; + border: none; + padding: 0; + color: #bababa; + box-shadow: none; + font-size: 0.75rem; + } +} + +[data-theme='dark'] { + .root input { + color: currentColor; + } + + .root.expanded input { + background-color: var(--ifm-background-color); + } +} diff --git a/src/theme/SearchBar/SearchInput/SearchInput.tsx b/src/theme/SearchBar/SearchInput/SearchInput.tsx new file mode 100644 index 0000000..ac6634f --- /dev/null +++ b/src/theme/SearchBar/SearchInput/SearchInput.tsx @@ -0,0 +1,84 @@ +import { useOS } from '@site/src/lib/useOS' +import { useWindowEventListener } from '@site/src/lib/useWindowEventListener' +import clsx from 'clsx' +import React from 'react' +import {} from 'react-use' +import styles from './SearchInput.module.scss' + +export type SearchInputProps = Omit< + React.HTMLProps, + 'value' | 'onChange' +> & + Pick, 'onChange'> & { + inputProps?: Omit, 'ref'> & { + ref: React.MutableRefObject + } + value?: string + active?: boolean + onFocus?: () => void + onCancel?: () => void + } + +export const SearchInput: React.FC = ({ + value, + active, + onChange, + onFocus: onFocusCallback, + onCancel, + className, + inputProps: { ref: inputRef, ...inputProps }, + ...props +}) => { + const os = useOS() + + const expanded = active || value?.length > 0 + + const focus = () => { + inputRef.current.focus() + } + + const blur = () => { + inputRef.current.blur() + onCancel && onCancel() + } + + useWindowEventListener('keydown', (event) => { + if (event.ctrlKey && event.code === 'KeyK') { + event.preventDefault() + focus() + } else if (event.code === 'Escape') { + blur() + } + }) + + const onFocus = (event: React.FocusEvent) => { + onFocusCallback && onFocusCallback() + } + + return ( +
+ Search + +
+ {active ? ( + esc + ) : ( + <> + {os === 'mac' ? '⌘' : 'ctrl'} + k + + )} +
+
+ ) +} diff --git a/src/theme/SearchBar/SearchInput/index.ts b/src/theme/SearchBar/SearchInput/index.ts new file mode 100644 index 0000000..9d6996c --- /dev/null +++ b/src/theme/SearchBar/SearchInput/index.ts @@ -0,0 +1 @@ +export * from './SearchInput' diff --git a/src/theme/SearchBar/SearchResultGroup/SearchResultGroup.module.scss b/src/theme/SearchBar/SearchResultGroup/SearchResultGroup.module.scss new file mode 100644 index 0000000..489f853 --- /dev/null +++ b/src/theme/SearchBar/SearchResultGroup/SearchResultGroup.module.scss @@ -0,0 +1,17 @@ +.root { + & > div:first-child { + padding: 0 14px; + font-size: 0.75rem; + font-weight: bold; + color: #828285; + } + + ul { + margin-top: 16px; + padding: 0; + } + + ul li { + list-style: none; + } +} diff --git a/src/theme/SearchBar/SearchResultGroup/SearchResultGroup.tsx b/src/theme/SearchBar/SearchResultGroup/SearchResultGroup.tsx new file mode 100644 index 0000000..f51ebec --- /dev/null +++ b/src/theme/SearchBar/SearchResultGroup/SearchResultGroup.tsx @@ -0,0 +1,23 @@ +import clsx from 'clsx' +import React from 'react' +import styles from './SearchResultGroup.module.scss' + +export type SearchResultGroupProps = React.HTMLProps & { + title: string +} + +export const SearchResultGroup: React.FC = ({ + className, + title = '', + children, + ...props +}) => { + return ( +
+
+ {title} +
+
    {children}
+
+ ) +} diff --git a/src/theme/SearchBar/SearchResultGroup/index.ts b/src/theme/SearchBar/SearchResultGroup/index.ts new file mode 100644 index 0000000..e316974 --- /dev/null +++ b/src/theme/SearchBar/SearchResultGroup/index.ts @@ -0,0 +1 @@ +export * from './SearchResultGroup' diff --git a/src/theme/SearchBar/SearchResultItem/SearchResultItem.module.scss b/src/theme/SearchBar/SearchResultItem/SearchResultItem.module.scss new file mode 100644 index 0000000..b7da2a6 --- /dev/null +++ b/src/theme/SearchBar/SearchResultItem/SearchResultItem.module.scss @@ -0,0 +1,38 @@ +.root { + text-decoration: none !important; +} + +.icon { + &.l1 { + } + + &.l2 { + opacity: 0.6; + } + + &.fill { + &, + & * { + fill: currentColor; + } + } + + &.stroke { + &, + & * { + stroke: currentColor; + } + } +} + +[data-theme='light'] { + .icon { + color: black; // todo: use ifm variables + } +} + +[data-theme='dark'] { + .icon { + color: white; // TODO: use ifm variables + } +} diff --git a/src/theme/SearchBar/SearchResultItem/SearchResultItem.tsx b/src/theme/SearchBar/SearchResultItem/SearchResultItem.tsx new file mode 100644 index 0000000..4dc6a82 --- /dev/null +++ b/src/theme/SearchBar/SearchResultItem/SearchResultItem.tsx @@ -0,0 +1,55 @@ +import Link, { Props as LinkProps } from '@docusaurus/Link' +import DocumentIcon from '@site/static/icons/document.svg' +import BlockIcon from '@site/static/icons/hashtag.svg' +import clsx from 'clsx' +import React from 'react' +import { SearchResultItemBase } from '../SearchResultItemBase' +import { SearchDocumentType } from '../types' +import styles from './SearchResultItem.module.scss' + +const icons: Record = { + [SearchDocumentType.Title]: ( + + ), + [SearchDocumentType.Heading]: ( + + ), + [SearchDocumentType.Paragraph]: ( + + ), +} + +export type SearchResultItemProps = React.HTMLProps & { + type: string | SearchDocumentType + title: string + href: string + content?: string + linkProps?: LinkProps +} + +export const SearchResultItem: React.FC = ({ + type, + href, + title, + content, + className, + linkProps: { className: linkClassName, ...linkProps } = {}, + ...props +}) => { + const icon = icons[type] + + return ( + + + + ) +} diff --git a/src/theme/SearchBar/SearchResultItem/index.ts b/src/theme/SearchBar/SearchResultItem/index.ts new file mode 100644 index 0000000..79634be --- /dev/null +++ b/src/theme/SearchBar/SearchResultItem/index.ts @@ -0,0 +1 @@ +export * from './SearchResultItem' diff --git a/src/theme/SearchBar/SearchResultItemBase/SearchResultItemBase.module.scss b/src/theme/SearchBar/SearchResultItemBase/SearchResultItemBase.module.scss new file mode 100644 index 0000000..8ea62ea --- /dev/null +++ b/src/theme/SearchBar/SearchResultItemBase/SearchResultItemBase.module.scss @@ -0,0 +1,37 @@ +// todo: use ifm variables + +.root { + display: flex; + align-items: center; + padding: 12px; + + mark { + color: #3165b4; + background: none; + } + + & > div { + margin-left: 26px; + + & > div { + color: #373738; + font-size: 0.875rem; + } + + & > p { + color: #828285; + font-size: 0.625rem; + margin: 0; + } + } +} + +[data-theme='dark'] { + .root { + & > div { + & > div { + color: var(--ifm-color-secondary); + } + } + } +} diff --git a/src/theme/SearchBar/SearchResultItemBase/SearchResultItemBase.tsx b/src/theme/SearchBar/SearchResultItemBase/SearchResultItemBase.tsx new file mode 100644 index 0000000..83f8de2 --- /dev/null +++ b/src/theme/SearchBar/SearchResultItemBase/SearchResultItemBase.tsx @@ -0,0 +1,27 @@ +import clsx from 'clsx' +import React from 'react' +import styles from './SearchResultItemBase.module.scss' + +export type SearchResultItemBaseProps = React.HTMLProps & { + title: string + content?: string + icon: React.ReactElement +} + +export const SearchResultItemBase: React.FC = ({ + icon, + title, + content, + className, + ...props +}) => { + return ( +
  • + {icon} +
    + {title &&
    } + {content &&

    } +

    +
  • + ) +} diff --git a/src/theme/SearchBar/SearchResultItemBase/index.ts b/src/theme/SearchBar/SearchResultItemBase/index.ts new file mode 100644 index 0000000..66c1d18 --- /dev/null +++ b/src/theme/SearchBar/SearchResultItemBase/index.ts @@ -0,0 +1 @@ +export * from './SearchResultItemBase' diff --git a/src/theme/SearchBar/SearchResults/SearchResults.module.scss b/src/theme/SearchBar/SearchResults/SearchResults.module.scss new file mode 100644 index 0000000..be53fc3 --- /dev/null +++ b/src/theme/SearchBar/SearchResults/SearchResults.module.scss @@ -0,0 +1,68 @@ +// TODO: use ifm variables + +.root { + padding: 0; +} + +.divider { + width: 100%; + padding: 0 14px; + + & > div { + height: 1px; + background-color: #ededed; + } +} + +.topBar { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + padding: 14px; + + span, + button { + font-size: 0.75rem; + font-weight: bold; + color: #c0c0c2; + } + + button { + color: #909091; + background: #eeeef1; + padding: 4px 12px; + border-radius: 8px; + } +} + +.noResults { + color: #909091; +} + +.groups { + max-height: 500px; + overflow-y: auto; + + .group { + margin: 16px 0; + } + + .divider:last-child { + display: none; + } +} + +[data-theme='dark'] { + .divider { + & > div { + opacity: 0.1; + } + } + + .topBar { + button { + background-color: var(--ifm-button-color); + } + } +} diff --git a/src/theme/SearchBar/SearchResults/SearchResults.tsx b/src/theme/SearchBar/SearchResults/SearchResults.tsx new file mode 100644 index 0000000..0a4bc2b --- /dev/null +++ b/src/theme/SearchBar/SearchResults/SearchResults.tsx @@ -0,0 +1,65 @@ +import clsx from 'clsx' +import React, { MutableRefObject, useMemo } from 'react' +import { SearchResultGroup } from '../SearchResultGroup' +import { SearchResultItem } from '../SearchResultItem' +import { SearchResult } from '../types' +import { groupSearchResult } from '../utils/groupSearchResult' +import styles from './SearchResults.module.scss' + +const divider = ( +
    +
    +
    +) + +export type SearchResultsProps = Omit< + React.HTMLProps, + 'results' +> & { + inputRef?: MutableRefObject + results: SearchResult[] + onClear: () => void +} + +export const SearchResults: React.FC = ({ + results, + onClear, + className, + ...props +}) => { + const total = results.length + const grouped = useMemo(() => groupSearchResult(results), [results]) + + return ( +
    +
    + {total} results + +
    + + {divider} + +
    + {grouped.map(([category, items], index) => ( + + + {items.map((item, itemIndex) => ( + + ))} + + + {divider} + + ))} +
    +
    + ) +} diff --git a/src/theme/SearchBar/SearchResults/index.ts b/src/theme/SearchBar/SearchResults/index.ts new file mode 100644 index 0000000..3583993 --- /dev/null +++ b/src/theme/SearchBar/SearchResults/index.ts @@ -0,0 +1 @@ +export * from './SearchResults' diff --git a/src/theme/SearchBar/SearchResultsContainer/SearchResultsContainer.module.scss b/src/theme/SearchBar/SearchResultsContainer/SearchResultsContainer.module.scss new file mode 100644 index 0000000..e7219a4 --- /dev/null +++ b/src/theme/SearchBar/SearchResultsContainer/SearchResultsContainer.module.scss @@ -0,0 +1,21 @@ +.root { + background-color: var(--ifm-background-surface-color); + border-radius: 1rem; + + left: 0; + top: 100%; + position: absolute; + + margin-top: 16px; + + width: 100%; + + opacity: 0; + visibility: hidden; + transition: 0.2s; + + &.visible { + opacity: 1; + visibility: visible; + } +} diff --git a/src/theme/SearchBar/SearchResultsContainer/SearchResultsContainer.tsx b/src/theme/SearchBar/SearchResultsContainer/SearchResultsContainer.tsx new file mode 100644 index 0000000..d373053 --- /dev/null +++ b/src/theme/SearchBar/SearchResultsContainer/SearchResultsContainer.tsx @@ -0,0 +1,34 @@ +import clsx from 'clsx' +import React, { MutableRefObject, useRef } from 'react' +import { useClickAway } from 'react-use' +import styles from './SearchResultsContainer.module.scss' + +export type SearchResultsContainerProps = React.HTMLProps & { + visible?: boolean + inputRef?: MutableRefObject + onClickOutside: (event: Event) => void +} + +export const SearchResultsContainer: React.FC = ({ + visible, + inputRef, + className, + onClickOutside, + children, + ...props +}) => { + const ref = useRef() + + useClickAway(ref, (event) => { + onClickOutside(event) + }) + + return ( +
    + {children} +
    + ) +} diff --git a/src/theme/SearchBar/SearchResultsContainer/index.ts b/src/theme/SearchBar/SearchResultsContainer/index.ts new file mode 100644 index 0000000..5ff8ed0 --- /dev/null +++ b/src/theme/SearchBar/SearchResultsContainer/index.ts @@ -0,0 +1 @@ +export * from './SearchResultsContainer' diff --git a/src/theme/SearchBar/hooks/useProxiedGeneratedData.ts b/src/theme/SearchBar/hooks/useProxiedGeneratedData.ts new file mode 100644 index 0000000..9cc50ac --- /dev/null +++ b/src/theme/SearchBar/hooks/useProxiedGeneratedData.ts @@ -0,0 +1,5 @@ +export const useProxiedGeneratedData = () => { + const win = window as any + + return win.getProxiedGeneratedData() +} diff --git a/src/theme/SearchBar/hooks/useSearch.ts b/src/theme/SearchBar/hooks/useSearch.ts new file mode 100644 index 0000000..114a7b8 --- /dev/null +++ b/src/theme/SearchBar/hooks/useSearch.ts @@ -0,0 +1,33 @@ +import { useEffect, useRef, useState } from 'react' +import { useVersionUrl } from './useVersionUrl' + +export const useSearch = () => { + const win = window as any + + const versionUrl = useVersionUrl() + + const [loaded, setLoaded] = useState(false) + const search = useRef(null) + + const init = async () => { + search.current = await win.createSearchInstance({ + resultsLimit: 50, + preferredVersionPath: versionUrl, + }) + + await search.current.init() + + setLoaded(true) + } + + useEffect(() => { + setLoaded(false) + + init() + }, [versionUrl]) + + return { + loaded, + query: async (input: string) => await search.current.query(input), + } +} diff --git a/src/theme/SearchBar/hooks/useVersionUrl.ts b/src/theme/SearchBar/hooks/useVersionUrl.ts new file mode 100644 index 0000000..ee02388 --- /dev/null +++ b/src/theme/SearchBar/hooks/useVersionUrl.ts @@ -0,0 +1,27 @@ +import { useActivePlugin } from '@docusaurus/plugin-content-docs/client' +import { useDocsPreferredVersion } from '@docusaurus/theme-common/internal' +import useDocusaurusContext from '@docusaurus/useDocusaurusContext' +import { useProxiedGeneratedData } from './useProxiedGeneratedData' + +export const useVersionUrl = () => { + const { + siteConfig: { baseUrl }, + } = useDocusaurusContext() + + const { docsPluginIdForPreferredVersion } = useProxiedGeneratedData() + + let result = baseUrl + + const activePlugin = useActivePlugin() + + const { preferredVersion } = useDocsPreferredVersion( + activePlugin?.pluginId ?? docsPluginIdForPreferredVersion, + ) + + result = + preferredVersion && !preferredVersion.isLast + ? preferredVersion.path + '/' + : result + + return result +} diff --git a/src/theme/SearchBar/index.tsx b/src/theme/SearchBar/index.tsx new file mode 100644 index 0000000..1e6ecf0 --- /dev/null +++ b/src/theme/SearchBar/index.tsx @@ -0,0 +1,8 @@ +import React from 'react' +import { SearchBar } from './SearchBar' + +const SearchBarWrapper: React.FC = () => { + return typeof window === 'undefined' ? <> : +} + +export default SearchBarWrapper diff --git a/src/theme/SearchBar/types.ts b/src/theme/SearchBar/types.ts new file mode 100644 index 0000000..e199beb --- /dev/null +++ b/src/theme/SearchBar/types.ts @@ -0,0 +1,61 @@ +export type SearchDocument = { + id: string + title: string + url: string + hash?: string + parentId?: string + breadcrumb?: string + sectionTitle?: string +} + +export enum SearchDocumentType { + Title = 'title', + Heading = 'heading', + Paragraph = 'paragraph', +} + +export type SearchResultBase = { + document: SearchDocument + type: SearchDocumentType + page: SearchDocument | undefined | false + metadata: MatchMetadata + tokens: string[] + highlighted: string +} + +export type SearchResultExtra = { + score: number + index: number + isInterOfTree: boolean + isLastOfTree: boolean +} + +export type SearchResult = SearchResultBase & SearchResultExtra + +export type MetadataPosition = [number, number] + +export interface MatchMetadata { + [token: string]: { + [field: string]: { + position: MetadataPosition[] + } + } +} + +// Grouped + +export type SearchResultGroupItem = { + type: SearchResult['type'] + url: string + hash: string + href: string + title: string + score: number + content: string +} + +export type SearchResultGroupItemWithCategory = SearchResultGroupItem & { + category: string +} + +export type GroupedSearchResult = [string, SearchResultGroupItem[]][] diff --git a/src/theme/SearchBar/utils/groupSearchResult.ts b/src/theme/SearchBar/utils/groupSearchResult.ts new file mode 100644 index 0000000..d793c20 --- /dev/null +++ b/src/theme/SearchBar/utils/groupSearchResult.ts @@ -0,0 +1,102 @@ +import groupBy from 'lodash/groupBy' +import omit from 'lodash/omit' +import { + GroupedSearchResult, + SearchDocument, + SearchDocumentType, + SearchResult, + SearchResultGroupItem, + SearchResultGroupItemWithCategory, +} from '../types' + +const convertSearchResult = ( + item: SearchResult, +): SearchResultGroupItemWithCategory => { + const { type, document, page, highlighted, score } = item + const { url, hash } = document + const href = url + (hash ?? '') + + switch (type) { + case SearchDocumentType.Title: { + return { + type, + url, + hash, + href, + score, + title: highlighted, + content: '', + category: document.breadcrumb[1] ?? document.title, + } + } + + case SearchDocumentType.Heading: { + const p = page as any as SearchDocument + + return { + type, + url, + hash, + href, + score, + title: highlighted, + content: '', + category: p?.breadcrumb?.[1] ?? p?.title ?? '', + } + } + + case SearchDocumentType.Paragraph: { + const p = page as any as SearchDocument + + return { + type, + url, + hash, + href, + score, + title: document.sectionTitle, + content: highlighted, + category: p?.breadcrumb?.[1] ?? p?.title ?? '', + } + } + } +} + +export const groupSearchResult = ( + results: SearchResult[], +): GroupedSearchResult => + Object.entries( + groupBy( + results.map((item) => convertSearchResult(item)), + 'category', + ), + ) + .map( + ([key, items]) => + [ + key, + items + .map((item) => omit(item, 'category')) + .sort((a, b) => (a.score > b.score ? -1 : 1)), + ] as [string, SearchResultGroupItem[]], + ) + .sort((a, b) => (a[1][0].score > b[1][0].score ? -1 : 1)) + .map(([category, items]) => [ + category, + Object.entries(groupBy(items, 'url')) + .map( + ([url, items]) => + [ + url, + items.sort((a, b) => + a.type === SearchDocumentType.Title + ? -1 + : a.score > b.score + ? -1 + : 1, + ), + ] as [string, SearchResultGroupItem[]], + ) + .sort((a, b) => (a[1][0].score > b[1][0].score ? -1 : 1)) + .flatMap(([url, items]) => items), + ]) diff --git a/static/icons/document.svg b/static/icons/document.svg new file mode 100644 index 0000000..df2985f --- /dev/null +++ b/static/icons/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/hashtag.svg b/static/icons/hashtag.svg new file mode 100644 index 0000000..4a771d5 --- /dev/null +++ b/static/icons/hashtag.svg @@ -0,0 +1,3 @@ + + + diff --git a/yarn.lock b/yarn.lock index 436e060..a9ea447 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,28 @@ # yarn lockfile v1 +"@acid-info/docusaurus-search-local@^0.32.1": + version "0.32.1" + resolved "https://registry.yarnpkg.com/@acid-info/docusaurus-search-local/-/docusaurus-search-local-0.32.1.tgz#c13da0f077b8b05f8ed5a16bdd1ea6126ea49716" + integrity sha512-cj/n/bmK3lySxKsnFVoKCXdzHV7/qtxxhZIdejcpW+Wj+b3P3Uv044F9eQwKK8LjOhc4TeD/KLFYhZ8SvYXTPA== + dependencies: + "@docusaurus/plugin-content-docs" "^2.0.0-rc.1" + "@docusaurus/theme-translations" "^2.0.0-rc.1" + "@docusaurus/utils" "^2.0.0-rc.1" + "@docusaurus/utils-common" "^2.0.0-rc.1" + "@docusaurus/utils-validation" "^2.0.0-rc.1" + "@easyops-cn/autocomplete.js" "^0.38.1" + "@node-rs/jieba" "^1.6.0" + cheerio "^1.0.0-rc.3" + clsx "^1.1.1" + debug "^4.2.0" + fs-extra "^10.0.0" + klaw-sync "^6.0.0" + lunr "^2.3.9" + lunr-languages "^1.4.0" + mark.js "^8.11.1" + tslib "^2.4.0" + "@algolia/autocomplete-core@1.7.1": version "1.7.1" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.1.tgz#025538b8a9564a9f3dd5bcf8a236d6951c76c7d1" @@ -1352,7 +1374,7 @@ utility-types "^3.10.0" webpack "^5.73.0" -"@docusaurus/plugin-content-docs@2.1.0": +"@docusaurus/plugin-content-docs@2.1.0", "@docusaurus/plugin-content-docs@^2.0.0-rc.1": version "2.1.0" resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.1.0.tgz#3fcdf258c13dde27268ce7108a102b74ca4c279b" integrity sha512-Rup5pqXrXlKGIC4VgwvioIhGWF7E/NNSlxv+JAxRYpik8VKlWsk9ysrdHIlpX+KJUCO9irnY21kQh2814mlp/Q== @@ -1534,7 +1556,7 @@ tslib "^2.4.0" utility-types "^3.10.0" -"@docusaurus/theme-translations@2.1.0": +"@docusaurus/theme-translations@2.1.0", "@docusaurus/theme-translations@^2.0.0-rc.1": version "2.1.0" resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.1.0.tgz#ce9a2955afd49bff364cfdfd4492b226f6dd3b6e" integrity sha512-07n2akf2nqWvtJeMy3A+7oSGMuu5F673AovXVwY0aGAux1afzGCiqIFlYW3EP0CujvDJAEFSQi/Tetfh+95JNg== @@ -1556,14 +1578,14 @@ webpack "^5.73.0" webpack-merge "^5.8.0" -"@docusaurus/utils-common@2.1.0": +"@docusaurus/utils-common@2.1.0", "@docusaurus/utils-common@^2.0.0-rc.1": version "2.1.0" resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.1.0.tgz#248434751096f8c6c644ed65eed2a5a070a227f8" integrity sha512-F2vgmt4yRFgRQR2vyEFGTWeyAdmgKbtmu3sjHObF0tjjx/pN0Iw/c6eCopaH34E6tc9nO0nvp01pwW+/86d1fg== dependencies: tslib "^2.4.0" -"@docusaurus/utils-validation@2.1.0": +"@docusaurus/utils-validation@2.1.0", "@docusaurus/utils-validation@^2.0.0-rc.1": version "2.1.0" resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.1.0.tgz#c8cf1d8454d924d9a564fefa86436268f43308e3" integrity sha512-AMJzWYKL3b7FLltKtDXNLO9Y649V2BXvrnRdnW2AA+PpBnYV78zKLSCz135cuWwRj1ajNtP4onbXdlnyvCijGQ== @@ -1574,7 +1596,7 @@ js-yaml "^4.1.0" tslib "^2.4.0" -"@docusaurus/utils@2.1.0": +"@docusaurus/utils@2.1.0", "@docusaurus/utils@^2.0.0-rc.1": version "2.1.0" resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.1.0.tgz#b77b45b22e61eb6c2dcad8a7e96f6db0409b655f" integrity sha512-fPvrfmAuC54n8MjZuG4IysaMdmvN5A/qr7iFLbSGSyDrsbP4fnui6KdZZIa/YOLIPLec8vjZ8RIITJqF18mx4A== @@ -1595,6 +1617,14 @@ url-loader "^4.1.1" webpack "^5.73.0" +"@easyops-cn/autocomplete.js@^0.38.1": + version "0.38.1" + resolved "https://registry.yarnpkg.com/@easyops-cn/autocomplete.js/-/autocomplete.js-0.38.1.tgz#46dff5795a9a032fa9b9250fdf63ca6c61c07629" + integrity sha512-drg76jS6syilOUmVNkyo1c7ZEBPcPuK+aJA7AksM5ZIIbV57DMHCywiCr+uHyv8BE5jUTU98j/H7gVrkHrWW3Q== + dependencies: + cssesc "^3.0.0" + immediate "^3.2.3" + "@hapi/hoek@^9.0.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" @@ -1714,6 +1744,90 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== +"@node-rs/jieba-android-arm-eabi@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-android-arm-eabi/-/jieba-android-arm-eabi-1.6.1.tgz#196f1052a564d2608e46c87114aa78232453b798" + integrity sha512-R1YQfsPr7sK3Tq1sM0//6lNAGJK9RnMT0ShITT+7EJYr5OufUBb38lf/mRhrLxR0NF1pycEsMjdCAwrWrHd8rA== + +"@node-rs/jieba-android-arm64@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-android-arm64/-/jieba-android-arm64-1.6.1.tgz#cb4db38d9fcb877ac06659281a2dc5f50fe7be52" + integrity sha512-hBRbj2uLmRFYDw2lWppTAPoyjeXkBKUT84h4fHUQj7CMU94Gc1IWkE4ocCqhvUhbaUXlCpocS9mB0/fc2641bw== + +"@node-rs/jieba-darwin-arm64@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-darwin-arm64/-/jieba-darwin-arm64-1.6.1.tgz#83ad4bddd9368556ccd46555a508abbf9007fa4b" + integrity sha512-GeoDe7XVTF6z8JUtD98QvwudsMaHV5EBXs5uO43SobeIkShH3Nujq5gLMD5kWoJXTxDrTgJe4wT42EwUaBEH2Q== + +"@node-rs/jieba-darwin-x64@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-darwin-x64/-/jieba-darwin-x64-1.6.1.tgz#ddd964b7874c208b964897898c5826ef195efcad" + integrity sha512-ENHYIS8b8JdMaUXEm0f8Y3+sHXu2UdukG1D/XGUNx+q5cn07HbwIg6L0tlGhE8dw4AhqoWHsExVaZ241Igh4iA== + +"@node-rs/jieba-freebsd-x64@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-freebsd-x64/-/jieba-freebsd-x64-1.6.1.tgz#8e8be576d471c0837dcf4a6130ab055cca588e80" + integrity sha512-chwB/9edtxqS8Jm3j4RMaJjH9AlXmijUgKv02oMw36e77HKpko+tENUN25Vrn/9GKsKGqIPeXpmCjeXCN1HVQA== + +"@node-rs/jieba-linux-arm-gnueabihf@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-linux-arm-gnueabihf/-/jieba-linux-arm-gnueabihf-1.6.1.tgz#be1c7205f0ecf03f8f9065ad60b58bb4f7615d71" + integrity sha512-tsb5fMGj4p8bHGfkf7bJ+HE2jxaixLTp3YnGg5D+kp8+HQRq8cp3ScG5cn8cq0phnJS/zfAp8rVfWInDagzKKQ== + +"@node-rs/jieba-linux-arm64-gnu@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-linux-arm64-gnu/-/jieba-linux-arm64-gnu-1.6.1.tgz#43608a4506f6b47bec3349312a18c1a51b6f3822" + integrity sha512-bSInORkJFfeZNR+i4rFoSZGbwkQtQlnZ0XfT/noTK9JUBDYErqQZPFjoaYAU45NWTk7p6Zkg30SuV1NTdWLaPw== + +"@node-rs/jieba-linux-arm64-musl@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-linux-arm64-musl/-/jieba-linux-arm64-musl-1.6.1.tgz#aef63ab32d3caa4ab7cc0f717dd7a6e774083b9b" + integrity sha512-qphL6xM7owfU8Hsh7GX73SDr/iApbnc+35mSLxbibAfCQnY89+WcBeWUUOSGM/Ov3VFaq4pyVlDFj0YjR01W2w== + +"@node-rs/jieba-linux-x64-gnu@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-linux-x64-gnu/-/jieba-linux-x64-gnu-1.6.1.tgz#8e09bb2c57fc546acc9cf8e1c879dcdf01e79717" + integrity sha512-f6hhlrbi2wel0xZG7m3Wvksimt9MSu1f3aYO2Kwavf4qjMRZqJzLz9HlCJAal6AXB9Qgg+685P+gftsWve47qw== + +"@node-rs/jieba-linux-x64-musl@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-linux-x64-musl/-/jieba-linux-x64-musl-1.6.1.tgz#f698db4b49cfd367b5c3f6b4352d5092ab3620e2" + integrity sha512-cTVcdR6zWqpnmdEUyWEII9zfE5lTeWN53TbiOPx8TCA+291/31Vqd7GA8YEPndUO8qgCx5uShSDFStBAEIhYNQ== + +"@node-rs/jieba-win32-arm64-msvc@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-win32-arm64-msvc/-/jieba-win32-arm64-msvc-1.6.1.tgz#43a20ca596eac90659a64721f0ad2130b2be199e" + integrity sha512-YuOTrjHazDraXcGXRHgPQ53nyJuH8QtTCngYKjAzxsdt8uN+txb1AY69OLMLBBZqLTOwY9dgcW70vGiLQMCTeg== + +"@node-rs/jieba-win32-ia32-msvc@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-win32-ia32-msvc/-/jieba-win32-ia32-msvc-1.6.1.tgz#eec9062cdc5dd951f7177576993bbc32fa405416" + integrity sha512-4+E843ImGpVlZ+LlT9E/13NHmmUg3UHQx419D6fFMorJUUQuK4cZJfE1z4tCgcrbV8S5Wew5LIFywlJeJLu0LQ== + +"@node-rs/jieba-win32-x64-msvc@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-win32-x64-msvc/-/jieba-win32-x64-msvc-1.6.1.tgz#3df4853afc175e4dd43794b08a71e8d25d00e807" + integrity sha512-veXNwm2VlseOzl7vaC7A/nZ4okp5/6edN7/Atj6mXnUbze/m/my5Rv5zUcW3U1D9VElnQ3srCHCa5vXljJuk6g== + +"@node-rs/jieba@^1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba/-/jieba-1.6.1.tgz#221aa586aa671cb029687256a4c86c86bfecbef9" + integrity sha512-pISKu8NIYKRvZp7mhYZYA8VCjJMqTsCe+mQcFFnAi3GNJsijGjef2peMFeDcvP72X8MsnNeYeg3rHkAybtefyQ== + optionalDependencies: + "@node-rs/jieba-android-arm-eabi" "1.6.1" + "@node-rs/jieba-android-arm64" "1.6.1" + "@node-rs/jieba-darwin-arm64" "1.6.1" + "@node-rs/jieba-darwin-x64" "1.6.1" + "@node-rs/jieba-freebsd-x64" "1.6.1" + "@node-rs/jieba-linux-arm-gnueabihf" "1.6.1" + "@node-rs/jieba-linux-arm64-gnu" "1.6.1" + "@node-rs/jieba-linux-arm64-musl" "1.6.1" + "@node-rs/jieba-linux-x64-gnu" "1.6.1" + "@node-rs/jieba-linux-x64-musl" "1.6.1" + "@node-rs/jieba-win32-arm64-msvc" "1.6.1" + "@node-rs/jieba-win32-ia32-msvc" "1.6.1" + "@node-rs/jieba-win32-x64-msvc" "1.6.1" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -2016,11 +2130,21 @@ dependencies: "@types/istanbul-lib-report" "*" +"@types/js-cookie@^2.2.6": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3" + integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA== + "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== +"@types/lodash@^4.14.186": + version "4.14.186" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.186.tgz#862e5514dd7bd66ada6c70ee5fce844b06c8ee97" + integrity sha512-eHcVlLXP0c2FlMPm56ITode2AgLMSa6aJ05JTTbYbI+7EMkCEE5qk2E41d5g2lCVTqRe0GnnRFurmlCsDODrPw== + "@types/mdast@^3.0.0": version "3.0.10" resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" @@ -2292,6 +2416,11 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" +"@xobotyi/scrollbar-width@^1.9.5": + version "1.9.5" + resolved "https://registry.yarnpkg.com/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz#80224a6919272f405b87913ca13b92929bdf3c4d" + integrity sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -2827,7 +2956,7 @@ cheerio-select@^2.1.0: domhandler "^5.0.3" domutils "^3.0.1" -cheerio@^1.0.0-rc.12: +cheerio@^1.0.0-rc.12, cheerio@^1.0.0-rc.3: version "1.0.0-rc.12" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== @@ -2917,7 +3046,7 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" -clsx@^1.2.1: +clsx@^1.1.1, clsx@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== @@ -3082,7 +3211,7 @@ copy-text-to-clipboard@^3.0.1: resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== -copy-to-clipboard@^3.3.2: +copy-to-clipboard@^3.3.1, copy-to-clipboard@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz#5b263ec2366224b100181dded7ce0579b340c107" integrity sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg== @@ -3171,6 +3300,14 @@ css-declaration-sorter@^6.3.0: resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz#be5e1d71b7a992433fb1c542c7a1b835e45682ec" integrity sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w== +css-in-js-utils@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz#3b472b398787291b47cfe3e44fecfdd9e914ba99" + integrity sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA== + dependencies: + hyphenate-style-name "^1.0.2" + isobject "^3.0.1" + css-loader@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.1.tgz#e98106f154f6e1baf3fc3bc455cb9981c1d5fd2e" @@ -3305,7 +3442,7 @@ csso@^4.2.0: dependencies: css-tree "^1.1.2" -csstype@^3.0.2: +csstype@^3.0.2, csstype@^3.0.6: version "3.1.1" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== @@ -3317,7 +3454,7 @@ debug@2.6.9, debug@^2.6.0: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -3608,6 +3745,13 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-stack-parser@^2.0.6: + version "2.1.4" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== + dependencies: + stackframe "^1.3.4" + es-module-lexer@^0.9.0: version "0.9.3" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" @@ -3801,6 +3945,11 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-shallow-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz#d4dcaf6472440dcefa6f88b98e3251e27f25628b" + integrity sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw== + fast-url-parser@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" @@ -3808,6 +3957,11 @@ fast-url-parser@1.1.3: dependencies: punycode "^1.3.2" +fastest-stable-stringify@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz#3757a6774f6ec8de40c4e86ec28ea02417214c76" + integrity sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q== + fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -3966,7 +4120,7 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-extra@^10.1.0: +fs-extra@^10.0.0, fs-extra@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== @@ -4147,7 +4301,7 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -4440,6 +4594,11 @@ husky@^8.0.1: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.1.tgz#511cb3e57de3e3190514ae49ed50f6bc3f50b3e9" integrity sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw== +hyphenate-style-name@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" + integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -4464,6 +4623,11 @@ image-size@^1.0.1: dependencies: queue "6.0.2" +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + immer@^9.0.7: version "9.0.15" resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc" @@ -4535,6 +4699,13 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +inline-style-prefixer@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-6.0.1.tgz#c5c0e43ba8831707afc5f5bbfd97edf45c1fa7ae" + integrity sha512-AsqazZ8KcRzJ9YPN1wMH2aNM7lkWQ8tSPrW5uDk1ziYwiAPWSZnUsC7lfZq+BDqLqz0B4Pho5wscWcJzVvRzDQ== + dependencies: + css-in-js-utils "^2.0.0" + interpret@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" @@ -4797,6 +4968,11 @@ joi@^17.6.0: "@sideway/formula" "^3.0.0" "@sideway/pinpoint" "^2.0.0" +js-cookie@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" + integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -4873,6 +5049,13 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -5007,6 +5190,16 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lunr-languages@^1.4.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/lunr-languages/-/lunr-languages-1.10.0.tgz#2afe9fff47b435d9bc74bd372fb923dbf8ee1990" + integrity sha512-BBjKKcwrieJlzwwc9M5H/MRXGJ2qyOSDx/NXYiwkuKjiLOOoouh0WsDzeqcLoUWcX31y7i8sb8IgsZKObdUCkw== + +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -5014,6 +5207,11 @@ make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: dependencies: semver "^6.0.0" +mark.js@^8.11.1: + version "8.11.1" + resolved "https://registry.yarnpkg.com/mark.js/-/mark.js-8.11.1.tgz#180f1f9ebef8b0e638e4166ad52db879beb2ffc5" + integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== + markdown-escapes@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" @@ -5216,6 +5414,20 @@ multimatch@^4.0.0: arrify "^2.0.1" minimatch "^3.0.4" +nano-css@^5.3.1: + version "5.3.5" + resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.3.5.tgz#3075ea29ffdeb0c7cb6d25edb21d8f7fa8e8fe8e" + integrity sha512-vSB9X12bbNu4ALBu7nigJgRViZ6ja3OU7CeuiV1zMIbXOdmkLahgtPmh3GBOlDxbKY0CitqlPdOReGlBLSp+yg== + dependencies: + css-tree "^1.1.2" + csstype "^3.0.6" + fastest-stable-stringify "^2.0.2" + inline-style-prefixer "^6.0.0" + rtl-css-js "^1.14.0" + sourcemap-codec "^1.4.8" + stacktrace-js "^2.0.2" + stylis "^4.0.6" + nanoid@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" @@ -6199,6 +6411,31 @@ react-textarea-autosize@^8.3.2: use-composed-ref "^1.3.0" use-latest "^1.2.1" +react-universal-interface@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b" + integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw== + +react-use@^17.4.0: + version "17.4.0" + resolved "https://registry.yarnpkg.com/react-use/-/react-use-17.4.0.tgz#cefef258b0a6c534a5c8021c2528ac6e1a4cdc6d" + integrity sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q== + dependencies: + "@types/js-cookie" "^2.2.6" + "@xobotyi/scrollbar-width" "^1.9.5" + copy-to-clipboard "^3.3.1" + fast-deep-equal "^3.1.3" + fast-shallow-equal "^1.0.0" + js-cookie "^2.2.1" + nano-css "^5.3.1" + react-universal-interface "^0.6.2" + resize-observer-polyfill "^1.5.1" + screenfull "^5.1.0" + set-harmonic-interval "^1.0.1" + throttle-debounce "^3.0.1" + ts-easing "^0.2.0" + tslib "^2.1.0" + react@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" @@ -6410,6 +6647,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +resize-observer-polyfill@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -6453,6 +6695,13 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rtl-css-js@^1.14.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/rtl-css-js/-/rtl-css-js-1.16.0.tgz#e8d682982441aadb63cabcb2f7385f3fb78ff26e" + integrity sha512-Oc7PnzwIEU4M0K1J4h/7qUUaljXhQ0kCObRsZjxs2HjkpKsnoTMvSmvJ4sqgJZd0zBoEfAyTdnK/jMIYvrjySQ== + dependencies: + "@babel/runtime" "^7.1.2" + rtl-detect@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" @@ -6567,6 +6816,11 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.0.0" +screenfull@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba" + integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== + section-matter@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" @@ -6674,6 +6928,11 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" +set-harmonic-interval@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249" + integrity sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g== + setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -6802,6 +7061,11 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA== + source-map@^0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -6812,6 +7076,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +sourcemap-codec@^1.4.8: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + space-separated-tokens@^1.0.0: version "1.1.5" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" @@ -6850,6 +7119,35 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-generator@^2.0.5: + version "2.0.10" + resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.10.tgz#8ae171e985ed62287d4f1ed55a1633b3fb53bb4d" + integrity sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ== + dependencies: + stackframe "^1.3.4" + +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== + +stacktrace-gps@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz#0c40b24a9b119b20da4525c398795338966a2fb0" + integrity sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ== + dependencies: + source-map "0.5.6" + stackframe "^1.3.4" + +stacktrace-js@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b" + integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg== + dependencies: + error-stack-parser "^2.0.6" + stack-generator "^2.0.5" + stacktrace-gps "^3.0.4" + state-toggle@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" @@ -6960,6 +7258,11 @@ stylehacks@^5.1.0: browserslist "^4.16.6" postcss-selector-parser "^6.0.4" +stylis@^4.0.6: + version "4.1.2" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.2.tgz#870b3c1c2275f51b702bb3da9e94eedad87bba41" + integrity sha512-Nn2CCrG2ZaFziDxaZPN43CXqn+j7tcdjPFCkRBkFue8QYXC2HdEwnw5TCBo4yQZ2WxKYeSi0fdoOrtEqgDrXbA== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -7040,6 +7343,11 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +throttle-debounce@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-3.0.1.tgz#32f94d84dfa894f786c9a1f290e7a645b6a19abb" + integrity sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg== + thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" @@ -7107,6 +7415,11 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== +ts-easing@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec" + integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ== + tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"