Skip to content

Commit 7d7001b

Browse files
authored
feat(Navigation): add custom elements support (#517)
Co-authored-by: 3y3 <[email protected]>
1 parent fb0fb2d commit 7d7001b

File tree

12 files changed

+97
-60
lines changed

12 files changed

+97
-60
lines changed

src/constructor-items.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@ import {
1818
TableBlock,
1919
TabsBlock,
2020
} from './blocks';
21-
import {BlockType, SubBlockType} from './models';
21+
import {BlockType, NavigationItemType, SubBlockType} from './models';
22+
import {
23+
GithubButton,
24+
NavigationButton,
25+
NavigationDropdown,
26+
NavigationLink,
27+
} from './navigation/components/NavigationItem';
28+
import SocialIcon from './navigation/components/SocialIcon/SocialIcon';
2229
import {
2330
BackgroundCard,
2431
BannerCard,
@@ -63,3 +70,11 @@ export const subBlockMap = {
6370
[SubBlockType.Content]: Content,
6471
[SubBlockType.Quote]: Quote,
6572
};
73+
74+
export const navItemMap = {
75+
[NavigationItemType.Button]: NavigationButton,
76+
[NavigationItemType.Social]: SocialIcon,
77+
[NavigationItemType.Dropdown]: NavigationDropdown,
78+
[NavigationItemType.Link]: NavigationLink,
79+
[NavigationItemType.GithubButton]: GithubButton,
80+
};

src/containers/PageConstructor/PageConstructor.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import blockOrigin from 'bem-cn-lite';
55

66
import BackgroundMedia from '../../components/BackgroundMedia/BackgroundMedia';
77
import {UIKIT_ROOT_CLASS} from '../../components/constants';
8-
import {blockMap, subBlockMap} from '../../constructor-items';
8+
import {blockMap, navItemMap, subBlockMap} from '../../constructor-items';
99
import {AnimateContext} from '../../context/animateContext';
1010
import {InnerContext} from '../../context/innerContext';
1111
import {useTheme} from '../../context/theme';
@@ -17,17 +17,16 @@ import {
1717
CustomItems,
1818
HeaderBlockTypes,
1919
NavigationData,
20+
NavigationItemTypes,
2021
PageContent,
2122
ShouldRenderBlock,
2223
SubBlockTypes,
2324
} from '../../models';
2425
import Layout from '../../navigation/containers/Layout/Layout';
2526
import {
2627
block as cnBlock,
27-
getCustomBlockTypes,
28-
getCustomHeaderTypes,
2928
getCustomItems,
30-
getCustomSubBlockTypes,
29+
getCustomTypes,
3130
getHeaderBlock,
3231
getOrderedBlocks,
3332
getThemedValue,
@@ -44,6 +43,8 @@ const ycr = blockOrigin(UIKIT_ROOT_CLASS);
4443

4544
export type ItemMap = typeof blockMap & typeof subBlockMap & CustomItems;
4645

46+
export type NavItemMap = typeof navItemMap & CustomItems;
47+
4748
export interface PageConstructorProps {
4849
content?: PageContent;
4950
shouldRenderBlock?: ShouldRenderBlock;
@@ -64,13 +65,21 @@ export const Constructor = (props: PageConstructorProps) => {
6465
const {context} = useMemo(
6566
() => ({
6667
context: {
67-
blockTypes: [...BlockTypes, ...getCustomBlockTypes(custom)],
68-
subBlockTypes: [...SubBlockTypes, ...getCustomSubBlockTypes(custom)],
69-
headerBlockTypes: [...HeaderBlockTypes, ...getCustomHeaderTypes(custom)],
68+
blockTypes: [...BlockTypes, ...getCustomTypes(['blocks', 'headers'], custom)],
69+
subBlockTypes: [...SubBlockTypes, ...getCustomTypes(['subBlocks'], custom)],
70+
headerBlockTypes: [...HeaderBlockTypes, ...getCustomTypes(['headers'], custom)],
71+
navigationBlockTypes: [
72+
...NavigationItemTypes,
73+
...getCustomTypes(['navigation'], custom),
74+
],
7075
itemMap: {
7176
...blockMap,
7277
...subBlockMap,
73-
...getCustomItems(custom),
78+
...getCustomItems(['blocks', 'headers', 'subBlocks'], custom),
79+
},
80+
navItemMap: {
81+
...navItemMap,
82+
...getCustomItems(['navigation'], custom),
7483
},
7584
loadables: custom?.loadable,
7685
shouldRenderBlock,

src/context/innerContext/InnerContext.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import React from 'react';
22

3-
import {ItemMap} from '../../containers/PageConstructor/PageConstructor';
3+
import {ItemMap, NavItemMap} from '../../containers/PageConstructor/PageConstructor';
44
import {CustomConfig, LoadableConfig, ShouldRenderBlock} from '../../models';
55

66
export interface InnerContextType {
77
blockTypes: string[];
88
subBlockTypes: string[];
99
headerBlockTypes: string[];
10+
navigationBlockTypes: string[];
1011
itemMap: ItemMap;
12+
navItemMap: NavItemMap;
1113
loadables?: LoadableConfig;
1214
shouldRenderBlock?: ShouldRenderBlock;
1315
customization?: Pick<CustomConfig, 'decorators'>;
@@ -17,5 +19,7 @@ export const InnerContext = React.createContext<InnerContextType>({
1719
blockTypes: [],
1820
subBlockTypes: [],
1921
headerBlockTypes: [],
22+
navigationBlockTypes: [],
2023
itemMap: {} as ItemMap,
24+
navItemMap: {} as NavItemMap,
2125
});

src/editor/store/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {useMemo, useReducer} from 'react';
22

33
import {DEFAULT_THEME} from '../../components/constants';
44
import {Block, BlockDecorationProps, HeaderBlockTypes, PageContent, Theme} from '../../models';
5-
import {getCustomHeaderTypes, getHeaderBlock} from '../../utils';
5+
import {getCustomTypes, getHeaderBlock} from '../../utils';
66
import {EditBlockActions, EditBlockControls} from '../components/EditBlock/EditBlock';
77
import {EditBlockProps, EditorProps, ViewModeItem} from '../types';
88

@@ -34,7 +34,7 @@ export function useEditorState({content: intialContent, custom}: Omit<EditorProp
3434
);
3535

3636
return useMemo(() => {
37-
const headerBlockTypes = [...HeaderBlockTypes, ...getCustomHeaderTypes(custom)];
37+
const headerBlockTypes = [...HeaderBlockTypes, ...getCustomTypes(['headers'], custom)];
3838
const contentHasHeader = Boolean(getHeaderBlock(content.blocks, headerBlockTypes));
3939
const checkIsHeader = (type: string) => headerBlockTypes.includes(type);
4040

src/models/constructor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export interface CustomConfig {
6363
blocks?: CustomItems;
6464
subBlocks?: CustomItems;
6565
headers?: CustomItems;
66+
navigation?: CustomItems;
6667
loadable?: LoadableConfig;
6768
decorators?: {
6869
block?: ((props: BlockDecorationProps) => React.ReactElement)[];

src/models/navigation.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export enum NavigationItemType {
1010
GithubButton = 'github-button',
1111
}
1212

13+
export const NavigationItemTypes = Object.values(NavigationItemType);
14+
1315
export interface NavigationItemBase {
1416
text: string;
1517
icon?: ImageProps;

src/navigation/__stories__/Navigation.stories.tsx

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React from 'react';
33
import {Meta, StoryFn} from '@storybook/react';
44

55
import {PageConstructor} from '../../containers/PageConstructor';
6-
import {NavigationData} from '../../models';
6+
import {CustomConfig, NavigationData} from '../../models';
77

88
import data from './data.json';
99

@@ -12,16 +12,39 @@ export default {
1212
component: PageConstructor,
1313
} as Meta;
1414

15-
const DefaultTemplate: StoryFn<NavigationData> = (args) => <PageConstructor navigation={args} />;
15+
const DefaultTemplate: StoryFn<{
16+
navigation: NavigationData;
17+
custom?: CustomConfig;
18+
}> = ({navigation, custom = {}}) => <PageConstructor navigation={navigation} custom={custom} />;
1619
export const DefaultNavigation = DefaultTemplate.bind({});
1720
export const NavigationWithBorder = DefaultTemplate.bind({});
21+
export const NavigationWithCustomItems = DefaultTemplate.bind({});
1822

19-
DefaultNavigation.args = data.navigation as NavigationData;
23+
DefaultNavigation.args = {
24+
navigation: data.navigation as NavigationData,
25+
};
2026

2127
NavigationWithBorder.args = {
22-
...data.navigation,
23-
header: {
24-
...data.navigation.header,
25-
withBorder: true,
28+
navigation: {
29+
...data.navigation,
30+
header: {
31+
...data.navigation.header,
32+
withBorder: true,
33+
},
34+
} as NavigationData,
35+
};
36+
37+
NavigationWithCustomItems.args = {
38+
custom: {
39+
navigation: {
40+
search: () => <div>Search</div>,
41+
},
2642
},
27-
} as NavigationData;
43+
navigation: {
44+
...data.navigation,
45+
header: {
46+
...data.navigation.header,
47+
rightItems: [...data.navigation.header.rightItems, {type: 'search'}],
48+
},
49+
} as NavigationData,
50+
};

src/navigation/components/NavigationItem/NavigationItem.tsx

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,28 @@
1-
import React, {useMemo} from 'react';
1+
import React, {useContext, useMemo} from 'react';
22

33
import {omit} from 'lodash';
44

55
import {BlockIdContext} from '../../../context/blockIdContext';
6-
import {NavigationItemType} from '../../../models';
6+
import {InnerContext} from '../../../context/innerContext';
7+
import {CustomItem, NavigationItemType} from '../../../models';
78
import {block} from '../../../utils';
89
import {NavigationItemProps} from '../../models';
9-
import SocialIcon from '../SocialIcon/SocialIcon';
10-
11-
import {GithubButton} from './components/GithubButton/GithubButton';
12-
import {NavigationButton} from './components/NavigationButton/NavigationButton';
13-
import {NavigationDropdown} from './components/NavigationDropdown/NavigationDropdown';
14-
import {NavigationLink} from './components/NavigationLink/NavigationLink';
1510

1611
import './NavigationItem.scss';
1712

1813
const b = block('navigation-item');
1914

2015
const ANALYTICS_ID = 'navigation';
2116

22-
//todo: add types support form component in map
23-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
24-
const NavigationItemsMap: Record<NavigationItemType, React.ComponentType<any>> = {
25-
[NavigationItemType.Button]: NavigationButton,
26-
[NavigationItemType.Social]: SocialIcon,
27-
[NavigationItemType.Dropdown]: NavigationDropdown,
28-
[NavigationItemType.Link]: NavigationLink,
29-
[NavigationItemType.GithubButton]: GithubButton,
30-
};
31-
3217
const NavigationItem: React.FC<NavigationItemProps> = ({
3318
data,
3419
className,
3520
menuLayout,
3621
...props
3722
}: NavigationItemProps) => {
3823
const {type = NavigationItemType.Link} = data;
39-
const Component = NavigationItemsMap[type];
24+
const {navItemMap} = useContext(InnerContext);
25+
const Component = navItemMap[type] as CustomItem;
4026
const componentProps = useMemo(() => {
4127
const componentProperties = {
4228
...data,
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export {GithubButton} from './components/GithubButton/GithubButton';
2+
export {NavigationButton} from './components/NavigationButton/NavigationButton';
3+
export {NavigationDropdown} from './components/NavigationDropdown/NavigationDropdown';
4+
export {NavigationLink} from './components/NavigationLink/NavigationLink';
5+
6+
import NavigationItem from './NavigationItem';
7+
8+
export default NavigationItem;

src/navigation/components/NavigationListItem/NavigationListItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22

33
import {NavigationListItemProps} from '../../models';
44
import {getItemClickHandler} from '../../utils';
5-
import NavigationItem from '../NavigationItem/NavigationItem';
5+
import NavigationItem from '../NavigationItem';
66

77
const NavigationListItem: React.FC<NavigationListItemProps> = ({
88
column,

0 commit comments

Comments
 (0)