Skip to content

Commit

Permalink
fix: review fixes, without menu item control integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Yuferev committed Mar 21, 2019
1 parent dbb1723 commit 62b9847
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 197 deletions.
23 changes: 23 additions & 0 deletions packages/core/src/menu/MenuControl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {PureComponent} from 'react'

import RenderChild from '../RenderChild'
import {MenuLevel, BaseMenuItem, MenuLevelBuilder} from './MenuLevelBuilder'

export interface MenuControlProps<Item extends BaseMenuItem> {
items: Item[]
selected: string
children: RenderChild<{
levels: MenuLevel<Item>[]
}>
}

export class MenuControl<Item extends BaseMenuItem> extends PureComponent<
MenuControlProps<Item>
> {
render() {
const {props} = this
return props.children({
levels: new MenuLevelBuilder(props.items).levels(props.selected),
})
}
}
29 changes: 15 additions & 14 deletions packages/core/src/menu/MenuLevelBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,30 @@ export type MenuTree<Item extends BaseMenuItem> = Item & {
sub?: MenuTree<Item>[]
}

export class MenuLevel<Item extends BaseMenuItem> {
constructor(public items: Item[], public activeId: string) {}
}
export type MenuLevel<Item extends BaseMenuItem> = {
items: Item[]
selected: string
} | undefined

export class MenuLevelBuilder<Item extends BaseMenuItem> {
constructor(protected items: MenuTree<Item>[]) {}

protected buildLevels(
activeId: string,
selected: string,
items: MenuTree<Item>[],
levels: (MenuLevel<Item> | undefined)[],
levels: MenuLevel<Item>[],
depth = 0,
parentActive = false
): boolean {
if (levels.length <= depth) levels.push(undefined)
let activeItem: MenuTree<Item> | undefined
for (let item of items) {
const currentActive = item.id === activeId
const currentActive = item.id === selected
const sub = item.sub
const childActive =
sub && sub.length > 0
? this.buildLevels(
activeId,
selected,
sub,
levels,
depth + 1,
Expand All @@ -43,10 +44,10 @@ export class MenuLevelBuilder<Item extends BaseMenuItem> {
}

if (activeItem || parentActive) {
levels[depth] = new MenuLevel(
levels[depth] = {
items,
activeItem ? activeItem.id : items[0].id
)
selected: activeItem ? activeItem.id : items[0].id
}
}

return !!activeItem
Expand All @@ -56,11 +57,11 @@ export class MenuLevelBuilder<Item extends BaseMenuItem> {
* Split MenuTree structure to levels.
* Returns array, where index is a menu level.
*
* @param activeId current menu item id
* @param selected current menu item id
*/
levels(activeId: string): (MenuLevel<Item> | undefined)[] {
const result: (MenuLevel<Item>[] | undefined) = []
this.buildLevels(activeId, this.items, result)
levels(selected: string): MenuLevel<Item>[] {
const result: MenuLevel<Item>[] = []
this.buildLevels(selected, this.items, result)
return result
}
}
1 change: 1 addition & 0 deletions packages/core/src/menu/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './MenuControl'
export * from './MenuLevelBuilder'
6 changes: 3 additions & 3 deletions packages/mobile/src/horizontal-menu/HorizontalMenu.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ class HorizontalMenuDemo extends React.Component {
constructor() {
super()
this.state = {
activeId: 'requests',
selected: 'requests',
}
}

render() {
return (
<HorizontalMenu
id="kassa-menu-first"
activeId={this.state.activeId}
onClick={item => this.setState({activeId: item.id})}
selected={this.state.selected}
onSelect={item => this.setState({selected: item.id})}
items={[
{
title: 'Услуги',
Expand Down
71 changes: 20 additions & 51 deletions packages/mobile/src/horizontal-menu/HorizontalMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,8 @@
import {BaseMenuItem, ButtonControl, styled} from '@qiwi/pijma-core'
import React, {ReactNode} from 'react'
import React from 'react'

import {HorizontalMenuItem} from './HorizontalMenuItem'

export interface HorizontalMenuRenderItemProps<Item extends BaseMenuItem> {
/**
* Html item id
*/
id: string
item: Item
active: boolean
onClick: () => void
}

const horizontalMenuRenderItemDefault = <Item extends BaseMenuItem>({
item,
active,
id,
onClick,
}: HorizontalMenuRenderItemProps<Item>): ReactNode => (
<ButtonControl
key={item.id}
onClick={onClick}
children={renderProps => (
<HorizontalMenuItem
active={active}
onClick={renderProps.onClick}
id={id}
children={item.title}
/>
)}
/>
)

// @see https://iamsteve.me/blog/entry/using-flexbox-for-horizontal-scrolling-navigation
export const HorizontalMenuContainer = styled('nav')(({theme}) => ({
display: 'flex',
Expand All @@ -59,33 +29,32 @@ export interface HorizontalMenuProps<Item extends BaseMenuItem = BaseMenuItem> {
/**
* Active menu item id
*/
activeId: string
selected: string
items: Item[]
onClick: (item: Item) => void
renderItem: (props: HorizontalMenuRenderItemProps<Item>) => ReactNode
onSelect: (item: Item) => void
}

// Do not use React.FC
// See https://github.com/sw-yx/react-typescript-cheatsheet#typing-defaultprops
export const HorizontalMenu = <Item extends BaseMenuItem = BaseMenuItem>({
export const HorizontalMenu = <Item extends BaseMenuItem>({
items,
renderItem,
onClick,
activeId,
onSelect,
selected,
id,
}: HorizontalMenuProps<Item>) => (
<HorizontalMenuContainer
id={id}
children={items.map(item =>
renderItem({
item,
id: `${id}-${item.id}`,
active: item.id === activeId,
onClick: onClick.bind(null, item),
})
)}
children={items.map(item => (
<ButtonControl
key={item.id}
onClick={onSelect.bind(null, item)}
children={renderProps => (
<HorizontalMenuItem
id={`${id}-${item.id}`}
active={selected === item.id}
onClick={renderProps.onClick}
children={item.title}
/>
)}
/>
))}
/>
)
HorizontalMenu.defaultProps = {
renderItem: horizontalMenuRenderItemDefault,
}
6 changes: 3 additions & 3 deletions packages/mobile/src/level-menu/LevelMenu.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ class LevelMenuDemo extends React.Component {
constructor() {
super()
this.state = {
activeId: 't2',
selected: 't2',
}
}

render() {
return (
<LevelMenu
id="kassa-menus"
activeId={this.state.activeId}
onClick={item => this.setState({activeId: item.id})}
selected={this.state.selected}
onSelect={item => this.setState({selected: item.id})}
items={[
{
title: 'Услуги',
Expand Down
52 changes: 25 additions & 27 deletions packages/mobile/src/level-menu/LevelMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
import {BaseMenuItem, Box, MenuLevelBuilder} from '@qiwi/pijma-core'
import React, {Component} from 'react'
import {BaseMenuItem, Box, MenuControl} from '@qiwi/pijma-core'
import React, {Fragment} from 'react'

import {HorizontalMenu} from '../horizontal-menu'
import {SelectMenu} from '../select-menu'

export interface LevelMenuProps<Item extends BaseMenuItem> {
id: string
activeId: string
selected: string
items: Item[]
onClick: (item: Item) => void
onSelect: (item: Item) => void
}

export class LevelMenu<Item extends BaseMenuItem> extends Component<
LevelMenuProps<Item>
> {
render() {
const {
props: {id, onClick, activeId, items},
} = this
const levels = new MenuLevelBuilder(items).levels(activeId)
const level0 = levels[0]
const level1 = levels[1]
const level2 = levels[2]
return (
<div id={id}>
export const LevelMenu = <Item extends BaseMenuItem>({
id,
onSelect,
selected,
items,
}: LevelMenuProps<Item>) => (
<MenuControl
items={items}
selected={selected}
children={({levels: [level0, level1, level2]}) => (
<Fragment>
{level0 && (
<HorizontalMenu
id={`${id}-0`}
items={level0.items}
onClick={onClick}
activeId={level0.activeId}
onSelect={onSelect}
selected={level0.selected}
/>
)}
{level1 && (
<Box id={`${id}-1-wrapper`} mt={4}>
<SelectMenu
id={`${id}-1`}
items={level1.items}
onClick={onClick}
activeId={level1.activeId}
onSelect={onSelect}
selected={level1.selected}
/>
</Box>
)}
Expand All @@ -47,12 +45,12 @@ export class LevelMenu<Item extends BaseMenuItem> extends Component<
<SelectMenu
id={`${id}-2`}
items={level2.items}
onClick={onClick}
activeId={level2.activeId}
onSelect={onSelect}
selected={level2.selected}
/>
</Box>
)}
</div>
)
}
}
</Fragment>
)}
/>
)
6 changes: 3 additions & 3 deletions packages/mobile/src/select-menu/SelectMenu.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ class SelectMenuDemo extends React.Component {
constructor() {
super()
this.state = {
activeId: 'transactions',
selected: 'transactions',
}
}

render() {
return (
<SelectMenu
id="kassa-menu-second"
activeId={this.state.activeId}
onClick={item => this.setState({activeId: item.id})}
selected={this.state.selected}
onSelect={item => this.setState({selected: item.id})}
items={[
{
title: 'Транзакции и отчеты',
Expand Down
Loading

0 comments on commit 62b9847

Please sign in to comment.