sanity-plugin-iframe-pane 2.1.1 → 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/LICENSE +1 -1
- package/README.md +86 -30
- 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 +3 -0
- package/package.json +8 -8
- package/src/Iframe.tsx +47 -5
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> This is a **Sanity Studio v3** plugin.
|
|
4
4
|
> For the v2 version, please refer to the [v2-branch](https://github.com/sanity-io/sanity-plugin-iframe-pane/tree/studio-v2).
|
|
5
5
|
|
|
6
|
-
Display any URL in a View Pane, along with helpful buttons to Copy the URL or open in a new tab.
|
|
6
|
+
Display any URL in a View Pane, along with helpful buttons to Copy the URL or open it in a new tab.
|
|
7
7
|
|
|
8
8
|
Accepts either a string or an async function to resolve a URL based on the current document.
|
|
9
9
|
|
|
@@ -23,37 +23,93 @@ yarn add sanity-plugin-iframe-pane
|
|
|
23
23
|
|
|
24
24
|
## Usage
|
|
25
25
|
|
|
26
|
-
This is designed to be used as a [Component inside of a View](https://www.sanity.io/docs/structure-builder-reference#c0c8284844b7).
|
|
26
|
+
This is designed to be used as a [Component inside of a View](https://www.sanity.io/docs/structure-builder-reference#c0c8284844b7).
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
The simplest way to configure views is by customizing the `defaultDocumentNode` setting in the `deskTool()` plugin.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
// ./sanity.config.ts
|
|
32
|
+
|
|
33
|
+
export default defineConfig({
|
|
34
|
+
// ...other config settings
|
|
35
|
+
plugins: [
|
|
36
|
+
deskTool({
|
|
37
|
+
defaultDocumentNode,
|
|
38
|
+
structure, // not required
|
|
39
|
+
}),
|
|
40
|
+
// ...other plugins
|
|
41
|
+
],
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
A basic example of a custom `defaultDocumentNode` function, to only show the Iframe Pane on `movie` type documents.
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
|
|
49
|
+
// ./src/defaultDocumentNode.ts
|
|
50
|
+
|
|
51
|
+
import {DefaultDocumentNodeResolver} from 'sanity/desk'
|
|
30
52
|
import Iframe from 'sanity-plugin-iframe-pane'
|
|
53
|
+
import {SanityDocument} from 'sanity'
|
|
54
|
+
|
|
55
|
+
// Customise this function to show the correct URL based on the current document
|
|
56
|
+
function getPreviewUrl(doc: SanityDocument) {
|
|
57
|
+
return doc?.slug?.current
|
|
58
|
+
? `${window.location.host}/${doc.slug.current}`
|
|
59
|
+
: `${window.location.host}`
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Import this into the deskTool() plugin
|
|
63
|
+
export const defaultDocumentNode: DefaultDocumentNodeResolver = (S, {schemaType}) => {
|
|
64
|
+
// Only show preview pane on `movie` schema type documents
|
|
65
|
+
switch (schemaType) {
|
|
66
|
+
case `movie`:
|
|
67
|
+
return S.document().views([
|
|
68
|
+
S.view.form(),
|
|
69
|
+
S.view
|
|
70
|
+
.component(Iframe)
|
|
71
|
+
.options({
|
|
72
|
+
url: (doc: SanityDocument) => getPreviewUrl(doc),
|
|
73
|
+
})
|
|
74
|
+
.title('Preview'),
|
|
75
|
+
])
|
|
76
|
+
default:
|
|
77
|
+
return S.document().views([S.view.form()])
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
31
81
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
82
|
+
## Options
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
// Required: Accepts an async function
|
|
86
|
+
url: (doc) => resolveProductionUrl(doc),
|
|
87
|
+
|
|
88
|
+
// OR a string
|
|
89
|
+
url: `https://sanity.io`,
|
|
90
|
+
|
|
91
|
+
// Optional: Display the Url in the pane
|
|
92
|
+
showDisplayUrl: true // boolean. default `true`.
|
|
93
|
+
|
|
94
|
+
// Optional: Set the default size
|
|
95
|
+
defaultSize: `mobile`, // default `desktop`
|
|
96
|
+
|
|
97
|
+
// Optional: Add a reload button, or reload on new document revisions
|
|
98
|
+
reload: {
|
|
99
|
+
button: true, // default `undefined`
|
|
100
|
+
revision: true, // boolean | number. default `undefined`. If a number is provided, add a delay (in ms) before the automatic reload on document revision
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
// Optional: Display a spinner while the iframe is loading
|
|
104
|
+
loader: true // boolean | string. default `undefined`. If a string is provided, it will be display below the spinner (e.g. Loading…)
|
|
105
|
+
|
|
106
|
+
// Optional: Pass attributes to the underlying `iframe` element:
|
|
107
|
+
// See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe
|
|
108
|
+
attributes: {
|
|
109
|
+
allow: 'fullscreen', // string, optional
|
|
110
|
+
referrerPolicy: 'strict-origin-when-cross-origin', // string, optional
|
|
111
|
+
sandbox: 'allow-same-origin', // string, optional
|
|
112
|
+
}
|
|
57
113
|
```
|
|
58
114
|
|
|
59
115
|
## License
|
|
@@ -71,6 +127,6 @@ on how to run this plugin with hotreload in the studio.
|
|
|
71
127
|
### Release new version
|
|
72
128
|
|
|
73
129
|
Run ["CI & Release" workflow](https://github.com/sanity-io/sanity-plugin-iframe-pane/actions/workflows/main.yml).
|
|
74
|
-
Make sure to select the
|
|
130
|
+
Make sure to select the `main` branch and check "Release new version".
|
|
75
131
|
|
|
76
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":[
|
|
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 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 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}},
|
|
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":[
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/lib/src/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export declare type IframeOptions = IframeOptions_2
|
|
|
9
9
|
declare type IframeOptions_2 = {
|
|
10
10
|
url: string | ((document: SanityDocumentLike) => unknown)
|
|
11
11
|
defaultSize?: 'desktop' | 'mobile'
|
|
12
|
+
loader?: boolean | string
|
|
13
|
+
showDisplayUrl?: boolean
|
|
12
14
|
reload: {
|
|
13
15
|
revision: boolean | number
|
|
14
16
|
button: boolean
|
|
@@ -17,6 +19,7 @@ declare type IframeOptions_2 = {
|
|
|
17
19
|
allow: string
|
|
18
20
|
referrerPolicy: HTMLAttributeReferrerPolicy | undefined
|
|
19
21
|
sandbox: string
|
|
22
|
+
onLoad: () => void
|
|
20
23
|
}>
|
|
21
24
|
}
|
|
22
25
|
|
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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable react/jsx-no-bind */
|
|
1
2
|
import React, {useEffect, useState, useRef} from 'react'
|
|
2
3
|
import {SanityDocumentLike} from 'sanity'
|
|
3
4
|
import {Box, Flex, Text, Button, ThemeProvider, Card, Spinner} from '@sanity/ui'
|
|
@@ -33,6 +34,8 @@ const sizes: SizeProps = {
|
|
|
33
34
|
export type IframeOptions = {
|
|
34
35
|
url: string | ((document: SanityDocumentLike) => unknown)
|
|
35
36
|
defaultSize?: 'desktop' | 'mobile'
|
|
37
|
+
loader?: boolean | string
|
|
38
|
+
showDisplayUrl?: boolean
|
|
36
39
|
reload: {
|
|
37
40
|
revision: boolean | number
|
|
38
41
|
button: boolean
|
|
@@ -41,6 +44,7 @@ export type IframeOptions = {
|
|
|
41
44
|
allow: string
|
|
42
45
|
referrerPolicy: HTMLAttributeReferrerPolicy | undefined
|
|
43
46
|
sandbox: string
|
|
47
|
+
onLoad: () => void
|
|
44
48
|
}>
|
|
45
49
|
}
|
|
46
50
|
|
|
@@ -55,9 +59,17 @@ const DEFAULT_SIZE = `desktop`
|
|
|
55
59
|
|
|
56
60
|
function Iframe(props: IframeProps) {
|
|
57
61
|
const {document: sanityDocument, options} = props
|
|
58
|
-
const {
|
|
62
|
+
const {
|
|
63
|
+
url,
|
|
64
|
+
defaultSize = DEFAULT_SIZE,
|
|
65
|
+
reload,
|
|
66
|
+
loader,
|
|
67
|
+
attributes = {},
|
|
68
|
+
showDisplayUrl = true,
|
|
69
|
+
} = options
|
|
59
70
|
const [displayUrl, setDisplayUrl] = useState(url && typeof url === 'string' ? url : ``)
|
|
60
71
|
const [iframeSize, setIframeSize] = useState(sizes?.[defaultSize] ? defaultSize : DEFAULT_SIZE)
|
|
72
|
+
const [loading, setLoading] = useState(false)
|
|
61
73
|
const input = useRef<HTMLTextAreaElement>(null)
|
|
62
74
|
const iframe = useRef<HTMLIFrameElement>(null)
|
|
63
75
|
const {displayed} = sanityDocument
|
|
@@ -77,6 +89,16 @@ function Iframe(props: IframeProps) {
|
|
|
77
89
|
// Funky way to reload an iframe without CORS issuies
|
|
78
90
|
// eslint-disable-next-line no-self-assign
|
|
79
91
|
iframe.current.src = iframe.current.src
|
|
92
|
+
|
|
93
|
+
setLoading(true)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function handleIframeLoad() {
|
|
97
|
+
setLoading(false)
|
|
98
|
+
// Run onLoad from attributes
|
|
99
|
+
if (attributes.onLoad && typeof attributes.onLoad === 'function') {
|
|
100
|
+
attributes.onLoad()
|
|
101
|
+
}
|
|
80
102
|
}
|
|
81
103
|
|
|
82
104
|
// Reload on new revisions
|
|
@@ -91,6 +113,7 @@ function Iframe(props: IframeProps) {
|
|
|
91
113
|
// Set initial URL and refresh on new revisions
|
|
92
114
|
useEffect(() => {
|
|
93
115
|
const getUrl = async () => {
|
|
116
|
+
setLoading(true)
|
|
94
117
|
const resolveUrl = typeof url === 'function' ? await url(displayed) : ``
|
|
95
118
|
|
|
96
119
|
// Only update state if URL has changed
|
|
@@ -138,9 +161,11 @@ function Iframe(props: IframeProps) {
|
|
|
138
161
|
/>
|
|
139
162
|
</Flex>
|
|
140
163
|
<Box flex={1}>
|
|
141
|
-
|
|
142
|
-
{
|
|
143
|
-
|
|
164
|
+
{showDisplayUrl && (
|
|
165
|
+
<Text size={0} textOverflow="ellipsis">
|
|
166
|
+
{displayUrl}
|
|
167
|
+
</Text>
|
|
168
|
+
)}
|
|
144
169
|
</Box>
|
|
145
170
|
<Flex align="center" gap={1}>
|
|
146
171
|
{reload?.button ? (
|
|
@@ -173,7 +198,23 @@ function Iframe(props: IframeProps) {
|
|
|
173
198
|
</Flex>
|
|
174
199
|
</Card>
|
|
175
200
|
<Card tone="transparent" padding={iframeSize === 'mobile' ? 2 : 0} style={{height: `100%`}}>
|
|
176
|
-
<Flex align="center" justify="center" style={{height: `100
|
|
201
|
+
<Flex align="center" justify="center" style={{height: `100%`, position: `relative`}}>
|
|
202
|
+
{loader && loading && (
|
|
203
|
+
<Flex justify="center" align="center" style={{inset: `0`, position: `absolute`}}>
|
|
204
|
+
<Flex
|
|
205
|
+
style={{...sizes[iframeSize], backgroundColor: `rgba(0,0,0,0.2)`}}
|
|
206
|
+
justify="center"
|
|
207
|
+
align="center"
|
|
208
|
+
>
|
|
209
|
+
<Card padding={4} radius={2} shadow={1}>
|
|
210
|
+
<Flex align="center" direction="column" gap={3} height="fill" justify="center">
|
|
211
|
+
<Spinner />
|
|
212
|
+
{loader && typeof loader === 'string' && <Text size={1}>{loader}</Text>}
|
|
213
|
+
</Flex>
|
|
214
|
+
</Card>
|
|
215
|
+
</Flex>
|
|
216
|
+
</Flex>
|
|
217
|
+
)}
|
|
177
218
|
<iframe
|
|
178
219
|
ref={iframe}
|
|
179
220
|
title="preview"
|
|
@@ -181,6 +222,7 @@ function Iframe(props: IframeProps) {
|
|
|
181
222
|
frameBorder="0"
|
|
182
223
|
src={displayUrl}
|
|
183
224
|
{...attributes}
|
|
225
|
+
onLoad={handleIframeLoad}
|
|
184
226
|
/>
|
|
185
227
|
</Flex>
|
|
186
228
|
</Card>
|