sanity-plugin-iframe-pane 1.0.13 → 1.0.16

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
@@ -4,7 +4,7 @@ Display any URL in a View Pane, along with helpful buttons to Copy the URL or op
4
4
 
5
5
  Accepts either a string or an async function to resolve a URL based on the current document.
6
6
 
7
- ![Iframe View Pane](https://user-images.githubusercontent.com/9684022/121473207-3548de00-c9ba-11eb-88a0-7d6c748b3f00.png)
7
+ ![Iframe View Pane](https://user-images.githubusercontent.com/9684022/144389599-496e1e50-62a7-4d5c-903a-889885eb8aab.png)
8
8
 
9
9
  ## Installation
10
10
 
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,8 +116,10 @@ function Iframe(_ref) {
106
116
  };
107
117
  }();
108
118
 
109
- if (!displayUrl && displayed !== null && displayed !== void 0 && displayed._id) getUrl();
110
- }, [displayed]);
119
+ if (typeof url !== 'string') {
120
+ getUrl();
121
+ }
122
+ }, [displayed._rev]);
111
123
 
112
124
  if (!displayUrl || typeof displayUrl !== 'string') {
113
125
  return /*#__PURE__*/_react.default.createElement(_ui.ThemeProvider, null, /*#__PURE__*/_react.default.createElement(_ui.Flex, {
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","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, ThemeProvider, Card, Spinner} 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 }, [displayed])\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"}
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.13",
3
+ "version": "1.0.16",
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": {
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "https://raw.githubusercontent.com/SimeonGriggs/sanity-plugin-iframe-pane"
13
+ "url": "https://github.com/SimeonGriggs/sanity-plugin-iframe-pane"
14
14
  },
15
15
  "keywords": [
16
16
  "sanity",
@@ -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
@@ -2,6 +2,7 @@ import React, {useEffect, useState, useRef} from 'react'
2
2
  import PropTypes from 'prop-types'
3
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,17 +39,23 @@ 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
- }, [displayed])
55
+ if (typeof url !== 'string') {
56
+ getUrl()
57
+ }
58
+ }, [displayed._rev])
55
59
 
56
60
  if (!displayUrl || typeof displayUrl !== 'string') {
57
61
  return (