Skip to content
This repository was archived by the owner on Apr 14, 2020. It is now read-only.

Commit b47edfd

Browse files
committed
feat(move): completes most of move
1 parent 09219ec commit b47edfd

14 files changed

Lines changed: 398 additions & 120 deletions

File tree

HOW_IT_WORKS.md

Lines changed: 0 additions & 30 deletions
This file was deleted.

package.json

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
"test": "jest",
1414
"codecov": "echo \"not implemented\"",
1515
"preversion": "npm test",
16-
"version":
17-
"version-changelog CHANGELOG.md && changelog-verify CHANGELOG.md && git add CHANGELOG.md && node ./scripts/deploy",
16+
"version": "version-changelog CHANGELOG.md && changelog-verify CHANGELOG.md && git add CHANGELOG.md && node ./scripts/deploy",
1817
"postversion": "git push && git push --tags",
1918
"storybook": "start-storybook -p 6006",
2019
"build-storybook": "build-storybook"
@@ -26,6 +25,7 @@
2625
"@types/enzyme": "^3.1.9",
2726
"@types/jest": "^22.2.3",
2827
"@types/react": "^16.3.11",
28+
"@types/react-dom": "^16.0.5",
2929
"@types/sinon": "^4.3.1",
3030
"@types/storybook__react": "^3.0.7",
3131
"babel-core": "^6.26.0",
@@ -46,13 +46,22 @@
4646
"webpack-dev-server": "^2.6.1",
4747
"webpack-merge": "^4.1.0"
4848
},
49-
"workspaces": ["packages/*"],
49+
"workspaces": [
50+
"packages/*"
51+
],
5052
"jest": {
5153
"transform": {
5254
"^.+\\.tsx?$": "ts-jest"
5355
},
5456
"setupTestFrameworkScriptFile": "<rootDir>test/setup.js",
5557
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
56-
"moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"]
58+
"moduleFileExtensions": [
59+
"ts",
60+
"tsx",
61+
"js",
62+
"jsx",
63+
"json",
64+
"node"
65+
]
5766
}
5867
}

packages/react-next/src/components/Baba.tsx

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,14 @@ interface Props {
6565
}
6666

6767
export default class Baba extends React.PureComponent<Props> {
68+
state = {
69+
shown: false,
70+
};
71+
6872
element: HTMLElement | null;
6973
reactNode: React.ReactNode;
7074
data: Data[];
75+
cancelClear?: () => void;
7176

7277
componentWillUnmount() {
7378
if (childrenStore.has(this.props.name)) {
@@ -84,6 +89,14 @@ export default class Baba extends React.PureComponent<Props> {
8489
return this.execute();
8590
}
8691

92+
delayedClear() {
93+
const id = setTimeout(() => {
94+
childrenStore.remove(this.props.name);
95+
}, 50);
96+
97+
return () => clearTimeout(id);
98+
}
99+
87100
store() {
88101
// Store position data so we can use it later.
89102
childrenStore.set(this.props.name, {
@@ -93,10 +106,7 @@ export default class Baba extends React.PureComponent<Props> {
93106
data: this.data,
94107
});
95108

96-
// If a target isn't found in 100ms, clear it out.
97-
setTimeout(() => {
98-
childrenStore.remove(this.props.name);
99-
}, 100);
109+
this.cancelClear = this.delayedClear();
100110
}
101111

102112
execute() {
@@ -113,6 +123,7 @@ export default class Baba extends React.PureComponent<Props> {
113123
// Add to the last block in the array.
114124
arr[arr.length - 1].push(() =>
115125
animate({
126+
caller: this,
116127
fromTarget: target,
117128
toTarget: {
118129
reactNode: this.reactNode,
@@ -139,12 +150,26 @@ export default class Baba extends React.PureComponent<Props> {
139150
);
140151

141152
// Trigger each blocks animations, one block at a time.
142-
return blocks.reduce<Promise<AnimationResult>>(
143-
(promise, block) => promise.then(() => Promise.all(block.map(animate => animate()))),
144-
Promise.resolve({} as AnimationResult)
145-
);
153+
return blocks
154+
.reduce<Promise<AnimationResult>>(
155+
(promise, block) => promise.then(() => Promise.all(block.map(animate => animate()))),
156+
Promise.resolve({} as AnimationResult)
157+
)
158+
.then(() => {
159+
childrenStore.remove(this.props.name);
160+
161+
// We're finished all the transitions! Show the child element.
162+
this.setState({
163+
shown: true,
164+
});
165+
});
146166
}
147167

168+
// Nothing was found, show the child element.
169+
this.setState({
170+
shown: true,
171+
});
172+
148173
return undefined;
149174
}
150175

@@ -166,6 +191,9 @@ export default class Baba extends React.PureComponent<Props> {
166191
receiveData={this.setData}
167192
receiveReactNode={this.setReactNode}
168193
receiveRef={this.setRef}
194+
style={{
195+
opacity: this.state.shown ? 1 : 0,
196+
}}
169197
>
170198
{this.props.children}
171199
</Collector>

packages/react-next/src/components/Collector.tsx

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,39 @@ export type Data =
1313
export type SupplyRef = (ref: HTMLElement | null) => void;
1414
export type SupplyReactNode = (reactNode: React.ReactNode) => void;
1515
export type SupplyData = (data: Data[]) => void;
16-
export type ChildrenSupplyRef = (getRef: SupplyRef) => React.ReactNode;
16+
export type ChildrenAsFunction = (props: { ref: SupplyRef; style: Style }) => React.ReactNode;
1717

1818
export interface AnimationData {
19+
caller: React.Component;
1920
fromTarget: TargetData;
2021
toTarget: TargetData;
2122
}
2223

24+
export interface Style {
25+
[key: string]: string | number | undefined;
26+
}
27+
2328
export interface TargetData extends GetElementSizeLocationReturnValue {
2429
reactNode: React.ReactNode;
2530
}
2631

2732
export interface CommonProps {
28-
children: ChildrenSupplyRef | React.ReactNode;
33+
children: ChildrenAsFunction | React.ReactNode;
2934
}
3035

3136
export interface Props extends CommonProps {
3237
receiveRef?: SupplyRef;
3338
receiveReactNode?: SupplyReactNode;
3439
receiveData?: SupplyData;
3540
data?: Data;
41+
style?: Style;
3642
}
3743

3844
export interface Collect {
3945
ref: SupplyRef;
4046
data: SupplyData;
4147
reactNode: SupplyReactNode;
48+
style: Style;
4249
}
4350

4451
const CollectContext = React.createContext<Collect>();
@@ -64,6 +71,7 @@ export default class Collector extends React.Component<Props> {
6471
collect && collect.reactNode(node);
6572
this.props.receiveReactNode && this.props.receiveReactNode(node);
6673
},
74+
style: this.props.style || {},
6775
}}
6876
>
6977
{this.props.children}
@@ -78,14 +86,17 @@ export default class Collector extends React.Component<Props> {
7886
{collect => {
7987
const children =
8088
typeof this.props.children === 'function' &&
81-
this.props.children((ref: HTMLElement) => {
82-
if (collect) {
83-
collect.ref(ref);
84-
}
89+
this.props.children({
90+
ref: (ref: HTMLElement) => {
91+
if (collect) {
92+
collect.ref(ref);
93+
}
8594

86-
if (this.props.receiveRef) {
87-
this.props.receiveRef(ref);
88-
}
95+
if (this.props.receiveRef) {
96+
this.props.receiveRef(ref);
97+
}
98+
},
99+
style: collect ? collect.style : {},
89100
});
90101

91102
if (collect) {
Lines changed: 93 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,108 @@
11
import * as React from 'react';
2-
import Collecter, { CommonProps, AnimationCallback } from './Collector';
2+
import { unstable_renderSubtreeIntoContainer, unmountComponentAtNode } from 'react-dom';
3+
import Collecter, { CommonProps, AnimationCallback, Data, Actions } from './Collector';
4+
import * as math from '../lib/math';
5+
import SimpleTween from './SimpleTween';
36

47
interface Props extends CommonProps {
58
duration?: number;
69
}
710

811
export default class Move extends React.Component<Props> {
9-
animate: AnimationCallback = data => {
10-
console.log('starting');
11-
console.log(data);
12+
static defaultProps = {
13+
duration: 300000,
14+
};
1215

16+
// This animation will transition the from node to the to node
17+
// and the to node to the to node, with a fade in between so we
18+
// get a nice seamless transition.
19+
animate: AnimationCallback = data => {
1320
return new Promise(resolve => {
14-
setTimeout(() => {
15-
console.log('finished');
16-
resolve();
17-
}, this.props.duration || 100);
21+
const x = data.toTarget.location.left - data.fromTarget.location.left;
22+
const y = data.toTarget.location.top - data.fromTarget.location.top;
23+
const xx = data.fromTarget.location.left - data.toTarget.location.left;
24+
const yy = data.fromTarget.location.top - data.toTarget.location.top;
25+
const element = document.createElement('div');
26+
const duration = this.props.duration as number;
27+
const noTransform = 'translate3d(0, 0, 0) scale3d(1, 1, 1)';
28+
document.body.appendChild(element);
29+
30+
const from = {
31+
transition: `transform ${duration}ms, opacity ${duration / 2}ms`,
32+
position: 'absolute',
33+
transformOrigin: '0 0',
34+
};
35+
36+
unstable_renderSubtreeIntoContainer(
37+
data.caller,
38+
<>
39+
<SimpleTween
40+
duration={this.props.duration as number}
41+
from={{
42+
...data.fromTarget.location,
43+
...from,
44+
transform: noTransform,
45+
opacity: 1,
46+
}}
47+
to={{
48+
transform: `translate3d(${x}px, ${y}px, 0) scale3d(${math.percentageDifference(
49+
data.toTarget.size.width,
50+
data.fromTarget.size.width
51+
)}, ${math.percentageDifference(
52+
data.toTarget.size.height,
53+
data.fromTarget.size.height
54+
)}, 1)`,
55+
opacity: 0,
56+
}}
57+
onFinish={() => {
58+
unmountComponentAtNode(element);
59+
document.body.removeChild(element);
60+
resolve();
61+
}}
62+
>
63+
{data.fromTarget.reactNode}
64+
</SimpleTween>
65+
66+
<SimpleTween
67+
duration={this.props.duration as number}
68+
from={{
69+
...data.toTarget.location,
70+
...from,
71+
opacity: 0,
72+
transform: `translate3d(${xx}px, ${yy}px, 0) scale3d(${math.percentageDifference(
73+
data.fromTarget.size.width,
74+
data.toTarget.size.width
75+
)}, ${math.percentageDifference(
76+
data.fromTarget.size.height,
77+
data.toTarget.size.height
78+
)}, 1)`,
79+
}}
80+
to={{
81+
transform: noTransform,
82+
opacity: 1,
83+
}}
84+
// TODO: Add a TweenManager or something so we receive one
85+
// hook to tell us all tweens are finished.
86+
onFinish={() => {}}
87+
>
88+
{React.cloneElement(data.toTarget.reactNode as any, {
89+
// This element will have style passed down from a Baba
90+
// componet, let's remove it so we have full control.
91+
style: {},
92+
})}
93+
</SimpleTween>
94+
</>,
95+
element
96+
);
1897
});
1998
};
2099

21100
render() {
22-
return (
23-
<Collecter
24-
data={{
25-
action: 'animation',
26-
payload: this.animate,
27-
}}
28-
>
29-
{this.props.children}
30-
</Collecter>
31-
);
101+
const data: Data = {
102+
action: Actions.animation,
103+
payload: this.animate,
104+
};
105+
106+
return <Collecter data={data}>{this.props.children}</Collecter>;
32107
}
33108
}

0 commit comments

Comments
 (0)