@humanspeak/svelte-headless-table 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +122 -0
  3. package/dist/bodyCells.d.ts +53 -0
  4. package/dist/bodyCells.js +90 -0
  5. package/dist/bodyRows.d.ts +82 -0
  6. package/dist/bodyRows.js +256 -0
  7. package/dist/columns.d.ts +76 -0
  8. package/dist/columns.js +96 -0
  9. package/dist/constants.d.ts +1 -0
  10. package/dist/constants.js +1 -0
  11. package/dist/createTable.d.ts +17 -0
  12. package/dist/createTable.js +36 -0
  13. package/dist/createViewModel.d.ts +38 -0
  14. package/dist/createViewModel.js +230 -0
  15. package/dist/headerCells.d.ts +80 -0
  16. package/dist/headerCells.js +147 -0
  17. package/dist/headerRows.d.ts +35 -0
  18. package/dist/headerRows.js +185 -0
  19. package/dist/index.d.ts +11 -0
  20. package/dist/index.js +12 -0
  21. package/dist/plugins/addColumnFilters.d.ts +39 -0
  22. package/dist/plugins/addColumnFilters.js +117 -0
  23. package/dist/plugins/addColumnOrder.d.ts +10 -0
  24. package/dist/plugins/addColumnOrder.js +24 -0
  25. package/dist/plugins/addDataExport.d.ts +21 -0
  26. package/dist/plugins/addDataExport.js +68 -0
  27. package/dist/plugins/addExpandedRows.d.ts +17 -0
  28. package/dist/plugins/addExpandedRows.js +51 -0
  29. package/dist/plugins/addFlatten.d.ts +19 -0
  30. package/dist/plugins/addFlatten.js +38 -0
  31. package/dist/plugins/addGridLayout.d.ts +2 -0
  32. package/dist/plugins/addGridLayout.js +73 -0
  33. package/dist/plugins/addGroupBy.d.ts +40 -0
  34. package/dist/plugins/addGroupBy.js +192 -0
  35. package/dist/plugins/addHiddenColumns.d.ts +9 -0
  36. package/dist/plugins/addHiddenColumns.js +17 -0
  37. package/dist/plugins/addPagination.d.ts +39 -0
  38. package/dist/plugins/addPagination.js +84 -0
  39. package/dist/plugins/addResizedColumns.d.ts +41 -0
  40. package/dist/plugins/addResizedColumns.js +252 -0
  41. package/dist/plugins/addSelectedRows.d.ts +29 -0
  42. package/dist/plugins/addSelectedRows.js +190 -0
  43. package/dist/plugins/addSortBy.d.ts +46 -0
  44. package/dist/plugins/addSortBy.js +176 -0
  45. package/dist/plugins/addSubRows.d.ts +9 -0
  46. package/dist/plugins/addSubRows.js +28 -0
  47. package/dist/plugins/addTableFilter.d.ts +28 -0
  48. package/dist/plugins/addTableFilter.js +95 -0
  49. package/dist/plugins/index.d.ts +15 -0
  50. package/dist/plugins/index.js +16 -0
  51. package/dist/plugins/package.json +5 -0
  52. package/dist/tableComponent.d.ts +19 -0
  53. package/dist/tableComponent.js +35 -0
  54. package/dist/types/Action.d.ts +5 -0
  55. package/dist/types/Action.js +1 -0
  56. package/dist/types/Entries.d.ts +3 -0
  57. package/dist/types/Entries.js +1 -0
  58. package/dist/types/KeyPath.d.ts +6 -0
  59. package/dist/types/KeyPath.js +1 -0
  60. package/dist/types/Label.d.ts +8 -0
  61. package/dist/types/Label.js +1 -0
  62. package/dist/types/Matrix.d.ts +1 -0
  63. package/dist/types/Matrix.js +1 -0
  64. package/dist/types/TablePlugin.d.ts +88 -0
  65. package/dist/types/TablePlugin.js +1 -0
  66. package/dist/utils/array.d.ts +2 -0
  67. package/dist/utils/array.js +9 -0
  68. package/dist/utils/attributes.d.ts +2 -0
  69. package/dist/utils/attributes.js +23 -0
  70. package/dist/utils/clone.d.ts +13 -0
  71. package/dist/utils/clone.js +18 -0
  72. package/dist/utils/compare.d.ts +2 -0
  73. package/dist/utils/compare.js +17 -0
  74. package/dist/utils/counter.d.ts +1 -0
  75. package/dist/utils/counter.js +7 -0
  76. package/dist/utils/css.d.ts +1 -0
  77. package/dist/utils/css.js +5 -0
  78. package/dist/utils/event.d.ts +1 -0
  79. package/dist/utils/event.js +5 -0
  80. package/dist/utils/filter.d.ts +4 -0
  81. package/dist/utils/filter.js +4 -0
  82. package/dist/utils/math.d.ts +2 -0
  83. package/dist/utils/math.js +2 -0
  84. package/dist/utils/matrix.d.ts +3 -0
  85. package/dist/utils/matrix.js +23 -0
  86. package/dist/utils/store.d.ts +37 -0
  87. package/dist/utils/store.js +123 -0
  88. package/package.json +98 -0
@@ -0,0 +1,76 @@
1
+ import type { DisplayBodyCell } from './bodyCells.js';
2
+ import type { TableState } from './createViewModel.js';
3
+ import type { DisplayLabel, HeaderLabel } from './types/Label.js';
4
+ import type { DataLabel } from './types/Label.js';
5
+ import type { AnyPlugins, PluginColumnConfigs } from './types/TablePlugin.js';
6
+ export interface ColumnInit<Item, Plugins extends AnyPlugins = AnyPlugins> {
7
+ header: HeaderLabel<Item, Plugins>;
8
+ footer?: HeaderLabel<Item, Plugins>;
9
+ height: number;
10
+ plugins?: PluginColumnConfigs<Plugins>;
11
+ }
12
+ export declare class Column<Item, Plugins extends AnyPlugins = AnyPlugins> {
13
+ header: HeaderLabel<Item, Plugins>;
14
+ footer?: HeaderLabel<Item, Plugins>;
15
+ height: number;
16
+ plugins?: PluginColumnConfigs<Plugins>;
17
+ constructor({ header, footer, height, plugins }: ColumnInit<Item, Plugins>);
18
+ isFlat(): this is FlatColumn<Item, Plugins>;
19
+ isData(): this is DataColumn<Item, Plugins>;
20
+ isDisplay(): this is DisplayColumn<Item, Plugins>;
21
+ isGroup(): this is GroupColumn<Item, Plugins>;
22
+ }
23
+ export type FlatColumnInit<Item, Plugins extends AnyPlugins = AnyPlugins, Id extends string = any> = Omit<ColumnInit<Item, Plugins>, 'height'> & {
24
+ id?: Id;
25
+ };
26
+ export declare class FlatColumn<Item, Plugins extends AnyPlugins = AnyPlugins, Id extends string = any> extends Column<Item, Plugins> {
27
+ __flat: boolean;
28
+ id: Id;
29
+ constructor({ header, footer, plugins, id }: FlatColumnInit<Item, Plugins>);
30
+ }
31
+ export type DataColumnInit<Item, Plugins extends AnyPlugins = AnyPlugins, Id extends string = string, Value = unknown> = DataColumnInitBase<Item, Plugins, Value> & ((Id extends keyof Item ? DataColumnInitKey<Item, Id> : never) | DataColumnInitIdAndKey<Item, Id, keyof Item> | DataColumnInitFnAndId<Item, Id, Value>);
32
+ export type DataColumnInitBase<Item, Plugins extends AnyPlugins = AnyPlugins, Value = unknown> = Omit<ColumnInit<Item, Plugins>, 'height'> & {
33
+ cell?: DataLabel<Item, Plugins, Value>;
34
+ };
35
+ export type DataColumnInitKey<Item, Id extends keyof Item> = {
36
+ accessor: Id;
37
+ id?: Id;
38
+ };
39
+ export type DataColumnInitIdAndKey<Item, Id extends string, Key extends keyof Item> = {
40
+ accessor: Key;
41
+ id?: Id;
42
+ };
43
+ export type DataColumnInitFnAndId<Item, Id extends string, Value> = {
44
+ accessor: keyof Item | ((item: Item) => Value);
45
+ id?: Id;
46
+ };
47
+ export declare class DataColumn<Item, Plugins extends AnyPlugins = AnyPlugins, Id extends string = any, Value = any> extends FlatColumn<Item, Plugins, Id> {
48
+ __data: boolean;
49
+ cell?: DataLabel<Item, Plugins, Value>;
50
+ accessorKey?: keyof Item;
51
+ accessorFn?: (item: Item) => Value;
52
+ constructor({ header, footer, plugins, cell, accessor, id }: DataColumnInit<Item, Plugins, Id, Value>);
53
+ getValue(item: Item): any;
54
+ }
55
+ export type DisplayColumnDataGetter<Item, Plugins extends AnyPlugins = AnyPlugins> = (cell: DisplayBodyCell<Item>, state?: TableState<Item, Plugins>) => unknown;
56
+ export type DisplayColumnInit<Item, Plugins extends AnyPlugins = AnyPlugins, Id extends string = any> = FlatColumnInit<Item, Plugins, Id> & {
57
+ cell: DisplayLabel<Item, Plugins>;
58
+ data?: DisplayColumnDataGetter<Item, Plugins>;
59
+ };
60
+ export declare class DisplayColumn<Item, Plugins extends AnyPlugins = AnyPlugins, Id extends string = any> extends FlatColumn<Item, Plugins, Id> {
61
+ __display: boolean;
62
+ cell: DisplayLabel<Item, Plugins>;
63
+ data?: DisplayColumnDataGetter<Item, Plugins>;
64
+ constructor({ header, footer, plugins, id, cell, data }: DisplayColumnInit<Item, Plugins, Id>);
65
+ }
66
+ export type GroupColumnInit<Item, Plugins extends AnyPlugins = AnyPlugins> = Omit<ColumnInit<Item, Plugins>, 'height'> & {
67
+ columns: Column<Item, Plugins>[];
68
+ };
69
+ export declare class GroupColumn<Item, Plugins extends AnyPlugins = AnyPlugins> extends Column<Item, Plugins> {
70
+ __group: boolean;
71
+ columns: Column<Item, Plugins>[];
72
+ ids: string[];
73
+ constructor({ header, footer, columns, plugins }: GroupColumnInit<Item, Plugins>);
74
+ }
75
+ export declare const getFlatColumnIds: <Item, Plugins extends AnyPlugins = AnyPlugins>(columns: Column<Item, Plugins>[]) => string[];
76
+ export declare const getFlatColumns: <Item, Plugins extends AnyPlugins = AnyPlugins>(columns: Column<Item, Plugins>[]) => FlatColumn<Item, Plugins>[];
@@ -0,0 +1,96 @@
1
+ export class Column {
2
+ header;
3
+ footer;
4
+ height;
5
+ plugins;
6
+ constructor({ header, footer, height, plugins }) {
7
+ this.header = header;
8
+ this.footer = footer;
9
+ this.height = height;
10
+ this.plugins = plugins;
11
+ }
12
+ // TODO Workaround for https://github.com/vitejs/vite/issues/9528
13
+ isFlat() {
14
+ return '__flat' in this;
15
+ }
16
+ // TODO Workaround for https://github.com/vitejs/vite/issues/9528
17
+ isData() {
18
+ return '__data' in this;
19
+ }
20
+ // TODO Workaround for https://github.com/vitejs/vite/issues/9528
21
+ isDisplay() {
22
+ return '__display' in this;
23
+ }
24
+ // TODO Workaround for https://github.com/vitejs/vite/issues/9528
25
+ isGroup() {
26
+ return '__group' in this;
27
+ }
28
+ }
29
+ export class FlatColumn extends Column {
30
+ // TODO Workaround for https://github.com/vitejs/vite/issues/9528
31
+ __flat = true;
32
+ id;
33
+ constructor({ header, footer, plugins, id }) {
34
+ super({ header, footer, plugins, height: 1 });
35
+ this.id = id ?? String(header);
36
+ }
37
+ }
38
+ export class DataColumn extends FlatColumn {
39
+ // TODO Workaround for https://github.com/vitejs/vite/issues/9528
40
+ __data = true;
41
+ cell;
42
+ accessorKey;
43
+ accessorFn;
44
+ constructor({ header, footer, plugins, cell, accessor, id }) {
45
+ super({ header, footer, plugins, id: 'Initialization not complete' });
46
+ this.cell = cell;
47
+ if (accessor instanceof Function) {
48
+ this.accessorFn = accessor;
49
+ }
50
+ else {
51
+ this.accessorKey = accessor;
52
+ }
53
+ if (id === undefined && this.accessorKey === undefined && header === undefined) {
54
+ throw new Error('A column id, string accessor, or header is required');
55
+ }
56
+ const accessorKeyId = typeof this.accessorKey === 'string' ? this.accessorKey : null;
57
+ this.id = (id ?? accessorKeyId ?? String(header));
58
+ }
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+ getValue(item) {
61
+ if (this.accessorFn !== undefined) {
62
+ return this.accessorFn(item);
63
+ }
64
+ if (this.accessorKey !== undefined) {
65
+ return item[this.accessorKey];
66
+ }
67
+ return undefined;
68
+ }
69
+ }
70
+ export class DisplayColumn extends FlatColumn {
71
+ // TODO Workaround for https://github.com/vitejs/vite/issues/9528
72
+ __display = true;
73
+ cell;
74
+ data;
75
+ constructor({ header, footer, plugins, id, cell, data }) {
76
+ super({ header, footer, plugins, id });
77
+ this.cell = cell;
78
+ this.data = data;
79
+ }
80
+ }
81
+ export class GroupColumn extends Column {
82
+ // TODO Workaround for https://github.com/vitejs/vite/issues/9528
83
+ __group = true;
84
+ columns;
85
+ ids;
86
+ constructor({ header, footer, columns, plugins }) {
87
+ const height = Math.max(...columns.map((c) => c.height)) + 1;
88
+ super({ header, footer, height, plugins });
89
+ this.columns = columns;
90
+ this.ids = getFlatColumnIds(columns);
91
+ }
92
+ }
93
+ export const getFlatColumnIds = (columns) => columns.flatMap((c) => (c.isFlat() ? [c.id] : c.isGroup() ? c.ids : []));
94
+ export const getFlatColumns = (columns) => {
95
+ return columns.flatMap((c) => (c.isFlat() ? [c] : c.isGroup() ? getFlatColumns(c.columns) : []));
96
+ };
@@ -0,0 +1 @@
1
+ export declare const NBSP = " ";
@@ -0,0 +1 @@
1
+ export const NBSP = ' ';
@@ -0,0 +1,17 @@
1
+ import { DataColumn, DisplayColumn, GroupColumn, type Column, type DataColumnInitBase, type DataColumnInitFnAndId, type DataColumnInitIdAndKey, type DataColumnInitKey, type DisplayColumnInit, type GroupColumnInit } from './columns.js';
2
+ import type { AnyPlugins } from './types/TablePlugin.js';
3
+ import type { ReadOrWritable } from './utils/store.js';
4
+ import { type CreateViewModelOptions, type TableViewModel } from './createViewModel.js';
5
+ export declare class Table<Item, Plugins extends AnyPlugins = AnyPlugins> {
6
+ data: ReadOrWritable<Item[]>;
7
+ plugins: Plugins;
8
+ constructor(data: ReadOrWritable<Item[]>, plugins: Plugins);
9
+ createColumns(columns: Column<Item, Plugins>[]): Column<Item, Plugins>[];
10
+ column<Id extends Exclude<keyof Item, symbol>>(def: DataColumnInitBase<Item, Plugins, Item[Id]> & DataColumnInitKey<Item, Id>): DataColumn<Item, Plugins, `${Id}`, Item[Id]>;
11
+ column<Id extends string, Key extends keyof Item>(def: DataColumnInitBase<Item, Plugins, Item[Key]> & DataColumnInitIdAndKey<Item, Id, Key>): DataColumn<Item, Plugins, Id, Item[Key]>;
12
+ column<Id extends string, Value>(def: DataColumnInitBase<Item, Plugins, Value> & DataColumnInitFnAndId<Item, Id, Value>): DataColumn<Item, Plugins, Id, Value>;
13
+ group(def: GroupColumnInit<Item, Plugins>): GroupColumn<Item, Plugins>;
14
+ display(def: DisplayColumnInit<Item, Plugins>): DisplayColumn<Item, Plugins>;
15
+ createViewModel(columns: Column<Item, Plugins>[], options?: CreateViewModelOptions<Item>): TableViewModel<Item, Plugins>;
16
+ }
17
+ export declare const createTable: <Item, Plugins extends AnyPlugins = AnyPlugins>(data: ReadOrWritable<Item[]>, plugins?: Plugins) => Table<Item, Plugins>;
@@ -0,0 +1,36 @@
1
+ import { DataColumn, DisplayColumn, getFlatColumnIds, GroupColumn } from './columns.js';
2
+ import { getDuplicates } from './utils/array.js';
3
+ import { createViewModel } from './createViewModel.js';
4
+ export class Table {
5
+ data;
6
+ plugins;
7
+ constructor(data, plugins) {
8
+ this.data = data;
9
+ this.plugins = plugins;
10
+ }
11
+ createColumns(columns) {
12
+ const ids = getFlatColumnIds(columns);
13
+ const duplicateIds = getDuplicates(ids);
14
+ if (duplicateIds.length !== 0) {
15
+ throw new Error(`Duplicate column ids not allowed: "${duplicateIds.join('", "')}"`);
16
+ }
17
+ return columns;
18
+ }
19
+ column(def) {
20
+ return new DataColumn(def);
21
+ }
22
+ group(def) {
23
+ return new GroupColumn(def);
24
+ }
25
+ display(def) {
26
+ return new DisplayColumn(def);
27
+ }
28
+ createViewModel(columns, options) {
29
+ return createViewModel(this, columns, options);
30
+ }
31
+ }
32
+ export const createTable = (data,
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ plugins = {}) => {
35
+ return new Table(data, plugins);
36
+ };
@@ -0,0 +1,38 @@
1
+ import { type Readable, type Writable } from 'svelte/store';
2
+ import { BodyRow } from './bodyRows.js';
3
+ import { FlatColumn, type Column } from './columns.js';
4
+ import type { Table } from './createTable.js';
5
+ import { HeaderRow } from './headerRows.js';
6
+ import type { AnyPlugins, PluginStates } from './types/TablePlugin.js';
7
+ export type TableAttributes<Item, Plugins extends AnyPlugins = AnyPlugins> = Record<string, unknown> & {
8
+ role: 'table';
9
+ };
10
+ export type TableHeadAttributes<Item, Plugins extends AnyPlugins = AnyPlugins> = Record<string, unknown>;
11
+ export type TableBodyAttributes<Item, Plugins extends AnyPlugins = AnyPlugins> = Record<string, unknown> & {
12
+ role: 'rowgroup';
13
+ };
14
+ export interface TableViewModel<Item, Plugins extends AnyPlugins = AnyPlugins> {
15
+ flatColumns: FlatColumn<Item, Plugins>[];
16
+ tableAttrs: Readable<TableAttributes<Item, Plugins>>;
17
+ tableHeadAttrs: Readable<TableHeadAttributes<Item, Plugins>>;
18
+ tableBodyAttrs: Readable<TableBodyAttributes<Item, Plugins>>;
19
+ visibleColumns: Readable<FlatColumn<Item, Plugins>[]>;
20
+ headerRows: Readable<HeaderRow<Item, Plugins>[]>;
21
+ originalRows: Readable<BodyRow<Item, Plugins>[]>;
22
+ rows: Readable<BodyRow<Item, Plugins>[]>;
23
+ pageRows: Readable<BodyRow<Item, Plugins>[]>;
24
+ pluginStates: PluginStates<Plugins>;
25
+ }
26
+ export type ReadOrWritable<T> = Readable<T> | Writable<T>;
27
+ export interface PluginInitTableState<Item, Plugins extends AnyPlugins = AnyPlugins> extends Omit<TableViewModel<Item, Plugins>, 'pluginStates'> {
28
+ data: ReadOrWritable<Item[]>;
29
+ columns: Column<Item, Plugins>[];
30
+ }
31
+ export interface TableState<Item, Plugins extends AnyPlugins = AnyPlugins> extends TableViewModel<Item, Plugins> {
32
+ data: ReadOrWritable<Item[]>;
33
+ columns: Column<Item, Plugins>[];
34
+ }
35
+ export interface CreateViewModelOptions<Item> {
36
+ rowDataId?: (item: Item, index: number) => string;
37
+ }
38
+ export declare const createViewModel: <Item, Plugins extends AnyPlugins = AnyPlugins>(table: Table<Item, Plugins>, columns: Column<Item, Plugins>[], { rowDataId }?: CreateViewModelOptions<Item>) => TableViewModel<Item, Plugins>;
@@ -0,0 +1,230 @@
1
+ import { derived, readable, writable } from 'svelte/store';
2
+ import { BodyRow, getBodyRows, getColumnedBodyRows } from './bodyRows.js';
3
+ import { FlatColumn, getFlatColumns } from './columns.js';
4
+ import { getHeaderRows, HeaderRow } from './headerRows.js';
5
+ import { finalizeAttributes } from './utils/attributes.js';
6
+ import { nonUndefined } from './utils/filter.js';
7
+ export const createViewModel = (table, columns, { rowDataId } = {}) => {
8
+ const { data, plugins } = table;
9
+ const $flatColumns = getFlatColumns(columns);
10
+ const flatColumns = readable($flatColumns);
11
+ const originalRows = derived([data, flatColumns], ([$data, $flatColumns]) => {
12
+ return getBodyRows($data, $flatColumns, { rowDataId });
13
+ });
14
+ // _stores need to be defined first to pass into plugins for initialization.
15
+ const _visibleColumns = writable([]);
16
+ const _headerRows = writable();
17
+ const _rows = writable([]);
18
+ const _pageRows = writable([]);
19
+ const _tableAttrs = writable({
20
+ role: 'table'
21
+ });
22
+ const _tableHeadAttrs = writable({});
23
+ const _tableBodyAttrs = writable({
24
+ role: 'rowgroup'
25
+ });
26
+ const pluginInitTableState = {
27
+ data,
28
+ columns,
29
+ flatColumns: $flatColumns,
30
+ tableAttrs: _tableAttrs,
31
+ tableHeadAttrs: _tableHeadAttrs,
32
+ tableBodyAttrs: _tableBodyAttrs,
33
+ visibleColumns: _visibleColumns,
34
+ headerRows: _headerRows,
35
+ originalRows,
36
+ rows: _rows,
37
+ pageRows: _pageRows
38
+ };
39
+ const pluginInstances = Object.fromEntries(Object.entries(plugins).map(([pluginName, plugin]) => {
40
+ const columnOptions = Object.fromEntries($flatColumns
41
+ .map((c) => {
42
+ const option = c.plugins?.[pluginName];
43
+ if (option === undefined)
44
+ return undefined;
45
+ return [c.id, option];
46
+ })
47
+ .filter(nonUndefined));
48
+ return [
49
+ pluginName,
50
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
+ plugin({ pluginName, tableState: pluginInitTableState, columnOptions })
52
+ ];
53
+ }));
54
+ const pluginStates = Object.fromEntries(Object.entries(pluginInstances).map(([key, pluginInstance]) => [
55
+ key,
56
+ pluginInstance.pluginState
57
+ ]));
58
+ const tableState = {
59
+ data,
60
+ columns,
61
+ flatColumns: $flatColumns,
62
+ tableAttrs: _tableAttrs,
63
+ tableHeadAttrs: _tableHeadAttrs,
64
+ tableBodyAttrs: _tableBodyAttrs,
65
+ visibleColumns: _visibleColumns,
66
+ headerRows: _headerRows,
67
+ originalRows,
68
+ rows: _rows,
69
+ pageRows: _pageRows,
70
+ pluginStates
71
+ };
72
+ const deriveTableAttrsFns = Object.values(pluginInstances)
73
+ .map((pluginInstance) => pluginInstance.deriveTableAttrs)
74
+ .filter(nonUndefined);
75
+ let tableAttrs = readable({
76
+ role: 'table'
77
+ });
78
+ deriveTableAttrsFns.forEach((fn) => {
79
+ tableAttrs = fn(tableAttrs);
80
+ });
81
+ const finalizedTableAttrs = derived(tableAttrs, ($tableAttrs) => {
82
+ const $finalizedAttrs = finalizeAttributes($tableAttrs);
83
+ _tableAttrs.set($finalizedAttrs);
84
+ return $finalizedAttrs;
85
+ });
86
+ const deriveTableHeadAttrsFns = Object.values(pluginInstances)
87
+ .map((pluginInstance) => pluginInstance.deriveTableBodyAttrs)
88
+ .filter(nonUndefined);
89
+ let tableHeadAttrs = readable({});
90
+ deriveTableHeadAttrsFns.forEach((fn) => {
91
+ tableHeadAttrs = fn(tableHeadAttrs);
92
+ });
93
+ const finalizedTableHeadAttrs = derived(tableHeadAttrs, ($tableHeadAttrs) => {
94
+ const $finalizedAttrs = finalizeAttributes($tableHeadAttrs);
95
+ _tableHeadAttrs.set($finalizedAttrs);
96
+ return $finalizedAttrs;
97
+ });
98
+ const deriveTableBodyAttrsFns = Object.values(pluginInstances)
99
+ .map((pluginInstance) => pluginInstance.deriveTableBodyAttrs)
100
+ .filter(nonUndefined);
101
+ let tableBodyAttrs = readable({
102
+ role: 'rowgroup'
103
+ });
104
+ deriveTableBodyAttrsFns.forEach((fn) => {
105
+ tableBodyAttrs = fn(tableBodyAttrs);
106
+ });
107
+ const finalizedTableBodyAttrs = derived(tableBodyAttrs, ($tableBodyAttrs) => {
108
+ const $finalizedAttrs = finalizeAttributes($tableBodyAttrs);
109
+ _tableBodyAttrs.set($finalizedAttrs);
110
+ return $finalizedAttrs;
111
+ });
112
+ const deriveFlatColumnsFns = Object.values(pluginInstances)
113
+ .map((pluginInstance) => pluginInstance.deriveFlatColumns)
114
+ .filter(nonUndefined);
115
+ let visibleColumns = flatColumns;
116
+ deriveFlatColumnsFns.forEach((fn) => {
117
+ // Variance of generic type here is unstable. Not sure how to fix.
118
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
+ visibleColumns = fn(visibleColumns);
120
+ });
121
+ const injectedColumns = derived(visibleColumns, ($visibleColumns) => {
122
+ _visibleColumns.set($visibleColumns);
123
+ return $visibleColumns;
124
+ });
125
+ const columnedRows = derived([originalRows, injectedColumns], ([$originalRows, $injectedColumns]) => {
126
+ return getColumnedBodyRows($originalRows, $injectedColumns.map((c) => c.id));
127
+ });
128
+ const deriveRowsFns = Object.values(pluginInstances)
129
+ .map((pluginInstance) => pluginInstance.deriveRows)
130
+ .filter(nonUndefined);
131
+ let rows = columnedRows;
132
+ deriveRowsFns.forEach((fn) => {
133
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
134
+ rows = fn(rows);
135
+ });
136
+ const injectedRows = derived(rows, ($rows) => {
137
+ // Inject state.
138
+ $rows.forEach((row) => {
139
+ row.injectState(tableState);
140
+ row.cells.forEach((cell) => {
141
+ cell.injectState(tableState);
142
+ });
143
+ });
144
+ // Apply plugin component hooks.
145
+ Object.entries(pluginInstances).forEach(([pluginName, pluginInstance]) => {
146
+ $rows.forEach((row) => {
147
+ if (pluginInstance.hooks?.['tbody.tr'] !== undefined) {
148
+ row.applyHook(pluginName, pluginInstance.hooks['tbody.tr'](row));
149
+ }
150
+ row.cells.forEach((cell) => {
151
+ if (pluginInstance.hooks?.['tbody.tr.td'] !== undefined) {
152
+ cell.applyHook(pluginName, pluginInstance.hooks['tbody.tr.td'](cell));
153
+ }
154
+ });
155
+ });
156
+ });
157
+ _rows.set($rows);
158
+ return $rows;
159
+ });
160
+ const derivePageRowsFns = Object.values(pluginInstances)
161
+ .map((pluginInstance) => pluginInstance.derivePageRows)
162
+ .filter(nonUndefined);
163
+ // Must derive from `injectedRows` instead of `rows` to ensure that `_rows` is set.
164
+ let pageRows = injectedRows;
165
+ derivePageRowsFns.forEach((fn) => {
166
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
167
+ pageRows = fn(pageRows);
168
+ });
169
+ const injectedPageRows = derived(pageRows, ($pageRows) => {
170
+ // Inject state.
171
+ $pageRows.forEach((row) => {
172
+ row.injectState(tableState);
173
+ row.cells.forEach((cell) => {
174
+ cell.injectState(tableState);
175
+ });
176
+ });
177
+ // Apply plugin component hooks.
178
+ Object.entries(pluginInstances).forEach(([pluginName, pluginInstance]) => {
179
+ $pageRows.forEach((row) => {
180
+ if (pluginInstance.hooks?.['tbody.tr'] !== undefined) {
181
+ row.applyHook(pluginName, pluginInstance.hooks['tbody.tr'](row));
182
+ }
183
+ row.cells.forEach((cell) => {
184
+ if (pluginInstance.hooks?.['tbody.tr.td'] !== undefined) {
185
+ cell.applyHook(pluginName, pluginInstance.hooks['tbody.tr.td'](cell));
186
+ }
187
+ });
188
+ });
189
+ });
190
+ _pageRows.set($pageRows);
191
+ return $pageRows;
192
+ });
193
+ const headerRows = derived(injectedColumns, ($injectedColumns) => {
194
+ const $headerRows = getHeaderRows(columns, $injectedColumns.map((c) => c.id));
195
+ // Inject state.
196
+ $headerRows.forEach((row) => {
197
+ row.injectState(tableState);
198
+ row.cells.forEach((cell) => {
199
+ cell.injectState(tableState);
200
+ });
201
+ });
202
+ // Apply plugin component hooks.
203
+ Object.entries(pluginInstances).forEach(([pluginName, pluginInstance]) => {
204
+ $headerRows.forEach((row) => {
205
+ if (pluginInstance.hooks?.['thead.tr'] !== undefined) {
206
+ row.applyHook(pluginName, pluginInstance.hooks['thead.tr'](row));
207
+ }
208
+ row.cells.forEach((cell) => {
209
+ if (pluginInstance.hooks?.['thead.tr.th'] !== undefined) {
210
+ cell.applyHook(pluginName, pluginInstance.hooks['thead.tr.th'](cell));
211
+ }
212
+ });
213
+ });
214
+ });
215
+ _headerRows.set($headerRows);
216
+ return $headerRows;
217
+ });
218
+ return {
219
+ tableAttrs: finalizedTableAttrs,
220
+ tableHeadAttrs: finalizedTableHeadAttrs,
221
+ tableBodyAttrs: finalizedTableBodyAttrs,
222
+ visibleColumns: injectedColumns,
223
+ flatColumns: $flatColumns,
224
+ headerRows,
225
+ originalRows,
226
+ rows: injectedRows,
227
+ pageRows: injectedPageRows,
228
+ pluginStates
229
+ };
230
+ };
@@ -0,0 +1,80 @@
1
+ import { TableComponent } from './tableComponent.js';
2
+ import type { HeaderLabel } from './types/Label.js';
3
+ import type { AnyPlugins } from './types/TablePlugin.js';
4
+ import type { RenderConfig } from '@humanspeak/svelte-subscribe';
5
+ export type HeaderCellInit<Item, Plugins extends AnyPlugins = AnyPlugins> = {
6
+ id: string;
7
+ label: HeaderLabel<Item, Plugins>;
8
+ colspan: number;
9
+ colstart: number;
10
+ };
11
+ export type HeaderCellAttributes<Item, Plugins extends AnyPlugins = AnyPlugins> = {
12
+ role: 'columnheader';
13
+ colspan: number;
14
+ };
15
+ export declare abstract class HeaderCell<Item, Plugins extends AnyPlugins = AnyPlugins> extends TableComponent<Item, Plugins, 'thead.tr.th'> {
16
+ label: HeaderLabel<Item, Plugins>;
17
+ colspan: number;
18
+ colstart: number;
19
+ constructor({ id, label, colspan, colstart }: HeaderCellInit<Item, Plugins>);
20
+ render(): RenderConfig;
21
+ attrs(): import("svelte/store").Readable<{
22
+ role: "columnheader";
23
+ colspan: number;
24
+ }>;
25
+ abstract clone(): HeaderCell<Item, Plugins>;
26
+ isFlat(): this is FlatHeaderCell<Item, Plugins>;
27
+ isData(): this is DataHeaderCell<Item, Plugins>;
28
+ isFlatDisplay(): this is FlatDisplayHeaderCell<Item, Plugins>;
29
+ isGroup(): this is GroupHeaderCell<Item, Plugins>;
30
+ isGroupDisplay(): this is GroupDisplayHeaderCell<Item, Plugins>;
31
+ }
32
+ export type FlatHeaderCellInit<Item, Plugins extends AnyPlugins = AnyPlugins> = Omit<HeaderCellInit<Item, Plugins>, 'colspan'>;
33
+ export type FlatHeaderCellAttributes<Item, Plugins extends AnyPlugins = AnyPlugins> = HeaderCellAttributes<Item, Plugins>;
34
+ export declare class FlatHeaderCell<Item, Plugins extends AnyPlugins = AnyPlugins> extends HeaderCell<Item, Plugins> {
35
+ __flat: boolean;
36
+ constructor({ id, label, colstart }: FlatHeaderCellInit<Item, Plugins>);
37
+ clone(): FlatHeaderCell<Item, Plugins>;
38
+ }
39
+ export type DataHeaderCellInit<Item, Plugins extends AnyPlugins = AnyPlugins> = FlatHeaderCellInit<Item, Plugins> & {
40
+ accessorKey?: keyof Item;
41
+ accessorFn?: (item: Item) => unknown;
42
+ };
43
+ export declare class DataHeaderCell<Item, Plugins extends AnyPlugins = AnyPlugins> extends FlatHeaderCell<Item, Plugins> {
44
+ __data: boolean;
45
+ accessorKey?: keyof Item;
46
+ accessorFn?: (item: Item) => unknown;
47
+ constructor({ id, label, accessorKey, accessorFn, colstart }: DataHeaderCellInit<Item, Plugins>);
48
+ clone(): DataHeaderCell<Item, Plugins>;
49
+ }
50
+ export type FlatDisplayHeaderCellInit<Item, Plugins extends AnyPlugins = AnyPlugins> = Omit<FlatHeaderCellInit<Item, Plugins>, 'label'> & {
51
+ label?: HeaderLabel<Item, Plugins>;
52
+ };
53
+ export declare class FlatDisplayHeaderCell<Item, Plugins extends AnyPlugins = AnyPlugins> extends FlatHeaderCell<Item, Plugins> {
54
+ __display: boolean;
55
+ constructor({ id, label, colstart }: FlatDisplayHeaderCellInit<Item, Plugins>);
56
+ clone(): FlatDisplayHeaderCell<Item, Plugins>;
57
+ }
58
+ export type GroupHeaderCellInit<Item, Plugins extends AnyPlugins = AnyPlugins> = Omit<HeaderCellInit<Item, Plugins>, 'id'> & {
59
+ ids: string[];
60
+ allIds: string[];
61
+ };
62
+ export declare class GroupHeaderCell<Item, Plugins extends AnyPlugins = AnyPlugins> extends HeaderCell<Item, Plugins> {
63
+ __group: boolean;
64
+ ids: string[];
65
+ allId: string;
66
+ allIds: string[];
67
+ constructor({ label, ids, allIds, colspan, colstart }: GroupHeaderCellInit<Item, Plugins>);
68
+ setIds(ids: string[]): void;
69
+ pushId(id: string): void;
70
+ clone(): GroupHeaderCell<Item, Plugins>;
71
+ }
72
+ export type GroupDisplayHeaderCellInit<Item, Plugins extends AnyPlugins = AnyPlugins> = Omit<GroupHeaderCellInit<Item, Plugins>, 'label' | 'colspan'> & {
73
+ label?: HeaderLabel<Item, Plugins>;
74
+ colspan?: number;
75
+ };
76
+ export declare class GroupDisplayHeaderCell<Item, Plugins extends AnyPlugins = AnyPlugins> extends GroupHeaderCell<Item, Plugins> {
77
+ __display: boolean;
78
+ constructor({ label, ids, allIds, colspan, colstart }: GroupDisplayHeaderCellInit<Item, Plugins>);
79
+ clone(): GroupDisplayHeaderCell<Item, Plugins>;
80
+ }