@humanspeak/svelte-headless-table 6.0.2 → 6.0.4
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 +3 -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/plugins/addVirtualScroll.d.ts +37 -0
- package/dist/plugins/addVirtualScroll.js +302 -0
- package/dist/plugins/addVirtualScroll.types.d.ts +139 -0
- package/dist/plugins/addVirtualScroll.types.js +1 -0
- package/dist/plugins/index.d.ts +1 -0
- package/dist/plugins/index.js +1 -0
- 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/HeightManager.d.ts +107 -0
- package/dist/utils/HeightManager.js +204 -0
- 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 +23 -23
|
@@ -5,12 +5,41 @@ import type { DataColumn, FlatColumn } from '../columns.js';
|
|
|
5
5
|
import type { PluginInitTableState, TableAttributes, TableBodyAttributes, TableHeadAttributes } from '../createViewModel.js';
|
|
6
6
|
import type { HeaderCell, HeaderCellAttributes } from '../headerCells.js';
|
|
7
7
|
import type { HeaderRow, HeaderRowAttributes } from '../headerRows.js';
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* A table plugin factory function.
|
|
10
|
+
* Receives initialization options and returns a plugin instance.
|
|
11
|
+
*
|
|
12
|
+
* @template Item - The type of data items in the table.
|
|
13
|
+
* @template PluginState - The state exposed by the plugin.
|
|
14
|
+
* @template ColumnOptions - Per-column configuration options.
|
|
15
|
+
* @template TablePropSet - Props added to table components.
|
|
16
|
+
* @template TableAttributeSet - Attributes added to table components.
|
|
17
|
+
*/
|
|
18
|
+
export type TablePlugin<Item, PluginState, ColumnOptions, TablePropSet extends AnyTablePropSet = AnyTablePropSet, TableAttributeSet extends AnyTableAttributeSet = AnyTableAttributeSet> = (_init: TablePluginInit<Item, ColumnOptions>) => TablePluginInstance<Item, PluginState, ColumnOptions, TablePropSet, TableAttributeSet>;
|
|
19
|
+
/**
|
|
20
|
+
* Initialization options passed to a table plugin.
|
|
21
|
+
*
|
|
22
|
+
* @template Item - The type of data items in the table.
|
|
23
|
+
* @template ColumnOptions - Per-column configuration options.
|
|
24
|
+
*/
|
|
9
25
|
export type TablePluginInit<Item, ColumnOptions> = {
|
|
26
|
+
/** The name/key of this plugin in the plugins object. */
|
|
10
27
|
pluginName: string;
|
|
28
|
+
/** The table state during plugin initialization. */
|
|
11
29
|
tableState: PluginInitTableState<Item>;
|
|
30
|
+
/** Column options keyed by column ID. */
|
|
12
31
|
columnOptions: Record<string, ColumnOptions>;
|
|
13
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* A plugin instance returned by a TablePlugin factory.
|
|
35
|
+
* Contains state, transformation functions, and component hooks.
|
|
36
|
+
*
|
|
37
|
+
* @template Item - The type of data items in the table.
|
|
38
|
+
* @template PluginState - The state exposed by the plugin.
|
|
39
|
+
* @template ColumnOptions - Per-column configuration options.
|
|
40
|
+
* @template TablePropSet - Props added to table components.
|
|
41
|
+
* @template TableAttributeSet - Attributes added to table components.
|
|
42
|
+
*/
|
|
14
43
|
export type TablePluginInstance<Item, PluginState, ColumnOptions, TablePropSet extends AnyTablePropSet = AnyTablePropSet, TableAttributeSet extends AnyTableAttributeSet = AnyTableAttributeSet> = {
|
|
15
44
|
pluginState: PluginState;
|
|
16
45
|
transformFlatColumnsFn?: Readable<TransformFlatColumnsFn<Item>>;
|
|
@@ -23,65 +52,166 @@ export type TablePluginInstance<Item, PluginState, ColumnOptions, TablePropSet e
|
|
|
23
52
|
columnOptions?: ColumnOptions;
|
|
24
53
|
hooks?: TableHooks<Item, TablePropSet, TableAttributeSet>;
|
|
25
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* A record of table plugins, keyed by plugin name.
|
|
57
|
+
* Used as a type constraint for the plugins parameter.
|
|
58
|
+
*/
|
|
26
59
|
export type AnyPlugins = Record<any, TablePlugin<any, any, any, any, any>>;
|
|
60
|
+
/**
|
|
61
|
+
* A record of plugin instances, keyed by plugin name.
|
|
62
|
+
* Used internally after plugins are initialized.
|
|
63
|
+
*/
|
|
27
64
|
export type AnyPluginInstances = Record<any, TablePluginInstance<any, any, any, any, any>>;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
65
|
+
/**
|
|
66
|
+
* A synchronous function that transforms flat columns.
|
|
67
|
+
*
|
|
68
|
+
* @template Item - The type of data items in the table.
|
|
69
|
+
*/
|
|
70
|
+
export type TransformFlatColumnsFn<Item> = (_flatColumns: DataColumn<Item>[]) => DataColumn<Item>[];
|
|
71
|
+
/**
|
|
72
|
+
* A reactive function that derives flat columns from a store.
|
|
73
|
+
*
|
|
74
|
+
* @template Item - The type of data items in the table.
|
|
75
|
+
*/
|
|
76
|
+
export type DeriveFlatColumnsFn<Item> = <Col extends FlatColumn<Item>>(_flatColumns: Readable<Col[]>) => Readable<Col[]>;
|
|
77
|
+
/**
|
|
78
|
+
* A reactive function that derives rows from a store.
|
|
79
|
+
*
|
|
80
|
+
* @template Item - The type of data items in the table.
|
|
81
|
+
*/
|
|
82
|
+
export type DeriveRowsFn<Item> = <Row extends BodyRow<Item>>(_rows: Readable<Row[]>) => Readable<Row[]>;
|
|
83
|
+
/**
|
|
84
|
+
* A generic reactive derivation function.
|
|
85
|
+
*
|
|
86
|
+
* @template T - The type being derived.
|
|
87
|
+
*/
|
|
88
|
+
export type DeriveFn<T> = (_obj: Readable<T>) => Readable<T>;
|
|
89
|
+
/**
|
|
90
|
+
* Maps component keys to their corresponding component types.
|
|
91
|
+
*
|
|
92
|
+
* @template Item - The type of data items in the table.
|
|
93
|
+
* @template Plugins - The plugins used by the table.
|
|
94
|
+
*/
|
|
32
95
|
export type Components<Item, Plugins extends AnyPlugins = AnyPlugins> = {
|
|
33
96
|
'thead.tr': HeaderRow<Item, Plugins>;
|
|
34
97
|
'thead.tr.th': HeaderCell<Item, Plugins>;
|
|
35
98
|
'tbody.tr': BodyRow<Item, Plugins>;
|
|
36
99
|
'tbody.tr.td': BodyCell<Item, Plugins>;
|
|
37
100
|
};
|
|
101
|
+
/**
|
|
102
|
+
* Maps component keys to their corresponding attribute types.
|
|
103
|
+
*
|
|
104
|
+
* @template Item - The type of data items in the table.
|
|
105
|
+
* @template Plugins - The plugins used by the table.
|
|
106
|
+
*/
|
|
38
107
|
export type AttributesForKey<Item, Plugins extends AnyPlugins = AnyPlugins> = {
|
|
39
108
|
'thead.tr': HeaderRowAttributes<Item, Plugins>;
|
|
40
109
|
'thead.tr.th': HeaderCellAttributes<Item, Plugins>;
|
|
41
110
|
'tbody.tr': BodyRowAttributes<Item, Plugins>;
|
|
42
111
|
'tbody.tr.td': BodyCellAttributes<Item, Plugins>;
|
|
43
112
|
};
|
|
113
|
+
/**
|
|
114
|
+
* Valid keys for table components: header rows, header cells, body rows, body cells.
|
|
115
|
+
*/
|
|
44
116
|
export type ComponentKeys = keyof Components<unknown>;
|
|
45
117
|
type TablePropSet<PropSet extends {
|
|
46
|
-
[
|
|
118
|
+
[_K in ComponentKeys]?: unknown;
|
|
47
119
|
}> = {
|
|
48
120
|
[K in ComponentKeys]: PropSet[K];
|
|
49
121
|
};
|
|
122
|
+
/**
|
|
123
|
+
* Creates a new table prop set type, filtering out undefined component props.
|
|
124
|
+
*
|
|
125
|
+
* @template PropSet - The prop set definition.
|
|
126
|
+
*/
|
|
50
127
|
export type NewTablePropSet<PropSet extends {
|
|
51
|
-
[
|
|
128
|
+
[_K in ComponentKeys]?: unknown;
|
|
52
129
|
}> = {
|
|
53
130
|
[K in ComponentKeys]: unknown extends PropSet[K] ? never : PropSet[K];
|
|
54
131
|
};
|
|
132
|
+
/**
|
|
133
|
+
* A table prop set with any types. Used as a type constraint.
|
|
134
|
+
*/
|
|
55
135
|
export type AnyTablePropSet = TablePropSet<any>;
|
|
136
|
+
/**
|
|
137
|
+
* Internal type for mapping component keys to attribute sets.
|
|
138
|
+
* @internal
|
|
139
|
+
*/
|
|
56
140
|
type TableAttributeSet<AttributeSet extends {
|
|
57
|
-
[
|
|
141
|
+
[_K in ComponentKeys]?: unknown;
|
|
58
142
|
}> = {
|
|
59
143
|
[K in ComponentKeys]: AttributeSet[K];
|
|
60
144
|
};
|
|
145
|
+
/**
|
|
146
|
+
* Creates a new table attribute set type, filtering out undefined component attributes.
|
|
147
|
+
*
|
|
148
|
+
* @template AttributeSet - The attribute set definition.
|
|
149
|
+
*/
|
|
61
150
|
export type NewTableAttributeSet<AttributeSet extends {
|
|
62
|
-
[
|
|
151
|
+
[_K in ComponentKeys]?: unknown;
|
|
63
152
|
}> = {
|
|
64
153
|
[K in ComponentKeys]: unknown extends AttributeSet[K] ? never : AttributeSet[K];
|
|
65
154
|
};
|
|
155
|
+
/**
|
|
156
|
+
* A table attribute set with any types. Used as a type constraint.
|
|
157
|
+
*/
|
|
66
158
|
export type AnyTableAttributeSet = TableAttributeSet<any>;
|
|
159
|
+
/**
|
|
160
|
+
* Hooks for attaching props and attributes to table components.
|
|
161
|
+
* Each hook receives a component and returns props/attrs stores.
|
|
162
|
+
*
|
|
163
|
+
* @template Item - The type of data items in the table.
|
|
164
|
+
* @template PropSet - The prop set type.
|
|
165
|
+
* @template AttributeSet - The attribute set type.
|
|
166
|
+
*/
|
|
67
167
|
export type TableHooks<Item, PropSet extends AnyTablePropSet = AnyTablePropSet, AttributeSet extends AnyTableAttributeSet = AnyTableAttributeSet> = {
|
|
68
|
-
[ComponentKey in keyof Components<Item>]?: (
|
|
168
|
+
[ComponentKey in keyof Components<Item>]?: (_component: Components<Item>[ComponentKey]) => ElementHook<PropSet[ComponentKey], AttributeSet[ComponentKey]>;
|
|
69
169
|
};
|
|
170
|
+
/**
|
|
171
|
+
* Return type for component hooks.
|
|
172
|
+
* Contains optional readable stores for props and attributes.
|
|
173
|
+
*
|
|
174
|
+
* @template Props - The props type.
|
|
175
|
+
* @template Attributes - The attributes type.
|
|
176
|
+
*/
|
|
70
177
|
export type ElementHook<Props, Attributes> = {
|
|
178
|
+
/** Reactive props store. */
|
|
71
179
|
props?: Readable<Props>;
|
|
180
|
+
/** Reactive attributes store. */
|
|
72
181
|
attrs?: Readable<Attributes>;
|
|
73
182
|
};
|
|
183
|
+
/**
|
|
184
|
+
* Extracts the plugin state types from a plugins record.
|
|
185
|
+
*
|
|
186
|
+
* @template Plugins - The plugins record type.
|
|
187
|
+
*/
|
|
74
188
|
export type PluginStates<Plugins extends AnyPlugins> = {
|
|
75
189
|
[K in keyof Plugins]: ReturnType<Plugins[K]>['pluginState'];
|
|
76
190
|
};
|
|
191
|
+
/**
|
|
192
|
+
* Internal type for extracting prop sets from plugins.
|
|
193
|
+
* @internal
|
|
194
|
+
*/
|
|
77
195
|
type TablePropSetForPluginKey<Plugins extends AnyPlugins> = {
|
|
78
196
|
[K in keyof Plugins]: Plugins[K] extends TablePlugin<any, any, any, infer TablePropSet> ? TablePropSet : never;
|
|
79
197
|
};
|
|
198
|
+
/**
|
|
199
|
+
* Combines prop sets from all plugins into a single type.
|
|
200
|
+
* Props are grouped by component key, then by plugin key.
|
|
201
|
+
*
|
|
202
|
+
* @template Plugins - The plugins record type.
|
|
203
|
+
*/
|
|
80
204
|
export type PluginTablePropSet<Plugins extends AnyPlugins> = {
|
|
81
205
|
[ComponentKey in ComponentKeys]: {
|
|
82
206
|
[PluginKey in keyof Plugins]: TablePropSetForPluginKey<Plugins>[PluginKey][ComponentKey];
|
|
83
207
|
};
|
|
84
208
|
};
|
|
209
|
+
/**
|
|
210
|
+
* Extracts column configuration types from all plugins.
|
|
211
|
+
* Used to type the `plugins` option in column definitions.
|
|
212
|
+
*
|
|
213
|
+
* @template Plugins - The plugins record type.
|
|
214
|
+
*/
|
|
85
215
|
export type PluginColumnConfigs<Plugins extends AnyPlugins> = Partial<{
|
|
86
216
|
[K in keyof Plugins]: ReturnType<Plugins[K]>['columnOptions'];
|
|
87
217
|
}>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HeightManager handles row height caching and calculations for virtual scrolling.
|
|
3
|
+
* It maintains a cache of measured row heights and provides methods to calculate
|
|
4
|
+
* scroll positions, visible ranges, and total heights.
|
|
5
|
+
*/
|
|
6
|
+
export declare class HeightManager {
|
|
7
|
+
/** Cache of measured row heights by row ID. */
|
|
8
|
+
private heightCache;
|
|
9
|
+
/** Estimated height for unmeasured rows. */
|
|
10
|
+
private estimatedRowHeight;
|
|
11
|
+
/** Sum of all measured heights. */
|
|
12
|
+
private totalMeasuredHeight;
|
|
13
|
+
/** Number of measured rows. */
|
|
14
|
+
private measuredCount;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new HeightManager.
|
|
17
|
+
*
|
|
18
|
+
* @param estimatedRowHeight - Initial estimated height for unmeasured rows.
|
|
19
|
+
*/
|
|
20
|
+
constructor(estimatedRowHeight?: number);
|
|
21
|
+
/**
|
|
22
|
+
* Set or update the height for a specific row.
|
|
23
|
+
*
|
|
24
|
+
* @param rowId - The unique identifier of the row.
|
|
25
|
+
* @param height - The measured height of the row in pixels.
|
|
26
|
+
* @returns True if the height changed, false otherwise.
|
|
27
|
+
*/
|
|
28
|
+
setHeight(rowId: string, height: number): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Get the height for a specific row.
|
|
31
|
+
* Returns the measured height if available, otherwise the estimated height.
|
|
32
|
+
*
|
|
33
|
+
* @param rowId - The unique identifier of the row.
|
|
34
|
+
* @returns The height of the row in pixels.
|
|
35
|
+
*/
|
|
36
|
+
getHeight(rowId: string): number;
|
|
37
|
+
/**
|
|
38
|
+
* Check if a row has been measured.
|
|
39
|
+
*
|
|
40
|
+
* @param rowId - The unique identifier of the row.
|
|
41
|
+
* @returns True if the row has been measured.
|
|
42
|
+
*/
|
|
43
|
+
hasMeasurement(rowId: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Get the average height of measured rows.
|
|
46
|
+
* Falls back to the estimated height if no rows have been measured.
|
|
47
|
+
*
|
|
48
|
+
* @returns The average row height in pixels.
|
|
49
|
+
*/
|
|
50
|
+
getAverageHeight(): number;
|
|
51
|
+
/**
|
|
52
|
+
* Calculate the total height for a given number of rows.
|
|
53
|
+
*
|
|
54
|
+
* @param rowIds - Array of row IDs in order.
|
|
55
|
+
* @returns The total height in pixels.
|
|
56
|
+
*/
|
|
57
|
+
getTotalHeight(rowIds: string[]): number;
|
|
58
|
+
/**
|
|
59
|
+
* Calculate the offset (top position) for a given row index.
|
|
60
|
+
*
|
|
61
|
+
* @param rowIds - Array of row IDs in order.
|
|
62
|
+
* @param index - The index of the target row.
|
|
63
|
+
* @returns The offset from the top in pixels.
|
|
64
|
+
*/
|
|
65
|
+
getOffsetForIndex(rowIds: string[], index: number): number;
|
|
66
|
+
/**
|
|
67
|
+
* Calculate which rows are visible given a scroll position and viewport height.
|
|
68
|
+
*
|
|
69
|
+
* @param rowIds - Array of row IDs in order.
|
|
70
|
+
* @param scrollTop - Current scroll position.
|
|
71
|
+
* @param viewportHeight - Height of the visible area.
|
|
72
|
+
* @param bufferSize - Number of extra rows to render above/below.
|
|
73
|
+
* @returns Object with start and end indices of visible rows.
|
|
74
|
+
*/
|
|
75
|
+
getVisibleRange(rowIds: string[], scrollTop: number, viewportHeight: number, bufferSize: number): {
|
|
76
|
+
start: number;
|
|
77
|
+
end: number;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Find the row index at a given scroll position.
|
|
81
|
+
*
|
|
82
|
+
* @param rowIds - Array of row IDs in order.
|
|
83
|
+
* @param scrollTop - The scroll position to find.
|
|
84
|
+
* @returns The index of the row at that position.
|
|
85
|
+
*/
|
|
86
|
+
getIndexAtOffset(rowIds: string[], scrollTop: number): number;
|
|
87
|
+
/**
|
|
88
|
+
* Clear all cached heights.
|
|
89
|
+
*/
|
|
90
|
+
clear(): void;
|
|
91
|
+
/**
|
|
92
|
+
* Remove a specific row from the cache.
|
|
93
|
+
*
|
|
94
|
+
* @param rowId - The unique identifier of the row to remove.
|
|
95
|
+
*/
|
|
96
|
+
remove(rowId: string): void;
|
|
97
|
+
/**
|
|
98
|
+
* Get the number of measured rows.
|
|
99
|
+
*/
|
|
100
|
+
get size(): number;
|
|
101
|
+
/**
|
|
102
|
+
* Update the estimated row height.
|
|
103
|
+
*
|
|
104
|
+
* @param height - New estimated height in pixels.
|
|
105
|
+
*/
|
|
106
|
+
setEstimatedRowHeight(height: number): void;
|
|
107
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HeightManager handles row height caching and calculations for virtual scrolling.
|
|
3
|
+
* It maintains a cache of measured row heights and provides methods to calculate
|
|
4
|
+
* scroll positions, visible ranges, and total heights.
|
|
5
|
+
*/
|
|
6
|
+
export class HeightManager {
|
|
7
|
+
/** Cache of measured row heights by row ID. */
|
|
8
|
+
heightCache = new Map();
|
|
9
|
+
/** Estimated height for unmeasured rows. */
|
|
10
|
+
estimatedRowHeight;
|
|
11
|
+
/** Sum of all measured heights. */
|
|
12
|
+
totalMeasuredHeight = 0;
|
|
13
|
+
/** Number of measured rows. */
|
|
14
|
+
measuredCount = 0;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new HeightManager.
|
|
17
|
+
*
|
|
18
|
+
* @param estimatedRowHeight - Initial estimated height for unmeasured rows.
|
|
19
|
+
*/
|
|
20
|
+
constructor(estimatedRowHeight = 40) {
|
|
21
|
+
this.estimatedRowHeight = estimatedRowHeight;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Set or update the height for a specific row.
|
|
25
|
+
*
|
|
26
|
+
* @param rowId - The unique identifier of the row.
|
|
27
|
+
* @param height - The measured height of the row in pixels.
|
|
28
|
+
* @returns True if the height changed, false otherwise.
|
|
29
|
+
*/
|
|
30
|
+
setHeight(rowId, height) {
|
|
31
|
+
const existing = this.heightCache.get(rowId);
|
|
32
|
+
if (existing === height) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
if (existing !== undefined) {
|
|
36
|
+
// Update existing measurement
|
|
37
|
+
this.totalMeasuredHeight -= existing;
|
|
38
|
+
this.totalMeasuredHeight += height;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// New measurement
|
|
42
|
+
this.totalMeasuredHeight += height;
|
|
43
|
+
this.measuredCount++;
|
|
44
|
+
}
|
|
45
|
+
this.heightCache.set(rowId, height);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get the height for a specific row.
|
|
50
|
+
* Returns the measured height if available, otherwise the estimated height.
|
|
51
|
+
*
|
|
52
|
+
* @param rowId - The unique identifier of the row.
|
|
53
|
+
* @returns The height of the row in pixels.
|
|
54
|
+
*/
|
|
55
|
+
getHeight(rowId) {
|
|
56
|
+
return this.heightCache.get(rowId) ?? this.getAverageHeight();
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Check if a row has been measured.
|
|
60
|
+
*
|
|
61
|
+
* @param rowId - The unique identifier of the row.
|
|
62
|
+
* @returns True if the row has been measured.
|
|
63
|
+
*/
|
|
64
|
+
hasMeasurement(rowId) {
|
|
65
|
+
return this.heightCache.has(rowId);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the average height of measured rows.
|
|
69
|
+
* Falls back to the estimated height if no rows have been measured.
|
|
70
|
+
*
|
|
71
|
+
* @returns The average row height in pixels.
|
|
72
|
+
*/
|
|
73
|
+
getAverageHeight() {
|
|
74
|
+
if (this.measuredCount === 0) {
|
|
75
|
+
return this.estimatedRowHeight;
|
|
76
|
+
}
|
|
77
|
+
return this.totalMeasuredHeight / this.measuredCount;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Calculate the total height for a given number of rows.
|
|
81
|
+
*
|
|
82
|
+
* @param rowIds - Array of row IDs in order.
|
|
83
|
+
* @returns The total height in pixels.
|
|
84
|
+
*/
|
|
85
|
+
getTotalHeight(rowIds) {
|
|
86
|
+
const avgHeight = this.getAverageHeight();
|
|
87
|
+
let total = 0;
|
|
88
|
+
for (const rowId of rowIds) {
|
|
89
|
+
total += this.heightCache.get(rowId) ?? avgHeight;
|
|
90
|
+
}
|
|
91
|
+
return total;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Calculate the offset (top position) for a given row index.
|
|
95
|
+
*
|
|
96
|
+
* @param rowIds - Array of row IDs in order.
|
|
97
|
+
* @param index - The index of the target row.
|
|
98
|
+
* @returns The offset from the top in pixels.
|
|
99
|
+
*/
|
|
100
|
+
getOffsetForIndex(rowIds, index) {
|
|
101
|
+
const avgHeight = this.getAverageHeight();
|
|
102
|
+
let offset = 0;
|
|
103
|
+
for (let i = 0; i < index && i < rowIds.length; i++) {
|
|
104
|
+
offset += this.heightCache.get(rowIds[i]) ?? avgHeight;
|
|
105
|
+
}
|
|
106
|
+
return offset;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Calculate which rows are visible given a scroll position and viewport height.
|
|
110
|
+
*
|
|
111
|
+
* @param rowIds - Array of row IDs in order.
|
|
112
|
+
* @param scrollTop - Current scroll position.
|
|
113
|
+
* @param viewportHeight - Height of the visible area.
|
|
114
|
+
* @param bufferSize - Number of extra rows to render above/below.
|
|
115
|
+
* @returns Object with start and end indices of visible rows.
|
|
116
|
+
*/
|
|
117
|
+
getVisibleRange(rowIds, scrollTop, viewportHeight, bufferSize) {
|
|
118
|
+
if (rowIds.length === 0) {
|
|
119
|
+
return { start: 0, end: 0 };
|
|
120
|
+
}
|
|
121
|
+
const avgHeight = this.getAverageHeight();
|
|
122
|
+
let offset = 0;
|
|
123
|
+
let start = 0;
|
|
124
|
+
let end = rowIds.length;
|
|
125
|
+
// Find start index (first row that's at least partially visible)
|
|
126
|
+
for (let i = 0; i < rowIds.length; i++) {
|
|
127
|
+
const height = this.heightCache.get(rowIds[i]) ?? avgHeight;
|
|
128
|
+
if (offset + height > scrollTop) {
|
|
129
|
+
start = Math.max(0, i - bufferSize);
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
offset += height;
|
|
133
|
+
}
|
|
134
|
+
// Find end index (first row that's completely below the viewport)
|
|
135
|
+
const bottomEdge = scrollTop + viewportHeight;
|
|
136
|
+
for (let i = start; i < rowIds.length; i++) {
|
|
137
|
+
const height = this.heightCache.get(rowIds[i]) ?? avgHeight;
|
|
138
|
+
if (offset >= bottomEdge) {
|
|
139
|
+
end = Math.min(rowIds.length, i + bufferSize);
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
offset += height;
|
|
143
|
+
}
|
|
144
|
+
// If we reached the end without finding bottomEdge, show all remaining rows
|
|
145
|
+
if (end === rowIds.length) {
|
|
146
|
+
end = rowIds.length;
|
|
147
|
+
}
|
|
148
|
+
return { start, end };
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Find the row index at a given scroll position.
|
|
152
|
+
*
|
|
153
|
+
* @param rowIds - Array of row IDs in order.
|
|
154
|
+
* @param scrollTop - The scroll position to find.
|
|
155
|
+
* @returns The index of the row at that position.
|
|
156
|
+
*/
|
|
157
|
+
getIndexAtOffset(rowIds, scrollTop) {
|
|
158
|
+
const avgHeight = this.getAverageHeight();
|
|
159
|
+
let offset = 0;
|
|
160
|
+
for (let i = 0; i < rowIds.length; i++) {
|
|
161
|
+
const height = this.heightCache.get(rowIds[i]) ?? avgHeight;
|
|
162
|
+
if (offset + height > scrollTop) {
|
|
163
|
+
return i;
|
|
164
|
+
}
|
|
165
|
+
offset += height;
|
|
166
|
+
}
|
|
167
|
+
return Math.max(0, rowIds.length - 1);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Clear all cached heights.
|
|
171
|
+
*/
|
|
172
|
+
clear() {
|
|
173
|
+
this.heightCache.clear();
|
|
174
|
+
this.totalMeasuredHeight = 0;
|
|
175
|
+
this.measuredCount = 0;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Remove a specific row from the cache.
|
|
179
|
+
*
|
|
180
|
+
* @param rowId - The unique identifier of the row to remove.
|
|
181
|
+
*/
|
|
182
|
+
remove(rowId) {
|
|
183
|
+
const height = this.heightCache.get(rowId);
|
|
184
|
+
if (height !== undefined) {
|
|
185
|
+
this.totalMeasuredHeight -= height;
|
|
186
|
+
this.measuredCount--;
|
|
187
|
+
this.heightCache.delete(rowId);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get the number of measured rows.
|
|
192
|
+
*/
|
|
193
|
+
get size() {
|
|
194
|
+
return this.measuredCount;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Update the estimated row height.
|
|
198
|
+
*
|
|
199
|
+
* @param height - New estimated height in pixels.
|
|
200
|
+
*/
|
|
201
|
+
setEstimatedRowHeight(height) {
|
|
202
|
+
this.estimatedRowHeight = height;
|
|
203
|
+
}
|
|
204
|
+
}
|
package/dist/utils/array.d.ts
CHANGED
|
@@ -1,2 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns an array containing only the distinct elements from the input array.
|
|
3
|
+
* Preserves the order of first occurrence.
|
|
4
|
+
*
|
|
5
|
+
* @template T - The type of elements in the array.
|
|
6
|
+
* @param items - The input array potentially containing duplicates.
|
|
7
|
+
* @returns A new array with duplicate elements removed.
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* getDistinct([1, 2, 2, 3, 1]) // Returns [1, 2, 3]
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
1
13
|
export declare const getDistinct: <T>(items: T[]) => T[];
|
|
14
|
+
/**
|
|
15
|
+
* Returns an array containing only the elements that appear more than once
|
|
16
|
+
* in the input array.
|
|
17
|
+
*
|
|
18
|
+
* @template T - The type of elements in the array.
|
|
19
|
+
* @param items - The input array to check for duplicates.
|
|
20
|
+
* @returns A new array containing only duplicate elements.
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* getDuplicates([1, 2, 2, 3, 1]) // Returns [1, 2]
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
2
26
|
export declare const getDuplicates: <T>(items: T[]) => T[];
|
package/dist/utils/array.js
CHANGED
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
import { getCounter } from './counter.js';
|
|
2
|
+
/**
|
|
3
|
+
* Returns an array containing only the distinct elements from the input array.
|
|
4
|
+
* Preserves the order of first occurrence.
|
|
5
|
+
*
|
|
6
|
+
* @template T - The type of elements in the array.
|
|
7
|
+
* @param items - The input array potentially containing duplicates.
|
|
8
|
+
* @returns A new array with duplicate elements removed.
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* getDistinct([1, 2, 2, 3, 1]) // Returns [1, 2, 3]
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
2
14
|
export const getDistinct = (items) => {
|
|
3
15
|
return Array.from(getCounter(items).keys());
|
|
4
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Returns an array containing only the elements that appear more than once
|
|
19
|
+
* in the input array.
|
|
20
|
+
*
|
|
21
|
+
* @template T - The type of elements in the array.
|
|
22
|
+
* @param items - The input array to check for duplicates.
|
|
23
|
+
* @returns A new array containing only duplicate elements.
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* getDuplicates([1, 2, 2, 3, 1]) // Returns [1, 2]
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
5
29
|
export const getDuplicates = (items) => {
|
|
6
30
|
return Array.from(getCounter(items).entries())
|
|
7
31
|
.filter(([, count]) => count !== 1)
|
|
@@ -1,2 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merges two attribute objects, with special handling for style properties.
|
|
3
|
+
* Style objects are deeply merged rather than overwritten.
|
|
4
|
+
*
|
|
5
|
+
* @template T - The type of the first attributes object.
|
|
6
|
+
* @template U - The type of the second attributes object.
|
|
7
|
+
* @param a - The first attributes object.
|
|
8
|
+
* @param b - The second attributes object (takes precedence for non-style properties).
|
|
9
|
+
* @returns A merged attributes object with combined styles.
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* mergeAttributes(
|
|
13
|
+
* { class: 'foo', style: { color: 'red' } },
|
|
14
|
+
* { class: 'bar', style: { fontSize: '14px' } }
|
|
15
|
+
* )
|
|
16
|
+
* // Returns { class: 'bar', style: { color: 'red', fontSize: '14px' } }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
1
19
|
export declare const mergeAttributes: <T extends Record<string, unknown>, U extends Record<string, unknown>>(a: T, b: U) => T & U;
|
|
20
|
+
/**
|
|
21
|
+
* Converts an attributes object's style property from an object to a CSS string.
|
|
22
|
+
* This prepares attributes for use in DOM elements.
|
|
23
|
+
*
|
|
24
|
+
* @template T - The type of the attributes object.
|
|
25
|
+
* @param attrs - The attributes object with a potential style object.
|
|
26
|
+
* @returns A new attributes object with the style converted to a string.
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* finalizeAttributes({ class: 'foo', style: { color: 'red' } })
|
|
30
|
+
* // Returns { class: 'foo', style: 'color:red' }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
2
33
|
export declare const finalizeAttributes: <T extends Record<string, unknown>>(attrs: T) => Record<string, unknown>;
|
package/dist/utils/attributes.js
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
import { stringifyCss } from './css.js';
|
|
2
|
+
/**
|
|
3
|
+
* Merges two attribute objects, with special handling for style properties.
|
|
4
|
+
* Style objects are deeply merged rather than overwritten.
|
|
5
|
+
*
|
|
6
|
+
* @template T - The type of the first attributes object.
|
|
7
|
+
* @template U - The type of the second attributes object.
|
|
8
|
+
* @param a - The first attributes object.
|
|
9
|
+
* @param b - The second attributes object (takes precedence for non-style properties).
|
|
10
|
+
* @returns A merged attributes object with combined styles.
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* mergeAttributes(
|
|
14
|
+
* { class: 'foo', style: { color: 'red' } },
|
|
15
|
+
* { class: 'bar', style: { fontSize: '14px' } }
|
|
16
|
+
* )
|
|
17
|
+
* // Returns { class: 'bar', style: { color: 'red', fontSize: '14px' } }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
2
20
|
export const mergeAttributes = (a, b) => {
|
|
3
21
|
if (a.style === undefined && b.style === undefined) {
|
|
4
22
|
return { ...a, ...b };
|
|
@@ -12,6 +30,19 @@ export const mergeAttributes = (a, b) => {
|
|
|
12
30
|
}
|
|
13
31
|
};
|
|
14
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Converts an attributes object's style property from an object to a CSS string.
|
|
35
|
+
* This prepares attributes for use in DOM elements.
|
|
36
|
+
*
|
|
37
|
+
* @template T - The type of the attributes object.
|
|
38
|
+
* @param attrs - The attributes object with a potential style object.
|
|
39
|
+
* @returns A new attributes object with the style converted to a string.
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* finalizeAttributes({ class: 'foo', style: { color: 'red' } })
|
|
43
|
+
* // Returns { class: 'foo', style: 'color:red' }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
15
46
|
export const finalizeAttributes = (attrs) => {
|
|
16
47
|
if (attrs.style === undefined || typeof attrs.style !== 'object') {
|
|
17
48
|
return attrs;
|
package/dist/utils/clone.d.ts
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for objects that can create a copy of themselves.
|
|
3
|
+
*
|
|
4
|
+
* @template T - The type of the cloned object.
|
|
5
|
+
*/
|
|
1
6
|
export interface Clonable<T> {
|
|
7
|
+
/** Creates and returns a copy of the object. */
|
|
2
8
|
clone(): T;
|
|
3
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Type guard that checks if an object implements the Clonable interface.
|
|
12
|
+
*
|
|
13
|
+
* @template T - The expected type of the cloned object.
|
|
14
|
+
* @param obj - The object to check.
|
|
15
|
+
* @returns True if the object has a clone method.
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* if (isClonable(obj)) {
|
|
19
|
+
* const copy = obj.clone()
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
4
23
|
export declare const isClonable: <T>(obj: unknown) => obj is Clonable<T>;
|
|
5
24
|
/**
|
|
6
25
|
* Create a new instance of a class instance with all properties shallow
|