@stacksjs/defaults 0.70.162 → 0.70.164
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/app/Actions/README.md +1 -1
- package/app/Commands/README.md +1 -1
- package/app/Jobs/README.md +1 -1
- package/app/Listeners/README.md +1 -1
- package/app/Middleware/README.md +1 -1
- package/app/Models/README.md +1 -1
- package/app/Notifications/README.md +1 -1
- package/app/README.md +1 -1
- package/package.json +1 -1
- package/resources/assets/styles/README.md +1 -1
- package/resources/components/Audio.stx +92 -0
- package/resources/components/Image.stx +59 -0
- package/resources/components/Video.stx +108 -0
- package/resources/components/index.ts +3 -0
- package/resources/emails/subscription-confirmation.stx +1 -1
- package/resources/functions/README.md +1 -1
- package/resources/plugins/preloader.ts +23 -0
- package/resources/views/index.stx +4 -4
package/app/Actions/README.md
CHANGED
|
@@ -52,7 +52,7 @@ For help, discussion about best practices, or any other conversation that would
|
|
|
52
52
|
|
|
53
53
|
For casual chit-chat with others using this package:
|
|
54
54
|
|
|
55
|
-
[Join the Stacks Discord Server](https://
|
|
55
|
+
[Join the Stacks Discord Server](https://stacksjs.com/discord)
|
|
56
56
|
|
|
57
57
|
## 📄 License
|
|
58
58
|
|
package/app/Commands/README.md
CHANGED
|
@@ -75,7 +75,7 @@ For help, discussion about best practices, or any other conversation that would
|
|
|
75
75
|
|
|
76
76
|
For casual chit-chat with others using this package:
|
|
77
77
|
|
|
78
|
-
[Join the Stacks Discord Server](https://
|
|
78
|
+
[Join the Stacks Discord Server](https://stacksjs.com/discord)
|
|
79
79
|
|
|
80
80
|
## 📄 License
|
|
81
81
|
|
package/app/Jobs/README.md
CHANGED
|
@@ -70,7 +70,7 @@ For help, discussion about best practices, or any other conversation that would
|
|
|
70
70
|
|
|
71
71
|
For casual chit-chat with others using this package:
|
|
72
72
|
|
|
73
|
-
[Join the Stacks Discord Server](https://
|
|
73
|
+
[Join the Stacks Discord Server](https://stacksjs.com/discord)
|
|
74
74
|
|
|
75
75
|
## 📄 License
|
|
76
76
|
|
package/app/Listeners/README.md
CHANGED
|
@@ -38,7 +38,7 @@ For help, discussion about best practices, or any other conversation that would
|
|
|
38
38
|
|
|
39
39
|
For casual chit-chat with others using this package:
|
|
40
40
|
|
|
41
|
-
[Join the Stacks Discord Server](https://
|
|
41
|
+
[Join the Stacks Discord Server](https://stacksjs.com/discord)
|
|
42
42
|
|
|
43
43
|
## 📄 License
|
|
44
44
|
|
package/app/Middleware/README.md
CHANGED
|
@@ -39,7 +39,7 @@ For help, discussion about best practices, or any other conversation that would
|
|
|
39
39
|
|
|
40
40
|
For casual chit-chat with others using this package:
|
|
41
41
|
|
|
42
|
-
[Join the Stacks Discord Server](https://
|
|
42
|
+
[Join the Stacks Discord Server](https://stacksjs.com/discord)
|
|
43
43
|
|
|
44
44
|
## 📄 License
|
|
45
45
|
|
package/app/Models/README.md
CHANGED
|
@@ -22,7 +22,7 @@ For help, discussion about best practices, or any other conversation that would
|
|
|
22
22
|
|
|
23
23
|
For casual chit-chat with others using this package:
|
|
24
24
|
|
|
25
|
-
[Join the Stacks Discord Server](https://
|
|
25
|
+
[Join the Stacks Discord Server](https://stacksjs.com/discord)
|
|
26
26
|
|
|
27
27
|
## 📄 License
|
|
28
28
|
|
|
@@ -22,7 +22,7 @@ For help, discussion about best practices, or any other conversation that would
|
|
|
22
22
|
|
|
23
23
|
For casual chit-chat with others using this package:
|
|
24
24
|
|
|
25
|
-
[Join the Stacks Discord Server](https://
|
|
25
|
+
[Join the Stacks Discord Server](https://stacksjs.com/discord)
|
|
26
26
|
|
|
27
27
|
## 📄 License
|
|
28
28
|
|
package/app/README.md
CHANGED
|
@@ -14,7 +14,7 @@ For help, discussion about best practices, or any other conversation that would
|
|
|
14
14
|
|
|
15
15
|
For casual chit-chat with others using this package:
|
|
16
16
|
|
|
17
|
-
[Join the Stacks Discord Server](https://
|
|
17
|
+
[Join the Stacks Discord Server](https://stacksjs.com/discord)
|
|
18
18
|
|
|
19
19
|
## 📄 License
|
|
20
20
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/defaults",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.70.
|
|
5
|
+
"version": "0.70.164",
|
|
6
6
|
"description": "Default Stacks scaffold resources (views, layouts, components, preloader) — shipped so apps consuming the framework from node_modules get the same fallback resources a vendored checkout provides. Source of truth: storage/framework/defaults.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"license": "MIT",
|
|
@@ -10,7 +10,7 @@ For help, discussion about best practices, or any other conversation that would
|
|
|
10
10
|
|
|
11
11
|
For casual chit-chat with others using this package:
|
|
12
12
|
|
|
13
|
-
[Join the Stacks Discord Server](https://
|
|
13
|
+
[Join the Stacks Discord Server](https://stacksjs.com/discord)
|
|
14
14
|
|
|
15
15
|
## 📄 License
|
|
16
16
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface AudioSource { src: string, type?: string }
|
|
3
|
+
interface AudioDrm {
|
|
4
|
+
widevine?: { url: string, headers?: Record<string, string> }
|
|
5
|
+
playready?: { url: string, headers?: Record<string, string> }
|
|
6
|
+
fairplay?: { url: string, certificateUrl: string, headers?: Record<string, string> }
|
|
7
|
+
}
|
|
8
|
+
interface AudioTrack { src: string, kind: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata', srclang?: string, label?: string, default?: boolean }
|
|
9
|
+
interface AudioProps {
|
|
10
|
+
src: string
|
|
11
|
+
sources?: AudioSource[]
|
|
12
|
+
drm?: AudioDrm
|
|
13
|
+
tracks?: AudioTrack[]
|
|
14
|
+
title?: string
|
|
15
|
+
artist?: string
|
|
16
|
+
artwork?: string
|
|
17
|
+
waveform?: string
|
|
18
|
+
controls?: boolean
|
|
19
|
+
autoplay?: boolean
|
|
20
|
+
loop?: boolean
|
|
21
|
+
muted?: boolean
|
|
22
|
+
preload?: 'none' | 'metadata' | 'auto'
|
|
23
|
+
crossorigin?: 'anonymous' | 'use-credentials'
|
|
24
|
+
class?: string
|
|
25
|
+
}
|
|
26
|
+
const props = defineProps<AudioProps>()
|
|
27
|
+
const src = props.src || ''
|
|
28
|
+
const sources = props.sources || []
|
|
29
|
+
const tracks = props.tracks || []
|
|
30
|
+
const title = props.title || 'Audio player'
|
|
31
|
+
const artist = props.artist || ''
|
|
32
|
+
const artwork = props.artwork || ''
|
|
33
|
+
const waveform = props.waveform || ''
|
|
34
|
+
const controls = props.controls !== false
|
|
35
|
+
const preload = props.preload || 'metadata'
|
|
36
|
+
const crossorigin = props.crossorigin || ''
|
|
37
|
+
const className = props.class || ''
|
|
38
|
+
const playerSources = (sources.length ? sources : src ? [{ src }] : []).map(source => props.drm && (source.type === 'application/dash+xml' || source.src.split(/[?#]/, 1)[0].toLowerCase().endsWith('.mpd')) ? { ...source, type: 'application/dash+xml', drm: props.drm } : source)
|
|
39
|
+
const playerTracks = tracks.map(track => ({ ...track, language: track.srclang }))
|
|
40
|
+
const playerConfig = JSON.stringify({ sources: playerSources, tracks: playerTracks, ...(props.drm ? { drm: props.drm } : {}) }).replaceAll('<', '\\u003c').replaceAll('>', '\\u003e').replaceAll('&', '\\u0026')
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<script client>
|
|
44
|
+
import { registerElements } from 'ts-video-player/elements'
|
|
45
|
+
registerElements()
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<figure class="m-0 overflow-hidden rounded-2xl bg-white shadow-sm ring-1 ring-stone-200 dark:bg-stone-950 dark:ring-stone-800 {{ className }}">
|
|
49
|
+
<div class="flex gap-4 items-center p-4 sm:p-5">
|
|
50
|
+
@if(artwork)
|
|
51
|
+
<img src="{{ artwork }}" alt="" width="72" height="72" loading="lazy" decoding="async" class="object-cover shrink-0 h-18 w-18 ring-1 ring-black/5 rounded-xl dark:ring-white/10">
|
|
52
|
+
@else
|
|
53
|
+
<div class="flex items-center justify-center shrink-0 h-18 w-18 text-stone-500 dark:text-stone-400 bg-stone-100 dark:bg-stone-900 rounded-xl" aria-hidden="true"><span class="h-7 w-7 i-hugeicons-music-note-01"></span></div>
|
|
54
|
+
@endif
|
|
55
|
+
<div class="flex-1 min-w-0">
|
|
56
|
+
<figcaption class="font-semibold text-sm text-stone-950 truncate dark:text-white">{{ title }}</figcaption>
|
|
57
|
+
@if(artist)<p class="mt-0.5 text-sm text-stone-500 truncate dark:text-stone-400">{{ artist }}</p>@endif
|
|
58
|
+
@if(waveform)<img src="{{ waveform }}" alt="" loading="lazy" decoding="async" class="object-cover mt-3 h-10 w-full opacity-70 dark:opacity-80">@endif
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
<div class="p-3 bg-stone-950 border-stone-100 border-t dark:border-stone-800">
|
|
62
|
+
<video-player src="{{ src }}" title="{{ title }}" data-media-config="{{ playerConfig }}" @if(controls) controls @endif @if(props.autoplay) autoplay @endif @if(props.loop) loop @endif @if(props.muted) muted @endif preload="{{ preload }}" @if(crossorigin) crossorigin="{{ crossorigin }}" keep-alive aria-label="{{ title }}" class="block overflow-hidden relative h-16 w-full text-white rounded-xl focus-within:ring-2 focus-within:ring-sky-500">
|
|
63
|
+
<media-error-display></media-error-display>
|
|
64
|
+
<audio data-native-fallback src="{{ src }}" @if(controls) controls @endif @if(props.autoplay) autoplay @endif @if(props.loop) loop @endif @if(props.muted) muted @endif preload="{{ preload }}" @if(crossorigin) crossorigin="{{ crossorigin }}" @endif aria-label="{{ title }}" class="block h-16 w-full accent-sky-500">
|
|
65
|
+
@foreach (sources as source)<source src="{{ source.src }}" @if(source.type) type="{{ source.type }}" @endif>@endforeach
|
|
66
|
+
@foreach (tracks as track)<track src="{{ track.src }}" kind="{{ track.kind }}" @if(track.srclang) srclang="{{ track.srclang }}" @endif @if(track.label) label="{{ track.label }}" @endif @if(track.default) default @endif>@endforeach
|
|
67
|
+
Your browser does not support audio playback.
|
|
68
|
+
</audio>
|
|
69
|
+
@if(controls)
|
|
70
|
+
<video-skin>
|
|
71
|
+
<media-seek-button slot="left" seconds="-10" aria-label="Back 10 seconds"></media-seek-button>
|
|
72
|
+
<media-play-button slot="left" aria-label="Play or pause"></media-play-button>
|
|
73
|
+
<media-seek-button slot="left" seconds="10" aria-label="Forward 10 seconds"></media-seek-button>
|
|
74
|
+
<media-time-group slot="center" class="font-mono tabular-nums text-xs"></media-time-group>
|
|
75
|
+
<media-progress-bar slot="center" @if(waveform) waveform="{{ waveform }}" @endif aria-label="Audio progress"></media-progress-bar>
|
|
76
|
+
<media-mute-button slot="right" aria-label="Mute or unmute"></media-mute-button>
|
|
77
|
+
<media-volume-slider slot="right" aria-label="Volume"></media-volume-slider>
|
|
78
|
+
<media-playback-rate-button slot="right" rates="0.5,0.75,1,1.25,1.5,2" aria-label="Playback speed"></media-playback-rate-button>
|
|
79
|
+
<media-settings-menu slot="right" aria-label="Audio settings"></media-settings-menu>
|
|
80
|
+
<media-airplay-button slot="right" aria-label="Play on AirPlay"></media-airplay-button>
|
|
81
|
+
<media-remote-playback-button slot="right" aria-label="Play on another device"></media-remote-playback-button>
|
|
82
|
+
</video-skin>
|
|
83
|
+
@endif
|
|
84
|
+
</video-player>
|
|
85
|
+
</div>
|
|
86
|
+
</figure>
|
|
87
|
+
|
|
88
|
+
<style>
|
|
89
|
+
video-player:not(:defined) video-skin { display: none; }
|
|
90
|
+
video-player:defined > [data-native-fallback] { display: none; }
|
|
91
|
+
@media (prefers-reduced-motion: reduce) { video-player, video-player * { transition-duration: 0.01ms !important; } }
|
|
92
|
+
</style>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface ImageSource { type: string, srcset: string, media?: string }
|
|
3
|
+
interface ImageProps {
|
|
4
|
+
src: string
|
|
5
|
+
alt: string
|
|
6
|
+
width?: number
|
|
7
|
+
height?: number
|
|
8
|
+
aspectRatio?: string
|
|
9
|
+
srcset?: string
|
|
10
|
+
sizes?: string
|
|
11
|
+
sources?: ImageSource[]
|
|
12
|
+
loading?: 'lazy' | 'eager'
|
|
13
|
+
decoding?: 'async' | 'sync' | 'auto'
|
|
14
|
+
fetchpriority?: 'high' | 'low' | 'auto'
|
|
15
|
+
priority?: boolean
|
|
16
|
+
decorative?: boolean
|
|
17
|
+
fit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'
|
|
18
|
+
position?: string
|
|
19
|
+
placeholder?: string
|
|
20
|
+
class?: string
|
|
21
|
+
}
|
|
22
|
+
const props = defineProps<ImageProps>()
|
|
23
|
+
if (!props.decorative && !props.alt?.trim()) throw new TypeError('Image alt text is required unless decorative is true')
|
|
24
|
+
const src = props.src || ''
|
|
25
|
+
const alt = props.decorative ? '' : props.alt || ''
|
|
26
|
+
const width = props.width || ''
|
|
27
|
+
const height = props.height || ''
|
|
28
|
+
const ratio = props.aspectRatio || (width && height ? `${width} / ${height}` : '')
|
|
29
|
+
const srcset = props.srcset || ''
|
|
30
|
+
const sizes = props.sizes || (srcset ? '100vw' : '')
|
|
31
|
+
const sources = props.sources || []
|
|
32
|
+
const loading = props.priority ? 'eager' : props.loading || 'lazy'
|
|
33
|
+
const decoding = props.decoding || 'async'
|
|
34
|
+
const priority = props.priority ? 'high' : props.fetchpriority || 'auto'
|
|
35
|
+
const fit = props.fit || 'cover'
|
|
36
|
+
const position = props.position || 'center'
|
|
37
|
+
const placeholder = props.placeholder || ''
|
|
38
|
+
const className = props.class || ''
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<picture class="relative block overflow-hidden bg-stone-100 dark:bg-stone-900 {{ className }}" @if(ratio) style="aspect-ratio: {{ ratio }};" @endif>
|
|
42
|
+
@foreach (sources as source)
|
|
43
|
+
<source type="{{ source.type }}" srcset="{{ source.srcset }}" @if(source.media) media="{{ source.media }}" @endif @if(sizes) sizes="{{ sizes }}" @endif>
|
|
44
|
+
@endforeach
|
|
45
|
+
<img
|
|
46
|
+
src="{{ src }}"
|
|
47
|
+
alt="{{ alt }}"
|
|
48
|
+
@if(width) width="{{ width }}" @endif
|
|
49
|
+
@if(height) height="{{ height }}" @endif
|
|
50
|
+
@if(srcset) srcset="{{ srcset }}" @endif
|
|
51
|
+
@if(sizes) sizes="{{ sizes }}" @endif
|
|
52
|
+
loading="{{ loading }}"
|
|
53
|
+
decoding="{{ decoding }}"
|
|
54
|
+
fetchpriority="{{ priority }}"
|
|
55
|
+
@if(props.decorative) aria-hidden="true" @endif
|
|
56
|
+
class="h-full w-full"
|
|
57
|
+
style="object-fit: {{ fit }}; object-position: {{ position }}; @if(placeholder) background: {{ placeholder }} center / cover no-repeat; @endif"
|
|
58
|
+
>
|
|
59
|
+
</picture>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface VideoSource { src: string, type?: string }
|
|
3
|
+
interface VideoDrm {
|
|
4
|
+
widevine?: { url: string, headers?: Record<string, string> }
|
|
5
|
+
playready?: { url: string, headers?: Record<string, string> }
|
|
6
|
+
fairplay?: { url: string, certificateUrl: string, headers?: Record<string, string> }
|
|
7
|
+
}
|
|
8
|
+
interface VideoTrack { src: string, kind: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata', srclang?: string, label?: string, default?: boolean }
|
|
9
|
+
interface VideoProps {
|
|
10
|
+
src: string
|
|
11
|
+
sources?: VideoSource[]
|
|
12
|
+
drm?: VideoDrm
|
|
13
|
+
tracks?: VideoTrack[]
|
|
14
|
+
poster?: string
|
|
15
|
+
title?: string
|
|
16
|
+
width?: number
|
|
17
|
+
height?: number
|
|
18
|
+
aspectRatio?: string
|
|
19
|
+
controls?: boolean
|
|
20
|
+
autoplay?: boolean
|
|
21
|
+
loop?: boolean
|
|
22
|
+
muted?: boolean
|
|
23
|
+
playsinline?: boolean
|
|
24
|
+
preload?: 'none' | 'metadata' | 'auto'
|
|
25
|
+
crossorigin?: 'anonymous' | 'use-credentials'
|
|
26
|
+
controlslist?: string
|
|
27
|
+
disablePictureInPicture?: boolean
|
|
28
|
+
class?: string
|
|
29
|
+
}
|
|
30
|
+
const props = defineProps<VideoProps>()
|
|
31
|
+
const src = props.src || ''
|
|
32
|
+
const sources = props.sources || []
|
|
33
|
+
const tracks = props.tracks || []
|
|
34
|
+
const title = props.title || 'Video player'
|
|
35
|
+
const poster = props.poster || ''
|
|
36
|
+
const width = props.width || ''
|
|
37
|
+
const height = props.height || ''
|
|
38
|
+
const ratio = props.aspectRatio || (width && height ? `${width} / ${height}` : '16 / 9')
|
|
39
|
+
const controls = props.controls !== false
|
|
40
|
+
const inline = props.playsinline !== false
|
|
41
|
+
const preload = props.preload || 'metadata'
|
|
42
|
+
const crossorigin = props.crossorigin || ''
|
|
43
|
+
const controlslist = props.controlslist || 'nodownload'
|
|
44
|
+
const className = props.class || ''
|
|
45
|
+
const playerSources = (sources.length ? sources : src ? [{ src }] : []).map(source => props.drm && (source.type === 'application/dash+xml' || source.src.split(/[?#]/, 1)[0].toLowerCase().endsWith('.mpd')) ? { ...source, type: 'application/dash+xml', drm: props.drm } : source)
|
|
46
|
+
const playerTracks = tracks.map(track => ({ ...track, language: track.srclang }))
|
|
47
|
+
const playerConfig = JSON.stringify({ sources: playerSources, tracks: playerTracks, ...(props.drm ? { drm: props.drm } : {}) }).replaceAll('<', '\\u003c').replaceAll('>', '\\u003e').replaceAll('&', '\\u0026')
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<script client>
|
|
51
|
+
import { registerElements } from 'ts-video-player/elements'
|
|
52
|
+
registerElements()
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<figure class="m-0 {{ className }}">
|
|
56
|
+
<video-player
|
|
57
|
+
src="{{ src }}"
|
|
58
|
+
data-media-config="{{ playerConfig }}"
|
|
59
|
+
@if(poster) poster="{{ poster }}" @endif
|
|
60
|
+
@if(controls) controls @endif
|
|
61
|
+
@if(props.autoplay) autoplay @endif
|
|
62
|
+
@if(props.loop) loop @endif
|
|
63
|
+
@if(props.muted) muted @endif
|
|
64
|
+
@if(inline) playsinline @endif
|
|
65
|
+
preload="{{ preload }}"
|
|
66
|
+
@if(crossorigin) crossorigin="{{ crossorigin }}" @endif
|
|
67
|
+
controlslist="{{ controlslist }}"
|
|
68
|
+
@if(props.disablePictureInPicture) disable-picture-in-picture @endif
|
|
69
|
+
keep-alive
|
|
70
|
+
aria-label="{{ title }}"
|
|
71
|
+
class="block overflow-hidden relative w-full bg-black ring-1 ring-black/10 rounded-2xl dark:ring-white/10 focus-within:ring-2 focus-within:ring-sky-500 shadow-sm group"
|
|
72
|
+
style="aspect-ratio: {{ ratio }};"
|
|
73
|
+
>
|
|
74
|
+
<media-error-display></media-error-display>
|
|
75
|
+
<video data-native-fallback src="{{ src }}" @if(poster) poster="{{ poster }}" @endif @if(width) width="{{ width }}" @endif @if(height) height="{{ height }}" @endif @if(controls) controls @endif @if(props.autoplay) autoplay @endif @if(props.loop) loop @endif @if(props.muted) muted @endif @if(inline) playsinline @endif preload="{{ preload }}" @if(crossorigin) crossorigin="{{ crossorigin }}" @endif controlslist="{{ controlslist }}" @if(props.disablePictureInPicture) disablepictureinpicture @endif aria-label="{{ title }}" class="object-contain h-full w-full">
|
|
76
|
+
@foreach (sources as source)
|
|
77
|
+
<source src="{{ source.src }}" @if(source.type) type="{{ source.type }}" @endif>
|
|
78
|
+
@endforeach
|
|
79
|
+
@foreach (tracks as track)
|
|
80
|
+
<track src="{{ track.src }}" kind="{{ track.kind }}" @if(track.srclang) srclang="{{ track.srclang }}" @endif @if(track.label) label="{{ track.label }}" @endif @if(track.default) default @endif>
|
|
81
|
+
@endforeach
|
|
82
|
+
Your browser does not support video playback.
|
|
83
|
+
</video>
|
|
84
|
+
<video-skin>
|
|
85
|
+
<media-seek-button slot="left" seconds="-10" aria-label="Back 10 seconds"></media-seek-button>
|
|
86
|
+
<media-play-button slot="left" aria-label="Play or pause"></media-play-button>
|
|
87
|
+
<media-seek-button slot="left" seconds="10" aria-label="Forward 10 seconds"></media-seek-button>
|
|
88
|
+
<media-live-button slot="left" aria-label="Go to live edge"></media-live-button>
|
|
89
|
+
<media-time-group slot="center" class="font-mono tabular-nums text-xs"></media-time-group>
|
|
90
|
+
<media-progress-bar slot="center" previews="metadata" aria-label="Video progress"></media-progress-bar>
|
|
91
|
+
<media-mute-button slot="right" aria-label="Mute or unmute"></media-mute-button>
|
|
92
|
+
<media-volume-slider slot="right" aria-label="Volume"></media-volume-slider>
|
|
93
|
+
<media-playback-rate-button slot="right" rates="0.5,0.75,1,1.25,1.5,2" aria-label="Playback speed"></media-playback-rate-button>
|
|
94
|
+
<media-settings-menu slot="right" aria-label="Video settings"></media-settings-menu>
|
|
95
|
+
<media-airplay-button slot="right" aria-label="Play on AirPlay"></media-airplay-button>
|
|
96
|
+
<media-remote-playback-button slot="right" aria-label="Play on another device"></media-remote-playback-button>
|
|
97
|
+
<media-pip-button slot="right" aria-label="Picture in Picture"></media-pip-button>
|
|
98
|
+
<media-fullscreen-button slot="right" aria-label="Fullscreen"></media-fullscreen-button>
|
|
99
|
+
</video-skin>
|
|
100
|
+
</video-player>
|
|
101
|
+
<figcaption class="sr-only">{{ title }}</figcaption>
|
|
102
|
+
</figure>
|
|
103
|
+
|
|
104
|
+
<style>
|
|
105
|
+
video-player:not(:defined) video-skin { display: none; }
|
|
106
|
+
video-player:defined > [data-native-fallback] { display: none; }
|
|
107
|
+
@media (prefers-reduced-motion: reduce) { video-player, video-player * { transition-duration: 0.01ms !important; } }
|
|
108
|
+
</style>
|
|
@@ -11,3 +11,6 @@ export { default as SidebarModern } from './Dashboard/SidebarModern.stx'
|
|
|
11
11
|
|
|
12
12
|
// Dashboard and UI components
|
|
13
13
|
export * from './Dashboard'
|
|
14
|
+
export { default as Audio } from './Audio.stx'
|
|
15
|
+
export { default as Image } from './Image.stx'
|
|
16
|
+
export { default as Video } from './Video.stx'
|
|
@@ -68,7 +68,7 @@ const year = props.year || new Date().getFullYear()
|
|
|
68
68
|
·
|
|
69
69
|
<a href="https://github.com/stacksjs/stacks" style="color: #888; text-decoration: none;">GitHub</a>
|
|
70
70
|
·
|
|
71
|
-
<a href="https://
|
|
71
|
+
<a href="https://stacksjs.com/discord" style="color: #888; text-decoration: none;">Discord</a>
|
|
72
72
|
</td>
|
|
73
73
|
</tr>
|
|
74
74
|
</table>
|
|
@@ -19,7 +19,7 @@ For help, discussion about best practices, or any other conversation that would
|
|
|
19
19
|
|
|
20
20
|
For casual chit-chat with others using this package:
|
|
21
21
|
|
|
22
|
-
[Join the Stacks Discord Server](https://
|
|
22
|
+
[Join the Stacks Discord Server](https://stacksjs.com/discord)
|
|
23
23
|
|
|
24
24
|
## 📄 License
|
|
25
25
|
|
|
@@ -96,6 +96,29 @@ if (!isRepl && !isPostinstall) {
|
|
|
96
96
|
// overrides while applying environment-specific file precedence. quiet: true
|
|
97
97
|
// prevents duplicate logging across multiple processes.
|
|
98
98
|
autoLoadEnv({ quiet: true, env: process.env.APP_ENV })
|
|
99
|
+
|
|
100
|
+
// Tell stx and ts-cloud where their state lives before anything imports them.
|
|
101
|
+
// Both keep it under `storage/` in a Stacks app rather than in a dot-directory
|
|
102
|
+
// at the project root, both take the location from their own config, and both
|
|
103
|
+
// read an environment variable ahead of that config — which is also what
|
|
104
|
+
// carries the answer into every process a command spawns. Setting it here
|
|
105
|
+
// means no boot order can leave a library writing to `.stx` / `.ts-cloud`.
|
|
106
|
+
//
|
|
107
|
+
// Guarded because this preload runs before ANY command: an app resolving
|
|
108
|
+
// `@stacksjs/path` from npm can legitimately be on a published version that
|
|
109
|
+
// predates this helper, and a bare call there throws
|
|
110
|
+
// `applyRuntimeDirectoryEnv is not a function` out of a bunfig preload,
|
|
111
|
+
// which takes down every `buddy` invocation including the `install` and
|
|
112
|
+
// `upgrade` that would fix it. Falling through leaves stx and ts-cloud on
|
|
113
|
+
// their own defaults, which is degraded but recoverable.
|
|
114
|
+
const pathPkg = '@stacksjs/' + 'path'
|
|
115
|
+
const { applyRuntimeDirectoryEnv } = await import('../../../core/path/src/index.ts')
|
|
116
|
+
.catch(() => import(pathPkg))
|
|
117
|
+
|
|
118
|
+
if (typeof applyRuntimeDirectoryEnv === 'function')
|
|
119
|
+
applyRuntimeDirectoryEnv()
|
|
120
|
+
else
|
|
121
|
+
console.warn('[stacks] installed @stacksjs/path has no applyRuntimeDirectoryEnv; stx and ts-cloud will use their default state directories. Run `buddy upgrade` to refresh the framework packages.')
|
|
99
122
|
}
|
|
100
123
|
|
|
101
124
|
// stx template engine plugin
|
|
@@ -325,7 +325,7 @@
|
|
|
325
325
|
data-icon-id="discord"
|
|
326
326
|
data-icon-type="link"
|
|
327
327
|
data-icon-section=""
|
|
328
|
-
data-icon-url="https://
|
|
328
|
+
data-icon-url="https://stacksjs.com/discord"
|
|
329
329
|
style="left: 620px; top: 260px;"
|
|
330
330
|
>
|
|
331
331
|
<div class="desktop-icon-image">💬</div>
|
|
@@ -1768,7 +1768,7 @@ export default {
|
|
|
1768
1768
|
|
|
1769
1769
|
<div style="background: #e0f2ff; border: 2px solid #0284c7; padding: 12px; border-radius: 4px; font-size: 11px;">
|
|
1770
1770
|
<strong>💡 Quick Links:</strong> For general inquiries, email us at <a href="mailto:hello@stacksjs.com" style="color: #0831d9;">hello@stacksjs.com</a>
|
|
1771
|
-
<br>For support questions, visit our <a href="https://
|
|
1771
|
+
<br>For support questions, visit our <a href="https://stacksjs.com/discord" target="_blank" style="color: #0831d9;">Discord community</a>
|
|
1772
1772
|
</div>
|
|
1773
1773
|
</div>
|
|
1774
1774
|
</div>
|
|
@@ -2607,7 +2607,7 @@ export default {
|
|
|
2607
2607
|
<div class="start-menu-item-icon">💖</div>
|
|
2608
2608
|
<div>Sponsor</div>
|
|
2609
2609
|
</button>
|
|
2610
|
-
<button class="start-menu-item" onclick="window.open('https://
|
|
2610
|
+
<button class="start-menu-item" onclick="window.open('https://stacksjs.com/discord', '_blank')">
|
|
2611
2611
|
<div class="start-menu-item-icon">💬</div>
|
|
2612
2612
|
<div>Discord</div>
|
|
2613
2613
|
</button>
|
|
@@ -2651,7 +2651,7 @@ export default {
|
|
|
2651
2651
|
<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
|
|
2652
2652
|
</svg>
|
|
2653
2653
|
</a>
|
|
2654
|
-
<a href="https://
|
|
2654
|
+
<a href="https://stacksjs.com/discord" target="_blank" class="quick-launch-icon" title="Discord">
|
|
2655
2655
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
2656
2656
|
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515a.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0a12.64 12.64 0 0 0-.617-1.25a.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057a19.9 19.9 0 0 0 5.993 3.03a.078.078 0 0 0 .084-.028a14.09 14.09 0 0 0 1.226-1.994a.076.076 0 0 0-.041-.106a13.107 13.107 0 0 1-1.872-.892a.077.077 0 0 1-.008-.128a10.2 10.2 0 0 0 .372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127a12.299 12.299 0 0 1-1.873.892a.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028a19.839 19.839 0 0 0 6.002-3.03a.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.956-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.955-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.946 2.418-2.157 2.418z"/>
|
|
2657
2657
|
</svg>
|