wally-ui 1.14.0 → 1.15.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.
Files changed (23) hide show
  1. package/package.json +1 -1
  2. package/playground/showcase/public/sitemap.xml +15 -0
  3. package/playground/showcase/src/app/app.routes.server.ts +4 -0
  4. package/playground/showcase/src/app/components/ai/ai-composer/ai-composer.html +11 -2
  5. package/playground/showcase/src/app/components/ai/ai-composer/ai-composer.ts +13 -3
  6. package/playground/showcase/src/app/components/audio-waveform/audio-waveform.css +0 -0
  7. package/playground/showcase/src/app/components/audio-waveform/audio-waveform.html +41 -0
  8. package/playground/showcase/src/app/components/audio-waveform/audio-waveform.service.spec.ts +16 -0
  9. package/playground/showcase/src/app/components/audio-waveform/audio-waveform.service.ts +175 -0
  10. package/playground/showcase/src/app/components/audio-waveform/audio-waveform.spec.ts +23 -0
  11. package/playground/showcase/src/app/components/audio-waveform/audio-waveform.ts +64 -0
  12. package/playground/showcase/src/app/components/selection-popover/selection-popover.html +8 -2
  13. package/playground/showcase/src/app/components/selection-popover/selection-popover.ts +76 -12
  14. package/playground/showcase/src/app/pages/documentation/components/audio-waveform-docs/audio-waveform-docs.css +1 -0
  15. package/playground/showcase/src/app/pages/documentation/components/audio-waveform-docs/audio-waveform-docs.examples.ts +146 -0
  16. package/playground/showcase/src/app/pages/documentation/components/audio-waveform-docs/audio-waveform-docs.html +576 -0
  17. package/playground/showcase/src/app/pages/documentation/components/audio-waveform-docs/audio-waveform-docs.ts +124 -0
  18. package/playground/showcase/src/app/pages/documentation/components/components.html +27 -0
  19. package/playground/showcase/src/app/pages/documentation/components/components.routes.ts +4 -0
  20. package/playground/showcase/src/app/pages/documentation/components/selection-popover-docs/selection-popover-docs.examples.ts +4 -0
  21. package/playground/showcase/src/app/pages/documentation/components/selection-popover-docs/selection-popover-docs.html +49 -0
  22. package/playground/showcase/src/app/pages/documentation/components/selection-popover-docs/selection-popover-docs.ts +1 -0
  23. package/playground/showcase/src/app/pages/home/home.html +1 -1
@@ -0,0 +1,124 @@
1
+ import { Component, signal, WritableSignal } from '@angular/core';
2
+
3
+ import { AiPromptService } from '../../../../core/services/ai-prompt.service';
4
+ import { getFormattedCode } from '../../../../core/utils/prism';
5
+
6
+ import { AudioWaveformCodeExamples } from './audio-waveform-docs.examples';
7
+
8
+ import { Breadcrumb, BreadcrumbItem } from '../../../../components/breadcrumb/breadcrumb';
9
+ import { AudioWaveform } from '../../../../components/audio-waveform/audio-waveform';
10
+ import { Button } from '../../../../components/button/button';
11
+
12
+ @Component({
13
+ selector: 'app-audio-waveform-docs',
14
+ imports: [
15
+ Breadcrumb,
16
+ AudioWaveform,
17
+ Button
18
+ ],
19
+ templateUrl: './audio-waveform-docs.html',
20
+ styleUrl: './audio-waveform-docs.css'
21
+ })
22
+ export class AudioWaveformDocs {
23
+ breadcrumbItems: BreadcrumbItem[] = [
24
+ { label: 'Home', url: '/' },
25
+ { label: 'Documentation', url: '/documentation' },
26
+ { label: 'Components', url: '/documentation/components' },
27
+ { label: 'Audio Waveform' }
28
+ ];
29
+
30
+ // Installation & Import
31
+ installationCode = getFormattedCode(AudioWaveformCodeExamples.installation, 'bash');
32
+ importCode = getFormattedCode(AudioWaveformCodeExamples.import, 'typescript');
33
+ componentImportCode = getFormattedCode(AudioWaveformCodeExamples.componentImport, 'typescript');
34
+
35
+ // Basic Usage
36
+ basicUsageCode = getFormattedCode(AudioWaveformCodeExamples.basicUsage, 'html');
37
+ withTimerCode = getFormattedCode(AudioWaveformCodeExamples.withTimer, 'html');
38
+ completeExampleCode = getFormattedCode(AudioWaveformCodeExamples.completeExample, 'html');
39
+ completeExampleTsCode = getFormattedCode(AudioWaveformCodeExamples.completeExampleTs, 'typescript');
40
+
41
+ // Service Integration
42
+ serviceIntegrationCode = getFormattedCode(AudioWaveformCodeExamples.serviceIntegration, 'typescript');
43
+
44
+ // Configuration
45
+ responsiveConfigCode = getFormattedCode(AudioWaveformCodeExamples.responsiveConfig, 'typescript');
46
+ webAudioConceptsCode = getFormattedCode(AudioWaveformCodeExamples.webAudioConcepts, 'typescript');
47
+
48
+ // Future Features
49
+ futureTranscriptionCode = getFormattedCode(AudioWaveformCodeExamples.futureTranscription, 'html');
50
+
51
+ // Properties
52
+ propertyIsStartRecordingCode = getFormattedCode(AudioWaveformCodeExamples.propertyIsStartRecording, 'typescript');
53
+ propertyIsStopRecordingCode = getFormattedCode(AudioWaveformCodeExamples.propertyIsStopRecording, 'typescript');
54
+ propertyShowTimerCode = getFormattedCode(AudioWaveformCodeExamples.propertyShowTimer, 'typescript');
55
+
56
+ // Service Properties
57
+ servicePropertyIsRecordingCode = getFormattedCode(AudioWaveformCodeExamples.servicePropertyIsRecording, 'typescript');
58
+ servicePropertyAudioDataCode = getFormattedCode(AudioWaveformCodeExamples.servicePropertyAudioData, 'typescript');
59
+ servicePropertyRecordedAudioBlobCode = getFormattedCode(AudioWaveformCodeExamples.servicePropertyRecordedAudioBlob, 'typescript');
60
+ servicePropertyRecordedAudioUrlCode = getFormattedCode(AudioWaveformCodeExamples.servicePropertyRecordedAudioUrl, 'typescript');
61
+
62
+ // Methods
63
+ methodDownloadRecordingCode = getFormattedCode(AudioWaveformCodeExamples.methodDownloadRecording, 'typescript');
64
+ methodClearRecordingCode = getFormattedCode(AudioWaveformCodeExamples.methodClearRecording, 'typescript');
65
+
66
+ // Configuration
67
+ configFFTSizeCode = getFormattedCode(AudioWaveformCodeExamples.configFFTSize, 'typescript');
68
+ configBarCountCode = getFormattedCode(AudioWaveformCodeExamples.configBarCount, 'typescript');
69
+ configSmoothingCode = getFormattedCode(AudioWaveformCodeExamples.configSmoothing, 'typescript');
70
+
71
+ // Accessibility & Browser Support
72
+ accessibilityExampleCode = getFormattedCode(AudioWaveformCodeExamples.accessibilityExample, 'html');
73
+ browserSupportCode = getFormattedCode(AudioWaveformCodeExamples.browserSupport, 'typescript');
74
+
75
+ // Interactive demo state
76
+ isRecording: WritableSignal<boolean> = signal<boolean>(false);
77
+ isRecordingWithoutTimer: WritableSignal<boolean> = signal<boolean>(false);
78
+ isRecordingWithTimer: WritableSignal<boolean> = signal<boolean>(false);
79
+ isRecordingWithDownload: WritableSignal<boolean> = signal<boolean>(false);
80
+
81
+ constructor(
82
+ private aiPromptService: AiPromptService
83
+ ) { }
84
+
85
+ startRecording(): void {
86
+ this.isRecording.set(true);
87
+ }
88
+
89
+ stopRecording(): void {
90
+ this.isRecording.set(false);
91
+ }
92
+
93
+ startRecordingWithoutTimer(): void {
94
+ this.isRecordingWithoutTimer.set(true);
95
+ }
96
+
97
+ stopRecordingWithoutTimer(): void {
98
+ this.isRecordingWithoutTimer.set(false);
99
+ }
100
+
101
+ startRecordingWithTimer(): void {
102
+ this.isRecordingWithTimer.set(true);
103
+ }
104
+
105
+ stopRecordingWithTimer(): void {
106
+ this.isRecordingWithTimer.set(false);
107
+ }
108
+
109
+ startRecordingWithDownload(): void {
110
+ this.isRecordingWithDownload.set(true);
111
+ }
112
+
113
+ stopRecordingWithDownload(): void {
114
+ this.isRecordingWithDownload.set(false);
115
+ }
116
+
117
+ get claudeUrl(): string {
118
+ return this.aiPromptService.generateClaudeUrl();
119
+ }
120
+
121
+ get chatGptUrl(): string {
122
+ return this.aiPromptService.generateChatGptUrl();
123
+ }
124
+ }
@@ -40,6 +40,33 @@
40
40
  </h2>
41
41
 
42
42
  <div class="space-y-0 border-2 border-neutral-300 dark:border-neutral-700">
43
+ <!-- Audio Waveform Component -->
44
+ <article class="group border-b-2 border-neutral-300 dark:border-neutral-700 last:border-b-0" role="article"
45
+ aria-labelledby="audio-waveform-heading">
46
+ <a href="/documentation/components/audio-waveform"
47
+ class="block px-4 py-4 sm:py-5 bg-white dark:bg-[#0a0a0a] hover:bg-[#0a0a0a] dark:hover:bg-white transition-all duration-150 cursor-pointer"
48
+ aria-label="Navigate to Audio Waveform component documentation with real-time FFT analysis, responsive bar count, and audio recording">
49
+ <div class="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3">
50
+ <div class="flex-1">
51
+ <div class="flex items-center gap-3 mb-2">
52
+ <h3 id="audio-waveform-heading"
53
+ class="text-base sm:text-lg font-bold text-[#0a0a0a] dark:text-white group-hover:text-white dark:group-hover:text-[#0a0a0a] uppercase tracking-wide transition-colors duration-150">
54
+ <span aria-hidden="true">&gt;_ </span>Audio Waveform
55
+ </h3>
56
+ <span class="text-[10px] font-bold bg-blue-500 text-white px-2 py-1 uppercase tracking-wider"
57
+ aria-label="Status: New Component">
58
+ NEW
59
+ </span>
60
+ </div>
61
+ <p
62
+ class="text-xs sm:text-sm text-neutral-600 dark:text-neutral-400 group-hover:text-neutral-300 dark:group-hover:text-neutral-600 transition-colors duration-150">
63
+ Real-time audio visualizer with Web Audio API, FFT frequency analysis, responsive bar count (mobile/desktop), 60fps animations, and automatic recording to WebM. Audio transcription coming soon.
64
+ </p>
65
+ </div>
66
+ </div>
67
+ </a>
68
+ </article>
69
+
43
70
  <!-- Breadcrumb Component -->
44
71
  <article class="group border-b-2 border-neutral-300 dark:border-neutral-700 last:border-b-0" role="article"
45
72
  aria-labelledby="breadcrumb-heading">
@@ -32,5 +32,9 @@ export const componentsRoutes: Routes = [
32
32
  {
33
33
  path: 'selection-popover',
34
34
  loadComponent: () => import('./selection-popover-docs/selection-popover-docs').then(m => m.SelectionPopoverDocs)
35
+ },
36
+ {
37
+ path: 'audio-waveform',
38
+ loadComponent: () => import('./audio-waveform-docs/audio-waveform-docs').then(m => m.AudioWaveformDocs)
35
39
  }
36
40
  ];
@@ -168,6 +168,10 @@ export const SelectionPopoverCodeExamples = {
168
168
  </div>
169
169
  </wally-selection-popover>`,
170
170
 
171
+ // === MOBILE SUPPORT ===
172
+
173
+ mobileSupport: `<!-- Automatic mobile support -->\n<wally-selection-popover (textSelected)="onSelect($event)">\n <!-- Works seamlessly on mobile devices:\n - Touch event support (touchstart, touchend)\n - Native selection menu prevention\n - Viewport-aware positioning (avoids virtual keyboard)\n - Larger touch targets on mobile (44x44px minimum)\n - Touch scroll prevention on popover\n - Adaptive delays for better touch detection\n -->\n\n <article>\n <p>Try selecting text on mobile - the popover automatically adapts!</p>\n </article>\n</wally-selection-popover>`,
174
+
171
175
  // === ADVANCED ===
172
176
 
173
177
  minSelectionLength: `<!-- Custom minimum selection length -->
@@ -332,6 +332,48 @@
332
332
  </div>
333
333
  </div>
334
334
  </article>
335
+
336
+ <!-- Mobile Support -->
337
+ <article class="mb-8" aria-labelledby="mobile-support-heading">
338
+ <h3 id="mobile-support-heading" class="text-sm sm:text-base font-bold text-[#0a0a0a] dark:text-white mb-3 uppercase">
339
+ <span aria-hidden="true">&gt; </span>Mobile Support
340
+ </h3>
341
+ <p class="text-xs sm:text-sm text-neutral-600 dark:text-neutral-400 mb-3 leading-relaxed">
342
+ The component works seamlessly on mobile devices with automatic optimizations for touch interactions. All features are enabled by default with zero configuration.
343
+ </p>
344
+ <div class="bg-neutral-100 dark:bg-[#121212] border border-neutral-300 dark:border-neutral-700 p-3 mb-4">
345
+ <pre><code [innerHTML]="mobileSupportCode" class="text-xs sm:text-sm text-[#0a0a0a] dark:text-white"></code></pre>
346
+ </div>
347
+ <div class="bg-white dark:bg-[#0f0f0f] border-2 border-neutral-300 dark:border-neutral-800 p-4">
348
+ <h4 class="text-xs font-bold text-[#0a0a0a] dark:text-white mb-3 uppercase">Automatic Mobile Features:</h4>
349
+ <ul class="space-y-2 text-xs sm:text-sm text-neutral-600 dark:text-neutral-400">
350
+ <li class="flex items-start gap-2">
351
+ <span class="text-green-600 dark:text-green-400 mt-0.5">✓</span>
352
+ <span>Touch event support (touchstart, touchend) with adaptive delays for better detection</span>
353
+ </li>
354
+ <li class="flex items-start gap-2">
355
+ <span class="text-green-600 dark:text-green-400 mt-0.5">✓</span>
356
+ <span>Native selection menu prevention - only your custom popover appears</span>
357
+ </li>
358
+ <li class="flex items-start gap-2">
359
+ <span class="text-green-600 dark:text-green-400 mt-0.5">✓</span>
360
+ <span>Viewport-aware positioning that avoids virtual keyboard overlap</span>
361
+ </li>
362
+ <li class="flex items-start gap-2">
363
+ <span class="text-green-600 dark:text-green-400 mt-0.5">✓</span>
364
+ <span>Larger touch targets (44x44px minimum) for better tap accuracy</span>
365
+ </li>
366
+ <li class="flex items-start gap-2">
367
+ <span class="text-green-600 dark:text-green-400 mt-0.5">✓</span>
368
+ <span>Touch scroll prevention on popover to avoid accidental dismissal</span>
369
+ </li>
370
+ <li class="flex items-start gap-2">
371
+ <span class="text-green-600 dark:text-green-400 mt-0.5">✓</span>
372
+ <span>Smart device detection using multiple methods (touch points, window width, touch API)</span>
373
+ </li>
374
+ </ul>
375
+ </div>
376
+ </article>
335
377
  </section>
336
378
 
337
379
  <!-- API Reference -->
@@ -462,6 +504,13 @@
462
504
  Full accessibility with role="dialog" and aria-label="Selection actions"
463
505
  </td>
464
506
  </tr>
507
+ <tr>
508
+ <td class="p-4 font-mono text-blue-600 dark:text-blue-400">Mobile Support</td>
509
+ <td class="p-4 text-gray-700 dark:text-gray-300">
510
+ Automatic touch event support, native menu prevention, larger touch targets, scroll prevention, and
511
+ viewport-aware positioning that avoids virtual keyboard overlap
512
+ </td>
513
+ </tr>
465
514
  </tbody>
466
515
  </table>
467
516
  </div>
@@ -51,6 +51,7 @@ export class SelectionPopoverDocs {
51
51
  keyboardAccessibilityCode = getFormattedCode(SelectionPopoverCodeExamples.keyboardAccessibility, 'html');
52
52
  eventHandlingCode = getFormattedCode(SelectionPopoverCodeExamples.eventHandling, 'html');
53
53
  eventHandlingTsCode = getFormattedCode(SelectionPopoverCodeExamples.eventHandlingTs, 'typescript');
54
+ mobileSupportCode = getFormattedCode(SelectionPopoverCodeExamples.mobileSupport, 'html');
54
55
 
55
56
  // Full Example
56
57
  fullExampleCode = getFormattedCode(SelectionPopoverCodeExamples.fullExample, 'html');
@@ -119,7 +119,7 @@
119
119
  </h4>
120
120
  <p
121
121
  class="text-xs sm:text-sm text-neutral-600 dark:text-neutral-400 group-hover:text-neutral-300 dark:group-hover:text-neutral-600 transition-colors duration-150">
122
- Browse 4+ production-ready Angular components: Button, Input, Carousel, Breadcrumb
122
+ Browse 7+ production-ready Angular components: Button, Input, Carousel, Breadcrumb
123
123
  with TypeScript examples
124
124
  </p>
125
125
  </div>