diff --git a/.size-snapshot.json b/.size-snapshot.json index eee0798..96a86c0 100644 --- a/.size-snapshot.json +++ b/.size-snapshot.json @@ -1,15 +1,15 @@ { "index.js": { - "bundled": 15270, - "minified": 8092, - "gzipped": 2701, + "bundled": 9500, + "minified": 9415, + "gzipped": 3419, "treeshaked": { "rollup": { - "code": 127, - "import_statements": 127 + "code": 8591, + "import_statements": 429 }, "webpack": { - "code": 1243 + "code": 10302 } } }, @@ -19,8 +19,8 @@ "gzipped": 3407 }, "index.cjs": { - "bundled": 21936, - "minified": 10996, - "gzipped": 3444 + "bundled": 12743, + "minified": 12730, + "gzipped": 4484 } } diff --git a/examples/config-overrides.js b/examples/config-overrides.js index 6912e7f..bf0d6cc 100644 --- a/examples/config-overrides.js +++ b/examples/config-overrides.js @@ -1,13 +1,26 @@ -const { override, addWebpackAlias, addWebpackPlugin } = require('customize-cra') +const { override, addWebpackAlias, addWebpackPlugin, removeModuleScopePlugin, babelInclude } = require('customize-cra') const { addReactRefresh } = require('customize-cra-react-refresh') const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin const path = require('path') -module.exports = override( - addReactRefresh(), - addWebpackAlias({ - // three$: path.resolve('./src/utils/three.js'), - // '../../../build/three.module.js': path.resolve('./src/utils/three.js'), - }), - //addWebpackPlugin(new BundleAnalyzerPlugin()) -) +module.exports = (config, env) => { + config.resolve.extensions = [...config.resolve.extensions, '.ts', '.tsx'] + return override( + addReactRefresh(), + removeModuleScopePlugin(), + babelInclude([path.resolve('src'), path.resolve('../src')]), + addWebpackAlias({ + 'react-three-flex': path.resolve('../src/index'), + postprocessing: path.resolve('node_modules/postprocessing'), + react: path.resolve('node_modules/react'), + 'react-dom': path.resolve('node_modules/react-dom'), + scheduler: path.resolve('node_modules/scheduler'), + 'react-scheduler': path.resolve('node_modules/react-scheduler'), + 'react-three-fiber': path.resolve('node_modules/react-three-fiber'), + drei: path.resolve('node_modules/drei'), + three$: path.resolve('./src/utils/three.js'), + '../../../build/three.module.js': path.resolve('./src/utils/three.js'), + }), + //addWebpackPlugin(new BundleAnalyzerPlugin()) + )(config, env) +} diff --git a/examples/public/yoga.wasm b/examples/public/yoga.wasm new file mode 100644 index 0000000..29f7ef2 Binary files /dev/null and b/examples/public/yoga.wasm differ diff --git a/package.json b/package.json index 3480df3..7f20153 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,8 @@ "build-storybook": "build-storybook" }, "dependencies": { - "yoga-layout-prebuilt": "^1.9.6" + "react-promise-suspense": "^0.3.3", + "yoga-wasm-slim": "^0.0.6" }, "devDependencies": { "@babel/core": "7.15.0", @@ -105,6 +106,7 @@ "rimraf": "^3.0.2", "rollup": "^2.26.10", "rollup-plugin-filesize": "^9.1.1", + "rollup-plugin-size-snapshot": "^0.12.0", "rollup-plugin-terser": "^7.0.2", "three": "^0.131.3", "ts-jest": "^27.0.4", diff --git a/rollup.config.js b/rollup.config.js index 11a9af2..25e6f85 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -4,6 +4,7 @@ import resolve from '@rollup/plugin-node-resolve' import json from '@rollup/plugin-json' import { terser } from 'rollup-plugin-terser' import filesize from 'rollup-plugin-filesize' +import { sizeSnapshot } from 'rollup-plugin-size-snapshot' const root = process.platform === 'win32' ? path.resolve('/') : '/' const external = (id) => !id.startsWith('.') && !id.startsWith(root) @@ -32,7 +33,8 @@ export default [ babel(getBabelOptions({ useESModules: true }, '>1%, not dead, not ie 11, not op_mini all')), resolve({ extensions }), terser(), - filesize() + filesize(), + sizeSnapshot(), ], }, { @@ -44,7 +46,8 @@ export default [ babel(getBabelOptions({ useESModules: false })), resolve({ extensions }), terser(), - filesize() + filesize(), + sizeSnapshot(), ], }, ] diff --git a/src/Box.tsx b/src/Box.tsx index 8ce17a7..812c430 100644 --- a/src/Box.tsx +++ b/src/Box.tsx @@ -1,10 +1,9 @@ import React, { useLayoutEffect, useRef, useMemo, useState } from 'react' import * as THREE from 'three' -import Yoga from 'yoga-layout-prebuilt' import { ReactThreeFiber, useFrame } from '@react-three/fiber' import mergeRefs from 'react-merge-refs' -import { setYogaProperties, rmUndefFromObj } from './util' +import { setYogaProperties, rmUndefFromObj, useYogaAsync } from './util' import { boxContext, flexContext, SharedBoxContext } from './context' import { R3FlexProps } from './props' import { useReflow, useContext } from './hooks' @@ -184,26 +183,28 @@ function BoxImpl( wrap, ]) + const yoga = useYogaAsync('./') + const { registerBox, unregisterBox, scaleFactor } = useContext(flexContext) const { node: parent } = useContext(boxContext) const group = useRef() - const node = useMemo(() => Yoga.Node.create(), []) + const node = useMemo(() => yoga._YGNodeNew(), []) const reflow = useReflow() useLayoutEffect(() => { - setYogaProperties(node, flexProps, scaleFactor) + setYogaProperties(yoga, node, flexProps, scaleFactor) }, [flexProps, node, scaleFactor]) // Make child known to the parents yoga instance *before* it calculates layout useLayoutEffect(() => { if (!group.current || !parent) return - parent.insertChild(node, parent.getChildCount()) + yoga._YGNodeInsertChild(parent, node, yoga._YGNodeGetChildCount(parent)) registerBox(node, group.current, flexProps, centerAnchor) // Remove child on unmount return () => { - parent.removeChild(node) + yoga._YGNodeRemoveChild(parent, node) unregisterBox(node) } }, [node, parent, flexProps, centerAnchor, registerBox, unregisterBox]) @@ -217,10 +218,10 @@ function BoxImpl( const epsilon = 1 / scaleFactor useFrame(() => { const width = - (typeof flexProps.width === 'number' ? flexProps.width : null) || node.getComputedWidth().valueOf() / scaleFactor + (typeof flexProps.width === 'number' ? flexProps.width : null) || yoga._YGNodeLayoutGetWidth(node) / scaleFactor const height = (typeof flexProps.height === 'number' ? flexProps.height : null) || - node.getComputedHeight().valueOf() / scaleFactor + yoga._YGNodeLayoutGetHeight(node) / scaleFactor if (Math.abs(width - size[0]) > epsilon || Math.abs(height - size[1]) > epsilon) { setSize([width, height]) diff --git a/src/Flex.tsx b/src/Flex.tsx index 44d30b4..ea85986 100644 --- a/src/Flex.tsx +++ b/src/Flex.tsx @@ -1,8 +1,8 @@ import React, { useLayoutEffect, useMemo, useCallback, PropsWithChildren, useRef } from 'react' -import Yoga, { YogaNode } from 'yoga-layout-prebuilt' import * as THREE from 'three' import { useFrame, useThree, ReactThreeFiber } from '@react-three/fiber' import mergeRefs from 'react-merge-refs' +import { YGNodeRef, CONSTANTS } from 'yoga-wasm-slim' import { setYogaProperties, @@ -13,6 +13,8 @@ import { getFlex2DSize, getOBBSize, getRootShift, + useYogaAsync, + setPropertyString, } from './util' import { boxContext, flexContext, SharedFlexContext, SharedBoxContext } from './context' import type { R3FlexProps, FlexYogaDirection, FlexPlane } from './props' @@ -37,7 +39,7 @@ export type FlexProps = PropsWithChildren< Omit, 'children'> > interface BoxesItem { - node: YogaNode + node: YGNodeRef group: THREE.Group flexProps: R3FlexProps centerAnchor: boolean @@ -223,7 +225,7 @@ function FlexImpl( // Keeps track of the yoga nodes of the children and the related wrapper groups const boxesRef = useRef([]) const registerBox = useCallback( - (node: YogaNode, group: THREE.Group, flexProps: R3FlexProps, centerAnchor: boolean = false) => { + (node: YGNodeRef, group: THREE.Group, flexProps: R3FlexProps, centerAnchor: boolean = false) => { const i = boxesRef.current.findIndex((b) => b.node === node) if (i !== -1) { boxesRef.current.splice(i, 1) @@ -232,17 +234,19 @@ function FlexImpl( }, [] ) - const unregisterBox = useCallback((node: YogaNode) => { + const unregisterBox = useCallback((node: YGNodeRef) => { const i = boxesRef.current.findIndex((b) => b.node === node) if (i !== -1) { boxesRef.current.splice(i, 1) } }, []) + const yoga = useYogaAsync('./') + // Reference to the yoga native node - const node = useMemo(() => Yoga.Node.create(), []) + const node = useMemo(() => yoga._YGNodeNew(), []) useLayoutEffect(() => { - setYogaProperties(node, flexProps, scaleFactor) + setYogaProperties(yoga, node, flexProps, scaleFactor) }, [node, flexProps, scaleFactor]) // Mechanism for invalidating and recalculating layout @@ -266,7 +270,11 @@ function FlexImpl( const depthAxis = getDepthAxis(plane) const [flexWidth, flexHeight] = getFlex2DSize(size, plane) const yogaDirection_ = - yogaDirection === 'ltr' ? Yoga.DIRECTION_LTR : yogaDirection === 'rtl' ? Yoga.DIRECTION_RTL : yogaDirection + yogaDirection === 'ltr' + ? CONSTANTS.DIRECTION_LTR + : yogaDirection === 'rtl' + ? CONSTANTS.DIRECTION_RTL + : yogaDirection // Shared context for flex and box const sharedFlexContext = useMemo( @@ -288,14 +296,7 @@ function FlexImpl( if (!disableSizeRecalc) { // Recalc all the sizes boxesRef.current.forEach(({ group, node, flexProps }) => { - const scaledWidth = typeof flexProps.width === 'number' ? flexProps.width * scaleFactor : flexProps.width - const scaledHeight = typeof flexProps.height === 'number' ? flexProps.height * scaleFactor : flexProps.height - - if (scaledWidth !== undefined && scaledHeight !== undefined) { - // Forced size, no need to calculate bounding box - node.setWidth(scaledWidth) - node.setHeight(scaledHeight) - } else if (node.getChildCount() === 0) { + if (yoga._YGNodeGetChildCount(node) === 0 || flexProps.width === undefined || flexProps.height === undefined) { // No size specified, calculate size if (rootGroup.current) { getOBBSize(group, rootGroup.current, boundingBox, vec) @@ -304,17 +305,17 @@ function FlexImpl( boundingBox.setFromObject(group).getSize(vec) } - node.setWidth(scaledWidth || vec[mainAxis] * scaleFactor) - node.setHeight(scaledHeight || vec[crossAxis] * scaleFactor) + setPropertyString(yoga, node, 'Width', flexProps.width || vec[mainAxis], scaleFactor) + setPropertyString(yoga, node, 'Height', flexProps.height || vec[crossAxis], scaleFactor) } }) } // Perform yoga layout calculation - node.calculateLayout(flexWidth * scaleFactor, flexHeight * scaleFactor, yogaDirection_) + yoga._YGNodeCalculateLayout(node, flexWidth * scaleFactor, flexHeight * scaleFactor, yogaDirection_) - const rootWidth = node.getComputedWidth() - const rootHeight = node.getComputedHeight() + const rootWidth = yoga._YGNodeLayoutGetWidth(node) + const rootHeight = yoga._YGNodeLayoutGetHeight(node) let minX = 0 let maxX = 0 @@ -323,8 +324,11 @@ function FlexImpl( // Reposition after recalculation boxesRef.current.forEach(({ group, node, centerAnchor }) => { - const { left, top, width, height } = node.getComputedLayout() - const [mainAxisShift, crossAxisShift] = getRootShift(rootCenterAnchor, rootWidth, rootHeight, node) + const left = yoga._YGNodeLayoutGetLeft(node) + const top = yoga._YGNodeLayoutGetTop(node) + const width = yoga._YGNodeLayoutGetWidth(node) + const height = yoga._YGNodeLayoutGetHeight(node) + const [mainAxisShift, crossAxisShift] = getRootShift(rootCenterAnchor, rootWidth, rootHeight, yoga, node) const position = vectorFromObject({ [mainAxis]: (mainAxisShift + left + (centerAnchor ? width / 2 : 0)) / scaleFactor, diff --git a/src/context.ts b/src/context.ts index 03c242d..b990f50 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,13 +1,13 @@ import { createContext } from 'react' -import { YogaNode } from 'yoga-layout-prebuilt' +import { YGNodeRef } from 'yoga-wasm-slim' import { Group } from 'three' import { R3FlexProps } from './props' export interface SharedFlexContext { scaleFactor: number requestReflow(): void - registerBox(node: YogaNode, group: Group, flexProps: R3FlexProps, centerAnchor?: boolean): void - unregisterBox(node: YogaNode): void + registerBox(node: YGNodeRef, group: Group, flexProps: R3FlexProps, centerAnchor?: boolean): void + unregisterBox(node: YGNodeRef): void notInitialized?: boolean } @@ -28,7 +28,7 @@ const initialSharedFlexContext: SharedFlexContext = { export const flexContext = createContext(initialSharedFlexContext) export interface SharedBoxContext { - node: YogaNode | null + node: YGNodeRef | null size: [number, number] centerAnchor?: boolean notInitialized?: boolean diff --git a/src/hooks.ts b/src/hooks.ts index 79ae372..016ca98 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -1,6 +1,7 @@ import { useCallback, useContext as useContextImpl, useMemo } from 'react' import { Mesh, Vector3 } from 'three' import { flexContext, boxContext } from './context' +import { setPropertyString, useYogaAsync } from './util' export function useContext(context: React.Context) { let result = useContextImpl(context) @@ -39,14 +40,15 @@ export function useFlexNode() { export function useSetSize(): (width: number, height: number) => void { const { requestReflow, scaleFactor } = useContext(flexContext) const node = useFlexNode() + const yoga = useYogaAsync('./') const sync = useCallback( (width: number, height: number) => { if (node == null) { throw new Error('yoga node is null. sync size is impossible') } - node.setWidth(width * scaleFactor) - node.setHeight(height * scaleFactor) + setPropertyString(yoga, node, 'Width', width, scaleFactor) + setPropertyString(yoga, node, 'Height', height, scaleFactor) requestReflow() }, [node, requestReflow] diff --git a/src/props.ts b/src/props.ts index b46b226..3251c29 100644 --- a/src/props.ts +++ b/src/props.ts @@ -1,23 +1,13 @@ -import { YogaFlexDirection, YogaAlign, YogaJustifyContent, YogaFlexWrap, YogaDirection } from 'yoga-layout-prebuilt' - -export type FlexYogaDirection = YogaDirection | 'ltr' | 'rtl' +export type FlexYogaDirection = 'ltr' | 'rtl' export type FlexPlane = 'xy' | 'yz' | 'xz' export type Value = string | number -export type FlexDirection = YogaFlexDirection | 'row' | 'column' | 'row-reverse' | 'column-reverse' +export type FlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse' -export type JustifyContent = - | YogaJustifyContent - | 'center' - | 'flex-end' - | 'flex-start' - | 'space-between' - | 'space-evenly' - | 'space-around' +export type JustifyContent = 'center' | 'flex-end' | 'flex-start' | 'space-between' | 'space-evenly' | 'space-around' export type Align = - | YogaAlign | 'auto' | 'baseline' | 'center' @@ -27,7 +17,7 @@ export type Align = | 'space-between' | 'stretch' -export type FlexWrap = YogaFlexWrap | 'no-wrap' | 'wrap' | 'wrap-reverse' +export type FlexWrap = 'no-wrap' | 'wrap' | 'wrap-reverse' export type R3FlexProps = Partial<{ // Align diff --git a/src/util.ts b/src/util.ts index d2ad6bf..f941a2b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,98 +1,151 @@ import { Box3, Matrix4, Object3D, Vector3 } from 'three' -import Yoga, { YogaNode } from 'yoga-layout-prebuilt' +import Yoga, { YogaApi, YGNodeRef, CONSTANTS } from 'yoga-wasm-slim' +import usePromise from 'react-promise-suspense' import { R3FlexProps, FlexPlane } from './props' +let yogaGlobalInstance: YogaApi | null = null +export function useYogaAsync(path: string): YogaApi { + return usePromise( + async (path: string) => { + if (!yogaGlobalInstance) { + const yoga = await Yoga({ locateFile: (file) => path + file }) + yogaGlobalInstance = yoga + } + return yogaGlobalInstance + }, + [path] + ) +} + export const capitalize = (s: string) => s[0].toUpperCase() + s.slice(1) export const jsxPropToYogaProp = (s: string) => s.toUpperCase().replace('-', '_') -export const setYogaProperties = (node: YogaNode, props: R3FlexProps, scaleFactor: number) => { +export function setPropertyString( + yogaInstance: YogaApi, + node: YGNodeRef, + name: string, + value: string | number, + scaleFactor: number, + ...additionalParams: any[] +) { + if (typeof value === 'number') { + ;(yogaInstance as any)[`_YGNodeStyleSet${name}`](node, ...additionalParams, value * scaleFactor) + } else if (value.endsWith('%')) { + ;(yogaInstance as any)[`_YGNodeStyleSet${name}Percent`](node, ...additionalParams, parseFloat(value)) + } else if (value === 'auto') { + ;(yogaInstance as any)[`_YGNodeStyleSet${name}Auto`](node, ...additionalParams) + } else if (value.endsWith('px')) { + ;(yogaInstance as any)[`_YGNodeStyleSet${name}`](node, ...additionalParams, parseFloat(value) * scaleFactor) + } +} + +export const setYogaProperties = (yogaInstance: YogaApi, node: YGNodeRef, props: R3FlexProps, scaleFactor: number) => { return Object.keys(props).forEach((name) => { const value = props[name as keyof R3FlexProps] + if (!value) return + + if (!value) return if (typeof value === 'string') { switch (name) { case 'flexDir': case 'dir': case 'flexDirection': - return node.setFlexDirection((Yoga as any)[`FLEX_DIRECTION_${jsxPropToYogaProp(value)}`]) + return yogaInstance._YGNodeStyleSetFlexDirection( + node, + CONSTANTS[`FLEX_DIRECTION_${jsxPropToYogaProp(value as string)}` as keyof typeof CONSTANTS] + ) case 'align': - node.setAlignItems((Yoga as any)[`ALIGN_${jsxPropToYogaProp(value)}`]) - return node.setAlignContent((Yoga as any)[`ALIGN_${jsxPropToYogaProp(value)}`]) - case 'alignContent': - return node.setAlignContent((Yoga as any)[`ALIGN_${jsxPropToYogaProp(value)}`]) case 'alignItems': - return node.setAlignItems((Yoga as any)[`ALIGN_${jsxPropToYogaProp(value)}`]) + return yogaInstance._YGNodeStyleSetAlignItems( + node, + CONSTANTS[`ALIGN_${jsxPropToYogaProp(value as string)}` as keyof typeof CONSTANTS] + ) + case 'alignContent': + return yogaInstance._YGNodeStyleSetAlignContent( + node, + CONSTANTS[`ALIGN_${jsxPropToYogaProp(value as string)}` as keyof typeof CONSTANTS] + ) case 'alignSelf': - return node.setAlignSelf((Yoga as any)[`ALIGN_${jsxPropToYogaProp(value)}`]) + return yogaInstance._YGNodeStyleSetAlignSelf( + node, + CONSTANTS[`ALIGN_${jsxPropToYogaProp(value as string)}` as keyof typeof CONSTANTS] + ) case 'justify': case 'justifyContent': - return node.setJustifyContent((Yoga as any)[`JUSTIFY_${jsxPropToYogaProp(value)}`]) + return yogaInstance._YGNodeStyleSetJustifyContent( + node, + CONSTANTS[`JUSTIFY_${jsxPropToYogaProp(value as string)}` as keyof typeof CONSTANTS] + ) case 'wrap': case 'flexWrap': - return node.setFlexWrap((Yoga as any)[`WRAP_${jsxPropToYogaProp(value)}`]) + return yogaInstance._YGNodeStyleSetFlexWrap( + node, + CONSTANTS[`WRAP_${jsxPropToYogaProp(value as string)}` as keyof typeof CONSTANTS] + ) + case 'basis': case 'flexBasis': - return node.setFlexBasis(value) + return setPropertyString(yogaInstance, node, 'FlexBasis', value, scaleFactor) default: - return (node[`set${capitalize(name)}` as keyof YogaNode] as any)(value) + return setPropertyString(yogaInstance, node, capitalize(name), value, scaleFactor) } } else if (typeof value === 'number') { - const scaledValue = value * scaleFactor switch (name) { - case 'basis': - case 'flexBasis': - return node.setFlexBasis(scaledValue) case 'grow': case 'flexGrow': - return node.setFlexGrow(scaledValue) + return setPropertyString(yogaInstance, node, 'FlexGrow', value, scaleFactor) case 'shrink': case 'flexShrink': - return node.setFlexShrink(scaledValue) - case 'align': - return node.setAlignItems(value as any) - case 'justify': - return node.setJustifyContent(value as any) - case 'flexDir': - case 'dir': - return node.setFlexDirection(value as any) - case 'wrap': - return node.setFlexWrap(value as any) + return setPropertyString(yogaInstance, node, 'FlexShrink', value, scaleFactor) + + case 'width': + return setPropertyString(yogaInstance, node, 'Width', value, scaleFactor) + case 'height': + return setPropertyString(yogaInstance, node, 'Height', value, scaleFactor) + + case 'maxHeight': + return setPropertyString(yogaInstance, node, 'MaxWidth', value, scaleFactor) + case 'maxWidth': + return setPropertyString(yogaInstance, node, 'MaxHeight', value, scaleFactor) + case 'minHeight': + return setPropertyString(yogaInstance, node, 'MinWidth', value, scaleFactor) + case 'minWidth': + return setPropertyString(yogaInstance, node, 'MinHeight', value, scaleFactor) + case 'padding': case 'p': - return node.setPadding(Yoga.EDGE_ALL, scaledValue) + return setPropertyString(yogaInstance, node, 'Padding', value, scaleFactor, CONSTANTS.EDGE_ALL) case 'paddingLeft': case 'pl': - return node.setPadding(Yoga.EDGE_LEFT, scaledValue) + return setPropertyString(yogaInstance, node, 'Padding', value, scaleFactor, CONSTANTS.EDGE_LEFT) case 'paddingRight': case 'pr': - return node.setPadding(Yoga.EDGE_RIGHT, scaledValue) + return setPropertyString(yogaInstance, node, 'Padding', value, scaleFactor, CONSTANTS.EDGE_RIGHT) case 'paddingTop': case 'pt': - return node.setPadding(Yoga.EDGE_TOP, scaledValue) + return setPropertyString(yogaInstance, node, 'Padding', value, scaleFactor, CONSTANTS.EDGE_TOP) case 'paddingBottom': case 'pb': - return node.setPadding(Yoga.EDGE_BOTTOM, scaledValue) + return setPropertyString(yogaInstance, node, 'Padding', value, scaleFactor, CONSTANTS.EDGE_BOTTOM) case 'margin': case 'm': - return node.setMargin(Yoga.EDGE_ALL, scaledValue) + return setPropertyString(yogaInstance, node, 'Margin', value, scaleFactor, CONSTANTS.EDGE_ALL) case 'marginLeft': case 'ml': - return node.setMargin(Yoga.EDGE_LEFT, scaledValue) + return setPropertyString(yogaInstance, node, 'Margin', value, scaleFactor, CONSTANTS.EDGE_LEFT) case 'marginRight': case 'mr': - return node.setMargin(Yoga.EDGE_RIGHT, scaledValue) + return setPropertyString(yogaInstance, node, 'Margin', value, scaleFactor, CONSTANTS.EDGE_RIGHT) case 'marginTop': case 'mt': - return node.setMargin(Yoga.EDGE_TOP, scaledValue) + return setPropertyString(yogaInstance, node, 'Margin', value, scaleFactor, CONSTANTS.EDGE_TOP) case 'marginBottom': case 'mb': - return node.setMargin(Yoga.EDGE_BOTTOM, scaledValue) - - default: - return (node[`set${capitalize(name)}` as keyof YogaNode] as any)(scaledValue) + return setPropertyString(yogaInstance, node, 'Margin', value, scaleFactor, CONSTANTS.EDGE_BOTTOM) } } }) @@ -156,16 +209,24 @@ export const getOBBSize = (object: Object3D, root: Object3D, bb: Box3, size: Vec root.updateMatrixWorld() } -const getIsTopLevelChild = (node: YogaNode) => !node.getParent()?.getParent() +// TODO add _YGNodeGetParent to yoga-wasm-slim +const getIsTopLevelChild = (yogaInstance: YogaApi, node: YGNodeRef) => { + // @ts-ignore TODO rm, it's only here so I could build the package + const parentNode = yogaInstance._YGNodeGetParent(node) + if (!parentNode) return false + // @ts-ignore TODO rm, it's only here so I could build the package + return !yogaInstance._YGNodeGetParent(parentNode) +} /** @returns [mainAxisShift, crossAxisShift] */ export const getRootShift = ( rootCenterAnchor: boolean | undefined, rootWidth: number, rootHeight: number, - node: YogaNode + yogaInstance: YogaApi, + node: YGNodeRef ) => { - if (!rootCenterAnchor || !getIsTopLevelChild(node)) { + if (!rootCenterAnchor || !getIsTopLevelChild(yogaInstance, node)) { return [0, 0] } const mainAxisShift = -rootWidth / 2 diff --git a/yarn.lock b/yarn.lock index a06dbc0..f86881c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1698,6 +1698,14 @@ is-module "^1.0.0" resolve "^1.19.0" +"@rollup/plugin-replace@^2.3.2": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz#a2d539314fbc77c244858faa523012825068510a" + integrity sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg== + dependencies: + "@rollup/pluginutils" "^3.1.0" + magic-string "^0.25.7" + "@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" @@ -2652,11 +2660,6 @@ dependencies: "@types/yargs-parser" "*" -"@types/yoga-layout@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.2.tgz#efaf9e991a7390dc081a0b679185979a83a9639a" - integrity sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw== - "@typescript-eslint/eslint-plugin@^4.29.1": version "4.29.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.1.tgz#808d206e2278e809292b5de752a91105da85860b" @@ -2932,7 +2935,7 @@ acorn@^6.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== -acorn@^7.1.1, acorn@^7.4.0: +acorn@^7.1.1, acorn@^7.2.0, acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== @@ -3829,7 +3832,7 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -bytes@3.1.0: +bytes@3.1.0, bytes@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== @@ -5550,6 +5553,11 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -6171,7 +6179,7 @@ gud@^1.0.0: resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== -gzip-size@5.1.1: +gzip-size@5.1.1, gzip-size@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== @@ -7219,7 +7227,7 @@ jest-config@^27.0.6: micromatch "^4.0.4" pretty-format "^27.0.6" -jest-diff@^26.0.0: +jest-diff@^26.0.0, jest-diff@^26.0.1: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== @@ -9764,6 +9772,13 @@ react-popper@^2.2.4: react-fast-compare "^3.0.1" warning "^4.0.2" +react-promise-suspense@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/react-promise-suspense/-/react-promise-suspense-0.3.3.tgz#b085c7e0ac22b85fd3d605b1c4f181cda4310bc9" + integrity sha512-OdehKsCEWYoV6pMcwxbvJH99UrbXylmXJ1QpEL9OfHaUBzcAihyfSJV8jFq325M/wW9iKc/BoiLROXxMul+MxA== + dependencies: + fast-deep-equal "^2.0.1" + react-reconciler@^0.26.2: version "0.26.2" resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.26.2.tgz#bbad0e2d1309423f76cf3c3309ac6c96e05e9d91" @@ -10217,6 +10232,21 @@ rollup-plugin-filesize@^9.1.1: pacote "^11.2.7" terser "^5.6.0" +rollup-plugin-size-snapshot@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-size-snapshot/-/rollup-plugin-size-snapshot-0.12.0.tgz#58953494afd2241cb5e856392e123416e298003f" + integrity sha512-3DrZdAUqRWgD7ZW7sMLtHqRfUqTnWZhP2CHsz/3RdyAL36uw/WQQBaKCmisntMRO9QPDno2USmUXSxS2U9NJcw== + dependencies: + "@rollup/plugin-replace" "^2.3.2" + acorn "^7.2.0" + bytes "^3.1.0" + chalk "^4.0.0" + gzip-size "^5.1.1" + jest-diff "^26.0.1" + memory-fs "^0.5.0" + terser "^4.7.0" + webpack "^4.43.0" + rollup-plugin-terser@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" @@ -11104,7 +11134,7 @@ terser-webpack-plugin@^4.2.3: terser "^5.3.4" webpack-sources "^1.4.3" -terser@^4.1.2, terser@^4.6.3: +terser@^4.1.2, terser@^4.6.3, terser@^4.7.0: version "4.8.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== @@ -11916,7 +11946,7 @@ webpack-virtual-modules@^0.2.2: dependencies: debug "^3.0.0" -webpack@4: +webpack@4, webpack@^4.43.0: version "4.46.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== @@ -12125,12 +12155,10 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -yoga-layout-prebuilt@^1.9.6: - version "1.10.0" - resolved "https://registry.yarnpkg.com/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.10.0.tgz#2936fbaf4b3628ee0b3e3b1df44936d6c146faa6" - integrity sha512-YnOmtSbv4MTf7RGJMK0FvZ+KD8OEe/J5BNnR0GHhD8J/XcG/Qvxgszm0Un6FTHWW4uHlTgP0IztiXQnGyIR45g== - dependencies: - "@types/yoga-layout" "1.9.2" +yoga-wasm-slim@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yoga-wasm-slim/-/yoga-wasm-slim-0.0.6.tgz#0b1604a28f6453260c0b772d45b9d4cf5b11380d" + integrity sha512-H8vUiyp+wbmU4vHl87Jt0vaAZiyItKhheCnE4/Rku2pUQdvWfbrqU+GlB4bTbVIxZu7ZUwcex6Zcg7+KcQerOQ== zstddec@^0.0.2: version "0.0.2"