diff --git a/packages/freesewing.shared/components/icons/clear.js b/packages/freesewing.shared/components/icons/clear.js
new file mode 100644
index 00000000000..4575242e144
--- /dev/null
+++ b/packages/freesewing.shared/components/icons/clear.js
@@ -0,0 +1,7 @@
+const ClearIcon = () => (
+
+)
+
+export default ClearIcon
diff --git a/packages/freesewing.shared/components/workbench/inputs/design-option-percentage.js b/packages/freesewing.shared/components/workbench/inputs/design-option-percentage.js
index 49f7d0f9503..66e11e5ac8b 100644
--- a/packages/freesewing.shared/components/workbench/inputs/design-option-percentage.js
+++ b/packages/freesewing.shared/components/workbench/inputs/design-option-percentage.js
@@ -1,6 +1,61 @@
+import { useState } from 'react'
+import ClearIcon from 'shared/components/icons/clear.js'
+import { formatMm, round } from 'shared/utils.js'
+
const DesignOptionPercentage = props => {
+ const { pct, max, min } = props.pattern.config.options[props.option]
+ const val = (typeof props.gist?.options?.[props.option] === 'undefined')
+ ? pct
+ : props.gist.options[props.option] * 100
+
+ const [value, setValue] = useState(val)
+
+ const handleChange = (evt) => {
+ const newVal = evt.target.value
+ setValue(newVal)
+ props.updateGist(['options', props.option], newVal/100)
+ }
+ const reset = () => {
+ setValue(pct)
+ props.unsetGist(['options', props.option])
+ }
+
return (
-
+
+
+ {round(min)}%
+ {round(val)}%
+ {round(max)}%
+
+
+
+
+ {props.pattern.config.options[props.option]?.toAbs
+ ? formatMm(props.pattern.config.options[props.option].toAbs(value/100, props.gist))
+ : ' '
+ }
+
+
+
+
)
}
diff --git a/packages/freesewing.shared/components/workbench/menu/design-options/option.js b/packages/freesewing.shared/components/workbench/menu/design-options/option.js
index 6fd8e646e78..842ce0c773d 100644
--- a/packages/freesewing.shared/components/workbench/menu/design-options/option.js
+++ b/packages/freesewing.shared/components/workbench/menu/design-options/option.js
@@ -1,7 +1,46 @@
import { linkClasses, Chevron } from 'shared/components/navigation/primary.js'
import PercentOption from 'shared/components/workbench/inputs/design-option-percentage'
+import { formatMm, formatPercentage, optionType } from 'shared/utils.js'
+
+const values = {
+ pct: props => {
+ const val = (typeof props.gist?.options?.[props.option] === 'undefined')
+ ? props.pattern.config.options[props.option].pct/100
+ : props.gist.options[props.option]
+ return (
+
+ {formatPercentage(val)}
+ {props.pattern.config.options[props.option]?.toAbs
+ ? ' | ' +formatMm(props.pattern.config.options[props.option]?.toAbs(val, props.gist))
+ : null
+ }
+
+ )
+ }
+}
+
+const Tmp = props => not yet
+
+const inputs = {
+ pct: PercentOption,
+ bool: Tmp,
+ count: Tmp,
+ deg: Tmp,
+ list: Tmp,
+ mm: Tmp,
+ constant: Tmp,
+}
+
const Option = props => {
+ const type = optionType(props.pattern.config.options[props.option])
+ const Input = inputs[type]
+ const Value = values[type]
+
return (
@@ -30,16 +69,13 @@ const Option = props => {
{ props.app.t(`options.${props.pattern.config.name}.${props.option}.title`) }
+
- {props.pattern.config.options[props.option]?.pct && }
- {JSON.stringify(props.pattern.config.options[props.option],null,2)}
-
- fixme
+
)
}
- //props.pattern.config.optionsgroups[props.group].map(option => (
export default Option
diff --git a/packages/freesewing.shared/components/wrappers/workbench.js b/packages/freesewing.shared/components/wrappers/workbench.js
index b654acf4529..007899e99a1 100644
--- a/packages/freesewing.shared/components/wrappers/workbench.js
+++ b/packages/freesewing.shared/components/wrappers/workbench.js
@@ -5,6 +5,7 @@ import Menu from 'shared/components/workbench/menu/index.js'
import Measurements, { Input } from 'shared/components/workbench/measurements/index.js'
import LabDraft from 'shared/components/workbench/draft/index.js'
import set from 'lodash.set'
+import unset from 'lodash.unset'
// Generates a default pattern gist to start from
const defaultGist = (pattern, language='en') => ({
@@ -60,13 +61,27 @@ const WorkbenchWrapper = ({ app, pattern }) => {
set(newGist, path, content)
setGist(newGist)
}
+ const unsetGist = (path) => {
+ const newGist = {...gist}
+ unset(newGist, path)
+ setGist(newGist)
+ }
+
// Required props for layout
const layoutProps = {
app: app,
noSearch: true,
workbench: true,
- AltMenu:
+ AltMenu:
}
return (
diff --git a/packages/freesewing.shared/package.json b/packages/freesewing.shared/package.json
index 5d6c6a56d4e..411c7dcdb19 100644
--- a/packages/freesewing.shared/package.json
+++ b/packages/freesewing.shared/package.json
@@ -16,6 +16,7 @@
"@tailwindcss/typography": "^0.5.0",
"daisyui": "^1.16.2",
"lodash.orderby": "^4.6.0",
+ "lodash.unset": "^4.5.2",
"react-markdown": "^7.1.1",
"react-timeago": "^6.2.1",
"rehype-highlight": "^5.0.1",
diff --git a/packages/freesewing.shared/utils.js b/packages/freesewing.shared/utils.js
new file mode 100644
index 00000000000..2d91cc0b4ab
--- /dev/null
+++ b/packages/freesewing.shared/utils.js
@@ -0,0 +1,76 @@
+// Generic rounding method
+export const round = (val, decimals=1) => Math.round(val*Math.pow(10, decimals))/Math.pow(10, decimals)
+
+// Rounds a value in mm
+export const roundMm = (val, units) => {
+ if (units === "imperial") return Math.round(val * 1000000) / 1000000;
+ else return Math.round(val * 10) / 10;
+}
+
+// Formatting for imperial values
+export const formatImperial = (neg, inch, numo = false, deno = false, format = 'html') => {
+ if (format === 'html') {
+ if (numo) return `${neg}${inch} ${numo}/${deno}`
+ else return `${neg}${inch}`
+ } else {
+ if (numo) return `${neg}${inch} ${numo}/${deno}`
+ else return `${neg}${inch}`
+ }
+}
+
+// Format a value in mm based on the user's units
+export const formatMm = (val, units, format = 'html') => {
+ val = roundMm(val)
+ if (units === 'imperial') {
+ if (val == 0) return formatImperial('', 0, false, false, format)
+ let negative = ''
+ let inches = ''
+ let rest = ''
+ let fraction = val / 25.4
+ if (fraction < 0) {
+ fraction = fraction * -1
+ negative = '-'
+ }
+ if (Math.abs(fraction) < 1) rest = fraction
+ else {
+ inches = Math.floor(fraction)
+ rest = fraction - inches
+ }
+ let suffix = ''
+ if (format === 'html') suffix = '"'
+ let fraction128 = Math.round(rest * 128)
+ if (fraction128 == 0) return formatImperial(negative, inches, false, false, format)
+ if (fraction128 % 64 == 0)
+ return formatImperial(negative, inches, fraction128 / 64, 2, format) + suffix
+ if (fraction128 % 32 == 0)
+ return formatImperial(negative, inches, fraction128 / 32, 4, format) + suffix
+ if (fraction128 % 16 == 0)
+ return formatImperial(negative, inches, fraction128 / 16, 8, format) + suffix
+ if (fraction128 % 8 == 0)
+ return formatImperial(negative, inches, fraction128 / 8, 16, format) + suffix
+ if (fraction128 % 4 == 0)
+ return formatImperial(negative, inches, fraction128 / 4, 32, format) + suffix
+ if (fraction128 % 2 == 0)
+ return formatImperial(negative, inches, fraction128 / 2, 64, format) + suffix
+
+ return negative + Math.round(fraction * 100) / 100 + suffix
+ } else {
+ if (format === 'html') return roundMm(val / 10) + 'cm'
+ else return roundMm(val / 10)
+ }
+}
+
+// Format a percentage (as in, between 0 and 1)
+export const formatPercentage = val => Math.round(1000*val)/10+'%'
+
+export const optionType = option => {
+ if (typeof option?.pct !== 'undefined') return 'pct'
+ if (typeof option?.bool !== 'undefined') return 'bool'
+ if (typeof option?.count !== 'undefined') return 'count'
+ if (typeof option?.deg !== 'undefined') return 'deg'
+ if (typeof option?.list !== 'undefined') return 'list'
+ if (typeof option?.mm !== 'undefined') return 'mm'
+
+ return 'constant'
+}
+
diff --git a/yarn.lock b/yarn.lock
index c868634c1c1..e54bef3b587 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -17514,6 +17514,11 @@ lodash.uniqby@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302"
integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=
+lodash.unset@^4.5.2:
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/lodash.unset/-/lodash.unset-4.5.2.tgz#370d1d3e85b72a7e1b0cdf2d272121306f23e4ed"
+ integrity sha1-Nw0dPoW3Kn4bDN8tJyEhMG8j5O0=
+
lodash@4.17.21, "lodash@>=3.5 <5", lodash@^4.1.1, lodash@^4.11.2, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.7.0, lodash@~4.17.10:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"