@hkdigital/lib-sveltekit 0.1.65 → 0.1.67

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.
@@ -11,6 +11,8 @@
11
11
  export default class AudioScene {
12
12
  state: string;
13
13
  loaded: boolean;
14
+ muted: boolean;
15
+ targetGain: number;
14
16
  destroy(): void;
15
17
  /**
16
18
  * Add in-memory audio source
@@ -44,6 +46,20 @@ export default class AudioScene {
44
46
  * @returns {Promise<AudioBufferSourceNode>}
45
47
  */
46
48
  getSourceNode(label: string): Promise<AudioBufferSourceNode>;
49
+ /**
50
+ * Set target gain
51
+ *
52
+ * @param {number} value
53
+ */
54
+ setTargetGain(value: number): void;
55
+ /**
56
+ * Get the scene gain
57
+ *
58
+ * @returns {number} value
59
+ */
60
+ getTargetGain(): number;
61
+ mute(): void;
62
+ unmute(): void;
47
63
  #private;
48
64
  }
49
65
  /**
@@ -41,9 +41,20 @@ export default class AudioScene {
41
41
  return this.state === STATE_LOADED;
42
42
  });
43
43
 
44
+ #targetGain = $state(1);
45
+
46
+ #unmutedTargetGain = 1;
47
+
48
+ muted = $derived( this.#targetGain === 0 );
49
+
50
+ targetGain = $derived( this.#targetGain );
51
+
44
52
  /** @type {AudioContext|null} */
45
53
  #audioContext = null;
46
54
 
55
+ /** {GainNode} */
56
+ #targetGainNode = null;
57
+
47
58
  /** @type {MemorySource[]} */
48
59
  #memorySources = $state([]);
49
60
 
@@ -220,7 +231,8 @@ export default class AudioScene {
220
231
  );
221
232
 
222
233
  // @ts-ignore
223
- sourceNode.connect(this.#getAudioContext().destination);
234
+ sourceNode.connect(this.#getGainNode());
235
+ // sourceNode.connect(this.#getAudioContext().destination);
224
236
 
225
237
  // Clean up
226
238
  sourceNode.onended = () => {
@@ -231,6 +243,62 @@ export default class AudioScene {
231
243
  return sourceNode;
232
244
  }
233
245
 
246
+ /**
247
+ * Set target gain
248
+ *
249
+ * @param {number} value
250
+ */
251
+ setTargetGain( value ) {
252
+ this.#targetGain = value;
253
+
254
+ // Set immediate
255
+ this.#getGainNode().gain.value = value;
256
+ }
257
+
258
+ /**
259
+ * Get the scene gain
260
+ *
261
+ * @returns {number} value
262
+ */
263
+ getTargetGain()
264
+ {
265
+ return this.#targetGain;
266
+ }
267
+
268
+ mute() {
269
+ if( this.muted )
270
+ {
271
+ return;
272
+ }
273
+
274
+ this.#unmutedTargetGain = this.#targetGain;
275
+ this.setTargetGain(0);
276
+ }
277
+
278
+ unmute() {
279
+ if( !this.muted )
280
+ {
281
+ return;
282
+ }
283
+
284
+ this.setTargetGain(this.#unmutedTargetGain);
285
+ }
286
+
287
+
288
+ #getGainNode()
289
+ {
290
+ if( !this.#targetGainNode )
291
+ {
292
+ const audioContext = this.#getAudioContext();
293
+
294
+ this.#targetGainNode = audioContext.createGain();
295
+ this.#targetGainNode.connect(audioContext.destination);
296
+ this.setTargetGain(this.#targetGain);
297
+ }
298
+
299
+ return this.#targetGainNode;
300
+ }
301
+
234
302
  #getAudioContext()
235
303
  {
236
304
  if( !this.#audioContext )
@@ -257,39 +325,4 @@ export default class AudioScene {
257
325
 
258
326
  throw new Error(`Source [${label}] has not been defined`);
259
327
  }
260
-
261
- // connect
262
- // play
263
-
264
- // source.connect(audioContext.destination);
265
- // source.loop = true;
266
- // source.start();
267
-
268
- // /**
269
- // * Get the source identified by the specified label
270
- // *
271
- // * @param {string} label
272
- // */
273
- // async getBufferSourceNode(label) {
274
- // // expect.notEmptyString( label );
275
-
276
- // for (const source of this.#memorySources) {
277
- // if (label === source.label) {
278
- // if (!source.bufferSourceNode) {
279
- // source.bufferSourceNode =
280
- // await source.AudioLoader.transferToBufferSource(this.#audioContext);
281
- // }
282
-
283
- // return source.bufferSourceNode;
284
- // }
285
- // }
286
- // }
287
-
288
- // async connectSourceToDestination(label) {
289
- // const source = await this.getBufferSourceNode(label);
290
-
291
- // if (source) {
292
- // source.connect(this.#audioContext.destination);
293
- // }
294
- // }
295
328
  }
@@ -27,6 +27,7 @@
27
27
  * legendBase?: string,
28
28
  * legendClasses?: string,
29
29
  * iconClasses?: string,
30
+ * initialValue?: string,
30
31
  * value?: string,
31
32
  * type?: 'text' | 'url' | 'email' | 'number',
32
33
  * pattern?: string,
@@ -43,7 +44,7 @@
43
44
  * } & { [attr: string]: any }}
44
45
  */
45
46
  let {
46
- initialValue,
47
+ initialValue = '',
47
48
  value = $bindable(''),
48
49
 
49
50
  isValid = $bindable(true),
@@ -91,7 +92,6 @@
91
92
 
92
93
  let inputRef = $state();
93
94
  let validationMessage = $state('');
94
- // let initialValue = $state('');
95
95
 
96
96
  $effect(() => {
97
97
  if (!inputRef) return;
@@ -10,6 +10,7 @@ type TextInput = {
10
10
  legendBase?: string;
11
11
  legendClasses?: string;
12
12
  iconClasses?: string;
13
+ initialValue?: string;
13
14
  value?: string;
14
15
  type?: "number" | "url" | "text" | "email";
15
16
  pattern?: string;
@@ -36,6 +37,7 @@ declare const TextInput: import("svelte").Component<{
36
37
  legendBase?: string;
37
38
  legendClasses?: string;
38
39
  iconClasses?: string;
40
+ initialValue?: string;
39
41
  value?: string;
40
42
  type?: "text" | "url" | "email" | "number";
41
43
  pattern?: string;
@@ -6,12 +6,13 @@
6
6
  getGameWidthOnPortrait
7
7
  } from './gamebox.util.js';
8
8
 
9
- import { enableContainerScaling } from '../../util/design-system/index.js';
9
+ //import { enableContainerScaling } from '../../util/design-system/index.js';
10
+ import { enableContainerScaling } from '@hkdigital/lib-sveltekit/util/design-system/index.js';
10
11
 
11
12
  /**
12
13
  * @typedef {{
13
14
  * isMobile:boolean,
14
- * device:string,
15
+ * os:'Android'|'iOS',
15
16
  * isFullscreen:boolean,
16
17
  * isDevMode:boolean,
17
18
  * requestDevmode:function,
@@ -98,12 +99,6 @@
98
99
  let gameWidth = $state();
99
100
  let gameHeight = $state();
100
101
 
101
- let isAppleMobile = getIsAppleMobile();
102
-
103
- let isPwa = $state(false);
104
-
105
- let device = $state();
106
-
107
102
  let iosWindowWidth = $state();
108
103
  let iosWindowHeight = $state();
109
104
 
@@ -197,6 +192,12 @@
197
192
 
198
193
  let show = $state(false);
199
194
 
195
+ const isAppleMobile = /iPhone|iPod/.test(navigator.userAgent);
196
+
197
+ let isPwa = $state(false);
198
+
199
+ let os = $state();
200
+
200
201
  let isMobile = $state(false);
201
202
 
202
203
  let isDevMode = $state(false);
@@ -211,7 +212,7 @@
211
212
 
212
213
  isMobile = getIsMobile();
213
214
 
214
- device = whatDevice();
215
+ os = getOS();
215
216
 
216
217
  // Run before show
217
218
  isFullscreen = !!document.fullscreenElement;
@@ -291,13 +292,9 @@
291
292
  };
292
293
  });
293
294
 
294
- function getIsAppleMobile() {
295
- return /iPhone|iPod/.test(navigator.userAgent);
296
- }
297
-
298
- function whatDevice() {
295
+ function getOS() {
299
296
  if (isAppleMobile) {
300
- return 'IOS';
297
+ return 'iOS';
301
298
  } else if (/Android/.test(navigator.userAgent)) {
302
299
  return 'Android';
303
300
  }
@@ -430,7 +427,7 @@
430
427
  {#if isFullscreen && !isDevMode}
431
428
  {@render snippetLandscape({
432
429
  isMobile,
433
- device,
430
+ os,
434
431
  isFullscreen,
435
432
  isDevMode,
436
433
  requestDevmode,
@@ -442,7 +439,7 @@
442
439
  <!-- Require fullscreen (on landscape) -->
443
440
  {@render snippetRequireFullscreen({
444
441
  isMobile,
445
- device,
442
+ os,
446
443
  isFullscreen,
447
444
  isDevMode,
448
445
  requestDevmode,
@@ -454,7 +451,7 @@
454
451
  <!-- Require install on home screen on mobile -->
455
452
  {@render snippetInstallOnHomeScreen({
456
453
  isMobile,
457
- device,
454
+ os,
458
455
  isFullscreen,
459
456
  isDevMode,
460
457
  requestDevmode,
@@ -465,7 +462,7 @@
465
462
  {:else}
466
463
  {@render snippetLandscape({
467
464
  isMobile,
468
- device,
465
+ os,
469
466
  isFullscreen,
470
467
  isDevMode,
471
468
  requestDevmode,
@@ -479,7 +476,7 @@
479
476
  <!-- *we do not try install home app -->
480
477
  {@render snippetLandscape({
481
478
  isMobile,
482
- device,
479
+ os,
483
480
  isFullscreen,
484
481
  isDevMode,
485
482
  requestDevmode,
@@ -495,7 +492,7 @@
495
492
  {#if isFullscreen && !isDevMode}
496
493
  {@render snippetPortrait({
497
494
  isMobile,
498
- device,
495
+ os,
499
496
  isFullscreen,
500
497
  isDevMode,
501
498
  requestDevmode,
@@ -507,7 +504,7 @@
507
504
  <!-- Require fullscreen (on landscape) -->
508
505
  {@render snippetRequireFullscreen({
509
506
  isMobile,
510
- device,
507
+ os,
511
508
  isFullscreen,
512
509
  isDevMode,
513
510
  requestDevmode,
@@ -519,7 +516,7 @@
519
516
  <!-- Require install on home screen on mobile -->
520
517
  {@render snippetInstallOnHomeScreen({
521
518
  isMobile,
522
- device,
519
+ os,
523
520
  isFullscreen,
524
521
  isDevMode,
525
522
  requestDevmode,
@@ -530,7 +527,7 @@
530
527
  {:else}
531
528
  {@render snippetPortrait({
532
529
  isMobile,
533
- device,
530
+ os,
534
531
  isFullscreen,
535
532
  isDevMode,
536
533
  requestDevmode,
@@ -544,7 +541,7 @@
544
541
  <!-- *we do not try install home app -->
545
542
  {@render snippetPortrait({
546
543
  isMobile,
547
- device,
544
+ os,
548
545
  isFullscreen,
549
546
  isDevMode,
550
547
  requestDevmode,
@@ -89,7 +89,7 @@ declare const GameBox: import("svelte").Component<{
89
89
  };
90
90
  snippetLandscape?: import("svelte").Snippet<[{
91
91
  isMobile: boolean;
92
- device: string;
92
+ os: "Android" | "iOS";
93
93
  isFullscreen: boolean;
94
94
  isDevMode: boolean;
95
95
  requestDevmode: Function;
@@ -99,7 +99,7 @@ declare const GameBox: import("svelte").Component<{
99
99
  }]>;
100
100
  snippetPortrait?: import("svelte").Snippet<[{
101
101
  isMobile: boolean;
102
- device: string;
102
+ os: "Android" | "iOS";
103
103
  isFullscreen: boolean;
104
104
  isDevMode: boolean;
105
105
  requestDevmode: Function;
@@ -109,7 +109,7 @@ declare const GameBox: import("svelte").Component<{
109
109
  }]>;
110
110
  snippetRequireFullscreen?: import("svelte").Snippet<[{
111
111
  isMobile: boolean;
112
- device: string;
112
+ os: "Android" | "iOS";
113
113
  isFullscreen: boolean;
114
114
  isDevMode: boolean;
115
115
  requestDevmode: Function;
@@ -119,7 +119,7 @@ declare const GameBox: import("svelte").Component<{
119
119
  }]>;
120
120
  snippetInstallOnHomeScreen?: import("svelte").Snippet<[{
121
121
  isMobile: boolean;
122
- device: string;
122
+ os: "Android" | "iOS";
123
123
  isFullscreen: boolean;
124
124
  isDevMode: boolean;
125
125
  requestDevmode: Function;
@@ -130,7 +130,7 @@ declare const GameBox: import("svelte").Component<{
130
130
  }, {}, "">;
131
131
  type SnippetParams = {
132
132
  isMobile: boolean;
133
- device: string;
133
+ os: "Android" | "iOS";
134
134
  isFullscreen: boolean;
135
135
  isDevMode: boolean;
136
136
  requestDevmode: Function;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hkdigital/lib-sveltekit",
3
- "version": "0.1.65",
3
+ "version": "0.1.67",
4
4
  "author": {
5
5
  "name": "HKdigital",
6
6
  "url": "https://hkdigital.nl"
@@ -74,6 +74,8 @@
74
74
  "@sveltejs/package": "2.3.7",
75
75
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
76
76
  "@tailwindcss/typography": "^0.5.16",
77
+ "@testing-library/svelte": "^5.2.7",
78
+ "@testing-library/user-event": "^14.6.1",
77
79
  "@types/eslint": "^9.6.1",
78
80
  "autoprefixer": "^10.4.20",
79
81
  "eslint": "^9.21.0",