@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.
- package/dist/Components/DragMenu/DragMenuHolder.svelte +104 -11
- package/dist/Components/DragMenu/DragMenuHolder.svelte.d.ts +9 -6
- package/dist/Components/DragMenu/DraggableCard.svelte +9 -5
- package/dist/Components/DragMenu/DraggableCard.svelte.d.ts +1 -1
- package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +30 -1
- package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +30 -1
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +30 -1
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +30 -2
- package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +31 -1
- package/dist/Components/Table/ColumnDefinitions/ExampleItemColumnDef.svelte.js +19 -8
- package/dist/Components/Table/Types/Columns/Definitions/ColumnDef.svelte.d.ts +2 -2
- package/dist/Components/Table/Types/Columns/Definitions/ColumnDef.svelte.js +2 -2
- package/dist/Components/Test/TestContextConsumer.svelte +13 -0
- package/dist/Components/Test/TestContextConsumer.svelte.d.ts +3 -0
- package/dist/Contexts/TestContext.svelte.d.ts +11 -0
- package/dist/Contexts/TestContext.svelte.js +30 -0
- package/dist/Helpers/Helpers.svelte.d.ts +2 -0
- package/dist/Helpers/Helpers.svelte.js +6 -2
- package/package.json +18 -18
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
<svelte:options runes />
|
|
2
2
|
|
|
3
3
|
<script lang="ts" module>
|
|
4
|
-
import
|
|
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
|
-
|
|
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:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
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
|
|
1
|
+
import { type Snippet } from 'svelte';
|
|
2
2
|
export interface Draggable<T> {
|
|
3
3
|
id: string;
|
|
4
|
-
|
|
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:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
45
|
+
isEditable: () => true
|
|
45
46
|
}),
|
|
46
47
|
new NumberInputDef({
|
|
47
48
|
header: 'Some Number',
|
|
48
49
|
id: 'someNumber',
|
|
49
|
-
|
|
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
|
-
|
|
71
|
-
|
|
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
|
-
|
|
87
|
+
isEditable: () => true,
|
|
77
88
|
showTime: true
|
|
78
89
|
}),
|
|
79
90
|
new DateInputDef({
|
|
80
91
|
header: 'Flo Date',
|
|
81
92
|
id: 'floDate',
|
|
82
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
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,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.
|
|
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.
|
|
34
|
+
"@eslint/js": "^9.39.2",
|
|
35
35
|
"@playwright/test": "^1.57.0",
|
|
36
|
-
"@storybook/addon-a11y": "^10.1.
|
|
37
|
-
"@storybook/addon-docs": "^10.1.
|
|
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.
|
|
40
|
-
"@storybook/sveltekit": "^10.1.
|
|
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.
|
|
47
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
48
|
-
"@typescript-eslint/parser": "^8.
|
|
49
|
-
"@vitest/browser": "^4.0.
|
|
50
|
-
"eslint": "^9.39.
|
|
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.
|
|
58
|
+
"prettier-plugin-svelte": "^3.4.1",
|
|
59
59
|
"publint": "^0.3.16",
|
|
60
|
-
"sass-embedded": "^1.
|
|
61
|
-
"storybook": "^10.1.
|
|
62
|
-
"svelte": "^5.
|
|
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.
|
|
67
|
-
"vite": "^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.
|
|
69
|
+
"vitest": "^4.0.16",
|
|
70
70
|
"vitest-browser-svelte": "^2.0.1"
|
|
71
71
|
},
|
|
72
72
|
"keywords": [
|