sanity-plugin-iframe-pane 1.0.11 → 1.0.15

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/README.md CHANGED
@@ -29,8 +29,8 @@ S.view
29
29
  url: `https://sanity.io`,
30
30
  // Optional: Set the default size
31
31
  defaultSize: `mobile`, // default `desktop`
32
- // Optional: Add a refresh button, or refresh on new document revisions
33
- refresh: {
32
+ // Optional: Add a reload button, or reload on new document revisions
33
+ reload: {
34
34
  button: true, // default `undefined`
35
35
  revision: true, // default `undefined`
36
36
  },
package/lib/Iframe.js CHANGED
@@ -13,6 +13,8 @@ var _ui = require("@sanity/ui");
13
13
 
14
14
  var _icons = require("@sanity/icons");
15
15
 
16
+ var _usehooksTs = require("usehooks-ts");
17
+
16
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
19
 
18
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); }
@@ -71,12 +73,16 @@ function Iframe(_ref) {
71
73
  var iframe = (0, _react.useRef)();
72
74
  var displayed = sanityDocument.displayed;
73
75
 
76
+ var _useCopyToClipboard = (0, _usehooksTs.useCopyToClipboard)(),
77
+ _useCopyToClipboard2 = _slicedToArray(_useCopyToClipboard, 2),
78
+ value = _useCopyToClipboard2[0],
79
+ copy = _useCopyToClipboard2[1];
80
+
74
81
  function handleCopy() {
75
- if (!(input !== null && input !== void 0 && input.current)) return;
76
- input.current.select();
77
- input.current.setSelectionRange(0, 99999); // eslint-disable-next-line react/prop-types
82
+ var _input$current;
78
83
 
79
- document.execCommand('copy');
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);
80
86
  }
81
87
 
82
88
  function handleReload() {
@@ -93,12 +99,16 @@ function Iframe(_ref) {
93
99
  if (reload !== null && reload !== void 0 && reload.revision) {
94
100
  handleReload();
95
101
  }
96
- }, [displayed === null || displayed === void 0 ? void 0 : displayed._rev]);
102
+ }, [displayed._rev]); // Set initial URL and refresh on new revisions
103
+
97
104
  (0, _react.useEffect)(() => {
98
105
  var getUrl = /*#__PURE__*/function () {
99
106
  var _ref2 = _asyncToGenerator(function* () {
100
- var resolveUrl = yield url(displayed);
101
- setDisplayUrl(resolveUrl);
107
+ var resolveUrl = yield url(displayed); // Only update state if URL has changed
108
+
109
+ if (resolveUrl !== displayUrl) {
110
+ setDisplayUrl(resolveUrl);
111
+ }
102
112
  });
103
113
 
104
114
  return function getUrl() {
@@ -106,15 +116,17 @@ function Iframe(_ref) {
106
116
  };
107
117
  }();
108
118
 
109
- if (!displayUrl && displayed !== null && displayed !== void 0 && displayed._id) getUrl(); // eslint-disable-next-line react-hooks/exhaustive-deps
110
- }, []);
119
+ if (typeof url !== 'string') {
120
+ getUrl();
121
+ }
122
+ }, [displayed._rev]);
111
123
 
112
124
  if (!displayUrl || typeof displayUrl !== 'string') {
113
- return /*#__PURE__*/_react.default.createElement("div", {
114
- style: {
115
- padding: "1rem"
116
- }
117
- }, "Loading...");
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)));
118
130
  }
119
131
 
120
132
  return /*#__PURE__*/_react.default.createElement(_ui.ThemeProvider, null, /*#__PURE__*/_react.default.createElement("textarea", {
package/lib/Iframe.js.map CHANGED
@@ -1 +1 @@
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","handleCopy","current","select","setSelectionRange","execCommand","handleReload","src","revision","_rev","getUrl","resolveUrl","_id","padding","position","pointerEvents","opacity","MobileDeviceIcon","button","UndoIcon","CopyIcon","LeaveIcon","window","open","propTypes","PropTypes","shape","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, Stack, ThemeProvider, Card} from '@sanity/ui'\nimport {UndoIcon, CopyIcon, LeaveIcon, MobileDeviceIcon} from '@sanity/icons'\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\n function handleCopy() {\n if (!input?.current) return\n\n input.current.select()\n input.current.setSelectionRange(0, 99999)\n\n // eslint-disable-next-line react/prop-types\n document.execCommand('copy')\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 useEffect(() => {\n const getUrl = async () => {\n const resolveUrl = await url(displayed)\n\n setDisplayUrl(resolveUrl)\n }\n\n if (!displayUrl && displayed?._id) getUrl()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n if (!displayUrl || typeof displayUrl !== 'string') {\n return <div style={{padding: `1rem`}}>Loading...</div>\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"}
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sanity-plugin-iframe-pane",
3
- "version": "1.0.11",
3
+ "version": "1.0.15",
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
  "main": "lib/Iframe.js",
6
6
  "scripts": {
@@ -21,7 +21,8 @@
21
21
  "dependencies": {
22
22
  "@sanity/icons": "^1.2.1",
23
23
  "@sanity/ui": "^0.36.12",
24
- "prop-types": "15.7.2"
24
+ "prop-types": "15.7.2",
25
+ "usehooks-ts": "^1.2.0"
25
26
  },
26
27
  "devDependencies": {
27
28
  "eslint": "7.32.0",
package/src/Iframe.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import React, {useEffect, useState, useRef} from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import {Box, Flex, Text, Button, Stack, ThemeProvider, Card} from '@sanity/ui'
3
+ import {Box, Flex, Text, Button, ThemeProvider, Card, Spinner} from '@sanity/ui'
4
4
  import {UndoIcon, CopyIcon, LeaveIcon, MobileDeviceIcon} from '@sanity/icons'
5
+ import {useCopyToClipboard} from 'usehooks-ts'
5
6
 
6
7
  const sizes = {
7
8
  desktop: {backgroundColor: `white`, width: `100%`, height: `100%`, maxHeight: `100%`},
@@ -16,15 +17,12 @@ function Iframe({document: sanityDocument, options}) {
16
17
  const input = useRef()
17
18
  const iframe = useRef()
18
19
  const {displayed} = sanityDocument
20
+ const [value, copy] = useCopyToClipboard()
19
21
 
20
22
  function handleCopy() {
21
- if (!input?.current) return
23
+ if (!input?.current?.value) return
22
24
 
23
- input.current.select()
24
- input.current.setSelectionRange(0, 99999)
25
-
26
- // eslint-disable-next-line react/prop-types
27
- document.execCommand('copy')
25
+ copy(input.current.value)
28
26
  }
29
27
 
30
28
  function handleReload() {
@@ -41,21 +39,32 @@ function Iframe({document: sanityDocument, options}) {
41
39
  if (reload?.revision) {
42
40
  handleReload()
43
41
  }
44
- }, [displayed?._rev])
42
+ }, [displayed._rev])
45
43
 
44
+ // Set initial URL and refresh on new revisions
46
45
  useEffect(() => {
47
46
  const getUrl = async () => {
48
47
  const resolveUrl = await url(displayed)
49
48
 
50
- setDisplayUrl(resolveUrl)
49
+ // Only update state if URL has changed
50
+ if (resolveUrl !== displayUrl) {
51
+ setDisplayUrl(resolveUrl)
52
+ }
51
53
  }
52
54
 
53
- if (!displayUrl && displayed?._id) getUrl()
54
- // eslint-disable-next-line react-hooks/exhaustive-deps
55
- }, [])
55
+ if (typeof url !== 'string') {
56
+ getUrl()
57
+ }
58
+ }, [displayed._rev])
56
59
 
57
60
  if (!displayUrl || typeof displayUrl !== 'string') {
58
- return <div style={{padding: `1rem`}}>Loading...</div>
61
+ return (
62
+ <ThemeProvider>
63
+ <Flex padding={5} items="center" justify="center">
64
+ <Spinner />
65
+ </Flex>
66
+ </ThemeProvider>
67
+ )
59
68
  }
60
69
 
61
70
  return (