UNPKG

@quillforms/block-editor

Version:
434 lines (416 loc) 13.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; exports.flattenBlocks = flattenBlocks; var _lodash = require("lodash"); var _constants = require("./constants"); var _blocks = require("@quillforms/blocks"); /* eslint-disable no-nested-ternary */ /** * External dependencies */ /** * Internal Dependencies */ const generateBlockId = () => { return Math.random().toString(36).substr(2, 9); }; /** * Sort blocks. We should have welcome screens at first then others then thankyou screens. * * @param {Object} blocks The blocks array. * * @return { Object } The sorted blocks */ function sortBlocks(blocks) { const priority = ['WELCOME_SCREENS', 'OTHERS', 'THANKYOU_SCREENS']; blocks.sort((a, b) => { const getCategory = block => { switch (block.name) { case 'welcome-screen': return 'WELCOME_SCREENS'; case 'thankyou-screen': return 'THANKYOU_SCREENS'; default: return 'OTHERS'; } }; const ap = priority.indexOf(getCategory(a)); const bp = priority.indexOf(getCategory(b)); return ap - bp; }); return blocks; } // Initial State const initialState = { currentBlockId: undefined, currentChildBlockId: undefined, blocks: [] }; // /** // * Utility returning an object with an empty object value for each key. // * // * @param {string[]} objectKeys Keys to fill. // * @return {Object} Object filled with empty object as values for each clientId. // */ // const fillKeysWithEmptyObject = ( // objectKeys: string[] // ): Record< string, {} > => { // return objectKeys.reduce( ( result, key ) => { // result[ key ] = {}; // return result; // }, {} ); // }; /** * Helper method to iterate through all blocks, recursing into inner blocks, * applying a transformation function to each one. * Returns a flattened object with the transformed blocks. * * @param {FormBlocks} blocks Blocks to flatten. * * @param transform * @return {Array} Flattened object. */ function flattenBlocks(blocks, transform = _lodash.identity) { const result = []; const stack = [...blocks]; while (stack.length) { // @ts-expect-error const { innerBlocks, ...block } = stack.shift(); if (innerBlocks) { (0, _lodash.forEach)(innerBlocks, ($block, index) => { innerBlocks[index] = { ...$block, parentId: block.id }; }); stack.push(...innerBlocks); } result[block.id] = transform(block); } return result; } /** * Reducer returning the form object. * * @param { BlockEditorPureState} state Current state. * @param {BlockEditorActionTypes} action Dispatched action. * * @return {BlockEditorPureState} Updated state. */ const BlockEditorReducer = (state = initialState, action) => { switch (action.type) { // SET UP STORE case _constants.SETUP_STORE: { const { initialPayload } = action; if (initialPayload.length > 0 && !state.currentBlockId) { return { blocks: initialPayload, currentBlockId: initialPayload[0].id, currentChildBlockId: undefined }; } return { ...state, blocks: initialPayload }; } case _constants.SET_BLOCKS: { const { blocks } = action; return { ...state, blocks }; } case 'REPLACE_BLOCK_NAME': { const { blockId, name, parentId } = action; const blocks = [...state.blocks]; let blockIndex; let parentIndex; if (typeof parentId !== 'undefined') { parentIndex = blocks.findIndex(item => item.id === parentId); if (parentIndex !== -1 && (0, _lodash.size)(blocks[parentIndex]?.innerBlocks) > 0) { blockIndex = blocks[parentIndex]?.innerBlocks?.findIndex(item => item.id === blockId); } else { return state; } } else { blockIndex = blocks.findIndex(item => item.id === blockId); } // const blockIndex = blocks.findIndex((block) => block.id === blockId); if (blockIndex === -1 || parentId && (parentIndex === -1 || !blocks[parentIndex]?.innerBlocks)) { return state; } if (parentId && parentIndex > -1) { blocks[parentIndex].innerBlocks[blockIndex].name = name; blocks[parentIndex].innerBlocks[blockIndex].attributes = (0, _blocks.sanitizeBlockAttributes)(name, blocks[parentIndex].innerBlocks[blockIndex].attributes); } else { blocks[blockIndex].name = name; if (blocks[blockIndex].name === 'group' && (0, _lodash.size)(blocks[blockIndex].innerBlocks) === 0) { blocks[blockIndex].innerBlocks = [{ name: 'short-text', id: generateBlockId(), attributes: {} }]; } blocks[blockIndex].attributes = (0, _blocks.sanitizeBlockAttributes)(name, blocks[blockIndex]?.attributes); } return { ...state, blocks: sortBlocks(blocks) }; } // SET BLOCK ATTRIBUTES case _constants.SET_BLOCK_ATTRIBUTES: { const { blockId, attributes, parentId } = action; let parentIndex; // Get block index within its category. let $blocks = [...state.blocks]; if (!$blocks) { return state; } if (typeof parentId !== 'undefined' && parentId !== blockId) { parentIndex = $blocks.findIndex(block => { return block.id === parentId; }); $blocks = [...state.blocks][parentIndex]?.innerBlocks; } if (!$blocks) { return state; } const blockIndex = $blocks.findIndex(block => { return block.id === blockId; }); // Ignore updates if block isn't known. if (blockIndex === -1) { return state; } // Consider as updates only changed values // const nextAttributes = reduce( // { ...attributes }, // ( result, value, key ) => { // if ( value !== result[ key ] ) { // result = getMutateSafeObject( // state.blocks[ blockIndex ], // result // ); // result[ key ] = value; // } // return result; // }, // state.blocks[ blockIndex ].attributes // ); const nextAttributes = { ...(0, _lodash.cloneDeep)($blocks[blockIndex].attributes), ...(0, _lodash.cloneDeep)(attributes) }; // // Skip update if nothing has been changed. The reference will // // match the original block if `reduce` had no changed values. // if ( nextAttributes === state.blocks[ blockIndex ].attributes ) { // return state; // } $blocks[blockIndex].attributes = nextAttributes; const blocks = [...state.blocks]; if (typeof parentIndex !== 'undefined') { blocks[parentIndex].innerBlocks = $blocks; $blocks = blocks; } return { ...state, blocks: $blocks }; } case _constants.REORDER_BLOCKS: { const { sourceIndex, destinationIndex, parentSourceIndex, parentDestIndex } = action; // Create deep copy of blocks const newBlocks = JSON.parse(JSON.stringify(state.blocks)); // Get source block and remove it from original position let sourceBlock; if (typeof parentSourceIndex === 'undefined') { sourceBlock = { ...newBlocks[sourceIndex] }; newBlocks.splice(sourceIndex, 1); } else { sourceBlock = { ...newBlocks[parentSourceIndex].innerBlocks[sourceIndex] }; newBlocks[parentSourceIndex].innerBlocks.splice(sourceIndex, 1); } // Insert block at new position if (typeof parentDestIndex === 'undefined') { // Insert at root level newBlocks.splice(destinationIndex, 0, sourceBlock); } else { // Insert into group if (!newBlocks[parentDestIndex].innerBlocks) { newBlocks[parentDestIndex].innerBlocks = []; } newBlocks[parentDestIndex].innerBlocks.splice(destinationIndex, 0, sourceBlock); } return { ...state, blocks: newBlocks }; } // INSERT NEW FORM BLOCK case _constants.INSERT_BLOCK: { const { block, destinationIndex, parent } = action; const blocks = [...state.blocks]; const index = destinationIndex; let parentBlock = undefined; if (index === undefined || index < 0) { return state; } if (!parent) { blocks.splice(index, 0, { ...block }); } else { const parentIndex = blocks.findIndex($block => $block.id === parent); parentBlock = blocks[parentIndex]; if (!blocks[parentIndex].innerBlocks) { blocks[parentIndex].innerBlocks = []; } blocks[parentIndex]?.innerBlocks?.splice(index, 0, { ...block }); } return { ...state, blocks: sortBlocks(blocks), currentBlockId: parentBlock ? parentBlock.id : block.id, currentChildBlockId: parentBlock ? block.id : undefined }; } // DELETE FORM BLOCK case _constants.DELETE_BLOCK: { const { blockId, parentId } = action; const originalBlocks = [...state.blocks]; let parentIndex; let blocks = originalBlocks; if (!blocks) { return state; } if (typeof parentId !== 'undefined') { var _blocks$parentIndex$i; parentIndex = blocks.findIndex(item => item.id === parentId); if (blocks) blocks = (_blocks$parentIndex$i = blocks?.[parentIndex]?.innerBlocks) !== null && _blocks$parentIndex$i !== void 0 ? _blocks$parentIndex$i : []; } // Get block index. const blockIndex = blocks.findIndex(item => item.id === blockId); // If block isn't found. if (blockIndex === -1) { return state; } const nextBlock = blocks[blockIndex + 1]; const prevBlock = blocks[blockIndex - 1]; blocks.splice(blockIndex, 1); const newCurrentBlockId = nextBlock ? nextBlock.id : prevBlock ? prevBlock.id : undefined; if (typeof parentIndex !== 'undefined') { const $blocks = originalBlocks; $blocks[parentIndex].innerBlocks = blocks; blocks = $blocks; } const newState = { ...state, currentBlockId: typeof parentIndex === 'undefined' ? newCurrentBlockId : state.currentBlockId, currentChildBlockId: typeof parentIndex === 'undefined' ? undefined : newCurrentBlockId, blocks }; return newState; } // SET CURRENT BLOCK case _constants.SET_CURRENT_BLOCK: { const { blockId } = action; const blockIndex = state.blocks.findIndex(item => item.id === blockId); // If block isn't found. if (blockIndex === -1) { return state; } if (blockId === state.currentBlockId) return state; return { ...state, currentBlockId: blockId, currentChildBlockId: undefined }; } // SET CURRENT CHILD BLOCK case _constants.SET_CURRENT_CHILD_BLOCK: { const { blockId } = action; if (blockId === state.currentChildBlockId) { return state; } // const parentblockIndex = state.blocks.findIndex( // ( item ) => item.id === state.currentBlockId // ); // // If block isn't found. // if ( // parentblockIndex === -1 || // typeof parentblockIndex === 'undefined' || // state.blocks.length === 0 || // ! state.blocks[ parentblockIndex ] // ) { // return state; // } // const childBlockIndex = state.blocks[ // parentblockIndex // ]?.innerBlocks?.findIndex( // ( item ) => item.id === state.currentBlockId // ); // if ( childBlockIndex === -1 ) { // return state; // } return { ...state, currentChildBlockId: blockId }; } } return state; }; const BlockEditorReducerWithHigherOrder = BlockEditorReducer; var _default = exports.default = BlockEditorReducerWithHigherOrder; //# sourceMappingURL=reducer.js.map