wip: work on editor
This commit is contained in:
parent
30ae7b09da
commit
c8b989afcb
16 changed files with 345 additions and 215 deletions
|
@ -105,6 +105,7 @@ packageJson:
|
||||||
"./components/Table": "./components/Table/index.mjs"
|
"./components/Table": "./components/Table/index.mjs"
|
||||||
"./components/Time": "./components/Time/index.mjs"
|
"./components/Time": "./components/Time/index.mjs"
|
||||||
"./components/Uuid": "./components/Uuid/index.mjs"
|
"./components/Uuid": "./components/Uuid/index.mjs"
|
||||||
|
"./components/Ux": "./components/Ux/index.mjs"
|
||||||
"./components/Yaml": "./components/Yaml/index.mjs"
|
"./components/Yaml": "./components/Yaml/index.mjs"
|
||||||
"./components/Xray": "./components/Xray/index.mjs"
|
"./components/Xray": "./components/Xray/index.mjs"
|
||||||
# Context
|
# Context
|
||||||
|
|
131
packages/react/components/Editor/components/Flag.mjs
Normal file
131
packages/react/components/Editor/components/Flag.mjs
Normal file
|
@ -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 <Icon className={className} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Flag = ({ data, handleUpdate }) => {
|
||||||
|
const btnIcon = data.suggest?.icon ? (
|
||||||
|
<FlagTypeIcon type={data.suggest.icon} className="tw-w-5 tw-h-6 sm:tw-w-6 tw-h-6" />
|
||||||
|
) : null
|
||||||
|
|
||||||
|
const button =
|
||||||
|
data.suggest?.text && data.suggest?.update ? (
|
||||||
|
<button
|
||||||
|
className={`tw-btn tw-btn-secondary tw-btn-outline tw-flex tw-flex-row tw-items-center ${
|
||||||
|
btnIcon ? 'tw-gap-6' : ''
|
||||||
|
}`}
|
||||||
|
onClick={() => handleUpdate(data.suggest.update)}
|
||||||
|
>
|
||||||
|
{btnIcon}
|
||||||
|
{data.suggest.text}
|
||||||
|
</button>
|
||||||
|
) : 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 (
|
||||||
|
<div className="tw-flex tw-flex-col tw-gap-2 tw-items-start">
|
||||||
|
<div className="first:tw-mt-0 tw-grow md flag">
|
||||||
|
<pre>{desc}</pre>
|
||||||
|
<pre>{notes}</pre>
|
||||||
|
</div>
|
||||||
|
{button ? (
|
||||||
|
<div className="tw-mt-2 tw-w-full tw-flex tw-flex-row tw-justify-end">{button}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FlagsAccordionTitle = ({ flags }) => {
|
||||||
|
const flagList = flattenFlags(flags)
|
||||||
|
|
||||||
|
if (Object.keys(flagList).length < 1) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h5 className="tw-flex tw-flex-row tw-gap-2 tw-items-center tw-justify-between tw-w-full">
|
||||||
|
<span className="tw-text-left">Flags ({Object.keys(flagList).length})</span>
|
||||||
|
<FlagTypeIcon className="tw-w-8 tw-h-8" />
|
||||||
|
</h5>
|
||||||
|
<p className="tw-text-left">
|
||||||
|
{Object.keys(flagList).length > 1
|
||||||
|
? 'Some issues about your current pattern need your attention.'
|
||||||
|
: 'A specific issue about your current pattern needs your attention.'}
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<SubAccordion
|
||||||
|
items={Object.entries(flagList).map(([key, flag], i) => {
|
||||||
|
const title = flag.replace ? mustache.render(flag.title, flag.replace) : flag.title
|
||||||
|
|
||||||
|
return [
|
||||||
|
<div className="tw-w-full tw-flex tw-flex-row tw-gap2 tw-justify-between" key={i}>
|
||||||
|
<div className="tw-flex tw-flex-row tw-items-center tw-gap-2">
|
||||||
|
<div className="tw-no-shrink">
|
||||||
|
<FlagIcon type={flag.type} />
|
||||||
|
</div>
|
||||||
|
<span className="tw-font-medium tw-text-left">{title}</span>
|
||||||
|
</div>
|
||||||
|
<span className="tw-uppercase tw-font-bold">{flag.type}</span>
|
||||||
|
</div>,
|
||||||
|
<Flag key={key} data={flag} handleUpdate={handleUpdate} />,
|
||||||
|
key,
|
||||||
|
]
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
// Dependencies
|
// Dependencies
|
||||||
import { missingMeasurements } from '../lib/index.mjs'
|
import { missingMeasurements, flattenFlags } from '../lib/index.mjs'
|
||||||
// Hooks
|
// Hooks
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
// Components
|
// Components
|
||||||
|
@ -7,9 +7,29 @@ import { Null } from './Null.mjs'
|
||||||
import { AsideViewMenuSpacer } from './AsideViewMenu.mjs'
|
import { AsideViewMenuSpacer } from './AsideViewMenu.mjs'
|
||||||
import { ViewIcon, viewLabels } from './views/index.mjs'
|
import { ViewIcon, viewLabels } from './views/index.mjs'
|
||||||
import { Tooltip } from './Tooltip.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 { DesignOptionsMenu } from './menus/DesignOptionsMenu.mjs'
|
||||||
import { CoreSettingsMenu } from './menus/CoreSettingsMenu.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 }) => (
|
export const HeaderMenuAllViews = ({ config, state, update, open, setOpen }) => (
|
||||||
<HeaderMenuViewMenu {...{ config, state, update, open, setOpen }} />
|
<HeaderMenuViewMenu {...{ config, state, update, open, setOpen }} />
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import React, { useState, useMemo, useCallback, forwardRef, useContext } from 'react'
|
import React, { useState, useMemo, useCallback, forwardRef, useContext } from 'react'
|
||||||
import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch'
|
import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch'
|
||||||
|
import { Pattern } from '@freesewing/react/components/Pattern'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A pattern you can pan and zoom
|
* A pattern you can pan and zoom
|
||||||
*/
|
*/
|
||||||
export const ZoomablePattern = forwardRef(function ZoomablePatternRef(props, ref) {
|
export const ZoomablePattern = forwardRef(function ZoomablePatternRef(props, ref) {
|
||||||
const { renderProps, Swizzled, rotate } = props
|
const { renderProps, rotate } = props
|
||||||
const { onTransformed, setZoomFunctions } = useContext(ZoomContext)
|
const { onTransformed, setZoomFunctions } = useContext(ZoomContext)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -24,9 +25,8 @@ export const ZoomablePattern = forwardRef(function ZoomablePatternRef(props, ref
|
||||||
id="pan-zoom-pattern"
|
id="pan-zoom-pattern"
|
||||||
>
|
>
|
||||||
{props.children || (
|
{props.children || (
|
||||||
<Swizzled.components.Pattern
|
<Pattern
|
||||||
{...{ renderProps }}
|
{...{ renderProps }}
|
||||||
t={Swizzled.methods.t}
|
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={`freesewing pattern w-full ${rotate ? '-rotate-90' : ''}`}
|
className={`freesewing pattern w-full ${rotate ? '-rotate-90' : ''}`}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -5,6 +5,22 @@ import {
|
||||||
menuCoreSettingsSammHandler,
|
menuCoreSettingsSammHandler,
|
||||||
menuCoreSettingsStructure,
|
menuCoreSettingsStructure,
|
||||||
} from '../../lib/index.mjs'
|
} 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
|
* The core settings menu
|
||||||
|
|
|
@ -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) => <MenuUxSettingInput {...drillProps} {...props} />,
|
||||||
|
aside: (props) => <MenuListInput {...drillProps} {...props} />,
|
||||||
|
kiosk: (props) => <MenuListInput {...drillProps} {...props} />,
|
||||||
|
rotate: (props) => <MenuListInput {...drillProps} {...props} />,
|
||||||
|
renderer: (props) => <MenuListInput {...drillProps} {...props} />,
|
||||||
|
}
|
||||||
|
const values = {
|
||||||
|
ux: (props) => <Ux ux={state.ui.ux} {...props} />,
|
||||||
|
aside: MenuListValue,
|
||||||
|
kiosk: MenuListValue,
|
||||||
|
rotate: MenuListValue,
|
||||||
|
renderer: MenuListValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MenuItemGroup
|
||||||
|
{...{
|
||||||
|
structure,
|
||||||
|
ux: state.ui?.ux,
|
||||||
|
currentValues: state.ui || {},
|
||||||
|
Item: (props) => (
|
||||||
|
<UiPreference updateHandler={update} {...{ inputs, values, Design }} {...props} />
|
||||||
|
),
|
||||||
|
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 }) => (
|
||||||
|
<MenuItem {...rest} name={name} allowToggle={!['ux', 'view'].includes(name) && ux > 3} ux={ux} />
|
||||||
|
)
|
|
@ -1,34 +1,62 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { mergeOptions } from '@freesewing/core'
|
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 = () => (
|
export const MenuConstantOptionValue = () => (
|
||||||
<span className="text-error">FIXME: No ConstantOptionvalue implemented</span>
|
<span className="text-error">FIXME: No ConstantOptionvalue implemented</span>
|
||||||
)
|
)
|
||||||
|
|
||||||
/** 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 }) => (
|
export const MenuCountOptionValue = ({ config, current, changed }) => (
|
||||||
<MenuShowValue {...{ current, changed, dflt: config.count }} />
|
<MenuShowValue {...{ current, changed, dflt: config.count }} />
|
||||||
)
|
)
|
||||||
|
|
||||||
/** 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 }) => (
|
export const MenuDegOptionValue = ({ config, current, changed }) => (
|
||||||
<MenuHighlightValue changed={changed}> {changed ? current : config.deg}°</MenuHighlightValue>
|
<MenuHighlightValue changed={changed}> {changed ? current : config.deg}°</MenuHighlightValue>
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A component to highlight a changed value
|
* 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
|
* @param {Function} children - The React children
|
||||||
*/
|
*/
|
||||||
export const MenuHighlightValue = ({ changed, children }) => (
|
export const MenuHighlightValue = ({ changed, children }) => (
|
||||||
<span className={changed ? 'text-accent' : ''}> {children} </span>
|
<span className={changed ? 'text-accent' : ''}> {children} </span>
|
||||||
)
|
)
|
||||||
|
|
||||||
/** Displays a list option value */
|
/**
|
||||||
export const MenuListOptionValue = (props) => (
|
* Displays a list option value
|
||||||
<MenuListValue {...props} t={(input) => 'fixme handle option translation'} />
|
*/
|
||||||
)
|
export const MenuListOptionValue = (props) => <MenuListValue {...props} t={t} />
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the correct, translated value for a list
|
* Displays the correct, translated value for a list
|
||||||
|
@ -51,20 +79,26 @@ export const MenuListValue = ({ current, config, changed }) => {
|
||||||
else if (val) key = <BoolYesIcon />
|
else if (val) key = <BoolYesIcon />
|
||||||
else key = <BoolNoIcon />
|
else key = <BoolNoIcon />
|
||||||
|
|
||||||
const translated = config.doNotTranslate || typeof key !== 'string' ? key : t(key)
|
const translated = config.doNotTranslate || key
|
||||||
|
|
||||||
return <MenuHighlightValue changed={changed}>{translated}</MenuHighlightValue>
|
return <MenuHighlightValue changed={changed}>{translated}</MenuHighlightValue>
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Displays the corrent, translated value for a boolean */
|
/**
|
||||||
|
* Displays the corrent, translated value for a boolean
|
||||||
|
*/
|
||||||
export const MenuBoolValue = MenuListOptionValue
|
export const MenuBoolValue = MenuListOptionValue
|
||||||
|
|
||||||
/** Displays the MmOptions are not supported */
|
/**
|
||||||
|
* Displays the MmOptions are not supported
|
||||||
|
*/
|
||||||
export const MenuMmOptionValue = () => (
|
export const MenuMmOptionValue = () => (
|
||||||
<span className="text-error">FIXME: No Mm Options are not supported</span>
|
<span className="text-error">FIXME: No Mm Options are not supported</span>
|
||||||
)
|
)
|
||||||
|
|
||||||
/** 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 }) => (
|
export const MenuMmValue = ({ current, config, units, changed }) => (
|
||||||
<MenuHighlightValue changed={changed}>
|
<MenuHighlightValue changed={changed}>
|
||||||
<span
|
<span
|
||||||
|
@ -75,7 +109,8 @@ export const MenuMmValue = ({ current, config, units, changed }) => (
|
||||||
</MenuHighlightValue>
|
</MenuHighlightValue>
|
||||||
)
|
)
|
||||||
|
|
||||||
/** 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 *
|
* SliderIcon Title THIS *
|
||||||
|
@ -83,7 +118,7 @@ export const MenuMmValue = ({ current, config, units, changed }) => (
|
||||||
* ----------------------0----------------------------------------------- *
|
* ----------------------0----------------------------------------------- *
|
||||||
* msg PencilIcon ResetIcon *
|
* msg PencilIcon ResetIcon *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* */
|
*/
|
||||||
export const MenuPctOptionValue = ({ config, current, settings, changed, patternConfig }) => {
|
export const MenuPctOptionValue = ({ config, current, settings, changed, patternConfig }) => {
|
||||||
const val = changed ? current : config.pct / 100
|
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
|
* 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.current - The current value, if it has been changed
|
||||||
* @param {Number|String|Boolean} options.dflt - The default value
|
* @param {Number|String|Boolean} options.dflt - The default value
|
||||||
* @param {Boolean} options.changed - Has the value been changed?
|
* @param {Boolean} options.changed - Has the value been changed?
|
||||||
|
@ -109,10 +145,24 @@ export const MenuShowValue = ({ current, dflt, changed }) => {
|
||||||
return <MenuHighlightValue changed={changed}> {changed ? current : dflt} </MenuHighlightValue>
|
return <MenuHighlightValue changed={changed}> {changed ? current : dflt} </MenuHighlightValue>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 }) => (
|
export const MenuScaleSettingValue = ({ current, config, changed }) => (
|
||||||
<MenuHighlightValue current={current} dflt={config.dflt} changed={changed} />
|
<MenuHighlightValue current={current} dflt={config.dflt} changed={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 }) => (
|
export const MenuOnlySettingValue = ({ current, config }) => (
|
||||||
<MenuHighlightValue
|
<MenuHighlightValue
|
||||||
current={current?.length}
|
current={current?.length}
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
export const UiPreferencesMenu = ({ Swizzled, update, state, Design }) => {
|
|
||||||
const structure = Swizzled.methods.menuUiPreferencesStructure()
|
|
||||||
|
|
||||||
const drillProps = { Design, state, update }
|
|
||||||
const inputs = {
|
|
||||||
ux: (props) => <Swizzled.components.MenuUxSettingInput {...drillProps} {...props} />,
|
|
||||||
aside: (props) => <Swizzled.components.MenuListInput {...drillProps} {...props} />,
|
|
||||||
kiosk: (props) => <Swizzled.components.MenuListInput {...drillProps} {...props} />,
|
|
||||||
rotate: (props) => <Swizzled.components.MenuListInput {...drillProps} {...props} />,
|
|
||||||
renderer: (props) => <Swizzled.components.MenuListInput {...drillProps} {...props} />,
|
|
||||||
}
|
|
||||||
const values = {
|
|
||||||
ux: (props) => <Swizzled.components.Ux ux={state.ui.ux} {...props} />,
|
|
||||||
aside: Swizzled.components.MenuListValue,
|
|
||||||
kiosk: Swizzled.components.MenuListValue,
|
|
||||||
rotate: Swizzled.components.MenuListValue,
|
|
||||||
renderer: Swizzled.components.MenuListValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Swizzled.components.MenuItemGroup
|
|
||||||
{...{
|
|
||||||
structure,
|
|
||||||
ux: state.ui?.ux,
|
|
||||||
currentValues: state.ui || {},
|
|
||||||
Item: (props) => (
|
|
||||||
<Swizzled.components.UiPreference
|
|
||||||
updateHandler={update}
|
|
||||||
{...{ inputs, values, Swizzled, Design }}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
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 }) => (
|
|
||||||
<Swizzled.components.MenuItem
|
|
||||||
{...rest}
|
|
||||||
name={name}
|
|
||||||
allowToggle={!['ux', 'view'].includes(name) && ux > 3}
|
|
||||||
ux={ux}
|
|
||||||
/>
|
|
||||||
)
|
|
|
@ -100,7 +100,7 @@ export const viewLabels = {
|
||||||
t: 'Choose a different view',
|
t: 'Choose a different view',
|
||||||
d: 'fixme',
|
d: 'fixme',
|
||||||
},
|
},
|
||||||
undos: {
|
undo: {
|
||||||
t: 'Undo History',
|
t: 'Undo History',
|
||||||
d: 'Time-travel through your recent pattern changes',
|
d: 'Time-travel through your recent pattern changes',
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// Dependencies
|
||||||
|
import { defaultConfig } from '../config/index.mjs'
|
||||||
// Components
|
// Components
|
||||||
import {
|
import {
|
||||||
ErrorIcon,
|
ErrorIcon,
|
||||||
|
@ -35,9 +37,10 @@ export function draft(Design, settings) {
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
export function flattenFlags(flags, config) {
|
|
||||||
|
export function flattenFlags(flags) {
|
||||||
const all = {}
|
const all = {}
|
||||||
for (const type of config.flagTypes) {
|
for (const type of defaultConfig.flagTypes) {
|
||||||
let i = 0
|
let i = 0
|
||||||
if (flags[type]) {
|
if (flags[type]) {
|
||||||
for (const flag of Object.values(flags[type])) {
|
for (const flag of Object.values(flags[type])) {
|
||||||
|
|
|
@ -1,13 +1,22 @@
|
||||||
export function menuUiPreferencesStructure(Swizzled) {
|
import { defaultConfig } from '../config/index.mjs'
|
||||||
const uiUx = Swizzled.config.uxLevels.ui
|
import {
|
||||||
|
MenuIcon,
|
||||||
|
KioskIcon,
|
||||||
|
RotateIcon,
|
||||||
|
RocketIcon,
|
||||||
|
UxIcon,
|
||||||
|
} from '@freesewing/react/components/Icon'
|
||||||
|
|
||||||
|
export function menuUiPreferencesStructure() {
|
||||||
|
const uiUx = defaultConfig.uxLevels.ui
|
||||||
const uiPreferences = {
|
const uiPreferences = {
|
||||||
ux: {
|
ux: {
|
||||||
ux: uiUx.ux,
|
ux: uiUx.ux,
|
||||||
emoji: '🖥️',
|
emoji: '🖥️',
|
||||||
list: [1, 2, 3, 4, 5],
|
list: [1, 2, 3, 4, 5],
|
||||||
choiceTitles: {},
|
choiceTitles: {},
|
||||||
icon: Swizzled.components.UxIcon,
|
icon: UxIcon,
|
||||||
dflt: Swizzled.config.defaultUx,
|
dflt: defaultConfig.defaultUx,
|
||||||
},
|
},
|
||||||
aside: {
|
aside: {
|
||||||
ux: uiUx.aside,
|
ux: uiUx.aside,
|
||||||
|
@ -17,7 +26,7 @@ export function menuUiPreferencesStructure(Swizzled) {
|
||||||
1: 'pe:withAside',
|
1: 'pe:withAside',
|
||||||
},
|
},
|
||||||
dflt: 1,
|
dflt: 1,
|
||||||
icon: Swizzled.components.MenuIcon,
|
icon: MenuIcon,
|
||||||
},
|
},
|
||||||
kiosk: {
|
kiosk: {
|
||||||
ux: uiUx.kiosk,
|
ux: uiUx.kiosk,
|
||||||
|
@ -27,7 +36,7 @@ export function menuUiPreferencesStructure(Swizzled) {
|
||||||
1: 'pe:kioskMode',
|
1: 'pe:kioskMode',
|
||||||
},
|
},
|
||||||
dflt: 0,
|
dflt: 0,
|
||||||
icon: Swizzled.components.KioskIcon,
|
icon: KioskIcon,
|
||||||
},
|
},
|
||||||
rotate: {
|
rotate: {
|
||||||
ux: uiUx.rotate,
|
ux: uiUx.rotate,
|
||||||
|
@ -37,7 +46,7 @@ export function menuUiPreferencesStructure(Swizzled) {
|
||||||
1: 'pe:rotateYes',
|
1: 'pe:rotateYes',
|
||||||
},
|
},
|
||||||
dflt: 0,
|
dflt: 0,
|
||||||
icon: Swizzled.components.RotateIcon,
|
icon: RotateIcon,
|
||||||
},
|
},
|
||||||
renderer: {
|
renderer: {
|
||||||
ux: uiUx.renderer,
|
ux: uiUx.renderer,
|
||||||
|
@ -51,7 +60,7 @@ export function menuUiPreferencesStructure(Swizzled) {
|
||||||
svg: 'SVG',
|
svg: 'SVG',
|
||||||
},
|
},
|
||||||
dflt: 'react',
|
dflt: 'react',
|
||||||
icon: Swizzled.components.RocketIcon,
|
icon: RocketIcon,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 ? <Icon className={className} /> : null
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Flag = ({ Swizzled, data, handleUpdate }) => {
|
|
||||||
const btnIcon = data.suggest?.icon ? (
|
|
||||||
<Swizzled.components.FlagTypeIcon type={data.suggest.icon} className="w-5 h-6 sm:w-6 h-6" />
|
|
||||||
) : null
|
|
||||||
const { t } = Swizzled.methods
|
|
||||||
|
|
||||||
const button =
|
|
||||||
data.suggest?.text && data.suggest?.update ? (
|
|
||||||
<button
|
|
||||||
className={`btn btn-secondary btn-outline flex flex-row items-center ${
|
|
||||||
btnIcon ? 'gap-6' : ''
|
|
||||||
}`}
|
|
||||||
onClick={() => handleUpdate(data.suggest.update)}
|
|
||||||
>
|
|
||||||
{btnIcon}
|
|
||||||
{t(data.suggest.text)}
|
|
||||||
</button>
|
|
||||||
) : 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 (
|
|
||||||
<div className="flex flex-col gap-2 items-start">
|
|
||||||
<div className="first:mt-0 grow md flag">
|
|
||||||
<pre>{desc}</pre>
|
|
||||||
<pre>{notes}</pre>
|
|
||||||
</div>
|
|
||||||
{button ? <div className="mt-2 w-full flex flex-row justify-end">{button}</div> : null}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
//<Mdx md={notes ? desc + notes : desc} />
|
|
||||||
|
|
||||||
export const FlagsAccordionTitle = ({ flags, Swizzled }) => {
|
|
||||||
const { t } = Swizzled.methods
|
|
||||||
const flagList = Swizzled.methods.flattenFlags(flags)
|
|
||||||
|
|
||||||
if (Object.keys(flagList).length < 1) return null
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h5 className="flex flex-row gap-2 items-center justify-between w-full">
|
|
||||||
<span className="text-left">
|
|
||||||
{t('pe:flagMenu.t')} ({Object.keys(flagList).length})
|
|
||||||
</span>
|
|
||||||
<Swizzled.components.FlagTypeIcon className="w-8 h-8" />
|
|
||||||
</h5>
|
|
||||||
<p className="text-left">
|
|
||||||
{Object.keys(flagList).length > 1 ? t('pe:flagMenuMany.d') : t('pe:flagMenuOne.d')}
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<Swizzled.components.SubAccordion
|
|
||||||
items={Object.entries(flagList).map(([key, flag], i) => {
|
|
||||||
const title = flag.replace ? mustache.render(t(flag.title), flag.replace) : t(flag.title)
|
|
||||||
|
|
||||||
return [
|
|
||||||
<div className="w-full flex flex-row gap2 justify-between" key={i}>
|
|
||||||
<div className="flex flex-row items-center gap-2">
|
|
||||||
<div className="no-shrink">
|
|
||||||
<Swizzled.components.FlagIcon type={flag.type} />
|
|
||||||
</div>
|
|
||||||
<span className="font-medium text-left">{title}</span>
|
|
||||||
</div>
|
|
||||||
<span className="uppercase font-bold">{flag.type}</span>
|
|
||||||
</div>,
|
|
||||||
<Swizzled.components.Flag key={key} t={t} data={flag} handleUpdate={handleUpdate} />,
|
|
||||||
key,
|
|
||||||
]
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
export const Ux = ({ Swizzled, ux = 0 }) => (
|
|
||||||
<div className="flex flex-row">
|
|
||||||
{[0, 1, 2, 3, 4].map((i) => (
|
|
||||||
<Swizzled.components.CircleIcon
|
|
||||||
key={i}
|
|
||||||
fill={i < ux ? true : false}
|
|
||||||
className={`w-6 h-6 ${i < ux ? 'stroke-secondary fill-secondary' : 'stroke-current'}`}
|
|
||||||
fillOpacity={0.3}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)
|
|
|
@ -242,6 +242,13 @@ export const FingerprintIcon = (props) => (
|
||||||
</IconWrapper>
|
</IconWrapper>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Looks lik an exclamation point inside a circle
|
||||||
|
export const FixmeIcon = (props) => (
|
||||||
|
<IconWrapper {...props}>
|
||||||
|
<path d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
|
||||||
|
</IconWrapper>
|
||||||
|
)
|
||||||
|
|
||||||
// Looks lik a flag
|
// Looks lik a flag
|
||||||
export const FlagIcon = (props) => (
|
export const FlagIcon = (props) => (
|
||||||
<IconWrapper {...props}>
|
<IconWrapper {...props}>
|
||||||
|
@ -753,12 +760,3 @@ export const ViewDocsIcon = DocsIcon
|
||||||
export const ViewDesignsIcon = DesignIcon
|
export const ViewDesignsIcon = DesignIcon
|
||||||
export const ViewViewPickerIcon = UiIcon
|
export const ViewViewPickerIcon = UiIcon
|
||||||
export const ViewUndosIcon = BackIcon
|
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
|
|
||||||
|
|
15
packages/react/components/Ux/index.mjs
Normal file
15
packages/react/components/Ux/index.mjs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { CircleIcon } from '@freesewing/react/components/Icon'
|
||||||
|
|
||||||
|
export const Ux = ({ ux = 0 }) => (
|
||||||
|
<div className="flex flex-row">
|
||||||
|
{[0, 1, 2, 3, 4].map((i) => (
|
||||||
|
<CircleIcon
|
||||||
|
key={i}
|
||||||
|
fill={i < ux ? true : false}
|
||||||
|
className={`tw-w-6 tw-h-6 ${i < ux ? 'tw-stroke-secondary tw-fill-secondary' : 'tw-stroke-current'}`}
|
||||||
|
fillOpacity={0.3}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
|
@ -58,6 +58,7 @@
|
||||||
"./components/Table": "./components/Table/index.mjs",
|
"./components/Table": "./components/Table/index.mjs",
|
||||||
"./components/Time": "./components/Time/index.mjs",
|
"./components/Time": "./components/Time/index.mjs",
|
||||||
"./components/Uuid": "./components/Uuid/index.mjs",
|
"./components/Uuid": "./components/Uuid/index.mjs",
|
||||||
|
"./components/Ux": "./components/Ux/index.mjs",
|
||||||
"./components/Yaml": "./components/Yaml/index.mjs",
|
"./components/Yaml": "./components/Yaml/index.mjs",
|
||||||
"./components/Xray": "./components/Xray/index.mjs",
|
"./components/Xray": "./components/Xray/index.mjs",
|
||||||
"./context/LoadingStatus": "./context/LoadingStatus/index.mjs",
|
"./context/LoadingStatus": "./context/LoadingStatus/index.mjs",
|
||||||
|
@ -81,12 +82,13 @@
|
||||||
"highlight.js": "^11.11.0",
|
"highlight.js": "^11.11.0",
|
||||||
"html-react-parser": "^5.0.7",
|
"html-react-parser": "^5.0.7",
|
||||||
"luxon": "^3.5.0",
|
"luxon": "^3.5.0",
|
||||||
"nuqs": "^2.3.0",
|
"nuqs": "^1.17.6",
|
||||||
"react-markdown": "^9.0.1",
|
"react-markdown": "^9.0.1",
|
||||||
"tlds": "^1.255.0",
|
"tlds": "^1.255.0",
|
||||||
"use-local-storage-state": "19.1.0",
|
"use-local-storage-state": "19.1.0",
|
||||||
"use-session-storage-state": "^19.0.0"
|
"use-session-storage-state": "^19.0.0"
|
||||||
},
|
},
|
||||||
|
"devDependencies": {},
|
||||||
"files": [
|
"files": [
|
||||||
"components/**",
|
"components/**",
|
||||||
"hooks/**",
|
"hooks/**",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue