@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.es.md +418 -2
- package/README.md +389 -2
- package/fesm2022/angular-helpers-browser-web-apis.mjs +1104 -3
- package/package.json +1 -1
- package/types/angular-helpers-browser-web-apis.d.ts +400 -6
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
|
-
###
|
|
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:
|