// Hooks import { useContext, useState } from 'react' import { useTranslation } from 'next-i18next' // Context import { ModalContext } from 'shared/context/modal-context.mjs' // Components import { ModalWrapper } from 'shared/components/wrappers/modal.mjs' import { Collapse } from 'shared/components/collapse.mjs' import { OptionsIcon, ClearIcon, HelpIcon, EditIcon } from 'shared/components/icons.mjs' import { optionsMenuStructure } from 'shared/utils.mjs' import { optionType } from 'shared/utils.mjs' import { BoolOptionInput, ConstantOptionInput, CountOptionInput, DegOptionInput, ListOptionInput, MmOptionInput, PctOptionInput, } from './inputs.mjs' import { BoolOptionValue, ConstantOptionValue, CountOptionValue, DegOptionValue, ListOptionValue, MmOptionValue, PctOptionValue, } from './values.mjs' export const ns = ['design-options'] // Facilitate lookup of the input component const inputs = { bool: BoolOptionInput, constant: ConstantOptionInput, count: CountOptionInput, deg: DegOptionInput, list: ListOptionInput, mm: MmOptionInput, pct: PctOptionInput, } // Facilitate lookup of the value component const values = { bool: BoolOptionValue, constant: ConstantOptionValue, count: CountOptionValue, deg: DegOptionValue, list: ListOptionValue, mm: MmOptionValue, pct: PctOptionValue, } // Emojis for option groups :) const emojis = { advanced: '🤓', fit: '👕', style: '💃đŸŊ', dflt: 'đŸ•šī¸', groupDflt: '📁', } const GroupTitle = ({ group, t, open = false }) => (
{emojis[group] ? emojis[group] : emojis.groupDflt} {t(`design-options:${group}.t`)} {open ? ':' : ''}
) const ClearButton = ({ update, name, open }) => ( ) export const DesignOption = ({ design, name, current, config, settings, update, t, loadDocs, changed = false, }) => { const [override, setOverride] = useState(false) const type = optionType(config) const Input = inputs[type] const Value = values[type] // Hide option? if (config?.hide || (typeof config?.hide === 'function' && config.hide(settings))) return null if (type === 'bool') { config = { ...config, list: [0, 1], choiceTitles: { 0: `${name}No`, 1: `${name}Yes`, }, valueTitles: { 0: 'no', 1: 'yes', }, dflt: config.dflt ? 1 : 0, } } const buttons = [] const openButtons = [] if (loadDocs) openButtons.push( ) if (['pct', 'count', 'deg'].includes(type)) openButtons.push( ) if (changed) { buttons.push() openButtons.push() } return ( {t(`${name}.t`)} } openTitle={t(`${name}.t`)} {...{ buttons, openButtons }} > ) } export const DesignOptionGroup = ({ design, patternConfig, settings, update, group, options, Option, t, loadDocs, topLevel = false, }) => ( } openTitle={t(group)} > {Object.entries(options).map(([option, type]) => typeof type === 'string' ? ( ) const wasChanged = (current, config) => { if (typeof current === 'undefined') return false if (current === config.dflt) return false return true } export const DesignOptions = ({ design, patternConfig, settings, update, language, Option = false, DynamicDocs = false, control, }) => { const { t } = useTranslation([design]) const { setModal } = useContext(ModalContext) // FIXME: Do we still care about passing in an Option component? if (!Option) Option = DesignOption const optionsMenu = optionsMenuStructure(patternConfig.options) const loadDocs = DynamicDocs ? (evt, option = false) => { evt.stopPropagation() setModal(
) } : false return ( <>
{control > 4 ? null : ( <>
{t('design-options:designOptions')}

{t('design-options:designOptions.d')}

)}
{Object.entries(optionsMenu).map(([group, option]) => typeof option === 'string' ? (