@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.
Files changed (130) hide show
  1. package/README.md +58 -58
  2. package/dist/Components/AccordionGroup.svelte +44 -63
  3. package/dist/Components/AccordionGroup.svelte.d.ts +2 -25
  4. package/dist/Components/AccordionGroupButton.svelte +106 -114
  5. package/dist/Components/AccordionGroupButton.svelte.d.ts +2 -2
  6. package/dist/Components/AccordionGroupButtonProps.d.ts +21 -0
  7. package/dist/Components/AccordionGroupButtonProps.js +1 -0
  8. package/dist/Components/Action.svelte +138 -138
  9. package/dist/Components/AlertModal.svelte +125 -125
  10. package/dist/Components/Base/ContextWrapper.svelte +50 -50
  11. package/dist/Components/Base/Pagination.svelte +190 -190
  12. package/dist/Components/Base/Snippets.svelte +29 -29
  13. package/dist/Components/BigRadioSet.svelte +29 -29
  14. package/dist/Components/Bubble.svelte +77 -77
  15. package/dist/Components/Button.svelte +197 -197
  16. package/dist/Components/Checkbox.svelte +68 -68
  17. package/dist/Components/CollapsibleCard.svelte +70 -70
  18. package/dist/Components/Contexts/ContextMenu.svelte +157 -157
  19. package/dist/Components/Contexts/ContextMenuDivider.svelte +11 -11
  20. package/dist/Components/Contexts/ContextMenuOption.svelte +52 -52
  21. package/dist/Components/Contexts/Toast.svelte +61 -61
  22. package/dist/Components/Contexts/ToastContainer.svelte +46 -46
  23. package/dist/Components/Contexts/Tooltip.svelte +26 -26
  24. package/dist/Components/DataMatrixIcon.svelte +41 -41
  25. package/dist/Components/DateInput.svelte +109 -109
  26. package/dist/Components/DatePicker.svelte +312 -312
  27. package/dist/Components/DesktopModal.svelte +106 -106
  28. package/dist/Components/Dial.svelte +151 -151
  29. package/dist/Components/DimensionInput.svelte +184 -184
  30. package/dist/Components/DragMenu/DragMenuHolder.svelte +106 -106
  31. package/dist/Components/DragMenu/DraggableCard.svelte +41 -41
  32. package/dist/Components/FileCard.svelte +20 -20
  33. package/dist/Components/FileUpload.svelte +196 -196
  34. package/dist/Components/GridInput.svelte +190 -190
  35. package/dist/Components/GridInputSet.svelte +22 -22
  36. package/dist/Components/HorizontalTabGroup.svelte +78 -78
  37. package/dist/Components/HorizontalTabGroupButton.svelte +96 -96
  38. package/dist/Components/Icon.svelte +97 -97
  39. package/dist/Components/Icons.js +357 -357
  40. package/dist/Components/LoadingAnimation.svelte +32 -32
  41. package/dist/Components/LoadingModal.svelte +47 -47
  42. package/dist/Components/LoadingOverlay.svelte +27 -27
  43. package/dist/Components/Modal.svelte +251 -251
  44. package/dist/Components/MultiSelect.svelte +197 -197
  45. package/dist/Components/Nav/Nav.svelte +97 -97
  46. package/dist/Components/Nav/NavServiceMenuList.svelte +34 -34
  47. package/dist/Components/Nav/NavTab.svelte +91 -91
  48. package/dist/Components/Nav/ServiceMenuItem.svelte +91 -91
  49. package/dist/Components/Nav/ServicesNav.svelte +53 -53
  50. package/dist/Components/NumberInput.svelte +144 -144
  51. package/dist/Components/PageHeading.svelte +36 -36
  52. package/dist/Components/PasswordInput.svelte +73 -73
  53. package/dist/Components/Portal.svelte +25 -25
  54. package/dist/Components/ProgressBubble.svelte +80 -80
  55. package/dist/Components/QuerySelect.svelte +411 -411
  56. package/dist/Components/SingleSelect.svelte +261 -261
  57. package/dist/Components/StepButton.svelte +120 -120
  58. package/dist/Components/StepForm.svelte +108 -108
  59. package/dist/Components/Switch.svelte +36 -36
  60. package/dist/Components/Table/Body/QuickSearchCell.svelte +632 -632
  61. package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +30 -30
  62. package/dist/Components/Table/Body/Rows/ColumnList.svelte +56 -56
  63. package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +179 -179
  64. package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +49 -49
  65. package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +180 -180
  66. package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +102 -102
  67. package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +119 -119
  68. package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +114 -114
  69. package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +96 -96
  70. package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +72 -72
  71. package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +131 -131
  72. package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +144 -144
  73. package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +238 -238
  74. package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +358 -358
  75. package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +338 -338
  76. package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +183 -183
  77. package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +309 -309
  78. package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +369 -369
  79. package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +170 -170
  80. package/dist/Components/Table/Body/Rows/TableRow.svelte +259 -259
  81. package/dist/Components/Table/Body/TableBody.svelte +67 -67
  82. package/dist/Components/Table/Headers/HighlightAllHeader.svelte +39 -39
  83. package/dist/Components/Table/Headers/SelectAllHeader.svelte +28 -28
  84. package/dist/Components/Table/Headers/TableHead.svelte +260 -260
  85. package/dist/Components/Table/Misc/ColumnPanel.svelte +78 -78
  86. package/dist/Components/Table/Misc/ColumnPanelModal.svelte +99 -99
  87. package/dist/Components/Table/Misc/FilterInput.svelte +556 -556
  88. package/dist/Components/Table/Misc/FilterPanel.svelte +46 -46
  89. package/dist/Components/Table/Misc/FilterPanelModal.svelte +67 -67
  90. package/dist/Components/Table/Misc/SidePanel.svelte +32 -32
  91. package/dist/Components/Table/Misc/TableFooter.svelte +304 -304
  92. package/dist/Components/Table/Misc/TableHorizontalBar.svelte +156 -156
  93. package/dist/Components/Table/Misc/TableSidebar.svelte +176 -176
  94. package/dist/Components/Table/Misc/ToolboxPanel.svelte +77 -77
  95. package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +91 -91
  96. package/dist/Components/Table/NestedTable.svelte +84 -84
  97. package/dist/Components/Table/Table.svelte +492 -492
  98. package/dist/Components/Test/TestContextConsumer.svelte +13 -13
  99. package/dist/Components/TextArea.svelte +108 -108
  100. package/dist/Components/TextInput.svelte +147 -147
  101. package/dist/Components/ThreeStateRadio.svelte +124 -124
  102. package/dist/Components/Touch/BoolCard.svelte +52 -52
  103. package/dist/Components/Touch/DateModal.svelte +217 -217
  104. package/dist/Components/Touch/EditCard.svelte +52 -52
  105. package/dist/Components/Touch/InfoCard.svelte +24 -24
  106. package/dist/Components/Touch/InfoTextCard.svelte +21 -21
  107. package/dist/Components/Touch/ModalExplanation.svelte +20 -20
  108. package/dist/Components/Touch/NumberKeyboard.svelte +268 -268
  109. package/dist/Components/Touch/NumberModal.svelte +69 -69
  110. package/dist/Components/Touch/PlusMinusCard.svelte +50 -50
  111. package/dist/Components/Touch/SelectModal.svelte +105 -105
  112. package/dist/Components/Touch/SummaryCard.svelte +65 -65
  113. package/dist/Components/Touch/TextAreaModal.svelte +86 -86
  114. package/dist/Components/Touch/TextModal.svelte +123 -123
  115. package/dist/Components/Touch/TouchCard.svelte +28 -28
  116. package/dist/Components/Touch/TouchModal.svelte +259 -259
  117. package/dist/Components/Touch/UtilityButton.svelte +91 -91
  118. package/dist/Components/VerticalTabGroup.svelte +66 -66
  119. package/dist/Components/VerticalTabGroupButton.svelte +97 -97
  120. package/dist/Helpers/Datamatrix.d.ts +10 -10
  121. package/dist/Helpers/Datamatrix.js +1 -1
  122. package/dist/Helpers/Helpers.svelte.js +6 -4
  123. package/dist/Types/Examples/ExampleModal.svelte +34 -34
  124. package/dist/index.d.ts +1 -0
  125. package/dist/scss/_basics.scss +12 -12
  126. package/dist/scss/_colours.scss +134 -134
  127. package/dist/scss/_mixins.scss +3016 -3016
  128. package/dist/scss/_sizing.scss +69 -69
  129. package/dist/scss/_transitions.scss +8 -8
  130. package/package.json +2 -2
@@ -1,41 +1,41 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- lang="ts"
5
- generics="T extends object"
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
-
14
- const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
15
-
16
- const backgroundColour = $derived.by(() => {
17
- return tableContext.sortedData.length > 0 && tableContext.allHighlighted
18
- ? Colour['$brand-primary']
19
- : Colour['$ui-white'];
20
- });
21
- </script>
22
-
23
- <div class="checkbox-cell">
24
- <div class="wrapper">
25
- <Action
26
- {backgroundColour}
27
- hoverBackgroundColour={Colour['$brand-dark']}
28
- size={Size.FillWidth}
29
- icon={{
30
- name: 'nothing',
31
- }}
32
- onclick={() => {
33
- tableContext.onHighlightAll()?.catch(devCatch);
34
- }}
35
- />
36
- </div>
37
- </div>
38
-
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ generics="T extends object"
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
+
14
+ const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
15
+
16
+ const backgroundColour = $derived.by(() => {
17
+ return tableContext.sortedData.length > 0 && tableContext.allHighlighted
18
+ ? Colour['$brand-primary']
19
+ : Colour['$ui-white'];
20
+ });
21
+ </script>
22
+
23
+ <div class="checkbox-cell">
24
+ <div class="wrapper">
25
+ <Action
26
+ {backgroundColour}
27
+ hoverBackgroundColour={Colour['$brand-dark']}
28
+ size={Size.FillWidth}
29
+ icon={{
30
+ name: 'nothing',
31
+ }}
32
+ onclick={() => {
33
+ tableContext.onHighlightAll()?.catch(devCatch);
34
+ }}
35
+ />
36
+ </div>
37
+ </div>
38
+
39
39
  <style>div.wrapper {
40
40
  position: absolute;
41
41
  top: 0;
@@ -45,4 +45,4 @@
45
45
  display: flex;
46
46
  align-items: stretch;
47
47
  justify-content: stretch;
48
- }</style>
48
+ }</style>
@@ -1,30 +1,30 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- lang="ts"
5
- generics="T extends object"
6
- >
7
- import { getContext } from 'svelte';
8
- import { TableContext } from '../Types/Context/TableContext.svelte.js';
9
-
10
- const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
11
-
12
- const checked: boolean = $derived(
13
- tableContext.dataRepo.data.length > 0 ? tableContext.allSelectedInCurrentPage : false
14
- );
15
- </script>
16
-
17
- <div class="checkbox-cell">
18
- <label>
19
- <input
20
- onchange={tableContext.selectAllInCurrentPage}
21
- type="checkbox"
22
- {checked}
23
- disabled={tableContext.showSelectedOnly}
24
- />
25
- </label>
26
- </div>
27
-
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ generics="T extends object"
6
+ >
7
+ import { getContext } from 'svelte';
8
+ import { TableContext } from '../Types/Context/TableContext.svelte.js';
9
+
10
+ const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
11
+
12
+ const checked: boolean = $derived(
13
+ tableContext.dataRepo.data.length > 0 ? tableContext.allSelectedInCurrentPage : false
14
+ );
15
+ </script>
16
+
17
+ <div class="checkbox-cell">
18
+ <label>
19
+ <input
20
+ onchange={tableContext.selectAllInCurrentPage}
21
+ type="checkbox"
22
+ {checked}
23
+ disabled={tableContext.showSelectedOnly}
24
+ />
25
+ </label>
26
+ </div>
27
+
28
28
  <style>input[type=checkbox] {
29
29
  height: var(--checkbox-height);
30
30
  padding: 1rem;
@@ -52,4 +52,4 @@ label {
52
52
 
53
53
  label {
54
54
  cursor: pointer;
55
- }</style>
55
+ }</style>
@@ -1,262 +1,262 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- module
5
- lang="ts"
6
- >
7
- import Icon from '../../Icon.svelte';
8
- import { TooltipContext } from '../../../Contexts/TooltipContext.svelte.js';
9
- import { Delay } from '../../../Delay/Delay.js';
10
- import { devCatch } from '../../../Helpers/Helpers.svelte.js';
11
- import { Colour } from '../../../scss/colours.js';
12
- import { Side } from '../../../Types/Internal/Side.js';
13
- import { Size } from '../../../Types/Internal/Size.js';
14
- import { Variant } from '../../../Types/Internal/Variant.js';
15
- import { getContext } from 'svelte';
16
- import type { ColumnDef } from '../Types/Columns/Definitions/ColumnDef.svelte.js';
17
- import { ExpandDef } from '../Types/Columns/Definitions/Expand/ExpandDef.svelte.js';
18
- import { RowSelectionDef } from '../Types/Columns/Definitions/RowSelection/RowSelectionDef.svelte.js';
19
- import { TableContext } from '../Types/Context/TableContext.svelte.js';
20
- import type { HeaderGroup } from '../Types/HeaderGroup.js';
21
- import HighlightAllHeader from './HighlightAllHeader.svelte';
22
- import SelectAllHeader from './SelectAllHeader.svelte';
23
-
24
- export interface TableHeadProps {
25
- showHighlight: boolean;
26
- side: 'left' | 'centre' | 'right';
27
- oncontextmenu?: (e: MouseEvent) => void;
28
- }
29
- </script>
30
-
31
- <script
32
- lang="ts"
33
- generics="T extends object"
34
- >
35
- const { showHighlight, side = 'centre', oncontextmenu }: TableHeadProps = $props();
36
-
37
- const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
38
- const tooltipContext = getContext<TooltipContext>(TooltipContext.identifier);
39
-
40
- const groups: Array<HeaderGroup<T>> = $derived.by(() => {
41
- void tableContext.table.columnVisibility;
42
- void Object.keys(tableContext.table.columnVisibility);
43
- void tableContext.table.columnPinning.left?.size;
44
- void tableContext.table.columnPinning.right?.size;
45
-
46
- return side === 'left'
47
- ? tableContext.table.getLeftHeaderGroups()
48
- : side === 'right'
49
- ? tableContext.table.getRightHeaderGroups()
50
- : tableContext.table.getCenterHeaderGroups();
51
- });
52
-
53
- const iconNames = {
54
- asc: 'sort-asc',
55
- desc: 'sort-desc',
56
- none: 'sort-none',
57
- } as const;
58
-
59
- let currentDropTarget: HTMLTableCellElement | null = $state(null);
60
-
61
- function setCurrentDropTarget(target: EventTarget | null) {
62
- currentDropTarget = target as HTMLTableCellElement | null;
63
- }
64
-
65
- function showtooltip(e: MouseEvent, columnDef: ColumnDef<T>): void {
66
- if (columnDef instanceof ExpandDef) {
67
- const rect = (e.target as HTMLElement).closest('th')?.getBoundingClientRect();
68
-
69
- if (!rect) {
70
- console.warn('could not find closest TH');
71
-
72
- return;
73
- }
74
-
75
- tooltipContext.showTooltip({
76
- text: `Show ${typeof columnDef.header === 'string' ? columnDef.header : columnDef.id}`,
77
- arrow: Side.Bottom,
78
- delay: Delay.Default,
79
- rect,
80
- });
81
- }
82
- }
83
-
84
- function hideTooltip(columnDef: ColumnDef<T>): void {
85
- if (columnDef instanceof ExpandDef) {
86
- tooltipContext.hideTooltip(
87
- `Show ${typeof columnDef.header === 'string' ? columnDef.header : columnDef.id}`
88
- );
89
- }
90
- }
91
-
92
- function onDrop() {
93
- if (!tableContext.dragTarget) {
94
- return;
95
- }
96
-
97
- // const dropTarget = (e.target as HTMLElement)?.closest('th');
98
- const dropTarget = currentDropTarget?.closest('th');
99
-
100
- if (dropTarget) {
101
- tableContext.reorderColumn(dropTarget);
102
- }
103
-
104
- currentDropTarget = null;
105
- }
106
-
107
- function setDragTarget(def: ColumnDef<T>) {
108
- tableContext.dragTarget = def;
109
- }
110
-
111
- const currentDropTargetId = $derived(
112
- (currentDropTarget as HTMLElement | null | undefined)?.closest('th')?.id
113
- );
114
- </script>
115
-
116
- <thead
117
- oncontextmenu={(e) => {
118
- e.stopPropagation();
119
- oncontextmenu?.(e);
120
- }}
121
- >
122
- {#each groups as group (group)}
123
- <tr>
124
- {#if showHighlight && group.headers.length}
125
- <th
126
- id="highlight-header"
127
- draggable={false}
128
- colspan="1"
129
- class="highlight-column"
130
- >
131
- <div class="th">
132
- <HighlightAllHeader />
133
- </div>
134
- </th>
135
- {/if}
136
-
137
- {#each group.headers as header (header)}
138
- {@const headerId = `${tableContext.tableName}-header-${header.id}`}
139
- <!-- {@const computedSize = tableContext.measureHeaderWidth(header.column.columnDef)} -->
140
- <th
141
- id={headerId}
142
- draggable={tableContext.allowColumnReordering}
143
- colSpan={header.colSpan}
144
- style="width: {Math.max(
145
- // computedSize,
146
- // header.column.columnDef.minSize ?? 0,
147
- // tableContext.columnSizing[header.id] ??
148
- header.getSize()
149
- )}px"
150
- class:action-column={!header.column.getCanSort()}
151
- class:targeted={currentDropTargetId === headerId}
152
- ondragstart={() => {
153
- setDragTarget(header.column.columnDef);
154
- }}
155
- ondragover={(e) => {
156
- e.preventDefault();
157
- if (tableContext.dragTarget?.id !== header.id) {
158
- setCurrentDropTarget(e.target);
159
- } else {
160
- setCurrentDropTarget(null);
161
- }
162
- }}
163
- ondrop={onDrop}
164
- >
165
- {#if !header.isPlaceholder}
166
- <div class="margin-right">
167
- {#if header.column.getCanSort()}
168
- <button
169
- onmouseenter={(e) => {
170
- showtooltip(e, header.column.columnDef);
171
- }}
172
- onmouseleave={() => {
173
- hideTooltip(header.column.columnDef);
174
- }}
175
- class="contents"
176
- onclick={header.column.getToggleSortingHandler()}
177
- >
178
- <div class="th cursor-pointer select-none">
179
- <div class="header-text-wrapper">
180
- {#if header.column.columnDef instanceof RowSelectionDef}
181
- <SelectAllHeader />
182
- {:else}
183
- {#if header.column.columnDef instanceof ExpandDef}
184
- <Icon
185
- name={header.column.columnDef.headerIcon}
186
- colour={Colour['$font-primary']}
187
- />
188
- {:else if typeof header.column.columnDef.header == 'string'}
189
- {header.column.columnDef.header}
190
- {:else}
191
- {@render header.column.columnDef.header()}
192
- {/if}
193
- <Icon
194
- variant={Variant.HeaderIcon}
195
- size={Size.Medium}
196
- name={iconNames[header.column.getIsSorted()]}
197
- />
198
- {/if}
199
- </div>
200
- </div>
201
- </button>
202
- {:else}
203
- {@const isRowSelect = header.column.columnDef instanceof RowSelectionDef}
204
- <!-- svelte-ignore a11y_no_static_element_interactions -->
205
- <div
206
- onmouseenter={(e) => {
207
- showtooltip(e, header.column.columnDef);
208
- }}
209
- onmouseleave={() => {
210
- hideTooltip(header.column.columnDef);
211
- }}
212
- class="contents"
213
- >
214
- <div
215
- class="th"
216
- class:nopadding={isRowSelect}
217
- >
218
- <div class="header-text-wrapper no-sort cursor-pointer select-none">
219
- {#if isRowSelect}
220
- <SelectAllHeader />
221
- {:else if header.column.columnDef instanceof ExpandDef}
222
- <Icon
223
- name={header.column.columnDef.headerIcon}
224
- colour={Colour['$font-primary']}
225
- />
226
- {:else if typeof header.column.columnDef.header == 'string'}
227
- {header.column.columnDef.header}
228
- {:else}
229
- {@render header.column.columnDef.header()}
230
- {/if}
231
- </div>
232
- </div>
233
- </div>
234
- {/if}
235
-
236
- {#if tableContext.enableResize}
237
- <!-- svelte-ignore a11y_no_static_element_interactions -->
238
- <div
239
- onmousedown={(e) => {
240
- e.preventDefault();
241
- e.stopImmediatePropagation();
242
- const handler = header.getResizeHandler();
243
- handler(e);
244
- }}
245
- ondblclick={() => {
246
- tableContext.autoResize(header.column.columnDef).catch(devCatch);
247
- }}
248
- class="resizer right"
249
- class:isResizing={header.column.getIsResizing()}
250
- ></div>
251
- {/if}
252
- </div>
253
- {/if}
254
- </th>
255
- {/each}
256
- </tr>
257
- {/each}
258
- </thead>
259
-
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ module
5
+ lang="ts"
6
+ >
7
+ import Icon from '../../Icon.svelte';
8
+ import { TooltipContext } from '../../../Contexts/TooltipContext.svelte.js';
9
+ import { Delay } from '../../../Delay/Delay.js';
10
+ import { devCatch } from '../../../Helpers/Helpers.svelte.js';
11
+ import { Colour } from '../../../scss/colours.js';
12
+ import { Side } from '../../../Types/Internal/Side.js';
13
+ import { Size } from '../../../Types/Internal/Size.js';
14
+ import { Variant } from '../../../Types/Internal/Variant.js';
15
+ import { getContext } from 'svelte';
16
+ import type { ColumnDef } from '../Types/Columns/Definitions/ColumnDef.svelte.js';
17
+ import { ExpandDef } from '../Types/Columns/Definitions/Expand/ExpandDef.svelte.js';
18
+ import { RowSelectionDef } from '../Types/Columns/Definitions/RowSelection/RowSelectionDef.svelte.js';
19
+ import { TableContext } from '../Types/Context/TableContext.svelte.js';
20
+ import type { HeaderGroup } from '../Types/HeaderGroup.js';
21
+ import HighlightAllHeader from './HighlightAllHeader.svelte';
22
+ import SelectAllHeader from './SelectAllHeader.svelte';
23
+
24
+ export interface TableHeadProps {
25
+ showHighlight: boolean;
26
+ side: 'left' | 'centre' | 'right';
27
+ oncontextmenu?: (e: MouseEvent) => void;
28
+ }
29
+ </script>
30
+
31
+ <script
32
+ lang="ts"
33
+ generics="T extends object"
34
+ >
35
+ const { showHighlight, side = 'centre', oncontextmenu }: TableHeadProps = $props();
36
+
37
+ const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
38
+ const tooltipContext = getContext<TooltipContext>(TooltipContext.identifier);
39
+
40
+ const groups: Array<HeaderGroup<T>> = $derived.by(() => {
41
+ void tableContext.table.columnVisibility;
42
+ void Object.keys(tableContext.table.columnVisibility);
43
+ void tableContext.table.columnPinning.left?.size;
44
+ void tableContext.table.columnPinning.right?.size;
45
+
46
+ return side === 'left'
47
+ ? tableContext.table.getLeftHeaderGroups()
48
+ : side === 'right'
49
+ ? tableContext.table.getRightHeaderGroups()
50
+ : tableContext.table.getCenterHeaderGroups();
51
+ });
52
+
53
+ const iconNames = {
54
+ asc: 'sort-asc',
55
+ desc: 'sort-desc',
56
+ none: 'sort-none',
57
+ } as const;
58
+
59
+ let currentDropTarget: HTMLTableCellElement | null = $state(null);
60
+
61
+ function setCurrentDropTarget(target: EventTarget | null) {
62
+ currentDropTarget = target as HTMLTableCellElement | null;
63
+ }
64
+
65
+ function showtooltip(e: MouseEvent, columnDef: ColumnDef<T>): void {
66
+ if (columnDef instanceof ExpandDef) {
67
+ const rect = (e.target as HTMLElement).closest('th')?.getBoundingClientRect();
68
+
69
+ if (!rect) {
70
+ console.warn('could not find closest TH');
71
+
72
+ return;
73
+ }
74
+
75
+ tooltipContext.showTooltip({
76
+ text: `Show ${typeof columnDef.header === 'string' ? columnDef.header : columnDef.id}`,
77
+ arrow: Side.Bottom,
78
+ delay: Delay.Default,
79
+ rect,
80
+ });
81
+ }
82
+ }
83
+
84
+ function hideTooltip(columnDef: ColumnDef<T>): void {
85
+ if (columnDef instanceof ExpandDef) {
86
+ tooltipContext.hideTooltip(
87
+ `Show ${typeof columnDef.header === 'string' ? columnDef.header : columnDef.id}`
88
+ );
89
+ }
90
+ }
91
+
92
+ function onDrop() {
93
+ if (!tableContext.dragTarget) {
94
+ return;
95
+ }
96
+
97
+ // const dropTarget = (e.target as HTMLElement)?.closest('th');
98
+ const dropTarget = currentDropTarget?.closest('th');
99
+
100
+ if (dropTarget) {
101
+ tableContext.reorderColumn(dropTarget);
102
+ }
103
+
104
+ currentDropTarget = null;
105
+ }
106
+
107
+ function setDragTarget(def: ColumnDef<T>) {
108
+ tableContext.dragTarget = def;
109
+ }
110
+
111
+ const currentDropTargetId = $derived(
112
+ (currentDropTarget as HTMLElement | null | undefined)?.closest('th')?.id
113
+ );
114
+ </script>
115
+
116
+ <thead
117
+ oncontextmenu={(e) => {
118
+ e.stopPropagation();
119
+ oncontextmenu?.(e);
120
+ }}
121
+ >
122
+ {#each groups as group (group)}
123
+ <tr>
124
+ {#if showHighlight && group.headers.length}
125
+ <th
126
+ id="highlight-header"
127
+ draggable={false}
128
+ colspan="1"
129
+ class="highlight-column"
130
+ >
131
+ <div class="th">
132
+ <HighlightAllHeader />
133
+ </div>
134
+ </th>
135
+ {/if}
136
+
137
+ {#each group.headers as header (header)}
138
+ {@const headerId = `${tableContext.tableName}-header-${header.id}`}
139
+ <!-- {@const computedSize = tableContext.measureHeaderWidth(header.column.columnDef)} -->
140
+ <th
141
+ id={headerId}
142
+ draggable={tableContext.allowColumnReordering}
143
+ colSpan={header.colSpan}
144
+ style="width: {Math.max(
145
+ // computedSize,
146
+ // header.column.columnDef.minSize ?? 0,
147
+ // tableContext.columnSizing[header.id] ??
148
+ header.getSize()
149
+ )}px"
150
+ class:action-column={!header.column.getCanSort()}
151
+ class:targeted={currentDropTargetId === headerId}
152
+ ondragstart={() => {
153
+ setDragTarget(header.column.columnDef);
154
+ }}
155
+ ondragover={(e) => {
156
+ e.preventDefault();
157
+ if (tableContext.dragTarget?.id !== header.id) {
158
+ setCurrentDropTarget(e.target);
159
+ } else {
160
+ setCurrentDropTarget(null);
161
+ }
162
+ }}
163
+ ondrop={onDrop}
164
+ >
165
+ {#if !header.isPlaceholder}
166
+ <div class="margin-right">
167
+ {#if header.column.getCanSort()}
168
+ <button
169
+ onmouseenter={(e) => {
170
+ showtooltip(e, header.column.columnDef);
171
+ }}
172
+ onmouseleave={() => {
173
+ hideTooltip(header.column.columnDef);
174
+ }}
175
+ class="contents"
176
+ onclick={header.column.getToggleSortingHandler()}
177
+ >
178
+ <div class="th cursor-pointer select-none">
179
+ <div class="header-text-wrapper">
180
+ {#if header.column.columnDef instanceof RowSelectionDef}
181
+ <SelectAllHeader />
182
+ {:else}
183
+ {#if header.column.columnDef instanceof ExpandDef}
184
+ <Icon
185
+ name={header.column.columnDef.headerIcon}
186
+ colour={Colour['$font-primary']}
187
+ />
188
+ {:else if typeof header.column.columnDef.header == 'string'}
189
+ {header.column.columnDef.header}
190
+ {:else}
191
+ {@render header.column.columnDef.header()}
192
+ {/if}
193
+ <Icon
194
+ variant={Variant.HeaderIcon}
195
+ size={Size.Medium}
196
+ name={iconNames[header.column.getIsSorted()]}
197
+ />
198
+ {/if}
199
+ </div>
200
+ </div>
201
+ </button>
202
+ {:else}
203
+ {@const isRowSelect = header.column.columnDef instanceof RowSelectionDef}
204
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
205
+ <div
206
+ onmouseenter={(e) => {
207
+ showtooltip(e, header.column.columnDef);
208
+ }}
209
+ onmouseleave={() => {
210
+ hideTooltip(header.column.columnDef);
211
+ }}
212
+ class="contents"
213
+ >
214
+ <div
215
+ class="th"
216
+ class:nopadding={isRowSelect}
217
+ >
218
+ <div class="header-text-wrapper no-sort cursor-pointer select-none">
219
+ {#if isRowSelect}
220
+ <SelectAllHeader />
221
+ {:else if header.column.columnDef instanceof ExpandDef}
222
+ <Icon
223
+ name={header.column.columnDef.headerIcon}
224
+ colour={Colour['$font-primary']}
225
+ />
226
+ {:else if typeof header.column.columnDef.header == 'string'}
227
+ {header.column.columnDef.header}
228
+ {:else}
229
+ {@render header.column.columnDef.header()}
230
+ {/if}
231
+ </div>
232
+ </div>
233
+ </div>
234
+ {/if}
235
+
236
+ {#if tableContext.enableResize}
237
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
238
+ <div
239
+ onmousedown={(e) => {
240
+ e.preventDefault();
241
+ e.stopImmediatePropagation();
242
+ const handler = header.getResizeHandler();
243
+ handler(e);
244
+ }}
245
+ ondblclick={() => {
246
+ tableContext.autoResize(header.column.columnDef).catch(devCatch);
247
+ }}
248
+ class="resizer right"
249
+ class:isResizing={header.column.getIsResizing()}
250
+ ></div>
251
+ {/if}
252
+ </div>
253
+ {/if}
254
+ </th>
255
+ {/each}
256
+ </tr>
257
+ {/each}
258
+ </thead>
259
+
260
260
  <style>th {
261
261
  position: relative;
262
262
  min-width: fit-content;
@@ -381,4 +381,4 @@ tr th:first-of-type {
381
381
  }
382
382
  tr th:last-of-type {
383
383
  border-right: none;
384
- }</style>
384
+ }</style>