UNPKG

@wordpress/block-library

Version:
8 lines (7 loc) 14.6 kB
{ "version": 3, "sources": ["../../src/table/state.js"], "sourcesContent": ["const INHERITED_COLUMN_ATTRIBUTES = [ 'align' ];\n\n/**\n * Creates a table state.\n *\n * @param {Object} options\n * @param {number} options.rowCount Row count for the table to create.\n * @param {number} options.columnCount Column count for the table to create.\n *\n * @return {Object} New table state.\n */\nexport function createTable( { rowCount, columnCount } ) {\n\treturn {\n\t\tbody: Array.from( { length: rowCount } ).map( () => ( {\n\t\t\tcells: Array.from( { length: columnCount } ).map( () => ( {\n\t\t\t\tcontent: '',\n\t\t\t\ttag: 'td',\n\t\t\t} ) ),\n\t\t} ) ),\n\t};\n}\n\n/**\n * Returns the first row in the table.\n *\n * @param {Object} state Current table state.\n *\n * @return {Object | undefined} The first table row.\n */\nexport function getFirstRow( state ) {\n\tif ( ! isEmptyTableSection( state.head ) ) {\n\t\treturn state.head[ 0 ];\n\t}\n\tif ( ! isEmptyTableSection( state.body ) ) {\n\t\treturn state.body[ 0 ];\n\t}\n\tif ( ! isEmptyTableSection( state.foot ) ) {\n\t\treturn state.foot[ 0 ];\n\t}\n}\n\n/**\n * Gets an attribute for a cell.\n *\n * @param {Object} state Current table state.\n * @param {Object} cellLocation The location of the cell\n * @param {string} attributeName The name of the attribute to get the value of.\n *\n * @return {*} The attribute value.\n */\nexport function getCellAttribute( state, cellLocation, attributeName ) {\n\tconst { sectionName, rowIndex, columnIndex } = cellLocation;\n\treturn state[ sectionName ]?.[ rowIndex ]?.cells?.[ columnIndex ]?.[\n\t\tattributeName\n\t];\n}\n\n/**\n * Returns updated cell attributes after applying the `updateCell` function to the selection.\n *\n * @param {Object} state The block attributes.\n * @param {Object} selection The selection of cells to update.\n * @param {Function} updateCell A function to update the selected cell attributes.\n *\n * @return {Object} New table state including the updated cells.\n */\nexport function updateSelectedCell( state, selection, updateCell ) {\n\tif ( ! selection ) {\n\t\treturn state;\n\t}\n\n\tconst tableSections = Object.fromEntries(\n\t\tObject.entries( state ).filter( ( [ key ] ) =>\n\t\t\t[ 'head', 'body', 'foot' ].includes( key )\n\t\t)\n\t);\n\tconst { sectionName: selectionSectionName, rowIndex: selectionRowIndex } =\n\t\tselection;\n\n\treturn Object.fromEntries(\n\t\tObject.entries( tableSections ).map( ( [ sectionName, section ] ) => {\n\t\t\tif (\n\t\t\t\tselectionSectionName &&\n\t\t\t\tselectionSectionName !== sectionName\n\t\t\t) {\n\t\t\t\treturn [ sectionName, section ];\n\t\t\t}\n\n\t\t\treturn [\n\t\t\t\tsectionName,\n\t\t\t\tsection.map( ( row, rowIndex ) => {\n\t\t\t\t\tif ( selectionRowIndex && selectionRowIndex !== rowIndex ) {\n\t\t\t\t\t\treturn row;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcells: row.cells.map(\n\t\t\t\t\t\t\t( cellAttributes, columnIndex ) => {\n\t\t\t\t\t\t\t\tconst cellLocation = {\n\t\t\t\t\t\t\t\t\tsectionName,\n\t\t\t\t\t\t\t\t\tcolumnIndex,\n\t\t\t\t\t\t\t\t\trowIndex,\n\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t! isCellSelected( cellLocation, selection )\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\treturn cellAttributes;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn updateCell( cellAttributes );\n\t\t\t\t\t\t\t}\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} )\n\t);\n}\n\n/**\n * Returns whether the cell at `cellLocation` is included in the selection `selection`.\n *\n * @param {Object} cellLocation An object containing cell location properties.\n * @param {Object} selection An object containing selection properties.\n *\n * @return {boolean} True if the cell is selected, false otherwise.\n */\nexport function isCellSelected( cellLocation, selection ) {\n\tif ( ! cellLocation || ! selection ) {\n\t\treturn false;\n\t}\n\n\tswitch ( selection.type ) {\n\t\tcase 'column':\n\t\t\treturn (\n\t\t\t\tselection.type === 'column' &&\n\t\t\t\tcellLocation.columnIndex === selection.columnIndex\n\t\t\t);\n\t\tcase 'cell':\n\t\t\treturn (\n\t\t\t\tselection.type === 'cell' &&\n\t\t\t\tcellLocation.sectionName === selection.sectionName &&\n\t\t\t\tcellLocation.columnIndex === selection.columnIndex &&\n\t\t\t\tcellLocation.rowIndex === selection.rowIndex\n\t\t\t);\n\t}\n}\n\n/**\n * Inserts a row in the table state.\n *\n * @param {Object} state Current table state.\n * @param {Object} options\n * @param {string} options.sectionName Section in which to insert the row.\n * @param {number} options.rowIndex Row index at which to insert the row.\n * @param {number} options.columnCount Column count for the table to create.\n *\n * @return {Object} New table state.\n */\nexport function insertRow( state, { sectionName, rowIndex, columnCount } ) {\n\tconst firstRow = getFirstRow( state );\n\tconst cellCount =\n\t\tcolumnCount === undefined ? firstRow?.cells?.length : columnCount;\n\n\t// Bail early if the function cannot determine how many cells to add.\n\tif ( ! cellCount ) {\n\t\treturn state;\n\t}\n\n\treturn {\n\t\t[ sectionName ]: [\n\t\t\t...state[ sectionName ].slice( 0, rowIndex ),\n\t\t\t{\n\t\t\t\tcells: Array.from( { length: cellCount } ).map(\n\t\t\t\t\t( _, index ) => {\n\t\t\t\t\t\tconst firstCellInColumn =\n\t\t\t\t\t\t\tfirstRow?.cells?.[ index ] ?? {};\n\n\t\t\t\t\t\tconst inheritedAttributes = Object.fromEntries(\n\t\t\t\t\t\t\tObject.entries( firstCellInColumn ).filter(\n\t\t\t\t\t\t\t\t( [ key ] ) =>\n\t\t\t\t\t\t\t\t\tINHERITED_COLUMN_ATTRIBUTES.includes( key )\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...inheritedAttributes,\n\t\t\t\t\t\t\tcontent: '',\n\t\t\t\t\t\t\ttag: sectionName === 'head' ? 'th' : 'td',\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\t...state[ sectionName ].slice( rowIndex ),\n\t\t],\n\t};\n}\n\n/**\n * Deletes a row from the table state.\n *\n * @param {Object} state Current table state.\n * @param {Object} options\n * @param {string} options.sectionName Section in which to delete the row.\n * @param {number} options.rowIndex Row index to delete.\n *\n * @return {Object} New table state.\n */\nexport function deleteRow( state, { sectionName, rowIndex } ) {\n\treturn {\n\t\t[ sectionName ]: state[ sectionName ].filter(\n\t\t\t( row, index ) => index !== rowIndex\n\t\t),\n\t};\n}\n\n/**\n * Inserts a column in the table state.\n *\n * @param {Object} state Current table state.\n * @param {Object} options\n * @param {number} options.columnIndex Column index at which to insert the column.\n *\n * @return {Object} New table state.\n */\nexport function insertColumn( state, { columnIndex } ) {\n\tconst tableSections = Object.fromEntries(\n\t\tObject.entries( state ).filter( ( [ key ] ) =>\n\t\t\t[ 'head', 'body', 'foot' ].includes( key )\n\t\t)\n\t);\n\n\treturn Object.fromEntries(\n\t\tObject.entries( tableSections ).map( ( [ sectionName, section ] ) => {\n\t\t\t// Bail early if the table section is empty.\n\t\t\tif ( isEmptyTableSection( section ) ) {\n\t\t\t\treturn [ sectionName, section ];\n\t\t\t}\n\n\t\t\treturn [\n\t\t\t\tsectionName,\n\t\t\t\tsection.map( ( row ) => {\n\t\t\t\t\t// Bail early if the row is empty or it's an attempt to insert past\n\t\t\t\t\t// the last possible index of the array.\n\t\t\t\t\tif ( isEmptyRow( row ) || row.cells.length < columnIndex ) {\n\t\t\t\t\t\treturn row;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcells: [\n\t\t\t\t\t\t\t...row.cells.slice( 0, columnIndex ),\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcontent: '',\n\t\t\t\t\t\t\t\ttag: sectionName === 'head' ? 'th' : 'td',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t...row.cells.slice( columnIndex ),\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} )\n\t);\n}\n\n/**\n * Deletes a column from the table state.\n *\n * @param {Object} state Current table state.\n * @param {Object} options\n * @param {number} options.columnIndex Column index to delete.\n *\n * @return {Object} New table state.\n */\nexport function deleteColumn( state, { columnIndex } ) {\n\tconst tableSections = Object.fromEntries(\n\t\tObject.entries( state ).filter( ( [ key ] ) =>\n\t\t\t[ 'head', 'body', 'foot' ].includes( key )\n\t\t)\n\t);\n\n\treturn Object.fromEntries(\n\t\tObject.entries( tableSections ).map( ( [ sectionName, section ] ) => {\n\t\t\t// Bail early if the table section is empty.\n\t\t\tif ( isEmptyTableSection( section ) ) {\n\t\t\t\treturn [ sectionName, section ];\n\t\t\t}\n\n\t\t\treturn [\n\t\t\t\tsectionName,\n\t\t\t\tsection\n\t\t\t\t\t.map( ( row ) => ( {\n\t\t\t\t\t\tcells:\n\t\t\t\t\t\t\trow.cells.length >= columnIndex\n\t\t\t\t\t\t\t\t? row.cells.filter(\n\t\t\t\t\t\t\t\t\t\t( cell, index ) => index !== columnIndex\n\t\t\t\t\t\t\t\t )\n\t\t\t\t\t\t\t\t: row.cells,\n\t\t\t\t\t} ) )\n\t\t\t\t\t.filter( ( row ) => row.cells.length ),\n\t\t\t];\n\t\t} )\n\t);\n}\n\n/**\n * Toggles the existence of a section.\n *\n * @param {Object} state Current table state.\n * @param {string} sectionName Name of the section to toggle.\n *\n * @return {Object} New table state.\n */\nexport function toggleSection( state, sectionName ) {\n\t// Section exists, replace it with an empty row to remove it.\n\tif ( ! isEmptyTableSection( state[ sectionName ] ) ) {\n\t\treturn { [ sectionName ]: [] };\n\t}\n\n\t// Get the length of the first row of the body to use when creating the header.\n\tconst columnCount = state.body?.[ 0 ]?.cells?.length ?? 1;\n\n\t// Section doesn't exist, insert an empty row to create the section.\n\treturn insertRow( state, { sectionName, rowIndex: 0, columnCount } );\n}\n\n/**\n * Determines whether a table section is empty.\n *\n * @param {Object} section Table section state.\n *\n * @return {boolean} True if the table section is empty, false otherwise.\n */\nexport function isEmptyTableSection( section ) {\n\treturn ! section || ! section.length || section.every( isEmptyRow );\n}\n\n/**\n * Determines whether a table row is empty.\n *\n * @param {Object} row Table row state.\n *\n * @return {boolean} True if the table section is empty, false otherwise.\n */\nexport function isEmptyRow( row ) {\n\treturn ! ( row.cells && row.cells.length );\n}\n"], "mappings": "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", "names": [] }