-
Notifications
You must be signed in to change notification settings - Fork 258
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Inline useSpaceStyle implementation into Space component
- Loading branch information
Showing
1 changed file
with
90 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,100 @@ | ||
import * as React from 'react' | ||
import { View } from 'react-native' | ||
import { useMemo } from 'react' | ||
import { View, ViewStyle } from 'react-native' | ||
|
||
import { SpaceProps, useSpaceStyle } from '../../hooks/useSpaceStyle' | ||
import { MarginRemProps, MarginRemStyle, useMarginRemStyle } from '../../hooks/useMarginRemStyle' | ||
|
||
interface OwnProps { | ||
export interface SpaceProps extends MarginRemProps { | ||
// Single-sided: | ||
/** Align children to the top */ | ||
alignBottom?: boolean | ||
/** Align children to the top */ | ||
alignLeft?: boolean | ||
/** Align children to the right */ | ||
alignRight?: boolean | ||
/** Align children to the top */ | ||
alignTop?: boolean | ||
|
||
// Multiple-sided: | ||
/** Aligns children to the center */ | ||
alignCenter?: boolean | ||
/** Aligns children to the center horizontally */ | ||
alignHorizontal?: boolean | ||
/** Aligns children to the center vertically */ | ||
alignVertical?: boolean | ||
|
||
// Children: | ||
children?: React.ReactNode | ||
|
||
/** | ||
* The `expand` space prop tells a component to expand its size within its | ||
* parent component. | ||
* | ||
* This is particularly useful when you want to use the space props to | ||
* align the component. | ||
*/ | ||
expand?: boolean | ||
|
||
/** | ||
* Changes the orientation of child component layout from column | ||
* (top-to-bottom) to row (left-to-right). | ||
* | ||
* The `row` prop is an additional, non-space props useful managing the | ||
* stacking direction of child components. By default, child components stack | ||
* vertically (column-based), from top to bottom. If `row={true}`, then | ||
* child components stack horizontally (row-based). | ||
* | ||
* The `row` prop does not affect the alignment or rem props (i.e. vertical | ||
* is always vertical regardless of the value set for the `row` prop). | ||
*/ | ||
row?: boolean | ||
} | ||
type Props = OwnProps & SpaceProps | ||
|
||
/** | ||
* Numbers are rem units, and boolean means to fill up assigned space; this | ||
* allows for centering and alignment (see useSpaceStyle hook for details). | ||
*/ | ||
export const Space = React.memo((props: Props) => { | ||
type SpaceStyle = Pick<ViewStyle, 'flex' | 'flexDirection' | 'alignItems' | 'justifyContent'> & MarginRemStyle | ||
|
||
export const Space = React.memo((props: SpaceProps) => { | ||
const { children } = props | ||
const spaceStyle = useSpaceStyle(props) | ||
const { aroundRem, horizontalRem, verticalRem, topRem, bottomRem, leftRem, rightRem, expand = false, row = false } = props | ||
const { alignBottom, alignLeft, alignRight, alignTop, alignCenter, alignHorizontal, alignVertical } = props | ||
|
||
const topFill = boolify(alignBottom, alignVertical, alignCenter) | ||
const bottomFill = boolify(alignTop, alignVertical, alignCenter) | ||
const leftFill = boolify(alignRight, alignHorizontal, alignCenter) | ||
const rightFill = boolify(alignLeft, alignHorizontal, alignCenter) | ||
|
||
// Margins: | ||
const marginRemStyle = useMarginRemStyle({ bottomRem, leftRem, rightRem, topRem, aroundRem, horizontalRem, verticalRem }) | ||
|
||
// Direction: | ||
const flexDirection = row ? 'row' : 'column' | ||
|
||
// Alignment: | ||
const horizontalAlignment = leftFill && rightFill ? 'center' : rightFill ? 'flex-start' : leftFill ? 'flex-end' : undefined | ||
const verticalAlignment = topFill && bottomFill ? 'center' : bottomFill ? 'flex-start' : topFill ? 'flex-end' : undefined | ||
const alignItems = row ? verticalAlignment : horizontalAlignment | ||
const justifyContent = row ? horizontalAlignment ?? (expand ? 'space-between' : undefined) : verticalAlignment | ||
|
||
// Flex: | ||
const alignSelf = expand ? 'stretch' : undefined | ||
const flexGrow = expand ? 1 : undefined | ||
|
||
const spaceStyle: SpaceStyle = useMemo( | ||
() => ({ | ||
alignSelf, | ||
alignItems, | ||
flexGrow, | ||
flexDirection, | ||
justifyContent, | ||
...marginRemStyle | ||
}), | ||
[alignItems, alignSelf, flexDirection, flexGrow, justifyContent, marginRemStyle] | ||
) | ||
|
||
return <View style={spaceStyle}>{children}</View> | ||
}) | ||
|
||
const boolify = (...things: Array<boolean | undefined>): boolean => { | ||
return things.some(thing => { | ||
return typeof thing === 'boolean' && thing | ||
}) | ||
} |