wip: Work on menus
This commit is contained in:
parent
07ba6df1c4
commit
b306d6374d
19 changed files with 249 additions and 210 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -129,3 +129,6 @@ scripts/verdaccio.sh
|
|||
|
||||
# e2e test results
|
||||
sites/*/playwright-report
|
||||
|
||||
# Local Netlify folder
|
||||
.netlify
|
||||
|
|
2
package-lock.json
generated
2
package-lock.json
generated
|
@ -62216,7 +62216,7 @@
|
|||
"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",
|
||||
|
|
|
@ -20,7 +20,7 @@ export const PatternLayout = (props) => {
|
|||
<div className="tw-flex tw-flex-col tw-h-full">
|
||||
<HeaderMenu state={props.state} {...{ update, Design, pattern, config }} />
|
||||
<div className="tw-flex lg:tw-flex-row tw-grow lg:tw-max-h-[90vh] tw-max-h-[calc(100vh-3rem)] tw-h-full tw-py-4 lg:tw-mt-6">
|
||||
<div className="lg:tw-w-2/3 tw-flex tw-flex-col tw-h-full tw-grow px-4">
|
||||
<div className="lg:tw-w-2/3 tw-flex tw-flex-col tw-h-full tw-grow tw-p-2 tw-shadow tw-mx-2">
|
||||
{props.output}
|
||||
</div>
|
||||
{menu ? (
|
||||
|
|
|
@ -5,7 +5,13 @@ import { designOptionType } from '@freesewing/utils'
|
|||
import React, { useState, useMemo } from 'react'
|
||||
// Components
|
||||
import { SubAccordion } from '../Accordion.mjs'
|
||||
import { EditIcon, GroupIcon, OptionsIcon, ResetIcon } from '@freesewing/react/components/Icon'
|
||||
import {
|
||||
EditIcon,
|
||||
GroupIcon,
|
||||
OptionsIcon,
|
||||
ResetIcon,
|
||||
TipIcon,
|
||||
} from '@freesewing/react/components/Icon'
|
||||
import { CoreSettingsMenu } from './CoreSettingsMenu.mjs'
|
||||
import { FormControl } from '@freesewing/react/components/Input'
|
||||
|
||||
|
@ -103,12 +109,14 @@ export const MenuItem = ({
|
|||
buttons.push(<ResetButton open disabled={!changed} key="clear" />)
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormControl
|
||||
label={
|
||||
FIXME_REMOVED_label={
|
||||
<span className="tw-text-base tw-font-normal">
|
||||
{config.choiceTitles ? config.choiceTitles[current] : i18n.en.o[name].d}
|
||||
</span>
|
||||
}
|
||||
label={false}
|
||||
id={config.name}
|
||||
labelBR={<div className="tw-flex tw-flex-row tw-items-center tw-gap-2">{buttons}</div>}
|
||||
labelBL={
|
||||
|
@ -121,6 +129,17 @@ export const MenuItem = ({
|
|||
>
|
||||
<Input {...drillProps} />
|
||||
</FormControl>
|
||||
{config.about ? (
|
||||
<div className="tw-flex tw-flex-row tw-border tw-border-success tw-rounded">
|
||||
<div className="tw-bg-success tw-text-success-content tw-p-1 tw-rounded-l tw-flex tw-flex-row tw-items-center">
|
||||
<TipIcon className="tw-w-6 tw-h-6 tw-text-success-content" />
|
||||
</div>
|
||||
<div className="tw-p-1 tw-text-sm tw-font-medium tw-bg-success/10 tw-grow tw-rounded-r">
|
||||
{config.about}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -206,7 +225,9 @@ export const MenuItemGroup = ({
|
|||
<div className="tw-flex tw-flex-row tw-items-center tw-justify-between tw-w-full" key="a">
|
||||
<div className="tw-flex tw-flex-row tw-items-center tw-gap-4 tw-w-full">
|
||||
<ItemIcon />
|
||||
<span className="tw-font-medium tw-capitalize">{getItemLabel(i18n, itemName)}</span>
|
||||
<span className="tw-font-medium tw-capitalize">
|
||||
{item.title ? item.title : getItemLabel(i18n, itemName)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="tw-font-bold">
|
||||
<Value
|
||||
|
|
|
@ -58,16 +58,17 @@ const getTitleAndDesc = (config = {}, i18n = {}, isDesignOption = false) => {
|
|||
}
|
||||
}
|
||||
|
||||
console.log(config)
|
||||
let titleKey = config.choiceTitles
|
||||
? config.choiceTitles[entry]
|
||||
? 'fixme' //config.choiceTitles[entry]
|
||||
: isDesignOption
|
||||
? i18n.en.o[name]
|
||||
: `${name}.o.${entry}`
|
||||
if (!config.choiceTitles && i18n && i18n.en.o[`${name}.${entry}`])
|
||||
titleKey = i18n.en.o[`${name}.${entry}`]
|
||||
console.log({ titleKey, titles: config.choiceTitles, isDesignOption })
|
||||
const title = config.titleMethod
|
||||
const title = config.title
|
||||
? config.title
|
||||
: config.titleMethod
|
||||
? config.titleMethod(entry)
|
||||
: typeof titleKey === 'string'
|
||||
? i18n.en.o[titleKey]?.t
|
||||
|
@ -115,8 +116,9 @@ export const MenuListInput = ({
|
|||
})
|
||||
|
||||
return config.list.map((entry) => {
|
||||
const { title, desc } = getTitleAndDesc(config, i18n, isDesignOption)
|
||||
const sideBySide = config.sideBySide || desc.length + title.length < 42
|
||||
const { title = false, about = false } = config //getTitleAndDesc(config, i18n, isDesignOption)
|
||||
if (!title || !about) console.log('No title or about in', { name, config, design })
|
||||
const sideBySide = config.sideBySide || about.length + title.length < 42
|
||||
|
||||
return (
|
||||
<ButtonFrame
|
||||
|
@ -136,8 +138,10 @@ export const MenuListInput = ({
|
|||
sideBySide ? 'tw-flex-row tw-justify-between tw-gap-2' : 'tw-flex-col'
|
||||
}`}
|
||||
>
|
||||
<div className="tw-font-bold tw-text-lg tw-shrink-0">{title}</div>
|
||||
{compact ? null : <div className="tw-text-base tw-font-normal">{desc}</div>}
|
||||
<div className="tw-font-semibold tw-shrink-0">{config.choiceTitles[entry]}</div>
|
||||
{compact || !config.choiceDescriptions ? null : (
|
||||
<div className="tw-text-base tw-font-normal">{config.choiceDescriptions[entry]}</div>
|
||||
)}
|
||||
</div>
|
||||
</ButtonFrame>
|
||||
)
|
||||
|
@ -199,74 +203,6 @@ export const MenuMmInput = (props) => {
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A number input that accepts comma or period decimal separators.
|
||||
* Because our use case is almost never going to include thousands, we're using a very simple way of accepting commas:
|
||||
* The validator checks for the presence of a single comma or period followed by numbers
|
||||
* The parser replaces a single comma with a period
|
||||
*
|
||||
* optionally accepts fractions
|
||||
* @param {Number} options.val the value of the input
|
||||
* @param {Function} options.onUpdate a function to handle when the value is updated to a valid value
|
||||
* @param {Boolean} options.fractions should the input allow fractional input
|
||||
*/
|
||||
//export const MenuNumberInput = ({
|
||||
// value,
|
||||
// onUpdate,
|
||||
// onMount,
|
||||
// className,
|
||||
// fractions = true,
|
||||
// min = -Infinity,
|
||||
// max = Infinity,
|
||||
// swizzled,
|
||||
//}) => {
|
||||
// const valid = useRef(validateVal(value, fractions, min, max))
|
||||
//
|
||||
// const handleChange = useCallback(
|
||||
// (newVal) => {
|
||||
// // only actually update if the value is valid
|
||||
// if (typeof onUpdate === 'function') {
|
||||
// onUpdate(valid.current, newVal)
|
||||
// }
|
||||
// },
|
||||
// [onUpdate, valid]
|
||||
// )
|
||||
//
|
||||
// // onChange
|
||||
// const onChange = useCallback(
|
||||
// (evt) => {
|
||||
// const newVal = evt.target.value
|
||||
// // set validity so it will display
|
||||
// valid.current = validateVal(newVal, fractions, min, max)
|
||||
//
|
||||
// // handle the change
|
||||
// handleChange(newVal)
|
||||
// },
|
||||
// [fractions, min, max, valid]
|
||||
// )
|
||||
//
|
||||
// const val = typeof value === 'undefined' ? config.dflt : value
|
||||
//
|
||||
// useEffect(() => {
|
||||
// if (typeof onMount === 'function') {
|
||||
// onMount(valid.current)
|
||||
// }
|
||||
// }, [onMount, valid])
|
||||
//
|
||||
// return (
|
||||
// <input
|
||||
// type="text"
|
||||
// inputMode="number"
|
||||
// className={`input input-secondary ${className || 'input-sm grow text-base-content'}
|
||||
// ${valid.current === false && 'input-error'}
|
||||
// ${valid.current && 'input-success'}
|
||||
// `}
|
||||
// value={val}
|
||||
// onChange={onChange}
|
||||
// />
|
||||
// )
|
||||
//}
|
||||
|
||||
/** A {@see SliderInput} to handle percentage values */
|
||||
export const MenuPctInput = ({ current, changed, updateHandler, config, ...rest }) => {
|
||||
const factor = 100
|
||||
|
|
|
@ -13,15 +13,15 @@ export const UiPreferencesMenu = ({ update, state, Design }) => {
|
|||
const drillProps = { Design, state, update }
|
||||
const inputs = {
|
||||
ux: (props) => <MenuUxSettingInput {...drillProps} {...props} />,
|
||||
aside: (props) => <MenuListInput {...drillProps} {...props} />,
|
||||
kiosk: (props) => <MenuListInput {...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,
|
||||
ux: (props) => <span>{state.ui.ux}/5</span>,
|
||||
//aside: MenuListValue,
|
||||
//kiosk: MenuListValue,
|
||||
rotate: MenuListValue,
|
||||
renderer: MenuListValue,
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ export const UiPreferencesMenu = ({ update, state, Design }) => {
|
|||
<UiPreference updateHandler={update} {...{ inputs, values, Design }} {...props} />
|
||||
),
|
||||
isFirst: true,
|
||||
name: 'pe:uiPreferences',
|
||||
name: 'UI Preferences',
|
||||
language: state.locale,
|
||||
passProps: {
|
||||
ux: state.ui?.ux,
|
||||
|
|
|
@ -64,9 +64,9 @@ export const DraftView = ({ Design, state, update, config }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<PatternLayout
|
||||
{...{ update, Design, output, state, pattern, config }}
|
||||
menu={state.ui?.aside ? <DraftMenu {...{ Design, pattern, update, state }} /> : null}
|
||||
/>
|
||||
<>
|
||||
<PatternLayout {...{ update, Design, output, state, pattern, config }} />
|
||||
<p className="tw-clear-both">where does this go?</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import React from 'react'
|
||||
// Dependencies
|
||||
import { defaultConfig as config } from '../config/index.mjs'
|
||||
import { measurementAsMm } from '@freesewing/utils'
|
||||
import { linkClasses } from '@freesewing/utils'
|
||||
/*
|
||||
* Components
|
||||
* Note that these are only used as returns values
|
||||
|
@ -58,19 +60,30 @@ export function menuCoreSettingsSammHandler({ updateHandler, config }) {
|
|||
export function menuCoreSettingsSaboolHandler({ toggleSa }) {
|
||||
return toggleSa
|
||||
}
|
||||
|
||||
const CoreDocsLink = ({ item }) => (
|
||||
<a href={`/docs/about/site/draft/#${item.toLowerCase()}`} className={`${linkClasses} tw-px-2`}>
|
||||
Learn more
|
||||
</a>
|
||||
)
|
||||
|
||||
export function menuCoreSettingsStructure({ units = 'metric', sabool = false, parts = [] }) {
|
||||
return {
|
||||
sabool: {
|
||||
dense: true,
|
||||
title: 'Include seam allowance',
|
||||
about: (
|
||||
<>
|
||||
Controls whether or not you want to include seam allowance on your pattern.
|
||||
<CoreDocsLink item="sabool" />
|
||||
</>
|
||||
),
|
||||
ux: config.uxLevels.core.sa,
|
||||
list: [0, 1],
|
||||
choiceTitles: {
|
||||
0: 'Do not include seam allowance',
|
||||
1: 'Include seam allowance',
|
||||
},
|
||||
choiceDescriptions: {
|
||||
0: 'This generates a pattern which does not include any seam allowance. The size of the seam allowance does not matter as no seam allowance will be included',
|
||||
1: 'This generates a pattern that will include seam allowance. The size of the seam allowance is set individually',
|
||||
},
|
||||
valueTitles: {
|
||||
0: 'No',
|
||||
1: 'Yes',
|
||||
|
@ -80,6 +93,13 @@ export function menuCoreSettingsStructure({ units = 'metric', sabool = false, pa
|
|||
},
|
||||
samm: sabool
|
||||
? {
|
||||
title: 'Seam Allowance Size',
|
||||
about: (
|
||||
<>
|
||||
Controls the size of the pattern's seam allowance.
|
||||
<CoreDocsLink item="sa" />
|
||||
</>
|
||||
),
|
||||
ux: config.uxLevels.core.sa,
|
||||
min: 0,
|
||||
max: units === 'imperial' ? 2 : 2.5,
|
||||
|
@ -87,17 +107,44 @@ export function menuCoreSettingsStructure({ units = 'metric', sabool = false, pa
|
|||
icon: SaIcon,
|
||||
}
|
||||
: false,
|
||||
units: {
|
||||
dense: true,
|
||||
title: 'Pattern units',
|
||||
about: (
|
||||
<>
|
||||
Allows you to switch between metric and imperial units on the pattern.
|
||||
<CoreDocsLink item="units" />
|
||||
</>
|
||||
),
|
||||
ux: config.uxLevels.core.units,
|
||||
list: ['metric', 'imperial'],
|
||||
dflt: 'metric',
|
||||
choiceTitles: {
|
||||
metric: 'Metric',
|
||||
imperial: 'Imperial',
|
||||
},
|
||||
valueTitles: {
|
||||
metric: 'Metric',
|
||||
imperial: 'Imperial',
|
||||
},
|
||||
icon: UnitsIcon,
|
||||
},
|
||||
paperless: {
|
||||
dense: true,
|
||||
title: 'Paperless pattern',
|
||||
about: (
|
||||
<>
|
||||
Trees are awesome, and taping together sewing patterns is not much fun. Try our paperless
|
||||
mode to avoid the need to print out your pattern altogether.
|
||||
<CoreDocsLink item="paperless" />
|
||||
</>
|
||||
),
|
||||
ux: config.uxLevels.core.paperless,
|
||||
list: [0, 1],
|
||||
choiceTitles: {
|
||||
0: 'Generate a regular pattern',
|
||||
1: 'Generate a paperless pattern',
|
||||
},
|
||||
choiceDescriptions: {
|
||||
0: 'This will generate a regular pattern, which you can them print out.',
|
||||
1: 'This will generate a pattern with dimensions and a grid, which allows you to transfer it on fabric or another medium without the need to print the pattern.',
|
||||
},
|
||||
valueTitles: {
|
||||
0: 'No',
|
||||
1: 'Yes',
|
||||
|
@ -105,35 +152,22 @@ export function menuCoreSettingsStructure({ units = 'metric', sabool = false, pa
|
|||
dflt: 0,
|
||||
icon: PaperlessIcon,
|
||||
},
|
||||
units: {
|
||||
ux: config.uxLevels.core.units,
|
||||
list: ['metric', 'imperial'],
|
||||
dflt: 'metric',
|
||||
choiceTitles: {
|
||||
metric: 'Metric',
|
||||
imperial: 'Imperial',
|
||||
},
|
||||
choiceDescriptions: {
|
||||
0: 'Use this if you use the metric system, and centimeters are something you are familiar with. This is the best choice for most people around the world.',
|
||||
1: 'Use this if inches are more familiar to you. This is often the preferred choice for people based in the UK & US.',
|
||||
},
|
||||
valueTitles: {
|
||||
metric: 'Metric',
|
||||
imperial: 'Imperial',
|
||||
},
|
||||
icon: UnitsIcon,
|
||||
},
|
||||
complete: {
|
||||
dense: true,
|
||||
title: 'Generate a detailed pattern',
|
||||
about: (
|
||||
<>
|
||||
Controls how detailed the pattern is; Either a complete pattern with all details, or a
|
||||
basic outline of the pattern parts.
|
||||
<CoreDocsLink item="complete" />
|
||||
</>
|
||||
),
|
||||
ux: config.uxLevels.core.complete,
|
||||
list: [1, 0],
|
||||
dflt: 1,
|
||||
choiceTitles: {
|
||||
0: 'Generate a pattern outline',
|
||||
1: 'Generate a complete pattern',
|
||||
},
|
||||
choiceDescriptions: {
|
||||
0: 'Only generate the outline of the pattern parts. Use this if you are looking to use a laser cutter or have other specific needs.',
|
||||
1: 'This will generate a complete pattern with all annotations, markings and lines. Use this if you are not certain what to choose.',
|
||||
1: 'Generate a detailed pattern',
|
||||
},
|
||||
valueTitles: {
|
||||
0: 'No',
|
||||
|
@ -142,6 +176,15 @@ export function menuCoreSettingsStructure({ units = 'metric', sabool = false, pa
|
|||
icon: DetailIcon,
|
||||
},
|
||||
expand: {
|
||||
dense: true,
|
||||
title: 'Expand pattern parts',
|
||||
about: (
|
||||
<>
|
||||
Controls efforts to save paper. Disable this to expand all pattern parts at the cost of
|
||||
using more space & paper.
|
||||
<CoreDocsLink item="expand" />
|
||||
</>
|
||||
),
|
||||
ux: config.uxLevels.core.expand,
|
||||
list: [1, 0],
|
||||
dflt: 1,
|
||||
|
@ -149,10 +192,6 @@ export function menuCoreSettingsStructure({ units = 'metric', sabool = false, pa
|
|||
0: 'Keep pattern parts compact where possible',
|
||||
1: 'Expand all pattern parts',
|
||||
},
|
||||
choiceDescriptions: {
|
||||
0: 'This will generate a more dense representation of the pattern which includes all info without using up too much space.',
|
||||
1: 'This will generate a pattern where all parts are drown to their full size, even if they are simple rectangles.',
|
||||
},
|
||||
valueTitles: {
|
||||
0: 'No',
|
||||
1: 'Yes',
|
||||
|
@ -160,6 +199,7 @@ export function menuCoreSettingsStructure({ units = 'metric', sabool = false, pa
|
|||
icon: ExpandIcon,
|
||||
},
|
||||
only: {
|
||||
title: 'Only included selected pattern parts',
|
||||
ux: config.uxLevels.core.only,
|
||||
dflt: false,
|
||||
list: parts,
|
||||
|
@ -167,6 +207,7 @@ export function menuCoreSettingsStructure({ units = 'metric', sabool = false, pa
|
|||
icon: IncludeIcon,
|
||||
},
|
||||
scale: {
|
||||
title: 'Pattern annotations scale',
|
||||
ux: config.uxLevels.core.scale,
|
||||
min: 0.1,
|
||||
max: 5,
|
||||
|
@ -175,6 +216,7 @@ export function menuCoreSettingsStructure({ units = 'metric', sabool = false, pa
|
|||
icon: ScaleIcon,
|
||||
},
|
||||
margin: {
|
||||
title: 'Pattern parts margin',
|
||||
ux: config.uxLevels.core.margin,
|
||||
min: 0,
|
||||
max: 2.5,
|
||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react'
|
|||
import { defaultConfig } from '../config/index.mjs'
|
||||
import { round } from '@freesewing/utils'
|
||||
import { formatDesignOptionValue, menuCoreSettingsStructure } from './index.mjs'
|
||||
import { menuUiPreferencesStructure } from './ui-preferences.mjs'
|
||||
// Components
|
||||
import {
|
||||
ErrorIcon,
|
||||
|
@ -113,7 +114,6 @@ export function getCoreSettingUndoStepData({ step, state, Design }) {
|
|||
* Save us some typing
|
||||
*/
|
||||
const cord = settingsValueCustomOrDefault
|
||||
const formatMm = formatMm
|
||||
const Html = HtmlSpan
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import React from 'react'
|
||||
import { defaultConfig } from '../config/index.mjs'
|
||||
import {
|
||||
MenuIcon,
|
||||
|
@ -11,28 +12,49 @@ export function menuUiPreferencesStructure() {
|
|||
const uiUx = defaultConfig.uxLevels.ui
|
||||
const uiPreferences = {
|
||||
ux: {
|
||||
dense: true,
|
||||
title: 'User Experience',
|
||||
about: 'Controls the user experience, from keep it simple, to give me all the powers',
|
||||
ux: uiUx.ux,
|
||||
emoji: '🖥️',
|
||||
list: [1, 2, 3, 4, 5],
|
||||
choiceTitles: {},
|
||||
choiceTitles: {
|
||||
1: 'Keep it as simple as possible',
|
||||
2: 'Keep it simple, but not too simple',
|
||||
3: 'Balance simplicity with power',
|
||||
4: 'Give me all powers, but keep me safe',
|
||||
5: 'Get out of my way',
|
||||
},
|
||||
_choiceDescriptions: {
|
||||
1: 'Hides all but the most crucial features.',
|
||||
2: 'Hides most of the advanced features.',
|
||||
3: 'Reveals the majority of advanced features, but not all of them.',
|
||||
4: 'Reveals all advanced features, keeps handrails and safety checks.',
|
||||
5: 'Reveals all advanced features, removes handrails and safety checks.',
|
||||
},
|
||||
icon: UxIcon,
|
||||
dflt: defaultConfig.defaultUx,
|
||||
},
|
||||
/*
|
||||
aside: {
|
||||
title: 'Aside Menu',
|
||||
about: 'Whether or not to display the aside menu',
|
||||
ux: uiUx.aside,
|
||||
list: [0, 1],
|
||||
choiceTitles: {
|
||||
0: 'pe:noAside',
|
||||
1: 'pe:withAside',
|
||||
0: 'Display the aside menu',
|
||||
1: 'Hide the aside menu',
|
||||
},
|
||||
choiceDescriptions: {
|
||||
0: 'pe:noAside',
|
||||
1: 'pe:withAside',
|
||||
0: 'Displays the Design Options, Core Settings, and UI Preferences menu on the side of the screen (not on mobile).',
|
||||
1: 'Uses the entire screen size for your pattern, providing access to the Design Options, Core Settings, and UI Preferences through the header navigation only.',
|
||||
},
|
||||
dflt: 1,
|
||||
icon: MenuIcon,
|
||||
},
|
||||
kiosk: {
|
||||
title: 'Kiosk View',
|
||||
about: 'Whether or not to hide the header and footer',
|
||||
ux: uiUx.kiosk,
|
||||
list: [0, 1],
|
||||
choiceTitles: {
|
||||
|
@ -46,26 +68,37 @@ export function menuUiPreferencesStructure() {
|
|||
dflt: 0,
|
||||
icon: KioskIcon,
|
||||
},
|
||||
*/
|
||||
rotate: {
|
||||
dense: true,
|
||||
title: 'Rotate Pattern',
|
||||
about: 'Allows you to rotate your pattern 90 degrees, handy for tall patterns',
|
||||
ux: uiUx.rotate,
|
||||
list: [0, 1],
|
||||
choiceTitles: {
|
||||
0: 'pe:rotateNo',
|
||||
1: 'pe:rotateYes',
|
||||
},
|
||||
choiceDescriptions: {
|
||||
0: 'pe:noAside',
|
||||
1: 'pe:withAside',
|
||||
0: 'Do not rotate the pattern',
|
||||
1: 'Rotate the pattern 90 degrees',
|
||||
},
|
||||
dflt: 0,
|
||||
icon: RotateIcon,
|
||||
},
|
||||
renderer: {
|
||||
dense: true,
|
||||
title: 'Pattern render engine',
|
||||
about: 'Change the way the pattern is rendered on screen',
|
||||
ux: uiUx.renderer,
|
||||
list: ['react', 'svg'],
|
||||
choiceTitles: {
|
||||
react: 'pe:renderWithReact',
|
||||
svg: 'pe:renderWithCore',
|
||||
react: (
|
||||
<span>
|
||||
Render using <em>@freesewing/react</em>
|
||||
</span>
|
||||
),
|
||||
svg: (
|
||||
<span>
|
||||
Render using <em>@freesewing/core</em>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
choiceDescriptions: {
|
||||
0: 'pe:noAside',
|
||||
|
@ -73,13 +106,12 @@ export function menuUiPreferencesStructure() {
|
|||
},
|
||||
valueTitles: {
|
||||
react: 'React',
|
||||
svg: 'SVG',
|
||||
svg: 'Core',
|
||||
},
|
||||
dflt: 'react',
|
||||
icon: RocketIcon,
|
||||
},
|
||||
}
|
||||
|
||||
uiPreferences.ux.list.forEach((i) => (uiPreferences.ux.choiceTitles[i] = 'pe:ux' + i))
|
||||
return uiPreferences
|
||||
}
|
||||
|
|
|
@ -89,6 +89,11 @@ export const ChatIcon = (props) => (
|
|||
export const CircleIcon = (props) => (
|
||||
<IconWrapper {...props}>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
{props.label ? (
|
||||
<text x="12" y="17.5" stroke="none" fill="currentColor" textAnchor="middle">
|
||||
{props.label}
|
||||
</text>
|
||||
) : null}
|
||||
</IconWrapper>
|
||||
)
|
||||
|
||||
|
|
|
@ -69,9 +69,9 @@ export const FormControl = ({
|
|||
<label className="tw-daisy-label tw-pb-0" htmlFor={forId}>
|
||||
{topLabelChildren}
|
||||
</label>
|
||||
) : (
|
||||
) : label ? (
|
||||
<div className="tw-daisy-label tw-pb-0">{topLabelChildren}</div>
|
||||
)}
|
||||
) : null}
|
||||
{children}
|
||||
{labelBL || labelBR ? (
|
||||
forId ? (
|
||||
|
@ -99,7 +99,7 @@ export const ButtonFrame = ({
|
|||
<button
|
||||
className={`
|
||||
tw-daisy-btn tw-daisy-btn-ghost tw-daisy-btn-secondary
|
||||
tw-w-full ${dense ? 'tw-mt-1 tw-py-0 tw-daisy-btn-sm' : 'tw-mt-2 tw-py-4 tw-h-auto tw-content-start'}
|
||||
tw-w-full ${dense ? 'tw-mt-1 tw-daisy-btn-sm tw-font-light' : 'tw-mt-2 tw-py-4 tw-h-auto tw-content-start'}
|
||||
tw-border-2 tw-border-secondary tw-text-left tw-bg-opacity-20
|
||||
${accordion ? 'hover:tw-bg-transparent' : 'hover:tw-bg-secondary hover:tw-bg-opacity-10'}
|
||||
hover:tw-border-secondary hover:tw-border-solid hover:tw-border-2
|
||||
|
|
|
@ -13,3 +13,9 @@ export const Ux = ({ ux = 0 }) => (
|
|||
))}
|
||||
</div>
|
||||
)
|
||||
|
||||
export const UxMini = ({ ux = 0 }) => (
|
||||
<div className="flex flex-row">
|
||||
<CircleIcon className={`tw-w-6 tw-h-6 tw-stroke-secondary tw-fill-secondary/20`} label={ux} />
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -83,4 +83,4 @@ submit an issue.
|
|||
We'd love to hear your feedback. We're **@freesewing_org** on
|
||||
[Twitter](https://twitter.com/freesewing_org) and
|
||||
[Instagram](https://instagram.com/freesewing_org), use the **#freesewing**
|
||||
hashtag, or [check our share page](/share).
|
||||
hashtag, or [check our share page](#fixme).
|
||||
|
|
|
@ -153,4 +153,4 @@ And if you happen to like what we do here, perhaps now is a good time to tell
|
|||
your friends about FreeSewing. After all, they can now check it out without
|
||||
needing to sign up.
|
||||
|
||||
PS: We have [a handy share page](/share/) you can use for this.
|
||||
PS: We have [a handy share page](#fixme) you can use for this.
|
||||
|
|
|
@ -17,9 +17,15 @@
|
|||
--neutral-50: #fafafa;
|
||||
--neutral-100: #f5f5f5;
|
||||
--neutral-200: #e5e5e5;
|
||||
--neutral-400: #a3a3a3;
|
||||
--neutral-500: #737373;
|
||||
--neutral-600: #525252;
|
||||
--neutral-900: #0a0a0a;
|
||||
--amber-600: #d97706;
|
||||
--red-500: #ef4444;
|
||||
--blue-500: #3b82f6;
|
||||
--pink-500: #ec4899;
|
||||
--violet-500: #8b5cf6;
|
||||
|
||||
/* Color Palette */
|
||||
--ifm-color-primary: var(--sky-500);
|
||||
|
@ -77,47 +83,17 @@
|
|||
--ifm-footer-link-color: var(--sky-600);
|
||||
|
||||
/*
|
||||
* These are variables to style FreeSewing SVG output (drafts, examples, and so on)
|
||||
* FreeSewing pattern vars
|
||||
*/
|
||||
--pattern-bg: #fafafa;
|
||||
--pattern-fabric: #404040;
|
||||
--pattern-lining: #10b981;
|
||||
--pattern-interfacing: #a3a3a3;
|
||||
--pattern-canvas: #d97706;
|
||||
--pattern-various: #ef4444;
|
||||
--pattern-mark: #3b82f6;
|
||||
--pattern-contrast: #ec4899;
|
||||
--pattern-note: #8b5cf6;
|
||||
--pattern-color-0: #ef4444;
|
||||
--pattern-color-1: #22c55e;
|
||||
--pattern-color-2: #3b82f6;
|
||||
--pattern-color-3: #eab308;
|
||||
--pattern-color-4: #ec4899;
|
||||
--pattern-color-5: #8b5cf6;
|
||||
--pattern-color-6: #14b8a6;
|
||||
--pattern-color-7: #f59e0b;
|
||||
--pattern-color-8: #d946ef;
|
||||
--pattern-color-9: #06b6d4;
|
||||
--pattern-text-xs: 0.2rem;
|
||||
--pattern-text-sm: 0.3rem;
|
||||
--pattern-text: 0.4rem;
|
||||
--pattern-text-lg: 0.6rem;
|
||||
--pattern-text-xl: 0.8rem;
|
||||
--pattern-text-2xl: 1.5rem;
|
||||
--pattern-text-3xl: 2rem;
|
||||
--pattern-text-4xl: 3rem;
|
||||
--pattern-scale: 1;
|
||||
--pattern-stroke-xs: 0.2px;
|
||||
--pattern-stroke-sm: 0.4px;
|
||||
--pattern-stroke: 0.7px;
|
||||
--pattern-stroke-lg: 1.3px;
|
||||
--pattern-stroke-xl: 2px;
|
||||
--pattern-stroke-2xl: 4px;
|
||||
--pattern-stroke-3xl: 6px;
|
||||
--pattern-stroke-4xl: 8px;
|
||||
--pattern-stroke-5xl: 12px;
|
||||
--pattern-stroke-6xl: 16px;
|
||||
--pattern-stroke-7xl: 20px;
|
||||
'--pattern-bg':var(--neutral-50);
|
||||
'--pattern-fabric':var(--neutral-900);
|
||||
'--pattern-lining':var(--emerald-500);
|
||||
'--pattern-interfacing':var(--neutral-400);
|
||||
,'--pattern-canvas': var(--amber-600);
|
||||
'--pattern-various':var(--red-500);
|
||||
'--pattern-mark':var(--blue-500);
|
||||
'--pattern-contrast':var(--pink-500);
|
||||
'--pattern-note':var(--violet-500);
|
||||
}
|
||||
|
||||
/* For readability concerns, you should choose a lighter palette in dark mode. */
|
||||
|
@ -148,6 +124,19 @@
|
|||
/* Footer colors */
|
||||
--ifm-footer-background-color: var(--neutral-900);
|
||||
--ifm-footer-link-color: var(--sky-300);
|
||||
|
||||
/*
|
||||
* FreeSewing pattern vars
|
||||
*/
|
||||
'--pattern-bg':var(--neutral-900);
|
||||
'--pattern-fabric':var(--neutral-5);
|
||||
'--pattern-lining':var(--emerald-500);
|
||||
'--pattern-interfacing':var(--neutral-400);
|
||||
,'--pattern-canvas': var(--amber-600);
|
||||
'--pattern-various':var(--red-500);
|
||||
'--pattern-mark':var(--blue-500);
|
||||
'--pattern-contrast':var(--pink-500);
|
||||
'--pattern-note':var(--violet-500);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -155,6 +144,11 @@
|
|||
*/
|
||||
@import './code.css';
|
||||
|
||||
/*
|
||||
* Add styling for FreeSewing patterns
|
||||
*/
|
||||
@import './patterns.css';
|
||||
|
||||
div.footer__copyright {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -70,7 +70,7 @@ export const theme = {
|
|||
'--focus-ring-offset': '2px',
|
||||
|
||||
'--pattern-bg': colors.neutral['900'],
|
||||
'--pattern-fabric': colors.neutral['300'],
|
||||
'--pattern-fabric': colors.neutral['50'],
|
||||
'--pattern-lining': colors.emerald['300'],
|
||||
'--pattern-interfacing': colors.neutral['500'],
|
||||
'--pattern-canvas': colors.amber['300'],
|
||||
|
|
|
@ -170,7 +170,7 @@ export const theme = {
|
|||
// Pattern background color
|
||||
'--pattern-bg': colors.neutral['50'],
|
||||
// Color for the main fabric
|
||||
'--pattern-fabric': colors.neutral['700'],
|
||||
'--pattern-fabric': colors.neutral['900'],
|
||||
// Color for lining fabric
|
||||
'--pattern-lining': colors.emerald['500'],
|
||||
// Color for interfacing
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue