@humanspeak/svelte-headless-table 6.0.2 → 6.0.3
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.
- package/README.md +2 -2
- package/dist/bodyCells.d.ts +116 -0
- package/dist/bodyCells.js +80 -0
- package/dist/bodyRows.d.ts +92 -0
- package/dist/bodyRows.js +55 -0
- package/dist/columns.d.ts +204 -0
- package/dist/columns.js +120 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +4 -0
- package/dist/createTable.d.ts +107 -0
- package/dist/createTable.js +92 -0
- package/dist/createViewModel.d.ts +105 -2
- package/dist/createViewModel.js +55 -1
- package/dist/headerCells.d.ts +210 -0
- package/dist/headerCells.js +151 -0
- package/dist/headerRows.d.ts +72 -0
- package/dist/headerRows.js +60 -0
- package/dist/plugins/addColumnFilters.d.ts +101 -0
- package/dist/plugins/addColumnFilters.js +55 -0
- package/dist/plugins/addColumnOrder.d.ts +30 -0
- package/dist/plugins/addColumnOrder.js +21 -0
- package/dist/plugins/addDataExport.d.ts +51 -0
- package/dist/plugins/addDataExport.js +30 -0
- package/dist/plugins/addExpandedRows.d.ts +41 -2
- package/dist/plugins/addExpandedRows.js +24 -0
- package/dist/plugins/addFlatten.d.ts +48 -3
- package/dist/plugins/addFlatten.js +28 -0
- package/dist/plugins/addGridLayout.d.ts +13 -0
- package/dist/plugins/addGridLayout.js +13 -0
- package/dist/plugins/addGroupBy.d.ts +80 -4
- package/dist/plugins/addGroupBy.js +48 -4
- package/dist/plugins/addHiddenColumns.d.ts +27 -0
- package/dist/plugins/addHiddenColumns.js +19 -0
- package/dist/plugins/addPagination.d.ts +54 -0
- package/dist/plugins/addPagination.js +29 -0
- package/dist/plugins/addResizedColumns.d.ts +58 -4
- package/dist/plugins/addResizedColumns.js +33 -0
- package/dist/plugins/addSelectedRows.d.ts +58 -2
- package/dist/plugins/addSelectedRows.js +42 -0
- package/dist/plugins/addSortBy.d.ts +83 -6
- package/dist/plugins/addSortBy.js +65 -24
- package/dist/plugins/addSubRows.d.ts +39 -1
- package/dist/plugins/addSubRows.js +25 -0
- package/dist/plugins/addTableFilter.d.ts +87 -3
- package/dist/plugins/addTableFilter.js +90 -40
- package/dist/tableComponent.d.ts +41 -0
- package/dist/tableComponent.js +37 -0
- package/dist/types/Action.d.ts +16 -2
- package/dist/types/Entries.d.ts +6 -0
- package/dist/types/KeyPath.d.ts +20 -0
- package/dist/types/Label.d.ts +26 -3
- package/dist/types/Matrix.d.ts +6 -0
- package/dist/types/TablePlugin.d.ts +140 -10
- package/dist/utils/array.d.ts +24 -0
- package/dist/utils/array.js +24 -0
- package/dist/utils/attributes.d.ts +31 -0
- package/dist/utils/attributes.js +31 -0
- package/dist/utils/clone.d.ts +19 -0
- package/dist/utils/clone.js +13 -0
- package/dist/utils/compare.d.ts +29 -0
- package/dist/utils/compare.js +29 -0
- package/dist/utils/counter.d.ts +12 -0
- package/dist/utils/counter.js +12 -0
- package/dist/utils/css.d.ts +11 -0
- package/dist/utils/css.js +11 -0
- package/dist/utils/event.d.ts +14 -0
- package/dist/utils/event.js +14 -0
- package/dist/utils/filter.d.ts +47 -0
- package/dist/utils/filter.js +47 -0
- package/dist/utils/math.d.ts +22 -0
- package/dist/utils/math.js +22 -0
- package/dist/utils/matrix.d.ts +24 -0
- package/dist/utils/matrix.js +24 -0
- package/dist/utils/store.d.ts +116 -9
- package/dist/utils/store.js +63 -0
- package/package.json +22 -22
|
@@ -4,6 +4,10 @@ import { BodyRow, DisplayBodyRow } from '../bodyRows.js';
|
|
|
4
4
|
import { isShiftClick } from '../utils/event.js';
|
|
5
5
|
import { nonUndefined } from '../utils/filter.js';
|
|
6
6
|
import { arraySetStore } from '../utils/store.js';
|
|
7
|
+
/**
|
|
8
|
+
* Extracts the ID prefix from a row ID.
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
7
11
|
const getIdPrefix = (id) => {
|
|
8
12
|
const prefixTokens = id.split('>').slice(0, -1);
|
|
9
13
|
if (prefixTokens.length === 0) {
|
|
@@ -11,16 +15,29 @@ const getIdPrefix = (id) => {
|
|
|
11
15
|
}
|
|
12
16
|
return `${prefixTokens.join('>')}>`;
|
|
13
17
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Recursively updates row IDs and depths for nested grouped rows.
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
18
22
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
23
|
const deepenIdAndDepth = (row, parentId) => {
|
|
20
24
|
row.id = `${parentId}>${row.id}`;
|
|
21
25
|
row.depth = row.depth + 1;
|
|
22
26
|
row.subRows?.forEach((subRow) => deepenIdAndDepth(subRow, parentId));
|
|
23
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* Groups rows by the specified column IDs, creating hierarchical grouped rows.
|
|
30
|
+
* Computes aggregate values for non-grouped columns.
|
|
31
|
+
*
|
|
32
|
+
* @template Item - The type of data items.
|
|
33
|
+
* @template Row - The row type.
|
|
34
|
+
* @template GroupOn - The grouping key type.
|
|
35
|
+
* @param rows - The rows to group.
|
|
36
|
+
* @param groupByIds - Column IDs to group by, in order.
|
|
37
|
+
* @param columnOptions - Per-column grouping configuration.
|
|
38
|
+
* @param props - Internal state tracking objects.
|
|
39
|
+
* @returns The grouped rows array.
|
|
40
|
+
*/
|
|
24
41
|
export const getGroupedRows = (rows, groupByIds, columnOptions, { repeatCellIds, aggregateCellIds, groupCellIds, allGroupByIds }) => {
|
|
25
42
|
if (groupByIds.length === 0) {
|
|
26
43
|
return rows;
|
|
@@ -119,6 +136,33 @@ export const getGroupedRows = (rows, groupByIds, columnOptions, { repeatCellIds,
|
|
|
119
136
|
}
|
|
120
137
|
return groupedRows;
|
|
121
138
|
};
|
|
139
|
+
/**
|
|
140
|
+
* Creates a group by plugin that enables grouping rows by column values.
|
|
141
|
+
* Groups are hierarchical - grouping by multiple columns creates nested groups.
|
|
142
|
+
*
|
|
143
|
+
* @template Item - The type of data items in the table.
|
|
144
|
+
* @param config - Configuration options.
|
|
145
|
+
* @returns A TablePlugin that provides grouping functionality.
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* const table = createTable(data, {
|
|
149
|
+
* group: addGroupBy({
|
|
150
|
+
* initialGroupByIds: ['department']
|
|
151
|
+
* })
|
|
152
|
+
* })
|
|
153
|
+
*
|
|
154
|
+
* // Configure aggregation for columns
|
|
155
|
+
* table.column({
|
|
156
|
+
* accessor: 'salary',
|
|
157
|
+
* header: 'Salary',
|
|
158
|
+
* plugins: {
|
|
159
|
+
* group: {
|
|
160
|
+
* getAggregateValue: (values) => values.reduce((a, b) => a + b, 0)
|
|
161
|
+
* }
|
|
162
|
+
* }
|
|
163
|
+
* })
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
122
166
|
export const addGroupBy = ({ initialGroupByIds = [], disableMultiGroup = false, isMultiGroupEvent = isShiftClick } = {}) => ({ columnOptions }) => {
|
|
123
167
|
const disabledGroupIds = Object.entries(columnOptions)
|
|
124
168
|
.filter(([, option]) => option.disable === true)
|
|
@@ -1,9 +1,36 @@
|
|
|
1
1
|
import { type Writable } from 'svelte/store';
|
|
2
2
|
import type { NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the addHiddenColumns plugin.
|
|
5
|
+
*/
|
|
3
6
|
export interface HiddenColumnsConfig {
|
|
7
|
+
/** Initial list of column IDs to hide. */
|
|
4
8
|
initialHiddenColumnIds?: string[];
|
|
5
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* State exposed by the addHiddenColumns plugin.
|
|
12
|
+
*/
|
|
6
13
|
export interface HiddenColumnsState {
|
|
14
|
+
/** Writable store containing the list of hidden column IDs. */
|
|
7
15
|
hiddenColumnIds: Writable<string[]>;
|
|
8
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a hidden columns plugin that enables showing/hiding table columns.
|
|
19
|
+
*
|
|
20
|
+
* @template Item - The type of data items in the table.
|
|
21
|
+
* @param config - Configuration options.
|
|
22
|
+
* @returns A TablePlugin that provides column visibility control.
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const table = createTable(data, {
|
|
26
|
+
* hide: addHiddenColumns({
|
|
27
|
+
* initialHiddenColumnIds: ['internalId', 'createdAt']
|
|
28
|
+
* })
|
|
29
|
+
* })
|
|
30
|
+
*
|
|
31
|
+
* // Hide/show columns dynamically
|
|
32
|
+
* const { hiddenColumnIds } = table.pluginStates.hide
|
|
33
|
+
* hiddenColumnIds.update(ids => [...ids, 'newColumn'])
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
9
36
|
export declare const addHiddenColumns: <Item>({ initialHiddenColumnIds }?: HiddenColumnsConfig) => TablePlugin<Item, HiddenColumnsState, Record<string, never>, NewTablePropSet<never>>;
|
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
import { derived, writable } from 'svelte/store';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a hidden columns plugin that enables showing/hiding table columns.
|
|
4
|
+
*
|
|
5
|
+
* @template Item - The type of data items in the table.
|
|
6
|
+
* @param config - Configuration options.
|
|
7
|
+
* @returns A TablePlugin that provides column visibility control.
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const table = createTable(data, {
|
|
11
|
+
* hide: addHiddenColumns({
|
|
12
|
+
* initialHiddenColumnIds: ['internalId', 'createdAt']
|
|
13
|
+
* })
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* // Hide/show columns dynamically
|
|
17
|
+
* const { hiddenColumnIds } = table.pluginStates.hide
|
|
18
|
+
* hiddenColumnIds.update(ids => [...ids, 'newColumn'])
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
2
21
|
export const addHiddenColumns = ({ initialHiddenColumnIds = [] } = {}) => () => {
|
|
3
22
|
const hiddenColumnIds = writable(initialHiddenColumnIds);
|
|
4
23
|
const pluginState = { hiddenColumnIds };
|
|
@@ -1,22 +1,45 @@
|
|
|
1
1
|
import { type Readable, type Updater, type Writable } from 'svelte/store';
|
|
2
2
|
import type { NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the addPagination plugin.
|
|
5
|
+
* Supports both client-side and server-side pagination modes.
|
|
6
|
+
*/
|
|
3
7
|
export type PaginationConfig = {
|
|
8
|
+
/** Initial page index (0-based). Defaults to 0. */
|
|
4
9
|
initialPageIndex?: number;
|
|
10
|
+
/** Initial page size. Defaults to 10. */
|
|
5
11
|
initialPageSize?: number;
|
|
6
12
|
} & ({
|
|
13
|
+
/** Client-side pagination mode. */
|
|
7
14
|
serverSide?: false | undefined;
|
|
8
15
|
serverItemCount?: undefined;
|
|
9
16
|
} | {
|
|
17
|
+
/** Server-side pagination mode. */
|
|
10
18
|
serverSide: true;
|
|
19
|
+
/** A readable store containing the total item count from the server. */
|
|
11
20
|
serverItemCount: Readable<number>;
|
|
12
21
|
});
|
|
22
|
+
/**
|
|
23
|
+
* State exposed by the addPagination plugin.
|
|
24
|
+
*/
|
|
13
25
|
export interface PaginationState {
|
|
26
|
+
/** Writable store for the current page size. */
|
|
14
27
|
pageSize: Writable<number>;
|
|
28
|
+
/** Writable store for the current page index (0-based). */
|
|
15
29
|
pageIndex: Writable<number>;
|
|
30
|
+
/** Readable store for the total number of pages. */
|
|
16
31
|
pageCount: Readable<number>;
|
|
32
|
+
/** Readable store indicating if there's a previous page. */
|
|
17
33
|
hasPreviousPage: Readable<boolean>;
|
|
34
|
+
/** Readable store indicating if there's a next page. */
|
|
18
35
|
hasNextPage: Readable<boolean>;
|
|
19
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Creates a page store with pagination state and navigation helpers.
|
|
39
|
+
*
|
|
40
|
+
* @param config - Configuration for the page store.
|
|
41
|
+
* @returns An object containing pagination state stores.
|
|
42
|
+
*/
|
|
20
43
|
export declare const createPageStore: ({ items, initialPageSize, initialPageIndex, serverSide, serverItemCount }: PageStoreConfig) => {
|
|
21
44
|
pageSize: {
|
|
22
45
|
subscribe: (this: void, run: import("svelte/store").Subscriber<number>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
|
|
@@ -29,11 +52,42 @@ export declare const createPageStore: ({ items, initialPageSize, initialPageInde
|
|
|
29
52
|
hasPreviousPage: Readable<boolean>;
|
|
30
53
|
hasNextPage: Readable<boolean>;
|
|
31
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* Configuration for createPageStore.
|
|
57
|
+
*/
|
|
32
58
|
export interface PageStoreConfig {
|
|
59
|
+
/** Readable store of items to paginate. */
|
|
33
60
|
items: Readable<unknown[]>;
|
|
61
|
+
/** Initial page size. */
|
|
34
62
|
initialPageSize?: number;
|
|
63
|
+
/** Initial page index (0-based). */
|
|
35
64
|
initialPageIndex?: number;
|
|
65
|
+
/** Whether pagination is server-side. */
|
|
36
66
|
serverSide?: boolean;
|
|
67
|
+
/** Total item count from server (for server-side pagination). */
|
|
37
68
|
serverItemCount?: Readable<number>;
|
|
38
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Creates a pagination plugin that enables paged navigation through table rows.
|
|
72
|
+
* Supports both client-side and server-side pagination.
|
|
73
|
+
*
|
|
74
|
+
* @template Item - The type of data items in the table.
|
|
75
|
+
* @param config - Configuration options for pagination.
|
|
76
|
+
* @returns A TablePlugin that provides pagination functionality.
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* const table = createTable(data, {
|
|
80
|
+
* page: addPagination({
|
|
81
|
+
* initialPageSize: 20,
|
|
82
|
+
* initialPageIndex: 0
|
|
83
|
+
* })
|
|
84
|
+
* })
|
|
85
|
+
*
|
|
86
|
+
* // Navigate pages
|
|
87
|
+
* const { pageIndex, pageCount, hasNextPage } = table.pluginStates.page
|
|
88
|
+
* if ($hasNextPage) {
|
|
89
|
+
* pageIndex.update(n => n + 1)
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
39
93
|
export declare const addPagination: <Item>({ initialPageIndex, initialPageSize, serverSide, serverItemCount }?: PaginationConfig) => TablePlugin<Item, PaginationState, Record<string, never>, NewTablePropSet<never>>;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { derived, writable } from 'svelte/store';
|
|
2
2
|
const MIN_PAGE_SIZE = 1;
|
|
3
|
+
/**
|
|
4
|
+
* Creates a page store with pagination state and navigation helpers.
|
|
5
|
+
*
|
|
6
|
+
* @param config - Configuration for the page store.
|
|
7
|
+
* @returns An object containing pagination state stores.
|
|
8
|
+
*/
|
|
3
9
|
export const createPageStore = ({ items, initialPageSize, initialPageIndex, serverSide, serverItemCount }) => {
|
|
4
10
|
const pageSize = writable(initialPageSize);
|
|
5
11
|
const updatePageSize = (fn) => {
|
|
@@ -47,6 +53,29 @@ export const createPageStore = ({ items, initialPageSize, initialPageIndex, serv
|
|
|
47
53
|
hasNextPage
|
|
48
54
|
};
|
|
49
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Creates a pagination plugin that enables paged navigation through table rows.
|
|
58
|
+
* Supports both client-side and server-side pagination.
|
|
59
|
+
*
|
|
60
|
+
* @template Item - The type of data items in the table.
|
|
61
|
+
* @param config - Configuration options for pagination.
|
|
62
|
+
* @returns A TablePlugin that provides pagination functionality.
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* const table = createTable(data, {
|
|
66
|
+
* page: addPagination({
|
|
67
|
+
* initialPageSize: 20,
|
|
68
|
+
* initialPageIndex: 0
|
|
69
|
+
* })
|
|
70
|
+
* })
|
|
71
|
+
*
|
|
72
|
+
* // Navigate pages
|
|
73
|
+
* const { pageIndex, pageCount, hasNextPage } = table.pluginStates.page
|
|
74
|
+
* if ($hasNextPage) {
|
|
75
|
+
* pageIndex.update(n => n + 1)
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
50
79
|
export const addPagination = ({ initialPageIndex = 0, initialPageSize = 10, serverSide = false, serverItemCount } = {}) => () => {
|
|
51
80
|
const prePaginatedRows = writable([]);
|
|
52
81
|
const paginatedRows = writable([]);
|
|
@@ -1,25 +1,50 @@
|
|
|
1
1
|
import { type Writable } from 'svelte/store';
|
|
2
2
|
import type { NewTableAttributeSet, NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the addResizedColumns plugin.
|
|
5
|
+
*/
|
|
3
6
|
export interface AddResizedColumnsConfig {
|
|
4
|
-
|
|
7
|
+
/** Callback fired when a resize operation ends. */
|
|
8
|
+
onResizeEnd?: (_ev: Event) => void;
|
|
5
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* State exposed by the addResizedColumns plugin.
|
|
12
|
+
*/
|
|
6
13
|
export type ResizedColumnsState = {
|
|
14
|
+
/** Writable store mapping column IDs to their current widths in pixels. */
|
|
7
15
|
columnWidths: Writable<Record<string, number>>;
|
|
8
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Per-column configuration options for resizing.
|
|
19
|
+
*/
|
|
9
20
|
export type ResizedColumnsColumnOptions = {
|
|
21
|
+
/** Initial width in pixels. */
|
|
10
22
|
initialWidth?: number;
|
|
23
|
+
/** Minimum width in pixels. */
|
|
11
24
|
minWidth?: number;
|
|
25
|
+
/** Maximum width in pixels. */
|
|
12
26
|
maxWidth?: number;
|
|
27
|
+
/** If true, resizing is disabled for this column. */
|
|
13
28
|
disable?: boolean;
|
|
14
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Props added to table elements by the resized columns plugin.
|
|
32
|
+
*/
|
|
15
33
|
export type ResizedColumnsPropSet = NewTablePropSet<{
|
|
16
34
|
'thead.tr.th': {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
35
|
+
/** Action to register the header cell element. */
|
|
36
|
+
(_node: Element): void;
|
|
37
|
+
/** Action to enable drag-to-resize on an element. */
|
|
38
|
+
drag: (_node: Element) => void;
|
|
39
|
+
/** Action to enable double-click-to-reset on an element. */
|
|
40
|
+
reset: (_node: Element) => void;
|
|
41
|
+
/** Whether resizing is disabled for this column. */
|
|
20
42
|
disabled: boolean;
|
|
21
43
|
};
|
|
22
44
|
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Attributes added to table elements by the resized columns plugin.
|
|
47
|
+
*/
|
|
23
48
|
export type ResizedColumnsAttributeSet = NewTableAttributeSet<{
|
|
24
49
|
'thead.tr.th': {
|
|
25
50
|
style?: {
|
|
@@ -38,4 +63,33 @@ export type ResizedColumnsAttributeSet = NewTableAttributeSet<{
|
|
|
38
63
|
};
|
|
39
64
|
};
|
|
40
65
|
}>;
|
|
66
|
+
/**
|
|
67
|
+
* Creates a resized columns plugin that enables drag-to-resize column widths.
|
|
68
|
+
* Supports both mouse and touch interactions.
|
|
69
|
+
*
|
|
70
|
+
* @template Item - The type of data items in the table.
|
|
71
|
+
* @param config - Configuration options.
|
|
72
|
+
* @returns A TablePlugin that provides column resizing functionality.
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const table = createTable(data, {
|
|
76
|
+
* resize: addResizedColumns({
|
|
77
|
+
* onResizeEnd: (event) => console.log('Resize ended')
|
|
78
|
+
* })
|
|
79
|
+
* })
|
|
80
|
+
*
|
|
81
|
+
* // Configure per-column options
|
|
82
|
+
* table.column({
|
|
83
|
+
* accessor: 'name',
|
|
84
|
+
* header: 'Name',
|
|
85
|
+
* plugins: {
|
|
86
|
+
* resize: {
|
|
87
|
+
* initialWidth: 200,
|
|
88
|
+
* minWidth: 100,
|
|
89
|
+
* maxWidth: 400
|
|
90
|
+
* }
|
|
91
|
+
* }
|
|
92
|
+
* })
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
41
95
|
export declare const addResizedColumns: <Item>({ onResizeEnd }?: AddResizedColumnsConfig) => TablePlugin<Item, ResizedColumnsState, ResizedColumnsColumnOptions, ResizedColumnsPropSet, ResizedColumnsAttributeSet>;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { keyed } from '@humanspeak/svelte-keyed';
|
|
2
2
|
import { derived, writable } from 'svelte/store';
|
|
3
3
|
import { sum } from '../utils/math.js';
|
|
4
|
+
/**
|
|
5
|
+
* Gets the X position from a mouse or touch event.
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
4
8
|
const getDragXPos = (event) => {
|
|
5
9
|
if (event instanceof MouseEvent)
|
|
6
10
|
return event.clientX;
|
|
@@ -17,6 +21,35 @@ const isCellDisabled = (cell, disabledIds) => {
|
|
|
17
21
|
}
|
|
18
22
|
return false;
|
|
19
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Creates a resized columns plugin that enables drag-to-resize column widths.
|
|
26
|
+
* Supports both mouse and touch interactions.
|
|
27
|
+
*
|
|
28
|
+
* @template Item - The type of data items in the table.
|
|
29
|
+
* @param config - Configuration options.
|
|
30
|
+
* @returns A TablePlugin that provides column resizing functionality.
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const table = createTable(data, {
|
|
34
|
+
* resize: addResizedColumns({
|
|
35
|
+
* onResizeEnd: (event) => console.log('Resize ended')
|
|
36
|
+
* })
|
|
37
|
+
* })
|
|
38
|
+
*
|
|
39
|
+
* // Configure per-column options
|
|
40
|
+
* table.column({
|
|
41
|
+
* accessor: 'name',
|
|
42
|
+
* header: 'Name',
|
|
43
|
+
* plugins: {
|
|
44
|
+
* resize: {
|
|
45
|
+
* initialWidth: 200,
|
|
46
|
+
* minWidth: 100,
|
|
47
|
+
* maxWidth: 400
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
* })
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
20
53
|
export const addResizedColumns = ({ onResizeEnd } = {}) => ({ columnOptions }) => {
|
|
21
54
|
const disabledResizeIds = Object.entries(columnOptions)
|
|
22
55
|
.filter(([, option]) => option.disable === true)
|
|
@@ -2,30 +2,86 @@ import { type Readable, type Writable } from 'svelte/store';
|
|
|
2
2
|
import type { BodyRow } from '../bodyRows.js';
|
|
3
3
|
import type { NewTablePropSet, TablePlugin } from '../types/TablePlugin.js';
|
|
4
4
|
import { type RecordSetStore } from '../utils/store.js';
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the addSelectedRows plugin.
|
|
7
|
+
*
|
|
8
|
+
* @template _Item - The type of data items (unused but required for type inference).
|
|
9
|
+
*/
|
|
10
|
+
export interface SelectedRowsConfig<_Item> {
|
|
11
|
+
/** Initial selection state keyed by data ID. */
|
|
6
12
|
initialSelectedDataIds?: Record<string, boolean>;
|
|
13
|
+
/** If true, selecting a parent row selects all its sub-rows. Defaults to true. */
|
|
7
14
|
linkDataSubRows?: boolean;
|
|
8
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* State exposed by the addSelectedRows plugin.
|
|
18
|
+
*
|
|
19
|
+
* @template Item - The type of data items in the table.
|
|
20
|
+
*/
|
|
9
21
|
export interface SelectedRowsState<Item> {
|
|
22
|
+
/** Store containing selected data IDs. */
|
|
10
23
|
selectedDataIds: RecordSetStore<string>;
|
|
24
|
+
/** Writable store for selecting/deselecting all rows. */
|
|
11
25
|
allRowsSelected: Writable<boolean>;
|
|
26
|
+
/** Readable store indicating if any rows are selected. */
|
|
12
27
|
someRowsSelected: Readable<boolean>;
|
|
28
|
+
/** Writable store for selecting/deselecting all rows on the current page. */
|
|
13
29
|
allPageRowsSelected: Writable<boolean>;
|
|
30
|
+
/** Readable store indicating if any rows on the current page are selected. */
|
|
14
31
|
somePageRowsSelected: Readable<boolean>;
|
|
15
|
-
|
|
32
|
+
/** Gets the selection state stores for a specific row. */
|
|
33
|
+
getRowState: (_row: BodyRow<Item>) => SelectedRowsRowState;
|
|
16
34
|
/** Cleans up internal subscriptions and clears the row state cache. Call when destroying the table. */
|
|
17
35
|
invalidate: () => void;
|
|
18
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Selection state for a single row.
|
|
39
|
+
*/
|
|
19
40
|
export interface SelectedRowsRowState {
|
|
41
|
+
/** Writable store for the row's selection state. */
|
|
20
42
|
isSelected: Writable<boolean>;
|
|
43
|
+
/** Readable store indicating if some (but not all) sub-rows are selected. */
|
|
21
44
|
isSomeSubRowsSelected: Readable<boolean>;
|
|
45
|
+
/** Readable store indicating if all sub-rows are selected. */
|
|
22
46
|
isAllSubRowsSelected: Readable<boolean>;
|
|
23
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Props added to table rows by the selected rows plugin.
|
|
50
|
+
*/
|
|
24
51
|
export type SelectedRowsPropSet = NewTablePropSet<{
|
|
25
52
|
'tbody.tr': {
|
|
53
|
+
/** Whether this row is selected. */
|
|
26
54
|
selected: boolean;
|
|
55
|
+
/** Whether some (but not all) sub-rows are selected. */
|
|
27
56
|
someSubRowsSelected: boolean;
|
|
57
|
+
/** Whether all sub-rows are selected. */
|
|
28
58
|
allSubRowsSelected: boolean;
|
|
29
59
|
};
|
|
30
60
|
}>;
|
|
61
|
+
/**
|
|
62
|
+
* Creates a row selection plugin that enables selecting/deselecting table rows.
|
|
63
|
+
* Supports hierarchical selection with parent-child row linking.
|
|
64
|
+
*
|
|
65
|
+
* @template Item - The type of data items in the table.
|
|
66
|
+
* @param config - Configuration options.
|
|
67
|
+
* @returns A TablePlugin that provides row selection functionality.
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const table = createTable(data, {
|
|
71
|
+
* select: addSelectedRows({
|
|
72
|
+
* linkDataSubRows: true // Selecting parent selects children
|
|
73
|
+
* })
|
|
74
|
+
* })
|
|
75
|
+
*
|
|
76
|
+
* // Access selection state
|
|
77
|
+
* const { selectedDataIds, allRowsSelected } = table.pluginStates.select
|
|
78
|
+
*
|
|
79
|
+
* // Toggle all rows
|
|
80
|
+
* allRowsSelected.set(true)
|
|
81
|
+
*
|
|
82
|
+
* // Check if a specific row is selected
|
|
83
|
+
* const rowState = table.pluginStates.select.getRowState(row)
|
|
84
|
+
* $rowState.isSelected // true or false
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
31
87
|
export declare const addSelectedRows: <Item>({ initialSelectedDataIds, linkDataSubRows }?: SelectedRowsConfig<Item>) => TablePlugin<Item, SelectedRowsState<Item>, Record<string, never>, SelectedRowsPropSet>;
|
|
@@ -3,6 +3,10 @@ import { derived, get } from 'svelte/store';
|
|
|
3
3
|
import { nonNull } from '../utils/filter.js';
|
|
4
4
|
import { recordSetStore } from '../utils/store.js';
|
|
5
5
|
import { DEFAULT_ROW_STATE_CACHE_CONFIG } from './cacheConfig.js';
|
|
6
|
+
/**
|
|
7
|
+
* Recursively checks if all sub-rows of a row are selected.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
6
10
|
const isAllSubRowsSelectedForRow = (row, $selectedDataIds, linkDataSubRows) => {
|
|
7
11
|
if (row.isData()) {
|
|
8
12
|
if (!linkDataSubRows || row.subRows === undefined) {
|
|
@@ -14,6 +18,10 @@ const isAllSubRowsSelectedForRow = (row, $selectedDataIds, linkDataSubRows) => {
|
|
|
14
18
|
}
|
|
15
19
|
return row.subRows.every((subRow) => isAllSubRowsSelectedForRow(subRow, $selectedDataIds, linkDataSubRows));
|
|
16
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Recursively checks if any sub-rows of a row are selected.
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
17
25
|
const isSomeSubRowsSelectedForRow = (row, $selectedDataIds, linkDataSubRows) => {
|
|
18
26
|
if (row.isData()) {
|
|
19
27
|
if (!linkDataSubRows || row.subRows === undefined) {
|
|
@@ -25,6 +33,10 @@ const isSomeSubRowsSelectedForRow = (row, $selectedDataIds, linkDataSubRows) =>
|
|
|
25
33
|
}
|
|
26
34
|
return row.subRows.some((subRow) => isSomeSubRowsSelectedForRow(subRow, $selectedDataIds, linkDataSubRows));
|
|
27
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* Recursively writes selection state for a row and its sub-rows.
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
28
40
|
const writeSelectedDataIds = (row, value, $selectedDataIds, linkDataSubRows) => {
|
|
29
41
|
if (row.isData()) {
|
|
30
42
|
$selectedDataIds[row.dataId] = value;
|
|
@@ -39,6 +51,10 @@ const writeSelectedDataIds = (row, value, $selectedDataIds, linkDataSubRows) =>
|
|
|
39
51
|
writeSelectedDataIds(subRow, value, $selectedDataIds, linkDataSubRows);
|
|
40
52
|
});
|
|
41
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* Creates a writable store for a row's selection state.
|
|
56
|
+
* @internal
|
|
57
|
+
*/
|
|
42
58
|
const getRowIsSelectedStore = (row, selectedDataIds, linkDataSubRows) => {
|
|
43
59
|
const { subscribe } = derived(selectedDataIds, ($selectedDataIds) => {
|
|
44
60
|
if (row.isData()) {
|
|
@@ -69,6 +85,32 @@ const getRowIsSelectedStore = (row, selectedDataIds, linkDataSubRows) => {
|
|
|
69
85
|
set
|
|
70
86
|
};
|
|
71
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* Creates a row selection plugin that enables selecting/deselecting table rows.
|
|
90
|
+
* Supports hierarchical selection with parent-child row linking.
|
|
91
|
+
*
|
|
92
|
+
* @template Item - The type of data items in the table.
|
|
93
|
+
* @param config - Configuration options.
|
|
94
|
+
* @returns A TablePlugin that provides row selection functionality.
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const table = createTable(data, {
|
|
98
|
+
* select: addSelectedRows({
|
|
99
|
+
* linkDataSubRows: true // Selecting parent selects children
|
|
100
|
+
* })
|
|
101
|
+
* })
|
|
102
|
+
*
|
|
103
|
+
* // Access selection state
|
|
104
|
+
* const { selectedDataIds, allRowsSelected } = table.pluginStates.select
|
|
105
|
+
*
|
|
106
|
+
* // Toggle all rows
|
|
107
|
+
* allRowsSelected.set(true)
|
|
108
|
+
*
|
|
109
|
+
* // Check if a specific row is selected
|
|
110
|
+
* const rowState = table.pluginStates.select.getRowState(row)
|
|
111
|
+
* $rowState.isSelected // true or false
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
72
114
|
export const addSelectedRows = ({ initialSelectedDataIds = {}, linkDataSubRows = true } = {}) => ({ tableState }) => {
|
|
73
115
|
const selectedDataIds = recordSetStore(initialSelectedDataIds);
|
|
74
116
|
// LRU cache for memoized row state with automatic eviction.
|