1
0
Fork 0

chore(markdown): Update option docs

This commit is contained in:
Joost De Cock 2022-02-05 17:44:23 +01:00
parent d0e05fe455
commit 52ddbaaa02
28 changed files with 952 additions and 631 deletions

View file

@ -2,6 +2,28 @@
title: dependencies
---
The `dependencies` key in the pattern configuration file allow you to configure
dependencies between different parts of your pattern.
For example, you may only be able to draft the sleeve after having drafted the
part that contains the armhole the sleeve should fit in.
Dependencies control the order in which parts get drafted, but are also used
when users requests to [only draft some parts of a
pattern](/reference/api/settings/only).
Behind the scenes, FreeSewing will draft all dependencies, and make sure to not
render them if they were not requested.
## Structure
An plain object of `key`-`value` pairs that controls the order in which pattern
parts will get drafted.
The value can either be a string, or an array of strings.
Those strings should be part names.
You read the configuration as: `key` depends on `value`.
## Example
```js
dependencies: {
front: "back",
@ -9,7 +31,10 @@ dependencies: {
}
```
An object of `key`-`value` pairs that controls the order in which pattern parts will get drafted.
In this example:
- The `front` part depends on the `back` part
- The `sleeveplacket` part depends on the `sleeve` and `cuff` parts.
<Tip>

View file

@ -2,19 +2,11 @@
title: Pattern configuration file
---
```js
import { version } from '../package.json'
The pattern configuration file holds a variety of information about the
pattern, its various parts, what measurements it requires, the options it
accepts and so on.
export default {
version,
name: "sorcha",
// More configuration here
}
```
A pattern configuration file exports a default object with the following properties:
<ReadMore />
It is part of the initial design and as such static in nature.
<Note>
@ -24,3 +16,23 @@ For run-time configuration, see [Pattern settings](/reference/api/settings).
</Note>
## Structure
The pattern configuration is a plain object with one or more of the following
properties:
<ReadMore />
## Example
Below is a minimal example. Look at [the Aaron config file][aaron] for a full example.
```js
const config = {
version: '0.0.1',
name: "sorcha",
// More configuration here
}
```
[aaron]: https://github.com/freesewing/freesewing/blob/develop/packages/aaron/config/index.js

View file

@ -2,14 +2,26 @@
title: hide
---
The `hide` key in the pattern configuration file allow you to configure
parts the should be hidden by default.
*Hidden* means that they will be drafted, but not rendered. This is
ypically used for a base part on which other parts are built.
Note that hidden parts will be rendered when the user requests
to [only draft some parts of a pattern](/reference/api/settings/only)
and includes the hidden part(s).
## Structure
An array with strings that hold part names.
## Example
```js
hide: [
"base"
]
```
An array that lists pattern parts that should be hidden by default.
Hidden means that they will be drafted, but not rendered. Typically used
for a base part on which other parts are built.
In the configuration above, the `base` part will be hidden by default.

View file

@ -2,19 +2,29 @@
title: inject
---
The `inject` key in the pattern configuration file allow you to configure
the rules for injecting one part into another.
By *injecting* we mean that rather than starting out with a fresh part,
you'll get a part that has the points, paths, and snippets of the injected part.
## Structure
A plain object of key/value pairs of parts.
The `value` part will be injected in the `key` part.
## Example
```js
inject: {
front: "back"
}
```
An object of key/value pairs of parts. The `value` part will be injected in the `key` part.
By *injected* we mean rather than starting out with a fresh part, you'll get a part that
has the points, paths, and snippets of the `value` part.
In this example, the `back` part will be injected in the `front` part.
In doing so, the `front` part will start out as a copy of the `back` part.
<Tip>
See [the Howto on Part inheritance](/howtos/code/inject) for an example.
See [the Howto on Part inheritance](/howtos/code/inject) for a hands-on example.
</Tip>

View file

@ -2,6 +2,16 @@
title: measurements
---
The `measurements` key in the pattern configuration file allow you to configure
the measurments that are required to draft the pattern.
## Structure
An array of strings where the strings are the names of the measurements
required to draft this pattern.
## Example
```js
measurements: [
"bicepsCircumference",
@ -9,8 +19,6 @@ measurements: [
]
```
An array with the names of the measurements required to draft this pattern.
<Note>
###### Don't just make up names
@ -20,3 +28,11 @@ for a list of measurement names already used in freesewing patterns.
It is a [best practice](/guides/best-practices/reuse-measurements/) to stick to these names.
</Note>
<Related>
This configuration is for **required measurements** only.
There is a also a way to configure [optional
measurements](/reference/api/config/optionalmeasurements)
</Related>

View file

@ -2,8 +2,17 @@
title: name
---
The `name` key in the pattern configuration holds the name of your design.
## Structure
The value should hold a string that is also a [valid NPM package
name](https://github.com/npm/validate-npm-package-name).
## Example
```js
name: "sorcha"
```
A string with the name of your pattern.
In this example, the pattern is named **Sorcha**.

View file

@ -2,14 +2,22 @@
title: optionalMeasurements
---
The `optionalMeasurements` key in the pattern configuration file allows
you to configure measurments that are optional to draft the pattern.
## Structure
An array of strings where the strings are the names of the optional
measurements.
## Example
```js
optionalMeasurements: [
'highBust'
]
```
An array with the names of optional measurements that can be used to draft this pattern.
<Note>
###### Why would you want optional measurements?

View file

@ -0,0 +1,65 @@
---
title: optionGroups
---
Option groups allow you to group options together when presenting them
to the user. They also support (one) level of sub-grouping which is
useful when your design has many options.
<Note>
##### This section applies to frontend integration
When you use FreeSewing patterns via the API -- in a backend NodeJS system
or on the command line for example -- all options can be used.
The conditional display of options is intended for frontend integration.
It is what's used on FreeSewing.org and our development environment alike, but
it is not intended as a way to block access to a given option. It merely hides it.
</Note>
## Structure
Option groups are stored under the `optionGroups` key in the pattern
configuration file.
They hold a plain object where each property can hold:
- An array of strings that are the names of the options to include in the group
- A plain object whose properties hold an array of strings that are the names
of the options to include in the group. (this creates a subgroup)
## Example
```js
optionGroups: {
fit: [
'chestEase',
'waistEase',
],
style: [
'cuffStyle',
'hemStyle',
{
collar: [
'collarHeight',
'collarShape'
]
}
],
}
```
The configuration above will create the following structure:
- **fit**
- `chestEase`
- `waistEase`
- **style**
- `cuffStyle`
- `hemStyle`
- **collar**
- `collarHeight`
- `collarShape`

View file

@ -0,0 +1,26 @@
---
title: boolean
---
For options where the choice is either `true` or `false`, **on** or **off**,
or **yes** or **no**, use a boolean option.
## Structure
A boolean option is a plain object with these properties:
- `bool` : Either `true` or `false` which will be the default
- `hide` <small>(optional)</small> : A method to [control the optional display of the option][hide]
[hide]: /reference/api/config/options#optionally-hide-options-by-configuring-a-hide-method
## Example
```js
options: {
withLining: {
bool: true
}
}
```

View file

@ -1,16 +0,0 @@
---
title: boolean
---
If your option is either `true` or `false`, or **on** or **off** or **yes** or **no**, you can use a boolean:
Your boolean option should be an object with these properties:
- `bool` : Either `true` or `false` which will be the default
```js
options: {
withLining: { bool: true }
}
```

View file

@ -1,231 +0,0 @@
---
title: options
---
Options come in 6 varities:
- [Constants](#constants) : A value that can't be changed
- [Booleans](#booleans) : A value that is either `true` or `false`
- [Percentages](#percentages) : A value in percent, with minimum and maximum values
- [Millimeters](#millimeters) : A value in millimeter, with minimum and maximum values
- [Degrees](#degrees) : A value in degrees, with minimum and maximum values
- [Counters](#counters) : An integer value, with minimum and maximum values
- [Lists](#lists) : A list of options with a default
Under the hood, millimeters, degrees, and counters are handled the same way.
We use different types because it easier to understand the nature of a given option.
### Constants
If your option is a scalar value (like a string or a number), it will be treated as a constant:
```js
options: {
collarFactor: 4.8
}
```
Rather than define constants in your code, it's good practice to set them in your configuration file.
This way, people who extend your pattern can change them if they would like to.
### Booleans
If your option is either `true` or `false, or **on** or **off** or **yes** or **no**, you can use a boolean:
Your boolean option should be an object with these properties:
- `bool` : Either `true` or `false` which will be the default
```js
options: {
withLining: { bool: true }
}
```
### Percentages
Percentage options are the bread and butter of freesewing.
Almost all your options will probably be percentages.
They make sure that your pattern will scale regardless of size,
and pass [the ant-man test](https://github.com/freesewing/antman).
Your percentage option should be an object with these properties:
- `pct` : The percentage
- `min` : The minimul that's allowed
- `max` : The maximum that's allowed
```js
options: {
acrossBackFactor: {
pct: 97,
min: 93,
max: 100
}
}
```
<Note>
###### Percentage options will be divided by 100 when loaded
You specify percentages in your config file. For example, `50` means 50%.
When your configuration is loaded, those percentages will by divided by 100.
So a percentage of `50` in your config file will be `0.5` when you read out that option in your pattern.
</Note>
### Millimeters
While we recommend using percentages where possible, sometimes that doesn't make sense.
For those cases, you can use millimeters.
Your millimeter option should be an object with these properties:
- `mm` : The default value in millimeter
- `min` : The minimul that's allowed
- `max` : The maximum that's allowed
```js
options: {
elasticWidth: {
mm: 35,
min: 5,
max: 80
}
}
```
### Degrees
For angles, use degrees.
Your degree option should be an object with these properties:
- `deg` : The default value in degrees
- `min` : The minimul that's allowed
- `max` : The maximum that's allowed
```js
options: {
collarAngle: {
deg: 85,
min: 60
max: 130
}
}
```
### Counters
For a given number of things, use counters.
Counters are for integers only. Things like number of buttons and so on.
Your counter option should be an object with these properties:
- `count` : The default integer value
- `min` : The minimal integer value that's allowed
- `max` : The maximum integer value that's allowed
```js
options: {
butttons: {
count: 7,
min: 4,
max: 12
}
}
```
### Lists
Use a list option when you want to offer an array of choices.
Your list option should be an object with these properties:
- `dflt` : The default for this option
- `list` : An array of available values options
```js
options: {
cuffStyle: {
dflt: "angledBarrelCuff",
list: [
"roundedBarrelCuff",
"angledBarrelCuff"
"straightBarrelCuff"
"roundedFrenchCuff"
"angledFrenchCuff"
"straightFrenchCuff"
]
}
}
```
## Extra
Patterns also take these configuration options to facilitate frontend integration:
### design
The name of the designer:
```js
design: "Joost De Cock"
```
### code
The name of the developer:
```js
code: "Joost De Cock"
```
### type
Either `pattern` or `block`.
```js
type: "pattern"
```
### difficulty
A `1` to `5` difficulty score that indicates how hard it is to make the pattern:
```js
difficulty: 3
```
### tags
A set of tags to allow filtering of patterns on the website:
```js
tags: ["underwear", "top", "basics"],
```
### optionGroups
Organises your pattern options in groups. It expects an object where the key is the group title,
and the value an array of options:
```js
optionGroups: {
fit: ["chestEase", "hipsEase", "stretchFactor"],
style: [
"armholeDrop",
"backlineBend",
"necklineBend",
"necklineDrop",
"shoulderStrapWidth",
"shoulderStrapPlacement",
"lengthBonus"
]
}
```

View file

@ -0,0 +1,37 @@
---
title: constant
---
If your option is a scalar value (like a string or a number),
it will be treated as a constant. Constant options are never
exposed in the frontend, but can still be set when using FreeSewing
via the API.
## Structure
Any option holding a scalar value is a constant option.
## Example
```js
options: {
collarFactor: 4.8,
fitCollar: false,
}
```
<Tip>
##### Why would you use this?
There are typically two use-cases for constant options:
- Rather than define constants in your code, it's good practice to set
them in your configuration file. This way, people who extend your
pattern can change them if they would like to.
- A constant option can be used as a feature-flag. Enabling or disabling
parts of the code beyond the control of the end user, but accessible to
developers.
</Tip>

View file

@ -1,17 +0,0 @@
---
title: constant
---
If your option is a scalar value (like a string or a number), it will be treated as a constant:
```js
options: {
collarFactor: 4.8
}
```
<Tip>
Rather than define constants in your code, it's good practice to set them in your configuration file.
This way, people who extend your pattern can change them if they would like to.
</Tip>

View file

@ -2,14 +2,21 @@
title: counter
---
For a given number of things, use a counter.
For a given number of things, use a counter option.
Counters are for integers only. Things like number of buttons and so on.
Your counter option should be an object with these properties:
## Structure
Your counter option should be a plain object with these properties:
- `count` : The default integer value
- `min` : The minimal integer value that's allowed
- `max` : The maximum integer value that's allowed
- `hide` <small>(optional)</small> : A method to [control the optional display of the option][hide]
[hide]: /reference/api/config/options#optionally-hide-options-by-configuring-a-hide-method
## Example
```js
options: {

View file

@ -0,0 +1,28 @@
---
title: degrees
---
For angles, use a degree option.
## Structure
Your degree option should be a plain object with these properties:
- `deg` : The default value in degrees
- `min` : The minimul that's allowed
- `max` : The maximum that's allowed
- `hide` <small>(optional)</small> : A method to [control the optional display of the option][hide]
[hide]: /reference/api/config/options#optionally-hide-options-by-configuring-a-hide-method
## Example
```js
options: {
collarAngle: {
deg: 85,
min: 60
max: 130
}
}
```

View file

@ -1,21 +0,0 @@
---
title: degrees
---
For angles, use degrees.
Your degree option should be an object with these properties:
- `deg` : The default value in degrees
- `min` : The minimul that's allowed
- `max` : The maximum that's allowed
```js
options: {
collarAngle: {
deg: 85,
min: 60
max: 130
}
}
```

View file

@ -2,13 +2,136 @@
title: options
---
Options come in 6 varities:
The design options stored under the `options` key in the pattern configuration
file give designers flexility to make one pattern with different variations.
<ReadMore list />
## The use case for (design) options
One of the things that sets FreeSewing apart is that sewing patterns are not
static. Each pattern is generated on the spot to accomodate the input
provided by the user. Input that typically includes their measurments.
This *made-to-measure* approach is sort of *our thing* at FreeSewing,
but why stop there?
There's a lot of things that can be left up to the user and taken into
consideration when drafting the pattern. Things like how many buttons to use,
whether or not to include pockets, shape of the collar, and so on. The only
limit really is the creativity of the designer.
The `options` section in a pattern's configuration file is what makes this
possible.
## The five option types you should know
There are the five option types that an aspiring pattern designer should be
familiar with:
1. [**boolean** options][bool] are for yes/no choices
1. [**counter** options][count] are for integer values
1. [**degree** options][deg] are for degrees
1. [**list** options][list] are for a list of possible choices
1. [**percentage** options][pct] are for percentages
<Tip>
In parametric design, percentage options are by far the most common.
They also have the most features and flexibility.
</Tip>
<Related>
For the sake of completeness, here are the two other types of options:
6. [**constant** options][const] are used as
[feature flags](https://en.wikipedia.org/wiki/Feature_toggle)
6. [**millimeter** options][const] are **deprecated** (in favor of [snapped
percentage options][snapped])
</Related>
## Features all five option types share
The five options types listed above (and the millimeter option to be complete)
share the following features:
### Default value
Each option has a default value. If the user does not specify a preference
the default value is what will be used to draft the pattern.
<Note>
Under the hood, millimeters, degrees, and counters are handled the same way.
We use different types because it easier to understand the nature of a given option.
How you configure the default value depends on the option type
</Note>
### Optionally hide options by configuring a `hide()` method
<Note>
##### This section applies to frontend integration
When you use FreeSewing patterns via the API -- in a backend NodeJS system
or on the command line for example -- all options can be used.
The conditional display of options is intended for frontend integration.
It is what's used on FreeSewing.org and our development environment alike, but
it is not intended as a way to block access to a given option. It merely hides it.
</Note>
By default options are shown to the user when:
- They are not a constant option
- **and**
- They are included in an optionGroup
You can further control the optional display of options by adding a method
to the `hide` key under you option, as such:
```js
myOption: {
pct: 50,
min: 0,
max: 100,
hide: function(settings) {
if (settings.measurments.chest > 100) return true
else return false
}
}
```
Your `hide` method will receive one parameter that holds the run-time confguration
of your pattern, which we typically refer to as [the settings](/reference/api/settings).
It contains among other things all measurements and options chosen by the user.
So you can make a choice whether to show the option or not.
If it's not obvious from the name, your `hide()` method you should:
- Return `true` or a truthy value to hide the option
- Return `false` or a falsy value to show the option
<Tip>
##### A `hide()` method is always present on your option
If you do not specify a `hide()` method, it will be populated with the default
`hide()` method -- which always returns `false` thus always showing the option.
In other words, the `hide()` option is always there and will always get called
to determine whether an option should be shown or not.
</Tip>
[bool]: /reference/api/config/options/bool
[const]: /reference/api/config/options/const
[count]: /reference/api/config/options/count
[deg]: /reference/api/config/options/deg
[list]: /reference/api/config/options/list
[pct]: /reference/api/config/options/pct
[snapped]: /reference/api/config/options/pct/snap

View file

@ -4,10 +4,17 @@ title: list
Use a list option when you want to offer an array of choices.
Your list option should be an object with these properties:
## Structure
Your list option should be a plain object with these properties:
- `dflt` : The default for this option
- `list` : An array of available values options
- `hide` <small>(optional)</small> : A method to [control the optional display of the option][hide]
[hide]: /reference/api/config/options#optionally-hide-options-by-configuring-a-hide-method
## Example
```js
options: {

View file

@ -6,11 +6,18 @@ While FreeSewing supports millimeter options, we recommend
using [percentage options][1] and will not accept
contributions that use millimeter options.
A millimeter option should be an object with these properties:
## Structure
A millimeter option should be a plain object with these properties:
- `mm` : The default value in millimeter
- `min` : The minimul that's allowed
- `max` : The maximum that's allowed
- `hide` <small>(optional)</small> : A method to [control the optional display of the option][hide]
[hide]: /reference/api/config/options#optionally-hide-options-by-configuring-a-hide-method
## Example
```js
options: {
@ -42,4 +49,4 @@ percentage option][1] instead.
</Comment>
[1]: /reference/api/config/options/percentage
[1]: /reference/api/config/options/pct

View file

@ -0,0 +1,61 @@
---
title: percentage
---
Percentage options are the bread and butter of freesewing.
Almost all your options will most likely be percentage options as
they ensure that your pattern will scale regardless of size.
## Structure
Your percentage option should be a plain object with these properties:
- `pct` : The default percentage
- `min` : The minimum percentage that's allowed
- `max` : The maximum percentage that's allowed
- `hide` <small>(optional)</small> : A method to [control the optional display of the option][hide]
- `fromAbs` <small>(optional)</small> : A method to [determine the percentage based on a value in millimeter][fromabs]
- `toAbs` <small>(optional)</small> : A method to [return the option value in millimeter][toabs]
- `snap` <small>(optional)</small> : The configuration to control [snapping of percentage options][snap]
[hide]: /reference/api/config/options#optionally-hide-options-by-configuring-a-hide-method
[fromabs]: /reference/api/config/options/pct/fromabs
[toabs]: /reference/api/config/options/pct/toabs
[snap]: /reference/api/config/options/pct/snap
<Note>
###### Percentage options will be divided by 100 when loaded
You specify percentages in your config file. For example, `50` means 50%.
When your configuration is loaded, those percentages will be divided by 100.
So a percentage of `50` in your config file will be `0.5` when you read out that option in your pattern.
###### Percentage options are not limited to the range 0-100
The minimum and maximum (and default) percentages are not restricted to the range from `0%` to `100%`.
A percentage option that spans from `-25%` to `135%` is just as valid.
</Note>
## Example
Below is a simple example:
```js
options: {
acrossBackFactor: {
pct: 97,
min: 93,
max: 100
}
}
```
## Advanced use
Percentage options have a few more tricks up their sleeve:
<ReadMore />

View file

@ -0,0 +1,99 @@
---
title: Setting a value in millimeter as a percentage option
---
Percentage options are great for parametric desing, but not always
very intuitive for the user. For example: A user may desire 13
centimeters (5 inches) of chest ease. But what percentage should
they set the `chestEase` option to to accomplish this?
To address this common grievance, FreeSewing allows you to add a
`fromAbs` method that should take a value in millimeter and
return the percentage the option should be set to to result in this
value.
<Note>
Note that this method will not change the percentage of the option.
It will merely return return a percentage value. It is up to the
frontend designer to then either set this value, or suggest it to
the user.
</Note>
## Structure
The `fromAbs` property should hold a function with the following
signature:
```js
function toAbs(millimeter, settings) {
// return a percentage here (0.5 is 50%)
}
```
The first parameter is the desired value in millimeter (for example
`130` for `13cm`).
The second parameter is the pattern's run-time configuration
or [settings](/reference/api/settings) which holds -- among other things -- the
measurements provided by the user.
## Example
In our example above, let's say that the `chestEase` option is
a simple percentage of the `chest` measurement. Our option
configuration could like like this:
```js
chestEase: {
pct: 8,
min: 0,
max: 20,
fromAbs: function(millimeter, settings) {
return millimeter / settings.measurements.chest
}
}
```
With object destructuring and fat-arrow notation,
you can write it a bit terser like this:
```js
fromAbs: (val, { measurements }) => val /measurements.chest
```
## Using pctBasedOn for simple measurement fractions
Many percentage options represent a simple fraction of a measurement
(chest circumference in the example above).
As this scenario is so common, `@freesewing/core` exports a `pctBasedOn` method
that will do the work for you:
```js
// First import the method
import { pctBasedOn } from '@freesewing/core'
const config = {
// ...
options: {
chestEase: {
pct: 8,
min: 0,
max: 20,
// Pass the measurement name as parameter
// and spread the return value into your option
...pctBasedOn('chest')
}
}
}
```
This will not only add an `fromAbs()` method to your option --
one that will return the percentage of any millimeter value passed into it --
it will also add a `toAbs()` method that does the inverse: return the
value in millimeter of whatever percentage the option is set to.
See [Reporting a percentage option value in
millimeter](/reference/api/config/options/pct/toabs) for details.

View file

@ -0,0 +1,243 @@
---
title: Snapped percentage options
---
Snapped percentage options are a hybrid between [list options][list] and
[percentage options][pct]. By combining traits of both, they create a
sort of *smart list option* that will select the most appropriate value
from the list, and also allow a pure parametric value if no close match
is found.
## Structure
Your snapped percentage option should be a plain object with these properties:
- `pct` : The default percentage
- `min` : The minimum percentage that's allowed
- `max` : The maximum percentage that's allowed
- `snap`: Holds the snap configuration (see [Snap configuration](#))
- `toAbs`: a method returning the **millimeter value** of the option ([see `toAbs()`](toabs))
- `hide` <small>(optional)</small> : A method to [control the optional display of the option][hide]
## Snap configuration
A snapped percentage option requires a `snap` property that will determine
what values to snap to.
There are three different scenarios:
### snap holds a number
When `snap` holds a number, the option will be *snapped* to a
multiple of this value.
In the example below, the absolute value of this option will be set to a multiple of `7`
(so one of `7`, `14`, `21`, `28`, `35`, ...).
```js
myOption: {
pct:5,
min: 0
max: 35,
snap: 7,
toAbs: (pct, { measurements }) => measurements.waistToFloor * pct
}
```
<Note>
In a case like this, the value will **always** be snapped,
because the snap points will be distributed equally across the entire range
of all possible inputs.
</Note>
### snap holds an array of numbers
When snap holds an array of numbers, the option will be *snapped* to one of
the numbers unless it's further away than half the distance to its closest neighbor.
In the example below, if the absolute value returned by `toAbs()` is in the
region of influence -- in this example between 4.5 and 69.5 -- the nearest snap value
will be used. If instead it is outside the region of influence, the result of
`toAbs()` will be uses as-is.
```js
myOption: {
pct:5,
min: 0
max: 35,
snap: [7, 12, 21, 34, 53, 64 ]
toAbs: (pct, { measurements }) => measurements.waistToFloor * pct
}
```
### snap is a plain object with `metric` and `imperial` properties that each hold an array of numbers
In this case, the behavior is exaxtle the same as when `snap` holds an array
of numbers.
The differnce is that this allows you to supply a different list of snap values
for users using metric or imperial units.
In the example below, the value of [settings.units](/api/settings/units) will
determine which list of snap values gets used.
Then, if the absolute value returned by `toAbs()` is in the
region of influence -- in this example between 4.5 and 69.5 -- the nearest snap value
will be used. If instead it is outside the region of influence, the result of
`toAbs()` will be uses as-is.
```js
myOption: {
pct:5,
min: 0
max: 35,
snap: {
metric: [7, 12, 21, 34, 53, 64 ],
imperial: [25.4, 50.8, 76.3 ],
}
}
```
<Comment by="joost">
##### Read on for an in-depth look at snapped percentage options
While this information above tells you how to use snapped percentage options,
it does not explain why or when you should use them, or how they work.
Read on if you'd like to learn more about that.
</Comment>
## Example use-case
To understand the need that snapped percentage options are addressing,
we'll use an example use-case: We'll be designing a pajama pants pattern
with an elasticated waist.
In our design, the `waistbandWidth` option should match the width of the
elastic we're going to use so we can construct the waistband accordingly.
We have a few different ways we can approach this:
### Approach A: We use a percentage option
We use a percentage option based on a vertical measurement, like
`waistToFloor`.
The elastic width people end up with is something like 34.12mm for
user A and 27.83mm for user B.
Those are not widths for sale in the store, so that's not great.
### Approach B: We use a list option
We use a list option with a selection of standard elastic
widths to choose from: from half and inch to 3 inches
in 0.5 inch increments.
User A is a doll enthusiasts and 0.5 inch is too big.
User B is working on a giant to go on a float in a parade, and 3 inch
is way too small.
While it would probably work for most people somewhat in the middle,
our solution does not scale.
### Approach C: We use a snapped percentage option
We combine approaches A and B and configure a snapped percentage option
with:
- A percentage based on `waistToFloor`
- Our list of standard elastic widths as *snaps*
For typical humans, our options will *snap* to the closest match in our
list and behave just like Approach A (with a list option).
For dolls and giants, the option will revert to the parametric value and
behave just like Approach B (with a percentage option).
Sweet!
## How snapped percentage options work
Before we wade into the details, let's first agree on terminology:
- The **percentage value** is the page passed by the user for the option.
Its value always represents a percentage.
- The **millimeter value** is the result of feeding the **percentage value** to
the `toAbs()` method. Its value always represents millimeters.
- The **snap values** are the values provided by the snap confguration.
Each of the values always represents millimeters.
Under the hood, and snapped percentage option will:
- Use `toAbs()` to calculate the **millimeter value** from the **percentage value**
- See whether the **millimeter value** approaches one of the **snap values**
- If so, use the snap value (in millimeter) as provided by one of the **snap values**
- If not, use the **millimeter value** as-is
If you're head's spinning, here's an image that will hopefully clarify things a bit:
![A visual guide to how snapped percentage options work](snap.png)
The gradient box represents the range of any given measurement,
from dolls all the way on the left, to giants all the way on the right.
The sort of middle green-colored region is what the designer had in mind
when designing the pattern, and they have set up snap values -- marked by
a red dot -- for values that they feel make sense.
The region of influence of any given snap point will extend 50% towards its
neighbor on both sides (indicated by the dashed lines).This means that the
region of snap points is continuous, once you're in, you're going to be
snapped to one of the snap points.
However, when you venture out into the area where the designer did not
configure any snap points, the absolute value will be used as-is, without
snapping, just as it would in a normal percentage option.
This system results in the best of both worlds:
- Things like elastic widths and so on can be configured to be fixed values,
of common elastic widths for example
- The absolute value will still scale up and down, but will snap to the closest
fixed value when appropriate.
- When the input measurements go somewhere the designer did not anticipate,
the option will just behave as a regular percentage option
## Using snapped percentage options in your pattern code
This is all well and good, but how do you use this?
Well, just like you can get the `options` object from our shorthand call,
you can now get the `absoluteOptions` object that holds absolute values
for those options with snaps configured.
In our paco example, what used to be:
```js
store.set('ankleElastic', measurements.waistToFloor * options.ankleElastic)
```
is now:
```js
store.set('ankleElastic', absoluteOptions.ankleElastic)
```
<Note>
There's really no added value in setting this in the store as `absoluteOptions`
is available everywhere, but we've changed as little as possible in the example
to clarify the difference.
</Note>
[fromabs]: /reference/api/config/options/pct/fromabs
[toabs]: /reference/api/config/options/pct/toabs
[pct]: /reference/api/config/options/pct
[list]: /reference/api/config/options/list
[hide]: /reference/api/config/options#optionally-hide-options-by-configuring-a-hide-method

View file

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Before After
Before After

View file

@ -0,0 +1,88 @@
---
title: Reporting a percentage option value in millimeter
---
Percentage options are great for parametric desing, but not always
very intuitive for the user. For example: Setting the `chestEase`
option to `9%` is not very meaningful unless you happen to know
what that percentage is based on.
To address this common grievance, FreeSewing allows you to add a
`toAbs` method that should return the value of the option in
millimeter.
## Structure
The `toAbs` property should hold a function with the following
signature:
```js
function toAbs(percentage, settings) {
// return value in millimeter here
}
```
The first parameter is the percentage value provided by the user (for example
`0.5` for `50%`).
The second parameter is the pattern's run-time configuration
or [settings](/reference/api/settings) which holds -- among other things -- the
measurements provided by the user.
## Example
In our example above, let's say that the `chestEase` option is
a simple percentage of the `chest` measurement. Our option
configuration could like like this:
```js
chestEase: {
pct: 8,
min: 0,
max: 20,
toAbs: function(value, settings) {
return settings.measurements.chest * value
}
}
```
With object destructuring and fat-arrow notation,
you can write it a bit terser like this:
```js
toAbs: (val, { measurements }) => measurements.chest * val
```
## Using pctBasedOn for simple measurement fractions
Many percentage options represent a simple fraction of a measurement
(chest circumference in the example above).
As this scenario is so common, `@freesewing/core` exports a `pctBasedOn` method
that will do the work for you:
```js
// First import the method
import { pctBasedOn } from '@freesewing/core'
const config = {
// ...
options: {
chestEase: {
pct: 8,
min: 0,
max: 20,
// Pass the measurement name as parameter
// and spread the return value into your option
...pctBasedOn('chest')
}
}
}
```
This will not only add an `toAbs()` method to your option -- one that will return
the value in millimeter of whatever percentage the option is set to -- it will
also add a `fromAbs()` method that does the inverse: return the percentage of
any millimeter value passed into it. See [Setting a value in millimeter as a
percentage option](/api/config/options/pct/fromabs) for details.

View file

@ -1,297 +0,0 @@
---
title: percentage
---
Percentage options are the bread and butter of freesewing.
Almost all your options will most likely be percentage options as
they ensure that your pattern will scale regardless of size.
Percentage options come in two varieties:
- Plain percentage options
- Snapped percentage options
For both varieties, the following is good to keep in mind:
<Note>
###### Percentage options will be divided by 100 when loaded
You specify percentages in your config file. For example, `50` means 50%.
When your configuration is loaded, those percentages will be divided by 100.
So a percentage of `50` in your config file will be `0.5` when you read out that option in your pattern.
###### Percentage options are not limited to the range 0-100
The minimum and maximum (and default) percentages are not restricted to the range from `0%` to `100%`.
A percentage option that spans from `-25%` to `135%` is just as valid.
</Note>
## Plain percentage options
A plain percentage option allows a user to specify a relative value (a percentage) which is
then used to produce an absolute value in mm based on one or more measurements.
A plain percentage option should be an object with these properties:
- `pct` : The default percentage
- `min` : The minimum percentage that's allowed
- `max` : The maximum percentage that's allowed
```js
options: {
acrossBackFactor: {
pct: 97,
min: 93,
max: 100
}
}
```
## Snapped percentage options
A snapped percentage option should be an object with these properties:
- `pct` : The default percentage
- `min` : The minimum percentage that's allowed
- `max` : The maximum percentage that's allowed
- `snap`: See below
- `toAbs`: See below
```js
options: {
acrossBackFactor: {
pct: 97,
min: 93,
max: 100
snap: 5,
toAbs: (val, { measurements }) => measurements.head * val
}
}
```
### How snapped percentage options work
In a so-called _snapped percentage option_ the absolute (i.e. not relative) value
of the option is snapped to discreet values ("snap points"). To make that happen,
the following happens under the hood:
- Use `toAbs()` to calculate an absolute value for the option
- See whether that approaches one of the absolute values provided by `snap`
- If so, use the snapped value
- If not, use the absolute value unchanged
If you're head's spinning, here's an image that will hopefully clarify things a bit:
![A visual guide to how snapped percentage options work](snap.png)
The gradient box represents the range of any given measurement,
from dolls all the way on the left, to giants all the way on the right.
The sort of middle green-colored region is what the designer had in mind
when designing the pattern, and they have set up snap points for values
that they feel make sense.
The region of influence of any given snap point will extend 50% towards its
neighbor on both sides (indicated by the dashed lines).This means that the
region of snap points is continuous, once you're in, you're going to be
snapped to one of the snap points.
However, when you venture out into the area where the designer did not
configure any snap points, the absolute value will be used as-is, without
snapping, just as it would in a normal percentage option.
This system results in the best of both worlds:
- Things like elastic widths and so on can be configured to be fixed values,
of common elastic widths for example
- The absolute value will still scale up and down, but will snap to the closest
fixed value when appropriate.
- When the input measurements go somewhere the designer did not anticipate,
the option will just behave as a regular `pct` option
### What does it take?
To make all this work, we need to clarify what we want to happen.
Specifically, we need to:
- Configure the `snap` property to define what values to snap to
- Pass a method to the `toAbs` property that will calculate the absolute value of the option
#### Configure the `snap` property to define what values to snap to
There are three different scenarios:
##### snap is a number
In this case, the **absolute value** of the option will be *snapped* to a
multiple of this value.
An example:
```js
myOption: {
pct:5,
min: 0
max: 35,
snap: 7
}
```
The absolute value of this option will be set to a multiple of `7`
(so one of `7`, `14`, `21`, `28`, `35`, ...)
<Note>
In a case like this, the value will **always** be snapped,
because the snap points will be distributed equally across the entire range
of all possible inputs.
</Note>
##### snap is an array of numbers
This will snap the **absolute value** of the option to one of the numbers in the
array/list if it is in the region of influence.
An example:
```js
myOption: {
pct:5,
min: 0
max: 35,
snap: [7, 12, 21, 34, 53, 64 ]
}
```
In this case, if the absolute value returned by `toAbs` is in the region of influence (in
this example between 4.5 and 69.5), the nearest snap point will be used. If instead it is
outside the region of influence, it will be used unchanged.
##### snap is an object with `metric` and `imperial` properties that each hold an array of numbers
This will work the same as an array of numbers, but it allows you to supply a
different array/list for users drawing metric, or imperial patterns.
An example config:
```js
myOption: {
pct:5,
min: 0
max: 35,
snap: {
metric: [7, 12, 21, 34, 53, 64 ],
imperial: [25.4, 50.8, 76.3 ],
}
}
```
In this case, the value of [settings.units](/api/settings/units) will determine which
list of snap points to use. If the absolute value returned by `toAbs` is in the region of
influence, the nearest snap point will be used. If instead it is outside the region of
influence, it will be used unchanged.
#### Pass a method to the `toAbs` property that will calculate the absolute value of the option
Our snap configuration depends on the **absolute value** of the option.
But we only receive the percentage value as input. It's up to us to come up
with the logic to turn that into its absolute value.
For this, `pct` options take the `toAbs` property that is a function with
the following signature:
```js
function toAbs(pctValue, settings) {
// return absolute value here
}
```
The first parameter is the percentage value provided by the user (for example
`0.5` for `50%`),
the second is the pattern's settings object which (among other things)
holds the measurements.
In the most common scenario, your option is a simple fraction of a measurement
(head circumference in the example below), so with object destructuring
and fat-arrow notation, you can write it a bit terser like this:
```js
toAbs: (val, { measurements }) => measurements.head * val
```
As this scenario is so common, `@freesewing/core` now exports a `pctBasedOn` method
that you can spread into your option config.
Here's an example from our Paco pattern:
First import the method:
```js
import { pctBasedOn } from '@freesewing/core'
```
Then use it in your option with the name of the measurement the option depends on:
```js
ankleElastic: {
pct: 5, min: 1, max: 13,
snap: {
metric: [ 5, 10, 12, 20, 25, 30, 40, 50, 80 ],
imperial: [ 6.35, 9.525, 12.7, 15.24, 19.05, 25.4, 30.48, 50.8, 76.2],
},
...pctBasedOn('waistToFloor')
},
```
<Note>
##### This does more under the hood for future use
This will not only add an `toAbs()` method to your option that calculates the
absolute value based on the measurement you specify. It will also add a `fromAbs()`
method that does the inverse: return the `pct` value required to achieve a certain
absolute value.
This ability to set a percentage option to whatever is required for a given absolute
value is on our roadmap, so by using this method you are future-proofing your code.
</Note>
### How to use this in your pattern code
This is all well and good, but how do you use this?
Well, just like you can get the `options` object from our shorthand call,
you can now get the `absoluteOptions` object that holds absolute values
for those options with snaps configured.
In our paco example, what used to be:
```js
store.set('ankleElastic', measurements.waistToFloor * options.ankleElastic)
```
is now:
```js
store.set('ankleElastic', absoluteOptions.ankleElastic)
```
<Note>
There's really no added value in setting this in the store as `absoluteOptions`
is available everywhere, but we've changed as little as possible in the example
to clarify the difference.
</Note>
### When to use this in your pattern code
Don't go rushing out turning every `pct` option into a snapped percentage option.
This makes sense in scenarios where you would be tempted to reach for a `mm` option.
Elastic width, waistband width, button size, other things that come in certain
sizes, you get the idea.

View file

@ -2,14 +2,8 @@
title: parts
---
```js
parts: [
"front",
"back"
]
```
An array that lists your (additional) pattern parts. The name must be the key the `pattern.parts` object.
The `parts` key in the pattern configuration file holds a list of
names of pattern parts.
<Tip>
@ -21,3 +15,17 @@ So if parts are included in the `dependencies`, `inject`, or `hide` configuratio
there's no need to include them here, as we already know of their existence.
</Tip>
## Structure
An array of strings where the strings are part name.
## Example
```js
parts: [
"front",
"back"
]
```

View file

@ -2,9 +2,17 @@
title: version
---
The `version` key in the pattern configuration holds the version
of the pattern. For a pattern that is published as an NPM package
this is typically the same version as set in the `package.json` file.
## Structure
A string that holds a valid semantic version number.
## Example
```
version: "0.3.1"
```
The version of your pattern.

View file

@ -2,10 +2,14 @@
title: options
---
The `options` setting allows you to specify the pattern-specific options
that have been implemented by the pattern designer.
The `options` setting allows you to specify values for the pattern-specific
options that have been implemented by the pattern designer.
The available options are listed in the pattern configuration.
Refer to the [the options section in the pattern configuration file][1] for
all details about using options in FreeSewing.
[1]: /reference/api/config/options
```js
import Brian from "@freesewing/brian";