wip: Rewrite tutorial for v3
This commit is contained in:
parent
7487f1f449
commit
32d6e938df
15 changed files with 349 additions and 303 deletions
|
@ -4,6 +4,8 @@
|
||||||
"p": {
|
"p": {
|
||||||
"bib": "Bib"
|
"bib": "Bib"
|
||||||
},
|
},
|
||||||
"s": {},
|
"s": {
|
||||||
|
"finishWithBiasTape": "Finish with bias tape"
|
||||||
|
},
|
||||||
"o": {}
|
"o": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,7 +173,7 @@ export const bib = {
|
||||||
paths.bias = paths.seam
|
paths.bias = paths.seam
|
||||||
.offset(-5)
|
.offset(-5)
|
||||||
.attr('class', 'various dashed')
|
.attr('class', 'various dashed')
|
||||||
.attr('data-text', 'finishWithBiasTape')
|
.attr('data-text', 'tutorial:finishWithBiasTape')
|
||||||
.attr('data-text-class', 'center fill-various')
|
.attr('data-text-class', 'center fill-various')
|
||||||
|
|
||||||
// Add the title
|
// Add the title
|
||||||
|
|
|
@ -13,11 +13,12 @@ export const step1 = {
|
||||||
snippets,
|
snippets,
|
||||||
complete,
|
complete,
|
||||||
sa,
|
sa,
|
||||||
|
store,
|
||||||
paperless,
|
paperless,
|
||||||
macro,
|
macro,
|
||||||
part,
|
part,
|
||||||
}) => {
|
}) => {
|
||||||
let w = 500 * options.size
|
const w = 500 * options.size
|
||||||
points.topLeft = new Point(0, 0)
|
points.topLeft = new Point(0, 0)
|
||||||
points.topRight = new Point(w, 0)
|
points.topRight = new Point(w, 0)
|
||||||
points.bottomLeft = new Point(0, w / 2)
|
points.bottomLeft = new Point(0, w / 2)
|
||||||
|
@ -32,33 +33,33 @@ export const step1 = {
|
||||||
.close()
|
.close()
|
||||||
.attr('class', 'fabric')
|
.attr('class', 'fabric')
|
||||||
|
|
||||||
// Complete?
|
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
|
||||||
if (complete) {
|
/*
|
||||||
points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
|
* Annotations
|
||||||
snippets.logo = new Snippet('logo', points.logo)
|
*/
|
||||||
points.text = points.logo
|
|
||||||
.shift(-90, w / 8)
|
|
||||||
.attr('data-text', 'hello')
|
|
||||||
.attr('data-text-class', 'center')
|
|
||||||
|
|
||||||
if (sa) {
|
// Cutlist
|
||||||
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
|
store.cutlist.setCut({ cut: 1, from: 'fabric' })
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Paperless?
|
// Logo & Hello
|
||||||
if (paperless) {
|
points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
|
||||||
macro('hd', {
|
snippets.logo = new Snippet('logo', points.logo)
|
||||||
from: points.bottomLeft,
|
|
||||||
to: points.bottomRight,
|
if (complete) points.text = points.logo.shift(-90, w / 8).addText('hello', 'center')
|
||||||
y: points.bottomLeft.y + sa + 15,
|
|
||||||
})
|
//Dimensions
|
||||||
macro('vd', {
|
macro('hd', {
|
||||||
from: points.bottomRight,
|
id: 'width',
|
||||||
to: points.topRight,
|
from: points.bottomLeft,
|
||||||
x: points.topRight.x + sa + 15,
|
to: points.bottomRight,
|
||||||
})
|
y: points.bottomLeft.y + sa + 15,
|
||||||
}
|
})
|
||||||
|
macro('vd', {
|
||||||
|
id: 'height',
|
||||||
|
from: points.bottomRight,
|
||||||
|
to: points.topRight,
|
||||||
|
x: points.topRight.x + sa + 15,
|
||||||
|
})
|
||||||
|
|
||||||
return part
|
return part
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
title: Design guide
|
title: Design guide
|
||||||
---
|
---
|
||||||
|
|
||||||
This short guide will illustrate and explain how designs work in FreeSewing.
|
Hi there and welcome to this guide that explains how FreeSewing designs work.
|
||||||
Not to be confused with how sewing patterns work — although there are [great books
|
|
||||||
about that](https://www.assembil.com/how-patterns-work-book/) if you're
|
|
||||||
interested — it's about what goes on under the hood each time a sewing
|
it's about what goes on under the hood each time a sewing
|
||||||
pattern is generated by FreeSewing.
|
pattern is generated by FreeSewing.
|
||||||
|
|
||||||
This illustration is a good starting point to gain a better
|
This illustration is a good starting point to gain a better
|
||||||
|
@ -185,10 +185,11 @@ understanding of the structure of a FreeSewing design:
|
||||||
```
|
```
|
||||||
</Example>
|
</Example>
|
||||||
|
|
||||||
If it looks like _a lot_ don't despair. There's a lot of repetition, and we'll
|
If it looks like _a lot_ don't despair. I included all the info on the
|
||||||
work through the building blocks step by step.
|
graphical overview, but most of it you can safely ignore and consider _under
|
||||||
|
the hood_ unless you want to do some really advanced things with FreeSewing.
|
||||||
|
|
||||||
If we look at our image, it can be divided into three areas:
|
If we look at our image through squinted eyes, we can identify three areas:
|
||||||
|
|
||||||
- The[ **Settings**](#the-settings) on the left
|
- The[ **Settings**](#the-settings) on the left
|
||||||
- The[ **Render stage**](#rendering-your-pattern) on the right
|
- The[ **Render stage**](#rendering-your-pattern) on the right
|
||||||
|
|
|
@ -3,68 +3,53 @@ title: Adding measurements
|
||||||
order: 130
|
order: 130
|
||||||
---
|
---
|
||||||
|
|
||||||
FreeSewing is all about _made-to-measure_ sewing patterns;
|
FreeSewing is all about _made-to-measure_ sewing patterns -- or *parametric
|
||||||
we are going to draft our pattern according to the measurements provided to us.
|
design* to use a more generic term.
|
||||||
|
|
||||||
|
That means that when drafting our pattern, I will take the measurements provided
|
||||||
|
by the user into account.
|
||||||
|
|
||||||
Which begs the question, which measurements?
|
Which begs the question, which measurements?
|
||||||
|
|
||||||
It is we, as the pattern designers, who decide which measurements are used
|
As the pattern designers, you get to decide which measurements are used
|
||||||
to draft our pattern. For our bib, the only measurement we need is the
|
to draft the pattern. For this bib, I am going to use the
|
||||||
_head circumference_.
|
_head circumference_.
|
||||||
|
|
||||||
So let's add it as a required measurement.
|
So let's add it as a required measurement.
|
||||||
|
|
||||||
## Adding required measurements
|
## Adding required measurements
|
||||||
|
|
||||||
In our `design/src/bib.mjs` file, on the `bib` object, there is a key called
|
In our `design/src/bib.mjs` file, we will add a `measurements` property to the `bib` object.
|
||||||
`measurements` (line 121) that will hold a list (an array) of all required measurements
|
This property will be an Array (a list) holding all required measurements for this part.
|
||||||
for this part.
|
|
||||||
|
|
||||||
We are going to use [*the official name* of the measurement](/reference/measurements). For head
|
I am usign [*the official name* of the measurement](/reference/measurements) here. For head
|
||||||
circumference, that name is `head`.
|
circumference, that name is `head`.
|
||||||
|
|
||||||
```design/src/bib.mjs
|
```design/src/bib.mjs
|
||||||
function draftBib({ part }) {
|
function draftBib({ part }) => {
|
||||||
return part
|
return part
|
||||||
}
|
}
|
||||||
|
|
||||||
export const bib = {
|
export const bib = {
|
||||||
name: 'tutorial.bib',
|
name: 'tutorial.bib',
|
||||||
draft: draftBib,
|
draft: draftBib,
|
||||||
from: false,
|
// highlight-start
|
||||||
hide: {
|
measurements: [ 'head' ],
|
||||||
self: false,
|
// highlight-end
|
||||||
from: false,
|
|
||||||
after: false
|
|
||||||
},
|
|
||||||
options: {},
|
|
||||||
// start-highlight
|
|
||||||
measurements: ['head'],
|
|
||||||
// end-highlight
|
|
||||||
optionalMeasurements: [],
|
|
||||||
plugins: []
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now everybody knows this part requires the `head` measurement.
|
From now on, this part requires the `head` measurement.
|
||||||
|
|
||||||
This change will also get picked up by the development environment, and we'll now see this screen:
|
This change will also get picked up by the development environment, which will now complain that it is missing some measurements.
|
||||||
|
Since it's just one measurement, I will simply enter a value by hand.
|
||||||

|
|
||||||
|
|
||||||
Since it's just one measurement, let's simply enter a value by hand.
|
|
||||||
For example `38` as 38 cm is a realistic head circumference measurement for a baby.
|
For example `38` as 38 cm is a realistic head circumference measurement for a baby.
|
||||||
|
|
||||||
Enter `38` in the box, and click on **Draft Design** in the sidebar under the **View** heading.
|
<Tip>
|
||||||
This brings us back to our work in progress:
|
|
||||||
|
|
||||||
|
##### Why using standard measurements names matters
|
||||||
|
|
||||||
## Notes
|
In principle, I can use any name I want for our measurements.
|
||||||
|
The FreeSewing core library does not care.
|
||||||
### Why using standard measurements names matters
|
|
||||||
|
|
||||||
In principle, we can use any name we want for our measurements.
|
|
||||||
Our core library really doesn't care.
|
|
||||||
|
|
||||||
However, if everybody uses their own (names for) measurements, then people
|
However, if everybody uses their own (names for) measurements, then people
|
||||||
aren't able to re-use their measurements across designs.
|
aren't able to re-use their measurements across designs.
|
||||||
|
@ -73,5 +58,7 @@ So if you have any intention at all to play nice with the FreeSewing ecosystem,
|
||||||
please make sure to re-use the names of existing measurements, rather than
|
please make sure to re-use the names of existing measurements, rather than
|
||||||
invent your own.
|
invent your own.
|
||||||
|
|
||||||
See our [best practices](/guides/best-practices/reuse-measurements) on this
|
See the [best practices](/guides/best-practices/reuse-measurements) on this
|
||||||
topic for details.
|
topic for details.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
|
@ -3,65 +3,78 @@ title: Adding options
|
||||||
order: 140
|
order: 140
|
||||||
---
|
---
|
||||||
|
|
||||||
We know what our bib should look like, and we have the _head_ measurement
|
I have shown what our bib should look like, and added the _head_ measurement
|
||||||
to work with. But there's still a number of choices we have to make:
|
to work with. But there's still a number of choices I have to make:
|
||||||
|
|
||||||
- How large should the neck opening be?
|
- How large should the neck opening be?
|
||||||
- How wide should the bib be?
|
- How wide should the bib be?
|
||||||
- How long should the bib be?
|
- How long should the bib be?
|
||||||
|
|
||||||
We can make all of these choices for the user and set them in stone, so to speak.
|
I could make all of these choices for the user and set them in stone, so to speak.
|
||||||
|
|
||||||
But since we're designing a pattern in code, it's trivial to make our pattern
|
But since the pattern I am designing is code, it is trivial (and _IMHO_ very satisfying)
|
||||||
flexible and let the user decide. All we have to do is add options to our part.
|
to make a pattern flexible and let the user choose.
|
||||||
|
All I need to do to give control to the user is add _options_ to the part.
|
||||||
|
|
||||||
## Add the neckRatio option
|
## Add the neckRatio option
|
||||||
|
|
||||||
The first option we're going to add controls the ratio between the neck opening
|
The first option I will add controls the ratio between the neck opening
|
||||||
and the head circumference. Let's call it `neckRatio`.
|
and the head circumference. Let's call it `neckRatio`.
|
||||||
|
|
||||||
We'll add a new `options` key to our part object for this:
|
For this, I will add the `options` property to our `bib` object:
|
||||||
|
|
||||||
```design/src/bib.mjs
|
```design/src/bib.mjs
|
||||||
function draftBib({ part }) {
|
function draftBib({ part }) => {
|
||||||
|
|
||||||
return part
|
return part
|
||||||
}
|
}
|
||||||
|
|
||||||
export const bib = {
|
export const bib = {
|
||||||
|
|
||||||
name: 'tutorial.bib',
|
name: 'tutorial.bib',
|
||||||
draft: draftBib,
|
draft: draftBib,
|
||||||
from: false,
|
measurements: [ 'head' ],
|
||||||
hide: {
|
|
||||||
self: false,
|
|
||||||
from: false,
|
|
||||||
after: false
|
|
||||||
},
|
|
||||||
// highlight-start
|
// highlight-start
|
||||||
options: {
|
options: {
|
||||||
neckRatio: { pct: 80, min: 70, max: 90, menu: 'fit' },
|
neckRatio: {
|
||||||
|
pct: 80,
|
||||||
|
min: 70,
|
||||||
|
max: 90,
|
||||||
|
menu: 'fit'
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
measurements: [],
|
|
||||||
optionalMeasurements: [],
|
|
||||||
plugins: []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Can you guess what it means?
|
Can you guess what it means?
|
||||||
|
|
||||||
- We've added a option of type percentage
|
- We've added the `options` property to our `bib` object
|
||||||
|
- On the `options` property, we have added `neckRatio` which holds the configuration for our option
|
||||||
|
- It is a `pct` option -- whcih means it's a percentage
|
||||||
|
- Its default value is 90%
|
||||||
- Its minimum value is 70%
|
- Its minimum value is 70%
|
||||||
- Its maximum value is 90%
|
- Its maximum value is 90%
|
||||||
- Its default value is 80%
|
|
||||||
- We've added this option to the *fit* menu
|
There are different types of options, but percentages are by far the most common ones.
|
||||||
|
They are all documented [in the part reference docs](/reference/api/part/config/options).
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
|
|
||||||
There are different types of options, but percentages are the most common ones.
|
##### What is `menu` and why should you care?
|
||||||
They are all documented [in the part reference docs](/reference/api/part/config/options).
|
|
||||||
|
The `menu` property on our option is *extra*.
|
||||||
|
It will be ignored by FreeSewing's core library and if we leave it out, our design will produce the same result.
|
||||||
|
|
||||||
|
Instead, this `menu` property is there for the benefit FreeSewing's development
|
||||||
|
environment which will use this to build a menu structure for the various
|
||||||
|
options.
|
||||||
|
|
||||||
|
Each option type has a number of required properties. But in addition to that,
|
||||||
|
you can add more to facilitate integrating with a front-end or other user
|
||||||
|
interface.
|
||||||
|
|
||||||
|
You will see that after adding this option, the development environment will
|
||||||
|
have a `fit` section under **Design Options**. This `menu` property is where
|
||||||
|
that is based on.
|
||||||
|
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
|
@ -70,25 +83,43 @@ They are all documented [in the part reference docs](/reference/api/part/config/
|
||||||
Let's do something similar for the width and length of our bib:
|
Let's do something similar for the width and length of our bib:
|
||||||
|
|
||||||
```design/src/bib.mjs
|
```design/src/bib.mjs
|
||||||
options: {
|
function draftBib({ part }) => {
|
||||||
neckRatio: { pct: 80, min: 70, max: 90, menu: 'fit' },
|
return part
|
||||||
widthRatio: { pct: 45, min: 35, max: 55, menu: 'style' },
|
}
|
||||||
lengthRatio: { pct: 75, min: 55, max: 85, menu: 'style' },
|
|
||||||
|
export const bib = {
|
||||||
|
name: 'tutorial.bib',
|
||||||
|
draft: draftBib,
|
||||||
|
measurements: [ 'head' ],
|
||||||
|
options: {
|
||||||
|
neckRatio: {
|
||||||
|
pct: 80,
|
||||||
|
min: 70,
|
||||||
|
max: 90,
|
||||||
|
menu: 'fit'
|
||||||
|
},
|
||||||
|
// highlight-start
|
||||||
|
widthRatio: {
|
||||||
|
pct: 45,
|
||||||
|
min: 35,
|
||||||
|
max: 55,
|
||||||
|
menu: 'style'
|
||||||
|
},
|
||||||
|
lengthRatio: {
|
||||||
|
pct: 75,
|
||||||
|
min: 55,
|
||||||
|
max: 85,
|
||||||
|
menu: 'style'
|
||||||
|
},
|
||||||
|
// highlight-end
|
||||||
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- We've added `widthRatio` and `lengthRatio` options
|
This pretty much the exact same thing, except that are placing this in the `style` menu.
|
||||||
- We've given all options sensible defaults
|
|
||||||
- We've given all options sensible maximum and minimum boundaries
|
|
||||||
- We've added these two new options to the *style* menu
|
|
||||||
|
|
||||||
Later, we'll test-drive our pattern to see how it behaves when we adapt the options
|
Later, I will test-drive our pattern to see how it behaves when we adapt the options
|
||||||
between their minimum and maximum values. At that time, we can still tweak these values.
|
between their minimum and maximum values. At that time, I may need to tweak these values.
|
||||||
|
|
||||||
With that out of the way, let's start drawing our bib.
|
With that out of the way, I will start drawing the bib.
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
The `menu` key on an option does not do anything for our pattern as such.
|
|
||||||
Instead it signals to the frontend that this is how options should be grouped
|
|
||||||
together and presented to the user.
|
|
||||||
|
|
|
@ -7,49 +7,7 @@ Time to turn our attention to the draft method of our part.
|
||||||
Inside our `design/src/bib.mjs` file, this is what it currently looks like:
|
Inside our `design/src/bib.mjs` file, this is what it currently looks like:
|
||||||
|
|
||||||
```design/src/bib.mjs
|
```design/src/bib.mjs
|
||||||
function draftBib ({
|
function draftBib({ part }) => {
|
||||||
// Uncomment below to destructure what you need
|
|
||||||
/*
|
|
||||||
* Content constructors
|
|
||||||
*/
|
|
||||||
//Path, // A Path constructor to create new paths
|
|
||||||
//Point, // A Point constructor to create new points
|
|
||||||
//Snippet, // A Snippet constructor to create new snippets
|
|
||||||
/*
|
|
||||||
* Content constainers
|
|
||||||
*/
|
|
||||||
//paths, // Add a Path to your part by adding it to this object
|
|
||||||
//points, // Add a Points to your part by adding it to this object
|
|
||||||
//snippets, // Add a Snippet to your part by adding it to this object
|
|
||||||
/*
|
|
||||||
* Access to settings
|
|
||||||
*/
|
|
||||||
//absoluteOptions, // Access to settings.absoluteOptions
|
|
||||||
//complete, // Access to settings.complete
|
|
||||||
//measurements, // Access to settings.measurements
|
|
||||||
//options, // Access to settings.options
|
|
||||||
//paperless, // Access to settings.paperless
|
|
||||||
//sa, // Access to settings.sa
|
|
||||||
//scale, // Access to settings.scale
|
|
||||||
/*
|
|
||||||
* Access to utilities
|
|
||||||
*/
|
|
||||||
//getId, //See the getId documentation
|
|
||||||
//hide, //See the hide documentation
|
|
||||||
//log, //See the logging documentation
|
|
||||||
//macro, //See the macros documentation
|
|
||||||
//setHidden, //See the setHidden documentation
|
|
||||||
//store, //See the store documentation
|
|
||||||
//unhide, //See the unhide documentation
|
|
||||||
//units, //See the units documentation
|
|
||||||
///utils, //See the utils documentation
|
|
||||||
/*
|
|
||||||
* Return value
|
|
||||||
*/
|
|
||||||
part, // Your draft method must return this
|
|
||||||
}) {
|
|
||||||
|
|
||||||
// Work your magic here
|
|
||||||
return part
|
return part
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
title: Pattern design tutorial
|
title: Pattern design tutorial
|
||||||
---
|
---
|
||||||
|
|
||||||
Welcome to the FreeSewing pattern design tutorial, where we'll learn how to
|
Hello there, and welcome to this FreeSewing pattern design tutorial.
|
||||||
design a made-to-measure sewing pattern, start to finish.
|
My name is Joost, and in this tutorial I will show you
|
||||||
|
how to design a made-to-measure sewing pattern, start to finish.
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
##### Before you start
|
##### Before you start
|
||||||
|
@ -13,11 +14,11 @@ guide](/guides/prerequisites). It's very short, but covers some basic
|
||||||
terminology and concepts that we'll use throughout this guide.
|
terminology and concepts that we'll use throughout this guide.
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
We will be designing a pattern for a baby bib. It's a very simple pattern, but
|
I will be designing a pattern for a baby bib. It's a very simple pattern, but
|
||||||
that's the point. Our focus today is on learning FreeSewing and how to
|
that's ok. It is a tutorial after all. This will give us plenty to work with.
|
||||||
translate our designs into code.
|
|
||||||
|
|
||||||
At the end of this tutorial, we will have created this pattern:
|
At the end of this tutorial, I will have created this pattern, and if you
|
||||||
|
follow along, so will you:
|
||||||
|
|
||||||
|
|
||||||
<Example tutorial="1" previewFirst="1" caption="Our end result">
|
<Example tutorial="1" previewFirst="1" caption="Our end result">
|
||||||
|
@ -30,13 +31,16 @@ function draftBib({
|
||||||
measurements,
|
measurements,
|
||||||
options,
|
options,
|
||||||
macro,
|
macro,
|
||||||
|
store,
|
||||||
complete,
|
complete,
|
||||||
snippets,
|
snippets,
|
||||||
Snippet,
|
Snippet,
|
||||||
part,
|
part,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
// Construct the quarter neck opening
|
/*
|
||||||
|
* Construct the quarter neck opening
|
||||||
|
*/
|
||||||
let tweak = 1
|
let tweak = 1
|
||||||
let target = (measurements.head * options.neckRatio) /4
|
let target = (measurements.head * options.neckRatio) /4
|
||||||
let delta
|
let delta
|
||||||
|
@ -57,7 +61,9 @@ function draftBib({
|
||||||
else tweak = tweak * 1.02
|
else tweak = tweak * 1.02
|
||||||
} while (Math.abs(delta) > 1)
|
} while (Math.abs(delta) > 1)
|
||||||
|
|
||||||
// Construct the complete neck opening
|
/*
|
||||||
|
* Construct the complete neck opening
|
||||||
|
*/
|
||||||
points.rightCp2 = points.rightCp1.flipY()
|
points.rightCp2 = points.rightCp1.flipY()
|
||||||
points.bottomCp1 = points.bottomCp2.flipX()
|
points.bottomCp1 = points.bottomCp2.flipX()
|
||||||
points.left = points.right.flipX()
|
points.left = points.right.flipX()
|
||||||
|
@ -67,7 +73,9 @@ function draftBib({
|
||||||
points.topCp1 = points.bottomCp2.flipY()
|
points.topCp1 = points.bottomCp2.flipY()
|
||||||
points.topCp2 = points.bottomCp1.flipY()
|
points.topCp2 = points.bottomCp1.flipY()
|
||||||
|
|
||||||
// Drawing the bib outline
|
/*
|
||||||
|
* Drawing the bib outline
|
||||||
|
*/
|
||||||
const width = measurements.head * options.widthRatio
|
const width = measurements.head * options.widthRatio
|
||||||
const length = measurements.head * options.lengthRatio
|
const length = measurements.head * options.lengthRatio
|
||||||
|
|
||||||
|
@ -92,7 +100,9 @@ function draftBib({
|
||||||
)
|
)
|
||||||
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
|
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
|
||||||
|
|
||||||
// Round the straps
|
/*
|
||||||
|
* Round the straps
|
||||||
|
*/
|
||||||
const strap = points.edgeTop.dy(points.top)
|
const strap = points.edgeTop.dy(points.top)
|
||||||
|
|
||||||
points.tipRight = points.edgeTop.translate(strap / 2, strap / 2)
|
points.tipRight = points.edgeTop.translate(strap / 2, strap / 2)
|
||||||
|
@ -132,10 +142,14 @@ function draftBib({
|
||||||
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Snap anchor
|
/*
|
||||||
|
* Snap anchor
|
||||||
|
*/
|
||||||
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||||
|
|
||||||
// Add points for second strap
|
/*
|
||||||
|
* Add points for second strap
|
||||||
|
*/
|
||||||
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
|
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
|
||||||
points.topCp1 = points.topCp2.flipX()
|
points.topCp1 = points.topCp2.flipX()
|
||||||
points.tipLeftTopStart = points.tipRightTopStart.flipX()
|
points.tipLeftTopStart = points.tipRightTopStart.flipX()
|
||||||
|
@ -148,7 +162,9 @@ function draftBib({
|
||||||
points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
|
points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
|
||||||
points.snapRight = points.snapLeft.flipX()
|
points.snapRight = points.snapLeft.flipX()
|
||||||
|
|
||||||
// Round the bottom corners
|
/*
|
||||||
|
* Round the bottom corners
|
||||||
|
*/
|
||||||
macro("round", {
|
macro("round", {
|
||||||
from: points.topLeft,
|
from: points.topLeft,
|
||||||
to: points.bottomRight,
|
to: points.bottomRight,
|
||||||
|
@ -164,7 +180,9 @@ function draftBib({
|
||||||
prefix: "bottomRight"
|
prefix: "bottomRight"
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create one path for the bib outline
|
/*
|
||||||
|
* Create one path for the bib outline
|
||||||
|
*/
|
||||||
paths.seam = new Path()
|
paths.seam = new Path()
|
||||||
.move(points.edgeLeft)
|
.move(points.edgeLeft)
|
||||||
.line(points.bottomLeftStart)
|
.line(points.bottomLeftStart)
|
||||||
|
@ -185,62 +203,66 @@ function draftBib({
|
||||||
.close()
|
.close()
|
||||||
.addClass("fabric")
|
.addClass("fabric")
|
||||||
|
|
||||||
if (complete) {
|
/*
|
||||||
// Add snaps
|
* Mark the bias tape, but only if complete is set
|
||||||
points.snapLeft = points.top
|
*/
|
||||||
.shiftFractionTowards(points.edgeTop, 0.5)
|
if (complete) paths.bias = paths.seam
|
||||||
points.snapRight = points.snapLeft.flipX()
|
.offset(-5)
|
||||||
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
|
.addClass("various dashed")
|
||||||
snippets.snapSocket = new Snippet('snap-socket', points.snapRight)
|
.addText("finishWithBiasTape", "center fill-various")
|
||||||
.attr('opacity', 0.5)
|
/*
|
||||||
|
* Annotations
|
||||||
|
*/
|
||||||
|
|
||||||
// Add a logo
|
// Cutlist
|
||||||
points.logo = new Point(0, 0)
|
store.cutlist.setCut({ cut: 1, from: 'fabric' })
|
||||||
snippets.logo = new Snippet("logo", points.logo)
|
|
||||||
|
// Snaps
|
||||||
|
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
|
||||||
|
points.snapRight = points.snapLeft.flipX()
|
||||||
|
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
|
||||||
|
snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
|
||||||
|
|
||||||
// Add a title
|
// Logo
|
||||||
points.title = points.bottom.shift(-90, 45)
|
points.logo = new Point(0, 0)
|
||||||
macro("title", {
|
snippets.logo = new Snippet("logo", points.logo)
|
||||||
at: points.title,
|
|
||||||
nr: 1,
|
|
||||||
title: "bib",
|
|
||||||
scale: 0.7
|
|
||||||
})
|
|
||||||
|
|
||||||
// Add a scalbox
|
// Title
|
||||||
points.scalebox = points.title.shift(-90, 55)
|
points.title = points.bottom.shift(-90, 45)
|
||||||
macro("scalebox", { at: points.scalebox })
|
macro("title", {
|
||||||
|
at: points.title,
|
||||||
|
nr: 1,
|
||||||
|
title: "bib",
|
||||||
|
scale: 0.7
|
||||||
|
})
|
||||||
|
|
||||||
paths.bias = paths.seam
|
// Scalbox
|
||||||
.offset(-5)
|
points.scalebox = points.title.shift(-90, 55)
|
||||||
.addClass("various dashed")
|
macro("scalebox", { at: points.scalebox })
|
||||||
.addText("finishWithBiasTape", "center fill-various")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return part
|
return part
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Example>
|
</Example>
|
||||||
|
|
||||||
Before we can get started, let's make sure we have the required software
|
|
||||||
installed on our computer:
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
|
Before I can get started, I want to make sure I have the required software
|
||||||
|
installed on my computer.
|
||||||
|
|
||||||
FreeSewing is a JavaScript library that can run in the browser, on
|
FreeSewing is a JavaScript library that can run in the browser, on
|
||||||
[Node.js](https://nodejs.org/), or a variety of other runtimes such as Deno,
|
[Node.js](https://nodejs.org/), or a variety of other runtimes such as Bun,
|
||||||
AWS Lambda, and so on.
|
Deno, AWS Lambda, and so on.
|
||||||
|
|
||||||
For development, we'll use Node.js. If we don't have Node.js on our system,
|
For development, I will use Node.js. If you don't have Node.js on our system,
|
||||||
follow the link above and install it on our system.
|
follow the link above and install it.
|
||||||
|
|
||||||
<Tip compact>We need Node.js 16 or higher to use FreeSewing</Tip>
|
<Tip compact>You need Node.js 18 (lts/hydrogen) or higher to use FreeSewing</Tip>
|
||||||
|
|
||||||
When we're done, we can test whether it works by running:
|
To test whether NodeJS is installed, and see it's version, you can run this command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
node -v
|
node -v
|
||||||
```
|
```
|
||||||
|
|
||||||
If we get the Node.js version number, we're all set.
|
If you get the Node.js version number, that means NodeJs is installed. Yay!
|
||||||
|
|
|
@ -3,42 +3,45 @@ title: Setting up the development environment
|
||||||
order: 100
|
order: 100
|
||||||
---
|
---
|
||||||
|
|
||||||
Open a terminal and enter the following command:
|
FreeSewing provides a development environment that visualizes your design for you.
|
||||||
|
|
||||||
|
To set it up, I will open a terminal and enter the following command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npx @freesewing/new-design@next
|
npx @freesewing/new-design@next
|
||||||
```
|
```
|
||||||
<Fixme compact>Remove `@next` suffix once v3 is in production</Fixme>
|
<Fixme compact>Remove `@next` suffix once v3 is in production</Fixme>
|
||||||
|
|
||||||
We'll be asked some questions.
|
It will ask some questions.
|
||||||
All the defaults will do, but here are the details:
|
All the defaults will do, but here are the details:
|
||||||
|
|
||||||
- *What template would you like to use?* — Pick the default: **Tutorial**
|
- *What template would you like to use?* — Pick the default: **Tutorial**
|
||||||
- *What package manager should we use?* — Pick the default: **npm**, unless you are certain you have **yarn** installed
|
- *What package manager should we use?* — Pick the default: **npm**, unless you are certain you have **yarn** installed
|
||||||
|
|
||||||
After we've answered these questions, files will be copied, dependencies installed, and components downloaded.
|
After answering these questions, files will be copied, dependencies installed, and requirements downloaded.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
|
|
||||||
This will take a few minutes because we're loading some software for our development environment.
|
This will take a few minutes because the development environment has a number
|
||||||
|
of dependencies that need to be downloaded.
|
||||||
|
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
When it's ready, enter the `tutorial` directory that was just created and run `npm run dev`:
|
When it's ready, you can enter the `tutorial` directory that was just created and run `npm run dev`:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd tutorial
|
cd tutorial
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Or if we chose to use yarn as package manager:
|
Or if you want to use yarn as package manager:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd tutorial
|
cd tutorial
|
||||||
yarn dev
|
yarn dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Now open our browser at http://localhost:8000
|
Now open a browser and go to http://localhost:8000
|
||||||
|
|
||||||
If all goes well, we'll should see this landing page:
|
If all goes well, we'll should see this landing page:
|
||||||
|
|
||||||
|
@ -48,5 +51,6 @@ If all goes well, we'll should see this landing page:
|
||||||
|
|
||||||
### Need help?
|
### Need help?
|
||||||
|
|
||||||
If you run into any issues, [join our **#development-help** chat room on on
|
If you run into any issues, head over to [FreeSewing.org/support](https://next.freesewing.org/support)
|
||||||
Discord](https://discord.freesewing.org/) and we'll figure it out together.
|
which lists the various ways in which you can get help.
|
||||||
|
|
||||||
|
|
|
@ -1,77 +1,84 @@
|
||||||
---
|
---
|
||||||
title: Our first part
|
title: Creating a part
|
||||||
order: 120
|
order: 120
|
||||||
---
|
---
|
||||||
|
|
||||||
Much like garments themselves, patterns are made up of _parts_.
|
Much like garments themselves, patterns are made up of _parts_.
|
||||||
Most patterns will have multiple parts. A sleeve, a back part, the collar, and
|
Most patterns will have multiple parts. A sleeve, a back part, the collar, and
|
||||||
so on. Our pattern is very simple, and only has one part: the bib.
|
so on. The pattern you create today is very simple, and only has one part: the bib.
|
||||||
|
|
||||||
It's a good idea to keep each part in its own file. We don't *have to* do
|
<Tip>
|
||||||
this, but it's a good habit to get into. When we create more elaborate designs
|
|
||||||
with multiple parts, keeping each in its own file makes for a more tidy
|
It's a good idea to keep each part in its own file. You don't *have to* do
|
||||||
and approachable code base.
|
this, but it's a good habit to get into.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
## bib.mjs
|
## bib.mjs
|
||||||
|
|
||||||
The previous step has already set everything up for us. Our design's main file
|
Since I chose the `tutorial` preset, the development environment is preconfigured for this tutorial.
|
||||||
lives in `design/src/index.mjs`, and our part lives in `design/src/bib.mjs`.
|
|
||||||
|
|
||||||
This `bib.mjs` is where we'll do all our work. The file includes a comments to guide you on how to use it. We removed those for clarity in our example. It currently looks like this:
|
The design's main file lives in `design/src/index.mjs`, and the bib part lives in `design/src/bib.mjs`.
|
||||||
|
|
||||||
|
This `bib.mjs` is where I will be doing most of the work.
|
||||||
|
The file that was created includes a lot of comments to provide guidance to those not using this tutorial.
|
||||||
|
I have removed those comments from the inline examples in this tutorial for clarity in our example.
|
||||||
|
|
||||||
|
The `bib.mjs` file currently looks like this:
|
||||||
|
|
||||||
```design/src/bib.mjs
|
```design/src/bib.mjs
|
||||||
import { pluginBundle } from "@freesewing/plugin-bundle"
|
/*
|
||||||
|
* This function drafts the part
|
||||||
function draftBib ({
|
*/
|
||||||
part, // Your draft method must return this
|
function draftBib ({ part }) => {
|
||||||
})
|
|
||||||
{
|
|
||||||
// Work your magic here
|
|
||||||
return part
|
return part
|
||||||
}
|
}
|
||||||
export const bib = {
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the part object
|
||||||
|
*/
|
||||||
|
export const bib = {
|
||||||
name: 'tutorial.bib',
|
name: 'tutorial.bib',
|
||||||
draft: draftBib,[],
|
draft: draftBib,
|
||||||
from: false,
|
|
||||||
hide: {
|
|
||||||
self: false,
|
|
||||||
from: false,
|
|
||||||
after: false
|
|
||||||
},
|
|
||||||
options: {},
|
|
||||||
measurements: [],
|
|
||||||
optionalMeasurements: [],
|
|
||||||
plugins: [ pluginBundle ]
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### The part object
|
### The part object
|
||||||
|
|
||||||
Each part in FreeSewing is an object that describes everything there is to know about the part.
|
Each part in FreeSewing is an object that describes the part, and has a `draft`
|
||||||
|
method to do the actual work of drafting the part.
|
||||||
|
|
||||||
The only mandatory keys on a part object are `name` and `draft`.
|
The only mandatory keys on a part object are `name` and `draft`.
|
||||||
|
|
||||||
<Related>
|
<Related>
|
||||||
|
|
||||||
Refer to [the part reference documentation](/reference/api/part) for
|
Refer to [the part reference documentation](/reference/api/part) for
|
||||||
all details about configuring the part object
|
all details about configuring the part object
|
||||||
</Related>
|
</Related>
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
|
||||||
|
A design in FreeSewing is a thin wrapper around a collection of parts.
|
||||||
|
Each parts stands on its own, and parts from various designs can be combined
|
||||||
|
to create other designs.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
|
||||||
#### The part name
|
#### The part name
|
||||||
|
|
||||||
```design/src/bib.mjs
|
```design/src/bib.mjs
|
||||||
name: 'tutorial.bib',
|
name: 'tutorial.bib',
|
||||||
```
|
```
|
||||||
|
|
||||||
A part's `name` should be unique in a pattern. Apart from that, anything goes.
|
A part's `name` should be unique in a design. I used `tutorial.bib` as the
|
||||||
Although we probably want to give it a sensible name.
|
name, because that makes sense.
|
||||||
|
|
||||||
As we can see in the example above, we're using `tutorial.bib` as the name.
|
<Warning>
|
||||||
|
|
||||||
<Tip>
|
I **strongly** recommend that you apply the same `designName.partName` naming scheme in all your parts.
|
||||||
We **strongly** recommend that you follow this `design.part` naming scheme to avoid
|
This avoids naming conflicts when mixing parts from various designs to create a new design.
|
||||||
naming conflicts when mixing parts from various designs to create new designs.
|
|
||||||
</Tip>
|
</Warning>
|
||||||
|
|
||||||
#### The part's draft method
|
#### The part's draft method
|
||||||
|
|
||||||
|
@ -81,7 +88,8 @@ naming conflicts when mixing parts from various designs to create new designs.
|
||||||
|
|
||||||
The second mandatory key on the part object is `draft` which should hold the method that drafts the part.
|
The second mandatory key on the part object is `draft` which should hold the method that drafts the part.
|
||||||
|
|
||||||
In our example above, it refers to the `draftBib` function we defined at the top of the file.
|
In the example above, it refers to the `draftBib` function that was defined at the top of the same `bib.mjs` file.
|
||||||
|
|
||||||
For now this function doesn't do much, but that will change soon enough.
|
For now this function doesn't do much, but that will change soon enough.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
|
@ -99,56 +107,76 @@ to get started. Or, read on for an explanation of what's going on in the
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
The `index.mjs` file is already complete and we won't be making any changes to
|
The `index.mjs` file is already complete and we won't be making any changes to
|
||||||
it. But for those who are curious about what's going on inside `index.mjs`,
|
it. But if you are curious about what's going on inside `index.mjs`,
|
||||||
we're including a version with comments below:
|
this is all we need:
|
||||||
|
|
||||||
```design/src/index.mjs
|
```design/src/index.mjs
|
||||||
/*
|
|
||||||
* Import the `Design` constructor
|
|
||||||
* from the FreeSewing core library
|
|
||||||
*
|
|
||||||
* This Design constructor is a method
|
|
||||||
* (also known as a function)
|
|
||||||
* that creates a new Design
|
|
||||||
*/
|
|
||||||
import { Design } from '@freesewing/core'
|
import { Design } from '@freesewing/core'
|
||||||
/*
|
|
||||||
* Import the `bib` part from the bib.mjs file
|
|
||||||
* in the same folder as this index.mjs file
|
|
||||||
*
|
|
||||||
* This is the part we'll be working on
|
|
||||||
* in this tutorial
|
|
||||||
*/
|
|
||||||
import { bib } from './bib.mjs'
|
import { bib } from './bib.mjs'
|
||||||
|
import { i18n } from '../i18n/index.mjs'
|
||||||
|
|
||||||
/*
|
const Tutorial = new Design({
|
||||||
* Create a new Pattern by passing
|
|
||||||
* a configuration object
|
|
||||||
* to the Design constructor
|
|
||||||
*/
|
|
||||||
const Pattern = new Design({
|
|
||||||
/*
|
|
||||||
* This `data` key is optional, but we
|
|
||||||
* typically add a name and version here
|
|
||||||
*/
|
|
||||||
data: {
|
|
||||||
name: "Tutorial",
|
|
||||||
},
|
|
||||||
/*
|
|
||||||
* This `parts` key is the most important thing
|
|
||||||
* It holds a list of `parts` for our Design.
|
|
||||||
* A Pattern/Design is in the end not much more
|
|
||||||
* than a collection of parts.
|
|
||||||
*/
|
|
||||||
parts: [ bib ],
|
parts: [ bib ],
|
||||||
})
|
})
|
||||||
|
|
||||||
/*
|
export { bib, Tutorial, i18n }
|
||||||
* We are exporting our Pattern
|
|
||||||
* (so others can use it)
|
|
||||||
* but we also (re-)export our bib part
|
|
||||||
* this allows others to re-use it
|
|
||||||
* in their own designs
|
|
||||||
*/
|
|
||||||
export { bib, Pattern }
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you are familiar with Javascript, I hope you are happy to see that FreeSewing uses ESM modules, and named exports.
|
||||||
|
|
||||||
|
If you are not familiar with Javascript, these `import` statements are how we load code from other files.
|
||||||
|
There's three of them:
|
||||||
|
|
||||||
|
```design/src/index.mjs
|
||||||
|
import { Design } from '@freesewing/core'
|
||||||
|
```
|
||||||
|
|
||||||
|
This loads the `Design` constructure from FreeSewing's core library.
|
||||||
|
A constructor is a function that creates something. So the `Design` constructor creates a Design.
|
||||||
|
|
||||||
|
```design/src/index.mjs
|
||||||
|
import { bib } from './bib.mjs'
|
||||||
|
```
|
||||||
|
|
||||||
|
This loads the `bib` part from the `bib.mjs` file in the same folder.
|
||||||
|
This is what we will be working on.
|
||||||
|
|
||||||
|
```design/src/index.mjs
|
||||||
|
import { i18n } from '../i18n/index.mjs'
|
||||||
|
```
|
||||||
|
|
||||||
|
And this loads something named `i18n` from the `index.mjs` file in the `i18n`
|
||||||
|
folder that's one level higher. These are the translations.
|
||||||
|
|
||||||
|
I will show you how you can provide translations for your designs towards the
|
||||||
|
end of this tutorial.
|
||||||
|
|
||||||
|
```design/src/index.mjs
|
||||||
|
const Tutorial = new Design({
|
||||||
|
parts: [ bib ],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
This is where the magic happens. We create a new Design by passing the Design
|
||||||
|
constructure a configuration object. All it holds is the `parts` key that is
|
||||||
|
an array of our parts.
|
||||||
|
|
||||||
|
Which goes to show that a design isn't much more than a bunch of parts.
|
||||||
|
|
||||||
|
```design/src/index.mjs
|
||||||
|
export { bib, Tutorial, i18n }
|
||||||
|
```
|
||||||
|
|
||||||
|
And then all that's left to do is export things so that people can use them.
|
||||||
|
These are named exports. We are exporting three things:
|
||||||
|
|
||||||
|
- `Tutorial` is our complete design. Exporting it means people can use it.
|
||||||
|
- `bib` is our part. We are exporting it so people can re-use just this part.
|
||||||
|
- `i18n` are the translations. We are exporting it so people can load them when using our Tutorial.
|
||||||
|
|
||||||
|
<Related>
|
||||||
|
|
||||||
|
Refer to [the design reference documentation](/reference/api/design) for
|
||||||
|
all details about what you can pass to the Design constructor.
|
||||||
|
</Related>
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@ order: 110
|
||||||
Inside our `tutorial` folder, the `design/src` folder holds the source code for
|
Inside our `tutorial` folder, the `design/src` folder holds the source code for
|
||||||
the new pattern we will create.
|
the new pattern we will create.
|
||||||
|
|
||||||
|
If you want to support internationalization in your design, your translations
|
||||||
|
go in the `design/i18n` folder.
|
||||||
|
|
||||||
We can safely ignore all other files and folders, as they are part of the
|
We can safely ignore all other files and folders, as they are part of the
|
||||||
FreeSewing development environment.
|
FreeSewing development environment.
|
||||||
So feel free to skip ahead to [Our first part](/tutorials/pattern-design/our-first-part).
|
So feel free to skip ahead to [Our first part](/tutorials/pattern-design/our-first-part).
|
||||||
|
|
|
@ -99,7 +99,7 @@ export default DocsPage
|
||||||
export async function getStaticProps({ params }) {
|
export async function getStaticProps({ params }) {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
...(await serverSideTranslations('en', ['docs', ...ns])),
|
...(await serverSideTranslations('en', ['docs', 'tutorial', ...ns])),
|
||||||
slug: params.slug.join('/'),
|
slug: params.slug.join('/'),
|
||||||
page: {
|
page: {
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
|
|
|
@ -7,7 +7,7 @@ export const MdxWrapper = ({ title = false, path, language, children, noFooter =
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{title ? <h1>{title}</h1> : null}
|
{title ? <h1>{title}</h1> : null}
|
||||||
<div className="text-primary mdx text-base-content text-base">{children}</div>
|
<div className="mdx text-base-content">{children}</div>
|
||||||
{noFooter ? null : (
|
{noFooter ? null : (
|
||||||
<div
|
<div
|
||||||
className={`flex flex-row gap-1 text-sm opacity-70 justify-end items-center
|
className={`flex flex-row gap-1 text-sm opacity-70 justify-end items-center
|
||||||
|
|
|
@ -15,7 +15,7 @@ export const MdxWrapper = ({ title = false, path, language, children }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{title ? <h1>{title}</h1> : null}
|
{title ? <h1>{title}</h1> : null}
|
||||||
<div className="text-primary mdx text-base-content text-base">
|
<div className="mdx text-base-content text-base">
|
||||||
<MDXProvider components={components}>{children}</MDXProvider>
|
<MDXProvider components={components}>{children}</MDXProvider>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -2,9 +2,13 @@ import { Tab, Tabs } from '../tabs.mjs'
|
||||||
import Md from 'react-markdown'
|
import Md from 'react-markdown'
|
||||||
import { pluginFlip } from '@freesewing/plugin-flip'
|
import { pluginFlip } from '@freesewing/plugin-flip'
|
||||||
import { pluginGore } from '@freesewing/plugin-gore'
|
import { pluginGore } from '@freesewing/plugin-gore'
|
||||||
|
import { pluginI18n } from '@freesewing/plugin-i18n'
|
||||||
import { Design } from '@freesewing/core'
|
import { Design } from '@freesewing/core'
|
||||||
import yaml from 'js-yaml'
|
import yaml from 'js-yaml'
|
||||||
import { Pattern, PatternXray } from '@freesewing/react-components'
|
import { Pattern, PatternXray } from '@freesewing/react-components'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
|
export const ns = ['tutorial', 'plugin-annotations']
|
||||||
|
|
||||||
// Get code from children
|
// Get code from children
|
||||||
export const asText = (reactEl) => {
|
export const asText = (reactEl) => {
|
||||||
|
@ -59,6 +63,7 @@ const buildPattern = (children, settings = { margin: 5 }, tutorial = false, pape
|
||||||
|
|
||||||
// Handles display of pattern in mormal or xray mode
|
// Handles display of pattern in mormal or xray mode
|
||||||
const ShowPattern = ({ renderProps, logs, mode = 'normal' }) => {
|
const ShowPattern = ({ renderProps, logs, mode = 'normal' }) => {
|
||||||
|
const { t } = useTranslation(ns)
|
||||||
if (!renderProps) return null
|
if (!renderProps) return null
|
||||||
|
|
||||||
if (logs.pattern.error.length > 0 || logs.sets[0].error.length > 0)
|
if (logs.pattern.error.length > 0 || logs.sets[0].error.length > 0)
|
||||||
|
@ -68,7 +73,11 @@ const ShowPattern = ({ renderProps, logs, mode = 'normal' }) => {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
return mode === 'xray' ? <PatternXray {...{ renderProps }} /> : <Pattern {...{ renderProps }} />
|
return mode === 'xray' ? (
|
||||||
|
<PatternXray {...{ renderProps, t }} className="freesewing pattern text-base-content" />
|
||||||
|
) : (
|
||||||
|
<Pattern {...{ renderProps, t }} className="freesewing pattern text-base-content" />
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper component dealing with the tabs and code view
|
// Wrapper component dealing with the tabs and code view
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue