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.
- package/package.json +1 -1
- package/playground/showcase/public/sitemap.xml +15 -0
- package/playground/showcase/src/app/app.routes.server.ts +4 -0
- package/playground/showcase/src/app/components/ai/ai-composer/ai-composer.html +11 -2
- package/playground/showcase/src/app/components/ai/ai-composer/ai-composer.ts +13 -3
- package/playground/showcase/src/app/components/audio-waveform/audio-waveform.css +0 -0
- package/playground/showcase/src/app/components/audio-waveform/audio-waveform.html +41 -0
- package/playground/showcase/src/app/components/audio-waveform/audio-waveform.service.spec.ts +16 -0
- package/playground/showcase/src/app/components/audio-waveform/audio-waveform.service.ts +175 -0
- package/playground/showcase/src/app/components/audio-waveform/audio-waveform.spec.ts +23 -0
- package/playground/showcase/src/app/components/audio-waveform/audio-waveform.ts +64 -0
- package/playground/showcase/src/app/components/selection-popover/selection-popover.html +8 -2
- package/playground/showcase/src/app/components/selection-popover/selection-popover.ts +76 -12
- package/playground/showcase/src/app/pages/documentation/components/audio-waveform-docs/audio-waveform-docs.css +1 -0
- package/playground/showcase/src/app/pages/documentation/components/audio-waveform-docs/audio-waveform-docs.examples.ts +146 -0
- package/playground/showcase/src/app/pages/documentation/components/audio-waveform-docs/audio-waveform-docs.html +576 -0
- package/playground/showcase/src/app/pages/documentation/components/audio-waveform-docs/audio-waveform-docs.ts +124 -0
- package/playground/showcase/src/app/pages/documentation/components/components.html +27 -0
- package/playground/showcase/src/app/pages/documentation/components/components.routes.ts +4 -0
- package/playground/showcase/src/app/pages/documentation/components/selection-popover-docs/selection-popover-docs.examples.ts +4 -0
- package/playground/showcase/src/app/pages/documentation/components/selection-popover-docs/selection-popover-docs.html +49 -0
- package/playground/showcase/src/app/pages/documentation/components/selection-popover-docs/selection-popover-docs.ts +1 -0
- 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">>_ </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">> </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
|
|
122
|
+
Browse 7+ production-ready Angular components: Button, Input, Carousel, Breadcrumb
|
|
123
123
|
with TypeScript examples
|
|
124
124
|
</p>
|
|
125
125
|
</div>
|