-
Notifications
You must be signed in to change notification settings - Fork 957
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BREAKING: refactor Button to new api
- Loading branch information
Artur Yorsh
committed
Feb 28, 2020
1 parent
ee100a5
commit 8e8c8a9
Showing
21 changed files
with
1,197 additions
and
279 deletions.
There are no files selected for viewing
48 changes: 48 additions & 0 deletions
48
src/components/devsupport/components/falsyFC/falsyFC.component.tsx
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 |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import React from 'react'; | ||
|
||
export type RenderProp<Props = {}> = (props?: Props) => React.ReactElement; | ||
|
||
export type FalsyFCProps<Props = {}> = Props & { | ||
component?: RenderProp<Props>; | ||
fallback?: React.ReactElement; | ||
}; | ||
|
||
/** | ||
* Helper component for optional properties that should render a component. | ||
* | ||
* Accepts props of a component that is expected to be rendered, | ||
* and `component` which may be a string, a function, null or undefined. | ||
* | ||
* If it is a function, will call it with props passed to this component. | ||
* Otherwise, will return null. | ||
* | ||
* @property {RenderProp} component - function component to be rendered. | ||
* @property {React.ReactElement} fallback - an element to render if children is null or undefined. | ||
* | ||
* @example Will render nothing. | ||
* ``` | ||
* <FalsyFC /> | ||
* ``` | ||
* | ||
* @example Will render red title. | ||
* ``` | ||
* const Title = () => ( | ||
* <FalsyFC | ||
* style={{ color: 'red' }} | ||
* component={props => <Text {...props}>Title</Text>} | ||
* /> | ||
* ); | ||
* ``` | ||
*/ | ||
export class FalsyFC<Props = {}> extends React.Component<FalsyFCProps<Props>> { | ||
|
||
public render(): React.ReactElement { | ||
const { component, fallback, ...props } = this.props; | ||
|
||
if (!component) { | ||
return fallback || null; | ||
} | ||
|
||
return component(props as Props); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
src/components/devsupport/components/falsyFC/falsyFC.spec.tsx
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 |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React from 'react'; | ||
import { Text } from 'react-native'; | ||
import { render } from 'react-native-testing-library'; | ||
import { FalsyFC } from './falsyFC.component'; | ||
|
||
it('should render nothing', function () { | ||
const component = render(<FalsyFC/>); | ||
expect(component.toJSON()).toEqual(null); | ||
}); | ||
|
||
it('should render provided function component', function () { | ||
const component = render( | ||
<FalsyFC style={{ color: 'red' }} component={props => <Text {...props}>I love Babel</Text>}/>, | ||
); | ||
|
||
const textComponent = component.getByText('I love Babel'); | ||
|
||
expect(textComponent).toBeTruthy(); | ||
expect(textComponent.props.style).toEqual({ | ||
color: 'red', | ||
}); | ||
}); | ||
|
||
it('should render fallback component', function () { | ||
const component = render( | ||
<FalsyFC | ||
component={null} | ||
fallback={<Text>I love Babel</Text>} | ||
/>, | ||
); | ||
|
||
const textComponent = component.getByText('I love Babel'); | ||
|
||
expect(textComponent).toBeTruthy(); | ||
}); |
70 changes: 70 additions & 0 deletions
70
src/components/devsupport/components/falsyText/falsyText.component.tsx
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 |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import React from 'react'; | ||
import { RenderProp } from '../falsyFC/falsyFC.component'; | ||
import { | ||
Text, | ||
TextProps, | ||
} from '../../../ui/text/text.component'; | ||
|
||
export interface FalsyTextProps extends Omit<TextProps, 'children'> { | ||
component?: RenderProp<TextProps> | React.ReactText; | ||
} | ||
|
||
/** | ||
* Helper component for optional text properties. | ||
* | ||
* Accepts same props as Text component, | ||
* and `component` which may be a string, a function, null or undefined. | ||
* | ||
* If it is null or undefined, will render nothing. | ||
* If it is a function, will call it with props passed to this component. | ||
* Otherwise, will render a Text with props passed to this component. | ||
* | ||
* @example Will render nothing. | ||
* ``` | ||
* <FalsyText /> | ||
* ``` | ||
* | ||
* @example Will render red title. | ||
* ``` | ||
* const Title = () => ( | ||
* <FalsyText style={{ color: 'red' }} component='Title' /> | ||
* ); | ||
* ``` | ||
* | ||
* @example Will render image and red title. | ||
* ``` | ||
* const renderTitle = (props) => ( | ||
* <React.Fragment> | ||
* <Image source={require('../asset.png')}/> | ||
* <Text {...props}>Title</Text> | ||
* </React.Fragment> | ||
* ); | ||
* | ||
* const Title = () => ( | ||
* <FalsyText | ||
* style={{ color: 'red' }} | ||
* component={renderTitle} | ||
* /> | ||
* ); | ||
* ``` | ||
*/ | ||
export class FalsyText extends React.Component<FalsyTextProps> { | ||
|
||
public render(): React.ReactElement { | ||
const { component, ...textProps } = this.props; | ||
|
||
if (!component) { | ||
return null; | ||
} | ||
|
||
if (typeof component === 'function') { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
return component(textProps as TextProps); | ||
} | ||
|
||
return ( | ||
<Text {...textProps}> | ||
{component} | ||
</Text> | ||
); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
src/components/devsupport/components/falsyText/falsyText.spec.tsx
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 |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import React from 'react'; | ||
import { Text } from 'react-native'; | ||
import { render } from 'react-native-testing-library'; | ||
import { mapping, light } from '@eva-design/eva'; | ||
import { FalsyText } from './falsyText.component'; | ||
import { ApplicationProvider } from '../../../theme'; | ||
|
||
it('should render nothing', function () { | ||
const component = render(<FalsyText/>); | ||
expect(component.toJSON()).toEqual(null); | ||
}); | ||
|
||
it('should render provided function component', function () { | ||
const component = render( | ||
<FalsyText | ||
style={{ color: 'red' }} | ||
component={props => <Text {...props}>I love Babel</Text>} | ||
/>, | ||
); | ||
|
||
const textComponent = component.getByText('I love Babel'); | ||
|
||
expect(textComponent).toBeTruthy(); | ||
expect(textComponent.props.style).toEqual({ | ||
color: 'red', | ||
}); | ||
}); | ||
|
||
it('should render ui kitten text', function () { | ||
const component = render( | ||
<ApplicationProvider mapping={mapping} theme={light}> | ||
<FalsyText component='I love Babel'/> | ||
</ApplicationProvider>, | ||
); | ||
|
||
const textComponent = component.getByText('I love Babel'); | ||
|
||
expect(textComponent).toBeTruthy(); | ||
}); |
78 changes: 78 additions & 0 deletions
78
src/components/devsupport/components/measure/measure.component.tsx
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 |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/** | ||
* @license | ||
* Copyright Akveo. All Rights Reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*/ | ||
|
||
import React from 'react'; | ||
import { | ||
findNodeHandle, | ||
UIManager, | ||
} from 'react-native'; | ||
import { Frame } from './type'; | ||
|
||
export interface MeasureElementProps<P = any> { | ||
force?: boolean; | ||
onMeasure: (frame: Frame) => void; | ||
children: React.ReactElement<P>; | ||
} | ||
|
||
export type MeasuringElement<P = any> = React.ReactElement; | ||
|
||
/** | ||
* Measures child element size and it's screen position asynchronously. | ||
* Returns measure result in `onMeasure` callback. | ||
* | ||
* Usage: | ||
* | ||
* ```tsx | ||
* const onMeasure = (frame: Frame): void => { | ||
* const { x, y } = frame.origin; | ||
* const { width, height } = frame.size; | ||
* ... | ||
* }; | ||
* | ||
* <MeasureElement onMeasure={onMeasure}> | ||
* <ElementToMeasure /> | ||
* </MeasureElement> | ||
* ``` | ||
* | ||
* By default, it measures each time onLayout is called, | ||
* but `force` property may be used to measure any time it's needed. | ||
* DON'T USE THIS FLAG IF THE COMPONENT RENDERS FIRST TIME OR YOU KNOW `onLayout` WILL BE CALLED. | ||
*/ | ||
export const MeasureElement = (props: MeasureElementProps): MeasuringElement => { | ||
|
||
const ref: React.RefObject<any> = React.useRef(); | ||
|
||
const bindToWindow = (frame: Frame, window: Frame): Frame => { | ||
if (frame.origin.x < window.size.width) { | ||
return frame; | ||
} | ||
|
||
const boundFrame: Frame = new Frame( | ||
frame.origin.x - window.size.width, | ||
frame.origin.y, | ||
frame.size.width, | ||
frame.size.height, | ||
); | ||
|
||
return bindToWindow(boundFrame, window); | ||
}; | ||
|
||
const onUIManagerMeasure = (x: number, y: number, w: number, h: number): void => { | ||
const frame: Frame = bindToWindow(new Frame(x, y, w, h), Frame.window()); | ||
props.onMeasure(frame); | ||
}; | ||
|
||
const measureSelf = (): void => { | ||
const node: number = findNodeHandle(ref.current); | ||
UIManager.measureInWindow(node, onUIManagerMeasure); | ||
}; | ||
|
||
if (props.force) { | ||
measureSelf(); | ||
} | ||
|
||
return React.cloneElement(props.children, { ref, onLayout: measureSelf }); | ||
}; |
58 changes: 58 additions & 0 deletions
58
src/components/devsupport/components/measure/measure.spec.tsx
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 |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import React from 'react'; | ||
import { Frame } from './type'; | ||
|
||
describe('@measure: frame class instance checks', () => { | ||
|
||
const lhsFrame: Frame = new Frame(2, 2, 2, 2); | ||
const rhsFrame: Frame = new Frame(4, 4, 2, 2); | ||
|
||
it('* left of', () => { | ||
const { origin: { x, y } } = rhsFrame.leftOf(lhsFrame); | ||
|
||
expect(x).toEqual(0); | ||
expect(y).toEqual(4); | ||
}); | ||
|
||
it('* top of', () => { | ||
const { origin: { x, y } } = rhsFrame.topOf(lhsFrame); | ||
|
||
expect(x).toEqual(4); | ||
expect(y).toEqual(0); | ||
}); | ||
|
||
it('* right of', () => { | ||
const { origin: { x, y } } = rhsFrame.rightOf(lhsFrame); | ||
|
||
expect(x).toEqual(4); | ||
expect(y).toEqual(4); | ||
}); | ||
|
||
it('* bottom of', () => { | ||
const { origin: { x, y } } = rhsFrame.bottomOf(lhsFrame); | ||
|
||
expect(x).toEqual(4); | ||
expect(y).toEqual(4); | ||
}); | ||
|
||
it('* center horizontal of', () => { | ||
const { origin: { x, y } } = rhsFrame.centerHorizontalOf(lhsFrame); | ||
|
||
expect(x).toEqual(2); | ||
expect(y).toEqual(4); | ||
}); | ||
|
||
it('* center vertical of', () => { | ||
const { origin: { x, y } } = rhsFrame.centerVerticalOf(lhsFrame); | ||
|
||
expect(x).toEqual(4); | ||
expect(y).toEqual(2); | ||
}); | ||
|
||
it('* center of', () => { | ||
const { origin: { x, y } } = rhsFrame.centerOf(lhsFrame); | ||
|
||
expect(x).toEqual(2); | ||
expect(y).toEqual(2); | ||
}); | ||
|
||
}); |
Oops, something went wrong.
Can't we use something like this: https://github.com/fernandopasik/react-children-utilities/blob/master/src/lib/onlyText.ts to better detect a component vs string? this way we could open more possibilities than forcing a function component.