@@ -11,8 +11,8 @@ import type { DocumentContext } from './DocumentView';
1111export function Images ( props : BlockProps < DocumentBlockImages > ) {
1212 const { document, block, style, context, isEstimatedOffscreen } = props ;
1313
14- const isMultipleImages = block . nodes . length > 1 ;
15- const { align = 'center' } = block . data ;
14+ const hasMultipleImages = block . nodes . length > 1 ;
15+ const { align = 'center' , withFrame } = block . data ;
1616
1717 return (
1818 < div
@@ -24,7 +24,8 @@ export function Images(props: BlockProps<DocumentBlockImages>) {
2424 align === 'center' && 'justify-center' ,
2525 align === 'right' && 'justify-end' ,
2626 align === 'left' && 'justify-start' ,
27- isMultipleImages && [ 'grid' , 'grid-flow-col' ]
27+ hasMultipleImages && [ 'grid' , 'grid-flow-col' ] ,
28+ withFrame && [ 'rounded-2xl' , 'border' , 'border-neutral' ]
2829 ) }
2930 >
3031 { block . nodes . map ( ( node : any , _i : number ) => (
@@ -36,6 +37,7 @@ export function Images(props: BlockProps<DocumentBlockImages>) {
3637 siblings = { block . nodes . length }
3738 context = { context }
3839 isEstimatedOffscreen = { isEstimatedOffscreen }
40+ withFrame = { withFrame }
3941 />
4042 ) ) }
4143 </ div >
@@ -62,8 +64,9 @@ async function ImageBlock(props: {
6264 context : DocumentContext ;
6365 siblings : number ;
6466 isEstimatedOffscreen : boolean ;
67+ withFrame ?: boolean ;
6568} ) {
66- const { block, context, isEstimatedOffscreen } = props ;
69+ const { block, context, isEstimatedOffscreen, withFrame } = props ;
6770
6871 const [ src , darkSrc ] = await Promise . all ( [
6972 context . contentContext ? resolveContentRef ( block . data . ref , context . contentContext ) : null ,
@@ -77,33 +80,63 @@ async function ImageBlock(props: {
7780 }
7881
7982 return (
80- < Caption { ...props } fit >
81- < Image
82- alt = { block . data . alt ?? '' }
83- sizes = { imageBlockSizes }
84- resize = { context . contentContext ?. imageResizer }
85- sources = { {
86- light : {
87- src : src . href ,
88- size : src . file ?. dimensions ,
89- } ,
90- dark : darkSrc
91- ? {
92- src : darkSrc . href ,
93- size : darkSrc . file ?. dimensions ,
94- }
95- : null ,
96- } }
97- priority = { isEstimatedOffscreen ? 'lazy' : 'high' }
98- preload
99- zoom
100- inlineStyle = { {
101- maxWidth : '100%' ,
102- width : getImageDimension ( block . data . width , undefined ) ,
103- height : getImageDimension ( block . data . height , 'auto' ) ,
104- } }
105- />
106- </ Caption >
83+ < div className = { tcls ( 'relative' , 'overflow-hidden' ) } >
84+ { /* Frame grid */ }
85+ { withFrame && (
86+ < div
87+ className = { tcls (
88+ '-top-0.5' ,
89+ '-left-0.5' ,
90+ 'absolute' ,
91+ 'inset-px' ,
92+ 'opacity-50' ,
93+ 'bg-[length:24px_24px,24px_24px]' ,
94+ 'bg-[linear-gradient(to_right,_rgb(234,235,238)_1px,_transparent_1px),linear-gradient(to_bottom,_rgb(234,235,238)_1px,_transparent_1px)]' ,
95+ 'bg-repeat'
96+ ) }
97+ />
98+ ) }
99+
100+ { /* Shadow overlay */ }
101+ { withFrame && (
102+ < div
103+ className = { tcls (
104+ 'pointer-events-none absolute inset-0 rounded-2xl' ,
105+ 'shadow-[inset_0_0_10px_7px_rgba(255,255,255,0.9)]' ,
106+ 'dark:shadow-[inset_0_0_10px_7px_rgba(21,23,28,0.9)]'
107+ ) }
108+ />
109+ ) }
110+
111+ < Caption { ...props } fit >
112+ < Image
113+ alt = { block . data . alt ?? '' }
114+ sizes = { imageBlockSizes }
115+ resize = { context . contentContext ?. imageResizer }
116+ sources = { {
117+ light : {
118+ src : src . href ,
119+ size : src . file ?. dimensions ,
120+ } ,
121+ dark : darkSrc
122+ ? {
123+ src : darkSrc . href ,
124+ size : darkSrc . file ?. dimensions ,
125+ }
126+ : null ,
127+ } }
128+ priority = { isEstimatedOffscreen ? 'lazy' : 'high' }
129+ preload
130+ zoom
131+ inlineStyle = { {
132+ maxWidth : '100%' ,
133+ width : getImageDimension ( block . data . width , undefined ) ,
134+ height : getImageDimension ( block . data . height , 'auto' ) ,
135+ } }
136+ style = { withFrame ? 'rounded-xl' : undefined }
137+ />
138+ </ Caption >
139+ </ div >
107140 ) ;
108141}
109142
0 commit comments