diff --git a/config/exceptions.yaml b/config/exceptions.yaml
index 124f370d643..3b47dc85614 100644
--- a/config/exceptions.yaml
+++ b/config/exceptions.yaml
@@ -105,6 +105,7 @@ packageJson:
"./components/Table": "./components/Table/index.mjs"
"./components/Time": "./components/Time/index.mjs"
"./components/Uuid": "./components/Uuid/index.mjs"
+ "./components/Ux": "./components/Ux/index.mjs"
"./components/Yaml": "./components/Yaml/index.mjs"
"./components/Xray": "./components/Xray/index.mjs"
# Context
diff --git a/packages/react/components/Editor/components/Flag.mjs b/packages/react/components/Editor/components/Flag.mjs
new file mode 100644
index 00000000000..e93b4bf5ec5
--- /dev/null
+++ b/packages/react/components/Editor/components/Flag.mjs
@@ -0,0 +1,131 @@
+import React from 'react'
+import mustache from 'mustache'
+import { defaultConfig } from '../config/index.mjs'
+import { flattenFlags } from '../lib/index.mjs'
+import {
+ ChatIcon,
+ ErrorIcon,
+ ExpandIcon,
+ DocsIcon,
+ FixmeIcon,
+ FlagIcon,
+ OptionsIcon,
+ TipIcon,
+ WarningIcon,
+ WrenchIcon,
+} from '@freesewing/react/components/Icon'
+import { SubAccordion } from './Accordion.mjs'
+
+/*
+ * Helper object to look up flag icons
+ */
+const flagIcons = {
+ error: ErrorIcon,
+ expand: ExpandIcon,
+ fixme: WrenchIcon,
+ info: DocsIcon,
+ note: ChatIcon,
+ otions: OptionsIcon,
+ tip: TipIcon,
+ warning: WarningIcon,
+}
+
+export const FlagTypeIcon = ({ type, className = 'tw-w-6 tw-h-6' }) => {
+ const Icon = flagIcons[type] || FixmeIcon
+
+ return
+}
+
+export const Flag = ({ data, handleUpdate }) => {
+ const btnIcon = data.suggest?.icon ? (
+
+ ) : null
+
+ const button =
+ data.suggest?.text && data.suggest?.update ? (
+ handleUpdate(data.suggest.update)}
+ >
+ {btnIcon}
+ {data.suggest.text}
+
+ ) : null
+
+ const desc = data.replace ? mustache.render(data.desc, data.replace) : data.desc
+ const notes = data.notes
+ ? Array.isArray(data.notes)
+ ? '\n\n' +
+ data.notes
+ .map((note) => (data.replace ? mustache.render(note, data.replace) : note))
+ .join('\n\n')
+ : '\n\n' + (data.replace ? mustache.render(data.notes, data.replace) : data.notes)
+ : null
+
+ return (
+
+
+ {button ? (
+
{button}
+ ) : null}
+
+ )
+}
+
+export const FlagsAccordionTitle = ({ flags }) => {
+ const flagList = flattenFlags(flags)
+
+ if (Object.keys(flagList).length < 1) return null
+
+ return (
+ <>
+
+ Flags ({Object.keys(flagList).length})
+
+
+
+ {Object.keys(flagList).length > 1
+ ? 'Some issues about your current pattern need your attention.'
+ : 'A specific issue about your current pattern needs your attention.'}
+
+ >
+ )
+}
+
+export const FlagsAccordionEntries = ({ flags, update }) => {
+ const flagList = flattenFlags(flags)
+
+ if (Object.keys(flagList).length < 1) return null
+
+ const handleUpdate = (config) => {
+ if (config.settings) update.settings(...config.settings)
+ if (config.ui) update.ui(...config.settings)
+ }
+
+ return (
+ {
+ const title = flag.replace ? mustache.render(flag.title, flag.replace) : flag.title
+
+ return [
+ ,
+ ,
+ key,
+ ]
+ })}
+ />
+ )
+}
diff --git a/packages/react/components/Editor/components/HeaderMenu.mjs b/packages/react/components/Editor/components/HeaderMenu.mjs
index b3cbe371a90..6416a2b5852 100644
--- a/packages/react/components/Editor/components/HeaderMenu.mjs
+++ b/packages/react/components/Editor/components/HeaderMenu.mjs
@@ -1,5 +1,5 @@
// Dependencies
-import { missingMeasurements } from '../lib/index.mjs'
+import { missingMeasurements, flattenFlags } from '../lib/index.mjs'
// Hooks
import React, { useState } from 'react'
// Components
@@ -7,9 +7,29 @@ import { Null } from './Null.mjs'
import { AsideViewMenuSpacer } from './AsideViewMenu.mjs'
import { ViewIcon, viewLabels } from './views/index.mjs'
import { Tooltip } from './Tooltip.mjs'
-import { ErrorIcon } from '@freesewing/react/components/Icon'
+import {
+ CircleIcon,
+ DetailIcon,
+ ErrorIcon,
+ ExpandIcon,
+ ExportIcon,
+ KioskIcon,
+ MenuIcon,
+ PaperlessIcon,
+ ResetAllIcon,
+ RocketIcon,
+ RotateIcon,
+ SaIcon,
+ SaveAsIcon,
+ SaveIcon,
+ TrashIcon,
+ UndoIcon,
+ UnitsIcon,
+} from '@freesewing/react/components/Icon'
import { DesignOptionsMenu } from './menus/DesignOptionsMenu.mjs'
import { CoreSettingsMenu } from './menus/CoreSettingsMenu.mjs'
+import { UiPreferencesMenu } from './menus/UiPreferencesMenu.mjs'
+import { FlagsAccordionEntries } from './Flag.mjs'
export const HeaderMenuAllViews = ({ config, state, update, open, setOpen }) => (
diff --git a/packages/react/components/Editor/components/ZoomablePattern.mjs b/packages/react/components/Editor/components/ZoomablePattern.mjs
index 8d6566c0d16..7e71cda3317 100644
--- a/packages/react/components/Editor/components/ZoomablePattern.mjs
+++ b/packages/react/components/Editor/components/ZoomablePattern.mjs
@@ -1,11 +1,12 @@
import React, { useState, useMemo, useCallback, forwardRef, useContext } from 'react'
import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch'
+import { Pattern } from '@freesewing/react/components/Pattern'
/*
* A pattern you can pan and zoom
*/
export const ZoomablePattern = forwardRef(function ZoomablePatternRef(props, ref) {
- const { renderProps, Swizzled, rotate } = props
+ const { renderProps, rotate } = props
const { onTransformed, setZoomFunctions } = useContext(ZoomContext)
return (
@@ -24,9 +25,8 @@ export const ZoomablePattern = forwardRef(function ZoomablePatternRef(props, ref
id="pan-zoom-pattern"
>
{props.children || (
-
diff --git a/packages/react/components/Editor/components/menus/CoreSettingsMenu.mjs b/packages/react/components/Editor/components/menus/CoreSettingsMenu.mjs
index 890e96e8fba..3c604677322 100644
--- a/packages/react/components/Editor/components/menus/CoreSettingsMenu.mjs
+++ b/packages/react/components/Editor/components/menus/CoreSettingsMenu.mjs
@@ -5,6 +5,22 @@ import {
menuCoreSettingsSammHandler,
menuCoreSettingsStructure,
} from '../../lib/index.mjs'
+import {
+ MenuBoolInput,
+ MenuListInput,
+ MenuMmInput,
+ MenuOnlySettingInput,
+ MenuSliderInput,
+} from './Input.mjs'
+import {
+ //MenuBoolValue,
+ MenuListValue,
+ MenuMmValue,
+ MenuOnlySettingValue,
+ MenuScaleSettingValue,
+} from './Value.mjs'
+import { MenuItemGroup } from './Container.mjs'
+import { SettingsIcon } from '@freesewing/react/components/Icon'
/**
* The core settings menu
diff --git a/packages/react/components/Editor/components/menus/UiPreferencesMenu.mjs b/packages/react/components/Editor/components/menus/UiPreferencesMenu.mjs
new file mode 100644
index 00000000000..ea578d6396c
--- /dev/null
+++ b/packages/react/components/Editor/components/menus/UiPreferencesMenu.mjs
@@ -0,0 +1,60 @@
+// Depdendencies
+import React from 'react'
+import { menuUiPreferencesStructure } from '../../lib/index.mjs'
+// Components
+import { MenuUxSettingInput, MenuListInput } from './Input.mjs'
+import { MenuListValue } from './Value.mjs'
+import { MenuItemGroup } from './Container.mjs'
+import { Ux } from '@freesewing/react/components/Ux'
+
+export const UiPreferencesMenu = ({ update, state, Design }) => {
+ console.log(state)
+ const structure = menuUiPreferencesStructure()
+
+ const drillProps = { Design, state, update }
+ const inputs = {
+ ux: (props) => ,
+ aside: (props) => ,
+ kiosk: (props) => ,
+ rotate: (props) => ,
+ renderer: (props) => ,
+ }
+ const values = {
+ ux: (props) => ,
+ aside: MenuListValue,
+ kiosk: MenuListValue,
+ rotate: MenuListValue,
+ renderer: MenuListValue,
+ }
+
+ return (
+ (
+
+ ),
+ isFirst: true,
+ name: 'pe:uiPreferences',
+ language: state.locale,
+ passProps: {
+ ux: state.ui?.ux,
+ settings: state.settings,
+ patternConfig: Design.patternConfig,
+ },
+ updateHandler: update.ui,
+ isDesignOptionsGroup: false,
+ state,
+ Design,
+ inputs,
+ values,
+ }}
+ />
+ )
+}
+
+export const UiPreference = ({ name, ux, ...rest }) => (
+ 3} ux={ux} />
+)
diff --git a/packages/react/components/Editor/components/menus/Value.mjs b/packages/react/components/Editor/components/menus/Value.mjs
index f72c49f32e1..fef47b76c7e 100644
--- a/packages/react/components/Editor/components/menus/Value.mjs
+++ b/packages/react/components/Editor/components/menus/Value.mjs
@@ -1,34 +1,62 @@
import React from 'react'
import { mergeOptions } from '@freesewing/core'
+import { formatMm } from '@freesewing/utils'
+import { BoolYesIcon, BoolNoIcon } from '@freesewing/react/components/Icon'
-/** Displays that constant values are not implemented in the front end */
+/**
+ * this method is here to capture deprecated use of the translation method
+ *
+ * @param {string} key - The translation key
+ * @retunr {string} key - Returns the key as-is
+ */
+const t = (key) => {
+ console.log('FIXME: t method called in react/components/Editor/components/menus/Value.mjs')
+ return key
+}
+
+/**
+ * Displays that constant values are not implemented in the front end
+ */
export const MenuConstantOptionValue = () => (
FIXME: No ConstantOptionvalue implemented
)
-/** Displays a count value*/
+/**
+ * Displays a count value
+ *
+ * @param {object} config - The option config
+ * @param {number} current - The current (count) value
+ * @param {bool} changed - Whether or not the value is non-default
+ */
export const MenuCountOptionValue = ({ config, current, changed }) => (
)
-/** Displays a degree value */
+/**
+ * Displays a degree value
+ *
+ * @param {object} config - The option config
+ * @param {number} current - The current (count) value
+ * @param {bool} changed - Whether or not the value is non-default
+ */
export const MenuDegOptionValue = ({ config, current, changed }) => (
{changed ? current : config.deg}°
)
/**
* A component to highlight a changed value
- * @param {Boolean} changed - Whether the value is changed or not
+ *
+ * @param {Boolean} changed - Whether the value is non-default
* @param {Function} children - The React children
*/
export const MenuHighlightValue = ({ changed, children }) => (
{children}
)
-/** Displays a list option value */
-export const MenuListOptionValue = (props) => (
- 'fixme handle option translation'} />
-)
+/**
+ * Displays a list option value
+ */
+export const MenuListOptionValue = (props) =>
/**
* Displays the correct, translated value for a list
@@ -51,20 +79,26 @@ export const MenuListValue = ({ current, config, changed }) => {
else if (val) key =
else key =
- const translated = config.doNotTranslate || typeof key !== 'string' ? key : t(key)
+ const translated = config.doNotTranslate || key
return {translated}
}
-/** Displays the corrent, translated value for a boolean */
+/**
+ * Displays the corrent, translated value for a boolean
+ */
export const MenuBoolValue = MenuListOptionValue
-/** Displays the MmOptions are not supported */
+/**
+ * Displays the MmOptions are not supported
+ */
export const MenuMmOptionValue = () => (
FIXME: No Mm Options are not supported
)
-/** Displays a formated mm value based on the current units */
+/**
+ * Displays a formated mm value based on the current units
+ */
export const MenuMmValue = ({ current, config, units, changed }) => (
(
)
-/** Displays the current percentage value, and the absolute value if configured
+/**
+ * Displays the current percentage value, and the absolute value if configured
*
**************************************************************************
* SliderIcon Title THIS *
@@ -83,7 +118,7 @@ export const MenuMmValue = ({ current, config, units, changed }) => (
* ----------------------0----------------------------------------------- *
* msg PencilIcon ResetIcon *
**************************************************************************
- * */
+ */
export const MenuPctOptionValue = ({ config, current, settings, changed, patternConfig }) => {
const val = changed ? current : config.pct / 100
@@ -101,6 +136,7 @@ export const MenuPctOptionValue = ({ config, current, settings, changed, pattern
/**
* A component to display a value, highligting it if it changed
+ *
* @param {Number|String|Boolean} options.current - The current value, if it has been changed
* @param {Number|String|Boolean} options.dflt - The default value
* @param {Boolean} options.changed - Has the value been changed?
@@ -109,10 +145,24 @@ export const MenuShowValue = ({ current, dflt, changed }) => {
return {changed ? current : dflt}
}
+/**
+ * Displays the value for core's scale setting
+ *
+ * @param {object} config - The option config
+ * @param {number} current - The current (count) value
+ * @param {bool} changed - Whether or not the value is non-default
+ */
export const MenuScaleSettingValue = ({ current, config, changed }) => (
)
+/**
+ * Displays the value for core's only setting
+ *
+ * @param {object} config - The option config
+ * @param {number} current - The current (count) value
+ * @param {bool} changed - Whether or not the value is non-default
+ */
export const MenuOnlySettingValue = ({ current, config }) => (
{
- const structure = Swizzled.methods.menuUiPreferencesStructure()
-
- const drillProps = { Design, state, update }
- const inputs = {
- ux: (props) => ,
- aside: (props) => ,
- kiosk: (props) => ,
- rotate: (props) => ,
- renderer: (props) => ,
- }
- const values = {
- ux: (props) => ,
- aside: Swizzled.components.MenuListValue,
- kiosk: Swizzled.components.MenuListValue,
- rotate: Swizzled.components.MenuListValue,
- renderer: Swizzled.components.MenuListValue,
- }
-
- return (
- (
-
- ),
- isFirst: true,
- name: 'pe:uiPreferences',
- language: state.locale,
- passProps: {
- ux: state.ui?.ux,
- settings: state.settings,
- patternConfig: Design.patternConfig,
- },
- updateHandler: update.ui,
- isDesignOptionsGroup: false,
- Swizzled,
- state,
- Design,
- inputs,
- values,
- }}
- />
- )
-}
-
-export const UiPreference = ({ Swizzled, name, ux, ...rest }) => (
- 3}
- ux={ux}
- />
-)
diff --git a/packages/react/components/Editor/components/views/index.mjs b/packages/react/components/Editor/components/views/index.mjs
index b8970b76fc4..6a488346b93 100644
--- a/packages/react/components/Editor/components/views/index.mjs
+++ b/packages/react/components/Editor/components/views/index.mjs
@@ -100,7 +100,7 @@ export const viewLabels = {
t: 'Choose a different view',
d: 'fixme',
},
- undos: {
+ undo: {
t: 'Undo History',
d: 'Time-travel through your recent pattern changes',
},
diff --git a/packages/react/components/Editor/lib/editor.mjs b/packages/react/components/Editor/lib/editor.mjs
index 0e0b1566ec1..611458fbf50 100644
--- a/packages/react/components/Editor/lib/editor.mjs
+++ b/packages/react/components/Editor/lib/editor.mjs
@@ -1,3 +1,5 @@
+// Dependencies
+import { defaultConfig } from '../config/index.mjs'
// Components
import {
ErrorIcon,
@@ -35,9 +37,10 @@ export function draft(Design, settings) {
return data
}
-export function flattenFlags(flags, config) {
+
+export function flattenFlags(flags) {
const all = {}
- for (const type of config.flagTypes) {
+ for (const type of defaultConfig.flagTypes) {
let i = 0
if (flags[type]) {
for (const flag of Object.values(flags[type])) {
diff --git a/packages/react/components/Editor/lib/ui-preferences.mjs b/packages/react/components/Editor/lib/ui-preferences.mjs
index 39c61b157fd..119984d7f6e 100644
--- a/packages/react/components/Editor/lib/ui-preferences.mjs
+++ b/packages/react/components/Editor/lib/ui-preferences.mjs
@@ -1,13 +1,22 @@
-export function menuUiPreferencesStructure(Swizzled) {
- const uiUx = Swizzled.config.uxLevels.ui
+import { defaultConfig } from '../config/index.mjs'
+import {
+ MenuIcon,
+ KioskIcon,
+ RotateIcon,
+ RocketIcon,
+ UxIcon,
+} from '@freesewing/react/components/Icon'
+
+export function menuUiPreferencesStructure() {
+ const uiUx = defaultConfig.uxLevels.ui
const uiPreferences = {
ux: {
ux: uiUx.ux,
emoji: '🖥️',
list: [1, 2, 3, 4, 5],
choiceTitles: {},
- icon: Swizzled.components.UxIcon,
- dflt: Swizzled.config.defaultUx,
+ icon: UxIcon,
+ dflt: defaultConfig.defaultUx,
},
aside: {
ux: uiUx.aside,
@@ -17,7 +26,7 @@ export function menuUiPreferencesStructure(Swizzled) {
1: 'pe:withAside',
},
dflt: 1,
- icon: Swizzled.components.MenuIcon,
+ icon: MenuIcon,
},
kiosk: {
ux: uiUx.kiosk,
@@ -27,7 +36,7 @@ export function menuUiPreferencesStructure(Swizzled) {
1: 'pe:kioskMode',
},
dflt: 0,
- icon: Swizzled.components.KioskIcon,
+ icon: KioskIcon,
},
rotate: {
ux: uiUx.rotate,
@@ -37,7 +46,7 @@ export function menuUiPreferencesStructure(Swizzled) {
1: 'pe:rotateYes',
},
dflt: 0,
- icon: Swizzled.components.RotateIcon,
+ icon: RotateIcon,
},
renderer: {
ux: uiUx.renderer,
@@ -51,7 +60,7 @@ export function menuUiPreferencesStructure(Swizzled) {
svg: 'SVG',
},
dflt: 'react',
- icon: Swizzled.components.RocketIcon,
+ icon: RocketIcon,
},
}
diff --git a/packages/react/components/Editor/swizzle/components/flags.mjs b/packages/react/components/Editor/swizzle/components/flags.mjs
deleted file mode 100644
index c549905f1fd..00000000000
--- a/packages/react/components/Editor/swizzle/components/flags.mjs
+++ /dev/null
@@ -1,103 +0,0 @@
-import mustache from 'mustache'
-
-export const FlagTypeIcon = ({ Swizzled, type, className = 'w-6 h-6' }) => {
- const Icon = Swizzled.components[`Flag${Swizzled.methods.capitalize(type)}Icon`]
-
- return Icon ? : null
-}
-
-export const Flag = ({ Swizzled, data, handleUpdate }) => {
- const btnIcon = data.suggest?.icon ? (
-
- ) : null
- const { t } = Swizzled.methods
-
- const button =
- data.suggest?.text && data.suggest?.update ? (
- handleUpdate(data.suggest.update)}
- >
- {btnIcon}
- {t(data.suggest.text)}
-
- ) : null
-
- const desc = data.replace ? mustache.render(t(data.desc), data.replace) : t(data.desc)
- const notes = data.notes
- ? Array.isArray(data.notes)
- ? '\n\n' +
- data.notes
- .map((note) => (data.replace ? mustache.render(t(note), data.replace) : t(note)))
- .join('\n\n')
- : '\n\n' + (data.replace ? mustache.render(t(data.notes), data.replace) : t(data.notes))
- : null
-
- return (
-
-
- {button ?
{button}
: null}
-
- )
-}
-//
-
-export const FlagsAccordionTitle = ({ flags, Swizzled }) => {
- const { t } = Swizzled.methods
- const flagList = Swizzled.methods.flattenFlags(flags)
-
- if (Object.keys(flagList).length < 1) return null
-
- return (
- <>
-
-
- {t('pe:flagMenu.t')} ({Object.keys(flagList).length})
-
-
-
-
- {Object.keys(flagList).length > 1 ? t('pe:flagMenuMany.d') : t('pe:flagMenuOne.d')}
-
- >
- )
-}
-
-export const FlagsAccordionEntries = ({ flags, update, Swizzled }) => {
- const flagList = Swizzled.methods.flattenFlags(flags)
- const { t } = Swizzled.methods
-
- if (Object.keys(flagList).length < 1) return null
-
- const handleUpdate = (config) => {
- if (config.settings) update.settings(...config.settings)
- if (config.ui) update.ui(...config.settings)
- }
-
- return (
- {
- const title = flag.replace ? mustache.render(t(flag.title), flag.replace) : t(flag.title)
-
- return [
- ,
- ,
- key,
- ]
- })}
- />
- )
-}
diff --git a/packages/react/components/Editor/swizzle/components/ux.mjs b/packages/react/components/Editor/swizzle/components/ux.mjs
deleted file mode 100644
index a48f72a2781..00000000000
--- a/packages/react/components/Editor/swizzle/components/ux.mjs
+++ /dev/null
@@ -1,12 +0,0 @@
-export const Ux = ({ Swizzled, ux = 0 }) => (
-
- {[0, 1, 2, 3, 4].map((i) => (
-
- ))}
-
-)
diff --git a/packages/react/components/Icon/index.mjs b/packages/react/components/Icon/index.mjs
index cfac80d20d9..487b52cf2c7 100644
--- a/packages/react/components/Icon/index.mjs
+++ b/packages/react/components/Icon/index.mjs
@@ -242,6 +242,13 @@ export const FingerprintIcon = (props) => (
)
+// Looks lik an exclamation point inside a circle
+export const FixmeIcon = (props) => (
+
+
+
+)
+
// Looks lik a flag
export const FlagIcon = (props) => (
@@ -753,12 +760,3 @@ export const ViewDocsIcon = DocsIcon
export const ViewDesignsIcon = DesignIcon
export const ViewViewPickerIcon = UiIcon
export const ViewUndosIcon = BackIcon
-// Flag icons
-export const FlagNoteIcon = ChatIcon
-export const FlagInfoIcon = DocsIcon
-export const FlagTipIcon = TipIcon
-export const FlagWarningIcon = WarningIcon
-export const FlagErrorIcon = ErrorIcon
-export const FlagFixmeIcon = WrenchIcon
-export const FlagExpandIcon = ExpandIcon
-export const FlagOtionsIcon = OptionsIcon
diff --git a/packages/react/components/Ux/index.mjs b/packages/react/components/Ux/index.mjs
new file mode 100644
index 00000000000..c01e1ffa99e
--- /dev/null
+++ b/packages/react/components/Ux/index.mjs
@@ -0,0 +1,15 @@
+import React from 'react'
+import { CircleIcon } from '@freesewing/react/components/Icon'
+
+export const Ux = ({ ux = 0 }) => (
+
+ {[0, 1, 2, 3, 4].map((i) => (
+
+ ))}
+
+)
diff --git a/packages/react/package.json b/packages/react/package.json
index 74dc6d1af64..fe2bb32d462 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -58,6 +58,7 @@
"./components/Table": "./components/Table/index.mjs",
"./components/Time": "./components/Time/index.mjs",
"./components/Uuid": "./components/Uuid/index.mjs",
+ "./components/Ux": "./components/Ux/index.mjs",
"./components/Yaml": "./components/Yaml/index.mjs",
"./components/Xray": "./components/Xray/index.mjs",
"./context/LoadingStatus": "./context/LoadingStatus/index.mjs",
@@ -81,12 +82,13 @@
"highlight.js": "^11.11.0",
"html-react-parser": "^5.0.7",
"luxon": "^3.5.0",
- "nuqs": "^2.3.0",
+ "nuqs": "^1.17.6",
"react-markdown": "^9.0.1",
"tlds": "^1.255.0",
"use-local-storage-state": "19.1.0",
"use-session-storage-state": "^19.0.0"
},
+ "devDependencies": {},
"files": [
"components/**",
"hooks/**",