@lavalogic/scoria 0.40.14 → 0.40.16

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 (141) hide show
  1. package/README.md +58 -58
  2. package/dist/Components/AccordionGroup.svelte +35 -46
  3. package/dist/Components/AccordionGroupButton.svelte +68 -76
  4. package/dist/Components/Action.svelte +103 -135
  5. package/dist/Components/AlertModal.svelte +171 -190
  6. package/dist/Components/AppointmentCalendar/AppointmentCalendar.svelte +614 -697
  7. package/dist/Components/Base/BaseModal.svelte +90 -116
  8. package/dist/Components/Base/ContextWrapper.svelte +67 -72
  9. package/dist/Components/Base/Pagination.svelte +173 -196
  10. package/dist/Components/Base/Snippets.svelte +34 -36
  11. package/dist/Components/BigRadioSet.svelte +36 -38
  12. package/dist/Components/Bubble.svelte +78 -101
  13. package/dist/Components/Button.svelte +175 -208
  14. package/dist/Components/Checkbox.svelte +75 -86
  15. package/dist/Components/CollapsibleCard.svelte +72 -86
  16. package/dist/Components/CollapsibleMenuGroup.svelte +52 -56
  17. package/dist/Components/ConditionBuilder/ConditionBuilder.svelte +39 -64
  18. package/dist/Components/Contexts/ContextMenu.svelte +141 -156
  19. package/dist/Components/Contexts/ContextMenuDivider.svelte +15 -15
  20. package/dist/Components/Contexts/ContextMenuOption.svelte +53 -60
  21. package/dist/Components/Contexts/Toast.svelte +81 -86
  22. package/dist/Components/Contexts/ToastContainer.svelte +58 -62
  23. package/dist/Components/Contexts/Tooltip.svelte +36 -37
  24. package/dist/Components/DataMatrixIcon.svelte +95 -108
  25. package/dist/Components/DateInput.svelte +118 -146
  26. package/dist/Components/DatePicker.svelte +255 -294
  27. package/dist/Components/DesktopModal.svelte +70 -90
  28. package/dist/Components/Dial.svelte +167 -197
  29. package/dist/Components/DimensionInput.svelte +124 -169
  30. package/dist/Components/DragMenu/DragMenuHolder.svelte +98 -114
  31. package/dist/Components/DragMenu/DraggableCard.svelte +64 -76
  32. package/dist/Components/FileCard.svelte +21 -24
  33. package/dist/Components/FileUpload.svelte +190 -225
  34. package/dist/Components/GridInput.svelte +159 -196
  35. package/dist/Components/GridInputSet.svelte +24 -29
  36. package/dist/Components/HorizontalTabGroup.svelte +73 -89
  37. package/dist/Components/HorizontalTabGroupButton.svelte +40 -44
  38. package/dist/Components/Icon.svelte +99 -128
  39. package/dist/Components/Icons.js +357 -357
  40. package/dist/Components/InfoAlert.svelte +35 -38
  41. package/dist/Components/LoadingAnimation.svelte +691 -755
  42. package/dist/Components/LoadingModal.svelte +36 -44
  43. package/dist/Components/LoadingOverlay.svelte +22 -26
  44. package/dist/Components/Modal.svelte +204 -254
  45. package/dist/Components/MultiSelect.svelte +186 -216
  46. package/dist/Components/Nav/Nav.svelte +94 -110
  47. package/dist/Components/Nav/NavServiceMenuList.svelte +57 -61
  48. package/dist/Components/Nav/NavTab.svelte +58 -62
  49. package/dist/Components/Nav/ServiceMenuItem.svelte +103 -111
  50. package/dist/Components/Nav/ServicesNav.svelte +72 -79
  51. package/dist/Components/NumberInput.svelte +121 -155
  52. package/dist/Components/OptionCards.svelte +62 -73
  53. package/dist/Components/PageHeading.svelte +23 -25
  54. package/dist/Components/PasswordInput.svelte +69 -88
  55. package/dist/Components/PopoverButton.svelte +69 -82
  56. package/dist/Components/Portal.svelte +29 -35
  57. package/dist/Components/ProgressBubble.svelte +91 -106
  58. package/dist/Components/QuerySelect.svelte +260 -346
  59. package/dist/Components/SidebarPanel.svelte +34 -36
  60. package/dist/Components/SingleSelect.svelte +196 -244
  61. package/dist/Components/StepButton.svelte +65 -70
  62. package/dist/Components/StepForm.svelte +115 -135
  63. package/dist/Components/Switch.svelte +57 -69
  64. package/dist/Components/Table/ARCHITECTURE.md +298 -298
  65. package/dist/Components/Table/Body/QuickSearchCell.svelte +578 -655
  66. package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +42 -51
  67. package/dist/Components/Table/Body/Rows/ColumnList.svelte +42 -58
  68. package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +403 -442
  69. package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +51 -78
  70. package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +165 -184
  71. package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +110 -123
  72. package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +134 -160
  73. package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +190 -231
  74. package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +82 -104
  75. package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +52 -87
  76. package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +122 -150
  77. package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +132 -159
  78. package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +190 -236
  79. package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +173 -211
  80. package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +204 -244
  81. package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +140 -177
  82. package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +188 -217
  83. package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +173 -193
  84. package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +166 -187
  85. package/dist/Components/Table/Body/Rows/TableRow.svelte +245 -288
  86. package/dist/Components/Table/Body/TableBody.svelte +141 -154
  87. package/dist/Components/Table/ColumnFactory.svelte.js +1 -0
  88. package/dist/Components/Table/Headers/HighlightAllHeader.svelte +35 -41
  89. package/dist/Components/Table/Headers/SelectAllHeader.svelte +24 -30
  90. package/dist/Components/Table/Headers/TableHead.svelte +348 -402
  91. package/dist/Components/Table/Misc/ColumnPanel.svelte +37 -39
  92. package/dist/Components/Table/Misc/ColumnPanelModal.svelte +35 -39
  93. package/dist/Components/Table/Misc/FilterInput.svelte +556 -619
  94. package/dist/Components/Table/Misc/FilterPanel.svelte +170 -183
  95. package/dist/Components/Table/Misc/FilterPanelModal.svelte +25 -31
  96. package/dist/Components/Table/Misc/ShareViewModal.svelte +252 -281
  97. package/dist/Components/Table/Misc/SidePanel.svelte +32 -35
  98. package/dist/Components/Table/Misc/TableConfigurationModal.svelte +574 -629
  99. package/dist/Components/Table/Misc/TableFooter.svelte +326 -332
  100. package/dist/Components/Table/Misc/TableHorizontalBar.svelte +134 -140
  101. package/dist/Components/Table/Misc/TableSidebar.svelte +183 -198
  102. package/dist/Components/Table/Misc/TableViewDropdown.svelte +83 -103
  103. package/dist/Components/Table/Misc/ToolboxPanel.svelte +83 -100
  104. package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +88 -107
  105. package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte +163 -190
  106. package/dist/Components/Table/NestedTable.svelte +102 -128
  107. package/dist/Components/Table/Table.svelte +531 -663
  108. package/dist/Components/Table/Types/Columns/Definitions/Actions/ActionsDef.svelte.d.ts +8 -6
  109. package/dist/Components/Table/Types/Columns/Definitions/Actions/ActionsDef.svelte.js +3 -3
  110. package/dist/Components/Test/TestContextConsumer.svelte +11 -13
  111. package/dist/Components/TextArea.svelte +95 -130
  112. package/dist/Components/TextInput.svelte +125 -176
  113. package/dist/Components/ThreeStateRadio.svelte +111 -130
  114. package/dist/Components/Touch/BoolCard.svelte +33 -45
  115. package/dist/Components/Touch/DateModal.svelte +164 -204
  116. package/dist/Components/Touch/EditCard.svelte +48 -59
  117. package/dist/Components/Touch/InfoCard.svelte +28 -31
  118. package/dist/Components/Touch/InfoTextCard.svelte +26 -28
  119. package/dist/Components/Touch/ModalExplanation.svelte +15 -17
  120. package/dist/Components/Touch/NumberKeyboard.svelte +181 -218
  121. package/dist/Components/Touch/NumberModal.svelte +59 -79
  122. package/dist/Components/Touch/PlusMinusCard.svelte +43 -46
  123. package/dist/Components/Touch/SelectModal.svelte +111 -126
  124. package/dist/Components/Touch/SummaryCard.svelte +80 -93
  125. package/dist/Components/Touch/TextAreaModal.svelte +72 -94
  126. package/dist/Components/Touch/TextModal.svelte +77 -105
  127. package/dist/Components/Touch/TouchCard.svelte +31 -33
  128. package/dist/Components/Touch/TouchModal.svelte +214 -270
  129. package/dist/Components/Touch/UtilityButton.svelte +88 -109
  130. package/dist/Components/VerticalTabGroup.svelte +60 -78
  131. package/dist/Components/VerticalTabGroupButton.svelte +54 -58
  132. package/dist/Helpers/Datamatrix.d.ts +19 -19
  133. package/dist/Helpers/Datamatrix.js +291 -291
  134. package/dist/Types/Examples/ExampleModal.svelte +31 -35
  135. package/dist/scss/_basics.scss +12 -12
  136. package/dist/scss/_colours.scss +134 -134
  137. package/dist/scss/_mixins.scss +3392 -3392
  138. package/dist/scss/_motion.scss +57 -57
  139. package/dist/scss/_sizing.scss +85 -85
  140. package/dist/scss/_transitions.scss +8 -8
  141. package/package.json +1 -1
@@ -1,254 +1,214 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- lang="ts"
5
- generics="T extends object, RowIdType extends Primitive"
6
- >
7
- import QuerySelect from '../../../../QuerySelect.svelte';
8
- import type { QueryDef } from '../../../Types/Columns/Definitions/Accessors/QueryDef.svelte.js';
9
- import { TableContext } from '../../../Types/Context/TableContext.svelte.js';
10
- import { type Primitive } from '../../../Types/Context/TableInitOptions.js';
11
- import { devCatch, loadingText } from '../../../../../Helpers/Helpers.svelte.js';
12
- import type { SelectOption } from '../../../../../Types/Internal/SelectOption.js';
13
- import { Validity } from '../../../../../Types/Internal/Validity.js';
14
- import { getContext, tick, untrack } from 'svelte';
15
- import { useAsyncEditable } from './_helpers/useAsyncEditable.svelte.js';
16
- import type { TableQuerySelectProps } from './TableQuerySelectProps.js';
17
-
18
- const { cell }: TableQuerySelectProps<T, unknown> = $props();
19
-
20
- const value = $derived((cell.getValue() ?? null) as unknown);
21
-
22
- const visibleValue = $derived(
23
- cell.column.columnDef.getDisplayValue(cell.row.original, cell.row.originalIndex)
24
- );
25
-
26
- let tdref = $state<HTMLElement | undefined>();
27
-
28
- /**
29
- * Narrow the column def to `QueryDef<T>`. `TableCell.column.columnDef`
30
- * is the loose `ColumnDef<T>`; `TableColumn` only dispatches this
31
- * component when the underlying def is a `QueryDef`, but the static
32
- * type does not reflect that.
33
- */
34
- const columnDef: QueryDef<T> = $derived(cell.column.columnDef) as unknown as QueryDef<T>;
35
-
36
- // `bind:options` below requires a `let` binding even though we never
37
- // reassign the reference (Svelte uses the binding for two-way wiring).
38
- // eslint-disable-next-line svelte/prefer-const
39
- let lastOptions: Array<SelectOption<unknown>> = $state([]);
40
-
41
- const tableContext = getContext<TableContext<T, RowIdType>>(TableContext.identifier);
42
-
43
- let valueAsyncCounter = 0;
44
- $effect(() => {
45
- void value;
46
- void lastOptions;
47
-
48
- untrack(() => {
49
- const localCounter = (valueAsyncCounter = valueAsyncCounter + 1);
50
- (async () => {
51
- try {
52
- const awaitedValue = await value;
53
- const label = (await visibleValue) ?? awaitedValue?.toString();
54
-
55
- if (awaitedValue != null && valueAsyncCounter === localCounter) {
56
- if (label == null) {
57
- throw new Error('invalid label and value');
58
- }
59
- if (!lastOptions.some((it) => it.value == awaitedValue)) {
60
- lastOptions.push({
61
- label,
62
- value: awaitedValue,
63
- });
64
- }
65
- } else if (columnDef.debug) {
66
- console.debug(
67
- `${cell.column.columnDef.id}: `,
68
- 'skipping async option insertion because it is stale'
69
- );
70
- }
71
- } catch (e) {
72
- if (columnDef.debug) {
73
- console.error(e);
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ generics="T extends object, RowIdType extends Primitive"
6
+ >import QuerySelect from "../../../../QuerySelect.svelte";
7
+ import { TableContext } from "../../../Types/Context/TableContext.svelte.js";
8
+ import "../../../Types/Context/TableInitOptions.js";
9
+ import { devCatch, loadingText } from "../../../../../Helpers/Helpers.svelte.js";
10
+ import { Validity } from "../../../../../Types/Internal/Validity.js";
11
+ import { getContext, tick, untrack } from "svelte";
12
+ import { useAsyncEditable } from "./_helpers/useAsyncEditable.svelte.js";
13
+ const { cell } = $props();
14
+ const value = $derived(cell.getValue() ?? null);
15
+ const visibleValue = $derived(cell.column.columnDef.getDisplayValue(cell.row.original, cell.row.originalIndex));
16
+ let tdref = $state();
17
+ /**
18
+ * Narrow the column def to `QueryDef<T>`. `TableCell.column.columnDef`
19
+ * is the loose `ColumnDef<T>`; `TableColumn` only dispatches this
20
+ * component when the underlying def is a `QueryDef`, but the static
21
+ * type does not reflect that.
22
+ */
23
+ const columnDef = $derived(cell.column.columnDef);
24
+ // `bind:options` below requires a `let` binding even though we never
25
+ // reassign the reference (Svelte uses the binding for two-way wiring).
26
+ // eslint-disable-next-line svelte/prefer-const
27
+ let lastOptions = $state([]);
28
+ const tableContext = getContext(TableContext.identifier);
29
+ let valueAsyncCounter = 0;
30
+ $effect(() => {
31
+ void value;
32
+ void lastOptions;
33
+ untrack(() => {
34
+ const localCounter = valueAsyncCounter = valueAsyncCounter + 1;
35
+ (async () => {
36
+ try {
37
+ const awaitedValue = await value;
38
+ const label = await visibleValue ?? awaitedValue?.toString();
39
+ if (awaitedValue != null && valueAsyncCounter === localCounter) {
40
+ if (label == null) {
41
+ throw new Error("invalid label and value");
74
42
  }
75
- if (valueAsyncCounter === localCounter) {
76
- //nothing happens
77
- } else if (columnDef.debug) {
78
- console.debug(
79
- `${cell.column.columnDef.id}: `,
80
- 'skipping caught async option insertion error because it is stale'
81
- );
43
+ if (!lastOptions.some((it) => it.value == awaitedValue)) {
44
+ lastOptions.push({
45
+ label,
46
+ value: awaitedValue
47
+ });
82
48
  }
49
+ } else if (columnDef.debug) {
50
+ console.debug(`${cell.column.columnDef.id}: `, "skipping async option insertion because it is stale");
83
51
  }
84
- })().catch(devCatch);
85
- });
86
- });
87
-
88
- const editable = useAsyncEditable<T, RowIdType>({
89
- cell: () => cell,
52
+ } catch (e) {
53
+ if (columnDef.debug) {
54
+ console.error(e);
55
+ }
56
+ if (valueAsyncCounter === localCounter) {} else if (columnDef.debug) {
57
+ console.debug(`${cell.column.columnDef.id}: `, "skipping caught async option insertion error because it is stale");
58
+ }
59
+ }
60
+ })().catch(devCatch);
90
61
  });
91
-
92
- function handleUnfocus(e: KeyboardEvent) {
93
- if (e.key === 'Escape') {
94
- e.preventDefault();
95
- e.stopPropagation();
96
- editable.leaveEditingViaKeyboard(tdref);
97
- return true;
98
- }
99
-
100
- if (e.key === 'Tab') {
101
- e.preventDefault();
102
- return true;
103
- }
104
-
105
- return false;
62
+ });
63
+ const editable = useAsyncEditable({ cell: () => cell });
64
+ function handleUnfocus(e) {
65
+ if (e.key === "Escape") {
66
+ e.preventDefault();
67
+ e.stopPropagation();
68
+ editable.leaveEditingViaKeyboard(tdref);
69
+ return true;
106
70
  }
107
-
108
- function keydownForce(e: KeyboardEvent) {
109
- const shouldStop = handleUnfocus(e);
110
- if (!shouldStop && !(e.key === 'ArrowUp' || e.key === 'ArrowDown')) {
111
- tick()
112
- .then(() => {
113
- tdref?.dispatchEvent(
114
- new KeyboardEvent('keydown', {
115
- key: e.key,
116
- altKey: e.getModifierState('Alt'),
117
- metaKey: e.getModifierState('Meta'),
118
- shiftKey: e.getModifierState('Shift'),
119
- ctrlKey: e.getModifierState('Control'),
120
- bubbles: true,
121
- })
122
- );
123
- })
124
- .catch(devCatch);
125
- }
71
+ if (e.key === "Tab") {
72
+ e.preventDefault();
73
+ return true;
126
74
  }
127
-
128
- /**
129
- * Track the inner QuerySelect input so the keydown re-dispatcher is
130
- * removed cleanly on blur or remount. This wiring is cell-specific
131
- * (Select / QuerySelect only) and so lives outside the shared
132
- * `useAsyncEditable` helper.
133
- */
134
- let activeKeydownTarget: HTMLInputElement | undefined;
135
-
136
- function addKeydownEvent(target: HTMLInputElement | undefined) {
137
- if (activeKeydownTarget && activeKeydownTarget !== target) {
138
- activeKeydownTarget.removeEventListener('keydown', keydownForce);
139
- }
140
- if (target) {
141
- target.addEventListener('keydown', keydownForce);
142
- activeKeydownTarget = target;
143
- }
75
+ return false;
76
+ }
77
+ function keydownForce(e) {
78
+ const shouldStop = handleUnfocus(e);
79
+ if (!shouldStop && !(e.key === "ArrowUp" || e.key === "ArrowDown")) {
80
+ tick().then(() => {
81
+ tdref?.dispatchEvent(new KeyboardEvent("keydown", {
82
+ key: e.key,
83
+ altKey: e.getModifierState("Alt"),
84
+ metaKey: e.getModifierState("Meta"),
85
+ shiftKey: e.getModifierState("Shift"),
86
+ ctrlKey: e.getModifierState("Control"),
87
+ bubbles: true
88
+ }));
89
+ }).catch(devCatch);
144
90
  }
145
-
146
- function removeKeydownEvent() {
147
- if (activeKeydownTarget) {
148
- activeKeydownTarget.removeEventListener('keydown', keydownForce);
149
- activeKeydownTarget = undefined;
150
- }
91
+ }
92
+ /**
93
+ * Track the inner QuerySelect input so the keydown re-dispatcher is
94
+ * removed cleanly on blur or remount. This wiring is cell-specific
95
+ * (Select / QuerySelect only) and so lives outside the shared
96
+ * `useAsyncEditable` helper.
97
+ */
98
+ let activeKeydownTarget;
99
+ function addKeydownEvent(target) {
100
+ if (activeKeydownTarget && activeKeydownTarget !== target) {
101
+ activeKeydownTarget.removeEventListener("keydown", keydownForce);
151
102
  }
152
-
153
- /**
154
- * Wire the `edit` custom event with cleanup on tdref remount or
155
- * component unmount. The listener plumbing lives in the shared
156
- * `useAsyncEditable` helper.
157
- */
158
- $effect(() => editable.attachEditListener(tdref));
159
-
160
- // Ensure the keydown listener is dropped when the cell unmounts.
161
- $effect(() => removeKeydownEvent);
162
- </script>
163
-
164
- {#if editable.isBeingEdited}
165
- <div
166
- class="select-cell"
167
- bind:this={tdref}
168
- >
169
- {#await value then value}
170
- <QuerySelect
171
- focusOnLoad
172
- name={cell.column.columnDef.id}
173
- valueProp={'value' as never}
174
- labelProp={'label' as never}
175
- clearable={cell.column.columnDef.clearable}
176
- valueAsObject={false}
177
- value={value as never}
178
- query={(v: string) => columnDef.query(v, cell.row.original, cell.row.originalIndex)}
179
- bind:options={lastOptions as never}
180
- onfocus={addKeydownEvent}
181
- onchange={(newValue: unknown) => {
182
- // `valueAsObject={false}` makes QuerySelect emit the
183
- // primitive value directly. The `as never` casts work
184
- // around component-generic inference (see TableSelect
185
- // for the same workaround).
186
- if (newValue !== value) {
187
- tableContext
188
- .onEditCell(cell.row.original, editable.focusDetails.coordinates, newValue ?? null)
189
- .catch(devCatch);
190
- }
191
-
192
- removeKeydownEvent();
193
- tableContext.focusStartIsBeingEdited = false;
194
- tick()
195
- .then(() => {
196
- tdref?.focus();
197
- })
198
- .catch(devCatch);
199
- }}
200
- />
201
- {/await}
202
- </div>
203
- {:else}
204
- <!-- svelte-ignore a11y_mouse_events_have_key_events -->
205
- <!-- svelte-ignore a11y_no_static_element_interactions -->
206
- <div
207
- style={editable.focusDetails.outline}
208
- bind:this={tdref}
209
- tabIndex="0"
210
- id={`${tableContext.tableName}-cell-${cell.row.visibleIndex}-${cell.column.id}`}
211
- class="focusable editable"
212
- class:multifocus={editable.focusDetails.isMultiFocused}
213
- class:multifocus-start={editable.focusDetails.isMultiFocusStart}
214
- class:info={editable.validity == Validity.Info}
215
- class:success={editable.validity == Validity.Valid}
216
- class:warning={editable.validity == Validity.Warning}
217
- class:error={editable.validity == Validity.Invalid}
218
- ondblclick={() => {
219
- editable.handleDoubleClickFocus();
220
- }}
221
- onmousedown={(e) => {
222
- // start focus only on left click
223
- if (e.button === 0) {
224
- if (e.shiftKey) {
225
- e.preventDefault();
226
- tableContext.setFocusEnd(editable.focusDetails.coordinates);
227
- } else {
228
- tableContext.startFocus(editable.focusDetails.coordinates);
229
- }
230
- }
231
- }}
232
- onmouseover={() => {
233
- if (tableContext.isMousingDown) {
234
- tableContext.setFocusEnd(editable.focusDetails.coordinates);
235
- }
236
- }}
237
- onmouseup={() => {
238
- const wasHandled = editable.handleSingleClickFocus();
239
- if (!wasHandled) {
240
- tableContext.endFocus(editable.focusDetails.coordinates);
241
- }
242
- }}
243
- >
244
- {#await visibleValue}
245
- {loadingText}
246
- {:then v}
247
- {v}
248
- {/await}
249
- </div>
250
- {/if}
251
-
103
+ if (target) {
104
+ target.addEventListener("keydown", keydownForce);
105
+ activeKeydownTarget = target;
106
+ }
107
+ }
108
+ function removeKeydownEvent() {
109
+ if (activeKeydownTarget) {
110
+ activeKeydownTarget.removeEventListener("keydown", keydownForce);
111
+ activeKeydownTarget = undefined;
112
+ }
113
+ }
114
+ /**
115
+ * Wire the `edit` custom event with cleanup on tdref remount or
116
+ * component unmount. The listener plumbing lives in the shared
117
+ * `useAsyncEditable` helper.
118
+ */
119
+ $effect(() => editable.attachEditListener(tdref));
120
+ // Ensure the keydown listener is dropped when the cell unmounts.
121
+ $effect(() => removeKeydownEvent);
122
+ </script>
123
+
124
+ {#if editable.isBeingEdited}
125
+ <div
126
+ class="select-cell"
127
+ bind:this={tdref}
128
+ >
129
+ {#await value then value}
130
+ <QuerySelect
131
+ focusOnLoad
132
+ name={cell.column.columnDef.id}
133
+ valueProp={'value' as never}
134
+ labelProp={'label' as never}
135
+ clearable={cell.column.columnDef.clearable}
136
+ valueAsObject={false}
137
+ value={value as never}
138
+ query={(v: string) => columnDef.query(v, cell.row.original, cell.row.originalIndex)}
139
+ bind:options={lastOptions as never}
140
+ onfocus={addKeydownEvent}
141
+ onchange={(newValue: unknown) => {
142
+ // `valueAsObject={false}` makes QuerySelect emit the
143
+ // primitive value directly. The `as never` casts work
144
+ // around component-generic inference (see TableSelect
145
+ // for the same workaround).
146
+ if (newValue !== value) {
147
+ tableContext
148
+ .onEditCell(cell.row.original, editable.focusDetails.coordinates, newValue ?? null)
149
+ .catch(devCatch);
150
+ }
151
+
152
+ removeKeydownEvent();
153
+ tableContext.focusStartIsBeingEdited = false;
154
+ tick()
155
+ .then(() => {
156
+ tdref?.focus();
157
+ })
158
+ .catch(devCatch);
159
+ }}
160
+ />
161
+ {/await}
162
+ </div>
163
+ {:else}
164
+ <!-- svelte-ignore a11y_mouse_events_have_key_events -->
165
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
166
+ <div
167
+ style={editable.focusDetails.outline}
168
+ bind:this={tdref}
169
+ tabIndex="0"
170
+ id={`${tableContext.tableName}-cell-${cell.row.visibleIndex}-${cell.column.id}`}
171
+ class="focusable editable"
172
+ class:multifocus={editable.focusDetails.isMultiFocused}
173
+ class:multifocus-start={editable.focusDetails.isMultiFocusStart}
174
+ class:info={editable.validity == Validity.Info}
175
+ class:success={editable.validity == Validity.Valid}
176
+ class:warning={editable.validity == Validity.Warning}
177
+ class:error={editable.validity == Validity.Invalid}
178
+ ondblclick={() => {
179
+ editable.handleDoubleClickFocus();
180
+ }}
181
+ onmousedown={(e) => {
182
+ // start focus only on left click
183
+ if (e.button === 0) {
184
+ if (e.shiftKey) {
185
+ e.preventDefault();
186
+ tableContext.setFocusEnd(editable.focusDetails.coordinates);
187
+ } else {
188
+ tableContext.startFocus(editable.focusDetails.coordinates);
189
+ }
190
+ }
191
+ }}
192
+ onmouseover={() => {
193
+ if (tableContext.isMousingDown) {
194
+ tableContext.setFocusEnd(editable.focusDetails.coordinates);
195
+ }
196
+ }}
197
+ onmouseup={() => {
198
+ const wasHandled = editable.handleSingleClickFocus();
199
+ if (!wasHandled) {
200
+ tableContext.endFocus(editable.focusDetails.coordinates);
201
+ }
202
+ }}
203
+ >
204
+ {#await visibleValue}
205
+ {loadingText}
206
+ {:then v}
207
+ {v}
208
+ {/await}
209
+ </div>
210
+ {/if}
211
+
252
212
  <style>.focusable,
253
213
  .checkbox-cell,
254
214
  .input-cell,
@@ -325,4 +285,4 @@
325
285
  --sv-item-wrap-padding: 0px 0.75rem;
326
286
  --input-height: var(--height);
327
287
  min-width: 0;
328
- }</style>
288
+ }</style>