sanity-plugin-iframe-pane 2.0.0 → 2.0.1-v3-studio.2

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
@@ -1,7 +1,10 @@
1
1
  # sanity-plugin-iframe-pane
2
2
 
3
- > NOTE
4
- > This is for the Studio v3 version of the plugin
3
+ > **NOTE**
4
+ >
5
+ > This is the **Sanity Studio v3 version** of sanity-plugin-iframe-pane.
6
+ >
7
+ > For the v2 version, please refer to the [v2-branch](https://github.com/sanity-io/sanity-plugin-iframe-pane).
5
8
 
6
9
  Display any URL in a View Pane, along with helpful buttons to Copy the URL or open in a new tab.
7
10
 
@@ -12,15 +15,17 @@ Accepts either a string or an async function to resolve a URL based on the curre
12
15
  ## Installation
13
16
 
14
17
  ```
15
- npm install --save sanity-plugin-iframe-pane-v3
18
+ npm install --save sanity-plugin-iframe-pane@studio-v3
16
19
  ```
17
20
 
18
21
  or
19
22
 
20
23
  ```
21
- yarn add sanity-plugin-iframe-pane-v3
24
+ yarn add sanity-plugin-iframe-pane@studio-v3
22
25
  ```
23
26
 
27
+ ## Usage
28
+
24
29
  This is designed to be used as a [Component inside of a View](https://www.sanity.io/docs/structure-builder-reference#c0c8284844b7).
25
30
 
26
31
  ```js
@@ -49,5 +54,19 @@ S.view
49
54
 
50
55
  ## License
51
56
 
52
- MIT © Simeon Griggs
53
- See LICENSE
57
+ MIT-licensed. See LICENSE.
58
+
59
+ ## Develop & test
60
+
61
+ This plugin uses [@sanity/plugin-kit](https://github.com/sanity-io/plugin-kit)
62
+ with default configuration for build & watch scripts.
63
+
64
+ See [Testing a plugin in Sanity Studio](https://github.com/sanity-io/plugin-kit#testing-a-plugin-in-sanity-studio)
65
+ on how to run this plugin with hotreload in the studio.
66
+
67
+ ### Release new version
68
+
69
+ Run ["CI & Release" workflow](https://github.com/sanity-io/sanity-plugin-iframe-pane/actions/workflows/main.yml).
70
+ Make sure to select the studio-v3 branch and check "Release new version".
71
+
72
+ Semantic release will only release on configured branches, so it is safe to run release on any branch.
@@ -0,0 +1,2 @@
1
+ import{jsx as e,jsxs as i}from"react/jsx-runtime";import{useState as n,useRef as t,useEffect as o}from"react";import{ThemeProvider as r,Flex as l,Spinner as a,Card as d,Button as c,Box as s,Text as p}from"@sanity/ui";import{MobileDeviceIcon as u,UndoIcon as f,CopyIcon as h,LeaveIcon as g}from"@sanity/icons";import{useCopyToClipboard as m}from"usehooks-ts";const y={desktop:{width:"100%",height:"100%",maxHeight:"100%"},mobile:{width:414,height:"100%",maxHeight:736}},v="desktop";function b(b){const{document:x,options:k}=b,{url:w,defaultSize:z=v,reload:C}=k,[S,j]=n(w&&"string"==typeof w?w:""),[O,B]=n((null==y?void 0:y[z])?z:v),H=t(null),R=t(null),{displayed:_}=x,[,E]=m();function I(){(null==R?void 0:R.current)&&(R.current.src=R.current.src)}return o((()=>{(null==C?void 0:C.revision)&&I()}),[_._rev,null==C?void 0:C.revision]),o((()=>{"function"==typeof w&&(async()=>{const e="function"==typeof w?await w(_):"";e!==S&&e&&"string"==typeof e&&j(e)})()}),[_._rev]),S&&"string"==typeof S?i(r,{children:[e("textarea",{style:{position:"absolute",pointerEvents:"none",opacity:0},ref:H,value:S,readOnly:!0,tabIndex:-1}),i(l,{direction:"column",style:{height:"100%"},children:[e(d,{padding:2,borderBottom:!0,children:i(l,{align:"center",gap:2,children:[e(l,{align:"center",gap:1,children:e(c,{fontSize:[1],padding:2,tone:"primary",mode:"mobile"===O?"default":"ghost",icon:u,onClick:()=>B("mobile"===O?"desktop":"mobile")})}),e(s,{flex:1,children:e(p,{size:0,textOverflow:"ellipsis",children:S})}),i(l,{align:"center",gap:1,children:[(null==C?void 0:C.button)?e(c,{fontSize:[1],padding:2,icon:f,title:"Reload","aria-label":"Reload",onClick:()=>I()}):null,e(c,{fontSize:[1],icon:h,padding:[2],title:"Copy","aria-label":"Copy",onClick:()=>{var e;(null==(e=null==H?void 0:H.current)?void 0:e.value)&&E(H.current.value)}}),e(c,{fontSize:[1],icon:g,padding:[2],text:"Open",tone:"primary",onClick:()=>window.open(S)})]})]})}),e(d,{tone:"transparent",padding:"mobile"===O?2:0,style:{height:"100%"},children:e(l,{align:"center",justify:"center",style:{height:"100%"},children:e("iframe",{ref:R,title:"preview",style:y[O],frameBorder:"0",src:S})})})]})]}):e(r,{children:e(l,{padding:5,align:"center",justify:"center",children:e(a,{})})})}export{b as default};
2
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/Iframe.tsx"],"sourcesContent":["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":["sizes","desktop","width","height","maxHeight","mobile","DEFAULT_SIZE","Iframe","props","document","sanityDocument","options","url","defaultSize","reload","displayUrl","setDisplayUrl","useState","iframeSize","setIframeSize","input","useRef","iframe","displayed","copy","useCopyToClipboard","handleReload","current","src","useEffect","revision","_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","frameBorder","Spinner"],"mappings":"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"}
package/lib/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("react/jsx-runtime"),n=require("react"),i=require("@sanity/ui"),t=require("@sanity/icons"),o=require("usehooks-ts");const r={desktop:{width:"100%",height:"100%",maxHeight:"100%"},mobile:{width:414,height:"100%",maxHeight:736}},l="desktop";module.exports=function(s){const{document:d,options:a}=s,{url:c,defaultSize:u=l,reload:p}=a,[x,h]=n.useState(c&&"string"==typeof c?c:""),[f,g]=n.useState((null==r?void 0:r[u])?u:l),y=n.useRef(null),v=n.useRef(null),{displayed:j}=d,[,m]=o.useCopyToClipboard();function b(){(null==v?void 0:v.current)&&(v.current.src=v.current.src)}return n.useEffect((()=>{(null==p?void 0:p.revision)&&b()}),[j._rev,null==p?void 0:p.revision]),n.useEffect((()=>{"function"==typeof c&&(async()=>{const e="function"==typeof c?await c(j):"";e!==x&&e&&"string"==typeof e&&h(e)})()}),[j._rev]),x&&"string"==typeof x?e.jsxs(i.ThemeProvider,{children:[e.jsx("textarea",{style:{position:"absolute",pointerEvents:"none",opacity:0},ref:y,value:x,readOnly:!0,tabIndex:-1}),e.jsxs(i.Flex,{direction:"column",style:{height:"100%"},children:[e.jsx(i.Card,{padding:2,borderBottom:!0,children:e.jsxs(i.Flex,{align:"center",gap:2,children:[e.jsx(i.Flex,{align:"center",gap:1,children:e.jsx(i.Button,{fontSize:[1],padding:2,tone:"primary",mode:"mobile"===f?"default":"ghost",icon:t.MobileDeviceIcon,onClick:()=>g("mobile"===f?"desktop":"mobile")})}),e.jsx(i.Box,{flex:1,children:e.jsx(i.Text,{size:0,textOverflow:"ellipsis",children:x})}),e.jsxs(i.Flex,{align:"center",gap:1,children:[(null==p?void 0:p.button)?e.jsx(i.Button,{fontSize:[1],padding:2,icon:t.UndoIcon,title:"Reload","aria-label":"Reload",onClick:()=>b()}):null,e.jsx(i.Button,{fontSize:[1],icon:t.CopyIcon,padding:[2],title:"Copy","aria-label":"Copy",onClick:()=>{var e;(null==(e=null==y?void 0:y.current)?void 0:e.value)&&m(y.current.value)}}),e.jsx(i.Button,{fontSize:[1],icon:t.LeaveIcon,padding:[2],text:"Open",tone:"primary",onClick:()=>window.open(x)})]})]})}),e.jsx(i.Card,{tone:"transparent",padding:"mobile"===f?2:0,style:{height:"100%"},children:e.jsx(i.Flex,{align:"center",justify:"center",style:{height:"100%"},children:e.jsx("iframe",{ref:v,title:"preview",style:r[f],frameBorder:"0",src:x})})})]})]}):e.jsx(i.ThemeProvider,{children:e.jsx(i.Flex,{padding:5,align:"center",justify:"center",children:e.jsx(i.Spinner,{})})})};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/Iframe.tsx"],"sourcesContent":["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":["sizes","desktop","width","height","maxHeight","mobile","DEFAULT_SIZE","props","document","sanityDocument","options","url","defaultSize","reload","displayUrl","setDisplayUrl","useState","iframeSize","setIframeSize","input","useRef","iframe","displayed","copy","useCopyToClipboard","handleReload","current","src","useEffect","revision","_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","frameBorder","Spinner"],"mappings":"+IAyBA,MAAMA,EAAmB,CACvBC,QAAS,CACPC,MAAO,OACPC,OAAQ,OACRC,UAAW,QAEbC,OAAQ,CACNH,MAAO,IACPC,OAAQ,OACRC,UAAW,MAoBTE,EAAe,yBAErB,SAAgBC,GACd,MAAQC,SAAUC,EAAgBC,QAAAA,GAAYH,GACxCI,IAAEA,EAAAC,YAAKA,EAAcN,EAAAO,OAAcA,GAAWH,GAC7CI,EAAYC,GAAiBC,EAAAA,SAClCL,GAAsB,iBAARA,EAAmBA,OAE5BM,EAAYC,GAAiBF,EAAAA,UAClC,MAAAhB,OAAA,EAAAA,EAAQY,IAAeA,EAAcN,GAEjCa,EAAQC,SAA4B,MACpCC,EAASD,SAA0B,OACnCE,UAAEA,GAAcb,IACbc,GAAQC,EAAAA,qBAQjB,SAASC,WACFJ,WAAQK,WAMNL,EAAAK,QAAQC,IAAMN,EAAOK,QAAQC,IACtC,CA8BA,OA3BAC,EAAAA,WAAU,YACJf,WAAQgB,WACGJ,GACf,GACC,CAACH,EAAUQ,KAAM,MAAAjB,OAAA,EAAAA,EAAQgB,WAG5BD,EAAAA,WAAU,KAcW,mBAARjB,GAbIoB,WACb,MAAMC,EAA4B,mBAARrB,QAA2BA,EAAIW,GAAa,GAIpEU,IAAelB,GACfkB,GACsB,iBAAfA,GAEPjB,EAAciB,EAChB,EAIOC,EACT,GAEC,CAACX,EAAUQ,OAEThB,GAAoC,iBAAfA,EAWvBoB,EAAAA,KAAAC,EAAAA,cAAA,CACCC,SAAA,CAACC,EAAAA,IAAA,WAAA,CACCC,MAAO,CAAEC,oBAAsBC,cAAe,OAAQC,QAAS,GAC/DC,IAAKvB,EACLwB,MAAO7B,EACP8B,UAAQ,EACRC,UAAU,IAEXX,EAAAA,KAAAY,EAAAA,KAAA,CAAKC,UAAU,SAAST,MAAO,CAAEnC,OAAA,QAChCiC,SAAA,CAACC,EAAAA,IAAAW,EAAAA,KAAA,CAAKC,QAAS,EAAGC,cAAY,EAC5Bd,SAACF,EAAAA,KAAAY,OAAA,CAAKK,MAAM,SAASC,IAAK,EACxBhB,SAAA,CAACC,EAAAA,IAAAS,EAAAA,KAAA,CAAKK,MAAM,SAASC,IAAK,EACxBhB,SAACC,EAAAA,IAAAgB,SAAA,CACCC,SAAU,CAAC,GACXL,QAAS,EACTM,KAAK,UACLC,KAAqB,WAAfvC,EAA0B,UAAY,QAC5CwC,KAAMC,EAAAA,iBACNC,QAAS,IACPzC,EAA6B,WAAfD,EAA0B,UAAY,cAIzDoB,EAAAA,IAAAuB,EAAAA,IAAA,CAAIC,KAAM,EACTzB,SAACC,EAAAA,IAAAyB,OAAA,CAAKC,KAAM,EAAGC,aAAa,WACzB5B,SAAAtB,MAGJoB,EAAAA,KAAAY,EAAAA,KAAA,CAAKK,MAAM,SAASC,IAAK,EACvBhB,SAAA,EAAA,MAAAvB,OAAA,EAAAA,EAAQoD,QACN5B,EAAAA,IAAAgB,SAAA,CACCC,SAAU,CAAC,GACXL,QAAS,EACTQ,KAAMS,EAAAA,SACNC,MAAM,SACN,aAAW,SACXR,QAAS,IAAMlC,MAEf,KACHY,EAAAA,IAAAgB,EAAAA,OAAA,CACCC,SAAU,CAAC,GACXG,KAAMW,EAAAA,SACNnB,QAAS,CAAC,GACVkB,MAAM,OACN,aAAW,OACXR,QAAS,KApGvB,IAtEFU,GAuES,OAAAA,EAAO,MAAAlD,OAAA,EAAAA,EAAAO,cAAS,EAAA2C,EAAA1B,QAEhBpB,EAAAJ,EAAMO,QAAQiB,MAiGmB,IAE3BN,EAAAA,IAAAgB,EAAAA,OAAA,CACCC,SAAU,CAAC,GACXG,KAAMa,EAAAA,UACNrB,QAAS,CAAC,GACVsB,KAAK,OACLhB,KAAK,UACLI,QAAS,IAAMa,OAAOC,KAAK3D,aAKlCuB,EAAAA,IAAAW,EAAAA,KAAA,CACCO,KAAK,cACLN,QAAwB,WAAfhC,EAA0B,EAAI,EACvCqB,MAAO,CAAEnC,OAAA,QAETiC,SAACC,EAAAA,IAAAS,OAAA,CAAKK,MAAM,SAASuB,QAAQ,SAASpC,MAAO,CAAEnC,OAAA,QAC7CiC,SAACC,EAAAA,IAAA,SAAA,CACCK,IAAKrB,EACL8C,MAAM,UACN7B,MAAOtC,EAAMiB,GACb0D,YAAY,IACZhD,IAAKb,cA9EZuB,EAAAA,IAAAF,EAAAA,cAAA,CACCC,SAACC,EAAAA,IAAAS,OAAA,CAAKG,QAAS,EAAGE,MAAM,SAASuB,QAAQ,SACvCtC,eAACwC,EAAQA,QAAA,OAmFnB"}
@@ -0,0 +1,28 @@
1
+ /// <reference types="react" />
2
+
3
+ import {SanityDocumentLike} from 'sanity'
4
+
5
+ declare function Iframe(props: IframeProps): JSX.Element
6
+ export default Iframe
7
+
8
+ export declare type IframeOptions = IframeOptions_2
9
+
10
+ declare type IframeOptions_2 = {
11
+ url: string | ((document: SanityDocumentLike) => unknown)
12
+ defaultSize?: Size
13
+ reload?: {
14
+ revision?: boolean
15
+ button?: boolean
16
+ }
17
+ }
18
+
19
+ declare type IframeProps = {
20
+ document: {
21
+ displayed: SanityDocumentLike
22
+ }
23
+ options: IframeOptions_2
24
+ }
25
+
26
+ declare type Size = 'desktop' | 'mobile'
27
+
28
+ export {}
package/package.json CHANGED
@@ -1,17 +1,20 @@
1
1
  {
2
2
  "name": "sanity-plugin-iframe-pane",
3
- "version": "2.0.0",
3
+ "version": "2.0.1-v3-studio.2",
4
4
  "description": "Display any URL in a View Pane, along with helpful buttons to Copy the URL or open in a new tab",
5
5
  "author": "Simeon Griggs <simeon@sanity.io>",
6
6
  "license": "MIT",
7
7
  "source": "./src/index.ts",
8
- "main": "./lib/cjs/index.js",
9
- "module": "./lib/esm/index.js",
10
- "types": "./lib/types/index.d.ts",
8
+ "main": "./lib/index.js",
9
+ "module": "./lib/index.esm.js",
10
+ "types": "./lib/src/index.d.ts",
11
11
  "exports": {
12
12
  ".": {
13
- "require": "./lib/cjs/index.js",
14
- "default": "./lib/esm/index.js"
13
+ "types": "./lib/src/index.d.ts",
14
+ "source": "./src/index.ts",
15
+ "import": "./lib/index.esm.js",
16
+ "require": "./lib/index.js",
17
+ "default": "./lib/index.esm.js"
15
18
  }
16
19
  },
17
20
  "files": [
@@ -23,43 +26,54 @@
23
26
  "scripts": {
24
27
  "clean": "rimraf lib",
25
28
  "lint": "eslint .",
26
- "prebuild": "npm run clean && plugin-kit verify-package --silent",
27
- "build": "parcel build --no-cache",
28
- "watch": "parcel watch",
29
+ "prebuild": "npm run clean && plugin-kit verify-package --silent && pkg-utils",
30
+ "build": "pkg-utils build",
31
+ "watch": "pkg-utils watch",
29
32
  "link-watch": "plugin-kit link-watch",
30
- "prepublishOnly": "npm run build"
33
+ "prepublishOnly": "npm run build",
34
+ "prepare": "husky install"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git@github.com:sanity-io/sanity-plugin-iframe-pane.git"
31
39
  },
32
- "repository": {},
33
40
  "engines": {
34
41
  "node": ">=14.0.0"
35
42
  },
36
43
  "dependencies": {
37
44
  "@sanity/icons": "^1.3.1",
38
- "@sanity/incompatible-plugin": "^0.0.1-studio-v3.1",
39
- "@sanity/ui": "^0.37.12",
45
+ "@sanity/incompatible-plugin": "^1.0.4",
46
+ "@sanity/ui": "^1.0.0-beta.31",
40
47
  "usehooks-ts": "^2.6.0"
41
48
  },
42
49
  "devDependencies": {
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",
50
+ "@commitlint/cli": "^17.2.0",
51
+ "@commitlint/config-conventional": "^17.2.0",
52
+ "@sanity/pkg-utils": "^1.16.2",
53
+ "@sanity/plugin-kit": "^2.0.7",
54
+ "@sanity/semantic-release-preset": "^2.0.2",
55
+ "@typescript-eslint/eslint-plugin": "^5.42.0",
56
+ "@typescript-eslint/parser": "^5.42.0",
57
+ "eslint": "^8.26.0",
49
58
  "eslint-config-prettier": "^8.5.0",
50
59
  "eslint-config-sanity": "^6.0.0",
51
60
  "eslint-plugin-prettier": "^4.2.1",
52
- "eslint-plugin-react": "^7.30.1",
61
+ "eslint-plugin-react": "^7.31.10",
53
62
  "eslint-plugin-react-hooks": "^4.6.0",
54
- "parcel": "^2.6.2",
63
+ "husky": "^8.0.1",
64
+ "lint-staged": "^13.0.3",
55
65
  "prettier": "^2.7.1",
56
- "react": "^17.0.0 || ^18.0.0",
66
+ "react": "^18.0.0",
57
67
  "rimraf": "^3.0.2",
58
- "sanity": "2.29.5-purple-unicorn.856",
59
- "typescript": "^4.7.4"
68
+ "sanity": "dev-preview || 3.0.0-rc.0",
69
+ "typescript": "^4.8.4"
60
70
  },
61
71
  "peerDependencies": {
62
- "react": "^17.0.0 || ^18.0.0",
63
- "sanity": "purple-unicorn"
64
- }
72
+ "react": "^18.0.0",
73
+ "sanity": "dev-preview || 3.0.0-rc.0"
74
+ },
75
+ "bugs": {
76
+ "url": "https://github.com/sanity-io/sanity-plugin-iframe-pane/issues"
77
+ },
78
+ "homepage": "https://github.com/sanity-io/sanity-plugin-iframe-pane#readme"
65
79
  }
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- import IframeComponent, { IframeOptions as IframeOptionsType } from "./Iframe";
1
+ import IframeComponent, {IframeOptions as IframeOptionsType} from './Iframe'
2
2
 
3
- export default IframeComponent;
3
+ export default IframeComponent
4
4
 
5
- export type IframeOptions = IframeOptionsType;
5
+ export type IframeOptions = IframeOptionsType
package/lib/cjs/index.js DELETED
@@ -1,204 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"mappings":"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","sources":["src/index.ts","src/Iframe.tsx"],"sourcesContent":["import IframeComponent, { IframeOptions as IframeOptionsType } from \"./Iframe\";\n\nexport default IframeComponent;\n\nexport type IframeOptions = IframeOptionsType;\n","import React, { useEffect, useState, useRef } from \"react\";\nimport { SanityDocumentLike } from \"sanity\";\nimport {\n Box,\n Flex,\n Text,\n Button,\n ThemeProvider,\n Card,\n Spinner,\n} from \"@sanity/ui\";\nimport { UndoIcon, CopyIcon, LeaveIcon, MobileDeviceIcon } from \"@sanity/icons\";\n\nimport { useCopyToClipboard } from \"usehooks-ts\";\n\ntype Size = \"desktop\" | \"mobile\";\n\ntype SizeProps = {\n [key in Size]: {\n width: string | number;\n height: string | number;\n maxHeight: string | number;\n };\n};\n\nconst sizes: SizeProps = {\n desktop: {\n width: `100%`,\n height: `100%`,\n maxHeight: `100%`,\n },\n mobile: {\n width: 414,\n height: `100%`,\n maxHeight: 736,\n },\n};\n\nexport type IframeOptions = {\n url: string | ((document: SanityDocumentLike) => unknown);\n defaultSize?: Size;\n reload?: {\n revision?: boolean;\n button?: boolean;\n };\n};\n\nexport type IframeProps = {\n document: {\n displayed: SanityDocumentLike;\n };\n options: IframeOptions;\n};\n\nconst DEFAULT_SIZE = `desktop`;\n\nfunction Iframe(props: IframeProps) {\n const { document: sanityDocument, options } = props;\n const { url, defaultSize = DEFAULT_SIZE, reload } = options;\n const [displayUrl, setDisplayUrl] = useState(\n url && typeof url === \"string\" ? url : ``\n );\n const [iframeSize, setIframeSize] = useState(\n sizes?.[defaultSize] ? defaultSize : DEFAULT_SIZE\n );\n const input = useRef<HTMLTextAreaElement>(null);\n const iframe = useRef<HTMLIFrameElement>(null);\n const { displayed } = sanityDocument;\n const [, copy] = useCopyToClipboard();\n\n function handleCopy() {\n if (!input?.current?.value) return;\n\n copy(input.current.value);\n }\n\n function handleReload() {\n if (!iframe?.current) {\n return;\n }\n\n // Funky way to reload an iframe without CORS issuies\n // eslint-disable-next-line no-self-assign\n iframe.current.src = iframe.current.src;\n }\n\n // Reload on new revisions\n useEffect(() => {\n if (reload?.revision) {\n handleReload();\n }\n }, [displayed._rev, reload?.revision]);\n\n // Set initial URL and refresh on new revisions\n useEffect(() => {\n const getUrl = async () => {\n const resolveUrl = typeof url === \"function\" ? await url(displayed) : ``;\n\n // Only update state if URL has changed\n if (\n resolveUrl !== displayUrl &&\n resolveUrl &&\n typeof resolveUrl === \"string\"\n ) {\n setDisplayUrl(resolveUrl);\n }\n };\n\n if (typeof url === \"function\") {\n getUrl();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [displayed._rev]);\n\n if (!displayUrl || typeof displayUrl !== \"string\") {\n return (\n <ThemeProvider>\n <Flex padding={5} align=\"center\" justify=\"center\">\n <Spinner />\n </Flex>\n </ThemeProvider>\n );\n }\n\n return (\n <ThemeProvider>\n <textarea\n style={{ position: `absolute`, pointerEvents: `none`, opacity: 0 }}\n ref={input}\n value={displayUrl}\n readOnly\n tabIndex={-1}\n />\n <Flex direction=\"column\" style={{ height: `100%` }}>\n <Card padding={2} borderBottom>\n <Flex align=\"center\" gap={2}>\n <Flex align=\"center\" gap={1}>\n <Button\n fontSize={[1]}\n padding={2}\n tone=\"primary\"\n mode={iframeSize === \"mobile\" ? \"default\" : \"ghost\"}\n icon={MobileDeviceIcon}\n onClick={() =>\n setIframeSize(iframeSize === \"mobile\" ? \"desktop\" : \"mobile\")\n }\n />\n </Flex>\n <Box flex={1}>\n <Text size={0} textOverflow=\"ellipsis\">\n {displayUrl}\n </Text>\n </Box>\n <Flex align=\"center\" gap={1}>\n {reload?.button ? (\n <Button\n fontSize={[1]}\n padding={2}\n icon={UndoIcon}\n title=\"Reload\"\n aria-label=\"Reload\"\n onClick={() => handleReload()}\n />\n ) : null}\n <Button\n fontSize={[1]}\n icon={CopyIcon}\n padding={[2]}\n title=\"Copy\"\n aria-label=\"Copy\"\n onClick={() => handleCopy()}\n />\n <Button\n fontSize={[1]}\n icon={LeaveIcon}\n padding={[2]}\n text=\"Open\"\n tone=\"primary\"\n onClick={() => window.open(displayUrl)}\n />\n </Flex>\n </Flex>\n </Card>\n <Card\n tone=\"transparent\"\n padding={iframeSize === \"mobile\" ? 2 : 0}\n style={{ height: `100%` }}\n >\n <Flex align=\"center\" justify=\"center\" style={{ height: `100%` }}>\n <iframe\n ref={iframe}\n title=\"preview\"\n style={sizes[iframeSize]}\n frameBorder=\"0\"\n src={displayUrl}\n />\n </Flex>\n </Card>\n </Flex>\n </ThemeProvider>\n );\n}\n\nexport default Iframe;\n"],"names":[],"version":3,"file":"index.js.map","sourceRoot":"../../"}
package/lib/esm/index.js DELETED
@@ -1,195 +0,0 @@
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
@@ -1 +0,0 @@
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":"../../"}
@@ -1,21 +0,0 @@
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
@@ -1 +0,0 @@
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":"../../"}