sanity-plugin-iframe-pane 2.2.0 → 2.3.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/README.md +4 -1
- package/lib/index.esm.js +1 -2
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +1 -2
- package/lib/index.js.map +1 -1
- package/lib/src/index.d.ts +1 -0
- package/package.json +8 -8
- package/src/Iframe.tsx +14 -4
package/README.md
CHANGED
|
@@ -88,6 +88,9 @@ url: (doc) => resolveProductionUrl(doc),
|
|
|
88
88
|
// OR a string
|
|
89
89
|
url: `https://sanity.io`,
|
|
90
90
|
|
|
91
|
+
// Optional: Display the Url in the pane
|
|
92
|
+
showDisplayUrl: true // boolean. default `true`.
|
|
93
|
+
|
|
91
94
|
// Optional: Set the default size
|
|
92
95
|
defaultSize: `mobile`, // default `desktop`
|
|
93
96
|
|
|
@@ -124,6 +127,6 @@ on how to run this plugin with hotreload in the studio.
|
|
|
124
127
|
### Release new version
|
|
125
128
|
|
|
126
129
|
Run ["CI & Release" workflow](https://github.com/sanity-io/sanity-plugin-iframe-pane/actions/workflows/main.yml).
|
|
127
|
-
Make sure to select the
|
|
130
|
+
Make sure to select the `main` branch and check "Release new version".
|
|
128
131
|
|
|
129
132
|
Semantic release will only release on configured branches, so it is safe to run release on any branch.
|
package/lib/index.esm.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function t(t){for(var i=1;i<arguments.length;i++){var r=null!=arguments[i]?arguments[i]:{};i%2?e(Object(r),!0).forEach((function(e){n(t,e,r[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):e(Object(r)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}import{jsx as i,jsxs as r}from"react/jsx-runtime";import{useState as o,useRef as l,useEffect as c}from"react";import{ThemeProvider as a,Flex as
|
|
2
|
-
//# sourceMappingURL=index.esm.js.map
|
|
1
|
+
function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function t(t){for(var i=1;i<arguments.length;i++){var r=null!=arguments[i]?arguments[i]:{};i%2?e(Object(r),!0).forEach((function(e){n(t,e,r[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):e(Object(r)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var i=n.call(e,t||"default");if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}import{jsx as i,jsxs as r}from"react/jsx-runtime";import{useState as o,useRef as l,useEffect as c}from"react";import{ThemeProvider as a,Flex as u,Spinner as d,Card as s,Button as p,Box as f,Text as y}from"@sanity/ui";import{MobileDeviceIcon as g,UndoIcon as h,CopyIcon as m,LeaveIcon as b}from"@sanity/icons";import{useCopyToClipboard as v}from"usehooks-ts";const O={desktop:{width:"100%",height:"100%",maxHeight:"100%"},mobile:{width:414,height:"100%",maxHeight:736}},j="desktop";function w(e){const{document:n,options:w}=e,{url:P,defaultSize:k=j,reload:S,loader:x,attributes:z={},showDisplayUrl:C=!0}=w,[D,E]=o(P&&"string"==typeof P?P:""),[L,B]=o((null==O?void 0:O[k])?k:j),[H,N]=o(!1),R=l(null),T=l(null),{displayed:_}=n,[,I]=v();function U(){(null==T?void 0:T.current)&&(T.current.src=T.current.src,N(!0))}return c((()=>{((null==S?void 0:S.revision)||0==(null==S?void 0:S.revision))&&setTimeout((()=>{U()}),Number(null==S?void 0:S.revision))}),[_._rev,null==S?void 0:S.revision]),c((()=>{"function"==typeof P&&(async()=>{N(!0);const e="function"==typeof P?await P(_):"";e!==D&&e&&"string"==typeof e&&E(e)})()}),[_._rev]),D&&"string"==typeof D?r(a,{children:[i("textarea",{style:{position:"absolute",pointerEvents:"none",opacity:0},ref:R,value:D,readOnly:!0,tabIndex:-1}),r(u,{direction:"column",style:{height:"100%"},children:[i(s,{padding:2,borderBottom:!0,children:r(u,{align:"center",gap:2,children:[i(u,{align:"center",gap:1,children:i(p,{fontSize:[1],padding:2,tone:"primary",mode:"mobile"===L?"default":"ghost",icon:g,onClick:()=>B("mobile"===L?"desktop":"mobile")})}),i(f,{flex:1,children:C&&i(y,{size:0,textOverflow:"ellipsis",children:D})}),r(u,{align:"center",gap:1,children:[(null==S?void 0:S.button)?i(p,{fontSize:[1],padding:2,icon:h,title:"Reload","aria-label":"Reload",onClick:()=>U()}):null,i(p,{fontSize:[1],icon:m,padding:[2],title:"Copy","aria-label":"Copy",onClick:()=>{var e;(null==(e=null==R?void 0:R.current)?void 0:e.value)&&I(R.current.value)}}),i(p,{fontSize:[1],icon:b,padding:[2],text:"Open",tone:"primary",onClick:()=>window.open(D)})]})]})}),i(s,{tone:"transparent",padding:"mobile"===L?2:0,style:{height:"100%"},children:r(u,{align:"center",justify:"center",style:{height:"100%",position:"relative"},children:[x&&H&&i(u,{justify:"center",align:"center",style:{inset:"0",position:"absolute"},children:i(u,{style:t(t({},O[L]),{},{backgroundColor:"rgba(0,0,0,0.2)"}),justify:"center",align:"center",children:i(s,{padding:4,radius:2,shadow:1,children:r(u,{align:"center",direction:"column",gap:3,height:"fill",justify:"center",children:[i(d,{}),x&&"string"==typeof x&&i(y,{size:1,children:x})]})})})}),i("iframe",t(t({ref:T,title:"preview",style:O[L],frameBorder:"0",src:D},z),{},{onLoad:function(){N(!1),z.onLoad&&"function"==typeof z.onLoad&&z.onLoad()}}))]})})]})]}):i(a,{children:i(u,{padding:5,align:"center",justify:"center",children:i(d,{})})})}export{w as default};//# sourceMappingURL=index.esm.js.map
|
package/lib/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/Iframe.tsx"],"sourcesContent":["/* eslint-disable react/jsx-no-bind */\nimport React, {useEffect, useState, useRef} from 'react'\nimport {SanityDocumentLike} from 'sanity'\nimport {Box, Flex, Text, Button, ThemeProvider, Card, Spinner} from '@sanity/ui'\nimport {UndoIcon, CopyIcon, LeaveIcon, MobileDeviceIcon} from '@sanity/icons'\nimport {HTMLAttributeReferrerPolicy} from 'react'\n\nimport {useCopyToClipboard} from 'usehooks-ts'\n\ntype Size = 'desktop' | 'mobile'\n\ntype SizeProps = {\n // eslint-disable-next-line no-unused-vars\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?: 'desktop' | 'mobile'\n loader?: boolean | string\n reload: {\n revision: boolean | number\n button: boolean\n }\n attributes?: Partial<{\n allow: string\n referrerPolicy: HTMLAttributeReferrerPolicy | undefined\n sandbox: string\n onLoad: () => void\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, loader, attributes = {}} = options\n const [displayUrl, setDisplayUrl] = useState(url && typeof url === 'string' ? url : ``)\n const [iframeSize, setIframeSize] = useState(sizes?.[defaultSize] ? defaultSize : DEFAULT_SIZE)\n const [loading, setLoading] = useState(false)\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 setLoading(true)\n }\n\n function handleIframeLoad() {\n setLoading(false)\n // Run onLoad from attributes\n if (attributes.onLoad && typeof attributes.onLoad === 'function') {\n attributes.onLoad()\n }\n }\n\n // Reload on new revisions\n useEffect(() => {\n if (reload?.revision || reload?.revision == 0) {\n setTimeout(() => {\n handleReload()\n }, Number(reload?.revision))\n }\n }, [displayed._rev, reload?.revision])\n\n // Set initial URL and refresh on new revisions\n useEffect(() => {\n const getUrl = async () => {\n setLoading(true)\n const resolveUrl = typeof url === 'function' ? await url(displayed) : ``\n\n // Only update state if URL has changed\n if (resolveUrl !== displayUrl && resolveUrl && typeof resolveUrl === 'string') {\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={() => 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 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 tone=\"transparent\" padding={iframeSize === 'mobile' ? 2 : 0} style={{height: `100%`}}>\n <Flex align=\"center\" justify=\"center\" style={{height: `100%`, position: `relative`}}>\n {loader && loading && (\n <Flex justify=\"center\" align=\"center\" style={{inset: `0`, position: `absolute`}}>\n <Flex\n style={{...sizes[iframeSize], backgroundColor: `rgba(0,0,0,0.2)`}}\n justify=\"center\"\n align=\"center\"\n >\n <Card padding={4} radius={2} shadow={1}>\n <Flex align=\"center\" direction=\"column\" gap={3} height=\"fill\" justify=\"center\">\n <Spinner />\n {loader && typeof loader === 'string' && <Text size={1}>{loader}</Text>}\n </Flex>\n </Card>\n </Flex>\n </Flex>\n )}\n <iframe\n ref={iframe}\n title=\"preview\"\n style={sizes[iframeSize]}\n frameBorder=\"0\"\n src={displayUrl}\n {...attributes}\n onLoad={handleIframeLoad}\n />\n </Flex>\n </Card>\n </Flex>\n </ThemeProvider>\n )\n}\n\nexport default Iframe\n"],"names":["sizes","desktop","width","height","maxHeight","mobile","DEFAULT_SIZE","Iframe","props","document","sanityDocument","options","url","defaultSize","reload","loader","attributes","displayUrl","setDisplayUrl","useState","iframeSize","setIframeSize","loading","setLoading","input","useRef","iframe","displayed","copy","useCopyToClipboard","handleReload","current","src","useEffect","revision","setTimeout","Number","_rev","async","resolveUrl","getUrl","jsxs","ThemeProvider","children","jsx","style","position","pointerEvents","opacity","ref","value","readOnly","tabIndex","Flex","direction","Card","padding","borderBottom","align","gap","Button","fontSize","tone","mode","icon","MobileDeviceIcon","onClick","Box","flex","Text","size","textOverflow","button","UndoIcon","title","CopyIcon","_a","LeaveIcon","text","window","open","justify","inset","backgroundColor","radius","shadow","Spinner","_objectSpread","frameBorder","onLoad"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/lib/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
"use strict";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var
|
|
2
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function t(t){for(var r=1;r<arguments.length;r++){var i=null!=arguments[r]?arguments[r]:{};r%2?e(Object(i),!0).forEach((function(e){n(t,e,i[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))}))}return t}function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var r=require("react/jsx-runtime"),i=require("react"),o=require("@sanity/ui"),l=require("@sanity/icons"),s=require("usehooks-ts");const c={desktop:{width:"100%",height:"100%",maxHeight:"100%"},mobile:{width:414,height:"100%",maxHeight:736}},a="desktop";module.exports=function(e){const{document:n,options:u}=e,{url:d,defaultSize:p=a,reload:f,loader:y,attributes:g={},showDisplayUrl:x=!0}=u,[j,h]=i.useState(d&&"string"==typeof d?d:""),[b,v]=i.useState((null==c?void 0:c[p])?p:a),[m,O]=i.useState(!1),w=i.useRef(null),S=i.useRef(null),{displayed:C}=n,[,P]=s.useCopyToClipboard();function k(){(null==S?void 0:S.current)&&(S.current.src=S.current.src,O(!0))}return i.useEffect((()=>{((null==f?void 0:f.revision)||0==(null==f?void 0:f.revision))&&setTimeout((()=>{k()}),Number(null==f?void 0:f.revision))}),[C._rev,null==f?void 0:f.revision]),i.useEffect((()=>{"function"==typeof d&&(async()=>{O(!0);const e="function"==typeof d?await d(C):"";e!==j&&e&&"string"==typeof e&&h(e)})()}),[C._rev]),j&&"string"==typeof j?r.jsxs(o.ThemeProvider,{children:[r.jsx("textarea",{style:{position:"absolute",pointerEvents:"none",opacity:0},ref:w,value:j,readOnly:!0,tabIndex:-1}),r.jsxs(o.Flex,{direction:"column",style:{height:"100%"},children:[r.jsx(o.Card,{padding:2,borderBottom:!0,children:r.jsxs(o.Flex,{align:"center",gap:2,children:[r.jsx(o.Flex,{align:"center",gap:1,children:r.jsx(o.Button,{fontSize:[1],padding:2,tone:"primary",mode:"mobile"===b?"default":"ghost",icon:l.MobileDeviceIcon,onClick:()=>v("mobile"===b?"desktop":"mobile")})}),r.jsx(o.Box,{flex:1,children:x&&r.jsx(o.Text,{size:0,textOverflow:"ellipsis",children:j})}),r.jsxs(o.Flex,{align:"center",gap:1,children:[(null==f?void 0:f.button)?r.jsx(o.Button,{fontSize:[1],padding:2,icon:l.UndoIcon,title:"Reload","aria-label":"Reload",onClick:()=>k()}):null,r.jsx(o.Button,{fontSize:[1],icon:l.CopyIcon,padding:[2],title:"Copy","aria-label":"Copy",onClick:()=>{var e;(null==(e=null==w?void 0:w.current)?void 0:e.value)&&P(w.current.value)}}),r.jsx(o.Button,{fontSize:[1],icon:l.LeaveIcon,padding:[2],text:"Open",tone:"primary",onClick:()=>window.open(j)})]})]})}),r.jsx(o.Card,{tone:"transparent",padding:"mobile"===b?2:0,style:{height:"100%"},children:r.jsxs(o.Flex,{align:"center",justify:"center",style:{height:"100%",position:"relative"},children:[y&&m&&r.jsx(o.Flex,{justify:"center",align:"center",style:{inset:"0",position:"absolute"},children:r.jsx(o.Flex,{style:t(t({},c[b]),{},{backgroundColor:"rgba(0,0,0,0.2)"}),justify:"center",align:"center",children:r.jsx(o.Card,{padding:4,radius:2,shadow:1,children:r.jsxs(o.Flex,{align:"center",direction:"column",gap:3,height:"fill",justify:"center",children:[r.jsx(o.Spinner,{}),y&&"string"==typeof y&&r.jsx(o.Text,{size:1,children:y})]})})})}),r.jsx("iframe",t(t({ref:S,title:"preview",style:c[b],frameBorder:"0",src:j},g),{},{onLoad:function(){O(!1),g.onLoad&&"function"==typeof g.onLoad&&g.onLoad()}}))]})})]})]}):r.jsx(o.ThemeProvider,{children:r.jsx(o.Flex,{padding:5,align:"center",justify:"center",children:r.jsx(o.Spinner,{})})})};//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/Iframe.tsx"],"sourcesContent":["/* eslint-disable react/jsx-no-bind */\nimport React, {useEffect, useState, useRef} from 'react'\nimport {SanityDocumentLike} from 'sanity'\nimport {Box, Flex, Text, Button, ThemeProvider, Card, Spinner} from '@sanity/ui'\nimport {UndoIcon, CopyIcon, LeaveIcon, MobileDeviceIcon} from '@sanity/icons'\nimport {HTMLAttributeReferrerPolicy} from 'react'\n\nimport {useCopyToClipboard} from 'usehooks-ts'\n\ntype Size = 'desktop' | 'mobile'\n\ntype SizeProps = {\n // eslint-disable-next-line no-unused-vars\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?: 'desktop' | 'mobile'\n loader?: boolean | string\n reload: {\n revision: boolean | number\n button: boolean\n }\n attributes?: Partial<{\n allow: string\n referrerPolicy: HTMLAttributeReferrerPolicy | undefined\n sandbox: string\n onLoad: () => void\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, loader, attributes = {}} = options\n const [displayUrl, setDisplayUrl] = useState(url && typeof url === 'string' ? url : ``)\n const [iframeSize, setIframeSize] = useState(sizes?.[defaultSize] ? defaultSize : DEFAULT_SIZE)\n const [loading, setLoading] = useState(false)\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 setLoading(true)\n }\n\n function handleIframeLoad() {\n setLoading(false)\n // Run onLoad from attributes\n if (attributes.onLoad && typeof attributes.onLoad === 'function') {\n attributes.onLoad()\n }\n }\n\n // Reload on new revisions\n useEffect(() => {\n if (reload?.revision || reload?.revision == 0) {\n setTimeout(() => {\n handleReload()\n }, Number(reload?.revision))\n }\n }, [displayed._rev, reload?.revision])\n\n // Set initial URL and refresh on new revisions\n useEffect(() => {\n const getUrl = async () => {\n setLoading(true)\n const resolveUrl = typeof url === 'function' ? await url(displayed) : ``\n\n // Only update state if URL has changed\n if (resolveUrl !== displayUrl && resolveUrl && typeof resolveUrl === 'string') {\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={() => 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 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 tone=\"transparent\" padding={iframeSize === 'mobile' ? 2 : 0} style={{height: `100%`}}>\n <Flex align=\"center\" justify=\"center\" style={{height: `100%`, position: `relative`}}>\n {loader && loading && (\n <Flex justify=\"center\" align=\"center\" style={{inset: `0`, position: `absolute`}}>\n <Flex\n style={{...sizes[iframeSize], backgroundColor: `rgba(0,0,0,0.2)`}}\n justify=\"center\"\n align=\"center\"\n >\n <Card padding={4} radius={2} shadow={1}>\n <Flex align=\"center\" direction=\"column\" gap={3} height=\"fill\" justify=\"center\">\n <Spinner />\n {loader && typeof loader === 'string' && <Text size={1}>{loader}</Text>}\n </Flex>\n </Card>\n </Flex>\n </Flex>\n )}\n <iframe\n ref={iframe}\n title=\"preview\"\n style={sizes[iframeSize]}\n frameBorder=\"0\"\n src={displayUrl}\n {...attributes}\n onLoad={handleIframeLoad}\n />\n </Flex>\n </Card>\n </Flex>\n </ThemeProvider>\n )\n}\n\nexport default Iframe\n"],"names":["sizes","desktop","width","height","maxHeight","mobile","DEFAULT_SIZE","props","document","sanityDocument","options","url","defaultSize","reload","loader","attributes","displayUrl","setDisplayUrl","useState","iframeSize","setIframeSize","loading","setLoading","input","useRef","iframe","displayed","copy","useCopyToClipboard","handleReload","current","src","useEffect","revision","setTimeout","Number","_rev","async","resolveUrl","getUrl","jsxs","ThemeProvider","children","jsx","style","position","pointerEvents","opacity","ref","value","readOnly","tabIndex","Flex","direction","Card","padding","borderBottom","align","gap","Button","fontSize","tone","mode","icon","MobileDeviceIcon","onClick","Box","flex","Text","size","textOverflow","button","UndoIcon","title","CopyIcon","_a","LeaveIcon","text","window","open","justify","inset","backgroundColor","radius","shadow","Spinner","_objectSpread","frameBorder","onLoad"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/lib/src/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanity-plugin-iframe-pane",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.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
|
"homepage": "https://github.com/sanity-io/sanity-plugin-iframe-pane#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -43,16 +43,16 @@
|
|
|
43
43
|
"watch": "pkg-utils watch"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@sanity/icons": "^2.
|
|
46
|
+
"@sanity/icons": "^2.2.2",
|
|
47
47
|
"@sanity/incompatible-plugin": "^1.0.4",
|
|
48
|
-
"@sanity/ui": "^1.
|
|
49
|
-
"usehooks-ts": "^2.
|
|
48
|
+
"@sanity/ui": "^1.3.0",
|
|
49
|
+
"usehooks-ts": "^2.9.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@commitlint/cli": "^17.2.0",
|
|
53
53
|
"@commitlint/config-conventional": "^17.2.0",
|
|
54
|
-
"@sanity/pkg-utils": "^1.
|
|
55
|
-
"@sanity/plugin-kit": "^2.
|
|
54
|
+
"@sanity/pkg-utils": "^1.20.4",
|
|
55
|
+
"@sanity/plugin-kit": "^2.2.0",
|
|
56
56
|
"@sanity/semantic-release-preset": "^2.0.2",
|
|
57
57
|
"@typescript-eslint/eslint-plugin": "^5.42.0",
|
|
58
58
|
"@typescript-eslint/parser": "^5.42.0",
|
|
@@ -65,11 +65,11 @@
|
|
|
65
65
|
"husky": "^8.0.1",
|
|
66
66
|
"lint-staged": "^13.0.3",
|
|
67
67
|
"prettier": "^2.7.1",
|
|
68
|
-
"prettier-plugin-packagejson": "^2.3
|
|
68
|
+
"prettier-plugin-packagejson": "^2.4.3",
|
|
69
69
|
"react": "^18",
|
|
70
70
|
"rimraf": "^3.0.2",
|
|
71
71
|
"sanity": "^3.0.0",
|
|
72
|
-
"typescript": "^
|
|
72
|
+
"typescript": "^5.0.0"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"react": "^18",
|
package/src/Iframe.tsx
CHANGED
|
@@ -35,6 +35,7 @@ export type IframeOptions = {
|
|
|
35
35
|
url: string | ((document: SanityDocumentLike) => unknown)
|
|
36
36
|
defaultSize?: 'desktop' | 'mobile'
|
|
37
37
|
loader?: boolean | string
|
|
38
|
+
showDisplayUrl?: boolean
|
|
38
39
|
reload: {
|
|
39
40
|
revision: boolean | number
|
|
40
41
|
button: boolean
|
|
@@ -58,7 +59,14 @@ const DEFAULT_SIZE = `desktop`
|
|
|
58
59
|
|
|
59
60
|
function Iframe(props: IframeProps) {
|
|
60
61
|
const {document: sanityDocument, options} = props
|
|
61
|
-
const {
|
|
62
|
+
const {
|
|
63
|
+
url,
|
|
64
|
+
defaultSize = DEFAULT_SIZE,
|
|
65
|
+
reload,
|
|
66
|
+
loader,
|
|
67
|
+
attributes = {},
|
|
68
|
+
showDisplayUrl = true,
|
|
69
|
+
} = options
|
|
62
70
|
const [displayUrl, setDisplayUrl] = useState(url && typeof url === 'string' ? url : ``)
|
|
63
71
|
const [iframeSize, setIframeSize] = useState(sizes?.[defaultSize] ? defaultSize : DEFAULT_SIZE)
|
|
64
72
|
const [loading, setLoading] = useState(false)
|
|
@@ -153,9 +161,11 @@ function Iframe(props: IframeProps) {
|
|
|
153
161
|
/>
|
|
154
162
|
</Flex>
|
|
155
163
|
<Box flex={1}>
|
|
156
|
-
|
|
157
|
-
{
|
|
158
|
-
|
|
164
|
+
{showDisplayUrl && (
|
|
165
|
+
<Text size={0} textOverflow="ellipsis">
|
|
166
|
+
{displayUrl}
|
|
167
|
+
</Text>
|
|
168
|
+
)}
|
|
159
169
|
</Box>
|
|
160
170
|
<Flex align="center" gap={1}>
|
|
161
171
|
{reload?.button ? (
|