Guest User

Untitled

a guest
Jul 23rd, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.69 KB | None | 0 0
  1. import React from "react";
  2. import yoga, { Node } from "yoga-layout";
  3. import deepEqual from "fast-deep-equal";
  4. import { Map } from "immutable";
  5.  
  6. const defaultLayout = {
  7. top: 0,
  8. left: 0,
  9. width: 0,
  10. height: 0
  11. };
  12.  
  13. const propToYogaCallMap = {
  14. position: "setPosition",
  15. width: "setWidth",
  16. height: "setHeight",
  17. padding: "setPadding"
  18. };
  19.  
  20. function callLayoutUpdateFuncs(node, styles) {
  21. if (!styles) return;
  22.  
  23. Object.keys(styles).forEach(key => {
  24. node[propToYogaCallMap[key]](styles[key]);
  25. });
  26. }
  27.  
  28. export const { Provider, Consumer } = React.createContext({});
  29.  
  30. export const layoutAware = Component => {
  31. return ({ ...props }) => {
  32. return (
  33. <Consumer>
  34. {data => (
  35. <Component
  36. parentNode={data.node}
  37. root={data.root}
  38. nodes={data.nodes}
  39. {...props}
  40. />
  41. )}
  42. </Consumer>
  43. );
  44. };
  45. };
  46.  
  47. export class LayoutRootNode extends React.Component {
  48. constructor(props) {
  49. super(props);
  50.  
  51. this.node = Node.create();
  52. this.descendents = Map([[this.node, undefined]]);
  53. }
  54.  
  55. componentDidMount() {
  56. callLayoutUpdateFuncs(this.node, this.props.styles);
  57. this.updateLayout();
  58. }
  59.  
  60. componentWillUnmount() {
  61. this.node = Node.create();
  62. this.descendents = new Map([[this.node, undefined]]);
  63. }
  64.  
  65. componentDidUpdate(prevProps) {
  66. if (!deepEqual(prevProps.styles, this.props.styles)) {
  67. callLayoutUpdateFuncs(this.node, this.styles);
  68. this.updateLayout();
  69. }
  70. }
  71.  
  72. registerNode = node => {
  73. this.descendents = this.descendents.set(node, undefined);
  74. };
  75.  
  76. deregisterNode = node => {
  77. this.descendents = this.descendents.delete(node);
  78. };
  79.  
  80. updateLayout = () => {
  81. if (this.node.isDirty()) {
  82. this.node.calculateLayout();
  83.  
  84. this.descendents = this.descendents.withMutations(map => {
  85. map.forEach((layout, node) => {
  86. const newLayout = node.getComputedLayout();
  87.  
  88. console.log("new", newLayout);
  89.  
  90. if (!deepEqual(newLayout, layout)) {
  91. map.set(node, newLayout);
  92. }
  93. });
  94. });
  95.  
  96. this.forceUpdate();
  97. }
  98. };
  99.  
  100. render() {
  101. const { render } = this.props;
  102. const layout = this.descendents.get(this.node) || defaultLayout;
  103.  
  104. return (
  105. <Provider
  106. value={{
  107. node: this.node,
  108. root: this,
  109. nodes: this.descendents
  110. }}
  111. >
  112. <LayoutNodeInternal render={render} layout={layout} />
  113. </Provider>
  114. );
  115. }
  116. }
  117.  
  118. @layoutAware
  119. export class LayoutNode extends React.Component {
  120. constructor(props) {
  121. super(props);
  122.  
  123. this.node = Node.create();
  124. }
  125.  
  126. componentDidMount() {
  127. this.props.parentNode.insertChild(this.node);
  128. this.props.root.registerNode(this.node);
  129.  
  130. callLayoutUpdateFuncs(this.node, this.styles);
  131. this.props.root.updateLayout();
  132. }
  133.  
  134. componentWillUnmount() {
  135. this.props.parentNode.removeChild(this.node);
  136. this.props.root.deregisterNode(this.node);
  137.  
  138. this.node.reset();
  139.  
  140. callLayoutUpdateFuncs(this.node, this.styles);
  141. this.props.root.updateLayout();
  142. }
  143.  
  144. componentDidUpdate(prevProps) {
  145. if (!deepEqual(prevProps.styles, this.props.styles)) {
  146. callLayoutUpdateFuncs(this.node, this.styles);
  147. this.props.root.updateLayout();
  148. }
  149. }
  150.  
  151. render() {
  152. const { render, nodes } = this.props;
  153. const layout = nodes.get(this.node) || defaultLayout;
  154.  
  155. return (
  156. <Provider
  157. value={{
  158. node: this.node,
  159. root: this.props.root,
  160. nodes: this.props.nodes
  161. }}
  162. >
  163. <LayoutNodeInternal render={render} layout={layout} />
  164. </Provider>
  165. );
  166. }
  167. }
  168.  
  169. export class LayoutNodeInternal extends React.PureComponent {
  170. render() {
  171. return this.props.render(this.props.layout);
  172. }
  173. }
Add Comment
Please, Sign In to add comment