@ghchinoy/lit-audio-ui 0.3.5 → 0.4.1
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/AGENT_SKILL.md +50 -0
- package/dist/components/atoms/ui-audio-next-button.js +46 -0
- package/dist/components/{ui-audio-play-button.js → atoms/ui-audio-play-button.js} +7 -7
- package/dist/components/atoms/ui-audio-prev-button.js +46 -0
- package/dist/components/{ui-audio-progress-slider.js → atoms/ui-audio-progress-slider.js} +6 -6
- package/dist/components/{ui-audio-time-display.js → atoms/ui-audio-time-display.js} +10 -11
- package/dist/components/{ui-audio-volume-slider.js → atoms/ui-audio-volume-slider.js} +8 -8
- package/dist/components/{ui-shimmering-text.js → atoms/ui-shimmering-text.js} +1 -1
- package/dist/components/{ui-speech-cancel-button.js → atoms/ui-speech-cancel-button.js} +6 -6
- package/dist/components/{ui-speech-record-button.js → atoms/ui-speech-record-button.js} +6 -6
- package/dist/components/{scream-voice-button.js → molecules/scream-voice-button.js} +2 -2
- package/dist/components/molecules/ui-3d-flip.js +126 -0
- package/dist/components/{ui-live-waveform.js → molecules/ui-live-waveform.js} +2 -2
- package/dist/components/{ui-mic-selector.js → molecules/ui-mic-selector.js} +2 -2
- package/dist/components/{ui-orb.js → molecules/ui-orb.js} +7 -2
- package/dist/components/molecules/ui-playlist.js +109 -0
- package/dist/components/{ui-scrolling-waveform.js → molecules/ui-scrolling-waveform.js} +2 -2
- package/dist/components/{ui-showcase-card.js → molecules/ui-showcase-card.js} +1 -1
- package/dist/components/molecules/ui-spectrum-visualizer.js +75 -0
- package/dist/components/{ui-speech-preview.js → molecules/ui-speech-preview.js} +5 -5
- package/dist/components/{ui-voice-button.js → molecules/ui-voice-button.js} +12 -7
- package/dist/components/{ui-voice-picker.js → molecules/ui-voice-picker.js} +3 -3
- package/dist/components/{ui-waveform.js → molecules/ui-waveform.js} +2 -2
- package/dist/components/{ui-audio-player.js → organisms/ui-audio-player.js} +5 -5
- package/dist/components/{ui-audio-provider.js → providers/ui-audio-provider.js} +36 -10
- package/dist/components/{ui-speech-provider.js → providers/ui-speech-provider.js} +6 -6
- package/dist/index.js +30 -24
- package/dist/scream-audio-ui.umd.js +1011 -824
- package/package.json +7 -3
package/AGENT_SKILL.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Agent Skill: Lit Audio UI Integration
|
|
2
|
+
|
|
3
|
+
A specialized skill for AI agents to autonomously implement high-performance audio visualizations and controls using the `@ghchinoy/lit-audio-ui` library.
|
|
4
|
+
|
|
5
|
+
## Capabilities
|
|
6
|
+
- Orchestrate complex audio playback using a headless provider.
|
|
7
|
+
- Implement real-time 2D and 3D audio visualizations (Orb, Waveforms, Spectrum).
|
|
8
|
+
- Construct accessible, theme-aware audio interfaces.
|
|
9
|
+
- Manage multi-track playlists with automatic state synchronization.
|
|
10
|
+
|
|
11
|
+
## Protocol: The "Lit Way"
|
|
12
|
+
|
|
13
|
+
### 1. Bootstrapping the Provider
|
|
14
|
+
Always wrap atomic components in a `<ui-audio-provider>` (for playback) or `<ui-speech-provider>` (for recording). These components manage the state machine and shared context.
|
|
15
|
+
|
|
16
|
+
### 2. Playlist & State Synchronization
|
|
17
|
+
When using `<ui-audio-provider>` with the `items` property:
|
|
18
|
+
- Listen to the `@state-change` event on the provider.
|
|
19
|
+
- Use `e.detail.currentIndex` to synchronize your parent component's metadata (e.g., Title, Artist, Album Art).
|
|
20
|
+
- The provider handles internal track advancing automatically when `autoAdvance` is true.
|
|
21
|
+
|
|
22
|
+
### 3. Visualizer "Bridge" Logic
|
|
23
|
+
Most visual components (`ui-orb`, `ui-spectrum-visualizer`, `ui-live-waveform`) require an `analyserNode`.
|
|
24
|
+
- They attempt to consume this from context automatically.
|
|
25
|
+
- **Tip:** Ensure the provider has finished initializing its AudioContext (triggered by the first user interaction) before expecting visualizations to appear.
|
|
26
|
+
|
|
27
|
+
### 4. Theming & Branding (Zero-JS)
|
|
28
|
+
The library uses Material Design 3 tokens with semantic overrides. Use these for dark-theme consistency:
|
|
29
|
+
- `--md-sys-color-primary`: Main theme color (e.g., `#d0bcff`).
|
|
30
|
+
- `--md-sys-color-surface-container-low`: Primary background for pickers and lists.
|
|
31
|
+
- `--ui-speech-wave-color`: Custom color for waveforms inside buttons (prevents 'black-on-black' issues).
|
|
32
|
+
- `--md-list-item-label-text-color`: high-contrast text color for playlists.
|
|
33
|
+
|
|
34
|
+
### 5. Layout & 3D Environments
|
|
35
|
+
If a component is inside a 3D transformed container (perspective/translateZ):
|
|
36
|
+
- Ensure `md-menu` (inside pickers) uses `positioning="popover"`.
|
|
37
|
+
- Use the `<ui-3d-flip>` utility for compact "back-of-card" tracklists.
|
|
38
|
+
- Apply `font-family: inherit` to library components to avoid default serif fonts.
|
|
39
|
+
|
|
40
|
+
### 6. Component Utility Registry
|
|
41
|
+
- `<ui-audio-time-display>`: Defaults to `full` mode (`current / total`). Use `format="elapsed"` or `format="remaining"` for single values.
|
|
42
|
+
- `<ui-spectrum-visualizer>`: Requires a `.height` property for reliable rendering.
|
|
43
|
+
|
|
44
|
+
## Simulation Mode
|
|
45
|
+
For development without microphone access, enable the `simulation` property on `<ui-speech-provider>`. This generates procedural audio data and mock transcription events.
|
|
46
|
+
|
|
47
|
+
## Quality Gates
|
|
48
|
+
- Ensure `crossorigin="anonymous"` is set on audio/video tags to allow analysis.
|
|
49
|
+
- Use `color-scheme: light dark;` on host elements to support native dark-mode sensitivity.
|
|
50
|
+
- Verify that `manual` mode handlers clear intervals/timeouts during state transitions.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { c as e } from "../../node_modules/@lit/context/lib/decorators/consume.js";
|
|
2
|
+
import { audioPlayerContext as t } from "../../utils/audio-context.js";
|
|
3
|
+
import { __decorate as n } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
4
|
+
import "@material/web/icon/icon.js";
|
|
5
|
+
import { LitElement as r, css as i, html as a } from "lit";
|
|
6
|
+
import { customElement as o } from "lit/decorators.js";
|
|
7
|
+
import "@material/web/iconbutton/icon-button.js";
|
|
8
|
+
/**
|
|
9
|
+
* Copyright 2026 Google LLC
|
|
10
|
+
*
|
|
11
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
* you may not use this file except in compliance with the License.
|
|
13
|
+
* You may obtain a copy of the License at
|
|
14
|
+
*
|
|
15
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
*
|
|
17
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
* See the License for the specific language governing permissions and
|
|
21
|
+
* limitations under the License.
|
|
22
|
+
*/
|
|
23
|
+
var s = class extends r {
|
|
24
|
+
static {
|
|
25
|
+
this.styles = i`
|
|
26
|
+
:host {
|
|
27
|
+
display: inline-block;
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
render() {
|
|
32
|
+
return a`
|
|
33
|
+
<md-icon-button
|
|
34
|
+
?disabled=${!(this.playerState && this.playerState.items.length > 0 && (this.playerState.currentIndex < this.playerState.items.length - 1 || this.playerState.autoAdvance))}
|
|
35
|
+
@click=${() => this.playerState?.next()}
|
|
36
|
+
>
|
|
37
|
+
<md-icon>skip_next</md-icon>
|
|
38
|
+
</md-icon-button>
|
|
39
|
+
`;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
n([e({
|
|
43
|
+
context: t,
|
|
44
|
+
subscribe: !0
|
|
45
|
+
})], s.prototype, "playerState", void 0), s = n([o("ui-audio-next-button")], s);
|
|
46
|
+
export { s as UiAudioNextButton };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { c as e } from "../../node_modules/@lit/context/lib/decorators/consume.js";
|
|
2
|
+
import { audioPlayerContext as t } from "../../utils/audio-context.js";
|
|
3
|
+
import { __decorate as n } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
4
|
+
import "@material/web/icon/icon.js";
|
|
4
5
|
import { LitElement as r, css as i, html as a } from "lit";
|
|
5
6
|
import { customElement as o, property as s } from "lit/decorators.js";
|
|
6
|
-
import "@material/web/icon/icon.js";
|
|
7
7
|
import "@material/web/iconbutton/filled-icon-button.js";
|
|
8
8
|
import "@material/web/progress/circular-progress.js";
|
|
9
9
|
var c = class extends r {
|
|
@@ -77,8 +77,8 @@ var c = class extends r {
|
|
|
77
77
|
this.playerState && this.playerState.togglePlay();
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
|
-
|
|
81
|
-
context:
|
|
80
|
+
n([e({
|
|
81
|
+
context: t,
|
|
82
82
|
subscribe: !0
|
|
83
|
-
}), s({ attribute: !1 })], c.prototype, "playerState", void 0), c =
|
|
83
|
+
}), s({ attribute: !1 })], c.prototype, "playerState", void 0), c = n([o("ui-audio-play-button")], c);
|
|
84
84
|
export { c as UiAudioPlayButton };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { c as e } from "../../node_modules/@lit/context/lib/decorators/consume.js";
|
|
2
|
+
import { audioPlayerContext as t } from "../../utils/audio-context.js";
|
|
3
|
+
import { __decorate as n } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
4
|
+
import "@material/web/icon/icon.js";
|
|
5
|
+
import { LitElement as r, css as i, html as a } from "lit";
|
|
6
|
+
import { customElement as o } from "lit/decorators.js";
|
|
7
|
+
import "@material/web/iconbutton/icon-button.js";
|
|
8
|
+
/**
|
|
9
|
+
* Copyright 2026 Google LLC
|
|
10
|
+
*
|
|
11
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
* you may not use this file except in compliance with the License.
|
|
13
|
+
* You may obtain a copy of the License at
|
|
14
|
+
*
|
|
15
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
*
|
|
17
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
* See the License for the specific language governing permissions and
|
|
21
|
+
* limitations under the License.
|
|
22
|
+
*/
|
|
23
|
+
var s = class extends r {
|
|
24
|
+
static {
|
|
25
|
+
this.styles = i`
|
|
26
|
+
:host {
|
|
27
|
+
display: inline-block;
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
render() {
|
|
32
|
+
return a`
|
|
33
|
+
<md-icon-button
|
|
34
|
+
?disabled=${!(this.playerState && this.playerState.items.length > 0 && (this.playerState.currentIndex > 0 || this.playerState.autoAdvance))}
|
|
35
|
+
@click=${() => this.playerState?.previous()}
|
|
36
|
+
>
|
|
37
|
+
<md-icon>skip_previous</md-icon>
|
|
38
|
+
</md-icon-button>
|
|
39
|
+
`;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
n([e({
|
|
43
|
+
context: t,
|
|
44
|
+
subscribe: !0
|
|
45
|
+
})], s.prototype, "playerState", void 0), s = n([o("ui-audio-prev-button")], s);
|
|
46
|
+
export { s as UiAudioPrevButton };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { c as e } from "../../node_modules/@lit/context/lib/decorators/consume.js";
|
|
2
|
+
import { audioPlayerContext as t } from "../../utils/audio-context.js";
|
|
3
|
+
import { __decorate as n } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
4
4
|
import { LitElement as r, css as i, html as a } from "lit";
|
|
5
5
|
import { customElement as o, property as s } from "lit/decorators.js";
|
|
6
6
|
import "@material/web/slider/slider.js";
|
|
@@ -45,8 +45,8 @@ var c = class extends r {
|
|
|
45
45
|
this._dragValue = e.target.value, this.playerState && this.playerState.seek(this._dragValue), this._isDragging = !1;
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
|
-
|
|
49
|
-
context:
|
|
48
|
+
n([e({
|
|
49
|
+
context: t,
|
|
50
50
|
subscribe: !0
|
|
51
|
-
}), s({ attribute: !1 })], c.prototype, "playerState", void 0), c =
|
|
51
|
+
}), s({ attribute: !1 })], c.prototype, "playerState", void 0), c = n([o("ui-audio-progress-slider")], c);
|
|
52
52
|
export { c as UiAudioProgressSlider };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { c as e } from "../../node_modules/@lit/context/lib/decorators/consume.js";
|
|
2
|
+
import { audioPlayerContext as t } from "../../utils/audio-context.js";
|
|
3
|
+
import { __decorate as n } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
4
4
|
import { LitElement as r, css as i, html as a } from "lit";
|
|
5
5
|
import { customElement as o, property as s } from "lit/decorators.js";
|
|
6
6
|
var c = class extends r {
|
|
7
7
|
constructor(...e) {
|
|
8
|
-
super(...e), this.format = "
|
|
8
|
+
super(...e), this.format = "combined", this.separator = " / ", this.compact = !1;
|
|
9
9
|
}
|
|
10
10
|
static {
|
|
11
11
|
this.styles = i`
|
|
@@ -24,17 +24,16 @@ var c = class extends r {
|
|
|
24
24
|
if (this.format === "remaining") {
|
|
25
25
|
let n = Math.max(0, t - e);
|
|
26
26
|
return a`-${this._formatTime(n)}`;
|
|
27
|
-
} else return a`${this._formatTime(e)}
|
|
28
|
-
${t ? this._formatTime(t) : "--:--"}`;
|
|
27
|
+
} else return a`${this._formatTime(e)}${this.separator}${t ? this._formatTime(t) : "--:--"}`;
|
|
29
28
|
}
|
|
30
29
|
_formatTime(e) {
|
|
31
|
-
if (!e || isNaN(e)) return "0:00";
|
|
30
|
+
if (!e || isNaN(e)) return this.compact, "0:00";
|
|
32
31
|
let t = Math.floor(e / 3600), n = Math.floor(e % 3600 / 60), r = Math.floor(e % 60), i = "";
|
|
33
|
-
return t > 0
|
|
32
|
+
return t > 0 ? i += "" + t + ":" + (n < 10 ? "0" : "") : this.compact, i += "" + n + ":" + (r < 10 ? "0" : ""), i += "" + r, i;
|
|
34
33
|
}
|
|
35
34
|
};
|
|
36
|
-
|
|
37
|
-
context:
|
|
35
|
+
n([e({
|
|
36
|
+
context: t,
|
|
38
37
|
subscribe: !0
|
|
39
|
-
}), s({ attribute: !1 })], c.prototype, "playerState", void 0),
|
|
38
|
+
}), s({ attribute: !1 })], c.prototype, "playerState", void 0), n([s({ type: String })], c.prototype, "format", void 0), n([s({ type: String })], c.prototype, "separator", void 0), n([s({ type: Boolean })], c.prototype, "compact", void 0), c = n([o("ui-audio-time-display")], c);
|
|
40
39
|
export { c as UiAudioTimeDisplay };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { c as e } from "../../node_modules/@lit/context/lib/decorators/consume.js";
|
|
2
|
+
import { audioPlayerContext as t } from "../../utils/audio-context.js";
|
|
3
|
+
import { __decorate as n } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
4
|
+
import "@material/web/icon/icon.js";
|
|
4
5
|
import { LitElement as r, css as i, html as a } from "lit";
|
|
5
6
|
import { customElement as o, property as s } from "lit/decorators.js";
|
|
6
|
-
import "@material/web/icon/icon.js";
|
|
7
|
-
import "@material/web/slider/slider.js";
|
|
8
7
|
import "@material/web/iconbutton/icon-button.js";
|
|
8
|
+
import "@material/web/slider/slider.js";
|
|
9
9
|
var c = class extends r {
|
|
10
10
|
static {
|
|
11
11
|
this.styles = i`
|
|
@@ -57,8 +57,8 @@ var c = class extends r {
|
|
|
57
57
|
this.playerState && this.playerState.toggleMute();
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
|
-
|
|
61
|
-
context:
|
|
60
|
+
n([e({
|
|
61
|
+
context: t,
|
|
62
62
|
subscribe: !0
|
|
63
|
-
}), s({ attribute: !1 })], c.prototype, "playerState", void 0), c =
|
|
63
|
+
}), s({ attribute: !1 })], c.prototype, "playerState", void 0), c = n([o("ui-audio-volume-slider")], c);
|
|
64
64
|
export { c as UiAudioVolumeSlider };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __decorate as e } from "
|
|
1
|
+
import { __decorate as e } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
2
2
|
import { LitElement as t, css as n, html as r } from "lit";
|
|
3
3
|
import { customElement as i, property as a, state as o } from "lit/decorators.js";
|
|
4
4
|
var s = class extends t {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { speechContext as n } from "
|
|
1
|
+
import { c as e } from "../../node_modules/@lit/context/lib/decorators/consume.js";
|
|
2
|
+
import { __decorate as t } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
3
|
+
import { speechContext as n } from "../../utils/speech-context.js";
|
|
4
|
+
import "@material/web/icon/icon.js";
|
|
4
5
|
import { LitElement as r, css as i, html as a } from "lit";
|
|
5
6
|
import { customElement as o } from "lit/decorators.js";
|
|
6
|
-
import "@material/web/icon/icon.js";
|
|
7
7
|
import "@material/web/iconbutton/icon-button.js";
|
|
8
8
|
var s = class extends r {
|
|
9
9
|
static {
|
|
@@ -40,8 +40,8 @@ var s = class extends r {
|
|
|
40
40
|
this._context?.cancel();
|
|
41
41
|
}
|
|
42
42
|
};
|
|
43
|
-
|
|
43
|
+
t([e({
|
|
44
44
|
context: n,
|
|
45
45
|
subscribe: !0
|
|
46
|
-
})], s.prototype, "_context", void 0), s =
|
|
46
|
+
})], s.prototype, "_context", void 0), s = t([o("ui-speech-cancel-button")], s);
|
|
47
47
|
export { s as UiSpeechCancelButton };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { speechContext as n } from "
|
|
1
|
+
import { c as e } from "../../node_modules/@lit/context/lib/decorators/consume.js";
|
|
2
|
+
import { __decorate as t } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
3
|
+
import { speechContext as n } from "../../utils/speech-context.js";
|
|
4
|
+
import "@material/web/icon/icon.js";
|
|
4
5
|
import { LitElement as r, css as i, html as a } from "lit";
|
|
5
6
|
import { customElement as o, property as s } from "lit/decorators.js";
|
|
6
|
-
import "@material/web/icon/icon.js";
|
|
7
7
|
import "@material/web/iconbutton/filled-icon-button.js";
|
|
8
8
|
var c = class extends r {
|
|
9
9
|
constructor(...e) {
|
|
@@ -75,8 +75,8 @@ var c = class extends r {
|
|
|
75
75
|
this._context && (this._context.state === "idle" ? this._context.start() : this._context.state === "recording" && this._context.stop());
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
|
-
|
|
78
|
+
t([e({
|
|
79
79
|
context: n,
|
|
80
80
|
subscribe: !0
|
|
81
|
-
})], c.prototype, "_context", void 0),
|
|
81
|
+
})], c.prototype, "_context", void 0), t([s({ type: String })], c.prototype, "size", void 0), c = t([o("ui-speech-record-button")], c);
|
|
82
82
|
export { c as UiSpeechRecordButton };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { __decorate as e } from "
|
|
1
|
+
import { __decorate as e } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
2
|
+
import "@material/web/icon/icon.js";
|
|
2
3
|
import { LitElement as t, css as n, html as r } from "lit";
|
|
3
4
|
import { customElement as i, property as a } from "lit/decorators.js";
|
|
4
5
|
import "@material/web/button/filled-button.js";
|
|
5
|
-
import "@material/web/icon/icon.js";
|
|
6
6
|
/**
|
|
7
7
|
* Copyright 2026 Google LLC
|
|
8
8
|
*
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { __decorate as e } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
2
|
+
import "@material/web/icon/icon.js";
|
|
3
|
+
import { LitElement as t, css as n, html as r } from "lit";
|
|
4
|
+
import { customElement as i, property as a } from "lit/decorators.js";
|
|
5
|
+
/**
|
|
6
|
+
* Copyright 2026 Google LLC
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
* you may not use this file except in compliance with the License.
|
|
10
|
+
* You may obtain a copy of the License at
|
|
11
|
+
*
|
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/
|
|
20
|
+
var o = class extends t {
|
|
21
|
+
constructor(...e) {
|
|
22
|
+
super(...e), this.flipped = !1, this.axis = "y", this.duration = "0.6s";
|
|
23
|
+
}
|
|
24
|
+
static {
|
|
25
|
+
this.styles = n`
|
|
26
|
+
:host {
|
|
27
|
+
display: block;
|
|
28
|
+
perspective: 1000px;
|
|
29
|
+
width: 100%;
|
|
30
|
+
height: 100%;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.flip-container {
|
|
34
|
+
position: relative;
|
|
35
|
+
width: 100%;
|
|
36
|
+
height: 100%;
|
|
37
|
+
text-align: center;
|
|
38
|
+
transition: transform var(--ui-3d-flip-duration, 0.6s);
|
|
39
|
+
transform-style: preserve-3d;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:host([flipped]) .flip-container {
|
|
43
|
+
transform: rotateY(180deg);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:host([flipped][axis='x']) .flip-container {
|
|
47
|
+
transform: rotateX(180deg);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.front,
|
|
51
|
+
.back {
|
|
52
|
+
position: absolute;
|
|
53
|
+
width: 100%;
|
|
54
|
+
height: 100%;
|
|
55
|
+
backface-visibility: hidden;
|
|
56
|
+
-webkit-backface-visibility: hidden;
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
border-radius: inherit;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.back {
|
|
64
|
+
transform: rotateY(180deg);
|
|
65
|
+
background: var(--md-sys-color-surface, #ffffff);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
:host([axis='x']) .back {
|
|
69
|
+
transform: rotateX(180deg);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Slot for optional trigger icon */
|
|
73
|
+
.flip-trigger {
|
|
74
|
+
position: absolute;
|
|
75
|
+
top: 12px;
|
|
76
|
+
right: 12px;
|
|
77
|
+
z-index: 10;
|
|
78
|
+
cursor: pointer;
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
justify-content: center;
|
|
82
|
+
}
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
render() {
|
|
86
|
+
return r`
|
|
87
|
+
<div
|
|
88
|
+
class="flip-container"
|
|
89
|
+
style="--ui-3d-flip-duration: ${this.duration}"
|
|
90
|
+
>
|
|
91
|
+
<div class="front">
|
|
92
|
+
<slot name="front"></slot>
|
|
93
|
+
<div class="flip-trigger" @click=${this.toggle}>
|
|
94
|
+
<slot name="flip-icon">
|
|
95
|
+
<!-- Default info icon if nothing provided -->
|
|
96
|
+
<md-icon style="color: white; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.5));">info</md-icon>
|
|
97
|
+
</slot>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="back">
|
|
101
|
+
<slot name="back"></slot>
|
|
102
|
+
<div class="flip-trigger" @click=${this.toggle}>
|
|
103
|
+
<slot name="flip-icon-back">
|
|
104
|
+
<md-icon style="color: var(--md-sys-color-primary);">close</md-icon>
|
|
105
|
+
</slot>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
toggle() {
|
|
112
|
+
this.flipped = !this.flipped, this.dispatchEvent(new CustomEvent("flip-change", {
|
|
113
|
+
detail: { flipped: this.flipped },
|
|
114
|
+
bubbles: !0,
|
|
115
|
+
composed: !0
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
e([a({
|
|
120
|
+
type: Boolean,
|
|
121
|
+
reflect: !0
|
|
122
|
+
})], o.prototype, "flipped", void 0), e([a({
|
|
123
|
+
type: String,
|
|
124
|
+
reflect: !0
|
|
125
|
+
})], o.prototype, "axis", void 0), e([a({ type: String })], o.prototype, "duration", void 0), o = e([i("ui-3d-flip")], o);
|
|
126
|
+
export { o as Ui3dFlip };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { __decorate as e } from "
|
|
2
|
-
import { applyCanvasEdgeFade as t, getNormalizedFrequencyData as n } from "
|
|
1
|
+
import { __decorate as e } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
2
|
+
import { applyCanvasEdgeFade as t, getNormalizedFrequencyData as n } from "../../utils/audio-utils.js";
|
|
3
3
|
import { LitElement as r, css as i, html as a } from "lit";
|
|
4
4
|
import { customElement as o, property as s, query as c } from "lit/decorators.js";
|
|
5
5
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { __decorate as e } from "
|
|
1
|
+
import { __decorate as e } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
2
2
|
import "./ui-live-waveform.js";
|
|
3
|
+
import "@material/web/icon/icon.js";
|
|
3
4
|
import { LitElement as t, css as n, html as r } from "lit";
|
|
4
5
|
import { customElement as i, property as a, query as o, state as s } from "lit/decorators.js";
|
|
5
|
-
import "@material/web/icon/icon.js";
|
|
6
6
|
import "@material/web/menu/menu.js";
|
|
7
7
|
import "@material/web/menu/menu-item.js";
|
|
8
8
|
import "@material/web/divider/divider.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __decorate as e } from "
|
|
1
|
+
import { __decorate as e } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
2
2
|
import { LitElement as t, css as n, html as r } from "lit";
|
|
3
3
|
import { customElement as i, property as a, query as o } from "lit/decorators.js";
|
|
4
4
|
import * as s from "three";
|
|
@@ -32,7 +32,12 @@ var c = class extends t {
|
|
|
32
32
|
this._initThree();
|
|
33
33
|
}
|
|
34
34
|
updated(e) {
|
|
35
|
-
e.has("colors") && this._updateColors();
|
|
35
|
+
e.has("colors") && this._updateColors(), e.has("seed") && this._updateSeed();
|
|
36
|
+
}
|
|
37
|
+
_updateSeed() {
|
|
38
|
+
if (!this._mesh) return;
|
|
39
|
+
let e = this._splitmix32(this.seed), t = new Float32Array(Array.from({ length: 7 }, () => e() * Math.PI * 2));
|
|
40
|
+
this._mesh.material.uniforms.uOffsets.value = t;
|
|
36
41
|
}
|
|
37
42
|
_updateColors() {
|
|
38
43
|
if (!(!this._targetColor1 || !this._targetColor2)) if (this.colors && this.colors.length === 2) this._targetColor1.set(this.colors[0]), this._targetColor2.set(this.colors[1]);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { c as e } from "../../node_modules/@lit/context/lib/decorators/consume.js";
|
|
2
|
+
import { audioPlayerContext as t } from "../../utils/audio-context.js";
|
|
3
|
+
import { __decorate as n } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
4
|
+
import "@material/web/icon/icon.js";
|
|
5
|
+
import { LitElement as r, css as i, html as a } from "lit";
|
|
6
|
+
import { customElement as o, property as s } from "lit/decorators.js";
|
|
7
|
+
import "@material/web/list/list.js";
|
|
8
|
+
import "@material/web/list/list-item.js";
|
|
9
|
+
/**
|
|
10
|
+
* Copyright 2026 Google LLC
|
|
11
|
+
*
|
|
12
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
13
|
+
* you may not use this file except in compliance with the License.
|
|
14
|
+
* You may obtain a copy of the License at
|
|
15
|
+
*
|
|
16
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
*
|
|
18
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
20
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
+
* See the License for the specific language governing permissions and
|
|
22
|
+
* limitations under the License.
|
|
23
|
+
*/
|
|
24
|
+
var c = class extends r {
|
|
25
|
+
constructor(...e) {
|
|
26
|
+
super(...e), this.header = "Queue", this.emptyText = "No tracks in queue";
|
|
27
|
+
}
|
|
28
|
+
static {
|
|
29
|
+
this.styles = i`
|
|
30
|
+
:host {
|
|
31
|
+
display: block;
|
|
32
|
+
background: var(--md-sys-color-surface-container-low, transparent);
|
|
33
|
+
border-radius: 12px;
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
font-family: inherit;
|
|
36
|
+
color-scheme: light dark;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.playlist-header {
|
|
40
|
+
padding: 16px 20px;
|
|
41
|
+
font-size: 0.75rem;
|
|
42
|
+
font-weight: 700;
|
|
43
|
+
text-transform: uppercase;
|
|
44
|
+
letter-spacing: 0.05em;
|
|
45
|
+
color: var(--md-sys-color-primary, #0066cc);
|
|
46
|
+
background: var(--md-sys-color-surface-container-low);
|
|
47
|
+
border-bottom: 1px solid var(--md-sys-color-outline-variant);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
md-list {
|
|
51
|
+
background: transparent;
|
|
52
|
+
--md-list-container-color: transparent;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
md-list-item {
|
|
56
|
+
--md-list-item-label-text-font: inherit;
|
|
57
|
+
--md-list-item-supporting-text-font: inherit;
|
|
58
|
+
--md-list-item-label-text-color: var(--md-sys-color-on-surface);
|
|
59
|
+
--md-list-item-supporting-text-color: var(--md-sys-color-on-surface-variant);
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
md-list-item[selected] {
|
|
64
|
+
--md-list-item-label-text-color: var(--md-sys-color-primary);
|
|
65
|
+
background: var(--md-sys-color-primary-container);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.now-playing-icon {
|
|
69
|
+
color: var(--md-sys-color-primary);
|
|
70
|
+
font-size: 18px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.empty-state {
|
|
74
|
+
padding: 32px;
|
|
75
|
+
text-align: center;
|
|
76
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
77
|
+
font-size: 0.9rem;
|
|
78
|
+
}
|
|
79
|
+
`;
|
|
80
|
+
}
|
|
81
|
+
render() {
|
|
82
|
+
let e = this.playerState?.items || [], t = this.playerState?.currentIndex ?? -1;
|
|
83
|
+
return a`
|
|
84
|
+
<div class="playlist-header">${this.header}</div>
|
|
85
|
+
|
|
86
|
+
${e.length === 0 ? a`<div class="empty-state">${this.emptyText}</div>` : a`
|
|
87
|
+
<md-list>
|
|
88
|
+
${e.map((e, n) => a`
|
|
89
|
+
<md-list-item
|
|
90
|
+
?selected=${n === t}
|
|
91
|
+
@click=${() => this.playerState?.select(n)}
|
|
92
|
+
>
|
|
93
|
+
<div slot="headline">${e.title || "Untitled Track"}</div>
|
|
94
|
+
<div slot="supporting-text">${e.artist || "Unknown Artist"}</div>
|
|
95
|
+
${n === t ? a`<md-icon slot="start" class="now-playing-icon"
|
|
96
|
+
>${this.playerState?.isPlaying ? "graphic_eq" : "play_arrow"}</md-icon
|
|
97
|
+
>` : a`<md-icon slot="start">music_note</md-icon>`}
|
|
98
|
+
</md-list-item>
|
|
99
|
+
`)}
|
|
100
|
+
</md-list>
|
|
101
|
+
`}
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
n([e({
|
|
106
|
+
context: t,
|
|
107
|
+
subscribe: !0
|
|
108
|
+
})], c.prototype, "playerState", void 0), n([s({ type: String })], c.prototype, "header", void 0), n([s({ type: String })], c.prototype, "emptyText", void 0), c = n([o("ui-playlist")], c);
|
|
109
|
+
export { c as UiPlaylist };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { __decorate as e } from "
|
|
2
|
-
import { applyCanvasEdgeFade as t } from "
|
|
1
|
+
import { __decorate as e } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
2
|
+
import { applyCanvasEdgeFade as t } from "../../utils/audio-utils.js";
|
|
3
3
|
import { LitElement as n, css as r, html as i } from "lit";
|
|
4
4
|
import { customElement as a, property as o, query as s } from "lit/decorators.js";
|
|
5
5
|
var c = class extends n {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __decorate as e } from "
|
|
1
|
+
import { __decorate as e } from "../../_virtual/_@oxc-project_runtime@0.113.0/helpers/decorate.js";
|
|
2
2
|
import { LitElement as t, css as n, html as r } from "lit";
|
|
3
3
|
import { customElement as i, property as a } from "lit/decorators.js";
|
|
4
4
|
import "@material/web/button/text-button.js";
|