@poirazis/supercomponents-shared 0.0.1

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 (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/dist/index.js +30635 -0
  4. package/dist/index.umd.cjs +12 -0
  5. package/dist/style.css +1 -0
  6. package/package.json +117 -0
  7. package/src/index.js +29 -0
  8. package/src/index.ts +31 -0
  9. package/src/lib/Actions/autoresize_textarea.js +14 -0
  10. package/src/lib/Actions/click_outside.js +80 -0
  11. package/src/lib/Actions/index.js +4 -0
  12. package/src/lib/Actions/position_dropdown.js +129 -0
  13. package/src/lib/SuperButton/SuperButton.svelte +341 -0
  14. package/src/lib/SuperFieldLabel/SuperFieldLabel.svelte +91 -0
  15. package/src/lib/SuperFieldsCommon.css +54 -0
  16. package/src/lib/SuperList/SuperList.svelte +308 -0
  17. package/src/lib/SuperList/drag-handle.svelte +31 -0
  18. package/src/lib/SuperPopover/SuperPopover.svelte +134 -0
  19. package/src/lib/SuperTable/SuperTable.css +410 -0
  20. package/src/lib/SuperTable/SuperTable.svelte +1332 -0
  21. package/src/lib/SuperTable/constants.js +85 -0
  22. package/src/lib/SuperTable/controls/ColumnsSection.svelte +34 -0
  23. package/src/lib/SuperTable/controls/ControlSection.svelte +3 -0
  24. package/src/lib/SuperTable/controls/RowButtonsColumn.svelte +169 -0
  25. package/src/lib/SuperTable/controls/SelectionColumn.svelte +174 -0
  26. package/src/lib/SuperTable/controls/SuperTableWelcome.svelte +58 -0
  27. package/src/lib/SuperTable/overlays/AddNewRowOverlay.svelte +52 -0
  28. package/src/lib/SuperTable/overlays/EmptyResultSetOverlay.svelte +13 -0
  29. package/src/lib/SuperTable/overlays/LoadingOverlay.svelte +3 -0
  30. package/src/lib/SuperTable/overlays/RowContextMenu copy.svelte +57 -0
  31. package/src/lib/SuperTable/overlays/RowContextMenu.svelte +58 -0
  32. package/src/lib/SuperTable/overlays/ScrollbarsOverlay.svelte +184 -0
  33. package/src/lib/SuperTable/overlays/SelectedActionsOverlay.svelte +64 -0
  34. package/src/lib/SuperTable/state/API.js +0 -0
  35. package/src/lib/SuperTable/state/SuperTableStateMachine.js +0 -0
  36. package/src/lib/SuperTable/types.js +0 -0
  37. package/src/lib/SuperTableCells/CellAttachment.svelte +288 -0
  38. package/src/lib/SuperTableCells/CellBoolean.svelte +158 -0
  39. package/src/lib/SuperTableCells/CellColor.svelte +460 -0
  40. package/src/lib/SuperTableCells/CellCommon.css +319 -0
  41. package/src/lib/SuperTableCells/CellDatetime.svelte +180 -0
  42. package/src/lib/SuperTableCells/CellIcon.svelte +627 -0
  43. package/src/lib/SuperTableCells/CellJSON.svelte +297 -0
  44. package/src/lib/SuperTableCells/CellLink.svelte +274 -0
  45. package/src/lib/SuperTableCells/CellLinkAdvanced.svelte +298 -0
  46. package/src/lib/SuperTableCells/CellLinkPickerSelect.svelte +355 -0
  47. package/src/lib/SuperTableCells/CellLinkPickerTable.svelte +91 -0
  48. package/src/lib/SuperTableCells/CellLinkPickerTree.svelte +226 -0
  49. package/src/lib/SuperTableCells/CellNumber.svelte +179 -0
  50. package/src/lib/SuperTableCells/CellNumberSimple.svelte +56 -0
  51. package/src/lib/SuperTableCells/CellOptions.svelte +631 -0
  52. package/src/lib/SuperTableCells/CellOptionsAdvanced.svelte +684 -0
  53. package/src/lib/SuperTableCells/CellSkeleton.svelte +59 -0
  54. package/src/lib/SuperTableCells/CellString.svelte +178 -0
  55. package/src/lib/SuperTableCells/CellStringSimple.svelte +55 -0
  56. package/src/lib/SuperTableCells/index.js +21 -0
  57. package/src/lib/SuperTableCells/remixIcons.js +6772 -0
  58. package/src/lib/SuperTableColumn/SuperTableColumn.svelte +392 -0
  59. package/src/lib/SuperTableColumn/index.js +9 -0
  60. package/src/lib/SuperTableColumn/parts/SuperColumnBody.svelte +57 -0
  61. package/src/lib/SuperTableColumn/parts/SuperColumnFooter.svelte +14 -0
  62. package/src/lib/SuperTableColumn/parts/SuperColumnHeader.svelte +228 -0
  63. package/src/lib/SuperTableColumn/parts/SuperColumnRow.svelte +142 -0
  64. package/src/lib/SuperTableColumn/parts/SuperColumnRowNew.svelte +34 -0
  65. package/src/lib/SuperTree/SuperTree.svelte +117 -0
  66. package/src/types/svelte-portal.d.ts +1 -0
@@ -0,0 +1,1332 @@
1
+ <script>
2
+ import { getContext, setContext, onDestroy, tick } from "svelte";
3
+ import fsm from "svelte-fsm";
4
+ import { writable } from "svelte/store";
5
+
6
+ import {
7
+ sizingMap,
8
+ defaultOperatorMap,
9
+ supportFilteringMap,
10
+ supportSortingMap,
11
+ supportEditingMap,
12
+ } from "./constants.js";
13
+
14
+ // Overlays
15
+ import ScrollbarsOverlay from "./overlays/ScrollbarsOverlay.svelte";
16
+ import EmptyResultSetOverlay from "./overlays/EmptyResultSetOverlay.svelte";
17
+ import AddNewRowOverlay from "./overlays/AddNewRowOverlay.svelte";
18
+ import SelectedActionsOverlay from "./overlays/SelectedActionsOverlay.svelte";
19
+ import LoadingOverlay from "./overlays/LoadingOverlay.svelte";
20
+
21
+ // Components
22
+ import SuperTableColumn from "../SuperTableColumn/SuperTableColumn.svelte";
23
+ import CellSkeleton from "../SuperTableCells/CellSkeleton.svelte";
24
+ import RowButtonsColumn from "./controls/RowButtonsColumn.svelte";
25
+ import SelectionColumn from "./controls/SelectionColumn.svelte";
26
+ import RowContextMenu from "./overlays/RowContextMenu.svelte";
27
+
28
+ // Sections
29
+ import ControlSection from "./controls/ControlSection.svelte";
30
+ import ColumnsSection from "./controls/ColumnsSection.svelte";
31
+
32
+ const {
33
+ API,
34
+ processStringSync,
35
+ notificationStore,
36
+ enrichButtonActions,
37
+ getAction,
38
+ ActionTypes,
39
+ Provider,
40
+ fetchData,
41
+ QueryUtils,
42
+ memo,
43
+ derivedMemo,
44
+ builderStore,
45
+ } = getContext("sdk");
46
+
47
+ const context = getContext("context");
48
+
49
+ // Internally used to appropriately enrich context
50
+ // this is component.id of the wrapper component seen by budibase
51
+ export let comp_id;
52
+ export let inBuilder;
53
+
54
+ // Properties
55
+ export let datasource;
56
+ export let idColumn = "_id";
57
+ export let sortColumn;
58
+ export let sortOrder;
59
+ export let limit = 50;
60
+ export let fetchOnScroll = true;
61
+ export let autoRefresh;
62
+ export let autoRefreshRate;
63
+ export let paginate;
64
+ export let filter;
65
+ export let emptyMessage;
66
+
67
+ export let columnList = [];
68
+ export let autocolumns;
69
+
70
+ export let tableActions;
71
+
72
+ export let showFooter;
73
+ export let showHeader = true;
74
+ export let size = "M";
75
+ export let canInsert, canDelete, canEdit, canResize, canFilter, canSelect;
76
+ export let superColumnsPos;
77
+
78
+ export let debounce = 750;
79
+ export let rowMenu;
80
+ export let rowMenuItems;
81
+ export let rowMenuIcon = "ri-more-fill";
82
+ export let menuItemsVisible = 0;
83
+ export let rowContextMenuItems;
84
+
85
+ export let preselectedIds;
86
+ export let hideSelectionColumn;
87
+ export let numberingColumn;
88
+ export let stickFirstColumn = false;
89
+ export let maxSelected = 0;
90
+ export let selectedActions;
91
+
92
+ export let beautifyLabels;
93
+ export let columnSizing = "flex";
94
+ export let columnMinWidth = "7rem";
95
+ export let columnMaxWidth = "auto";
96
+ export let columnFixedWidth = "7rem";
97
+ export let dividers = "horizontal";
98
+ export let dividersColor;
99
+
100
+ export let rowColorTemplate, rowBGColorTemplate;
101
+ export let rowHeight;
102
+
103
+ export let footerColorTemplate, footerBGColorTemplate;
104
+
105
+ export let useOptionColors = true;
106
+ export let optionsViewMode = "colorText";
107
+ export let relViewMode = "pills";
108
+ export let zebraColors = false;
109
+ export let quiet;
110
+ export let highlighters;
111
+ export let entitySingular = "Row";
112
+ export let entityPlural = "Rows";
113
+
114
+ // Events
115
+ export let onRowSelect;
116
+ export let onCellChange;
117
+ export let onRowClick;
118
+ export let onCellClick;
119
+ export let onLinkClick;
120
+ export let onRowDblClick;
121
+ export let onInsert;
122
+ export let afterInsert;
123
+ export let onDelete;
124
+ export let afterDelete;
125
+ export let afterEdit;
126
+ export let onRefresh;
127
+
128
+ const dataSourceStore = memo(datasource);
129
+ const columnsStore = memo(columnList);
130
+ const filterStore = memo(filter);
131
+ $: dataSourceStore.set(datasource);
132
+ $: filterStore.set(filter);
133
+ $: columnsStore.set(columnList);
134
+ $: stbData = createFetch($dataSourceStore);
135
+ $: _rowHeight = rowHeight
136
+ ? toNumber(
137
+ processStringSync(rowHeight, {
138
+ [comp_id]: { row: {} },
139
+ })
140
+ ) || sizingMap[size].rowHeight
141
+ : sizingMap[size].rowHeight;
142
+
143
+ // Internal Variables
144
+ let timer;
145
+
146
+ let stbColumnFilters = [];
147
+ let highlighted;
148
+ let scrollHeight;
149
+ let clientHeight;
150
+ let columnStates = [];
151
+ let canScroll;
152
+ let horizontalVisible;
153
+ let maxBodyHeight;
154
+ let viewport;
155
+ let columnsViewport;
156
+ let start = 0;
157
+ let end = 0;
158
+ let touchStartY = 0;
159
+ let touchStartX = 0;
160
+ let overflow;
161
+ let isEmpty;
162
+ let _limit = limit;
163
+
164
+ // Inserting New Record
165
+ let temp_scroll_pos;
166
+ let new_row;
167
+
168
+ // Turm non primitive props into reactive stores to limit refreshes
169
+
170
+ const stbSettings = memo({});
171
+ const stbSchema = writable(0);
172
+ // Create Stores
173
+ const stbScrollPos = memo(0);
174
+ const stbScrollOffset = memo(0);
175
+ const stbScrollPercent = memo(0);
176
+ const stbHorizontalScrollPos = memo(0);
177
+ const stbHorizontalScrollPercent = memo(0);
178
+
179
+ const stbVisibleRows = memo([]);
180
+
181
+ const stbMenuID = memo(-1);
182
+ const stbMenuAnchor = memo(-1);
183
+ const stbSelected = memo([]);
184
+ const stbHovered = memo(-1);
185
+ const stbEditing = memo(-1);
186
+ const stbSortColumn = memo({});
187
+ const stbSortOrder = memo({});
188
+
189
+ // Update Settings Reactively so children can react to changes
190
+ $: stbSettings.set({
191
+ inBuilder: $builderStore?.inBuilder,
192
+ autocolumns,
193
+ superColumnsPos,
194
+ columnSizing: columnSizing || "flexible",
195
+ columnMaxWidth: columnMaxWidth || "auto",
196
+ columnMinWidth: columnMinWidth || "7rem",
197
+ columnFixedWidth: columnFixedWidth || "7rem",
198
+ debounce,
199
+ hideSelectionColumn,
200
+ dividers,
201
+ dividersColor,
202
+ showFooter,
203
+ showHeader,
204
+ rowMenuIcon,
205
+ features: {
206
+ canSelect,
207
+ maxSelected,
208
+ canFilter,
209
+ canEdit,
210
+ canDelete,
211
+ canInsert,
212
+ canResize,
213
+ },
214
+ data: {
215
+ datasource,
216
+ idColumn,
217
+ filter,
218
+ sortColumn,
219
+ sortOrder,
220
+ limit,
221
+ emptyMessage:
222
+ emptyMessage || entityPlural
223
+ ? "No " + entityPlural + " found"
224
+ : "No Rows Found",
225
+ paginate,
226
+ autoRefresh,
227
+ autoRefreshRate,
228
+ fetchOnScroll,
229
+ schema: $stbSchema,
230
+ },
231
+ appearance: {
232
+ size,
233
+ headerHeight: showHeader ? sizingMap[size].headerHeight : 0,
234
+ footerHeight: showFooter ? sizingMap[size].headerHeight : 0,
235
+ rowHeight: _rowHeight,
236
+ numberingColumn,
237
+ hideSelectionColumn,
238
+ quiet,
239
+ useOptionColors,
240
+ optionsViewMode,
241
+ relViewMode,
242
+ zebraColors,
243
+ dynamicColors: true,
244
+ highlighters,
245
+ rowColorTemplate,
246
+ rowBGColorTemplate,
247
+ footerColorTemplate,
248
+ footerBGColorTemplate,
249
+ cellPadding: sizingMap[size].cellPadding,
250
+ beautifyLabels,
251
+ },
252
+ events: {
253
+ onRowClick,
254
+ onRowDblClick,
255
+ onCellChange,
256
+ onRowSelect,
257
+ onDelete,
258
+ afterDelete,
259
+ },
260
+ });
261
+
262
+ $: stbRowMetadata = derivedMemo(
263
+ [stbData, stbSettings],
264
+ ([$stbData, $stbSettings]) => {
265
+ if (!$stbData?.loaded) return [];
266
+ return (
267
+ $stbData?.rows?.map((row) => ({
268
+ height: rowHeight
269
+ ? toNumber(
270
+ processStringSync(rowHeight, {
271
+ [comp_id]: { row },
272
+ })
273
+ ) || $stbSettings.appearance.rowHeight
274
+ : $stbSettings.appearance.rowHeight,
275
+ bgcolor: rowBGColorTemplate
276
+ ? processStringSync(rowBGColorTemplate, {
277
+ [comp_id]: { row },
278
+ })
279
+ : undefined,
280
+ color: rowColorTemplate
281
+ ? processStringSync(rowColorTemplate, {
282
+ [comp_id]: { row },
283
+ })
284
+ : undefined,
285
+ })) || [{}]
286
+ );
287
+ }
288
+ );
289
+
290
+ $: cumulativeHeights = derivedMemo(
291
+ [stbRowMetadata, stbSettings],
292
+ ([$meta, $settings]) => {
293
+ const defaultRowHeight = $settings.appearance?.rowHeight || 36; // Fallback if undefined
294
+ return $meta.map((_, i) =>
295
+ $meta
296
+ .slice(0, i + 1)
297
+ .reduce((sum, meta) => sum + (meta.height || defaultRowHeight), 0)
298
+ );
299
+ }
300
+ );
301
+
302
+ // The Super Table API
303
+ const tableAPI = {
304
+ unflattenObject: (obj, delimiter = ".") => {
305
+ if (!obj) return {};
306
+
307
+ return Object.keys(obj).reduce((res, k) => {
308
+ const keys = k.split(delimiter);
309
+ keys.reduce((acc, e, i) => {
310
+ // Check if this is the last key in the path
311
+ if (i === keys.length - 1) {
312
+ acc[e] = obj[k]; // Assign the original value (including booleans)
313
+ return acc;
314
+ }
315
+
316
+ // Determine the type for the next level
317
+ const nextKey = keys[i + 1];
318
+ if (!acc[e]) {
319
+ acc[e] = isNaN(Number(nextKey)) ? {} : [];
320
+ }
321
+ return acc[e];
322
+ }, res);
323
+ return res;
324
+ }, {});
325
+ },
326
+ populateColumns: (schema, list, auto) => {
327
+ let jsoncolumnslist = [];
328
+ let autocolumnsList = [];
329
+ let columns = [];
330
+
331
+ if (schema) {
332
+ if (auto) {
333
+ autocolumnsList = Object.keys(schema)
334
+ .filter((v) => schema[v].autocolumn)
335
+ .map((v) => tableAPI.enrichColumn(schema, schema[v]));
336
+ }
337
+
338
+ if (list?.length) {
339
+ columns = list.map((column) =>
340
+ tableAPI.enrichColumn(schema, { ...column, field: column.name })
341
+ );
342
+ } else {
343
+ jsoncolumnslist = Object.keys(schema)
344
+ .filter((v) => schema[v].nestedJSON)
345
+ .map((v) => tableAPI.enrichColumn(schema, schema[v]));
346
+
347
+ columns = Object.keys(schema)
348
+ .filter(
349
+ (v) =>
350
+ !schema[v].autocolumn &&
351
+ !schema[v].nestedJSON &&
352
+ schema[v]?.visible != false &&
353
+ v != idColumn
354
+ )
355
+ .map((v) => {
356
+ return tableAPI.enrichColumn(schema, {
357
+ ...schema[v],
358
+ field: v ?? schema[v].field ?? schema[v].name,
359
+ });
360
+ });
361
+ }
362
+
363
+ return [...columns, ...jsoncolumnslist, ...autocolumnsList].sort(
364
+ (a, b) => a.order - b.order
365
+ );
366
+ }
367
+ },
368
+ enrichColumn: (schema, bbcolumn) => {
369
+ let type;
370
+ let columnSchema;
371
+
372
+ if (bbcolumn.field.includes(".")) {
373
+ let words = bbcolumn.field.split(".");
374
+ let outerSchema = schema[words[0]].schema;
375
+ columnSchema = outerSchema[words[1]];
376
+ type = columnSchema.type;
377
+ } else {
378
+ type = schema[bbcolumn.field]?.type;
379
+ columnSchema = schema[bbcolumn.field];
380
+
381
+ // TODO : Let the ST handle self relationships inline
382
+ /**
383
+ if (bbcolumn.field.startsWith("fk_self_")) {
384
+ (type = "link"),
385
+ (columnSchema = {
386
+ ...columnSchema,
387
+ tableId: $dataSourceStore.tableId,
388
+ relationshipType: "self",
389
+ type: "link",
390
+ });
391
+ }
392
+ */
393
+ }
394
+
395
+ return {
396
+ ...bbcolumn,
397
+ name: bbcolumn.field,
398
+ widthOverride: bbcolumn.width,
399
+ readonly: schema[bbcolumn.field]?.readonly,
400
+ canEdit:
401
+ supportEditingMap[type] &&
402
+ canEdit &&
403
+ !schema[bbcolumn.name]?.readonly,
404
+ canFilter: supportFilteringMap[type] ? canFilter : false,
405
+ canSort: supportSortingMap[type],
406
+ filteringOperators: QueryUtils.getValidOperatorsForType({ type }),
407
+ defaultFilteringOperator: defaultOperatorMap[type],
408
+ headerAlign: bbcolumn.align ? bbcolumn.align : "flex-start",
409
+ type,
410
+ displayName: beautifyLabel(bbcolumn.displayName ?? bbcolumn.field),
411
+ schema: columnSchema,
412
+ };
413
+ },
414
+ enrichContext: (row) => {
415
+ return {
416
+ ...$context,
417
+ [comp_id]: {
418
+ ...$context[comp_id],
419
+ row,
420
+ },
421
+ };
422
+ },
423
+ registerSuperColumn: (id, state) => {
424
+ columnStates = [...columnStates, { id, state }];
425
+ },
426
+ unregisterSuperColumn: (id) => {
427
+ let pos = columnStates.findIndex((col) => col.id == id);
428
+ if (pos > -1) {
429
+ columnStates.splice(pos, 1);
430
+ columnStates = columnStates;
431
+ }
432
+ },
433
+ executeRowButtonAction: async (index, action) => {
434
+ let cmd = enrichButtonActions(
435
+ action,
436
+ tableAPI.enrichContext($stbData.rows[index])
437
+ );
438
+ await cmd?.();
439
+ },
440
+ executeRowOnClickAction: async (index) => {
441
+ await tableAPI.executeRowButtonAction(index, onRowClick);
442
+ },
443
+ executeCellOnClickAction: async (index, column, value, id) => {
444
+ let cmd = enrichButtonActions(
445
+ onCellClick,
446
+ tableAPI.enrichContext($stbData.rows[index])
447
+ );
448
+ await cmd?.({ column, value, id });
449
+ },
450
+ executeOnLinkClickAction: async (column, linkItem) => {
451
+ let cmd = enrichButtonActions(onLinkClick, {
452
+ column,
453
+ id: linkItem._id,
454
+ primaryDisplay: linkItem.primaryDisplay,
455
+ });
456
+ await cmd?.({
457
+ column,
458
+ id: linkItem._id,
459
+ primaryDisplay: linkItem.primaryDisplay,
460
+ });
461
+ },
462
+ executeRowOnDblClickAction: async (id) => {
463
+ await tableAPI.executeRowButtonAction(id, onRowDblClick);
464
+ },
465
+ executeRowOnSelectAction: async (index) => {
466
+ await tick();
467
+ let cmd = enrichButtonActions(
468
+ onRowSelect,
469
+ tableAPI.enrichContext($stbData.rows[index])
470
+ );
471
+ await cmd?.();
472
+ },
473
+ showContextMenu: (id, anchor) => {
474
+ if (rowContextMenuItems?.length && $stbMenuID != id) {
475
+ $stbMenuID = id;
476
+ $stbMenuAnchor = anchor;
477
+ } else {
478
+ $stbMenuID = -1;
479
+ $stbMenuAnchor = -1;
480
+ }
481
+ },
482
+ executeRowContextMenuAction: async (id, action) => {
483
+ await tableAPI.executeRowButtonAction(id, action);
484
+ $stbMenuID = -1;
485
+ $stbMenuAnchor = -1;
486
+ },
487
+ executeSelectedRowsAction: async (action) => {
488
+ tableAPI.executeRowButtonAction(null, action);
489
+ },
490
+ selectRow: (index) => {
491
+ let id = $stbData.rows[index][idColumn] ?? index;
492
+
493
+ if (maxSelected != 1) {
494
+ if ($stbSelected.includes(id)) {
495
+ $stbSelected.splice($stbSelected.indexOf(id), 1);
496
+ $stbSelected = $stbSelected;
497
+ } else {
498
+ if (maxSelected == 0 || $stbSelected.length < maxSelected)
499
+ $stbSelected = [...$stbSelected, id];
500
+ else
501
+ notificationStore.actions.warning(
502
+ "Cannot select more than " +
503
+ maxSelected +
504
+ " " +
505
+ (entityPlural || "Rows")
506
+ );
507
+ }
508
+ } else {
509
+ if ($stbSelected.includes(id)) {
510
+ $stbSelected = [];
511
+ } else {
512
+ $stbSelected = [id];
513
+ }
514
+ }
515
+
516
+ // Fire Assigned Events
517
+ if ($stbSelected.length) tableAPI.executeRowOnSelectAction(index);
518
+ },
519
+ selectAllRows: () => {
520
+ if ($stbSelected.length != $stbData.rows.length)
521
+ $stbSelected = $stbData.rows.map((x) => x[idColumn]);
522
+ else $stbSelected = [];
523
+
524
+ tableAPI.executeRowOnSelectAction();
525
+ },
526
+ insertRow: async (row) => {
527
+ let cmd_after = enrichButtonActions(afterInsert, $context);
528
+ let saved_row;
529
+ if (onInsert && onInsert.length) {
530
+ let cmd = enrichButtonActions(onInsert, $context);
531
+ await cmd?.();
532
+ } else {
533
+ stbState.startSave();
534
+ try {
535
+ saved_row = await API.saveRow({ ...new_row, tableId });
536
+ } catch (e) {
537
+ console.log(e);
538
+ } finally {
539
+ await cmd_after?.({ newRow: saved_row });
540
+ stbState.endSave();
541
+ }
542
+ }
543
+ },
544
+ deleteRow: async (index) => {
545
+ let id = $stbData.rows[index][idColumn];
546
+ let row = $stbData.rows[index];
547
+
548
+ let autoDelete = [
549
+ {
550
+ parameters: {
551
+ confirm: true,
552
+ notificationOverride: true,
553
+ customTitleText: "Delete " + (entitySingular || "Row") + " ?",
554
+ confirmText:
555
+ "Are you sure you want to delete this " +
556
+ (entitySingular || "Row") +
557
+ " ?",
558
+ tableId: tableId,
559
+ rowId: id,
560
+ },
561
+ "##eventHandlerType": "Delete Row",
562
+ },
563
+ ];
564
+
565
+ let cmd;
566
+ let cmd_after = enrichButtonActions(
567
+ afterDelete,
568
+ tableAPI.enrichContext($stbData.rows[index])
569
+ );
570
+
571
+ if (onDelete?.length) {
572
+ cmd = enrichButtonActions(
573
+ onDelete,
574
+ tableAPI.enrichContext($stbData.rows[index])
575
+ );
576
+ } else {
577
+ cmd = enrichButtonActions(autoDelete, {});
578
+ }
579
+
580
+ await cmd?.({ row });
581
+ await cmd_after?.({ row });
582
+
583
+ // Remove row from the selected list if selected
584
+ if ($stbSelected.includes(id)) {
585
+ $stbSelected.splice($stbSelected.indexOf(id), 1);
586
+ $stbSelected = $stbSelected;
587
+ }
588
+
589
+ // Refresh the dataset
590
+ stbData.refresh();
591
+ },
592
+ deleteSelectedRows: async () => {
593
+ let autoDelete = [
594
+ {
595
+ parameters: {
596
+ confirm: true,
597
+ notificationOverride: true,
598
+ customTitleText:
599
+ "Delete " +
600
+ $stbSelected.length +
601
+ " " +
602
+ (entityPlural || "Rows") +
603
+ " ?",
604
+ confirmText:
605
+ "Are you sure you want to delete these " +
606
+ (entityPlural || "Rows") +
607
+ " ?",
608
+ tableId: tableId,
609
+ rowId: $stbSelected,
610
+ },
611
+ "##eventHandlerType": "Delete Row",
612
+ },
613
+ ];
614
+ let cmd = enrichButtonActions(autoDelete, {});
615
+ let cmd_after = enrichButtonActions(afterDelete, $context);
616
+ await cmd?.();
617
+ await cmd_after?.();
618
+ stbData.refresh();
619
+ },
620
+ patchRow: async (patch) => {
621
+ patch = tableAPI.unflattenObject(patch);
622
+ if (tableId) {
623
+ try {
624
+ let row = await API.patchRow({
625
+ tableId,
626
+ ...patch,
627
+ });
628
+
629
+ stbState.refresh();
630
+ let richContext = {
631
+ ...$context,
632
+ [comp_id]: { row },
633
+ };
634
+ let cmd_after = enrichButtonActions(afterEdit, richContext);
635
+ await cmd_after?.({ row });
636
+ return row;
637
+ } catch (ex) {
638
+ console.log(ex);
639
+ }
640
+ }
641
+ },
642
+ };
643
+
644
+ // Super Table State Machine
645
+ const stbState = fsm("Init", {
646
+ "*": {
647
+ init() {
648
+ return "Init";
649
+ },
650
+ async refresh() {
651
+ if (stbData.loaded) await stbData?.refresh();
652
+ this.enrichRows();
653
+ this.calculateRowBoundaries();
654
+ },
655
+ enrichRows() {},
656
+ scrollToTop() {
657
+ $stbScrollPos = 0;
658
+ $stbScrollOffset = 0;
659
+ this.calculateRowBoundaries();
660
+ },
661
+ scrollTo(position) {
662
+ $stbScrollPos = position;
663
+ this.calculateRowBoundaries();
664
+ },
665
+ scrollToEnd() {
666
+ $stbScrollPos = scrollHeight - maxBodyHeight;
667
+ this.calculateRowBoundaries();
668
+ },
669
+ calculateBoundaries() {
670
+ let rows = $stbData?.rows;
671
+ if (!rows || !viewport) return;
672
+
673
+ const defaultRowHeight = $stbSettings.appearance.rowHeight;
674
+
675
+ // Calculate scrollHeight as sum of row heights from stbRowMetadata
676
+ scrollHeight =
677
+ ($cumulativeHeights[$cumulativeHeights.length - 1] || 0) +
678
+ (canInsert ? 4 * defaultRowHeight : 2 * defaultRowHeight);
679
+
680
+ // Calculate maxBodyHeight, adding one row height for extra space
681
+
682
+ maxBodyHeight =
683
+ viewport.clientHeight -
684
+ $stbSettings.appearance.headerHeight -
685
+ $stbSettings.appearance.footerHeight +
686
+ defaultRowHeight; // Add extra row height for negative margin
687
+
688
+ // Determine if scrolling is needed
689
+ canScroll = scrollHeight > maxBodyHeight;
690
+ overflow = canScroll;
691
+
692
+ // Update scroll percentage
693
+ $stbScrollPercent =
694
+ scrollHeight > maxBodyHeight
695
+ ? $stbScrollPos / (scrollHeight - maxBodyHeight)
696
+ : 0;
697
+
698
+ // Recalculate visible row boundaries
699
+ this.calculateRowBoundaries();
700
+ },
701
+ calculateRowBoundaries() {
702
+ let rows = $stbData?.rows;
703
+ if (!rows?.length || !viewport || !$cumulativeHeights.length) return;
704
+
705
+ const defaultRowHeight = $stbSettings.appearance.rowHeight;
706
+ let start = $stbVisibleRows?.length ? $stbVisibleRows[0] - 1 : 0;
707
+ start = Math.max(0, start); // Ensure start doesn't go negative
708
+ let end = 0;
709
+
710
+ // Find start index using cumulativeHeights
711
+ for (let i = 0; i < rows.length; i++) {
712
+ if ($cumulativeHeights[i] > $stbScrollPos) {
713
+ start = i;
714
+ break;
715
+ }
716
+ }
717
+
718
+ // Find end index using cumulativeHeights
719
+ for (let i = start; i < rows.length; i++) {
720
+ if (
721
+ $cumulativeHeights[i] >=
722
+ $stbScrollPos + maxBodyHeight - defaultRowHeight
723
+ ) {
724
+ end = i + 1;
725
+ break;
726
+ }
727
+ }
728
+
729
+ // Ensure all rows are included when at the bottom
730
+ end = end || rows.length;
731
+
732
+ // Update visible rows
733
+ $stbVisibleRows = $stbData?.rows
734
+ ?.slice(start, end)
735
+ .map((_, i) => i + start);
736
+
737
+ // Calculate scroll offset for rendering
738
+ const startHeight = start > 0 ? $cumulativeHeights[start - 1] : 0;
739
+ $stbScrollOffset = $stbScrollPos - startHeight;
740
+
741
+ // Ensure offset doesn't exceed bounds at the end
742
+ if ($stbScrollPos >= scrollHeight - maxBodyHeight) {
743
+ $stbScrollPos = Math.max(0, scrollHeight - maxBodyHeight);
744
+ $stbScrollOffset = Math.min(
745
+ $stbScrollOffset,
746
+ maxBodyHeight - defaultRowHeight
747
+ );
748
+ }
749
+
750
+ // Fetch more rows if nearing the end of loaded data
751
+ if (fetchOnScroll && rows.length > 0) {
752
+ const loadedHeight = $cumulativeHeights[rows.length - 1];
753
+ const remainingHeight =
754
+ loadedHeight - ($stbScrollPos + maxBodyHeight);
755
+ if (remainingHeight < maxBodyHeight && rows.length == _limit) {
756
+ stbState.fetchMoreRows.debounce(200, 100); // Debounced fetch call
757
+ }
758
+ }
759
+ },
760
+ handleVerticalScroll(delta) {
761
+ $stbScrollPos = Math.max(
762
+ Math.min(
763
+ $stbScrollPos + delta,
764
+ Math.max(0, scrollHeight - maxBodyHeight)
765
+ ),
766
+ 0
767
+ );
768
+ $stbScrollPercent =
769
+ scrollHeight > maxBodyHeight
770
+ ? $stbScrollPos / (scrollHeight - maxBodyHeight)
771
+ : 0;
772
+ $stbScrollOffset = Math.floor(
773
+ $stbScrollPos % $stbSettings.appearance.rowHeight
774
+ );
775
+
776
+ this.calculateRowBoundaries.debounce(1);
777
+ },
778
+ handleWheel(e) {
779
+ if ($stbState == "Inserting") {
780
+ e.preventDefault();
781
+ e.stopPropagation();
782
+ return;
783
+ }
784
+
785
+ if (e.deltaY && canScroll) {
786
+ e.preventDefault();
787
+ e.stopPropagation();
788
+ this.handleVerticalScroll(e.deltaY);
789
+ } else if (e.deltaX) {
790
+ if ($stbHorizontalScrollPos + e.deltaX < 0) {
791
+ $stbHorizontalScrollPos = 0;
792
+ $stbHorizontalScrollPercent = 0;
793
+ return;
794
+ }
795
+ if (
796
+ $stbHorizontalScrollPos + e.deltaX >
797
+ columnsViewport?.scrollWidth - columnsViewport.clientWidth
798
+ ) {
799
+ $stbHorizontalScrollPos =
800
+ columnsViewport?.scrollWidth - columnsViewport.clientWidth;
801
+ $stbHorizontalScrollPercent = 1;
802
+ return;
803
+ }
804
+
805
+ $stbHorizontalScrollPos += e.deltaX;
806
+ $stbHorizontalScrollPercent =
807
+ $stbHorizontalScrollPos / columnsViewport.scrollWidth;
808
+ }
809
+ },
810
+ handleKeyboard(e) {
811
+ // TODO : Table Keyboard Handler
812
+ },
813
+ handleTouch(e, type) {
814
+ if ($stbData.loading || $stbState === "Inserting") {
815
+ e.preventDefault();
816
+ return;
817
+ }
818
+
819
+ if (type === "start") {
820
+ touchStartY = e.touches[0].clientY;
821
+ touchStartX = e.touches[0].clientX;
822
+ } else if (type === "move" && canScroll) {
823
+ const touchY = e.touches[0].clientY;
824
+ const touchX = e.touches[0].clientX;
825
+ const deltaY = touchStartY - touchY; // Positive for swipe up, negative for swipe down
826
+ const deltaX = touchStartX - touchX;
827
+
828
+ // Prioritize vertical scrolling if swipe is mostly vertical
829
+ if (Math.abs(deltaY) > Math.abs(deltaX)) {
830
+ e.preventDefault(); // Prevent native vertical scroll
831
+ this.handleVerticalScroll(deltaY * 0.5); // Adjust sensitivity (0.5 for smoother scrolling)
832
+ touchStartY = touchY; // Update start position for continuous scrolling
833
+ }
834
+ }
835
+ },
836
+ sortBy(column, order) {
837
+ sortColumn = column;
838
+ sortOrder = order;
839
+ $stbSortColumn = column;
840
+ $stbSortOrder = order;
841
+ },
842
+ resizeRow(index, size) {
843
+ $stbRowMetadata[index].height =
844
+ size || $stbSettings.appearance.rowHeight;
845
+ this.calculateBoundaries.debounce(20);
846
+ },
847
+ handleRowClick(index, column, value, id) {
848
+ if (canSelect && !canEdit) tableAPI.selectRow(index);
849
+ if (onCellClick) {
850
+ tableAPI.executeCellOnClickAction(index, column, value, id);
851
+ tableAPI.executeRowOnClickAction(index);
852
+ } else {
853
+ tableAPI.executeRowOnClickAction(index);
854
+ }
855
+ },
856
+ addRow() {
857
+ if (!onInsert || onInsert?.length == 0) {
858
+ return "Inserting";
859
+ } else {
860
+ tableAPI.insertRow();
861
+ }
862
+ },
863
+ edit() {
864
+ return "Editing";
865
+ },
866
+ },
867
+ Init: {
868
+ _enter() {
869
+ if (timer) clearInterval(timer);
870
+ start = 0;
871
+ end = 0;
872
+ $stbScrollPos = 0;
873
+ $stbScrollOffset = 0;
874
+ $stbHorizontalScrollPos = 0;
875
+ $stbSelected = [];
876
+ if (_limit != limit) _limit = limit;
877
+ },
878
+ synch(fetchState) {
879
+ if (fetchState.loaded) {
880
+ this.enrichRows();
881
+ this.calculateBoundaries();
882
+ if (autoRefresh && !inBuilder) {
883
+ timer = setInterval(() => {
884
+ stbData?.refresh();
885
+ onRefresh?.();
886
+ }, autoRefreshRate * 1000);
887
+ }
888
+ return "Idle";
889
+ }
890
+ },
891
+ },
892
+ Idle: {
893
+ _enter() {
894
+ isEmpty = $stbData.rows.length < 1;
895
+ },
896
+ _exit() {},
897
+ synch(fetchState) {
898
+ if (fetchState.loading) return;
899
+ this.enrichRows();
900
+ this.calculateBoundaries();
901
+ isEmpty = !$stbData?.rows.length;
902
+ },
903
+ addFilter(filterObj) {
904
+ stbColumnFilters = [...stbColumnFilters, filterObj];
905
+ return "Filtered";
906
+ },
907
+ fetchMoreRows(size) {
908
+ _limit = _limit + size;
909
+ stbData.update({ limit: _limit });
910
+ },
911
+ },
912
+ Filtered: {
913
+ _enter() {},
914
+ _exit() {},
915
+ addFilter(filterObj) {
916
+ this.removeFilter(filterObj.id);
917
+ stbColumnFilters = [...stbColumnFilters, filterObj];
918
+ },
919
+ removeFilter(id) {
920
+ let pos = stbColumnFilters.find((x) => x.id == id);
921
+ if (pos) {
922
+ stbColumnFilters = stbColumnFilters.toSpliced(pos, 1);
923
+ }
924
+ },
925
+ clearFilter(id) {
926
+ let pos = stbColumnFilters.find((x) => x.id == id);
927
+ if (pos) {
928
+ stbColumnFilters = stbColumnFilters.toSpliced(pos, 1);
929
+ }
930
+ if (!stbColumnFilters.length) return "Idle";
931
+ },
932
+ clear() {
933
+ stbColumnFilters = [];
934
+ columnStates.forEach(({ state }) => state.reset());
935
+ return "Idle";
936
+ },
937
+ synch(fetchState) {
938
+ if (fetchState.loaded) {
939
+ this.enrichRows();
940
+ this.calculateBoundaries();
941
+ this.calculateRowBoundaries();
942
+
943
+ isEmpty = fetchState.rows.length < 1;
944
+ }
945
+ },
946
+ },
947
+ Editing: {
948
+ async patchRow(index, id, rev, field, change) {
949
+ let patch = { _id: id, _rev: rev, [field]: change };
950
+ await tableAPI.patchRow(index, patch);
951
+ stbState.refresh();
952
+ return "Idle";
953
+ },
954
+ endEdit() {
955
+ return "Idle";
956
+ },
957
+ },
958
+ Inserting: {
959
+ _enter() {
960
+ isEmpty = false;
961
+ columnStates.forEach(({ state }) => state.addRow());
962
+ new_row = {};
963
+ temp_scroll_pos = $stbScrollPos;
964
+ this.scrollToEnd();
965
+ },
966
+ _exit() {
967
+ columnStates.forEach(({ state }) => state.cancelAddRow());
968
+ this.scrollTo(temp_scroll_pos);
969
+ },
970
+ cancelAddRow() {
971
+ return "Idle";
972
+ },
973
+ endSave() {
974
+ this.refresh();
975
+ return "Idle";
976
+ },
977
+ setValue(field, value) {
978
+ new_row[field] = value;
979
+ },
980
+ },
981
+ });
982
+
983
+ $: stbSchema.set($stbData?.definition?.schema);
984
+
985
+ // Virtual List Capabilities reacting to viewport change
986
+ $: stbState.calculateBoundaries(
987
+ clientHeight,
988
+ canInsert,
989
+ $stbSortColumn,
990
+ fetchOnScroll,
991
+ rowHeight
992
+ );
993
+
994
+ // Scroll to Top when filter changes
995
+ $: stbState.scrollToTop(query);
996
+
997
+ $: if (canSelect) stbSelected.set(preselectedIds ?? []);
998
+ else stbSelected.set([]);
999
+
1000
+ $: idColumn = $stbData?.definition?.primary?.[0]
1001
+ ? $stbData?.definition?.primary?.[0]
1002
+ : $stbSchema?.id
1003
+ ? "id"
1004
+ : "_id";
1005
+
1006
+ // Reactively set the Table Settings store
1007
+
1008
+ $: if (datasource.type == "provider") {
1009
+ let dataProviderId = datasource.providerId;
1010
+ let addExtension = getAction(
1011
+ dataProviderId,
1012
+ ActionTypes.AddDataProviderQueryExtension
1013
+ );
1014
+
1015
+ let removeExtension = getAction(
1016
+ dataProviderId,
1017
+ ActionTypes.RemoveDataProviderQueryExtension
1018
+ );
1019
+ }
1020
+
1021
+ // Data Related
1022
+ $: defaultQuery = QueryUtils.buildQuery($filterStore);
1023
+ $: queryExtension = QueryUtils.buildQuery(stbColumnFilters);
1024
+ $: query = extendQuery(defaultQuery, [queryExtension]);
1025
+
1026
+ $: stbData?.update({
1027
+ query,
1028
+ sortColumn,
1029
+ sortOrder,
1030
+ });
1031
+ $: stbState.synch($stbData);
1032
+ $: tableId = $stbData?.definition?.tableId || $stbData?.definition?._id;
1033
+
1034
+ // Derived Store with the columns to be rendered
1035
+ $: superColumns = derivedMemo(
1036
+ [stbSchema, columnsStore, stbSettings],
1037
+ ([$stbSchema, $columnsStore, $stbSettings]) => {
1038
+ if ($stbSchema)
1039
+ return tableAPI.populateColumns($stbSchema, $columnsStore, autocolumns);
1040
+ }
1041
+ );
1042
+
1043
+ // Derived Store with common column settings
1044
+ const commonColumnOptions = derivedMemo(stbSettings, ($stbSettings) => {
1045
+ return {
1046
+ hasChildren: false,
1047
+ maxWidth: columnMaxWidth || "auto",
1048
+ minWidth: columnMinWidth || "7rem",
1049
+ fixedWidth: columnFixedWidth || "7rem",
1050
+ sizing: columnSizing,
1051
+ canResize,
1052
+ canEdit: inBuilder ? false : canEdit,
1053
+ showFooter,
1054
+ showHeader,
1055
+ cellPadding: sizingMap[size].cellPadding,
1056
+ headerHeight: sizingMap[size].headerHeight,
1057
+ rowHeight: sizingMap[size].rowHeight,
1058
+ highlighters,
1059
+ useOptionColors: $stbSettings?.appearance?.useOptionColors || false,
1060
+ optionsViewMode,
1061
+ relViewMode,
1062
+ zebraColors,
1063
+ quiet,
1064
+ };
1065
+ });
1066
+
1067
+ $: dividersStyles = {
1068
+ color:
1069
+ $stbSettings.dividersColor ?? "var(--spectrum-global-color-gray-200)",
1070
+ horizontal:
1071
+ $stbSettings.dividers == "both" || $stbSettings.dividers == "horizontal"
1072
+ ? "1px solid var(--super-table-devider-color)"
1073
+ : "1px solid transparent",
1074
+ vertical:
1075
+ $stbSettings.dividers == "both" || $stbSettings.dividers == "vertical"
1076
+ ? "1px solid var(--super-table-devider-color)"
1077
+ : "none",
1078
+ };
1079
+
1080
+ // Build our data and actions ontext
1081
+ $: actions = [
1082
+ {
1083
+ type: ActionTypes.ClearRowSelection,
1084
+ callback: () => {
1085
+ $stbSelected = [];
1086
+ },
1087
+ },
1088
+ {
1089
+ type: ActionTypes.RefreshDatasource,
1090
+ callback: () => stbData?.refresh(),
1091
+ },
1092
+ ];
1093
+
1094
+ // The "row" is dynamically enriched, but show the first one in the builder for preview
1095
+ $: dataContext = {
1096
+ row: inBuilder ? $stbData?.rows[0] : {},
1097
+ hoveredRow: $stbData?.rows[$stbHovered],
1098
+ rows: $stbData?.rows,
1099
+ selectedRows: $stbData?.rows.filter((x) =>
1100
+ $stbSelected.includes(x[idColumn])
1101
+ ),
1102
+ selectedIds: $stbSelected,
1103
+ info: $stbData?.info,
1104
+ datasource: datasource || {},
1105
+ schema: $stbSchema,
1106
+ rowsLength: $stbData?.rows.length,
1107
+ pageNumber: $stbData?.pageNumber + 1,
1108
+ entitySingular,
1109
+ entityPlural,
1110
+ offset: 0,
1111
+ limit: 100,
1112
+ };
1113
+
1114
+ // Show Action Buttons Column
1115
+ $: showButtonColumnRight = rowMenu == "columnRight" && rowMenuItems?.length;
1116
+ $: showButtonColumnLeft = rowMenu == "columnLeft" && rowMenuItems?.length;
1117
+
1118
+ const createFetch = (datasource) => {
1119
+ stbState.init();
1120
+ return fetchData({
1121
+ API,
1122
+ datasource,
1123
+ options: {
1124
+ query,
1125
+ sortColumn,
1126
+ sortOrder,
1127
+ limit,
1128
+ paginate: true,
1129
+ },
1130
+ });
1131
+ };
1132
+
1133
+ const extendQuery = (defaultQuery, extensions) => {
1134
+ const extensionValues = Object.values(extensions || {});
1135
+ let extendedQuery = { ...defaultQuery };
1136
+ extensionValues.forEach((extension) => {
1137
+ Object.entries(extension || {}).forEach(([operator, fields]) => {
1138
+ extendedQuery[operator] =
1139
+ operator != "onEmptyFilter"
1140
+ ? {
1141
+ ...extendedQuery[operator],
1142
+ ...fields,
1143
+ }
1144
+ : "none";
1145
+ });
1146
+ });
1147
+ return extendedQuery;
1148
+ };
1149
+
1150
+ const beautifyLabel = (label) => {
1151
+ if (!beautifyLabels || !label) return label;
1152
+
1153
+ let fields = label.split(".");
1154
+ fields.forEach((field, index) => {
1155
+ let words = field.split("_");
1156
+ words.forEach((word, index) => {
1157
+ if (word) words[index] = word[0]?.toUpperCase() + word?.slice(1);
1158
+ });
1159
+ fields[index] = words.join(" ");
1160
+ });
1161
+ return fields.join(" - ");
1162
+ };
1163
+
1164
+ // Expose Context
1165
+ setContext("stbScrollPos", stbScrollPos);
1166
+ setContext("stbScrollOffset", stbScrollOffset);
1167
+ setContext("stbHorizontalScrollPos", stbHorizontalScrollPos);
1168
+ setContext("stbHovered", stbHovered);
1169
+ setContext("stbSelected", stbSelected);
1170
+ setContext("stbEditing", stbEditing);
1171
+ setContext("stbState", stbState);
1172
+ setContext("stbSettings", stbSettings);
1173
+ setContext("stbSortColumn", stbSortColumn);
1174
+ setContext("stbSortOrder", stbSortOrder);
1175
+ setContext("stbMenuID", stbMenuID);
1176
+ setContext("stbMenuAnchor", stbMenuAnchor);
1177
+ setContext("stbAPI", tableAPI);
1178
+ setContext("stbVisibleRows", stbVisibleRows);
1179
+ $: setContext("stbRowMetadata", stbRowMetadata);
1180
+ $: setContext("stbData", stbData);
1181
+ $: setContext("stbSchema", stbSchema);
1182
+
1183
+ function toNumber(input) {
1184
+ const num = Number(input);
1185
+ return isNaN(num) ? null : num;
1186
+ }
1187
+
1188
+ onDestroy(() => {
1189
+ if (timer) clearInterval(timer);
1190
+ });
1191
+
1192
+ /**
1193
+ $: console.log("Table State : " + $stbState);
1194
+ $: console.log("Table Filters : ", stbColumnFilters);
1195
+ $: console.log("Table Settings : ", $stbSettings);
1196
+ */
1197
+
1198
+ $: console.log($stbSchema);
1199
+ </script>
1200
+
1201
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
1202
+ <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
1203
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
1204
+ <div
1205
+ class="super-table"
1206
+ class:quiet
1207
+ bind:this={viewport}
1208
+ bind:clientHeight
1209
+ style:font-size={sizingMap[size].rowFontSize}
1210
+ style:--super-table-devider-color={dividersStyles.color}
1211
+ style:--super-table-body-height={maxBodyHeight}
1212
+ style:--super-table-header-height={$stbSettings.appearance.headerHeight}
1213
+ style:--super-table-footer-height={$stbSettings.appearance.footerHeight}
1214
+ style:--super-table-horizontal-dividers={dividersStyles.horizontal}
1215
+ style:--super-table-vertical-dividers={dividersStyles.vertical}
1216
+ style:--super-table-cell-padding={sizingMap[size].cellPadding}
1217
+ style:--super-column-top-offset={$stbScrollOffset * -1}
1218
+ on:mouseenter={() => (highlighted = true)}
1219
+ on:mouseleave={() => {
1220
+ highlighted = false;
1221
+ $stbHovered = null;
1222
+ }}
1223
+ on:keydown={stbState.handleKeyboard}
1224
+ on:wheel={stbState.handleWheel}
1225
+ on:touchstart={(e) => stbState.handleTouch(e, "start")}
1226
+ on:touchmove={(e) => stbState.handleTouch(e, "move")}
1227
+ on:touchend={(e) => stbState.handleTouch(e, "end")}
1228
+ >
1229
+ <Provider {actions} data={dataContext} />
1230
+ {#key columnSizing}
1231
+ {#if $stbState != "Init"}
1232
+ {#if !isEmpty}
1233
+ <ControlSection>
1234
+ <SelectionColumn {hideSelectionColumn} />
1235
+
1236
+ {#if showButtonColumnLeft}
1237
+ <RowButtonsColumn {rowMenuItems} {menuItemsVisible} {rowMenu} />
1238
+ {/if}
1239
+
1240
+ {#if stickFirstColumn && $superColumns.length > 1}
1241
+ <SuperTableColumn
1242
+ sticky={true}
1243
+ scrollPos={$stbHorizontalScrollPos}
1244
+ columnOptions={{
1245
+ ...$superColumns[0],
1246
+ ...$commonColumnOptions,
1247
+ overflow,
1248
+ isFirst: true,
1249
+ isLast:
1250
+ $superColumns?.length == 1 &&
1251
+ !showButtonColumnRight &&
1252
+ canScroll,
1253
+ }}
1254
+ />
1255
+ {/if}
1256
+ </ControlSection>
1257
+ {/if}
1258
+
1259
+ <ColumnsSection
1260
+ {stbSettings}
1261
+ {superColumns}
1262
+ {commonColumnOptions}
1263
+ {canScroll}
1264
+ bind:columnsViewport
1265
+ >
1266
+ <slot />
1267
+ </ColumnsSection>
1268
+
1269
+ {#if showButtonColumnRight && !isEmpty}
1270
+ <ControlSection>
1271
+ <RowButtonsColumn
1272
+ {rowMenuItems}
1273
+ {menuItemsVisible}
1274
+ {rowMenu}
1275
+ {canScroll}
1276
+ right={true}
1277
+ />
1278
+ </ControlSection>
1279
+ {/if}
1280
+
1281
+ <ScrollbarsOverlay
1282
+ anchor={columnsViewport}
1283
+ clientHeight={maxBodyHeight}
1284
+ {scrollHeight}
1285
+ {highlighted}
1286
+ {isEmpty}
1287
+ bind:horizontalVisible
1288
+ on:positionChange={stbState.calculateRowBoundaries}
1289
+ />
1290
+
1291
+ <EmptyResultSetOverlay
1292
+ {isEmpty}
1293
+ message={$stbSettings.data.emptyMessage}
1294
+ top={$superColumns?.length
1295
+ ? $stbSettings.appearance.headerHeight + 16
1296
+ : 16}
1297
+ bottom={horizontalVisible ? 24 : 16}
1298
+ />
1299
+
1300
+ <RowContextMenu {rowContextMenuItems} />
1301
+
1302
+ {#if $stbSettings.features.canInsert || $stbState == "Filtered"}
1303
+ <AddNewRowOverlay
1304
+ {stbState}
1305
+ {tableAPI}
1306
+ {highlighted}
1307
+ {tableActions}
1308
+ footer={$stbSettings.showFooter}
1309
+ />
1310
+ {/if}
1311
+
1312
+ {#if $stbSettings.features.canSelect && selectedActions?.length}
1313
+ <SelectedActionsOverlay
1314
+ {stbSettings}
1315
+ {selectedActions}
1316
+ {stbSelected}
1317
+ {tableAPI}
1318
+ {stbState}
1319
+ {highlighted}
1320
+ {entitySingular}
1321
+ {entityPlural}
1322
+ />
1323
+ {/if}
1324
+
1325
+ {#if $stbData.loading}
1326
+ <LoadingOverlay />
1327
+ {/if}
1328
+ {:else}
1329
+ <CellSkeleton />
1330
+ {/if}
1331
+ {/key}
1332
+ </div>