add Picture component for displaying images in articles with h/v/s layout support
This commit is contained in:
1 parent
1bd80aa0b2
commit
a55d474336
7 files changed
+75
-75
No files matched your search
+9
-11
@@ -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':
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
)
|
||||
})
|
||||
@@ -1,12 +0,0 @@
|
||||
.image {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.image.pending {
|
||||
/* opacity: 0; */
|
||||
}
|
||||
|
||||
.image.loaded {
|
||||
/* opacity: 1; */
|
||||
}
|
||||
@@ -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
@@ -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 = {
|
||||
|
||||
Reference in new issue
Block a user