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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 Simeon Griggs
3
+ Copyright (c) 2022 Simeon Griggs
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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
- ![Iframe View Pane](https://user-images.githubusercontent.com/9684022/121473207-3548de00-c9ba-11eb-88a0-7d6c748b3f00.png)
10
+ ![Iframe View Pane](https://user-images.githubusercontent.com/9684022/144389599-496e1e50-62a7-4d5c-903a-889885eb8aab.png)
8
11
 
9
12
  ## Installation
10
13
 
11
14
  ```
12
- sanity install iframe-pane
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).
@@ -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":"../../"}
@@ -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": "1.0.15",
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
- "main": "lib/Iframe.js",
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
- "build": "sanipack build",
8
- "watch": "sanipack build --watch",
9
- "prepublishOnly": "sanipack build && sanipack verify"
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
- "type": "git",
13
- "url": "https://raw.githubusercontent.com/SimeonGriggs/sanity-plugin-iframe-pane"
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.2.1",
23
- "@sanity/ui": "^0.36.12",
24
- "prop-types": "15.7.2",
25
- "usehooks-ts": "^1.2.0"
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
- "eslint": "7.32.0",
29
- "eslint-config-prettier": "8.3.0",
30
- "eslint-config-sanity": "5.1.0",
31
- "eslint-plugin-react": "7.26.0",
32
- "prettier": "2.4.1",
33
- "sanipack": "2.0.1"
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.2"
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
@@ -1,7 +1,8 @@
1
1
  {
2
- "paths": {
3
- "source": "./src",
4
- "compiled": "./lib"
5
- },
6
- "parts": []
7
- }
2
+ "parts": [
3
+ {
4
+ "implements": "part:@sanity/base/sanity-root",
5
+ "path": "./v2-incompatible.js"
6
+ }
7
+ ]
8
+ }
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,5 @@
1
+ import IframeComponent, { IframeOptions as IframeOptionsType } from "./Iframe";
2
+
3
+ export default IframeComponent;
4
+
5
+ export type IframeOptions = IframeOptionsType;
@@ -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
@@ -1,3 +0,0 @@
1
- {
2
- "extends": "sanipack/babel"
3
- }
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