wip(shared): Work on workbench views
This commit is contained in:
parent
cab7f5d2c5
commit
c53ff25053
25 changed files with 386 additions and 96 deletions
|
@ -12,7 +12,7 @@ const OpenTitleButton = ({
|
||||||
<div
|
<div
|
||||||
role="button"
|
role="button"
|
||||||
className={`flex flex-row items-center justify-between w-full ${
|
className={`flex flex-row items-center justify-between w-full ${
|
||||||
top ? 'lg:rounded-t-lg' : 'lg:rounded-b-lg'
|
bottom ? 'lg:rounded-b-lg' : 'lg:rounded-t-lg'
|
||||||
}
|
}
|
||||||
bg-${color} text-${color}-content px-4 py-1 text-lg font-medium`}
|
bg-${color} text-${color}-content px-4 py-1 text-lg font-medium`}
|
||||||
onClick={toggle}
|
onClick={toggle}
|
||||||
|
|
|
@ -8,10 +8,10 @@ import { LoadingContext } from 'shared/context/loading-context.mjs'
|
||||||
import {
|
import {
|
||||||
BeakerIcon,
|
BeakerIcon,
|
||||||
BriefcaseIcon,
|
BriefcaseIcon,
|
||||||
ClearIcon,
|
|
||||||
CodeIcon,
|
CodeIcon,
|
||||||
CutIcon,
|
CutIcon,
|
||||||
FingerprintIcon,
|
HelpIcon,
|
||||||
|
HomeIcon,
|
||||||
MenuIcon,
|
MenuIcon,
|
||||||
OptionsIcon,
|
OptionsIcon,
|
||||||
PrintIcon,
|
PrintIcon,
|
||||||
|
@ -20,8 +20,6 @@ import {
|
||||||
import { Ribbon } from 'shared/components/ribbon.mjs'
|
import { Ribbon } from 'shared/components/ribbon.mjs'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { ModalMenu } from 'site/components/navigation/modal-menu.mjs'
|
import { ModalMenu } from 'site/components/navigation/modal-menu.mjs'
|
||||||
import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
|
|
||||||
import { ControlSettings } from 'shared/components/account/control.mjs'
|
|
||||||
|
|
||||||
export const ns = ['workbench', 'sections']
|
export const ns = ['workbench', 'sections']
|
||||||
|
|
||||||
|
@ -40,6 +38,7 @@ export const NavButton = ({
|
||||||
active ? 'font-heavy' : ''
|
active ? 'font-heavy' : ''
|
||||||
}`
|
}`
|
||||||
const span = <span className="block font-bold hidden 2xl:block">{label}</span>
|
const span = <span className="block font-bold hidden 2xl:block">{label}</span>
|
||||||
|
console.log('in button', label, onClick)
|
||||||
|
|
||||||
return onClick ? (
|
return onClick ? (
|
||||||
<button {...{ onClick, className }} title={label}>
|
<button {...{ onClick, className }} title={label}>
|
||||||
|
@ -143,37 +142,27 @@ const NavIcons = ({ setModal, setView, view }) => {
|
||||||
>
|
>
|
||||||
<CodeIcon className={iconSize} />
|
<CodeIcon className={iconSize} />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
<NavButton
|
|
||||||
onClick={() => setView('clear')}
|
|
||||||
label={t('workbench:clear')}
|
|
||||||
color={colors[8]}
|
|
||||||
extraClasses="hidden lg:flex"
|
|
||||||
>
|
|
||||||
<ClearIcon className={iconSize} />
|
|
||||||
</NavButton>
|
|
||||||
<NavSpacer />
|
<NavSpacer />
|
||||||
<NavButton
|
<NavButton
|
||||||
label={t('workbench:control')}
|
label={t('workbench:help')}
|
||||||
color={colors[9]}
|
color={colors[8]}
|
||||||
onClick={() =>
|
href="/docs/site/draft"
|
||||||
setModal(
|
extraClasses="hidden lg:flex"
|
||||||
<ModalWrapper>
|
|
||||||
<ControlSettings noBack title />
|
|
||||||
<div className="mb-3"></div>
|
|
||||||
</ModalWrapper>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<FingerprintIcon className={iconSize} />
|
<HelpIcon className={iconSize} />
|
||||||
|
</NavButton>
|
||||||
|
<NavButton label={t('workbench:home')} color={colors[9]} href="/">
|
||||||
|
<HomeIcon className={iconSize} />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WorkbenchHeader = ({ view, setView }) => {
|
export const WorkbenchHeader = ({ view, setView, update }) => {
|
||||||
const { setModal } = useContext(ModalContext)
|
const { setModal } = useContext(ModalContext)
|
||||||
const { loading } = useContext(LoadingContext)
|
const { loading } = useContext(LoadingContext)
|
||||||
const [show, setShow] = useState(true)
|
const [show, setShow] = useState(true)
|
||||||
|
console.log('header', update)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
|
@ -196,7 +185,7 @@ export const WorkbenchHeader = ({ view, setView }) => {
|
||||||
|
|
||||||
{/* Mobile content */}
|
{/* Mobile content */}
|
||||||
<div className="flex lg:hidden flex-row items-center justify-between w-full">
|
<div className="flex lg:hidden flex-row items-center justify-between w-full">
|
||||||
<NavIcons setModal={setModal} setView={setView} />
|
<NavIcons {...{ setModal, setView, update }} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -38,6 +38,7 @@ export const Workbench = ({ design, Design, baseSettings, DynamicDocs, from }) =
|
||||||
// Effect
|
// Effect
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Force re-render when baseSettings changes. Required when they are loaded async.
|
// Force re-render when baseSettings changes. Required when they are loaded async.
|
||||||
|
console.log('in effect')
|
||||||
setSettings({ ...baseSettings, embed: true })
|
setSettings({ ...baseSettings, embed: true })
|
||||||
}, [baseSettings])
|
}, [baseSettings])
|
||||||
|
|
||||||
|
@ -54,11 +55,11 @@ export const Workbench = ({ design, Design, baseSettings, DynamicDocs, from }) =
|
||||||
if (error)
|
if (error)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WorkbenchHeader setView={setView} />
|
<WorkbenchHeader {...{ view, setView, update }} />
|
||||||
{error}
|
{error}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
console.log(baseSettings)
|
|
||||||
// Deal with each view
|
// Deal with each view
|
||||||
const viewProps = {
|
const viewProps = {
|
||||||
account,
|
account,
|
||||||
|
@ -102,7 +103,7 @@ export const Workbench = ({ design, Design, baseSettings, DynamicDocs, from }) =
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WorkbenchHeader setView={setView} view={view} />
|
<WorkbenchHeader {...{ view, setView, update }} />
|
||||||
{viewContent}
|
{viewContent}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -111,18 +111,4 @@ export const loadSettingsConfig = ({
|
||||||
step: 1,
|
step: 1,
|
||||||
emoji: '🔲',
|
emoji: '🔲',
|
||||||
},
|
},
|
||||||
renderer: {
|
|
||||||
control: 4, // Show when control > 3
|
|
||||||
list: ['react', 'svg'],
|
|
||||||
choiceTitles: {
|
|
||||||
react: 'renderWithReact',
|
|
||||||
svg: 'renderWithCore',
|
|
||||||
},
|
|
||||||
valueTitles: {
|
|
||||||
react: 'React',
|
|
||||||
svg: 'SVG',
|
|
||||||
},
|
|
||||||
dflt: 'react',
|
|
||||||
emoji: '🚀',
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,12 +19,6 @@ margin.t: Margin
|
||||||
margin.d: Controls the margin around pattern parts
|
margin.d: Controls the margin around pattern parts
|
||||||
scale.t: Scale
|
scale.t: Scale
|
||||||
scale.d: Controls the overall line width, font size, and other elements that do not scale with the pattern's measurements
|
scale.d: Controls the overall line width, font size, and other elements that do not scale with the pattern's measurements
|
||||||
renderer.t: Render Engine
|
|
||||||
renderer.d: Controls how the pattern is rendered (drawn) on the screen
|
|
||||||
renderWithReact.t: Render with FreeSewing's React components
|
|
||||||
renderWithReact.d: Render as SVG through our React components. Allows interactivity and is optimized for screen. Use this if you are not sure what to pick.
|
|
||||||
renderWithCore.t: Render with Freesewing's Core library
|
|
||||||
renderWithCore.d: Render directly to SVG from Core. Allows no interactivity and is optimized for print. Use this if you want to know what it will look like when exported.
|
|
||||||
de.t: German
|
de.t: German
|
||||||
de.d: Use this to generate a German pattern
|
de.d: Use this to generate a German pattern
|
||||||
en.t: English
|
en.t: English
|
||||||
|
|
|
@ -62,7 +62,7 @@ const inputs = {
|
||||||
units: UnitsSettingInput,
|
units: UnitsSettingInput,
|
||||||
}
|
}
|
||||||
|
|
||||||
const CoreTitle = ({ name, t, changed, current = null, open = false, emoji = '' }) => (
|
export const CoreTitle = ({ name, t, changed, current = null, open = false, emoji = '' }) => (
|
||||||
<div className={`flex flex-row gap-1 items-center w-full ${open ? '' : 'justify-between'}`}>
|
<div className={`flex flex-row gap-1 items-center w-full ${open ? '' : 'justify-between'}`}>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
<span role="img" className="pr-2">
|
<span role="img" className="pr-2">
|
||||||
|
@ -94,6 +94,7 @@ export const Setting = ({
|
||||||
settingsConfig,
|
settingsConfig,
|
||||||
changed,
|
changed,
|
||||||
loadDocs,
|
loadDocs,
|
||||||
|
control,
|
||||||
}) => {
|
}) => {
|
||||||
const drillProps = { name, config, current, update, t, units, changed }
|
const drillProps = { name, config, current, update, t, units, changed }
|
||||||
|
|
||||||
|
@ -144,6 +145,36 @@ export const Setting = ({
|
||||||
|
|
||||||
const titleProps = { name, t, current: <Value {...drillProps} />, emoji: config.emoji }
|
const titleProps = { name, t, current: <Value {...drillProps} />, emoji: config.emoji }
|
||||||
|
|
||||||
|
const boolSettings = ['sabool', 'paperless', 'details']
|
||||||
|
|
||||||
|
if (control > 4) {
|
||||||
|
// Save gurus some clicks
|
||||||
|
if (boolSettings.includes(name))
|
||||||
|
return (
|
||||||
|
<Collapse
|
||||||
|
color={changed ? 'accent' : 'primary'}
|
||||||
|
title={<CoreTitle {...titleProps} />}
|
||||||
|
onClick={() => update.settings([name], current ? 0 : 1)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
if (name === 'units')
|
||||||
|
return (
|
||||||
|
<Collapse
|
||||||
|
color={changed ? 'accent' : 'primary'}
|
||||||
|
title={<CoreTitle {...titleProps} />}
|
||||||
|
onClick={() => update.settings([name], current === 'metric' ? 'imperial' : 'metric')}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
if (name === 'renderer')
|
||||||
|
return (
|
||||||
|
<Collapse
|
||||||
|
color={changed ? 'accent' : 'primary'}
|
||||||
|
title={<CoreTitle {...titleProps} />}
|
||||||
|
onClick={() => update.ui([name], current === 'svg' ? 'react' : 'svg')}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Collapse
|
<Collapse
|
||||||
color={changed ? 'accent' : 'primary'}
|
color={changed ? 'accent' : 'primary'}
|
||||||
|
@ -230,7 +261,7 @@ export const CoreSettings = ({
|
||||||
.map((name) => (
|
.map((name) => (
|
||||||
<Setting
|
<Setting
|
||||||
key={name}
|
key={name}
|
||||||
{...{ name, design, update, t, patternConfig, loadDocs }}
|
{...{ name, design, update, t, patternConfig, loadDocs, control }}
|
||||||
config={settingsConfig[name]}
|
config={settingsConfig[name]}
|
||||||
current={settings[name]}
|
current={settings[name]}
|
||||||
changed={wasChanged(settings[name], name, settingsConfig)}
|
changed={wasChanged(settings[name], name, settingsConfig)}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { ChoiceButton } from 'shared/components/choice-button.mjs'
|
||||||
import orderBy from 'lodash.orderby'
|
import orderBy from 'lodash.orderby'
|
||||||
|
|
||||||
// Shared input for list inputs
|
// Shared input for list inputs
|
||||||
export const ListSetting = ({ name, list, config, current, update, t }) => {
|
export const ListSetting = ({ name, list, config, current, update, t, setUi }) => {
|
||||||
if (typeof current === 'undefined') current = config.dflt
|
if (typeof current === 'undefined') current = config.dflt
|
||||||
|
|
||||||
const [value, setValue] = useState(current)
|
const [value, setValue] = useState(current)
|
||||||
|
@ -12,7 +12,8 @@ export const ListSetting = ({ name, list, config, current, update, t }) => {
|
||||||
const handleChange = (newCurrent) => {
|
const handleChange = (newCurrent) => {
|
||||||
if (newCurrent === config.dflt) reset()
|
if (newCurrent === config.dflt) reset()
|
||||||
else {
|
else {
|
||||||
update.settings([name], newCurrent)
|
if (setUi) update.ui(setUi, newCurrent)
|
||||||
|
else update.settings([name], newCurrent)
|
||||||
setValue(newCurrent)
|
setValue(newCurrent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +140,6 @@ export const UnitsSettingInputs = ({ name, config, current, update, t }) => (
|
||||||
|
|
||||||
export const MarginSettingInput = (props) => <MmSetting {...props} />
|
export const MarginSettingInput = (props) => <MmSetting {...props} />
|
||||||
export const ScaleSettingInput = (props) => <NrSetting {...props} />
|
export const ScaleSettingInput = (props) => <NrSetting {...props} />
|
||||||
export const RendererSettingInput = (props) => <ListSetting {...props} />
|
|
||||||
export const CompleteSettingInput = (props) => <ListSetting {...props} />
|
export const CompleteSettingInput = (props) => <ListSetting {...props} />
|
||||||
export const PaperlessSettingInput = (props) => <ListSetting {...props} />
|
export const PaperlessSettingInput = (props) => <ListSetting {...props} />
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ const ListValue = ({ current, t, config, changed }) =>
|
||||||
? t(`core-settings:${config.valueTitles[current]}`)
|
? t(`core-settings:${config.valueTitles[current]}`)
|
||||||
: t(`core-settings:${config.valueTitles[config.dflt]}`)
|
: t(`core-settings:${config.valueTitles[config.dflt]}`)
|
||||||
|
|
||||||
export const RendererSettingValue = ListValue
|
|
||||||
export const LocaleSettingValue = ListValue
|
export const LocaleSettingValue = ListValue
|
||||||
export const CompleteSettingValue = ListValue
|
export const CompleteSettingValue = ListValue
|
||||||
export const PaperlessSettingValue = ListValue
|
export const PaperlessSettingValue = ListValue
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
export const loadSettingsConfig = () => ({
|
||||||
|
control: {
|
||||||
|
control: 1, // Show when control > 0
|
||||||
|
list: ['1', '2', '3', '4', '5'],
|
||||||
|
choiceTitles: {
|
||||||
|
1: 'renderWithReact',
|
||||||
|
2: 'renderWithCore',
|
||||||
|
3: 'renderWithCore',
|
||||||
|
4: 'renderWithCore',
|
||||||
|
5: 'renderWithCore',
|
||||||
|
},
|
||||||
|
valueTitles: {
|
||||||
|
1: 'renderWithReact',
|
||||||
|
2: 'renderWithCore',
|
||||||
|
3: 'renderWithCore',
|
||||||
|
4: 'renderWithCore',
|
||||||
|
5: 'renderWithCore',
|
||||||
|
},
|
||||||
|
dflt: '2',
|
||||||
|
emoji: '🖥️',
|
||||||
|
},
|
||||||
|
renderer: {
|
||||||
|
control: 4, // Show when control > 3
|
||||||
|
list: ['react', 'svg'],
|
||||||
|
choiceTitles: {
|
||||||
|
react: 'renderWithReact',
|
||||||
|
svg: 'renderWithCore',
|
||||||
|
},
|
||||||
|
valueTitles: {
|
||||||
|
react: 'React',
|
||||||
|
svg: 'SVG',
|
||||||
|
},
|
||||||
|
dflt: 'react',
|
||||||
|
emoji: '🚀',
|
||||||
|
},
|
||||||
|
})
|
210
sites/shared/components/workbench/menus/ui-settings/index.mjs
Normal file
210
sites/shared/components/workbench/menus/ui-settings/index.mjs
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
import { XrayIcon } from 'shared/components/icons.mjs'
|
||||||
|
//import { ConsoleLog } from './log.mjs'
|
||||||
|
//import { XrayReset } from './reset.mjs'
|
||||||
|
//import { XrayList } from './list.mjs'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
import { Popout } from 'shared/components/popout.mjs'
|
||||||
|
//Dependencies
|
||||||
|
import { loadSettingsConfig } from './config.mjs'
|
||||||
|
// Components
|
||||||
|
import { Collapse } from 'shared/components/collapse.mjs'
|
||||||
|
import { HelpIcon } from 'shared/components/icons.mjs'
|
||||||
|
import { ControlSettingInput, RendererSettingInput, XRaySettingInput } from './inputs.mjs'
|
||||||
|
import { ControlSettingValue, RendererSettingValue, XRaySettingValue } from './values.mjs'
|
||||||
|
|
||||||
|
export const ns = ['ui-settings']
|
||||||
|
|
||||||
|
// Facilitate lookup of the value component
|
||||||
|
const values = {
|
||||||
|
control: ControlSettingValue,
|
||||||
|
renderer: RendererSettingValue,
|
||||||
|
xray: XRaySettingValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Facilitate lookup of the input component
|
||||||
|
const inputs = {
|
||||||
|
control: ControlSettingInput,
|
||||||
|
renderer: RendererSettingInput,
|
||||||
|
xray: XRaySettingInput,
|
||||||
|
}
|
||||||
|
|
||||||
|
const wasChanged = (current, name, settingsConfig) => {
|
||||||
|
if (typeof current === 'undefined') return false
|
||||||
|
if (current === settingsConfig[name].dflt) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UiTitle = ({ name, t, changed, current = null, open = false, emoji = '' }) => (
|
||||||
|
<div className={`flex flex-row gap-1 items-center w-full ${open ? '' : 'justify-between'}`}>
|
||||||
|
<span className="font-medium">
|
||||||
|
<span role="img" className="pr-2">
|
||||||
|
{emoji}
|
||||||
|
</span>
|
||||||
|
{t(`ui-settings:${name}.t`)}
|
||||||
|
{open ? ':' : ''}
|
||||||
|
</span>
|
||||||
|
<span className="font-bold">{current}</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const Setting = ({
|
||||||
|
name,
|
||||||
|
config,
|
||||||
|
current,
|
||||||
|
update,
|
||||||
|
t,
|
||||||
|
settingsConfig,
|
||||||
|
changed,
|
||||||
|
loadDocs,
|
||||||
|
control,
|
||||||
|
ui,
|
||||||
|
}) => {
|
||||||
|
const drillProps = { name, config, current, update, t, changed, control }
|
||||||
|
|
||||||
|
// Don't bother with X-Ray in SVG mode
|
||||||
|
if (name === 'xray' && ui.renderer === 'svg') return null
|
||||||
|
|
||||||
|
const Input = inputs[name]
|
||||||
|
const Value = values[name]
|
||||||
|
|
||||||
|
const buttons = []
|
||||||
|
const openButtons = []
|
||||||
|
if (loadDocs)
|
||||||
|
openButtons.push(
|
||||||
|
<button
|
||||||
|
className="btn btn-xs btn-ghost px-0"
|
||||||
|
key="help"
|
||||||
|
onClick={(evt) => loadDocs(evt, name)}
|
||||||
|
>
|
||||||
|
<HelpIcon className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
if (changed) {
|
||||||
|
buttons.push(
|
||||||
|
<button
|
||||||
|
className="btn btn-accent"
|
||||||
|
key="clear"
|
||||||
|
onClick={(evt) => {
|
||||||
|
evt.stopPropagation()
|
||||||
|
update.settings([name], config.dflt)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ClearIcon />
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
openButtons.push(
|
||||||
|
<button
|
||||||
|
className="btn btn-ghost btn-xs px-0"
|
||||||
|
key="clear"
|
||||||
|
onClick={(evt) => {
|
||||||
|
evt.stopPropagation()
|
||||||
|
update.settings([name], config.dflt)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ClearIcon />
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const titleProps = { name, t, current: <Value {...drillProps} />, emoji: config.emoji }
|
||||||
|
|
||||||
|
const boolSettings = ['sabool', 'paperless', 'details']
|
||||||
|
|
||||||
|
if (control > 4) {
|
||||||
|
// Save gurus some clicks
|
||||||
|
if (name === 'renderer')
|
||||||
|
return (
|
||||||
|
<Collapse
|
||||||
|
color={changed ? 'accent' : 'primary'}
|
||||||
|
title={<UiTitle {...titleProps} />}
|
||||||
|
onClick={() => (current === 'svg' ? update.ui([name]) : update.ui([name], 'svg'))}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Collapse
|
||||||
|
color={changed ? 'accent' : 'primary'}
|
||||||
|
openTitle={<UiTitle open {...titleProps} />}
|
||||||
|
title={<UiTitle {...titleProps} />}
|
||||||
|
buttons={buttons}
|
||||||
|
openButtons={openButtons}
|
||||||
|
>
|
||||||
|
<Input {...drillProps} />
|
||||||
|
</Collapse>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UiSettings = ({
|
||||||
|
design,
|
||||||
|
update,
|
||||||
|
settings,
|
||||||
|
ui,
|
||||||
|
account,
|
||||||
|
control,
|
||||||
|
language,
|
||||||
|
DynamicDocs,
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation(ns)
|
||||||
|
|
||||||
|
const settingsConfig = loadSettingsConfig()
|
||||||
|
|
||||||
|
const loadDocs = DynamicDocs
|
||||||
|
? (evt, setting = false) => {
|
||||||
|
evt.stopPropagation()
|
||||||
|
let path = `site/draft/ui-settings`
|
||||||
|
if (setting) path += `/${setting}`
|
||||||
|
setModal(
|
||||||
|
<ModalWrapper>
|
||||||
|
<div className="max-w-prose">
|
||||||
|
<DynamicDocs path={path} language={language} />
|
||||||
|
</div>
|
||||||
|
</ModalWrapper>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
: false
|
||||||
|
|
||||||
|
const openButtons = []
|
||||||
|
if (loadDocs)
|
||||||
|
openButtons.push(
|
||||||
|
<button
|
||||||
|
className="btn btn-xs btn-ghost px-0 z-10"
|
||||||
|
key="help"
|
||||||
|
onClick={(evt) => loadDocs(evt)}
|
||||||
|
>
|
||||||
|
<HelpIcon className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
const toggleXray = () => update.ui(['xray', 'enabled'], ui?.xray?.enabled ? false : true)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="px-2 mt-8">
|
||||||
|
{control > 4 ? (
|
||||||
|
<div className="border-t border-solid border-base-300 pb-2 mx-36"></div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<h5 className="flex flex-row gap-2 items-center">
|
||||||
|
<XrayIcon />
|
||||||
|
<span>{t('ui-settings:uiSettings')}</span>
|
||||||
|
</h5>
|
||||||
|
<p>{t('ui-settings:uiSettings.d')}</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{Object.keys(settingsConfig)
|
||||||
|
.filter((name) => settingsConfig[name].control <= control)
|
||||||
|
.map((name) => (
|
||||||
|
<Setting
|
||||||
|
key={name}
|
||||||
|
{...{ name, design, update, t, loadDocs, control }}
|
||||||
|
config={settingsConfig[name]}
|
||||||
|
current={ui[name]}
|
||||||
|
changed={wasChanged(settings[name], name, settingsConfig)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { ChoiceButton } from 'shared/components/choice-button.mjs'
|
||||||
|
import { ControlSettings } from 'shared/components/account/control.mjs'
|
||||||
|
|
||||||
|
// Shared input for list inputs
|
||||||
|
export const ListSetting = ({ name, list, config, current, update, t }) => {
|
||||||
|
if (typeof current === 'undefined') current = config.dflt
|
||||||
|
|
||||||
|
const [value, setValue] = useState(current)
|
||||||
|
|
||||||
|
const handleChange = (newCurrent) => {
|
||||||
|
if (newCurrent === config.dflt) reset()
|
||||||
|
else {
|
||||||
|
update.ui([name], newCurrent)
|
||||||
|
setValue(newCurrent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const reset = () => {
|
||||||
|
update.ui([name])
|
||||||
|
setValue(config.dflt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>{t(`ui-settings:${name}.d`)}</p>
|
||||||
|
{config.list.map((entry) => (
|
||||||
|
<ChoiceButton
|
||||||
|
key={entry}
|
||||||
|
title={t(`ui-settings:${config.choiceTitles[entry]}.t`)}
|
||||||
|
color={entry === config.dflt ? 'primary' : 'accent'}
|
||||||
|
active={current === entry}
|
||||||
|
onClick={() => handleChange(entry)}
|
||||||
|
>
|
||||||
|
{t(`ui-settings:${config.choiceTitles[entry]}.d`)}
|
||||||
|
</ChoiceButton>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ControlSettingInput = ({ t, name }) => (
|
||||||
|
<>
|
||||||
|
<p>{t(`ui-settings:${name}.d`)}</p>
|
||||||
|
<ControlSettings noBack />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const RendererSettingInput = ({ name, config, current, update, t }) => (
|
||||||
|
<ListSetting
|
||||||
|
{...{ name, config, current, update, t }}
|
||||||
|
list={config.list.map((key) => ({
|
||||||
|
key,
|
||||||
|
title: key,
|
||||||
|
}))}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const XRaySettingInput = (props) => <ListSetting {...props} />
|
|
@ -0,0 +1,11 @@
|
||||||
|
uiSettings.t: UI Preferences
|
||||||
|
uiSettings.d: These preferences control the UI (User Interface) aspects of our online pattern drafting environment.
|
||||||
|
renderer.t: Render Engine
|
||||||
|
renderer.d: Controls how the pattern is rendered (drawn) on the screen
|
||||||
|
renderWithReact.t: Render with FreeSewing's React components
|
||||||
|
renderWithReact.d: Render as SVG through our React components. Allows interactivity and is optimized for screen. Use this if you are not sure what to pick.
|
||||||
|
renderWithCore.t: Render with Freesewing's Core library
|
||||||
|
renderWithCore.d: Render directly to SVG from Core. Allows no interactivity and is optimized for print. Use this if you want to know what it will look like when exported.
|
||||||
|
control.t: User Experience
|
||||||
|
control.d: Which user experience do you prefer? Please note that this is an account setting, so it will impact the entire website.
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Difficulty } from 'shared/components/designs/difficulty.mjs'
|
||||||
|
|
||||||
|
const ListValue = ({ current, t, config, changed }) =>
|
||||||
|
changed
|
||||||
|
? t(`ui-settings:${config.valueTitles[current]}`)
|
||||||
|
: t(`ui-settings:${config.valueTitles[config.dflt]}`)
|
||||||
|
|
||||||
|
export const RendererSettingValue = ListValue
|
||||||
|
export const XRaysValue = ListValue
|
||||||
|
export const ControlSettingValue = ({ control }) => <Difficulty score={control} />
|
|
@ -1,35 +0,0 @@
|
||||||
import { XrayIcon } from 'shared/components/icons.mjs'
|
|
||||||
//import { ConsoleLog } from './log.mjs'
|
|
||||||
//import { XrayReset } from './reset.mjs'
|
|
||||||
//import { XrayList } from './list.mjs'
|
|
||||||
import { useTranslation } from 'next-i18next'
|
|
||||||
import { Popout } from 'shared/components/popout.mjs'
|
|
||||||
|
|
||||||
export const ns = ['xray']
|
|
||||||
|
|
||||||
export const XrayMenu = ({ design, update, settings, ui, account, control }) => {
|
|
||||||
const { t } = useTranslation(ns)
|
|
||||||
|
|
||||||
if (ui.renderer !== 'react' || control < 4) return null
|
|
||||||
|
|
||||||
const toggleXray = () => update.ui(['xray', 'enabled'], ui?.xray?.enabled ? false : true)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="px-2 mt-8">
|
|
||||||
{control > 4 ? (
|
|
||||||
<div className="border-t border-solid border-base-300 pb-2 mx-36"></div>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<h5 className="flex flex-row gap-2 items-center">
|
|
||||||
<XrayIcon />
|
|
||||||
<span>{t('xray:xrayPattern')}</span>
|
|
||||||
</h5>
|
|
||||||
<p>{t('core-settings:coreSettings.d')}</p>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<Popout fixme>Implement X-Ray</Popout>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ export const Pattern = ({ pattern, setView, settings, ui, update }) => {
|
||||||
|
|
||||||
// Render as SVG
|
// Render as SVG
|
||||||
return ui.renderer === 'svg' ? (
|
return ui.renderer === 'svg' ? (
|
||||||
<div dangerouslySetInnerHTML={{ __html: patern.render() }} />
|
<div dangerouslySetInnerHTML={{ __html: pattern.render() }} />
|
||||||
) : (
|
) : (
|
||||||
<SvgWrapper renderProps={pattern.getRenderProps()} {...{ update, settings, ui }} />
|
<SvgWrapper renderProps={pattern.getRenderProps()} {...{ update, settings, ui }} />
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,9 +6,9 @@ import {
|
||||||
CoreSettings,
|
CoreSettings,
|
||||||
ns as coreMenuNs,
|
ns as coreMenuNs,
|
||||||
} from 'shared/components/workbench/menus/core-settings/index.mjs'
|
} from 'shared/components/workbench/menus/core-settings/index.mjs'
|
||||||
import { XrayMenu, ns as xrayNs } from 'shared/components/workbench/menus/xray/index.mjs'
|
import { UiSettings, ns as uiNs } from 'shared/components/workbench/menus/ui-settings/index.mjs'
|
||||||
|
|
||||||
export const ns = [...coreMenuNs, ...designMenuNs, ...xrayNs]
|
export const ns = [...coreMenuNs, ...designMenuNs, ...uiNs]
|
||||||
|
|
||||||
export const DraftMenu = ({
|
export const DraftMenu = ({
|
||||||
design,
|
design,
|
||||||
|
@ -38,7 +38,7 @@ export const DraftMenu = ({
|
||||||
<nav className="grow mb-12">
|
<nav className="grow mb-12">
|
||||||
<DesignOptions {...menuProps} />
|
<DesignOptions {...menuProps} />
|
||||||
<CoreSettings {...menuProps} />
|
<CoreSettings {...menuProps} />
|
||||||
<XrayMenu {...menuProps} ui={ui} />
|
<UiSettings {...menuProps} ui={ui} />
|
||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ cutLayout: Cut Layout
|
||||||
save: Save
|
save: Save
|
||||||
export: Export
|
export: Export
|
||||||
edit: Edit
|
edit: Edit
|
||||||
clear: Clear
|
reset: Reset
|
||||||
help: Help
|
help: Help
|
||||||
name: Name
|
name: Name
|
||||||
width: Width
|
width: Width
|
||||||
|
@ -20,4 +20,3 @@ showOnlyThisPart: Show only this pattern part
|
||||||
partInfo: Pattern part info
|
partInfo: Pattern part info
|
||||||
pathInfo: Path info
|
pathInfo: Path info
|
||||||
part: Pattern part
|
part: Pattern part
|
||||||
control: Experience
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue