@lavalogic/scoria 0.40.13 → 0.40.15

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 (143) 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 -87
  16. package/dist/Components/CollapsibleMenuGroup.svelte +53 -57
  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 +151 -0
  56. package/dist/Components/PopoverButton.svelte.d.ts +9 -0
  57. package/dist/Components/PopoverButtonProps.d.ts +21 -0
  58. package/dist/Components/PopoverButtonProps.js +1 -0
  59. package/dist/Components/Portal.svelte +29 -35
  60. package/dist/Components/ProgressBubble.svelte +91 -106
  61. package/dist/Components/QuerySelect.svelte +260 -346
  62. package/dist/Components/SidebarPanel.svelte +34 -36
  63. package/dist/Components/SingleSelect.svelte +196 -244
  64. package/dist/Components/StepButton.svelte +65 -70
  65. package/dist/Components/StepForm.svelte +115 -135
  66. package/dist/Components/Switch.svelte +57 -69
  67. package/dist/Components/Table/ARCHITECTURE.md +298 -298
  68. package/dist/Components/Table/Body/QuickSearchCell.svelte +578 -655
  69. package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +42 -51
  70. package/dist/Components/Table/Body/Rows/ColumnList.svelte +42 -58
  71. package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +403 -442
  72. package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +51 -78
  73. package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +165 -184
  74. package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +110 -123
  75. package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +134 -160
  76. package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +190 -231
  77. package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +82 -104
  78. package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +52 -87
  79. package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +122 -150
  80. package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +132 -159
  81. package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +190 -236
  82. package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +173 -211
  83. package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +204 -244
  84. package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +140 -177
  85. package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +188 -217
  86. package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +173 -193
  87. package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +166 -187
  88. package/dist/Components/Table/Body/Rows/TableRow.svelte +245 -288
  89. package/dist/Components/Table/Body/TableBody.svelte +141 -154
  90. package/dist/Components/Table/Headers/HighlightAllHeader.svelte +35 -41
  91. package/dist/Components/Table/Headers/SelectAllHeader.svelte +24 -30
  92. package/dist/Components/Table/Headers/TableHead.svelte +348 -402
  93. package/dist/Components/Table/Misc/ColumnPanel.svelte +37 -39
  94. package/dist/Components/Table/Misc/ColumnPanelModal.svelte +35 -39
  95. package/dist/Components/Table/Misc/FilterInput.svelte +556 -619
  96. package/dist/Components/Table/Misc/FilterPanel.svelte +170 -183
  97. package/dist/Components/Table/Misc/FilterPanelModal.svelte +25 -31
  98. package/dist/Components/Table/Misc/ShareViewModal.svelte +252 -281
  99. package/dist/Components/Table/Misc/SidePanel.svelte +32 -35
  100. package/dist/Components/Table/Misc/TableConfigurationModal.svelte +574 -629
  101. package/dist/Components/Table/Misc/TableFooter.svelte +326 -332
  102. package/dist/Components/Table/Misc/TableHorizontalBar.svelte +134 -140
  103. package/dist/Components/Table/Misc/TableSidebar.svelte +183 -198
  104. package/dist/Components/Table/Misc/TableViewDropdown.svelte +83 -103
  105. package/dist/Components/Table/Misc/ToolboxPanel.svelte +83 -100
  106. package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +88 -107
  107. package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte +163 -190
  108. package/dist/Components/Table/NestedTable.svelte +102 -128
  109. package/dist/Components/Table/Table.svelte +531 -663
  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/index.d.ts +2 -0
  136. package/dist/index.js +1 -0
  137. package/dist/scss/_basics.scss +12 -12
  138. package/dist/scss/_colours.scss +134 -134
  139. package/dist/scss/_mixins.scss +3392 -3392
  140. package/dist/scss/_motion.scss +57 -57
  141. package/dist/scss/_sizing.scss +85 -85
  142. package/dist/scss/_transitions.scss +8 -8
  143. 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>