@hkdigital/lib-sveltekit 0.0.81 → 0.0.83
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/classes/svelte/audio/AudioLoader.svelte.d.ts +30 -0
- package/dist/classes/svelte/audio/AudioLoader.svelte.js +58 -0
- package/dist/classes/svelte/audio/AudioScene.svelte.d.ts +52 -0
- package/dist/classes/svelte/audio/AudioScene.svelte.js +282 -0
- package/dist/classes/svelte/audio/mocks.d.ts +7 -0
- package/dist/classes/svelte/audio/mocks.js +35 -0
- package/dist/classes/svelte/final-state-machine/FiniteStateMachine.svelte.d.ts +50 -0
- package/dist/classes/svelte/final-state-machine/FiniteStateMachine.svelte.js +133 -0
- package/dist/classes/svelte/final-state-machine/index.d.ts +1 -0
- package/dist/classes/svelte/final-state-machine/index.js +1 -0
- package/dist/classes/svelte/image/ImageLoader.svelte.d.ts +8 -0
- package/dist/classes/svelte/image/ImageLoader.svelte.js +12 -0
- package/dist/classes/svelte/image/ImageVariantsLoader.svelte.d.ts +39 -0
- package/dist/classes/svelte/image/ImageVariantsLoader.svelte.js +151 -0
- package/dist/classes/svelte/image/index.d.ts +2 -0
- package/dist/classes/svelte/image/index.js +4 -0
- package/dist/classes/svelte/image/mocks.d.ts +7 -0
- package/dist/classes/svelte/image/mocks.js +38 -0
- package/dist/classes/svelte/image/typedef.d.ts +16 -0
- package/dist/classes/svelte/image/typedef.js +10 -0
- package/dist/classes/svelte/loading-state-machine/LoadingStateMachine.svelte.d.ts +12 -0
- package/dist/classes/svelte/loading-state-machine/LoadingStateMachine.svelte.js +107 -0
- package/dist/classes/svelte/loading-state-machine/constants.d.ts +12 -0
- package/dist/classes/svelte/loading-state-machine/constants.js +16 -0
- package/dist/classes/svelte/loading-state-machine/index.d.ts +2 -0
- package/dist/classes/svelte/loading-state-machine/index.js +3 -0
- package/dist/classes/svelte/network-loader/NetworkLoader.svelte.d.ts +85 -0
- package/dist/classes/svelte/network-loader/NetworkLoader.svelte.js +295 -0
- package/dist/classes/svelte/network-loader/constants.d.ts +2 -0
- package/dist/classes/svelte/network-loader/constants.js +3 -0
- package/dist/classes/svelte/network-loader/index.d.ts +2 -0
- package/dist/classes/svelte/network-loader/index.js +3 -0
- package/dist/components/image/ResponsiveImage.svelte +103 -0
- package/dist/components/image/ResponsiveImage.svelte.d.ts +15 -0
- package/dist/components/image/index.d.ts +4 -1
- package/dist/components/image/index.js +5 -1
- package/dist/types/imagetools.d.ts +16 -13
- package/dist/types/imagetools.js +8 -0
- package/dist/util/expect/arrays.d.ts +4 -0
- package/dist/util/expect/arrays.js +6 -1
- package/dist/util/http/response.js +1 -0
- package/dist/util/svelte/wait/index.d.ts +15 -0
- package/dist/util/svelte/wait/index.js +38 -0
- package/package.json +3 -1
@@ -0,0 +1,295 @@
|
|
1
|
+
import { CONTENT_TYPE } from '@hkdigital/lib-sveltekit/constants/http/index.js';
|
2
|
+
|
3
|
+
import {
|
4
|
+
LoadingStateMachine,
|
5
|
+
STATE_INITIAL,
|
6
|
+
STATE_LOADING,
|
7
|
+
STATE_UNLOADING,
|
8
|
+
STATE_LOADED,
|
9
|
+
STATE_CANCELLED,
|
10
|
+
STATE_ERROR,
|
11
|
+
LOAD,
|
12
|
+
// CANCEL,
|
13
|
+
ERROR,
|
14
|
+
LOADED,
|
15
|
+
UNLOAD,
|
16
|
+
INITIAL
|
17
|
+
} from '../loading-state-machine/index.js';
|
18
|
+
|
19
|
+
import * as expect from '@hkdigital/lib-sveltekit/util/expect/index.js';
|
20
|
+
|
21
|
+
import {
|
22
|
+
httpGet,
|
23
|
+
loadResponseBuffer
|
24
|
+
} from '@hkdigital/lib-sveltekit/util/http/index.js';
|
25
|
+
|
26
|
+
import { ERROR_NOT_LOADED, ERROR_TRANSFERRED } from './constants.js';
|
27
|
+
|
28
|
+
/**
|
29
|
+
* NetworkLoader instance
|
30
|
+
* - Loads network data from network into an ArrayBuffer
|
31
|
+
* - Loaded data can be transferred to an AudioBufferSourceNode
|
32
|
+
*/
|
33
|
+
export default class NetworkLoader {
|
34
|
+
_state = new LoadingStateMachine();
|
35
|
+
|
36
|
+
// @note this exported state is set by $effect's
|
37
|
+
state = $state(STATE_INITIAL);
|
38
|
+
|
39
|
+
loaded = $derived.by(() => {
|
40
|
+
return this.state === STATE_LOADED;
|
41
|
+
});
|
42
|
+
|
43
|
+
/** @type {string|null} */
|
44
|
+
_url = null;
|
45
|
+
|
46
|
+
/** @type {number} */
|
47
|
+
_bytesLoaded = $state(0);
|
48
|
+
|
49
|
+
/** @type {number} */
|
50
|
+
_size = $state(0);
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Response headers
|
54
|
+
* @type {Headers|null}
|
55
|
+
*/
|
56
|
+
_headers = $state(null);
|
57
|
+
|
58
|
+
/** @type {ArrayBuffer|null} */
|
59
|
+
_buffer = null;
|
60
|
+
|
61
|
+
// Export state property as readonly
|
62
|
+
progress = $derived.by(() => {
|
63
|
+
return {
|
64
|
+
bytesLoaded: this._bytesLoaded,
|
65
|
+
size: this._size,
|
66
|
+
loaded: this.loaded
|
67
|
+
};
|
68
|
+
});
|
69
|
+
|
70
|
+
/** @type {null|(()=>void)} */
|
71
|
+
_abortLoading = null;
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Construct NetworkLoader
|
75
|
+
*
|
76
|
+
* @param {object} _
|
77
|
+
* @param {string} _.url
|
78
|
+
*/
|
79
|
+
constructor({ url }) {
|
80
|
+
expect.absOrRelUrl(url);
|
81
|
+
|
82
|
+
this._url = url;
|
83
|
+
|
84
|
+
const state = this._state;
|
85
|
+
|
86
|
+
$effect(() => {
|
87
|
+
switch (state.current) {
|
88
|
+
case STATE_LOADING:
|
89
|
+
{
|
90
|
+
// console.log('NetworkLoader:loading');
|
91
|
+
this.#load();
|
92
|
+
}
|
93
|
+
break;
|
94
|
+
|
95
|
+
case STATE_UNLOADING:
|
96
|
+
{
|
97
|
+
// console.log('NetworkLoader:unloading');
|
98
|
+
this.#unload();
|
99
|
+
}
|
100
|
+
break;
|
101
|
+
|
102
|
+
case STATE_LOADED:
|
103
|
+
{
|
104
|
+
// console.error(
|
105
|
+
// 'NetworkLoader:loaded',
|
106
|
+
// $state.snapshot({ bytes: this.size })
|
107
|
+
// );
|
108
|
+
|
109
|
+
// Abort function is no longer needed
|
110
|
+
this._abortLoading = null;
|
111
|
+
}
|
112
|
+
break;
|
113
|
+
|
114
|
+
case STATE_CANCELLED:
|
115
|
+
{
|
116
|
+
// console.log('NetworkLoader:cancelled');
|
117
|
+
// TODO
|
118
|
+
}
|
119
|
+
break;
|
120
|
+
|
121
|
+
case STATE_ERROR:
|
122
|
+
{
|
123
|
+
console.log('NetworkLoader:error', state.error);
|
124
|
+
}
|
125
|
+
break;
|
126
|
+
} // end switch
|
127
|
+
|
128
|
+
this.state = state.current;
|
129
|
+
});
|
130
|
+
}
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Start loading all network data
|
134
|
+
*/
|
135
|
+
load() {
|
136
|
+
this._state.send(LOAD);
|
137
|
+
}
|
138
|
+
|
139
|
+
/**
|
140
|
+
* Unoad all network data
|
141
|
+
*/
|
142
|
+
unload() {
|
143
|
+
this._state.send(UNLOAD);
|
144
|
+
}
|
145
|
+
|
146
|
+
/**
|
147
|
+
* Get network data size in bytes
|
148
|
+
* - Info comes from the content length response header
|
149
|
+
*
|
150
|
+
* @returns {number}
|
151
|
+
*/
|
152
|
+
get size() {
|
153
|
+
return this._size;
|
154
|
+
}
|
155
|
+
|
156
|
+
/**
|
157
|
+
* Get content type from response header
|
158
|
+
*
|
159
|
+
* @returns {string|null}
|
160
|
+
*/
|
161
|
+
getContentType() {
|
162
|
+
if (!this._headers) {
|
163
|
+
throw new Error(ERROR_NOT_LOADED);
|
164
|
+
}
|
165
|
+
|
166
|
+
return this._headers.get(CONTENT_TYPE);
|
167
|
+
}
|
168
|
+
|
169
|
+
/**
|
170
|
+
* Get data as array buffer
|
171
|
+
*
|
172
|
+
* @note If the data has been transferred, the data is
|
173
|
+
* no longer available as ArrayBuffer
|
174
|
+
*
|
175
|
+
* @returns {ArrayBuffer}
|
176
|
+
*/
|
177
|
+
getArrayBuffer() {
|
178
|
+
if (!this._buffer) {
|
179
|
+
throw new Error(ERROR_NOT_LOADED);
|
180
|
+
}
|
181
|
+
|
182
|
+
if (this._buffer.detached) {
|
183
|
+
throw new Error(ERROR_TRANSFERRED);
|
184
|
+
}
|
185
|
+
|
186
|
+
return this._buffer;
|
187
|
+
}
|
188
|
+
|
189
|
+
/**
|
190
|
+
* Get data as Uint8Array
|
191
|
+
*
|
192
|
+
* @returns {Uint8Array}
|
193
|
+
*/
|
194
|
+
getUint8Array() {
|
195
|
+
return new Uint8Array(this.getArrayBuffer());
|
196
|
+
}
|
197
|
+
|
198
|
+
/**
|
199
|
+
* Get data as Blob
|
200
|
+
* - The Blob type is set using the response header
|
201
|
+
* content type
|
202
|
+
*
|
203
|
+
* @returns {Blob}
|
204
|
+
*/
|
205
|
+
getBlob() {
|
206
|
+
const type = this.getContentType();
|
207
|
+
|
208
|
+
const options = {};
|
209
|
+
|
210
|
+
if (type) {
|
211
|
+
options.type = type;
|
212
|
+
}
|
213
|
+
|
214
|
+
return new Blob([this.getArrayBuffer()], options);
|
215
|
+
}
|
216
|
+
|
217
|
+
/**
|
218
|
+
* Internal method that initializes the loading process
|
219
|
+
* and transitions to state LOADED when done
|
220
|
+
*/
|
221
|
+
async #load() {
|
222
|
+
try {
|
223
|
+
// console.log('#load', this._url);
|
224
|
+
|
225
|
+
if (this._abortLoading) {
|
226
|
+
// console.log('Abort loading');
|
227
|
+
this._abortLoading();
|
228
|
+
this._abortLoading = null;
|
229
|
+
}
|
230
|
+
|
231
|
+
/** @type {()=>void} */
|
232
|
+
let abortRequest;
|
233
|
+
|
234
|
+
/**
|
235
|
+
* @param {object} _
|
236
|
+
* @param {()=>void} _.abort
|
237
|
+
*/
|
238
|
+
const requestHandler = ({ abort }) => {
|
239
|
+
abortRequest = abort;
|
240
|
+
};
|
241
|
+
|
242
|
+
this._bytesLoaded = 0;
|
243
|
+
this._size = 0;
|
244
|
+
|
245
|
+
// @ts-ignore
|
246
|
+
const response = await httpGet({ url: this._url, requestHandler });
|
247
|
+
|
248
|
+
this._headers = response.headers;
|
249
|
+
|
250
|
+
// console.log('headers', this._headers);
|
251
|
+
// console.log('response', response);
|
252
|
+
|
253
|
+
const { bufferPromise, abort: abortLoadBody } = loadResponseBuffer(
|
254
|
+
response,
|
255
|
+
({ bytesLoaded, size }) => {
|
256
|
+
this._bytesLoaded = bytesLoaded;
|
257
|
+
this._size = size;
|
258
|
+
}
|
259
|
+
);
|
260
|
+
|
261
|
+
this._abortLoading = () => {
|
262
|
+
abortRequest();
|
263
|
+
abortLoadBody();
|
264
|
+
};
|
265
|
+
|
266
|
+
this._buffer = await bufferPromise;
|
267
|
+
|
268
|
+
this._state.send(LOADED);
|
269
|
+
} catch (e) {
|
270
|
+
this._state.send(ERROR, e);
|
271
|
+
}
|
272
|
+
}
|
273
|
+
|
274
|
+
/**
|
275
|
+
* Internal method that initializes the unloading process
|
276
|
+
* and transitions to state INITIAL when done
|
277
|
+
*/
|
278
|
+
async #unload() {
|
279
|
+
try {
|
280
|
+
if (this._abortLoading) {
|
281
|
+
this._abortLoading();
|
282
|
+
this._abortLoading = null;
|
283
|
+
}
|
284
|
+
|
285
|
+
this._bytesLoaded = 0;
|
286
|
+
this._size = 0;
|
287
|
+
this._headers = null;
|
288
|
+
this._buffer = null;
|
289
|
+
|
290
|
+
this._state.send(INITIAL);
|
291
|
+
} catch (e) {
|
292
|
+
this._state.send(ERROR, e);
|
293
|
+
}
|
294
|
+
}
|
295
|
+
} // end class
|
@@ -0,0 +1,103 @@
|
|
1
|
+
<script>
|
2
|
+
/** @typedef {import('../../types/imagetools.js').ImageVariant} ImageVariant */
|
3
|
+
|
4
|
+
import { ImageVariantsLoader } from '../../classes/svelte/image/index.js';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* @type {{
|
8
|
+
* base?: string,
|
9
|
+
* classes?: string
|
10
|
+
* boxBase?: string,
|
11
|
+
* boxClasses?: string
|
12
|
+
* boxAttrs?: { [attr: string]: * },
|
13
|
+
* images: ImageVariant[],
|
14
|
+
* alt?: string
|
15
|
+
* } & { [attr: string]: * }}
|
16
|
+
*/
|
17
|
+
const {
|
18
|
+
base,
|
19
|
+
classes,
|
20
|
+
boxBase,
|
21
|
+
boxClasses,
|
22
|
+
boxAttrs,
|
23
|
+
|
24
|
+
// Functional
|
25
|
+
images,
|
26
|
+
alt = '',
|
27
|
+
|
28
|
+
// Attributes
|
29
|
+
...attrs
|
30
|
+
} = $props();
|
31
|
+
|
32
|
+
let variantsLoader = new ImageVariantsLoader(images);
|
33
|
+
|
34
|
+
let containerWidth = $state(0);
|
35
|
+
|
36
|
+
/** @type {ImageVariant|null} */
|
37
|
+
let imageVariant = $state(null);
|
38
|
+
|
39
|
+
$effect(() => {
|
40
|
+
variantsLoader.updateOptimalImageVariant(containerWidth);
|
41
|
+
});
|
42
|
+
|
43
|
+
// $effect(() => {
|
44
|
+
// console.log('imageVariant', $state.snapshot(imageVariant));
|
45
|
+
// });
|
46
|
+
|
47
|
+
/** @type {string|null} */
|
48
|
+
let imageUrl = $state(null);
|
49
|
+
|
50
|
+
$effect(() => {
|
51
|
+
let image;
|
52
|
+
|
53
|
+
if (variantsLoader.loaded) {
|
54
|
+
// @ts-ignore
|
55
|
+
imageUrl = variantsLoader.getObjectUrl();
|
56
|
+
|
57
|
+
// image = new Image();
|
58
|
+
// image.src = url;
|
59
|
+
|
60
|
+
// image.onload = () => {
|
61
|
+
// console.log('loaded');
|
62
|
+
// imageUrl = url;
|
63
|
+
// };
|
64
|
+
}
|
65
|
+
|
66
|
+
return () => {
|
67
|
+
// if (image) {
|
68
|
+
// image.onload = null;
|
69
|
+
// image = undefined;
|
70
|
+
// }
|
71
|
+
|
72
|
+
if (imageUrl) {
|
73
|
+
URL.revokeObjectURL(imageUrl);
|
74
|
+
imageUrl = null;
|
75
|
+
}
|
76
|
+
};
|
77
|
+
});
|
78
|
+
|
79
|
+
let variant = $derived(variantsLoader.variant);
|
80
|
+
|
81
|
+
// let image = $derived(variantsLoader.image);
|
82
|
+
</script>
|
83
|
+
|
84
|
+
<div
|
85
|
+
bind:clientWidth={containerWidth}
|
86
|
+
data-hk--responsive-image-box
|
87
|
+
class="{boxBase} {boxClasses}"
|
88
|
+
{...boxAttrs}
|
89
|
+
>
|
90
|
+
<!-- <p class="p text-white">variant: {JSON.stringify(variant)}</p> -->
|
91
|
+
|
92
|
+
{#if variant}
|
93
|
+
<img
|
94
|
+
data-responsive-image
|
95
|
+
src={imageUrl ? imageUrl : ''}
|
96
|
+
width={variant.width}
|
97
|
+
height={variant.height}
|
98
|
+
{alt}
|
99
|
+
class="{boxBase} {boxClasses}"
|
100
|
+
{...attrs}
|
101
|
+
/>
|
102
|
+
{/if}
|
103
|
+
</div>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
export default ResponsiveImage;
|
2
|
+
export type ImageVariant = any;
|
3
|
+
declare const ResponsiveImage: import("svelte").Component<{
|
4
|
+
base?: string;
|
5
|
+
classes?: string;
|
6
|
+
boxBase?: string;
|
7
|
+
boxClasses?: string;
|
8
|
+
boxAttrs?: {
|
9
|
+
[attr: string]: any;
|
10
|
+
};
|
11
|
+
images: ImageVariant[];
|
12
|
+
alt?: string;
|
13
|
+
} & {
|
14
|
+
[attr: string]: any;
|
15
|
+
}, {}, "">;
|
@@ -1,68 +1,71 @@
|
|
1
1
|
|
2
|
+
|
3
|
+
// Reference the JSDoc types (doesn't work?)
|
4
|
+
// export type ImageVariant = import('./imagetools.js').ImageVariant;
|
5
|
+
|
2
6
|
interface ImageVariant {
|
3
7
|
src: string;
|
4
8
|
width?: number;
|
5
9
|
height?: number;
|
6
|
-
|
7
10
|
}
|
8
11
|
|
9
12
|
declare module '*?responsive' {
|
10
|
-
const out:
|
13
|
+
const out: ImageVariant[];
|
11
14
|
export default out;
|
12
15
|
}
|
13
16
|
|
14
17
|
declare module '*&responsive' {
|
15
|
-
const out:
|
18
|
+
const out: ImageVariant[];
|
16
19
|
export default out;
|
17
20
|
}
|
18
21
|
|
19
22
|
declare module '*?preset=gradient' {
|
20
|
-
const out:
|
23
|
+
const out: ImageVariant[]|string[]|string;
|
21
24
|
export default out;
|
22
25
|
}
|
23
26
|
|
24
27
|
declare module '*&preset=gradient' {
|
25
|
-
const out:
|
28
|
+
const out: ImageVariant[]|string[]|string;
|
26
29
|
export default out;
|
27
30
|
}
|
28
31
|
|
29
32
|
declare module '*?preset=photo' {
|
30
|
-
const out:
|
33
|
+
const out: ImageVariant[]|string[]|string;
|
31
34
|
export default out;
|
32
35
|
}
|
33
36
|
|
34
37
|
declare module '*&preset=photo' {
|
35
|
-
const out:
|
38
|
+
const out: ImageVariant[]|string[]|string;
|
36
39
|
export default out;
|
37
40
|
}
|
38
41
|
|
39
42
|
declare module '*?preset=drawing' {
|
40
|
-
const out:
|
43
|
+
const out: ImageVariant[]|string[]|string;
|
41
44
|
export default out;
|
42
45
|
}
|
43
46
|
|
44
47
|
declare module '*&preset=drawing' {
|
45
|
-
const out:
|
48
|
+
const out: ImageVariant[]|string[]|string;
|
46
49
|
export default out;
|
47
50
|
}
|
48
51
|
|
49
52
|
declare module '*?preset=savedata' {
|
50
|
-
const out:
|
53
|
+
const out: ImageVariant[]|string[]|string;
|
51
54
|
export default out;
|
52
55
|
}
|
53
56
|
|
54
57
|
declare module '*&preset=savedata' {
|
55
|
-
const out:
|
58
|
+
const out: ImageVariant[]|string[]|string;
|
56
59
|
export default out;
|
57
60
|
}
|
58
61
|
|
59
62
|
declare module '*?preset=blur' {
|
60
|
-
const out:
|
63
|
+
const out: ImageVariant[]|string[]|string;
|
61
64
|
export default out;
|
62
65
|
}
|
63
66
|
|
64
67
|
declare module '*&preset=blur' {
|
65
|
-
const out:
|
68
|
+
const out: ImageVariant[]|string[]|string;
|
66
69
|
export default out;
|
67
70
|
}
|
68
71
|
|
@@ -10,6 +10,10 @@ export function stringArray(value: any): void;
|
|
10
10
|
* @param {any} value
|
11
11
|
*/
|
12
12
|
export function objectArray(value: any): void;
|
13
|
+
/**
|
14
|
+
* Throws an exception if the value is not an Array or the array is empty
|
15
|
+
*/
|
16
|
+
export function notEmptyArray(value: any): void;
|
13
17
|
/**
|
14
18
|
* Throws a validation error if value is not array like
|
15
19
|
* - Checks if the value is an object and has a property `length`
|
@@ -29,7 +29,12 @@ export function objectArray(value) {
|
|
29
29
|
v.parse(v.array(v.looseObject({})), value);
|
30
30
|
}
|
31
31
|
|
32
|
-
|
32
|
+
/**
|
33
|
+
* Throws an exception if the value is not an Array or the array is empty
|
34
|
+
*/
|
35
|
+
export function notEmptyArray(value) {
|
36
|
+
v.parse(v.pipe(v.instance(Array), v.nonEmpty()), value);
|
37
|
+
}
|
33
38
|
|
34
39
|
/**
|
35
40
|
* Throws a validation error if value is not array like
|
@@ -143,6 +143,7 @@ export async function waitForAndCheckResponse(responsePromise, url) {
|
|
143
143
|
*/
|
144
144
|
export function loadResponseBuffer(response, onProgress) {
|
145
145
|
// @note size might be 0
|
146
|
+
// @note might not be send by server in dev mode
|
146
147
|
const size = getResponseSize(response);
|
147
148
|
|
148
149
|
let bytesLoaded = 0;
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/**
|
2
|
+
* Waits for a state condition to be met by running the checkFn
|
3
|
+
* function after each Svelte tick
|
4
|
+
*
|
5
|
+
* @param {() => boolean} checkFn -
|
6
|
+
* Should return true when desired state is reached
|
7
|
+
*
|
8
|
+
* @param {number} [maxWaitMs=1000]
|
9
|
+
*
|
10
|
+
* @returns {Promise<void>} Promise that resolves when the check
|
11
|
+
* function returns true
|
12
|
+
* @throws {Error} if maxAttempts is reached before
|
13
|
+
* predicate returns true
|
14
|
+
*/
|
15
|
+
export function waitForState(checkFn: () => boolean, maxWaitMs?: number): Promise<void>;
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import { tick } from 'svelte';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Waits for a state condition to be met by running the checkFn
|
5
|
+
* function after each Svelte tick
|
6
|
+
*
|
7
|
+
* @param {() => boolean} checkFn -
|
8
|
+
* Should return true when desired state is reached
|
9
|
+
*
|
10
|
+
* @param {number} [maxWaitMs=1000]
|
11
|
+
*
|
12
|
+
* @returns {Promise<void>} Promise that resolves when the check
|
13
|
+
* function returns true
|
14
|
+
* @throws {Error} if maxAttempts is reached before
|
15
|
+
* predicate returns true
|
16
|
+
*/
|
17
|
+
export function waitForState(checkFn, maxWaitMs = 1000) {
|
18
|
+
let startedAt = Date.now();
|
19
|
+
|
20
|
+
return new Promise((resolve, reject) => {
|
21
|
+
async function checkLoop() {
|
22
|
+
if (checkFn()) {
|
23
|
+
resolve();
|
24
|
+
return;
|
25
|
+
}
|
26
|
+
|
27
|
+
if (Date.now() - startedAt >= maxWaitMs) {
|
28
|
+
reject(new Error(`State change timeout`));
|
29
|
+
return;
|
30
|
+
}
|
31
|
+
|
32
|
+
await tick();
|
33
|
+
checkLoop();
|
34
|
+
}
|
35
|
+
|
36
|
+
checkLoop();
|
37
|
+
});
|
38
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@hkdigital/lib-sveltekit",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.83",
|
4
4
|
"author": "Jens Kleinhout, HKdigital (https://hkdigital.nl)",
|
5
5
|
"license": "ISC",
|
6
6
|
"repository": {
|
@@ -61,10 +61,12 @@
|
|
61
61
|
"eslint-config-prettier": "^9.1.0",
|
62
62
|
"eslint-plugin-svelte": "^2.46.1",
|
63
63
|
"globals": "^15.14.0",
|
64
|
+
"jsdom": "^26.0.0",
|
64
65
|
"prettier": "^3.4.2",
|
65
66
|
"prettier-plugin-svelte": "^3.3.2",
|
66
67
|
"prettier-plugin-tailwindcss": "^0.6.9",
|
67
68
|
"publint": "^0.2.12",
|
69
|
+
"standardized-audio-context-mock": "^9.7.15",
|
68
70
|
"svelte": "^5.16.0",
|
69
71
|
"svelte-check": "^4.1.1",
|
70
72
|
"tailwindcss": "^3.4.17",
|