feat(components): ✨ add new Picture
component
This commit is contained in:
parent
a2f872ae9d
commit
28397a383a
28
components/Picture.tsx
Normal file
28
components/Picture.tsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { unwrapSignalOrValue } from ':src/utils.ts'
|
||||
import { Ensure } from ':types'
|
||||
import { JSX } from 'preact'
|
||||
|
||||
export type PictureProps =
|
||||
& { formats: string[] }
|
||||
& Ensure<JSX.HTMLAttributes<HTMLImageElement>, 'src' | 'alt' | 'loading'>
|
||||
|
||||
export function Picture(
|
||||
{ formats, src, ...props }: PictureProps,
|
||||
) {
|
||||
const groups = unwrapSignalOrValue(src)?.match(/(?<path>.*)(?<ext>\.\w+)/)
|
||||
?.groups
|
||||
if (groups === undefined) {
|
||||
throw new SyntaxError(`unable to parse path of "${src.valueOf()}"`)
|
||||
}
|
||||
|
||||
const { path } = groups
|
||||
|
||||
return (
|
||||
<picture>
|
||||
{formats.map((format) => (
|
||||
<source type={`image/${format}`} srcset={`${path}.${format}`} />
|
||||
))}
|
||||
<img src={src} {...props} />
|
||||
</picture>
|
||||
)
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import { asset } from '$fresh/runtime.ts'
|
||||
import { Picture } from ':components/Picture.tsx'
|
||||
|
||||
export function SponsorCards() {
|
||||
return (
|
||||
|
@ -13,7 +14,12 @@ function SponsorCard(
|
|||
) {
|
||||
return (
|
||||
<a class='components__sponsor_card' href={href} target='_blank'>
|
||||
<img src={asset(src)} alt={alt} />
|
||||
<Picture
|
||||
src={asset(src)}
|
||||
alt={alt}
|
||||
loading={'lazy'}
|
||||
formats={['avif']}
|
||||
/>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
":components/": "./components/",
|
||||
":islands/": "./islands/",
|
||||
":src/": "./src/",
|
||||
":types": "./types.ts",
|
||||
"@cohabit/cohamail/": "./packages/@cohabit__cohamail@0.2.1/",
|
||||
"@cohabit/ressources_manager/": "./packages/@cohabit__ressources_manager@0.1.3/",
|
||||
"@deno/gfm": "jsr:@deno/gfm@^0.8.2",
|
||||
|
|
20
src/utils.ts
20
src/utils.ts
|
@ -1,3 +1,4 @@
|
|||
import { SignalLike } from '$fresh/src/types.ts'
|
||||
import { JsonValue } from '$std/json/common.ts'
|
||||
import { decodeBase64 } from '@std/encoding/base64'
|
||||
import { JsonStringifyStream } from '@std/json'
|
||||
|
@ -171,3 +172,22 @@ export function base64ToString(base64: string): string {
|
|||
const bytes = decodeBase64(base64)
|
||||
return new TextDecoder().decode(bytes)
|
||||
}
|
||||
|
||||
export function unwrapSignalOrValue<T>(valueOrSignal: T | SignalLike<T>): T {
|
||||
if (typeof valueOrSignal !== 'object') {
|
||||
return valueOrSignal
|
||||
}
|
||||
|
||||
if (valueOrSignal === null) {
|
||||
return valueOrSignal
|
||||
}
|
||||
|
||||
if (
|
||||
'value' in valueOrSignal && 'peek' in valueOrSignal &&
|
||||
'subscribe' in valueOrSignal
|
||||
) {
|
||||
return valueOrSignal.value
|
||||
}
|
||||
|
||||
return valueOrSignal
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue