@lavalogic/scoria 0.17.2 → 0.18.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 (46) hide show
  1. package/dist/Components/Table/Body/QuickSearchCell.svelte +78 -73
  2. package/dist/Components/Table/Body/Rows/ColumnList.svelte +1 -1
  3. package/dist/Components/Table/Body/Rows/ColumnListRowProps.d.ts +1 -1
  4. package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +12 -6
  5. package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +15 -35
  6. package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +15 -35
  7. package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +35 -4
  8. package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +60 -26
  9. package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +14 -35
  10. package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +35 -5
  11. package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +82 -139
  12. package/dist/Components/Table/Body/Rows/Columns/TableDatePickerProps.d.ts +1 -1
  13. package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +15 -35
  14. package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte.d.ts +1 -2
  15. package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +14 -34
  16. package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +93 -37
  17. package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte.d.ts +12 -13
  18. package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +14 -34
  19. package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +14 -34
  20. package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +40 -61
  21. package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte.d.ts +12 -11
  22. package/dist/Components/Table/ColumnDefinitions/ExampleItemColumnDefRepository.svelte.js +39 -29
  23. package/dist/Components/Table/Misc/FilterInput.svelte +1 -1
  24. package/dist/Components/Table/Table.svelte +15 -16
  25. package/dist/Components/Table/Types/Columns/DateColumn.d.ts +2 -2
  26. package/dist/Components/Table/Types/Columns/DateTableCell.d.ts +2 -2
  27. package/dist/Components/Table/Types/Columns/Definitions/ColumnDefSet.d.ts +1 -1
  28. package/dist/Components/Table/Types/Columns/Definitions/JSONColumnDefSet.d.ts +1 -1
  29. package/dist/Components/Table/Types/Columns/Definitions/ValidationFn.d.ts +1 -1
  30. package/dist/Components/Table/Types/Context/ITable.d.ts +0 -1
  31. package/dist/Components/Table/Types/Context/Row.d.ts +3 -3
  32. package/dist/Components/Table/Types/Context/TableContext.svelte.d.ts +16 -22
  33. package/dist/Components/Table/Types/Context/TableContext.svelte.js +299 -275
  34. package/dist/Components/Table/Types/DataRepository/IDataRepository.d.ts +1 -1
  35. package/dist/Components/Table/Types/DataRepository/ILocalDataRepository.d.ts +1 -1
  36. package/dist/Components/Table/Types/DataRepository/LocalTableDataRepository.svelte.d.ts +2 -2
  37. package/dist/Components/Table/Types/DataRepository/LocalTableDataRepository.svelte.js +23 -7
  38. package/dist/Components/Table/Types/DataRepository/TableDataRepository.svelte.d.ts +2 -2
  39. package/dist/Components/Table/Types/DataRepository/TableDataRepository.svelte.js +2 -4
  40. package/dist/Components/Table/Types/Focus/TableFocusDetails.svelte.d.ts +18 -36
  41. package/dist/Components/Table/Types/Focus/TableFocusDetails.svelte.js +77 -113
  42. package/dist/Components/TextInput.svelte +11 -4
  43. package/dist/Components/Touch/DateModal.svelte +26 -14
  44. package/dist/Helpers/Helpers.svelte.d.ts +5 -1
  45. package/dist/Helpers/Helpers.svelte.js +9 -10
  46. package/package.json +14 -14
@@ -1,5 +1,5 @@
1
1
  import { browser, dev } from '$app/environment';
2
- import { asyncAll, asyncFilterIndices, asyncForEach, asyncMap, asyncSleep, devCatch, getCanvasContext, getErrorMessage, } from '../../../../Helpers/Helpers.svelte.js';
2
+ import { asyncAll, asyncForEach, asyncMap, asyncSleep, devCatch, getCanvasContext, } from '../../../../Helpers/Helpers.svelte.js';
3
3
  import { tick, untrack } from 'svelte';
4
4
  import { SvelteMap, SvelteSet } from 'svelte/reactivity';
5
5
  import { ColumnType } from '../Columns/ColumnType.js';
@@ -13,7 +13,6 @@ import { BubbleDef } from '../Columns/Definitions/Display/BubbleDef.svelte.js';
13
13
  import { DisplayDef } from '../Columns/Definitions/Display/DisplayDef.svelte.js';
14
14
  import { ProgressBarDef } from '../Columns/Definitions/Display/ProgressBarDef.svelte.js';
15
15
  import { RowSelectionDef } from '../Columns/Definitions/RowSelection/RowSelectionDef.svelte.js';
16
- import { allowedEmptyFilterModes } from '../DataRepository/LocalTableDataRepository.svelte.js';
17
16
  import { PaginationType } from '../Pagination/PaginationType.js';
18
17
  import { ToolbarPosition } from '../Toolbar/ToolbarPosition.js';
19
18
  const SORTING_ICON_WIDTH = 24;
@@ -71,6 +70,7 @@ export class TableContext {
71
70
  $effect(() => {
72
71
  void this.currentPageData;
73
72
  void this.selectedItems;
73
+ void this.paginationRepo?.paginationState.pageIndex;
74
74
  untrack(async () => {
75
75
  await this.currentPageData;
76
76
  if (this.paginationRepo?.paginationState.pageIndex != undefined) {
@@ -80,6 +80,62 @@ export class TableContext {
80
80
  }
81
81
  }).catch(devCatch);
82
82
  });
83
+ let filteredIndicesAbortController = null;
84
+ $effect(() => {
85
+ (async () => {
86
+ void this.dataRepo.filtering;
87
+ void this.dataRepo.data;
88
+ void this.columnDefsById;
89
+ filteredIndicesAbortController?.abort();
90
+ const currentController = (filteredIndicesAbortController = new AbortController());
91
+ const data = this.dataRepo.data;
92
+ const columnDefsById = this.columnDefsById;
93
+ // if (!$effect.tracking()) {
94
+ // // console.warn(`filtered indices are not in a tracking context`);
95
+ // throw new Error(`filtered indices are not in a tracking context`);
96
+ // }
97
+ if (!this.dataRepo.filtering.length) {
98
+ this._filteredIndices = data.map((_item, index) => {
99
+ return index;
100
+ });
101
+ }
102
+ else {
103
+ await asyncSleep(300);
104
+ const filtered = [];
105
+ for (let index = 0; index < data.length; ++index) {
106
+ if (currentController.signal.aborted) {
107
+ if (dev) {
108
+ console.log(`filtered indices have been aborted`);
109
+ }
110
+ return;
111
+ }
112
+ const item = data[index];
113
+ const row = this.createRow(item, index, index);
114
+ const x = await asyncAll(this.dataRepo.filtering, async (filter) => {
115
+ if (currentController.signal.aborted) {
116
+ return false;
117
+ }
118
+ const def = columnDefsById.get(filter.id);
119
+ if (!def) {
120
+ console.warn(`Could not find column def for filter with id ${filter.id}`);
121
+ return false;
122
+ }
123
+ if (def.filterFn) {
124
+ return await def.filterFn(row, filter.id, filter.value); //HACK how much parsing will be needed to be type safe?
125
+ }
126
+ if (this.debug) {
127
+ console.warn(`column ${def.id} did not have a filter function`);
128
+ }
129
+ return false;
130
+ });
131
+ if (x) {
132
+ filtered.push(index);
133
+ }
134
+ }
135
+ this._filteredIndices = filtered;
136
+ }
137
+ })().catch(devCatch);
138
+ });
83
139
  if (defaultColumnDefs.remoteFilters) {
84
140
  this.remoteFilters = defaultColumnDefs.remoteFilters;
85
141
  }
@@ -153,110 +209,6 @@ export class TableContext {
153
209
  })
154
210
  .catch(devCatch);
155
211
  }
156
- $effect(() => {
157
- void this.paginationRepo?.paginationType;
158
- void this.dataRepo.filtering;
159
- void this.dataRepo.filterModes;
160
- void this.dataRepo.data;
161
- void this.paginationRepo?.paginationState;
162
- // console.log('massive effect start');
163
- (async () => {
164
- const startTime = Date.now();
165
- let currentTimer;
166
- const abortController = new AbortController();
167
- try {
168
- if (this.paginationRepo?.paginationType == PaginationType.Local) {
169
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
170
- const checkedIds = new Set();
171
- const filterState = this.dataRepo.filtering.filter((filter) => {
172
- const snapshot = $state.snapshot(filter.value);
173
- checkedIds.add(filter.id);
174
- const filterMode = this.dataRepo.filterModes.get(filter.id);
175
- return ((snapshot !== '' &&
176
- snapshot != null &&
177
- (!Array.isArray(snapshot) || !!snapshot[0])) ||
178
- (!!filterMode && allowedEmptyFilterModes.has(filterMode)));
179
- });
180
- const data = this.dataRepo.data;
181
- currentTimer = ++this.filterTimer;
182
- await asyncSleep(150);
183
- if (currentTimer != this.filterTimer) {
184
- throw new Error('stale filter');
185
- }
186
- if (!filterState.length) {
187
- if (dev) {
188
- console.log('no filter state was found');
189
- }
190
- this.filteredIndices = data.map((_item, index) => {
191
- return index;
192
- });
193
- }
194
- else {
195
- this.dataRepo.isLoading = true;
196
- if (this.debug) {
197
- console.log('getting filter promise');
198
- }
199
- const settled = $state({ value: false });
200
- const filterPromise = asyncFilterIndices(data, async (item, index) => {
201
- const row = this.createRow(item, index, index);
202
- return asyncAll(filterState, async (filter) => {
203
- abortController.signal.throwIfAborted();
204
- const def = this.columnDefsById.get(filter.id);
205
- if (!def) {
206
- console.warn(`Could not find column def for filter with id ${filter.id}`);
207
- return false;
208
- }
209
- if (def.filterFn) {
210
- return def.filterFn(row, filter.id, filter.value); //HACK how much parsing will be needed to be type safe?
211
- }
212
- if (this.debug) {
213
- console.warn(`column ${def.id} did not have a filter function`);
214
- }
215
- return false;
216
- });
217
- });
218
- filterPromise
219
- .then((indices) => {
220
- if (this.debug) {
221
- console.log(`iteration ${currentTimer}: got indices from filter promise:`, indices);
222
- }
223
- this.filteredIndices = indices;
224
- })
225
- .catch((e) => {
226
- if (this.debug) {
227
- console.log(`caught filter rejection:`, e);
228
- console.log(`iteration ${currentTimer} cancelled after ${Date.now() - startTime}ms`);
229
- }
230
- })
231
- .finally(() => {
232
- if (this.debug) {
233
- console.log(`timer ${currentTimer} is settled`);
234
- }
235
- settled.value = true;
236
- if (currentTimer === this.filterTimer) {
237
- this.dataRepo.isLoading = false;
238
- }
239
- else if (this.debug) {
240
- console.warn(`skipping disabling load overlay because current timer is ${currentTimer} but newest is ${this.filterTimer}`);
241
- }
242
- });
243
- await this.filteringLoop(currentTimer, abortController, settled, startTime);
244
- }
245
- }
246
- }
247
- catch (e) {
248
- if (dev) {
249
- const message = getErrorMessage(e);
250
- if (!message.toLocaleLowerCase().startsWith('stale')) {
251
- console.error(`Iteration ${currentTimer}`, e);
252
- }
253
- else {
254
- console.log(`iteration ${currentTimer} cancelled after ${Date.now() - startTime}ms`);
255
- }
256
- }
257
- }
258
- })().catch(devCatch);
259
- });
260
212
  }
261
213
  // #endregion
262
214
  // #region stores
@@ -346,24 +298,52 @@ export class TableContext {
346
298
  set selectedPreset(v) {
347
299
  this._selectedPreset = v;
348
300
  }
349
- _focusedRowIndexIds = $state(new SvelteSet());
350
- get focusedRowIndexIds() {
351
- return this._focusedRowIndexIds;
352
- }
353
- set focusedRowIndexIds(v) {
354
- this._focusedRowIndexIds = v;
355
- }
301
+ _pageColData = $derived.by(async () => {
302
+ if (!this.focusStart || !this.focusEnd) {
303
+ return { indices: new SvelteSet(), affectedColumns: new SvelteSet() };
304
+ }
305
+ const { row: startRowIndexId, column: startColumnIndex } = this.focusStart;
306
+ const { row: endRowIndexId, column: endColumnIndex } = this.focusEnd;
307
+ const model = await this.sortedRowModel;
308
+ const startRowIndex = model.rows.findIndex((row) => row.visibleIndex === startRowIndexId);
309
+ const endRowIndex = model.rows.findIndex((row) => row.visibleIndex === endRowIndexId);
310
+ if (startRowIndex == -1 || endRowIndex == -1) {
311
+ return { indices: new SvelteSet(), affectedColumns: new SvelteSet() };
312
+ }
313
+ const minRowIndex = Math.min(startRowIndex, endRowIndex);
314
+ const maxRowIndex = Math.max(startRowIndex, endRowIndex);
315
+ const minColumnIndex = Math.min(startColumnIndex, endColumnIndex);
316
+ const maxColumnIndex = Math.max(startColumnIndex, endColumnIndex);
317
+ const affectedColumns = new SvelteSet();
318
+ const visibility = this.columnVisibility;
319
+ this.columnDefs
320
+ .filter((it) => 'index' in it &&
321
+ visibility[it.id] !== false &&
322
+ // TODO handle pinning behaviour
323
+ // !columnPinning.left?.includes(it.id) &&
324
+ // !columnPinning.right?.includes(it.id) &&
325
+ // (!('columnType' in it) || it.columnType === undefined || it.columnType === 'Accessor') &&
326
+ it.index >= minColumnIndex &&
327
+ it.index <= maxColumnIndex)
328
+ .forEach((it) => affectedColumns.add(it.id));
329
+ const indices = new SvelteSet();
330
+ for (let i = minRowIndex; i <= maxRowIndex; i++) {
331
+ indices.add(parseInt(model.rows[i].id));
332
+ }
333
+ return { indices, affectedColumns };
334
+ });
335
+ focusedRowIndices = $derived.by(async () => {
336
+ void this._pageColData;
337
+ return (await this._pageColData).indices;
338
+ });
356
339
  _highlightedItems = $state(new SvelteMap());
357
340
  get highlightedItems() {
358
341
  return this._highlightedItems;
359
342
  }
360
- _focusedColumnIds = $state(new SvelteSet());
361
- get focusedColumnIds() {
362
- return this._focusedColumnIds;
363
- }
364
- set focusedColumnIds(v) {
365
- this._focusedColumnIds = v;
366
- }
343
+ focusedColumnIds = $derived.by(async () => {
344
+ void this._pageColData;
345
+ return (await this._pageColData).affectedColumns;
346
+ });
367
347
  _isMousingDown = $state(false);
368
348
  get isMousingDown() {
369
349
  return this._isMousingDown;
@@ -377,7 +357,6 @@ export class TableContext {
377
357
  }
378
358
  set focusStart(v) {
379
359
  this._focusStart = v;
380
- this._recalculateFocusedElements().catch(devCatch);
381
360
  }
382
361
  _focusStartIsBeingEdited = $state(false);
383
362
  get focusStartIsBeingEdited() {
@@ -392,7 +371,6 @@ export class TableContext {
392
371
  }
393
372
  set focusEnd(v) {
394
373
  this._focusEnd = v;
395
- this._recalculateFocusedElements().catch(devCatch);
396
374
  }
397
375
  _singleClickEditing = $state(false);
398
376
  get singleClickEditing() {
@@ -534,9 +512,6 @@ export class TableContext {
534
512
  get selectedItems() {
535
513
  return this._selectedItems;
536
514
  }
537
- set selectedItems(v) {
538
- this._selectedItems = v;
539
- }
540
515
  _invalidValues = $state(new SvelteMap());
541
516
  get invalidValues() {
542
517
  return this._invalidValues;
@@ -552,8 +527,7 @@ export class TableContext {
552
527
  this._hasInvalidSelectedItems = v;
553
528
  }
554
529
  // FIXME decide
555
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
556
- columnDefsById = $derived(new Map(this.columnDefs.map((it) => [it.id, it])));
530
+ columnDefsById = $derived(new SvelteMap(this.columnDefs.map((it) => [it.id, it])));
557
531
  getSortingFn = (id, desc) => {
558
532
  if (this.dataRepo.data.length == 0) {
559
533
  return undefined;
@@ -582,60 +556,66 @@ export class TableContext {
582
556
  // }
583
557
  return comparableSortingFn(id, desc);
584
558
  };
585
- // private _filterTimer: ReturnType<typeof setTimeout> | undefined;
586
- _filterTimer = 1;
587
- get filterTimer() {
588
- return this._filterTimer;
589
- }
590
- set filterTimer(v) {
591
- this._filterTimer = v;
592
- }
593
559
  _filteredIndices = $state([]);
594
560
  get filteredIndices() {
595
561
  return this._filteredIndices;
596
562
  }
597
- set filteredIndices(v) {
598
- if (this.debug) {
599
- console.log('updating filtered indices');
600
- }
601
- this._filteredIndices = v;
602
- }
603
- filteredData = $derived.by(() => {
563
+ filteredData = $derived.by(async () => {
604
564
  void this.dataRepo.data;
605
565
  void this.filteredIndices;
606
566
  void this.showSelectedOnly;
607
- const dataRepo = this.dataRepo;
567
+ void this.selectedItems.size;
608
568
  if (this.paginationRepo?.paginationType == PaginationType.Local) {
609
569
  const data = this.showSelectedOnly
610
570
  ? // FIXME this will show the selected items by order of insertion to the selectedItems map.
611
571
  [...this.selectedItems.values()]
612
572
  : this.filteredIndices.map((index) => {
613
- return dataRepo.data[index];
573
+ return this.dataRepo.data[index];
614
574
  });
615
575
  return data;
616
576
  }
617
577
  if (this.debug) {
618
578
  console.log(`updating filtered data. Selected only: ${this.showSelectedOnly}`);
619
579
  }
620
- return this.showSelectedOnly ? [...this.selectedItems.values()] : dataRepo.data;
580
+ return this.showSelectedOnly ? [...this.selectedItems.values()] : this.dataRepo.data;
621
581
  });
622
- // eslint-disable-next-line @typescript-eslint/require-await
582
+ sortedDataAbortController = null;
623
583
  sortedData = $derived.by(async () => {
584
+ // if (!$effect.tracking()) {
585
+ // throw new Error(`sorted data is not in a tracking context`);
586
+ // }
587
+ void this.filteredData;
588
+ void this.dataRepo.sorting;
589
+ this.sortedDataAbortController?.abort();
590
+ const currentController = (this.sortedDataAbortController = new AbortController());
624
591
  if (this.debug) {
625
592
  console.log('sorted data');
626
593
  }
627
- const fd = this.filteredData;
628
- const sorting = this.dataRepo.sorting;
629
594
  if (this.paginationRepo?.paginationType == PaginationType.Local) {
630
- const dataToSort = fd.concat();
595
+ const data = await this.filteredData;
596
+ if (currentController.signal.aborted) {
597
+ return [];
598
+ }
599
+ const dataToSort = data.concat();
631
600
  dataToSort.sort((a, b) => {
632
- const end = sorting.length;
601
+ if (currentController.signal.aborted) {
602
+ return 0;
603
+ }
604
+ const end = this.dataRepo.sorting.length;
633
605
  for (let i = 0; i < end; i++) {
634
- const { id, desc } = sorting[i];
606
+ const { id, desc } = this.dataRepo.sorting[i];
635
607
  const sortingFn = this.getSortingFn(id, desc);
636
608
  if (sortingFn) {
609
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
610
+ if (currentController.signal.aborted) {
611
+ return 0;
612
+ }
637
613
  const result = sortingFn(a, b);
638
614
  if (result != 0) {
615
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
616
+ if (currentController.signal.aborted) {
617
+ return 0;
618
+ }
639
619
  return result;
640
620
  }
641
621
  }
@@ -647,11 +627,14 @@ export class TableContext {
647
627
  });
648
628
  return dataToSort;
649
629
  }
650
- return fd;
630
+ return this.filteredData;
651
631
  });
652
632
  sortedRowModel = $derived.by(async () => {
653
633
  void this.originalRowIndices;
654
634
  void this.sortedData;
635
+ // if (!$effect.tracking()) {
636
+ // throw new Error(`filtered indices are not in a tracking context`);
637
+ // }
655
638
  const sd = await this.sortedData;
656
639
  const ori = await this.originalRowIndices;
657
640
  const rows = await asyncMap(sd, async (item, index) => {
@@ -662,54 +645,110 @@ export class TableContext {
662
645
  }
663
646
  return this.createRow(item, index, unsortedIndex);
664
647
  });
648
+ const rowsById = $derived(new SvelteMap(rows.map((it, index) => [index.toString(), it]))); //FIXME should this be by sorted id or by original id?
665
649
  return {
666
- rows,
667
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
668
- rowsById: new Map(rows.map((it, index) => [index.toString(), it])), //FIXME should this be by sorted id or by original id?
650
+ get rows() {
651
+ return rows;
652
+ },
653
+ get rowsById() {
654
+ return rowsById;
655
+ },
669
656
  };
670
657
  });
658
+ CurrentPageDataAbortController = null;
671
659
  currentPageData = $derived.by(async () => {
660
+ // void this.originalRowIndices;
672
661
  void this.sortedData;
673
- const dataRepo = this.dataRepo;
662
+ void this.dataRepo.pageStartIndex;
663
+ void this.dataRepo.pageEndIndexExclusive;
664
+ // if (!$effect.tracking()) {
665
+ // throw new Error(`Current Page Data is not in a tracking context`);
666
+ // }
667
+ this.CurrentPageDataAbortController?.abort();
668
+ const currentController = (this.CurrentPageDataAbortController = new AbortController());
674
669
  const sd = await this.sortedData;
675
- if (dataRepo.paginationType != PaginationType.Local) {
670
+ if (currentController.signal.aborted) {
671
+ return [];
672
+ }
673
+ if (this.dataRepo.paginationType != PaginationType.Local) {
676
674
  return sd;
677
675
  }
678
- const x = sd.slice(dataRepo.pageStartIndex, dataRepo.pageEndIndexExclusive);
679
- return x;
676
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
677
+ if (currentController.signal.aborted) {
678
+ return [];
679
+ }
680
+ return sd.slice(this.dataRepo.pageStartIndex, this.dataRepo.pageEndIndexExclusive);
680
681
  });
681
- // FIXME this is most likely the cuplrit for add pod not working on receipt. It may be one tick behind the other values
682
+ // FIXME this is most likely the cuplrit for add pod not working on receipt.
683
+ // Tracking changes in a promise of a map is a problem
684
+ // worst case fix: turn it into a map of promises
682
685
  originalRowIndices = $derived.by(async () => {
683
686
  const dataRepo = this.dataRepo;
684
687
  const awaited = await asyncMap(dataRepo.data, async (item, index) => [await this.selectionExtractor(item), index]);
685
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
686
- return new Map(awaited);
688
+ return new SvelteMap(awaited);
687
689
  });
688
- paginationRowModel = $derived.by(async () => {
689
- void this.originalRowIndices;
690
+ rowsPromiseAbortController = null;
691
+ rowsPromise = $derived.by(async () => {
692
+ // void this.originalRowIndices;
690
693
  void this.currentPageData;
691
- void this.columnDefsById;
694
+ // void this.columnDefsById;
692
695
  void this.columnVisibility;
693
696
  void this.paginationRepo?.sorting;
694
697
  void this.columnPinning;
698
+ this.rowsPromiseAbortController?.abort();
699
+ const currentController = (this.rowsPromiseAbortController = new AbortController());
695
700
  const currentPageData = await this.currentPageData;
696
- const rows = await asyncMap(currentPageData, async (item, index) => {
697
- const unsortedIndex = (await this.originalRowIndices).get(item) ?? index;
698
- const row = {
699
- getValue: async (key) => {
701
+ if (currentController.signal.aborted) {
702
+ return [];
703
+ }
704
+ const indices = await this.originalRowIndices;
705
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
706
+ if (currentController.signal.aborted) {
707
+ return [];
708
+ }
709
+ return currentPageData.map((item, index) => {
710
+ const unsortedIndex = indices.get(item) ?? index;
711
+ const getValue = $derived.by(() => {
712
+ void item;
713
+ void index;
714
+ return async (key) => {
715
+ void item;
716
+ void index;
717
+ // if (!$effect.tracking()) {
718
+ // throw new Error(`filtered indices are not in a tracking context`);
719
+ // }
700
720
  const gotValue = await this.columnDefsById.get(key)?.accessorFn?.(item, index);
701
721
  if (gotValue !== undefined) {
702
722
  return gotValue;
703
723
  }
704
724
  return item[key];
725
+ };
726
+ });
727
+ const row = {
728
+ get getValue() {
729
+ return getValue;
730
+ },
731
+ get original() {
732
+ return item;
733
+ },
734
+ get visibleIndex() {
735
+ return index;
736
+ },
737
+ get originalIndex() {
738
+ return unsortedIndex;
739
+ },
740
+ get id() {
741
+ return index.toString();
742
+ },
743
+ get getLeftVisibleCells() {
744
+ return () => leftVisibleCells;
745
+ },
746
+ get getRightVisibleCells() {
747
+ return () => rightVisibleCells;
748
+ },
749
+ get getCenterVisibleCells() {
750
+ return () => centerVisibleCells;
705
751
  },
706
- original: item,
707
- visibleIndex: index,
708
- originalIndex: unsortedIndex,
709
- id: index.toString(),
710
- getLeftVisibleCells: () => leftVisibleCells,
711
- getRightVisibleCells: () => rightVisibleCells,
712
- getCenterVisibleCells: () => centerVisibleCells,
713
752
  };
714
753
  const makeRow = (def) => {
715
754
  const isSorted = $derived.by(() => {
@@ -723,24 +762,43 @@ export class TableContext {
723
762
  return 'asc';
724
763
  });
725
764
  const isVisible = $derived(this.columnVisibility[def.id] != false);
765
+ const getToggleSortingHandler = $derived(() => def.allowSorting ? this.getToggleSortingHandler(def) : undefined);
726
766
  return {
727
767
  column: {
728
- columnDef: def,
729
- getCanSort: () => def.allowSorting,
730
- getIsResizing: () => def.isResizing,
731
- getIsSorted: () => isSorted,
732
- getIsVisible: () => isVisible,
733
- getToggleSortingHandler: () => def.allowSorting ? this.getToggleSortingHandler(def) : undefined,
734
- id: def.id,
768
+ get columnDef() {
769
+ return def;
770
+ },
771
+ get getCanSort() {
772
+ return () => def.allowSorting;
773
+ },
774
+ get getIsResizing() {
775
+ return () => def.isResizing;
776
+ },
777
+ get getIsSorted() {
778
+ return () => isSorted;
779
+ },
780
+ get getIsVisible() {
781
+ return () => isVisible;
782
+ },
783
+ get id() {
784
+ return def.id;
785
+ },
786
+ get getToggleSortingHandler() {
787
+ return getToggleSortingHandler;
788
+ },
735
789
  },
736
790
  id: `${index}_${def.id}`,
737
- row: row,
738
- getValue: () => {
739
- const gotValue = def.accessorFn?.(item, index);
740
- if (gotValue !== undefined) {
741
- return gotValue;
742
- }
743
- return item[def.id];
791
+ get row() {
792
+ return row;
793
+ },
794
+ get getValue() {
795
+ return () => {
796
+ const gotValue = def.accessorFn?.(item, index);
797
+ if (gotValue !== undefined) {
798
+ return gotValue;
799
+ }
800
+ return item[def.id];
801
+ };
744
802
  },
745
803
  };
746
804
  };
@@ -760,19 +818,30 @@ export class TableContext {
760
818
  .map(makeRow));
761
819
  return row;
762
820
  });
821
+ });
822
+ paginationRowModel = $derived.by(async () => {
823
+ void this.rowsPromise;
824
+ const rows = await this.rowsPromise;
763
825
  return {
764
826
  rows,
765
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
766
- rowsById: new Map(rows.map((it, index) => [index.toString(), it])), //FIXME should this be by sorted id or by original id?
827
+ rowsById: new SvelteMap(rows.map((it, index) => [index.toString(), it])), //FIXME should this be by sorted id or by original id?
767
828
  };
768
829
  });
769
830
  // #endregion
770
831
  // #region public methods
771
832
  selectionContains = async (item) => {
833
+ void item;
834
+ void this.isSelectable;
835
+ void this.selectedItems.size;
836
+ // if (!$effect.tracking()) {
837
+ // throw new Error(`selectionContains is not ran in a tracking context`);
838
+ // }
772
839
  if (!this.isSelectable) {
773
840
  return true;
774
841
  }
775
- return this.selectedItems.has(await this.selectionExtractor(item));
842
+ const identity = await this.selectionExtractor(item);
843
+ const has = this.selectedItems.has(identity);
844
+ return has;
776
845
  };
777
846
  addInvalidValue = async (item) => {
778
847
  this.invalidValues.set(await this.selectionExtractor(item), item);
@@ -795,7 +864,16 @@ export class TableContext {
795
864
  resetHighlightedRows = () => {
796
865
  this.highlightedItems.clear();
797
866
  };
798
- toggleSelected = async (item, selected) => {
867
+ toggleSelected = async (item) => {
868
+ const key = await this.selectionExtractor(item);
869
+ if (this.selectedItems.has(key)) {
870
+ this.selectedItems.delete(key);
871
+ }
872
+ else {
873
+ this.selectedItems.set(key, item);
874
+ }
875
+ };
876
+ setSelected = async (item, selected) => {
799
877
  const key = await this.selectionExtractor(item);
800
878
  if (selected) {
801
879
  this.selectedItems.set(key, item);
@@ -805,7 +883,7 @@ export class TableContext {
805
883
  }
806
884
  };
807
885
  setSelectionMap = (set) => {
808
- this.selectedItems = set;
886
+ this._selectedItems = set;
809
887
  };
810
888
  updateSelectedItems = async () => {
811
889
  const pageStartIndex = this.paginationRepo ? this.paginationRepo.pageStartIndex : 0;
@@ -1133,14 +1211,13 @@ export class TableContext {
1133
1211
  }
1134
1212
  // this.forceVisibilityUpdate();
1135
1213
  };
1136
- updateColumnSizing = (stateOrCallback) => {
1137
- if (typeof stateOrCallback == 'function') {
1138
- this.columnSizing = stateOrCallback(this.columnSizing);
1139
- }
1140
- else {
1141
- this.columnSizing = stateOrCallback;
1142
- }
1143
- };
1214
+ // public updateColumnSizing: OnChangeFn<ColumnSizingState> = (stateOrCallback) => {
1215
+ // if (typeof stateOrCallback == 'function') {
1216
+ // this.columnSizing = stateOrCallback(this.columnSizing);
1217
+ // } else {
1218
+ // this.columnSizing = stateOrCallback;
1219
+ // }
1220
+ // };
1144
1221
  table = $derived(generateTableOptions(this));
1145
1222
  // private _rowModel = $derived<RowModel<T> | undefined>(this.dataRepo?.data && this.table.rowModel);
1146
1223
  // public get rowModel() {
@@ -1275,8 +1352,7 @@ export class TableContext {
1275
1352
  _performRowCopy = async ({ items, indicesByItem, focusedElementData, affectedColumns, }) => {
1276
1353
  const focusedColumnIds = affectedColumns.map((it) => encapsulate(typeof it.header === 'string' ? it.header : it.id));
1277
1354
  const value = await (async () => {
1278
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
1279
- const selectColumns = new Map();
1355
+ const selectColumns = new SvelteMap();
1280
1356
  for (let i = affectedColumns.length - 1; i > -1; i--) {
1281
1357
  const columnDef = affectedColumns[i];
1282
1358
  if (columnDef instanceof SelectDef) {
@@ -1788,6 +1864,9 @@ export class TableContext {
1788
1864
  console.warn('no focusEnd found');
1789
1865
  return;
1790
1866
  }
1867
+ // if (!$effect.tracking()) {
1868
+ // throw new Error(`_moveFocusEndRow is not in a tracking context.`);
1869
+ // }
1791
1870
  const focusEnd = this.focusEnd;
1792
1871
  const rows = (await this.paginationRowModel).rows;
1793
1872
  const endRowIndex = rows.findIndex((row) => row.visibleIndex === focusEnd.row);
@@ -1809,47 +1888,9 @@ export class TableContext {
1809
1888
  })();
1810
1889
  this.moveFocus({ ...this.focusStart, row: newEndRowIndex });
1811
1890
  }
1812
- async _recalculateFocusedElements() {
1813
- if (!this.focusStart || !this.focusEnd) {
1814
- this.focusedRowIndexIds = new SvelteSet();
1815
- this.focusedColumnIds = new SvelteSet();
1816
- return;
1817
- }
1818
- const { row: startRowIndexId, column: startColumnIndex } = this.focusStart;
1819
- const { row: endRowIndexId, column: endColumnIndex } = this.focusEnd;
1820
- const model = await this.sortedRowModel;
1821
- const startRowIndex = model.rows.findIndex((row) => row.visibleIndex === startRowIndexId);
1822
- const endRowIndex = model.rows.findIndex((row) => row.visibleIndex === endRowIndexId);
1823
- if (startRowIndex == -1 || endRowIndex == -1) {
1824
- return;
1825
- }
1826
- const minRowIndex = Math.min(startRowIndex, endRowIndex);
1827
- const maxRowIndex = Math.max(startRowIndex, endRowIndex);
1828
- const minColumnIndex = Math.min(startColumnIndex, endColumnIndex);
1829
- const maxColumnIndex = Math.max(startColumnIndex, endColumnIndex);
1830
- const affectedColumns = new SvelteSet();
1831
- const visibility = this.columnVisibility;
1832
- this.columnDefs
1833
- .filter((it) => 'index' in it &&
1834
- visibility[it.id] !== false &&
1835
- // TODO handle pinning behaviour
1836
- // !columnPinning.left?.includes(it.id) &&
1837
- // !columnPinning.right?.includes(it.id) &&
1838
- // (!('columnType' in it) || it.columnType === undefined || it.columnType === 'Accessor') &&
1839
- it.index >= minColumnIndex &&
1840
- it.index <= maxColumnIndex)
1841
- .forEach((it) => affectedColumns.add(it.id));
1842
- const indices = new SvelteSet();
1843
- for (let i = minRowIndex; i <= maxRowIndex; i++) {
1844
- indices.add(parseInt(model.rows[i].id));
1845
- }
1846
- this.focusedRowIndexIds = indices;
1847
- this.focusedColumnIds = affectedColumns;
1848
- }
1849
1891
  async getHighlightedRowData() {
1850
1892
  const affectedColumns = this.columnDefs.filter(this.columnDefReturnsTextValue);
1851
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
1852
- const indices = new Map();
1893
+ const indices = new SvelteMap();
1853
1894
  const selectedRows = [...this.highlightedItems.values()];
1854
1895
  const sortedData = await this.sortedData;
1855
1896
  for (const item of selectedRows) {
@@ -1924,8 +1965,7 @@ export class TableContext {
1924
1965
  this.columnDefReturnsTextValue(it));
1925
1966
  });
1926
1967
  const selectedRows = [];
1927
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
1928
- const indices = new Map();
1968
+ const indices = new SvelteMap();
1929
1969
  for (let i = minRowIndex; i <= maxRowIndex; i++) {
1930
1970
  const row = model.rows[i];
1931
1971
  const item = row.original;
@@ -1977,8 +2017,12 @@ export class TableContext {
1977
2017
  affectedColumns,
1978
2018
  };
1979
2019
  }
1980
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
1981
- return { items: [], indicesByItem: new Map(), focusedElementData: [], affectedColumns: [] };
2020
+ return {
2021
+ items: [],
2022
+ indicesByItem: new SvelteMap(),
2023
+ focusedElementData: [],
2024
+ affectedColumns: [],
2025
+ };
1982
2026
  }
1983
2027
  updateDefsBasedOnPinning = () => {
1984
2028
  const leftDefs = [];
@@ -2005,8 +2049,7 @@ export class TableContext {
2005
2049
  return allDefs;
2006
2050
  };
2007
2051
  assertNoDuplicateIds() {
2008
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
2009
- const foundIds = new Set();
2052
+ const foundIds = new SvelteSet();
2010
2053
  this.defaultColumnDefs.defs.forEach((def) => {
2011
2054
  if (foundIds.has(def.id)) {
2012
2055
  throw new Error(`Duplicate Column Definition ID ${def.id} in table ${this.tableName}`);
@@ -2180,15 +2223,13 @@ export class TableContext {
2180
2223
  }
2181
2224
  _setNewPinningState() {
2182
2225
  this.columnPinning = {
2183
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
2184
- left: new Map(this.columnPinning.left &&
2226
+ left: new SvelteMap(this.columnPinning.left &&
2185
2227
  this.columnDefs
2186
2228
  .filter((col) => {
2187
2229
  return this.columnPinning.left?.has(col.id);
2188
2230
  })
2189
2231
  .map((col, index) => [col.id, index])),
2190
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
2191
- right: new Map(this.columnPinning.right &&
2232
+ right: new SvelteMap(this.columnPinning.right &&
2192
2233
  this.columnDefs
2193
2234
  .filter((col) => this.columnPinning.right?.has(col.id))
2194
2235
  .map((col, index) => [col.id, index])),
@@ -2238,22 +2279,6 @@ export class TableContext {
2238
2279
  };
2239
2280
  });
2240
2281
  }
2241
- async filteringLoop(currentTimer, abortController, settled, startTime) {
2242
- for (;;) {
2243
- if (currentTimer !== this.filterTimer) {
2244
- if (this.debug) {
2245
- console.log(`aborting due to stale data`);
2246
- }
2247
- abortController.abort('stale data');
2248
- return;
2249
- }
2250
- if (settled.value) {
2251
- console.log(`iteration ${currentTimer} finished ${Date.now() - startTime}ms`);
2252
- return;
2253
- }
2254
- await tick();
2255
- }
2256
- }
2257
2282
  }
2258
2283
  // #region static functions
2259
2284
  function areDefsEquivalent(newColumnDefs, oldColumnDefs) {
@@ -2283,8 +2308,7 @@ function areDefsEquivalent(newColumnDefs, oldColumnDefs) {
2283
2308
  });
2284
2309
  }
2285
2310
  function columnDefsToMap(defs) {
2286
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
2287
- const map = new Map();
2311
+ const map = new SvelteMap();
2288
2312
  defs.forEach((def) => {
2289
2313
  map.set(def.id, def);
2290
2314
  });
@@ -2450,9 +2474,9 @@ function generateTableOptions(contextObj) {
2450
2474
  get onColumnVisibilityChange() {
2451
2475
  return contextObj.updateVisibility;
2452
2476
  },
2453
- get onColumnSizingChange() {
2454
- return contextObj.updateColumnSizing;
2455
- },
2477
+ // get onColumnSizingChange() {
2478
+ // return contextObj.updateColumnSizing;
2479
+ // },
2456
2480
  get onColumnFiltersChange() {
2457
2481
  return contextObj.updateFilters;
2458
2482
  },