@lavalogic/scoria 0.5.7 → 0.7.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.
@@ -1,19 +1,24 @@
1
1
  <svelte:options runes />
2
2
 
3
3
  <script lang="ts" module>
4
- import type { Snippet } from 'svelte';
4
+ import { DraggableCard } from '../../index.js';
5
+ import { tick, type Snippet } from 'svelte';
5
6
 
6
7
  export interface Draggable<T> {
7
8
  id: string;
8
- name: string;
9
+ title: string;
10
+ subtitle: string;
9
11
  original: T;
12
+ selected?: boolean;
13
+ toggleSelected?: () => void;
10
14
  }
11
15
 
12
16
  export interface DragMenuHolderProps<T> {
13
- items: Draggable<T>[];
14
- consider: (items: Draggable<T>[]) => void;
15
- finalise: (items: Draggable<T>[]) => void;
16
- snippet: Snippet<[Draggable<T>, number]>;
17
+ items: T[];
18
+ transformToDraggable: (item: T) => Draggable<T>;
19
+ snippet?: Snippet<[Draggable<T>, number]>;
20
+
21
+ onUpdate: (items: T[]) => void;
17
22
 
18
23
  label?: string;
19
24
  flipDurationMS?: number;
@@ -25,15 +30,68 @@
25
30
  import { flip } from 'svelte/animate';
26
31
 
27
32
  const {
28
- items,
29
- consider,
30
- finalise,
31
- snippet,
33
+ items: originalItems,
34
+ onUpdate,
35
+ snippet: customSnippet,
36
+ transformToDraggable,
32
37
  flipDurationMS = 60,
33
38
  label
34
39
  }: DragMenuHolderProps<T> = $props();
40
+
41
+ let items: Draggable<T>[] = $state([]);
42
+
43
+ function consider(newItems: Draggable<T>[]) {
44
+ items = newItems;
45
+ }
46
+ function finalise(newItems: Draggable<T>[]) {
47
+ items = newItems;
48
+ onUpdate(items.map((it) => it.original));
49
+ }
50
+
51
+ $effect.pre(() => {
52
+ void originalItems;
53
+ items = originalItems.map(transformToDraggable);
54
+ });
55
+
56
+ const snippet = $derived(customSnippet ?? draggableWithSelect);
57
+
58
+ function up(item: Draggable<T>, index: number) {
59
+ const before = items.slice(0, index);
60
+ const next = before.pop();
61
+ const [removed, ...after] = items.slice(index);
62
+
63
+ before.push(removed);
64
+ if (next) {
65
+ before.push(next);
66
+ }
67
+ before.push(...after);
68
+ items = before;
69
+ }
70
+
71
+ function down(item: Draggable<T>, index: number) {
72
+ const before = items.slice(0, index);
73
+
74
+ const [removed, previous, ...after] = items.slice(index);
75
+
76
+ if (previous) {
77
+ before.push(previous);
78
+ }
79
+ before.push(removed);
80
+ before.push(...after);
81
+ items = before;
82
+ }
35
83
  </script>
36
84
 
85
+ {#snippet draggableWithSelect<T>(item: Draggable<T>, index: number)}
86
+ <DraggableCard
87
+ title={item.title}
88
+ subtitle={item.subtitle}
89
+ {index}
90
+ selectable
91
+ selected={item.selected}
92
+ />
93
+ {/snippet}
94
+
37
95
  <div class="wrapper">
38
96
  {#if label}
39
97
  <span class="top-label">{label}</span>
@@ -49,14 +107,49 @@
49
107
  finalise(e.detail.items);
50
108
  }}
51
109
  >
110
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
52
111
  {#each items as item, index (item.id)}
53
- <div class="contents" animate:flip={{ duration: flipDurationMS }}>
112
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
113
+ <div
114
+ class="contents"
115
+ onclick={(e) => {
116
+ if (item.toggleSelected) {
117
+ e.stopPropagation();
118
+ item.toggleSelected();
119
+ }
120
+ }}
121
+ animate:flip={{ duration: flipDurationMS }}
122
+ >
54
123
  {@render snippet(item, index)}
55
124
  </div>
56
125
  {/each}
57
126
  </div>
58
127
  </div>
59
128
 
129
+ <!--
130
+ tabindex="0"
131
+ role="button"
132
+ onkeydown={(e) => {
133
+ const prevTarget = e.target;
134
+ console.log(e.key);
135
+ if (e.key == 'ArrowUp') {
136
+ e.stopPropagation();
137
+ up(item, index);
138
+ } else if (e.key == 'ArrowDown') {
139
+ e.stopPropagation();
140
+ down(item, index);
141
+ } else if (e.key == ' ') {
142
+ alert('SPACEBAR');
143
+ }
144
+ tick().then(() => {
145
+ if (prevTarget && 'focus' in prevTarget) {
146
+ (prevTarget as HTMLElement).focus();
147
+ } else {
148
+ console.warn(`prev target is undefined`);
149
+ }
150
+ });
151
+ }} -->
152
+
60
153
  <style>.top-label {
61
154
  position: absolute;
62
155
  left: 0.5rem;
@@ -1,14 +1,17 @@
1
- import type { Snippet } from 'svelte';
1
+ import { type Snippet } from 'svelte';
2
2
  export interface Draggable<T> {
3
3
  id: string;
4
- name: string;
4
+ title: string;
5
+ subtitle: string;
5
6
  original: T;
7
+ selected?: boolean;
8
+ toggleSelected?: () => void;
6
9
  }
7
10
  export interface DragMenuHolderProps<T> {
8
- items: Draggable<T>[];
9
- consider: (items: Draggable<T>[]) => void;
10
- finalise: (items: Draggable<T>[]) => void;
11
- snippet: Snippet<[Draggable<T>, number]>;
11
+ items: T[];
12
+ transformToDraggable: (item: T) => Draggable<T>;
13
+ snippet?: Snippet<[Draggable<T>, number]>;
14
+ onUpdate: (items: T[]) => void;
12
15
  label?: string;
13
16
  flipDurationMS?: number;
14
17
  }
@@ -9,13 +9,11 @@
9
9
 
10
10
  touch?: boolean;
11
11
  selected?: boolean; // default false
12
- disabled?: boolean; // default false
12
+ toggleSelected?: () => void;
13
13
  }
14
14
  </script>
15
15
 
16
16
  <script lang="ts">
17
- import { Size } from '../../Types/Internal/Size.js';
18
-
19
17
  import Checkbox from '../Checkbox.svelte';
20
18
 
21
19
  let {
@@ -25,14 +23,20 @@
25
23
  index,
26
24
  selected = $bindable(false),
27
25
  touch = false,
28
- disabled = false
26
+ toggleSelected
29
27
  }: DraggableCardProps = $props();
30
28
  </script>
31
29
 
32
30
  <div class="card" class:touch>
33
31
  {#if selectable}
34
32
  <div class="limit-size" class:touch>
35
- <Checkbox value={selected} onchange={() => (selected = !selected)} />
33
+ <Checkbox
34
+ value={selected}
35
+ onchange={(e) => {
36
+ e.stopPropagation();
37
+ toggleSelected?.();
38
+ }}
39
+ />
36
40
  </div>
37
41
  {/if}
38
42
  <div class="text" class:touch>
@@ -5,7 +5,7 @@ export interface DraggableCardProps {
5
5
  index: number;
6
6
  touch?: boolean;
7
7
  selected?: boolean;
8
- disabled?: boolean;
8
+ toggleSelected?: () => void;
9
9
  }
10
10
  declare const DraggableCard: import("svelte").Component<DraggableCardProps, {}, "selected">;
11
11
  type DraggableCard = ReturnType<typeof DraggableCard>;
@@ -9,6 +9,7 @@
9
9
  import { ToastContext } from '../../../../../Contexts/ToastContext.svelte.js';
10
10
  import { Validity } from '../../../../../Types/Internal/Validity.js';
11
11
  import type { DateTableCell } from '../../../Types/Columns/DateTableCell.js';
12
+ import { dev } from '$app/environment';
12
13
 
13
14
  export interface TableDatePickerProps<T extends object> {
14
15
  cell: DateTableCell<T>;
@@ -32,7 +33,35 @@
32
33
  id: columnDef.id as string & keyof T
33
34
  });
34
35
 
35
- const editable = $derived(cell.column.columnDef.editable === true);
36
+ const editableAsync = $derived(
37
+ cell.column.columnDef.isEditable(cell.row.original, cell.row.originalIndex)
38
+ );
39
+ let editable = $state(false);
40
+
41
+ let asyncCounter = 0;
42
+ $effect(() => {
43
+ void editableAsync;
44
+ const localCounter = (asyncCounter = asyncCounter + 1);
45
+ (async () => {
46
+ try {
47
+ const isEditable = await editableAsync;
48
+ if (asyncCounter === localCounter) {
49
+ editable = isEditable;
50
+ } else if (dev) {
51
+ console.log('skipping async editable because it is stale');
52
+ }
53
+ } catch (e) {
54
+ if (dev) {
55
+ console.error(e);
56
+ }
57
+ if (asyncCounter === localCounter) {
58
+ editable = false;
59
+ } else if (dev) {
60
+ console.log('skipping async editable because it is stale');
61
+ }
62
+ }
63
+ })();
64
+ });
36
65
  const focusDetails: TableFocusDetails<T> = $derived(
37
66
  new TableFocusDetails(cell, tableContext, toast)
38
67
  );
@@ -7,6 +7,8 @@
7
7
  </script>
8
8
 
9
9
  <script lang="ts" generics="T extends object">
10
+ import { dev } from '$app/environment';
11
+
10
12
  import NumberInput from '../../../../NumberInput.svelte';
11
13
  import { NumberInputDef } from '../../../Types/Columns/Definitions/Accessors/NumberInputDef.svelte.js';
12
14
  import type { TableCell } from '../../../Types/Columns/TableCell.js';
@@ -49,7 +51,34 @@
49
51
  const tableContext = getContext<TableContext<T>>(TableContext.identifier);
50
52
  const { toast } = getContext<ToastContext>(ToastContext.identifier);
51
53
 
52
- const editable = $derived(cell.column.columnDef.editable === true);
54
+ const editableAsync = $derived(
55
+ cell.column.columnDef.isEditable(cell.row.original, cell.row.originalIndex)
56
+ );
57
+ let editable = $state(false);
58
+ let asyncCounter = 0;
59
+ $effect(() => {
60
+ void editableAsync;
61
+ const localCounter = (asyncCounter = asyncCounter + 1);
62
+ (async () => {
63
+ try {
64
+ const isEditable = await editableAsync;
65
+ if (asyncCounter === localCounter) {
66
+ editable = isEditable;
67
+ } else if (dev) {
68
+ console.log('skipping async editable because it is stale');
69
+ }
70
+ } catch (e) {
71
+ if (dev) {
72
+ console.error(e);
73
+ }
74
+ if (asyncCounter === localCounter) {
75
+ editable = false;
76
+ } else if (dev) {
77
+ console.log('skipping async editable because it is stale');
78
+ }
79
+ }
80
+ })();
81
+ });
53
82
 
54
83
  const focusDetails: TableFocusDetails<T> = $derived(
55
84
  new TableFocusDetails(cell, tableContext, toast)
@@ -1,6 +1,7 @@
1
1
  <svelte:options runes />
2
2
 
3
3
  <script lang="ts" module>
4
+ import { dev } from '$app/environment';
4
5
  import QuerySelect from '../../../../QuerySelect.svelte';
5
6
  import type { Column } from '../../../Types/Columns/Column.js';
6
7
  import type { QueryDef } from '../../../Types/Columns/Definitions/Accessors/QueryDef.svelte.js';
@@ -46,7 +47,35 @@
46
47
  const tableContext = getContext<TableContext<T>>(TableContext.identifier);
47
48
  const { toast } = getContext<ToastContext>(ToastContext.identifier);
48
49
 
49
- const editable = $derived(columnDef.editable === true);
50
+ const editableAsync = $derived(
51
+ cell.column.columnDef.isEditable(cell.row.original, cell.row.originalIndex)
52
+ );
53
+ let editable = $state(false);
54
+
55
+ let asyncCounter = 0;
56
+ $effect(() => {
57
+ void editableAsync;
58
+ const localCounter = (asyncCounter = asyncCounter + 1);
59
+ (async () => {
60
+ try {
61
+ const isEditable = await editableAsync;
62
+ if (asyncCounter === localCounter) {
63
+ editable = isEditable;
64
+ } else if (dev) {
65
+ console.log('skipping async editable because it is stale');
66
+ }
67
+ } catch (e) {
68
+ if (dev) {
69
+ console.error(e);
70
+ }
71
+ if (asyncCounter === localCounter) {
72
+ editable = false;
73
+ } else if (dev) {
74
+ console.log('skipping async editable because it is stale');
75
+ }
76
+ }
77
+ })();
78
+ });
50
79
 
51
80
  const focusDetails: TableFocusDetails<T> = $derived(
52
81
  new TableFocusDetails(cell, tableContext, toast)
@@ -1,6 +1,7 @@
1
1
  <svelte:options runes />
2
2
 
3
3
  <script lang="ts" module>
4
+ import { dev } from '$app/environment';
4
5
  import SingleSelect from '../../../../SingleSelect.svelte';
5
6
  import type { Column } from '../../../Types/Columns/Column.js';
6
7
  import type { SelectDef } from '../../../Types/Columns/Definitions/Accessors/SelectDef.svelte.js';
@@ -28,7 +29,7 @@
28
29
 
29
30
  let tdref = $state<HTMLTableCellElement | undefined>();
30
31
 
31
- const selectValue = $derived(cell.getValue() as T |null|undefined);
32
+ const selectValue = $derived(cell.getValue() as T | null | undefined);
32
33
 
33
34
  const visibleValue = $derived(
34
35
  cell.column.columnDef.getDisplayValue!(cell.row.original, cell.row.originalIndex)
@@ -39,7 +40,34 @@
39
40
  const tableContext = getContext<TableContext<T>>(TableContext.identifier);
40
41
  const { toast } = getContext<ToastContext>(ToastContext.identifier);
41
42
 
42
- const editable = $derived(cell.column.columnDef.editable === true);
43
+ const editableAsync = $derived(
44
+ cell.column.columnDef.isEditable(cell.row.original, cell.row.originalIndex)
45
+ );
46
+ let editable = $state(false);
47
+ let asyncCounter = 0;
48
+ $effect(() => {
49
+ void editableAsync;
50
+ const localCounter = (asyncCounter = asyncCounter + 1);
51
+ (async () => {
52
+ try {
53
+ const isEditable = await editableAsync;
54
+ if (asyncCounter === localCounter) {
55
+ editable = isEditable;
56
+ } else if (dev) {
57
+ console.log('skipping async editable because it is stale');
58
+ }
59
+ } catch (e) {
60
+ if (dev) {
61
+ console.error(e);
62
+ }
63
+ if (asyncCounter === localCounter) {
64
+ editable = false;
65
+ } else if (dev) {
66
+ console.log('skipping async editable because it is stale');
67
+ }
68
+ }
69
+ })();
70
+ });
43
71
 
44
72
  const focusDetails: TableFocusDetails<T> = $derived(
45
73
  new TableFocusDetails(cell, tableContext, toast)
@@ -7,6 +7,8 @@
7
7
  </script>
8
8
 
9
9
  <script lang="ts" generics="T extends object">
10
+ import { dev } from '$app/environment';
11
+
10
12
  import type { TableCell } from '../../../Types/Columns/TableCell.js';
11
13
  import { TableContext } from '../../../Types/Context/TableContext.svelte.js';
12
14
  import { TableFocusDetails } from '../../../Types/Focus/TableFocusDetails.svelte.js';
@@ -22,7 +24,35 @@
22
24
  // getNumberColumnDefOrError(cell.column.columnDef)
23
25
  // );
24
26
 
25
- const editable = $derived(cell.column.columnDef.editable === true);
27
+ const editableAsync = $derived(
28
+ cell.column.columnDef.isEditable(cell.row.original, cell.row.originalIndex)
29
+ );
30
+ let editable = $state(false);
31
+
32
+ let asyncCounter = 0;
33
+ $effect(() => {
34
+ void editableAsync;
35
+ const localCounter = (asyncCounter = asyncCounter + 1);
36
+ (async () => {
37
+ try {
38
+ const isEditable = await editableAsync;
39
+ if (asyncCounter === localCounter) {
40
+ editable = isEditable;
41
+ } else if (dev) {
42
+ console.log('skipping async editable because it is stale');
43
+ }
44
+ } catch (e) {
45
+ if (dev) {
46
+ console.error(e);
47
+ }
48
+ if (asyncCounter === localCounter) {
49
+ editable = false;
50
+ } else if (dev) {
51
+ console.log('skipping async editable because it is stale');
52
+ }
53
+ }
54
+ })();
55
+ });
26
56
 
27
57
  const value = $derived(cell.getValue());
28
58
 
@@ -10,6 +10,7 @@ import { BubbleDef } from '../Types/Columns/Definitions/Display/BubbleDef.svelte
10
10
  import { DisplayDef } from '../Types/Columns/Definitions/Display/DisplayDef.svelte.js';
11
11
  import { ProgressBarDef } from '../Types/Columns/Definitions/Display/ProgressBarDef.svelte.js';
12
12
  import { ValidityDef } from '../Types/Columns/Definitions/Display/ValidityDef.svelte.js';
13
+ import { asyncSleep } from '../../../Helpers/Helpers.svelte.js';
13
14
  export class ExampleItemColumnDef {
14
15
  static generateExampleItemColumnDefs(modal) {
15
16
  let defs = $state([
@@ -41,12 +42,12 @@ export class ExampleItemColumnDef {
41
42
  new TextInputDef({
42
43
  header: 'Name',
43
44
  id: 'name',
44
- editable: true
45
+ isEditable: () => true
45
46
  }),
46
47
  new NumberInputDef({
47
48
  header: 'Some Number',
48
49
  id: 'someNumber',
49
- editable: true,
50
+ isEditable: () => true,
50
51
  min: 0,
51
52
  max: 12345
52
53
  }),
@@ -67,25 +68,35 @@ export class ExampleItemColumnDef {
67
68
  new DateInputDef({
68
69
  header: 'Some Date',
69
70
  id: 'someDate',
70
- editable: true,
71
- defaultHidden: true
71
+ isEditable: async (item) => {
72
+ if (item.someDate?.getFullYear() == 2030) {
73
+ await asyncSleep(1000);
74
+ return false;
75
+ }
76
+ else if (item.someDate?.getFullYear() == 2029) {
77
+ await asyncSleep(5000);
78
+ return false;
79
+ }
80
+ return true;
81
+ }
82
+ // defaultHidden: true
72
83
  }),
73
84
  new DateInputDef({
74
85
  header: 'Some Date With Time',
75
86
  id: 'someDateWithTime',
76
- editable: true,
87
+ isEditable: () => true,
77
88
  showTime: true
78
89
  }),
79
90
  new DateInputDef({
80
91
  header: 'Flo Date',
81
92
  id: 'floDate',
82
- editable: true,
93
+ isEditable: () => true,
83
94
  defaultHidden: true
84
95
  }),
85
96
  new DateInputDef({
86
97
  header: 'Flo Date With Time',
87
98
  id: 'floDateWithTime',
88
- editable: true,
99
+ isEditable: () => true,
89
100
  defaultHidden: true,
90
101
  showTime: true
91
102
  }),
@@ -114,7 +125,7 @@ export class ExampleItemColumnDef {
114
125
  ];
115
126
  },
116
127
  getDisplayValue: (item) => item.someSelect,
117
- editable: true
128
+ isEditable: () => true
118
129
  }),
119
130
  new BubbleDef({
120
131
  header: 'Generated Bubble',
@@ -16,7 +16,7 @@ export interface ColumnDefProps<T extends object, FilterFnType = undefined> {
16
16
  defaultHidden?: boolean;
17
17
  minSize?: Pixels;
18
18
  width?: Pixels;
19
- editable?: boolean;
19
+ isEditable?: (item: T, index: number) => boolean | Promise<boolean>;
20
20
  resizable?: boolean;
21
21
  isValid?: ValidationFn<T>;
22
22
  filterFn?: FilterFn<T, FilterFnType> | CustomFilterFn;
@@ -57,7 +57,7 @@ export declare abstract class ColumnDef<T extends object, FilterFnType = undefin
57
57
  get getDisplayValue(): ((item: T, index: number) => string | null | Promise<string | null>) | undefined;
58
58
  set getDisplayValue(v: ((item: T, index: number) => string | null | Promise<string | null>) | undefined);
59
59
  toJSON(): object;
60
- readonly editable: boolean;
60
+ readonly isEditable: (item: T, index: number) => boolean | Promise<boolean>;
61
61
  readonly resizable: boolean;
62
62
  readonly header: string | Snippet;
63
63
  }
@@ -10,7 +10,7 @@ export class ColumnDef {
10
10
  this.accessorFn = $derived(props.accessorFn);
11
11
  this._minSize = $state(props.minSize ?? 48);
12
12
  this._width = $state(props.width ?? props.minSize ?? 48);
13
- this.editable = $derived(props.editable ?? false);
13
+ this.isEditable = $derived(props.isEditable ?? (() => false));
14
14
  this.resizable = $derived(props.resizable ?? true);
15
15
  this.header = $derived(props.header);
16
16
  this._filterValueType = $derived(props.filterValueType);
@@ -84,7 +84,7 @@ export class ColumnDef {
84
84
  toJSON() {
85
85
  return { columnType: this.columnType, id: this.id, header: this.header };
86
86
  }
87
- editable;
87
+ isEditable;
88
88
  resizable;
89
89
  header;
90
90
  }
@@ -0,0 +1,13 @@
1
+ <svelte:options runes />
2
+
3
+ <script lang="ts">
4
+ import { TestContext } from '../../Contexts/TestContext.svelte.js';
5
+ import { getContext } from 'svelte';
6
+
7
+ const testContext = getContext<TestContext>(TestContext.identifier);
8
+ </script>
9
+
10
+ <h1>counter 1: {testContext.value1.value}</h1>
11
+ <p>Ref wrapper 1 is incremented every time you click the button</p>
12
+ <h2>counter 2: {testContext.value2.value}</h2>
13
+ <p>ref wrapper 2 adds ref wrapper 1's value every time ref wrapper 1's value is divisible by 3</p>
@@ -0,0 +1,3 @@
1
+ declare const TestContextConsumer: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type TestContextConsumer = ReturnType<typeof TestContextConsumer>;
3
+ export default TestContextConsumer;
@@ -0,0 +1,11 @@
1
+ import type { RefWrapper } from '../Types/Internal/RefWrapper.js';
2
+ export declare class TestContext {
3
+ static readonly identifier: unique symbol;
4
+ private _value1;
5
+ get value1(): RefWrapper<number>;
6
+ set value1(v: RefWrapper<number>);
7
+ private _value2;
8
+ get value2(): RefWrapper<number>;
9
+ set value2(v: RefWrapper<number>);
10
+ useTestEffect(sourceValue: RefWrapper<number>): RefWrapper<number>;
11
+ }
@@ -0,0 +1,30 @@
1
+ import { refWrapper } from '../Helpers/Helpers.svelte.js';
2
+ import { untrack } from 'svelte';
3
+ export class TestContext {
4
+ static identifier = Symbol();
5
+ _value1 = $state(refWrapper(0));
6
+ get value1() {
7
+ return this._value1;
8
+ }
9
+ set value1(v) {
10
+ this._value1 = v;
11
+ }
12
+ _value2 = $state(this.useTestEffect(this.value1));
13
+ get value2() {
14
+ return this._value2;
15
+ }
16
+ set value2(v) {
17
+ this._value2 = v;
18
+ }
19
+ useTestEffect(sourceValue) {
20
+ const internalState = refWrapper(0);
21
+ $effect(() => {
22
+ if (sourceValue.value % 3 == 0) {
23
+ untrack(() => {
24
+ internalState.value += sourceValue.value;
25
+ });
26
+ }
27
+ });
28
+ return internalState;
29
+ }
30
+ }
@@ -26,4 +26,6 @@ export declare function isErrorResponse(error: unknown): error is IErrorResponse
26
26
  export declare function getErrorMessage(error: unknown, includeUUID?: boolean): string;
27
27
  export declare function isValidEmailAddress(emailAddress: string): RegExpMatchArray | null;
28
28
  export declare function gridItem(element: HTMLElement): (() => void) | undefined;
29
+ export type Milliseconds = number;
30
+ export declare function asyncSleep(delay: Milliseconds): Promise<void>;
29
31
  export {};
@@ -1,4 +1,5 @@
1
1
  import { Sizing } from '../scss/sizing.js';
2
+ import { untrack } from 'svelte';
2
3
  export function autoPluralise(text, quantity = 2, { capitalise = false } = {}) {
3
4
  if (quantity === 1) {
4
5
  return text;
@@ -39,11 +40,11 @@ export function generateUUID() {
39
40
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
40
41
  let r = Math.random() * 16;
41
42
  if (d > 0) {
42
- r = (d + r) % 16 | 0;
43
+ r = ((d + r) % 16) | 0;
43
44
  d = Math.floor(d / 16);
44
45
  }
45
46
  else {
46
- r = (d2 + r) % 16 | 0;
47
+ r = ((d2 + r) % 16) | 0;
47
48
  d2 = Math.floor(d2 / 16);
48
49
  }
49
50
  return (c == 'x' ? r : (r & 0x7) | 0x8).toString(16);
@@ -165,3 +166,6 @@ export function gridItem(element) {
165
166
  observer.observe(firstChild);
166
167
  return () => observer.unobserve(firstChild);
167
168
  }
169
+ export async function asyncSleep(delay) {
170
+ await new Promise((r) => setTimeout(r, delay));
171
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lavalogic/scoria",
3
3
  "description": "Svelte components used for the FloWMS Web Frontend",
4
- "version": "0.5.7",
4
+ "version": "0.7.0",
5
5
  "publishConfig": {
6
6
  "access": "restricted"
7
7
  },
@@ -31,23 +31,23 @@
31
31
  "devDependencies": {
32
32
  "@chromatic-com/storybook": "^4.1.3",
33
33
  "@eslint/compat": "^2.0.0",
34
- "@eslint/js": "^9.39.1",
34
+ "@eslint/js": "^9.39.2",
35
35
  "@playwright/test": "^1.57.0",
36
- "@storybook/addon-a11y": "^10.1.7",
37
- "@storybook/addon-docs": "^10.1.7",
36
+ "@storybook/addon-a11y": "^10.1.10",
37
+ "@storybook/addon-docs": "^10.1.10",
38
38
  "@storybook/addon-svelte-csf": "^5.0.10",
39
- "@storybook/addon-vitest": "^10.1.7",
40
- "@storybook/sveltekit": "^10.1.7",
39
+ "@storybook/addon-vitest": "^10.1.10",
40
+ "@storybook/sveltekit": "^10.1.10",
41
41
  "@sveltejs/adapter-node": "^5.4.0",
42
42
  "@sveltejs/kit": "^2.49.2",
43
43
  "@sveltejs/package": "^2.5.7",
44
44
  "@sveltejs/vite-plugin-svelte": "^6.2.1",
45
45
  "@types/eslint": "^9.6.1",
46
- "@types/node": "^24.10.3",
47
- "@typescript-eslint/eslint-plugin": "^8.49.0",
48
- "@typescript-eslint/parser": "^8.49.0",
49
- "@vitest/browser": "^4.0.15",
50
- "eslint": "^9.39.1",
46
+ "@types/node": "^24.10.4",
47
+ "@typescript-eslint/eslint-plugin": "^8.50.0",
48
+ "@typescript-eslint/parser": "^8.50.0",
49
+ "@vitest/browser": "^4.0.16",
50
+ "eslint": "^9.39.2",
51
51
  "eslint-config-prettier": "^10.1.8",
52
52
  "eslint-plugin-storybook": "10.1.4",
53
53
  "eslint-plugin-svelte": "^3.13.1",
@@ -55,18 +55,18 @@
55
55
  "mdsvex": "^0.12.6",
56
56
  "playwright": "^1.57.0",
57
57
  "prettier": "^3.7.4",
58
- "prettier-plugin-svelte": "^3.4.0",
58
+ "prettier-plugin-svelte": "^3.4.1",
59
59
  "publint": "^0.3.16",
60
- "sass-embedded": "^1.96.0",
61
- "storybook": "^10.1.7",
62
- "svelte": "^5.45.10",
60
+ "sass-embedded": "^1.97.0",
61
+ "storybook": "^10.1.10",
62
+ "svelte": "^5.46.0",
63
63
  "svelte-check": "^4.3.4",
64
64
  "svelte-render-scan": "^1.1.0",
65
65
  "typescript": "^5.9.3",
66
- "typescript-eslint": "^8.49.0",
67
- "vite": "^7.2.7",
66
+ "typescript-eslint": "^8.50.0",
67
+ "vite": "^7.3.0",
68
68
  "vite-plugin-devtools-json": "^1.0.0",
69
- "vitest": "^4.0.15",
69
+ "vitest": "^4.0.16",
70
70
  "vitest-browser-svelte": "^2.0.1"
71
71
  },
72
72
  "keywords": [