mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 09:26:06 +08:00
parent
fbcbf4d522
commit
0d619766e0
@ -154,6 +154,7 @@
|
|||||||
"@ant-design/bisheng-plugin": "^2.3.0",
|
"@ant-design/bisheng-plugin": "^2.3.0",
|
||||||
"@ant-design/hitu": "^0.0.0-alpha.13",
|
"@ant-design/hitu": "^0.0.0-alpha.13",
|
||||||
"@ant-design/tools": "^13.4.1-beta.0",
|
"@ant-design/tools": "^13.4.1-beta.0",
|
||||||
|
"@docsearch/react": "^3.0.0-alpha.36",
|
||||||
"@qixian.cs/github-contributors-list": "^1.0.3",
|
"@qixian.cs/github-contributors-list": "^1.0.3",
|
||||||
"@stackblitz/sdk": "^1.3.0",
|
"@stackblitz/sdk": "^1.3.0",
|
||||||
"@types/classnames": "^2.2.8",
|
"@types/classnames": "^2.2.8",
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
@import '../template/Layout/Header/DocSearch.less';
|
||||||
|
|
||||||
[data-theme='dark'] {
|
[data-theme='dark'] {
|
||||||
/* Change autocomplete styles in WebKit */
|
/* Change autocomplete styles in WebKit */
|
||||||
input:-webkit-autofill,
|
input:-webkit-autofill,
|
||||||
@ -366,4 +368,22 @@
|
|||||||
color: rgba(255, 255, 255, 0.65);
|
color: rgba(255, 255, 255, 0.65);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// customization DocSearch Modal component in dark mode
|
||||||
|
#antd_algolia_search_modal {
|
||||||
|
.customDocSearch();
|
||||||
|
|
||||||
|
// additional style reset in dark mode
|
||||||
|
--docsearch-key-gradient: @background-color-light;
|
||||||
|
--docsearch-logo-color: @white;
|
||||||
|
|
||||||
|
.DocSearch-Modal,
|
||||||
|
.DocSearch-Commands-Key {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DocSearch-Hit a {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.algolia-docsearch-suggestion--highlight {
|
.algolia-docsearch-suggestion--highlight {
|
||||||
|
padding: 0;
|
||||||
color: @primary-color;
|
color: @primary-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
site/theme/template/Layout/Header/DocSearch.less
Normal file
32
site/theme/template/Layout/Header/DocSearch.less
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// theme customization for DocSearch Modal
|
||||||
|
.customDocSearch() {
|
||||||
|
.DocSearch {
|
||||||
|
--docsearch-primary-color: @primary-color;
|
||||||
|
--docsearch-text-color: @text-color;
|
||||||
|
--docsearch-muted-color: @text-color-secondary;
|
||||||
|
--docsearch-container-background: @modal-mask-bg;
|
||||||
|
--docsearch-searchbox-shadow: inset 0 0 0 2px @primary-color;
|
||||||
|
|
||||||
|
// Modal
|
||||||
|
--docsearch-modal-background: @modal-content-bg;
|
||||||
|
|
||||||
|
// Search box
|
||||||
|
--docsearch-searchbox-background: @input-bg;
|
||||||
|
--docsearch-searchbox-focus-background: @input-bg;
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
--docsearch-footer-background: @modal-content-bg;
|
||||||
|
|
||||||
|
// Hits
|
||||||
|
--docsearch-hit-background: @modal-content-bg;
|
||||||
|
--docsearch-hit-color: @primary-color;
|
||||||
|
--docsearch-hit-active-color: @text-color-inverse;
|
||||||
|
--docsearch-highlight-color: @primary-color;
|
||||||
|
|
||||||
|
// apply antd modal style
|
||||||
|
.DocSearch-Footer {
|
||||||
|
border-top: @modal-footer-border-width @modal-footer-border-style
|
||||||
|
@modal-footer-border-color-split;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
@import '../../../static/theme.less';
|
@import '../../../static/theme.less';
|
||||||
@import '../../../../../components/style/themes/default.less';
|
@import '../../../../../components/style/themes/default.less';
|
||||||
@import './index.less';
|
@import './index.less';
|
||||||
|
@import './DocSearch.less';
|
||||||
|
|
||||||
@search-icon-color: #ced4d9;
|
@search-icon-color: #ced4d9;
|
||||||
|
|
||||||
@ -17,6 +18,23 @@
|
|||||||
border-left: 1px solid @site-border-color-split;
|
border-left: 1px solid @site-border-color-split;
|
||||||
transition: width 0.5s;
|
transition: width 0.5s;
|
||||||
|
|
||||||
|
.keybindings {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keybinding {
|
||||||
|
color: @search-icon-color;
|
||||||
|
kbd {
|
||||||
|
display: inline-block;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
padding: 0;
|
||||||
|
// better keybinding font display using `Arial`
|
||||||
|
font-family: Arial; /* stylelint-disable-line font-family-no-missing-generic-family-keyword */
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ant-row-rtl & {
|
.ant-row-rtl & {
|
||||||
margin: 0 0 0 auto !important;
|
margin: 0 0 0 auto !important;
|
||||||
padding-right: 16px;
|
padding-right: 16px;
|
||||||
@ -39,6 +57,12 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-input-affix-wrapper {
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
@ -136,3 +160,28 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.DocSearch {
|
||||||
|
font-family: @font-family;
|
||||||
|
}
|
||||||
|
|
||||||
|
#antd_algolia_search_modal {
|
||||||
|
// avoid the veritcal scrollbar(looks like a white block)
|
||||||
|
.DocSearch-Hit-title {
|
||||||
|
overflow-y: hidden;
|
||||||
|
|
||||||
|
mark {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset original `box-shadow` style
|
||||||
|
.DocSearch-Footer {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// customization DocSearch Modal component in light mode
|
||||||
|
body[data-theme='default'] #antd_algolia_search_modal {
|
||||||
|
.customDocSearch();
|
||||||
|
}
|
196
site/theme/template/Layout/Header/SearchBar.tsx
Normal file
196
site/theme/template/Layout/Header/SearchBar.tsx
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import * as ReactDOM from 'react-dom';
|
||||||
|
import { Link, browserHistory } from 'bisheng/router';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { Helmet } from 'react-helmet-async';
|
||||||
|
import canUseDom from 'rc-util/lib/Dom/canUseDom';
|
||||||
|
import { Input, Tooltip, Typography } from 'antd';
|
||||||
|
import { SearchOutlined } from '@ant-design/icons';
|
||||||
|
import { DocSearchProps, useDocSearchKeyboardEvents, DocSearchModalProps } from '@docsearch/react';
|
||||||
|
import '@docsearch/css';
|
||||||
|
|
||||||
|
import { SharedProps } from './interface';
|
||||||
|
import { IAlgoliaConfig, transformHitUrl } from './algolia-config';
|
||||||
|
|
||||||
|
import './SearchBar.less';
|
||||||
|
|
||||||
|
const { Text } = Typography;
|
||||||
|
|
||||||
|
export interface SearchBarProps extends SharedProps {
|
||||||
|
onTriggerFocus?: (focus: boolean) => void;
|
||||||
|
responsive: null | 'narrow' | 'crowded';
|
||||||
|
algoliaConfig: IAlgoliaConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
let SearchModal: React.FC<DocSearchModalProps> | null = null;
|
||||||
|
|
||||||
|
const Hit: DocSearchProps['hitComponent'] = ({ hit, children }) => {
|
||||||
|
const toUrl = React.useMemo(() => transformHitUrl(hit.url), [hit.url]);
|
||||||
|
return <Link to={toUrl}>{children}</Link>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CTRL_KEY = 'Ctrl';
|
||||||
|
const CMD_KEY = '⌘';
|
||||||
|
|
||||||
|
function isAppleDevice() {
|
||||||
|
return /(mac|iphone|ipod|ipad)/i.test(navigator.platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recompose for algolia DocSearch Component Inspiring by
|
||||||
|
*
|
||||||
|
* - [@docusaurus-theme-search-algolia](https://docusaurus.io/docs/api/themes/@docusaurus/theme-search-algolia)
|
||||||
|
* - [DocSearchModal Docs](https://autocomplete-experimental.netlify.app/docs/DocSearchModal)
|
||||||
|
*/
|
||||||
|
export const SearchBar = ({
|
||||||
|
isZhCN,
|
||||||
|
responsive,
|
||||||
|
onTriggerFocus,
|
||||||
|
algoliaConfig,
|
||||||
|
}: SearchBarProps) => {
|
||||||
|
const [isInputFocus, setInputFocus] = React.useState(false);
|
||||||
|
const [inputSearch, setInputSearch] = React.useState('');
|
||||||
|
|
||||||
|
const [isModalOpen, setModalOpen] = React.useState(false);
|
||||||
|
const [searchModalQuery, setSearchModalQuery] = React.useState('');
|
||||||
|
const searchPlaceholder = isZhCN ? '在 ant.design 中搜索' : 'Search in ant.design';
|
||||||
|
const searchInputPlaceholder = isZhCN ? '搜索' : 'Search';
|
||||||
|
|
||||||
|
const triggerSearchModalImport = React.useCallback(() => {
|
||||||
|
if (SearchModal) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return import('@docsearch/react/modal').then(({ DocSearchModal }) => {
|
||||||
|
SearchModal = DocSearchModal;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleInputFocus = React.useCallback((focus: boolean) => {
|
||||||
|
setInputFocus(focus);
|
||||||
|
onTriggerFocus?.(focus);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleInputChange = React.useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
triggerSearchModalImport();
|
||||||
|
setInputSearch(event.target.value);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const searchModalContainer = React.useMemo(() => {
|
||||||
|
if (!canUseDom()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const id = 'antd_algolia_search_modal';
|
||||||
|
let searchModalContainer$ = document.querySelector(`#${id}`);
|
||||||
|
if (!searchModalContainer$) {
|
||||||
|
const containerDiv = document.createElement('div');
|
||||||
|
containerDiv.id = id;
|
||||||
|
document.body.appendChild(containerDiv);
|
||||||
|
searchModalContainer$ = containerDiv;
|
||||||
|
}
|
||||||
|
return searchModalContainer$;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleModalOpen = React.useCallback(() => {
|
||||||
|
triggerSearchModalImport().then(() => {
|
||||||
|
handleInputFocus(true);
|
||||||
|
setModalOpen(true);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleModalClose = React.useCallback(() => {
|
||||||
|
// clear search value in SearchModal
|
||||||
|
setSearchModalQuery('');
|
||||||
|
setModalOpen(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useDocSearchKeyboardEvents({
|
||||||
|
isOpen: isModalOpen,
|
||||||
|
onOpen: handleModalOpen,
|
||||||
|
onClose: handleModalClose,
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchParameters = React.useMemo(() => algoliaConfig.getSearchParams(isZhCN), [isZhCN]);
|
||||||
|
|
||||||
|
const navigator = React.useRef({
|
||||||
|
navigate({ itemUrl }: { itemUrl: string }) {
|
||||||
|
browserHistory.push(itemUrl);
|
||||||
|
},
|
||||||
|
}).current;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="search-box"
|
||||||
|
className={classNames({
|
||||||
|
'narrow-mode': responsive,
|
||||||
|
focused: isInputFocus,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<Helmet>
|
||||||
|
{/* pre-connect to algolia server */}
|
||||||
|
<link
|
||||||
|
rel="preconnect"
|
||||||
|
href={`https://${algoliaConfig.appId}-dsn.algolia.net`}
|
||||||
|
crossOrigin="anonymous"
|
||||||
|
/>
|
||||||
|
</Helmet>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
placeholder={searchInputPlaceholder}
|
||||||
|
onTouchStart={triggerSearchModalImport}
|
||||||
|
onMouseOver={triggerSearchModalImport}
|
||||||
|
value={inputSearch}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
onFocus={() => {
|
||||||
|
triggerSearchModalImport();
|
||||||
|
handleInputFocus(true);
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
handleInputFocus(false);
|
||||||
|
}}
|
||||||
|
prefix={<SearchOutlined />}
|
||||||
|
suffix={
|
||||||
|
typeof window !== 'undefined' && (
|
||||||
|
<Tooltip placement="right" title={isZhCN ? '唤起搜索窗' : 'Search in doc modal'}>
|
||||||
|
<span
|
||||||
|
className="keybindings"
|
||||||
|
onClick={() => {
|
||||||
|
// move userSearch to SearchModal
|
||||||
|
setSearchModalQuery(inputSearch);
|
||||||
|
setInputSearch('');
|
||||||
|
handleModalOpen();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text keyboard className="keybinding">
|
||||||
|
{isAppleDevice() ? CMD_KEY : CTRL_KEY}
|
||||||
|
</Text>
|
||||||
|
<Text keyboard className="keybinding">
|
||||||
|
K
|
||||||
|
</Text>
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{SearchModal &&
|
||||||
|
searchModalContainer &&
|
||||||
|
isModalOpen &&
|
||||||
|
ReactDOM.createPortal(
|
||||||
|
<SearchModal
|
||||||
|
navigator={navigator}
|
||||||
|
onClose={handleModalClose}
|
||||||
|
initialScrollY={window.scrollY}
|
||||||
|
initialQuery={searchModalQuery}
|
||||||
|
placeholder={searchPlaceholder}
|
||||||
|
hitComponent={Hit}
|
||||||
|
apiKey={algoliaConfig.apiKey}
|
||||||
|
indexName={algoliaConfig.indexName}
|
||||||
|
transformItems={algoliaConfig.transformData}
|
||||||
|
searchParameters={searchParameters}
|
||||||
|
/>,
|
||||||
|
searchModalContainer,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -1,62 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import { Input } from 'antd';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { SearchOutlined } from '@ant-design/icons';
|
|
||||||
import { SharedProps } from './interface';
|
|
||||||
|
|
||||||
import './SearchBox.less';
|
|
||||||
|
|
||||||
export interface SearchBoxProps extends SharedProps {
|
|
||||||
onTriggerFocus?: (focus: boolean) => void;
|
|
||||||
responsive: null | 'narrow' | 'crowded';
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ({ isZhCN, responsive, onTriggerFocus }: SearchBoxProps) => {
|
|
||||||
const inputRef = React.useRef<any>(null);
|
|
||||||
const [focused, setFocused] = React.useState(false);
|
|
||||||
const searchPlaceholder = isZhCN ? '在 ant.design 中搜索' : 'Search in ant.design';
|
|
||||||
|
|
||||||
function triggerFocus(focus: boolean) {
|
|
||||||
setFocused(focus);
|
|
||||||
onTriggerFocus?.(focus);
|
|
||||||
}
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
function keyupHandler(event: KeyboardEvent) {
|
|
||||||
if (event.keyCode === 83 && event.target === document.body) {
|
|
||||||
inputRef.current.focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('keyup', keyupHandler);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener('keyup', keyupHandler);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
id="search-box"
|
|
||||||
className={classNames({
|
|
||||||
'narrow-mode': responsive,
|
|
||||||
focused,
|
|
||||||
})}
|
|
||||||
onClick={() => {
|
|
||||||
inputRef.current.focus();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SearchOutlined />
|
|
||||||
<Input
|
|
||||||
ref={inputRef}
|
|
||||||
placeholder={searchPlaceholder}
|
|
||||||
onFocus={() => {
|
|
||||||
triggerFocus(true);
|
|
||||||
}}
|
|
||||||
onBlur={() => {
|
|
||||||
triggerFocus(false);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
28
site/theme/template/Layout/Header/algolia-config.ts
Normal file
28
site/theme/template/Layout/Header/algolia-config.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { DocSearchHit } from '@docsearch/react/dist/esm/types';
|
||||||
|
|
||||||
|
let _internalATag: HTMLAnchorElement | null;
|
||||||
|
|
||||||
|
export function transformHitUrl(hitUrl: string) {
|
||||||
|
_internalATag = _internalATag || document.createElement('a');
|
||||||
|
// `new URL` is not supported in IE
|
||||||
|
_internalATag.href = hitUrl;
|
||||||
|
return `${_internalATag.pathname}${window.location.search || ''}${_internalATag.hash}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AlgoliaConfig = {
|
||||||
|
appId: 'BH4D9OD16A',
|
||||||
|
apiKey: '60ac2c1a7d26ab713757e4a081e133d0',
|
||||||
|
indexName: 'ant_design',
|
||||||
|
getSearchParams(isZhCN: boolean) {
|
||||||
|
return { facetFilters: [`tags:${isZhCN ? 'cn' : 'en'}`] };
|
||||||
|
},
|
||||||
|
transformData(hits: DocSearchHit[]) {
|
||||||
|
hits.forEach(hit => {
|
||||||
|
hit.url = transformHitUrl(hit.url);
|
||||||
|
});
|
||||||
|
return hits;
|
||||||
|
},
|
||||||
|
debug: false, // Set debug to true if you want to inspect the dropdown
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IAlgoliaConfig = typeof AlgoliaConfig;
|
@ -3,16 +3,19 @@ import { FormattedMessage, injectIntl } from 'react-intl';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { UnorderedListOutlined } from '@ant-design/icons';
|
import { UnorderedListOutlined } from '@ant-design/icons';
|
||||||
import { Select, Row, Col, Popover, Button } from 'antd';
|
import { Select, Row, Col, Popover, Button } from 'antd';
|
||||||
|
import canUseDom from 'rc-util/lib/Dom/canUseDom';
|
||||||
|
// import { browserHistory } from 'bisheng/router';
|
||||||
|
|
||||||
import * as utils from '../../utils';
|
import * as utils from '../../utils';
|
||||||
import packageJson from '../../../../../package.json';
|
import packageJson from '../../../../../package.json';
|
||||||
import Logo from './Logo';
|
import Logo from './Logo';
|
||||||
import SearchBox from './SearchBox';
|
import { SearchBar } from './SearchBar';
|
||||||
import More from './More';
|
import More from './More';
|
||||||
import Navigation from './Navigation';
|
import Navigation from './Navigation';
|
||||||
import Github from './Github';
|
import Github from './Github';
|
||||||
import SiteContext from '../SiteContext';
|
import SiteContext from '../SiteContext';
|
||||||
import { ping } from '../../utils';
|
import { ping } from '../../utils';
|
||||||
|
import { AlgoliaConfig } from './algolia-config';
|
||||||
|
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
@ -23,35 +26,6 @@ const { Option } = Select;
|
|||||||
|
|
||||||
const antdVersion: string = packageJson.version;
|
const antdVersion: string = packageJson.version;
|
||||||
|
|
||||||
let docsearch: any;
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
// eslint-disable-next-line global-require
|
|
||||||
docsearch = require('docsearch.js');
|
|
||||||
}
|
|
||||||
|
|
||||||
function initDocSearch(locale: string) {
|
|
||||||
if (!docsearch) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const lang = locale === 'zh-CN' ? 'cn' : 'en';
|
|
||||||
docsearch({
|
|
||||||
apiKey: '60ac2c1a7d26ab713757e4a081e133d0',
|
|
||||||
indexName: 'ant_design',
|
|
||||||
inputSelector: '#search-box input',
|
|
||||||
algoliaOptions: { facetFilters: [`tags:${lang}`] },
|
|
||||||
transformData(hits: { url: string }[]) {
|
|
||||||
const a = document.createElement('a');
|
|
||||||
hits.forEach(hit => {
|
|
||||||
// `new URL` is not supported in IE
|
|
||||||
a.href = hit.url;
|
|
||||||
hit.url = `${a.pathname}${window.location.search || ''}${a.hash}`;
|
|
||||||
});
|
|
||||||
return hits;
|
|
||||||
},
|
|
||||||
debug: false, // Set debug to true if you want to inspect the dropdown
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HeaderProps {
|
export interface HeaderProps {
|
||||||
intl: {
|
intl: {
|
||||||
locale: string;
|
locale: string;
|
||||||
@ -62,6 +36,44 @@ export interface HeaderProps {
|
|||||||
changeDirection: (direction: string) => void;
|
changeDirection: (direction: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let docsearch: any;
|
||||||
|
const triggerDocSearchImport = () => {
|
||||||
|
if (docsearch) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return import('docsearch.js').then(ds => {
|
||||||
|
docsearch = ds.default;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function initDocSearch(isZhCN: boolean) {
|
||||||
|
if (!canUseDom()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
triggerDocSearchImport().then(() => {
|
||||||
|
docsearch({
|
||||||
|
appId: AlgoliaConfig.appId,
|
||||||
|
apiKey: AlgoliaConfig.apiKey,
|
||||||
|
indexName: AlgoliaConfig.indexName,
|
||||||
|
inputSelector: '#search-box input',
|
||||||
|
algoliaOptions: AlgoliaConfig.getSearchParams(isZhCN),
|
||||||
|
transformData: AlgoliaConfig.transformData,
|
||||||
|
debug: AlgoliaConfig.debug,
|
||||||
|
// https://docsearch.algolia.com/docs/behavior#handleselected
|
||||||
|
// handleSelected: (input, _$1, suggestion, _$2, context) => {
|
||||||
|
// doesn't refresh
|
||||||
|
// // Prevents the default behavior on click
|
||||||
|
// if (context.selectionMethod === 'click') {
|
||||||
|
// input.setVal('');
|
||||||
|
// browserHistory.push(suggestion.url);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
interface HeaderState {
|
interface HeaderState {
|
||||||
menuVisible: boolean;
|
menuVisible: boolean;
|
||||||
windowWidth: number;
|
windowWidth: number;
|
||||||
@ -84,7 +96,8 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { intl, router } = this.props;
|
const { intl, router } = this.props;
|
||||||
router.listen(this.handleHideMenu);
|
router.listen(this.handleHideMenu);
|
||||||
initDocSearch(intl.locale);
|
|
||||||
|
initDocSearch(intl.locale === 'zh');
|
||||||
|
|
||||||
window.addEventListener('resize', this.onWindowResize);
|
window.addEventListener('resize', this.onWindowResize);
|
||||||
this.onWindowResize();
|
this.onWindowResize();
|
||||||
@ -237,15 +250,6 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
|||||||
isRTL,
|
isRTL,
|
||||||
};
|
};
|
||||||
|
|
||||||
const searchBox = (
|
|
||||||
<SearchBox
|
|
||||||
key="search"
|
|
||||||
{...sharedProps}
|
|
||||||
responsive={responsive}
|
|
||||||
onTriggerFocus={this.onTriggerSearching}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const navigationNode = (
|
const navigationNode = (
|
||||||
<Navigation
|
<Navigation
|
||||||
key="nav"
|
key="nav"
|
||||||
@ -341,7 +345,13 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
|||||||
<Logo {...sharedProps} location={location} />
|
<Logo {...sharedProps} location={location} />
|
||||||
</Col>
|
</Col>
|
||||||
<Col {...colProps[1]} className="menu-row">
|
<Col {...colProps[1]} className="menu-row">
|
||||||
{searchBox}
|
<SearchBar
|
||||||
|
key="search"
|
||||||
|
{...sharedProps}
|
||||||
|
algoliaConfig={AlgoliaConfig}
|
||||||
|
responsive={responsive}
|
||||||
|
onTriggerFocus={this.onTriggerSearching}
|
||||||
|
/>
|
||||||
{!isMobile && menu}
|
{!isMobile && menu}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"antd/es/*": ["components/*"]
|
"antd/es/*": ["components/*"]
|
||||||
},
|
},
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
|
9
typings/custom-typings.d.ts
vendored
9
typings/custom-typings.d.ts
vendored
@ -51,3 +51,12 @@ declare module '*.json' {
|
|||||||
export const version: string;
|
export const version: string;
|
||||||
export default value;
|
export default value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '@docsearch/react/style/modal';
|
||||||
|
|
||||||
|
declare module '@docsearch/react/modal' {
|
||||||
|
import { DocSearchModal as value } from '@docsearch/react';
|
||||||
|
export const DocSearchModal = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'docsearch.js';
|
||||||
|
Loading…
Reference in New Issue
Block a user