1
0
Fork 0

fix [react]: Recursion loop in Xray

This commit is contained in:
joostdecock 2024-12-10 18:03:03 +01:00
parent a6b11b5a24
commit bfea59af4d
5 changed files with 152 additions and 133 deletions

View file

@ -1,7 +1,4 @@
// __SDEFILE__ - This file is a dependency for the stand-alone environment
// eslint-disable-next-line no-unused-vars
import React, { forwardRef } from 'react' import React, { forwardRef } from 'react'
// Components that can be swizzled
import { Svg as DefaultSvg } from './svg.mjs' import { Svg as DefaultSvg } from './svg.mjs'
import { Defs as DefaultDefs } from './defs.mjs' import { Defs as DefaultDefs } from './defs.mjs'
import { Group as DefaultGroup } from './group.mjs' import { Group as DefaultGroup } from './group.mjs'
@ -13,11 +10,12 @@ import { Path as DefaultPath } from './path.mjs'
import { Grid as DefaultGrid } from './grid.mjs' import { Grid as DefaultGrid } from './grid.mjs'
import { Text as DefaultText, TextOnPath as DefaultTextOnPath } from './text.mjs' import { Text as DefaultText, TextOnPath as DefaultTextOnPath } from './text.mjs'
import { Circle as DefaultCircle } from './circle.mjs' import { Circle as DefaultCircle } from './circle.mjs'
import { getId, getProps, withinPartBounds, translateStrings } from './utils.mjs'
/* /*
* Allow people to swizzle these components * Allow people to override these components
*/ */
export const defaultPatternComponents = { const defaultComponents = {
Svg: DefaultSvg, Svg: DefaultSvg,
Defs: DefaultDefs, Defs: DefaultDefs,
Group: DefaultGroup, Group: DefaultGroup,
@ -32,26 +30,29 @@ export const defaultPatternComponents = {
Circle: DefaultCircle, Circle: DefaultCircle,
} }
export const Pattern = forwardRef( /*
( * The pattern component
{ * FIXME: document props
*/
const Pattern = forwardRef((props, ref) => {
if (!props.renderProps) return null
// Destructure props
const {
renderProps = false, renderProps = false,
t = (string) => string, t = (string) => string,
components = {},
children = false, children = false,
className = 'freesewing pattern', className = 'freesewing pattern',
}, components = {},
ref } = props
) => {
if (!renderProps) return null
// Merge default and swizzled components // Merge default and swizzled components
components = { const mergedComponents = {
...defaultPatternComponents, ...defaultComponents,
...components, ...components,
} }
const { Svg, Defs, Stack, Group } = components const { Svg, Defs, Stack, Group } = mergedComponents
const optionalProps = {} const optionalProps = {}
if (className) optionalProps.className = className if (className) optionalProps.className = className
@ -77,14 +78,23 @@ export const Pattern = forwardRef(
stackName={stackName} stackName={stackName}
stack={renderProps.stacks[stackName]} stack={renderProps.stacks[stackName]}
settings={renderProps.settings} settings={renderProps.settings}
components={components} components={mergedComponents}
t={t} t={t}
/> />
))} ))}
</Group> </Group>
</Svg> </Svg>
) )
} })
)
Pattern.displayName = 'Pattern' export {
// utils
getId,
getProps,
withinPartBounds,
translateStrings,
// default components
defaultComponents,
// The Pattern component itself
Pattern,
}

View file

@ -1,5 +1,3 @@
// __SDEFILE__ - This file is a dependency for the stand-alone environment
// eslint-disable-next-line no-unused-vars
import React from 'react' import React from 'react'
export const getProps = (obj) => { export const getProps = (obj) => {

View file

@ -1,39 +1,36 @@
// __SDEFILE__ - This file is a dependency for the stand-alone environment
// eslint-disable-next-line no-unused-vars
import React, { forwardRef } from 'react' import React, { forwardRef } from 'react'
import { defaultPatternComponents } from '../pattern/index.mjs' import { defaultComponents as patternComponents } from '@freesewing/react/components/Pattern'
// Components that can be swizzled
import { PointXray } from './point.mjs' import { PointXray } from './point.mjs'
import { PathXray } from './path.mjs' import { PathXray } from './path.mjs'
/* /*
* Allow people to swizzle these components * Allow people to override these components
*/ */
export const defaultPatternXrayComponents = { const defaultComponents = {
...defaultPatternComponents,
Point: PointXray, Point: PointXray,
Path: PathXray, Path: PathXray,
} }
export const PatternXray = forwardRef( export const Xray = forwardRef((props, ref) => {
( if (!props.renderProps) return null
{
// desctructure props
const {
renderProps = false, renderProps = false,
t = (string) => string, t = (string) => string,
components = {},
children = false, children = false,
className = 'freesewing pattern', className = 'freesewing pattern',
}, components = {},
ref } = props
) => {
if (!renderProps) return null
// Merge default and swizzled components // Merge pattern, default, and custom components
components = { const mergedComponents = {
...defaultPatternXrayComponents, ...patternComponents,
...defaultComponents,
...components, ...components,
} }
const { Svg, Defs, Stack, Group } = components const { Svg, Defs, Stack, Group } = mergedComponents
const optionalProps = {} const optionalProps = {}
if (className) optionalProps.className = className if (className) optionalProps.className = className
@ -59,14 +56,11 @@ export const PatternXray = forwardRef(
stackName={stackName} stackName={stackName}
stack={renderProps.stacks[stackName]} stack={renderProps.stacks[stackName]}
settings={renderProps.settings} settings={renderProps.settings}
components={components} components={mergedComponents}
t={t} t={t}
/> />
))} ))}
</Group> </Group>
</Svg> </Svg>
) )
} })
)
PatternXray.displayName = 'PatternXray'

View file

@ -1,8 +1,8 @@
// __SDEFILE__ - This file is a dependency for the stand-alone environment
import React from 'react' import React from 'react'
// Components import {
import { Path } from '../pattern/path.mjs' getProps,
import { getProps } from '../pattern/utils.mjs' defaultComponents as patternComponents,
} from '@freesewing/react/components/Pattern'
const coords = (point) => `${point.x},${point.y}` const coords = (point) => `${point.x},${point.y}`
@ -10,7 +10,7 @@ const Cp = ({ at }) => (
<circle cx={at.x} cy={at.y} r={0.75} className="stroke-md opacity-50 text-warning" /> <circle cx={at.x} cy={at.y} r={0.75} className="stroke-md opacity-50 text-warning" />
) )
const Xray = ({ path }) => { export const Xray = ({ path, components }) => {
const output = [] const output = []
let prev let prev
let i = 0 let i = 0
@ -38,9 +38,18 @@ const Xray = ({ path }) => {
return output return output
} }
export const PathXray = ({ stackName, pathName, part, path, settings, components, t }) => ( export const PathXray = ({ stackName, pathName, part, path, settings, components, t }) => {
<> /*
* We use the Path component from Pattern here
* If we would extract Path from the components passed down,
* we'd create a recursion loop as the Path we call below
* would be this very PathXray component.
*/
const { Path } = patternComponents
return (
<g>
<Xray path={path} /> <Xray path={path} />
<Path {...{ stackName, pathName, path, part, settings, components, t }} /> <Path {...{ stackName, pathName, path, part, settings, components, t }} />
</> </g>
) )
}

View file

@ -1,12 +1,20 @@
// __SDEFILE__ - This file is a dependency for the stand-alone environment
import React from 'react' import React from 'react'
// Components import {
import { Point } from '../pattern/point.mjs' withinPartBounds,
import { withinPartBounds } from '../pattern/utils.mjs' defaultComponents as patternComponents,
} from '@freesewing/react/components/Pattern'
export const PointXray = ({ stackName, pointName, part, point, settings, components, t }) => { export const PointXray = ({ stackName, pointName, part, point, settings, components, t }) => {
// Don't include parts outside the part bounding box // Don't include parts outside the part bounding box
if (!withinPartBounds(point, part)) return null if (!withinPartBounds(point, part)) return null
/*
* We use the Point component from Pattern here
* If we would extract Point from the components passed down,
* we'd create a recursion loop as the Point we call below
* would be this very PointXray component.
*/
const { Point } = patternComponents
return ( return (
<> <>
<Point {...{ stackName, pointName, part, point, settings, components, t }} /> <Point {...{ stackName, pointName, part, point, settings, components, t }} />