1
0
Fork 0

chore: Remove deprecated code

This commit is contained in:
joostdecock 2022-08-24 09:30:38 +02:00
parent 0730541889
commit d8e1d5b4bc
271 changed files with 3 additions and 16413 deletions

File diff suppressed because it is too large Load diff

View file

@ -56,9 +56,6 @@ Check out [out v3 roadmap](https://github.com/freesewing/freesewing/discussions/
see what we've planning. And we are open to ideas/suggestions for what you would like to see what we've planning. And we are open to ideas/suggestions for what you would like to
see in our mext major release. see in our mext major release.
Also note that the default branch (`develop`) is dedicated to work on version 3.
Code for version to is available in the `v2` branch.
## Getting started ⚡ ## Getting started ⚡
As this is a monorepo. You'll need [NodeJS v14](https://nodejs.org), [lerna](https://lerna.js.org/) and [yarn](https://yarnpkg.com/) on your system. As this is a monorepo. You'll need [NodeJS v14](https://nodejs.org), [lerna](https://lerna.js.org/) and [yarn](https://yarnpkg.com/) on your system.
@ -270,4 +267,4 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<!-- ALL-CONTRIBUTORS-LIST:END --> <!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

View file

@ -1,16 +1,10 @@
{ {
"components": "A collection of React components for FreeSewing web UIs",
"config-helpers": "A FreeSewing package to facilitate pattern configurations", "config-helpers": "A FreeSewing package to facilitate pattern configurations",
"core": "A library for creating made-to-measure sewing patterns", "core": "A library for creating made-to-measure sewing patterns",
"css-theme": "A CSS theme for FreeSewing web UIs",
"gatsby-remark-jargon": "A gatsby-transformer-remark sub-plugin for jargon terms",
"i18n": "Translations for the FreeSewing project", "i18n": "Translations for the FreeSewing project",
"models": "Body measurements data for a range of default sizes", "models": "Body measurements data for a range of default sizes",
"mui-theme": "A Material-UI theme for FreeSewing web UIs",
"new-design": "Initializer package for a new FreeSewing design: npx @freesewing/new-design", "new-design": "Initializer package for a new FreeSewing design: npx @freesewing/new-design",
"pattern-info": "Information about available freesewing patterns", "pattern-info": "Information about available freesewing patterns",
"prettier-config": "FreeSewing's shared configuration for prettier", "prettier-config": "FreeSewing's shared configuration for prettier",
"rehype-jargon": "A Rehype plugin for jargon terms", "rehype-jargon": "A Rehype plugin for jargon terms"
"remark-jargon": "A Remark plugin for jargon terms",
"utils": "A collection of utilities shared across freesewing projects"
} }

View file

@ -6,7 +6,6 @@
"plugin-buttons": "A FreeSewing plugin that provides button, buttonhole, and snap snippets", "plugin-buttons": "A FreeSewing plugin that provides button, buttonhole, and snap snippets",
"plugin-cutonfold": "A FreeSewing plugin to add cut-on-fold indicators on your patterns", "plugin-cutonfold": "A FreeSewing plugin to add cut-on-fold indicators on your patterns",
"plugin-dimension": "A FreeSewing plugin to add dimensions to your (paperless) pattern", "plugin-dimension": "A FreeSewing plugin to add dimensions to your (paperless) pattern",
"plugin-export-dxf": "A FreeSewing plugin to export your pattern as DXF-ASTM",
"plugin-flip": "A FreeSewing plugin to flip parts horizontally", "plugin-flip": "A FreeSewing plugin to flip parts horizontally",
"plugin-gore": "A FreeSewing plugin to generate gores for a semi-sphere or dome", "plugin-gore": "A FreeSewing plugin to generate gores for a semi-sphere or dome",
"plugin-grainline": "A FreeSewing plugin to add grainline indicators on your patterns", "plugin-grainline": "A FreeSewing plugin to add grainline indicators on your patterns",
@ -21,7 +20,6 @@
"plugin-svgattr": "A FreeSewing plugin to set SVG attributes", "plugin-svgattr": "A FreeSewing plugin to set SVG attributes",
"plugin-theme": "A FreeSewing plugin that provides a default theme", "plugin-theme": "A FreeSewing plugin that provides a default theme",
"plugin-title": "A FreeSewing plugin to add a title to your pattern parts", "plugin-title": "A FreeSewing plugin to add a title to your pattern parts",
"plugin-validate": "A FreeSewing plugin that validates aspects of your code",
"plugin-versionfree-svg": "A FreeSewing plugin to keep version info out of your SVG to allow easy diffs across versions" "plugin-versionfree-svg": "A FreeSewing plugin to keep version info out of your SVG to allow easy diffs across versions"
} }

View file

@ -3,7 +3,5 @@
"dev": "FreeSewing website with documentation for contributors & developers", "dev": "FreeSewing website with documentation for contributors & developers",
"lab": "FreeSewing website to test various patterns", "lab": "FreeSewing website to test various patterns",
"org": "FreeSewing website", "org": "FreeSewing website",
"shared": "Shared code and React components for different websites", "shared": "Shared code and React components for different websites"
"strapi": "Freesewing's Strapi instance",
"svgtopdf": "FreeSewing on-demand tiler"
} }

View file

@ -1,4 +0,0 @@
import "storybook-addon-material-ui";
import "@storybook/addon-backgrounds/register";
import "@storybook/addon-knobs/register";
//import '@storybook/addon-notes/register';

View file

@ -1,11 +0,0 @@
export const dark = [
{
name: "dark",
value: "#212529",
default: true
}
];
export default {
dark
};

View file

@ -1,20 +0,0 @@
import React from "react";
import "../../css-theme/dist/theme.css";
import { configure } from "@storybook/react";
import { addDecorator } from "@storybook/react";
import { IntlProvider } from "react-intl";
import { strings } from "@freesewing/i18n";
function loadStories() {
// Load all 'stories.js' files under src
const req = require.context("../src", true, /stories\.js$/);
req.keys().forEach(filename => req(filename));
}
addDecorator(story => (
<IntlProvider locale="en" messages={strings.en}>
{story()}
</IntlProvider>
));
configure(loadStories, module);

View file

@ -1,331 +0,0 @@
# Change log for: @freesewing/components
## 2.21.0 (2022-06-27)
### Changed
- Migrated from Rollup to Esbuild for all builds
## 2.20.8 (2022-05-21)
### Fixed
- Fix restore of pattern defaults in draft configurator Closes [#1932](https://github.com/freesewing/freesewing/issues/1932)
## 2.20.7 (2022-02-20)
### Fixed
- Type-check for optionalMeasurements key in gist Closes [#1918](https://github.com/freesewing/freesewing/issues/1918)
## 2.20.6 (2022-02-17)
### Fixed
- Handle unset props.pattern in DraftConfigurator option.hide check
## 2.20.0 (2022-01-24)
### Added
- Added support for `settings.scale` to Draft and Workbench components
### Fixed
- Support handling of `&#160;` in text
## 2.19.2 (2021-11-02)
### Added
- Added linedrawing for Tiberius
- Added linedrawing for Walburga
## 2.19.0 (2021-10-17)
### Added
- Added Bee linedrawing
### Changed
- Added measurements for dolls & giants to Workbench measurments selector
- Added sampling for dolls & giants to Workbench tests
### Fixed
- Added missing linedrawing for Yuri
## 2.17.0 (2021-07-01)
### Added
- Added Reddit icon to Icon component
- Added Ursula linedrawing to Linedrawings
### Changed
- Caption should not be passed as children to Legend and Example components See https://github.com/freesewing/freesewing/issues/1043
- Changed antman references to antperson
### Removed
- Removed Gitter icon from Icon component
### Fixed
- Correctly load saved value for mm options See [#1136](https://github.com/freesewing/freesewing/issues/1136)
## 2.16.2 (2021-05-05)
### Fixed
- Don't publish ESM modules as it causes issues with react-intl See [#1079](https://github.com/freesewing/freesewing/issues/1079)
## 2.16.1 (2021-05-30)
### Added
- Added a new `designs` icon
- We now publish .mjs files again for the different components
## 2.16.0 (2021-05-24)
### Changed
- Migrated to React 17
- Migrated to create-react-app/react-scripts 4
- Migrated to Webpack 5
- Changes to Workbench
- Added rollup sass plugin
- Updated for new major version of react-markdown
## 2.15.0 (2021-04-15)
### Added
- Added charlie LineDrawing
### Changed
- Show raised info above pattern in workbench
- Round point coordinates in design UI now that they are no longer rounded in core
### Fixed
- Always show design mode switch
## 2.14.0 (2021-03-07)
### Added
- Added Bella linedrawing
- Added Cornelius linedrawing
## 2.13.0 (2021-02-13)
### Added
- Linedrawing for hortensia
### Fixed
- Check point attributes are present before using them
## 2.11.3 (2021-01-16)
### Fixed
- Fixed links in Workbench footer
## 2.11.2 (2021-01-11)
### Fixed
- Fixed links in Workbench footer
## 2.11.0 (2021-01-10)
### Added
- Added some more examples to the Examples component
- Draft configurator now supports collapsing of subgroups
- Draft configurator now supports actions atop the menu
### Removed
- Removed the Emblem component
- Removed the Navbar component
- Removed the Ogol component
### Fixed
- Include basic themeing in Example component
- Updated the note and tip icons
## 2.10.6 (2020-11-15)
### Added
- Workbench now supports loading a pattern configuration from a (github) gist
## 2.10.3 (2020-11-08)
### Changed
- Draft component now supports snippets in the same way as the render method
## 2.10.1 (2020-11-07)
### Changed
- Changes to workbench
## 2.9.0 (2020-10-02)
### Added
- Added Teagan line drawing
- Added Discord icon in Icon component
## 2.8.0 (2020-08-10)
### Added
- Added Paco to LineDrawing component
### Removed
- Removed the `Footer` component
## 2.7.1 (2020-07-24)
### Added
- Workbench now includes events debug output and enables debug by default
## 2.7.0 (2020-07-12)
### Added
- The `sampleConfigurator` component now supports the antwoman test (in addition to the antman test)
- Changed `models` to `people` in `sampleConfigurator`
- The `Legend` component is new, it is similar to the `Example` component but only for the pattern notation legend
- Added support for custom sample styles
- Added Titan linedrawing
### Changed
- Handle escaped quotes for React render. See [#437](https://github.com/freesewing/freesewing/issues/437)
### Fixed
- Fixed bug that broke millimeter sliders
## 2.6.0 (2020-05-01)
### Added
- [#368](https://github.com/freesewing/freesewing/issues/368): Allow pan and zoom in the Workbench component.
- [#374](https://github.com/freesewing/freesewing/issues/374): Allow (extra) translations to be added to the workbench component
- New shortcut buttons and sidebar collapse support for Workbench
- Refactor to remove prop-types dependency
- Reworked the withLanguage component to allow adding translations at run-time
## 2.4.2 (2020-03-08)
### Changed
- Don't load docs in DraftConfigurator
## 2.4.1 (2020-03-04)
### Fixed
- Fixed `updatePatternData` props issue in the Workbench component
## 2.2.0 (2020-02-22)
### Added
- Added LineDrawing for Breanna
### Changed
- DraftConfigurator has been updated to reflect frontend naming changes
- Updated Workbench component to pass data rather than gist to DraftConfigurator
- Term `pattern` is now `design`
- Term `recipe` is now `pattern`
- Term `gist` is now `data`
## 2.1.4 (2019-11-01)
### Deprecated
- The Draft component has been renamed to Render. Draft still works, but will be removed in a future release.
### Removed
- The Ogol component has been removed as it wasn't used
## 2.1.1 (2019-10-13)
### Added
- Added the fixme type Blockquote component
## 2.1.0 (2019-10-06)
### Added
- Added support for restoring recipe and pattern defaults in DraftConfigurator
### Changed
- Added Penelope and Waralee linedrawings
- Changed animation of the Spinner component
### Fixed
- Fixed display of nested option in SampleConfigurator
- Fixed conflicting key values in React components
- Fixed issue with display of list options in Draftconfigurator
## 2.0.4 (2019-09-27)
### Added
- Advanced options and settings are now hidden by default in DraftConfigurator
### Fixed
- [#104](https://github.com/freesewing/freesewing/issues/104): Fixed incorrect embed setting on Workbench pattern export
## 2.0.3 (2019-09-15)
### Changed
- Tweaked DraftConfigurator tags to match CSS rules after frontend upgrade to react-intl v3
## 2.0.2 (2019-09-06)
### Fixed
- [#104](https://github.com/freesewing/freesewing.org/issues/104): Changed `onDragEnd` to `onChangeCommitted` in slider element (change in material-ui API when slider came out of beta)
- Workbench now also lets you preload a `withBreasts` set of measurements
- DraftConfigurator now properly styles pattern options 3 levels deep
- [#105](https://github.com/freesewing/freesewing.org/issues/105): Moved state change in render loop to useEffect
## 2.0.0 (2019-08-25)
### Added
- Initial release
This is the **initial release**, and the start of this change log.
> Prior to version 2, FreeSewing was not a JavaScript project.
> As such, that history is out of scope for this change log.

View file

@ -1,288 +0,0 @@
![FreeSewing](https://static.freesewing.org/banner.png)
<p align='center'><a
href="https://www.npmjs.com/package/@freesewing/components"
title="@freesewing/components on NPM"
><img src="https://img.shields.io/npm/v/@freesewing/components.svg"
alt="@freesewing/components on NPM"/>
</a><a
href="https://opensource.org/licenses/MIT"
title="License: MIT"
><img src="https://img.shields.io/npm/l/@freesewing/components.svg?label=License"
alt="License: MIT"/>
</a><a
href="https://deepscan.io/dashboard#view=project&tid=2114&pid=2993&bid=23256"
title="Code quality on DeepScan"
><img src="https://deepscan.io/api/teams/2114/projects/2993/branches/23256/badge/grade.svg"
alt="Code quality on DeepScan"/>
</a><a
href="https://github.com/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen+label%3Apkg%3Acomponents"
title="Open issues tagged pkg:components"
><img src="https://img.shields.io/github/issues/freesewing/freesewing/pkg:components.svg?label=Issues"
alt="Open issues tagged pkg:components"/>
</a><a
href="#contributors-"
title="All Contributors"
><img src="https://img.shields.io/badge/all_contributors-98-pink.svg"
alt="All Contributors"/>
</a></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://chat.freesewing.org"
title="Chat with us on Discord"
><img src="https://img.shields.io/discord/698854858052075530?label=Chat%20on%20Discord"
alt="Chat with us on Discord"/>
</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>
# @freesewing/components
A collection of React components for FreeSewing web UIs
## 🚨🚨 This packages is deprecated 🚨🚨
This package will not be part of FreeSewing v3.
> #### Note: Version 3 is a work in progress
>
> We are working on a new major version (v3) but it is not ready for prime-time.
> For production use, please refer to our v2 packages (the `latest` on NPM)
> or [the `v2` branch in our monorepo](https://github.com/freesewing/freesewing/tree/v2).
## What am I looking at? 🤔
This repository is our *monorepo* holding all our NPM designs, plugins, other NPM packages, and (web)sites.
This folder holds: @freesewing/components
If you're not entirely sure what to do or how to start, type this command:
```
npm run tips
```
> If you don't want to set up a dev environment, you can run it in your browser:
>
> [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/freesewing/freesewing)
>
> We recommend that you fork our repository and then
> put `gitpod.io/#<entire-url-of-your-fork` into a browser
> to start up a browser-based dev environment of your own.
## About FreeSewing 💀
Where the world of makers and developers collide, that's where you'll find FreeSewing.
If you're a maker, checkout [freesewing.org](https://freesewing.org/) where you can generate
our sewing patterns adapted to your measurements.
If you're a developer, our documentation is on [freesewing.dev](https://freesewing.dev/).
Our [core library](https://freesewing.dev/reference/api/) is a *batteries-included* toolbox
for parametric design of sewing patterns. But we also provide a range
of [plugins](https://freesewing.dev/reference/plugins/) that further extend the
functionality of the platform.
If you have NodeJS installed, you can try it right now by running:
```bash
npx create-freesewing-pattern
```
Or, consult our getting started guides
for [Linux](https://freesewing.dev/tutorials/getting-started-linux/),
[MacOS](https://freesewing.dev/tutorials/getting-started-mac/),
or [Windows](https://freesewing.dev/tutorials/getting-started-windows/).
We also have a [pattern design tutorial](https://freesewing.dev/tutorials/pattern-design/) that
walks you through your first parametric design,
and [a friendly community](https://freesewing.org/community/where/) with
people who can help you when you get stuck.
## 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, and you can spend a few coind without
hardship, then you should [join us and become a patron](https://freesewing.org/community/join).
## Links 👩‍💻
- 💻 Makers website: [freesewing.org](https://freesewing.org)
- 💻 Developers website: [freesewing.dev](https://freesewing.dev)
- 💬 Chat: On Discord via [discord.freesewing.org](https://discord.freesewing.org/)
- ✅ Todo list/Kanban board: On Github via [todo.freesewing.org](https://todo.freesewing.org/)
- 🐦 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 [chatrooms on Discord](https://chat.freesewing.org/) are 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).
## Contributors ✨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="http://adamrtomkins.github.io/"><img src="https://avatars.githubusercontent.com/u/5709603?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Adam Tomkins</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=AdamRTomkins" title="Documentation">📖</a></td>
<td align="center"><a href="http://polymerisation-des-concepts.fr/"><img src="https://avatars.githubusercontent.com/u/365999?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alexandre Ignjatovic</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=bankair" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/AlfaLyr"><img src="https://avatars.githubusercontent.com/u/39273729?v=4?s=100" width="100px;" alt=""/><br /><sub><b>AlfaLyr</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=AlfaLyr" title="Code">💻</a> <a href="#plugin-AlfaLyr" title="Plugin/utility libraries">🔌</a> <a href="#design-AlfaLyr" title="Design">🎨</a></td>
<td align="center"><a href="http://thelettereph.com"><img src="https://avatars.githubusercontent.com/u/357684?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew James</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=ephphatha" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/annekecaramin"><img src="https://avatars.githubusercontent.com/u/38046191?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Anneke</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=annekecaramin" title="Documentation">📖</a> <a href="#translation-annekecaramin" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/anniekao"><img src="https://avatars.githubusercontent.com/u/1550506?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Annie Kao</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=anniekao" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/Anternative"><img src="https://avatars.githubusercontent.com/u/81079850?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Anternative</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=Anternative" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/Quiltmaster"><img src="https://avatars.githubusercontent.com/u/71795777?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Anthony</b></sub></a><br /><a href="#question-Quiltmaster" title="Answering Questions">💬</a></td>
<td align="center"><a href="https://github.com/arigrayzel"><img src="https://avatars.githubusercontent.com/u/33040950?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ari Grayzel-student</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=arigrayzel" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/BenJamesBen"><img src="https://avatars.githubusercontent.com/u/109869956?v=4?s=100" width="100px;" alt=""/><br /><sub><b>BenJamesBen</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=BenJamesBen" title="Code">💻</a> <a href="https://github.com/freesewing/freesewing/commits?author=BenJamesBen" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/camerondubas"><img src="https://avatars.githubusercontent.com/u/6216460?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cameron Dubas</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=camerondubas" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/cabi"><img src="https://avatars.githubusercontent.com/u/2596253?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Carsten Biebricher</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=cabi" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/cathyzoller"><img src="https://avatars.githubusercontent.com/u/2120275?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cathy Zoller</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=cathyzoller" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/Chantalbijoux"><img src="https://avatars.githubusercontent.com/u/39673694?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chantal Lapointe</b></sub></a><br /><a href="#translation-Chantalbijoux" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/dpiquet"><img src="https://avatars.githubusercontent.com/u/4688628?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Damien PIQUET</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=dpiquet" title="Code">💻</a></td>
<td align="center"><a href="https://www.darigovresearch.com/"><img src="https://avatars.githubusercontent.com/u/30328618?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Darigov Research</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=darigovresearch" title="Documentation">📖</a> <a href="#ideas-darigovresearch" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/ElenaFdR"><img src="https://avatars.githubusercontent.com/u/5113815?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Elena FdR</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=ElenaFdR" title="Documentation">📖</a> <a href="#blog-ElenaFdR" title="Blogposts">📝</a></td>
<td align="center"><a href="https://emmanuelnyachoke.com/"><img src="https://avatars.githubusercontent.com/u/1908926?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Emmanuel Nyachoke</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=enyachoke" title="Code">💻</a> <a href="https://github.com/freesewing/freesewing/commits?author=enyachoke" title="Documentation">📖</a></td>
<td align="center"><a href="http://enochriese.com"><img src="https://avatars.githubusercontent.com/u/5298929?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Enoch Riese</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=eriese" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/EvEkSwed"><img src="https://avatars.githubusercontent.com/u/39723451?v=4?s=100" width="100px;" alt=""/><br /><sub><b>EvEkSwed</b></sub></a><br /><a href="#translation-EvEkSwed" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/Fantastik-Maman"><img src="https://avatars.githubusercontent.com/u/39785382?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fantastik-Maman</b></sub></a><br /><a href="#translation-Fantastik-Maman" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center"><a href="https://www.forresto.com/"><img src="https://avatars.githubusercontent.com/u/395307?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Forrest O.</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=forresto" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/fmatray"><img src="https://avatars.githubusercontent.com/u/8267716?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Frédéric</b></sub></a><br /><a href="#translation-fmatray" title="Translation">🌍</a></td>
<td align="center"><a href="https://www.linkedin.com/in/glennfmatthews/"><img src="https://avatars.githubusercontent.com/u/5603551?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Glenn Matthews</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=glennmatthews" title="Documentation">📖</a></td>
<td align="center"><a href="https://greg.technology/"><img src="https://avatars.githubusercontent.com/u/1017304?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Greg Sadetsky</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=gregsadetsky" title="Documentation">📖</a></td>
<td align="center"><a href="https://kirby.zone"><img src="https://avatars.githubusercontent.com/u/75245963?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Igor Couto</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/issues?q=author%3Aiocouto" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=eltociear" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/Irapeke"><img src="https://avatars.githubusercontent.com/u/39604334?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Irapeke</b></sub></a><br /><a href="#translation-Irapeke" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/jsawo"><img src="https://avatars.githubusercontent.com/u/1294706?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jacek Sawoszczuk</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=jsawo" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/jgfichte"><img src="https://avatars.githubusercontent.com/u/1787162?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jason Williams</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=jgfichte" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/jejacks0n"><img src="https://avatars.githubusercontent.com/u/13765?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jeremy Jackson</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=jejacks0n" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/joeschofield0"><img src="https://avatars.githubusercontent.com/u/47668691?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joe Schofield</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=joeschofield0" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/Joebidido"><img src="https://avatars.githubusercontent.com/u/39796210?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joebidido</b></sub></a><br /><a href="#translation-Joebidido" title="Translation">🌍</a></td>
<td align="center"><a href="https://joost.at/"><img src="https://avatars.githubusercontent.com/u/1708494?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joost De Cock</b></sub></a><br /><a href="#maintenance-joostdecock" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/joshessman"><img src="https://avatars.githubusercontent.com/u/9941074?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Josh Essman</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=joshessman" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="http://www.earth.li/~kake/"><img src="https://avatars.githubusercontent.com/u/1956810?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kake</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=KakeLP" title="Documentation">📖</a></td>
<td align="center"><a href="https://twitter.com/kapunahele"><img src="https://avatars.githubusercontent.com/u/4116963?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kapunahele Wong</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=kapunahelewong" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/tangerineshark"><img src="https://avatars.githubusercontent.com/u/70777269?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Karen</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=tangerineshark" title="Documentation">📖</a> <a href="#eventOrganizing-tangerineshark" title="Event Organizing">📋</a></td>
<td align="center"><a href="https://github.com/mcgnly"><img src="https://avatars.githubusercontent.com/u/5653631?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Katie McGinley</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=mcgnly" title="Documentation">📖</a></td>
<td align="center"><a href="http://www.kieranklaassen.com/"><img src="https://avatars.githubusercontent.com/u/209089?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kieran Klaassen</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=kieranklaassen" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Kittycatou"><img src="https://avatars.githubusercontent.com/u/48165583?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kittycatou</b></sub></a><br /><a href="#translation-Kittycatou" title="Translation">🌍</a></td>
<td align="center"><a href="https://www.krishoward.org/"><img src="https://avatars.githubusercontent.com/u/5946286?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kris</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=web-goddess" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/kristinruben"><img src="https://avatars.githubusercontent.com/u/17237479?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kristin Ruben</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=kristinruben" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Loudepeuter"><img src="https://avatars.githubusercontent.com/u/38081954?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Loudepeuter</b></sub></a><br /><a href="#translation-Loudepeuter" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/lucibytes"><img src="https://avatars.githubusercontent.com/u/77203781?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lucian</b></sub></a><br /><a href="#eventOrganizing-lucibytes" title="Event Organizing">📋</a></td>
<td align="center"><a href="https://github.com/manufakturedelweiss"><img src="https://avatars.githubusercontent.com/u/38063391?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Marcus</b></sub></a><br /><a href="#translation-manufakturedelweiss" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/martintribo"><img src="https://avatars.githubusercontent.com/u/1613442?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Martin Tribo</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=martintribo" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/nadege"><img src="https://avatars.githubusercontent.com/u/3792171?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nadege Michel</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=nadege" title="Tests">⚠️</a> <a href="https://github.com/freesewing/freesewing/commits?author=nadege" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/nataliasayang"><img src="https://avatars.githubusercontent.com/u/48160791?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Natalia</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=nataliasayang" title="Code">💻</a> <a href="#design-nataliasayang" title="Design">🎨</a> <a href="#blog-nataliasayang" title="Blogposts">📝</a></td>
</tr>
<tr>
<td align="center"><a href="http://yergler.net/"><img src="https://avatars.githubusercontent.com/u/510875?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nathan Yergler</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=nyergler" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/nicholasdower"><img src="https://avatars.githubusercontent.com/u/9117775?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nick Dower</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=nicholasdower" title="Documentation">📖</a> <a href="https://github.com/freesewing/freesewing/commits?author=nicholasdower" title="Code">💻</a> <a href="https://github.com/freesewing/freesewing/issues?q=author%3Anicholasdower" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/nchilada"><img src="https://avatars.githubusercontent.com/u/692925?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nikhil Chelliah</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=nchilada" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/OysteinHoiby"><img src="https://avatars.githubusercontent.com/u/49735055?v=4?s=100" width="100px;" alt=""/><br /><sub><b>OysteinHoiby</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=OysteinHoiby" title="Code">💻</a></td>
<td align="center"><a href="https://pat.forringer.com/"><img src="https://avatars.githubusercontent.com/u/136456?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Patrick Forringer</b></sub></a><br /><a href="#plugin-destos" title="Plugin/utility libraries">🔌</a></td>
<td align="center"><a href="http://pd75.github.io/"><img src="https://avatars.githubusercontent.com/u/10294795?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Paul</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=PD75" title="Documentation">📖</a> <a href="#blog-PD75" title="Blogposts">📝</a> <a href="#translation-PD75" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/phillipthelen"><img src="https://avatars.githubusercontent.com/u/298062?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Phillip Thelen</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=phillipthelen" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/Pixieish"><img src="https://avatars.githubusercontent.com/u/32991415?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pixieish</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=Pixieish" title="Documentation">📖</a></td>
<td align="center"><a href="https://www.uza.be/persoon/prof-dr-sorcha-ni-dhubhghaill"><img src="https://avatars.githubusercontent.com/u/30624634?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Prof. dr. Sorcha Ní Dhubhghaill</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=sorchanidhubhghaill" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/QuentinFelix"><img src="https://avatars.githubusercontent.com/u/5288091?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Quentin FELIX</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=QuentinFelix" title="Code">💻</a> <a href="#design-QuentinFelix" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/RikHekker"><img src="https://avatars.githubusercontent.com/u/31843274?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rik Hekker</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/issues?q=author%3ARikHekker" title="Bug reports">🐛</a></td>
<td align="center"><a href="http://resume.livingston-gray.com/faq.html"><img src="https://avatars.githubusercontent.com/u/6462?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sam Livingston-Gray</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=geeksam" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/sannek"><img src="https://avatars.githubusercontent.com/u/17491062?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sanne</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=sannek" title="Code">💻</a> <a href="https://github.com/freesewing/freesewing/commits?author=sannek" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/Tyrannogina"><img src="https://avatars.githubusercontent.com/u/19556565?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sara Latorre</b></sub></a><br /><a href="#translation-Tyrannogina" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/SeaZeeZee"><img src="https://avatars.githubusercontent.com/u/86711383?v=4?s=100" width="100px;" alt=""/><br /><sub><b>SeaZeeZee</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=SeaZeeZee" title="Documentation">📖</a> <a href="https://github.com/freesewing/freesewing/commits?author=SeaZeeZee" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/SimonbJohnson"><img src="https://avatars.githubusercontent.com/u/2110742?v=4?s=100" width="100px;" alt=""/><br /><sub><b>SimonbJohnson</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/issues?q=author%3ASimonbJohnson" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://www.instagram.com/celine_mge/"><img src="https://avatars.githubusercontent.com/u/57619777?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Slylele</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=Slylele" title="Documentation">📖</a> <a href="#translation-Slylele" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/Soazillon"><img src="https://avatars.githubusercontent.com/u/40845940?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Soazillon</b></sub></a><br /><a href="#translation-Soazillon" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/SoneaTheBest"><img src="https://avatars.githubusercontent.com/u/64635425?v=4?s=100" width="100px;" alt=""/><br /><sub><b>SoneaTheBest</b></sub></a><br /><a href="#translation-SoneaTheBest" title="Translation">🌍</a></td>
<td align="center"><a href="http://metafly.info/"><img src="https://avatars.githubusercontent.com/u/961256?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stefan Sydow</b></sub></a><br /><a href="#translation-stsydow" title="Translation">🌍</a> <a href="https://github.com/freesewing/freesewing/commits?author=stsydow" title="Documentation">📖</a> <a href="https://github.com/freesewing/freesewing/commits?author=stsydow" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/TriploidTree"><img src="https://avatars.githubusercontent.com/u/4170521?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tríona</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=TriploidTree" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/theUnmutual"><img src="https://avatars.githubusercontent.com/u/22374635?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Unmutual</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=theUnmutual" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/woutervdub"><img src="https://avatars.githubusercontent.com/u/24414629?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Wouter van Wageningen</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=woutervdub" title="Code">💻</a> <a href="#design-woutervdub" title="Design">🎨</a> <a href="#tool-woutervdub" title="Tools">🔧</a></td>
<td align="center"><a href="https://github.com/amysews"><img src="https://avatars.githubusercontent.com/u/25280778?v=4?s=100" width="100px;" alt=""/><br /><sub><b>amysews</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=amysews" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/anna-puk"><img src="https://avatars.githubusercontent.com/u/100537439?v=4?s=100" width="100px;" alt=""/><br /><sub><b>anna-puk</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=anna-puk" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/beautifulsummermoon"><img src="https://avatars.githubusercontent.com/u/40396388?v=4?s=100" width="100px;" alt=""/><br /><sub><b>beautifulsummermoon</b></sub></a><br /><a href="#translation-beautifulsummermoon" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/berce"><img src="https://avatars.githubusercontent.com/u/10439709?v=4?s=100" width="100px;" alt=""/><br /><sub><b>berce</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=berce" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/biou"><img src="https://avatars.githubusercontent.com/u/1340376?v=4?s=100" width="100px;" alt=""/><br /><sub><b>biou</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=biou" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/bobgeorgethe3rd"><img src="https://avatars.githubusercontent.com/u/16866285?v=4?s=100" width="100px;" alt=""/><br /><sub><b>bobgeorgethe3rd</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=bobgeorgethe3rd" title="Code">💻</a> <a href="https://github.com/freesewing/freesewing/commits?author=bobgeorgethe3rd" title="Documentation">📖</a> <a href="#design-bobgeorgethe3rd" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/brmlyklr"><img src="https://avatars.githubusercontent.com/u/22308713?v=4?s=100" width="100px;" alt=""/><br /><sub><b>brmlyklr</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=brmlyklr" title="Documentation">📖</a></td>
<td align="center"><a href="http://www.chrisbarrett.fr"><img src="https://avatars.githubusercontent.com/u/2373249?v=4?s=100" width="100px;" alt=""/><br /><sub><b>chri5b</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=chri5b" title="Code">💻</a> <a href="https://github.com/freesewing/freesewing/commits?author=chri5b" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/dingcycle"><img src="https://avatars.githubusercontent.com/u/1681985?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dingcycle</b></sub></a><br /><a href="#translation-dingcycle" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/drowned-in-books"><img src="https://avatars.githubusercontent.com/u/100040772?v=4?s=100" width="100px;" alt=""/><br /><sub><b>drowned-in-books</b></sub></a><br /><a href="#question-drowned-in-books" title="Answering Questions">💬</a></td>
<td align="center"><a href="https://github.com/econo202"><img src="https://avatars.githubusercontent.com/u/34138153?v=4?s=100" width="100px;" alt=""/><br /><sub><b>econo202</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=econo202" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/ericamattos"><img src="https://avatars.githubusercontent.com/u/4341417?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ericamattos</b></sub></a><br /><a href="#translation-ericamattos" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/fightingrabbit"><img src="https://avatars.githubusercontent.com/u/25751445?v=4?s=100" width="100px;" alt=""/><br /><sub><b>fightingrabbit</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=fightingrabbit" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/DocSpencer77"><img src="https://avatars.githubusercontent.com/u/43393580?v=4?s=100" width="100px;" alt=""/><br /><sub><b>gaylyndie</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=DocSpencer77" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/grimlokason"><img src="https://avatars.githubusercontent.com/u/5112238?v=4?s=100" width="100px;" alt=""/><br /><sub><b>grimlokason</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=grimlokason" title="Code">💻</a></td>
<td align="center"><a href="https://weblog.redisdead.net"><img src="https://avatars.githubusercontent.com/u/6494414?v=4?s=100" width="100px;" alt=""/><br /><sub><b>hellgy</b></sub></a><br /><a href="#design-hellgy" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/jackseye"><img src="https://avatars.githubusercontent.com/u/27834526?v=4?s=100" width="100px;" alt=""/><br /><sub><b>jackseye</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=jackseye" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/marckiesel"><img src="https://avatars.githubusercontent.com/u/39653780?v=4?s=100" width="100px;" alt=""/><br /><sub><b>marckiesel</b></sub></a><br /><a href="#translation-marckiesel" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/Mesil"><img src="https://avatars.githubusercontent.com/u/14284175?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mesil</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/issues?q=author%3Amesil" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/starfetch"><img src="https://avatars.githubusercontent.com/u/80041179?v=4?s=100" width="100px;" alt=""/><br /><sub><b>starfetch</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=starfetch" title="Code">💻</a> <a href="https://github.com/freesewing/freesewing/commits?author=starfetch" title="Documentation">📖</a> <a href="#translation-starfetch" title="Translation">🌍</a> <a href="#design-starfetch" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/ttimearl"><img src="https://avatars.githubusercontent.com/u/77916590?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ttimearl</b></sub></a><br /><a href="#content-ttimearl" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/chrisgloom"><img src="https://avatars.githubusercontent.com/u/15905991?v=4?s=100" width="100px;" alt=""/><br /><sub><b>tuesgloomsday</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=chrisgloom" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/valadaptive"><img src="https://avatars.githubusercontent.com/u/79560998?v=4?s=100" width="100px;" alt=""/><br /><sub><b>valadaptive</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=valadaptive" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/viocky"><img src="https://avatars.githubusercontent.com/u/39279173?v=4?s=100" width="100px;" alt=""/><br /><sub><b>viocky</b></sub></a><br /><a href="#translation-viocky" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/woolishboy"><img src="https://avatars.githubusercontent.com/u/57816321?v=4?s=100" width="100px;" alt=""/><br /><sub><b>woolishboy</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=woolishboy" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/cloutiy"><img src="https://avatars.githubusercontent.com/u/8433147?v=4?s=100" width="100px;" alt=""/><br /><sub><b>yc</b></sub></a><br /><a href="#translation-cloutiy" title="Translation">🌍</a></td>
</tr>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

View file

@ -1,67 +0,0 @@
/* This script will build the various components with esbuild */
const esbuild = require('esbuild')
const pkg = require('./package.json')
// Create banner based on package info
const banner = `/**
* ${pkg.name} | v${pkg.version}
* ${pkg.description}
* (c) ${new Date().getFullYear()} ${pkg.author}
* @license ${pkg.license}
*/`
// Shared esbuild options
const options = {
banner: { js: banner },
bundle: true,
entryPoints: [
'./src/Blockquote/index.js',
'./src/Draft/index.js',
'./src/DraftConfigurator/index.js',
'./src/Example/index.js',
'./src/Icon/index.js',
'./src/Legend/index.js',
'./src/LineDrawing/index.js',
'./src/Logo/index.js',
'./src/Robot/index.js',
'./src/SampleConfigurator/index.js',
'./src/Spinner/index.js',
'./src/withGist/index.js',
'./src/withLanguage/index.js',
'./src/withStorage/index.js',
'./src/Workbench/index.js',
],
external: [
"@freesewing",
"react",
"react-dom",
"react-intl",
"@material-ui",
"axios",
"babel",
"prismjs",
"react-markdown",
"file-saver",
"yaml",
],
format: 'cjs',
metafile: process.env.VERBOSE ? true : false,
minify: process.env.NO_MINIFY ? false : true,
loader: { '.js': 'jsx' },
outdir: './',
sourcemap: true,
}
// Let esbuild do its thing
// Only generating CJS since this will be dropped in v3
let result
(async () => {
result = await esbuild
.build(options)
.catch(() => process.exit(1))
if (process.env.VERBOSE) {
const info = await esbuild.analyzeMetafile(result.metafile)
console.log(info)
}
})()

View file

@ -1,4 +0,0 @@
## 🚨🚨 This packages is deprecated 🚨🚨
This package will not be part of FreeSewing v3.

View file

@ -1,90 +0,0 @@
{
"name": "@freesewing/components",
"version": "3.0.0-alpha.0",
"description": "A collection of React components for FreeSewing web UIs",
"author": "Joost De Cock <joost@joost.at> (https://github.com/joostdecock)",
"homepage": "https://freesewing.org/",
"repository": "github:freesewing/freesewing",
"license": "MIT",
"bugs": {
"url": "https://github.com/freesewing/freesewing/issues"
},
"funding": {
"type": "individual",
"url": "https://freesewing.org/patrons/join"
},
"keywords": [
"freesewing",
"react"
],
"main": "dist/index.js",
"scripts": {
"build": "node build.js",
"clean": "rimraf Blockquote && rimraf Draft && rimraf DraftConfigurator && rimraf Emblem && rimraf Example && rimraf Footer && rimraf Icon && rimraf Legend && rimraf LineDrawing && rimraf Logo && rimraf Navbar && rimraf Ogol && rimraf Robot && rimraf SampleConfigurator && rimraf Spinner && rimraf withGist && rimraf withLanguage && rimraf withStorage && rimraf Workbench",
"mbuild": "NO_MINIFY=1 node build.js",
"symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -",
"test": "echo \"components: No tests configured. Perhaps you'd like to do this?\" && exit 0",
"vbuild": "VERBOSE=1 node build.js",
"lab": "cd ../../sites/lab && yarn start",
"tips": "node ../../scripts/help.mjs",
"storybook": "start-storybook -p 6663",
"cibuild_step6": "node build.js"
},
"peerDependencies": {
"axios": "^0.25.0",
"react": "^17.0.2",
"@freesewing/pattern-info": "^3.0.0-alpha.0",
"@freesewing/mui-theme": "^3.0.0-alpha.0",
"@freesewing/css-theme": "^3.0.0-alpha.0",
"@freesewing/plugin-theme": "^3.0.0-alpha.0",
"@freesewing/core": "^3.0.0-alpha.0",
"@freesewing/models": "^3.0.0-alpha.0",
"@freesewing/examples": "^3.0.0-alpha.0",
"@freesewing/rendertest": "^3.0.0-alpha.0",
"@freesewing/tutorial": "^3.0.0-alpha.0",
"@fontsource/permanent-marker": "latest",
"@fontsource/roboto-mono": "latest",
"@fontsource/ubuntu": "latest",
"@freesewing/i18n": "^3.0.0-alpha.0",
"@freesewing/utils": "^3.0.0-alpha.0",
"react-intl": "^5.25.1",
"@material-ui/core": "^4.12.3",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^v4.0.0-alpha.60",
"prismjs": "^1.25.0",
"react-markdown": "^6.0.2",
"file-saver": "^2.0.5",
"yaml": "^1.10.2"
},
"dependencies": {},
"devDependencies": {},
"files": [
"Blockquote/*",
"Draft/*",
"DraftConfigurator/*",
"Emblem/*",
"Example/*",
"Footer/*",
"Icon/*",
"Legend/*",
"LineDrawing/*",
"Logo/*",
"Navbar/*",
"Ogol/*",
"Robot/*",
"SampleConfigurator/*",
"Spinner/*",
"withGist/*",
"withLanguage/*",
"withStorage/*",
"Workbench/*"
],
"publishConfig": {
"access": "public",
"tag": "next"
},
"engines": {
"node": ">=14.0.0",
"npm": ">=6"
}
}

View file

@ -1,36 +0,0 @@
import React, { useState, useEffect } from 'react'
import Radio from '@material-ui/core/Radio'
import RadioGroup from '@material-ui/core/RadioGroup'
import FormControlLabel from '@material-ui/core/FormControlLabel'
const Bool = ({ dflt = false, labels = ['false', 'true'], value, name, updateValue }) => {
const [val, setVal] = useState(dflt)
useEffect(() => {
if (value !== val) setVal(value)
}, [value])
const toggle = () => {
updateValue(name, !val)
setVal(!val)
}
return (
<RadioGroup onChange={toggle} value={JSON.stringify(val)}>
<FormControlLabel
control={<Radio color="primary" />}
value="false"
checked={val === 'true' || val === true || val === 1 ? false : true}
label={labels[0]}
className="po-list-item"
/>
<FormControlLabel
control={<Radio color="primary" />}
value="true"
checked={val === 'true' || val === true || val === 1 ? true : false}
label={labels[1]}
className="po-list-item"
/>
</RadioGroup>
)
}
export default Bool

View file

@ -1,17 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import FormFieldBool from ".";
const props = {
updateValue: (name, value) =>
console.log(`Updated option ${name}, value is now: ${value}`),
name: "exampleBoolOption"
};
const noyes = ["No", "Yes"];
storiesOf("Low level/Form/FormFieldBool", module)
.add("Basic", () => <FormFieldBool {...props} />)
.add("False", () => <FormFieldBool {...props} dflt={false} />)
.add("True", () => <FormFieldBool {...props} dflt={true} />)
.add("No", () => <FormFieldBool {...props} dflt={false} labels={noyes} />)
.add("Yes", () => <FormFieldBool {...props} dflt={true} labels={noyes} />);

View file

@ -1,40 +0,0 @@
import React, { useState } from 'react'
import FormGroup from '@material-ui/core/FormGroup'
import FormControlLabel from '@material-ui/core/FormControlLabel'
import Checkbox from '@material-ui/core/Checkbox'
const FormFieldChecks = (props) => {
const [value, setValue] = useState(props.dflt ? props.dflt : [])
const toggle = (part) => {
let parts = value.slice(0)
let index = parts.indexOf(part)
if (index === -1) parts.push(part)
else parts.splice(index, 1)
setValue(parts)
props.updateValue(props.name, parts)
}
return (
<FormGroup>
{Object.keys(props.checks).map((i) => {
return (
<FormControlLabel
control={
<Checkbox
checked={value.indexOf(i) === -1 ? false : true}
onChange={() => toggle(i)}
value={i}
/>
}
label={props.checks[i]}
key={i}
className="po-list-item"
/>
)
})}
</FormGroup>
)
}
export default FormFieldChecks

View file

@ -1,21 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import FormFieldChecks from ".";
const props = {
updateValue: (name, value) =>
console.log(`Updated option ${name}, value is now: ${value}`),
name: "exampleChecksOption",
checks: {
apple: "Apple",
banana: "Banana",
cherry: "Cherry"
},
dflt: []
};
storiesOf("Low level/Form/FormFieldChecks", module)
.add("Basic", () => <FormFieldChecks {...props} />)
.add("Apple", () => <FormFieldChecks {...props} dflt={["apple"]} />)
.add("Banana", () => <FormFieldChecks {...props} dflt={["banana"]} />)
.add("Cherry", () => <FormFieldChecks {...props} dflt={["cherry"]} />);

View file

@ -1,32 +0,0 @@
import React, { useState, useEffect } from 'react'
import Radio from '@material-ui/core/Radio'
import RadioGroup from '@material-ui/core/RadioGroup'
import FormControlLabel from '@material-ui/core/FormControlLabel'
const FormFieldList = (props) => {
const [value, setValue] = useState(props.dflt)
useEffect(() => {
if (props.value !== value) setValue(props.value)
}, [props.value])
const update = (evt) => {
props.updateValue(props.name, evt.target.value)
setValue(evt.target.value)
}
return (
<RadioGroup onChange={update} value={value}>
{Object.keys(props.list).map((item, index) => (
<FormControlLabel
key={item}
control={<Radio color="primary" />}
value={item}
checked={value === item ? true : false}
label={props.list[item]}
className="po-list-item"
/>
))}
</RadioGroup>
)
}
export default FormFieldList

View file

@ -1,20 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import FormFieldList from ".";
const props = {
updateValue: (name, value) =>
console.log(`Updated option ${name}, value is now: ${value}`),
name: "exampleListOption",
list: {
apple: "Apple",
banana: "Banana",
cherry: "Cherry"
}
};
storiesOf("Low level/Form/FormFieldList", module)
.add("Basic", () => <FormFieldList {...props} />)
.add("Apple", () => <FormFieldList {...props} dflt="apple" />)
.add("Banana", () => <FormFieldList {...props} dflt="banana" />)
.add("Cherry", () => <FormFieldList {...props} dflt="cherry" />);

View file

@ -1,55 +0,0 @@
import React, { useState, useEffect } from 'react'
import TextField from '@material-ui/core/TextField'
import IconButton from '@material-ui/core/IconButton'
import InvalidIcon from '@material-ui/icons/Warning'
import InputAdornment from '@material-ui/core/InputAdornment'
import roundMm from '@freesewing/utils/roundMm'
import isDegMeasurement from '@freesewing/utils/isDegMeasurement'
import { injectIntl } from 'react-intl'
const FormFieldMeasurement = (props) => {
const initialValue = (name, val) => (isDegMeasurement(name) ? val : roundMm(val / 10))
const [value, setValue] = useState(initialValue(props.name, props.value))
useEffect(() => {
if (!isNaN(props.value))
setValue(isDegMeasurement(props.name) ? props.value : roundMm(props.value / 10))
}, [props.value])
const update = (evt) => {
setValue(evt.target.value)
if (evt.target.value.slice(-1) !== '.') {
props.updateValue(props.name, evt.target.value * (isDegMeasurement(props.name) ? 1 : 10))
}
}
const suffix = (name) => (isDegMeasurement(name) ? '°' : props.units === 'imperial' ? '"' : 'cm')
return (
<TextField
id={props.name}
fullWidth={true}
label={props.intl.formatMessage({ id: props.label })}
margin="normal"
variant="outlined"
value={value}
type="text"
onChange={update}
InputProps={{
endAdornment: (
<InputAdornment position="end">
{isNaN(props.value) ? (
<InvalidIcon color="error" />
) : (
<IconButton classes={{ label: 'color-success' }} size="small">
{suffix(props.name)}
</IconButton>
)}
</InputAdornment>
)
}}
/>
)
}
export default injectIntl(FormFieldMeasurement)

View file

@ -1,19 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import FormFieldSlider from ".";
const props = {
updateValue: (name, value) =>
console.log(`Updated option ${name}, value is now: ${value}`),
name: "exampleSliderOption"
};
storiesOf("Low level/Form/FormFieldSlider", module)
.add("Basic", () => <FormFieldSlider {...props} />)
.add("From 1 to 10", () => <FormFieldSlider {...props} min={1} max={10} />)
.add("Step: 1", () => (
<FormFieldSlider {...props} min={1} max={10} step={1} />
))
.add("Defalt: 7", () => (
<FormFieldSlider {...props} min={1} max={10} dflt={7} />
));

View file

@ -1,49 +0,0 @@
import React, { useState, useEffect } from 'react'
import Slider from '@material-ui/core/Slider'
import { withStyles } from '@material-ui/core/styles'
const PaddedSlider = withStyles({
container: {
padding: '25px 0'
},
track: { height: '4px' },
thumb: { width: '16px', height: '16px' }
})(Slider)
const FormFieldSlider = ({
min = 0,
max = 100,
step = 0.1,
label = false,
updateValue,
name,
value
}) => {
const [val, setVal] = useState(value)
useEffect(() => {
if (value !== val) setVal(value)
}, [value])
const update = (evt, newValue) => {
updateValue(name, newValue, evt)
setVal(newValue)
}
return (
<PaddedSlider
value={val}
min={min}
max={max}
step={step}
onChange={update}
onChangeCommitted={update}
classes={{
track: 'slider-track',
thumb: 'slider-thumb'
}}
aria-labelledby={label}
/>
)
}
export default FormFieldSlider

View file

@ -1,19 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import FormFieldSlider from ".";
const props = {
updateValue: (name, value) =>
console.log(`Updated option ${name}, value is now: ${value}`),
name: "exampleSliderOption"
};
storiesOf("Low level/Form/FormFieldSlider", module)
.add("Basic", () => <FormFieldSlider {...props} />)
.add("From 1 to 10", () => <FormFieldSlider {...props} min={1} max={10} />)
.add("Step: 1", () => (
<FormFieldSlider {...props} min={1} max={10} step={1} />
))
.add("Defalt: 7", () => (
<FormFieldSlider {...props} min={1} max={10} dflt={7} />
));

View file

@ -1 +0,0 @@
// noop

View file

@ -1,16 +0,0 @@
import React from 'react'
import Icon from '../Icon'
const Blockquote = (props) => {
const attr = Object.assign({}, props)
delete attr.type
delete attr.children
return (
<blockquote className={props.type || 'note'} {...attr}>
{props.children || null}
{props.type !== 'fixme' && <Icon icon={props.type} className={'icon ' + props.type} />}
</blockquote>
)
}
export default Blockquote

View file

@ -1,12 +0,0 @@
import React from 'react'
const Circle = (props) => (
<circle
cx={props.point.x}
cy={props.point.y}
r={props.point.attributes.get('data-circle')}
{...props.point.attributes.asPropsIfPrefixIs('data-circle-')}
/>
)
export default Circle

View file

@ -1,71 +0,0 @@
import React from 'react'
const style = ` style="fill: none; stroke: currentColor;" `
const grids = {
imperial: `
<pattern id="grid" height="25.4" width="25.4" patternUnits="userSpaceOnUse" key="grid">
<path class="gridline lg imperial" d="M 0 0 L 0 25.4 L 25.4 25.4" ${style} />
<path
class="gridline lg imperial"
d="M 12.7 0 L 12.7 25.4 M 0 12.7 L 25.4 12.7"
${style}
/>
<path
class="gridline sm imperial"
d="M 3.175 0 L 3.175 25.4 M 6.32 0 L 6.35 25.4 M 9.525 0 L 9.525 25.4 M 15.875 0 L 15.875 25.4 M 19.05 0 L 19.05 25.4 M 22.225 0 L 22.225 25.4"
${style}
/>
<path
class="gridline sm imperial"
d="M 0 3.175 L 25.4 3.175 M 0 6.32 L 25.4 6.35 M 0 9.525 L 25.4 9.525 M 0 15.875 L 25.4 15.875 M 0 19.05 L 25.4 19.05 M 0 22.225 L 25.4 22.225"
${style}
/>
</pattern>
`,
metric: `
<pattern id="grid" height="100" width="100" patternUnits="userSpaceOnUse" key="grid">
<path class="gridline lg metric" d="M 0 0 L 0 100 L 100 100" ${style} />
<path class="gridline metric" d="M 50 0 L 50 100 M 0 50 L 100 50" ${style} />
<path
class="gridline sm metric"
d="M 10 0 L 10 100 M 20 0 L 20 100 M 30 0 L 30 100 M 40 0 L 40 100 M 60 0 L 60 100 M 70 0 L 70 100 M 80 0 L 80 100 M 90 0 L 90 100"
${style}
/>
<path
class="gridline sm metric"
d="M 0 10 L 100 10 M 0 20 L 100 20 M 0 30 L 100 30 M 0 40 L 100 40 M 0 60 L 100 60 M 0 70 L 100 70 M 0 80 L 100 80 M 0 90 L 100 90"
${style}
/>
<path
class="gridline xs metric"
d="M 5 0 L 5 100 M 15 0 L 15 100 M 25 0 L 25 100 M 35 0 L 35 100 M 45 0 L 45 100 M 55 0 L 55 100 M 65 0 L 65 100 M 75 0 L 75 100 M 85 0 L 85 100 M 95 0 L 95 100"
${style}
/>
<path
class="gridline xs metric"
d="M 0 5 L 100 5 M 0 15 L 100 15 M 0 25 L 100 25 M 0 35 L 100 35 M 0 45 L 100 45 M 0 55 L 100 55 M 0 65 L 100 65 M 0 75 L 100 75 M 0 85 L 100 85 M 0 95 L 100 95"
${style}
/>
</pattern>
`
}
const Defs = (props) => {
let defs = props.svg.defs
if (props.settings.paperless) {
defs += grids[props.settings.units || 'metric']
for (let p in props.parts) {
let anchor = { x: 0, y: 0 }
if (typeof props.parts[p].points.gridAnchor !== 'undefined')
anchor = props.parts[p].points.gridAnchor
else if (typeof props.parts[p].points.anchor !== 'undefined')
anchor = props.parts[p].points.anchor
defs += `<pattern id="grid-${p}" key="grid-${p}" xlink:href="#grid" x="${anchor.x}" y="${anchor.y}" />`
}
}
return <defs dangerouslySetInnerHTML={{ __html: defs }} />
}
export default Defs

View file

@ -1,65 +0,0 @@
import React from 'react'
const DesignPath = (props) => {
let output = []
let i = 0
let from = null
for (let op of props.path.ops) {
let key = props.part + props.name + i
if (op.type === 'curve') {
output.push(
<path
key={key + 'cp1'}
d={`M ${from.x},${from.y} L ${op.cp1.x},${op.cp1.y}`}
className="design path cp"
/>
)
i++
output.push(
<path
key={key + 'cp2'}
d={`M ${op.to.x},${op.to.y} L ${op.cp2.x},${op.cp2.y}`}
className="design path cp"
/>
)
i++
output.push(
<circle
key={key + 'cpcirc1'}
cx={op.cp1.x}
cy={op.cp1.y}
r={3.5}
className="design path cp"
/>
)
i++
output.push(
<circle
key={key + 'cpcirc2'}
cx={op.cp2.x}
cy={op.cp2.y}
r={3.5}
className="design path cp"
/>
)
from = op.to
} else if (op.type !== 'close') from = op.to
}
output.push(
<path
key={props.part + props.name + 'dpath'}
d={props.path.asPathstring()}
onClick={() =>
props.raiseEvent('path', {
path: props.path,
name: props.name,
part: props.part
})
}
className="design hovertrap"
/>
)
return output
}
export default DesignPath

File diff suppressed because one or more lines are too long

View file

@ -1,22 +0,0 @@
import React from 'react'
const DesignPoint = (props) => (
<g className={props.className}>
<circle cx={props.point.x} cy={props.point.y} r="2" className="center" />
<circle
cx={props.point.x}
cy={props.point.y}
r="7.5"
className="hovertrap"
onClick={() =>
props.raiseEvent('point', {
point: props.point,
name: props.name,
part: props.part
})
}
/>
</g>
)
export default DesignPoint

File diff suppressed because one or more lines are too long

View file

@ -1,139 +0,0 @@
import React from 'react'
import Path from '../Path'
import Point from '../Point'
import Snippet from '../Snippet'
import { getProps } from '../utils'
const Part = (props) => {
const focusPoint = (point, i) => {
let p = props.part.points[point]
let pathString = `M ${p.x} ${props.part.topLeft.y} `
pathString += `L ${p.x} ${props.part.bottomRight.y} `
pathString += `M ${props.part.topLeft.x} ${p.y} `
pathString += `L ${props.part.bottomRight.x} ${p.y} `
let classes = 'focus point c' + (i % 4) // Cycle through 4 CSS classes
return (
<React.Fragment key={'fp' + point}>
<path d={pathString} className={classes} />
<circle
cx={p.x}
cy={p.y}
r="5"
className={classes}
onClick={() =>
props.raiseEvent('clearFocus', {
part: props.name,
type: 'points',
name: point
})
}
/>
</React.Fragment>
)
}
const focusCoords = (p, i) => {
let pathString = `M ${p.x} ${props.part.topLeft.y} `
pathString += `L ${p.x} ${props.part.bottomRight.y} `
pathString += `M ${props.part.topLeft.x} ${p.y} `
pathString += `L ${props.part.bottomRight.x} ${p.y} `
let classes = 'focus coords c' + (i % 4) // Cycle through 4 CSS classes
return (
<React.Fragment key={'cp' + i}>
<path d={pathString} className={classes} />
<circle
cx={p.x}
cy={p.y}
r="5"
className={classes}
onClick={() =>
props.raiseEvent('clearFocus', {
part: props.name,
type: 'coords',
data: p
})
}
/>
</React.Fragment>
)
}
let grid = props.paperless ? (
<rect
x={props.part.topLeft.x}
y={props.part.topLeft.y}
width={props.part.width}
height={props.part.height}
className="grid"
fill={'url(#grid-' + props.name + ')'}
/>
) : null
let focus = []
if (props.design) {
if (props.focus && typeof props.focus[props.name] !== 'undefined') {
for (let i in props.focus[props.name].points)
focus.push(focusPoint(props.focus[props.name].points[i], i))
for (let i in props.focus[props.name].paths) {
let name = props.focus[props.name].paths[i]
focus.push(
<path
key={'fpa-' + name}
d={props.part.paths[name].asPathstring()}
className={'focus path c' + (i % 4)}
onClick={() =>
props.raiseEvent('clearFocus', {
part: props.name,
type: 'paths',
name
})
}
/>
)
}
for (let i in props.focus[props.name].coords)
focus.push(focusCoords(props.focus[props.name].coords[i], i))
}
}
return (
<g {...getProps(props.part)} id={`part-${props.name}`}>
{grid}
{Object.keys(props.part.paths).map((name) => (
<Path
key={name}
name={name}
part={props.name}
language={props.language}
path={props.part.paths[name]}
focus={props.focus}
topLeft={props.part.topLeft}
bottomRight={props.part.bottomRight}
design={props.design}
raiseEvent={props.raiseEvent}
/>
))}
{Object.keys(props.part.points).map((name) => (
<Point
key={name}
name={name}
part={props.name}
language={props.language}
scale={props.scale}
point={props.part.points[name]}
focus={props.focus}
topLeft={props.part.topLeft}
bottomRight={props.part.bottomRight}
design={props.design}
raiseEvent={props.raiseEvent}
/>
))}
{Object.keys(props.part.snippets).map((name) => (
<Snippet key={name} name={name} snippet={props.part.snippets[name]} scale={props.scale} />
))}
{focus}
</g>
)
}
export default Part

View file

@ -1,20 +0,0 @@
import React from 'react'
import TextOnPath from '../TextOnPath'
import DesignPath from '../DesignPath'
import { getProps } from '../utils'
const Path = (props) => {
if (!props.path.render) return null
const output = []
const pathId = 'path-' + props.part + '-' + props.name
if (props.design) output.push(<DesignPath {...props} key={'dpa-' + props.name} />)
output.push(
<path id={pathId} key={pathId} d={props.path.asPathstring()} {...getProps(props.path)} />
)
if (props.path.attributes.get('data-text'))
output.push(<TextOnPath key={'text-on-path-' + props.name} pathId={pathId} {...props} />)
return output
}
export default Path

View file

@ -1,18 +0,0 @@
import React from 'react'
import DesignPoint from '../DesignPoint'
import Text from '../Text'
import Circle from '../Circle'
const Point = (props) => {
const output = []
if (props.design)
output.push(<DesignPoint {...props} key={'dp-' + props.name} className="design point" />)
if (props.point.attributes && props.point.attributes.get('data-text'))
output.push(<Text {...props} key={'point-' + props.name} />)
if (props.point.attributes && props.point.attributes.get('data-circle'))
output.push(<Circle point={props.point} key={'circle-' + props.name} />)
return output.length < 1 ? null : output
}
export default Point

View file

@ -1,27 +0,0 @@
import React from 'react'
import { getProps } from '../utils'
const Snippet = (props) => {
const snippetProps = {
xlinkHref: '#' + props.snippet.def,
x: props.snippet.anchor.x,
y: props.snippet.anchor.y
}
const scale = (props.snippet.attributes.get('data-scale') || 1) * (props.scale || 1)
const rotate = props.snippet.attributes.get('data-rotate')
if (scale || rotate) {
snippetProps.transform = ''
if (scale) {
snippetProps.transform += `translate(${snippetProps.x}, ${snippetProps.y}) `
snippetProps.transform += `scale(${scale}) `
snippetProps.transform += `translate(${snippetProps.x * -1}, ${snippetProps.y * -1}) `
}
if (rotate) {
snippetProps.transform += `rotate(${rotate}, ${snippetProps.x}, ${snippetProps.y}) `
}
}
return <use {...snippetProps} {...getProps(props.snippet)} />
}
export default Snippet

View file

@ -1,33 +0,0 @@
import React from 'react'
const Svg = ({
embed = true,
design = false,
language = 'en',
className = 'freesewing pattern draft',
style = {},
viewBox = false,
width,
height,
children
}) => {
let attributes = {
xmlns: 'http://www.w3.org/2000/svg',
'xmlns:svg': 'http://www.w3.org/2000/svg',
xmlnsXlink: 'http://www.w3.org/1999/xlink',
xmlLang: language,
viewBox: viewBox || `0 0 ${width} ${height}`,
className,
style
}
if (!embed) {
attributes.width = width + 'mm'
attributes.height = height + 'mm'
}
if (design) attributes.className += ' design'
return <svg {...attributes}>{children}</svg>
}
export default Svg

View file

@ -1,44 +0,0 @@
import React from 'react'
import { strings } from '@freesewing/i18n'
const Text = (props) => {
let text = []
// Handle translation
let translated = ''
for (let string of props.point.attributes.getAsArray('data-text')) {
if (strings[props.language]['plugin.' + string])
translated += strings[props.language]['plugin.' + string]
else translated += string.toString().replace(/&quot;/g, '"')
translated += ' '
}
// Handle muti-line text
if (translated.indexOf('\n') !== -1) {
let key = 0
let lines = translated.split('\n')
text.push(<tspan key={'tspan-' + key} dangerouslySetInnerHTML={{ __html: lines.shift()}} />)
let lineHeight = (props.point.attributes.get('data-text-lineheight') || 12) * (props.scale || 1)
for (let line of lines) {
key++
text.push(
<tspan
key={'tspan-' + key}
x={props.point.x}
dy={lineHeight}
dangerouslySetInnerHTML={{ __html: line.toString().replace(/&quot;/g, '"')}}
/>
)
}
} else text.push(<tspan key="tspan-1" dangerouslySetInnerHTML={{ __html: translated}} />)
return (
<text
x={props.point.x}
y={props.point.y}
{...props.point.attributes.asPropsIfPrefixIs('data-text-')}
>
{text}
</text>
)
}
export default Text

View file

@ -1,39 +0,0 @@
import React from 'react'
import { strings } from '@freesewing/i18n'
const TextOnPath = (props) => {
let text = []
// Handle translation
let translated = ''
for (let string of props.path.attributes.getAsArray('data-text')) {
if (strings[props.language]['plugin.' + string])
translated += strings[props.language]['plugin.' + string]
else translated += string.toString().replace(/&quot;/g, '"')
translated += ' '
}
let textPathProps = {
xlinkHref: '#' + props.pathId,
startOffset: '0%'
}
let align = props.path.attributes.get('data-text-class')
if (align && align.indexOf('center') > -1) textPathProps.startOffset = '50%'
else if (align && align.indexOf('right') > -1) textPathProps.startOffset = '100%'
/*
* We need dangerouslySetInnerHTML here to make sure we have a way to
* add whitespace that works both in the browser as in SVG.
* Whitespace = &#160;
*/
return (
<text>
<textPath {...textPathProps}>
<tspan
{...props.path.attributes.asPropsIfPrefixIs('data-text-')}
dangerouslySetInnerHTML={{ __html: translated }}
/>
</textPath>
</text>
)
}
export default TextOnPath

View file

@ -1,38 +0,0 @@
import React from 'react'
import Svg from './Svg'
import Defs from './Defs'
import Part from './Part'
const Draft = (props) => (
<Svg
embed={props.settings.embed}
width={props.width}
height={props.height}
language={props.settings.locale}
id={props.settings.idPrefix + 'svg'}
design={props.design || false}
style={props.style || {}}
viewBox={props.viewBox}
className={props.className || 'freesewing draft pattern'}
>
<Defs {...props} />
<g>
{Object.keys(props.parts).map((name) => (
<Part
part={props.parts[name]}
language={props.settings.locale}
paperless={props.settings.paperless}
units={props.settings.units}
scale={props.settings.scale}
key={name}
name={name}
focus={props.focus || false}
design={props.design || false}
raiseEvent={props.raiseEvent}
/>
))}
</g>
</Svg>
)
export default Draft

View file

@ -1,36 +0,0 @@
export const getProps = (obj) => {
/** I can't believe it but there seems to be no method on NPM todo this */
const cssKey = (key) => {
let chunks = key.split('-')
if (chunks.length > 1) {
key = chunks.shift()
for (let s of chunks) key += s.charAt(0).toUpperCase() + s.slice(1)
}
return key
}
const convert = (css) => {
let style = {}
let rules = css.split(';')
for (let rule of rules) {
let chunks = rule.split(':')
if (chunks.length === 2) style[cssKey(chunks[0].trim())] = chunks[1].trim()
}
return style
}
let rename = {
class: 'className',
'marker-start': 'markerStart',
'marker-end': 'markerEnd'
}
let props = {}
for (let key in obj.attributes.list) {
if (key === 'style') props[key] = convert(obj.attributes.get(key))
if (Object.keys(rename).indexOf(key) !== -1) props[rename[key]] = obj.attributes.get(key)
else if (key !== 'style') props[key] = obj.attributes.get(key)
}
return props
}

View file

@ -1,4 +0,0 @@
import React from 'react'
import PatternOptionBool from '../PatternOptionBool'
export default props => <PatternOptionBool {...props} name="advanced" />

View file

@ -1,22 +0,0 @@
import React from 'react'
import { storiesOf } from '@storybook/react'
import Sa from '.'
const props = {
raiseEvent: (type, data) => console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) => console.log(`Updated setting ${name}, value is now: ${value}`),
name: 'sa',
dflt: 'dflt',
title: 'Seam allowance',
desc:
"This is the seam allowance description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it.",
labels: {
none: 'No seam allowance',
dflt: 'Standard seam allowance',
custom: 'Custom seam allowance'
}
}
storiesOf('Low level/DraftSettingSa', module)
.add('Metric', () => <Sa {...props} units="metric" />)
.add('Imperial', () => <Sa {...props} units="imperial" />)

View file

@ -1,4 +0,0 @@
import React from "react";
import PatternOptionBool from "../PatternOptionBool";
export default props => <PatternOptionBool {...props} name="complete" />;

View file

@ -1,19 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Complete from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated setting ${name}, value is now: ${value}`),
dflt: true,
title: "Complete (known as 'detail' in the frontend) title",
desc:
"This is the complete description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it.",
labels: ["No", "Yes"]
};
storiesOf("Low level/DraftSettingComplete", module).add("Basic", () => (
<Complete {...props} />
));

View file

@ -1,4 +0,0 @@
import React from 'react'
import PatternOptionBool from '../PatternOptionBool'
export default (props) => <PatternOptionBool {...props} name="debug" />

View file

@ -1,22 +0,0 @@
import React from 'react'
import { storiesOf } from '@storybook/react'
import Sa from '.'
const props = {
raiseEvent: (type, data) => console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) => console.log(`Updated setting ${name}, value is now: ${value}`),
name: 'sa',
dflt: 'dflt',
title: 'Seam allowance',
desc:
"This is the seam allowance description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it.",
labels: {
none: 'No seam allowance',
dflt: 'Standard seam allowance',
custom: 'Custom seam allowance'
}
}
storiesOf('Low level/DraftSettingSa', module)
.add('Metric', () => <Sa {...props} units="metric" />)
.add('Imperial', () => <Sa {...props} units="imperial" />)

View file

@ -1,66 +0,0 @@
import React, { useState } from 'react'
import FormFieldList from '../../.form/FormFieldList'
import OptionPreamble from '../OptionPreamble'
import { injectIntl } from 'react-intl'
import { languages } from '@freesewing/i18n'
const DraftSettingLanguage = (props) => {
const [value, setValue] = useState(props.value === null ? props.intl.locale : props.value)
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => {
props.updateValue(props.name, newValue)
setValue(newValue)
}
const reset = () => {
setValue(props.dflt || props.intl.locale)
props.updateValue(props.name, props.dflt || props.intl.locale)
}
const patternReset = () => {
setValue(props.intl.locale)
props.updateValue(props.name, props.intl.locale)
}
const toggleExpanded = () => setExpanded(!expanded)
const option = (
<FormFieldList
name={props.name}
value={value}
dflt={props.dflt}
designDflt={props.intl.locale}
onChange={update}
label={'po-list-' + props.name}
updateValue={update}
list={languages}
/>
)
return (
<li>
<OptionPreamble
dflt={props.dflt}
designDflt={props.intl.locale}
value={value}
desc={props.desc}
title={props.title}
id={'po-list-' + props.name}
displayValue={languages[value]}
reset={reset}
patternReset={patternReset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() =>
props.raiseEvent('showHelp', {
type: 'draftSetting',
value: props.name
})
}
option={option}
noDocs={props.noDocs}
/>
</li>
)
}
export default injectIntl(DraftSettingLanguage)

View file

@ -1,27 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Lang from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated setting ${name}, value is now: ${value}`),
name: "exampleDraftSettingLanguage",
dflt: "en",
title:
"I am a language draft setting. This is my title. I'm wrapped in an h4 tag",
desc:
"This is the description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it.",
languages: {
de: "German",
en: "English",
es: "Spanish",
fr: "French",
nl: "Dutch"
}
};
storiesOf("Low level/DraftSettingLanguage", module).add("Basic", () => (
<Lang {...props} />
));

View file

@ -1,79 +0,0 @@
import React, { useState } from 'react'
import FormFieldSlider from '../../.form/FormFieldSlider'
import formatMm from '@freesewing/utils/formatMm'
import roundMm from '@freesewing/utils/roundMm'
import sliderStep from '@freesewing/utils/sliderStep'
import OptionPreamble from '../OptionPreamble'
const DraftSettingMargin = (props) => {
const [value, setValue] = useState(props.value === null ? props.dflt : props.value)
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => {
newValue = roundMm(newValue)
// Sometimes, when sliding, the rapid succession of updates
// causes a weird timing issue to result in a value that is NaN.
// If that's the case, just ignore this update and keep the
// previous one instead
if (!isNaN(newValue)) {
setValue(newValue)
if (evt.type !== 'mousemove') props.updateValue('margin', newValue)
} else {
props.updateValue('margin', value)
}
}
const reset = () => {
setValue(props.dflt)
props.updateValue('margin', props.dflt)
}
const patternReset = () => {
setValue(props.designDflt)
props.updateValue('margin', props.designDflt)
}
const toggleExpanded = () => setExpanded(!expanded)
let option = (
<FormFieldSlider
name="customSa"
value={value}
dflt={props.dflt}
label="po-slider-margin"
updateValue={update}
min={0}
max={25.4}
step={sliderStep[props.units]}
/>
)
return (
<li>
<OptionPreamble
dflt={props.dflt}
designDflt={props.designDflt}
value={value}
desc={props.desc}
title={props.title}
id="po-slider-margin"
displayValue={formatMm(value, props.units)}
displayFormat="html"
reset={reset}
patternReset={patternReset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() =>
props.raiseEvent('showHelp', {
type: 'draftSetting',
value: 'margin'
})
}
option={option}
noDocs={props.noDocs}
/>
</li>
)
}
export default DraftSettingMargin

View file

@ -1,19 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Margin from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated setting ${name}, value is now: ${value}`),
name: "margin",
dflt: 2,
title: "Margin",
desc:
"This is the margin description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it."
};
storiesOf("Low level/DraftSettingMargin", module)
.add("Metric", () => <Margin {...props} units="metric" />)
.add("Imperial", () => <Margin {...props} units="imperial" />);

View file

@ -1,107 +0,0 @@
import React, { useState } from 'react'
import FormFieldChecks from '../../.form/FormFieldChecks'
import FormFieldList from '../../.form/FormFieldList'
import OptionPreamble from '../OptionPreamble'
const DraftSettingOnly = props => {
const [value, setValue] = useState(
props.value === null ? 'dflt' : props.value === false ? 'dflt' : 'custom'
)
const [parts, setParts] = useState(value === 'custom' ? props.value : props.customDflt)
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => {
setValue(newValue)
if (newValue === 'dflt') props.updateValue('only', false)
else props.updateValue('only', parts)
}
let onlyDfltToggle = 'dflt'
if (props.dflt === 'custom' || Array.isArray(props.dflt)) onlyDfltToggle = 'custom'
const reset = () => {
setValue(onlyDfltToggle)
if (onlyDfltToggle === 'dflt') {
setParts([])
props.updateValue('only', false)
} else {
setParts(props.dflt)
props.updateValue('only', props.dflt)
}
}
const patternReset = () => {
setValue('dflt')
setParts([])
props.updateValue('only', false)
}
const updateCustom = (name, newValue, evt) => {
props.updateValue('only', newValue)
setParts(newValue)
}
const toggleExpanded = () => setExpanded(!expanded)
const list = {
dflt: props.labels.dflt,
custom: props.labels.custom
}
let option = (
<FormFieldList
name="only"
value={value}
dflt={props.dflt}
designDflt={props.dflt}
onChange={update}
label="po-list-only"
updateValue={update}
list={list}
/>
)
if (value === 'custom')
option = (
<React.Fragment>
{option}
<FormFieldChecks
checks={props.parts}
name="parts"
value={value}
dflt={parts}
onChange={updateCustom}
label="po-list-only"
updateValue={updateCustom}
list={list}
/>
</React.Fragment>
)
return (
<li>
<OptionPreamble
dflt={onlyDfltToggle}
designDflt="dflt"
sameButDifferent={props.dflt !== props.value}
value={value}
desc={props.desc}
title={props.title}
id="po-list-only"
displayValue={props.labels[value]}
reset={reset}
patternReset={patternReset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() =>
props.raiseEvent('showHelp', {
type: 'draftSetting',
value: 'only'
})
}
option={option}
noDocs={props.noDocs}
/>
</li>
)
}
export default DraftSettingOnly

View file

@ -1,38 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Sa from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated setting ${name}, value is now: ${value}`),
title: "Only (known as contents on the website) title",
desc:
"This is the only description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it.",
labels: {
dflt: "Default",
custom: "Custom"
},
dflt: "dflt",
customDflt: [],
parts: {
front: "Front",
back: "Back",
sleeve: "Sleeve",
pocket: "Pocket"
}
};
storiesOf("Low level/DraftSettingOnly", module)
.add("Default", () => <Sa {...props} />)
.add("Default, all parts preselected", () => (
<Sa {...props} customDflt={Object.keys(props.parts)} />
))
.add("Custom, some parts preselected", () => (
<Sa
{...props}
dflt="custom"
customDflt={Object.keys(props.parts).slice(2)}
/>
));

View file

@ -1,4 +0,0 @@
import React from "react";
import PatternOptionBool from "../PatternOptionBool";
export default props => <PatternOptionBool {...props} name="paperless" />;

View file

@ -1,20 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Paperless from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated setting ${name}, value is now: ${value}`),
name: "paperless",
dflt: false,
title: "Paperless title",
desc:
"This is the paperless description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it.",
labels: ["No", "Yes"]
};
storiesOf("Low level/DraftSettingPaperless", module).add("Basic", () => (
<Paperless {...props} />
));

View file

@ -1,133 +0,0 @@
import React, { useState } from 'react'
import FormFieldList from '../../.form/FormFieldList'
import FormFieldSlider from '../../.form/FormFieldSlider'
import formatMm from '@freesewing/utils/formatMm'
import roundMm from '@freesewing/utils/roundMm'
import defaultSa from '@freesewing/utils/defaultSa'
import sliderStep from '@freesewing/utils/sliderStep'
import OptionPreamble from '../OptionPreamble'
const DraftSettingSa = (props) => {
const [value, setValue] = useState(
props.value === defaultSa[props.units] ? 'dflt' : props.value === 0 ? 'none' : 'custom'
)
const [saValue, setSaValue] = useState(
props.value === null ? defaultSa[props.units] : props.value
)
const [customValue, setCustomValue] = useState(value === 'custom' ? props.value : 10)
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => {
switch (newValue) {
case 'none':
props.updateValue('sa', 0)
setValue(newValue)
setSaValue(0)
break
case 'dflt':
props.updateValue('sa', defaultSa[props.units])
setValue(newValue)
setSaValue(defaultSa[props.units])
break
default:
props.updateValue('sa', customValue)
setValue(newValue)
setSaValue(customValue)
break
}
}
let saDfltToggle = 'dflt'
if (props.dflt === 0) saDfltToggle = 'none'
if (props.dflt !== 10) saDfltToggle = 'custom'
const reset = () => {
setValue(saDfltToggle)
setSaValue(props.dflt)
props.updateValue('sa', props.dflt)
}
const patternReset = () => {
setValue('dflt')
setSaValue(defaultSa[props.units])
props.updateValue('sa', defaultSa[props.units])
}
const toggleExpanded = () => setExpanded(!expanded)
const updateCustom = (name, newValue, evt) => {
newValue = roundMm(newValue)
// Sometimes, when sliding, the rapid succession of updates
// causes a weird timing issue to result in a value that is NaN.
// If that's the case, just ignore this update and keep the
// previous one instead
if (!isNaN(newValue)) {
setSaValue(newValue)
setCustomValue(newValue)
if (evt.type !== 'mousemove') props.updateValue('sa', newValue)
} else {
props.updateValue('sa', customValue)
}
}
const list = {
none: props.labels.none,
dflt: props.labels.dflt,
custom: props.labels.custom
}
let option = (
<FormFieldList
name="sa"
value={value}
dflt={'dflt'}
onChange={update}
label="po-bool-sa"
updateValue={update}
list={list}
/>
)
if (value === 'custom')
option = (
<React.Fragment>
{option}
<FormFieldSlider
name="customSa"
value={saValue}
dflt={defaultSa[props.units]}
label="po-bool-sa"
updateValue={updateCustom}
min={0}
max={25.4}
step={sliderStep[props.units]}
/>
</React.Fragment>
)
return (
<li className={expanded ? 'expanded' : 'collapsed'}>
<OptionPreamble
dflt={saDfltToggle}
designDflt={'dflt'}
sameButDifferent={props.dflt !== props.value}
value={value}
desc={props.desc}
title={props.title}
id="po-list-sa"
displayValue={formatMm(saValue, props.units)}
displayFormat="html"
reset={reset}
patternReset={patternReset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() =>
props.raiseEvent('showHelp', {
type: 'draftSetting',
value: 'sa'
})
}
option={option}
noDocs={props.noDocs}
/>
</li>
)
}
export default DraftSettingSa

View file

@ -1,24 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Sa from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated setting ${name}, value is now: ${value}`),
name: "sa",
dflt: "dflt",
title: "Seam allowance",
desc:
"This is the seam allowance description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it.",
labels: {
none: "No seam allowance",
dflt: "Standard seam allowance",
custom: "Custom seam allowance"
}
};
storiesOf("Low level/DraftSettingSa", module)
.add("Metric", () => <Sa {...props} units="metric" />)
.add("Imperial", () => <Sa {...props} units="imperial" />);

View file

@ -1,76 +0,0 @@
import React, { useState } from 'react'
import FormFieldSlider from '../../.form/FormFieldSlider'
import sliderStep from '@freesewing/utils/sliderStep'
import OptionPreamble from '../OptionPreamble'
const DraftSettingScale = (props) => {
const [value, setValue] = useState(props.value === null ? props.dflt : props.value)
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => {
// Sometimes, when sliding, the rapid succession of updates
// causes a weird timing issue to result in a value that is NaN.
// If that's the case, just ignore this update and keep the
// previous one instead
if (!isNaN(newValue)) {
setValue(newValue)
if (evt.type !== 'mousemove') props.updateValue('scale', newValue)
} else {
props.updateValue('scale', value)
}
}
const reset = () => {
setValue(props.dflt)
props.updateValue('scale', props.dflt)
}
const patternReset = () => {
setValue(props.designDflt)
props.updateValue('scale', props.designDflt)
}
const toggleExpanded = () => setExpanded(!expanded)
let option = (
<FormFieldSlider
name="scale"
value={value}
dflt={props.dflt}
label="po-slider-scale"
updateValue={update}
min={0.05}
max={5}
step={sliderStep[props.units]}
/>
)
return (
<li>
<OptionPreamble
dflt={props.dflt}
designDflt={props.designDflt}
value={value}
desc={props.desc}
title={props.title}
id="po-slider-scale"
displayValue={value}
displayFormat="html"
reset={reset}
patternReset={patternReset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() =>
props.raiseEvent('showHelp', {
type: 'draftSetting',
value: 'scale'
})
}
option={option}
noDocs={props.noDocs}
/>
</li>
)
}
export default DraftSettingScale

View file

@ -1,18 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Scale from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated setting ${name}, value is now: ${value}`),
name: "scale",
dflt: 2,
title: "Scale",
desc:
"This is the scale description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it."
};
storiesOf("Low level/DraftSettingScale", module)
.add("Scale", () => <Scale {...props} />)

View file

@ -1,65 +0,0 @@
import React, { useState } from 'react'
import FormFieldList from '../../.form/FormFieldList'
import OptionPreamble from '../OptionPreamble'
const DraftSettingUnits = props => {
const [value, setValue] = useState(props.dflt)
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => {
props.updateValue(props.name, newValue)
setValue(newValue)
}
const reset = () => {
setValue(props.dflt)
props.updateValue(props.name, props.dflt)
}
const patternReset = () => {
setValue(props.designDflt)
props.updateValue(props.name, props.designDflt)
}
const toggleExpanded = () => setExpanded(!expanded)
let option = (
<FormFieldList
name="units"
value={value}
dflt={props.dflt}
onChange={update}
label="po-bool-units"
updateValue={update}
list={props.list}
/>
)
return (
<li>
<OptionPreamble
dflt={props.dflt}
designDflt={props.designDflt}
value={value}
desc={props.desc}
title={props.title}
id="po-list-units"
displayValue={props.list[value]}
reset={reset}
patternReset={patternReset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() =>
props.raiseEvent('showHelp', {
type: 'draftSetting',
value: 'units'
})
}
option={option}
noDocs={props.noDocs}
/>
</li>
)
}
export default DraftSettingUnits

View file

@ -1,23 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Units from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated setting ${name}, value is now: ${value}`),
name: "paperless",
dflt: "metric",
title: "Units title",
desc:
"This is the units description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it.",
list: {
metric: "Metric",
imperial: "Imperial"
}
};
storiesOf("Low level/DraftSettingUnits", module).add("Basic", () => (
<Units {...props} />
));

View file

@ -1,151 +0,0 @@
import React, { useState } from 'react'
import { FormattedMessage } from 'react-intl'
import DraftSettingSa from '../DraftSettingSa'
import DraftSettingScale from '../DraftSettingScale'
import DraftSettingMargin from '../DraftSettingMargin'
import DraftSettingComplete from '../DraftSettingComplete'
import DraftSettingPaperless from '../DraftSettingPaperless'
import DraftSettingAdvanced from '../DraftSettingAdvanced'
import DraftSettingDebug from '../DraftSettingDebug'
import DraftSettingUnits from '../DraftSettingUnits'
import DraftSettingLanguage from '../DraftSettingLanguage'
import DraftSettingOnly from '../DraftSettingOnly'
import RightIcon from '@material-ui/icons/KeyboardArrowRight'
const DraftSettings = ({
units = 'metric',
raiseEvent,
updateValue,
noDocs,
pattern,
config,
data = { settings: {} }
}) => {
// State
const [expanded, setExpanded] = useState([])
// Building blocks
const noyes = [<FormattedMessage id="app.no" />, <FormattedMessage id="app.yes" />]
const hideshow = [<FormattedMessage id="app.hide" />, <FormattedMessage id="app.show" />]
const metricimperial = {
metric: <FormattedMessage id="app.metricUnits" />,
imperial: <FormattedMessage id="app.imperialUnits" />
}
const labels = {
sa: {
none: <FormattedMessage id="app.noSeamAllowance" />,
dflt: <FormattedMessage id="app.standardSeamAllowance" />,
custom: <FormattedMessage id="app.customSeamAllowance" />
},
only: {
dflt: <FormattedMessage id="app.default" />,
custom: <FormattedMessage id="app.custom" />
},
paperless: noyes,
advanced: hideshow,
complete: hideshow,
debug: noyes
}
// Methods
const toggleGroup = (group) => {
let shown = expanded.slice(0)
let index = shown.indexOf(group)
if (index === -1) shown.push(group)
else shown.splice(index, 1)
setExpanded(shown)
}
const getDefault = (setting, pattern = false) => {
if (pattern && typeof pattern.settings[setting] !== 'undefined')
return pattern.settings[setting]
switch (setting) {
case 'sa':
return 10
case 'scale':
return 1
case 'only':
return 'dflt'
case 'complete':
return true
case 'margin':
return 2
case 'units':
return units
case 'debug':
return false
default:
return false
}
}
const addProps = (setting) => {
let childProps = {
raiseEvent,
updateValue,
units,
key: setting,
name: setting,
labels: labels[setting],
noDocs,
dflt: getDefault(setting, pattern),
designDflt: getDefault(setting)
}
childProps.title = <FormattedMessage id={'settings.' + setting + '.title'} />
childProps.desc = <FormattedMessage id={'settings.' + setting + '.description'} />
if (setting === 'only') {
childProps.customDflt = []
childProps.parts = {}
if (config.draftOrder) {
for (let part of config.draftOrder)
childProps.parts[part] = <FormattedMessage id={'parts.' + part} />
}
}
if (typeof data.settings[setting] !== 'undefined') childProps.value = data.settings[setting]
else childProps.value = null
return childProps
}
const groups = {
advanced: [
<DraftSettingLanguage {...addProps('locale')} />,
<DraftSettingUnits {...addProps('units')} list={metricimperial} />,
<DraftSettingComplete {...addProps('complete')} />,
<DraftSettingScale {...addProps('scale')} />,
<DraftSettingMargin {...addProps('margin')} />,
<DraftSettingOnly {...addProps('only')} />,
<DraftSettingDebug {...addProps('debug')} />
]
}
return (
<>
<ul className="config level-1 nogroups">
<DraftSettingSa {...addProps('sa')} />
<DraftSettingPaperless {...addProps('paperless')} />
<DraftSettingAdvanced {...addProps('advanced')} />
</ul>
{data.settings.advanced && (
<ul className="config level-1">
{Object.keys(groups).map((group) => {
let open = true
if (expanded.indexOf(group) === -1) open = false
let children = null
if (open) children = groups[group].map((component) => component)
return (
<React.Fragment key={group}>
<li className={open ? 'expanded' : 'collapsed'} key={group + '-ghead'}>
<span onClick={() => toggleGroup(group)}>
<RightIcon className={'icon-col-exp ' + (open ? 'expanded' : 'collapsed')} />
<FormattedMessage id={'optiongroups.' + group} />
</span>
</li>
{children}
</React.Fragment>
)
})}
</ul>
)}
</>
)
}
export default DraftSettings

View file

@ -1,29 +0,0 @@
import React from 'react'
import { storiesOf } from '@storybook/react'
import DraftSettings from '.'
const props = {
raiseEvent: (type, data) => console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (type, data) => console.log(`Update ${type} with new value`, data),
data: {
settings: {
options: {}
}
},
languages: {
de: 'German',
en: 'English',
es: 'Spanish',
fr: 'French',
nl: 'Dutch'
},
language: 'en'
}
storiesOf('Low level/DraftSettings', module)
.add('Simon metric', () => (
<DraftSettings pattern="simon" data={false} units="metric" {...props} />
))
.add('Trayvon imperial', () => (
<DraftSettings pattern="trayvon" data={false} units="imperial" {...props} />
))

View file

@ -1,104 +0,0 @@
import React from 'react'
import Pct from '../PatternOptionPercentage'
import Deg from '../PatternOptionDegree'
import Mm from '../PatternOptionMillimeter'
import Bool from '../PatternOptionBool'
import List from '../PatternOptionList'
import Count from '../PatternOptionCount'
import optionType from '@freesewing/utils/optionType'
import optionDefault from '@freesewing/utils/optionDefault'
import { FormattedMessage } from 'react-intl'
import { injectIntl } from 'react-intl'
import OptionSubGroup from '../OptionSubGroup'
const OptionGroup = (props) => {
const renderOption = (name, sub = false) => {
let option = props.config.options[name]
let type = optionType(option)
let stringKey = `options.${props.config.name}.${name}.`
let extraProps = {
name,
dflt: optionDefault(name, props.config.options[name], props.pattern),
designDflt: optionDefault(name, props.config.options[name]),
units: props.units,
updateValue: props.updateValue,
raiseEvent: props.raiseEvent,
title: <FormattedMessage id={stringKey + 'title'} />,
desc: <FormattedMessage id={stringKey + 'description'} />,
intl: props.intl,
pattern: props.config.name,
key: name,
noDocs: props.noDocs
}
if (
typeof props.data !== 'undefined' &&
typeof props.data.settings !== 'undefined' &&
typeof props.data.settings.options !== 'undefined' &&
typeof props.data.settings.options[name] !== 'undefined'
)
extraProps.value = props.data.settings.options[name]
else extraProps.value = null
let noyes = [<FormattedMessage id="app.no" />, <FormattedMessage id="app.yes" />]
switch (type) {
case 'pct':
return <Pct {...option} {...extraProps} />
break
case 'deg':
return <Deg {...option} {...extraProps} />
break
case 'mm':
return <Mm {...option} {...extraProps} units={props.units} />
break
case 'bool':
return <Bool {...option} {...extraProps} labels={noyes} />
break
case 'list':
return <List {...option} {...extraProps} />
break
case 'count':
return <Count {...option} {...extraProps} />
break
default:
throw new Error('Unsupported option type: ' + type)
}
}
return (
<>
{props.options.map(nameOrGroup => {
let output = []
if (typeof nameOrGroup === 'object') {
const group = nameOrGroup
// Subgroup
for (const subGroup in group) {
let children = []
for (const name of group[subGroup]) {
const option = props.config.options[name]
if (!props.pattern || !option.hide(props.pattern.settings.options)) {
children.push(renderOption(name, true))
}
}
output.push(
<OptionSubGroup
title={<FormattedMessage id={'optiongroups.' + subGroup} />}
children={children}
key={subGroup}
/>
)
}
} else {
const name = nameOrGroup
const option = props.config.options[name]
if (!props.pattern || !option.hide(props.pattern.settings.options)) {
output.push(renderOption(name))
}
}
return output
})}
</>
)
}
export default injectIntl(OptionGroup)

View file

@ -1,38 +0,0 @@
import React from 'react'
import { storiesOf } from '@storybook/react'
import OptionGroup from '.'
const options = {
armholeDrop: { pct: 10, min: 1, max: 75 },
backlineBend: { pct: 50, min: 50, max: 100 },
chestEase: { pct: 8, min: 0, max: 20 },
hipsEase: { pct: 8, min: 0, max: 20 },
lengthBonus: { pct: 10, min: -20, max: 60 },
necklineBend: { pct: 100, min: 40, max: 100 },
necklineDrop: { pct: 20, min: 10, max: 35 },
stretchFactor: { pct: 5, min: 0, max: 15 },
shoulderStrapWidth: { pct: 15, min: 10, max: 40 },
shoulderStrapPlacement: { pct: 40, min: 20, max: 80 }
}
const props = {
raiseEvent: (type, data) => console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (type, data) => console.log(`Update ${type} with new value`, data),
data: {
settings: {
options: {}
}
},
pattern: {
config: {
name: 'aaron',
options: options
}
},
dflts: { options: {} },
options: Object.keys(options)
}
storiesOf('Low level/OptionGroup', module).add('Simon metric', () => (
<OptionGroup pattern="simon" {...props} units="metric" />
))

View file

@ -1,106 +0,0 @@
import React from 'react'
import IconButton from '@material-ui/core/IconButton'
import RightIcon from '@material-ui/icons/KeyboardArrowRight'
import ResetIcon from '@material-ui/icons/SettingsBackupRestore'
import { injectIntl } from 'react-intl'
const OptionPreamble = ({
intl,
title,
desc,
dflt,
designDflt,
option,
value,
displayValue,
displayFormat = 'node',
sameButDifferent,
expanded,
toggleExpanded,
reset,
patternReset
}) => {
const styles = {
container: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center'
},
left: {
flexGrow: 1,
margin: '0 0.5rem'
},
right: {
margin: '0 5px 0 0 ',
textAlign: 'right'
}
}
const resetLabel = intl.formatMessage({
id: 'app.restoreDefaults',
defaultMessage: ' ♻️ '
})
const resetDesignLabel = intl.formatMessage({
id: 'app.restoreDesignDefaults',
defaultMessage: ' ♻️ '
})
const resetPatternLabel = intl.formatMessage({
id: 'app.restorePatternDefaults',
defaultMessage: ' ♻️ '
})
let pattern = false
if (dflt !== designDflt) pattern = true
let displayClass = value === dflt ? 'dflt' : 'custom'
if (pattern && value === designDflt) displayClass = 'p-dflt'
else if (pattern && sameButDifferent) displayClass = 'custom'
let dspValue = <span className={displayClass}>{displayValue}</span>
if (displayFormat === 'html')
dspValue = <span className={displayClass} dangerouslySetInnerHTML={{ __html: displayValue }} />
return (
<React.Fragment>
<div onClick={toggleExpanded} style={styles.container}>
<div style={styles.left}>
<RightIcon className={'icon-col-exp ' + (expanded ? 'expanded' : 'collapsed')} />
{title}
</div>
<div style={styles.right}>{dspValue}</div>
</div>
<div className={expanded ? 'col-exp expanded' : 'col-exp collapsed'}>
<div style={styles.container}>
<div style={styles.left}>
<p>{desc}</p>
</div>
<div style={styles.right}>
{pattern ? (
<IconButton
title={resetDesignLabel}
aria-label={resetDesignLabel}
color="primary"
disabled={value === designDflt ? true : false}
onClick={patternReset}
className="mini-icon-btn pattern"
>
<ResetIcon />
</IconButton>
) : null}
<IconButton
title={pattern ? resetPatternLabel : resetLabel}
aria-label={pattern ? resetPatternLabel : resetLabel}
color="primary"
disabled={value === dflt && !sameButDifferent ? true : false}
onClick={reset}
className={'mini-icon-btn' + (pattern ? ' pattern' : '')}
>
<ResetIcon />
</IconButton>
</div>
</div>
{option}
</div>
</React.Fragment>
)
}
export default injectIntl(OptionPreamble)

View file

@ -1,20 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Preamble from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
id: "example",
value: 120,
displayValue: "12cm",
name: "examplePctDegCountOption",
dflt: 50,
title: "This is the title. I'm wrapped in an h4 tag",
desc:
"This is the description. I'm wrapped in a p tag. This component is used within other components, and not very useful on its own."
};
storiesOf("Low level/OptionPreamble", module).add("Preamble", () => (
<Preamble {...props} />
));

View file

@ -1,18 +0,0 @@
import React, { useState } from 'react'
import RightIcon from '@material-ui/icons/KeyboardArrowRight'
const OptionSubGroup = ({ title, children }) => {
const [open, setOpen] = useState(false)
return (
<li>
<span className="subheading" onClick={() => setOpen(!open)}>
<RightIcon className={`icon-col-exp ${open ? 'expanded' : ''}`} />
{title}
</span>
{open && <ul className="config level-3">{children}</ul>}
</li>
)
}
export default OptionSubGroup

View file

@ -1,64 +0,0 @@
import React, { useState } from 'react'
import FormFieldBool from '../../.form/FormFieldBool'
import OptionPreamble from '../OptionPreamble'
const PatternOptionBool = (props) => {
const [value, setValue] = useState(props.value === null ? props.dflt : props.value)
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => {
props.updateValue(props.name, newValue)
setValue(newValue)
}
const reset = () => {
setValue(props.dflt)
props.updateValue(props.name, props.dflt)
}
const patternReset = () => {
setValue(props.designDflt)
props.updateValue(props.name, props.designDflt)
}
const toggleExpanded = () => setExpanded(!expanded)
let option = (
<FormFieldBool
name={props.name}
value={value}
dflt={props.dflt}
onChange={update}
label={'po-bool-' + props.name}
updateValue={update}
labels={props.labels}
/>
)
return (
<li className={expanded ? 'expanded' : 'collapsed'}>
<OptionPreamble
dflt={props.dflt}
designDflt={props.designDflt}
value={value}
desc={props.desc}
title={props.title}
id={'po-list-' + props.name}
displayValue={value ? props.labels[1] : props.labels[0]}
toggleExpanded={toggleExpanded}
expanded={expanded}
reset={reset}
patternReset={patternReset}
showHelp={() =>
props.raiseEvent('showHelp', {
type: 'draftSetting',
value: props.name
})
}
option={option}
noDocs={props.noDocs}
/>
</li>
)
}
export default PatternOptionBool

View file

@ -1,21 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Bool from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated pct/deg/count option ${name}, value is now: ${value}`),
name: "examplePatternOptionBool",
dflt: false,
title:
"I am a boolean pattern option. This is my title. I'm wrapped in an h4 tag",
desc:
"This is the description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it.",
labels: ["No", "Yes"]
};
storiesOf("Low level/PatternOptionBool", module)
.add("Basic", () => <Bool {...props} />)
.add("Yes as default", () => <Bool {...props} dflt={true} />);

View file

@ -1,4 +0,0 @@
import React from "react";
import PatternOptionPctDegCount from "../PatternOptionPctDegCount";
export default props => <PatternOptionPctDegCount {...props} type="count" />;

View file

@ -1,21 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Count from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated percentage option ${name}, value is now: ${value}`),
name: "exampleCountOption",
dflt: 50,
title:
"I am a pattern count option. This is my title. I'm wrapped in an h4 tag",
desc:
"This is the description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it."
};
storiesOf("Low level/PatternOptionCount", module)
.add("Basic", () => <Count {...props} />)
.add("From 20 to 80", () => <Count {...props} min={20} max={80} />)
.add("Step: 5", () => <Count {...props} step={5} />);

View file

@ -1,4 +0,0 @@
import React from "react";
import PatternOptionPctDegCount from "../PatternOptionPctDegCount";
export default props => <PatternOptionPctDegCount {...props} type="deg" />;

View file

@ -1,22 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Pct from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated degree option ${name}, value is now: ${value}`),
name: "exampleDegreeOption",
dflt: 45,
max: 90,
title:
"I am a pattern degree option. This is my title. I'm wrapped in an h4 tag",
desc:
"This is the description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it."
};
storiesOf("Low level/PatternOptionDegree", module)
.add("Basic", () => <Pct {...props} />)
.add("From 30 to 45", () => <Pct {...props} min={30} max={45} />)
.add("Step: 10", () => <Pct {...props} step={10} max={180} dflt={90} />);

View file

@ -1,72 +0,0 @@
import React, { useState } from 'react'
import FormFieldList from '../../.form/FormFieldList'
import OptionPreamble from '../OptionPreamble'
const PatternOptionList = (props) => {
const [value, setValue] = useState(props.dflt)
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => {
props.updateValue(props.name, newValue)
setValue(newValue)
}
const reset = () => {
setValue(props.dflt)
props.updateValue(props.name, props.dflt)
}
const patternReset = () => {
setValue(props.designDflt)
props.updateValue(props.name, props.designDflt)
}
const toggleExpanded = () => setExpanded(!expanded)
// Add translations
let stringKey = `options.${props.pattern}.${props.name}.options.`
let list = {}
for (let item of props.list)
list[item] = props.intl.formatMessage({
id: stringKey + item,
defaultMessage: item
})
let option = (
<FormFieldList
name={props.name}
value={value}
dflt={props.dflt}
designDflt={props.designDflt}
onChange={update}
label={'po-list-' + props.name}
updateValue={update}
list={list}
/>
)
return (
<li className={expanded ? 'expanded' : 'collapsed'}>
<OptionPreamble
dflt={props.dflt}
value={value}
desc={props.desc}
title={props.title}
id={'po-list-' + props.name}
displayValue={list[value]}
reset={reset}
patternReset={patternReset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() =>
props.raiseEvent('showHelp', {
type: 'patternOption',
value: props.name
})
}
option={option}
noDocs={props.noDocs}
/>
</li>
)
}
export default PatternOptionList

View file

@ -1,25 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import List from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated pct/deg/count option ${name}, value is now: ${value}`),
name: "exampleListOption",
dflt: "banana",
title:
"I am a pattern list option. This is my title. I'm wrapped in an h4 tag",
desc:
"This is the description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it.",
list: {
apple: "Apple",
banana: "Banana",
cherry: "Cherry"
}
};
storiesOf("Low level/PatternOptionList", module).add("Basic", () => (
<List {...props} />
));

View file

@ -1,87 +0,0 @@
import React, { useState } from 'react'
import sliderStep from '@freesewing/utils/sliderStep'
import roundMm from '@freesewing/utils/roundMm'
import roundMmUp from '@freesewing/utils/roundMmUp'
import roundMmDown from '@freesewing/utils/roundMmDown'
import formatMm from '@freesewing/utils/formatMm'
import FormFieldSlider from '../../.form/FormFieldSlider'
import OptionPreamble from '../OptionPreamble'
const PatternOptionMillimeter = ({
title = false,
desc = false,
units = 'metric',
min = 0,
max = 100,
updateValue,
name,
dflt,
value,
raiseEvent,
noDocs
}) => {
const [val, setVal] = useState(value === null ? dflt : value)
const [previousValue, setPreviousValue] = useState(dflt)
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => {
newValue = roundMm(newValue, units)
// Sometimes, when sliding, the rapid succession of updates
// causes a weird timing issue to result in a value that is NaN.
// If that's the case, just ignore this update and keep the
// previous one instead
if (!isNaN(newValue)) {
setVal(newValue)
if (evt.type !== 'mousemove') updateValue(name, newValue)
} else {
if (evt.type !== 'mousemove') updateValue(name, val)
}
}
const reset = () => {
setVal(dflt)
updateValue(name, dflt)
}
const toggleExpanded = () => setExpanded(!expanded)
let option = (
<FormFieldSlider
name={name}
value={val}
min={roundMmUp(min, units)}
max={roundMmDown(max, units)}
step={sliderStep[units]}
onChange={update}
label={'po-mm-' + name}
updateValue={update}
/>
)
return (
<li className={expanded ? 'expanded' : 'collapsed'}>
<OptionPreamble
dflt={dflt}
value={val}
desc={desc}
title={title}
id={'po-mm-' + name}
displayValue={formatMm(val, units)}
displayFormat="html"
reset={reset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() =>
raiseEvent('showHelp', {
type: 'patternOption',
value: name
})
}
option={option}
noDocs={noDocs}
/>
</li>
)
}
export default PatternOptionMillimeter

View file

@ -1,34 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Mm from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated millimeter option ${name}, value is now: ${value}`),
name: "examplePercentageOption",
dflt: 50,
units: "metric",
title:
"I am a pattern millimeter option. This is my title. I'm wrapped in an h4 tag",
desc:
"This is the description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it (we've made it green in this example)."
};
const maxNotOnStep =
"Since our step is 0.1mm and our max value is 124.86 mm, it falls in between two steps (124.8mm and 124.9mm). Picking the max value would result in the rounded max value of 124.9mm, which is outside our max boundary. So we always round the max value down to the closest step. Also note that while the displayed value rounds to mm, under the hood we use 1/10th of a mm and the actual value passed for the max here is not 12.5cm but 124.8mm (12.48cm)";
const minNotOnStep =
"Since our step is 0.1mm and our min value is 24.06 mm, it falls in between two steps (24mm and 24.1mm). Picking the min value would result in the rounded min value of 24mm, which is outside our min boundary. So we always round the min value up to the closest step. Also note that while the displayed value rounds to mm, under the hood we use 1/10th of a mm and the actual value passed for the min here is not 2.4cm but 24.1mm (2.41cm)";
storiesOf("Low level/PatternOptionMillimeter", module)
.add("Metric", () => <Mm {...props} />)
.add("Max: 12.486 cm", () => (
<Mm {...props} max={124.86} desc={maxNotOnStep} />
))
.add("Min: 2.406 cm", () => <Mm {...props} min={24.06} desc={minNotOnStep} />)
.add("Negative", () => <Mm {...props} min={-40} dflt={0} />)
.add("Imperial", () => <Mm {...props} units="imperial" />)
.add("Imperial negative", () => (
<Mm {...props} min={-40} dflt={0} units="imperial" />
));

View file

@ -1,97 +0,0 @@
import React, { useState } from 'react'
import FormFieldSlider from '../../.form/FormFieldSlider'
import OptionPreamble from '../OptionPreamble'
const PatternOptionPctDegCount = ({
min = 0,
max = 100,
step = 0.1,
type = 'pct',
updateValue,
name,
dflt,
designDflt,
title,
desc,
value,
raiseEvent,
noDocs
}) => {
let factor = 1
if (type === 'pct') factor = 100
const round = (val) => Math.round(val * 10) / 10
const [val, setVal] = useState(value === null ? dflt : round(value * factor))
const [previousValue, setPreviousValue] = useState(value === null ? dflt : round(value * factor))
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => {
newValue = round(newValue)
// Sometimes, when sliding, the rapid succession of updates
// causes a weird timing issue to result in a value that is NaN.
// If that's the case, just ignore this update and keep the
// previous one instead
if (!isNaN(newValue)) {
setVal(newValue)
if (evt.type !== 'mousemove') updateValue(name, newValue / factor)
} else {
if (evt.type !== 'mousemove') updateValue(name, value / factor)
}
}
const reset = () => {
setVal(dflt)
updateValue(name, dflt / factor)
}
const patternReset = () => {
setVal(designDflt)
updateValue(name, designDflt / factor)
}
const toggleExpanded = () => setExpanded(!expanded)
let unit = ''
if (type === 'pct') unit = '%'
if (type === 'deg') unit = '°'
let option = (
<FormFieldSlider
name={name}
value={val}
min={min}
max={max}
step={type === 'count' ? 1 : step}
onChange={update}
label={'po-' + type + '-' + name}
updateValue={update}
/>
)
return (
<li className={expanded ? 'expanded' : 'collapsed'}>
<OptionPreamble
dflt={dflt}
designDflt={designDflt}
value={val}
desc={desc}
title={title}
id={'po-' + type + '-' + name}
displayValue={val + unit}
reset={reset}
patternReset={patternReset}
toggleExpanded={toggleExpanded}
expanded={expanded}
showHelp={() =>
raiseEvent('showHelp', {
type: 'patternOption',
value: name
})
}
option={option}
noDocs={noDocs}
/>
</li>
)
}
export default PatternOptionPctDegCount

View file

@ -1,26 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import PctDegCount from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated pct/deg/count option ${name}, value is now: ${value}`),
name: "examplePctDegCountOption",
dflt: 50,
title: "This is the title. I'm wrapped in an h4 tag",
desc:
"This is the description. I'm wrapped in a p tag. This component is the base for the percentage, degree, and count pattern options."
};
storiesOf("Low level/PatternOptionPctDegCount", module).add(
"Percentage",
() => <PctDegCount {...props} type="pct" />
);
storiesOf("Low level/PatternOptionPctDegCount", module).add("Degree", () => (
<PctDegCount {...props} type="deg" />
));
storiesOf("Low level/PatternOptionPctDegCount", module).add("Count", () => (
<PctDegCount {...props} type="count" />
));

View file

@ -1,4 +0,0 @@
import React from "react";
import PatternOptionPctDegCount from "../PatternOptionPctDegCount";
export default props => <PatternOptionPctDegCount {...props} type="pct" />;

View file

@ -1,21 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Pct from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (name, value) =>
console.log(`Updated percentage option ${name}, value is now: ${value}`),
name: "examplePercentageOption",
dflt: 50,
title:
"I am a pattern percentage option. This is my title. I'm wrapped in an h4 tag",
desc:
"This is the description. I'm wrapped in a p tag. This component only sets the CSS class on a non-default value. It's up to you to supply the CSS to style it."
};
storiesOf("Low level/PatternOptionPercentage", module)
.add("Basic", () => <Pct {...props} />)
.add("From 20 to 80", () => <Pct {...props} min={20} max={80} />)
.add("Step: 5", () => <Pct {...props} step={5} />);

View file

@ -1,60 +0,0 @@
import React, { useState } from 'react'
import OptionGroup from '../OptionGroup'
import { FormattedMessage } from 'react-intl'
import RightIcon from '@material-ui/icons/KeyboardArrowRight'
const PatternOptions = (props) => {
const [expanded, setExpanded] = useState([])
const toggleGroup = (group) => {
let shown = expanded.slice(0)
let index = shown.indexOf(group)
if (index === -1) shown.push(group)
else shown.splice(index, 1)
setExpanded(shown)
}
const renderGroup = (group) => {
let open = true
if (expanded.indexOf(group) === -1) open = false
let output = []
let children = null
if (expanded.indexOf(group) !== -1)
children = (
<ul className="config level-2">
<OptionGroup
noDocs={props.noDocs}
key={group + '-group'}
units={props.units}
config={props.config}
data={props.data}
pattern={props.pattern}
options={props.config.optionGroups[group]}
updateValue={props.updateValue}
raiseEvent={props.raiseEvent}
/>
</ul>
)
output.push(
<li className={open ? 'expanded' : 'collapsed'} key={group + '-ghead'}>
<span onClick={() => toggleGroup(group)}>
<RightIcon className={'icon-col-exp ' + (open ? 'expanded' : 'collapsed')} />
<FormattedMessage id={'optiongroups.' + group} />
</span>
{children}
</li>
)
return output
}
const children = []
for (let group in props.config.optionGroups) {
if (props.data.settings.advanced || group !== 'advanced') {
children.push(renderGroup(group))
}
}
return <ul className="config level-1">{children}</ul>
}
export default PatternOptions

View file

@ -1,21 +0,0 @@
import React from 'react'
import { storiesOf } from '@storybook/react'
import PatternOptions from '.'
const props = {
raiseEvent: (type, data) => console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (type, data) => console.log(`Update ${type} with new value`, data),
data: {
settings: {
options: {}
}
}
}
storiesOf('Low level/PatternOptions', module)
.add('Simon metric', () => (
<PatternOptions pattern="simon" data={false} units="metric" {...props} />
))
.add('Trayvon imperial', () => (
<PatternOptions design="trayvon" data={false} units="imperial" {...props} />
))

View file

@ -1,62 +0,0 @@
import React from 'react'
import { FormattedMessage } from 'react-intl'
import PatternOptions from './PatternOptions'
import DraftSettings from './DraftSettings'
import TuneIcon from '@material-ui/icons/Tune'
import WrenchIcon from '@material-ui/icons/Build'
import PlayIcon from '@material-ui/icons/PlayCircleOutline'
const DraftConfigurator = ({
noDocs = false,
units = 'metric',
config = {},
data = {},
pattern,
updatePatternData,
raiseEvent,
actions = false
}) => {
let childProps = {
noDocs,
units,
config,
data,
pattern,
raiseEvent
}
return (
<ul id="draft-config">
{actions && (
<li>
<span>
<PlayIcon />
<FormattedMessage id="app.actions" />
</span>
<ul className="config level-1">{actions}</ul>
</li>
)}
<li>
<span>
<TuneIcon />
<FormattedMessage id="app.designOptions" />
</span>
<PatternOptions
{...childProps}
updateValue={(name, value) => updatePatternData(value, 'settings', 'options', name)}
/>
</li>
<li>
<span>
<WrenchIcon />
<FormattedMessage id="app.patternOptions" />
</span>
<DraftSettings
{...childProps}
updateValue={(name, value) => updatePatternData(value, 'settings', name)}
/>
</li>
</ul>
)
}
export default DraftConfigurator

View file

@ -1,20 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import GistConfigurator from ".";
//import { IntlProvider } from "react-intl";
//import { strings } from "@freesewing/i18n";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (type, data) =>
console.log(`Update ${type} with new value`, data)
};
storiesOf("DraftConfigurator", module)
.add("Simon metric", () => (
<GistConfigurator pattern="simon" {...props} units="metric" />
))
.add("Trayvon imperial", () => (
<GistConfigurator pattern="trayvon" {...props} units="imperial" />
));

View file

@ -1,119 +0,0 @@
import React, { useState } from 'react'
import examples from '@freesewing/examples'
import rendertest from '@freesewing/rendertest'
import tutorial from '@freesewing/tutorial'
import Draft from '../Draft'
import Design from '../Workbench/Design'
import IconButton from '@material-ui/core/IconButton'
import ResetIcon from '@material-ui/icons/SettingsBackupRestore'
import Switch from '@material-ui/core/Switch'
import { withStyles } from '@material-ui/core/styles'
const PurpleSwitch = withStyles({
switchBase: {
color: '#868e96',
'&$checked': {
color: '#845ef7'
},
'&$checked + $track': {
backgroundColor: '#9775fa'
}
},
checked: {},
track: {
backgroundColor: '#868e96'
}
})(Switch)
const Example = ({
pattern = 'examples',
design = true,
caption = '',
children=null,
options = {},
settings,
part = '',
sample
}) => {
const [designMode, setDesignMode] = useState(false)
const [focus, setFocus] = useState(null)
if (caption) console.log('Passing the caption prop to @freesewing/components/Example is deprecated. See: https://github.com/freesewing/freesewing/issues/1043')
const raiseEvent = (type, data) => {
if (type === 'clearFocusAll') return setFocus(null)
let f = {}
if (focus !== null) f = { ...focus }
if (typeof f[data.part] === 'undefined') f[data.part] = { paths: [], points: [], coords: [] }
if (type === 'point') f[data.part].points.push(data.name)
else if (type === 'path') f[data.part].paths.push(data.name)
else if (type === 'coords') f[data.part].coords.push(data.coords)
else if (type === 'clearFocus') {
let i = focus[data.part][data.type].indexOf(data.name)
f[data.part][data.type].splice(i, 1)
}
setFocus(f)
}
let focusCount = 0
if (focus !== null) {
for (let p of Object.keys(focus)) {
for (let i in focus[p].points) focusCount++
for (let i in focus[p].paths) focusCount++
for (let i in focus[p].coords) focusCount++
}
}
const patterns = {
examples,
rendertest,
tutorial
}
settings = {
options: { ...options },
measurements: { head: 390 },
...settings
}
if (part !== '') settings.only = [part]
const patternInstance = new patterns[pattern](settings)
if (sample) patternInstance.sample()
else patternInstance.draft()
const patternProps = patternInstance.getRenderProps()
return (
<figure className={designMode ? 'design example' : 'example'}>
<div className="example">
<div className="actions">
<IconButton
disabled={!designMode}
color="primary"
onClick={() => raiseEvent('clearFocusAll', null)}
>
<ResetIcon />
</IconButton>
<PurpleSwitch
checked={designMode}
onChange={() => setDesignMode(!designMode)}
value={designMode}
color="primary"
className="switch-accent"
/>
</div>
<Draft {...patternProps} design={designMode} focus={focus} raiseEvent={raiseEvent} />
</div>
<figcaption>{caption || children}</figcaption>
{designMode && (
<div className="design">
<Design
focus={focus}
design={designMode}
raiseEvent={raiseEvent}
parts={patternProps.parts}
/>
</div>
)}
</figure>
)
}
export default Example

View file

@ -1,59 +0,0 @@
// These are from simpleicons.org - thanks guys!
const discord =
'M20.222 0c1.406 0 2.54 1.137 2.607 2.475V24l-2.677-2.273-1.47-1.338-1.604-1.398.67 2.205H3.71c-1.402 0-2.54-1.065-2.54-2.476V2.48C1.17 1.142 2.31.003 3.715.003h16.5L20.222 0zm-6.118 5.683h-.03l-.202.2c2.073.6 3.076 1.537 3.076 1.537-1.336-.668-2.54-1.002-3.744-1.137-.87-.135-1.74-.064-2.475 0h-.2c-.47 0-1.47.2-2.81.735-.467.203-.735.336-.735.336s1.002-1.002 3.21-1.537l-.135-.135s-1.672-.064-3.477 1.27c0 0-1.805 3.144-1.805 7.02 0 0 1 1.74 3.743 1.806 0 0 .4-.533.805-1.002-1.54-.468-2.14-1.404-2.14-1.404s.134.066.335.2h.06c.03 0 .044.015.06.03v.006c.016.016.03.03.06.03.33.136.66.27.93.4.466.202 1.065.403 1.8.536.93.135 1.996.2 3.21 0 .6-.135 1.2-.267 1.8-.535.39-.2.87-.4 1.397-.737 0 0-.6.936-2.205 1.404.33.466.795 1 .795 1 2.744-.06 3.81-1.8 3.87-1.726 0-3.87-1.815-7.02-1.815-7.02-1.635-1.214-3.165-1.26-3.435-1.26l.056-.02zm.168 4.413c.703 0 1.27.6 1.27 1.335 0 .74-.57 1.34-1.27 1.34-.7 0-1.27-.6-1.27-1.334.002-.74.573-1.338 1.27-1.338zm-4.543 0c.7 0 1.266.6 1.266 1.335 0 .74-.57 1.34-1.27 1.34-.7 0-1.27-.6-1.27-1.334 0-.74.57-1.338 1.27-1.338z'
const github =
'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'
const twitter =
'M23.954 4.569c-.885.389-1.83.654-2.825.775 1.014-.611 1.794-1.574 2.163-2.723-.951.555-2.005.959-3.127 1.184-.896-.959-2.173-1.559-3.591-1.559-2.717 0-4.92 2.203-4.92 4.917 0 .39.045.765.127 1.124C7.691 8.094 4.066 6.13 1.64 3.161c-.427.722-.666 1.561-.666 2.475 0 1.71.87 3.213 2.188 4.096-.807-.026-1.566-.248-2.228-.616v.061c0 2.385 1.693 4.374 3.946 4.827-.413.111-.849.171-1.296.171-.314 0-.615-.03-.916-.086.631 1.953 2.445 3.377 4.604 3.417-1.68 1.319-3.809 2.105-6.102 2.105-.39 0-.779-.023-1.17-.067 2.189 1.394 4.768 2.209 7.557 2.209 9.054 0 13.999-7.496 13.999-13.986 0-.209 0-.42-.015-.63.961-.689 1.8-1.56 2.46-2.548l-.047-.02z'
const instagram =
'M12 0C8.74 0 8.333.015 7.053.072 5.775.132 4.905.333 4.14.63c-.789.306-1.459.717-2.126 1.384S.935 3.35.63 4.14C.333 4.905.131 5.775.072 7.053.012 8.333 0 8.74 0 12s.015 3.667.072 4.947c.06 1.277.261 2.148.558 2.913.306.788.717 1.459 1.384 2.126.667.666 1.336 1.079 2.126 1.384.766.296 1.636.499 2.913.558C8.333 23.988 8.74 24 12 24s3.667-.015 4.947-.072c1.277-.06 2.148-.262 2.913-.558.788-.306 1.459-.718 2.126-1.384.666-.667 1.079-1.335 1.384-2.126.296-.765.499-1.636.558-2.913.06-1.28.072-1.687.072-4.947s-.015-3.667-.072-4.947c-.06-1.277-.262-2.149-.558-2.913-.306-.789-.718-1.459-1.384-2.126C21.319 1.347 20.651.935 19.86.63c-.765-.297-1.636-.499-2.913-.558C15.667.012 15.26 0 12 0zm0 2.16c3.203 0 3.585.016 4.85.071 1.17.055 1.805.249 2.227.415.562.217.96.477 1.382.896.419.42.679.819.896 1.381.164.422.36 1.057.413 2.227.057 1.266.07 1.646.07 4.85s-.015 3.585-.074 4.85c-.061 1.17-.256 1.805-.421 2.227-.224.562-.479.96-.899 1.382-.419.419-.824.679-1.38.896-.42.164-1.065.36-2.235.413-1.274.057-1.649.07-4.859.07-3.211 0-3.586-.015-4.859-.074-1.171-.061-1.816-.256-2.236-.421-.569-.224-.96-.479-1.379-.899-.421-.419-.69-.824-.9-1.38-.165-.42-.359-1.065-.42-2.235-.045-1.26-.061-1.649-.061-4.844 0-3.196.016-3.586.061-4.861.061-1.17.255-1.814.42-2.234.21-.57.479-.96.9-1.381.419-.419.81-.689 1.379-.898.42-.166 1.051-.361 2.221-.421 1.275-.045 1.65-.06 4.859-.06l.045.03zm0 3.678c-3.405 0-6.162 2.76-6.162 6.162 0 3.405 2.76 6.162 6.162 6.162 3.405 0 6.162-2.76 6.162-6.162 0-3.405-2.76-6.162-6.162-6.162zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm7.846-10.405c0 .795-.646 1.44-1.44 1.44-.795 0-1.44-.646-1.44-1.44 0-.794.646-1.439 1.44-1.439.793-.001 1.44.645 1.44 1.439z'
const google =
'M 12.25009,0 C 7.5567085,0 3.5033589,2.69334 1.530043,6.613315 0.71674427,8.240005 0.25,10.06676 0.25,12.00009 c 0,1.93333 0.46674427,3.759905 1.280043,5.386595 C 3.5033589,21.30666 7.5567085,24 12.25009,24 c 3.239959,0 5.959944,-1.066635 7.94668,-2.906575 2.266629,-2.093365 3.573349,-5.173415 3.573349,-8.826735 0,-0.98666 -0.08023,-1.70661 -0.253496,-2.453265 l -11.266533,0 0,4.45322 6.613137,0 c -0.133283,1.106705 -0.853233,2.77333 -2.453266,3.89327 -1.013315,0.706675 -2.373243,1.199975 -4.159871,1.199975 -3.173318,0 -5.8666835,-2.09327 -6.826777,-4.986605 -0.2533286,-0.746655 -0.399991,-1.54657 -0.399991,-2.373195 0,-0.82672 0.1467055,-1.62672 0.386706,-2.373375 C 6.3834495,6.73338 9.076772,4.63993 12.25009,4.63993 c 2.253301,0 3.773228,0.973465 4.639932,1.786855 L 20.27666,3.12004 C 18.196718,1.186705 15.490049,0 12.25009,0 Z'
const facebook =
'M22.676 0H1.324C.593 0 0 .593 0 1.324v21.352C0 23.408.593 24 1.324 24h11.494v-9.294H9.689v-3.621h3.129V8.41c0-3.099 1.894-4.785 4.659-4.785 1.325 0 2.464.097 2.796.141v3.24h-1.921c-1.5 0-1.792.721-1.792 1.771v2.311h3.584l-.465 3.63H16.56V24h6.115c.733 0 1.325-.592 1.325-1.324V1.324C24 .593 23.408 0 22.676 0'
const reddit = 'M 11.710829,0.00384705 C 5.0683862,0.16990815 -0.16221405,5.6505729 0.00384705,12.293016 0.16990814,18.686369 5.3178021,23.833614 11.628124,24.082706 18.270567,24.248767 23.833939,19.018167 24,12.375723 V 11.710829 C 23.833939,5.0683862 18.353273,-0.16221404 11.710829,0.00384705 Z m 5.187788,5.10021625 c 0.15698,0.00649 0.313636,0.048326 0.458939,0.1313569 0.581214,0.3321223 0.912687,1.0793971 0.580565,1.660611 C 17.605998,7.4772452 16.858724,7.808718 16.27751,7.4765965 15.862357,7.3105352 15.614238,6.8947339 15.614238,6.3965506 L 13.038995,5.8159854 12.208689,9.55236 c 1.826672,0.08303 3.48858,0.664893 4.651007,1.495199 0.664245,-0.664245 1.826673,-0.664245 2.490917,0 0.332122,0.332121 0.49786,0.747274 0.49786,1.245457 0.249091,0.747275 -0.249092,1.327193 -0.830306,1.576284 v 0.49948 c 0,2.740009 -3.155161,4.897506 -7.057597,4.897506 -3.9024357,0 -7.0575963,-2.157497 -7.0575963,-4.897506 V 13.8693 C 3.9896377,13.454147 3.6578398,12.458754 3.989962,11.545418 c 0.2490916,-0.664245 0.9120387,-1.08037 1.5762832,-0.99734 0.4981831,0 0.9133359,0.167358 1.2454581,0.499481 C 8.2232228,10.134222 9.8848065,9.55236 11.545418,9.55236 l 0.913011,-4.1515273 c 0,-0.083031 0.08271,-0.1654124 0.08271,-0.1654125 0.08303,-0.08303 0.166711,-0.084328 0.249741,-0.084328 l 2.906069,0.664893 C 15.946037,5.3800751 16.427678,5.084603 16.898617,5.1040633 Z M 9.3026198,12.293016 c -0.6642443,0 -1.2454583,0.581214 -1.2454583,1.245458 0,0.664245 0.498183,1.245459 1.2454583,1.245459 0.6642442,0 1.2454582,-0.581214 1.2454582,-1.245459 0,-0.664244 -0.581214,-1.245458 -1.2454582,-1.245458 z m 5.4813132,0 c -0.664245,0 -1.245459,0.581214 -1.245459,1.245458 0,0.664245 0.581214,1.245459 1.245459,1.245459 0.664245,0 1.245458,-0.581214 1.245458,-1.245459 0,-0.664244 -0.581213,-1.245458 -1.245458,-1.245458 z m -5.3872557,3.943952 c -0.072653,0 -0.135249,0.04021 -0.1767645,0.123249 -0.1660605,0.16606 -0.1660605,0.332121 0,0.415152 0.8303052,0.830306 2.4905922,0.914633 2.9887762,0.914633 0.498183,0 2.077061,-0.08433 2.990396,-0.914633 -0.08303,-0.08303 -0.084,-0.249092 -0.167034,-0.415152 -0.166061,-0.166062 -0.332121,-0.166062 -0.415152,0 -0.498183,0.581213 -1.660611,0.747598 -2.490917,0.747598 -0.830305,0 -1.992733,-0.166385 -2.4909165,-0.747598 -0.08303,-0.08303 -0.1657365,-0.123249 -0.2383882,-0.123249 z'
const note =
'M 12,3 C 11.54,3 11.07,3.04 10.6,3.14 7.84,3.67 5.64,5.9 5.12,8.66 4.64,11.27 5.6,13.67 7.34,15.22 7.77,15.6 8,16.13 8,16.69 V 19 c 0,1.1 0.9,2 2,2 h 0.28 c 0.35,0.6 0.98,1 1.72,1 0.74,0 1.38,-0.4 1.72,-1 H 14 c 1.1,0 2,-0.9 2,-2 V 16.69 C 16,16.14 16.22,15.6 16.64,15.23 18.09,13.95 19,12.08 19,10 19,6.13 15.87,3 12,3 Z m 2,16 h -4 v -1 h 4 z m 0,-2 h -4 v -1 h 4 z M 12.5,11.41 V 14 h -1 V 11.41 L 9.67,9.59 10.38,8.88 12,10.5 13.62,8.88 14.33,9.59 Z'
const tip =
'M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z'
const warning =
'M7.58 4.08L6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2c.15-2.65 1.51-4.97 3.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43c2.02 1.45 3.39 3.77 3.54 6.42zM18 11c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2v-5zm-6 11c.14 0 .27-.01.4-.04.65-.14 1.18-.58 1.44-1.18.1-.24.15-.5.15-.78h-4c.01 1.1.9 2 2.01 2z'
const units =
'M 1.2481485,5.9969994 C 0.57472916,5.9969994 0,6.5763504 0,7.2510315 V 14.751864 C 0,15.427642 0.57290973,16 1.2481485,16 H 22.753805 C 23.427222,16 24,15.426545 24,14.751864 V 7.2510315 C 24,6.5752543 23.429042,5.9969994 22.753805,5.9969994 Z M 2.0001628,7.997229 H 2.5021567 V 9.9974209 H 3.4983316 V 7.997229 H 4.5042727 V 9.9974209 H 5.5004476 V 7.997229 h 1.0039881 v 3.004219 H 7.5006105 V 7.997229 H 8.4967853 V 9.9974209 H 9.500773 V 7.997229 h 0.996175 v 2.0001919 h 1.005941 V 7.997229 h 0.996175 v 2.0001919 h 1.003988 V 7.997229 h 0.996175 v 2.0001919 h 1.003987 V 7.997229 h 0.996176 v 3.004219 h 1.003987 V 7.997229 h 0.996176 v 2.0001919 h 1.00594 V 7.997229 h 0.996176 v 2.0001919 h 1.003987 V 7.997229 h 0.494181 V 13.99977 H 19.202735 V 11.659724 H 17.599088 V 13.99977 H 12.801823 V 10.854937 H 11.200131 V 13.99977 H 6.4009116 V 11.659724 H 4.7992186 V 13.99977 H 2.0001628 Z'
const measurements =
'M 1.7792969,4.1816406 C 1.4635303,4.2034836 1.2472407,4.5095002 1.3320312,4.8144531 2.0126746,7.4312978 2.3589401,9.6399539 2.4804688,11.576172 l -0.2792969,0.179687 c -0.2007566,0.128704 -0.362752,0.219425 -0.5644531,0.480469 -0.1008507,0.130522 -0.2414074,0.337804 -0.2460938,0.683594 -0.00469,0.34579 0.2212218,0.709779 0.4121094,0.861328 0.3438312,0.272974 0.5293755,0.265612 0.7070312,0.279297 -0.102277,2.28979 -0.5523838,4.163493 -1.15625,5.869141 -0.266254,0.647707 0.7399311,1.004673 0.9414063,0.333984 0.6291584,-1.777086 1.0947468,-3.759245 1.2011719,-6.16211 0.8587499,0.0021 1.9817457,-0.02871 3.2402343,0.08203 1.266623,0.111458 2.5881834,0.388821 3.6914059,0.923828 -0.8838667,0.895791 -1.5848887,2.046501 -1.9218746,3.492187 l -0.2265625,0.972657 1.9472651,0.455078 0.226563,-0.97461 c 0.285273,-1.223836 0.850633,-2.097458 1.613281,-2.771484 0.508245,0.558951 0.895359,1.267092 1.117188,2.21875 l 0.226562,0.972656 1.949219,-0.453125 -0.228516,-0.974609 c -0.263451,-1.130219 -0.752009,-2.068727 -1.375,-2.835938 1.029043,-0.475861 2.194264,-0.776127 3.316407,-0.958984 1.232141,-0.200782 2.333045,-0.266545 3.220703,-0.341797 0.08818,2.494183 0.568253,4.529139 1.214843,6.355469 0.201481,0.670677 1.207649,0.313718 0.941407,-0.333984 -0.627794,-1.773234 -1.099219,-3.716671 -1.175781,-6.132811 0.04197,-0.0074 0.08942,-0.01089 0.130859,-0.01953 0.203289,-0.04241 0.397475,-0.06086 0.701172,-0.28711 0.151848,-0.113123 0.350634,-0.325838 0.427734,-0.634765 0.0771,-0.308927 -0.0063,-0.622179 -0.105469,-0.806641 -0.19843,-0.368923 -0.391632,-0.467629 -0.59375,-0.601562 l -0.472656,-0.3125 c 0.145104,-1.8337507 0.478549,-3.8949994 1.109375,-6.3203139 0.09171,-0.3306355 -0.169212,-0.6533027 -0.511719,-0.6328125 -0.218769,0.013497 -0.40325,0.1678902 -0.455078,0.3808594 -0.737,2.8335196 -1.100379,5.2405579 -1.199218,7.341797 -0.815925,0.07419 -2.080274,0.132785 -3.554688,0.373047 -1.478459,0.240919 -3.106344,0.671272 -4.574219,1.509765 -0.13911,-0.09127 -0.278493,-0.182969 -0.421875,-0.263671 -1.545631,-0.869966 -3.2877636,-1.195282 -4.8417966,-1.332032 -1.384279,-0.121812 -2.5095809,-0.08087 -3.296875,-0.08008 L 3.4980469,11.929688 C 3.4010459,9.8222094 3.0389322,7.4079513 2.2988281,4.5625 2.2413801,4.3260531 2.0220721,4.1652822 1.7792969,4.1816406 Z'
const withBreasts =
'm 8.233159,2.5000002 c 0,0 0.03684,1.4367676 0.07562,2.1541457 C 8.413989,6.5901608 7.3671071,6.9496995 7.3372662,8.1692173 7.3029172,9.5719723 8.2152,10.315942 8.255388,12.267223 8.290568,13.973294 7.1739465,15.012709 7.1739465,17.259683 9.46861,17.549817 10.668009,19.205086 11.354231,21.5 h 0.109763 0.93923 0.109803 c 0.686181,-2.294914 1.88558,-3.950183 4.180285,-4.240317 0,-2.246974 -1.116622,-3.286389 -1.081483,-4.99246 0.04015,-1.951281 0.952433,-2.6952507 0.918122,-4.0980057 -0.0298,-1.2195178 -1.076723,-1.5790565 -0.971513,-3.5150714 0.0389,-0.7173781 0.07562,-2.1541457 0.07562,-2.1541457 h -0.722313 c 0,1.5276628 -1.146752,3.7763442 -2.978112,3.7763442 -1.831402,0 -2.978154,-2.2486814 -2.978154,-3.7763442 z'
const withoutBreasts =
'M 6.2021092,6.7988281 C 5.0433189,10.972649 5.2215488,13.211802 5.2215488,16.798828 h 5.8983122 l 0.143133,-1.21128 c 0.331559,-1.834081 0.655671,-2.543616 1.078829,0.07477 l 0.134587,1.136509 h 5.896176 c 0,-3.587026 0.180363,-5.826179 -0.978425,-9.9999999 z'
const designs = 'M 11.974745,2.9104165 c -1.528527,0 -2.784485,1.256277 -2.784485,2.7848068 0,0.7494035 0.300482,1.4388587 0.786371,1.9393863 a 0.79436575,0.79436575 0 0 0 0.0084,0.00839 c 0.38087,0.3808653 0.745407,0.6251708 0.94538,0.8248328 0.19998,0.1996612 0.25013,0.2644989 0.25013,0.519072 V 9.6465486 L 2.0590674,14.913054 c -0.284779,0.164416 -0.836034,0.466125 -1.31649616,0.961104 -0.4804697,0.494981 -0.92450835,1.339947 -0.6668386,2.258534 0.2202611,0.785239 0.7746008,1.348564 1.34156666,1.587845 0.5669735,0.23928 1.0981677,0.23415 1.4684955,0.23415 h 6.2292502 5.582178 6.22925 c 0.370328,0 0.901583,0.0051 1.468557,-0.23415 0.566974,-0.239281 1.121495,-0.802606 1.341756,-1.587845 0.25767,-0.918587 -0.18662,-1.763553 -0.667089,-2.258534 C 22.589235,15.379179 22.03823,15.07747 21.753452,14.913054 L 12.76908,9.7258014 V 8.9869116 c 0,-0.7037243 -0.35623,-1.2837462 -0.716532,-1.6434766 C 11.69477,6.9862306 11.349385,6.7584045 11.114868,6.5255482 10.906224,6.3095381 10.778796,6.0225704 10.778796,5.6952216 c 0,-0.6700011 0.525949,-1.1962032 1.195949,-1.1962032 0.670007,0 1.196206,0.5262021 1.196206,1.1962032 a 0.79428633,0.79428633 0 0 0 0.794335,0.7942692 0.79428633,0.79428633 0 0 0 0.794268,-0.7942692 c 0,-1.5285296 -1.256276,-2.7848051 -2.784809,-2.7848051 z m -0.06859,8.2926595 8.991884,5.191357 c 0.289472,0.167124 0.693472,0.413355 0.943933,0.671385 0.250463,0.258029 0.313011,0.371405 0.247537,0.604827 -0.102886,0.366772 -0.190028,0.402129 -0.359686,0.473732 -0.169667,0.07161 -0.470133,0.09952 -0.803363,0.09952 H 14.697212 9.115034 2.8857834 c -0.3332299,0 -0.6336968,-0.02792 -0.8033621,-0.09952 -0.1696653,-0.07161 -0.2567452,-0.10696 -0.3596267,-0.473732 -0.06548,-0.233422 -0.00303,-0.346798 0.2474764,-0.604827 0.2504623,-0.25803 0.6547126,-0.504259 0.9441829,-0.671385 z'
export default {
designs,
discord,
github,
twitter,
instagram,
google,
facebook,
reddit,
note,
tip,
warning,
units,
measurements,
withBreasts,
withoutBreasts
}

View file

@ -1,24 +0,0 @@
import React from 'react'
import icons from './icons'
const Icon = ({
size = 24,
viewBox = '0 0 24 24',
className = '',
icon = 'github',
color = false,
style = {}
}) => (
<svg
style={style}
className={className}
xmlns="http://www.w3.org/2000/svg"
width={size}
height={size}
viewBox={viewBox}
>
<path stroke="none" fill={color ? color : 'currentColor'} d={icons[icon]} />
</svg>
)
export default Icon

View file

@ -1,27 +0,0 @@
import React from 'react'
import LegendPattern from '@freesewing/legend'
import Draft from '../Draft'
const Legend = ({ caption = false, part = '', children=null }) => {
const patternProps = new LegendPattern({
only: part,
measurements: {
head: 370
}
})
.draft()
.getRenderProps()
if (caption) console.log('Passing the caption prop to @freesewing/components/Legend is deprecated. See: https://github.com/freesewing/freesewing/issues/1043')
return (
<figure>
<div className="shadow">
<Draft {...patternProps} />
</div>
<figcaption>{caption || children}</figcaption>
</figure>
)
}
export default Legend

View file

@ -1,18 +0,0 @@
import React from 'react'
import patterns from './patterns'
const LineDrawing = (props) => {
const attr = {
style: props.style || {},
className: 'fs linedrawing ' + (props.className || ''),
xmlns: 'http://www.w3.org/2000/svg',
viewBox: '0 0 270 270'
}
if (props.size) {
attr.width = props.size
attr.height = props.size
}
return <svg {...attr}>{patterns[props.pattern || 'aaron'] || null}</svg>
}
export default LineDrawing

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,13 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import Logo from ".";
storiesOf("Logo", module)
.add("Default", () => <Logo />)
.add("Custom size", () => <Logo size={100} />)
.add("Custom color", () => (
<div style={{ color: "green" }}>
<Logo />
</div>
))
.add("Embedded", () => <Logo embed={true} />);

View file

@ -1,23 +0,0 @@
import React from 'react'
import poses from './poses'
const Robot = ({
size = 124,
viewBox = '0 0 500 500',
className = '',
pose = 'yay',
color = false,
embed = false
}) => (
<svg
className={className || ''}
xmlns="http://www.w3.org/2000/svg"
width={embed ? '' : size || 124}
height={embed ? '' : size || 124}
viewBox={viewBox || '0 0 500 500'}
>
<path stroke="none" fill={color ? color : 'currentColor'} d={poses[pose]} />
</svg>
)
export default Robot

File diff suppressed because one or more lines are too long

View file

@ -1,54 +0,0 @@
import React from 'react'
import { FormattedMessage } from 'react-intl'
import { injectIntl } from 'react-intl'
const OptionGroup = (props) => {
return (
<React.Fragment>
{props.options.map((name) => {
let output = []
if (typeof name === 'object') {
// Subgroup
for (let subGroup of Object.keys(name)) {
output.push(
<h5 key={subGroup + '-title'}>
<FormattedMessage id={'optiongroups.' + subGroup} />
</h5>
)
let children = []
for (let option of name[subGroup])
children.push(
<li>
<a
href="#logo"
onClick={() => props.sampleOption(option)}
className={props.activeOption === option ? 'active' : ''}
>
<FormattedMessage
id={'options.' + props.config.name + '.' + option + '.title'}
/>
</a>
</li>
)
output.push(<ul style={{ paddingLeft: '1rem' }}>{children}</ul>)
}
} else
output.push(
<li>
<a
href="#logo"
onClick={() => props.sampleOption(name)}
className={props.activeOption === name ? 'active' : ''}
>
<FormattedMessage id={'options.' + props.config.name + '.' + name + '.title'} />
</a>
</li>
)
return output
})}
</React.Fragment>
)
}
export default injectIntl(OptionGroup)

View file

@ -1,40 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import OptionGroup from ".";
const options = {
armholeDrop: { pct: 10, min: 1, max: 75 },
backlineBend: { pct: 50, min: 50, max: 100 },
chestEase: { pct: 8, min: 0, max: 20 },
hipsEase: { pct: 8, min: 0, max: 20 },
lengthBonus: { pct: 10, min: -20, max: 60 },
necklineBend: { pct: 100, min: 40, max: 100 },
necklineDrop: { pct: 20, min: 10, max: 35 },
stretchFactor: { pct: 5, min: 0, max: 15 },
shoulderStrapWidth: { pct: 15, min: 10, max: 40 },
shoulderStrapPlacement: { pct: 40, min: 20, max: 80 }
};
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (type, data) =>
console.log(`Update ${type} with new value`, data),
gist: {
settings: {
options: {}
}
},
pattern: {
config: {
name: "aaron",
options: options
}
},
dflts: { options: {} },
options: Object.keys(options)
};
storiesOf("Low level/OptionGroup", module).add("Simon metric", () => (
<OptionGroup pattern="simon" {...props} units="metric" />
));

View file

@ -1,35 +0,0 @@
import React from 'react'
import OptionGroup from '../OptionGroup'
import { FormattedMessage } from 'react-intl'
const PatternOptions = (props) => {
const renderGroup = (group) => {
let output = []
let children = (
<ul>
<OptionGroup
key={group + '-group'}
units={props.units}
config={props.config}
options={props.config.optionGroups[group]}
sampleOption={props.sampleOption}
activeOption={props.activeOption}
/>
</ul>
)
output.push(
<li key={group + '-ghead'}>
<h6>
<FormattedMessage id={'optiongroups.' + group} />
</h6>
{children}
</li>
)
return output
}
return <ul>{Object.keys(props.config.optionGroups).map((group) => renderGroup(group))}</ul>
}
export default PatternOptions

View file

@ -1,28 +0,0 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import PatternOptions from ".";
const props = {
raiseEvent: (type, data) =>
console.log(`Action of type ${type} triggered, data passed is`, data),
updateValue: (type, data) =>
console.log(`Update ${type} with new value`, data),
gist: {
settings: {
options: {}
}
}
};
storiesOf("Low level/PatternOptions", module)
.add("Simon metric", () => (
<PatternOptions pattern="simon" gist={false} units="metric" {...props} />
))
.add("Trayvon imperial", () => (
<PatternOptions
pattern="trayvon"
gist={false}
units="imperial"
{...props}
/>
));

View file

@ -1,152 +0,0 @@
import React, { useState } from 'react'
import { FormattedMessage } from 'react-intl'
import PatternOptions from './PatternOptions'
import { withBreasts, withoutBreasts } from '@freesewing/models'
import nonHuman from '../Workbench/Measurements/non-human.js'
const SampleConfigurator = (props) => {
const [type, setType] = useState()
const [instance, setInstance] = useState()
const sampleOption = (option) => {
setType('option')
setInstance(option)
props.updateGist(
{
type: 'option',
option
},
'settings',
'sample'
)
}
const sampleMeasurement = (measurement) => {
setType('measurement')
setInstance(measurement)
props.updateGist(
{
type: 'measurement',
measurement
},
'settings',
'sample'
)
}
const sampleModels = (models) => {
setType('models')
props.updateGist(
{
type: 'models',
models
},
'settings',
'sample'
)
}
return (
<ul>
<li>
<h5>
<FormattedMessage id="app.patternOptions" />
</h5>
<PatternOptions
config={props.config}
gist={props.gist}
sampleOption={sampleOption}
activeOption={type === 'option' ? instance : null}
/>
</li>
<li>
<h5>
<FormattedMessage id="app.measurements" />
</h5>
<ul>
{props.config.measurements.map((m) => (
<li key={m}>
<a
href="#logo"
onClick={() => sampleMeasurement(m)}
className={type === 'measurement' && instance === m ? 'active' : ''}
>
<FormattedMessage id={'measurements.' + m} />
</a>
</li>
))}
</ul>
</li>
<li>
<h5>
<FormattedMessage id="app.people" />
</h5>
<ul>
<li>
<a
href="#logo"
onClick={() => {
sampleModels(withBreasts)
setType('models')
setInstance('withBreasts')
}}
className={type === 'models' && instance === 'withBreasts' ? 'active' : ''}
>
<FormattedMessage id="app.withBreasts" />
</a>
</li>
<li>
<a
href="#logo"
onClick={() => {
sampleModels(withoutBreasts)
setType('models')
setInstance('withoutBreasts')
}}
className={type === 'models' && instance === 'withoutBreasts' ? 'active' : ''}
>
<FormattedMessage id="app.withoutBreasts" />
</a>
</li>
</ul>
</li>
{['dolls', 'giants'].map(type => (
<li key={type}>
<h5>
<FormattedMessage id={`app.${type}`} />
</h5>
<ul>
<li>
<a
href="#logo"
onClick={() => {
sampleModels(nonHuman.withBreasts[type])
setType('models')
setInstance('withBreasts')
}}
className={type === 'models' && instance === 'withBreasts' ? 'active' : ''}
>
<FormattedMessage id="app.withBreasts" />
</a>
</li>
<li>
<a
href="#logo"
onClick={() => {
sampleModels(nonHuman.withoutBreasts[type])
setType('models')
setInstance('withoutBreasts')
}}
className={type === 'models' && instance === 'withoutBreasts' ? 'active' : ''}
>
<FormattedMessage id="app.withoutBreasts" />
</a>
</li>
</ul>
</li>
))}
</ul>
)
}
export default SampleConfigurator

Some files were not shown because too many files have changed in this diff Show more