first commit
This commit is contained in:
parent
84899dea1a
commit
5827b79afa
39 changed files with 88385 additions and 0 deletions
9
packages/yuri/.babelrc
Normal file
9
packages/yuri/.babelrc
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
["@babel/preset-env", {
|
||||||
|
"modules": false
|
||||||
|
}],
|
||||||
|
"@babel/preset-react"
|
||||||
|
],
|
||||||
|
"plugins": ["@babel/plugin-proposal-class-properties"]
|
||||||
|
}
|
9
packages/yuri/.editorconfig
Normal file
9
packages/yuri/.editorconfig
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
23
packages/yuri/.eslintrc
Normal file
23
packages/yuri/.eslintrc
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"parser": "babel-eslint",
|
||||||
|
"extends": [
|
||||||
|
"standard",
|
||||||
|
"standard-react"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"es6": true
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"react"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
// don't force es6 functions to include space before paren
|
||||||
|
"space-before-function-paren": 0,
|
||||||
|
|
||||||
|
// allow specifying true explicitly for boolean props
|
||||||
|
"react/jsx-boolean-value": 0
|
||||||
|
}
|
||||||
|
}
|
2
packages/yuri/.gitignore
vendored
Normal file
2
packages/yuri/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dist
|
||||||
|
node_modules
|
2
packages/yuri/.npmignore
Normal file
2
packages/yuri/.npmignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules/
|
||||||
|
dist/
|
4
packages/yuri/.travis.yml
Normal file
4
packages/yuri/.travis.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- 9
|
||||||
|
- 8
|
21
packages/yuri/LICENSE
Normal file
21
packages/yuri/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Biou
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
31
packages/yuri/README.md
Normal file
31
packages/yuri/README.md
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# yuri
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
[](https://www.npmjs.com/package/yuri) [](https://standardjs.com)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save yuri
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import React, { Component } from 'react'
|
||||||
|
|
||||||
|
import MyComponent from 'yuri'
|
||||||
|
|
||||||
|
class Example extends Component {
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<MyComponent />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
© [biou](https://github.com/biou)
|
145
packages/yuri/config/index.js
Normal file
145
packages/yuri/config/index.js
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
import { version } from '../package.json'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'yuri',
|
||||||
|
version: version,
|
||||||
|
design: 'Hellgy',
|
||||||
|
code: 'Biou',
|
||||||
|
department: 'tops',
|
||||||
|
type: 'pattern',
|
||||||
|
difficulty: 3,
|
||||||
|
optionGroups: {
|
||||||
|
fit: [
|
||||||
|
'bicepsEase',
|
||||||
|
'chestEase',
|
||||||
|
'cuffEase',
|
||||||
|
'collarEase',
|
||||||
|
'shoulderEase',
|
||||||
|
'hipsEase',
|
||||||
|
'ribbingStretch',
|
||||||
|
],
|
||||||
|
style: [
|
||||||
|
'lengthBonus',
|
||||||
|
'sleeveLengthBonus',
|
||||||
|
'ribbing',
|
||||||
|
'ribbingHeight',
|
||||||
|
's3Collar',
|
||||||
|
's3Armhole',
|
||||||
|
],
|
||||||
|
advanced: [
|
||||||
|
'acrossBackFactor',
|
||||||
|
'armholeDepthFactor',
|
||||||
|
'backNeckCutout',
|
||||||
|
'frontArmholeDeeper',
|
||||||
|
'sleeveWidthGuarantee',
|
||||||
|
{
|
||||||
|
sleevecap: [
|
||||||
|
'sleevecapEase',
|
||||||
|
'sleevecapTopFactorX',
|
||||||
|
'sleevecapTopFactorY',
|
||||||
|
'sleevecapBackFactorX',
|
||||||
|
'sleevecapBackFactorY',
|
||||||
|
'sleevecapFrontFactorX',
|
||||||
|
'sleevecapFrontFactorY',
|
||||||
|
'sleevecapQ1Offset',
|
||||||
|
'sleevecapQ2Offset',
|
||||||
|
'sleevecapQ3Offset',
|
||||||
|
'sleevecapQ4Offset',
|
||||||
|
'sleevecapQ1Spread1',
|
||||||
|
'sleevecapQ1Spread2',
|
||||||
|
'sleevecapQ2Spread1',
|
||||||
|
'sleevecapQ2Spread2',
|
||||||
|
'sleevecapQ3Spread1',
|
||||||
|
'sleevecapQ3Spread2',
|
||||||
|
'sleevecapQ4Spread1',
|
||||||
|
'sleevecapQ4Spread2',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
measurements: [
|
||||||
|
'biceps',
|
||||||
|
'chest',
|
||||||
|
'head',
|
||||||
|
'hips',
|
||||||
|
'hpsToWaistBack',
|
||||||
|
'waistToHips',
|
||||||
|
'neck',
|
||||||
|
'shoulderSlope',
|
||||||
|
'shoulderToShoulder',
|
||||||
|
'shoulderToWrist',
|
||||||
|
'wrist',
|
||||||
|
'hpsToBust',
|
||||||
|
],
|
||||||
|
dependencies: {
|
||||||
|
backBase: 'base',
|
||||||
|
frontBase: 'backBase',
|
||||||
|
sleevecap: 'frontBase',
|
||||||
|
sleeveBase: 'sleevecap',
|
||||||
|
back: 'backBase',
|
||||||
|
front: 'frontBase',
|
||||||
|
sleeve: 'sleeveBase',
|
||||||
|
// hoodCenter: 'hoodSide',
|
||||||
|
// hoodSide: ['front', 'back'],
|
||||||
|
},
|
||||||
|
inject: {
|
||||||
|
backBase: 'base',
|
||||||
|
frontBase: 'backBase',
|
||||||
|
sleeveBase: 'sleevecap',
|
||||||
|
back: 'backBase',
|
||||||
|
front: 'frontBase',
|
||||||
|
sleeve: 'sleeveBase',
|
||||||
|
},
|
||||||
|
hide: ['base', 'sleevecap', 'backBase', 'frontBase', 'sleeveBase'],
|
||||||
|
parts: ['cuff', 'gusset', 'hoodSide', 'hoodCenter'],
|
||||||
|
options: {
|
||||||
|
// Constants
|
||||||
|
brianFitSleeve: true,
|
||||||
|
brianFitCollar: true,
|
||||||
|
collarFactor: 4.8,
|
||||||
|
shoulderSlopeReduction: 0,
|
||||||
|
|
||||||
|
// Options inherited from Brian
|
||||||
|
acrossBackFactor: { pct: 97, min: 93, max: 100 },
|
||||||
|
armholeDepthFactor: { pct: 65, min: 50, max: 70 },
|
||||||
|
backNeckCutout: { pct: 5, min: 2, max: 8 },
|
||||||
|
bicepsEase: { pct: 8, min: 0, max: 20 },
|
||||||
|
chestEase: { pct: 8, min: -4, max: 20 },
|
||||||
|
collarEase: { pct: 20, min: 10, max: 30 },
|
||||||
|
cuffEase: { pct: 20, min: 10, max: 60 },
|
||||||
|
frontArmholeDeeper: { pct: 0.5, min: 0, max: 1.5 },
|
||||||
|
lengthBonus: { pct: 10, min: 5, max: 15 },
|
||||||
|
shoulderEase: { pct: 0.5, min: -2, max: 6 },
|
||||||
|
// s3 is short for Shoulder Seam Shift
|
||||||
|
s3Collar: { pct: 0, min: -100, max: 100 },
|
||||||
|
s3Armhole: { pct: 0, min: -100, max: 100 },
|
||||||
|
sleeveLengthBonus: { pct: 1, min: 0, max: 10 },
|
||||||
|
sleevecapEase: { pct: 0, min: 0, max: 10 },
|
||||||
|
sleevecapTopFactorX: { pct: 50, min: 25, max: 75 },
|
||||||
|
sleevecapTopFactorY: { pct: 100, min: 35, max: 165 },
|
||||||
|
sleevecapBackFactorX: { pct: 60, min: 35, max: 65 },
|
||||||
|
sleevecapBackFactorY: { pct: 33, min: 30, max: 65 },
|
||||||
|
sleevecapFrontFactorX: { pct: 55, min: 35, max: 65 },
|
||||||
|
sleevecapFrontFactorY: { pct: 33, min: 30, max: 65 },
|
||||||
|
sleevecapQ1Offset: { pct: 3, min: 0, max: 7 },
|
||||||
|
sleevecapQ2Offset: { pct: 5.5, min: 0, max: 7 },
|
||||||
|
sleevecapQ3Offset: { pct: 4.5, min: 0, max: 7 },
|
||||||
|
sleevecapQ4Offset: { pct: 1, min: 0, max: 7 },
|
||||||
|
sleevecapQ1Spread1: { pct: 6, min: 4, max: 20 },
|
||||||
|
sleevecapQ1Spread2: { pct: 15, min: 4, max: 20 },
|
||||||
|
sleevecapQ2Spread1: { pct: 15, min: 4, max: 20 },
|
||||||
|
sleevecapQ2Spread2: { pct: 10, min: 4, max: 20 },
|
||||||
|
sleevecapQ3Spread1: { pct: 10, min: 4, max: 20 },
|
||||||
|
sleevecapQ3Spread2: { pct: 8, min: 4, max: 20 },
|
||||||
|
sleevecapQ4Spread1: { pct: 7, min: 4, max: 20 },
|
||||||
|
sleevecapQ4Spread2: { pct: 7, min: 4, max: 20 },
|
||||||
|
sleeveWidthGuarantee: { pct: 90, min: 25, max: 100 },
|
||||||
|
|
||||||
|
// Options specific to Yuri
|
||||||
|
ribbing: { bool: false },
|
||||||
|
|
||||||
|
ribbingHeight: { pct: 10, min: 5, max: 15 },
|
||||||
|
hipsEase: { pct: 0, min: 0, max: 10 },
|
||||||
|
ribbingStretch: { pct: 15, min: 0, max: 30 },
|
||||||
|
},
|
||||||
|
}
|
10
packages/yuri/example/.babelrc
Normal file
10
packages/yuri/example/.babelrc
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["prismjs", {
|
||||||
|
"languages": ["javascript", "css", "markup"],
|
||||||
|
"plugins": ["line-numbers"],
|
||||||
|
"theme": "twilight",
|
||||||
|
"css": true
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
1
packages/yuri/example/.env
Normal file
1
packages/yuri/example/.env
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SKIP_PREFLIGHT_CHECK=true
|
96
packages/yuri/example/README.md
Normal file
96
packages/yuri/example/README.md
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
<p align="center">
|
||||||
|
<a title="Go to freesewing.org" href="https://freesewing.org/"><img src="https://freesewing.org/img/logo/black.svg" align="center" width="150px" alt="Freesewing logo"/></a>
|
||||||
|
<br>
|
||||||
|
<a href="https://freesewing.org/">FreeSewing v2</a>
|
||||||
|
</p>
|
||||||
|
<p align="center">A JavaScript library for made-to-measure sewing patterns</p>
|
||||||
|
<p align='center'><a
|
||||||
|
href="https://twitter.com/freesewing_org"
|
||||||
|
title="Follow @freesewing_org on Twitter"
|
||||||
|
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Follow%20us-blue.svg?logo=twitter&logoColor=white&logoWidth=15"
|
||||||
|
alt="Follow @freesewing_org on Twitter"/>
|
||||||
|
</a><a
|
||||||
|
href="https://gitter.im/freesewing/freesewing"
|
||||||
|
title="Chat with us on Gitter"
|
||||||
|
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Chat%20with%20us-CA0547.svg?logo=gitter&logoColor=white&logoWidth=15"
|
||||||
|
alt="Chat with us on Gitter"/>
|
||||||
|
</a><a
|
||||||
|
href="https://freesewing.org/patrons/join"
|
||||||
|
title="Become a FreeSewing Patron"
|
||||||
|
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Support%20us-blueviolet.svg?logo=cash-app&logoColor=white&logoWidth=15"
|
||||||
|
alt="Become a FreeSewing Patron"/>
|
||||||
|
</a><a
|
||||||
|
href="https://instagram.com/freesewing_org"
|
||||||
|
title="Follow @freesewing_org on Twitter"
|
||||||
|
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Follow%20us-E4405F.svg?logo=instagram&logoColor=white&logoWidth=15"
|
||||||
|
alt="Follow @freesewing_org on Twitter"/>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# yuri example
|
||||||
|
|
||||||
|
This project was bootstrapped with [Create Freesewing Pattern](https://en.freesewing.dev/create-freesewing-pattern):
|
||||||
|
|
||||||
|
```js
|
||||||
|
npm init freesewing-pattern
|
||||||
|
```
|
||||||
|
|
||||||
|
This example folder is part of the local development environment.
|
||||||
|
It is **not** part of the pattern's source code.
|
||||||
|
|
||||||
|
To run this example, follow these steps:
|
||||||
|
|
||||||
|
- In the folder above this one, run: `yarn start` (or `npm start`)
|
||||||
|
- Then, in new terminal, run the same command in this folder: `yarn start` (or `npm start`)
|
||||||
|
|
||||||
|
This will spin up the development environment, similar to [our online demo](https://yuri.freesewing.dev/).
|
||||||
|
|
||||||
|
## About FreeSewing 🤔
|
||||||
|
|
||||||
|
Where the world of makers and developers collide, that's where you'll find FreeSewing.
|
||||||
|
|
||||||
|
Our [core library](https://freesewing.dev/en/freesewing) is a *batteries-included* toolbox
|
||||||
|
for parametric design of sewing patterns. It's a modular system (check our list
|
||||||
|
of [plugins](https://freesewing.dev/en/plugins) and getting started is as simple as:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm init freesewing-pattern
|
||||||
|
```
|
||||||
|
|
||||||
|
The [getting started] section on [freesewing.dev](https://freesewing.dev/) is a good
|
||||||
|
entrypoint to our documentation, but you'll find a lot more there, including
|
||||||
|
our [API documentation](https://freesewing.dev/en/freesewing/api),
|
||||||
|
as well as [examples](https://freesewing.dev/en/freesewing/examples),
|
||||||
|
and [best practices](https://freesewing.dev/en/do).
|
||||||
|
|
||||||
|
If you're a maker, checkout [freesewing.org](https://freesewing/) where you can generate
|
||||||
|
our sewing patterns adapted to your measurements.
|
||||||
|
|
||||||
|
## Support FreeSewing: Become a patron 🥰
|
||||||
|
|
||||||
|
FreeSewing is an open source project run by a community,
|
||||||
|
and financially supported by our patrons.
|
||||||
|
|
||||||
|
If you feel what we do is worthwhile, you too
|
||||||
|
should [become a patron](https://freesewing.org/patrons/join).
|
||||||
|
|
||||||
|
## Links 👩💻
|
||||||
|
|
||||||
|
- 💻 Makers website: [freesewing.org](https://freesewing.org)
|
||||||
|
- 💻 Developers website: [freesewing.dev](https://freesewing.org)
|
||||||
|
- 💬 Chat: [gitter.im/freesewing](https://gitter.im/freesewing/freesewing)
|
||||||
|
- 🐦 Twitter: [@freesewing_org](https://twitter.com/freesewing_org)
|
||||||
|
- 📷 Instagram: [@freesewing_org](https://instagram.com/freesewing_org)
|
||||||
|
|
||||||
|
## License: MIT 🤓
|
||||||
|
|
||||||
|
© [Joost De Cock](https://github.com/joostdecock).
|
||||||
|
See [the license file](https://github.com/freesewing/freesewing/blob/develop/LICENSE) for details.
|
||||||
|
|
||||||
|
## Where to get help 🤯
|
||||||
|
|
||||||
|
Our [chatroom on Gitter](https://gitter.im) is the best place to ask questions,
|
||||||
|
share your feedback, or just hang out.
|
||||||
|
|
||||||
|
If you want to report a problem, please [create an issue](https://github.com/freesewing/freesewing/issues/new).
|
||||||
|
|
9
packages/yuri/example/netlify.toml
Normal file
9
packages/yuri/example/netlify.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[build]
|
||||||
|
base = "packages/yuri/example"
|
||||||
|
publish = "build"
|
||||||
|
command = "npm run build"
|
||||||
|
|
||||||
|
[[redirects]]
|
||||||
|
from = "/*"
|
||||||
|
to = "/index.html"
|
||||||
|
status = 200
|
40090
packages/yuri/example/package-lock.json
generated
Normal file
40090
packages/yuri/example/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
51
packages/yuri/example/package.json
Normal file
51
packages/yuri/example/package.json
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
{
|
||||||
|
"name": "yuri",
|
||||||
|
"homepage": "https://yuri.freesewing.dev/",
|
||||||
|
"version": "2.17.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@fontsource/permanent-marker": "latest",
|
||||||
|
"@fontsource/roboto-mono": "latest",
|
||||||
|
"@fontsource/ubuntu": "latest",
|
||||||
|
"@freesewing/components": "latest",
|
||||||
|
"@freesewing/core": "latest",
|
||||||
|
"@freesewing/css-theme": "latest",
|
||||||
|
"@freesewing/i18n": "latest",
|
||||||
|
"@freesewing/models": "latest",
|
||||||
|
"@freesewing/mui-theme": "latest",
|
||||||
|
"@freesewing/pattern-info": "latest",
|
||||||
|
"@freesewing/plugin-bundle": "latest",
|
||||||
|
"@freesewing/plugin-theme": "latest",
|
||||||
|
"@freesewing/plugin-i18n": "latest",
|
||||||
|
"@freesewing/plugin-svgattr": "latest",
|
||||||
|
"@freesewing/utils": "latest",
|
||||||
|
"@material-ui/core": "^4.11.4",
|
||||||
|
"@material-ui/icons": "^4.11.2",
|
||||||
|
"@material-ui/lab": "^v4.0.0-alpha.57",
|
||||||
|
"prismjs": "1.23.0",
|
||||||
|
"react": "^17.0.2",
|
||||||
|
"react-dom": "^17.0.2",
|
||||||
|
"react-intl": "^5.18.0",
|
||||||
|
"react-scripts": "^4.0.3",
|
||||||
|
"file-saver": "^2.0.5",
|
||||||
|
"react-markdown": "6.0.2",
|
||||||
|
"source-map-explorer": "^2.5.2"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"analyze": "source-map-explorer 'build/static/js/*.js'",
|
||||||
|
"size": "source-map-explorer 'build/static/js/*.js' --tsv --no-root",
|
||||||
|
"start": "react-scripts start",
|
||||||
|
"build": "react-scripts build",
|
||||||
|
"test": "react-scripts test",
|
||||||
|
"eject": "react-scripts eject"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": "react-app"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"defaults"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-plugin-prismjs": "2.0.1"
|
||||||
|
}
|
||||||
|
}
|
BIN
packages/yuri/example/public/favicon.ico
Normal file
BIN
packages/yuri/example/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
41
packages/yuri/example/public/index.html
Normal file
41
packages/yuri/example/public/index.html
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||||
|
<link rel="stylesheet" href="layout.css">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="theme-color" content="#000000">
|
||||||
|
<!--
|
||||||
|
manifest.json provides metadata used when your web app is added to the
|
||||||
|
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||||
|
-->
|
||||||
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||||
|
<!--
|
||||||
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
|
Only files inside the `public` folder can be referenced from the HTML.
|
||||||
|
|
||||||
|
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||||
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
|
-->
|
||||||
|
<title>yuri</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
You need to enable JavaScript to run this app.
|
||||||
|
</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
<!--
|
||||||
|
This HTML file is a template.
|
||||||
|
If you open it directly in the browser, you will see an empty page.
|
||||||
|
|
||||||
|
You can add webfonts, meta tags, or analytics to this file.
|
||||||
|
The build step will place the bundled scripts into the <body> tag.
|
||||||
|
|
||||||
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
|
To create a production bundle, use `npm run build` or `yarn build`.
|
||||||
|
-->
|
||||||
|
</body>
|
||||||
|
</html>
|
1
packages/yuri/example/public/layout.css
Normal file
1
packages/yuri/example/public/layout.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
div.layout-wrapper{width:100%;margin:0;padding:0;background-color:red;background:#f8f9fa;background:linear-gradient(90deg, #f1f3f5 0%, #f1f3f5 25%, #f8f9fa 26%, #f8f9fa 100%)}div.layout-wrapper div.layout{display:flex;max-width:1600px;margin:auto;padding:0;flex-direction:row;flex-wrap:nowrap;justify-content:space-between;background-color:#f8f9fa;min-height:calc(100vh - 64px)}div.layout-wrapper div.layout>aside{width:33%;background:#f1f3f5;border-right:2px solid #dee2e6}div.layout-wrapper div.layout>section{margin:0;padding:1rem}div.layout-wrapper div.layout>section>div.content{max-width:66ch;min-width:340px}div.layout-wrapper div.layout>section>div.content.wide{max-width:100%;margin:auto}.theme-wrapper.dark header{background-color:#1a1d21}.theme-wrapper.dark div.layout-wrapper{background:#f8f9fa;background:linear-gradient(90deg, #1a1d21 0%, #1a1d21 25%, #212529 26%, #212529 100%)}.theme-wrapper.dark div.layout-wrapper div.layout{background-color:#212529}.theme-wrapper.dark div.layout-wrapper div.layout>aside{background-color:#1a1d21;border-right:2px solid #343a40}header a svg{color:#ced4da}header a:first-of-type svg{color:#f8f9fa}header a:hover svg{color:#b197fc}header a span,header button span{color:#ced4da}header a span svg,header button span svg{color:#dee2e6}header a:hover span,header button:hover span{color:#f8f9fa}header a:hover span svg,header button:hover span svg{color:#b197fc}header a,header button{padding:0 1vw !important}@media (min-width: 1200px){div.layout>section{width:63%}}@media (max-width: 1199px) and (min-width: 960px){div.layout>aside{width:298px}div.layout>section{width:calc(100% - 300px - 4rem);max-width:none;margin:0 1rem 0 3rem}}@media (max-width: 959px){div.layout>aside{width:218px}div.layout>section{width:calc(100% - 220px - 4rem);max-width:none;margin:0;padding:0 2rem}div.layout>section div.content{min-width:inherit}}@media (max-width: 599px){div.layout>aside{display:none}div.layout>section{width:calc(100%);margin:0 auto;padding:0 1.5rem;max-width:none}}div.gatsby-highlight{margin-bottom:1rem}@media (max-width: 599px){#mobile-menu{position:fixed;top:0;left:0;width:100%;height:100vh;padding:0 0 1rem;max-width:600px;z-index:-10;transition:opacity 0.25s ease 0s;opacity:0;overflow:scroll}#mobile-menu>ul,#mobile-menu>div{transform:translate(0px, 10px);transition:transform 0.25s ease 0s}.theme-wrapper.show-menu #mobile-menu{opacity:1;z-index:10}.theme-wrapper.show-menu #mobile-menu>div{transform:translate(0px, 0px)}}.theme-wrapper.light div.draft-ui-menu,.theme-wrapper.light div.menu{background:#f1f3f5}.theme-wrapper.dark div.draft-ui-menu,.theme-wrapper.dark div.menu{background:#343a40}.theme-wrapper.show-menu div.menu{opacity:1;z-index:10}.theme-wrapper.show-menu div.menu>div{transform:translate(0px, 0px)}div.spaced-buttons>button{margin:0 0.5rem 0.5rem 0}div.spaced>*{margin:0 0.5rem 0.5rem 0}ul#pre-main-menu{margin:0;padding:0}.boldish{font-weight:500}.freesewing.draft{padding:1rem}li.action{clear:both}li.action span.MuiSwitch-root{float:right}.theme-wrapper.light ul#draft-config li.action.toggle.off,.theme-wrapper.dark ul#draft-config li.action.toggle.off{color:#868e96}.theme-wrapper.light ul#draft-config li.action.toggle.off>span svg,.theme-wrapper.dark ul#draft-config li.action.toggle.off>span svg{color:#868e96}footer{background-color:#1a1d21;color:#adb5bd;padding:3rem 0 6rem}footer a{color:#dee2e6 !important;font-weight:400}footer a:hover{color:#d0bfff !important}footer div.cols{display:flex;flex-direction:row;justify-content:space-between;max-width:1600px;margin:auto;padding:0 1.5rem}footer div.cols>div{min-width:150px;max-width:calc(20% - 4rem);padding:0 2rem 0 0;width:100%}footer ul{text-align:left;font-size:1.1rem;margin:0;padding:0;width:100%}footer ul li:first-of-type{padding:0.35rem 0.75rem}footer ul li{display:block}footer ul li a:hover{text-decoration:none !important}footer ul li.heading{font-weight:bold;border-bottom:3px solid #adb5bd;margin-bottom:0.5rem}@media (min-width: 1200px){footer div.cols>div:last-of-type{min-width:350px}}@media (min-width: 600px) and (max-width: 959px){footer div.cols{flex-wrap:wrap}footer div.cols>div{width:calc(30% - 4rem);padding:0 1rem}}@media (max-width: 599px){footer div.cols{display:block}footer div.cols>div{margin:2rem auto 0;max-width:calc(100% - 4rem)}footer div.cols>div:first-of-type{margin-top:0}}
|
15
packages/yuri/example/public/manifest.json
Normal file
15
packages/yuri/example/public/manifest.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"short_name": "yuri",
|
||||||
|
"name": "yuri",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
|
"type": "image/x-icon"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": ".",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
45
packages/yuri/example/src/App.js
Normal file
45
packages/yuri/example/src/App.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import React from 'react'
|
||||||
|
import freesewing from '@freesewing/core'
|
||||||
|
import Workbench from '@freesewing/components/Workbench'
|
||||||
|
import '@freesewing/css-theme'
|
||||||
|
import Pattern from './pattern/src/index.js'
|
||||||
|
/*
|
||||||
|
* The following symlink is required to make this import work:
|
||||||
|
* `root_folder/example/src/pattern => `../../`
|
||||||
|
*
|
||||||
|
* Without it, we can't import the pattern as a local file
|
||||||
|
* since create-react-app does not allow imports outside ./src
|
||||||
|
* If it's imported as a dependency, webpack will cache the
|
||||||
|
* build and there will be no hot-reloading of changes
|
||||||
|
*/
|
||||||
|
|
||||||
|
const App = (props) => {
|
||||||
|
// You can use this to add translations
|
||||||
|
/*
|
||||||
|
let translations = {
|
||||||
|
JSON: 'JSON',
|
||||||
|
someOtherString: 'Some other string that needs translation'
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Adds support for loading an external pattern configuration
|
||||||
|
let recreate = false
|
||||||
|
if (window) recreate = window.location.pathname.substr(1).split('/')
|
||||||
|
if (recreate.length === 3 && recreate[0] === 'recreate') {
|
||||||
|
recreate = { from: recreate[1], id: recreate[2] }
|
||||||
|
} else {
|
||||||
|
recreate = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Workbench
|
||||||
|
freesewing={freesewing}
|
||||||
|
Pattern={Pattern}
|
||||||
|
userLanguage="en"
|
||||||
|
recreate={recreate}
|
||||||
|
// translations={translations}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App
|
9
packages/yuri/example/src/App.test.js
Normal file
9
packages/yuri/example/src/App.test.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom'
|
||||||
|
import App from './App'
|
||||||
|
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const div = document.createElement('div')
|
||||||
|
ReactDOM.render(<App />, div)
|
||||||
|
ReactDOM.unmountComponentAtNode(div)
|
||||||
|
})
|
12
packages/yuri/example/src/index.js
Normal file
12
packages/yuri/example/src/index.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom'
|
||||||
|
import App from './App'
|
||||||
|
import * as serviceWorker from './serviceWorker'
|
||||||
|
import './layout.css'
|
||||||
|
|
||||||
|
ReactDOM.render(<App />, document.getElementById('root'))
|
||||||
|
|
||||||
|
// If you want your app to work offline and load faster, you can change
|
||||||
|
// unregister() to register() below. Note this comes with some pitfalls.
|
||||||
|
// Learn more about service workers: http://bit.ly/CRA-PWA
|
||||||
|
serviceWorker.unregister()
|
213
packages/yuri/example/src/layout.css
Normal file
213
packages/yuri/example/src/layout.css
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.MuiToolbar-root {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
div.layout-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #f8f9fa;
|
||||||
|
background: linear-gradient(90deg, #f1f3f5 0%, #f1f3f5 25%, #f8f9fa 26%, #f8f9fa 100%); }
|
||||||
|
div.layout-wrapper div.layout {
|
||||||
|
display: flex;
|
||||||
|
max-width: 1600px;
|
||||||
|
margin: auto;
|
||||||
|
padding: 0;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
min-height: calc(100vh - 64px); }
|
||||||
|
div.layout-wrapper div.layout > aside {
|
||||||
|
width: 33%;
|
||||||
|
background: #f1f3f5;
|
||||||
|
border-right: 2px solid #dee2e6; }
|
||||||
|
div.layout-wrapper div.layout > section {
|
||||||
|
margin: 0;
|
||||||
|
padding: 1rem; }
|
||||||
|
div.layout-wrapper div.layout > section > div.content {
|
||||||
|
max-width: 66ch;
|
||||||
|
min-width: 340px; }
|
||||||
|
div.layout-wrapper div.layout > section > div.content.wide {
|
||||||
|
max-width: 100%;
|
||||||
|
margin: auto; }
|
||||||
|
|
||||||
|
.theme-wrapper.dark header {
|
||||||
|
background-color: #1a1d21; }
|
||||||
|
|
||||||
|
.theme-wrapper.dark div.layout-wrapper {
|
||||||
|
background: #f8f9fa;
|
||||||
|
background: linear-gradient(90deg, #1a1d21 0%, #1a1d21 25%, #212529 26%, #212529 100%); }
|
||||||
|
.theme-wrapper.dark div.layout-wrapper div.layout {
|
||||||
|
background-color: #212529; }
|
||||||
|
.theme-wrapper.dark div.layout-wrapper div.layout > aside {
|
||||||
|
background-color: #1a1d21;
|
||||||
|
border-right: 2px solid #343a40; }
|
||||||
|
|
||||||
|
/* monitor */
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
div.layout > section {
|
||||||
|
width: 63%; } }
|
||||||
|
|
||||||
|
/* slate */
|
||||||
|
@media (max-width: 1199px) and (min-width: 960px) {
|
||||||
|
div.layout > aside {
|
||||||
|
width: 298px; }
|
||||||
|
div.layout > section {
|
||||||
|
width: calc(100% - 300px - 4rem);
|
||||||
|
max-width: none;
|
||||||
|
margin: 0 1rem 0 3rem; } }
|
||||||
|
|
||||||
|
/* tablet */
|
||||||
|
@media (max-width: 959px) {
|
||||||
|
div.layout > aside {
|
||||||
|
width: 218px; }
|
||||||
|
div.layout > section {
|
||||||
|
width: calc(100% - 220px - 4rem);
|
||||||
|
max-width: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 2rem; }
|
||||||
|
div.layout > section div.content {
|
||||||
|
min-width: inherit; } }
|
||||||
|
|
||||||
|
/* mobile */
|
||||||
|
@media (max-width: 599px) {
|
||||||
|
div.layout > aside {
|
||||||
|
display: none; }
|
||||||
|
div.layout > section {
|
||||||
|
width: calc(100%);
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
max-width: none; } }
|
||||||
|
|
||||||
|
div.gatsby-highlight {
|
||||||
|
margin-bottom: 1rem; }
|
||||||
|
|
||||||
|
@media (max-width: 599px) {
|
||||||
|
#mobile-menu {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
padding: 0 0 1rem;
|
||||||
|
max-width: 600px;
|
||||||
|
z-index: -10;
|
||||||
|
transition: opacity 0.25s ease 0s;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: scroll; }
|
||||||
|
#mobile-menu > ul,
|
||||||
|
#mobile-menu > div {
|
||||||
|
transform: translate(0px, 10px);
|
||||||
|
transition: transform 0.25s ease 0s; }
|
||||||
|
.theme-wrapper.show-menu #mobile-menu {
|
||||||
|
opacity: 1;
|
||||||
|
z-index: 10; }
|
||||||
|
.theme-wrapper.show-menu #mobile-menu > div {
|
||||||
|
transform: translate(0px, 0px); } }
|
||||||
|
|
||||||
|
.theme-wrapper.light div.draft-ui-menu,
|
||||||
|
.theme-wrapper.light div.menu {
|
||||||
|
background: #f1f3f5; }
|
||||||
|
|
||||||
|
.theme-wrapper.dark div.draft-ui-menu,
|
||||||
|
.theme-wrapper.dark div.menu {
|
||||||
|
background: #343a40; }
|
||||||
|
|
||||||
|
.theme-wrapper.show-menu div.menu {
|
||||||
|
opacity: 1;
|
||||||
|
z-index: 10; }
|
||||||
|
.theme-wrapper.show-menu div.menu > div {
|
||||||
|
transform: translate(0px, 0px); }
|
||||||
|
|
||||||
|
div.spaced-buttons > button {
|
||||||
|
margin: 0 0.5rem 0.5rem 0; }
|
||||||
|
|
||||||
|
div.spaced > * {
|
||||||
|
margin: 0 0.5rem 0.5rem 0; }
|
||||||
|
|
||||||
|
ul#pre-main-menu {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0; }
|
||||||
|
|
||||||
|
.boldish {
|
||||||
|
font-weight: 500; }
|
||||||
|
|
||||||
|
.freesewing.draft {
|
||||||
|
padding: 1rem; }
|
||||||
|
|
||||||
|
li.action {
|
||||||
|
clear: both; }
|
||||||
|
|
||||||
|
li.action span.MuiSwitch-root {
|
||||||
|
float: right; }
|
||||||
|
|
||||||
|
.theme-wrapper.light ul#draft-config li.action.toggle.off,
|
||||||
|
.theme-wrapper.dark ul#draft-config li.action.toggle.off {
|
||||||
|
color: #868e96; }
|
||||||
|
.theme-wrapper.light ul#draft-config li.action.toggle.off > span svg,
|
||||||
|
.theme-wrapper.dark ul#draft-config li.action.toggle.off > span svg {
|
||||||
|
color: #868e96; }
|
||||||
|
|
||||||
|
footer {
|
||||||
|
background-color: #1a1d21;
|
||||||
|
color: #adb5bd;
|
||||||
|
padding: 3rem 0 6rem; }
|
||||||
|
footer a {
|
||||||
|
color: #dee2e6 !important;
|
||||||
|
font-weight: 400; }
|
||||||
|
footer a:hover {
|
||||||
|
color: #d0bfff !important; }
|
||||||
|
footer div.cols {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
max-width: 1600px;
|
||||||
|
margin: auto;
|
||||||
|
padding: 0 1.5rem; }
|
||||||
|
footer div.cols > div {
|
||||||
|
min-width: 150px;
|
||||||
|
max-width: calc(20% - 4rem);
|
||||||
|
padding: 0 2rem 0 0;
|
||||||
|
width: 100%; }
|
||||||
|
footer ul {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%; }
|
||||||
|
footer ul li:first-of-type {
|
||||||
|
padding: 0.35rem 0.75rem; }
|
||||||
|
footer ul li {
|
||||||
|
display: block; }
|
||||||
|
footer ul li a:hover {
|
||||||
|
text-decoration: none !important; }
|
||||||
|
footer ul li.heading {
|
||||||
|
font-weight: bold;
|
||||||
|
border-bottom: 3px solid #adb5bd;
|
||||||
|
margin-bottom: 0.5rem; }
|
||||||
|
|
||||||
|
/* XL screens */
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
footer div.cols > div:last-of-type {
|
||||||
|
min-width: 350px; } }
|
||||||
|
|
||||||
|
/* SM screens */
|
||||||
|
@media (min-width: 600px) and (max-width: 959px) {
|
||||||
|
footer div.cols {
|
||||||
|
flex-wrap: wrap; }
|
||||||
|
footer div.cols > div {
|
||||||
|
width: calc(30% - 4rem);
|
||||||
|
padding: 0 1rem; } }
|
||||||
|
|
||||||
|
/* XS screens */
|
||||||
|
@media (max-width: 599px) {
|
||||||
|
footer div.cols {
|
||||||
|
display: block; }
|
||||||
|
footer div.cols > div {
|
||||||
|
margin: 2rem auto 0;
|
||||||
|
max-width: calc(100% - 4rem); }
|
||||||
|
footer div.cols > div:first-of-type {
|
||||||
|
margin-top: 0; } }
|
284
packages/yuri/example/src/layout.scss
Normal file
284
packages/yuri/example/src/layout.scss
Normal file
|
@ -0,0 +1,284 @@
|
||||||
|
@import '../../../../../../node_modules/open-color/open-color.scss';
|
||||||
|
|
||||||
|
// Global style overrides
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.MuiToolbar-root {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main page content layout
|
||||||
|
div.layout-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: $oc-gray-0;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
$oc-gray-1 0%,
|
||||||
|
$oc-gray-1 25%,
|
||||||
|
$oc-gray-0 26%,
|
||||||
|
$oc-gray-0 100%
|
||||||
|
);
|
||||||
|
div.layout {
|
||||||
|
display: flex;
|
||||||
|
max-width: 1600px;
|
||||||
|
margin: auto;
|
||||||
|
padding: 0;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
background-color: $oc-gray-0;
|
||||||
|
min-height: calc(100vh - 64px);
|
||||||
|
> aside {
|
||||||
|
width: 33%;
|
||||||
|
background: $oc-gray-1;
|
||||||
|
border-right: 2px solid $oc-gray-3;
|
||||||
|
}
|
||||||
|
> section {
|
||||||
|
margin: 0;
|
||||||
|
padding: 1rem;
|
||||||
|
> div.content {
|
||||||
|
max-width: 66ch;
|
||||||
|
min-width: 340px;
|
||||||
|
}
|
||||||
|
> div.content.wide {
|
||||||
|
max-width: 100%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.theme-wrapper.dark {
|
||||||
|
header {
|
||||||
|
background-color: darken($oc-gray-9, 3);
|
||||||
|
}
|
||||||
|
div.layout-wrapper {
|
||||||
|
background: $oc-gray-0;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
darken($oc-gray-9, 3) 0%,
|
||||||
|
darken($oc-gray-9, 3) 25%,
|
||||||
|
$oc-gray-9 26%,
|
||||||
|
$oc-gray-9 100%
|
||||||
|
);
|
||||||
|
div.layout {
|
||||||
|
background-color: $oc-gray-9;
|
||||||
|
> aside {
|
||||||
|
background-color: darken($oc-gray-9, 3);
|
||||||
|
border-right: 2px solid $oc-gray-8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* monitor */
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
div.layout > section {
|
||||||
|
width: 63%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* slate */
|
||||||
|
@media (max-width: 1199px) and (min-width: 960px) {
|
||||||
|
div.layout {
|
||||||
|
> aside {
|
||||||
|
width: 298px; // 2px border
|
||||||
|
}
|
||||||
|
> section {
|
||||||
|
width: calc(100% - 300px - 4rem);
|
||||||
|
max-width: none;
|
||||||
|
margin: 0 1rem 0 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tablet */
|
||||||
|
@media (max-width: 959px) {
|
||||||
|
div.layout {
|
||||||
|
> aside {
|
||||||
|
width: 218px; // 2px border
|
||||||
|
}
|
||||||
|
> section {
|
||||||
|
width: calc(100% - 220px - 4rem);
|
||||||
|
max-width: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 2rem;
|
||||||
|
div.content {
|
||||||
|
min-width: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* mobile */
|
||||||
|
@media (max-width: 599px) {
|
||||||
|
div.layout {
|
||||||
|
> aside {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
> section {
|
||||||
|
width: calc(100%);
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Candidates for theme inclusion
|
||||||
|
div.gatsby-highlight {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 599px) {
|
||||||
|
#mobile-menu {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
padding: 0 0 1rem;
|
||||||
|
max-width: 600px;
|
||||||
|
z-index: -10;
|
||||||
|
transition: opacity 0.25s ease 0s;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: scroll;
|
||||||
|
> ul,
|
||||||
|
> div {
|
||||||
|
transform: translate(0px, 10px);
|
||||||
|
transition: transform 0.25s ease 0s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.theme-wrapper.show-menu #mobile-menu {
|
||||||
|
opacity: 1;
|
||||||
|
z-index: 10;
|
||||||
|
> div {
|
||||||
|
transform: translate(0px, 0px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-wrapper.light div.draft-ui-menu,
|
||||||
|
.theme-wrapper.light div.menu {
|
||||||
|
background: $oc-gray-1;
|
||||||
|
}
|
||||||
|
.theme-wrapper.dark div.draft-ui-menu,
|
||||||
|
.theme-wrapper.dark div.menu {
|
||||||
|
background: $oc-gray-8;
|
||||||
|
}
|
||||||
|
.theme-wrapper.show-menu div.menu {
|
||||||
|
opacity: 1;
|
||||||
|
z-index: 10;
|
||||||
|
> div {
|
||||||
|
transform: translate(0px, 0px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.spaced-buttons > button {
|
||||||
|
margin: 0 0.5rem 0.5rem 0;
|
||||||
|
}
|
||||||
|
div.spaced > * {
|
||||||
|
margin: 0 0.5rem 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#pre-main-menu {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.boldish {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.freesewing.draft {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
li.action {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
li.action span.MuiSwitch-root {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.theme-wrapper.light ul#draft-config li.action.toggle.off,
|
||||||
|
.theme-wrapper.dark ul#draft-config li.action.toggle.off {
|
||||||
|
color: $oc-gray-6;
|
||||||
|
> span svg {
|
||||||
|
color: $oc-gray-6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
background-color: #1a1d21;
|
||||||
|
color: #adb5bd;
|
||||||
|
padding: 3rem 0 6rem;
|
||||||
|
a {
|
||||||
|
color: #dee2e6 !important;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #d0bfff !important;
|
||||||
|
}
|
||||||
|
div.cols {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
max-width: 1600px;
|
||||||
|
margin: auto;
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
> div {
|
||||||
|
min-width: 150px;
|
||||||
|
max-width: calc(20% - 4rem);
|
||||||
|
padding: 0 2rem 0 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
li:first-of-type {
|
||||||
|
padding: 0.35rem 0.75rem;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: block;
|
||||||
|
a:hover {
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
li.heading {
|
||||||
|
font-weight: bold;
|
||||||
|
border-bottom: 3px solid #adb5bd;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XL screens */
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
footer div.cols > div:last-of-type {
|
||||||
|
min-width: 350px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* SM screens */
|
||||||
|
@media (min-width: 600px) and (max-width: 959px) {
|
||||||
|
footer div.cols {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
> div {
|
||||||
|
width: calc(30% - 4rem);
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* XS screens */
|
||||||
|
@media (max-width: 599px) {
|
||||||
|
footer div.cols {
|
||||||
|
display: block;
|
||||||
|
> div {
|
||||||
|
margin: 2rem auto 0;
|
||||||
|
max-width: calc(100% - 4rem);
|
||||||
|
}
|
||||||
|
> div:first-of-type {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
packages/yuri/example/src/pattern
Symbolic link
1
packages/yuri/example/src/pattern
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/Users/biou/Projects/yuri
|
123
packages/yuri/example/src/serviceWorker.js
Normal file
123
packages/yuri/example/src/serviceWorker.js
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
// In production, we register a service worker to serve assets from local cache.
|
||||||
|
|
||||||
|
// This lets the app load faster on subsequent visits in production, and gives
|
||||||
|
// it offline capabilities. However, it also means that developers (and users)
|
||||||
|
// will only see deployed updates on the "N+1" visit to a page, since previously
|
||||||
|
// cached resources are updated in the background.
|
||||||
|
|
||||||
|
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
|
||||||
|
// This link also includes instructions on opting out of this behavior.
|
||||||
|
|
||||||
|
const isLocalhost = Boolean(
|
||||||
|
window.location.hostname === 'localhost' ||
|
||||||
|
// [::1] is the IPv6 localhost address.
|
||||||
|
window.location.hostname === '[::1]' ||
|
||||||
|
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||||
|
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
|
||||||
|
)
|
||||||
|
|
||||||
|
export function register(config) {
|
||||||
|
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||||
|
// The URL constructor is available in all browsers that support SW.
|
||||||
|
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
|
||||||
|
if (publicUrl.origin !== window.location.origin) {
|
||||||
|
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||||
|
// from what our page is served on. This might happen if a CDN is used to
|
||||||
|
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
|
||||||
|
|
||||||
|
if (isLocalhost) {
|
||||||
|
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||||
|
checkValidServiceWorker(swUrl, config)
|
||||||
|
|
||||||
|
// Add some additional logging to localhost, pointing developers to the
|
||||||
|
// service worker/PWA documentation.
|
||||||
|
navigator.serviceWorker.ready.then(() => {
|
||||||
|
console.log(
|
||||||
|
'This web app is being served cache-first by a service ' +
|
||||||
|
'worker. To learn more, visit https://goo.gl/SC7cgQ'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Is not local host. Just register service worker
|
||||||
|
registerValidSW(swUrl, config)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerValidSW(swUrl, config) {
|
||||||
|
navigator.serviceWorker
|
||||||
|
.register(swUrl)
|
||||||
|
.then((registration) => {
|
||||||
|
registration.onupdatefound = () => {
|
||||||
|
const installingWorker = registration.installing
|
||||||
|
installingWorker.onstatechange = () => {
|
||||||
|
if (installingWorker.state === 'installed') {
|
||||||
|
if (navigator.serviceWorker.controller) {
|
||||||
|
// At this point, the old content will have been purged and
|
||||||
|
// the fresh content will have been added to the cache.
|
||||||
|
// It's the perfect time to display a "New content is
|
||||||
|
// available; please refresh." message in your web app.
|
||||||
|
console.log('New content is available; please refresh.')
|
||||||
|
|
||||||
|
// Execute callback
|
||||||
|
if (config.onUpdate) {
|
||||||
|
config.onUpdate(registration)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// At this point, everything has been precached.
|
||||||
|
// It's the perfect time to display a
|
||||||
|
// "Content is cached for offline use." message.
|
||||||
|
console.log('Content is cached for offline use.')
|
||||||
|
|
||||||
|
// Execute callback
|
||||||
|
if (config.onSuccess) {
|
||||||
|
config.onSuccess(registration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error during service worker registration:', error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkValidServiceWorker(swUrl, config) {
|
||||||
|
// Check if the service worker can be found. If it can't reload the page.
|
||||||
|
fetch(swUrl)
|
||||||
|
.then((response) => {
|
||||||
|
// Ensure service worker exists, and that we really are getting a JS file.
|
||||||
|
if (
|
||||||
|
response.status === 404 ||
|
||||||
|
response.headers.get('content-type').indexOf('javascript') === -1
|
||||||
|
) {
|
||||||
|
// No service worker found. Probably a different app. Reload the page.
|
||||||
|
navigator.serviceWorker.ready.then((registration) => {
|
||||||
|
registration.unregister().then(() => {
|
||||||
|
window.location.reload()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Service worker found. Proceed as normal.
|
||||||
|
registerValidSW(swUrl, config)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
console.log('No internet connection found. App is running in offline mode.')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unregister() {
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
navigator.serviceWorker.ready.then((registration) => {
|
||||||
|
registration.unregister()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
46218
packages/yuri/package-lock.json
generated
Normal file
46218
packages/yuri/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
67
packages/yuri/package.json
Normal file
67
packages/yuri/package.json
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
{
|
||||||
|
"name": "@biou/yuri",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"author": "hellgy",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "github:biou/yuri",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/biou/yuri/issues"
|
||||||
|
},
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"module": "dist/index.es.js",
|
||||||
|
"jsnext:main": "dist/index.es.js",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12",
|
||||||
|
"npm": ">=6"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "rollup -c",
|
||||||
|
"start": "rollup -c -w",
|
||||||
|
"prepare": "npm run build",
|
||||||
|
"predeploy": "cd example && npm install && npm run build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@freesewing/core": "^2.17.1",
|
||||||
|
"@freesewing/plugin-bundle": "^2.17.1",
|
||||||
|
"@freesewing/brian": "^2.17.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"react": "^17.0.2",
|
||||||
|
"react-dom": "^17.0.2",
|
||||||
|
"@freesewing/core": "latest",
|
||||||
|
"@freesewing/plugin-bundle": "latest",
|
||||||
|
"@freesewing/components": "latest",
|
||||||
|
"@freesewing/css-theme": "latest",
|
||||||
|
"@freesewing/i18n": "latest",
|
||||||
|
"@freesewing/mui-theme": "latest",
|
||||||
|
"@freesewing/plugin-bust": "latest",
|
||||||
|
"@freesewing/plugin-buttons": "latest",
|
||||||
|
"@freesewing/plugin-debug": "latest",
|
||||||
|
"@freesewing/plugin-flip": "latest",
|
||||||
|
"@freesewing/utils": "latest",
|
||||||
|
"react-scripts": "^4.0.3",
|
||||||
|
"webpack": "^5.37.0",
|
||||||
|
"rollup": "^2.48.0",
|
||||||
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
||||||
|
"rollup-plugin-terser": "^7.0.2",
|
||||||
|
"@rollup/plugin-babel": "^5.1.0",
|
||||||
|
"@rollup/plugin-commonjs": "^14.0.0",
|
||||||
|
"@rollup/plugin-url": "^6.0.0",
|
||||||
|
"@rollup/plugin-json": "^4.1.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^13.0.0",
|
||||||
|
"@rollup/plugin-yaml": "^3.0.0",
|
||||||
|
"@material-ui/core": "^4.11.4",
|
||||||
|
"@material-ui/icons": "^4.11.2",
|
||||||
|
"@material-ui/lab": "^4.0.0-alpha.58",
|
||||||
|
"axios": "0.21.1",
|
||||||
|
"react-intl": "5.17.6",
|
||||||
|
"prop-types": "15.7.2",
|
||||||
|
"file-saver": "^2.0.5",
|
||||||
|
"eslint": "^7.27.0",
|
||||||
|
"eslint-config-standard": "^16.0.3",
|
||||||
|
"eslint-config-standard-react": "^11.0.1",
|
||||||
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
"eslint-plugin-promise": "^5.1.0"
|
||||||
|
}
|
||||||
|
}
|
43
packages/yuri/rollup.config.js
Normal file
43
packages/yuri/rollup.config.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import url from '@rollup/plugin-url'
|
||||||
|
import babel from '@rollup/plugin-babel'
|
||||||
|
import resolve from '@rollup/plugin-node-resolve'
|
||||||
|
import commonjs from '@rollup/plugin-commonjs'
|
||||||
|
import json from '@rollup/plugin-json'
|
||||||
|
import { terser } from 'rollup-plugin-terser'
|
||||||
|
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
|
||||||
|
// import postcss from 'rollup-plugin-postcss'
|
||||||
|
import { main, module, name, version, description, author, license } from './package.json'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: 'src/index.js',
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
file: main,
|
||||||
|
format: 'cjs',
|
||||||
|
sourcemap: true,
|
||||||
|
exports: 'default'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: module,
|
||||||
|
format: 'es',
|
||||||
|
sourcemap: true,
|
||||||
|
exports: 'default'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
peerDepsExternal(),
|
||||||
|
// postcss({ modules: true }),
|
||||||
|
url({ exclude: ['**/*.svg'] }),
|
||||||
|
babel({
|
||||||
|
exclude: 'node_modules/**'
|
||||||
|
}),
|
||||||
|
resolve({ browser: true }),
|
||||||
|
json(),
|
||||||
|
commonjs(),
|
||||||
|
terser({
|
||||||
|
output: {
|
||||||
|
preamble: `/**\n * ${name} | v${version}\n * ${description}\n * (c) ${new Date().getFullYear()} ${author}\n * @license ${license}\n */`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
5
packages/yuri/src/.eslintrc
Normal file
5
packages/yuri/src/.eslintrc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"jest": true
|
||||||
|
}
|
||||||
|
}
|
98
packages/yuri/src/back.js
Normal file
98
packages/yuri/src/back.js
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
import { sharedDimensions } from './shared'
|
||||||
|
|
||||||
|
export default function (part) {
|
||||||
|
const {
|
||||||
|
store,
|
||||||
|
macro,
|
||||||
|
Path,
|
||||||
|
Point,
|
||||||
|
points,
|
||||||
|
paths,
|
||||||
|
complete,
|
||||||
|
paperless,
|
||||||
|
sa,
|
||||||
|
options,
|
||||||
|
measurements
|
||||||
|
} = part.shorthand()
|
||||||
|
|
||||||
|
// Clear paths from Brian
|
||||||
|
for (const i in paths) {
|
||||||
|
if (['backArmhole', 'backCollar'].indexOf(i) === -1) delete paths[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shorten body to take ribbing into account
|
||||||
|
if (options.ribbing) {
|
||||||
|
const rh = options.ribbingHeight * (measurements.hpsToWaistBack + measurements.waistToHips)
|
||||||
|
for (const p of ['hem', 'cbHem']) points[p] = points[p].shift(90, rh)
|
||||||
|
store.set('ribbingHeight', rh)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shape side seam
|
||||||
|
points.hips.x = (measurements.hips * (1 + options.hipsEase)) / 4
|
||||||
|
points.hem.x = points.hips.x
|
||||||
|
points.hemCp2 = new Point(points.hips.x, points.cbWaist.y)
|
||||||
|
|
||||||
|
// add some points for Yuri
|
||||||
|
points.cbBottom = new Point(0, points.cbHem.y * 1.27)
|
||||||
|
points.bottom = new Point(points.hem.x * 1.23, points.cbBottom.y * 0.97)
|
||||||
|
points.bottomCp2 = new Point(points.bottom.x, points.cbWaist.y)
|
||||||
|
// end Yuri points
|
||||||
|
|
||||||
|
// Store length of the neck seam
|
||||||
|
store.set(
|
||||||
|
'backNeckSeamLength',
|
||||||
|
new Path().move(points.neck).curve_(points.neckCp2, points.cbNeck).length()
|
||||||
|
)
|
||||||
|
store.set(
|
||||||
|
'neckCutoutBack',
|
||||||
|
points.cbNeck.y
|
||||||
|
)
|
||||||
|
|
||||||
|
console.log(points.bottom)
|
||||||
|
// Paths
|
||||||
|
paths.gussetBase = new Path().move(points.bottom).line(points.armhole).attr('class', 'note stroke-xxl')
|
||||||
|
store.set('gussetLength', paths.gussetBase.length())
|
||||||
|
paths.saBase = new Path()
|
||||||
|
.move(points.armhole)
|
||||||
|
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
|
||||||
|
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
|
||||||
|
.join(paths.backArmhole)
|
||||||
|
.line(points.s3CollarSplit)
|
||||||
|
.join(paths.backCollar)
|
||||||
|
.attr('class', 'note stroke-xxl')
|
||||||
|
paths.hemBase = new Path().move(points.cbBottom).line(points.bottom).attr('class', 'note stroke-xxl')
|
||||||
|
paths.gussetBase.render = false
|
||||||
|
paths.saBase.render = false
|
||||||
|
paths.hemBase.render = false
|
||||||
|
|
||||||
|
paths.seam = paths.gussetBase.join(paths.saBase)
|
||||||
|
.clone()
|
||||||
|
.line(points.cbBottom)
|
||||||
|
.join(paths.hemBase)
|
||||||
|
.close()
|
||||||
|
.attr('class', 'fabric')
|
||||||
|
|
||||||
|
// Complete?
|
||||||
|
if (complete) {
|
||||||
|
macro('cutonfold', {
|
||||||
|
from: points.cbNeck,
|
||||||
|
to: points.cbBottom,
|
||||||
|
grainline: true
|
||||||
|
})
|
||||||
|
macro('scalebox', { at: new Point(points.armholePitch.x / 2, points.cbWaist.y) })
|
||||||
|
if (sa) {
|
||||||
|
paths.sa = paths.hemBase.offset(options.ribbing ? sa : 3 * sa).join(paths.saBase.offset(sa))
|
||||||
|
paths.sa
|
||||||
|
.move(paths.sa.end())
|
||||||
|
.line(points.cbNeck)
|
||||||
|
.move(paths.sa.start())
|
||||||
|
.line(points.cbBottom)
|
||||||
|
.attr('class', 'fabric sa')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paperless?
|
||||||
|
if (paperless) sharedDimensions(part, 'back')
|
||||||
|
|
||||||
|
return part
|
||||||
|
}
|
19
packages/yuri/src/cuff.js
Normal file
19
packages/yuri/src/cuff.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { draftRibbing } from './shared'
|
||||||
|
|
||||||
|
export default (part) => {
|
||||||
|
const { complete, points, measurements, options, macro } = part.shorthand()
|
||||||
|
if (!options.ribbing) return part
|
||||||
|
|
||||||
|
draftRibbing(part, measurements.wrist * (1 + options.cuffEase) * (1 - options.ribbingStretch))
|
||||||
|
|
||||||
|
// Complete pattern?
|
||||||
|
if (complete) {
|
||||||
|
macro('title', {
|
||||||
|
at: points.title,
|
||||||
|
nr: 7,
|
||||||
|
title: 'cuff'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return part
|
||||||
|
}
|
90
packages/yuri/src/front.js
Normal file
90
packages/yuri/src/front.js
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
import { sharedDimensions } from './shared'
|
||||||
|
|
||||||
|
export default function (part) {
|
||||||
|
const {
|
||||||
|
store,
|
||||||
|
Point,
|
||||||
|
Path,
|
||||||
|
points,
|
||||||
|
paths,
|
||||||
|
complete,
|
||||||
|
paperless,
|
||||||
|
sa,
|
||||||
|
options,
|
||||||
|
measurements,
|
||||||
|
macro
|
||||||
|
} = part.shorthand()
|
||||||
|
|
||||||
|
// Clear paths from Brian
|
||||||
|
for (const i in paths) {
|
||||||
|
if (['frontArmhole', 'frontCollar'].indexOf(i) === -1) delete paths[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shorten body to take ribbing into account
|
||||||
|
if (options.ribbing) {
|
||||||
|
for (const p of ['hem', 'cfHem']) points[p] = points[p].shift(90, store.get('ribbingHeight'))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shape side seam
|
||||||
|
points.hips.x = (measurements.hips * (1 + options.hipsEase)) / 4
|
||||||
|
points.hem.x = points.hips.x
|
||||||
|
points.hemCp2 = new Point(points.hips.x, points.cfWaist.y)
|
||||||
|
|
||||||
|
// add some points for Yuri
|
||||||
|
points.cfBottom = new Point(0, points.cfHem.y * 1.27)
|
||||||
|
points.bottom = new Point(points.hem.x * 1.23, points.cfBottom.y * 0.97)
|
||||||
|
points.bottomCp2 = new Point(points.bottom.x, points.cfWaist.y)
|
||||||
|
points.button = new Point(points.s3CollarSplit.x - 2 / 3 * measurements.shoulderToShoulder, points.s3CollarSplit.y + measurements.hpsToBust * 1.17)
|
||||||
|
// end Yuri points
|
||||||
|
|
||||||
|
// Store length of the neck seam
|
||||||
|
store.set(
|
||||||
|
'frontNeckSeamLength',
|
||||||
|
new Path()
|
||||||
|
.move(points.neck)
|
||||||
|
.curve(points.neckCp2Front, points.cfNeckCp1, points.cfNeck)
|
||||||
|
.length()
|
||||||
|
)
|
||||||
|
store.set(
|
||||||
|
'neckCutoutFront',
|
||||||
|
points.cfNeck.y
|
||||||
|
)
|
||||||
|
|
||||||
|
// Paths
|
||||||
|
paths.saBase = new Path()
|
||||||
|
.move(points.bottom)
|
||||||
|
.line(points.armhole)
|
||||||
|
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
|
||||||
|
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
|
||||||
|
.join(paths.frontArmhole)
|
||||||
|
.line(points.s3CollarSplit)
|
||||||
|
.attr('class', 'note stroke-xxl')
|
||||||
|
paths.buttonBase = new Path()
|
||||||
|
.move(points.s3CollarSplit)
|
||||||
|
.line(points.button)
|
||||||
|
.line(points.cfBottom)
|
||||||
|
.attr('class', 'note stroke-xxl')
|
||||||
|
paths.hemBase = new Path().move(points.cfBottom).line(points.bottom).attr('class', 'note stroke-xxl')
|
||||||
|
paths.saBase.render = false
|
||||||
|
paths.hemBase.render = false
|
||||||
|
paths.buttonBase.render = false
|
||||||
|
|
||||||
|
paths.seam = paths.saBase.clone().join(paths.buttonBase).join(paths.hemBase).close().attr('class', 'fabric')
|
||||||
|
|
||||||
|
// Complete?
|
||||||
|
if (complete) {
|
||||||
|
macro('grainline', {
|
||||||
|
from: points.s3CollarSplit,
|
||||||
|
to: new Point(points.s3CollarSplit.x, points.bottom.y)
|
||||||
|
})
|
||||||
|
if (sa) {
|
||||||
|
paths.sa = paths.hemBase.offset(options.ribbing ? sa : 3 * sa).join(paths.saBase.offset(sa)).join(paths.buttonBase.offset(3 * sa))
|
||||||
|
paths.sa = paths.sa.line(paths.sa.start()).close().attr('class', 'fabric sa')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paperless?
|
||||||
|
if (paperless) sharedDimensions(part, 'front')
|
||||||
|
|
||||||
|
return part
|
||||||
|
}
|
71
packages/yuri/src/gusset.js
Normal file
71
packages/yuri/src/gusset.js
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
export default function (part) {
|
||||||
|
const {
|
||||||
|
Point,
|
||||||
|
Path,
|
||||||
|
points,
|
||||||
|
paths,
|
||||||
|
Snippet,
|
||||||
|
snippets,
|
||||||
|
complete,
|
||||||
|
sa,
|
||||||
|
paperless,
|
||||||
|
macro,
|
||||||
|
store
|
||||||
|
} = part.shorthand()
|
||||||
|
|
||||||
|
const w = store.get('gussetLength')
|
||||||
|
points.top = new Point(0, 0)
|
||||||
|
points.bottom = new Point(0, w)
|
||||||
|
points.right = points.bottom.rotate(33.0, points.top)
|
||||||
|
points.cp1 = new Point(0, w * 6 / 5).rotate(90, points.bottom)
|
||||||
|
points.cp2 = new Point(points.right.x, points.right.y * 6 / 5).rotate(-60, points.right)
|
||||||
|
points.title = new Point(0, 2 * w / 3).rotate(15, points.top)
|
||||||
|
|
||||||
|
paths.hat = new Path()
|
||||||
|
.move(points.right)
|
||||||
|
.line(points.top)
|
||||||
|
.line(points.bottom)
|
||||||
|
.attr('class', 'fabric')
|
||||||
|
|
||||||
|
paths.curve = new Path()
|
||||||
|
.move(points.bottom)
|
||||||
|
.curve(points.cp1, points.cp2, points.right)
|
||||||
|
.attr('class', 'fabric')
|
||||||
|
|
||||||
|
paths.seam = paths.hat.join(paths.curve)
|
||||||
|
|
||||||
|
// Complete?
|
||||||
|
if (complete) {
|
||||||
|
macro('cutonfold', {
|
||||||
|
from: new Point(points.top.x, points.top.y + 50),
|
||||||
|
to: points.bottom,
|
||||||
|
grainline: true
|
||||||
|
})
|
||||||
|
macro('title', {
|
||||||
|
at: points.title,
|
||||||
|
nr: 4,
|
||||||
|
title: 'gusset'
|
||||||
|
})
|
||||||
|
points.logo = points.title.shift(-75, 100)
|
||||||
|
snippets.logo = new Snippet('logo', points.logo)
|
||||||
|
if (sa) {
|
||||||
|
paths.sa = paths.hat.offset(sa).join(paths.curve.offset(3 * sa)).attr('class', 'fabric sa')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paperless?
|
||||||
|
if (paperless) {
|
||||||
|
macro('hd', {
|
||||||
|
from: points.bottomLeft,
|
||||||
|
to: points.bottomRight,
|
||||||
|
y: points.bottomLeft.y + sa + 15
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.bottomRight,
|
||||||
|
to: points.topRight,
|
||||||
|
x: points.topRight.x + sa + 15
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return part
|
||||||
|
}
|
82
packages/yuri/src/hoodcenter.js
Normal file
82
packages/yuri/src/hoodcenter.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
export default function (part) {
|
||||||
|
const {
|
||||||
|
store,
|
||||||
|
sa,
|
||||||
|
Point,
|
||||||
|
points,
|
||||||
|
Path,
|
||||||
|
paths,
|
||||||
|
complete,
|
||||||
|
paperless,
|
||||||
|
macro,
|
||||||
|
units
|
||||||
|
} = part.shorthand()
|
||||||
|
|
||||||
|
const width = store.get('hoodCenterWidth')
|
||||||
|
const length = complete ? width * 2.5 : store.get('hoodCenterLength')
|
||||||
|
points.topLeft = new Point(0, 0)
|
||||||
|
points.bottomLeft = new Point(0, width)
|
||||||
|
points.topMidLeft = new Point(width, 0)
|
||||||
|
points.bottomMidLeft = new Point(width, width)
|
||||||
|
points.topMidRight = new Point(width * 1.5, 0)
|
||||||
|
points.bottomMidRight = new Point(width * 1.5, width)
|
||||||
|
points.topRight = new Point(length, 0)
|
||||||
|
points.bottomRight = new Point(length, width)
|
||||||
|
|
||||||
|
if (complete) {
|
||||||
|
paths.seam = new Path()
|
||||||
|
.move(points.topMidLeft)
|
||||||
|
.line(points.topLeft)
|
||||||
|
.line(points.bottomLeft)
|
||||||
|
.line(points.bottomMidLeft)
|
||||||
|
.move(points.bottomMidRight)
|
||||||
|
.line(points.bottomRight)
|
||||||
|
.line(points.topRight)
|
||||||
|
.line(points.topMidRight)
|
||||||
|
.attr('class', 'fabric')
|
||||||
|
paths.hint = new Path()
|
||||||
|
.move(points.topMidLeft)
|
||||||
|
.line(points.topMidRight)
|
||||||
|
.move(points.bottomMidLeft)
|
||||||
|
.line(points.bottomMidRight)
|
||||||
|
.attr('class', 'fabric dashed')
|
||||||
|
} else {
|
||||||
|
paths.seam = new Path()
|
||||||
|
.move(points.topLeft)
|
||||||
|
.line(points.bottomLeft)
|
||||||
|
.line(points.bottomRight)
|
||||||
|
.line(points.topRight)
|
||||||
|
.close()
|
||||||
|
.attr('class', 'fabric')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete pattern?
|
||||||
|
if (complete) {
|
||||||
|
if (sa) {
|
||||||
|
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
|
||||||
|
}
|
||||||
|
points.title = points.bottomLeft.shiftFractionTowards(points.topRight, 0.5)
|
||||||
|
macro('title', { at: points.title, nr: 6, title: 'hoodCenter' })
|
||||||
|
macro('grainline', {
|
||||||
|
from: points.topLeft.shift(-90, width / 2),
|
||||||
|
to: points.topRight.shift(-90, width / 2)
|
||||||
|
})
|
||||||
|
// Always include this dimension as we don't print the entire part
|
||||||
|
macro('hd', {
|
||||||
|
from: points.bottomLeft,
|
||||||
|
to: points.bottomRight,
|
||||||
|
y: points.bottomRight.y + sa + 15,
|
||||||
|
text: units(store.get('hoodCenterLength'))
|
||||||
|
})
|
||||||
|
// Paperless?
|
||||||
|
if (paperless) {
|
||||||
|
macro('vd', {
|
||||||
|
from: points.bottomRight,
|
||||||
|
to: points.topRight,
|
||||||
|
x: points.topRight.x + sa + 15
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return part
|
||||||
|
}
|
149
packages/yuri/src/hoodside.js
Normal file
149
packages/yuri/src/hoodside.js
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
export default function (part) {
|
||||||
|
const {
|
||||||
|
store,
|
||||||
|
sa,
|
||||||
|
Point,
|
||||||
|
points,
|
||||||
|
Path,
|
||||||
|
paths,
|
||||||
|
Snippet,
|
||||||
|
snippets,
|
||||||
|
measurements,
|
||||||
|
complete,
|
||||||
|
paperless,
|
||||||
|
macro
|
||||||
|
} = part.shorthand()
|
||||||
|
|
||||||
|
const neckOpening = store.get('frontNeckSeamLength') + store.get('backNeckSeamLength')
|
||||||
|
const hoodOpening = measurements.head
|
||||||
|
const neckCutoutDelta = store.get('neckCutoutFront') - store.get('neckCutoutBack')
|
||||||
|
store.set('hoodCenterWidth', measurements.head / 10)
|
||||||
|
const halfCenterPanel = store.get('hoodCenterWidth') / 2
|
||||||
|
points.topLeft = new Point(0, 0)
|
||||||
|
points.topRight = new Point(neckOpening, 0)
|
||||||
|
points.neckRight = new Point(neckOpening, (hoodOpening - halfCenterPanel) / 2)
|
||||||
|
points.neckLeft = new Point(0, points.neckRight.y)
|
||||||
|
points.frontLeft = points.neckLeft.shift(-90, neckCutoutDelta)
|
||||||
|
points.frontEdge = points.neckRight.shift(-90, neckCutoutDelta)
|
||||||
|
points.neckEdge = points.neckLeft.shift(0, halfCenterPanel)
|
||||||
|
points.neckEdgeCp2 = new Point(points.neckRight.x / 2, points.neckEdge.y)
|
||||||
|
points.frontEdgeCp1 = new Point(points.neckEdgeCp2.x, points.frontEdge.y)
|
||||||
|
points.shoulderNotch = new Path()
|
||||||
|
.move(points.neckEdge)
|
||||||
|
.curve(points.neckEdgeCp2, points.frontEdgeCp1, points.frontEdge)
|
||||||
|
.shiftAlong(store.get('backNeckSeamLength') - halfCenterPanel)
|
||||||
|
points.hoodTop = new Point(points.shoulderNotch.x, points.topLeft.y)
|
||||||
|
points.hoodTopCp2 = points.hoodTop.shift(180, points.neckEdge.y * 0.7)
|
||||||
|
points.hoodRim = new Point(points.frontEdge.x, points.neckRight.y * 0.2)
|
||||||
|
points.hoodTopCp1 = points.hoodTop.shift(0, points.hoodTop.dx(points.hoodRim) / 2)
|
||||||
|
points.frontEdgeCp2 = points.frontEdge.shift(90, halfCenterPanel)
|
||||||
|
points._tmp1 = new Path()
|
||||||
|
.move(points.hoodRim)
|
||||||
|
.curve(points.hoodRim, points.hoodTopCp1, points.hoodTop)
|
||||||
|
.shiftAlong(2)
|
||||||
|
.rotate(90, points.hoodRim)
|
||||||
|
points.hoodRimCp = points.hoodRim.shiftTowards(points._tmp1, points.neckRight.y / 3)
|
||||||
|
points.neckRoll = points.neckRight.shift(180, halfCenterPanel)
|
||||||
|
points._tmp2 = new Path()
|
||||||
|
.move(points.neckRoll)
|
||||||
|
.curve(points.neckRoll, points.hoodRimCp, points.hoodRim)
|
||||||
|
.shiftAlong(2)
|
||||||
|
points.neckRollCp2 = points.neckRoll.shiftTowards(points._tmp2, halfCenterPanel)
|
||||||
|
points.neckRollCp1 = points.neckRollCp2.rotate(180, points.neckRoll)
|
||||||
|
|
||||||
|
paths.seam = new Path()
|
||||||
|
.move(points.frontEdge)
|
||||||
|
.curve(points.frontEdgeCp2, points.neckRollCp1, points.neckRoll)
|
||||||
|
.curve(points.neckRollCp2, points.hoodRimCp, points.hoodRim)
|
||||||
|
.curve(points.hoodRim, points.hoodTopCp1, points.hoodTop)
|
||||||
|
.curve(points.hoodTopCp2, points.neckEdge, points.neckEdge)
|
||||||
|
.curve(points.neckEdgeCp2, points.frontEdgeCp1, points.frontEdge)
|
||||||
|
.close()
|
||||||
|
.attr('class', 'fabric')
|
||||||
|
|
||||||
|
// Store length of center seam
|
||||||
|
store.set(
|
||||||
|
'hoodCenterLength',
|
||||||
|
new Path()
|
||||||
|
.move(points.hoodRim)
|
||||||
|
.curve(points.hoodRim, points.hoodTopCp1, points.hoodTop)
|
||||||
|
.curve(points.hoodTopCp2, points.neckEdge, points.neckEdge)
|
||||||
|
.length()
|
||||||
|
)
|
||||||
|
|
||||||
|
// Complete pattern?
|
||||||
|
if (complete) {
|
||||||
|
if (sa) {
|
||||||
|
// Reversing this curve sidesteps a bezierjs edge case
|
||||||
|
paths.sa = paths.seam
|
||||||
|
.reverse()
|
||||||
|
.offset(sa * -1)
|
||||||
|
.attr('class', 'fabric sa')
|
||||||
|
}
|
||||||
|
points.title = points.hoodTop.shift(-90, 50)
|
||||||
|
macro('title', { at: points.title, nr: 5, title: 'hoodSide' })
|
||||||
|
points.logo = points.title.shift(-90, 60)
|
||||||
|
snippets.logo = new Snippet('logo', points.logo)
|
||||||
|
macro('grainline', {
|
||||||
|
from: points.shoulderNotch,
|
||||||
|
to: points.hoodTop
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paperless?
|
||||||
|
if (paperless) {
|
||||||
|
const neckSeam = new Path()
|
||||||
|
.move(points.neckEdge)
|
||||||
|
.curve(points.neckEdgeCp2, points.frontEdgeCp1, points.frontEdge)
|
||||||
|
.split(points.shoulderNotch)
|
||||||
|
const centralSeam = new Path()
|
||||||
|
.move(points.hoodRim)
|
||||||
|
.curve(points.hoodRim, points.hoodTopCp1, points.hoodTop)
|
||||||
|
.curve(points.hoodTopCp2, points.neckEdge, points.neckEdge)
|
||||||
|
.reverse()
|
||||||
|
const openingSeam = new Path()
|
||||||
|
.move(points.neckRoll)
|
||||||
|
.curve(points.neckRollCp2, points.hoodRimCp, points.hoodRim)
|
||||||
|
|
||||||
|
macro('pd', {
|
||||||
|
path: neckSeam[0],
|
||||||
|
d: sa + 15
|
||||||
|
})
|
||||||
|
macro('pd', {
|
||||||
|
path: neckSeam[1],
|
||||||
|
d: sa + 15
|
||||||
|
})
|
||||||
|
macro('pd', {
|
||||||
|
path: centralSeam,
|
||||||
|
d: sa * -1 - 15
|
||||||
|
})
|
||||||
|
macro('hd', {
|
||||||
|
from: points.neckEdge,
|
||||||
|
to: points.frontEdge,
|
||||||
|
y: points.frontEdge.y + sa + 30
|
||||||
|
})
|
||||||
|
macro('hd', {
|
||||||
|
from: centralSeam.edge('left'),
|
||||||
|
to: points.frontEdge,
|
||||||
|
y: points.frontEdge.y + sa + 45
|
||||||
|
})
|
||||||
|
const openingEdge = openingSeam.edge('left')
|
||||||
|
macro('hd', {
|
||||||
|
from: openingEdge,
|
||||||
|
to: points.frontEdge,
|
||||||
|
y: openingEdge.y
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.frontEdge,
|
||||||
|
to: points.hoodRim,
|
||||||
|
x: points.hoodRim.x + sa + 15
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.frontEdge,
|
||||||
|
to: points.hoodTop,
|
||||||
|
x: points.hoodRim.x + sa + 30
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return part
|
||||||
|
}
|
43
packages/yuri/src/index.js
Normal file
43
packages/yuri/src/index.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import freesewing from '@freesewing/core'
|
||||||
|
import plugins from '@freesewing/plugin-bundle'
|
||||||
|
import Brian from '@freesewing/brian'
|
||||||
|
import config from '../config'
|
||||||
|
// Parts
|
||||||
|
import draftBack from './back'
|
||||||
|
import draftFront from './front'
|
||||||
|
import draftSleeve from './sleeve'
|
||||||
|
import draftCuff from './cuff'
|
||||||
|
import draftGusset from './gusset'
|
||||||
|
import draftHoodSide from './hoodside'
|
||||||
|
import draftHoodCenter from './hoodcenter'
|
||||||
|
|
||||||
|
// Create new design
|
||||||
|
const Pattern = new freesewing.Design(config, plugins)
|
||||||
|
|
||||||
|
// Attach draft methods from Brian to prototype
|
||||||
|
Pattern.prototype.draftBase = function (part) {
|
||||||
|
return new Brian(this.settings).draftBase(part)
|
||||||
|
}
|
||||||
|
Pattern.prototype.draftFrontBase = function (part) {
|
||||||
|
return new Brian(this.settings).draftFront(part)
|
||||||
|
}
|
||||||
|
Pattern.prototype.draftBackBase = function (part) {
|
||||||
|
return new Brian(this.settings).draftBack(part)
|
||||||
|
}
|
||||||
|
Pattern.prototype.draftSleevecap = function (part) {
|
||||||
|
return new Brian(this.settings).draftSleevecap(part)
|
||||||
|
}
|
||||||
|
Pattern.prototype.draftSleeveBase = function (part) {
|
||||||
|
return new Brian(this.settings).draftSleeve(part)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach own draft methods to prototype
|
||||||
|
Pattern.prototype.draftBack = draftBack
|
||||||
|
Pattern.prototype.draftFront = draftFront
|
||||||
|
Pattern.prototype.draftSleeve = draftSleeve
|
||||||
|
Pattern.prototype.draftCuff = draftCuff
|
||||||
|
Pattern.prototype.draftGusset = draftGusset
|
||||||
|
Pattern.prototype.draftHoodSide = draftHoodSide
|
||||||
|
Pattern.prototype.draftHoodCenter = draftHoodCenter
|
||||||
|
|
||||||
|
export default Pattern
|
165
packages/yuri/src/shared.js
Normal file
165
packages/yuri/src/shared.js
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
export const sharedDimensions = function (part, s) {
|
||||||
|
let { macro, Point, points, sa } = part.shorthand()
|
||||||
|
|
||||||
|
if (s === 'front') {
|
||||||
|
points.cHem = points.cfHem
|
||||||
|
points.cNeck = points.cfNeck
|
||||||
|
} else {
|
||||||
|
points.cHem = points.cbHem
|
||||||
|
points.cNeck = points.cbNeck
|
||||||
|
}
|
||||||
|
|
||||||
|
macro('hd', {
|
||||||
|
from: points.cHem,
|
||||||
|
to: points.hem,
|
||||||
|
y: points.cHem.y + 3 * sa + 15,
|
||||||
|
})
|
||||||
|
macro('ld', {
|
||||||
|
from: new Point(0, points.armholePitch.y),
|
||||||
|
to: points.armholePitch,
|
||||||
|
})
|
||||||
|
macro('hd', {
|
||||||
|
from: points.cNeck,
|
||||||
|
to: points.neck,
|
||||||
|
y: points.neck.y - sa - 15,
|
||||||
|
})
|
||||||
|
macro('hd', {
|
||||||
|
from: points.cNeck,
|
||||||
|
to: points.shoulder,
|
||||||
|
y: points.neck.y - sa - 30,
|
||||||
|
})
|
||||||
|
macro('hd', {
|
||||||
|
from: points.cNeck,
|
||||||
|
to: points.armhole,
|
||||||
|
y: points.neck.y - sa - 45,
|
||||||
|
})
|
||||||
|
macro('ld', {
|
||||||
|
from: points.neck,
|
||||||
|
to: points.shoulder,
|
||||||
|
d: -15,
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.hem,
|
||||||
|
to: points.armhole,
|
||||||
|
x: points.armhole.x + sa + 15,
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.armhole,
|
||||||
|
to: points.armholePitch,
|
||||||
|
x: points.armhole.x + sa + 15,
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.armholePitch,
|
||||||
|
to: points.shoulder,
|
||||||
|
x: points.armhole.x + sa + 15,
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.armhole,
|
||||||
|
to: points.shoulder,
|
||||||
|
x: points.armhole.x + sa + 30,
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.armhole,
|
||||||
|
to: points.neck,
|
||||||
|
x: points.armhole.x + sa + 45,
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.cNeck,
|
||||||
|
to: points.neck,
|
||||||
|
x: points.cNeck.x - 15,
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.cHem,
|
||||||
|
to: points.cNeck,
|
||||||
|
x: points.cNeck.x - 15,
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.cHem,
|
||||||
|
to: points.neck,
|
||||||
|
x: points.cNeck.x - 30,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const draftRibbing = function (part, length) {
|
||||||
|
let {
|
||||||
|
store,
|
||||||
|
measurements,
|
||||||
|
options,
|
||||||
|
points,
|
||||||
|
paths,
|
||||||
|
Path,
|
||||||
|
Point,
|
||||||
|
sa,
|
||||||
|
complete,
|
||||||
|
paperless,
|
||||||
|
macro,
|
||||||
|
units,
|
||||||
|
} = part.shorthand()
|
||||||
|
// Don't run this every time, except when sampling
|
||||||
|
if (typeof store.get('ribbingHeight') === 'undefined' || part.context.settings.sample) {
|
||||||
|
store.set(
|
||||||
|
'ribbingHeight',
|
||||||
|
(measurements.hpsToWaistBack + measurements.waistToHips) * options.ribbingHeight
|
||||||
|
)
|
||||||
|
}
|
||||||
|
let height = store.get('ribbingHeight')
|
||||||
|
let gap = 25
|
||||||
|
let lead = 50
|
||||||
|
if (length < 125) lead = length / 3
|
||||||
|
|
||||||
|
points.topLeft = new Point(0, 0)
|
||||||
|
points.topRight = new Point(height * 2, 0)
|
||||||
|
points.leftGapStart = new Point(0, lead)
|
||||||
|
points.rightGapEnd = new Point(points.topRight.x, lead)
|
||||||
|
points.leftGapEnd = new Point(0, lead + gap)
|
||||||
|
points.rightGapStart = new Point(points.topRight.x, lead + gap)
|
||||||
|
points.bottomLeft = new Point(0, gap + 2 * lead)
|
||||||
|
points.bottomRight = new Point(points.topRight.x, gap + 2 * lead)
|
||||||
|
|
||||||
|
paths.seam = new Path()
|
||||||
|
.move(points.rightGapEnd)
|
||||||
|
.line(points.topRight)
|
||||||
|
.line(points.topLeft)
|
||||||
|
.line(points.leftGapStart)
|
||||||
|
.move(points.leftGapEnd)
|
||||||
|
.line(points.bottomLeft)
|
||||||
|
.line(points.bottomRight)
|
||||||
|
.line(points.rightGapStart)
|
||||||
|
.attr('class', 'various')
|
||||||
|
|
||||||
|
paths.hint = new Path()
|
||||||
|
.move(points.leftGapStart)
|
||||||
|
.line(points.leftGapEnd)
|
||||||
|
.move(points.rightGapStart)
|
||||||
|
.line(points.rightGapEnd)
|
||||||
|
.attr('class', 'various dashed')
|
||||||
|
|
||||||
|
if (complete) {
|
||||||
|
points.title = new Point(points.bottomRight.x / 2, points.bottomRight.y / 2)
|
||||||
|
if (sa) {
|
||||||
|
paths.sa = new Path()
|
||||||
|
.move(points.topLeft)
|
||||||
|
.line(points.bottomLeft)
|
||||||
|
.line(points.bottomRight)
|
||||||
|
.line(points.topRight)
|
||||||
|
.line(points.topLeft)
|
||||||
|
.close()
|
||||||
|
.offset(sa)
|
||||||
|
.attr('class', 'various sa')
|
||||||
|
}
|
||||||
|
macro('vd', {
|
||||||
|
from: points.bottomRight,
|
||||||
|
to: points.topRight,
|
||||||
|
x: points.topRight.x - 25,
|
||||||
|
text: units(length),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paperless) {
|
||||||
|
macro('hd', {
|
||||||
|
from: points.topLeft,
|
||||||
|
to: points.topRight,
|
||||||
|
y: points.topRight.y - sa - 15,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
88
packages/yuri/src/sleeve.js
Normal file
88
packages/yuri/src/sleeve.js
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
export default function (part) {
|
||||||
|
let {
|
||||||
|
Point,
|
||||||
|
Path,
|
||||||
|
points,
|
||||||
|
paths,
|
||||||
|
store,
|
||||||
|
options,
|
||||||
|
complete,
|
||||||
|
sa,
|
||||||
|
paperless,
|
||||||
|
macro,
|
||||||
|
} = part.shorthand()
|
||||||
|
|
||||||
|
// Clear paths from Brian, but keep sleevecap
|
||||||
|
for (let p of Object.keys(paths)) {
|
||||||
|
if (p !== 'sleevecap') delete paths[p]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shorten sleeve to take ribbing into account
|
||||||
|
if (options.ribbing) {
|
||||||
|
for (let p of ['wristLeft', 'wristRight'])
|
||||||
|
points[p] = points[p].shift(90, store.get('ribbingHeight'))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paths
|
||||||
|
paths.saBase = new Path()
|
||||||
|
.move(points.wristRight)
|
||||||
|
.line(points.bicepsRight)
|
||||||
|
.join(paths.sleevecap)
|
||||||
|
.line(points.wristLeft)
|
||||||
|
.attr('class', 'various stroke-xxl')
|
||||||
|
paths.hemBase = new Path()
|
||||||
|
.move(points.wristLeft)
|
||||||
|
.line(points.wristRight)
|
||||||
|
.attr('class', 'various stroke-xxl')
|
||||||
|
paths.saBase.render = false
|
||||||
|
paths.hemBase.render = false
|
||||||
|
|
||||||
|
paths.seam = paths.saBase.join(paths.hemBase).close().attr('class', 'fabric')
|
||||||
|
|
||||||
|
// Complete?
|
||||||
|
if (complete) {
|
||||||
|
macro('grainline', {
|
||||||
|
from: new Point(0, points.wristLeft.y),
|
||||||
|
to: new Point(0, points.backPitch.y),
|
||||||
|
})
|
||||||
|
if (sa) {
|
||||||
|
if (options.ribbing) paths.sa = paths.seam.offset(sa)
|
||||||
|
else {
|
||||||
|
paths.sa = paths.saBase
|
||||||
|
.clone()
|
||||||
|
.offset(sa)
|
||||||
|
.join(paths.hemBase.offset(3 * sa))
|
||||||
|
.close()
|
||||||
|
}
|
||||||
|
paths.sa.attr('class', 'fabric sa')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paperless?
|
||||||
|
if (paperless) {
|
||||||
|
let hemSa = sa
|
||||||
|
if (!options.ribbing) hemSa = 3 * sa
|
||||||
|
macro('hd', {
|
||||||
|
from: points.wristLeft,
|
||||||
|
to: points.wristRight,
|
||||||
|
y: points.wristLeft.y + hemSa + 15,
|
||||||
|
})
|
||||||
|
macro('hd', {
|
||||||
|
from: points.bicepsLeft,
|
||||||
|
to: points.bicepsRight,
|
||||||
|
y: points.sleeveTip.y - sa - 15,
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.wristLeft,
|
||||||
|
to: points.bicepsLeft,
|
||||||
|
x: points.bicepsLeft.x - sa - 15,
|
||||||
|
})
|
||||||
|
macro('vd', {
|
||||||
|
from: points.wristLeft,
|
||||||
|
to: points.sleeveTip,
|
||||||
|
x: points.bicepsLeft.x - sa - 30,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return part
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue