import * as React from 'react' import {__, _x, sprintf} from '@wordpress/i18n' import { Modal, CheckboxControl, __experimentalVStack as VStack, } from '@wordpress/components' import { useContext, useState, } from '@wordpress/element' import { useDispatch, } from '@wordpress/data' import { store as noticesStore, } from '@wordpress/notices' import { ActionInput, } from '@ska/components' import { usePresetOptionsEdit, type PresetBlockAttributes, } from '..' import { useSkaBlocksDispatch, } from '../../../tailwind/reducer' import { InspectorControlsContext, } from '../../../tailwind/inspector-controls' import type { TailwindFeatureAttributes, SelectorsValue, VariablesValue, } from '../../../types' export interface CreatePresetProps { onRequestClose: () => void } const CreatePreset: React.FC = ({ onRequestClose, }) => { const [, presetDispatch] = usePresetOptionsEdit() const { attributes, setAttributes, features, } = useContext(InspectorControlsContext) const dispatch = useSkaBlocksDispatch(attributes, setAttributes) const { skaBlocksSelectors = {}, skaBlocksVariables = {}, } = attributes const { record: variablesRecord = {}, } = skaBlocksVariables const { createSuccessNotice, createErrorNotice, } = useDispatch(noticesStore) const [presetName, setPresetName] = useState('') const [isLoading, setIsLoading] = useState(false) const [excludedFeatures, setExcludedFeatures] = useState([]) const usedFeatures = features.filter(({hasValue}) => hasValue) const selectors = Object.keys(skaBlocksSelectors) const [excludedSelectors, setExcludedSelectors] = useState([]) const variables = Object.keys(variablesRecord) const [excludedVariables, setExcludedVariables] = useState([]) const onCreatePreset = async (name: string) => { if(isLoading) { return } if(!name) { createErrorNotice(__('Preset name is required', 'ska-blocks'), {type: 'snackbar'}) return } const includedFeatures = usedFeatures.filter(({id}) => !excludedFeatures.includes(id)) const includedSelectors = selectors.filter(s => !excludedSelectors.includes(s)) const includedVariables = variables.filter(v => !excludedVariables.includes(v)) if( !includedFeatures.length && !includedSelectors.length && !includedVariables.length ) { createErrorNotice(__('Cannot create empty preset', 'ska-blocks'), {type: 'snackbar'}) return } const presetAttributes = { ...includedFeatures.reduce((acc, {id}) => { acc[id] = attributes[id] return acc }, {} as PresetBlockAttributes), ...(includedSelectors.length > 0 && { skaBlocksSelectors: includedSelectors.reduce((acc, cur) => { acc[cur] = skaBlocksSelectors[cur] return acc }, {} as PresetBlockAttributes), }), ...(includedVariables.length > 0 && { skaBlocksVariables: { record: includedVariables.reduce((acc, cur) => { acc[cur] = variablesRecord[cur] return acc }, {} as PresetBlockAttributes), }, }), } setIsLoading(true) try { const slug = await presetDispatch.addPreset({title: name, attributes: presetAttributes}) dispatch.batch([ dispatch.actions.addPreset(slug), dispatch.actions.setAttributes({ /** Unset features that got added to the preset. */ ...includedFeatures.reduce((acc, cur) => { acc[cur.id] = undefined return acc }, {} as TailwindFeatureAttributes), ...(includedSelectors.length > 0 && { /** Retain selectors that didn't get added to the preset. */ skaBlocksSelectors: selectors.reduce((acc, cur) => { if(!includedSelectors.includes(cur)) { acc[cur] = skaBlocksSelectors[cur] } return acc }, {} as SelectorsValue), /** All selectors got added, reset selectors. */ ...(includedSelectors.length === selectors.length && { skaBlocksSelectors: undefined, }), }), ...(includedVariables.length > 0 && { /** Retain variables that didn't get added to the preset. */ skaBlocksVariables: { ...skaBlocksVariables, record: variables.reduce((acc, cur) => { if(!includedVariables.includes(cur)) { acc[cur] = variablesRecord[cur] } return acc }, {} as NonNullable), }, /** All variables got added, reset variables. */ ...(includedVariables.length === variables.length && { skaBlocksVariables: undefined, }), }), }), ]) createSuccessNotice(sprintf(__('Created preset "%s"', 'ska-blocks'), name), {type: 'snackbar'}) } catch(error: any) { const errorMessage = typeof error === 'object' && Object.hasOwnProperty('message') && error?.code !== 'unknown_error' ? error.message : __('An error occurred while saving the preset.', 'ska-blocks') createErrorNotice(errorMessage, {type: 'snackbar'}) } finally { setExcludedFeatures([]) setExcludedSelectors([]) setPresetName('') setIsLoading(false) onRequestClose() } } return ( setPresetName('')} onSubmit={onCreatePreset} disabled={isLoading} /> {usedFeatures.length > 0 && (
{__('Features', 'ska-blocks')} {usedFeatures.map(({id, label}) => ( setExcludedFeatures( excludedFeatures.includes(id) ? excludedFeatures.filter(eid => eid !== id) : excludedFeatures.concat(id) )} __nextHasNoMarginBottom /> ))}
)} {selectors.length > 0 && (
{__('Selectors', 'ska-blocks')} {selectors.map(selector => ( setExcludedSelectors( excludedSelectors.includes(selector) ? excludedSelectors.filter(s => s !== selector) : excludedSelectors.concat(selector) )} __nextHasNoMarginBottom /> ))}
)} {variables.length > 0 && (
{__('Variables', 'ska-blocks')} {variables.map(variable => ( setExcludedVariables( excludedVariables.includes(variable) ? excludedVariables.filter(v => v !== variable) : excludedVariables.concat(variable) )} __nextHasNoMarginBottom /> ))}
)}
) } export default CreatePreset