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"