diff --git a/sites/shared/components/workbench/draft/utils.js b/sites/shared/components/workbench/draft/utils.js
index f023e26b58b..6e439318c01 100644
--- a/sites/shared/components/workbench/draft/utils.js
+++ b/sites/shared/components/workbench/draft/utils.js
@@ -34,3 +34,13 @@ export const getProps = (obj) => {
return props
}
+
+export const dx = (pointA, pointB) => pointB.x - pointA.x
+export const dy = (pointA, pointB) => pointB.y - pointA.y
+export const rad2deg = radians => radians * 57.29577951308232
+export const angle = (pointA, pointB) => {
+ let rad = Math.atan2(-1 * dy(pointA, pointB), dx(pointA, pointB))
+ while (rad < 0) rad += 2 * Math.PI
+
+ return rad2deg(rad)
+}
diff --git a/sites/shared/components/workbench/layout/draft.js b/sites/shared/components/workbench/layout/draft/index.js
similarity index 55%
rename from sites/shared/components/workbench/layout/draft.js
rename to sites/shared/components/workbench/layout/draft/index.js
index c67232ab5a4..2c2df9d5909 100644
--- a/sites/shared/components/workbench/layout/draft.js
+++ b/sites/shared/components/workbench/layout/draft/index.js
@@ -73,197 +73,10 @@
* how custom layouts are supported in the core. And I would like to discuss this with the core team.
*/
import { useEffect, useRef, useState } from 'react'
-import Svg from '../draft/svg'
-import Defs from '../draft/defs'
-import Path from '../draft/path'
-import Point from '../draft/point'
-import Snippet from '../draft/snippet'
-import {PartInner} from '../draft/part'
-import { getProps } from '../draft/utils'
-import { drag } from 'd3-drag'
-import { select } from 'd3-selection'
-
-const Buttons = ({ transform, flip, rotate, setRotate, resetPart }) => {
- const letter = 'F'
- const style = { style: {fill: 'white', fontSize: 18, fontWeight: 'bold', textAnchor: 'middle'} }
-
- return (
-
- {rotate
- ?
- :
- }
-
-
- {letter}
-
- flip('y')}>
-
- {letter}
-
- flip('x')}>
-
- {letter}
-
-
- )
-}
-
-const dx = (pointA, pointB) => pointB.x - pointA.x
-const dy = (pointA, pointB) => pointB.y - pointA.y
-const rad2deg = radians => radians * 57.29577951308232
-const angle = (pointA, pointB) => {
- let rad = Math.atan2(-1 * dy(pointA, pointB), dx(pointA, pointB))
- while (rad < 0) rad += 2 * Math.PI
-
- return rad2deg(rad)
-}
-
-const generateTransform = (x, y, rot, flipX, flipY, part) => {
- const center = {
- x: part.topLeft.x + (part.bottomRight.x - part.topLeft.x)/2,
- y: part.topLeft.y + (part.bottomRight.y - part.topLeft.y)/2,
- }
- const dx = part.topLeft.x - center.x
- const dy = part.topLeft.y - center.y
- const transforms = [`translate(${x},${y})`]
- if (flipX) transforms.push(
- `translate(${center.x * -1}, ${center.y * -1})`,
- 'scale(-1, 1)',
- `translate(${center.x * -1 + 2 * dx}, ${center.y})`
- )
- if (flipY) transforms.push(
- `translate(${center.x * -1}, ${center.y * -1})`,
- 'scale(1, -1)',
- `translate(${center.x}, ${center.y * -1 + 2 * dy})`,
- )
- if (rot) transforms.push(
- `rotate(${rot}, ${center.x}, ${center.y})`
- )
-
- return transforms.join(' ')
-}
-
-const Part = props => {
- const { layout, gist, name, part} = props
-
- const partLayout = layout.parts[name]
-
- // Don't just assume this makes sense
- if (typeof layout.parts?.[name]?.move?.x === 'undefined') return null
-
- // Use a ref for direct DOM manipulation
- const partRef = useRef(null)
- const centerRef = useRef(null)
-
- // State variable to switch between moving or rotating the part
- const [rotate, setRotate] = useState(false)
-
- // Initialize drag handler
- useEffect(() => {
- handleDrag(select(partRef.current))
- }, [rotate, layout])
-
- // These are kept as vars because re-rendering on drag would kill performance
- // Managing the difference between re-render and direct DOM updates makes this
- // whole thing a bit tricky to wrap your head around
- let translateX = partLayout.move.x
- let translateY = partLayout.move.y
- let partRotation = partLayout.rotate || 0;
- let rotation = partRotation;
- let flipX = partLayout.flipX ? true : false
- let flipY = partLayout.flipY ? true : false
- let partRect
-
- const center = {
- x: part.topLeft.x + (part.bottomRight.x - part.topLeft.x)/2,
- y: part.topLeft.y + (part.bottomRight.y - part.topLeft.y)/2,
- }
-
- const getRotation = (event) => angle(center, event.subject) - angle(center, { x:event.x, y: event.y });
-
- const handleDrag = drag()
- .subject(function(event) {
- return rotate ? { x: event.x, y: event.y } : {x: translateX, y: translateY}
- })
- .on('start', function(event) {
- partRect = partRef.current.getBoundingClientRect()
- })
- .on('drag', function(event) {
- if (rotate) {
- let newRotation = getRotation(event);
- if (flipX) newRotation *= -1
- if (flipY) newRotation *= -1
- rotation = partRotation + newRotation
- }
- else {
- translateX = event.x
- translateY = event.y
- }
- const me = select(this);
- me.attr('transform', generateTransform(translateX, translateY, rotation, flipX, flipY, part));
- })
- .on('end', function(event) {
- updateLayout()
- })
-
- const resetPart = () => {
- rotation = 0
- flipX = 0
- flipY = 0
- updateLayout()
- }
- const toggleDragRotate = () => {
- updateLayout()
- setRotate(!rotate)
- }
- const updateLayout = () => {
- props.updateLayout(name, {
- move: {
- x: translateX,
- y: translateY,
- },
- rotate: rotation,
- flipX,
- flipY
- })
- }
-
- // Method to flip (mirror) the part along the X or Y axis
- const flip = axis => {
- if (axis === 'x') flipX = !flipX
- else flipY = !flipY
- updateLayout()
- }
-
- return (
-
- {PartInner(props)}
- {props.name !== 'pages' && <>
-
-
-
- >}
-
- )
-}
+import Svg from '../../draft/svg'
+import Defs from '../../draft/defs'
+import { angle } from '../../draft/utils'
+import Part from './part'
const Draft = props => {
if (!props.gistReady) {return null}
@@ -288,8 +101,7 @@ const Draft = props => {
// Helper method to update part layout and re-calculate width * height
const updateLayout = (name, config) => {
// Start creating new layout
- const oldLayout = {...layout } || false;
- const newLayout = {...oldLayout}
+ const newLayout = {...layout}
newLayout.parts[name] = config
newLayout.width = layout.width
newLayout.height = layout.height
diff --git a/sites/shared/components/workbench/layout/draft/part.js b/sites/shared/components/workbench/layout/draft/part.js
new file mode 100644
index 00000000000..e3887b78374
--- /dev/null
+++ b/sites/shared/components/workbench/layout/draft/part.js
@@ -0,0 +1,182 @@
+import Path from '../../draft/path'
+import Point from '../../draft/point'
+import Snippet from '../../draft/snippet'
+import {PartInner} from '../../draft/part'
+import { getProps, angle } from '../../draft/utils'
+import { drag } from 'd3-drag'
+import { select } from 'd3-selection'
+import { useRef, useState, useEffect} from 'react'
+
+const Buttons = ({ transform, flip, rotate, setRotate, resetPart }) => {
+ const letter = 'F'
+ const style = { style: {fill: 'white', fontSize: 18, fontWeight: 'bold', textAnchor: 'middle'} }
+
+ return (
+
+ {rotate
+ ?
+ :
+ }
+
+
+ {letter}
+
+ flip('y')}>
+
+ {letter}
+
+ flip('x')}>
+
+ {letter}
+
+
+ )
+}
+
+const generateTransform = (x, y, rot, flipX, flipY, part) => {
+ const center = {
+ x: part.topLeft.x + (part.bottomRight.x - part.topLeft.x)/2,
+ y: part.topLeft.y + (part.bottomRight.y - part.topLeft.y)/2,
+ }
+ const dx = part.topLeft.x - center.x
+ const dy = part.topLeft.y - center.y
+ const transforms = [`translate(${x},${y})`]
+ if (flipX) transforms.push(
+ `translate(${center.x * -1}, ${center.y * -1})`,
+ 'scale(-1, 1)',
+ `translate(${center.x * -1 + 2 * dx}, ${center.y})`
+ )
+ if (flipY) transforms.push(
+ `translate(${center.x * -1}, ${center.y * -1})`,
+ 'scale(1, -1)',
+ `translate(${center.x}, ${center.y * -1 + 2 * dy})`,
+ )
+ if (rot) transforms.push(
+ `rotate(${rot}, ${center.x}, ${center.y})`
+ )
+
+ return transforms.join(' ')
+}
+
+const Part = props => {
+ const { layout, gist, name, part} = props
+
+ const partLayout = layout.parts[name]
+
+ // Don't just assume this makes sense
+ if (typeof layout.parts?.[name]?.move?.x === 'undefined') return null
+
+ // Use a ref for direct DOM manipulation
+ const partRef = useRef(null)
+ const centerRef = useRef(null)
+
+ // State variable to switch between moving or rotating the part
+ const [rotate, setRotate] = useState(false)
+
+ // Initialize drag handler
+ useEffect(() => {
+ handleDrag(select(partRef.current))
+ }, [rotate, layout])
+
+ // These are kept as vars because re-rendering on drag would kill performance
+ // Managing the difference between re-render and direct DOM updates makes this
+ // whole thing a bit tricky to wrap your head around
+ let translateX = partLayout.move.x
+ let translateY = partLayout.move.y
+ let partRotation = partLayout.rotate || 0;
+ let rotation = partRotation;
+ let flipX = partLayout.flipX ? true : false
+ let flipY = partLayout.flipY ? true : false
+ let partRect
+
+ const center = {
+ x: part.topLeft.x + (part.bottomRight.x - part.topLeft.x)/2,
+ y: part.topLeft.y + (part.bottomRight.y - part.topLeft.y)/2,
+ }
+
+ const getRotation = (event) => angle(center, event.subject) - angle(center, { x:event.x, y: event.y });
+
+ const handleDrag = drag()
+ .subject(function(event) {
+ return rotate ? { x: event.x, y: event.y } : {x: translateX, y: translateY}
+ })
+ .on('start', function(event) {
+ partRect = partRef.current.getBoundingClientRect()
+ })
+ .on('drag', function(event) {
+ if (rotate) {
+ let newRotation = getRotation(event);
+ if (flipX) newRotation *= -1
+ if (flipY) newRotation *= -1
+ rotation = partRotation + newRotation
+ }
+ else {
+ translateX = event.x
+ translateY = event.y
+ }
+ const me = select(this);
+ me.attr('transform', generateTransform(translateX, translateY, rotation, flipX, flipY, part));
+ })
+ .on('end', function(event) {
+ updateLayout()
+ })
+
+ const resetPart = () => {
+ rotation = 0
+ flipX = 0
+ flipY = 0
+ updateLayout()
+ }
+ const toggleDragRotate = () => {
+ updateLayout()
+ setRotate(!rotate)
+ }
+ const updateLayout = () => {
+ props.updateLayout(name, {
+ move: {
+ x: translateX,
+ y: translateY,
+ },
+ rotate: rotation,
+ flipX,
+ flipY
+ })
+ }
+
+ // Method to flip (mirror) the part along the X or Y axis
+ const flip = axis => {
+ if (axis === 'x') flipX = !flipX
+ else flipY = !flipY
+ updateLayout()
+ }
+
+ return (
+
+ {PartInner(props)}
+ {props.name !== 'pages' && <>
+
+
+
+ >}
+
+ )
+}
+
+export default Part
diff --git a/sites/shared/components/workbench/layout/print/index.js b/sites/shared/components/workbench/layout/print/index.js
index 7075008a216..fe54ede1963 100644
--- a/sites/shared/components/workbench/layout/print/index.js
+++ b/sites/shared/components/workbench/layout/print/index.js
@@ -1,7 +1,7 @@
import { useEffect } from 'react'
import { useTranslation } from 'next-i18next'
import Settings from './settings'
-import Draft from '../draft'
+import Draft from '../draft/index'
import pluginBuilder from './plugin'
const PrintLayout = props => {