1
0
Fork 0

feat(components): Better snippet support in Draft component

The Draft react component would load the snippets that are part of our
plugin bundle. However, any additional snippets that are created by
plugins would not not get added to the `defs` section, and thus not
be rendered.

This changes the behavior by doing two things:

 - in `core` it adds an SVG object to the renderProps, and makes
   sure to run the `preRender` hook on this SVG object prior to
   returning the renderProps. This way, svg.defs now holds all
   defs, including any that may have been added by custom plugins
 - in the `Draft` component, we no longer add a list of predefined
   snippets to the defs section, but instead just use the svg.defs
   section verbatim. This removes any discrepancies in how SVG
   rendering and React rendering handles the defs section of the
   SVG document, and thus displays snippets.
This commit is contained in:
Joost De Cock 2020-11-08 18:19:10 +01:00
parent d493e30f30
commit 1a5b2769aa
10 changed files with 66 additions and 182 deletions

View file

@ -34,8 +34,8 @@ const createConfig = (component, module) => {
const config = []
// When developing, you can use this to only rebuild the components you're working on
let dev = true
let only = ['Workbench']
let dev = false
let only = ['Draft', 'Workbench']
for (let component of components) {
if (!dev || only.indexOf(component) !== -1) config.push(createConfig(component, false))
// Webpack doesn't handle .mjs very well

View file

@ -1,60 +0,0 @@
import React from 'react'
const Grid = (props) => {
let style = {
style: {
fill: 'none',
stroke: 'currentColor'
}
}
if (props.units === 'imperial')
return (
<pattern id="grid" height="25.4" width="25.4" patternUnits="userSpaceOnUse" key="grid">
<path className="gridline lg imperial" d="M 0 0 L 0 25.4 L 25.4 25.4" {...style} />
<path
className="gridline lg imperial"
d="M 12.7 0 L 12.7 25.4 M 0 12.7 L 25.4 12.7"
{...style}
/>
<path
className="gridline sm imperial"
d="M 3.175 0 L 3.175 25.4 M 6.32 0 L 6.35 25.4 M 9.525 0 L 9.525 25.4 M 15.875 0 L 15.875 25.4 M 19.05 0 L 19.05 25.4 M 22.225 0 L 22.225 25.4"
{...style}
/>
<path
className="gridline sm imperial"
d="M 0 3.175 L 25.4 3.175 M 0 6.32 L 25.4 6.35 M 0 9.525 L 25.4 9.525 M 0 15.875 L 25.4 15.875 M 0 19.05 L 25.4 19.05 M 0 22.225 L 25.4 22.225"
{...style}
/>
</pattern>
)
else
return (
<pattern id="grid" height="100" width="100" patternUnits="userSpaceOnUse" key="grid">
<path className="gridline lg metric" d="M 0 0 L 0 100 L 100 100" {...style} />
<path className="gridline metric" d="M 50 0 L 50 100 M 0 50 L 100 50" {...style} />
<path
className="gridline sm metric"
d="M 10 0 L 10 100 M 20 0 L 20 100 M 30 0 L 30 100 M 40 0 L 40 100 M 60 0 L 60 100 M 70 0 L 70 100 M 80 0 L 80 100 M 90 0 L 90 100"
{...style}
/>
<path
className="gridline sm metric"
d="M 0 10 L 100 10 M 0 20 L 100 20 M 0 30 L 100 30 M 0 40 L 100 40 M 0 60 L 100 60 M 0 70 L 100 70 M 0 80 L 100 80 M 0 90 L 100 90"
{...style}
/>
<path
className="gridline xs metric"
d="M 5 0 L 5 100 M 15 0 L 15 100 M 25 0 L 25 100 M 35 0 L 35 100 M 45 0 L 45 100 M 55 0 L 55 100 M 65 0 L 65 100 M 75 0 L 75 100 M 85 0 L 85 100 M 95 0 L 95 100"
{...style}
/>
<path
className="gridline xs metric"
d="M 0 5 L 100 5 M 0 15 L 100 15 M 0 25 L 100 25 M 0 35 L 100 35 M 0 45 L 100 45 M 0 55 L 100 55 M 0 65 L 100 65 M 0 75 L 100 75 M 0 85 L 100 85 M 0 95 L 100 95"
{...style}
/>
</pattern>
)
}
export default Grid

File diff suppressed because one or more lines are too long

View file

@ -1,34 +0,0 @@
import React from 'react'
const Markers = (props) => {
const markerProps = {
orient: 'auto',
refX: '0.0',
refY: '0.0',
style: { overflow: 'visible' }
}
const from = { d: 'M 0,0 L 12,-4 C 10,-2 10,2 12, 4 z' }
const to = { d: 'M 0,0 L -12,-4 C -10,-2 -10,2 -12, 4 z' }
const types = {
grainline: 'note',
cutonfold: 'note',
dimension: 'mark'
}
let output = []
for (let type in types) {
output.push(
<marker id={type + 'From'} key={type + '-from'} {...markerProps}>
<path className={types[type] + ' fill-' + types[type]} {...from} />
</marker>
)
output.push(
<marker id={type + 'To'} key={type + '-to'} {...markerProps}>
<path className={types[type] + ' fill-' + types[type]} {...to} />
</marker>
)
}
return output
}
export default Markers

View file

@ -1,56 +0,0 @@
import React from 'react'
import logoPathString from './logo-path'
const Snippets = (props) => {
const fill = { fill: 'currentColor', stroke: 'none' }
const stroke = { fill: 'none', stroke: 'currentColor' }
return [
<g id="notch" className="snippet notch" key="notch">
<circle cy="0" cx="0" r="1.4" {...fill} />
<circle cy="0" cx="0" r="2.8" {...stroke} />
</g>,
<g id="bnotch" className="snippet bnotch" key="bnotch">
<path d="M -1.1 -1.1 L 1.1 1.1 M 1.1 -1.1 L -1.1 1.1" {...stroke} />
<circle cy="0" cx="0" r="2.8" {...stroke} />
</g>,
<g id="button" className="snippet button" key="button">
<circle cx="0" cy="0" r="3.4" {...stroke} /> />
<circle cx="-1" cy="-1" r="0.5" {...fill} />
<circle cx="1" cy="-1" r="0.5" {...fill} />
<circle cx="1" cy="1" r="0.5" {...fill} />
<circle cx="-1" cy="1" r="0.5" {...fill} />
</g>,
<g id="buttonhole" className="snippet buttonhole" key="buttonhole">
<path d="M -1,-5 L 1,-5 L 1,5 L -1,5 z" {...stroke} />
<path d="M -1,-5 L 1,-5 L 1,-4 L -1,-4 z M -1,5 L 1,5 L 1,4 L -1,4 z" {...fill} />
</g>,
<radialGradient key="grad" id="snap-stud-grad" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="30%" style={{ stopColor: 'rgb(235,235,235)', stopOpacity: 1 }} />
<stop offset="80%" style={{ stopColor: 'rgb(100,100,100)', stopOpacity: 1 }} />
</radialGradient>,
<g id="snap-stud" key="snapstud">
<circle cx="0" cy="0" r="3.4" style={{ stroke: '#666', fill: '#dddddd', strokeWidth: 0.3 }} />
<circle cx="0" cy="0" r="1.8" style={{ stroke: 'none', fill: 'url(#snap-stud-grad)' }} />
<path
style={{ fill: 'none', stroke: '#666', strokeWidth: 0.2 }}
d="M -2,0 L -3,0 M 2,0 L 3,0 M 0,2 L 0,3 M 0,-2 L 0,-3 M 1.5,1.5 L 2.1,2.1 M -1.5,1.5 L -2.1,2.1 M -1.5,-1.5 L -2.1,-2.1 M 1.5,-1.5 L 2.1,-2.1"
/>
</g>,
<g id="snap-socket" key="snapsocket">
<circle cx="0" cy="0" r="3.4" style={{ stroke: '#666', fill: '#bbbbbb', strokeWidth: 0.3 }} />
<circle cx="0" cy="0" r="2" style={{ stroke: '#666', fill: '#dddddd', strokeWidth: 0.4 }} />
<path
style={{ fill: 'none', stroke: '#666', strokeWidth: 0.5 }}
d="M -1.7,-1 L -1.7,1 M 1.7,-1 L 1.7,1"
/>
</g>,
<g id="eyelet" className="snippet eyelet" key="eyelet">
<circle cy="0" cx="0" r="2.5" {...stroke} />
</g>,
<g id="logo" className="snippet logo" transform="translate(-23 -36)" key="logo">
<path d={logoPathString} {...fill} />
</g>
]
}
export default Snippets

File diff suppressed because one or more lines are too long

View file

@ -1,33 +1,71 @@
import React from 'react'
import Markers from './Markers'
import Snippets from './Snippets'
import Grid from './Grid'
const style = ` style="fill: none; stroke: currentColor;" `
const grids = {
imperial: `
<pattern id="grid" height="25.4" width="25.4" patternUnits="userSpaceOnUse" key="grid">
<path class="gridline lg imperial" d="M 0 0 L 0 25.4 L 25.4 25.4" ${style} />
<path
class="gridline lg imperial"
d="M 12.7 0 L 12.7 25.4 M 0 12.7 L 25.4 12.7"
${style}
/>
<path
class="gridline sm imperial"
d="M 3.175 0 L 3.175 25.4 M 6.32 0 L 6.35 25.4 M 9.525 0 L 9.525 25.4 M 15.875 0 L 15.875 25.4 M 19.05 0 L 19.05 25.4 M 22.225 0 L 22.225 25.4"
${style}
/>
<path
class="gridline sm imperial"
d="M 0 3.175 L 25.4 3.175 M 0 6.32 L 25.4 6.35 M 0 9.525 L 25.4 9.525 M 0 15.875 L 25.4 15.875 M 0 19.05 L 25.4 19.05 M 0 22.225 L 25.4 22.225"
${style}
/>
</pattern>
`,
metric: `
<pattern id="grid" height="100" width="100" patternUnits="userSpaceOnUse" key="grid">
<path class="gridline lg metric" d="M 0 0 L 0 100 L 100 100" ${style} />
<path class="gridline metric" d="M 50 0 L 50 100 M 0 50 L 100 50" ${style} />
<path
class="gridline sm metric"
d="M 10 0 L 10 100 M 20 0 L 20 100 M 30 0 L 30 100 M 40 0 L 40 100 M 60 0 L 60 100 M 70 0 L 70 100 M 80 0 L 80 100 M 90 0 L 90 100"
${style}
/>
<path
class="gridline sm metric"
d="M 0 10 L 100 10 M 0 20 L 100 20 M 0 30 L 100 30 M 0 40 L 100 40 M 0 60 L 100 60 M 0 70 L 100 70 M 0 80 L 100 80 M 0 90 L 100 90"
${style}
/>
<path
class="gridline xs metric"
d="M 5 0 L 5 100 M 15 0 L 15 100 M 25 0 L 25 100 M 35 0 L 35 100 M 45 0 L 45 100 M 55 0 L 55 100 M 65 0 L 65 100 M 75 0 L 75 100 M 85 0 L 85 100 M 95 0 L 95 100"
${style}
/>
<path
class="gridline xs metric"
d="M 0 5 L 100 5 M 0 15 L 100 15 M 0 25 L 100 25 M 0 35 L 100 35 M 0 45 L 100 45 M 0 55 L 100 55 M 0 65 L 100 65 M 0 75 L 100 75 M 0 85 L 100 85 M 0 95 L 100 95"
${style}
/>
</pattern>
`
}
const Defs = (props) => {
let paperlessGrids = null
if (props.paperless) {
paperlessGrids = []
let defs = props.svg.defs
if (props.settings.paperless) {
defs += grids[props.settings.units || 'metric']
for (let p in props.parts) {
let anchor = { x: 0, y: 0 }
if (typeof props.parts[p].points.gridAnchor !== 'undefined')
anchor = props.parts[p].points.gridAnchor
else if (typeof props.parts[p].points.anchor !== 'undefined')
anchor = props.parts[p].points.anchor
paperlessGrids.push(
<pattern id={'grid-' + p} key={'grid-' + p} xlinkHref="#grid" x={anchor.x} y={anchor.y} />
)
defs += `<pattern id="grid-${p}" key="grid-${p}" xlink:href="#grid" x="${anchor.x}" y="${anchor.y}" />`
}
}
return (
<defs>
<Markers />
<Snippets />
<Grid units={props.units} />
{paperlessGrids}
{props.extraDefs || '<!-- no extras -->'}
<g></g>
</defs>
)
return <defs dangerouslySetInnerHTML={{ __html: defs }} />
}
export default Defs

View file

@ -15,13 +15,7 @@ const Draft = (props) => (
viewBox={props.viewBox}
className={props.className || 'freesewing draft'}
>
<Defs
units={props.settings.units}
parts={props.parts}
paperless={props.settings.paperless}
design={props.design || false}
extraDefs={props.extraDefs}
/>
<Defs {...props} />
<g>
{Object.keys(props.parts).map((name) => (
<Part

View file

@ -123,7 +123,6 @@ const Workbench = ({
return true
}
}
console.log('measurements ok', measurements)
return false
}

View file

@ -649,8 +649,13 @@ Pattern.prototype.wants = function (partName) {
* an external renderer (eg. a React component)
*/
Pattern.prototype.getRenderProps = function () {
// Run pre-render hook
let svg = new Svg(this)
svg.hooks = this.hooks
svg.runHooks('preRender')
this.pack()
let props = {}
let props = { svg }
props.width = this.width
props.height = this.height
props.settings = this.settings