diff --git a/packages/react/components/Editor/components/HeaderMenu.mjs b/packages/react/components/Editor/components/HeaderMenu.mjs index cac15ebe357..0d36c9470c7 100644 --- a/packages/react/components/Editor/components/HeaderMenu.mjs +++ b/packages/react/components/Editor/components/HeaderMenu.mjs @@ -264,6 +264,7 @@ export const HeaderMenuDraftViewFlags = (props) => { export const HeaderMenuDraftViewIcons = (props) => { const { update, state } = props + const { settings = {} } = state // Guard against undefined settings const Button = HeaderMenuButton const size = 'tw:w-5 tw:h-5' const muted = 'tw:text-current tw:opacity-50' @@ -281,55 +282,49 @@ export const HeaderMenuDraftViewIcons = (props) => { updateHandler={update.toggleSa} tooltip="Turns Seam Allowance on or off (see Core Settings)" > - + ) : null} {ux >= levels.units ? ( ) : null} {ux >= levels.paperless ? ( ) : null} {ux >= levels.complete ? ( ) : null} {ux >= levels.expand ? ( ) : null} @@ -450,6 +445,7 @@ export const HeaderMenuTestIcons = (props) => { export const HeaderMenuSaveIcons = (props) => { const { update, state } = props + const { settings = {} } = state // Guard against undefined settings const backend = useBackend() const Button = HeaderMenuButton const size = 'tw:w-5 tw:h-5' @@ -463,9 +459,7 @@ export const HeaderMenuSaveIcons = (props) => { if (pid) { const loadingId = 'savePattern' update.startLoading(loadingId) - const patternData = { - settings: state.settings, - } + const patternData = { settings } const result = await backend.updatePattern(pid, patternData) if (result[0] === 200) { update.stopLoading(loadingId) @@ -599,6 +593,7 @@ export const HeaderMenuLayoutView = (props) => ( export const HeaderMenuLayoutViewIcons = (props) => { const { pattern, update, state } = props + const { settings = {} } = state // Guard against undefined settings const [tweaks, setTweaks] = useState(0) // Is the current custom layout an actual layout? @@ -611,12 +606,12 @@ export const HeaderMenuLayoutViewIcons = (props) => { */ if ( tweaks === 0 && - typeof props.state.ui?.layout === 'object' && - typeof props.state.settings?.layout !== 'object' + typeof state.ui?.layout === 'object' && + typeof settings?.layout !== 'object' ) applyLayout() setTweaks(tweaks + 1) - }, [props.state.ui.layout]) + }, [state.ui.layout]) const applyLayout = () => { setTweaks(-1) @@ -633,7 +628,7 @@ export const HeaderMenuLayoutViewIcons = (props) => { const pages = pattern.setStores[0].get('pages', {}) const format = state.ui.print?.pages?.size ? state.ui.print.pages.size - : state.settings?.units === 'imperial' + : settings.units === 'imperial' ? 'letter' : 'a4' const { cols, rows, count } = pages diff --git a/packages/react/components/Editor/components/menus/CoreSettingsMenu.mjs b/packages/react/components/Editor/components/menus/CoreSettingsMenu.mjs index 82f165f9ffa..4c457cf0441 100644 --- a/packages/react/components/Editor/components/menus/CoreSettingsMenu.mjs +++ b/packages/react/components/Editor/components/menus/CoreSettingsMenu.mjs @@ -31,9 +31,11 @@ import { SettingsIcon } from '@freesewing/react/components/Icon' * @param {Object} props.update - Object holding state handlers */ export const CoreSettingsMenu = ({ Design, state, i18n, update }) => { + const { settings = {} } = state // Guard against undefined settings + const structure = menuCoreSettingsStructure({ - units: state.settings?.units, - sabool: state.settings?.sabool, + units: settings.units, + sabool: settings.sabool, parts: Design.patternConfig.draftOrder, }) @@ -66,7 +68,7 @@ export const CoreSettingsMenu = ({ Design, state, i18n, update }) => { {...{ structure, ux: state.ui.ux, - currentValues: state.settings || {}, + currentValues: settings, Icon: SettingsIcon, Item: (props) => ( @@ -75,7 +77,7 @@ export const CoreSettingsMenu = ({ Design, state, i18n, update }) => { name: 'Core Settings', passProps: { ux: state.ui.ux, - settings: state.settings, + settings, patternConfig: Design.patternConfig, toggleSa: update.toggleSa, }, diff --git a/packages/react/components/Editor/components/menus/DesignOptionsMenu.mjs b/packages/react/components/Editor/components/menus/DesignOptionsMenu.mjs index 9ca52fd4324..7251ead07fb 100644 --- a/packages/react/components/Editor/components/menus/DesignOptionsMenu.mjs +++ b/packages/react/components/Editor/components/menus/DesignOptionsMenu.mjs @@ -35,14 +35,19 @@ import { OptionsIcon } from '@freesewing/react/components/Icon' * @param {Object} props.update - Object holding state handlers */ export const DesignOptionsMenu = ({ Design, isFirst = true, state, i18n, update }) => { + /* + * Ensure state is not undefined + */ + const { settings = {} } = state + const structure = useMemo( () => menuDesignOptionsStructure( Design.designConfig.data.id, Design.patternConfig.options, - state.settings + settings ), - [Design.designConfig.data.id, Design.patternConfig, state.settings] + [Design.designConfig.data.id, Design.patternConfig, settings] ) const updateHandler = useCallback( (name, value = '__UNSET__') => update.settings(['options', ...name], value), @@ -76,14 +81,14 @@ export const DesignOptionsMenu = ({ Design, isFirst = true, state, i18n, update {...{ structure, ux: state.ui.ux, - currentValues: state.settings.options || {}, + currentValues: settings.options || {}, Icon: OptionsIcon, Item: (props) => , isFirst, name: 'Design Options', passProps: { ux: state.ui.ux, - settings: state.settings, + settings, patternConfig: Design.patternConfig, }, updateHandler, diff --git a/packages/react/components/Editor/components/menus/Input.mjs b/packages/react/components/Editor/components/menus/Input.mjs index a2a1d05cbb6..0eb32377987 100644 --- a/packages/react/components/Editor/components/menus/Input.mjs +++ b/packages/react/components/Editor/components/menus/Input.mjs @@ -282,6 +282,7 @@ export const MenuSliderInput = ({ state, Design, }) => { + const { settings = {} } = state // Guard against undefined settings const { max, min } = config const handleChange = useSharedHandlers({ current, @@ -330,10 +331,10 @@ export const MenuSliderInput = ({ __html: formatMm( config.toAbs( val / 100, - state.settings, - mergeOptions(state.settings, Design.patternConfig.options) + settings, + mergeOptions(settings, Design.patternConfig.options) ), - state.settings?.units + settings.units ), }} /> @@ -360,25 +361,22 @@ export const MenuSliderInput = ({ export const MenuEditOption = (props) => { const { config, handleChange } = props + const { settings = {} } = props.state // Guard against undefined settings const type = designOptionType(config) const [manualEdit, setManualEdit] = useState(props.current) const [abs, setAbs] = useState(false) const [units, setUnits] = useState( - abs - ? props.state.settings?.units === 'imperial' - ? 'inch' - : 'cm' - : defaultConfig.menuOptionEditLabels[type] + abs ? (settings.units === 'imperial' ? 'inch' : 'cm') : defaultConfig.menuOptionEditLabels[type] ) const onUpdate = useCallback( (validVal, units) => { if (validVal !== null && validVal !== false) { if (type === 'pct' && units === 'cm') - return handleChange(config.fromAbs(Number(validVal) * 1000, props.state.settings)) + return handleChange(config.fromAbs(Number(validVal) * 1000, settings)) if (type === 'pct' && units === 'inch') - return handleChange(config.fromAbs(Number(validVal) * 2540, props.state.settings)) + return handleChange(config.fromAbs(Number(validVal) * 2540, settings)) return handleChange(validVal) } }, @@ -387,7 +385,7 @@ export const MenuEditOption = (props) => { const toggleInputUnits = () => { if (abs) setUnits(defaultConfig.menuOptionEditLabels[type]) - else setUnits(props.state.settings?.units === 'imperial' ? 'inch' : 'cm') + else setUnits(settings.units === 'imperial' ? 'inch' : 'cm') setAbs(!abs) console.log('in toogg;e') } diff --git a/packages/react/components/Editor/components/menus/LayoutMenu.mjs b/packages/react/components/Editor/components/menus/LayoutMenu.mjs index 9cdcee48404..4357f3d570d 100644 --- a/packages/react/components/Editor/components/menus/LayoutMenu.mjs +++ b/packages/react/components/Editor/components/menus/LayoutMenu.mjs @@ -48,7 +48,7 @@ export const LayoutSettingsMenu = ({ update, state, Design }) => { name: 'UI Preferences', passProps: { ux: state.ui?.ux, - settings: state.settings, + settings: state?.settings, patternConfig: Design.patternConfig, }, updateHandler: (key, val) => update.ui(['layout', key], val), diff --git a/packages/react/components/Editor/components/menus/TestMenu.mjs b/packages/react/components/Editor/components/menus/TestMenu.mjs index 18f87e891f1..fdba2078c52 100644 --- a/packages/react/components/Editor/components/menus/TestMenu.mjs +++ b/packages/react/components/Editor/components/menus/TestMenu.mjs @@ -16,14 +16,15 @@ import { BeakerIcon, OptionsIcon } from '@freesewing/react/components/Icon' * @param {Object} props.update - Object holding state handlers */ export const TestOptionsMenu = ({ Design, state, i18n, update }) => { + const { settings = {} } = state // Guard against undefined settings const structure = useMemo( () => menuDesignOptionsStructure( Design.designConfig.data.id, Design.patternConfig.options, - state.settings + settings ), - [Design.designConfig.data.id, Design.patternConfig, state.settings] + [Design.designConfig.data.id, Design.patternConfig, settings] ) return ( diff --git a/packages/react/components/Editor/components/menus/UiPreferencesMenu.mjs b/packages/react/components/Editor/components/menus/UiPreferencesMenu.mjs index 5e39b2723ec..cb441df0718 100644 --- a/packages/react/components/Editor/components/menus/UiPreferencesMenu.mjs +++ b/packages/react/components/Editor/components/menus/UiPreferencesMenu.mjs @@ -10,6 +10,7 @@ export const UiPreferencesMenu = ({ update, state, Design }) => { const structure = menuUiPreferencesStructure() const drillProps = { Design, state, update } + const { settings = {} } = state // Guard against undefined settings const inputs = { aside: (props) => , ux: (props) => , @@ -37,7 +38,7 @@ export const UiPreferencesMenu = ({ update, state, Design }) => { language: state.locale, passProps: { ux: state.ui?.ux, - settings: state.settings, + settings, patternConfig: Design.patternConfig, }, updateHandler: update.ui, diff --git a/packages/react/components/Editor/components/views/EditSettingsView.mjs b/packages/react/components/Editor/components/views/EditSettingsView.mjs index 471849c303d..e133c3ee641 100644 --- a/packages/react/components/Editor/components/views/EditSettingsView.mjs +++ b/packages/react/components/Editor/components/views/EditSettingsView.mjs @@ -21,7 +21,7 @@ import { yaml as yamlLang } from '@codemirror/lang-yaml' * @param {Object} props.update - Helper object for updating the editor state */ export const EditSettingsView = (props) => { - const [settings, setSettings] = useState(props.state.settings) + const [settings, setSettings] = useState(props.state?.settings || {}) const { state, config, update } = props return ( @@ -49,21 +49,22 @@ export const PrimedSettingsEditor = (props) => { * Destructure props */ const { state } = props + const stateSettings = state.settings || {} // Guard against undefined settings /* * React state */ /* eslint-disable-next-line no-unused-vars */ - const [settings, update, setSettings] = useStateObject(state.settings) // Holds the settings + const [settings, update, setSettings] = useStateObject(stateSettings) // Holds the settings const [showDelta, setShowDelta] = useState(false) - const [localYaml, setLocalYaml] = useState(yaml.stringify(state.settings)) // Holds the settings as YAML + const [localYaml, setLocalYaml] = useState(yaml.stringify(stateSettings)) // Holds the settings as YAML /* * Method to revert to the settings in the editor state */ const revert = () => { - setSettings(clone(state.settings)) - setLocalYaml(yaml.stringify(state.settings)) + setSettings(clone(stateSettings)) + setLocalYaml(yaml.stringify(stateSettings)) } /* @@ -79,7 +80,7 @@ export const PrimedSettingsEditor = (props) => { * Handle settings delta */ const delta = - diffCheck(yaml.stringify(state.settings), yaml.stringify(settings)).length > 1 ? true : false + diffCheck(yaml.stringify(stateSettings), yaml.stringify(settings)).length > 1 ? true : false const onChangeYaml = (input) => { let newSettings @@ -131,7 +132,7 @@ export const PrimedSettingsEditor = (props) => { {showDelta ? (
{ const { config, state, update } = props + const { settings = {} } = state // Guard against undefined settings const [link, setLink] = useState(false) const [format, setFormat] = useState(false) @@ -41,7 +42,7 @@ export const ExportView = (props) => { design: props.design, Design: props.Design, ui: props.state.ui, - settings: props.state.settings, + settings, setLink, setFormat, startLoading: update.startLoading, diff --git a/packages/react/components/Editor/components/views/InspectView.mjs b/packages/react/components/Editor/components/views/InspectView.mjs index 5d76a28cb1a..0c4ed3cd6cc 100644 --- a/packages/react/components/Editor/components/views/InspectView.mjs +++ b/packages/react/components/Editor/components/views/InspectView.mjs @@ -24,6 +24,7 @@ import { DraftErrorHandler } from './DraftErrorHandler.mjs' * @return {function} DraftView - React component */ export const InspectView = ({ Design, state, update, config }) => { + const { settings = {} } = state // Guard against undefined settings const { setModal, clearModal, modalContent } = useContext(ModalContext) const info = { @@ -48,7 +49,7 @@ export const InspectView = ({ Design, state, update, config }) => { /* * First, attempt to draft */ - const { pattern, failure, errors } = draft(Design, state.settings) + const { pattern, failure, errors } = draft(Design, settings) /* * Create object holding strings for translation diff --git a/packages/react/components/Editor/components/views/LogView.mjs b/packages/react/components/Editor/components/views/LogView.mjs index dc0e67a6993..a4fc41d338e 100644 --- a/packages/react/components/Editor/components/views/LogView.mjs +++ b/packages/react/components/Editor/components/views/LogView.mjs @@ -21,7 +21,8 @@ const levels = ['error', 'warn', 'info', 'debug'] */ export const LogView = (props) => { const { state, config, update } = props - const { pattern } = draft(props.Design, state.settings) + const { settings = {} } = state // Guard against undefined settings + const { pattern } = draft(props.Design, settings) return ( <> diff --git a/packages/react/components/Editor/components/views/SaveView.mjs b/packages/react/components/Editor/components/views/SaveView.mjs index 522a9b08520..852dcf5c474 100644 --- a/packages/react/components/Editor/components/views/SaveView.mjs +++ b/packages/react/components/Editor/components/views/SaveView.mjs @@ -23,6 +23,7 @@ import { HeaderMenu } from '../HeaderMenu.mjs' * @param {Object} props.update - Helper object for updating the editor state */ export const SaveView = ({ config, state, update }) => { + const { settings = {} } = state // Guard against undefined settings // Hooks const backend = useBackend() @@ -34,7 +35,7 @@ export const SaveView = ({ config, state, update }) => { const [saveAs] = useState(false) // FIXME const addSettingsToNotes = () => { - setNotes(notes + '\n\n#### Settings\n\n```yaml\n' + yaml.dump(state.settings) + '\n````') + setNotes(notes + '\n\n#### Settings\n\n```yaml\n' + yaml.dump(settings) + '\n````') } const saveAsNewPattern = async () => { @@ -44,7 +45,7 @@ export const SaveView = ({ config, state, update }) => { design: state.design, name, public: false, - settings: state.settings, + settings, data: {}, } if (withNotes) patternData.notes = notes @@ -69,7 +70,7 @@ export const SaveView = ({ config, state, update }) => { setLoadingStatus([true, 'Saving pattern...']) const patternData = { design: state.design, - settings: state.settings, + settings, name, public: false, data: {}, diff --git a/packages/react/components/Editor/components/views/TestView.mjs b/packages/react/components/Editor/components/views/TestView.mjs index 23af90b3267..4ba076b2104 100644 --- a/packages/react/components/Editor/components/views/TestView.mjs +++ b/packages/react/components/Editor/components/views/TestView.mjs @@ -143,14 +143,15 @@ export const TestView = ({ Design, state, update, config }) => { } const SampleOptionsMenu = ({ Design, state, update }) => { + const { settings = {} } = state // Guard against undefined settings const structure = useMemo( () => menuDesignOptionsStructure( Design.designConfig.data.id, Design.patternConfig.options, - state.settings + settings ), - [Design.designConfig.data.id, Design.patternConfig, state.settings] + [Design.designConfig.data.id, Design.patternConfig, settings] ) return diff --git a/packages/react/components/Editor/components/views/UndosView.mjs b/packages/react/components/Editor/components/views/UndosView.mjs index 37e4310dcf3..906cceda4d0 100644 --- a/packages/react/components/Editor/components/views/UndosView.mjs +++ b/packages/react/components/Editor/components/views/UndosView.mjs @@ -17,6 +17,7 @@ import { getUndoStepData } from '../../lib/index.mjs' * @param {object} update - ViewWrapper state update object */ export const UndosView = ({ Design, update, state, config }) => { + const { settings = {} } = state // Guard against undefined settings const steps = orderBy(state._.undos, 'time', 'desc') return ( @@ -32,7 +33,7 @@ export const UndosView = ({ Design, update, state, config }) => {

For example, you can click the button below to change the pattern rotation:

@@ -71,6 +72,7 @@ export const UndoStepTimeAgo = ({ step }) => { } export const UndoStep = ({ update, state, step, Design, compact = false, index = 0 }) => { + const { settings = {} } = state // Guard against undefined settings /* * Ensure path is always an array */ @@ -79,7 +81,7 @@ export const UndoStep = ({ update, state, step, Design, compact = false, index = /* * Figure this out once */ - const imperial = state.settings?.units === 'imperial' ? true : false + const imperial = settings.units === 'imperial' ? true : false /* * Metadata can be ignored diff --git a/packages/react/components/Editor/index.mjs b/packages/react/components/Editor/index.mjs index f1f65fb53f0..20c2bda6a96 100644 --- a/packages/react/components/Editor/index.mjs +++ b/packages/react/components/Editor/index.mjs @@ -157,6 +157,7 @@ export const Editor = ({ * @param (object) props.config - The editor config */ const viewfinder = ({ design, designs, state, config }) => { + const { settings = {} } = state // Guard against undefined settings /* * Grab Design from props or state and make them extra props */ @@ -174,7 +175,7 @@ const viewfinder = ({ design, designs, state, config }) => { */ const [measurementsOk, missingMeasurements] = hasRequiredMeasurements( designs[design], - state.settings?.measurements + settings.measurements ) if (missingMeasurements) extraProps.missingMeasurements = missingMeasurements diff --git a/packages/react/components/Editor/lib/design-options.mjs b/packages/react/components/Editor/lib/design-options.mjs index 30a479e557e..268b48e423a 100644 --- a/packages/react/components/Editor/lib/design-options.mjs +++ b/packages/react/components/Editor/lib/design-options.mjs @@ -111,7 +111,8 @@ export function menuDesignOptionsStructure(design, options, settings, asFullList * Since these structures can be nested with option groups, this needs some extra logic */ export function getOptionStructure(option, Design, state) { - const structure = menuDesignOptionsStructure(Design.patternConfig.options, state.settings) + const { settings = {} } = state // Guard against undefined settings + const structure = menuDesignOptionsStructure(Design.patternConfig.options, settings) return findOption(structure, option) } diff --git a/packages/react/components/Editor/lib/editor.mjs b/packages/react/components/Editor/lib/editor.mjs index 7f750114c35..947cb8b8e10 100644 --- a/packages/react/components/Editor/lib/editor.mjs +++ b/packages/react/components/Editor/lib/editor.mjs @@ -159,10 +159,11 @@ export function getUiPreferenceUndoStepData({ step }) { export function getCoreSettingUndoStepData({ step, state, Design }) { const field = step.path[1] + const { settings = {} } = state // Guard against undefined settings const structure = menuCoreSettingsStructure({ language: state.language, - units: state.settings.units, - sabool: state.settings.sabool, + units: settings.units, + sabool: settings.sabool, parts: Design.patternConfig.draftOrder, })