123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- // Utilities
- import { capitalize, inject, provide, ref, watchEffect } from 'vue';
- import { consoleError, propsFactory } from "../../../util/index.mjs"; // Types
- export const makeDataTableHeaderProps = propsFactory({
- headers: Array
- }, 'DataTable-header');
- export const VDataTableHeadersSymbol = Symbol.for('vuetify:data-table-headers');
- const defaultHeader = {
- title: '',
- sortable: false
- };
- const defaultActionHeader = {
- ...defaultHeader,
- width: 48
- };
- function priorityQueue() {
- let arr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
- const queue = arr.map(element => ({
- element,
- priority: 0
- }));
- return {
- enqueue: (element, priority) => {
- let added = false;
- for (let i = 0; i < queue.length; i++) {
- const item = queue[i];
- if (item.priority > priority) {
- queue.splice(i, 0, {
- element,
- priority
- });
- added = true;
- break;
- }
- }
- if (!added) queue.push({
- element,
- priority
- });
- },
- size: () => queue.length,
- count: () => {
- let count = 0;
- if (!queue.length) return 0;
- const whole = Math.floor(queue[0].priority);
- for (let i = 0; i < queue.length; i++) {
- if (Math.floor(queue[i].priority) === whole) count += 1;
- }
- return count;
- },
- dequeue: () => {
- return queue.shift();
- }
- };
- }
- function extractLeaves(item) {
- let columns = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
- if (!item.children) {
- columns.push(item);
- } else {
- for (const child of item.children) {
- extractLeaves(child, columns);
- }
- }
- return columns;
- }
- function extractKeys(headers) {
- let keys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Set();
- for (const item of headers) {
- if (item.key) keys.add(item.key);
- if (item.children) {
- extractKeys(item.children, keys);
- }
- }
- return keys;
- }
- function getDefaultItem(item) {
- if (!item.key) return undefined;
- if (item.key === 'data-table-group') return defaultHeader;
- if (['data-table-expand', 'data-table-select'].includes(item.key)) return defaultActionHeader;
- return undefined;
- }
- function getDepth(item) {
- let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- if (!item.children) return depth;
- return Math.max(depth, ...item.children.map(child => getDepth(child, depth + 1)));
- }
- function parseFixedColumns(items) {
- let seenFixed = false;
- function setFixed(item) {
- let parentFixed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- if (!item) return;
- if (parentFixed) {
- item.fixed = true;
- }
- if (item.fixed) {
- if (item.children) {
- for (let i = item.children.length - 1; i >= 0; i--) {
- setFixed(item.children[i], true);
- }
- } else {
- if (!seenFixed) {
- item.lastFixed = true;
- } else if (isNaN(+item.width)) {
- consoleError(`Multiple fixed columns should have a static width (key: ${item.key})`);
- }
- seenFixed = true;
- }
- } else {
- if (item.children) {
- for (let i = item.children.length - 1; i >= 0; i--) {
- setFixed(item.children[i]);
- }
- } else {
- seenFixed = false;
- }
- }
- }
- for (let i = items.length - 1; i >= 0; i--) {
- setFixed(items[i]);
- }
- function setFixedOffset(item) {
- let fixedOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- if (!item) return fixedOffset;
- if (item.children) {
- item.fixedOffset = fixedOffset;
- for (const child of item.children) {
- fixedOffset = setFixedOffset(child, fixedOffset);
- }
- } else if (item.fixed) {
- item.fixedOffset = fixedOffset;
- fixedOffset += parseFloat(item.width || '0') || 0;
- }
- return fixedOffset;
- }
- let fixedOffset = 0;
- for (const item of items) {
- fixedOffset = setFixedOffset(item, fixedOffset);
- }
- }
- function parse(items, maxDepth) {
- const headers = [];
- let currentDepth = 0;
- const queue = priorityQueue(items);
- while (queue.size() > 0) {
- let rowSize = queue.count();
- const row = [];
- let fraction = 1;
- while (rowSize > 0) {
- const {
- element: item,
- priority
- } = queue.dequeue();
- const diff = maxDepth - currentDepth - getDepth(item);
- row.push({
- ...item,
- rowspan: diff ?? 1,
- colspan: item.children ? extractLeaves(item).length : 1
- });
- if (item.children) {
- for (const child of item.children) {
- // This internally sorts items that are on the same priority "row"
- const sort = priority % 1 + fraction / Math.pow(10, currentDepth + 2);
- queue.enqueue(child, currentDepth + diff + sort);
- }
- }
- fraction += 1;
- rowSize -= 1;
- }
- currentDepth += 1;
- headers.push(row);
- }
- const columns = items.map(item => extractLeaves(item)).flat();
- return {
- columns,
- headers
- };
- }
- function convertToInternalHeaders(items) {
- const internalHeaders = [];
- for (const item of items) {
- const defaultItem = {
- ...getDefaultItem(item),
- ...item
- };
- const key = defaultItem.key ?? (typeof defaultItem.value === 'string' ? defaultItem.value : null);
- const value = defaultItem.value ?? key ?? null;
- const internalItem = {
- ...defaultItem,
- key,
- value,
- sortable: defaultItem.sortable ?? (defaultItem.key != null || !!defaultItem.sort),
- children: defaultItem.children ? convertToInternalHeaders(defaultItem.children) : undefined
- };
- internalHeaders.push(internalItem);
- }
- return internalHeaders;
- }
- export function createHeaders(props, options) {
- const headers = ref([]);
- const columns = ref([]);
- const sortFunctions = ref({});
- const sortRawFunctions = ref({});
- const filterFunctions = ref({});
- watchEffect(() => {
- const _headers = props.headers || Object.keys(props.items[0] ?? {}).map(key => ({
- key,
- title: capitalize(key)
- }));
- const items = _headers.slice();
- const keys = extractKeys(items);
- if (options?.groupBy?.value.length && !keys.has('data-table-group')) {
- items.unshift({
- key: 'data-table-group',
- title: 'Group'
- });
- }
- if (options?.showSelect?.value && !keys.has('data-table-select')) {
- items.unshift({
- key: 'data-table-select'
- });
- }
- if (options?.showExpand?.value && !keys.has('data-table-expand')) {
- items.push({
- key: 'data-table-expand'
- });
- }
- const internalHeaders = convertToInternalHeaders(items);
- parseFixedColumns(internalHeaders);
- const maxDepth = Math.max(...internalHeaders.map(item => getDepth(item))) + 1;
- const parsed = parse(internalHeaders, maxDepth);
- headers.value = parsed.headers;
- columns.value = parsed.columns;
- const flatHeaders = parsed.headers.flat(1);
- for (const header of flatHeaders) {
- if (!header.key) continue;
- if (header.sortable) {
- if (header.sort) {
- sortFunctions.value[header.key] = header.sort;
- }
- if (header.sortRaw) {
- sortRawFunctions.value[header.key] = header.sortRaw;
- }
- }
- if (header.filter) {
- filterFunctions.value[header.key] = header.filter;
- }
- }
- });
- const data = {
- headers,
- columns,
- sortFunctions,
- sortRawFunctions,
- filterFunctions
- };
- provide(VDataTableHeadersSymbol, data);
- return data;
- }
- export function useHeaders() {
- const data = inject(VDataTableHeadersSymbol);
- if (!data) throw new Error('Missing headers!');
- return data;
- }
- //# sourceMappingURL=headers.mjs.map
|