@lavalogic/scoria 0.17.2 → 0.18.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 (46) hide show
  1. package/dist/Components/Table/Body/QuickSearchCell.svelte +78 -73
  2. package/dist/Components/Table/Body/Rows/ColumnList.svelte +1 -1
  3. package/dist/Components/Table/Body/Rows/ColumnListRowProps.d.ts +1 -1
  4. package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +12 -6
  5. package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +15 -35
  6. package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +15 -35
  7. package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +35 -4
  8. package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +60 -26
  9. package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +14 -35
  10. package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +35 -5
  11. package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +82 -139
  12. package/dist/Components/Table/Body/Rows/Columns/TableDatePickerProps.d.ts +1 -1
  13. package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +15 -35
  14. package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte.d.ts +1 -2
  15. package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +14 -34
  16. package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +93 -37
  17. package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte.d.ts +12 -13
  18. package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +14 -34
  19. package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +14 -34
  20. package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +40 -61
  21. package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte.d.ts +12 -11
  22. package/dist/Components/Table/ColumnDefinitions/ExampleItemColumnDefRepository.svelte.js +39 -29
  23. package/dist/Components/Table/Misc/FilterInput.svelte +1 -1
  24. package/dist/Components/Table/Table.svelte +15 -16
  25. package/dist/Components/Table/Types/Columns/DateColumn.d.ts +2 -2
  26. package/dist/Components/Table/Types/Columns/DateTableCell.d.ts +2 -2
  27. package/dist/Components/Table/Types/Columns/Definitions/ColumnDefSet.d.ts +1 -1
  28. package/dist/Components/Table/Types/Columns/Definitions/JSONColumnDefSet.d.ts +1 -1
  29. package/dist/Components/Table/Types/Columns/Definitions/ValidationFn.d.ts +1 -1
  30. package/dist/Components/Table/Types/Context/ITable.d.ts +0 -1
  31. package/dist/Components/Table/Types/Context/Row.d.ts +3 -3
  32. package/dist/Components/Table/Types/Context/TableContext.svelte.d.ts +16 -22
  33. package/dist/Components/Table/Types/Context/TableContext.svelte.js +299 -275
  34. package/dist/Components/Table/Types/DataRepository/IDataRepository.d.ts +1 -1
  35. package/dist/Components/Table/Types/DataRepository/ILocalDataRepository.d.ts +1 -1
  36. package/dist/Components/Table/Types/DataRepository/LocalTableDataRepository.svelte.d.ts +2 -2
  37. package/dist/Components/Table/Types/DataRepository/LocalTableDataRepository.svelte.js +23 -7
  38. package/dist/Components/Table/Types/DataRepository/TableDataRepository.svelte.d.ts +2 -2
  39. package/dist/Components/Table/Types/DataRepository/TableDataRepository.svelte.js +2 -4
  40. package/dist/Components/Table/Types/Focus/TableFocusDetails.svelte.d.ts +18 -36
  41. package/dist/Components/Table/Types/Focus/TableFocusDetails.svelte.js +77 -113
  42. package/dist/Components/TextInput.svelte +11 -4
  43. package/dist/Components/Touch/DateModal.svelte +26 -14
  44. package/dist/Helpers/Helpers.svelte.d.ts +5 -1
  45. package/dist/Helpers/Helpers.svelte.js +9 -10
  46. package/package.json +14 -14
@@ -88,7 +88,7 @@
88
88
  const isSelectOpen = $derived(openedSelect?.value === selectSymbol);
89
89
 
90
90
  // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
91
- let value: unknown | null = $state(null);
91
+ let asdfvalue: unknown | null = $state(null);
92
92
  let valueMin: number | null = $state(null);
93
93
  let valueMax: number | null = $state(null);
94
94
 
@@ -118,15 +118,13 @@
118
118
  return;
119
119
  }
120
120
  void filteringStateValue;
121
- if (def.debug) {
122
- console.log('filtering state value:', $state.snapshot(filteringStateValue));
123
- }
121
+
124
122
  if (hasQuery(customFilter)) {
125
123
  if (def.debug) {
126
124
  console.log('has query');
127
125
  }
128
126
 
129
- untrack(() => {
127
+ untrack(async () => {
130
128
  const gotValue = filteringStateValue as Array<unknown> | undefined;
131
129
 
132
130
  try {
@@ -137,12 +135,12 @@
137
135
  console.log(`query values:`, tableContext.dataRepo.__queryValues);
138
136
  }
139
137
  const key = customFilter.id;
140
- const x = tableContext.dataRepo.__queryValues.get(key);
138
+ const x = await tableContext.dataRepo.__queryValues.get(key);
141
139
 
142
140
  if (def.debug) {
143
141
  console.log('value:', $state.snapshot(x));
144
142
  }
145
- value = x ?? null;
143
+ asdfvalue = (await x) ?? null;
146
144
  } else if (def.debug) {
147
145
  console.log(
148
146
  'filtering state value was undefined',
@@ -151,9 +149,9 @@
151
149
  }
152
150
  } catch (e) {
153
151
  console.warn(e);
154
- value = null;
152
+ asdfvalue = null;
155
153
  }
156
- });
154
+ }).catch(devCatch);
157
155
  } else if (isSelect) {
158
156
  if (def.debug) {
159
157
  console.log('is select (not query)');
@@ -209,31 +207,40 @@
209
207
  const gotValue = filteringStateValue;
210
208
  if (gotValue != undefined) {
211
209
  const [min, max] = gotValue as [number, number | undefined];
212
- value = min;
210
+ asdfvalue = min;
213
211
  valueMin = min;
214
212
  valueMax = max ?? null;
215
213
  } else {
216
- value = valueMin = valueMax = null;
214
+ asdfvalue = valueMin = valueMax = null;
217
215
  }
218
216
  } else if (tableContext.paginationRepo?.filtering) {
219
217
  const gotValue = filteringStateValue;
218
+
220
219
  if (gotValue != undefined) {
221
220
  const [min] = gotValue as [number, number | undefined];
222
- value = min;
221
+ asdfvalue = min;
223
222
  valueMin = min;
224
223
  valueMax = min;
225
224
  } else {
226
- value = valueMin = valueMax = null;
225
+ asdfvalue = valueMin = valueMax = null;
227
226
  }
228
227
  }
229
228
  } else if (tableContext.paginationRepo?.filtering) {
230
229
  const gotValue = filteringStateValue;
231
230
  if (gotValue == null || typeof gotValue == 'string' || typeof gotValue == 'number') {
232
- value = gotValue;
231
+ //RATS
232
+ rats(gotValue);
233
+ asdfvalue = gotValue;
233
234
  }
234
235
  }
235
236
  });
236
237
 
238
+ function rats(gotValue: unknown) {
239
+ // RATS
240
+ if (dev && gotValue != null && typeof gotValue == 'object' && gotValue instanceof Promise) {
241
+ throw new Error(`Unexpected Promise`);
242
+ }
243
+ }
237
244
  onMount(() => {
238
245
  const filterOption =
239
246
  tableContext.paginationRepo?.filtering &&
@@ -244,17 +251,19 @@
244
251
  [valueMin, valueMax] = filterOption.value;
245
252
  if (valueMax == undefined) {
246
253
  valueMax = valueMin;
247
- value = valueMin?.toString();
254
+ asdfvalue = valueMin?.toString();
248
255
  } else if (valueMin == undefined) {
249
256
  valueMin = valueMax;
250
- value = valueMax.toString();
257
+ asdfvalue = valueMax.toString();
251
258
  } else {
252
- value = valueMin.toString();
259
+ asdfvalue = valueMin.toString();
253
260
  }
254
261
  } else if (!hasQuery(customFilter)) {
255
262
  const gotValue = filterOption.value;
256
263
  if (gotValue == null || typeof gotValue == 'string' || typeof gotValue == 'number') {
257
- value = gotValue;
264
+ //RATS
265
+ rats(gotValue);
266
+ asdfvalue = gotValue;
258
267
  }
259
268
  }
260
269
  }
@@ -274,7 +283,8 @@
274
283
  return (newValue: SelectOption<unknown> | null) => {
275
284
  tableContext.paginationRepo?.filterBy(def.id, newValue?.value ?? null);
276
285
  tableContext.dataRepo.__queryValues.set(label, newValue);
277
- value = newValue;
286
+ rats(newValue);
287
+ asdfvalue = newValue;
278
288
  };
279
289
  }
280
290
 
@@ -282,9 +292,12 @@
282
292
  return (newValue: SelectOption<unknown> | null) => {
283
293
  tableContext.paginationRepo?.filterBy(def.id, newValue?.value ?? null);
284
294
  tableContext.dataRepo.__queryValues.set(label, newValue?.value ?? null);
285
- value = newValue?.value ?? null;
295
+ rats(newValue);
296
+ asdfvalue = newValue?.value ?? null;
286
297
  };
287
298
  }
299
+
300
+ let isNullFilter = $derived(selectedNumberFilterType?.value == NumberDateFilterMode.null);
288
301
  </script>
289
302
 
290
303
  <td class="input-cell {inputId}">
@@ -356,7 +369,7 @@
356
369
  name={customFilter.objectName ?? 'Item'}
357
370
  valueProp="value"
358
371
  labelProp="label"
359
- value={value as null}
372
+ value={asdfvalue as null}
360
373
  query={customFilter.query}
361
374
  bind:options={lastQueryOptions}
362
375
  onchange={generateOnChangePrimitive(label)}
@@ -372,7 +385,7 @@
372
385
  name={customFilter.objectName ?? 'Item'}
373
386
  valueProp="value"
374
387
  labelProp="label"
375
- value={value as null}
388
+ value={asdfvalue as null}
376
389
  query={customFilter.query}
377
390
  bind:options={lastQueryOptions}
378
391
  onchange={generateOnChangeObject(label)}
@@ -464,46 +477,41 @@
464
477
  onkeydown={closeOnCtrlF}
465
478
  />
466
479
  </div>
467
- {:else if value == null || typeof value == 'number'}
468
- <div class="input-wrapper right">
469
- {#if selectedNumberFilterType?.value == NumberDateFilterMode.null}
470
- <TextInput
471
- data-type="quicksearch"
472
- id={inputId}
473
- value="is Null"
474
- disabled
475
- variant={InputVariant.Table}
476
- />
477
- {:else}
478
- <NumberInput
479
- data-type="quicksearch"
480
- id={inputId}
481
- bind:value={valueMin}
482
- variant={InputVariant.Table}
483
- placeholder="Min&hellip;"
484
- oninput={() => {
485
- tableContext.paginationRepo?.filterBy(def.id, [valueMin, null]);
486
- }}
487
- onkeydown={closeOnCtrlF}
488
- />
489
- {/if}
490
- </div>
491
- {:else if typeof value == 'string'}
492
- <div class="input-wrapper right">
493
- <TextInput
494
- data-type="quicksearch"
495
- id={inputId}
496
- bind:value={value as string | null}
497
- placeholder="Filter&hellip;"
498
- variant={InputVariant.Table}
499
- oninput={() => {
500
- tableContext.paginationRepo?.filterBy(def.id, [value]);
501
- }}
502
- onkeydown={closeOnCtrlF}
503
- />
504
- </div>
480
+ {:else}
481
+ <svelte:boundary>
482
+ <div class="input-wrapper right">
483
+ {#await isNullFilter}
484
+ loading
485
+ {:then isNullFilter}
486
+ {#if isNullFilter}
487
+ <TextInput
488
+ data-type="quicksearch"
489
+ id={inputId}
490
+ value="is Null"
491
+ disabled
492
+ variant={InputVariant.Table}
493
+ />
494
+ {:else}
495
+ <!-- NOTE: This is a text input in order to support the __in functionality, which is a comma separated list of numbers -->
496
+ <TextInput
497
+ data-type="quicksearch"
498
+ id={inputId}
499
+ bind:value={asdfvalue as string | null}
500
+ placeholder="Filter&hellip;"
501
+ variant={InputVariant.Table}
502
+ oninput={() => {
503
+ tableContext.paginationRepo?.filterBy(def.id, [asdfvalue || null]);
504
+ }}
505
+ onkeydown={closeOnCtrlF}
506
+ />
507
+ {/if}
508
+ {:catch e}
509
+ {@debug e}
510
+ {/await}
511
+ </div>
512
+ </svelte:boundary>
505
513
  {/if}
506
- {:else if value == null || typeof value == 'string'}
514
+ {:else if asdfvalue == null || typeof asdfvalue == 'string'}
507
515
  <div class="input-wrapper right">
508
516
  {#if selectedStringFilterType?.value == StringFilterMode.null}
509
517
  <TextInput
@@ -526,10 +534,10 @@
526
534
  data-type="quicksearch"
527
535
  id={inputId}
528
536
  oninput={() => {
529
- tableContext.paginationRepo?.filterBy(def.id, value);
537
+ tableContext.paginationRepo?.filterBy(def.id, asdfvalue);
530
538
  }}
531
539
  variant={InputVariant.Table}
532
- bind:value={value as string | null}
540
+ bind:value={asdfvalue as string | null}
533
541
  placeholder="Filter&hellip;"
534
542
  />
535
543
  {/if}
@@ -584,19 +592,16 @@
584
592
 
585
593
  const newFilterType = newValue?.value ?? NumberDateFilterMode.In;
586
594
 
587
- tableContext.paginationRepo?.setFilterMode(def.id, newFilterType);
595
+ if (newFilterType !== oldFilterType?.value) {
596
+ tableContext.paginationRepo?.setFilterMode(def.id, newFilterType);
588
597
 
589
- if (selectedNumberFilterType?.value !== oldFilterType?.value) {
590
- if (oldFilterType?.value === NumberDateFilterMode.Between) {
591
- valueMax = null;
598
+ if (newFilterType === NumberDateFilterMode.Between) {
592
599
  tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMin]);
600
+ } else if (newFilterType === NumberDateFilterMode.In) {
601
+ tableContext.paginationRepo?.filterBy(def.id, [asdfvalue]);
602
+ } else {
603
+ tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMax]);
593
604
  }
594
-
595
- if (newFilterType === NumberDateFilterMode.In) {
596
- tableContext.paginationRepo?.filterBy(def.id, [value]);
597
- }
598
-
599
- // TODO what about the other modes?
600
605
  }
601
606
  }}
602
607
  onkeydown={(e: KeyboardEvent) => {
@@ -15,7 +15,7 @@
15
15
 
16
16
  const { searchValue }: ColumnListProps = $props();
17
17
 
18
- const visibleColumns: Array<ColumnDef<T, never, unknown>> = $derived.by(() => {
18
+ const visibleColumns: Array<ColumnDef<T>> = $derived.by(() => {
19
19
  const lowercasedSearchValue = searchValue.toLocaleLowerCase();
20
20
  return tableContext.columnDefs.filter(
21
21
  (it) =>
@@ -1,4 +1,4 @@
1
1
  import type { ColumnDef } from '../../Types/Columns/Definitions/ColumnDef.svelte.js';
2
2
  export interface ColumnListRowProps<T extends object> {
3
- columnDef: ColumnDef<T, never, unknown> | null;
3
+ columnDef: ColumnDef<T> | null;
4
4
  }
@@ -1,6 +1,9 @@
1
1
  <svelte:options runes />
2
2
 
3
- <script lang="ts" module>
3
+ <script
4
+ lang="ts"
5
+ module
6
+ >
4
7
  import { AccessorDef } from '../../../Types/Columns/Definitions/Accessors/AccessorDef.svelte.js';
5
8
  import type { ColumnDef } from '../../../Types/Columns/Definitions/ColumnDef.svelte.js';
6
9
  import type { Component } from 'svelte';
@@ -12,6 +15,13 @@
12
15
  import TableQuerySelect from './TableQuerySelect.svelte';
13
16
  import TableSelect from './TableSelect.svelte';
14
17
  import TableTextInput from './TableTextInput.svelte';
18
+ </script>
19
+
20
+ <script
21
+ lang="ts"
22
+ generics="T extends object"
23
+ >
24
+ const { cell }: AccessorComponentProps<T> = $props();
15
25
 
16
26
  const cellTypes: Record<
17
27
  'Number' | 'Date' | 'Select' | 'Checkbox' | 'Query' | 'Text',
@@ -22,12 +32,8 @@
22
32
  Select: TableSelect,
23
33
  Query: TableQuerySelect,
24
34
  Checkbox: TableCheckbox,
25
- Text: TableTextInput
35
+ Text: TableTextInput,
26
36
  } as const;
27
- </script>
28
-
29
- <script lang="ts" generics="T extends object, ">
30
- const { cell }: AccessorComponentProps<T> = $props();
31
37
 
32
38
  const CurrentComponent = $derived(getAppropriateAccessorDef(cell.column.columnDef));
33
39
 
@@ -10,12 +10,11 @@
10
10
  import { TableContext } from '../../../Types/Context/TableContext.svelte.js';
11
11
  import { MultiFocusEdge } from '../../../Types/Focus/MultiFocusEdge.js';
12
12
  import { TableFocusDetails } from '../../../Types/Focus/TableFocusDetails.svelte.js';
13
- import { ToastContext } from '../../../../../Contexts/ToastContext.svelte.js';
14
- import { asyncMap, devCatch, refWrapper } from '../../../../../Helpers/Helpers.svelte.js';
13
+ import { asyncMap, devCatch, isValidityTuple, refWrapper } from '../../../../../Helpers/Helpers.svelte.js';
15
14
  import { Colour, ColourSet } from '../../../../../scss/colours.js';
16
15
  import { Size } from '../../../../../Types/Internal/Size.js';
17
16
  import { Validity } from '../../../../../Types/Internal/Validity.js';
18
- import { getContext, tick, untrack } from 'svelte';
17
+ import { getContext, untrack } from 'svelte';
19
18
  import type { ActionsCellProps } from './ActionsCellProps.js';
20
19
  import TableAction from './TableAction.svelte';
21
20
 
@@ -31,7 +30,6 @@
31
30
  const value = $derived(cell.getValue());
32
31
 
33
32
  const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
34
- const toastContext = getContext<ToastContext>(ToastContext.identifier);
35
33
 
36
34
  const actions: Array<TableActionButton<T>> = $derived(cell.column.columnDef.actions);
37
35
 
@@ -39,8 +37,8 @@
39
37
  const thisPopupIsVisibile = $derived(thisPopup === shownPopup.value);
40
38
  const hasValue: boolean = $derived(value !== undefined);
41
39
  const edge: MultiFocusEdge | undefined = $state();
42
- const focusDetails: TableFocusDetails<T> = $derived(
43
- new TableFocusDetails(cell, tableContext, toastContext.toast)
40
+ const focusDetails: TableFocusDetails<T, never> = $derived(
41
+ new TableFocusDetails(cell, tableContext)
44
42
  );
45
43
 
46
44
  let cellRef: HTMLDivElement | undefined = $state();
@@ -73,40 +71,22 @@
73
71
  }
74
72
  });
75
73
 
76
- let previousValidity: Validity = $state(Validity.Valid);
77
74
  let validity: Validity = $state(Validity.Valid);
78
75
  $effect(() => {
79
- focusDetails.validityTuple
80
- .then(([newValidity]) => {
81
- untrack(() => {
82
- tick()
83
- .then(() => {
84
- validity = newValidity;
85
- })
86
- .catch(devCatch);
87
- });
76
+ const validityPromise = focusDetails.validity;
77
+
78
+ validityPromise
79
+ .then((v) => {
80
+ if (!v) {
81
+ validity = Validity.Neutral;
82
+ } else if (isValidityTuple(v)) {
83
+ validity = v.value;
84
+ } else {
85
+ validity = v;
86
+ }
88
87
  })
89
88
  .catch(devCatch);
90
89
  });
91
-
92
- $effect(() => {
93
- if (validity != previousValidity) {
94
- untrack(() => {
95
- tick()
96
- .then(() => {
97
- const x =
98
- validity === Validity.Invalid
99
- ? tableContext.addInvalidValue(cell.row.original)
100
- : tableContext.removeInvalidValue(cell.row.original);
101
-
102
- previousValidity = validity;
103
-
104
- return x;
105
- })
106
- .catch(devCatch);
107
- });
108
- }
109
- });
110
90
  </script>
111
91
 
112
92
  <!-- svelte-ignore a11y_mouse_events_have_key_events -->
@@ -9,10 +9,9 @@
9
9
  import { BubbleDef } from '../../../Types/Columns/Definitions/Display/BubbleDef.svelte.js';
10
10
  import { TableContext } from '../../../Types/Context/TableContext.svelte.js';
11
11
  import { TableFocusDetails } from '../../../Types/Focus/TableFocusDetails.svelte.js';
12
- import { ToastContext } from '../../../../../Contexts/ToastContext.svelte.js';
13
- import { devCatch } from '../../../../../Helpers/Helpers.svelte.js';
12
+ import { devCatch, isValidityTuple } from '../../../../../Helpers/Helpers.svelte.js';
14
13
  import { Validity } from '../../../../../Types/Internal/Validity.js';
15
- import { getContext, tick, untrack } from 'svelte';
14
+ import { getContext } from 'svelte';
16
15
  import type { FocusableImmutableCellProps } from './FocusableImmutableCellProps.js';
17
16
 
18
17
  const { cell }: FocusableImmutableCellProps<T, FilterValueType> = $props();
@@ -20,46 +19,27 @@
20
19
  const values = $derived(cell.getValue()) as Array<string> | Promise<Array<string>>;
21
20
 
22
21
  const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
23
- const toastContext = getContext<ToastContext>(ToastContext.identifier);
24
22
 
25
- const focusDetails: TableFocusDetails<T> = $derived(
26
- new TableFocusDetails(cell, tableContext, toastContext.toast)
23
+ const focusDetails: TableFocusDetails<T, never> = $derived(
24
+ new TableFocusDetails(cell, tableContext)
27
25
  );
28
26
 
29
- let previousValidity: Validity = $state(Validity.Valid);
30
27
  let validity: Validity = $state(Validity.Valid);
31
28
  $effect(() => {
32
- focusDetails.validityTuple
33
- .then(([newValidity]) => {
34
- untrack(() => {
35
- tick()
36
- .then(() => {
37
- validity = newValidity;
38
- })
39
- .catch(devCatch);
40
- });
29
+ const validityPromise = focusDetails.validity;
30
+
31
+ validityPromise
32
+ .then((v) => {
33
+ if (!v) {
34
+ validity = Validity.Neutral;
35
+ } else if (isValidityTuple(v)) {
36
+ validity = v.value;
37
+ } else {
38
+ validity = v;
39
+ }
41
40
  })
42
41
  .catch(devCatch);
43
42
  });
44
-
45
- $effect(() => {
46
- if (validity != previousValidity) {
47
- untrack(() => {
48
- tick()
49
- .then(() => {
50
- const x =
51
- validity === Validity.Invalid
52
- ? tableContext.addInvalidValue(cell.row.original)
53
- : tableContext.removeInvalidValue(cell.row.original);
54
-
55
- previousValidity = validity;
56
-
57
- return x;
58
- })
59
- .catch(devCatch);
60
- });
61
- }
62
- });
63
43
  </script>
64
44
 
65
45
  <!-- svelte-ignore a11y_mouse_events_have_key_events -->
@@ -8,9 +8,10 @@
8
8
  import { TableContext } from '../../../Types/Context/TableContext.svelte.js';
9
9
  import type { Primitive } from '../../../Types/Context/TableInitOptions.js';
10
10
  import { TableFocusDetails } from '../../../Types/Focus/TableFocusDetails.svelte.js';
11
- import { ToastContext } from '../../../../../Contexts/ToastContext.svelte.js';
11
+ import { devCatch, isValidityTuple } from '../../../../../Helpers/Helpers.svelte.js';
12
12
  import { ColourSet } from '../../../../../scss/colours.js';
13
13
  import { Size } from '../../../../../Types/Internal/Size.js';
14
+ import { Validity } from '../../../../../Types/Internal/Validity.js';
14
15
  import { getContext } from 'svelte';
15
16
  import type { ExpandCellProps } from './ExpandCellProps.js';
16
17
 
@@ -21,18 +22,38 @@
21
22
  }: ExpandCellProps<T, R, IdType, FilterValueType> = $props();
22
23
 
23
24
  const tableContext = getContext<TableContext<T, never>>(TableContext.identifier);
24
- const toastContext = getContext<ToastContext>(ToastContext.identifier);
25
- const focusDetails: TableFocusDetails<T> = $derived(
26
- new TableFocusDetails(cell, tableContext, toastContext.toast)
25
+ const focusDetails: TableFocusDetails<T, never> = $derived(
26
+ new TableFocusDetails(cell, tableContext)
27
27
  );
28
28
 
29
29
  const enabled: boolean | Promise<boolean> = $derived(
30
30
  cell.column.columnDef.isEnabled(cell.row.original, cell.row.originalIndex)
31
31
  );
32
+
33
+ let validity: Validity = $state(Validity.Valid);
34
+ $effect(() => {
35
+ const validityPromise = focusDetails.validity;
36
+
37
+ validityPromise
38
+ .then((v) => {
39
+ if (!v) {
40
+ validity = Validity.Neutral;
41
+ } else if (isValidityTuple(v)) {
42
+ validity = v.value;
43
+ } else {
44
+ validity = v;
45
+ }
46
+ })
47
+ .catch(devCatch);
48
+ });
32
49
  </script>
33
50
 
34
51
  <!-- svelte-ignore a11y_mouse_events_have_key_events -->
35
52
  <td
53
+ class:info={validity == Validity.Info}
54
+ class:success={validity == Validity.Valid}
55
+ class:warning={validity == Validity.Warning}
56
+ class:error={validity == Validity.Invalid}
36
57
  class="focusable"
37
58
  onmousedown={(e) => {
38
59
  // start focus only on left click
@@ -127,6 +148,16 @@ td {
127
148
  --td-padding-right: 0;
128
149
  }
129
150
 
151
+ td.info {
152
+ background-color: #1f81a0;
153
+ }
154
+ td.warning {
155
+ background-color: #f8eab8;
156
+ }
157
+ td.error {
158
+ background-color: #f9e9e9;
159
+ }
160
+
130
161
  div.slot-wrapper.multifocus {
131
162
  background-color: var(--multifocus-colour, #f4fbfd);
132
163
  }