@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
@@ -16,7 +16,7 @@ export interface IDataRepository<T extends object> {
16
16
  updateSorting?: OnChangeFn<SortingState>;
17
17
  manualSorting?: boolean;
18
18
  sorting: SortingState;
19
- filtering: ColumnFiltersState<unknown>;
19
+ filtering: ColumnFiltersState;
20
20
  filterModes: SvelteMap<string, FilterMode>;
21
21
  setFilterMode: (id: string, mode: FilterMode) => void;
22
22
  filterBy: (id: string, value: unknown) => void;
@@ -9,7 +9,7 @@ export interface ILocalDataRepository<T extends object> extends IDataRepository<
9
9
  setPage: (page: number) => void;
10
10
  nextPage: () => void;
11
11
  prevPage: () => void;
12
- filtering: ColumnFiltersState<unknown>;
12
+ filtering: ColumnFiltersState;
13
13
  filterModes: SvelteMap<string, FilterMode>;
14
14
  setFilterMode: (id: string, mode: FilterMode) => void;
15
15
  filterBy: (id: string, value: unknown) => void;
@@ -30,8 +30,8 @@ export declare class LocalTableDataRepository<T extends object> extends TableDat
30
30
  private _totalRows;
31
31
  get totalRows(): number;
32
32
  private _filtering;
33
- get filtering(): ColumnFiltersState<unknown>;
34
- set filtering(v: ColumnFiltersState<unknown>);
33
+ get filtering(): ColumnFiltersState;
34
+ set filtering(v: ColumnFiltersState);
35
35
  updateSorting: OnChangeFn<SortingState>;
36
36
  readonly paginationType: "Local";
37
37
  readonly setFilterMode: (id: string, mode: FilterMode | undefined) => void;
@@ -9,6 +9,19 @@ export const allowedEmptyFilterModes = new SvelteSet([
9
9
  StringFilterMode.null,
10
10
  NumberDateFilterMode.null,
11
11
  ]);
12
+ const inclusiveFilterModes = new SvelteSet([
13
+ //strings
14
+ StringFilterMode.NotEquals,
15
+ StringFilterMode.NotContains,
16
+ StringFilterMode.NotStartsWith,
17
+ StringFilterMode.NotEndsWith,
18
+ StringFilterMode.NotIn,
19
+ //numbers and dates
20
+ NumberDateFilterMode.NotEquals,
21
+ NumberDateFilterMode.NotIn,
22
+ NumberDateFilterMode.null,
23
+ ]);
24
+ // let totalRedraws = 0;
12
25
  export class LocalTableDataRepository extends TableDataRepository {
13
26
  addEmptyRow;
14
27
  debug;
@@ -98,7 +111,7 @@ export class LocalTableDataRepository extends TableDataRepository {
98
111
  const filterMode = this.filterModes.get(id);
99
112
  const hasValue = (filterMode && allowedEmptyFilterModes.has(filterMode)) ||
100
113
  (value != null &&
101
- ((typeof value === 'object' && Array.isArray(value) && value.length !== 0) ||
114
+ ((Array.isArray(value) && value[0] != null) ||
102
115
  (typeof value === 'string' && value.length !== 0) ||
103
116
  (typeof value !== 'object' && typeof value !== 'string')));
104
117
  if (hasValue) {
@@ -113,7 +126,7 @@ export class LocalTableDataRepository extends TableDataRepository {
113
126
  console.log(`LOCAL REPO: no filter mode found for ${id}, skipping value ${value?.toString()}...`);
114
127
  }
115
128
  else {
116
- console.log(`LOCAL REPO: no value found for id ${id}. Skipping...`);
129
+ console.log(`LOCAL REPO: no filter value found for id ${id}. Skipping...`);
117
130
  }
118
131
  }
119
132
  }
@@ -199,12 +212,13 @@ export class LocalTableDataRepository extends TableDataRepository {
199
212
  values) => {
200
213
  const columnValue = await row.getValue(columnId);
201
214
  const filterType = this.filterModes.get(columnId) ?? NumberDateFilterMode.In;
215
+ const isValueInvalid = columnValue == null || typeof columnValue != 'number' || isNaN(columnValue);
202
216
  if (filterType == NumberDateFilterMode.null) {
203
217
  // TODO test
204
- return columnValue == null || typeof columnValue != 'number' || isNaN(columnValue);
218
+ return isValueInvalid;
205
219
  }
206
- if (!columnValue || typeof columnValue != 'number') {
207
- return false;
220
+ if (isValueInvalid || typeof columnValue != 'number') {
221
+ return inclusiveFilterModes.has(filterType);
208
222
  }
209
223
  switch (filterType) {
210
224
  case NumberDateFilterMode.Equals: {
@@ -317,8 +331,10 @@ export class LocalTableDataRepository extends TableDataRepository {
317
331
  return columnValue == null;
318
332
  }
319
333
  if (!filterValue) {
320
- console.log('empty search value');
321
- return true;
334
+ if (this.debug) {
335
+ console.log(`no value. going by inclusive or not`);
336
+ }
337
+ return inclusiveFilterModes.has(filterType);
322
338
  }
323
339
  filterValue = filterValue.trim().toLocaleLowerCase();
324
340
  const columnValue = (await row.getValue(columnId))
@@ -1,4 +1,4 @@
1
- import { SvelteMap } from 'svelte/reactivity';
1
+ import { SvelteMap, SvelteSet } from 'svelte/reactivity';
2
2
  import type { ColumnFiltersState } from '../Filtering/ColumnFiltersState.js';
3
3
  import type { FilterMode } from '../Filtering/FilterMode.js';
4
4
  import type { FilterType } from '../Filtering/FilterType.js';
@@ -42,7 +42,7 @@ export declare abstract class TableDataRepository<T extends object, out FilterVa
42
42
  get forceRefresh(): () => void;
43
43
  set forceRefresh(v: () => void);
44
44
  readonly registerRefreshMethod: (method: () => void) => void;
45
- protected getValueSet(values: Array<string | number | undefined>): Set<number>;
45
+ protected getValueSet(values: Array<string | number | undefined>): SvelteSet<number>;
46
46
  static getValues(values: Array<string | number | null | undefined>): Array<number>;
47
47
  static getMinMax(values: Array<string | number | null | undefined>): number[] | undefined[];
48
48
  }
@@ -1,5 +1,5 @@
1
1
  import { browser } from '$app/environment';
2
- import { SvelteMap } from 'svelte/reactivity';
2
+ import { SvelteMap, SvelteSet } from 'svelte/reactivity';
3
3
  export class TableDataRepository {
4
4
  tableName;
5
5
  getUserId;
@@ -47,9 +47,7 @@ export class TableDataRepository {
47
47
  this._forceRefresh = method;
48
48
  };
49
49
  getValueSet(values) {
50
- // FIXME
51
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
52
- return new Set(TableDataRepository.getValues(values));
50
+ return new SvelteSet(TableDataRepository.getValues(values));
53
51
  }
54
52
  static getValues(values) {
55
53
  return values
@@ -1,41 +1,23 @@
1
- import type { ToastContext } from '../../../../Contexts/ToastContext.svelte.js';
2
1
  import { Validity } from '../../../../Types/Internal/Validity.js';
2
+ import type { ValidityWrapper } from '../../../../Types/Internal/ValidityWrapper.js';
3
3
  import type { TableCell } from '../Columns/TableCell.js';
4
4
  import type { TableContext } from '../Context/TableContext.svelte.js';
5
+ import type { Primitive } from '../Context/TableInitOptions.js';
5
6
  import type { CellCoordinates } from '../Coordinates/CellCoordinates.js';
6
- export declare class TableFocusDetails<T extends object> {
7
- private toastCallback;
8
- constructor(cell: TableCell<T>, tableContext: TableContext<T, never>, toastCallback: ToastContext['toast']);
9
- private _cell;
10
- get cell(): TableCell<T>;
11
- set cell(v: TableCell<T>);
12
- private _tableContext;
13
- get tableContext(): TableContext<T, never>;
14
- set tableContext(v: TableContext<T, never>);
15
- private _coordinates;
16
- get coordinates(): CellCoordinates;
17
- private _isMultiFocused;
18
- get isMultiFocused(): boolean;
19
- private _hasMultipleFocus;
20
- get hasMultipleFocus(): boolean;
21
- private _isMultiFocusStart;
22
- get isMultiFocusStart(): boolean;
23
- private _topToBottom;
24
- get topToBottom(): boolean;
25
- private _leftToRight;
26
- get leftToRight(): boolean;
27
- private _leftEdge;
28
- get leftEdge(): boolean;
29
- private _topEdge;
30
- get topEdge(): boolean;
31
- private _rightEdge;
32
- get rightEdge(): boolean;
33
- private _bottomEdge;
34
- get bottomEdge(): boolean;
35
- private _validityTuple;
36
- private __validityTuple;
37
- get validityTuple(): Promise<[Validity, string | undefined]>;
38
- set validityTuple(v: Promise<[Validity, string | undefined]>);
39
- private _outline;
40
- get outline(): string;
7
+ export declare class TableFocusDetails<T extends object, RowIdType extends Primitive> {
8
+ private cell;
9
+ private tableContext;
10
+ constructor(cell: TableCell<T>, tableContext: TableContext<T, RowIdType>);
11
+ coordinates: CellCoordinates;
12
+ isMultiFocused: boolean;
13
+ hasMultipleFocus: boolean;
14
+ isMultiFocusStart: boolean;
15
+ topToBottom: boolean;
16
+ leftToRight: boolean;
17
+ readonly leftEdge: boolean;
18
+ readonly topEdge: boolean;
19
+ readonly rightEdge: boolean;
20
+ readonly bottomEdge: boolean;
21
+ readonly validity: Promise<Validity | ValidityWrapper | undefined>;
22
+ readonly outline: string;
41
23
  }
@@ -1,64 +1,63 @@
1
- import { devCatch, isErrorResponse } from '../../../../Helpers/Helpers.svelte.js';
1
+ import { devCatch } from '../../../../Helpers/Helpers.svelte.js';
2
2
  import { Colour } from '../../../../scss/colours.js';
3
3
  import { Validity } from '../../../../Types/Internal/Validity.js';
4
- import { tick } from 'svelte';
5
4
  export class TableFocusDetails {
6
- toastCallback;
7
- constructor(cell, tableContext, toastCallback) {
8
- this.toastCallback = toastCallback;
9
- this._cell = $derived(cell);
10
- this._tableContext = $derived(tableContext);
11
- }
12
- _cell;
13
- get cell() {
14
- return this._cell;
15
- }
16
- set cell(v) {
17
- this._cell = v;
18
- }
19
- _tableContext;
20
- get tableContext() {
21
- return this._tableContext;
22
- }
23
- set tableContext(v) {
24
- this._tableContext = v;
25
- }
26
- _coordinates = $derived({
27
- row: this.cell.row.visibleIndex,
28
- column: this.cell.column.columnDef.index,
29
- id: this.cell.column.columnDef.id,
30
- });
31
- get coordinates() {
32
- return this._coordinates;
33
- }
34
- _isMultiFocused = $derived(this.tableContext.focusedColumnIds.has(this.cell.column.columnDef.id) &&
35
- this.tableContext.focusedRowIndexIds.has(this.cell.row.visibleIndex));
36
- get isMultiFocused() {
37
- return this._isMultiFocused;
38
- }
39
- _hasMultipleFocus = $derived(this.isMultiFocused &&
40
- (this.tableContext.focusedColumnIds.size > 1 || this.tableContext.focusedRowIndexIds.size > 1));
41
- get hasMultipleFocus() {
42
- return this._hasMultipleFocus;
43
- }
44
- _isMultiFocusStart = $derived(this.hasMultipleFocus &&
45
- this.tableContext.focusStart?.id === this.coordinates.id &&
46
- this.tableContext.focusStart.column === this.coordinates.column &&
47
- this.tableContext.focusStart.row === this.coordinates.row);
48
- get isMultiFocusStart() {
49
- return this._isMultiFocusStart;
50
- }
51
- _topToBottom = $derived(this.hasMultipleFocus &&
52
- (this.tableContext.focusStart?.row ?? 0) < (this.tableContext.focusEnd?.row ?? 0));
53
- get topToBottom() {
54
- return this._topToBottom;
55
- }
56
- _leftToRight = $derived(this.hasMultipleFocus &&
57
- (this.tableContext.focusStart?.column ?? 0) < (this.tableContext.focusEnd?.column ?? 0));
58
- get leftToRight() {
59
- return this._leftToRight;
60
- }
61
- _leftEdge = $derived.by(() => {
5
+ cell;
6
+ tableContext;
7
+ constructor(cell, tableContext) {
8
+ this.cell = cell;
9
+ this.tableContext = tableContext;
10
+ this.coordinates = $derived({
11
+ row: this.cell.row.visibleIndex,
12
+ column: this.cell.column.columnDef.index,
13
+ id: this.cell.column.columnDef.id,
14
+ });
15
+ $effect(() => {
16
+ void this.tableContext.focusedColumnIds;
17
+ void this.tableContext.focusedRowIndices;
18
+ (async () => {
19
+ this.isMultiFocused =
20
+ (await this.tableContext.focusedColumnIds).has(this.cell.column.columnDef.id) &&
21
+ (await this.tableContext.focusedRowIndices).has(this.cell.row.visibleIndex);
22
+ })().catch(devCatch);
23
+ });
24
+ $effect(() => {
25
+ void this.isMultiFocused;
26
+ void this.tableContext.focusedColumnIds;
27
+ void this.tableContext.focusedRowIndices;
28
+ (async () => {
29
+ this.hasMultipleFocus =
30
+ (await this.tableContext.focusedColumnIds).size > 1 ||
31
+ (await this.tableContext.focusedRowIndices).size > 1;
32
+ })().catch(devCatch);
33
+ });
34
+ this.isMultiFocusStart = $derived.by(() => {
35
+ void this.hasMultipleFocus;
36
+ return (this.hasMultipleFocus &&
37
+ this.tableContext.focusStart?.id === this.coordinates.id &&
38
+ this.tableContext.focusStart.column === this.coordinates.column &&
39
+ this.tableContext.focusStart.row === this.coordinates.row);
40
+ });
41
+ this.topToBottom = $derived.by(() => {
42
+ void this.hasMultipleFocus;
43
+ return (this.hasMultipleFocus &&
44
+ (this.tableContext.focusStart?.row ?? 0) < (this.tableContext.focusEnd?.row ?? 0));
45
+ });
46
+ this.leftToRight = $derived.by(() => {
47
+ void this.hasMultipleFocus;
48
+ return (this.hasMultipleFocus &&
49
+ (this.tableContext.focusStart?.column ?? 0) < (this.tableContext.focusEnd?.column ?? 0));
50
+ });
51
+ }
52
+ coordinates;
53
+ isMultiFocused = $state(false);
54
+ hasMultipleFocus = $state(false);
55
+ isMultiFocusStart;
56
+ topToBottom;
57
+ leftToRight;
58
+ leftEdge = $derived.by(() => {
59
+ void this.isMultiFocused;
60
+ void this.leftToRight;
62
61
  if (this.isMultiFocused) {
63
62
  if (this.leftToRight) {
64
63
  return this.coordinates.column === this.tableContext.focusStart?.column;
@@ -69,10 +68,9 @@ export class TableFocusDetails {
69
68
  }
70
69
  return false;
71
70
  });
72
- get leftEdge() {
73
- return this._leftEdge;
74
- }
75
- _topEdge = $derived.by(() => {
71
+ topEdge = $derived.by(() => {
72
+ void this.isMultiFocused;
73
+ void this.leftToRight;
76
74
  if (this.isMultiFocused) {
77
75
  if (this.topToBottom) {
78
76
  return this.coordinates.row === this.tableContext.focusStart?.row;
@@ -83,10 +81,9 @@ export class TableFocusDetails {
83
81
  }
84
82
  return false;
85
83
  });
86
- get topEdge() {
87
- return this._topEdge;
88
- }
89
- _rightEdge = $derived.by(() => {
84
+ rightEdge = $derived.by(() => {
85
+ void this.isMultiFocused;
86
+ void this.leftToRight;
90
87
  if (this.isMultiFocused) {
91
88
  if (this.leftToRight) {
92
89
  return this.coordinates.column === this.tableContext.focusEnd?.column;
@@ -97,10 +94,9 @@ export class TableFocusDetails {
97
94
  }
98
95
  return false;
99
96
  });
100
- get rightEdge() {
101
- return this._rightEdge;
102
- }
103
- _bottomEdge = $derived.by(() => {
97
+ bottomEdge = $derived.by(() => {
98
+ void this.isMultiFocused;
99
+ void this.leftToRight;
104
100
  if (this.isMultiFocused) {
105
101
  if (this.topToBottom) {
106
102
  return this.coordinates.row === this.tableContext.focusEnd?.row;
@@ -111,44 +107,18 @@ export class TableFocusDetails {
111
107
  }
112
108
  return false;
113
109
  });
114
- get bottomEdge() {
115
- return this._bottomEdge;
116
- }
117
- _validityTuple = $derived.by(() => {
118
- return this.__validityTuple(this.cell.column.columnDef.isValid, this.cell.row.original);
110
+ validity = $derived.by(async () => {
111
+ void this.tableContext.selectedItems.size;
112
+ void this.cell.column.columnDef.isValid;
113
+ void this.tableContext.selectionContains;
114
+ void this.cell.row.original;
115
+ return this.cell.column.columnDef.isValid?.(this.cell.row.original, this.tableContext.selectionContains(this.cell.row.original));
119
116
  });
120
- async __validityTuple(isValid, original) {
121
- try {
122
- void original;
123
- const result = (await isValid?.(original, await this.tableContext.selectionContains(original))) ??
124
- Validity.Valid;
125
- if (isWrapper(result)) {
126
- return [result.value, result.reason];
127
- }
128
- else {
129
- return [result, undefined];
130
- }
131
- }
132
- catch (e) {
133
- console.warn('validity error:', e);
134
- return tick().then(() => {
135
- if (isErrorResponse(e)) {
136
- this.toastCallback(e);
137
- }
138
- else {
139
- devCatch(e);
140
- }
141
- return [Validity.Valid, undefined];
142
- });
143
- }
144
- }
145
- get validityTuple() {
146
- return this._validityTuple;
147
- }
148
- set validityTuple(v) {
149
- this._validityTuple = v;
150
- }
151
- _outline = $derived.by(() => {
117
+ outline = $derived.by(() => {
118
+ void this.topEdge;
119
+ void this.rightEdge;
120
+ void this.bottomEdge;
121
+ void this.leftEdge;
152
122
  const x = [];
153
123
  if (this.topEdge) {
154
124
  x.push(`inset 0px 2px 0px 0px ${Colour['$brand-primary']}`);
@@ -169,10 +139,4 @@ export class TableFocusDetails {
169
139
  return '';
170
140
  }
171
141
  });
172
- get outline() {
173
- return this._outline;
174
- }
175
- }
176
- function isWrapper(result) {
177
- return typeof result == 'object' && 'value' in result;
178
142
  }
@@ -34,7 +34,7 @@
34
34
  onblur,
35
35
  onfocus,
36
36
  onkeydown,
37
- oninput
37
+ oninput,
38
38
  }: TextInputProps = $props();
39
39
 
40
40
  let isInvalid = $derived(
@@ -62,12 +62,17 @@
62
62
  >{labelTop}{#if optional}<i>&nbsp;- optional</i>{/if}</span
63
63
  >
64
64
  {#if variant === InputVariant.Default}
65
- <span class="border" class:invalid={isInvalid}
65
+ <span
66
+ class="border"
67
+ class:invalid={isInvalid}
66
68
  >{labelTop}{#if optional}<i>&nbsp;- optional</i>{/if}</span
67
69
  >
68
70
  {/if}
69
71
  {/if}
70
- <div class="icon-container" class:for-modal={variant == InputVariant.Modal}>
72
+ <div
73
+ class="icon-container"
74
+ class:for-modal={variant == InputVariant.Modal}
75
+ >
71
76
  {#if leftIcon}
72
77
  <!-- TODO make this identical to right icon -->
73
78
  <Icon
@@ -130,7 +135,9 @@
130
135
  </div>
131
136
  {/if}
132
137
  {#if labelRight}
133
- <span class="right-label" class:for-modal={variant == InputVariant.Modal}>{labelRight}</span
138
+ <span
139
+ class="right-label"
140
+ class:for-modal={variant == InputVariant.Modal}>{labelRight}</span
134
141
  >
135
142
  {/if}
136
143
  </div>
@@ -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 { devCatch, passthrough } from '../../Helpers/Helpers.svelte.js';
5
8
  import { ColourSet } from '../../scss/colours.js';
6
9
  import { InputVariant } from '../../Types/Internal/InputVariant.js';
@@ -44,13 +47,10 @@
44
47
  inclusive = false,
45
48
  explanation,
46
49
  allowOverride = false,
47
- showTime = false
50
+ showTime = false,
48
51
  }: DateModalProps = $props();
49
52
 
50
- // svelte-ignore state_referenced_locally
51
- let valueSnapshot = $state(value);
52
- // svelte-ignore state_referenced_locally
53
- let tempValue = $state(value ?? new Date());
53
+ let tempValue = $derived(value ?? new Date());
54
54
  let overrideValue = $state(new Date());
55
55
  let isBeingEdited = $state(false);
56
56
  let inputRef: HTMLInputElement | undefined = $state();
@@ -62,11 +62,9 @@
62
62
  }
63
63
 
64
64
  $effect(() => {
65
- if (value && value !== valueSnapshot) {
66
- valueSnapshot = value;
67
- tempValue = value;
68
- isBeingEdited = false;
69
- }
65
+ void value;
66
+
67
+ isBeingEdited = false;
70
68
  });
71
69
 
72
70
  $effect(() => {
@@ -167,14 +165,28 @@
167
165
 
168
166
  <div class="inputs">
169
167
  {#if allowOverride && isBeingEdited}
170
- <DatePicker {showTime} {onsubmit} {namedMonths} bind:date={overrideValue} />
168
+ <DatePicker
169
+ {showTime}
170
+ {onsubmit}
171
+ {namedMonths}
172
+ bind:date={overrideValue}
173
+ />
171
174
  {/if}
172
- <DatePicker {showTime} {onsubmit} {namedMonths} bind:date={tempValue} />
175
+ <DatePicker
176
+ {showTime}
177
+ {onsubmit}
178
+ {namedMonths}
179
+ bind:date={tempValue}
180
+ />
173
181
  </div>
174
182
 
175
183
  {#snippet footer()}
176
184
  <div class="modal-footer">
177
- <button onkeydown={passthrough} type="submit" disabled={!isValid}>Confirm</button>
185
+ <button
186
+ onkeydown={passthrough}
187
+ type="submit"
188
+ disabled={!isValid}>Confirm</button
189
+ >
178
190
  <button
179
191
  onkeydown={passthrough}
180
192
  type="button"
@@ -1,10 +1,13 @@
1
1
  import type { CustomFilter } from '../Components/Table/Types/Filtering/CustomFilter.js';
2
2
  import type { InputDate, InputDateWithTime, SQLDate } from '../Types/Internal/Misc.js';
3
3
  import type { RefWrapper } from '../Types/Internal/RefWrapper.js';
4
+ import type { Validity } from '../Types/Internal/Validity.js';
5
+ import type { ValidityWrapper } from '../Types/Internal/ValidityWrapper.js';
6
+ import { SvelteSet } from 'svelte/reactivity';
4
7
  export declare function autoPluralise(text: string, quantity?: number, { capitalise }?: {
5
8
  capitalise?: boolean | undefined;
6
9
  }): string;
7
- export declare const vowels: Set<string>;
10
+ export declare const vowels: SvelteSet<string>;
8
11
  export declare function generateShortUUID<T extends string>(): T;
9
12
  export declare function generateUUID<T extends string>(): T;
10
13
  export declare function refWrapper<T>(initial: T): RefWrapper<T>;
@@ -47,3 +50,4 @@ export declare function devCatch(e: unknown): void;
47
50
  export declare function hasQuery<FilterValueType>(customFilter: CustomFilter<FilterValueType> | undefined): customFilter is CustomFilter<FilterValueType> & Required<Pick<CustomFilter<FilterValueType>, 'query'>>;
48
51
  export declare function isDateTuple(value: unknown): value is [Date | null, Date | null];
49
52
  export declare function isNumberTuple(value: unknown): value is [number | null, number | null];
53
+ export declare function isValidityTuple(v: Validity | ValidityWrapper | undefined): v is ValidityWrapper;
@@ -2,6 +2,7 @@ import { dev } from '$app/environment';
2
2
  import { CustomFilterType } from '../Components/Table/Types/Filtering/CustomFilterType.js';
3
3
  import { Sizing } from '../scss/sizing.js';
4
4
  import { untrack } from 'svelte';
5
+ import { SvelteDate, SvelteSet } from 'svelte/reactivity';
5
6
  export function autoPluralise(text, quantity = 2, { capitalise = false } = {}) {
6
7
  if (quantity === 1) {
7
8
  return text;
@@ -29,16 +30,14 @@ export function autoPluralise(text, quantity = 2, { capitalise = false } = {}) {
29
30
  }
30
31
  }
31
32
  }
32
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
33
- export const vowels = new Set(['a', 'e', 'i', 'o', 'u']);
33
+ export const vowels = new SvelteSet(['a', 'e', 'i', 'o', 'u']);
34
34
  // generic is present to bypass floatAlias type requirements and the like
35
35
  export function generateShortUUID() {
36
36
  return generateUUID().substring(0, 13);
37
37
  }
38
38
  // taken from https://stackoverflow.com/a/8809472/18712055
39
39
  export function generateUUID() {
40
- let // eslint-disable-next-line svelte/prefer-svelte-reactivity
41
- d = new Date().getTime(),
40
+ let d = new SvelteDate().getTime(),
42
41
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
43
42
  d2 = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0;
44
43
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
@@ -67,8 +66,7 @@ export function refWrapper(initial) {
67
66
  }
68
67
  export function SQLFriendly(date) {
69
68
  if (typeof date === 'string') {
70
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
71
- date = new Date(date);
69
+ date = new SvelteDate(date);
72
70
  }
73
71
  return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
74
72
  .getDate()
@@ -77,12 +75,10 @@ export function SQLFriendly(date) {
77
75
  }
78
76
  export function SQLFriendlyWithLocalTime(date, timeDate) {
79
77
  if (typeof date === 'string') {
80
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
81
- date = new Date(date);
78
+ date = new SvelteDate(date);
82
79
  }
83
80
  if (typeof timeDate === 'string') {
84
- // eslint-disable-next-line svelte/prefer-svelte-reactivity
85
- timeDate = new Date(date);
81
+ timeDate = new SvelteDate(date);
86
82
  }
87
83
  return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
88
84
  .getDate()
@@ -269,3 +265,6 @@ export function isNumberTuple(value) {
269
265
  (value[0] === null || typeof value[0] == 'number') &&
270
266
  (value[1] === null || typeof value[1] == 'number'));
271
267
  }
268
+ export function isValidityTuple(v) {
269
+ return v != null && typeof v == 'object';
270
+ }