@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,17 @@
1
+ import type { BodyRow } from '../bodyRows.js';
2
+ import type { NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
3
+ import { type RecordSetStore } from '../utils/store.js';
4
+ import { type Readable, type Writable } from 'svelte/store';
5
+ export interface ExpandedRowsConfig<Item> {
6
+ initialExpandedIds?: Record<string, boolean>;
7
+ }
8
+ export interface ExpandedRowsState<Item> {
9
+ expandedIds: RecordSetStore<string>;
10
+ getRowState: (row: BodyRow<Item>) => ExpandedRowsRowState;
11
+ }
12
+ export interface ExpandedRowsRowState {
13
+ isExpanded: Writable<boolean>;
14
+ canExpand: Readable<boolean>;
15
+ isAllSubRowsExpanded: Readable<boolean>;
16
+ }
17
+ export declare const addExpandedRows: <Item>({ initialExpandedIds }?: ExpandedRowsConfig<Item>) => TablePlugin<Item, ExpandedRowsState<Item>, Record<string, never>, NewTablePropSet<never>>;
@@ -0,0 +1,51 @@
1
+ import { recordSetStore } from '../utils/store.js';
2
+ import { keyed } from '@humanspeak/svelte-keyed';
3
+ import { derived, readable } from 'svelte/store';
4
+ const withExpandedRows = (row, expandedIds) => {
5
+ if (row.subRows === undefined) {
6
+ return [row];
7
+ }
8
+ if (expandedIds[row.id] !== true) {
9
+ return [row];
10
+ }
11
+ const expandedSubRows = row.subRows.flatMap((subRow) => withExpandedRows(subRow, expandedIds));
12
+ return [row, ...expandedSubRows];
13
+ };
14
+ export const addExpandedRows = ({ initialExpandedIds = {} } = {}) => () => {
15
+ const expandedIds = recordSetStore(initialExpandedIds);
16
+ const getRowState = (row) => {
17
+ const isExpanded = keyed(expandedIds, row.id);
18
+ const canExpand = readable((row.subRows?.length ?? 0) > 0);
19
+ const subRowExpandedIds = derived(expandedIds, ($expandedIds) => {
20
+ // Check prefix with '>' to match child ids while ignoring this row's id.
21
+ return Object.entries($expandedIds).filter(([id, expanded]) => id.startsWith(`${row.id}>`) && expanded);
22
+ });
23
+ // If the number of expanded subRows is equal to the number of subRows
24
+ // that can expand, then all subRows are expanded.
25
+ const isAllSubRowsExpanded = derived(subRowExpandedIds, ($subRowExpandedIds) => {
26
+ if (row.subRows === undefined) {
27
+ return true;
28
+ }
29
+ // canExpand is derived from the presence of the `subRows` property.
30
+ const expandableSubRows = row.subRows.filter((subRow) => subRow.subRows !== undefined);
31
+ return $subRowExpandedIds.length === expandableSubRows.length;
32
+ });
33
+ return {
34
+ isExpanded,
35
+ canExpand,
36
+ isAllSubRowsExpanded
37
+ };
38
+ };
39
+ const pluginState = { expandedIds, getRowState };
40
+ const deriveRows = (rows) => {
41
+ return derived([rows, expandedIds], ([$rows, $expandedIds]) => {
42
+ return $rows.flatMap((row) => {
43
+ return withExpandedRows(row, $expandedIds);
44
+ });
45
+ });
46
+ };
47
+ return {
48
+ pluginState,
49
+ deriveRows
50
+ };
51
+ };
@@ -0,0 +1,19 @@
1
+ import type { BodyRow } from '../bodyRows.js';
2
+ import type { NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
3
+ import { type Writable } from 'svelte/store';
4
+ export interface FlattenConfig {
5
+ initialDepth?: number;
6
+ }
7
+ export interface FlattenState {
8
+ depth: Writable<number>;
9
+ }
10
+ export interface FlattenColumnOptions<Item> {
11
+ }
12
+ export type FlattenPropSet = NewTablePropSet<{
13
+ 'tbody.tr.td': {
14
+ flatten: (depth: number) => void;
15
+ unflatten: () => void;
16
+ };
17
+ }>;
18
+ export declare const getFlattenedRows: <Item, Row extends BodyRow<Item>>(rows: Row[], depth: number) => Row[];
19
+ export declare const addFlatten: <Item>({ initialDepth }?: FlattenConfig) => TablePlugin<Item, FlattenState, FlattenColumnOptions<Item>, FlattenPropSet>;
@@ -0,0 +1,38 @@
1
+ import { derived, writable } from 'svelte/store';
2
+ export const getFlattenedRows = (rows, depth) => {
3
+ if (depth === 0)
4
+ return rows;
5
+ const flattenedRows = [];
6
+ for (const row of rows) {
7
+ if (row.subRows === undefined)
8
+ continue;
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ flattenedRows.push(...getFlattenedRows(row.subRows, depth - 1));
11
+ }
12
+ return flattenedRows;
13
+ };
14
+ export const addFlatten = ({ initialDepth = 0 } = {}) => () => {
15
+ const depth = writable(initialDepth);
16
+ const pluginState = { depth };
17
+ const deriveRows = (rows) => {
18
+ return derived([rows, depth], ([$rows, $depth]) => {
19
+ return getFlattenedRows($rows, $depth);
20
+ });
21
+ };
22
+ return {
23
+ pluginState,
24
+ deriveRows,
25
+ hooks: {
26
+ 'tbody.tr.td': () => {
27
+ const props = derived([], () => {
28
+ const flatten = ($depth) => {
29
+ depth.set($depth);
30
+ };
31
+ const unflatten = () => flatten(0);
32
+ return { flatten, unflatten };
33
+ });
34
+ return { props };
35
+ }
36
+ }
37
+ };
38
+ };
@@ -0,0 +1,2 @@
1
+ import type { NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
2
+ export declare const addGridLayout: <Item>() => TablePlugin<Item, Record<string, never>, Record<string, never>, NewTablePropSet<never>>;
@@ -0,0 +1,73 @@
1
+ import { derived } from 'svelte/store';
2
+ export const addGridLayout = () => ({ tableState }) => {
3
+ const pluginState = {};
4
+ const deriveTableAttrs = (attrs) => {
5
+ return derived([attrs, tableState.visibleColumns], ([$attrs, $visibleColumns]) => {
6
+ return {
7
+ ...$attrs,
8
+ style: {
9
+ display: 'grid',
10
+ 'grid-template-columns': `repeat(${$visibleColumns.length}, auto)`
11
+ }
12
+ };
13
+ });
14
+ };
15
+ const deriveTableHeadAttrs = (attrs) => {
16
+ return derived(attrs, ($attrs) => {
17
+ return {
18
+ ...$attrs,
19
+ style: {
20
+ display: 'contents'
21
+ }
22
+ };
23
+ });
24
+ };
25
+ const deriveTableBodyAttrs = (attrs) => {
26
+ return derived(attrs, ($attrs) => {
27
+ return {
28
+ ...$attrs,
29
+ style: {
30
+ display: 'contents'
31
+ }
32
+ };
33
+ });
34
+ };
35
+ return {
36
+ pluginState,
37
+ deriveTableAttrs,
38
+ deriveTableHeadAttrs,
39
+ deriveTableBodyAttrs,
40
+ hooks: {
41
+ 'thead.tr': () => {
42
+ const attrs = derived([], () => {
43
+ return {
44
+ style: {
45
+ display: 'contents'
46
+ }
47
+ };
48
+ });
49
+ return { attrs };
50
+ },
51
+ 'thead.tr.th': (cell) => {
52
+ const attrs = derived([], () => {
53
+ return {
54
+ style: {
55
+ 'grid-column': `${cell.colstart + 1} / span ${cell.colspan}`
56
+ }
57
+ };
58
+ });
59
+ return { attrs };
60
+ },
61
+ 'tbody.tr': () => {
62
+ const attrs = derived([], () => {
63
+ return {
64
+ style: {
65
+ display: 'contents'
66
+ }
67
+ };
68
+ });
69
+ return { attrs };
70
+ }
71
+ }
72
+ };
73
+ };
@@ -0,0 +1,40 @@
1
+ import { BodyRow } from '../bodyRows.js';
2
+ import type { DataLabel } from '../types/Label.js';
3
+ import type { NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
4
+ import { type ArraySetStore } from '../utils/store.js';
5
+ export interface GroupByConfig {
6
+ initialGroupByIds?: string[];
7
+ disableMultiGroup?: boolean;
8
+ isMultiGroupEvent?: (event: Event) => boolean;
9
+ }
10
+ export interface GroupByState {
11
+ groupByIds: ArraySetStore<string>;
12
+ }
13
+ export interface GroupByColumnOptions<Item, Value = any, GroupOn extends string | number = any, Aggregate = any> {
14
+ disable?: boolean;
15
+ getAggregateValue?: (values: GroupOn[]) => Aggregate;
16
+ getGroupOn?: (value: Value) => GroupOn;
17
+ cell?: DataLabel<Item>;
18
+ }
19
+ export type GroupByPropSet = NewTablePropSet<{
20
+ 'thead.tr.th': {
21
+ grouped: boolean;
22
+ toggle: (event: Event) => void;
23
+ clear: () => void;
24
+ disabled: boolean;
25
+ };
26
+ 'tbody.tr.td': {
27
+ repeated: boolean;
28
+ aggregated: boolean;
29
+ grouped: boolean;
30
+ };
31
+ }>;
32
+ interface GetGroupedRowsProps {
33
+ repeatCellIds: Record<string, boolean>;
34
+ aggregateCellIds: Record<string, boolean>;
35
+ groupCellIds: Record<string, boolean>;
36
+ allGroupByIds: string[];
37
+ }
38
+ export declare const getGroupedRows: <Item, Row extends BodyRow<Item>, GroupOn extends string | number = any>(rows: Row[], groupByIds: string[], columnOptions: Record<string, GroupByColumnOptions<Item>>, { repeatCellIds, aggregateCellIds, groupCellIds, allGroupByIds }: GetGroupedRowsProps) => Row[];
39
+ export declare const addGroupBy: <Item>({ initialGroupByIds, disableMultiGroup, isMultiGroupEvent }?: GroupByConfig) => TablePlugin<Item, GroupByState, GroupByColumnOptions<Item>, GroupByPropSet>;
40
+ export {};
@@ -0,0 +1,192 @@
1
+ import { DataBodyCell } from '../bodyCells.js';
2
+ import { BodyRow, DisplayBodyRow } from '../bodyRows.js';
3
+ import { isShiftClick } from '../utils/event.js';
4
+ import { nonUndefined } from '../utils/filter.js';
5
+ import { arraySetStore } from '../utils/store.js';
6
+ import { derived, writable } from 'svelte/store';
7
+ const getIdPrefix = (id) => {
8
+ const prefixTokens = id.split('>').slice(0, -1);
9
+ if (prefixTokens.length === 0) {
10
+ return '';
11
+ }
12
+ return `${prefixTokens.join('>')}>`;
13
+ };
14
+ const getIdLeaf = (id) => {
15
+ const tokens = id.split('>');
16
+ return tokens[tokens.length - 1] ?? '';
17
+ };
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ const deepenIdAndDepth = (row, parentId) => {
20
+ row.id = `${parentId}>${row.id}`;
21
+ row.depth = row.depth + 1;
22
+ row.subRows?.forEach((subRow) => deepenIdAndDepth(subRow, parentId));
23
+ };
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ export const getGroupedRows = (rows, groupByIds, columnOptions, { repeatCellIds, aggregateCellIds, groupCellIds, allGroupByIds }) => {
26
+ if (groupByIds.length === 0) {
27
+ return rows;
28
+ }
29
+ if (rows.length === 0) {
30
+ return rows;
31
+ }
32
+ const idPrefix = getIdPrefix(rows[0].id);
33
+ const [groupById, ...restIds] = groupByIds;
34
+ const subRowsForGroupOnValue = new Map();
35
+ for (const row of rows) {
36
+ const cell = row.cellForId[groupById];
37
+ if (!cell.isData()) {
38
+ break;
39
+ }
40
+ const columnOption = columnOptions[groupById] ?? {};
41
+ const { getGroupOn } = columnOption;
42
+ const groupOnValue = getGroupOn?.(cell.value) ?? cell.value;
43
+ if (typeof groupOnValue === 'function' || typeof groupOnValue === 'object') {
44
+ console.warn(`Missing \`getGroupOn\` column option to aggregate column "${groupById}" with object values`);
45
+ }
46
+ const subRows = subRowsForGroupOnValue.get(groupOnValue) ?? [];
47
+ subRowsForGroupOnValue.set(groupOnValue, [...subRows, row]);
48
+ }
49
+ const groupedRows = [];
50
+ let groupRowIdx = 0;
51
+ for (const [groupOnValue, subRows] of subRowsForGroupOnValue.entries()) {
52
+ // Guaranteed to have at least one subRow.
53
+ const firstRow = subRows[0];
54
+ const groupRow = new DisplayBodyRow({
55
+ id: `${idPrefix}${groupRowIdx++}`,
56
+ // TODO Differentiate data rows and grouped rows.
57
+ depth: firstRow.depth,
58
+ cells: [],
59
+ cellForId: {}
60
+ });
61
+ const groupRowCellForId = Object.fromEntries(Object.entries(firstRow.cellForId).map(([id, cell]) => {
62
+ if (id === groupById) {
63
+ const newCell = new DataBodyCell({
64
+ column: cell.column,
65
+ row: groupRow,
66
+ value: groupOnValue
67
+ });
68
+ return [id, newCell];
69
+ }
70
+ const columnCells = subRows.map((row) => row.cellForId[id]).filter(nonUndefined);
71
+ if (!columnCells[0].isData()) {
72
+ const clonedCell = columnCells[0].clone();
73
+ clonedCell.row = groupRow;
74
+ return [id, clonedCell];
75
+ }
76
+ const { cell: label, getAggregateValue } = columnOptions[id] ?? {};
77
+ const columnValues = columnCells.map((cell) => cell.value);
78
+ const value = getAggregateValue === undefined ? '' : getAggregateValue(columnValues);
79
+ const newCell = new DataBodyCell({
80
+ column: cell.column,
81
+ row: groupRow,
82
+ value,
83
+ label
84
+ });
85
+ return [id, newCell];
86
+ }));
87
+ const groupRowCells = firstRow.cells.map((cell) => {
88
+ return groupRowCellForId[cell.id];
89
+ });
90
+ groupRow.cellForId = groupRowCellForId;
91
+ groupRow.cells = groupRowCells;
92
+ const groupRowSubRows = subRows.map((subRow) => {
93
+ const clonedSubRow = subRow.clone({ includeCells: true, includeSubRows: true });
94
+ deepenIdAndDepth(clonedSubRow, groupRow.id);
95
+ return clonedSubRow;
96
+ });
97
+ groupRow.subRows = getGroupedRows(groupRowSubRows, restIds, columnOptions, {
98
+ repeatCellIds,
99
+ aggregateCellIds,
100
+ groupCellIds,
101
+ allGroupByIds
102
+ });
103
+ groupedRows.push(groupRow);
104
+ groupRow.cells.forEach((cell) => {
105
+ if (cell.id === groupById) {
106
+ groupCellIds[cell.rowColId()] = true;
107
+ }
108
+ else {
109
+ aggregateCellIds[cell.rowColId()] = true;
110
+ }
111
+ });
112
+ groupRow.subRows.forEach((subRow) => {
113
+ subRow.parentRow = groupRow;
114
+ subRow.cells.forEach((cell) => {
115
+ if (allGroupByIds.includes(cell.id) && groupCellIds[cell.rowColId()] !== true) {
116
+ repeatCellIds[cell.rowColId()] = true;
117
+ }
118
+ });
119
+ });
120
+ }
121
+ return groupedRows;
122
+ };
123
+ export const addGroupBy = ({ initialGroupByIds = [], disableMultiGroup = false, isMultiGroupEvent = isShiftClick } = {}) => ({ columnOptions }) => {
124
+ const disabledGroupIds = Object.entries(columnOptions)
125
+ .filter(([, option]) => option.disable === true)
126
+ .map(([columnId]) => columnId);
127
+ const groupByIds = arraySetStore(initialGroupByIds);
128
+ const repeatCellIds = writable({});
129
+ const aggregateCellIds = writable({});
130
+ const groupCellIds = writable({});
131
+ const pluginState = {
132
+ groupByIds
133
+ };
134
+ const deriveRows = (rows) => {
135
+ return derived([rows, groupByIds], ([$rows, $groupByIds]) => {
136
+ const $repeatCellIds = {};
137
+ const $aggregateCellIds = {};
138
+ const $groupCellIds = {};
139
+ const $groupedRows = getGroupedRows($rows, $groupByIds, columnOptions, {
140
+ repeatCellIds: $repeatCellIds,
141
+ aggregateCellIds: $aggregateCellIds,
142
+ groupCellIds: $groupCellIds,
143
+ allGroupByIds: $groupByIds
144
+ });
145
+ repeatCellIds.set($repeatCellIds);
146
+ aggregateCellIds.set($aggregateCellIds);
147
+ groupCellIds.set($groupCellIds);
148
+ return $groupedRows;
149
+ });
150
+ };
151
+ return {
152
+ pluginState,
153
+ deriveRows,
154
+ hooks: {
155
+ 'thead.tr.th': (cell) => {
156
+ const disabled = disabledGroupIds.includes(cell.id) || !cell.isData();
157
+ const props = derived(groupByIds, ($groupByIds) => {
158
+ const grouped = $groupByIds.includes(cell.id);
159
+ const toggle = (event) => {
160
+ if (!cell.isData())
161
+ return;
162
+ if (disabled)
163
+ return;
164
+ groupByIds.toggle(cell.id, {
165
+ clearOthers: disableMultiGroup || !isMultiGroupEvent(event)
166
+ });
167
+ };
168
+ const clear = () => {
169
+ groupByIds.remove(cell.id);
170
+ };
171
+ return {
172
+ grouped,
173
+ toggle,
174
+ clear,
175
+ disabled
176
+ };
177
+ });
178
+ return { props };
179
+ },
180
+ 'tbody.tr.td': (cell) => {
181
+ const props = derived([repeatCellIds, aggregateCellIds, groupCellIds], ([$repeatCellIds, $aggregateCellIds, $groupCellIds]) => {
182
+ return {
183
+ repeated: $repeatCellIds[cell.rowColId()] === true,
184
+ aggregated: $aggregateCellIds[cell.rowColId()] === true,
185
+ grouped: $groupCellIds[cell.rowColId()] === true
186
+ };
187
+ });
188
+ return { props };
189
+ }
190
+ }
191
+ };
192
+ };
@@ -0,0 +1,9 @@
1
+ import type { NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
2
+ import { type Writable } from 'svelte/store';
3
+ export interface HiddenColumnsConfig {
4
+ initialHiddenColumnIds?: string[];
5
+ }
6
+ export interface HiddenColumnsState {
7
+ hiddenColumnIds: Writable<string[]>;
8
+ }
9
+ export declare const addHiddenColumns: <Item>({ initialHiddenColumnIds }?: HiddenColumnsConfig) => TablePlugin<Item, HiddenColumnsState, Record<string, never>, NewTablePropSet<never>>;
@@ -0,0 +1,17 @@
1
+ import { derived, writable } from 'svelte/store';
2
+ export const addHiddenColumns = ({ initialHiddenColumnIds = [] } = {}) => () => {
3
+ const hiddenColumnIds = writable(initialHiddenColumnIds);
4
+ const pluginState = { hiddenColumnIds };
5
+ const deriveFlatColumns = (flatColumns) => {
6
+ return derived([flatColumns, hiddenColumnIds], ([$flatColumns, $hiddenColumnIds]) => {
7
+ if ($hiddenColumnIds.length === 0) {
8
+ return $flatColumns;
9
+ }
10
+ return $flatColumns.filter((c) => !$hiddenColumnIds.includes(c.id));
11
+ });
12
+ };
13
+ return {
14
+ pluginState,
15
+ deriveFlatColumns
16
+ };
17
+ };
@@ -0,0 +1,39 @@
1
+ import type { NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
2
+ import { type Readable, type Updater, type Writable } from 'svelte/store';
3
+ export type PaginationConfig = {
4
+ initialPageIndex?: number;
5
+ initialPageSize?: number;
6
+ } & ({
7
+ serverSide?: false | undefined;
8
+ serverItemCount?: undefined;
9
+ } | {
10
+ serverSide: true;
11
+ serverItemCount: Readable<number>;
12
+ });
13
+ export interface PaginationState {
14
+ pageSize: Writable<number>;
15
+ pageIndex: Writable<number>;
16
+ pageCount: Readable<number>;
17
+ hasPreviousPage: Readable<boolean>;
18
+ hasNextPage: Readable<boolean>;
19
+ }
20
+ export declare const createPageStore: ({ items, initialPageSize, initialPageIndex, serverSide, serverItemCount }: PageStoreConfig) => {
21
+ pageSize: {
22
+ subscribe: (this: void, run: import("svelte/store").Subscriber<number>, invalidate?: import("svelte/store").Invalidator<number> | undefined) => import("svelte/store").Unsubscriber;
23
+ update: (fn: Updater<number>) => void;
24
+ set: (newPageSize: number) => void;
25
+ };
26
+ pageIndex: Writable<number>;
27
+ pageCount: Readable<number>;
28
+ serverItemCount: Readable<number> | undefined;
29
+ hasPreviousPage: Readable<boolean>;
30
+ hasNextPage: Readable<boolean>;
31
+ };
32
+ export interface PageStoreConfig {
33
+ items: Readable<unknown[]>;
34
+ initialPageSize?: number;
35
+ initialPageIndex?: number;
36
+ serverSide?: boolean;
37
+ serverItemCount?: Readable<number>;
38
+ }
39
+ export declare const addPagination: <Item>({ initialPageIndex, initialPageSize, serverSide, serverItemCount }?: PaginationConfig) => TablePlugin<Item, PaginationState, Record<string, never>, NewTablePropSet<never>>;
@@ -0,0 +1,84 @@
1
+ import { derived, writable } from 'svelte/store';
2
+ const MIN_PAGE_SIZE = 1;
3
+ export const createPageStore = ({ items, initialPageSize, initialPageIndex, serverSide, serverItemCount }) => {
4
+ const pageSize = writable(initialPageSize);
5
+ const updatePageSize = (fn) => {
6
+ pageSize.update(($pageSize) => {
7
+ const newPageSize = fn($pageSize);
8
+ return Math.max(newPageSize, MIN_PAGE_SIZE);
9
+ });
10
+ };
11
+ const setPageSize = (newPageSize) => updatePageSize(() => newPageSize);
12
+ const pageIndex = writable(initialPageIndex);
13
+ function calcPageCountAndLimitIndex([$pageSize, $itemCount]) {
14
+ const $pageCount = Math.ceil($itemCount / $pageSize);
15
+ pageIndex.update(($pageIndex) => {
16
+ if ($pageCount > 0 && $pageIndex >= $pageCount) {
17
+ return $pageCount - 1;
18
+ }
19
+ return $pageIndex;
20
+ });
21
+ return $pageCount;
22
+ }
23
+ let pageCount;
24
+ if (serverSide && serverItemCount != null) {
25
+ pageCount = derived([pageSize, serverItemCount], calcPageCountAndLimitIndex);
26
+ }
27
+ else {
28
+ const itemCount = derived(items, ($items) => $items.length);
29
+ pageCount = derived([pageSize, itemCount], calcPageCountAndLimitIndex);
30
+ }
31
+ const hasPreviousPage = derived(pageIndex, ($pageIndex) => {
32
+ return $pageIndex > 0;
33
+ });
34
+ const hasNextPage = derived([pageIndex, pageCount], ([$pageIndex, $pageCount]) => {
35
+ return $pageIndex < $pageCount - 1;
36
+ });
37
+ return {
38
+ pageSize: {
39
+ subscribe: pageSize.subscribe,
40
+ update: updatePageSize,
41
+ set: setPageSize
42
+ },
43
+ pageIndex,
44
+ pageCount,
45
+ serverItemCount,
46
+ hasPreviousPage,
47
+ hasNextPage
48
+ };
49
+ };
50
+ export const addPagination = ({ initialPageIndex = 0, initialPageSize = 10, serverSide = false, serverItemCount } = {}) => () => {
51
+ const prePaginatedRows = writable([]);
52
+ const paginatedRows = writable([]);
53
+ const { pageSize, pageIndex, pageCount, hasPreviousPage, hasNextPage } = createPageStore({
54
+ items: prePaginatedRows,
55
+ initialPageIndex,
56
+ initialPageSize,
57
+ serverSide,
58
+ serverItemCount
59
+ });
60
+ const pluginState = {
61
+ pageSize,
62
+ pageIndex,
63
+ pageCount,
64
+ hasPreviousPage,
65
+ hasNextPage
66
+ };
67
+ const derivePageRows = (rows) => {
68
+ return derived([rows, pageSize, pageIndex], ([$rows, $pageSize, $pageIndex]) => {
69
+ prePaginatedRows.set($rows);
70
+ if (serverSide) {
71
+ paginatedRows.set($rows);
72
+ return $rows;
73
+ }
74
+ const startIdx = $pageIndex * $pageSize;
75
+ const _paginatedRows = $rows.slice(startIdx, startIdx + $pageSize);
76
+ paginatedRows.set(_paginatedRows);
77
+ return _paginatedRows;
78
+ });
79
+ };
80
+ return {
81
+ pluginState,
82
+ derivePageRows
83
+ };
84
+ };
@@ -0,0 +1,41 @@
1
+ import type { NewTableAttributeSet, NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
2
+ import { type Writable } from 'svelte/store';
3
+ export interface AddResizedColumnsConfig {
4
+ onResizeEnd?: (ev: Event) => void;
5
+ }
6
+ export type ResizedColumnsState = {
7
+ columnWidths: Writable<Record<string, number>>;
8
+ };
9
+ export type ResizedColumnsColumnOptions = {
10
+ initialWidth?: number;
11
+ minWidth?: number;
12
+ maxWidth?: number;
13
+ disable?: boolean;
14
+ };
15
+ export type ResizedColumnsPropSet = NewTablePropSet<{
16
+ 'thead.tr.th': {
17
+ (node: Element): void;
18
+ drag: (node: Element) => void;
19
+ reset: (node: Element) => void;
20
+ disabled: boolean;
21
+ };
22
+ }>;
23
+ export type ResizedColumnsAttributeSet = NewTableAttributeSet<{
24
+ 'thead.tr.th': {
25
+ style?: {
26
+ width: string;
27
+ 'min-width': string;
28
+ 'max-width': string;
29
+ 'box-sizing': 'border-box';
30
+ };
31
+ };
32
+ 'tbody.tr.td': {
33
+ style?: {
34
+ width: string;
35
+ 'min-width': string;
36
+ 'max-width': string;
37
+ 'box-sizing': 'border-box';
38
+ };
39
+ };
40
+ }>;
41
+ export declare const addResizedColumns: <Item>({ onResizeEnd }?: AddResizedColumnsConfig) => TablePlugin<Item, ResizedColumnsState, ResizedColumnsColumnOptions, ResizedColumnsPropSet, ResizedColumnsAttributeSet>;