UNPKG

@tanstack/table-core

Version:

Headless UI for building powerful tables & datagrids for TS/JS.

271 lines (252 loc) 12.2 kB
/** * table-core * * Copyright (c) TanStack * * This source code is licensed under the MIT license found in the * LICENSE.md file in the root directory of this source tree. * * @license MIT */ 'use strict'; var utils = require('../utils.js'); const debug = 'debugHeaders'; // function createHeader(table, column, options) { var _options$id; const id = (_options$id = options.id) != null ? _options$id : column.id; let header = { id, column, index: options.index, isPlaceholder: !!options.isPlaceholder, placeholderId: options.placeholderId, depth: options.depth, subHeaders: [], colSpan: 0, rowSpan: 0, headerGroup: null, getLeafHeaders: () => { const leafHeaders = []; const recurseHeader = h => { if (h.subHeaders && h.subHeaders.length) { h.subHeaders.map(recurseHeader); } leafHeaders.push(h); }; recurseHeader(header); return leafHeaders; }, getContext: () => ({ table, header: header, column }) }; table._features.forEach(feature => { feature.createHeader == null || feature.createHeader(header, table); }); return header; } const Headers = { createTable: table => { // Header Groups table.getHeaderGroups = utils.memo(() => [table.getAllColumns(), table.getVisibleLeafColumns(), table.getState().columnPinning.left, table.getState().columnPinning.right], (allColumns, leafColumns, left, right) => { var _left$map$filter, _right$map$filter; const leftColumns = (_left$map$filter = left == null ? void 0 : left.map(columnId => leafColumns.find(d => d.id === columnId)).filter(Boolean)) != null ? _left$map$filter : []; const rightColumns = (_right$map$filter = right == null ? void 0 : right.map(columnId => leafColumns.find(d => d.id === columnId)).filter(Boolean)) != null ? _right$map$filter : []; const centerColumns = leafColumns.filter(column => !(left != null && left.includes(column.id)) && !(right != null && right.includes(column.id))); const headerGroups = buildHeaderGroups(allColumns, [...leftColumns, ...centerColumns, ...rightColumns], table); return headerGroups; }, utils.getMemoOptions(table.options, debug, 'getHeaderGroups')); table.getCenterHeaderGroups = utils.memo(() => [table.getAllColumns(), table.getVisibleLeafColumns(), table.getState().columnPinning.left, table.getState().columnPinning.right], (allColumns, leafColumns, left, right) => { leafColumns = leafColumns.filter(column => !(left != null && left.includes(column.id)) && !(right != null && right.includes(column.id))); return buildHeaderGroups(allColumns, leafColumns, table, 'center'); }, utils.getMemoOptions(table.options, debug, 'getCenterHeaderGroups')); table.getLeftHeaderGroups = utils.memo(() => [table.getAllColumns(), table.getVisibleLeafColumns(), table.getState().columnPinning.left], (allColumns, leafColumns, left) => { var _left$map$filter2; const orderedLeafColumns = (_left$map$filter2 = left == null ? void 0 : left.map(columnId => leafColumns.find(d => d.id === columnId)).filter(Boolean)) != null ? _left$map$filter2 : []; return buildHeaderGroups(allColumns, orderedLeafColumns, table, 'left'); }, utils.getMemoOptions(table.options, debug, 'getLeftHeaderGroups')); table.getRightHeaderGroups = utils.memo(() => [table.getAllColumns(), table.getVisibleLeafColumns(), table.getState().columnPinning.right], (allColumns, leafColumns, right) => { var _right$map$filter2; const orderedLeafColumns = (_right$map$filter2 = right == null ? void 0 : right.map(columnId => leafColumns.find(d => d.id === columnId)).filter(Boolean)) != null ? _right$map$filter2 : []; return buildHeaderGroups(allColumns, orderedLeafColumns, table, 'right'); }, utils.getMemoOptions(table.options, debug, 'getRightHeaderGroups')); // Footer Groups table.getFooterGroups = utils.memo(() => [table.getHeaderGroups()], headerGroups => { return [...headerGroups].reverse(); }, utils.getMemoOptions(table.options, debug, 'getFooterGroups')); table.getLeftFooterGroups = utils.memo(() => [table.getLeftHeaderGroups()], headerGroups => { return [...headerGroups].reverse(); }, utils.getMemoOptions(table.options, debug, 'getLeftFooterGroups')); table.getCenterFooterGroups = utils.memo(() => [table.getCenterHeaderGroups()], headerGroups => { return [...headerGroups].reverse(); }, utils.getMemoOptions(table.options, debug, 'getCenterFooterGroups')); table.getRightFooterGroups = utils.memo(() => [table.getRightHeaderGroups()], headerGroups => { return [...headerGroups].reverse(); }, utils.getMemoOptions(table.options, debug, 'getRightFooterGroups')); // Flat Headers table.getFlatHeaders = utils.memo(() => [table.getHeaderGroups()], headerGroups => { return headerGroups.map(headerGroup => { return headerGroup.headers; }).flat(); }, utils.getMemoOptions(table.options, debug, 'getFlatHeaders')); table.getLeftFlatHeaders = utils.memo(() => [table.getLeftHeaderGroups()], left => { return left.map(headerGroup => { return headerGroup.headers; }).flat(); }, utils.getMemoOptions(table.options, debug, 'getLeftFlatHeaders')); table.getCenterFlatHeaders = utils.memo(() => [table.getCenterHeaderGroups()], left => { return left.map(headerGroup => { return headerGroup.headers; }).flat(); }, utils.getMemoOptions(table.options, debug, 'getCenterFlatHeaders')); table.getRightFlatHeaders = utils.memo(() => [table.getRightHeaderGroups()], left => { return left.map(headerGroup => { return headerGroup.headers; }).flat(); }, utils.getMemoOptions(table.options, debug, 'getRightFlatHeaders')); // Leaf Headers table.getCenterLeafHeaders = utils.memo(() => [table.getCenterFlatHeaders()], flatHeaders => { return flatHeaders.filter(header => { var _header$subHeaders; return !((_header$subHeaders = header.subHeaders) != null && _header$subHeaders.length); }); }, utils.getMemoOptions(table.options, debug, 'getCenterLeafHeaders')); table.getLeftLeafHeaders = utils.memo(() => [table.getLeftFlatHeaders()], flatHeaders => { return flatHeaders.filter(header => { var _header$subHeaders2; return !((_header$subHeaders2 = header.subHeaders) != null && _header$subHeaders2.length); }); }, utils.getMemoOptions(table.options, debug, 'getLeftLeafHeaders')); table.getRightLeafHeaders = utils.memo(() => [table.getRightFlatHeaders()], flatHeaders => { return flatHeaders.filter(header => { var _header$subHeaders3; return !((_header$subHeaders3 = header.subHeaders) != null && _header$subHeaders3.length); }); }, utils.getMemoOptions(table.options, debug, 'getRightLeafHeaders')); table.getLeafHeaders = utils.memo(() => [table.getLeftHeaderGroups(), table.getCenterHeaderGroups(), table.getRightHeaderGroups()], (left, center, right) => { var _left$0$headers, _left$, _center$0$headers, _center$, _right$0$headers, _right$; return [...((_left$0$headers = (_left$ = left[0]) == null ? void 0 : _left$.headers) != null ? _left$0$headers : []), ...((_center$0$headers = (_center$ = center[0]) == null ? void 0 : _center$.headers) != null ? _center$0$headers : []), ...((_right$0$headers = (_right$ = right[0]) == null ? void 0 : _right$.headers) != null ? _right$0$headers : [])].map(header => { return header.getLeafHeaders(); }).flat(); }, utils.getMemoOptions(table.options, debug, 'getLeafHeaders')); } }; function buildHeaderGroups(allColumns, columnsToGroup, table, headerFamily) { var _headerGroups$0$heade, _headerGroups$; // Find the max depth of the columns: // build the leaf column row // build each buffer row going up // placeholder for non-existent level // real column for existing level let maxDepth = 0; const findMaxDepth = function (columns, depth) { if (depth === void 0) { depth = 1; } maxDepth = Math.max(maxDepth, depth); columns.filter(column => column.getIsVisible()).forEach(column => { var _column$columns; if ((_column$columns = column.columns) != null && _column$columns.length) { findMaxDepth(column.columns, depth + 1); } }, 0); }; findMaxDepth(allColumns); let headerGroups = []; const createHeaderGroup = (headersToGroup, depth) => { // The header group we are creating const headerGroup = { depth, id: [headerFamily, `${depth}`].filter(Boolean).join('_'), headers: [] }; // The parent columns we're going to scan next const pendingParentHeaders = []; // Scan each column for parents headersToGroup.forEach(headerToGroup => { // What is the latest (last) parent column? const latestPendingParentHeader = [...pendingParentHeaders].reverse()[0]; const isLeafHeader = headerToGroup.column.depth === headerGroup.depth; let column; let isPlaceholder = false; if (isLeafHeader && headerToGroup.column.parent) { // The parent header is new column = headerToGroup.column.parent; } else { // The parent header is repeated column = headerToGroup.column; isPlaceholder = true; } if (latestPendingParentHeader && (latestPendingParentHeader == null ? void 0 : latestPendingParentHeader.column) === column) { // This column is repeated. Add it as a sub header to the next batch latestPendingParentHeader.subHeaders.push(headerToGroup); } else { // This is a new header. Let's create it const header = createHeader(table, column, { id: [headerFamily, depth, column.id, headerToGroup == null ? void 0 : headerToGroup.id].filter(Boolean).join('_'), isPlaceholder, placeholderId: isPlaceholder ? `${pendingParentHeaders.filter(d => d.column === column).length}` : undefined, depth, index: pendingParentHeaders.length }); // Add the headerToGroup as a subHeader of the new header header.subHeaders.push(headerToGroup); // Add the new header to the pendingParentHeaders to get grouped // in the next batch pendingParentHeaders.push(header); } headerGroup.headers.push(headerToGroup); headerToGroup.headerGroup = headerGroup; }); headerGroups.push(headerGroup); if (depth > 0) { createHeaderGroup(pendingParentHeaders, depth - 1); } }; const bottomHeaders = columnsToGroup.map((column, index) => createHeader(table, column, { depth: maxDepth, index })); createHeaderGroup(bottomHeaders, maxDepth - 1); headerGroups.reverse(); // headerGroups = headerGroups.filter(headerGroup => { // return !headerGroup.headers.every(header => header.isPlaceholder) // }) const recurseHeadersForSpans = headers => { const filteredHeaders = headers.filter(header => header.column.getIsVisible()); return filteredHeaders.map(header => { let colSpan = 0; let rowSpan = 0; let childRowSpans = [0]; if (header.subHeaders && header.subHeaders.length) { childRowSpans = []; recurseHeadersForSpans(header.subHeaders).forEach(_ref => { let { colSpan: childColSpan, rowSpan: childRowSpan } = _ref; colSpan += childColSpan; childRowSpans.push(childRowSpan); }); } else { colSpan = 1; } const minChildRowSpan = Math.min(...childRowSpans); rowSpan = rowSpan + minChildRowSpan; header.colSpan = colSpan; header.rowSpan = rowSpan; return { colSpan, rowSpan }; }); }; recurseHeadersForSpans((_headerGroups$0$heade = (_headerGroups$ = headerGroups[0]) == null ? void 0 : _headerGroups$.headers) != null ? _headerGroups$0$heade : []); return headerGroups; } exports.Headers = Headers; exports.buildHeaderGroups = buildHeaderGroups; //# sourceMappingURL=headers.js.map