import { createUseOptions, createUseOptionsEdit, Options, RootKey, type OptionDispatch, type OptionSelect, } from '@ska/plugin' import { uniqueId, uniqueSlugForObject, } from '@ska/utils' import SkaBlocks from '../../SkaBlocks' import { presetOptions as initialState, } from '../../data' import { resolvePreset, type BlockPreset, type Presets, type Preset, type PresetSlug, } from '.' import type { tBlockAttributes, } from '@ska/shared' export type PresetOptions = Options<{ presets: Presets }> export const PRESETS_ROOT_KEY = 'ska_blocks_presets' as RootKey const useOptions = createUseOptions(PRESETS_ROOT_KEY, initialState) const useOptionsEdit = createUseOptionsEdit(PRESETS_ROOT_KEY, initialState) const usePresetOptionsEdit = () => { const [select, dispatch] = useOptionsEdit() const getPreset = (slug: BlockPreset['id']): Preset => { const presets = select.getOption('presets') as any as PresetOptions['presets'] if(Object(presets).hasOwnProperty(slug)) { return presets[slug] } return resolvePreset(slug, presets) } const addPreset = async ({title, attributes}: {title: string, attributes: tBlockAttributes}) => { const presets = select.getOption('presets') as any as PresetOptions['presets'] const slug: PresetSlug = uniqueSlugForObject(title, presets) const classNames = SkaBlocks.tailwind.getClassNames(attributes) const css = await SkaBlocks.compiler.compileComponent('.ska-preset-selector', classNames) dispatch.updateOption({ option: 'presets', value: { ...presets, [slug]: { ref: uniqueId(), title, attrs: JSON.stringify(attributes), cx: classNames, css, t: Math.floor(Date.now() / 1000), v: SkaBlocks.compiler.t, isDefault: false, }, } as PresetOptions['presets'], }) return slug } const updatePreset = (slug: PresetSlug, updates: Partial>) => { const presets = select.getOption('presets') as any as PresetOptions['presets'] if(!Object(presets).hasOwnProperty(slug)) { throw new Error(`Preset "${slug}" not found.`) } const nextPreset = { ...presets[slug], ...updates, } dispatch.updateOption({ option: 'presets', value: { ...presets, [slug]: nextPreset, }, }) } const updatePresetAttributes = async (slug: PresetSlug, attributes: tBlockAttributes, updates?: Partial>) => { const cx = SkaBlocks.tailwind.getClassNames(attributes) const css = await SkaBlocks.compiler.compileComponent('.ska-preset-selector', cx) const presets = select.getOption('presets') as any as PresetOptions['presets'] if(!Object(presets).hasOwnProperty(slug)) { throw new Error(`Preset "${slug}" not found.`) } const nextPreset = { ...presets[slug], isDefault: false, ...updates, attrs: JSON.stringify(attributes), cx, css, t: Math.floor(Date.now() / 1000), v: SkaBlocks.compiler.t, } dispatch.updateOption({ option: 'presets', value: { ...presets, [slug]: nextPreset, }, }) } const deletePreset = (slug: PresetSlug) => { const presets = select.getOption('presets') as any as PresetOptions['presets'] const { [slug]: _preset, ...nextPresets } = presets dispatch.updateOption({ option: 'presets', value: { ...nextPresets, }, }) } return [ { ...select, getPreset, }, { ...dispatch, addPreset, updatePreset, updatePresetAttributes, deletePreset, }, ] as [ OptionSelect & { getPreset: typeof getPreset, }, OptionDispatch & { addPreset: typeof addPreset, updatePreset: typeof updatePreset, updatePresetAttributes: typeof updatePresetAttributes, deletePreset: typeof deletePreset, }, ] } export type PresetsSelect = ReturnType[0] export type PresetsDispatch = ReturnType[1] export { useOptions as usePresetOptions, usePresetOptionsEdit, }