@lavalogic/scoria 0.33.0 → 0.35.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.
- package/README.md +58 -58
- package/dist/Components/AccordionGroup.svelte +44 -63
- package/dist/Components/AccordionGroup.svelte.d.ts +2 -25
- package/dist/Components/AccordionGroupButton.svelte +106 -114
- package/dist/Components/AccordionGroupButton.svelte.d.ts +2 -2
- package/dist/Components/AccordionGroupButtonProps.d.ts +21 -0
- package/dist/Components/AccordionGroupButtonProps.js +1 -0
- package/dist/Components/Action.svelte +138 -138
- package/dist/Components/AlertModal.svelte +125 -125
- package/dist/Components/Base/ContextWrapper.svelte +50 -50
- package/dist/Components/Base/Pagination.svelte +190 -190
- package/dist/Components/Base/Snippets.svelte +29 -29
- package/dist/Components/BigRadioSet.svelte +29 -29
- package/dist/Components/Bubble.svelte +77 -77
- package/dist/Components/Button.svelte +197 -197
- package/dist/Components/Checkbox.svelte +68 -68
- package/dist/Components/CollapsibleCard.svelte +70 -70
- package/dist/Components/Contexts/ContextMenu.svelte +157 -157
- package/dist/Components/Contexts/ContextMenuDivider.svelte +11 -11
- package/dist/Components/Contexts/ContextMenuOption.svelte +52 -52
- package/dist/Components/Contexts/Toast.svelte +61 -61
- package/dist/Components/Contexts/ToastContainer.svelte +46 -46
- package/dist/Components/Contexts/Tooltip.svelte +26 -26
- package/dist/Components/DataMatrixIcon.svelte +41 -41
- package/dist/Components/DateInput.svelte +109 -109
- package/dist/Components/DatePicker.svelte +312 -312
- package/dist/Components/DesktopModal.svelte +106 -106
- package/dist/Components/Dial.svelte +151 -151
- package/dist/Components/DimensionInput.svelte +184 -184
- package/dist/Components/DragMenu/DragMenuHolder.svelte +106 -106
- package/dist/Components/DragMenu/DraggableCard.svelte +41 -41
- package/dist/Components/FileCard.svelte +20 -20
- package/dist/Components/FileUpload.svelte +196 -196
- package/dist/Components/GridInput.svelte +190 -190
- package/dist/Components/GridInputSet.svelte +22 -22
- package/dist/Components/HorizontalTabGroup.svelte +78 -78
- package/dist/Components/HorizontalTabGroupButton.svelte +96 -96
- package/dist/Components/Icon.svelte +97 -97
- package/dist/Components/Icons.js +357 -357
- package/dist/Components/LoadingAnimation.svelte +32 -32
- package/dist/Components/LoadingModal.svelte +47 -47
- package/dist/Components/LoadingOverlay.svelte +27 -27
- package/dist/Components/Modal.svelte +251 -251
- package/dist/Components/MultiSelect.svelte +197 -197
- package/dist/Components/Nav/Nav.svelte +97 -97
- package/dist/Components/Nav/NavServiceMenuList.svelte +34 -34
- package/dist/Components/Nav/NavTab.svelte +91 -91
- package/dist/Components/Nav/ServiceMenuItem.svelte +91 -91
- package/dist/Components/Nav/ServicesNav.svelte +53 -53
- package/dist/Components/NumberInput.svelte +144 -144
- package/dist/Components/PageHeading.svelte +36 -36
- package/dist/Components/PasswordInput.svelte +73 -73
- package/dist/Components/Portal.svelte +25 -25
- package/dist/Components/ProgressBubble.svelte +80 -80
- package/dist/Components/QuerySelect.svelte +411 -411
- package/dist/Components/SingleSelect.svelte +261 -261
- package/dist/Components/StepButton.svelte +120 -120
- package/dist/Components/StepForm.svelte +108 -108
- package/dist/Components/Switch.svelte +36 -36
- package/dist/Components/Table/Body/QuickSearchCell.svelte +632 -632
- package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +30 -30
- package/dist/Components/Table/Body/Rows/ColumnList.svelte +56 -56
- package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +179 -179
- package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +49 -49
- package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +180 -180
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +102 -102
- package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +119 -119
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +114 -114
- package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +96 -96
- package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +72 -72
- package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +131 -131
- package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +144 -144
- package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +238 -238
- package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +358 -358
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +338 -338
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +183 -183
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +309 -309
- package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +369 -369
- package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +170 -170
- package/dist/Components/Table/Body/Rows/TableRow.svelte +259 -259
- package/dist/Components/Table/Body/TableBody.svelte +67 -67
- package/dist/Components/Table/Headers/HighlightAllHeader.svelte +39 -39
- package/dist/Components/Table/Headers/SelectAllHeader.svelte +28 -28
- package/dist/Components/Table/Headers/TableHead.svelte +260 -260
- package/dist/Components/Table/Misc/ColumnPanel.svelte +78 -78
- package/dist/Components/Table/Misc/ColumnPanelModal.svelte +99 -99
- package/dist/Components/Table/Misc/FilterInput.svelte +556 -556
- package/dist/Components/Table/Misc/FilterPanel.svelte +46 -46
- package/dist/Components/Table/Misc/FilterPanelModal.svelte +67 -67
- package/dist/Components/Table/Misc/SidePanel.svelte +32 -32
- package/dist/Components/Table/Misc/TableFooter.svelte +304 -304
- package/dist/Components/Table/Misc/TableHorizontalBar.svelte +156 -156
- package/dist/Components/Table/Misc/TableSidebar.svelte +176 -176
- package/dist/Components/Table/Misc/ToolboxPanel.svelte +77 -77
- package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +91 -91
- package/dist/Components/Table/NestedTable.svelte +84 -84
- package/dist/Components/Table/Table.svelte +492 -492
- package/dist/Components/Test/TestContextConsumer.svelte +13 -13
- package/dist/Components/TextArea.svelte +108 -108
- package/dist/Components/TextInput.svelte +147 -147
- package/dist/Components/ThreeStateRadio.svelte +124 -124
- package/dist/Components/Touch/BoolCard.svelte +52 -52
- package/dist/Components/Touch/DateModal.svelte +217 -217
- package/dist/Components/Touch/EditCard.svelte +52 -52
- package/dist/Components/Touch/InfoCard.svelte +24 -24
- package/dist/Components/Touch/InfoTextCard.svelte +21 -21
- package/dist/Components/Touch/ModalExplanation.svelte +20 -20
- package/dist/Components/Touch/NumberKeyboard.svelte +268 -268
- package/dist/Components/Touch/NumberModal.svelte +69 -69
- package/dist/Components/Touch/PlusMinusCard.svelte +50 -50
- package/dist/Components/Touch/SelectModal.svelte +105 -105
- package/dist/Components/Touch/SummaryCard.svelte +65 -65
- package/dist/Components/Touch/TextAreaModal.svelte +86 -86
- package/dist/Components/Touch/TextModal.svelte +123 -123
- package/dist/Components/Touch/TouchCard.svelte +28 -28
- package/dist/Components/Touch/TouchModal.svelte +259 -259
- package/dist/Components/Touch/UtilityButton.svelte +91 -91
- package/dist/Components/VerticalTabGroup.svelte +66 -66
- package/dist/Components/VerticalTabGroupButton.svelte +97 -97
- package/dist/Helpers/Datamatrix.d.ts +10 -10
- package/dist/Helpers/Datamatrix.js +1 -1
- package/dist/Helpers/Helpers.svelte.js +6 -4
- package/dist/Types/Examples/ExampleModal.svelte +34 -34
- package/dist/index.d.ts +1 -0
- package/dist/scss/_basics.scss +12 -12
- package/dist/scss/_colours.scss +134 -134
- package/dist/scss/_mixins.scss +3016 -3016
- package/dist/scss/_sizing.scss +69 -69
- package/dist/scss/_transitions.scss +8 -8
- package/package.json +2 -2
|
@@ -1,494 +1,494 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<script
|
|
4
|
-
lang="ts"
|
|
5
|
-
module
|
|
6
|
-
>
|
|
7
|
-
import {
|
|
8
|
-
ContextMenuContext,
|
|
9
|
-
type IContextMenuOption,
|
|
10
|
-
} from '../../Contexts/ContextMenuContext.svelte';
|
|
11
|
-
import { devCatch, refWrapper } from '../../Helpers/Helpers.svelte';
|
|
12
|
-
import type { RefWrapper } from '../../Types/Internal/RefWrapper.js';
|
|
13
|
-
import { getContext, onMount, setContext, tick, untrack } from 'svelte';
|
|
14
|
-
import LoadingOverlay from '../LoadingOverlay.svelte';
|
|
15
|
-
import type { HeightData } from './Body/HeightData.js';
|
|
16
|
-
import { shownPopup } from './Body/Rows/Columns/ActionsCell.svelte';
|
|
17
|
-
import TableBody from './Body/TableBody.svelte';
|
|
18
|
-
import TableHead from './Headers/TableHead.svelte';
|
|
19
|
-
import TableFooter from './Misc/TableFooter.svelte';
|
|
20
|
-
import TableHorizontalBar from './Misc/TableHorizontalBar.svelte';
|
|
21
|
-
import TableSidebar from './Misc/TableSidebar.svelte';
|
|
22
|
-
import { TableContext } from './Types/Context/TableContext.svelte';
|
|
23
|
-
import type { Primitive } from './Types/Context/TableInitOptions.js';
|
|
24
|
-
import { PaginationType } from './Types/Pagination/PaginationType.js';
|
|
25
|
-
import { ToolbarPosition } from './Types/Toolbar/ToolbarPosition.js';
|
|
26
|
-
|
|
27
|
-
declare global {
|
|
28
|
-
interface HTMLElementEventMap {
|
|
29
|
-
edit: CustomEvent<{
|
|
30
|
-
selectAll: boolean;
|
|
31
|
-
}>;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface TableProps<T extends object, IdType extends Primitive> {
|
|
36
|
-
readonly tableContext: TableContext<T, IdType>;
|
|
37
|
-
nested?: boolean;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export const quickFilterContextIdentifier: symbol = Symbol();
|
|
41
|
-
|
|
42
|
-
const openedQuickFilterSelect = refWrapper(null);
|
|
43
|
-
</script>
|
|
44
|
-
|
|
45
|
-
<script
|
|
46
|
-
lang="ts"
|
|
47
|
-
generics="T extends object,IdType extends Primitive"
|
|
48
|
-
>
|
|
49
|
-
const { nested = false, tableContext }: TableProps<T, IdType> = $props();
|
|
50
|
-
|
|
51
|
-
// NOTE: known limitation. This is passed as a wrapper, and they should never require reassignment. It is deeply reactive
|
|
52
|
-
// svelte-ignore state_referenced_locally
|
|
53
|
-
setContext(TableContext.identifier, tableContext);
|
|
54
|
-
|
|
55
|
-
const { openContextMenu: _openContextMenu } = getContext<ContextMenuContext>(
|
|
56
|
-
ContextMenuContext.identifier
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
let ref: HTMLDivElement | undefined = $state();
|
|
60
|
-
let unfocusRef: HTMLDivElement | undefined = $state();
|
|
61
|
-
|
|
62
|
-
setContext(quickFilterContextIdentifier, openedQuickFilterSelect);
|
|
63
|
-
|
|
64
|
-
$effect(() => {
|
|
65
|
-
void tableContext.focusStart;
|
|
66
|
-
void ref;
|
|
67
|
-
untrack(() => {
|
|
68
|
-
if (tableContext.focusStart && ref) {
|
|
69
|
-
const { row, column: index } = tableContext.focusStart;
|
|
70
|
-
let element = ref.querySelector(
|
|
71
|
-
`#${tableContext.tableName}-cell-${row}-${tableContext.columnDefs[index].id}`
|
|
72
|
-
) as HTMLElement | undefined;
|
|
73
|
-
|
|
74
|
-
if (element?.tabIndex == -1) {
|
|
75
|
-
const td = element;
|
|
76
|
-
element = td.querySelector('button') as HTMLElement | undefined;
|
|
77
|
-
if (!element) {
|
|
78
|
-
element = td.querySelector('input') as HTMLElement | undefined;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
element?.focus({ preventScroll: true });
|
|
83
|
-
element?.scrollIntoView({
|
|
84
|
-
behavior: 'instant',
|
|
85
|
-
block: 'nearest',
|
|
86
|
-
inline: 'nearest',
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
$effect(() => {
|
|
93
|
-
if (tableContext.focusEnd && ref) {
|
|
94
|
-
const { row, column: index } = tableContext.focusEnd;
|
|
95
|
-
const cell = ref.querySelector(
|
|
96
|
-
`#${tableContext.tableName}-cell-${row}-${tableContext.columnDefs[index].id}`
|
|
97
|
-
) as HTMLElement | undefined;
|
|
98
|
-
|
|
99
|
-
cell?.scrollIntoView({
|
|
100
|
-
behavior: 'instant',
|
|
101
|
-
block: 'nearest',
|
|
102
|
-
inline: 'nearest',
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
function openContextMenu(e: MouseEvent) {
|
|
108
|
-
e.stopPropagation();
|
|
109
|
-
|
|
110
|
-
if (
|
|
111
|
-
(e.target as HTMLElement).tagName === 'INPUT' ||
|
|
112
|
-
(e.target as HTMLElement).closest('.select-wrapper') != null
|
|
113
|
-
) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const clickedElement = document.activeElement?.id.split('-cell-')[1]?.split('-');
|
|
118
|
-
|
|
119
|
-
if (clickedElement) {
|
|
120
|
-
const [rowString, columnId] = clickedElement;
|
|
121
|
-
const row = parseInt(rowString);
|
|
122
|
-
|
|
123
|
-
if (
|
|
124
|
-
!tableContext.focusedColumnIds.has(columnId) ||
|
|
125
|
-
!tableContext.focusedRowIndices.has(row)
|
|
126
|
-
) {
|
|
127
|
-
const columnIndex = tableContext.columnDefs.find((it) => it.id === columnId)?.index;
|
|
128
|
-
|
|
129
|
-
if (columnIndex) {
|
|
130
|
-
tableContext.moveFocus({
|
|
131
|
-
column: columnIndex,
|
|
132
|
-
row,
|
|
133
|
-
id: columnId,
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// this may not exist in http contexts
|
|
140
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
141
|
-
if (tableContext.allowCopy && window.Clipboard) {
|
|
142
|
-
e.preventDefault();
|
|
143
|
-
|
|
144
|
-
const options: Array<IContextMenuOption> = [
|
|
145
|
-
{
|
|
146
|
-
callback: () => {
|
|
147
|
-
tableContext.copyDataToClipboard().catch(devCatch);
|
|
148
|
-
},
|
|
149
|
-
text: 'Copy Selection',
|
|
150
|
-
},
|
|
151
|
-
];
|
|
152
|
-
|
|
153
|
-
if (tableContext.hasHighlightedItems) {
|
|
154
|
-
options.push({
|
|
155
|
-
callback: () => {
|
|
156
|
-
tableContext.copyHighlightedRowsToClipboard().catch(devCatch);
|
|
157
|
-
},
|
|
158
|
-
text: 'Copy Highlighted Rows',
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
_openContextMenu(e, options).catch(devCatch);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function handleClickOutside(e: MouseEvent) {
|
|
167
|
-
const target = e.target as HTMLElement;
|
|
168
|
-
if (target.isConnected) {
|
|
169
|
-
if (target.closest('div.floating') == null && target.closest('div.stick-right') == null) {
|
|
170
|
-
openedQuickFilterSelect.value = null;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (target.closest('div.slot-wrapper') == null) {
|
|
174
|
-
// svelte type gen/eslint miscommunication
|
|
175
|
-
(shownPopup as RefWrapper<symbol | undefined>).value = undefined;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// nested table resizing
|
|
181
|
-
let isResizing = $state(false);
|
|
182
|
-
let remPxRatio = $state(0);
|
|
183
|
-
const minNestedHeight = $derived(20 * remPxRatio);
|
|
184
|
-
|
|
185
|
-
// HACK please figure this one out
|
|
186
|
-
let nestedHeight = $derived(minNestedHeight);
|
|
187
|
-
|
|
188
|
-
let tableRef: HTMLDivElement | undefined = undefined;
|
|
189
|
-
let mousedDownEmptySpace = $state(false);
|
|
190
|
-
|
|
191
|
-
onMount(() => {
|
|
192
|
-
remPxRatio = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
function addOverrideResizeHandler() {
|
|
196
|
-
isResizing = true;
|
|
197
|
-
window.addEventListener('mousemove', onResize);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function onResize(e: MouseEvent) {
|
|
201
|
-
const sliderHeight = tableRef ? e.clientY - tableRef.getBoundingClientRect().top : 0;
|
|
202
|
-
nestedHeight = Math.max(sliderHeight, minNestedHeight);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function removeOverrideResizeHandler() {
|
|
206
|
-
isResizing = false;
|
|
207
|
-
window.removeEventListener('mousemove', onResize);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const usesLoading = $derived(
|
|
211
|
-
tableContext.paginationRepo &&
|
|
212
|
-
tableContext.paginationRepo.paginationType === PaginationType.Remote
|
|
213
|
-
);
|
|
214
|
-
|
|
215
|
-
const shouldUnfocusRemote = $derived(
|
|
216
|
-
usesLoading &&
|
|
217
|
-
tableContext.paginationRepo?.isLoading === false &&
|
|
218
|
-
tableContext.paginationRepo.paginationState.pageIndex !==
|
|
219
|
-
tableContext.paginationRepo.previouslyViewedPage
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
const shouldUnfocusLocal = $derived(
|
|
223
|
-
!usesLoading && tableContext.paginationRepo?.paginationState.pageIndex
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
$effect(() => {
|
|
227
|
-
if ((shouldUnfocusRemote || shouldUnfocusLocal) && unfocusRef) {
|
|
228
|
-
untrack(() => {
|
|
229
|
-
tableContext.unfocus();
|
|
230
|
-
});
|
|
231
|
-
unfocusRef.scrollTop = 0;
|
|
232
|
-
} else if (usesLoading && tableContext.paginationRepo?.isLoading === false) {
|
|
233
|
-
// refocus same element after a reload
|
|
234
|
-
// this does not break mutifocus
|
|
235
|
-
untrack(() => {
|
|
236
|
-
const fs = tableContext.focusStart;
|
|
237
|
-
if (!fs) {
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
const idToFocusTo = `#${tableContext.tableName}-cell-${fs.row}-${fs.id}`;
|
|
241
|
-
|
|
242
|
-
tick()
|
|
243
|
-
.then(() => {
|
|
244
|
-
if (idToFocusTo) {
|
|
245
|
-
(document.querySelector(idToFocusTo) as HTMLTableCellElement | undefined)?.focus();
|
|
246
|
-
}
|
|
247
|
-
})
|
|
248
|
-
.catch(devCatch);
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
const leftTotalSize = $derived(tableContext.table.getLeftTotalSize());
|
|
254
|
-
const centreTotalSize = $derived(tableContext.table.getCenterTotalSize());
|
|
255
|
-
const rightTotalSize = $derived(tableContext.table.getRightTotalSize());
|
|
256
|
-
|
|
257
|
-
const leftColumns = $derived(tableContext.table.getLeftVisibleLeafColumns());
|
|
258
|
-
const centreColumns = $derived(tableContext.table.getCenterVisibleLeafColumns());
|
|
259
|
-
const rightColumns = $derived(tableContext.table.getRightVisibleLeafColumns());
|
|
260
|
-
|
|
261
|
-
const appropriateSide = $derived.by(() => {
|
|
262
|
-
if (leftColumns.length > 0) {
|
|
263
|
-
return 'left';
|
|
264
|
-
} else if (rightColumns.length != tableContext.columnDefs.length) {
|
|
265
|
-
return 'centre';
|
|
266
|
-
} else {
|
|
267
|
-
return 'right';
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
type SvelteTableElement = {
|
|
272
|
-
rowHeights: RefWrapper<Array<number>>;
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
let leftTable: SvelteTableElement | undefined = $state();
|
|
276
|
-
let centreTable: SvelteTableElement | undefined = $state();
|
|
277
|
-
let rightTable: SvelteTableElement | undefined = $state();
|
|
278
|
-
|
|
279
|
-
const totalRowSizes: Array<HeightData<T>> = $derived.by(() => {
|
|
280
|
-
if (!leftTable || !centreTable || !rightTable) {
|
|
281
|
-
return [];
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// console.debug(`got refs for all tables`);
|
|
285
|
-
const centre = centreTable.rowHeights.value;
|
|
286
|
-
const right = rightTable.rowHeights.value;
|
|
287
|
-
|
|
288
|
-
return leftTable.rowHeights.value.map((_leftHeight, index) => {
|
|
289
|
-
const leftHeight = _leftHeight || 0;
|
|
290
|
-
const centreHeight = centre[index] || 0;
|
|
291
|
-
const rightHeight = right[index] || 0;
|
|
292
|
-
|
|
293
|
-
const maxHeight = Math.max(leftHeight, centreHeight, rightHeight);
|
|
294
|
-
const applyTo: HeightData<T>['applyTo'] = [];
|
|
295
|
-
|
|
296
|
-
if (leftHeight < maxHeight) {
|
|
297
|
-
// console.debug(`left (${leftHeight}) was lower than max (${maxHeight})`);
|
|
298
|
-
applyTo.push('left');
|
|
299
|
-
}
|
|
300
|
-
if (centreHeight < maxHeight) {
|
|
301
|
-
// console.debug(`centre (${centreHeight}) was lower than max (${maxHeight})`);
|
|
302
|
-
applyTo.push('centre');
|
|
303
|
-
}
|
|
304
|
-
if (rightHeight < maxHeight) {
|
|
305
|
-
// console.debug(`right (${rightHeight}) was lower than max (${maxHeight})`);
|
|
306
|
-
applyTo.push('right');
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return {
|
|
310
|
-
index,
|
|
311
|
-
applyTo,
|
|
312
|
-
maxHeight,
|
|
313
|
-
};
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
|
-
</script>
|
|
317
|
-
|
|
318
|
-
<svelte:window
|
|
319
|
-
onmouseup={(e: MouseEvent) => {
|
|
320
|
-
if (
|
|
321
|
-
// if it's not a click on an item in the context menu
|
|
322
|
-
!(e.target as HTMLElement | undefined)?.classList.contains('context-menu-item') &&
|
|
323
|
-
// if it's outside the table or inside the empty space of the table
|
|
324
|
-
(e.target === unfocusRef ||
|
|
325
|
-
((e.target as HTMLElement | undefined)?.closest('.table-wrapper') == null &&
|
|
326
|
-
mousedDownEmptySpace))
|
|
327
|
-
) {
|
|
328
|
-
tableContext.unfocus();
|
|
329
|
-
}
|
|
330
|
-
mousedDownEmptySpace = false;
|
|
331
|
-
|
|
332
|
-
if (tableContext.isMousingDown) {
|
|
333
|
-
tableContext.isMousingDown = false;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
removeOverrideResizeHandler();
|
|
337
|
-
}}
|
|
338
|
-
onclick={(e: MouseEvent) => {
|
|
339
|
-
handleClickOutside(e);
|
|
340
|
-
}}
|
|
341
|
-
onmousedown={(e: MouseEvent) => {
|
|
342
|
-
mousedDownEmptySpace =
|
|
343
|
-
e.target === unfocusRef || (e.target as HTMLElement).closest('.table-wrapper') == null;
|
|
344
|
-
}}
|
|
345
|
-
/>
|
|
346
|
-
|
|
347
|
-
<div
|
|
348
|
-
class="grid"
|
|
349
|
-
class:nested
|
|
350
|
-
>
|
|
351
|
-
{#if tableContext.dataRepo.isLoading}
|
|
352
|
-
<LoadingOverlay
|
|
353
|
-
absolute
|
|
354
|
-
borderRadius="4px"
|
|
355
|
-
message={tableContext.dataRepo.loadingMessage}
|
|
356
|
-
/>
|
|
357
|
-
{/if}
|
|
358
|
-
|
|
359
|
-
<div
|
|
360
|
-
class="horizontal-bar"
|
|
361
|
-
class:border={tableContext.toolbarPosition === ToolbarPosition.Top}
|
|
362
|
-
>
|
|
363
|
-
{#if tableContext.toolbarPosition === ToolbarPosition.Top}
|
|
364
|
-
<TableHorizontalBar />
|
|
365
|
-
{/if}
|
|
366
|
-
</div>
|
|
367
|
-
|
|
368
|
-
<div
|
|
369
|
-
class="sidebar-wrapper sidebar-wrapper-left"
|
|
370
|
-
class:nested
|
|
371
|
-
style="--nested-height: {nestedHeight}px;"
|
|
372
|
-
>
|
|
373
|
-
{#if tableContext.toolbarPosition === ToolbarPosition.Left}
|
|
374
|
-
<div class="sidebar toolbar-left">
|
|
375
|
-
<TableSidebar />
|
|
376
|
-
</div>
|
|
377
|
-
{/if}
|
|
378
|
-
</div>
|
|
379
|
-
<div
|
|
380
|
-
class="sidebar-wrapper sidebar-wrapper-right"
|
|
381
|
-
class:nested
|
|
382
|
-
style="--nested-height: {nestedHeight}px;"
|
|
383
|
-
>
|
|
384
|
-
{#if tableContext.toolbarPosition === ToolbarPosition.Right}
|
|
385
|
-
<div class="sidebar toolbar-right">
|
|
386
|
-
<TableSidebar />
|
|
387
|
-
</div>
|
|
388
|
-
{/if}
|
|
389
|
-
</div>
|
|
390
|
-
|
|
391
|
-
<div class="footer">
|
|
392
|
-
{#if tableContext.displayFooter}
|
|
393
|
-
<TableFooter />
|
|
394
|
-
{/if}
|
|
395
|
-
</div>
|
|
396
|
-
|
|
397
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
398
|
-
<div
|
|
399
|
-
bind:this={tableRef}
|
|
400
|
-
class="datatable"
|
|
401
|
-
class:nested
|
|
402
|
-
class:compact={tableContext.isCompact}
|
|
403
|
-
class:quick-filtering={tableContext.showQuickFiltering}
|
|
404
|
-
onkeydown={tableContext.handleTdKeydown}
|
|
405
|
-
>
|
|
406
|
-
<div
|
|
407
|
-
class="flex_table"
|
|
408
|
-
bind:this={ref}
|
|
409
|
-
class:nested
|
|
410
|
-
>
|
|
411
|
-
<div
|
|
412
|
-
bind:this={unfocusRef}
|
|
413
|
-
class="table-wrapper"
|
|
414
|
-
oncontextmenu={openContextMenu}
|
|
415
|
-
>
|
|
416
|
-
<!-- {#if leftTotalSize > 0} -->
|
|
417
|
-
<table
|
|
418
|
-
class="datatable__table left"
|
|
419
|
-
style="min-width: {leftTotalSize}px"
|
|
420
|
-
>
|
|
421
|
-
<TableHead
|
|
422
|
-
showHighlight={leftTotalSize > 0}
|
|
423
|
-
side="left"
|
|
424
|
-
/>
|
|
425
|
-
<TableBody
|
|
426
|
-
includeHighlight={appropriateSide == 'left'}
|
|
427
|
-
columns={leftColumns}
|
|
428
|
-
side="left"
|
|
429
|
-
heights={totalRowSizes}
|
|
430
|
-
bind:this={leftTable}
|
|
431
|
-
/>
|
|
432
|
-
</table>
|
|
433
|
-
<!-- {/if} -->
|
|
434
|
-
|
|
435
|
-
<!-- {#if centreTotalSize > 0} -->
|
|
436
|
-
|
|
437
|
-
<table
|
|
438
|
-
class="datatable__table centre"
|
|
439
|
-
style="min-width: {centreTotalSize}px"
|
|
440
|
-
>
|
|
441
|
-
<TableHead
|
|
442
|
-
showHighlight={leftTotalSize == 0}
|
|
443
|
-
side="centre"
|
|
444
|
-
/>
|
|
445
|
-
<TableBody
|
|
446
|
-
includeHighlight={appropriateSide == 'centre'}
|
|
447
|
-
columns={centreColumns}
|
|
448
|
-
side="centre"
|
|
449
|
-
heights={totalRowSizes}
|
|
450
|
-
bind:this={centreTable}
|
|
451
|
-
/>
|
|
452
|
-
</table>
|
|
453
|
-
<!-- {/if} -->
|
|
454
|
-
|
|
455
|
-
<!-- {#if rightTotalSize > 0} -->
|
|
456
|
-
<table
|
|
457
|
-
class="datatable__table right"
|
|
458
|
-
style="min-width: {rightTotalSize}px"
|
|
459
|
-
>
|
|
460
|
-
<TableHead
|
|
461
|
-
showHighlight={false}
|
|
462
|
-
side="right"
|
|
463
|
-
/>
|
|
464
|
-
<TableBody
|
|
465
|
-
includeHighlight={appropriateSide == 'right'}
|
|
466
|
-
columns={rightColumns}
|
|
467
|
-
side="right"
|
|
468
|
-
heights={totalRowSizes}
|
|
469
|
-
bind:this={rightTable}
|
|
470
|
-
/>
|
|
471
|
-
</table>
|
|
472
|
-
<!-- {/if} -->
|
|
473
|
-
</div>
|
|
474
|
-
|
|
475
|
-
<!-- TODO add filter callbacks -->
|
|
476
|
-
</div>
|
|
477
|
-
|
|
478
|
-
{#if nested}
|
|
479
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
480
|
-
<div
|
|
481
|
-
class:isResizing
|
|
482
|
-
class="resizer"
|
|
483
|
-
onmousedown={(e) => {
|
|
484
|
-
e.preventDefault();
|
|
485
|
-
addOverrideResizeHandler();
|
|
486
|
-
}}
|
|
487
|
-
></div>
|
|
488
|
-
{/if}
|
|
489
|
-
</div>
|
|
490
|
-
</div>
|
|
491
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<script
|
|
4
|
+
lang="ts"
|
|
5
|
+
module
|
|
6
|
+
>
|
|
7
|
+
import {
|
|
8
|
+
ContextMenuContext,
|
|
9
|
+
type IContextMenuOption,
|
|
10
|
+
} from '../../Contexts/ContextMenuContext.svelte';
|
|
11
|
+
import { devCatch, refWrapper } from '../../Helpers/Helpers.svelte';
|
|
12
|
+
import type { RefWrapper } from '../../Types/Internal/RefWrapper.js';
|
|
13
|
+
import { getContext, onMount, setContext, tick, untrack } from 'svelte';
|
|
14
|
+
import LoadingOverlay from '../LoadingOverlay.svelte';
|
|
15
|
+
import type { HeightData } from './Body/HeightData.js';
|
|
16
|
+
import { shownPopup } from './Body/Rows/Columns/ActionsCell.svelte';
|
|
17
|
+
import TableBody from './Body/TableBody.svelte';
|
|
18
|
+
import TableHead from './Headers/TableHead.svelte';
|
|
19
|
+
import TableFooter from './Misc/TableFooter.svelte';
|
|
20
|
+
import TableHorizontalBar from './Misc/TableHorizontalBar.svelte';
|
|
21
|
+
import TableSidebar from './Misc/TableSidebar.svelte';
|
|
22
|
+
import { TableContext } from './Types/Context/TableContext.svelte';
|
|
23
|
+
import type { Primitive } from './Types/Context/TableInitOptions.js';
|
|
24
|
+
import { PaginationType } from './Types/Pagination/PaginationType.js';
|
|
25
|
+
import { ToolbarPosition } from './Types/Toolbar/ToolbarPosition.js';
|
|
26
|
+
|
|
27
|
+
declare global {
|
|
28
|
+
interface HTMLElementEventMap {
|
|
29
|
+
edit: CustomEvent<{
|
|
30
|
+
selectAll: boolean;
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface TableProps<T extends object, IdType extends Primitive> {
|
|
36
|
+
readonly tableContext: TableContext<T, IdType>;
|
|
37
|
+
nested?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const quickFilterContextIdentifier: symbol = Symbol();
|
|
41
|
+
|
|
42
|
+
const openedQuickFilterSelect = refWrapper(null);
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<script
|
|
46
|
+
lang="ts"
|
|
47
|
+
generics="T extends object,IdType extends Primitive"
|
|
48
|
+
>
|
|
49
|
+
const { nested = false, tableContext }: TableProps<T, IdType> = $props();
|
|
50
|
+
|
|
51
|
+
// NOTE: known limitation. This is passed as a wrapper, and they should never require reassignment. It is deeply reactive
|
|
52
|
+
// svelte-ignore state_referenced_locally
|
|
53
|
+
setContext(TableContext.identifier, tableContext);
|
|
54
|
+
|
|
55
|
+
const { openContextMenu: _openContextMenu } = getContext<ContextMenuContext>(
|
|
56
|
+
ContextMenuContext.identifier
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
let ref: HTMLDivElement | undefined = $state();
|
|
60
|
+
let unfocusRef: HTMLDivElement | undefined = $state();
|
|
61
|
+
|
|
62
|
+
setContext(quickFilterContextIdentifier, openedQuickFilterSelect);
|
|
63
|
+
|
|
64
|
+
$effect(() => {
|
|
65
|
+
void tableContext.focusStart;
|
|
66
|
+
void ref;
|
|
67
|
+
untrack(() => {
|
|
68
|
+
if (tableContext.focusStart && ref) {
|
|
69
|
+
const { row, column: index } = tableContext.focusStart;
|
|
70
|
+
let element = ref.querySelector(
|
|
71
|
+
`#${tableContext.tableName}-cell-${row}-${tableContext.columnDefs[index].id}`
|
|
72
|
+
) as HTMLElement | undefined;
|
|
73
|
+
|
|
74
|
+
if (element?.tabIndex == -1) {
|
|
75
|
+
const td = element;
|
|
76
|
+
element = td.querySelector('button') as HTMLElement | undefined;
|
|
77
|
+
if (!element) {
|
|
78
|
+
element = td.querySelector('input') as HTMLElement | undefined;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
element?.focus({ preventScroll: true });
|
|
83
|
+
element?.scrollIntoView({
|
|
84
|
+
behavior: 'instant',
|
|
85
|
+
block: 'nearest',
|
|
86
|
+
inline: 'nearest',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
$effect(() => {
|
|
93
|
+
if (tableContext.focusEnd && ref) {
|
|
94
|
+
const { row, column: index } = tableContext.focusEnd;
|
|
95
|
+
const cell = ref.querySelector(
|
|
96
|
+
`#${tableContext.tableName}-cell-${row}-${tableContext.columnDefs[index].id}`
|
|
97
|
+
) as HTMLElement | undefined;
|
|
98
|
+
|
|
99
|
+
cell?.scrollIntoView({
|
|
100
|
+
behavior: 'instant',
|
|
101
|
+
block: 'nearest',
|
|
102
|
+
inline: 'nearest',
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
function openContextMenu(e: MouseEvent) {
|
|
108
|
+
e.stopPropagation();
|
|
109
|
+
|
|
110
|
+
if (
|
|
111
|
+
(e.target as HTMLElement).tagName === 'INPUT' ||
|
|
112
|
+
(e.target as HTMLElement).closest('.select-wrapper') != null
|
|
113
|
+
) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const clickedElement = document.activeElement?.id.split('-cell-')[1]?.split('-');
|
|
118
|
+
|
|
119
|
+
if (clickedElement) {
|
|
120
|
+
const [rowString, columnId] = clickedElement;
|
|
121
|
+
const row = parseInt(rowString);
|
|
122
|
+
|
|
123
|
+
if (
|
|
124
|
+
!tableContext.focusedColumnIds.has(columnId) ||
|
|
125
|
+
!tableContext.focusedRowIndices.has(row)
|
|
126
|
+
) {
|
|
127
|
+
const columnIndex = tableContext.columnDefs.find((it) => it.id === columnId)?.index;
|
|
128
|
+
|
|
129
|
+
if (columnIndex) {
|
|
130
|
+
tableContext.moveFocus({
|
|
131
|
+
column: columnIndex,
|
|
132
|
+
row,
|
|
133
|
+
id: columnId,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// this may not exist in http contexts
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
141
|
+
if (tableContext.allowCopy && window.Clipboard) {
|
|
142
|
+
e.preventDefault();
|
|
143
|
+
|
|
144
|
+
const options: Array<IContextMenuOption> = [
|
|
145
|
+
{
|
|
146
|
+
callback: () => {
|
|
147
|
+
tableContext.copyDataToClipboard().catch(devCatch);
|
|
148
|
+
},
|
|
149
|
+
text: 'Copy Selection',
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
if (tableContext.hasHighlightedItems) {
|
|
154
|
+
options.push({
|
|
155
|
+
callback: () => {
|
|
156
|
+
tableContext.copyHighlightedRowsToClipboard().catch(devCatch);
|
|
157
|
+
},
|
|
158
|
+
text: 'Copy Highlighted Rows',
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
_openContextMenu(e, options).catch(devCatch);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function handleClickOutside(e: MouseEvent) {
|
|
167
|
+
const target = e.target as HTMLElement;
|
|
168
|
+
if (target.isConnected) {
|
|
169
|
+
if (target.closest('div.floating') == null && target.closest('div.stick-right') == null) {
|
|
170
|
+
openedQuickFilterSelect.value = null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (target.closest('div.slot-wrapper') == null) {
|
|
174
|
+
// svelte type gen/eslint miscommunication
|
|
175
|
+
(shownPopup as RefWrapper<symbol | undefined>).value = undefined;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// nested table resizing
|
|
181
|
+
let isResizing = $state(false);
|
|
182
|
+
let remPxRatio = $state(0);
|
|
183
|
+
const minNestedHeight = $derived(20 * remPxRatio);
|
|
184
|
+
|
|
185
|
+
// HACK please figure this one out
|
|
186
|
+
let nestedHeight = $derived(minNestedHeight);
|
|
187
|
+
|
|
188
|
+
let tableRef: HTMLDivElement | undefined = undefined;
|
|
189
|
+
let mousedDownEmptySpace = $state(false);
|
|
190
|
+
|
|
191
|
+
onMount(() => {
|
|
192
|
+
remPxRatio = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
function addOverrideResizeHandler() {
|
|
196
|
+
isResizing = true;
|
|
197
|
+
window.addEventListener('mousemove', onResize);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function onResize(e: MouseEvent) {
|
|
201
|
+
const sliderHeight = tableRef ? e.clientY - tableRef.getBoundingClientRect().top : 0;
|
|
202
|
+
nestedHeight = Math.max(sliderHeight, minNestedHeight);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function removeOverrideResizeHandler() {
|
|
206
|
+
isResizing = false;
|
|
207
|
+
window.removeEventListener('mousemove', onResize);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const usesLoading = $derived(
|
|
211
|
+
tableContext.paginationRepo &&
|
|
212
|
+
tableContext.paginationRepo.paginationType === PaginationType.Remote
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
const shouldUnfocusRemote = $derived(
|
|
216
|
+
usesLoading &&
|
|
217
|
+
tableContext.paginationRepo?.isLoading === false &&
|
|
218
|
+
tableContext.paginationRepo.paginationState.pageIndex !==
|
|
219
|
+
tableContext.paginationRepo.previouslyViewedPage
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
const shouldUnfocusLocal = $derived(
|
|
223
|
+
!usesLoading && tableContext.paginationRepo?.paginationState.pageIndex
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
$effect(() => {
|
|
227
|
+
if ((shouldUnfocusRemote || shouldUnfocusLocal) && unfocusRef) {
|
|
228
|
+
untrack(() => {
|
|
229
|
+
tableContext.unfocus();
|
|
230
|
+
});
|
|
231
|
+
unfocusRef.scrollTop = 0;
|
|
232
|
+
} else if (usesLoading && tableContext.paginationRepo?.isLoading === false) {
|
|
233
|
+
// refocus same element after a reload
|
|
234
|
+
// this does not break mutifocus
|
|
235
|
+
untrack(() => {
|
|
236
|
+
const fs = tableContext.focusStart;
|
|
237
|
+
if (!fs) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const idToFocusTo = `#${tableContext.tableName}-cell-${fs.row}-${fs.id}`;
|
|
241
|
+
|
|
242
|
+
tick()
|
|
243
|
+
.then(() => {
|
|
244
|
+
if (idToFocusTo) {
|
|
245
|
+
(document.querySelector(idToFocusTo) as HTMLTableCellElement | undefined)?.focus();
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
.catch(devCatch);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const leftTotalSize = $derived(tableContext.table.getLeftTotalSize());
|
|
254
|
+
const centreTotalSize = $derived(tableContext.table.getCenterTotalSize());
|
|
255
|
+
const rightTotalSize = $derived(tableContext.table.getRightTotalSize());
|
|
256
|
+
|
|
257
|
+
const leftColumns = $derived(tableContext.table.getLeftVisibleLeafColumns());
|
|
258
|
+
const centreColumns = $derived(tableContext.table.getCenterVisibleLeafColumns());
|
|
259
|
+
const rightColumns = $derived(tableContext.table.getRightVisibleLeafColumns());
|
|
260
|
+
|
|
261
|
+
const appropriateSide = $derived.by(() => {
|
|
262
|
+
if (leftColumns.length > 0) {
|
|
263
|
+
return 'left';
|
|
264
|
+
} else if (rightColumns.length != tableContext.columnDefs.length) {
|
|
265
|
+
return 'centre';
|
|
266
|
+
} else {
|
|
267
|
+
return 'right';
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
type SvelteTableElement = {
|
|
272
|
+
rowHeights: RefWrapper<Array<number>>;
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
let leftTable: SvelteTableElement | undefined = $state();
|
|
276
|
+
let centreTable: SvelteTableElement | undefined = $state();
|
|
277
|
+
let rightTable: SvelteTableElement | undefined = $state();
|
|
278
|
+
|
|
279
|
+
const totalRowSizes: Array<HeightData<T>> = $derived.by(() => {
|
|
280
|
+
if (!leftTable || !centreTable || !rightTable) {
|
|
281
|
+
return [];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// console.debug(`got refs for all tables`);
|
|
285
|
+
const centre = centreTable.rowHeights.value;
|
|
286
|
+
const right = rightTable.rowHeights.value;
|
|
287
|
+
|
|
288
|
+
return leftTable.rowHeights.value.map((_leftHeight, index) => {
|
|
289
|
+
const leftHeight = _leftHeight || 0;
|
|
290
|
+
const centreHeight = centre[index] || 0;
|
|
291
|
+
const rightHeight = right[index] || 0;
|
|
292
|
+
|
|
293
|
+
const maxHeight = Math.max(leftHeight, centreHeight, rightHeight);
|
|
294
|
+
const applyTo: HeightData<T>['applyTo'] = [];
|
|
295
|
+
|
|
296
|
+
if (leftHeight < maxHeight) {
|
|
297
|
+
// console.debug(`left (${leftHeight}) was lower than max (${maxHeight})`);
|
|
298
|
+
applyTo.push('left');
|
|
299
|
+
}
|
|
300
|
+
if (centreHeight < maxHeight) {
|
|
301
|
+
// console.debug(`centre (${centreHeight}) was lower than max (${maxHeight})`);
|
|
302
|
+
applyTo.push('centre');
|
|
303
|
+
}
|
|
304
|
+
if (rightHeight < maxHeight) {
|
|
305
|
+
// console.debug(`right (${rightHeight}) was lower than max (${maxHeight})`);
|
|
306
|
+
applyTo.push('right');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return {
|
|
310
|
+
index,
|
|
311
|
+
applyTo,
|
|
312
|
+
maxHeight,
|
|
313
|
+
};
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
</script>
|
|
317
|
+
|
|
318
|
+
<svelte:window
|
|
319
|
+
onmouseup={(e: MouseEvent) => {
|
|
320
|
+
if (
|
|
321
|
+
// if it's not a click on an item in the context menu
|
|
322
|
+
!(e.target as HTMLElement | undefined)?.classList.contains('context-menu-item') &&
|
|
323
|
+
// if it's outside the table or inside the empty space of the table
|
|
324
|
+
(e.target === unfocusRef ||
|
|
325
|
+
((e.target as HTMLElement | undefined)?.closest('.table-wrapper') == null &&
|
|
326
|
+
mousedDownEmptySpace))
|
|
327
|
+
) {
|
|
328
|
+
tableContext.unfocus();
|
|
329
|
+
}
|
|
330
|
+
mousedDownEmptySpace = false;
|
|
331
|
+
|
|
332
|
+
if (tableContext.isMousingDown) {
|
|
333
|
+
tableContext.isMousingDown = false;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
removeOverrideResizeHandler();
|
|
337
|
+
}}
|
|
338
|
+
onclick={(e: MouseEvent) => {
|
|
339
|
+
handleClickOutside(e);
|
|
340
|
+
}}
|
|
341
|
+
onmousedown={(e: MouseEvent) => {
|
|
342
|
+
mousedDownEmptySpace =
|
|
343
|
+
e.target === unfocusRef || (e.target as HTMLElement).closest('.table-wrapper') == null;
|
|
344
|
+
}}
|
|
345
|
+
/>
|
|
346
|
+
|
|
347
|
+
<div
|
|
348
|
+
class="grid"
|
|
349
|
+
class:nested
|
|
350
|
+
>
|
|
351
|
+
{#if tableContext.dataRepo.isLoading}
|
|
352
|
+
<LoadingOverlay
|
|
353
|
+
absolute
|
|
354
|
+
borderRadius="4px"
|
|
355
|
+
message={tableContext.dataRepo.loadingMessage}
|
|
356
|
+
/>
|
|
357
|
+
{/if}
|
|
358
|
+
|
|
359
|
+
<div
|
|
360
|
+
class="horizontal-bar"
|
|
361
|
+
class:border={tableContext.toolbarPosition === ToolbarPosition.Top}
|
|
362
|
+
>
|
|
363
|
+
{#if tableContext.toolbarPosition === ToolbarPosition.Top}
|
|
364
|
+
<TableHorizontalBar />
|
|
365
|
+
{/if}
|
|
366
|
+
</div>
|
|
367
|
+
|
|
368
|
+
<div
|
|
369
|
+
class="sidebar-wrapper sidebar-wrapper-left"
|
|
370
|
+
class:nested
|
|
371
|
+
style="--nested-height: {nestedHeight}px;"
|
|
372
|
+
>
|
|
373
|
+
{#if tableContext.toolbarPosition === ToolbarPosition.Left}
|
|
374
|
+
<div class="sidebar toolbar-left">
|
|
375
|
+
<TableSidebar />
|
|
376
|
+
</div>
|
|
377
|
+
{/if}
|
|
378
|
+
</div>
|
|
379
|
+
<div
|
|
380
|
+
class="sidebar-wrapper sidebar-wrapper-right"
|
|
381
|
+
class:nested
|
|
382
|
+
style="--nested-height: {nestedHeight}px;"
|
|
383
|
+
>
|
|
384
|
+
{#if tableContext.toolbarPosition === ToolbarPosition.Right}
|
|
385
|
+
<div class="sidebar toolbar-right">
|
|
386
|
+
<TableSidebar />
|
|
387
|
+
</div>
|
|
388
|
+
{/if}
|
|
389
|
+
</div>
|
|
390
|
+
|
|
391
|
+
<div class="footer">
|
|
392
|
+
{#if tableContext.displayFooter}
|
|
393
|
+
<TableFooter />
|
|
394
|
+
{/if}
|
|
395
|
+
</div>
|
|
396
|
+
|
|
397
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
398
|
+
<div
|
|
399
|
+
bind:this={tableRef}
|
|
400
|
+
class="datatable"
|
|
401
|
+
class:nested
|
|
402
|
+
class:compact={tableContext.isCompact}
|
|
403
|
+
class:quick-filtering={tableContext.showQuickFiltering}
|
|
404
|
+
onkeydown={tableContext.handleTdKeydown}
|
|
405
|
+
>
|
|
406
|
+
<div
|
|
407
|
+
class="flex_table"
|
|
408
|
+
bind:this={ref}
|
|
409
|
+
class:nested
|
|
410
|
+
>
|
|
411
|
+
<div
|
|
412
|
+
bind:this={unfocusRef}
|
|
413
|
+
class="table-wrapper"
|
|
414
|
+
oncontextmenu={openContextMenu}
|
|
415
|
+
>
|
|
416
|
+
<!-- {#if leftTotalSize > 0} -->
|
|
417
|
+
<table
|
|
418
|
+
class="datatable__table left"
|
|
419
|
+
style="min-width: {leftTotalSize}px"
|
|
420
|
+
>
|
|
421
|
+
<TableHead
|
|
422
|
+
showHighlight={leftTotalSize > 0}
|
|
423
|
+
side="left"
|
|
424
|
+
/>
|
|
425
|
+
<TableBody
|
|
426
|
+
includeHighlight={appropriateSide == 'left'}
|
|
427
|
+
columns={leftColumns}
|
|
428
|
+
side="left"
|
|
429
|
+
heights={totalRowSizes}
|
|
430
|
+
bind:this={leftTable}
|
|
431
|
+
/>
|
|
432
|
+
</table>
|
|
433
|
+
<!-- {/if} -->
|
|
434
|
+
|
|
435
|
+
<!-- {#if centreTotalSize > 0} -->
|
|
436
|
+
|
|
437
|
+
<table
|
|
438
|
+
class="datatable__table centre"
|
|
439
|
+
style="min-width: {centreTotalSize}px"
|
|
440
|
+
>
|
|
441
|
+
<TableHead
|
|
442
|
+
showHighlight={leftTotalSize == 0}
|
|
443
|
+
side="centre"
|
|
444
|
+
/>
|
|
445
|
+
<TableBody
|
|
446
|
+
includeHighlight={appropriateSide == 'centre'}
|
|
447
|
+
columns={centreColumns}
|
|
448
|
+
side="centre"
|
|
449
|
+
heights={totalRowSizes}
|
|
450
|
+
bind:this={centreTable}
|
|
451
|
+
/>
|
|
452
|
+
</table>
|
|
453
|
+
<!-- {/if} -->
|
|
454
|
+
|
|
455
|
+
<!-- {#if rightTotalSize > 0} -->
|
|
456
|
+
<table
|
|
457
|
+
class="datatable__table right"
|
|
458
|
+
style="min-width: {rightTotalSize}px"
|
|
459
|
+
>
|
|
460
|
+
<TableHead
|
|
461
|
+
showHighlight={false}
|
|
462
|
+
side="right"
|
|
463
|
+
/>
|
|
464
|
+
<TableBody
|
|
465
|
+
includeHighlight={appropriateSide == 'right'}
|
|
466
|
+
columns={rightColumns}
|
|
467
|
+
side="right"
|
|
468
|
+
heights={totalRowSizes}
|
|
469
|
+
bind:this={rightTable}
|
|
470
|
+
/>
|
|
471
|
+
</table>
|
|
472
|
+
<!-- {/if} -->
|
|
473
|
+
</div>
|
|
474
|
+
|
|
475
|
+
<!-- TODO add filter callbacks -->
|
|
476
|
+
</div>
|
|
477
|
+
|
|
478
|
+
{#if nested}
|
|
479
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
480
|
+
<div
|
|
481
|
+
class:isResizing
|
|
482
|
+
class="resizer"
|
|
483
|
+
onmousedown={(e) => {
|
|
484
|
+
e.preventDefault();
|
|
485
|
+
addOverrideResizeHandler();
|
|
486
|
+
}}
|
|
487
|
+
></div>
|
|
488
|
+
{/if}
|
|
489
|
+
</div>
|
|
490
|
+
</div>
|
|
491
|
+
|
|
492
492
|
<style>div.grid {
|
|
493
493
|
border-radius: 4px;
|
|
494
494
|
display: grid;
|
|
@@ -657,4 +657,4 @@ div.sidebar-wrapper .sidebar.toolbar-right {
|
|
|
657
657
|
position: sticky;
|
|
658
658
|
z-index: 2;
|
|
659
659
|
right: 0;
|
|
660
|
-
}</style>
|
|
660
|
+
}</style>
|