@humanspeak/svelte-headless-table
Version:
A powerful, headless table library for Svelte that provides complete control over table UI while handling complex data operations like sorting, filtering, pagination, grouping, and row expansion. Build custom, accessible data tables with zero styling opin
97 lines (96 loc) • 3.3 kB
JavaScript
import { derived, get } from 'svelte/store';
import { isReadable } from '../utils/store.js';
/**
* Converts rows to an array of plain objects.
* @internal
*/
const getObjectsFromRows = (rows, ids, childrenKey) => {
return rows.map((row) => {
const dataObject = Object.fromEntries(ids.map((id) => {
const cell = row.cellForId[id];
if (cell.isData()) {
return [id, cell.value];
}
if (cell.isDisplay() && cell.column.data !== undefined) {
let data = cell.column.data(cell, row.state);
if (isReadable(data)) {
data = get(data);
}
return [id, data];
}
return [id, null];
}));
if (row.subRows !== undefined) {
dataObject[childrenKey] = getObjectsFromRows(row.subRows, ids, childrenKey);
}
return dataObject;
});
};
/**
* Converts rows to CSV format.
* @internal
*/
const getCsvFromRows = (rows, ids) => {
const dataLines = rows.map((row) => {
const line = ids.map((id) => {
const cell = row.cellForId[id];
if (cell.isData()) {
return cell.value;
}
if (cell.isDisplay() && cell.column.data !== undefined) {
let data = cell.column.data(cell, row.state);
if (isReadable(data)) {
data = get(data);
}
return data;
}
return null;
});
return line.join(',');
});
const headerLine = ids.join(',');
return headerLine + '\n' + dataLines.join('\n');
};
/**
* Creates a data export plugin that provides reactive exports of table data.
* Supports exporting to objects, JSON, or CSV formats.
*
* @template Item - The type of data items in the table.
* @template F - The export format type.
* @param config - Configuration options.
* @returns A TablePlugin that provides data export functionality.
* @example
* ```typescript
* const table = createTable(data, {
* export: addDataExport({
* format: 'csv',
* childrenKey: 'subItems'
* })
* })
*
* // Access exported data
* const { exportedData } = table.pluginStates.export
* $: csvData = $exportedData
* ```
*/
export const addDataExport = ({ format = 'object', childrenKey = 'children' } = {}) => ({ tableState, columnOptions }) => {
const excludedIds = Object.entries(columnOptions)
.filter(([, option]) => option.exclude === true)
.map(([columnId]) => columnId);
const { visibleColumns, rows } = tableState;
const exportedIds = derived(visibleColumns, ($visibleColumns) => $visibleColumns.map((c) => c.id).filter((id) => !excludedIds.includes(id)));
const exportedData = derived([rows, exportedIds], ([$rows, $exportedIds]) => {
switch (format) {
case 'json':
return JSON.stringify(getObjectsFromRows($rows, $exportedIds, childrenKey));
case 'csv':
return getCsvFromRows($rows, $exportedIds);
default:
return getObjectsFromRows($rows, $exportedIds, childrenKey);
}
});
const pluginState = { exportedData };
return {
pluginState
};
};