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 { asset } from '$fresh/runtime.ts'
|
||||||
|
import { Picture } from ':components/Picture.tsx'
|
||||||
|
|
||||||
export function SponsorCards() {
|
export function SponsorCards() {
|
||||||
return (
|
return (
|
||||||
|
@ -13,7 +14,12 @@ function SponsorCard(
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<a class='components__sponsor_card' href={href} target='_blank'>
|
<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>
|
</a>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
":components/": "./components/",
|
":components/": "./components/",
|
||||||
":islands/": "./islands/",
|
":islands/": "./islands/",
|
||||||
":src/": "./src/",
|
":src/": "./src/",
|
||||||
|
":types": "./types.ts",
|
||||||
"@cohabit/cohamail/": "./packages/@cohabit__cohamail@0.2.1/",
|
"@cohabit/cohamail/": "./packages/@cohabit__cohamail@0.2.1/",
|
||||||
"@cohabit/ressources_manager/": "./packages/@cohabit__ressources_manager@0.1.3/",
|
"@cohabit/ressources_manager/": "./packages/@cohabit__ressources_manager@0.1.3/",
|
||||||
"@deno/gfm": "jsr:@deno/gfm@^0.8.2",
|
"@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 { JsonValue } from '$std/json/common.ts'
|
||||||
import { decodeBase64 } from '@std/encoding/base64'
|
import { decodeBase64 } from '@std/encoding/base64'
|
||||||
import { JsonStringifyStream } from '@std/json'
|
import { JsonStringifyStream } from '@std/json'
|
||||||
|
@ -171,3 +172,22 @@ export function base64ToString(base64: string): string {
|
||||||
const bytes = decodeBase64(base64)
|
const bytes = decodeBase64(base64)
|
||||||
return new TextDecoder().decode(bytes)
|
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