Skip to content

fix: omit empty components (#38) #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .husky/.gitignore

This file was deleted.

4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run pre-commit
4 changes: 1 addition & 3 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ src
assets
__tests__
coverage
.husky
.jest

tsconfig.json
.travis.yml
.prettierrc

.eslintrc.js
global.d.ts
yarn-error.log
babel.config.js
jest.config.js
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# native-layout-stack Changelog
# Native Layout Stack Changelog

## 1.0.0 (Soon)

### Features

- added `Stack`, `Spacer` components
- added `LayoutProvider`
- added the `Stack`, `Spacer` components
- added the `LayoutProvider`
23 changes: 11 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
# [native-layout-stack](https://github.com/native-ly/native-layout-stack)
# [Native Layout Stack](https://github.com/native-ly/native-layout-stack)

[![NPM version](https://img.shields.io/npm/v/native-layout-stack?style=flat-square)](https://www.npmjs.com/package/native-layout-stack)
[![NPM downloads](https://img.shields.io/npm/dm/native-layout-stack?style=flat-square)](https://www.npmjs.com/package/native-layout-stack)
[![NPM license](https://img.shields.io/npm/l/native-layout-stack?style=flat-square)](https://www.npmjs.com/package/native-layout-stack)
[![NPM version](https://flat.badgen.net/npm/v/native-layout-stack)](https://www.npmjs.com/package/native-layout-stack)
[![NPM downloads](https://flat.badgen.net/npm/dm/native-layout-stack)](https://www.npmjs.com/package/native-layout-stack)
[![NPM license](https://flat.badgen.net/npm/license/native-layout-stack)](https://www.npmjs.com/package/native-layout-stack)
[![run in expo snack](https://img.shields.io/badge/Run%20in%20Snack-4630EB?style=flat-square&logo=EXPO&labelColor=FFF&logoColor=000)](https://snack.expo.io/@jbiesiada/native-layout-stack)
[![Codecov](https://img.shields.io/codecov/c/github/native-ly/native-layout-stack?style=flat-square)](https://codecov.io/gh/native-ly/native-layout-stack)
[![Travis](https://img.shields.io/travis/com/native-ly/native-layout-stack/main?style=flat-square)](https://travis-ci.com/native-ly/native-layout-stack)
[![Codecov](https://flat.badgen.net/codecov/c/github/native-ly/native-layout-stack)](https://codecov.io/gh/native-ly/native-layout-stack)
[![Travis](https://flat.badgen.net/travis/native-ly/native-layout-stack)](https://travis-ci.com/native-ly/native-layout-stack)
[![Bundle size](https://flat.badgen.net/packagephobia/install/native-layout-stack)](https://packagephobia.com/result?p=native-layout-stack)

## About

[SwiftUI](https://developer.apple.com/xcode/swiftui/) like layout management for React Native

### Idea

This library recreates SwiftUI components in React Native:
This library recreates the SwiftUI components in React Native:

**Stack**

Expand Down Expand Up @@ -46,7 +47,7 @@ $ yarn add native-layout-stack

## Getting Started

**Connect libary with project using ES6 import:**
**Connect the library with the project using ES6 import:**

```js
import { LayoutProvider, Stack, Spacer } from 'native-layout-stack'
Expand All @@ -60,17 +61,15 @@ import { LayoutProvider, Stack, Spacer } from 'native-layout-stack'
| ------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| padding | Space or [Space] or [Space, Space] or [Space, Space, Space] or [Space, Space, Space, Space] | Outer space |
| spaces | Space | Space between children |
| omitNull | boolean | Skip elements that are `null` or `React.Fragment` |
| arrayDivision | boolean | |
| debug | boolean | Add random color to spaces |

### Stack

Stack extends ViewProps and implements all [`LayoutProvider`](#layoutprovider) props without `debug`
Stack extends [ViewProps](https://reactnative.dev/docs/view#props) and implements all [`LayoutProvider`](#layoutprovider) props without `debug`

### Spacer

Component uses ViewProps
Component uses [ViewProps](https://reactnative.dev/docs/view#props)

### Types

Expand Down
65 changes: 32 additions & 33 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"prepack": "npm run clean && npm run prettier && npm run lint && npm run build",
"prepack": "npm run prettier && npm run lint && npm run build",
"clean": "rimraf lib/*",
"build": "tsc",
"prebuild": "npm run clean",
"test": "jest --coverage",
"watch": "npm run build -- --watch",
"watch:test": "npm run test -- --watch",
"lint": "eslint --fix 'src/**/*.{tsx,ts}'",
"prettier": "prettier --write 'src/**/*.{tsx,ts}'",
"commit": "git-cz",
"semantic-release": "semantic-release"
"semantic-release": "semantic-release",
"prepare": "husky install",
"pre-commit": "lint-staged"
},
"repository": {
"type": "git",
Expand All @@ -38,36 +41,37 @@
"homepage": "https://github.com/native-ly/native-layout-stack#readme",
"dependencies": {
"randomcolor": "^0.6.2",
"react-safe-context-hooks": "^1.0.0"
"react-safe-context-hooks": "^1.0.1"
},
"devDependencies": {
"@testing-library/jest-native": "^3.4.3",
"@testing-library/react-native": "^7.1.0",
"@types/jest": "^26.0.20",
"@types/randomcolor": "^0.5.5",
"@types/react": "^17.0.2",
"@types/react-native": "^0.63.50",
"@typescript-eslint/parser": "^4.15.1",
"babel-jest": "^26.6.3",
"@babel/core": "^7.16.0",
"@testing-library/jest-native": "^4.0.4",
"@testing-library/react-native": "^8.0.0",
"@types/jest": "^27.0.2",
"@types/randomcolor": "^0.5.6",
"@types/react": "^17.0.34",
"@types/react-native": "^0.66.3",
"@typescript-eslint/parser": "^5.3.1",
"babel-jest": "^27.3.1",
"cz-conventional-changelog": "^3.3.0",
"cz-emoji": "^1.3.1",
"eslint": "^7.20.0",
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-react-native": "^3.10.0",
"husky": "^5.0.9",
"jest": "^26.6.3",
"lint-staged": "^10.5.4",
"prettier": "^2.2.1",
"react": "^16.13.1",
"react-native": "^0.62.1",
"react-test-renderer": "^17.0.1",
"semantic-release": "^17.3.9",
"semantic-release-gitmoji": "^1.3.4",
"ts-jest": "^26.5.1",
"typescript": "^4.1.5"
"eslint": "^8.2.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.27.0",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-react-native": "^3.11.0",
"husky": "^7.0.4",
"jest": "^27.3.1",
"lint-staged": "^11.2.6",
"prettier": "^2.4.1",
"react": "^17.0.2",
"react-native": "^0.66.3",
"react-test-renderer": "^17.0.2",
"semantic-release": "^18.0.0",
"semantic-release-gitmoji": "^1.4.2",
"ts-jest": "^27.0.7",
"typescript": "^4.4.4"
},
"peerDependencies": {
"react": ">=16.8.0",
Expand All @@ -78,11 +82,6 @@
"path": "cz-emoji"
}
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{tsx,ts}": [
"npm run prettier",
Expand Down
14 changes: 4 additions & 10 deletions src/components/Spacer.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
import React from 'react'
import { StyleSheet, View, ViewProps } from 'react-native'
import randomColor from 'randomcolor'

import { useStack } from '../hooks'
import { useDebugStyle } from '../hooks'

interface Props extends ViewProps {}

export const Spacer = ({ style, ...props }: Props) => {
const { debug, debugColor = randomColor() } = useStack()
export const Spacer = ({ style, debug, ...props }: Props) => {
const debugStyle = useDebugStyle(debug)

return (
<View
{...props}
style={StyleSheet.flatten([
style,
{ flex: 1 },
// TODO refactor
debug && { backgroundColor: debugColor },
])}
style={StyleSheet.flatten([style, { flex: 1 }, debugStyle])}
/>
)
}
38 changes: 13 additions & 25 deletions src/components/Stack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,13 @@ import { useStack } from '../hooks'

import { preparePaddings } from '../helpers/preparePaddings'

import { BaseProps } from '../interfaces/BaseProps'
import { BaseProps } from '../types/BaseProps'

interface Props extends ViewProps, BaseProps {
readonly children: React.ReactNode | React.ReactNodeArray
}
interface Props extends ViewProps {}

export const Stack = ({
children,
spaces,
padding,
omitNull,
style,
...props
}: Props) => {
// TODO
export const Stack = ({ children, style, spaces,
padding, ...props }: Props) => {
const globalConfig = useStack()

// TODO refactor
Expand All @@ -42,7 +35,7 @@ export const Stack = ({
[stackSpaces]
)

const renderDivider = useCallback(
const divider = useCallback(
(): React.ReactElement => (
<View
style={StyleSheet.flatten([
Expand All @@ -64,14 +57,15 @@ export const Stack = ({
(index: number) => {
if (!isSpacer) return []

return React.cloneElement(renderDivider(), {
return React.cloneElement(divider, {
key: `stack-divider-${index}`,
})
},
[isSpacer, renderDivider]
[isSpacer, divider]
)

const renderStack = useCallback(() => {

const stack = useMemo(() => {
let elements = Array.isArray(children) ? children : [children]

elements = elements.filter((child) => {
Expand All @@ -94,16 +88,10 @@ export const Stack = ({
return [...children, addSpaces(index), child]
}, [])
}, [addSpaces, children, stackOmitNull])

return (
<View
{...props}
style={StyleSheet.flatten([
style,
preparePaddings(stackPadding || 0, globalConfig.debug),
])}
>
{renderStack()}
<View>
{stack}
</View>
)
}
25 changes: 10 additions & 15 deletions src/context.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
import React from 'react'

import { BaseProps } from './interfaces/BaseProps'
import { BaseProps } from './types/BaseProps'

export interface Props extends BaseProps {
readonly debug?: boolean
readonly debugColor?: string
}

// TODO
// TODO? undefined
// export const LayoutContext = React.createContext<Props | undefined>(undefined)
export const LayoutContext = React.createContext<Props>({
padding: undefined,
spaces: undefined,
arrayDivision: undefined,
omitNull: undefined, // TODO
// omitElements: [null, React.Fragment],
// omitElements: React.Fragment,
spacing: undefined,
align: undefined,
horizontal: false,
debug: false,
debugColor: undefined,
// debugColor: {
// stack: '#f00',
// spacer: '#000',
// }
})

LayoutContext.displayName = 'LayoutContext'

export const LayoutProvider: React.FC<Props> = ({ children, ...props }) => (
export const LayoutProvider = ({
children,
...props
}: Props & { readonly children: React.ReactNode }) => (
<LayoutContext.Provider value={props}>{children}</LayoutContext.Provider>
)
1 change: 1 addition & 0 deletions src/helpers/preparePaddings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const preparePaddings = (
): ViewStyle => {
const color = randomColor()

// TODO || -> ??
if (typeof paddings === 'number' || typeof paddings === 'string') {
return debug
? { borderWidth: typeSafePaddings(paddings), borderColor: color }
Expand Down
3 changes: 3 additions & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export { useStack } from './useStack'
export { useDebugStyle } from './useDebugStyle'
export { useSpacing } from './useSpacing'
export { useSpacingHelpers } from './useSpacingHelpers'
9 changes: 9 additions & 0 deletions src/hooks/useDebugStyle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import randomColor from 'randomcolor'

import { useStack } from '.'

export const useDebugStyle = (debug?: boolean) => {
const { debug: globalDebug } = useStack()

return debug ?? globalDebug ? { backgroundColor: randomColor() } : undefined
}
7 changes: 7 additions & 0 deletions src/hooks/useSpacing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { useStack } from '.'

export const useSpacing = (value: number) => {
const { spacing } = useStack()

return spacing * value
}
10 changes: 10 additions & 0 deletions src/hooks/useSpacingHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useStack } from '.'

export const useSpacingHelpers = () => {
const { spacing } = useStack()

const multiply = (value: number) => value * spacing
const divide = (value: number) => value / spacing

return { multiply, divide }
}
5 changes: 3 additions & 2 deletions src/hooks/useStack.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useSafeContext } from 'react-safe-context-hooks'
import { useContext } from 'react'
// import { useSafeContext } from 'react-safe-context-hooks'

import { LayoutContext } from '../context'

export const useStack = () => useSafeContext(LayoutContext)
export const useStack = () => useContext(LayoutContext)
8 changes: 0 additions & 8 deletions src/interfaces/BaseProps.ts

This file was deleted.

Loading