Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React from "react";
- import yoga, { Node } from "yoga-layout";
- import deepEqual from "fast-deep-equal";
- import { Map } from "immutable";
- const defaultLayout = {
- top: 0,
- left: 0,
- width: 0,
- height: 0
- };
- const propToYogaCallMap = {
- position: "setPosition",
- width: "setWidth",
- height: "setHeight",
- padding: "setPadding"
- };
- function callLayoutUpdateFuncs(node, styles) {
- if (!styles) return;
- Object.keys(styles).forEach(key => {
- node[propToYogaCallMap[key]](styles[key]);
- });
- }
- export const { Provider, Consumer } = React.createContext({});
- export const layoutAware = Component => {
- return ({ ...props }) => {
- return (
- <Consumer>
- {data => (
- <Component
- parentNode={data.node}
- root={data.root}
- nodes={data.nodes}
- {...props}
- />
- )}
- </Consumer>
- );
- };
- };
- export class LayoutRootNode extends React.Component {
- constructor(props) {
- super(props);
- this.node = Node.create();
- this.descendents = Map([[this.node, undefined]]);
- }
- componentDidMount() {
- callLayoutUpdateFuncs(this.node, this.props.styles);
- this.updateLayout();
- }
- componentWillUnmount() {
- this.node = Node.create();
- this.descendents = new Map([[this.node, undefined]]);
- }
- componentDidUpdate(prevProps) {
- if (!deepEqual(prevProps.styles, this.props.styles)) {
- callLayoutUpdateFuncs(this.node, this.styles);
- this.updateLayout();
- }
- }
- registerNode = node => {
- this.descendents = this.descendents.set(node, undefined);
- };
- deregisterNode = node => {
- this.descendents = this.descendents.delete(node);
- };
- updateLayout = () => {
- if (this.node.isDirty()) {
- this.node.calculateLayout();
- this.descendents = this.descendents.withMutations(map => {
- map.forEach((layout, node) => {
- const newLayout = node.getComputedLayout();
- console.log("new", newLayout);
- if (!deepEqual(newLayout, layout)) {
- map.set(node, newLayout);
- }
- });
- });
- this.forceUpdate();
- }
- };
- render() {
- const { render } = this.props;
- const layout = this.descendents.get(this.node) || defaultLayout;
- return (
- <Provider
- value={{
- node: this.node,
- root: this,
- nodes: this.descendents
- }}
- >
- <LayoutNodeInternal render={render} layout={layout} />
- </Provider>
- );
- }
- }
- @layoutAware
- export class LayoutNode extends React.Component {
- constructor(props) {
- super(props);
- this.node = Node.create();
- }
- componentDidMount() {
- this.props.parentNode.insertChild(this.node);
- this.props.root.registerNode(this.node);
- callLayoutUpdateFuncs(this.node, this.styles);
- this.props.root.updateLayout();
- }
- componentWillUnmount() {
- this.props.parentNode.removeChild(this.node);
- this.props.root.deregisterNode(this.node);
- this.node.reset();
- callLayoutUpdateFuncs(this.node, this.styles);
- this.props.root.updateLayout();
- }
- componentDidUpdate(prevProps) {
- if (!deepEqual(prevProps.styles, this.props.styles)) {
- callLayoutUpdateFuncs(this.node, this.styles);
- this.props.root.updateLayout();
- }
- }
- render() {
- const { render, nodes } = this.props;
- const layout = nodes.get(this.node) || defaultLayout;
- return (
- <Provider
- value={{
- node: this.node,
- root: this.props.root,
- nodes: this.props.nodes
- }}
- >
- <LayoutNodeInternal render={render} layout={layout} />
- </Provider>
- );
- }
- }
- export class LayoutNodeInternal extends React.PureComponent {
- render() {
- return this.props.render(this.props.layout);
- }
- }
Add Comment
Please, Sign In to add comment