UNPKG

@wordpress/block-editor

Version:
8 lines (7 loc) 11.6 kB
{ "version": 3, "sources": ["../../../src/components/grid/use-grid-layout-sync.js"], "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport { useEffect, useMemo } from '@wordpress/element';\nimport { usePrevious } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport { store as blockEditorStore } from '../../store';\nimport { GridRect } from './utils';\nimport { setImmutably } from '../../utils/object';\n\nexport function useGridLayoutSync( { clientId: gridClientId } ) {\n\tconst { gridLayout, blockOrder, selectedBlockLayout } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getBlockAttributes, getBlockOrder } =\n\t\t\t\tselect( blockEditorStore );\n\t\t\tconst selectedBlock = select( blockEditorStore ).getSelectedBlock();\n\t\t\treturn {\n\t\t\t\tgridLayout: getBlockAttributes( gridClientId ).layout ?? {},\n\t\t\t\tblockOrder: getBlockOrder( gridClientId ),\n\t\t\t\tselectedBlockLayout: selectedBlock?.attributes.style?.layout,\n\t\t\t};\n\t\t},\n\t\t[ gridClientId ]\n\t);\n\n\tconst { getBlockAttributes, getBlockRootClientId } =\n\t\tuseSelect( blockEditorStore );\n\tconst { updateBlockAttributes, __unstableMarkNextChangeAsNotPersistent } =\n\t\tuseDispatch( blockEditorStore );\n\n\tconst selectedBlockRect = useMemo(\n\t\t() =>\n\t\t\tselectedBlockLayout ? new GridRect( selectedBlockLayout ) : null,\n\t\t[ selectedBlockLayout ]\n\t);\n\n\tconst previouslySelectedBlockRect = usePrevious( selectedBlockRect );\n\tconst previousIsManualPlacement = usePrevious(\n\t\tgridLayout.isManualPlacement\n\t);\n\tconst previousBlockOrder = usePrevious( blockOrder );\n\n\tuseEffect( () => {\n\t\tconst updates = {};\n\n\t\tif ( gridLayout.isManualPlacement ) {\n\t\t\tconst occupiedRects = [];\n\n\t\t\t// Respect the position of blocks that already have a columnStart and rowStart value.\n\t\t\tfor ( const clientId of blockOrder ) {\n\t\t\t\tconst {\n\t\t\t\t\tcolumnStart,\n\t\t\t\t\trowStart,\n\t\t\t\t\tcolumnSpan = 1,\n\t\t\t\t\trowSpan = 1,\n\t\t\t\t} = getBlockAttributes( clientId ).style?.layout ?? {};\n\t\t\t\tif ( ! columnStart || ! rowStart ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\toccupiedRects.push(\n\t\t\t\t\tnew GridRect( {\n\t\t\t\t\t\tcolumnStart,\n\t\t\t\t\t\trowStart,\n\t\t\t\t\t\tcolumnSpan,\n\t\t\t\t\t\trowSpan,\n\t\t\t\t\t} )\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// When in manual mode, ensure that every block has a columnStart and rowStart value.\n\t\t\tfor ( const clientId of blockOrder ) {\n\t\t\t\tconst attributes = getBlockAttributes( clientId );\n\t\t\t\tconst {\n\t\t\t\t\tcolumnStart,\n\t\t\t\t\trowStart,\n\t\t\t\t\tcolumnSpan = 1,\n\t\t\t\t\trowSpan = 1,\n\t\t\t\t} = attributes.style?.layout ?? {};\n\t\t\t\tif ( columnStart && rowStart ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst [ newColumnStart, newRowStart ] = placeBlock(\n\t\t\t\t\toccupiedRects,\n\t\t\t\t\tgridLayout.columnCount,\n\t\t\t\t\tcolumnSpan,\n\t\t\t\t\trowSpan,\n\t\t\t\t\tpreviouslySelectedBlockRect?.columnEnd,\n\t\t\t\t\tpreviouslySelectedBlockRect?.rowEnd\n\t\t\t\t);\n\t\t\t\toccupiedRects.push(\n\t\t\t\t\tnew GridRect( {\n\t\t\t\t\t\tcolumnStart: newColumnStart,\n\t\t\t\t\t\trowStart: newRowStart,\n\t\t\t\t\t\tcolumnSpan,\n\t\t\t\t\t\trowSpan,\n\t\t\t\t\t} )\n\t\t\t\t);\n\t\t\t\tupdates[ clientId ] = {\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\t...attributes.style,\n\t\t\t\t\t\tlayout: {\n\t\t\t\t\t\t\t...attributes.style?.layout,\n\t\t\t\t\t\t\tcolumnStart: newColumnStart,\n\t\t\t\t\t\t\trowStart: newRowStart,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Ensure there's enough rows to fit all blocks.\n\t\t\tconst bottomMostRow = Math.max(\n\t\t\t\t...occupiedRects.map( ( r ) => r.rowEnd )\n\t\t\t);\n\t\t\tif (\n\t\t\t\t! gridLayout.rowCount ||\n\t\t\t\tgridLayout.rowCount < bottomMostRow\n\t\t\t) {\n\t\t\t\tupdates[ gridClientId ] = {\n\t\t\t\t\tlayout: {\n\t\t\t\t\t\t...gridLayout,\n\t\t\t\t\t\trowCount: bottomMostRow,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Unset grid layout attributes for blocks removed from the grid.\n\t\t\tfor ( const clientId of previousBlockOrder ?? [] ) {\n\t\t\t\tif ( ! blockOrder.includes( clientId ) ) {\n\t\t\t\t\tconst rootClientId = getBlockRootClientId( clientId );\n\n\t\t\t\t\t// Block was removed from the editor, so nothing to do.\n\t\t\t\t\tif ( rootClientId === null ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check if the block is being moved to another grid.\n\t\t\t\t\t// If so, do nothing and let the new grid parent handle\n\t\t\t\t\t// the attributes.\n\t\t\t\t\tconst rootAttributes = getBlockAttributes( rootClientId );\n\t\t\t\t\tif ( rootAttributes?.layout?.type === 'grid' ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst attributes = getBlockAttributes( clientId );\n\t\t\t\t\tconst {\n\t\t\t\t\t\tcolumnStart,\n\t\t\t\t\t\trowStart,\n\t\t\t\t\t\tcolumnSpan,\n\t\t\t\t\t\trowSpan,\n\t\t\t\t\t\t...layout\n\t\t\t\t\t} = attributes.style?.layout ?? {};\n\n\t\t\t\t\tif ( columnStart || rowStart || columnSpan || rowSpan ) {\n\t\t\t\t\t\tconst hasEmptyLayoutAttribute =\n\t\t\t\t\t\t\tObject.keys( layout ).length === 0;\n\n\t\t\t\t\t\tupdates[ clientId ] = setImmutably(\n\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t[ 'style', 'layout' ],\n\t\t\t\t\t\t\thasEmptyLayoutAttribute ? undefined : layout\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Remove all of the columnStart and rowStart values\n\t\t\t// when switching from manual to auto mode,\n\t\t\tif ( previousIsManualPlacement === true ) {\n\t\t\t\tfor ( const clientId of blockOrder ) {\n\t\t\t\t\tconst attributes = getBlockAttributes( clientId );\n\t\t\t\t\tconst { columnStart, rowStart, ...layout } =\n\t\t\t\t\t\tattributes.style?.layout ?? {};\n\t\t\t\t\t// Only update attributes if columnStart or rowStart are set.\n\t\t\t\t\tif ( columnStart || rowStart ) {\n\t\t\t\t\t\tconst hasEmptyLayoutAttribute =\n\t\t\t\t\t\t\tObject.keys( layout ).length === 0;\n\n\t\t\t\t\t\tupdates[ clientId ] = setImmutably(\n\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t[ 'style', 'layout' ],\n\t\t\t\t\t\t\thasEmptyLayoutAttribute ? undefined : layout\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove row styles in auto mode\n\t\t\tif ( gridLayout.rowCount ) {\n\t\t\t\tupdates[ gridClientId ] = {\n\t\t\t\t\tlayout: {\n\t\t\t\t\t\t...gridLayout,\n\t\t\t\t\t\trowCount: undefined,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( Object.keys( updates ).length ) {\n\t\t\t__unstableMarkNextChangeAsNotPersistent();\n\t\t\tupdateBlockAttributes(\n\t\t\t\tObject.keys( updates ),\n\t\t\t\tupdates,\n\t\t\t\t/* uniqueByBlock: */ true\n\t\t\t);\n\t\t}\n\t}, [\n\t\t// Actual deps to sync:\n\t\tgridClientId,\n\t\tgridLayout,\n\t\tpreviousBlockOrder,\n\t\tblockOrder,\n\t\tpreviouslySelectedBlockRect,\n\t\tpreviousIsManualPlacement,\n\t\t// These won't change, but the linter thinks they might:\n\t\t__unstableMarkNextChangeAsNotPersistent,\n\t\tgetBlockAttributes,\n\t\tgetBlockRootClientId,\n\t\tupdateBlockAttributes,\n\t] );\n}\n\n/**\n * @param {GridRect[]} occupiedRects\n * @param {number} gridColumnCount\n * @param {number} blockColumnSpan\n * @param {number} blockRowSpan\n * @param {number?} startColumn\n * @param {number?} startRow\n */\nfunction placeBlock(\n\toccupiedRects,\n\tgridColumnCount,\n\tblockColumnSpan,\n\tblockRowSpan,\n\tstartColumn = 1,\n\tstartRow = 1\n) {\n\tfor ( let row = startRow; ; row++ ) {\n\t\tfor (\n\t\t\tlet column = row === startRow ? startColumn : 1;\n\t\t\tcolumn <= gridColumnCount;\n\t\t\tcolumn++\n\t\t) {\n\t\t\tconst candidateRect = new GridRect( {\n\t\t\t\tcolumnStart: column,\n\t\t\t\trowStart: row,\n\t\t\t\tcolumnSpan: blockColumnSpan,\n\t\t\t\trowSpan: blockRowSpan,\n\t\t\t} );\n\t\t\tif (\n\t\t\t\t! occupiedRects.some( ( r ) =>\n\t\t\t\t\tr.intersectsRect( candidateRect )\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn [ column, row ];\n\t\t\t}\n\t\t}\n\t}\n}\n"], "mappings": ";AAGA,SAAS,aAAa,iBAAiB;AACvC,SAAS,WAAW,eAAe;AACnC,SAAS,mBAAmB;AAK5B,SAAS,SAAS,wBAAwB;AAC1C,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAEtB,SAAS,kBAAmB,EAAE,UAAU,aAAa,GAAI;AAC/D,QAAM,EAAE,YAAY,YAAY,oBAAoB,IAAI;AAAA,IACvD,CAAE,WAAY;AACb,YAAM,EAAE,oBAAAA,qBAAoB,cAAc,IACzC,OAAQ,gBAAiB;AAC1B,YAAM,gBAAgB,OAAQ,gBAAiB,EAAE,iBAAiB;AAClE,aAAO;AAAA,QACN,YAAYA,oBAAoB,YAAa,EAAE,UAAU,CAAC;AAAA,QAC1D,YAAY,cAAe,YAAa;AAAA,QACxC,qBAAqB,eAAe,WAAW,OAAO;AAAA,MACvD;AAAA,IACD;AAAA,IACA,CAAE,YAAa;AAAA,EAChB;AAEA,QAAM,EAAE,oBAAoB,qBAAqB,IAChD,UAAW,gBAAiB;AAC7B,QAAM,EAAE,uBAAuB,wCAAwC,IACtE,YAAa,gBAAiB;AAE/B,QAAM,oBAAoB;AAAA,IACzB,MACC,sBAAsB,IAAI,SAAU,mBAAoB,IAAI;AAAA,IAC7D,CAAE,mBAAoB;AAAA,EACvB;AAEA,QAAM,8BAA8B,YAAa,iBAAkB;AACnE,QAAM,4BAA4B;AAAA,IACjC,WAAW;AAAA,EACZ;AACA,QAAM,qBAAqB,YAAa,UAAW;AAEnD,YAAW,MAAM;AAChB,UAAM,UAAU,CAAC;AAEjB,QAAK,WAAW,mBAAoB;AACnC,YAAM,gBAAgB,CAAC;AAGvB,iBAAY,YAAY,YAAa;AACpC,cAAM;AAAA,UACL;AAAA,UACA;AAAA,UACA,aAAa;AAAA,UACb,UAAU;AAAA,QACX,IAAI,mBAAoB,QAAS,EAAE,OAAO,UAAU,CAAC;AACrD,YAAK,CAAE,eAAe,CAAE,UAAW;AAClC;AAAA,QACD;AACA,sBAAc;AAAA,UACb,IAAI,SAAU;AAAA,YACb;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACD,CAAE;AAAA,QACH;AAAA,MACD;AAGA,iBAAY,YAAY,YAAa;AACpC,cAAM,aAAa,mBAAoB,QAAS;AAChD,cAAM;AAAA,UACL;AAAA,UACA;AAAA,UACA,aAAa;AAAA,UACb,UAAU;AAAA,QACX,IAAI,WAAW,OAAO,UAAU,CAAC;AACjC,YAAK,eAAe,UAAW;AAC9B;AAAA,QACD;AACA,cAAM,CAAE,gBAAgB,WAAY,IAAI;AAAA,UACvC;AAAA,UACA,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,6BAA6B;AAAA,UAC7B,6BAA6B;AAAA,QAC9B;AACA,sBAAc;AAAA,UACb,IAAI,SAAU;AAAA,YACb,aAAa;AAAA,YACb,UAAU;AAAA,YACV;AAAA,YACA;AAAA,UACD,CAAE;AAAA,QACH;AACA,gBAAS,QAAS,IAAI;AAAA,UACrB,OAAO;AAAA,YACN,GAAG,WAAW;AAAA,YACd,QAAQ;AAAA,cACP,GAAG,WAAW,OAAO;AAAA,cACrB,aAAa;AAAA,cACb,UAAU;AAAA,YACX;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAGA,YAAM,gBAAgB,KAAK;AAAA,QAC1B,GAAG,cAAc,IAAK,CAAE,MAAO,EAAE,MAAO;AAAA,MACzC;AACA,UACC,CAAE,WAAW,YACb,WAAW,WAAW,eACrB;AACD,gBAAS,YAAa,IAAI;AAAA,UACzB,QAAQ;AAAA,YACP,GAAG;AAAA,YACH,UAAU;AAAA,UACX;AAAA,QACD;AAAA,MACD;AAGA,iBAAY,YAAY,sBAAsB,CAAC,GAAI;AAClD,YAAK,CAAE,WAAW,SAAU,QAAS,GAAI;AACxC,gBAAM,eAAe,qBAAsB,QAAS;AAGpD,cAAK,iBAAiB,MAAO;AAC5B;AAAA,UACD;AAKA,gBAAM,iBAAiB,mBAAoB,YAAa;AACxD,cAAK,gBAAgB,QAAQ,SAAS,QAAS;AAC9C;AAAA,UACD;AAEA,gBAAM,aAAa,mBAAoB,QAAS;AAChD,gBAAM;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,GAAG;AAAA,UACJ,IAAI,WAAW,OAAO,UAAU,CAAC;AAEjC,cAAK,eAAe,YAAY,cAAc,SAAU;AACvD,kBAAM,0BACL,OAAO,KAAM,MAAO,EAAE,WAAW;AAElC,oBAAS,QAAS,IAAI;AAAA,cACrB;AAAA,cACA,CAAE,SAAS,QAAS;AAAA,cACpB,0BAA0B,SAAY;AAAA,YACvC;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD,OAAO;AAGN,UAAK,8BAA8B,MAAO;AACzC,mBAAY,YAAY,YAAa;AACpC,gBAAM,aAAa,mBAAoB,QAAS;AAChD,gBAAM,EAAE,aAAa,UAAU,GAAG,OAAO,IACxC,WAAW,OAAO,UAAU,CAAC;AAE9B,cAAK,eAAe,UAAW;AAC9B,kBAAM,0BACL,OAAO,KAAM,MAAO,EAAE,WAAW;AAElC,oBAAS,QAAS,IAAI;AAAA,cACrB;AAAA,cACA,CAAE,SAAS,QAAS;AAAA,cACpB,0BAA0B,SAAY;AAAA,YACvC;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAGA,UAAK,WAAW,UAAW;AAC1B,gBAAS,YAAa,IAAI;AAAA,UACzB,QAAQ;AAAA,YACP,GAAG;AAAA,YACH,UAAU;AAAA,UACX;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,QAAK,OAAO,KAAM,OAAQ,EAAE,QAAS;AACpC,8CAAwC;AACxC;AAAA,QACC,OAAO,KAAM,OAAQ;AAAA,QACrB;AAAA;AAAA,QACqB;AAAA,MACtB;AAAA,IACD;AAAA,EACD,GAAG;AAAA;AAAA,IAEF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAE;AACH;AAUA,SAAS,WACR,eACA,iBACA,iBACA,cACA,cAAc,GACd,WAAW,GACV;AACD,WAAU,MAAM,YAAY,OAAQ;AACnC,aACK,SAAS,QAAQ,WAAW,cAAc,GAC9C,UAAU,iBACV,UACC;AACD,YAAM,gBAAgB,IAAI,SAAU;AAAA,QACnC,aAAa;AAAA,QACb,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,SAAS;AAAA,MACV,CAAE;AACF,UACC,CAAE,cAAc;AAAA,QAAM,CAAE,MACvB,EAAE,eAAgB,aAAc;AAAA,MACjC,GACC;AACD,eAAO,CAAE,QAAQ,GAAI;AAAA,MACtB;AAAA,IACD;AAAA,EACD;AACD;", "names": ["getBlockAttributes"] }