Initial commit
This commit is contained in:
138
layouts/_default/baseof.html
Executable file
138
layouts/_default/baseof.html
Executable file
@@ -0,0 +1,138 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ .Site.LanguageCode | default "en" }}" class="dark">
|
||||
<head>
|
||||
{{- partial "head/meta.html" . -}}
|
||||
{{- partial "head/opengraph.html" . -}}
|
||||
{{- partial "head/twitter.html" . -}}
|
||||
{{- partial "head/json-ld.html" . -}}
|
||||
{{- partial "head/preload.html" . -}}
|
||||
{{- partial "head/favicon.html" . -}}
|
||||
|
||||
{{/* CSS - built by Tailwind CLI to static folder */}}
|
||||
<link rel="stylesheet" href="/css/main.css">
|
||||
</head>
|
||||
<body
|
||||
x-data
|
||||
hx-boost="true"
|
||||
hx-target="#main-content"
|
||||
hx-select="#main-content"
|
||||
hx-swap="innerHTML show:top"
|
||||
hx-push-url="true"
|
||||
class="text-text-primary min-h-screen flex flex-col"
|
||||
>
|
||||
{{/* WebGL Background Canvas (preserved across navigation) */}}
|
||||
<canvas
|
||||
id="webgl-bg"
|
||||
hx-preserve="true"
|
||||
class="fixed inset-0 -z-10 pointer-events-none"
|
||||
aria-hidden="true"
|
||||
></canvas>
|
||||
|
||||
{{- partial "header.html" . -}}
|
||||
|
||||
<main id="main-content" class="flex-1">
|
||||
{{- block "main" . }}{{- end -}}
|
||||
</main>
|
||||
|
||||
{{- partial "footer.html" . -}}
|
||||
|
||||
{{/* Persistent Audio Player (preserved across navigation) */}}
|
||||
<div id="audio-player-container" hx-preserve="true" class="fixed bottom-0 left-0 right-0 z-player">
|
||||
{{- partial "player.html" . -}}
|
||||
</div>
|
||||
|
||||
{{/* WebGL Visualizer Canvas (preserved) */}}
|
||||
<canvas
|
||||
id="visualizer"
|
||||
hx-preserve="true"
|
||||
class="fixed inset-0 pointer-events-none z-visualizer"
|
||||
aria-hidden="true"
|
||||
></canvas>
|
||||
|
||||
{{/* Alpine.js - data and stores defined before CDN loads */}}
|
||||
<script>
|
||||
// Define Alpine stores and components BEFORE Alpine loads
|
||||
document.addEventListener('alpine:init', () => {
|
||||
// Global audio store
|
||||
Alpine.store('audio', {
|
||||
currentTrack: null,
|
||||
isPlaying: false,
|
||||
progress: 0,
|
||||
duration: 0,
|
||||
volume: 0.8
|
||||
});
|
||||
|
||||
// Player UI component
|
||||
Alpine.data('playerUI', () => ({
|
||||
togglePlay() {
|
||||
window.__pivoine?.audioManager?.toggle();
|
||||
},
|
||||
seek(time) {
|
||||
window.__pivoine?.audioManager?.seek(parseFloat(time));
|
||||
},
|
||||
setVolume(v) {
|
||||
const volume = parseFloat(v);
|
||||
Alpine.store('audio').volume = volume;
|
||||
window.__pivoine?.audioManager?.setVolume(volume);
|
||||
localStorage.setItem('pivoine-volume', volume);
|
||||
},
|
||||
toggleMute() {
|
||||
const store = Alpine.store('audio');
|
||||
if (store.volume > 0) {
|
||||
this._previousVolume = store.volume;
|
||||
this.setVolume(0);
|
||||
} else {
|
||||
this.setVolume(this._previousVolume || 0.8);
|
||||
}
|
||||
},
|
||||
formatTime(seconds) {
|
||||
if (!seconds || isNaN(seconds)) return '0:00';
|
||||
const mins = Math.floor(seconds / 60);
|
||||
const secs = Math.floor(seconds % 60);
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
||||
},
|
||||
_previousVolume: 0.8
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
{{/* htmx */}}
|
||||
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||
|
||||
{{/* Alpine.js */}}
|
||||
<script defer src="https://unpkg.com/alpinejs@3.14.8/dist/cdn.min.js"></script>
|
||||
|
||||
{{/* Main JS - audio manager and visualizer */}}
|
||||
{{- $js := resources.Get "js/main.js" -}}
|
||||
{{- if $js -}}
|
||||
{{- $jsOpts := dict "format" "esm" -}}
|
||||
{{- if hugo.IsProduction -}}
|
||||
{{- $jsOpts = merge $jsOpts (dict "minify" true) -}}
|
||||
{{- end -}}
|
||||
{{- $js = $js | js.Build $jsOpts -}}
|
||||
{{- if hugo.IsProduction -}}
|
||||
{{- $js = $js | fingerprint -}}
|
||||
{{- end -}}
|
||||
<script type="module" src="{{ $js.RelPermalink }}"></script>
|
||||
{{- end -}}
|
||||
|
||||
{{/* Analytics */}}
|
||||
{{- if and .Site.Params.umami.enabled hugo.IsProduction -}}
|
||||
{{- partial "analytics.html" . -}}
|
||||
{{- end -}}
|
||||
|
||||
<script>
|
||||
// htmx config
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof htmx !== 'undefined') {
|
||||
htmx.config.globalViewTransitions = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Re-init components after htmx swap
|
||||
document.body.addEventListener('htmx:afterSwap', function() {
|
||||
window.dispatchEvent(new CustomEvent('page:loaded'));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user