sanity-plugin-iframe-pane 2.3.1 → 2.3.2-canary.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.
Files changed (40) hide show
  1. package/README.md +15 -5
  2. package/lib/_chunks/is-valid-secret-57fea7e5.js +35 -0
  3. package/lib/_chunks/is-valid-secret-57fea7e5.js.map +1 -0
  4. package/lib/_chunks/is-valid-secret-7b704c76.cjs +41 -0
  5. package/lib/_chunks/is-valid-secret-7b704c76.cjs.map +1 -0
  6. package/lib/_chunks/types-107599a1.js +34 -0
  7. package/lib/_chunks/types-107599a1.js.map +1 -0
  8. package/lib/_chunks/types-4a29b6ac.cjs +38 -0
  9. package/lib/_chunks/types-4a29b6ac.cjs.map +1 -0
  10. package/lib/index.cjs +462 -154
  11. package/lib/index.cjs.js +3 -1
  12. package/lib/index.cjs.map +1 -1
  13. package/lib/index.d.ts +38 -11
  14. package/lib/index.js +462 -158
  15. package/lib/index.js.map +1 -1
  16. package/lib/is-valid-secret.cjs +8 -0
  17. package/lib/is-valid-secret.cjs.js +4 -0
  18. package/lib/is-valid-secret.cjs.map +1 -0
  19. package/lib/is-valid-secret.d.ts +41 -0
  20. package/lib/is-valid-secret.js +2 -0
  21. package/lib/is-valid-secret.js.map +1 -0
  22. package/lib/preview-url.cjs +77 -0
  23. package/lib/preview-url.cjs.js +4 -0
  24. package/lib/preview-url.cjs.map +1 -0
  25. package/lib/preview-url.d.ts +17 -0
  26. package/lib/preview-url.js +72 -0
  27. package/lib/preview-url.js.map +1 -0
  28. package/package.json +34 -10
  29. package/src/DisplayUrl.tsx +21 -0
  30. package/src/GetUrlSecret.tsx +80 -0
  31. package/src/Iframe.tsx +272 -158
  32. package/src/Toolbar.tsx +153 -0
  33. package/src/defineUrlResolver.tsx +31 -0
  34. package/src/index.ts +3 -5
  35. package/src/is-valid-secret.ts +2 -0
  36. package/src/isValidSecret.tsx +67 -0
  37. package/src/preview-url.ts +2 -0
  38. package/src/previewUrl.ts +62 -0
  39. package/src/types.ts +17 -0
  40. package/src/utils.ts +45 -0
package/lib/index.cjs CHANGED
@@ -1,93 +1,118 @@
1
1
  'use strict';
2
2
 
3
+ Object.defineProperty(exports, '__esModule', {
4
+ value: true
5
+ });
3
6
  var jsxRuntime = require('react/jsx-runtime');
4
7
  var icons = require('@sanity/icons');
5
8
  var ui = require('@sanity/ui');
9
+ var framerMotion = require('framer-motion');
6
10
  var react = require('react');
11
+ var sanity = require('sanity');
12
+ var isValidSecret = require('./_chunks/is-valid-secret-7b704c76.cjs');
13
+ var types = require('./_chunks/types-4a29b6ac.cjs');
7
14
  var usehooksTs = require('usehooks-ts');
15
+ function GetUrlSecret(props) {
16
+ const {
17
+ urlSecretId,
18
+ setUrlSecret,
19
+ urlSecret,
20
+ setError
21
+ } = props;
22
+ const client = sanity.useClient({
23
+ apiVersion: isValidSecret.apiVersion
24
+ });
25
+ const [secretExpiresAt, setSecretExpiresAt] = react.useState(null);
26
+ if (!urlSecretId.includes(".")) {
27
+ throw new TypeError("`urlSecretId` must have a dot prefix, `".concat(urlSecretId, "` is not secure, add a prefix, for example `preview.").concat(urlSecretId, "` "));
28
+ }
29
+ react.useEffect(() => {
30
+ if (urlSecret) return;
31
+ async function getSecret(signal) {
32
+ const data = await client.fetch(isValidSecret.fetchSecretQuery, {
33
+ id: urlSecretId
34
+ }, {
35
+ signal,
36
+ tag: isValidSecret.tag
37
+ });
38
+ if (signal.aborted) return;
39
+ if (!(data == null ? void 0 : data.secret) || !(data == null ? void 0 : data._updatedAt)) {
40
+ try {
41
+ const newUpdatedAt = /* @__PURE__ */new Date();
42
+ const newSecret = await types.patchUrlSecret(client, urlSecretId, signal);
43
+ if (signal.aborted) return;
44
+ setUrlSecret(newSecret);
45
+ setSecretExpiresAt(types.getExpiresAt(newUpdatedAt));
46
+ } catch (err) {
47
+ console.error("Failed to create a new preview secret. Ensure the `client` has a `token` specified that has `write` permissions.", err);
48
+ }
49
+ return;
50
+ }
51
+ if ((data == null ? void 0 : data.secret) !== urlSecret) {
52
+ setUrlSecret(data == null ? void 0 : data.secret);
53
+ setSecretExpiresAt(types.getExpiresAt(new Date(data == null ? void 0 : data._updatedAt)));
54
+ }
55
+ }
56
+ const abort = new AbortController();
57
+ getSecret(abort.signal).catch(error => error.name !== "AbortError" && setError(error));
58
+ return () => abort.abort();
59
+ }, [client, setError, setUrlSecret, urlSecret, urlSecretId]);
60
+ react.useEffect(() => {
61
+ if (!secretExpiresAt) return;
62
+ const timeout = setTimeout(() => {
63
+ setUrlSecret(null);
64
+ setSecretExpiresAt(null);
65
+ }, Math.max(0, secretExpiresAt.getTime() - /* @__PURE__ */new Date().getTime()));
66
+ return () => clearTimeout(timeout);
67
+ }, [secretExpiresAt, setUrlSecret]);
68
+ return null;
69
+ }
70
+ function DisplayUrl(_ref) {
71
+ let {
72
+ displayUrl
73
+ } = _ref;
74
+ const truncatedUrl = react.useMemo(() => {
75
+ const url = new URL(displayUrl);
76
+ if (url.searchParams.has("secret")) {
77
+ url.searchParams.delete("secret");
78
+ url.searchParams.append("secret", "***");
79
+ }
80
+ return "".concat(url.origin === location.origin ? "" : url.origin).concat(url.pathname).concat(url.search);
81
+ }, [displayUrl]);
82
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
83
+ size: 0,
84
+ textOverflow: "ellipsis",
85
+ title: displayUrl,
86
+ children: truncatedUrl
87
+ });
88
+ }
8
89
  const sizes = {
9
90
  desktop: {
10
91
  width: "100%",
11
- height: "100%",
12
- maxHeight: "100%"
92
+ height: "100%"
13
93
  },
14
94
  mobile: {
15
95
  width: 414,
16
- height: "100%",
17
- maxHeight: 736
96
+ height: 746
18
97
  }
19
98
  };
20
99
  const DEFAULT_SIZE = "desktop";
21
- function Iframe(props) {
100
+ function Toolbar(props) {
22
101
  const {
23
- document: sanityDocument,
24
- options
102
+ displayUrl,
103
+ iframeSize,
104
+ setIframeSize,
105
+ reloading,
106
+ showDisplayUrl,
107
+ reloadButton,
108
+ handleReload
25
109
  } = props;
26
- const {
27
- url,
28
- defaultSize = DEFAULT_SIZE,
29
- reload,
30
- loader,
31
- attributes = {},
32
- showDisplayUrl = true
33
- } = options;
34
- const [displayUrl, setDisplayUrl] = react.useState(url && typeof url === "string" ? url : "");
35
- const [iframeSize, setIframeSize] = react.useState((sizes == null ? void 0 : sizes[defaultSize]) ? defaultSize : DEFAULT_SIZE);
36
- const [loading, setLoading] = react.useState(false);
37
110
  const input = react.useRef(null);
38
- const iframe = react.useRef(null);
39
111
  const {
40
- displayed
41
- } = sanityDocument;
112
+ push: pushToast
113
+ } = ui.useToast();
42
114
  const [, copy] = usehooksTs.useCopyToClipboard();
43
- function handleCopy() {
44
- var _a;
45
- if (!((_a = input == null ? void 0 : input.current) == null ? void 0 : _a.value)) return;
46
- copy(input.current.value);
47
- }
48
- function handleReload() {
49
- if (!(iframe == null ? void 0 : iframe.current)) {
50
- return;
51
- }
52
- iframe.current.src = iframe.current.src;
53
- setLoading(true);
54
- }
55
- function handleIframeLoad() {
56
- setLoading(false);
57
- if (attributes.onLoad && typeof attributes.onLoad === "function") {
58
- attributes.onLoad();
59
- }
60
- }
61
- react.useEffect(() => {
62
- if ((reload == null ? void 0 : reload.revision) || (reload == null ? void 0 : reload.revision) == 0) {
63
- setTimeout(() => {
64
- handleReload();
65
- }, Number(reload == null ? void 0 : reload.revision));
66
- }
67
- }, [displayed._rev, reload == null ? void 0 : reload.revision]);
68
- react.useEffect(() => {
69
- const getUrl = async () => {
70
- setLoading(true);
71
- const resolveUrl = typeof url === "function" ? await url(displayed) : "";
72
- if (resolveUrl !== displayUrl && resolveUrl && typeof resolveUrl === "string") {
73
- setDisplayUrl(resolveUrl);
74
- }
75
- };
76
- if (typeof url === "function") {
77
- getUrl();
78
- }
79
- }, [displayed._rev]);
80
- if (!displayUrl || typeof displayUrl !== "string") {
81
- return /* @__PURE__ */jsxRuntime.jsx(ui.ThemeProvider, {
82
- children: /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
83
- padding: 5,
84
- align: "center",
85
- justify: "center",
86
- children: /* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {})
87
- })
88
- });
89
- }
90
- return /* @__PURE__ */jsxRuntime.jsxs(ui.ThemeProvider, {
115
+ return /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
91
116
  children: [/* @__PURE__ */jsxRuntime.jsx("textarea", {
92
117
  style: {
93
118
  position: "absolute",
@@ -98,119 +123,402 @@ function Iframe(props) {
98
123
  value: displayUrl,
99
124
  readOnly: true,
100
125
  tabIndex: -1
101
- }), /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
102
- direction: "column",
103
- style: {
104
- height: "100%"
105
- },
106
- children: [/* @__PURE__ */jsxRuntime.jsx(ui.Card, {
107
- padding: 2,
108
- borderBottom: true,
109
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
126
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
127
+ padding: 2,
128
+ borderBottom: true,
129
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
130
+ align: "center",
131
+ gap: 2,
132
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
110
133
  align: "center",
111
- gap: 2,
112
- children: [/* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
113
- align: "center",
114
- gap: 1,
134
+ gap: 1,
135
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Tooltip, {
136
+ content: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
137
+ size: 1,
138
+ style: {
139
+ whiteSpace: "nowrap"
140
+ },
141
+ children: iframeSize === "mobile" ? "Exit mobile preview" : "Preview mobile viewport"
142
+ }),
143
+ padding: 2,
115
144
  children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
145
+ disabled: !displayUrl,
116
146
  fontSize: [1],
117
147
  padding: 2,
118
- tone: "primary",
119
148
  mode: iframeSize === "mobile" ? "default" : "ghost",
120
149
  icon: icons.MobileDeviceIcon,
121
150
  onClick: () => setIframeSize(iframeSize === "mobile" ? "desktop" : "mobile")
122
151
  })
123
- }), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
124
- flex: 1,
125
- children: showDisplayUrl && /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
126
- size: 0,
127
- textOverflow: "ellipsis",
128
- children: displayUrl
129
- })
130
- }), /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
131
- align: "center",
132
- gap: 1,
133
- children: [(reload == null ? void 0 : reload.button) ? /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
152
+ })
153
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
154
+ flex: 1,
155
+ children: showDisplayUrl && displayUrl && /* @__PURE__ */jsxRuntime.jsx(DisplayUrl, {
156
+ displayUrl
157
+ })
158
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
159
+ align: "center",
160
+ gap: 1,
161
+ children: [reloadButton ? /* @__PURE__ */jsxRuntime.jsx(ui.Tooltip, {
162
+ content: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
163
+ size: 1,
164
+ style: {
165
+ whiteSpace: "nowrap"
166
+ },
167
+ children: reloading ? "Reloading\u2026" : "Reload"
168
+ }),
169
+ padding: 2,
170
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
171
+ disabled: !displayUrl,
172
+ mode: "bleed",
134
173
  fontSize: [1],
135
174
  padding: 2,
136
- icon: icons.UndoIcon,
137
- title: "Reload",
175
+ icon: /* @__PURE__ */jsxRuntime.jsx(icons.UndoIcon, {
176
+ style: {
177
+ transform: "rotate(90deg) scaleY(-1)"
178
+ }
179
+ }),
180
+ loading: reloading,
138
181
  "aria-label": "Reload",
139
182
  onClick: () => handleReload()
140
- }) : null, /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
183
+ })
184
+ }) : null, /* @__PURE__ */jsxRuntime.jsx(ui.Tooltip, {
185
+ content: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
186
+ size: 1,
187
+ style: {
188
+ whiteSpace: "nowrap"
189
+ },
190
+ children: "Copy URL"
191
+ }),
192
+ padding: 2,
193
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
194
+ mode: "bleed",
195
+ disabled: !displayUrl,
141
196
  fontSize: [1],
142
- icon: icons.CopyIcon,
197
+ icon: icons.ClipboardIcon,
143
198
  padding: [2],
144
- title: "Copy",
145
- "aria-label": "Copy",
146
- onClick: () => handleCopy()
147
- }), /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
199
+ "aria-label": "Copy URL",
200
+ onClick: () => {
201
+ var _a;
202
+ if (!((_a = input == null ? void 0 : input.current) == null ? void 0 : _a.value)) return;
203
+ copy(input.current.value);
204
+ pushToast({
205
+ closable: true,
206
+ status: "success",
207
+ title: "The URL is copied to the clipboard"
208
+ });
209
+ }
210
+ })
211
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Tooltip, {
212
+ content: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
213
+ size: 1,
214
+ style: {
215
+ whiteSpace: "nowrap"
216
+ },
217
+ children: "Open URL in a new tab"
218
+ }),
219
+ padding: 2,
220
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
221
+ disabled: !displayUrl,
148
222
  fontSize: [1],
149
- icon: icons.LeaveIcon,
150
- padding: [2],
223
+ icon: icons.LaunchIcon,
224
+ mode: "ghost",
225
+ paddingY: [2],
151
226
  text: "Open",
152
- tone: "primary",
227
+ "aria-label": "Open URL in a new tab",
153
228
  onClick: () => window.open(displayUrl)
154
- })]
229
+ })
155
230
  })]
156
- })
157
- }), /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
231
+ })]
232
+ })
233
+ })]
234
+ });
235
+ }
236
+ const MotionFlex = framerMotion.motion(ui.Flex);
237
+ function Iframe(props) {
238
+ var _a;
239
+ const [error, setError] = react.useState(null);
240
+ if (error) {
241
+ throw error;
242
+ }
243
+ const {
244
+ document: sanityDocument,
245
+ options
246
+ } = props;
247
+ const {
248
+ url,
249
+ urlSecretId,
250
+ defaultSize = DEFAULT_SIZE,
251
+ reload,
252
+ loader = "Loading\u2026",
253
+ attributes = {},
254
+ showDisplayUrl = true
255
+ } = options;
256
+ const [iframeSize, setIframeSize] = react.useState(((_a = sizes) == null ? void 0 : _a[defaultSize]) ? defaultSize : DEFAULT_SIZE);
257
+ const [workaroundEmptyDocument, setWorkaroundEmptyDocument] = react.useState(true);
258
+ react.useEffect(() => {
259
+ const timeout = setTimeout(() => setWorkaroundEmptyDocument(false), 1e3);
260
+ return () => clearTimeout(timeout);
261
+ }, []);
262
+ const prefersReducedMotion = ui.usePrefersReducedMotion();
263
+ const [urlState, setUrlState] = react.useState(() => typeof url === "function" ? "" : url);
264
+ const [loading, setLoading] = react.useState(true);
265
+ const [reloading, setReloading] = react.useState(false);
266
+ const iframe = react.useRef(null);
267
+ const {
268
+ displayed
269
+ } = sanityDocument;
270
+ const handleReload = react.useCallback(() => {
271
+ if (!(iframe == null ? void 0 : iframe.current)) {
272
+ return;
273
+ }
274
+ iframe.current.src = iframe.current.src;
275
+ setReloading(true);
276
+ }, []);
277
+ const deferredRevision = react.useDeferredValue(displayed._rev);
278
+ const displayUrl = typeof urlState === "string" ? urlState : "";
279
+ return /* @__PURE__ */jsxRuntime.jsx(framerMotion.MotionConfig, {
280
+ transition: prefersReducedMotion ? {
281
+ duration: 0
282
+ } : void 0,
283
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
284
+ direction: "column",
285
+ style: {
286
+ height: "100%"
287
+ },
288
+ children: [/* @__PURE__ */jsxRuntime.jsx(Toolbar, {
289
+ displayUrl,
290
+ iframeSize,
291
+ reloading,
292
+ setIframeSize,
293
+ showDisplayUrl,
294
+ reloadButton: !!(reload == null ? void 0 : reload.button),
295
+ handleReload
296
+ }), urlState === types.MissingSlug && !workaroundEmptyDocument ? /* @__PURE__ */jsxRuntime.jsx(MissingSlugScreen, {}) : /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
158
297
  tone: "transparent",
159
- padding: iframeSize === "mobile" ? 2 : 0,
160
298
  style: {
161
299
  height: "100%"
162
300
  },
301
+ children: /* @__PURE__ */jsxRuntime.jsx(Frame, {
302
+ ref: iframe,
303
+ loader,
304
+ loading,
305
+ reloading,
306
+ iframeSize,
307
+ setReloading,
308
+ setLoading,
309
+ displayUrl,
310
+ attributes
311
+ })
312
+ }), typeof url === "function" && /* @__PURE__ */jsxRuntime.jsx(AsyncUrl, {
313
+ url,
314
+ displayed,
315
+ urlSecretId,
316
+ setDisplayUrl: setUrlState,
317
+ setError
318
+ }, deferredRevision), displayUrl && ((reload == null ? void 0 : reload.revision) || (reload == null ? void 0 : reload.revision) === 0) && /* @__PURE__ */jsxRuntime.jsx(ReloadOnRevision, {
319
+ revision: reload.revision,
320
+ _rev: deferredRevision,
321
+ handleReload
322
+ })]
323
+ })
324
+ });
325
+ }
326
+ const Frame = react.forwardRef(function Frame2(props, iframe) {
327
+ const {
328
+ loader,
329
+ loading,
330
+ setLoading,
331
+ iframeSize,
332
+ attributes,
333
+ reloading,
334
+ displayUrl,
335
+ setReloading
336
+ } = props;
337
+ function handleIframeLoad() {
338
+ setLoading(false);
339
+ setReloading(false);
340
+ if (attributes.onLoad && typeof attributes.onLoad === "function") {
341
+ attributes.onLoad();
342
+ }
343
+ }
344
+ return /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
345
+ align: "center",
346
+ justify: "center",
347
+ style: {
348
+ height: "100%",
349
+ position: "relative"
350
+ },
351
+ children: [/* @__PURE__ */jsxRuntime.jsx(framerMotion.AnimatePresence, {
352
+ children: loader && loading && /* @__PURE__ */jsxRuntime.jsx(MotionFlex, {
353
+ initial: "initial",
354
+ animate: "animate",
355
+ exit: "exit",
356
+ variants: spinnerVariants,
357
+ justify: "center",
358
+ align: "center",
359
+ style: {
360
+ inset: "0",
361
+ position: "absolute"
362
+ },
163
363
  children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
164
- align: "center",
165
- justify: "center",
166
364
  style: {
167
- height: "100%",
168
- position: "relative"
365
+ ...sizes[iframeSize]
169
366
  },
170
- children: [loader && loading && /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
171
- justify: "center",
172
- align: "center",
173
- style: {
174
- inset: "0",
175
- position: "absolute"
176
- },
177
- children: /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
178
- style: {
179
- ...sizes[iframeSize],
180
- backgroundColor: "rgba(0,0,0,0.2)"
181
- },
182
- justify: "center",
183
- align: "center",
184
- children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
185
- padding: 4,
186
- radius: 2,
187
- shadow: 1,
188
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
189
- align: "center",
190
- direction: "column",
191
- gap: 3,
192
- height: "fill",
193
- justify: "center",
194
- children: [/* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {}), loader && typeof loader === "string" && /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
195
- size: 1,
196
- children: loader
197
- })]
198
- })
199
- })
200
- })
201
- }), /* @__PURE__ */jsxRuntime.jsx("iframe", {
202
- ref: iframe,
203
- title: "preview",
204
- style: sizes[iframeSize],
205
- frameBorder: "0",
206
- src: displayUrl,
207
- ...attributes,
208
- onLoad: handleIframeLoad
367
+ justify: "center",
368
+ align: "center",
369
+ direction: "column",
370
+ gap: 4,
371
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {
372
+ muted: true
373
+ }), loader && typeof loader === "string" && /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
374
+ muted: true,
375
+ size: 1,
376
+ children: loader
209
377
  })]
210
378
  })
211
- })]
379
+ })
380
+ }), /* @__PURE__ */jsxRuntime.jsx(framerMotion.motion.iframe, {
381
+ ref: iframe,
382
+ title: "preview",
383
+ frameBorder: "0",
384
+ style: {
385
+ maxHeight: "100%"
386
+ },
387
+ src: displayUrl,
388
+ initial: ["background", iframeSize],
389
+ variants: iframeVariants,
390
+ animate: [loader && loading ? "background" : "active", reloading ? "reloading" : "idle", iframeSize],
391
+ ...attributes,
392
+ onLoad: handleIframeLoad
212
393
  })]
213
394
  });
395
+ });
396
+ const spinnerVariants = {
397
+ initial: {
398
+ opacity: 1
399
+ },
400
+ animate: {
401
+ opacity: [0, 0, 1]
402
+ },
403
+ exit: {
404
+ opacity: [1, 0, 0]
405
+ }
406
+ };
407
+ const iframeVariants = {
408
+ ...sizes,
409
+ desktop: {
410
+ ...sizes.desktop,
411
+ boxShadow: "0 0 0 0px var(--card-shadow-outline-color)"
412
+ },
413
+ mobile: {
414
+ ...sizes.mobile,
415
+ boxShadow: "0 0 0 1px var(--card-shadow-outline-color)"
416
+ },
417
+ background: {
418
+ opacity: 0,
419
+ scale: 1
420
+ },
421
+ idle: {
422
+ scale: 1
423
+ },
424
+ reloading: {
425
+ scale: [1, 1, 1, 0.98]
426
+ },
427
+ active: {
428
+ opacity: [0, 0, 1],
429
+ scale: 1
430
+ }
431
+ };
432
+ function ReloadOnRevision(props) {
433
+ const {
434
+ revision,
435
+ handleReload,
436
+ _rev
437
+ } = props;
438
+ const [initialRev] = react.useState(_rev);
439
+ react.useEffect(() => {
440
+ if (_rev !== initialRev) {
441
+ const timeout = setTimeout(handleReload, Number(revision === true ? 300 : revision));
442
+ return () => clearTimeout(timeout);
443
+ }
444
+ }, [_rev, revision, handleReload, initialRev]);
445
+ return null;
446
+ }
447
+ function AsyncUrl(props) {
448
+ const {
449
+ urlSecretId,
450
+ setDisplayUrl,
451
+ setError
452
+ } = props;
453
+ const [displayed] = react.useState(props.displayed);
454
+ const [url] = react.useState(() => props.url);
455
+ const [urlSecret, setUrlSecret] = react.useState(null);
456
+ react.useEffect(() => {
457
+ if (urlSecretId && !urlSecret) return;
458
+ const getUrl = async signal => {
459
+ const resolveUrl = await url(displayed, urlSecret, abort.signal);
460
+ if (!signal.aborted && resolveUrl) {
461
+ setDisplayUrl(resolveUrl);
462
+ }
463
+ };
464
+ const abort = new AbortController();
465
+ getUrl(abort.signal).catch(error => error.name !== "AbortError" && setError(error));
466
+ return () => abort.abort();
467
+ }, [displayed, setDisplayUrl, setError, url, urlSecret, urlSecretId]);
468
+ if (urlSecretId) {
469
+ return /* @__PURE__ */jsxRuntime.jsx(GetUrlSecret, {
470
+ urlSecretId,
471
+ urlSecret,
472
+ setUrlSecret,
473
+ setError
474
+ });
475
+ }
476
+ return null;
477
+ }
478
+ function MissingSlugScreen() {
479
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
480
+ height: "fill",
481
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
482
+ align: "center",
483
+ height: "fill",
484
+ justify: "center",
485
+ padding: 4,
486
+ sizing: "border",
487
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Container, {
488
+ width: 0,
489
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
490
+ padding: 4,
491
+ radius: 2,
492
+ shadow: 1,
493
+ tone: "caution",
494
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
495
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
496
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
497
+ size: 1,
498
+ children: /* @__PURE__ */jsxRuntime.jsx(icons.WarningOutlineIcon, {})
499
+ })
500
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
501
+ flex: 1,
502
+ marginLeft: 3,
503
+ space: 3,
504
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Text, {
505
+ as: "h1",
506
+ size: 1,
507
+ weight: "bold",
508
+ children: "Missing slug"
509
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
510
+ as: "p",
511
+ muted: true,
512
+ size: 1,
513
+ children: "Add a slug to see the preview."
514
+ })]
515
+ })]
516
+ })
517
+ })
518
+ })
519
+ })
520
+ });
214
521
  }
215
- module.exports = Iframe;
522
+ exports.Iframe = Iframe;
523
+ exports.default = Iframe;
216
524
  //# sourceMappingURL=index.cjs.map
package/lib/index.cjs.js CHANGED
@@ -1,3 +1,5 @@
1
1
  import cjs from './index.cjs';
2
2
 
3
- export default cjs;
3
+ export const Iframe = cjs.Iframe;
4
+
5
+ export default cjs.default;