@lavalogic/scoria 0.38.10 → 0.38.12

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 (115) hide show
  1. package/README.md +58 -58
  2. package/dist/Components/AccordionGroup.svelte +46 -46
  3. package/dist/Components/AccordionGroupButton.svelte +76 -76
  4. package/dist/Components/Action.svelte +136 -136
  5. package/dist/Components/AppointmentCalendar/AppointmentCalendar.svelte +702 -702
  6. package/dist/Components/Base/BaseModal.svelte +125 -125
  7. package/dist/Components/Base/ContextWrapper.svelte +72 -72
  8. package/dist/Components/Base/Pagination.svelte +198 -198
  9. package/dist/Components/Base/Snippets.svelte +36 -36
  10. package/dist/Components/BigRadioSet.svelte +38 -38
  11. package/dist/Components/Bubble.svelte +101 -101
  12. package/dist/Components/Button.svelte +209 -209
  13. package/dist/Components/Checkbox.svelte +86 -86
  14. package/dist/Components/Contexts/ContextMenu.svelte +164 -164
  15. package/dist/Components/Contexts/ContextMenuDivider.svelte +15 -15
  16. package/dist/Components/Contexts/ContextMenuOption.svelte +60 -60
  17. package/dist/Components/Contexts/ToastContainer.svelte +65 -65
  18. package/dist/Components/Contexts/Tooltip.svelte +37 -37
  19. package/dist/Components/DataMatrixIcon.svelte +112 -112
  20. package/dist/Components/DateInput.svelte +148 -148
  21. package/dist/Components/DatePicker.svelte +300 -300
  22. package/dist/Components/DesktopModal.svelte +90 -90
  23. package/dist/Components/Dial.svelte +204 -204
  24. package/dist/Components/DimensionInput.svelte +170 -170
  25. package/dist/Components/DragMenu/DragMenuHolder.svelte +119 -119
  26. package/dist/Components/DragMenu/DraggableCard.svelte +77 -77
  27. package/dist/Components/FileCard.svelte +24 -24
  28. package/dist/Components/FileUpload.svelte +236 -236
  29. package/dist/Components/GridInputSet.svelte +29 -29
  30. package/dist/Components/HorizontalTabGroup.svelte +82 -82
  31. package/dist/Components/HorizontalTabGroupButton.svelte +44 -44
  32. package/dist/Components/Icon.svelte +128 -128
  33. package/dist/Components/Icons.js +357 -357
  34. package/dist/Components/LoadingAnimation.svelte +29 -29
  35. package/dist/Components/LoadingModal.svelte +45 -45
  36. package/dist/Components/LoadingOverlay.svelte +25 -25
  37. package/dist/Components/Modal.svelte +258 -258
  38. package/dist/Components/MultiSelect.svelte +220 -220
  39. package/dist/Components/Nav/NavServiceMenuList.svelte +43 -43
  40. package/dist/Components/Nav/NavTab.svelte +62 -62
  41. package/dist/Components/Nav/ServicesNav.svelte +80 -80
  42. package/dist/Components/NumberInput.svelte +157 -157
  43. package/dist/Components/PageHeading.svelte +25 -25
  44. package/dist/Components/PasswordInput.svelte +88 -88
  45. package/dist/Components/Portal.svelte +36 -36
  46. package/dist/Components/QuerySelect.svelte +366 -366
  47. package/dist/Components/SingleSelect.svelte +250 -250
  48. package/dist/Components/StepButton.svelte +70 -70
  49. package/dist/Components/StepForm.svelte +140 -140
  50. package/dist/Components/Switch.svelte +69 -69
  51. package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +51 -51
  52. package/dist/Components/Table/Body/Rows/ColumnList.svelte +59 -59
  53. package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +79 -79
  54. package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +120 -120
  55. package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +105 -105
  56. package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +87 -87
  57. package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +126 -126
  58. package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +159 -159
  59. package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +246 -246
  60. package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +216 -216
  61. package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +179 -179
  62. package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +197 -197
  63. package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +190 -190
  64. package/dist/Components/Table/Body/Rows/TableRow.svelte +290 -290
  65. package/dist/Components/Table/Headers/HighlightAllHeader.svelte +41 -41
  66. package/dist/Components/Table/Headers/SelectAllHeader.svelte +30 -30
  67. package/dist/Components/Table/Misc/FilterInput.svelte +37 -16
  68. package/dist/Components/Table/Misc/SidePanel.svelte +35 -35
  69. package/dist/Components/Table/Misc/TableConfigurationModal.svelte +71 -0
  70. package/dist/Components/Table/Misc/ToolboxPanel.svelte +100 -100
  71. package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +107 -107
  72. package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte +225 -0
  73. package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte.d.ts +26 -0
  74. package/dist/Components/Table/Misc/UpdateViewOptionsModalProps.d.ts +21 -0
  75. package/dist/Components/Table/Misc/UpdateViewOptionsModalProps.js +1 -0
  76. package/dist/Components/Table/Types/Context/TableContext.svelte.d.ts +49 -1
  77. package/dist/Components/Table/Types/Context/TableContext.svelte.js +142 -1
  78. package/dist/Components/Table/Types/DataRepository/BuiltInRemoteRepository.svelte.d.ts +2 -2
  79. package/dist/Components/Table/Types/DataRepository/BuiltInRemoteRepository.svelte.js +20 -2
  80. package/dist/Components/Table/Types/DataRepository/IDataRepository.d.ts +9 -1
  81. package/dist/Components/Table/Types/DataRepository/ILocalDataRepository.d.ts +1 -1
  82. package/dist/Components/Table/Types/DataRepository/IRemoteDataRepository.d.ts +1 -1
  83. package/dist/Components/Table/Types/DataRepository/TableDataRepository.svelte.d.ts +1 -1
  84. package/dist/Components/Table/Types/Persistence/DatatableView.d.ts +25 -0
  85. package/dist/Components/Test/TestContextConsumer.svelte +13 -13
  86. package/dist/Components/TextArea.svelte +130 -130
  87. package/dist/Components/TextInput.svelte +176 -176
  88. package/dist/Components/ThreeStateRadio.svelte +131 -131
  89. package/dist/Components/Touch/BoolCard.svelte +45 -45
  90. package/dist/Components/Touch/DateModal.svelte +209 -209
  91. package/dist/Components/Touch/EditCard.svelte +59 -59
  92. package/dist/Components/Touch/InfoCard.svelte +31 -31
  93. package/dist/Components/Touch/InfoTextCard.svelte +28 -28
  94. package/dist/Components/Touch/ModalExplanation.svelte +17 -17
  95. package/dist/Components/Touch/NumberKeyboard.svelte +225 -225
  96. package/dist/Components/Touch/NumberModal.svelte +79 -79
  97. package/dist/Components/Touch/PlusMinusCard.svelte +46 -46
  98. package/dist/Components/Touch/SummaryCard.svelte +93 -93
  99. package/dist/Components/Touch/TextAreaModal.svelte +95 -95
  100. package/dist/Components/Touch/TextModal.svelte +106 -106
  101. package/dist/Components/Touch/TouchCard.svelte +33 -33
  102. package/dist/Components/Touch/TouchModal.svelte +274 -274
  103. package/dist/Components/Touch/UtilityButton.svelte +109 -109
  104. package/dist/Components/VerticalTabGroup.svelte +79 -79
  105. package/dist/Components/VerticalTabGroupButton.svelte +58 -58
  106. package/dist/Helpers/Datamatrix.d.ts +19 -19
  107. package/dist/Helpers/Datamatrix.js +291 -291
  108. package/dist/Types/Examples/ExampleModal.svelte +35 -35
  109. package/dist/index.d.ts +1 -1
  110. package/dist/scss/_basics.scss +12 -12
  111. package/dist/scss/_colours.scss +134 -134
  112. package/dist/scss/_motion.scss +57 -57
  113. package/dist/scss/_sizing.scss +85 -85
  114. package/dist/scss/_transitions.scss +8 -8
  115. package/package.json +1 -1
@@ -1,292 +1,292 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- lang="ts"
5
- generics="T extends object, RowIdType extends Primitive"
6
- >
7
- import type { ScoriaStorageKey } from '../../../../Types/Internal/Misc.js';
8
- import { dev } from '$app/environment';
9
- import { devCatch, generateWeakId } from '../../../../Helpers/Helpers.svelte.js';
10
- import { getContext, untrack } from 'svelte';
11
- import NestedTable from '../../NestedTable.svelte';
12
- import type { ExpandDef } from '../../Types/Columns/Definitions/Expand/ExpandDef.svelte.js';
13
- import type { DefsWrapper } from '../../Types/Columns/DefsWrapper.js';
14
- import type { TableCell } from '../../Types/Columns/TableCell.js';
15
- import { TableContext } from '../../Types/Context/TableContext.svelte.js';
16
- import { type Primitive } from '../../Types/Context/TableInitOptions.js';
17
- import ColumnHighlight from './ColumnHighlight.svelte';
18
- import TableColumn from './Columns/TableColumn.svelte';
19
- import type { TableRowProps } from './TableRowProps.js';
20
-
21
- const tableContext = getContext<TableContext<T, RowIdType>>(TableContext.identifier);
22
-
23
- const { row, odd = false, includeHighlight }: TableRowProps<T> = $props();
24
-
25
- const hoverable = $derived(tableContext.changeColourOnHover);
26
-
27
- // Visible cells in display order: left-pinned -> centre -> right-pinned.
28
- // The browser now handles row-height alignment natively because all
29
- // cells live in the same grid row, so the previous per-side fan-out
30
- // and height-reconciliation pool is gone.
31
- const leftCells: Array<TableCell<T>> = $derived(row.getLeftVisibleCells());
32
- const centreCells: Array<TableCell<T>> = $derived(row.getCenterVisibleCells());
33
- const rightCells: Array<TableCell<T>> = $derived(row.getRightVisibleCells());
34
-
35
- // Cumulative pinning offsets for the sticky-positioned cells. Reads
36
- // rendered widths from `_columnRenderedWidths` (populated by the
37
- // ResizeObserver in TableHead) so the sticky positions stay
38
- // accurate even though each pinned column track uses
39
- // `minmax(W, 1fr)` and the actual width can exceed `columnDef.width`.
40
- function renderedWidth(cell: TableCell<T>): number {
41
- return tableContext._columnRenderedWidths.get(cell.column.id) ?? cell.column.columnDef.width;
42
- }
43
-
44
- const leftOffsets: Array<number> = $derived.by(() => {
45
- void tableContext._columnRenderedWidths.size;
46
- const offsets: Array<number> = [];
47
- let cumulative = includeHighlight ? 20 : 0;
48
- for (const cell of leftCells) {
49
- offsets.push(cumulative);
50
- cumulative += renderedWidth(cell);
51
- }
52
- return offsets;
53
- });
54
-
55
- const rightOffsets: Array<number> = $derived.by(() => {
56
- void tableContext._columnRenderedWidths.size;
57
- const offsets = new Array<number>(rightCells.length).fill(0);
58
- let cumulative = 0;
59
- for (let i = rightCells.length - 1; i >= 0; i--) {
60
- offsets[i] = cumulative;
61
- cumulative += renderedWidth(rightCells[i]);
62
- }
63
- return offsets;
64
- });
65
-
66
- let expandedColumnDef: ExpandDef<T, object> | undefined = $state();
67
-
68
- $effect(() => {
69
- if (leftCells.length + centreCells.length + rightCells.length > 0) {
70
- void tableContext.table.data;
71
- void tableContext.paginationRepo?.paginationState.pageIndex;
72
- void tableContext.paginationRepo?.paginationState.pageSize;
73
- untrack(() => {
74
- expandedColumnDef = undefined;
75
- });
76
- }
77
- });
78
-
79
- let innerDataPromise: Array<object> | Promise<Array<object>> | undefined = $state();
80
- let innerColumnDefs: DefsWrapper<object> = $state({ defs: [] });
81
- let innerTableName: ScoriaStorageKey | undefined = $state();
82
-
83
- let prevExpandedColumnDef: ExpandDef<T, object> | undefined = $state();
84
-
85
- const firstCell = $derived(leftCells.at(0) ?? centreCells.at(0) ?? rightCells.at(0));
86
- const rowIndex = $derived(firstCell?.row.visibleIndex);
87
- let id = $state<RowIdType | undefined>();
88
- const highlighted = $derived(id != undefined && tableContext.highlightedItems.has(id));
89
-
90
- $effect(() => {
91
- void row.original;
92
- void tableContext.selectionExtractor;
93
-
94
- if (rowIndex != undefined) {
95
- const maybePromise = tableContext.selectionExtractor(row.original);
96
- if (maybePromise instanceof Promise) {
97
- maybePromise
98
- .then((it) => {
99
- id = it;
100
- })
101
- .catch(devCatch);
102
- } else {
103
- id = maybePromise;
104
- }
105
- } else {
106
- id = undefined;
107
- }
108
- });
109
-
110
- const showHighlightButton = $derived(rowIndex != null && includeHighlight);
111
-
112
- $effect(() => {
113
- void expandedColumnDef;
114
-
115
- untrack(() => {
116
- // Guard: if all columns have been hidden the cells arrays are
117
- // empty; `firstCell` would otherwise be undefined.
118
- if (!firstCell) {
119
- return;
120
- }
121
- if (expandedColumnDef && expandedColumnDef.id != prevExpandedColumnDef?.id) {
122
- prevExpandedColumnDef = expandedColumnDef;
123
- innerColumnDefs = expandedColumnDef.getInnerColumnDefs(
124
- firstCell.row.original,
125
- firstCell.row.originalIndex
126
- );
127
-
128
- innerDataPromise = expandedColumnDef.accessorFn(
129
- firstCell.row.original,
130
- firstCell.row.originalIndex
131
- ) as Promise<Array<object>>;
132
- innerTableName = expandedColumnDef.innerTableName;
133
- } else if (
134
- !expandedColumnDef ||
135
- tableContext.columnVisibility[expandedColumnDef.id] === false
136
- ) {
137
- innerTableName = undefined;
138
- expandedColumnDef = prevExpandedColumnDef = innerDataPromise = undefined;
139
- innerColumnDefs = { defs: [] };
140
- }
141
- });
142
- });
143
-
144
- function onExpandChange(columnDef: ExpandDef<T, object>) {
145
- if (expandedColumnDef?.id === columnDef.id) {
146
- expandedColumnDef = undefined;
147
- } else {
148
- expandedColumnDef = columnDef;
149
- }
150
- }
151
-
152
- // Stable fallback name used when an ExpandDef does not supply its own
153
- // `innerTableName`. Generating this once per row prevents localStorage
154
- // preset keys from accumulating UUID-keyed garbage every expand toggle.
155
- const fallbackInnerTableName = generateWeakId<ScoriaStorageKey>();
156
-
157
- /**
158
- * Inline style appended to a cell's `style="..."` when its column opts
159
- * into `wrapValue`. The hooks switch the leaf cell's `white-space`,
160
- * `overflow-x`, and `height` to wrap-friendly values. Implemented as
161
- * CSS-variable overrides so the table-cell-basic mixin in
162
- * `_mixins.scss` consumes them via `var(--cell-* , fallback)`.
163
- */
164
- function cellWrapStyle(cell: TableCell<T>): string {
165
- return cell.column.columnDef.wrapValue
166
- ? '--cell-white-space: normal; --cell-overflow-x: visible; --cell-height: auto; --cell-min-height: var(--height);'
167
- : '';
168
- }
169
- </script>
170
-
171
- <div
172
- role="row"
173
- class="datatable-row"
174
- class:hoverable
175
- class:alt={tableContext.alternateRowColours && odd}
176
- class:highlighted
177
- >
178
- {#if showHighlightButton}
179
- <div
180
- role="cell"
181
- class="cell highlight-cell pinned-left"
182
- style="left: 0px"
183
- >
184
- <ColumnHighlight
185
- rowIndex={rowIndex ??
186
- (() => {
187
- if (dev) {
188
- console.error(`column had invalid row index: ${rowIndex}`);
189
- }
190
- return -1;
191
- })()}
192
- {highlighted}
193
- toggleHighlightedRow={() => {
194
- tableContext.toggleHighlightedRow(row.original)?.catch(devCatch);
195
- }}
196
- />
197
- </div>
198
- {/if}
199
- {#each leftCells as cell, index (cell.column.id)}
200
- <div
201
- role="cell"
202
- class="cell pinned-left"
203
- style="left: {leftOffsets[index]}px; {cellWrapStyle(cell)}"
204
- >
205
- <TableColumn
206
- {cell}
207
- {expandedColumnDef}
208
- {onExpandChange}
209
- />
210
- </div>
211
- {/each}
212
- {#each centreCells as cell (cell.column.id)}
213
- <div
214
- role="cell"
215
- class="cell"
216
- style={cellWrapStyle(cell)}
217
- >
218
- <TableColumn
219
- {cell}
220
- {expandedColumnDef}
221
- {onExpandChange}
222
- />
223
- </div>
224
- {/each}
225
- {#each rightCells as cell, index (cell.column.id)}
226
- <div
227
- role="cell"
228
- class="cell pinned-right"
229
- style="right: {rightOffsets[index]}px; {cellWrapStyle(cell)}"
230
- >
231
- <TableColumn
232
- {cell}
233
- {expandedColumnDef}
234
- {onExpandChange}
235
- />
236
- </div>
237
- {/each}
238
- </div>
239
-
240
- {#if expandedColumnDef}
241
- <div
242
- role="row"
243
- class="datatable-row expand-row"
244
- >
245
- <div
246
- role="cell"
247
- class="cell expand-cell"
248
- >
249
- {#await innerDataPromise}
250
- loading&hellip;
251
- {:then data}
252
- {#if data && data.length}
253
- {@const options = expandedColumnDef.innerTableOptions}
254
- {#if innerTableName}
255
- {#key innerTableName}
256
- <NestedTable
257
- tableName={innerTableName}
258
- {data}
259
- columnDefWrapper={innerColumnDefs}
260
- {options}
261
- getUserId={tableContext.getUserId}
262
- />
263
- {/key}
264
- {:else}
265
- <NestedTable
266
- tableName={fallbackInnerTableName}
267
- {data}
268
- columnDefWrapper={innerColumnDefs}
269
- {options}
270
- getUserId={tableContext.getUserId}
271
- />
272
- {/if}
273
- {:else if !data}
274
- Error Fetching data
275
- {:else}
276
- No Data
277
- {/if}
278
- {:catch e}
279
- {#if dev}
280
- error: {e}
281
- <!-- eslint-disable-next-line svelte/no-at-debug-tags -->
282
- {@debug e}
283
- {/if}
284
- Error Fetching data
285
- {/await}
286
- </div>
287
- </div>
288
- {/if}
289
-
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ generics="T extends object, RowIdType extends Primitive"
6
+ >
7
+ import type { ScoriaStorageKey } from '../../../../Types/Internal/Misc.js';
8
+ import { dev } from '$app/environment';
9
+ import { devCatch, generateWeakId } from '../../../../Helpers/Helpers.svelte.js';
10
+ import { getContext, untrack } from 'svelte';
11
+ import NestedTable from '../../NestedTable.svelte';
12
+ import type { ExpandDef } from '../../Types/Columns/Definitions/Expand/ExpandDef.svelte.js';
13
+ import type { DefsWrapper } from '../../Types/Columns/DefsWrapper.js';
14
+ import type { TableCell } from '../../Types/Columns/TableCell.js';
15
+ import { TableContext } from '../../Types/Context/TableContext.svelte.js';
16
+ import { type Primitive } from '../../Types/Context/TableInitOptions.js';
17
+ import ColumnHighlight from './ColumnHighlight.svelte';
18
+ import TableColumn from './Columns/TableColumn.svelte';
19
+ import type { TableRowProps } from './TableRowProps.js';
20
+
21
+ const tableContext = getContext<TableContext<T, RowIdType>>(TableContext.identifier);
22
+
23
+ const { row, odd = false, includeHighlight }: TableRowProps<T> = $props();
24
+
25
+ const hoverable = $derived(tableContext.changeColourOnHover);
26
+
27
+ // Visible cells in display order: left-pinned -> centre -> right-pinned.
28
+ // The browser now handles row-height alignment natively because all
29
+ // cells live in the same grid row, so the previous per-side fan-out
30
+ // and height-reconciliation pool is gone.
31
+ const leftCells: Array<TableCell<T>> = $derived(row.getLeftVisibleCells());
32
+ const centreCells: Array<TableCell<T>> = $derived(row.getCenterVisibleCells());
33
+ const rightCells: Array<TableCell<T>> = $derived(row.getRightVisibleCells());
34
+
35
+ // Cumulative pinning offsets for the sticky-positioned cells. Reads
36
+ // rendered widths from `_columnRenderedWidths` (populated by the
37
+ // ResizeObserver in TableHead) so the sticky positions stay
38
+ // accurate even though each pinned column track uses
39
+ // `minmax(W, 1fr)` and the actual width can exceed `columnDef.width`.
40
+ function renderedWidth(cell: TableCell<T>): number {
41
+ return tableContext._columnRenderedWidths.get(cell.column.id) ?? cell.column.columnDef.width;
42
+ }
43
+
44
+ const leftOffsets: Array<number> = $derived.by(() => {
45
+ void tableContext._columnRenderedWidths.size;
46
+ const offsets: Array<number> = [];
47
+ let cumulative = includeHighlight ? 20 : 0;
48
+ for (const cell of leftCells) {
49
+ offsets.push(cumulative);
50
+ cumulative += renderedWidth(cell);
51
+ }
52
+ return offsets;
53
+ });
54
+
55
+ const rightOffsets: Array<number> = $derived.by(() => {
56
+ void tableContext._columnRenderedWidths.size;
57
+ const offsets = new Array<number>(rightCells.length).fill(0);
58
+ let cumulative = 0;
59
+ for (let i = rightCells.length - 1; i >= 0; i--) {
60
+ offsets[i] = cumulative;
61
+ cumulative += renderedWidth(rightCells[i]);
62
+ }
63
+ return offsets;
64
+ });
65
+
66
+ let expandedColumnDef: ExpandDef<T, object> | undefined = $state();
67
+
68
+ $effect(() => {
69
+ if (leftCells.length + centreCells.length + rightCells.length > 0) {
70
+ void tableContext.table.data;
71
+ void tableContext.paginationRepo?.paginationState.pageIndex;
72
+ void tableContext.paginationRepo?.paginationState.pageSize;
73
+ untrack(() => {
74
+ expandedColumnDef = undefined;
75
+ });
76
+ }
77
+ });
78
+
79
+ let innerDataPromise: Array<object> | Promise<Array<object>> | undefined = $state();
80
+ let innerColumnDefs: DefsWrapper<object> = $state({ defs: [] });
81
+ let innerTableName: ScoriaStorageKey | undefined = $state();
82
+
83
+ let prevExpandedColumnDef: ExpandDef<T, object> | undefined = $state();
84
+
85
+ const firstCell = $derived(leftCells.at(0) ?? centreCells.at(0) ?? rightCells.at(0));
86
+ const rowIndex = $derived(firstCell?.row.visibleIndex);
87
+ let id = $state<RowIdType | undefined>();
88
+ const highlighted = $derived(id != undefined && tableContext.highlightedItems.has(id));
89
+
90
+ $effect(() => {
91
+ void row.original;
92
+ void tableContext.selectionExtractor;
93
+
94
+ if (rowIndex != undefined) {
95
+ const maybePromise = tableContext.selectionExtractor(row.original);
96
+ if (maybePromise instanceof Promise) {
97
+ maybePromise
98
+ .then((it) => {
99
+ id = it;
100
+ })
101
+ .catch(devCatch);
102
+ } else {
103
+ id = maybePromise;
104
+ }
105
+ } else {
106
+ id = undefined;
107
+ }
108
+ });
109
+
110
+ const showHighlightButton = $derived(rowIndex != null && includeHighlight);
111
+
112
+ $effect(() => {
113
+ void expandedColumnDef;
114
+
115
+ untrack(() => {
116
+ // Guard: if all columns have been hidden the cells arrays are
117
+ // empty; `firstCell` would otherwise be undefined.
118
+ if (!firstCell) {
119
+ return;
120
+ }
121
+ if (expandedColumnDef && expandedColumnDef.id != prevExpandedColumnDef?.id) {
122
+ prevExpandedColumnDef = expandedColumnDef;
123
+ innerColumnDefs = expandedColumnDef.getInnerColumnDefs(
124
+ firstCell.row.original,
125
+ firstCell.row.originalIndex
126
+ );
127
+
128
+ innerDataPromise = expandedColumnDef.accessorFn(
129
+ firstCell.row.original,
130
+ firstCell.row.originalIndex
131
+ ) as Promise<Array<object>>;
132
+ innerTableName = expandedColumnDef.innerTableName;
133
+ } else if (
134
+ !expandedColumnDef ||
135
+ tableContext.columnVisibility[expandedColumnDef.id] === false
136
+ ) {
137
+ innerTableName = undefined;
138
+ expandedColumnDef = prevExpandedColumnDef = innerDataPromise = undefined;
139
+ innerColumnDefs = { defs: [] };
140
+ }
141
+ });
142
+ });
143
+
144
+ function onExpandChange(columnDef: ExpandDef<T, object>) {
145
+ if (expandedColumnDef?.id === columnDef.id) {
146
+ expandedColumnDef = undefined;
147
+ } else {
148
+ expandedColumnDef = columnDef;
149
+ }
150
+ }
151
+
152
+ // Stable fallback name used when an ExpandDef does not supply its own
153
+ // `innerTableName`. Generating this once per row prevents localStorage
154
+ // preset keys from accumulating UUID-keyed garbage every expand toggle.
155
+ const fallbackInnerTableName = generateWeakId<ScoriaStorageKey>();
156
+
157
+ /**
158
+ * Inline style appended to a cell's `style="..."` when its column opts
159
+ * into `wrapValue`. The hooks switch the leaf cell's `white-space`,
160
+ * `overflow-x`, and `height` to wrap-friendly values. Implemented as
161
+ * CSS-variable overrides so the table-cell-basic mixin in
162
+ * `_mixins.scss` consumes them via `var(--cell-* , fallback)`.
163
+ */
164
+ function cellWrapStyle(cell: TableCell<T>): string {
165
+ return cell.column.columnDef.wrapValue
166
+ ? '--cell-white-space: normal; --cell-overflow-x: visible; --cell-height: auto; --cell-min-height: var(--height);'
167
+ : '';
168
+ }
169
+ </script>
170
+
171
+ <div
172
+ role="row"
173
+ class="datatable-row"
174
+ class:hoverable
175
+ class:alt={tableContext.alternateRowColours && odd}
176
+ class:highlighted
177
+ >
178
+ {#if showHighlightButton}
179
+ <div
180
+ role="cell"
181
+ class="cell highlight-cell pinned-left"
182
+ style="left: 0px"
183
+ >
184
+ <ColumnHighlight
185
+ rowIndex={rowIndex ??
186
+ (() => {
187
+ if (dev) {
188
+ console.error(`column had invalid row index: ${rowIndex}`);
189
+ }
190
+ return -1;
191
+ })()}
192
+ {highlighted}
193
+ toggleHighlightedRow={() => {
194
+ tableContext.toggleHighlightedRow(row.original)?.catch(devCatch);
195
+ }}
196
+ />
197
+ </div>
198
+ {/if}
199
+ {#each leftCells as cell, index (cell.column.id)}
200
+ <div
201
+ role="cell"
202
+ class="cell pinned-left"
203
+ style="left: {leftOffsets[index]}px; {cellWrapStyle(cell)}"
204
+ >
205
+ <TableColumn
206
+ {cell}
207
+ {expandedColumnDef}
208
+ {onExpandChange}
209
+ />
210
+ </div>
211
+ {/each}
212
+ {#each centreCells as cell (cell.column.id)}
213
+ <div
214
+ role="cell"
215
+ class="cell"
216
+ style={cellWrapStyle(cell)}
217
+ >
218
+ <TableColumn
219
+ {cell}
220
+ {expandedColumnDef}
221
+ {onExpandChange}
222
+ />
223
+ </div>
224
+ {/each}
225
+ {#each rightCells as cell, index (cell.column.id)}
226
+ <div
227
+ role="cell"
228
+ class="cell pinned-right"
229
+ style="right: {rightOffsets[index]}px; {cellWrapStyle(cell)}"
230
+ >
231
+ <TableColumn
232
+ {cell}
233
+ {expandedColumnDef}
234
+ {onExpandChange}
235
+ />
236
+ </div>
237
+ {/each}
238
+ </div>
239
+
240
+ {#if expandedColumnDef}
241
+ <div
242
+ role="row"
243
+ class="datatable-row expand-row"
244
+ >
245
+ <div
246
+ role="cell"
247
+ class="cell expand-cell"
248
+ >
249
+ {#await innerDataPromise}
250
+ loading&hellip;
251
+ {:then data}
252
+ {#if data && data.length}
253
+ {@const options = expandedColumnDef.innerTableOptions}
254
+ {#if innerTableName}
255
+ {#key innerTableName}
256
+ <NestedTable
257
+ tableName={innerTableName}
258
+ {data}
259
+ columnDefWrapper={innerColumnDefs}
260
+ {options}
261
+ getUserId={tableContext.getUserId}
262
+ />
263
+ {/key}
264
+ {:else}
265
+ <NestedTable
266
+ tableName={fallbackInnerTableName}
267
+ {data}
268
+ columnDefWrapper={innerColumnDefs}
269
+ {options}
270
+ getUserId={tableContext.getUserId}
271
+ />
272
+ {/if}
273
+ {:else if !data}
274
+ Error Fetching data
275
+ {:else}
276
+ No Data
277
+ {/if}
278
+ {:catch e}
279
+ {#if dev}
280
+ error: {e}
281
+ <!-- eslint-disable-next-line svelte/no-at-debug-tags -->
282
+ {@debug e}
283
+ {/if}
284
+ Error Fetching data
285
+ {/await}
286
+ </div>
287
+ </div>
288
+ {/if}
289
+
290
290
  <style>.datatable-row {
291
291
  display: grid;
292
292
  grid-template-columns: var(--cols);
@@ -351,4 +351,4 @@
351
351
  padding: 0;
352
352
  display: block;
353
353
  width: 100%;
354
- }</style>
354
+ }</style>
@@ -1,43 +1,43 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- lang="ts"
5
- generics="T extends object, IdType extends Primitive"
6
- >
7
- import { devCatch } from '../../../Helpers/Helpers.svelte.js';
8
- import { Colour } from '../../../scss/colours.js';
9
- import { Size } from '../../../Types/Internal/Size.js';
10
- import { getContext } from 'svelte';
11
- import Action from '../../Action.svelte';
12
- import { TableContext } from '../Types/Context/TableContext.svelte.js';
13
- import type { Primitive } from '../Types/Context/TableInitOptions.js';
14
-
15
- const tableContext = getContext<TableContext<T, IdType>>(TableContext.identifier);
16
-
17
- const backgroundColour = $derived.by(() => {
18
- return tableContext.sortedData.length > 0 && tableContext.allHighlighted
19
- ? Colour['$brand-primary']
20
- : Colour['$ui-white'];
21
- });
22
- </script>
23
-
24
- <div class="highlight-header">
25
- <div class="wrapper">
26
- <Action
27
- label="Highlight all rows"
28
- {backgroundColour}
29
- hoverBackgroundColour={Colour['$brand-dark']}
30
- size={Size.FillWidth}
31
- icon={{
32
- name: 'nothing',
33
- }}
34
- onclick={() => {
35
- tableContext.onHighlightAll()?.catch(devCatch);
36
- }}
37
- />
38
- </div>
39
- </div>
40
-
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ generics="T extends object, IdType extends Primitive"
6
+ >
7
+ import { devCatch } from '../../../Helpers/Helpers.svelte.js';
8
+ import { Colour } from '../../../scss/colours.js';
9
+ import { Size } from '../../../Types/Internal/Size.js';
10
+ import { getContext } from 'svelte';
11
+ import Action from '../../Action.svelte';
12
+ import { TableContext } from '../Types/Context/TableContext.svelte.js';
13
+ import type { Primitive } from '../Types/Context/TableInitOptions.js';
14
+
15
+ const tableContext = getContext<TableContext<T, IdType>>(TableContext.identifier);
16
+
17
+ const backgroundColour = $derived.by(() => {
18
+ return tableContext.sortedData.length > 0 && tableContext.allHighlighted
19
+ ? Colour['$brand-primary']
20
+ : Colour['$ui-white'];
21
+ });
22
+ </script>
23
+
24
+ <div class="highlight-header">
25
+ <div class="wrapper">
26
+ <Action
27
+ label="Highlight all rows"
28
+ {backgroundColour}
29
+ hoverBackgroundColour={Colour['$brand-dark']}
30
+ size={Size.FillWidth}
31
+ icon={{
32
+ name: 'nothing',
33
+ }}
34
+ onclick={() => {
35
+ tableContext.onHighlightAll()?.catch(devCatch);
36
+ }}
37
+ />
38
+ </div>
39
+ </div>
40
+
41
41
  <style>div.wrapper {
42
42
  position: absolute;
43
43
  top: 0;
@@ -47,4 +47,4 @@
47
47
  display: flex;
48
48
  align-items: stretch;
49
49
  justify-content: stretch;
50
- }</style>
50
+ }</style>