sanity-plugin-iframe-pane 1.0.15 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +11 -2
- package/lib/cjs/index.js +204 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/esm/index.js +195 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/types/index.d.ts +21 -0
- package/lib/types/index.d.ts.map +1 -0
- package/package.json +52 -40
- package/sanity.json +7 -6
- package/src/Iframe.tsx +204 -0
- package/src/index.ts +5 -0
- package/v2-incompatible.js +11 -0
- package/.babelrc +0 -3
- package/lib/Iframe.js +0 -230
- package/lib/Iframe.js.map +0 -1
- package/src/Iframe.js +0 -159
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
# sanity-plugin-iframe-pane
|
|
2
2
|
|
|
3
|
+
> NOTE
|
|
4
|
+
> This is for the Studio v3 version of the plugin
|
|
5
|
+
|
|
3
6
|
Display any URL in a View Pane, along with helpful buttons to Copy the URL or open in a new tab.
|
|
4
7
|
|
|
5
8
|
Accepts either a string or an async function to resolve a URL based on the current document.
|
|
6
9
|
|
|
7
|
-

|
|
8
11
|
|
|
9
12
|
## Installation
|
|
10
13
|
|
|
11
14
|
```
|
|
12
|
-
|
|
15
|
+
npm install --save sanity-plugin-iframe-pane-v3
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
or
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
yarn add sanity-plugin-iframe-pane-v3
|
|
13
22
|
```
|
|
14
23
|
|
|
15
24
|
This is designed to be used as a [Component inside of a View](https://www.sanity.io/docs/structure-builder-reference#c0c8284844b7).
|
package/lib/cjs/index.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
var $k7rGe$reactjsxruntime = require("react/jsx-runtime");
|
|
2
|
+
var $k7rGe$react = require("react");
|
|
3
|
+
var $k7rGe$sanityui = require("@sanity/ui");
|
|
4
|
+
var $k7rGe$sanityicons = require("@sanity/icons");
|
|
5
|
+
var $k7rGe$usehooksts = require("usehooks-ts");
|
|
6
|
+
|
|
7
|
+
function $parcel$defineInteropFlag(a) {
|
|
8
|
+
Object.defineProperty(a, '__esModule', {value: true, configurable: true});
|
|
9
|
+
}
|
|
10
|
+
function $parcel$export(e, n, v, s) {
|
|
11
|
+
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
$parcel$defineInteropFlag(module.exports);
|
|
15
|
+
|
|
16
|
+
$parcel$export(module.exports, "default", () => $244e63ca53592e4d$export$2e2bcd8739ae039);
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const $f4b318483f84cb22$var$sizes = {
|
|
23
|
+
desktop: {
|
|
24
|
+
width: `100%`,
|
|
25
|
+
height: `100%`,
|
|
26
|
+
maxHeight: `100%`
|
|
27
|
+
},
|
|
28
|
+
mobile: {
|
|
29
|
+
width: 414,
|
|
30
|
+
height: `100%`,
|
|
31
|
+
maxHeight: 736
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const $f4b318483f84cb22$var$DEFAULT_SIZE = `desktop`;
|
|
35
|
+
function $f4b318483f84cb22$var$Iframe(props) {
|
|
36
|
+
const { document: sanityDocument , options: options } = props;
|
|
37
|
+
const { url: url , defaultSize: defaultSize = $f4b318483f84cb22$var$DEFAULT_SIZE , reload: reload } = options;
|
|
38
|
+
const [displayUrl, setDisplayUrl] = (0, $k7rGe$react.useState)(url && typeof url === "string" ? url : ``);
|
|
39
|
+
const [iframeSize, setIframeSize] = (0, $k7rGe$react.useState)($f4b318483f84cb22$var$sizes?.[defaultSize] ? defaultSize : $f4b318483f84cb22$var$DEFAULT_SIZE);
|
|
40
|
+
const input = (0, $k7rGe$react.useRef)(null);
|
|
41
|
+
const iframe = (0, $k7rGe$react.useRef)(null);
|
|
42
|
+
const { displayed: displayed } = sanityDocument;
|
|
43
|
+
const [, copy] = (0, $k7rGe$usehooksts.useCopyToClipboard)();
|
|
44
|
+
function handleCopy() {
|
|
45
|
+
if (!input?.current?.value) return;
|
|
46
|
+
copy(input.current.value);
|
|
47
|
+
}
|
|
48
|
+
function handleReload() {
|
|
49
|
+
if (!iframe?.current) return;
|
|
50
|
+
// Funky way to reload an iframe without CORS issuies
|
|
51
|
+
// eslint-disable-next-line no-self-assign
|
|
52
|
+
iframe.current.src = iframe.current.src;
|
|
53
|
+
}
|
|
54
|
+
// Reload on new revisions
|
|
55
|
+
(0, $k7rGe$react.useEffect)(()=>{
|
|
56
|
+
if (reload?.revision) handleReload();
|
|
57
|
+
}, [
|
|
58
|
+
displayed._rev,
|
|
59
|
+
reload?.revision
|
|
60
|
+
]);
|
|
61
|
+
// Set initial URL and refresh on new revisions
|
|
62
|
+
(0, $k7rGe$react.useEffect)(()=>{
|
|
63
|
+
const getUrl = async ()=>{
|
|
64
|
+
const resolveUrl = typeof url === "function" ? await url(displayed) : ``;
|
|
65
|
+
// Only update state if URL has changed
|
|
66
|
+
if (resolveUrl !== displayUrl && resolveUrl && typeof resolveUrl === "string") setDisplayUrl(resolveUrl);
|
|
67
|
+
};
|
|
68
|
+
if (typeof url === "function") getUrl();
|
|
69
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
70
|
+
}, [
|
|
71
|
+
displayed._rev
|
|
72
|
+
]);
|
|
73
|
+
if (!displayUrl || typeof displayUrl !== "string") return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.ThemeProvider), {
|
|
74
|
+
children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Flex), {
|
|
75
|
+
padding: 5,
|
|
76
|
+
align: "center",
|
|
77
|
+
justify: "center",
|
|
78
|
+
children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Spinner), {})
|
|
79
|
+
})
|
|
80
|
+
});
|
|
81
|
+
return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.ThemeProvider), {
|
|
82
|
+
children: [
|
|
83
|
+
/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)("textarea", {
|
|
84
|
+
style: {
|
|
85
|
+
position: `absolute`,
|
|
86
|
+
pointerEvents: `none`,
|
|
87
|
+
opacity: 0
|
|
88
|
+
},
|
|
89
|
+
ref: input,
|
|
90
|
+
value: displayUrl,
|
|
91
|
+
readOnly: true,
|
|
92
|
+
tabIndex: -1
|
|
93
|
+
}),
|
|
94
|
+
/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Flex), {
|
|
95
|
+
direction: "column",
|
|
96
|
+
style: {
|
|
97
|
+
height: `100%`
|
|
98
|
+
},
|
|
99
|
+
children: [
|
|
100
|
+
/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Card), {
|
|
101
|
+
padding: 2,
|
|
102
|
+
borderBottom: true,
|
|
103
|
+
children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Flex), {
|
|
104
|
+
align: "center",
|
|
105
|
+
gap: 2,
|
|
106
|
+
children: [
|
|
107
|
+
/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Flex), {
|
|
108
|
+
align: "center",
|
|
109
|
+
gap: 1,
|
|
110
|
+
children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Button), {
|
|
111
|
+
fontSize: [
|
|
112
|
+
1
|
|
113
|
+
],
|
|
114
|
+
padding: 2,
|
|
115
|
+
tone: "primary",
|
|
116
|
+
mode: iframeSize === "mobile" ? "default" : "ghost",
|
|
117
|
+
icon: (0, $k7rGe$sanityicons.MobileDeviceIcon),
|
|
118
|
+
onClick: ()=>setIframeSize(iframeSize === "mobile" ? "desktop" : "mobile")
|
|
119
|
+
})
|
|
120
|
+
}),
|
|
121
|
+
/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Box), {
|
|
122
|
+
flex: 1,
|
|
123
|
+
children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Text), {
|
|
124
|
+
size: 0,
|
|
125
|
+
textOverflow: "ellipsis",
|
|
126
|
+
children: displayUrl
|
|
127
|
+
})
|
|
128
|
+
}),
|
|
129
|
+
/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Flex), {
|
|
130
|
+
align: "center",
|
|
131
|
+
gap: 1,
|
|
132
|
+
children: [
|
|
133
|
+
reload?.button ? /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Button), {
|
|
134
|
+
fontSize: [
|
|
135
|
+
1
|
|
136
|
+
],
|
|
137
|
+
padding: 2,
|
|
138
|
+
icon: (0, $k7rGe$sanityicons.UndoIcon),
|
|
139
|
+
title: "Reload",
|
|
140
|
+
"aria-label": "Reload",
|
|
141
|
+
onClick: ()=>handleReload()
|
|
142
|
+
}) : null,
|
|
143
|
+
/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Button), {
|
|
144
|
+
fontSize: [
|
|
145
|
+
1
|
|
146
|
+
],
|
|
147
|
+
icon: (0, $k7rGe$sanityicons.CopyIcon),
|
|
148
|
+
padding: [
|
|
149
|
+
2
|
|
150
|
+
],
|
|
151
|
+
title: "Copy",
|
|
152
|
+
"aria-label": "Copy",
|
|
153
|
+
onClick: ()=>handleCopy()
|
|
154
|
+
}),
|
|
155
|
+
/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Button), {
|
|
156
|
+
fontSize: [
|
|
157
|
+
1
|
|
158
|
+
],
|
|
159
|
+
icon: (0, $k7rGe$sanityicons.LeaveIcon),
|
|
160
|
+
padding: [
|
|
161
|
+
2
|
|
162
|
+
],
|
|
163
|
+
text: "Open",
|
|
164
|
+
tone: "primary",
|
|
165
|
+
onClick: ()=>window.open(displayUrl)
|
|
166
|
+
})
|
|
167
|
+
]
|
|
168
|
+
})
|
|
169
|
+
]
|
|
170
|
+
})
|
|
171
|
+
}),
|
|
172
|
+
/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Card), {
|
|
173
|
+
tone: "transparent",
|
|
174
|
+
padding: iframeSize === "mobile" ? 2 : 0,
|
|
175
|
+
style: {
|
|
176
|
+
height: `100%`
|
|
177
|
+
},
|
|
178
|
+
children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Flex), {
|
|
179
|
+
align: "center",
|
|
180
|
+
justify: "center",
|
|
181
|
+
style: {
|
|
182
|
+
height: `100%`
|
|
183
|
+
},
|
|
184
|
+
children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)("iframe", {
|
|
185
|
+
ref: iframe,
|
|
186
|
+
title: "preview",
|
|
187
|
+
style: $f4b318483f84cb22$var$sizes[iframeSize],
|
|
188
|
+
frameBorder: "0",
|
|
189
|
+
src: displayUrl
|
|
190
|
+
})
|
|
191
|
+
})
|
|
192
|
+
})
|
|
193
|
+
]
|
|
194
|
+
})
|
|
195
|
+
]
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
var $f4b318483f84cb22$export$2e2bcd8739ae039 = $f4b318483f84cb22$var$Iframe;
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
var $244e63ca53592e4d$export$2e2bcd8739ae039 = (0, $f4b318483f84cb22$export$2e2bcd8739ae039);
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"mappings":"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","sources":["src/index.ts","src/Iframe.tsx"],"sourcesContent":["import IframeComponent, { IframeOptions as IframeOptionsType } from \"./Iframe\";\n\nexport default IframeComponent;\n\nexport type IframeOptions = IframeOptionsType;\n","import React, { useEffect, useState, useRef } from \"react\";\nimport { SanityDocumentLike } from \"sanity\";\nimport {\n Box,\n Flex,\n Text,\n Button,\n ThemeProvider,\n Card,\n Spinner,\n} from \"@sanity/ui\";\nimport { UndoIcon, CopyIcon, LeaveIcon, MobileDeviceIcon } from \"@sanity/icons\";\n\nimport { useCopyToClipboard } from \"usehooks-ts\";\n\ntype Size = \"desktop\" | \"mobile\";\n\ntype SizeProps = {\n [key in Size]: {\n width: string | number;\n height: string | number;\n maxHeight: string | number;\n };\n};\n\nconst sizes: SizeProps = {\n desktop: {\n width: `100%`,\n height: `100%`,\n maxHeight: `100%`,\n },\n mobile: {\n width: 414,\n height: `100%`,\n maxHeight: 736,\n },\n};\n\nexport type IframeOptions = {\n url: string | ((document: SanityDocumentLike) => unknown);\n defaultSize?: Size;\n reload?: {\n revision?: boolean;\n button?: boolean;\n };\n};\n\nexport type IframeProps = {\n document: {\n displayed: SanityDocumentLike;\n };\n options: IframeOptions;\n};\n\nconst DEFAULT_SIZE = `desktop`;\n\nfunction Iframe(props: IframeProps) {\n const { document: sanityDocument, options } = props;\n const { url, defaultSize = DEFAULT_SIZE, reload } = options;\n const [displayUrl, setDisplayUrl] = useState(\n url && typeof url === \"string\" ? url : ``\n );\n const [iframeSize, setIframeSize] = useState(\n sizes?.[defaultSize] ? defaultSize : DEFAULT_SIZE\n );\n const input = useRef<HTMLTextAreaElement>(null);\n const iframe = useRef<HTMLIFrameElement>(null);\n const { displayed } = sanityDocument;\n const [, copy] = useCopyToClipboard();\n\n function handleCopy() {\n if (!input?.current?.value) return;\n\n copy(input.current.value);\n }\n\n function handleReload() {\n if (!iframe?.current) {\n return;\n }\n\n // Funky way to reload an iframe without CORS issuies\n // eslint-disable-next-line no-self-assign\n iframe.current.src = iframe.current.src;\n }\n\n // Reload on new revisions\n useEffect(() => {\n if (reload?.revision) {\n handleReload();\n }\n }, [displayed._rev, reload?.revision]);\n\n // Set initial URL and refresh on new revisions\n useEffect(() => {\n const getUrl = async () => {\n const resolveUrl = typeof url === \"function\" ? await url(displayed) : ``;\n\n // Only update state if URL has changed\n if (\n resolveUrl !== displayUrl &&\n resolveUrl &&\n typeof resolveUrl === \"string\"\n ) {\n setDisplayUrl(resolveUrl);\n }\n };\n\n if (typeof url === \"function\") {\n getUrl();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [displayed._rev]);\n\n if (!displayUrl || typeof displayUrl !== \"string\") {\n return (\n <ThemeProvider>\n <Flex padding={5} align=\"center\" justify=\"center\">\n <Spinner />\n </Flex>\n </ThemeProvider>\n );\n }\n\n return (\n <ThemeProvider>\n <textarea\n style={{ position: `absolute`, pointerEvents: `none`, opacity: 0 }}\n ref={input}\n value={displayUrl}\n readOnly\n tabIndex={-1}\n />\n <Flex direction=\"column\" style={{ height: `100%` }}>\n <Card padding={2} borderBottom>\n <Flex align=\"center\" gap={2}>\n <Flex align=\"center\" gap={1}>\n <Button\n fontSize={[1]}\n padding={2}\n tone=\"primary\"\n mode={iframeSize === \"mobile\" ? \"default\" : \"ghost\"}\n icon={MobileDeviceIcon}\n onClick={() =>\n setIframeSize(iframeSize === \"mobile\" ? \"desktop\" : \"mobile\")\n }\n />\n </Flex>\n <Box flex={1}>\n <Text size={0} textOverflow=\"ellipsis\">\n {displayUrl}\n </Text>\n </Box>\n <Flex align=\"center\" gap={1}>\n {reload?.button ? (\n <Button\n fontSize={[1]}\n padding={2}\n icon={UndoIcon}\n title=\"Reload\"\n aria-label=\"Reload\"\n onClick={() => handleReload()}\n />\n ) : null}\n <Button\n fontSize={[1]}\n icon={CopyIcon}\n padding={[2]}\n title=\"Copy\"\n aria-label=\"Copy\"\n onClick={() => handleCopy()}\n />\n <Button\n fontSize={[1]}\n icon={LeaveIcon}\n padding={[2]}\n text=\"Open\"\n tone=\"primary\"\n onClick={() => window.open(displayUrl)}\n />\n </Flex>\n </Flex>\n </Card>\n <Card\n tone=\"transparent\"\n padding={iframeSize === \"mobile\" ? 2 : 0}\n style={{ height: `100%` }}\n >\n <Flex align=\"center\" justify=\"center\" style={{ height: `100%` }}>\n <iframe\n ref={iframe}\n title=\"preview\"\n style={sizes[iframeSize]}\n frameBorder=\"0\"\n src={displayUrl}\n />\n </Flex>\n </Card>\n </Flex>\n </ThemeProvider>\n );\n}\n\nexport default Iframe;\n"],"names":[],"version":3,"file":"index.js.map","sourceRoot":"../../"}
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import {jsx as $gGrEF$jsx, jsxs as $gGrEF$jsxs} from "react/jsx-runtime";
|
|
2
|
+
import {useState as $gGrEF$useState, useRef as $gGrEF$useRef, useEffect as $gGrEF$useEffect} from "react";
|
|
3
|
+
import {ThemeProvider as $gGrEF$ThemeProvider, Flex as $gGrEF$Flex, Spinner as $gGrEF$Spinner, Card as $gGrEF$Card, Button as $gGrEF$Button, Box as $gGrEF$Box, Text as $gGrEF$Text} from "@sanity/ui";
|
|
4
|
+
import {MobileDeviceIcon as $gGrEF$MobileDeviceIcon, UndoIcon as $gGrEF$UndoIcon, CopyIcon as $gGrEF$CopyIcon, LeaveIcon as $gGrEF$LeaveIcon} from "@sanity/icons";
|
|
5
|
+
import {useCopyToClipboard as $gGrEF$useCopyToClipboard} from "usehooks-ts";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const $b1fbe8f05b2a0ffa$var$sizes = {
|
|
13
|
+
desktop: {
|
|
14
|
+
width: `100%`,
|
|
15
|
+
height: `100%`,
|
|
16
|
+
maxHeight: `100%`
|
|
17
|
+
},
|
|
18
|
+
mobile: {
|
|
19
|
+
width: 414,
|
|
20
|
+
height: `100%`,
|
|
21
|
+
maxHeight: 736
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const $b1fbe8f05b2a0ffa$var$DEFAULT_SIZE = `desktop`;
|
|
25
|
+
function $b1fbe8f05b2a0ffa$var$Iframe(props) {
|
|
26
|
+
const { document: sanityDocument , options: options } = props;
|
|
27
|
+
const { url: url , defaultSize: defaultSize = $b1fbe8f05b2a0ffa$var$DEFAULT_SIZE , reload: reload } = options;
|
|
28
|
+
const [displayUrl, setDisplayUrl] = (0, $gGrEF$useState)(url && typeof url === "string" ? url : ``);
|
|
29
|
+
const [iframeSize, setIframeSize] = (0, $gGrEF$useState)($b1fbe8f05b2a0ffa$var$sizes?.[defaultSize] ? defaultSize : $b1fbe8f05b2a0ffa$var$DEFAULT_SIZE);
|
|
30
|
+
const input = (0, $gGrEF$useRef)(null);
|
|
31
|
+
const iframe = (0, $gGrEF$useRef)(null);
|
|
32
|
+
const { displayed: displayed } = sanityDocument;
|
|
33
|
+
const [, copy] = (0, $gGrEF$useCopyToClipboard)();
|
|
34
|
+
function handleCopy() {
|
|
35
|
+
if (!input?.current?.value) return;
|
|
36
|
+
copy(input.current.value);
|
|
37
|
+
}
|
|
38
|
+
function handleReload() {
|
|
39
|
+
if (!iframe?.current) return;
|
|
40
|
+
// Funky way to reload an iframe without CORS issuies
|
|
41
|
+
// eslint-disable-next-line no-self-assign
|
|
42
|
+
iframe.current.src = iframe.current.src;
|
|
43
|
+
}
|
|
44
|
+
// Reload on new revisions
|
|
45
|
+
(0, $gGrEF$useEffect)(()=>{
|
|
46
|
+
if (reload?.revision) handleReload();
|
|
47
|
+
}, [
|
|
48
|
+
displayed._rev,
|
|
49
|
+
reload?.revision
|
|
50
|
+
]);
|
|
51
|
+
// Set initial URL and refresh on new revisions
|
|
52
|
+
(0, $gGrEF$useEffect)(()=>{
|
|
53
|
+
const getUrl = async ()=>{
|
|
54
|
+
const resolveUrl = typeof url === "function" ? await url(displayed) : ``;
|
|
55
|
+
// Only update state if URL has changed
|
|
56
|
+
if (resolveUrl !== displayUrl && resolveUrl && typeof resolveUrl === "string") setDisplayUrl(resolveUrl);
|
|
57
|
+
};
|
|
58
|
+
if (typeof url === "function") getUrl();
|
|
59
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
60
|
+
}, [
|
|
61
|
+
displayed._rev
|
|
62
|
+
]);
|
|
63
|
+
if (!displayUrl || typeof displayUrl !== "string") return /*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$ThemeProvider), {
|
|
64
|
+
children: /*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Flex), {
|
|
65
|
+
padding: 5,
|
|
66
|
+
align: "center",
|
|
67
|
+
justify: "center",
|
|
68
|
+
children: /*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Spinner), {})
|
|
69
|
+
})
|
|
70
|
+
});
|
|
71
|
+
return /*#__PURE__*/ (0, $gGrEF$jsxs)((0, $gGrEF$ThemeProvider), {
|
|
72
|
+
children: [
|
|
73
|
+
/*#__PURE__*/ (0, $gGrEF$jsx)("textarea", {
|
|
74
|
+
style: {
|
|
75
|
+
position: `absolute`,
|
|
76
|
+
pointerEvents: `none`,
|
|
77
|
+
opacity: 0
|
|
78
|
+
},
|
|
79
|
+
ref: input,
|
|
80
|
+
value: displayUrl,
|
|
81
|
+
readOnly: true,
|
|
82
|
+
tabIndex: -1
|
|
83
|
+
}),
|
|
84
|
+
/*#__PURE__*/ (0, $gGrEF$jsxs)((0, $gGrEF$Flex), {
|
|
85
|
+
direction: "column",
|
|
86
|
+
style: {
|
|
87
|
+
height: `100%`
|
|
88
|
+
},
|
|
89
|
+
children: [
|
|
90
|
+
/*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Card), {
|
|
91
|
+
padding: 2,
|
|
92
|
+
borderBottom: true,
|
|
93
|
+
children: /*#__PURE__*/ (0, $gGrEF$jsxs)((0, $gGrEF$Flex), {
|
|
94
|
+
align: "center",
|
|
95
|
+
gap: 2,
|
|
96
|
+
children: [
|
|
97
|
+
/*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Flex), {
|
|
98
|
+
align: "center",
|
|
99
|
+
gap: 1,
|
|
100
|
+
children: /*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Button), {
|
|
101
|
+
fontSize: [
|
|
102
|
+
1
|
|
103
|
+
],
|
|
104
|
+
padding: 2,
|
|
105
|
+
tone: "primary",
|
|
106
|
+
mode: iframeSize === "mobile" ? "default" : "ghost",
|
|
107
|
+
icon: (0, $gGrEF$MobileDeviceIcon),
|
|
108
|
+
onClick: ()=>setIframeSize(iframeSize === "mobile" ? "desktop" : "mobile")
|
|
109
|
+
})
|
|
110
|
+
}),
|
|
111
|
+
/*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Box), {
|
|
112
|
+
flex: 1,
|
|
113
|
+
children: /*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Text), {
|
|
114
|
+
size: 0,
|
|
115
|
+
textOverflow: "ellipsis",
|
|
116
|
+
children: displayUrl
|
|
117
|
+
})
|
|
118
|
+
}),
|
|
119
|
+
/*#__PURE__*/ (0, $gGrEF$jsxs)((0, $gGrEF$Flex), {
|
|
120
|
+
align: "center",
|
|
121
|
+
gap: 1,
|
|
122
|
+
children: [
|
|
123
|
+
reload?.button ? /*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Button), {
|
|
124
|
+
fontSize: [
|
|
125
|
+
1
|
|
126
|
+
],
|
|
127
|
+
padding: 2,
|
|
128
|
+
icon: (0, $gGrEF$UndoIcon),
|
|
129
|
+
title: "Reload",
|
|
130
|
+
"aria-label": "Reload",
|
|
131
|
+
onClick: ()=>handleReload()
|
|
132
|
+
}) : null,
|
|
133
|
+
/*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Button), {
|
|
134
|
+
fontSize: [
|
|
135
|
+
1
|
|
136
|
+
],
|
|
137
|
+
icon: (0, $gGrEF$CopyIcon),
|
|
138
|
+
padding: [
|
|
139
|
+
2
|
|
140
|
+
],
|
|
141
|
+
title: "Copy",
|
|
142
|
+
"aria-label": "Copy",
|
|
143
|
+
onClick: ()=>handleCopy()
|
|
144
|
+
}),
|
|
145
|
+
/*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Button), {
|
|
146
|
+
fontSize: [
|
|
147
|
+
1
|
|
148
|
+
],
|
|
149
|
+
icon: (0, $gGrEF$LeaveIcon),
|
|
150
|
+
padding: [
|
|
151
|
+
2
|
|
152
|
+
],
|
|
153
|
+
text: "Open",
|
|
154
|
+
tone: "primary",
|
|
155
|
+
onClick: ()=>window.open(displayUrl)
|
|
156
|
+
})
|
|
157
|
+
]
|
|
158
|
+
})
|
|
159
|
+
]
|
|
160
|
+
})
|
|
161
|
+
}),
|
|
162
|
+
/*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Card), {
|
|
163
|
+
tone: "transparent",
|
|
164
|
+
padding: iframeSize === "mobile" ? 2 : 0,
|
|
165
|
+
style: {
|
|
166
|
+
height: `100%`
|
|
167
|
+
},
|
|
168
|
+
children: /*#__PURE__*/ (0, $gGrEF$jsx)((0, $gGrEF$Flex), {
|
|
169
|
+
align: "center",
|
|
170
|
+
justify: "center",
|
|
171
|
+
style: {
|
|
172
|
+
height: `100%`
|
|
173
|
+
},
|
|
174
|
+
children: /*#__PURE__*/ (0, $gGrEF$jsx)("iframe", {
|
|
175
|
+
ref: iframe,
|
|
176
|
+
title: "preview",
|
|
177
|
+
style: $b1fbe8f05b2a0ffa$var$sizes[iframeSize],
|
|
178
|
+
frameBorder: "0",
|
|
179
|
+
src: displayUrl
|
|
180
|
+
})
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
]
|
|
184
|
+
})
|
|
185
|
+
]
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
var $b1fbe8f05b2a0ffa$export$2e2bcd8739ae039 = $b1fbe8f05b2a0ffa$var$Iframe;
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
var $df9eabe9bda49ea8$export$2e2bcd8739ae039 = (0, $b1fbe8f05b2a0ffa$export$2e2bcd8739ae039);
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
export {$df9eabe9bda49ea8$export$2e2bcd8739ae039 as default};
|
|
195
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"mappings":"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","sources":["src/index.ts","src/Iframe.tsx"],"sourcesContent":["import IframeComponent, { IframeOptions as IframeOptionsType } from \"./Iframe\";\n\nexport default IframeComponent;\n\nexport type IframeOptions = IframeOptionsType;\n","import React, { useEffect, useState, useRef } from \"react\";\nimport { SanityDocumentLike } from \"sanity\";\nimport {\n Box,\n Flex,\n Text,\n Button,\n ThemeProvider,\n Card,\n Spinner,\n} from \"@sanity/ui\";\nimport { UndoIcon, CopyIcon, LeaveIcon, MobileDeviceIcon } from \"@sanity/icons\";\n\nimport { useCopyToClipboard } from \"usehooks-ts\";\n\ntype Size = \"desktop\" | \"mobile\";\n\ntype SizeProps = {\n [key in Size]: {\n width: string | number;\n height: string | number;\n maxHeight: string | number;\n };\n};\n\nconst sizes: SizeProps = {\n desktop: {\n width: `100%`,\n height: `100%`,\n maxHeight: `100%`,\n },\n mobile: {\n width: 414,\n height: `100%`,\n maxHeight: 736,\n },\n};\n\nexport type IframeOptions = {\n url: string | ((document: SanityDocumentLike) => unknown);\n defaultSize?: Size;\n reload?: {\n revision?: boolean;\n button?: boolean;\n };\n};\n\nexport type IframeProps = {\n document: {\n displayed: SanityDocumentLike;\n };\n options: IframeOptions;\n};\n\nconst DEFAULT_SIZE = `desktop`;\n\nfunction Iframe(props: IframeProps) {\n const { document: sanityDocument, options } = props;\n const { url, defaultSize = DEFAULT_SIZE, reload } = options;\n const [displayUrl, setDisplayUrl] = useState(\n url && typeof url === \"string\" ? url : ``\n );\n const [iframeSize, setIframeSize] = useState(\n sizes?.[defaultSize] ? defaultSize : DEFAULT_SIZE\n );\n const input = useRef<HTMLTextAreaElement>(null);\n const iframe = useRef<HTMLIFrameElement>(null);\n const { displayed } = sanityDocument;\n const [, copy] = useCopyToClipboard();\n\n function handleCopy() {\n if (!input?.current?.value) return;\n\n copy(input.current.value);\n }\n\n function handleReload() {\n if (!iframe?.current) {\n return;\n }\n\n // Funky way to reload an iframe without CORS issuies\n // eslint-disable-next-line no-self-assign\n iframe.current.src = iframe.current.src;\n }\n\n // Reload on new revisions\n useEffect(() => {\n if (reload?.revision) {\n handleReload();\n }\n }, [displayed._rev, reload?.revision]);\n\n // Set initial URL and refresh on new revisions\n useEffect(() => {\n const getUrl = async () => {\n const resolveUrl = typeof url === \"function\" ? await url(displayed) : ``;\n\n // Only update state if URL has changed\n if (\n resolveUrl !== displayUrl &&\n resolveUrl &&\n typeof resolveUrl === \"string\"\n ) {\n setDisplayUrl(resolveUrl);\n }\n };\n\n if (typeof url === \"function\") {\n getUrl();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [displayed._rev]);\n\n if (!displayUrl || typeof displayUrl !== \"string\") {\n return (\n <ThemeProvider>\n <Flex padding={5} align=\"center\" justify=\"center\">\n <Spinner />\n </Flex>\n </ThemeProvider>\n );\n }\n\n return (\n <ThemeProvider>\n <textarea\n style={{ position: `absolute`, pointerEvents: `none`, opacity: 0 }}\n ref={input}\n value={displayUrl}\n readOnly\n tabIndex={-1}\n />\n <Flex direction=\"column\" style={{ height: `100%` }}>\n <Card padding={2} borderBottom>\n <Flex align=\"center\" gap={2}>\n <Flex align=\"center\" gap={1}>\n <Button\n fontSize={[1]}\n padding={2}\n tone=\"primary\"\n mode={iframeSize === \"mobile\" ? \"default\" : \"ghost\"}\n icon={MobileDeviceIcon}\n onClick={() =>\n setIframeSize(iframeSize === \"mobile\" ? \"desktop\" : \"mobile\")\n }\n />\n </Flex>\n <Box flex={1}>\n <Text size={0} textOverflow=\"ellipsis\">\n {displayUrl}\n </Text>\n </Box>\n <Flex align=\"center\" gap={1}>\n {reload?.button ? (\n <Button\n fontSize={[1]}\n padding={2}\n icon={UndoIcon}\n title=\"Reload\"\n aria-label=\"Reload\"\n onClick={() => handleReload()}\n />\n ) : null}\n <Button\n fontSize={[1]}\n icon={CopyIcon}\n padding={[2]}\n title=\"Copy\"\n aria-label=\"Copy\"\n onClick={() => handleCopy()}\n />\n <Button\n fontSize={[1]}\n icon={LeaveIcon}\n padding={[2]}\n text=\"Open\"\n tone=\"primary\"\n onClick={() => window.open(displayUrl)}\n />\n </Flex>\n </Flex>\n </Card>\n <Card\n tone=\"transparent\"\n padding={iframeSize === \"mobile\" ? 2 : 0}\n style={{ height: `100%` }}\n >\n <Flex align=\"center\" justify=\"center\" style={{ height: `100%` }}>\n <iframe\n ref={iframe}\n title=\"preview\"\n style={sizes[iframeSize]}\n frameBorder=\"0\"\n src={displayUrl}\n />\n </Flex>\n </Card>\n </Flex>\n </ThemeProvider>\n );\n}\n\nexport default Iframe;\n"],"names":[],"version":3,"file":"index.js.map","sourceRoot":"../../"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SanityDocumentLike } from "sanity";
|
|
2
|
+
type Size = "desktop" | "mobile";
|
|
3
|
+
type _IframeOptions1 = {
|
|
4
|
+
url: string | ((document: SanityDocumentLike) => unknown);
|
|
5
|
+
defaultSize?: Size;
|
|
6
|
+
reload?: {
|
|
7
|
+
revision?: boolean;
|
|
8
|
+
button?: boolean;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
type IframeProps = {
|
|
12
|
+
document: {
|
|
13
|
+
displayed: SanityDocumentLike;
|
|
14
|
+
};
|
|
15
|
+
options: _IframeOptions1;
|
|
16
|
+
};
|
|
17
|
+
declare function Iframe(props: IframeProps): JSX.Element;
|
|
18
|
+
export default IframeComponent;
|
|
19
|
+
export type IframeOptions = _IframeOptions1;
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"mappings":";AAeA,YAAY,SAAS,GAAG,QAAQ,CAAC;AAuBjC,uBAA4B;IAC1B,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,kBAAkB,KAAK,OAAO,CAAC,CAAC;IAC1D,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,mBAA0B;IACxB,QAAQ,EAAE;QACR,SAAS,EAAE,kBAAkB,CAAC;KAC/B,CAAC;IACF,OAAO,EAAE,eAAa,CAAC;CACxB,CAAC;AAIF,wBAAgB,KAAK,EAAE,WAAW,eAiJjC;ACvMD,eAAe,eAAe,CAAC;AAE/B,4BAA4B,eAAiB,CAAC","sources":["src/src/Iframe.tsx","src/src/index.ts","src/index.ts"],"sourcesContent":[null,null,"import IframeComponent, { IframeOptions as IframeOptionsType } from \"./Iframe\";\n\nexport default IframeComponent;\n\nexport type IframeOptions = IframeOptionsType;\n"],"names":[],"version":3,"file":"index.d.ts.map","sourceRoot":"../../"}
|
package/package.json
CHANGED
|
@@ -1,53 +1,65 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanity-plugin-iframe-pane",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Display any URL in a View Pane, along with helpful buttons to Copy the URL or open in a new tab",
|
|
5
|
-
"
|
|
5
|
+
"author": "Simeon Griggs <simeon@sanity.io>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"source": "./src/index.ts",
|
|
8
|
+
"main": "./lib/cjs/index.js",
|
|
9
|
+
"module": "./lib/esm/index.js",
|
|
10
|
+
"types": "./lib/types/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"require": "./lib/cjs/index.js",
|
|
14
|
+
"default": "./lib/esm/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"src",
|
|
19
|
+
"lib",
|
|
20
|
+
"v2-incompatible.js",
|
|
21
|
+
"sanity.json"
|
|
22
|
+
],
|
|
6
23
|
"scripts": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
24
|
+
"clean": "rimraf lib",
|
|
25
|
+
"lint": "eslint .",
|
|
26
|
+
"prebuild": "npm run clean && plugin-kit verify-package --silent",
|
|
27
|
+
"build": "parcel build --no-cache",
|
|
28
|
+
"watch": "parcel watch",
|
|
29
|
+
"link-watch": "plugin-kit link-watch",
|
|
30
|
+
"prepublishOnly": "npm run build"
|
|
10
31
|
},
|
|
11
|
-
"repository": {
|
|
12
|
-
|
|
13
|
-
"
|
|
32
|
+
"repository": {},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=14.0.0"
|
|
14
35
|
},
|
|
15
|
-
"keywords": [
|
|
16
|
-
"sanity",
|
|
17
|
-
"sanity-plugin"
|
|
18
|
-
],
|
|
19
|
-
"author": "Simeon Griggs <simeon@sanity.io>",
|
|
20
|
-
"license": "MIT",
|
|
21
36
|
"dependencies": {
|
|
22
|
-
"@sanity/icons": "^1.
|
|
23
|
-
"@sanity/
|
|
24
|
-
"
|
|
25
|
-
"usehooks-ts": "^
|
|
37
|
+
"@sanity/icons": "^1.3.1",
|
|
38
|
+
"@sanity/incompatible-plugin": "^0.0.1-studio-v3.1",
|
|
39
|
+
"@sanity/ui": "^0.37.12",
|
|
40
|
+
"usehooks-ts": "^2.6.0"
|
|
26
41
|
},
|
|
27
42
|
"devDependencies": {
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"eslint-plugin
|
|
32
|
-
"
|
|
33
|
-
"
|
|
43
|
+
"@parcel/packager-ts": "^2.6.2",
|
|
44
|
+
"@parcel/transformer-typescript-types": "^2.6.2",
|
|
45
|
+
"@sanity/plugin-kit": "^0.1.0-v3-studio.1",
|
|
46
|
+
"@typescript-eslint/eslint-plugin": "^5.30.7",
|
|
47
|
+
"@typescript-eslint/parser": "^5.30.7",
|
|
48
|
+
"eslint": "^8.20.0",
|
|
49
|
+
"eslint-config-prettier": "^8.5.0",
|
|
50
|
+
"eslint-config-sanity": "^6.0.0",
|
|
51
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
52
|
+
"eslint-plugin-react": "^7.30.1",
|
|
53
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
54
|
+
"parcel": "^2.6.2",
|
|
55
|
+
"prettier": "^2.7.1",
|
|
56
|
+
"react": "^17.0.0 || ^18.0.0",
|
|
57
|
+
"rimraf": "^3.0.2",
|
|
58
|
+
"sanity": "2.29.5-purple-unicorn.856",
|
|
59
|
+
"typescript": "^4.7.4"
|
|
34
60
|
},
|
|
35
61
|
"peerDependencies": {
|
|
36
|
-
"react": "^17.0.
|
|
37
|
-
|
|
38
|
-
"prettier": {
|
|
39
|
-
"semi": false,
|
|
40
|
-
"printWidth": 100,
|
|
41
|
-
"bracketSpacing": false,
|
|
42
|
-
"singleQuote": true
|
|
43
|
-
},
|
|
44
|
-
"eslintConfig": {
|
|
45
|
-
"parser": "sanipack/babel/eslint-parser",
|
|
46
|
-
"extends": [
|
|
47
|
-
"sanity",
|
|
48
|
-
"sanity/react",
|
|
49
|
-
"prettier",
|
|
50
|
-
"prettier/react"
|
|
51
|
-
]
|
|
62
|
+
"react": "^17.0.0 || ^18.0.0",
|
|
63
|
+
"sanity": "purple-unicorn"
|
|
52
64
|
}
|
|
53
65
|
}
|
package/sanity.json
CHANGED
package/src/Iframe.tsx
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import React, { useEffect, useState, useRef } from "react";
|
|
2
|
+
import { SanityDocumentLike } from "sanity";
|
|
3
|
+
import {
|
|
4
|
+
Box,
|
|
5
|
+
Flex,
|
|
6
|
+
Text,
|
|
7
|
+
Button,
|
|
8
|
+
ThemeProvider,
|
|
9
|
+
Card,
|
|
10
|
+
Spinner,
|
|
11
|
+
} from "@sanity/ui";
|
|
12
|
+
import { UndoIcon, CopyIcon, LeaveIcon, MobileDeviceIcon } from "@sanity/icons";
|
|
13
|
+
|
|
14
|
+
import { useCopyToClipboard } from "usehooks-ts";
|
|
15
|
+
|
|
16
|
+
type Size = "desktop" | "mobile";
|
|
17
|
+
|
|
18
|
+
type SizeProps = {
|
|
19
|
+
[key in Size]: {
|
|
20
|
+
width: string | number;
|
|
21
|
+
height: string | number;
|
|
22
|
+
maxHeight: string | number;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const sizes: SizeProps = {
|
|
27
|
+
desktop: {
|
|
28
|
+
width: `100%`,
|
|
29
|
+
height: `100%`,
|
|
30
|
+
maxHeight: `100%`,
|
|
31
|
+
},
|
|
32
|
+
mobile: {
|
|
33
|
+
width: 414,
|
|
34
|
+
height: `100%`,
|
|
35
|
+
maxHeight: 736,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type IframeOptions = {
|
|
40
|
+
url: string | ((document: SanityDocumentLike) => unknown);
|
|
41
|
+
defaultSize?: Size;
|
|
42
|
+
reload?: {
|
|
43
|
+
revision?: boolean;
|
|
44
|
+
button?: boolean;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type IframeProps = {
|
|
49
|
+
document: {
|
|
50
|
+
displayed: SanityDocumentLike;
|
|
51
|
+
};
|
|
52
|
+
options: IframeOptions;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const DEFAULT_SIZE = `desktop`;
|
|
56
|
+
|
|
57
|
+
function Iframe(props: IframeProps) {
|
|
58
|
+
const { document: sanityDocument, options } = props;
|
|
59
|
+
const { url, defaultSize = DEFAULT_SIZE, reload } = options;
|
|
60
|
+
const [displayUrl, setDisplayUrl] = useState(
|
|
61
|
+
url && typeof url === "string" ? url : ``
|
|
62
|
+
);
|
|
63
|
+
const [iframeSize, setIframeSize] = useState(
|
|
64
|
+
sizes?.[defaultSize] ? defaultSize : DEFAULT_SIZE
|
|
65
|
+
);
|
|
66
|
+
const input = useRef<HTMLTextAreaElement>(null);
|
|
67
|
+
const iframe = useRef<HTMLIFrameElement>(null);
|
|
68
|
+
const { displayed } = sanityDocument;
|
|
69
|
+
const [, copy] = useCopyToClipboard();
|
|
70
|
+
|
|
71
|
+
function handleCopy() {
|
|
72
|
+
if (!input?.current?.value) return;
|
|
73
|
+
|
|
74
|
+
copy(input.current.value);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function handleReload() {
|
|
78
|
+
if (!iframe?.current) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Funky way to reload an iframe without CORS issuies
|
|
83
|
+
// eslint-disable-next-line no-self-assign
|
|
84
|
+
iframe.current.src = iframe.current.src;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Reload on new revisions
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (reload?.revision) {
|
|
90
|
+
handleReload();
|
|
91
|
+
}
|
|
92
|
+
}, [displayed._rev, reload?.revision]);
|
|
93
|
+
|
|
94
|
+
// Set initial URL and refresh on new revisions
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
const getUrl = async () => {
|
|
97
|
+
const resolveUrl = typeof url === "function" ? await url(displayed) : ``;
|
|
98
|
+
|
|
99
|
+
// Only update state if URL has changed
|
|
100
|
+
if (
|
|
101
|
+
resolveUrl !== displayUrl &&
|
|
102
|
+
resolveUrl &&
|
|
103
|
+
typeof resolveUrl === "string"
|
|
104
|
+
) {
|
|
105
|
+
setDisplayUrl(resolveUrl);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
if (typeof url === "function") {
|
|
110
|
+
getUrl();
|
|
111
|
+
}
|
|
112
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
113
|
+
}, [displayed._rev]);
|
|
114
|
+
|
|
115
|
+
if (!displayUrl || typeof displayUrl !== "string") {
|
|
116
|
+
return (
|
|
117
|
+
<ThemeProvider>
|
|
118
|
+
<Flex padding={5} align="center" justify="center">
|
|
119
|
+
<Spinner />
|
|
120
|
+
</Flex>
|
|
121
|
+
</ThemeProvider>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<ThemeProvider>
|
|
127
|
+
<textarea
|
|
128
|
+
style={{ position: `absolute`, pointerEvents: `none`, opacity: 0 }}
|
|
129
|
+
ref={input}
|
|
130
|
+
value={displayUrl}
|
|
131
|
+
readOnly
|
|
132
|
+
tabIndex={-1}
|
|
133
|
+
/>
|
|
134
|
+
<Flex direction="column" style={{ height: `100%` }}>
|
|
135
|
+
<Card padding={2} borderBottom>
|
|
136
|
+
<Flex align="center" gap={2}>
|
|
137
|
+
<Flex align="center" gap={1}>
|
|
138
|
+
<Button
|
|
139
|
+
fontSize={[1]}
|
|
140
|
+
padding={2}
|
|
141
|
+
tone="primary"
|
|
142
|
+
mode={iframeSize === "mobile" ? "default" : "ghost"}
|
|
143
|
+
icon={MobileDeviceIcon}
|
|
144
|
+
onClick={() =>
|
|
145
|
+
setIframeSize(iframeSize === "mobile" ? "desktop" : "mobile")
|
|
146
|
+
}
|
|
147
|
+
/>
|
|
148
|
+
</Flex>
|
|
149
|
+
<Box flex={1}>
|
|
150
|
+
<Text size={0} textOverflow="ellipsis">
|
|
151
|
+
{displayUrl}
|
|
152
|
+
</Text>
|
|
153
|
+
</Box>
|
|
154
|
+
<Flex align="center" gap={1}>
|
|
155
|
+
{reload?.button ? (
|
|
156
|
+
<Button
|
|
157
|
+
fontSize={[1]}
|
|
158
|
+
padding={2}
|
|
159
|
+
icon={UndoIcon}
|
|
160
|
+
title="Reload"
|
|
161
|
+
aria-label="Reload"
|
|
162
|
+
onClick={() => handleReload()}
|
|
163
|
+
/>
|
|
164
|
+
) : null}
|
|
165
|
+
<Button
|
|
166
|
+
fontSize={[1]}
|
|
167
|
+
icon={CopyIcon}
|
|
168
|
+
padding={[2]}
|
|
169
|
+
title="Copy"
|
|
170
|
+
aria-label="Copy"
|
|
171
|
+
onClick={() => handleCopy()}
|
|
172
|
+
/>
|
|
173
|
+
<Button
|
|
174
|
+
fontSize={[1]}
|
|
175
|
+
icon={LeaveIcon}
|
|
176
|
+
padding={[2]}
|
|
177
|
+
text="Open"
|
|
178
|
+
tone="primary"
|
|
179
|
+
onClick={() => window.open(displayUrl)}
|
|
180
|
+
/>
|
|
181
|
+
</Flex>
|
|
182
|
+
</Flex>
|
|
183
|
+
</Card>
|
|
184
|
+
<Card
|
|
185
|
+
tone="transparent"
|
|
186
|
+
padding={iframeSize === "mobile" ? 2 : 0}
|
|
187
|
+
style={{ height: `100%` }}
|
|
188
|
+
>
|
|
189
|
+
<Flex align="center" justify="center" style={{ height: `100%` }}>
|
|
190
|
+
<iframe
|
|
191
|
+
ref={iframe}
|
|
192
|
+
title="preview"
|
|
193
|
+
style={sizes[iframeSize]}
|
|
194
|
+
frameBorder="0"
|
|
195
|
+
src={displayUrl}
|
|
196
|
+
/>
|
|
197
|
+
</Flex>
|
|
198
|
+
</Card>
|
|
199
|
+
</Flex>
|
|
200
|
+
</ThemeProvider>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export default Iframe;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const {showIncompatiblePluginDialog} = require('@sanity/incompatible-plugin')
|
|
2
|
+
const {name, version, sanityExchangeUrl} = require('./package.json')
|
|
3
|
+
|
|
4
|
+
export default showIncompatiblePluginDialog({
|
|
5
|
+
name: name,
|
|
6
|
+
versions: {
|
|
7
|
+
v3: version,
|
|
8
|
+
v2: undefined,
|
|
9
|
+
},
|
|
10
|
+
sanityExchangeUrl,
|
|
11
|
+
})
|
package/.babelrc
DELETED
package/lib/Iframe.js
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
-
|
|
10
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
|
-
|
|
12
|
-
var _ui = require("@sanity/ui");
|
|
13
|
-
|
|
14
|
-
var _icons = require("@sanity/icons");
|
|
15
|
-
|
|
16
|
-
var _usehooksTs = require("usehooks-ts");
|
|
17
|
-
|
|
18
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
-
|
|
20
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
21
|
-
|
|
22
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
23
|
-
|
|
24
|
-
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
25
|
-
|
|
26
|
-
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
27
|
-
|
|
28
|
-
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
29
|
-
|
|
30
|
-
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
31
|
-
|
|
32
|
-
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
33
|
-
|
|
34
|
-
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
35
|
-
|
|
36
|
-
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
37
|
-
|
|
38
|
-
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
39
|
-
|
|
40
|
-
var sizes = {
|
|
41
|
-
desktop: {
|
|
42
|
-
backgroundColor: "white",
|
|
43
|
-
width: "100%",
|
|
44
|
-
height: "100%",
|
|
45
|
-
maxHeight: "100%"
|
|
46
|
-
},
|
|
47
|
-
mobile: {
|
|
48
|
-
backgroundColor: "white",
|
|
49
|
-
width: 414,
|
|
50
|
-
height: "100%",
|
|
51
|
-
maxHeight: 736
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
function Iframe(_ref) {
|
|
56
|
-
var sanityDocument = _ref.document,
|
|
57
|
-
options = _ref.options;
|
|
58
|
-
var url = options.url,
|
|
59
|
-
defaultSize = options.defaultSize,
|
|
60
|
-
reload = options.reload;
|
|
61
|
-
|
|
62
|
-
var _useState = (0, _react.useState)(typeof url === 'string' ? url : ""),
|
|
63
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
64
|
-
displayUrl = _useState2[0],
|
|
65
|
-
setDisplayUrl = _useState2[1];
|
|
66
|
-
|
|
67
|
-
var _useState3 = (0, _react.useState)(defaultSize && sizes !== null && sizes !== void 0 && sizes[defaultSize] ? defaultSize : "desktop"),
|
|
68
|
-
_useState4 = _slicedToArray(_useState3, 2),
|
|
69
|
-
iframeSize = _useState4[0],
|
|
70
|
-
setIframeSize = _useState4[1];
|
|
71
|
-
|
|
72
|
-
var input = (0, _react.useRef)();
|
|
73
|
-
var iframe = (0, _react.useRef)();
|
|
74
|
-
var displayed = sanityDocument.displayed;
|
|
75
|
-
|
|
76
|
-
var _useCopyToClipboard = (0, _usehooksTs.useCopyToClipboard)(),
|
|
77
|
-
_useCopyToClipboard2 = _slicedToArray(_useCopyToClipboard, 2),
|
|
78
|
-
value = _useCopyToClipboard2[0],
|
|
79
|
-
copy = _useCopyToClipboard2[1];
|
|
80
|
-
|
|
81
|
-
function handleCopy() {
|
|
82
|
-
var _input$current;
|
|
83
|
-
|
|
84
|
-
if (!(input !== null && input !== void 0 && (_input$current = input.current) !== null && _input$current !== void 0 && _input$current.value)) return;
|
|
85
|
-
copy(input.current.value);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function handleReload() {
|
|
89
|
-
if (!(iframe !== null && iframe !== void 0 && iframe.current)) {
|
|
90
|
-
return;
|
|
91
|
-
} // Funky way to reload an iframe without CORS issuies
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
iframe.current.src = iframe.current.src;
|
|
95
|
-
} // Reload on new revisions
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
(0, _react.useEffect)(() => {
|
|
99
|
-
if (reload !== null && reload !== void 0 && reload.revision) {
|
|
100
|
-
handleReload();
|
|
101
|
-
}
|
|
102
|
-
}, [displayed._rev]); // Set initial URL and refresh on new revisions
|
|
103
|
-
|
|
104
|
-
(0, _react.useEffect)(() => {
|
|
105
|
-
var getUrl = /*#__PURE__*/function () {
|
|
106
|
-
var _ref2 = _asyncToGenerator(function* () {
|
|
107
|
-
var resolveUrl = yield url(displayed); // Only update state if URL has changed
|
|
108
|
-
|
|
109
|
-
if (resolveUrl !== displayUrl) {
|
|
110
|
-
setDisplayUrl(resolveUrl);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
return function getUrl() {
|
|
115
|
-
return _ref2.apply(this, arguments);
|
|
116
|
-
};
|
|
117
|
-
}();
|
|
118
|
-
|
|
119
|
-
if (typeof url !== 'string') {
|
|
120
|
-
getUrl();
|
|
121
|
-
}
|
|
122
|
-
}, [displayed._rev]);
|
|
123
|
-
|
|
124
|
-
if (!displayUrl || typeof displayUrl !== 'string') {
|
|
125
|
-
return /*#__PURE__*/_react.default.createElement(_ui.ThemeProvider, null, /*#__PURE__*/_react.default.createElement(_ui.Flex, {
|
|
126
|
-
padding: 5,
|
|
127
|
-
items: "center",
|
|
128
|
-
justify: "center"
|
|
129
|
-
}, /*#__PURE__*/_react.default.createElement(_ui.Spinner, null)));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return /*#__PURE__*/_react.default.createElement(_ui.ThemeProvider, null, /*#__PURE__*/_react.default.createElement("textarea", {
|
|
133
|
-
style: {
|
|
134
|
-
position: "absolute",
|
|
135
|
-
pointerEvents: "none",
|
|
136
|
-
opacity: 0
|
|
137
|
-
},
|
|
138
|
-
ref: input,
|
|
139
|
-
value: displayUrl,
|
|
140
|
-
readOnly: true,
|
|
141
|
-
tabIndex: "-1"
|
|
142
|
-
}), /*#__PURE__*/_react.default.createElement(_ui.Flex, {
|
|
143
|
-
direction: "column",
|
|
144
|
-
style: {
|
|
145
|
-
height: "100%"
|
|
146
|
-
}
|
|
147
|
-
}, /*#__PURE__*/_react.default.createElement(_ui.Card, {
|
|
148
|
-
padding: 2,
|
|
149
|
-
borderBottom: 1
|
|
150
|
-
}, /*#__PURE__*/_react.default.createElement(_ui.Flex, {
|
|
151
|
-
align: "center",
|
|
152
|
-
gap: 2
|
|
153
|
-
}, /*#__PURE__*/_react.default.createElement(_ui.Flex, {
|
|
154
|
-
align: "center",
|
|
155
|
-
gap: 1
|
|
156
|
-
}, /*#__PURE__*/_react.default.createElement(_ui.Button, {
|
|
157
|
-
fontSize: [1],
|
|
158
|
-
padding: 2,
|
|
159
|
-
tone: "primary",
|
|
160
|
-
mode: iframeSize === 'mobile' ? 'default' : 'ghost',
|
|
161
|
-
icon: _icons.MobileDeviceIcon,
|
|
162
|
-
onClick: () => setIframeSize(iframeSize === 'mobile' ? 'desktop' : 'mobile')
|
|
163
|
-
})), /*#__PURE__*/_react.default.createElement(_ui.Box, {
|
|
164
|
-
flex: 1
|
|
165
|
-
}, /*#__PURE__*/_react.default.createElement(_ui.Text, {
|
|
166
|
-
size: 0,
|
|
167
|
-
textOverflow: "ellipsis"
|
|
168
|
-
}, displayUrl)), /*#__PURE__*/_react.default.createElement(_ui.Flex, {
|
|
169
|
-
align: "center",
|
|
170
|
-
gap: 1
|
|
171
|
-
}, reload !== null && reload !== void 0 && reload.button ? /*#__PURE__*/_react.default.createElement(_ui.Button, {
|
|
172
|
-
fontSize: [1],
|
|
173
|
-
padding: 2,
|
|
174
|
-
icon: _icons.UndoIcon // text="Reload"
|
|
175
|
-
,
|
|
176
|
-
title: "Reload",
|
|
177
|
-
"aria-label": "Reload",
|
|
178
|
-
onClick: () => handleReload()
|
|
179
|
-
}) : null, /*#__PURE__*/_react.default.createElement(_ui.Button, {
|
|
180
|
-
fontSize: [1],
|
|
181
|
-
icon: _icons.CopyIcon,
|
|
182
|
-
padding: [2] // text="Copy"
|
|
183
|
-
,
|
|
184
|
-
title: "Copy",
|
|
185
|
-
"aria-label": "Copy",
|
|
186
|
-
onClick: () => handleCopy()
|
|
187
|
-
}), /*#__PURE__*/_react.default.createElement(_ui.Button, {
|
|
188
|
-
fontSize: [1],
|
|
189
|
-
icon: _icons.LeaveIcon,
|
|
190
|
-
padding: [2],
|
|
191
|
-
text: "Open",
|
|
192
|
-
tone: "primary",
|
|
193
|
-
onClick: () => window.open(displayUrl)
|
|
194
|
-
})))), /*#__PURE__*/_react.default.createElement(_ui.Card, {
|
|
195
|
-
tone: "transparent",
|
|
196
|
-
padding: iframeSize === 'mobile' ? 2 : 0,
|
|
197
|
-
style: {
|
|
198
|
-
height: "100%"
|
|
199
|
-
}
|
|
200
|
-
}, /*#__PURE__*/_react.default.createElement(_ui.Flex, {
|
|
201
|
-
align: "center",
|
|
202
|
-
justify: "center",
|
|
203
|
-
style: {
|
|
204
|
-
height: "100%"
|
|
205
|
-
}
|
|
206
|
-
}, /*#__PURE__*/_react.default.createElement("iframe", {
|
|
207
|
-
ref: iframe,
|
|
208
|
-
title: "preview",
|
|
209
|
-
style: sizes[iframeSize],
|
|
210
|
-
frameBorder: "0",
|
|
211
|
-
src: displayUrl
|
|
212
|
-
})))));
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
Iframe.propTypes = {
|
|
216
|
-
document: _propTypes.default.shape({
|
|
217
|
-
displayed: _propTypes.default.shape({
|
|
218
|
-
_id: _propTypes.default.string.isRequired,
|
|
219
|
-
slug: _propTypes.default.shape({
|
|
220
|
-
current: _propTypes.default.string
|
|
221
|
-
})
|
|
222
|
-
})
|
|
223
|
-
}),
|
|
224
|
-
options: _propTypes.default.shape({
|
|
225
|
-
url: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func])
|
|
226
|
-
})
|
|
227
|
-
};
|
|
228
|
-
var _default = Iframe;
|
|
229
|
-
exports.default = _default;
|
|
230
|
-
//# sourceMappingURL=Iframe.js.map
|
package/lib/Iframe.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Iframe.js"],"names":["sizes","desktop","backgroundColor","width","height","maxHeight","mobile","Iframe","sanityDocument","document","options","url","defaultSize","reload","displayUrl","setDisplayUrl","iframeSize","setIframeSize","input","iframe","displayed","value","copy","handleCopy","current","handleReload","src","revision","_rev","getUrl","resolveUrl","position","pointerEvents","opacity","MobileDeviceIcon","button","UndoIcon","CopyIcon","LeaveIcon","window","open","propTypes","PropTypes","shape","_id","string","isRequired","slug","oneOfType","func"],"mappings":"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","sourcesContent":["import React, {useEffect, useState, useRef} from 'react'\nimport PropTypes from 'prop-types'\nimport {Box, Flex, Text, Button, ThemeProvider, Card, Spinner} from '@sanity/ui'\nimport {UndoIcon, CopyIcon, LeaveIcon, MobileDeviceIcon} from '@sanity/icons'\nimport {useCopyToClipboard} from 'usehooks-ts'\n\nconst sizes = {\n desktop: {backgroundColor: `white`, width: `100%`, height: `100%`, maxHeight: `100%`},\n mobile: {backgroundColor: `white`, width: 414, height: `100%`, maxHeight: 736},\n}\nfunction Iframe({document: sanityDocument, options}) {\n const {url, defaultSize, reload} = options\n const [displayUrl, setDisplayUrl] = useState(typeof url === 'string' ? url : ``)\n const [iframeSize, setIframeSize] = useState(\n defaultSize && sizes?.[defaultSize] ? defaultSize : `desktop`\n )\n const input = useRef()\n const iframe = useRef()\n const {displayed} = sanityDocument\n const [value, copy] = useCopyToClipboard()\n\n function handleCopy() {\n if (!input?.current?.value) return\n\n copy(input.current.value)\n }\n\n function handleReload() {\n if (!iframe?.current) {\n return\n }\n\n // Funky way to reload an iframe without CORS issuies\n iframe.current.src = iframe.current.src\n }\n\n // Reload on new revisions\n useEffect(() => {\n if (reload?.revision) {\n handleReload()\n }\n }, [displayed._rev])\n\n // Set initial URL and refresh on new revisions\n useEffect(() => {\n const getUrl = async () => {\n const resolveUrl = await url(displayed)\n\n // Only update state if URL has changed\n if (resolveUrl !== displayUrl) {\n setDisplayUrl(resolveUrl)\n }\n }\n\n if (typeof url !== 'string') {\n getUrl()\n }\n }, [displayed._rev])\n\n if (!displayUrl || typeof displayUrl !== 'string') {\n return (\n <ThemeProvider>\n <Flex padding={5} items=\"center\" justify=\"center\">\n <Spinner />\n </Flex>\n </ThemeProvider>\n )\n }\n\n return (\n <ThemeProvider>\n <textarea\n style={{position: `absolute`, pointerEvents: `none`, opacity: 0}}\n ref={input}\n value={displayUrl}\n readOnly\n tabIndex=\"-1\"\n />\n <Flex direction=\"column\" style={{height: `100%`}}>\n <Card padding={2} borderBottom={1}>\n <Flex align=\"center\" gap={2}>\n <Flex align=\"center\" gap={1}>\n <Button\n fontSize={[1]}\n padding={2}\n tone=\"primary\"\n mode={iframeSize === 'mobile' ? 'default' : 'ghost'}\n icon={MobileDeviceIcon}\n onClick={() => setIframeSize(iframeSize === 'mobile' ? 'desktop' : 'mobile')}\n />\n </Flex>\n <Box flex={1}>\n <Text size={0} textOverflow=\"ellipsis\">\n {displayUrl}\n </Text>\n </Box>\n <Flex align=\"center\" gap={1}>\n {reload?.button ? (\n <Button\n fontSize={[1]}\n padding={2}\n icon={UndoIcon}\n // text=\"Reload\"\n title=\"Reload\"\n aria-label=\"Reload\"\n onClick={() => handleReload()}\n />\n ) : null}\n <Button\n fontSize={[1]}\n icon={CopyIcon}\n padding={[2]}\n // text=\"Copy\"\n title=\"Copy\"\n aria-label=\"Copy\"\n onClick={() => handleCopy()}\n />\n <Button\n fontSize={[1]}\n icon={LeaveIcon}\n padding={[2]}\n text=\"Open\"\n tone=\"primary\"\n onClick={() => window.open(displayUrl)}\n />\n </Flex>\n </Flex>\n </Card>\n <Card tone=\"transparent\" padding={iframeSize === 'mobile' ? 2 : 0} style={{height: `100%`}}>\n <Flex align=\"center\" justify=\"center\" style={{height: `100%`}}>\n <iframe\n ref={iframe}\n title=\"preview\"\n style={sizes[iframeSize]}\n frameBorder=\"0\"\n src={displayUrl}\n />\n </Flex>\n </Card>\n </Flex>\n </ThemeProvider>\n )\n}\n\nIframe.propTypes = {\n document: PropTypes.shape({\n displayed: PropTypes.shape({\n _id: PropTypes.string.isRequired,\n slug: PropTypes.shape({\n current: PropTypes.string,\n }),\n }),\n }),\n options: PropTypes.shape({\n url: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),\n }),\n}\n\nexport default Iframe\n"],"file":"Iframe.js"}
|
package/src/Iframe.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import React, {useEffect, useState, useRef} from 'react'
|
|
2
|
-
import PropTypes from 'prop-types'
|
|
3
|
-
import {Box, Flex, Text, Button, ThemeProvider, Card, Spinner} from '@sanity/ui'
|
|
4
|
-
import {UndoIcon, CopyIcon, LeaveIcon, MobileDeviceIcon} from '@sanity/icons'
|
|
5
|
-
import {useCopyToClipboard} from 'usehooks-ts'
|
|
6
|
-
|
|
7
|
-
const sizes = {
|
|
8
|
-
desktop: {backgroundColor: `white`, width: `100%`, height: `100%`, maxHeight: `100%`},
|
|
9
|
-
mobile: {backgroundColor: `white`, width: 414, height: `100%`, maxHeight: 736},
|
|
10
|
-
}
|
|
11
|
-
function Iframe({document: sanityDocument, options}) {
|
|
12
|
-
const {url, defaultSize, reload} = options
|
|
13
|
-
const [displayUrl, setDisplayUrl] = useState(typeof url === 'string' ? url : ``)
|
|
14
|
-
const [iframeSize, setIframeSize] = useState(
|
|
15
|
-
defaultSize && sizes?.[defaultSize] ? defaultSize : `desktop`
|
|
16
|
-
)
|
|
17
|
-
const input = useRef()
|
|
18
|
-
const iframe = useRef()
|
|
19
|
-
const {displayed} = sanityDocument
|
|
20
|
-
const [value, copy] = useCopyToClipboard()
|
|
21
|
-
|
|
22
|
-
function handleCopy() {
|
|
23
|
-
if (!input?.current?.value) return
|
|
24
|
-
|
|
25
|
-
copy(input.current.value)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function handleReload() {
|
|
29
|
-
if (!iframe?.current) {
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Funky way to reload an iframe without CORS issuies
|
|
34
|
-
iframe.current.src = iframe.current.src
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Reload on new revisions
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (reload?.revision) {
|
|
40
|
-
handleReload()
|
|
41
|
-
}
|
|
42
|
-
}, [displayed._rev])
|
|
43
|
-
|
|
44
|
-
// Set initial URL and refresh on new revisions
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
const getUrl = async () => {
|
|
47
|
-
const resolveUrl = await url(displayed)
|
|
48
|
-
|
|
49
|
-
// Only update state if URL has changed
|
|
50
|
-
if (resolveUrl !== displayUrl) {
|
|
51
|
-
setDisplayUrl(resolveUrl)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (typeof url !== 'string') {
|
|
56
|
-
getUrl()
|
|
57
|
-
}
|
|
58
|
-
}, [displayed._rev])
|
|
59
|
-
|
|
60
|
-
if (!displayUrl || typeof displayUrl !== 'string') {
|
|
61
|
-
return (
|
|
62
|
-
<ThemeProvider>
|
|
63
|
-
<Flex padding={5} items="center" justify="center">
|
|
64
|
-
<Spinner />
|
|
65
|
-
</Flex>
|
|
66
|
-
</ThemeProvider>
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<ThemeProvider>
|
|
72
|
-
<textarea
|
|
73
|
-
style={{position: `absolute`, pointerEvents: `none`, opacity: 0}}
|
|
74
|
-
ref={input}
|
|
75
|
-
value={displayUrl}
|
|
76
|
-
readOnly
|
|
77
|
-
tabIndex="-1"
|
|
78
|
-
/>
|
|
79
|
-
<Flex direction="column" style={{height: `100%`}}>
|
|
80
|
-
<Card padding={2} borderBottom={1}>
|
|
81
|
-
<Flex align="center" gap={2}>
|
|
82
|
-
<Flex align="center" gap={1}>
|
|
83
|
-
<Button
|
|
84
|
-
fontSize={[1]}
|
|
85
|
-
padding={2}
|
|
86
|
-
tone="primary"
|
|
87
|
-
mode={iframeSize === 'mobile' ? 'default' : 'ghost'}
|
|
88
|
-
icon={MobileDeviceIcon}
|
|
89
|
-
onClick={() => setIframeSize(iframeSize === 'mobile' ? 'desktop' : 'mobile')}
|
|
90
|
-
/>
|
|
91
|
-
</Flex>
|
|
92
|
-
<Box flex={1}>
|
|
93
|
-
<Text size={0} textOverflow="ellipsis">
|
|
94
|
-
{displayUrl}
|
|
95
|
-
</Text>
|
|
96
|
-
</Box>
|
|
97
|
-
<Flex align="center" gap={1}>
|
|
98
|
-
{reload?.button ? (
|
|
99
|
-
<Button
|
|
100
|
-
fontSize={[1]}
|
|
101
|
-
padding={2}
|
|
102
|
-
icon={UndoIcon}
|
|
103
|
-
// text="Reload"
|
|
104
|
-
title="Reload"
|
|
105
|
-
aria-label="Reload"
|
|
106
|
-
onClick={() => handleReload()}
|
|
107
|
-
/>
|
|
108
|
-
) : null}
|
|
109
|
-
<Button
|
|
110
|
-
fontSize={[1]}
|
|
111
|
-
icon={CopyIcon}
|
|
112
|
-
padding={[2]}
|
|
113
|
-
// text="Copy"
|
|
114
|
-
title="Copy"
|
|
115
|
-
aria-label="Copy"
|
|
116
|
-
onClick={() => handleCopy()}
|
|
117
|
-
/>
|
|
118
|
-
<Button
|
|
119
|
-
fontSize={[1]}
|
|
120
|
-
icon={LeaveIcon}
|
|
121
|
-
padding={[2]}
|
|
122
|
-
text="Open"
|
|
123
|
-
tone="primary"
|
|
124
|
-
onClick={() => window.open(displayUrl)}
|
|
125
|
-
/>
|
|
126
|
-
</Flex>
|
|
127
|
-
</Flex>
|
|
128
|
-
</Card>
|
|
129
|
-
<Card tone="transparent" padding={iframeSize === 'mobile' ? 2 : 0} style={{height: `100%`}}>
|
|
130
|
-
<Flex align="center" justify="center" style={{height: `100%`}}>
|
|
131
|
-
<iframe
|
|
132
|
-
ref={iframe}
|
|
133
|
-
title="preview"
|
|
134
|
-
style={sizes[iframeSize]}
|
|
135
|
-
frameBorder="0"
|
|
136
|
-
src={displayUrl}
|
|
137
|
-
/>
|
|
138
|
-
</Flex>
|
|
139
|
-
</Card>
|
|
140
|
-
</Flex>
|
|
141
|
-
</ThemeProvider>
|
|
142
|
-
)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
Iframe.propTypes = {
|
|
146
|
-
document: PropTypes.shape({
|
|
147
|
-
displayed: PropTypes.shape({
|
|
148
|
-
_id: PropTypes.string.isRequired,
|
|
149
|
-
slug: PropTypes.shape({
|
|
150
|
-
current: PropTypes.string,
|
|
151
|
-
}),
|
|
152
|
-
}),
|
|
153
|
-
}),
|
|
154
|
-
options: PropTypes.shape({
|
|
155
|
-
url: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
|
156
|
-
}),
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export default Iframe
|