@angular-helpers/browser-web-apis 21.1.0 → 21.2.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/README.md CHANGED
@@ -23,14 +23,40 @@ Angular services package for a structured and secure access layer over browser W
23
23
  - `MediaDevicesService` - Media device listing and management
24
24
  - `GeolocationService` - Geolocation API access
25
25
  - `NotificationService` - Browser notifications API
26
+ - `MediaRecorderService` - Record audio/video from MediaStream
26
27
 
27
- ### Web APIs
28
+ ### Observer APIs
29
+
30
+ - `IntersectionObserverService` - Detect when elements enter/exit viewport
31
+ - `ResizeObserverService` - Watch for element size changes
32
+
33
+ ### System APIs
34
+
35
+ - `BatteryService` - Monitor battery status and charging state
36
+ - `PageVisibilityService` - Track document visibility state changes
37
+ - `ScreenWakeLockService` - Prevent screen from dimming or locking
38
+ - `ScreenOrientationService` - Read and lock screen orientation
39
+ - `FullscreenService` - Toggle fullscreen mode for elements
40
+ - `VibrationService` - Trigger haptic feedback patterns
41
+ - `SpeechSynthesisService` - Text-to-speech with voice selection
42
+
43
+ ### Network APIs
28
44
 
29
- - `WebWorkerService` - Web Worker management
30
45
  - `WebSocketService` - WebSocket connection handling
46
+ - `ServerSentEventsService` - Server-Sent Events client
47
+ - `BroadcastChannelService` - Inter-tab communication
48
+ - `NetworkInformationService` - Connection info and online status
49
+
50
+ ### Storage & I/O APIs
51
+
31
52
  - `WebStorageService` - LocalStorage and SessionStorage helpers
32
53
  - `WebShareService` - Native Web Share API support
33
54
  - `ClipboardService` - System clipboard access
55
+ - `FileSystemAccessService` - Open/save files via native picker
56
+
57
+ ### Web APIs
58
+
59
+ - `WebWorkerService` - Web Worker management
34
60
 
35
61
  ### Security & Capabilities
36
62
 
@@ -132,6 +158,367 @@ export class LocationComponent {
132
158
  }
133
159
  ```
134
160
 
161
+ ### IntersectionObserverService
162
+
163
+ ```typescript
164
+ import { IntersectionObserverService } from '@angular-helpers/browser-web-apis';
165
+
166
+ export class LazyImageComponent {
167
+ private intersectionService = inject(IntersectionObserverService);
168
+ private elementRef = inject(ElementRef);
169
+
170
+ isVisible = signal(false);
171
+
172
+ ngAfterViewInit() {
173
+ this.intersectionService
174
+ .observeVisibility(this.elementRef.nativeElement, { threshold: 0.5 })
175
+ .subscribe((visible) => this.isVisible.set(visible));
176
+ }
177
+ }
178
+ ```
179
+
180
+ ### ResizeObserverService
181
+
182
+ ```typescript
183
+ import { ResizeObserverService } from '@angular-helpers/browser-web-apis';
184
+
185
+ export class ResponsiveComponent {
186
+ private resizeService = inject(ResizeObserverService);
187
+ private elementRef = inject(ElementRef);
188
+
189
+ elementSize = signal<ElementSize | null>(null);
190
+
191
+ ngAfterViewInit() {
192
+ this.resizeService
193
+ .observeSize(this.elementRef.nativeElement)
194
+ .subscribe((size) => this.elementSize.set(size));
195
+ }
196
+ }
197
+ ```
198
+
199
+ ### PageVisibilityService
200
+
201
+ ```typescript
202
+ import { PageVisibilityService } from '@angular-helpers/browser-web-apis';
203
+
204
+ export class AnalyticsComponent {
205
+ private visibilityService = inject(PageVisibilityService);
206
+
207
+ ngOnInit() {
208
+ this.visibilityService.watch().subscribe((state) => {
209
+ console.log('Page is now:', state);
210
+ });
211
+ }
212
+ }
213
+ ```
214
+
215
+ ### FullscreenService
216
+
217
+ ```typescript
218
+ import { FullscreenService } from '@angular-helpers/browser-web-apis';
219
+
220
+ export class VideoPlayerComponent {
221
+ private fullscreenService = inject(FullscreenService);
222
+
223
+ async toggleFullscreen() {
224
+ await this.fullscreenService.toggle();
225
+ }
226
+ }
227
+ ```
228
+
229
+ ### ScreenWakeLockService
230
+
231
+ ```typescript
232
+ import { ScreenWakeLockService } from '@angular-helpers/browser-web-apis';
233
+
234
+ export class PresentationComponent {
235
+ private wakeLockService = inject(ScreenWakeLockService);
236
+
237
+ async keepScreenOn() {
238
+ await this.wakeLockService.request();
239
+ }
240
+
241
+ async releaseScreen() {
242
+ await this.wakeLockService.release();
243
+ }
244
+ }
245
+ ```
246
+
247
+ ### BroadcastChannelService
248
+
249
+ ```typescript
250
+ import { BroadcastChannelService } from '@angular-helpers/browser-web-apis';
251
+
252
+ export class SyncComponent {
253
+ private broadcastService = inject(BroadcastChannelService);
254
+
255
+ ngOnInit() {
256
+ // Listen for messages from other tabs
257
+ this.broadcastService.open<string>('app-sync').subscribe((msg) => {
258
+ console.log('Received:', msg);
259
+ });
260
+ }
261
+
262
+ sendMessage(data: string) {
263
+ this.broadcastService.post('app-sync', data);
264
+ }
265
+ }
266
+ ```
267
+
268
+ ### ServerSentEventsService
269
+
270
+ ```typescript
271
+ import { ServerSentEventsService } from '@angular-helpers/browser-web-apis';
272
+
273
+ export class LiveFeedComponent {
274
+ private sseService = inject(ServerSentEventsService);
275
+
276
+ connectToEvents() {
277
+ this.sseService.connect('https://api.example.com/events').subscribe({
278
+ next: (message) => console.log('Event:', message),
279
+ error: (err) => console.error('SSE error:', err),
280
+ });
281
+ }
282
+ }
283
+ ```
284
+
285
+ ### VibrationService
286
+
287
+ ```typescript
288
+ import { VibrationService } from '@angular-helpers/browser-web-apis';
289
+
290
+ export class FeedbackComponent {
291
+ private vibrationService = inject(VibrationService);
292
+
293
+ onSuccess() {
294
+ this.vibrationService.success();
295
+ }
296
+
297
+ onError() {
298
+ this.vibrationService.error();
299
+ }
300
+ }
301
+ ```
302
+
303
+ ### SpeechSynthesisService
304
+
305
+ ```typescript
306
+ import { SpeechSynthesisService } from '@angular-helpers/browser-web-apis';
307
+
308
+ export class VoiceComponent {
309
+ private speechService = inject(SpeechSynthesisService);
310
+
311
+ speakText(text: string) {
312
+ this.speechService.speak(text).subscribe((state) => {
313
+ console.log('Speech state:', state);
314
+ });
315
+ }
316
+ }
317
+ ```
318
+
319
+ ### BatteryService
320
+
321
+ ```typescript
322
+ import { BatteryService } from '@angular-helpers/browser-web-apis';
323
+
324
+ export class PowerComponent {
325
+ private batteryService = inject(BatteryService);
326
+
327
+ async ngOnInit() {
328
+ try {
329
+ // Initialize and get initial battery info
330
+ const batteryInfo = await this.batteryService.initialize();
331
+ console.log('Battery level:', batteryInfo.level);
332
+ console.log('Is charging:', batteryInfo.charging);
333
+
334
+ // Watch for battery changes
335
+ this.batteryService.watchBatteryInfo().subscribe((info) => {
336
+ console.log('Battery updated:', info);
337
+ });
338
+ } catch (error) {
339
+ console.error('Battery API not supported:', error);
340
+ }
341
+ }
342
+ }
343
+ ```
344
+
345
+ ### ClipboardService
346
+
347
+ ```typescript
348
+ import { ClipboardService } from '@angular-helpers/browser-web-apis';
349
+
350
+ export class CopyComponent {
351
+ private clipboardService = inject(ClipboardService);
352
+
353
+ async copyToClipboard(text: string) {
354
+ try {
355
+ await this.clipboardService.writeText(text);
356
+ console.log('Copied successfully');
357
+ } catch (error) {
358
+ console.error('Failed to copy:', error);
359
+ }
360
+ }
361
+
362
+ async pasteFromClipboard(): Promise<string> {
363
+ try {
364
+ const text = await this.clipboardService.readText();
365
+ return text;
366
+ } catch (error) {
367
+ console.error('Failed to read clipboard:', error);
368
+ return '';
369
+ }
370
+ }
371
+ }
372
+ ```
373
+
374
+ ### FileSystemAccessService
375
+
376
+ ```typescript
377
+ import { FileSystemAccessService } from '@angular-helpers/browser-web-apis';
378
+
379
+ export class FileManagerComponent {
380
+ private fileService = inject(FileSystemAccessService);
381
+
382
+ async openFiles() {
383
+ try {
384
+ const files = await this.fileService.openFile({
385
+ multiple: true,
386
+ types: [
387
+ {
388
+ description: 'Text files',
389
+ accept: { 'text/plain': ['.txt'] },
390
+ },
391
+ ],
392
+ });
393
+ console.log('Selected files:', files);
394
+ } catch (error) {
395
+ console.error('Failed to open files:', error);
396
+ }
397
+ }
398
+
399
+ async saveContent(content: string) {
400
+ try {
401
+ await this.fileService.saveFile(content, {
402
+ suggestedName: 'document.txt',
403
+ });
404
+ } catch (error) {
405
+ console.error('Failed to save file:', error);
406
+ }
407
+ }
408
+ }
409
+ ```
410
+
411
+ ### MediaRecorderService
412
+
413
+ ```typescript
414
+ import { MediaRecorderService } from '@angular-helpers/browser-web-apis';
415
+
416
+ export class RecorderComponent {
417
+ private recorderService = inject(MediaRecorderService);
418
+ private stream: MediaStream | null = null;
419
+
420
+ async startRecording() {
421
+ try {
422
+ this.stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
423
+ await this.recorderService.start(this.stream, { mimeType: 'video/webm' });
424
+ } catch (error) {
425
+ console.error('Failed to start recording:', error);
426
+ }
427
+ }
428
+
429
+ stopRecording() {
430
+ const result = this.recorderService.stop();
431
+ if (result) {
432
+ console.log('Recording saved, blob URL:', result.url);
433
+ }
434
+ }
435
+ }
436
+ ```
437
+
438
+ ### WebSocketService
439
+
440
+ ```typescript
441
+ import { WebSocketService } from '@angular-helpers/browser-web-apis';
442
+
443
+ export class LiveComponent {
444
+ private wsService = inject(WebSocketService);
445
+
446
+ connect() {
447
+ this.wsService
448
+ .connect({
449
+ url: 'wss://example.com/socket',
450
+ reconnectInterval: 3000,
451
+ maxReconnectAttempts: 5,
452
+ })
453
+ .subscribe((status) => {
454
+ console.log('Connection status:', status);
455
+ });
456
+
457
+ this.wsService.getMessages().subscribe((message) => {
458
+ console.log('Received:', message);
459
+ });
460
+ }
461
+
462
+ sendMessage(data: unknown) {
463
+ this.wsService.send({ type: 'message', data });
464
+ }
465
+ }
466
+ ```
467
+
468
+ ### WebStorageService
469
+
470
+ ```typescript
471
+ import { WebStorageService } from '@angular-helpers/browser-web-apis';
472
+
473
+ export class SettingsComponent {
474
+ private storageService = inject(WebStorageService);
475
+
476
+ saveSetting(key: string, value: unknown) {
477
+ this.storageService.setLocalStorage(key, value);
478
+ }
479
+
480
+ getSetting<T>(key: string): T | null {
481
+ return this.storageService.getLocalStorage<T>(key);
482
+ }
483
+
484
+ watchSetting<T>(key: string) {
485
+ return this.storageService.watchLocalStorage<T>(key).subscribe((value) => {
486
+ console.log('Setting changed:', value);
487
+ });
488
+ }
489
+ }
490
+ ```
491
+
492
+ ### WebWorkerService
493
+
494
+ ```typescript
495
+ import { WebWorkerService } from '@angular-helpers/browser-web-apis';
496
+
497
+ export class WorkerComponent {
498
+ private workerService = inject(WebWorkerService);
499
+
500
+ async createWorker() {
501
+ this.workerService
502
+ .createWorker('calc-worker', '/assets/workers/calc.worker.js')
503
+ .subscribe((status) => {
504
+ console.log('Worker status:', status);
505
+ });
506
+
507
+ this.workerService.getMessages('calc-worker').subscribe((message) => {
508
+ console.log('Worker response:', message);
509
+ });
510
+ }
511
+
512
+ sendTask(data: unknown) {
513
+ this.workerService.postMessage('calc-worker', {
514
+ id: 'task-1',
515
+ type: 'CALCULATE',
516
+ data,
517
+ });
518
+ }
519
+ }
520
+ ```
521
+
135
522
  ## Browser Support
136
523
 
137
524
  The services automatically validate browser support and unsupported-path handling: