UNPKG

react-email-builder

Version:
233 lines (232 loc) 9.07 kB
import { useCallback, useContext, useMemo } from 'react'; import { EmailBuilderConfigContext, EmailBuilderDefaultFontStyleContext, EmailBuilderSelectedBlockInfoContext, EmailBuilderStateContext, SetEmailBuilderStateContext } from '../context'; import { copyBlock, createPlaceholder } from '../utils'; export function useEmailBuilderConfig() { return useContext(EmailBuilderConfigContext); } export function useEmailBuilderState() { return useContext(EmailBuilderStateContext); } export function useSetEmailBuilderState() { return useContext(SetEmailBuilderStateContext); } export function useSelectedBlock() { return useContext(EmailBuilderSelectedBlockInfoContext); } export function useBlockStyle(block) { const { style } = block; const fontStyle = useContext(EmailBuilderDefaultFontStyleContext); return useMemo(() => { const p = style.padding || []; const u = undefined; return { ...fontStyle, backgroundColor: style.bgColor, paddingTop: p[0] ?? u, paddingRight: p[1] ?? u, paddingBottom: p[2] ?? u, paddingLeft: p[3] ?? u }; }, [fontStyle, style]); } export function useBlockEditor(blockId) { const setState = useSetEmailBuilderState(); return useCallback((mutate) => { setState((prev) => ({ ...prev, blocks: prev.blocks.map((block) => { if (block.id === blockId) { return mutate(block); } if (block.type === 'columns') { let columnsTouched = false; const cols = block; const nextColumns = { ...cols, attrs: { ...cols.attrs, columns: cols.attrs.columns.map((column) => { let columnTouched = false; const nextColumn = { ...column, blocks: column.blocks.map((columnBlock) => { if (columnBlock.id === blockId) { columnTouched = true; return mutate(columnBlock); } return columnBlock; }) }; if (columnTouched) { columnsTouched = true; } return columnTouched ? nextColumn : column; }) } }; return columnsTouched ? nextColumns : block; } return block; }) })); }, [setState, blockId]); } export function useBlockAttrsEditor(block) { const setBlock = useBlockEditor(block.id); const setAttrs = useCallback((attrs) => { setBlock((prev) => ({ ...prev, attrs: { ...prev.attrs, ...attrs } })); }, [setBlock]); return setAttrs; } export function useDeleteBlock() { const setState = useSetEmailBuilderState(); return useCallback((blockId) => { setState((prev) => { const filterBlocks = (blocks) => { const newBlocks = []; let touched = false; blocks.forEach((block) => { if (block.id === blockId) { touched = true; } else { let newBlock = block; if (newBlock.type === 'columns') { const cols = newBlock; let columnsTouched = false; newBlock = { ...cols, attrs: { ...cols.attrs, columns: cols.attrs.columns.map((column) => { const newColumnBlocks = filterBlocks(column.blocks); if (newColumnBlocks !== column.blocks) { columnsTouched = true; return { ...column, blocks: newColumnBlocks }; } return column; }) } }; if (columnsTouched) { touched = true; } else { newBlock = block; } } newBlocks.push(newBlock); } }); if (touched && !newBlocks.length) { newBlocks.push(createPlaceholder()); } return touched ? newBlocks : blocks; }; const prevSelected = prev.selectedId === blockId; return { ...prev, blocks: filterBlocks(prev.blocks), selectedId: prevSelected ? undefined : prev.selectedId, dragoverId: prev.dragoverId === blockId ? undefined : prev.dragoverId, tab: prevSelected && prev.tab === 'settings' ? 'blocks' : prev.tab }; }); }, [setState]); } export function useMoveBlock() { const setState = useSetEmailBuilderState(); return useCallback((blockId, direction) => { setState((prev) => { const move = (blocks) => { const newBlocks = [...blocks]; const index = newBlocks.findIndex((block) => block.id === blockId); if (index > -1) { const max = newBlocks.length - 1; let target = index + direction; if (target < 0) { target = 0; } if (target > max) { target = max; } const old = newBlocks[target]; newBlocks[target] = newBlocks[index]; newBlocks[index] = old; return newBlocks; } return blocks; }; return { ...prev, blocks: move(prev.blocks).map((block) => { if (block.type === 'columns') { const cols = block; return { ...block, attrs: { ...cols.attrs, columns: cols.attrs.columns.map((column) => ({ ...column, blocks: move(column.blocks) })) } }; } return block; }) }; }); }, [setState]); } export function useCopyBlock() { const setState = useSetEmailBuilderState(); const config = useEmailBuilderConfig(); return useCallback((blockId) => { setState((prev) => { let copiedBlockId; const copy = (blocks) => { const newBlocks = []; blocks.forEach((block) => { newBlocks.push(block); if (block.id === blockId) { const copied = copyBlock(block, config); copiedBlockId = copied.id; newBlocks.push(copied); } }); return newBlocks; }; const blocks = copy(prev.blocks).map((block) => { if (block.type === 'columns') { const cols = block; return { ...cols, attrs: { ...cols.attrs, columns: cols.attrs.columns.map((col) => ({ ...col, blocks: copy(col.blocks) })) } }; } return block; }); return { ...prev, blocks, selectedId: copiedBlockId }; }); }, [setState, config]); }