import * as React from 'react' import {__, _x} from '@wordpress/i18n' import cx from 'classnames' import { useEffect, useRef, useState, } from '@wordpress/element' import { __experimentalNavigatorButton as NavigatorButton, } from '@wordpress/components' import { edit as editIcon, styles as stylesIcon, filter as filterIcon, link as linkIcon, linkOff as linkOffIcon, } from '@wordpress/icons' import { ArrayEditor, } from '../../../components' import { isManagedPreset, usePresetOptionsEdit, PresetsModal, type PresetSlug, type ResolvedBlockPreset, } from '..' import type { ArrayValueControlProps, ButtonGridButtonProps, } from '@ska/components' import type { SkaBlocksActionTypes, } from '../../../tailwind/reducer' export interface PresetsListProps { presets: ResolvedBlockPreset[] dispatch: SkaBlocksActionTypes } const PresetRow: React.FC = ({value}) => { const [presetsSelect] = usePresetOptionsEdit() const { ref, title, loading, } = presetsSelect.getPreset(value) return (
{title} {loading === 'off' && ` (${__('Loading disabled', 'ska-blocks')})`}
) } const PresetsList: React.FC = ({ presets: blockPresets, dispatch, }) => { const [presetsSelect] = usePresetOptionsEdit() const [replace, setReplace] = useState(undefined) /** * Hack for dispatch.presetToggleStatic(). * For performance reasons the dispatch only loads dynamic presets that the block currently has (which is almost always 0), * so when a preset type is toggled it's not yet loaded/unloaded and won't be available when applying Tailwind. * This triggers a second update that will process the attributes again, accounting for the change in presets. */ const shouldForceUpdateRef = useRef(false) useEffect(() => { if(!shouldForceUpdateRef.current) { return } dispatch.setAttributes({}) shouldForceUpdateRef.current = false }, [dispatch]) return <> id.toString())} onChange={ids => dispatch.updateBlockPresets( ids.map(slug => blockPresets.find(({id}) => id === slug)) as any as ResolvedBlockPreset[] )} ValueControl={PresetRow} getButtons={(buttons, presetSlug) => { const preset = presetsSelect.getPreset(presetSlug) if(preset.ref === '404') { return [ { label: __('Replace preset', 'ska-blocks'), icon: linkIcon, onClick: () => { setReplace(presetSlug) }, }, buttons[buttons.findIndex(({key}) => key === 'remove-row')], ] as ButtonGridButtonProps[] } const { attrs, } = preset const { isStatic = false, } = blockPresets.find(({id}) => presetSlug === id) || {} return [ buttons[buttons.findIndex(({key}) => key === 'move-up')], { label: __('Merge preset', 'ska-blocks'), icon: linkOffIcon, onClick: () => dispatch.mergePreset({id: presetSlug, presetAttributes: JSON.parse(attrs)}), }, { label: __('Edit preset', 'ska-blocks'), icon: editIcon, iconProps: {size: 14}, as: NavigatorButton, path: `/preset/${presetSlug}`, }, buttons[buttons.findIndex(({key}) => key === 'move-down')], { label: isStatic ? __('Switch to dynamic', 'ska-blocks') : __('Switch to static', 'ska-blocks'), icon: isStatic ? stylesIcon : filterIcon, className: cx({ 'ska-presets__toggle-static': isStatic, 'ska-presets__toggle-dynamic': !isStatic, }), iconProps: {size: 14}, onClick: () => { dispatch.presetToggleStatic(presetSlug) shouldForceUpdateRef.current = true }, }, { ...buttons[buttons.findIndex(({key}) => key === 'remove-row')], label: __('Remove preset', 'ska-blocks'), }, ] as ButtonGridButtonProps[] }} /> {replace && ( { dispatch.batch([ dispatch.actions.removePreset(replace), dispatch.actions.addPreset(slug), ]) setReplace(undefined) }} onRemovePreset={slug => dispatch.removePreset(slug)} onRequestClose={() => setReplace(undefined)} /> )} } export default PresetsList