feat(lab): Bring up info on paths when clicked upon
This commit is contained in:
parent
e153fbc925
commit
a37e66c0e5
11 changed files with 473 additions and 35 deletions
22
sites/shared/components/modal.js
Normal file
22
sites/shared/components/modal.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { useState } from 'react'
|
||||
|
||||
const Modal = ({ cancel, children }) => {
|
||||
|
||||
|
||||
return (
|
||||
<div className={`
|
||||
fixed top-0 left-0 right-0 w-screen h-screen
|
||||
bg-neutral bg-opacity-70 z-30
|
||||
hover:cursor-pointer flex flex-col justify-center
|
||||
`} onClick={cancel}>
|
||||
<div className="m-auto text-neutral-content lightbox" style={{
|
||||
maxHeight: "calc(100vh - 6rem)",
|
||||
maxWidth: "calc(100vw - 6rem)",
|
||||
}}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Modal
|
|
@ -3,7 +3,7 @@ import Error from './error.js'
|
|||
import Robot from 'shared/components/robot/index.js'
|
||||
|
||||
const LabDraft = props => {
|
||||
const { app, draft, design, gist, updateGist, unsetGist, feedback } = props
|
||||
const { app, draft, design, gist, updateGist, unsetGist, showInfo, feedback } = props
|
||||
|
||||
if (!draft) return null
|
||||
|
||||
|
@ -32,7 +32,7 @@ const LabDraft = props => {
|
|||
? <Error {...{ draft, patternProps, updateGist }} />
|
||||
: null
|
||||
}
|
||||
<SvgWrapper {...{ draft, patternProps, gist, updateGist, unsetGist, app, feedback }} />
|
||||
<SvgWrapper {...{ draft, patternProps, gist, updateGist, unsetGist, showInfo, app, feedback }} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,21 +1,436 @@
|
|||
import React from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import TextOnPath from '../text-on-path'
|
||||
import { getProps } from '../utils'
|
||||
import { round } from 'shared/utils'
|
||||
|
||||
const XrayPath = props => (
|
||||
<g>
|
||||
const pointInfo = point => point
|
||||
? `[ ${round(point.x, 2)}, ${round(point.y, 2)} ]`
|
||||
: null
|
||||
|
||||
const Tr = ({ children }) => <tr className="border border-base-300">{children}</tr>
|
||||
const KeyTd = ({ children }) => <td className="p-3 text-right">{children}:</td>
|
||||
const ValTd = ({ children }) => <td className="p-3">{children}</td>
|
||||
|
||||
const TextAlongPath = ({id, size, fill="var(--pattern-note)", txt}) => (
|
||||
<text>
|
||||
<textPath xlinkHref={`#${id}`} startOffset="50%">
|
||||
<tspan
|
||||
style={{ textAnchor: 'middle', fontSize: size }}
|
||||
className="fill-neutral-content fill-opacity-50"
|
||||
dy={size * -0.4}
|
||||
>
|
||||
{txt}
|
||||
</tspan>
|
||||
</textPath>
|
||||
</text>
|
||||
)
|
||||
const PointCircle = ({ point, size, className="stroke-neutral-content" }) => (
|
||||
<circle
|
||||
cx={point.x} cy={point.y} r={size/50}
|
||||
className={className}
|
||||
fill="none" strokeWidth={size/150} strokeOpacity="0.5"
|
||||
/>
|
||||
)
|
||||
|
||||
const pathDimensions = (from, to, cp1=false, cp2=false, path=false) => {
|
||||
const topLeft = {
|
||||
x: (to.x < from.x) ? to.x : from.x,
|
||||
y: (to.y < from.y) ? to.y : from.y,
|
||||
}
|
||||
const bottomRight = {
|
||||
x: (to.x > from.x) ? to.x : from.x,
|
||||
y: (to.y > from.y) ? to.y : from.y,
|
||||
}
|
||||
let bbox = false
|
||||
// Deal with curves
|
||||
if (cp1 && cp2) {
|
||||
if (cp1.x < topLeft.x) topLeft.x = cp1.x
|
||||
if (cp2.x < topLeft.x) topLeft.x = cp2.x
|
||||
if (cp1.x > bottomRight.x) bottomRight.x = cp1.x
|
||||
if (cp2.x > bottomRight.x) bottomRight.x = cp2.x
|
||||
if (cp1.y < topLeft.y) topLeft.y = cp1.y
|
||||
if (cp2.y < topLeft.y) topLeft.y = cp2.y
|
||||
if (cp1.y > bottomRight.y) bottomRight.y = cp1.y
|
||||
if (cp2.y > bottomRight.y) bottomRight.y = cp2.y
|
||||
// This undocumented core methods returns the curve's bounding box
|
||||
bbox = path.boundary()
|
||||
}
|
||||
const w = bottomRight.x - topLeft.x
|
||||
const h = bottomRight.y - topLeft.y
|
||||
const size = w > h ? w : h
|
||||
|
||||
return {
|
||||
topLeft,
|
||||
bottomRight,
|
||||
w,
|
||||
h,
|
||||
size,
|
||||
bbox
|
||||
}
|
||||
}
|
||||
|
||||
const Defs = () => (
|
||||
<defs>
|
||||
<marker orient="auto" refY="0.0" refX="0.0" id="arrowTo" style={{overflow: 'visible'}}>
|
||||
<path className="fill-neutral-content" d="M 0,0 L -12,-4 C -10,-2 -10,2 -12, 4 z" fillOpacity="0.5"></path>
|
||||
</marker>
|
||||
<marker orient="auto" refY="0.0" refX="0.0" id="arrowFrom" style={{overflow: 'visible'}}>
|
||||
<path className="fill-neutral-content" d="M 0,0 L 12,-4 C 10,-2 10,2 12, 4 z" fillOpacity="0.5"></path>
|
||||
</marker>
|
||||
</defs>
|
||||
)
|
||||
|
||||
const svgProps = {
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
xmlnsSvg: "http://www.w3.org/2000/svg",
|
||||
xmlnsXlink: "http://www.w3.org/1999/xlink",
|
||||
style: { maxHeight: 'inherit', strokeLinecap: 'round', strokeLinejoin: 'round' },
|
||||
}
|
||||
|
||||
const Line = (props) => {
|
||||
const ops = props.path.ops
|
||||
const from = ops[0].to
|
||||
const to = ops[1].to
|
||||
const { topLeft, bottomRight, w, h, size } = pathDimensions(from, to)
|
||||
const id = `${props.partName}_${props.pathName}_${props.i}`
|
||||
|
||||
const xyProps = {
|
||||
className: "stroke-neutral-content",
|
||||
strokeOpacity: "0.5",
|
||||
fill: "none",
|
||||
strokeWidth: (size/300),
|
||||
}
|
||||
|
||||
return (
|
||||
<svg {...svgProps}
|
||||
viewBox={`${topLeft.x - (size/10)} ${topLeft.y - (size/10)} ${w + (size/5)} ${h + (size/5)}`}
|
||||
>
|
||||
<path id={`${id}_x`} {...xyProps}
|
||||
d={`M ${topLeft.x},${bottomRight.y} L ${bottomRight.x},${bottomRight.y}`}
|
||||
/>
|
||||
<TextAlongPath id={`${id}_x`} size={size/18} txt={round(bottomRight.x - topLeft.x, 2)+'mm'} />
|
||||
<path id={`${id}_y`} {...xyProps}
|
||||
d={`M ${topLeft.x},${bottomRight.y} L ${topLeft.x},${topLeft.y}`}
|
||||
/>
|
||||
<TextAlongPath id={`${id}_y`} size={size/18} txt={round(bottomRight.y - topLeft.y, 2)+'mm'} />
|
||||
<path
|
||||
id={id}
|
||||
d={`M ${from.x},${from.y} L ${to.x},${to.y}`}
|
||||
className="stroke-neutral-content"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={(size/100)}
|
||||
/>
|
||||
<TextAlongPath id={id} size={size/18} txt={round(props.path.length(), 2)+'mm'} />
|
||||
<PointCircle point={from} size={size} />
|
||||
<PointCircle point={to} size={size} />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
const Curve = (props) => {
|
||||
const ops = props.path.ops
|
||||
const from = ops[0].to
|
||||
const { to, cp1, cp2 } = ops[1]
|
||||
const { topLeft, bottomRight, w, h, size, bbox } = pathDimensions(from, to, cp1, cp2, props.path)
|
||||
const id = `${props.partName}_${props.pathName}_${props.i}`
|
||||
|
||||
const cpProps = {
|
||||
className: "stroke-success",
|
||||
strokeOpacity: "0.85",
|
||||
fill: "none",
|
||||
strokeWidth: (size/300),
|
||||
}
|
||||
const xyProps = {
|
||||
...cpProps,
|
||||
strokeOpacity: "0.5",
|
||||
className: "stroke-neutral-content",
|
||||
markerEnd: "url(#arrowTo)",
|
||||
markerStart: "url(#arrowFrom)",
|
||||
}
|
||||
|
||||
return (
|
||||
<svg {...svgProps}
|
||||
viewBox={`${topLeft.x - (size/10)} ${topLeft.y - (size/10)} ${w + (size/5)} ${h + (size/5)}`}
|
||||
>
|
||||
<Defs />
|
||||
<path id={`${id}_x`} {...xyProps}
|
||||
d={`M ${bbox.topLeft.x},${bbox.bottomRight.y} L ${bbox.bottomRight.x},${bbox.bottomRight.y}`}
|
||||
/>
|
||||
<TextAlongPath id={`${id}_x`} size={size/18} txt={round(bbox.bottomRight.x - bbox.topLeft.x, 2)+'mm'} />
|
||||
<path id={`${id}_y`} {...xyProps}
|
||||
d={`M ${bbox.topLeft.x},${bbox.bottomRight.y} L ${bbox.topLeft.x},${bbox.topLeft.y}`}
|
||||
/>
|
||||
<TextAlongPath id={`${id}_y`} size={size/18} txt={round(bbox.bottomRight.y - bbox.topLeft.y, 2)+'mm'} />
|
||||
<path id={`${id}_cp1`} {...cpProps} d={`M ${from.x},${from.y} L ${cp1.x},${cp1.y}`} />
|
||||
<PointCircle point={cp1} size={size} className="stroke-success" />
|
||||
<path id={`${id}_cp2`} {...cpProps} d={`M ${to.x},${to.y} L ${cp2.x},${cp2.y}`} />
|
||||
<PointCircle point={cp2} size={size} className="stroke-success"/>
|
||||
<path
|
||||
id={id}
|
||||
d={`M ${from.x},${from.y} C ${cp1.x},${cp1.y} ${cp2.x},${cp2.y} ${to.x},${to.y}`}
|
||||
className="stroke-neutral-content"
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={(size/100)}
|
||||
/>
|
||||
<TextAlongPath id={id} size={size/18} txt={round(props.path.length(), 2)+'mm'} />
|
||||
<PointCircle point={from} size={size} />
|
||||
<PointCircle point={to} size={size} />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
const MiniPath = props => {
|
||||
const ops = props.path.ops
|
||||
const bbox = props.path.boundary()
|
||||
const id = `${props.partName}_${props.pathName}_mini}`
|
||||
const w = bbox.bottomRight.x - bbox.topLeft.x
|
||||
const h = bbox.bottomRight.y - bbox.topLeft.y
|
||||
const size = w > h ? w : h
|
||||
|
||||
const xyProps = {
|
||||
fill: "none",
|
||||
strokeWidth: (size/300),
|
||||
strokeOpacity: "0.5",
|
||||
className: "stroke-neutral-content",
|
||||
markerEnd: "url(#arrowTo)",
|
||||
markerStart: "url(#arrowFrom)",
|
||||
}
|
||||
|
||||
return (
|
||||
<svg {...svgProps}
|
||||
viewBox={`${bbox.topLeft.x - (size/10)} ${bbox.topLeft.y - (size/10)} ${w + (size/5)} ${h + (size/5)}`}
|
||||
className="freesewing pattern z-50"
|
||||
>
|
||||
<Defs />
|
||||
<path id={`${id}_x`} {...xyProps}
|
||||
d={`M ${bbox.topLeft.x},${bbox.bottomRight.y} L ${bbox.bottomRight.x},${bbox.bottomRight.y}`}
|
||||
/>
|
||||
<TextAlongPath id={`${id}_x`} size={size/18} txt={round(bbox.bottomRight.x - bbox.topLeft.x, 2)+'mm'} />
|
||||
<path id={`${id}_y`} {...xyProps}
|
||||
d={`M ${bbox.topLeft.x},${bbox.bottomRight.y} L ${bbox.topLeft.x},${bbox.topLeft.y}`}
|
||||
/>
|
||||
<TextAlongPath id={`${id}_y`} size={size/18} txt={round(bbox.bottomRight.y - bbox.topLeft.y, 2)+'mm'} />
|
||||
<path
|
||||
id={id}
|
||||
d={props.path.asPathstring()}
|
||||
className="stroke-neutral-content"
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={(size/100)}
|
||||
/>
|
||||
<TextAlongPath id={id} size={size/18} txt={round(props.path.length(), 2)+'mm'} />
|
||||
<XrayPath {...props} />)
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
const lineInfo = (props) => (
|
||||
<div className="p-4 border bg-neutral bg-opacity-60 shadow rounded-lg">
|
||||
<h5 className="text-neutral-content text-center pb-4">Line info</h5>
|
||||
<div className="flex flex-row flex-wrap">
|
||||
<table className="border-collapse h-fit">
|
||||
<tbody>
|
||||
<Tr>
|
||||
<KeyTd>From</KeyTd>
|
||||
<ValTd>{pointInfo(props.path.ops[0].to)}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>To</KeyTd>
|
||||
<ValTd>{pointInfo(props.path.ops[1].to)}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Length</KeyTd>
|
||||
<ValTd>{round(props.path.length(), 2)}mm</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Part</KeyTd>
|
||||
<ValTd>{props.partName}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Draw Op</KeyTd>
|
||||
<ValTd>{props.i}/{props.ops.length}</ValTd>
|
||||
</Tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="max-w-md" style={{ maxHeight: '80vh' }}>
|
||||
<Line {...props} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const XrayLine = props => (
|
||||
<>
|
||||
<path
|
||||
d={props.path.asPathstring()}
|
||||
{...getProps(props.path)}
|
||||
className="opacity-0 stroke-3xl stroke-contrast hover:opacity-25 hover:cursor-pointer"
|
||||
onClick={() => props.updateGist(
|
||||
['_state', 'xray', 'parts', props.partName, 'paths', props.pathName],
|
||||
1
|
||||
)}
|
||||
className="opacity-0 stroke-4xl stroke-note hover:opacity-25 hover:cursor-pointer"
|
||||
onClick={(evt) => { evt.stopPropagation(); props.showInfo(lineInfo(props)) }}
|
||||
/>
|
||||
</g>
|
||||
</>
|
||||
)
|
||||
|
||||
const curveInfo = (props) => (
|
||||
<div className="p-4 border bg-neutral bg-opacity-40 shadow rounded-lg">
|
||||
<h5 className="text-neutral-content text-center pb-4">Curve info</h5>
|
||||
<div className="flex flex-row flex-wrap">
|
||||
<table className="border-collapse h-fit">
|
||||
<tbody>
|
||||
<Tr>
|
||||
<KeyTd>From</KeyTd>
|
||||
<ValTd>{pointInfo(props.path.ops[0].to)}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Cp1</KeyTd>
|
||||
<ValTd>{pointInfo(props.path.ops[1].cp1)}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Cp2</KeyTd>
|
||||
<ValTd>{pointInfo(props.path.ops[1].cp2)}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>To</KeyTd>
|
||||
<ValTd>{pointInfo(props.path.ops[1].to)}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Length</KeyTd>
|
||||
<ValTd>{round(props.path.length(), 2)}mm</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Part</KeyTd>
|
||||
<ValTd>{props.partName}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Draw Op</KeyTd>
|
||||
<ValTd>{props.i}/{props.ops.length}</ValTd>
|
||||
</Tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="max-w-md" style={{ maxHeight: '80vh' }}>
|
||||
<Curve {...props} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const Attributes = ({ list }) => list
|
||||
? (
|
||||
<ul>
|
||||
{Object.keys(list).map(key => (
|
||||
<li><strong>{key}</strong>: {list[key]}</li>
|
||||
))}
|
||||
</ul>
|
||||
) : null
|
||||
|
||||
const pathInfo = (props) => {
|
||||
const bbox = props.path.boundary()
|
||||
|
||||
return (
|
||||
<div className="p-4 border bg-neutral bg-opacity-40 shadow rounded-lg">
|
||||
<h5 className="text-neutral-content text-center pb-4">Path info</h5>
|
||||
<div className="flex flex-row flex-wrap overflow-scroll" style={{ maxHeight: '80vh' }}>
|
||||
<table className="border-collapse h-fit">
|
||||
<tbody>
|
||||
<Tr>
|
||||
<KeyTd>Name</KeyTd>
|
||||
<ValTd>{bbox.name}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Length</KeyTd>
|
||||
<ValTd>{round(props.path.length(), 2)}mm</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Width</KeyTd>
|
||||
<ValTd>{round(bbox.bottomRight.x - bbox.topLeft.x, 2)}mm</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Height</KeyTd>
|
||||
<ValTd>{round(bbox.bottomRight.y - bbox.topLeft.y, 2)}mm</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Top Left</KeyTd>
|
||||
<ValTd>{pointInfo(bbox.topLeft)}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Bottom Right</KeyTd>
|
||||
<ValTd>{pointInfo(bbox.bottomRight)}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Part</KeyTd>
|
||||
<ValTd>{props.partName}</ValTd>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<KeyTd>Attributes</KeyTd>
|
||||
<ValTd><Attributes list={bbox.attributes.list} /></ValTd>
|
||||
</Tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table className="border-collapse h-fit">
|
||||
<tbody>
|
||||
{props.path.ops.map((op, i) => (
|
||||
<Tr key={i}>
|
||||
<KeyTd>{i}</KeyTd>
|
||||
<ValTd><PathOp op={op}/></ValTd>
|
||||
</Tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="max-w-md">
|
||||
<MiniPath {...props} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const PathOp = ({ op }) => {
|
||||
if (op.type === 'move') return <span><strong>Move</strong> to {pointInfo(op.to)}</span>
|
||||
else if (op.type === 'line') return <span><strong>Line</strong> to {pointInfo(op.to)}</span>
|
||||
else if (op.type === 'curve') return (
|
||||
<span>
|
||||
<strong>Curve</strong> to {pointInfo(op.to)}
|
||||
<br />
|
||||
Cp1: {pointInfo(op.cp1)}
|
||||
<br />
|
||||
Cp2: {pointInfo(op.cp2)}
|
||||
</span>
|
||||
)
|
||||
else if (op.type === 'noop') return <strong>NOOP</strong>
|
||||
else if (op.type === 'close') return <strong>Close</strong>
|
||||
else return <strong>FIXME: unknown path operation type: {op.type}</strong>
|
||||
}
|
||||
|
||||
const XrayCurve = props => (
|
||||
<path
|
||||
d={props.path.asPathstring()}
|
||||
{...getProps(props.path)}
|
||||
className="opacity-0 stroke-4xl stroke-lining hover:opacity-25 hover:cursor-pointer"
|
||||
onClick={(evt) => { evt.stopPropagation(); props.showInfo(curveInfo(props)) }}
|
||||
/>
|
||||
)
|
||||
|
||||
const XrayPath = props => {
|
||||
const ops = props.path.divide()
|
||||
|
||||
return (
|
||||
<g>
|
||||
<path
|
||||
d={props.path.asPathstring()}
|
||||
{...getProps(props.path)}
|
||||
className="opacity-0 stroke-7xl stroke-contrast hover:opacity-25 hover:cursor-pointer"
|
||||
onClick={(evt) => { evt.preventDefault(); props.showInfo(pathInfo(props)) }}
|
||||
/>
|
||||
{ops.length > 1
|
||||
? ops.map((op,i) => (op.ops[1].type === 'curve')
|
||||
? <XrayCurve {...props} path={op} ops={ops} i={i} pathName={`${props.pathName}_test`} />
|
||||
: <XrayLine {...props} path={op} ops={ops} i={i} pathName={`${props.pathName}_test`} />
|
||||
) : null
|
||||
}
|
||||
</g>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
const Path = props => {
|
||||
const { path, partName, pathName } = props
|
||||
|
|
|
@ -26,7 +26,7 @@ import Part from './part'
|
|||
*/
|
||||
|
||||
const SvgWrapper = props => {
|
||||
const { patternProps, gist, app, updateGist, unsetGist } = props
|
||||
const { patternProps, gist, app, updateGist, unsetGist, showInfo } = props
|
||||
|
||||
return <SizeMe>{({ size }) => (
|
||||
<TransformWrapper
|
||||
|
@ -41,7 +41,7 @@ const SvgWrapper = props => {
|
|||
<style>{`:root { --pattern-scale: ${gist.scale || 1}}`}</style>
|
||||
<g>
|
||||
{Object.keys(patternProps.parts).map((name) => (
|
||||
<Part {...{ app, gist, updateGist, unsetGist }}
|
||||
<Part {...{ app, gist, updateGist, unsetGist, showInfo }}
|
||||
key={name}
|
||||
partName={name}
|
||||
part={patternProps.parts[name]}
|
||||
|
|
|
@ -8,6 +8,7 @@ import defaultSettings from 'shared/components/workbench/default-settings.js'
|
|||
import DraftError from 'shared/components/workbench/draft/error.js'
|
||||
import theme from '@freesewing/plugin-theme'
|
||||
import preloaders from 'shared/components/workbench/preload.js'
|
||||
import Modal from 'shared/components/modal'
|
||||
|
||||
// Views
|
||||
import Measurements from 'shared/components/workbench/measurements/index.js'
|
||||
|
@ -63,6 +64,7 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
|
|||
// State for gist
|
||||
const [gist, setGist, ready] = useLocalStorage(`${design.config.name}_gist`, defaultGist(design, app.locale))
|
||||
const [messages, setMessages] = useState([])
|
||||
const [popup, setPopup] = useState(false)
|
||||
|
||||
// If we don't have the required measurements,
|
||||
// force view to measurements
|
||||
|
@ -124,14 +126,16 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
|
|||
}
|
||||
|
||||
// Props to pass down
|
||||
const componentProps = { app, design, gist, updateGist, unsetGist, setGist, draft, feedback }
|
||||
const componentProps = { app, design, gist, updateGist, unsetGist, setGist, draft, feedback, showInfo: setPopup }
|
||||
// Required props for layout
|
||||
const layoutProps = {
|
||||
app: app,
|
||||
noSearch: true,
|
||||
workbench: true,
|
||||
AltMenu: <Menu {...componentProps }/>
|
||||
AltMenu: <Menu {...componentProps }/>,
|
||||
showInfo: setPopup,
|
||||
}
|
||||
console.log(popup)
|
||||
|
||||
// Layout to use
|
||||
const LayoutComponent = layout
|
||||
|
@ -145,6 +149,7 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
|
|||
return <LayoutComponent {...layoutProps}>
|
||||
{messages}
|
||||
<Component {...componentProps} />
|
||||
{popup && <Modal cancel={() => setPopup(false)}>{popup}</Modal>}
|
||||
</LayoutComponent>
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ svg.freesewing.pattern {
|
|||
|
||||
/* Don't let the SVG surpass the parent container */
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
|
||||
/* Reset */
|
||||
path, circle { fill: none; stroke: none; }
|
||||
|
@ -25,6 +26,9 @@ svg.freesewing.pattern {
|
|||
.stroke-3xl { stroke-width: calc(var(--pattern-stroke-3xl) * var(--pattern-scale)); }
|
||||
.stroke-4xl { stroke-width: calc(var(--pattern-stroke-4xl) * var(--pattern-scale)); }
|
||||
.stroke-5xl { stroke-width: calc(var(--pattern-stroke-5xl) * var(--pattern-scale)); }
|
||||
.stroke-6xl { stroke-width: calc(var(--pattern-stroke-6xl) * var(--pattern-scale)); }
|
||||
.stroke-7xl { stroke-width: calc(var(--pattern-stroke-7xl) * var(--pattern-scale)); }
|
||||
.stroke-8xl { stroke-width: calc(var(--pattern-stroke-8xl) * var(--pattern-scale)); }
|
||||
|
||||
/* Stroke dasharray utility classes */
|
||||
.sa { stroke-dasharray: 1, 3; }
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const colors = require('tailwindcss/colors')
|
||||
const light = require('./light')
|
||||
|
||||
module.exports = {
|
||||
'fontFamily': '-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif',
|
||||
...light, // Startr from defaults, so we don't miss anything
|
||||
'primary': colors.violet['700'],
|
||||
'primary-focus': colors.violet['600'],
|
||||
'primary-content': colors.violet['50'],
|
||||
|
@ -82,23 +83,4 @@ module.exports = {
|
|||
'--pattern-dev-5': colors.violet['500'],
|
||||
'--pattern-dev-6': colors.teal['500'],
|
||||
'--pattern-dev-7': colors.neutral['500'],
|
||||
|
||||
'--pattern-text-xs': '0.2rem',
|
||||
'--pattern-text-sm': '0.3rem',
|
||||
'--pattern-text': '0.4rem',
|
||||
'--pattern-text-lg': '0.6rem',
|
||||
'--pattern-text-xl': '0.8rem',
|
||||
'--pattern-text-2xl': '1.5rem',
|
||||
'--pattern-text-3xl': '2rem',
|
||||
'--pattern-text-4xl': '3rem',
|
||||
|
||||
'--pattern-scale': '1',
|
||||
'--pattern-stroke-xs': "0.2px",
|
||||
'--pattern-stroke-sm': "0.4px",
|
||||
'--pattern-stroke': "0.7px",
|
||||
'--pattern-stroke-lg': "1.3px",
|
||||
'--pattern-stroke-xl': "2px",
|
||||
'--pattern-stroke-2xl': "4px",
|
||||
'--pattern-stroke-3xl': "6px",
|
||||
'--pattern-stroke-4xl': "8px",
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
const colors = require('tailwindcss/colors')
|
||||
const light = require('./light')
|
||||
|
||||
const bg = '#002808'
|
||||
module.exports = {
|
||||
...light, // Startr from defaults, so we don't miss anything
|
||||
'fontFamily': `ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace;`,
|
||||
'primary': colors.lime['700'],
|
||||
'primary-focus': colors.lime['600'],
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const colors = require('tailwindcss/colors')
|
||||
const light = require('./light')
|
||||
|
||||
module.exports = {
|
||||
'fontFamily': '-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif',
|
||||
|
|
|
@ -251,4 +251,10 @@ module.exports = {
|
|||
'--pattern-stroke-3xl': "6px",
|
||||
// Pattern 4xl stroke width
|
||||
'--pattern-stroke-4xl': "8px",
|
||||
// Pattern 5xl stroke width
|
||||
'--pattern-stroke-5xl': "12px",
|
||||
// Pattern 6xl stroke width
|
||||
'--pattern-stroke-6xl': "16px",
|
||||
// Pattern 7xl stroke width
|
||||
'--pattern-stroke-7xl': "20px",
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const colors = require('tailwindcss/colors')
|
||||
const light = require('./light')
|
||||
|
||||
const blue = '#77cbf9'
|
||||
const pink = '#ecadb9'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue