Skip to content

Commit

Permalink
feat!: Add Search
Browse files Browse the repository at this point in the history
  • Loading branch information
3y3 committed Sep 20, 2024
1 parent 935765b commit 57c3947
Show file tree
Hide file tree
Showing 17 changed files with 509 additions and 68 deletions.
2 changes: 1 addition & 1 deletion src/components/App/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function RichNavPage({data, props, controls}: PageProps<WithNavigation>)

const CustomSuggest = useCallback(() => <Suggest />, []);
const CustomControls = useCallback(() => <HeaderControls {...controls} />, [controls]);
const navigation = useNavigation(data, CustomControls, CustomSuggest);
const navigation = useNavigation(data, controls, CustomControls, CustomSuggest);

const CustomPage = useCallback(
() => (
Expand Down
76 changes: 45 additions & 31 deletions src/components/App/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type {NavigationData, PageContent} from '@gravity-ui/page-constructor';
import type {ReactElement} from 'react';
import type {Props as HeaderControlsProps} from '../HeaderControls';
import type {SearchConfig} from '../Search';
import type {RouterConfig} from '../Router';

import React, {useEffect} from 'react';
import React, {useEffect, useMemo} from 'react';
import {ThemeProvider} from '@gravity-ui/uikit';
import {
ConsentPopup,
Expand All @@ -11,11 +13,12 @@ import {
DocLeadingPageData,
DocPageData,
Lang,
Router,
configure,
} from '@diplodoc/components';
import '@diplodoc/transform/dist/js/yfm';

import {SearchProvider} from '../Search';
import {RouterProvider} from '../Router';
import {getDirection, updateRootClassName, updateThemeClassName} from '../../utils';
import {LangProvider} from '../../hooks/useLang';
import '../../interceptors/leading-page-links';
Expand All @@ -38,7 +41,8 @@ export type DocAnalytics = {
export interface AppProps {
lang: Lang;
langs: Lang[];
router: Router;
router: RouterConfig;
search?: SearchConfig;
analytics?: DocAnalytics;
}

Expand All @@ -63,7 +67,7 @@ function hasNavigation(
}

export function App(props: DocInnerProps): ReactElement {
const {data, router, lang, analytics} = props;
const {data, router, lang, search, analytics} = props;

configure({
lang,
Expand All @@ -75,20 +79,26 @@ export function App(props: DocInnerProps): ReactElement {

const {theme, textSize, wideFormat, fullScreen, showMiniToc} = settings;

const page = {
router,

theme,
textSize,
wideFormat,
fullScreen,
showMiniToc,
};
const controls: HeaderControlsProps = {
...settings,
...langs,
mobileView,
};
const page = useMemo(
() => ({
router,

theme,
textSize,
wideFormat,
fullScreen,
showMiniToc,
}),
[router, theme, textSize, wideFormat, fullScreen, showMiniToc],
);
const controls: HeaderControlsProps = useMemo(
() => ({
...settings,
...langs,
mobileView,
}),
[langs, settings, mobileView],
);
const direction = getDirection(lang);

useEffect(() => {
Expand All @@ -100,19 +110,23 @@ export function App(props: DocInnerProps): ReactElement {
<div className="App">
<ThemeProvider theme={theme} direction={direction}>
<LangProvider value={lang}>
{hasNavigation(data) ? (
<RichNavPage data={data} props={page} controls={controls} />
) : (
<LegacyNavPage data={data} props={page} controls={controls} />
)}
{analytics && (
<ConsentPopup
router={router}
gtmId={analytics?.gtm?.id || ''}
consentMode={analytics?.gtm?.mode}
/>
)}
<Runtime />
<RouterProvider value={router}>
<SearchProvider value={search}>
{hasNavigation(data) ? (
<RichNavPage data={data} props={page} controls={controls} />
) : (
<LegacyNavPage data={data} props={page} controls={controls} />
)}
{analytics && (
<ConsentPopup
router={router}
gtmId={analytics?.gtm?.id || ''}
consentMode={analytics?.gtm?.mode}
/>
)}
<Runtime />
</SearchProvider>
</RouterProvider>
</LangProvider>
</ThemeProvider>
</div>
Expand Down
49 changes: 31 additions & 18 deletions src/components/ConstructorPage/useNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@ import type {ReactNode} from 'react';
import type {NavigationData} from '@gravity-ui/page-constructor';
import type {DocBasePageData} from '@diplodoc/components';
import type {WithNavigation} from '../App';
import type {Props as HeaderControlsProps} from '../HeaderControls';

import React, { useMemo } from 'react';
import { ControlSizes, CustomNavigation, MobileDropdown } from '@diplodoc/components';
import React, {useMemo} from 'react';
import {ControlSizes, CustomNavigation, MobileDropdown} from '@diplodoc/components';

import {HEADER_HEIGHT} from '../../constants';
import {useRouter} from '../';

export const useNavigation = (
data: DocBasePageData<WithNavigation>,
controls: HeaderControlsProps,
CustomControls: () => ReactNode,
CustomSuggest: () => ReactNode,
) => {
const {toc} = data;
const {navigation} = toc;
Expand All @@ -20,22 +24,30 @@ export const useNavigation = (
const withControls = rightItems.some((item: {type: string}) => item.type === 'controls');

const router = useRouter();
const userSettings = useSettings();

const navigationData = useMemo(() => ({
withBorder: true,
leftItems: leftItems,
rightItems: rightItems,
}), [leftItems, rightItems]);
const navigationTocData = useMemo(() => ({
toc,
router,
headerHeight: HEADER_HEIGHT
}), [toc, router]);
const mobileControlsData = useMemo(() => ({
controlSize: ControlSizes.L,
userSettings
}), [userSettings]);
const navigationData = useMemo(
() => ({
withBorder: true,
leftItems: leftItems,
rightItems: rightItems,
}),
[leftItems, rightItems],
);
const navigationTocData = useMemo(
() => ({
toc,
router,
headerHeight: HEADER_HEIGHT,
}),
[toc, router],
);
const mobileControlsData = useMemo(
() => ({
controlSize: ControlSizes.L,
userSettings: controls,
}),
[controls],
);

const layout = useMemo(
() => ({
Expand All @@ -58,13 +70,14 @@ export const useNavigation = (
const config = useMemo(
() => ({
custom: {
search: CustomSuggest,
controls: CustomControls,
MobileDropdown: MobileDropdown,
},
layout,
withControls,
}),
[CustomControls, layout, withControls],
[CustomSuggest, CustomControls, layout, withControls],
);

return config;
Expand Down
20 changes: 20 additions & 0 deletions src/components/Router/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type {Router} from '@diplodoc/components';

import {createContext, useContext} from 'react';

export interface RouterConfig extends Router {
depth: number;
}

export const RouterContext = createContext<RouterConfig>({
pathname: '/',
depth: 0,
});

RouterContext.displayName = 'RouterContext';

export const RouterProvider = RouterContext.Provider;

export function useRouter() {
return useContext(RouterContext);
}
5 changes: 5 additions & 0 deletions src/components/Search/Search.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react';

export const Search = () => {
return <div>Initial</div>;
};
17 changes: 17 additions & 0 deletions src/components/Search/Suggest.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.Suggest {
margin-right: 20px;
min-width: 200px;
transition: min-width 0.3s;

.dc-root_focused-search & {
min-width: 500px;
}

&__Item {
&__Marker {
background: var(--g-color-base-neutral-medium);
padding: 0 3px 1px;
border-radius: 4px;
}
}
}
41 changes: 41 additions & 0 deletions src/components/Search/Suggest.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type {ISearchProvider, SearchSuggestApi} from '@diplodoc/components';

import React, {useCallback, useRef} from 'react';
import {SearchSuggest} from '@diplodoc/components';

import {updateRootClassName} from '../../utils';

import {useProvider} from './useProvider';
import './Suggest.scss';

export function Suggest() {
const provider: ISearchProvider | null = useProvider();
const suggest = useRef<SearchSuggestApi>(null);

const onFocus = useCallback(() => {
updateRootClassName({focusSearch: true});
}, []);

const onBlur = useCallback(() => {
updateRootClassName({focusSearch: false});
setTimeout(() => {
if (suggest.current) {
suggest.current.close();
}
}, 100);
}, []);

if (!provider) {
return null;
}

return (
<SearchSuggest
ref={suggest}
provider={provider}
onFocus={onFocus}
onBlur={onBlur}
classNameContainer={'Suggest'}
/>
);
}
13 changes: 13 additions & 0 deletions src/components/Search/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {SearchConfig, WorkerApi, WorkerConfig} from './types';

import {createContext} from 'react';

export type {SearchConfig, WorkerConfig, WorkerApi};

export const SearchContext = createContext<SearchConfig | null | undefined>(null);

SearchContext.displayName = 'SearchContext';

export const SearchProvider = SearchContext.Provider;

export {Search} from './Search';
Loading

0 comments on commit 57c3947

Please sign in to comment.