-
Notifications
You must be signed in to change notification settings - Fork 10.3k
/
layout-wrapper.tsx
111 lines (101 loc) · 3.04 KB
/
layout-wrapper.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path="../global.d.ts" />
import React, { Fragment, FunctionComponent } from "react"
import terserMacro from "../../macros/terser.macro"
import { Layout } from "../image-utils"
export interface ILayoutWrapperProps {
layout: Layout
width: number
height: number
}
const NativeScriptLoading: FunctionComponent = () => (
<script
type="module"
dangerouslySetInnerHTML={{
__html: terserMacro`
const hasNativeLazyLoadSupport = typeof HTMLImageElement !== "undefined" && "loading" in HTMLImageElement.prototype;
if (hasNativeLazyLoadSupport) {
const gatsbyImages = document.querySelectorAll('img[data-main-image]');
for (let mainImage of gatsbyImages) {
if (mainImage.dataset.src) {
mainImage.setAttribute('src', mainImage.dataset.src)
mainImage.removeAttribute('data-src')
}
if (mainImage.dataset.srcset) {
mainImage.setAttribute('srcset', mainImage.dataset.srcset)
mainImage.removeAttribute('data-srcset')
}
const sources = mainImage.parentNode.querySelectorAll('source[data-srcset]');
for (let source of sources) {
source.setAttribute('srcset', source.dataset.srcset)
source.removeAttribute('data-srcset')
}
if (mainImage.complete) {
mainImage.style.opacity = 1;
}
}
}
`,
}}
/>
)
export function getSizer(
layout: Layout,
width: number,
height: number
): string {
let sizer: string | null = null
if (layout === `fullWidth`) {
sizer = `<div aria-hidden="true" style="padding-top: ${
(height / width) * 100
}%;"></div>`
}
if (layout === `constrained`) {
sizer = `<div style="max-width: ${width}px; display: block;"><img alt="" role="presentation" aria-hidden="true" src="data:image/svg+xml;charset=utf-8,%3Csvg height='${height}' width='${width}' xmlns='http://www.w3.org/2000/svg' version='1.1'%3E%3C/svg%3E" style="max-width: 100%; display: block; position: static;"></div>`
}
return sizer
}
const Sizer: FunctionComponent<ILayoutWrapperProps> = function Sizer({
layout,
width,
height,
}) {
if (layout === `fullWidth`) {
return (
<div aria-hidden style={{ paddingTop: `${(height / width) * 100}%` }} />
)
}
if (layout === `constrained`) {
return (
<div style={{ maxWidth: width, display: `block` }}>
<img
alt=""
role="presentation"
aria-hidden="true"
src={`data:image/svg+xml;charset=utf-8,%3Csvg height='${height}' width='${width}' xmlns='http://www.w3.org/2000/svg' version='1.1'%3E%3C/svg%3E`}
style={{
maxWidth: `100%`,
display: `block`,
position: `static`,
}}
/>
</div>
)
}
return null
}
export const LayoutWrapper: FunctionComponent<ILayoutWrapperProps> = function LayoutWrapper({
children,
...props
}) {
return (
<Fragment>
<Sizer {...props} />
{children}
{
// eslint-disable-next-line no-undef
SERVER && <NativeScriptLoading />
}
</Fragment>
)
}