wally-ui 1.14.1 → 1.16.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/dist/cli.js +0 -0
- package/package.json +1 -1
- package/playground/showcase/public/sitemap.xml +15 -0
- package/playground/showcase/src/app/app.routes.server.ts +8 -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/combobox/combobox-content/combobox-content.css +0 -0
- package/playground/showcase/src/app/components/combobox/combobox-content/combobox-content.html +41 -0
- package/playground/showcase/src/app/components/combobox/combobox-content/combobox-content.spec.ts +228 -0
- package/playground/showcase/src/app/components/combobox/combobox-content/combobox-content.ts +217 -0
- package/playground/showcase/src/app/components/combobox/combobox-empty/combobox-empty.css +0 -0
- package/playground/showcase/src/app/components/combobox/combobox-empty/combobox-empty.html +3 -0
- package/playground/showcase/src/app/components/combobox/combobox-empty/combobox-empty.spec.ts +56 -0
- package/playground/showcase/src/app/components/combobox/combobox-empty/combobox-empty.ts +11 -0
- package/playground/showcase/src/app/components/combobox/combobox-group/combobox-group.css +0 -0
- package/playground/showcase/src/app/components/combobox/combobox-group/combobox-group.html +11 -0
- package/playground/showcase/src/app/components/combobox/combobox-group/combobox-group.spec.ts +57 -0
- package/playground/showcase/src/app/components/combobox/combobox-group/combobox-group.ts +11 -0
- package/playground/showcase/src/app/components/combobox/combobox-input/combobox-input.css +0 -0
- package/playground/showcase/src/app/components/combobox/combobox-input/combobox-input.html +71 -0
- package/playground/showcase/src/app/components/combobox/combobox-input/combobox-input.spec.ts +468 -0
- package/playground/showcase/src/app/components/combobox/combobox-input/combobox-input.ts +90 -0
- package/playground/showcase/src/app/components/combobox/combobox-item/combobox-item.css +0 -0
- package/playground/showcase/src/app/components/combobox/combobox-item/combobox-item.html +58 -0
- package/playground/showcase/src/app/components/combobox/combobox-item/combobox-item.spec.ts +173 -0
- package/playground/showcase/src/app/components/combobox/combobox-item/combobox-item.ts +37 -0
- package/playground/showcase/src/app/components/combobox/combobox-search/combobox-search.css +0 -0
- package/playground/showcase/src/app/components/combobox/combobox-search/combobox-search.html +11 -0
- package/playground/showcase/src/app/components/combobox/combobox-search/combobox-search.spec.ts +166 -0
- package/playground/showcase/src/app/components/combobox/combobox-search/combobox-search.ts +36 -0
- package/playground/showcase/src/app/components/combobox/combobox-trigger/combobox-trigger.css +0 -0
- package/playground/showcase/src/app/components/combobox/combobox-trigger/combobox-trigger.html +8 -0
- package/playground/showcase/src/app/components/combobox/combobox-trigger/combobox-trigger.spec.ts +137 -0
- package/playground/showcase/src/app/components/combobox/combobox-trigger/combobox-trigger.ts +30 -0
- package/playground/showcase/src/app/components/combobox/combobox.css +0 -0
- package/playground/showcase/src/app/components/combobox/combobox.html +3 -0
- package/playground/showcase/src/app/components/combobox/combobox.spec.ts +391 -0
- package/playground/showcase/src/app/components/combobox/combobox.ts +59 -0
- package/playground/showcase/src/app/components/combobox/lib/models/combobox.model.ts +13 -0
- package/playground/showcase/src/app/components/combobox/lib/service/combobox.service.spec.ts +530 -0
- package/playground/showcase/src/app/components/combobox/lib/service/combobox.service.ts +191 -0
- package/playground/showcase/src/app/components/combobox/lib/types/combobox-position.type.ts +1 -0
- package/playground/showcase/src/app/components/combobox/lib/types/combobox-trigger-mode.type.ts +1 -0
- package/playground/showcase/src/app/core/services/seo.service.ts +100 -0
- 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/combobox-docs/combobox-docs.component.css +0 -0
- package/playground/showcase/src/app/pages/documentation/components/combobox-docs/combobox-docs.component.html +383 -0
- package/playground/showcase/src/app/pages/documentation/components/combobox-docs/combobox-docs.component.spec.ts +23 -0
- package/playground/showcase/src/app/pages/documentation/components/combobox-docs/combobox-docs.component.ts +333 -0
- package/playground/showcase/src/app/pages/documentation/components/combobox-docs/combobox-docs.examples.ts +226 -0
- package/playground/showcase/src/app/pages/documentation/components/components.html +27 -0
- package/playground/showcase/src/app/pages/documentation/components/components.routes.ts +8 -0
- package/playground/showcase/src/app/pages/home/home.html +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ComboboxPosition = 'bottom' | 'top' | 'left' | 'right';
|
package/playground/showcase/src/app/components/combobox/lib/types/combobox-trigger-mode.type.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ComboboxTriggerMode = 'input' | 'custom';
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Injectable, inject, PLATFORM_ID } from '@angular/core';
|
|
2
|
+
import { isPlatformBrowser, DOCUMENT } from '@angular/common';
|
|
3
|
+
import { Meta, Title } from '@angular/platform-browser';
|
|
4
|
+
|
|
5
|
+
export interface SeoConfig {
|
|
6
|
+
title: string;
|
|
7
|
+
description: string;
|
|
8
|
+
url?: string;
|
|
9
|
+
image?: string;
|
|
10
|
+
keywords?: string;
|
|
11
|
+
type?: 'website' | 'article';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@Injectable({
|
|
15
|
+
providedIn: 'root'
|
|
16
|
+
})
|
|
17
|
+
export class SeoService {
|
|
18
|
+
private meta = inject(Meta);
|
|
19
|
+
private titleService = inject(Title);
|
|
20
|
+
private platformId = inject(PLATFORM_ID);
|
|
21
|
+
private document = inject(DOCUMENT);
|
|
22
|
+
|
|
23
|
+
private readonly baseUrl = 'https://wally-ui.com';
|
|
24
|
+
private readonly defaultImage = 'https://wally-ui.com/assets/og-image.png';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Updates all SEO meta tags for the current page
|
|
28
|
+
*/
|
|
29
|
+
updateTags(config: SeoConfig): void {
|
|
30
|
+
const {
|
|
31
|
+
title,
|
|
32
|
+
description,
|
|
33
|
+
url = '',
|
|
34
|
+
image = this.defaultImage,
|
|
35
|
+
keywords = 'Angular, TypeScript, UI Components, Design System, Open Source',
|
|
36
|
+
type = 'website'
|
|
37
|
+
} = config;
|
|
38
|
+
|
|
39
|
+
const fullTitle = `${title} - Wally UI`;
|
|
40
|
+
const fullUrl = `${this.baseUrl}${url}`;
|
|
41
|
+
|
|
42
|
+
// Update page title
|
|
43
|
+
this.titleService.setTitle(fullTitle);
|
|
44
|
+
|
|
45
|
+
// Update or create meta tags
|
|
46
|
+
this.meta.updateTag({ name: 'description', content: description });
|
|
47
|
+
this.meta.updateTag({ name: 'keywords', content: keywords });
|
|
48
|
+
|
|
49
|
+
// Open Graph tags
|
|
50
|
+
this.meta.updateTag({ property: 'og:title', content: fullTitle });
|
|
51
|
+
this.meta.updateTag({ property: 'og:description', content: description });
|
|
52
|
+
this.meta.updateTag({ property: 'og:url', content: fullUrl });
|
|
53
|
+
this.meta.updateTag({ property: 'og:image', content: image });
|
|
54
|
+
this.meta.updateTag({ property: 'og:type', content: type });
|
|
55
|
+
|
|
56
|
+
// Twitter Card tags
|
|
57
|
+
this.meta.updateTag({ name: 'twitter:card', content: 'summary_large_image' });
|
|
58
|
+
this.meta.updateTag({ name: 'twitter:title', content: fullTitle });
|
|
59
|
+
this.meta.updateTag({ name: 'twitter:description', content: description });
|
|
60
|
+
this.meta.updateTag({ name: 'twitter:image', content: image });
|
|
61
|
+
|
|
62
|
+
// Canonical URL
|
|
63
|
+
this.updateCanonicalUrl(fullUrl);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Updates or creates canonical link tag (browser only)
|
|
68
|
+
*/
|
|
69
|
+
private updateCanonicalUrl(url: string): void {
|
|
70
|
+
if (!isPlatformBrowser(this.platformId)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let link: HTMLLinkElement | null = this.document.querySelector('link[rel="canonical"]');
|
|
75
|
+
|
|
76
|
+
if (!link) {
|
|
77
|
+
link = this.document.createElement('link');
|
|
78
|
+
link.setAttribute('rel', 'canonical');
|
|
79
|
+
this.document.head.appendChild(link);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
link.setAttribute('href', url);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Removes all dynamic meta tags (useful for cleanup)
|
|
87
|
+
*/
|
|
88
|
+
clearTags(): void {
|
|
89
|
+
this.meta.removeTag('name="description"');
|
|
90
|
+
this.meta.removeTag('name="keywords"');
|
|
91
|
+
this.meta.removeTag('property="og:title"');
|
|
92
|
+
this.meta.removeTag('property="og:description"');
|
|
93
|
+
this.meta.removeTag('property="og:url"');
|
|
94
|
+
this.meta.removeTag('property="og:image"');
|
|
95
|
+
this.meta.removeTag('name="twitter:card"');
|
|
96
|
+
this.meta.removeTag('name="twitter:title"');
|
|
97
|
+
this.meta.removeTag('name="twitter:description"');
|
|
98
|
+
this.meta.removeTag('name="twitter:image"');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/* Audio Waveform Documentation Styles */
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Audio Waveform documentation code examples
|
|
2
|
+
export const AudioWaveformCodeExamples = {
|
|
3
|
+
// Installation
|
|
4
|
+
installation: `npx wally-ui add audio-waveform`,
|
|
5
|
+
|
|
6
|
+
// Import examples
|
|
7
|
+
import: `import { AudioWaveform } from './components/wally-ui/audio-waveform/audio-waveform';
|
|
8
|
+
import { AudioWaveformService } from './components/wally-ui/audio-waveform/audio-waveform.service';`,
|
|
9
|
+
|
|
10
|
+
componentImport: `@Component({
|
|
11
|
+
selector: 'app-example',
|
|
12
|
+
imports: [AudioWaveform],
|
|
13
|
+
templateUrl: './example.html'
|
|
14
|
+
})`,
|
|
15
|
+
|
|
16
|
+
// Basic usage
|
|
17
|
+
basicUsage: `<wally-audio-waveform
|
|
18
|
+
[isStartRecording]="isRecording()"
|
|
19
|
+
[isStopRecording]="!isRecording()">
|
|
20
|
+
</wally-audio-waveform>`,
|
|
21
|
+
|
|
22
|
+
// With timer
|
|
23
|
+
withTimer: `<wally-audio-waveform
|
|
24
|
+
[isStartRecording]="isRecording()"
|
|
25
|
+
[isStopRecording]="!isRecording()"
|
|
26
|
+
[showTimer]="true">
|
|
27
|
+
</wally-audio-waveform>`,
|
|
28
|
+
|
|
29
|
+
// Complete Example with Controls
|
|
30
|
+
completeExample: `<div class="flex flex-col gap-4">
|
|
31
|
+
<!-- Waveform Visualizer -->
|
|
32
|
+
<wally-audio-waveform
|
|
33
|
+
[isStartRecording]="isRecording()"
|
|
34
|
+
[isStopRecording]="!isRecording()"
|
|
35
|
+
[showTimer]="true">
|
|
36
|
+
</wally-audio-waveform>
|
|
37
|
+
|
|
38
|
+
<!-- Recording Controls -->
|
|
39
|
+
<div class="flex gap-2">
|
|
40
|
+
@if (!isRecording()) {
|
|
41
|
+
<button (click)="startRecording()"
|
|
42
|
+
class="px-4 py-2 bg-red-500 text-white rounded-full">
|
|
43
|
+
Start Recording
|
|
44
|
+
</button>
|
|
45
|
+
} @else {
|
|
46
|
+
<button (click)="stopRecording()"
|
|
47
|
+
class="px-4 py-2 bg-neutral-500 text-white rounded-full">
|
|
48
|
+
Stop Recording
|
|
49
|
+
</button>
|
|
50
|
+
}
|
|
51
|
+
</div>
|
|
52
|
+
</div>`,
|
|
53
|
+
|
|
54
|
+
completeExampleTs: `export class RecordingComponent {
|
|
55
|
+
isRecording = signal(false);
|
|
56
|
+
|
|
57
|
+
startRecording() {
|
|
58
|
+
this.isRecording.set(true);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
stopRecording() {
|
|
62
|
+
this.isRecording.set(false);
|
|
63
|
+
}
|
|
64
|
+
}`,
|
|
65
|
+
|
|
66
|
+
// Service Integration
|
|
67
|
+
serviceIntegration: `// Access the service to get recorded audio
|
|
68
|
+
export class RecordingComponent {
|
|
69
|
+
@ViewChild(AudioWaveform) audioWaveform!: AudioWaveform;
|
|
70
|
+
|
|
71
|
+
downloadRecording() {
|
|
72
|
+
const service = this.audioWaveform.audioWaveformService;
|
|
73
|
+
service.downloadRecording('my-recording.webm');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getRecordedBlob() {
|
|
77
|
+
const service = this.audioWaveform.audioWaveformService;
|
|
78
|
+
const blob = service.recordedAudioBlob();
|
|
79
|
+
return blob;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
clearRecording() {
|
|
83
|
+
const service = this.audioWaveform.audioWaveformService;
|
|
84
|
+
service.clearRecording();
|
|
85
|
+
}
|
|
86
|
+
}`,
|
|
87
|
+
|
|
88
|
+
// Responsive Configuration
|
|
89
|
+
responsiveConfig: `// Service Configuration (auto-responsive)
|
|
90
|
+
// Mobile (< 768px): 30 bars
|
|
91
|
+
// Desktop (>= 768px): 65 bars
|
|
92
|
+
// Automatically adjusts based on screen width`,
|
|
93
|
+
|
|
94
|
+
// Future: Audio Transcription
|
|
95
|
+
futureTranscription: `// COMING SOON: Audio Transcription
|
|
96
|
+
// The component will support automatic transcription in a future release
|
|
97
|
+
|
|
98
|
+
<wally-audio-waveform
|
|
99
|
+
[isStartRecording]="isRecording()"
|
|
100
|
+
[isStopRecording]="!isRecording()"
|
|
101
|
+
[enableTranscription]="true"
|
|
102
|
+
(transcriptionComplete)="onTranscription($event)">
|
|
103
|
+
</wally-audio-waveform>`,
|
|
104
|
+
|
|
105
|
+
// Web Audio API Concepts
|
|
106
|
+
webAudioConcepts: `// How it works under the hood:
|
|
107
|
+
// 1. getUserMedia() - Request microphone access
|
|
108
|
+
// 2. AudioContext - Process audio in real-time
|
|
109
|
+
// 3. AnalyserNode - FFT analysis (256 samples → 128 frequencies)
|
|
110
|
+
// 4. getByteFrequencyData() - Get frequency values (0-255)
|
|
111
|
+
// 5. Normalize to 0-100% for bar heights
|
|
112
|
+
// 6. requestAnimationFrame - Smooth 60fps animation`,
|
|
113
|
+
|
|
114
|
+
// Properties: Inputs
|
|
115
|
+
propertyIsStartRecording: `isStartRecording: InputSignal<boolean> = input<boolean>(false);`,
|
|
116
|
+
propertyIsStopRecording: `isStopRecording: InputSignal<boolean> = input<boolean>(false);`,
|
|
117
|
+
propertyShowTimer: `showTimer: InputSignal<boolean> = input<boolean>(false);`,
|
|
118
|
+
|
|
119
|
+
// Properties: Service Signals
|
|
120
|
+
servicePropertyIsRecording: `isRecording: WritableSignal<boolean>`,
|
|
121
|
+
servicePropertyAudioData: `audioData: WritableSignal<number[]> // Bar heights (0-100%)`,
|
|
122
|
+
servicePropertyRecordedAudioBlob: `recordedAudioBlob: WritableSignal<Blob | null>`,
|
|
123
|
+
servicePropertyRecordedAudioUrl: `recordedAudioUrl: WritableSignal<string | null>`,
|
|
124
|
+
|
|
125
|
+
// Methods
|
|
126
|
+
methodDownloadRecording: `downloadRecording(filename?: string): void`,
|
|
127
|
+
methodClearRecording: `clearRecording(): void`,
|
|
128
|
+
|
|
129
|
+
// Configuration constants
|
|
130
|
+
configFFTSize: `FFT_SIZE = 256 // Higher = more frequency detail`,
|
|
131
|
+
configBarCount: `BAR_COUNT = 30 (mobile) | 65 (desktop) // Auto-responsive`,
|
|
132
|
+
configSmoothing: `SMOOTHING = 0.8 // 0 (no smoothing) to 1 (max smoothing)`,
|
|
133
|
+
|
|
134
|
+
// Accessibility
|
|
135
|
+
accessibilityExample: `<!-- The component includes built-in accessibility -->
|
|
136
|
+
<!-- Timer updates announced via aria-live region (when showTimer=true) -->
|
|
137
|
+
<!-- Waveform visualizer is decorative (aria-hidden) -->`,
|
|
138
|
+
|
|
139
|
+
// Browser Support
|
|
140
|
+
browserSupport: `// Requires modern browsers with:
|
|
141
|
+
// - Web Audio API
|
|
142
|
+
// - MediaStream API
|
|
143
|
+
// - MediaRecorder API
|
|
144
|
+
//
|
|
145
|
+
// Supported: Chrome 60+, Firefox 55+, Safari 14+, Edge 79+`,
|
|
146
|
+
};
|