diff --git a/packages/core/src/part.mjs b/packages/core/src/part.mjs
index 8e9517ba3fd..0ef1e047272 100644
--- a/packages/core/src/part.mjs
+++ b/packages/core/src/part.mjs
@@ -111,31 +111,15 @@ Part.prototype.boundary = function () {
if (topLeft.y === Infinity) topLeft.y = 0
if (bottomRight.x === -Infinity) bottomRight.x = 0
if (bottomRight.y === -Infinity) bottomRight.y = 0
- // Add margin
- let margin = this.context.settings.margin
- if (this.context.settings.paperless && margin < 10) margin = 10
- this.topLeft = new Point(topLeft.x - margin, topLeft.y - margin)
- this.bottomRight = new Point(bottomRight.x + margin, bottomRight.y + margin)
+
+ this.topLeft = topLeft
+ this.bottomRight = bottomRight
this.width = this.bottomRight.x - this.topLeft.x
this.height = this.bottomRight.y - this.topLeft.y
return this
}
-/** Homes part so that its top left corner is in (0,0) */
-Part.prototype.home = function () {
- if (this.topLeft !== false) return this
- else this.boundary()
- if (this.topLeft.x == 0 && this.topLeft.y == 0) return this
- else {
- this.attr('transform', `translate(${this.topLeft.x * -1}, ${this.topLeft.y * -1})`)
- this.layout.move.x = this.topLeft.x * -1
- this.layout.move.y = this.topLeft.y * -1
- }
-
- return this
-}
-
/** Adds an attribute. This is here to make this call chainable in assignment */
Part.prototype.attr = function (name, value, overwrite = false) {
if (overwrite) this.attributes.set(name, value)
diff --git a/packages/core/src/pattern.mjs b/packages/core/src/pattern.mjs
index 5e5b1388252..bb7aacfc44b 100644
--- a/packages/core/src/pattern.mjs
+++ b/packages/core/src/pattern.mjs
@@ -104,6 +104,19 @@ Pattern.prototype.__createPartWithContext = function (name) {
return part
}
+Pattern.prototype.__createStackWithContext = function (name) {
+ // Context object to add to Stack closure
+ const stack = new Stack()
+ stack.name = name
+ stack.context = {
+ config: this.config,
+ settings: this.settings,
+ store: this.store,
+ }
+
+ return stack
+}
+
// Merges default for options with user-provided options
Pattern.prototype.__loadOptionDefaults = function () {
if (Object.keys(this.config.options).length < 1) return this
@@ -548,7 +561,8 @@ Pattern.prototype.pack = function () {
// First, create all stacks
this.stacks = {}
for (const [name, part] of Object.entries(this.parts)) {
- if (typeof this.stacks[part.stack] === 'undefined') this.stacks[part.stack] = new Stack(part.stack)
+ if (typeof this.stacks[part.stack] === 'undefined')
+ this.stacks[part.stack] = this.__createStackWithContext(part.stack)
this.stacks[part.stack].addPart(part)
}
@@ -558,7 +572,8 @@ Pattern.prototype.pack = function () {
stack.attributes.remove('transform')
if (!this.isStackHidden(key)) {
stack.home()
- if (this.settings.layout === true) bins.push({ id: key, width: stack.width, height: stack.height })
+ if (this.settings.layout === true)
+ bins.push({ id: key, width: stack.width, height: stack.height })
else {
if (this.width < stack.width) this.width = stack.width
if (this.height < stack.height) this.height = stack.height
@@ -573,7 +588,6 @@ Pattern.prototype.pack = function () {
if (bin.x !== 0 || bin.y !== 0) {
stack.attr('transform', `translate(${bin.x}, ${bin.y})`)
}
-
this.autoLayout.stacks[bin.id].move = {
x: bin.x + stack.layout.move.x,
y: bin.y + stack.layout.move.y,
@@ -845,6 +859,12 @@ Pattern.prototype.getRenderProps = function () {
}
}
}
+ props.stacks = {}
+ for (let s in this.stacks) {
+ if (!this.isStackHidden(s)) {
+ props.stacks[s] = this.stacks[s]
+ }
+ }
return props
}
diff --git a/packages/core/src/stack.mjs b/packages/core/src/stack.mjs
index 76aa73b382c..7f516a5be6b 100644
--- a/packages/core/src/stack.mjs
+++ b/packages/core/src/stack.mjs
@@ -2,7 +2,7 @@ import { Attributes } from './attributes.mjs'
import { Point } from './point.mjs'
import * as utils from './utils.mjs'
-export function Stack(name=null) {
+export function Stack(name = null) {
// Non-enumerable properties
utils.addNonEnumProp(this, 'freeId', 0)
utils.addNonEnumProp(this, 'topLeft', false)
@@ -20,20 +20,20 @@ export function Stack(name=null) {
}
/* Adds a part to the stack */
-Stack.prototype.addPart = function(part) {
+Stack.prototype.addPart = function (part) {
if (part) this.parts.add(part)
return this
}
/* Returns a list of parts in this stack */
-Stack.prototype.getPartList = function(part) {
+Stack.prototype.getPartList = function (part) {
return [...this.parts]
}
/* Returns a list of names of parts in this stack */
-Stack.prototype.getPartNames = function(part) {
- return [...this.parts].map(p => p.name)
+Stack.prototype.getPartNames = function (part) {
+ return [...this.parts].map((p) => p.name)
}
/** Homes the stack so that its top left corner is in (0,0) */
@@ -58,9 +58,11 @@ Stack.prototype.home = function () {
/** Calculates the stack's bounding box and sets it */
Stack.prototype.home = function () {
+ if (this.topLeft) return this // Cached
this.topLeft = new Point(Infinity, Infinity)
this.bottomRight = new Point(-Infinity, -Infinity)
for (const part of this.getPartList()) {
+ part.boundary()
if (part.topLeft.x < this.topLeft.x) this.topLeft.x = part.topLeft.x
if (part.topLeft.y < this.topLeft.y) this.topLeft.y = part.topLeft.y
if (part.bottomRight.x > this.bottomRight.x) this.bottomRight.x = part.bottomRight.x
@@ -73,8 +75,53 @@ Stack.prototype.home = function () {
if (this.bottomRight.x === -Infinity) this.bottomRight.x = 0
if (this.bottomRight.y === -Infinity) this.bottomRight.y = 0
+ // Add margin
+ let margin = this.context.settings.margin
+ if (this.context.settings.paperless && margin < 10) margin = 10
+ this.topLeft.x -= margin
+ this.topLeft.y -= margin
+ this.bottomRight.x += margin
+ this.bottomRight.y += margin
+
+ // Set dimensions
this.width = this.bottomRight.x - this.topLeft.x
this.height = this.bottomRight.y - this.topLeft.y
+ this.width = this.bottomRight.x - this.topLeft.x
+ this.height = this.bottomRight.y - this.topLeft.y
+
+ // Add transform
+ this.anchor = this.getAnchor()
+
+ if (this.topLeft.x === this.anchor.x && this.topLeft.y === this.anchor.y) return this
+ else {
+ this.attr('transform', `translate(${this.anchor.x - this.topLeft.x}, ${this.anchor.y - this.topLeft.y})`)
+ this.layout.move.x = this.anchor.x - this.topLeft.x
+ this.layout.move.y = this.anchor.y - this.topLeft.y
+ }
+
+ return this
+}
+
+/** Finds the anchor to aling parts in this stack */
+Stack.prototype.getAnchor = function() {
+ let anchorPoint = true
+ let gridAnchorPoint = true
+ const parts = this.getPartList()
+ for (const part of parts) {
+ if (typeof part.points.anchor === 'undefined') anchorPoint = false
+ if (typeof part.points.gridAnchor === 'undefined') gridAnchorPoint = false
+ }
+
+ if (anchorPoint) return parts[0].points.anchor
+ if (gridAnchorPoint) return parts[0].points.gridAnchor
+
+ return new Point(0,0)
+}
+
+/** Adds an attribute. This is here to make this call chainable in assignment */
+Stack.prototype.attr = function (name, value, overwrite = false) {
+ if (overwrite) this.attributes.set(name, value)
+ else this.attributes.add(name, value)
return this
}
diff --git a/packages/core/tests/stacks.test.mjs b/packages/core/tests/stacks.test.mjs
index e22a18cb85a..1331325baf1 100644
--- a/packages/core/tests/stacks.test.mjs
+++ b/packages/core/tests/stacks.test.mjs
@@ -4,7 +4,6 @@ import { round, Design, Point, pctBasedOn } from '../src/index.mjs'
const expect = chai.expect
describe('Stacks', () => {
-
describe('Pattern.init()', () => {
const partA = {
name: 'test.partA',
@@ -12,9 +11,9 @@ describe('Stacks', () => {
options: {
size: { pct: 40, min: 20, max: 80 },
},
- draft: ({ points, Point, paths, Path, part, store, measurements, options}) => {
+ draft: ({ points, Point, paths, Path, part, store, measurements, options }) => {
store.set('size', measurements.head * options.size)
- points.from = new Point(0,0)
+ points.from = new Point(0, 0)
points.to = new Point(0, store.get('size'))
paths.line = new Path().move(points.from).line(points.to)
return part
@@ -25,8 +24,8 @@ describe('Stacks', () => {
name: 'test.partB',
measurements: ['head'],
after: partA,
- draft: ({ points, Point, paths, Path, part, store}) => {
- points.from = new Point(0,store.get('size'))
+ draft: ({ points, Point, paths, Path, part, store }) => {
+ points.from = new Point(0, store.get('size'))
points.to = new Point(store.get('size'), store.get('size'))
paths.line = new Path().move(points.from).line(points.to)
return part
@@ -36,7 +35,7 @@ describe('Stacks', () => {
const partC = {
name: 'test.partC',
after: partB,
- draft: ({ points, Point, paths, Path, part, store}) => {
+ draft: ({ points, Point, paths, Path, part, store }) => {
points.from = new Point(store.get('size'), store.get('size'))
points.to = new Point(store.get('size'), 0)
paths.line = new Path().move(points.from).line(points.to)
@@ -47,13 +46,13 @@ describe('Stacks', () => {
const partD = {
name: 'test.partD',
after: partC,
- draft: ({ points, Point, paths, Path, part, store}) => {
+ draft: ({ points, Point, paths, Path, part, store }) => {
points.from = new Point(store.get('size'), 0)
points.to = new Point(0, 0)
paths.line = new Path().move(points.from).line(points.to)
return part
},
- // stack: 'box',
+ // stack: 'box',
}
const Pattern = new Design({
@@ -65,8 +64,8 @@ describe('Stacks', () => {
})
const pattern = new Pattern({
measurements: {
- head: 400
- }
+ head: 400,
+ },
})
pattern.draft()
console.log(pattern.store.logs)
@@ -90,6 +89,5 @@ describe('Stacks', () => {
pattern.config.resolvedDependencies['test.partC'].indexOf('test.partB') !== -1
).to.equal(true)
})
-
})
})
diff --git a/sites/shared/components/workbench/draft/index.js b/sites/shared/components/workbench/draft/index.js
index 4e6a3959d2d..b0625c095e8 100644
--- a/sites/shared/components/workbench/draft/index.js
+++ b/sites/shared/components/workbench/draft/index.js
@@ -27,7 +27,7 @@ const LabDraft = props => {
return (
<>
- {(!patternProps || patternProps.events?.error?.length > 0)
+ {(!patternProps || patternProps.logs?.error?.length > 0)
?
: null
}
diff --git a/sites/shared/components/workbench/draft/stack.js b/sites/shared/components/workbench/draft/stack.js
new file mode 100644
index 00000000000..e733e205759
--- /dev/null
+++ b/sites/shared/components/workbench/draft/stack.js
@@ -0,0 +1,20 @@
+import Part from './part'
+import { getProps } from './utils'
+
+const Stack = props => {
+ const { stackName, stack, patternProps, gist, app, updateGist, unsetGist, showInfo } = props
+
+ return (
+
+ {[...stack.parts].map((part) => (
+
+ ))}
+
+ )
+}
+
+export default Stack
diff --git a/sites/shared/components/workbench/draft/svg-wrapper.js b/sites/shared/components/workbench/draft/svg-wrapper.js
index 8f737841084..6aeaf14a799 100644
--- a/sites/shared/components/workbench/draft/svg-wrapper.js
+++ b/sites/shared/components/workbench/draft/svg-wrapper.js
@@ -2,7 +2,7 @@ import { SizeMe } from 'react-sizeme'
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch"
import Svg from './svg'
import Defs from './defs'
-import Part from './part'
+import Stack from './stack'
/* What's with all the wrapping?
*
@@ -40,11 +40,11 @@ const SvgWrapper = props => {
- {Object.keys(patternProps.parts).map((name) => (
- (
+
))}