add Picture component for displaying images in articles with h/v/s layout support

This commit is contained in:
tmshv committed 2021-09-21 16:07:30 +03:00
1 parent 1bd80aa0b2
commit a55d474336
7 files changed
+75 -75

No files matched your search

+9 -11
View File
@@ -1,5 +1,4 @@
import Head from 'next/head'
import Image from 'next/image'
import { App } from 'src/components/App'
import { tail } from 'lodash'
import { Page } from 'src/components/Page'
@@ -16,6 +15,7 @@ import { paramsToSlug } from '@/remote/lib'
import { PageGrid } from '@/components/PageGrid'
import { useRouter } from 'next/router'
import { FileCard } from '@/components/FIleCard'
import { Picture } from '@/components/Picture'
async function getUrls() {
let urls = []
@@ -114,16 +114,14 @@ const Index: NextPage<Props> = props => {
case 'image':
return (
<figure key={i} className="kazimir__image">
<Image
src={x.data.src}
alt={x.data.alt}
width={x.data.width}
height={x.data.height}
layout={'responsive'}
/>
<figcaption>{x.data.caption}</figcaption>
</figure>
<Picture
key={i}
src={x.data.src}
alt={x.data.alt}
width={x.data.width}
height={x.data.height}
caption={x.data.caption}
/>
)
case 'file':
-1
View File
@@ -4,7 +4,6 @@ import 'src/style/style.css'
import 'src/style/content.css'
import 'src/style/article.css'
import 'src/style/marker/marker-table.css'
import 'src/style/kazimir/image.css'
import 'src/style/kazimir/video.css'
import App from 'next/app'
-36
View File
@@ -1,36 +0,0 @@
import s from './styles.module.css'
import { memo, useRef, useEffect, useCallback } from 'react'
export type ImageProps = {
style?: React.CSSProperties
src: string
alt?: string
srcSet?: string
}
export const Image: React.FC<ImageProps> = memo(props => {
const ref = useRef<HTMLImageElement>()
const onLoad = useCallback((event) => {
event.target.classList.add('loaded')
event.target.classList.remove('pending')
}, [])
useEffect(() => {
if (ref.current) {
ref.current.classList.add('pending')
}
})
return (
<img
ref={ref}
onLoad={onLoad}
className={s.image}
style={props.style}
alt={props.alt}
src={props.src}
srcSet={props.srcSet}
/>
)
})
-12
View File
@@ -1,12 +0,0 @@
.image {
width: 100%;
display: block;
}
.image.pending {
/* opacity: 0; */
}
.image.loaded {
/* opacity: 1; */
}
+48
View File
@@ -0,0 +1,48 @@
import s from './picture.module.css'
import { memo } from 'react'
import Image from 'next/image'
import { Pic } from '@/types'
const modifiers = new Map([
['square', s.square],
['vertical', s.vertical],
['horizontal', ''],
])
function size(w: number, h: number, tolerance: number) {
const r = w / h
if (r < 1 && r > tolerance) {
return 'square'
}
if (w < h) {
return 'vertical'
}
return 'horizontal'
}
export type PictureProps = Pic & {
style?: React.CSSProperties
}
export const Picture: React.FC<PictureProps> = memo(props => {
const ss = size(props.width, props.height, 0.95)
const layout = modifiers.get(ss)
return (
<figure className={`${s.pic} ${layout}`}>
<Image
src={props.src}
alt={props.alt}
width={props.width}
height={props.height}
layout={'responsive'}
/>
{!props.caption ? null : (
<figcaption>{props.caption} ({props.width}x{props.height})</figcaption>
)}
</figure>
)
})
@@ -1,22 +1,23 @@
.kazimir__image {
.pic {
/* position: relative; */
/* width: calc(100% + var(--kazimir-image-increase)); */
/* margin-left: calc(-0.5 * var(--kazimir-image-increase)); */
margin-bottom: var(--size-xl);
}
.kazimir__image p {
margin-left: calc(0.5 * var(--kazimir-image-increase));
.pic.vertical {
max-width: 60%;
}
.kazimir__image img {
.pic.square {
max-width: 80%;
}
.pic img {
border-radius: var(--radius);
max-width: 100%;
max-height: 35em;
}
.kazimir__image figcaption {
.pic figcaption {
color: var(--color-text);
font-size: var(--font-size-second);
font-style: italic;
+9 -7
View File
@@ -98,6 +98,14 @@ export type ImageDefinition = {
alt?: string
}
export type Pic = {
src: string
alt?: string
width: number
height: number
caption?: string
}
export type TextToken = {
token: 'text'
data: string
@@ -105,13 +113,7 @@ export type TextToken = {
export type ImageToken = {
token: 'image'
data: {
src: string
alt: string
caption: string
width: number
height: number
}
data: Pic
}
export type FileTokenData = {