sanity-plugin-mux-input 2.1.1 → 2.2.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.
Files changed (66) hide show
  1. package/lib/index.cjs +4037 -4
  2. package/lib/index.cjs.map +1 -1
  3. package/lib/index.d.ts +14 -1
  4. package/lib/index.js +4026 -2
  5. package/lib/index.js.map +1 -1
  6. package/package.json +27 -28
  7. package/src/actions/assets.ts +30 -2
  8. package/src/components/ConfigureApi.tsx +9 -1
  9. package/src/components/FormField.tsx +8 -10
  10. package/src/components/IconInfo.tsx +23 -0
  11. package/src/components/Input.styled.tsx +0 -8
  12. package/src/components/Input.tsx +4 -3
  13. package/src/components/InputBrowser.tsx +1 -8
  14. package/src/components/Player.styled.tsx +5 -144
  15. package/src/components/Player.tsx +23 -109
  16. package/src/components/PlayerActionsMenu.tsx +0 -4
  17. package/src/components/SelectAsset.tsx +18 -58
  18. package/src/components/SelectSortOptions.tsx +45 -0
  19. package/src/components/SpinnerBox.tsx +17 -0
  20. package/src/components/StudioTool.tsx +20 -0
  21. package/src/components/VideoDetails/DeleteDialog.tsx +156 -0
  22. package/src/components/VideoDetails/VideoDetails.tsx +298 -0
  23. package/src/components/VideoDetails/VideoReferences.tsx +70 -0
  24. package/src/components/VideoDetails/useVideoDetails.ts +85 -0
  25. package/src/components/VideoInBrowser.tsx +183 -0
  26. package/src/components/VideoMetadata.tsx +43 -0
  27. package/src/components/VideoPlayer.tsx +69 -0
  28. package/src/components/VideoThumbnail.tsx +106 -0
  29. package/src/components/VideosBrowser.tsx +83 -0
  30. package/src/components/__legacy__Uploader.tsx +2 -9
  31. package/src/components/documentPreview/DocumentPreview.tsx +107 -0
  32. package/src/components/documentPreview/DraftStatus.tsx +34 -0
  33. package/src/components/documentPreview/MissingSchemaType.tsx +33 -0
  34. package/src/components/documentPreview/PaneItemPreview.tsx +71 -0
  35. package/src/components/documentPreview/PublishedStatus.tsx +35 -0
  36. package/src/components/documentPreview/TimeAgo.tsx +13 -0
  37. package/src/components/documentPreview/paneItemTypes.ts +7 -0
  38. package/src/components/icons/Resolution.tsx +12 -0
  39. package/src/components/icons/StopWatch.tsx +20 -0
  40. package/src/components/icons/ToolIcon.tsx +21 -0
  41. package/src/hooks/useAssets.ts +61 -0
  42. package/src/hooks/useCancelUpload.ts +2 -2
  43. package/src/hooks/useClient.ts +3 -1
  44. package/src/hooks/useDocReferences.ts +21 -0
  45. package/src/hooks/useInView.ts +45 -0
  46. package/src/index.ts +2 -0
  47. package/src/plugin.tsx +1 -1
  48. package/src/util/constants.ts +7 -0
  49. package/src/util/createSearchFilter.ts +78 -0
  50. package/src/util/formatSeconds.ts +22 -0
  51. package/src/util/getAnimatedPosterSrc.ts +1 -1
  52. package/src/util/getPlaybackId.ts +1 -1
  53. package/src/util/getPlaybackPolicy.ts +1 -1
  54. package/src/util/getVideoMetadata.ts +18 -0
  55. package/src/util/types.ts +16 -1
  56. package/lib/_chunks/Player-547f8e2a.cjs +0 -474
  57. package/lib/_chunks/Player-547f8e2a.cjs.map +0 -1
  58. package/lib/_chunks/Player-bfdb96f6.js +0 -465
  59. package/lib/_chunks/Player-bfdb96f6.js.map +0 -1
  60. package/lib/_chunks/index-39e38243.cjs +0 -3251
  61. package/lib/_chunks/index-39e38243.cjs.map +0 -1
  62. package/lib/_chunks/index-71899191.js +0 -3229
  63. package/lib/_chunks/index-71899191.js.map +0 -1
  64. package/src/components/EditThumbnailDialog.tsx +0 -74
  65. package/src/components/VideoSource.styled.tsx +0 -235
  66. package/src/components/VideoSource.tsx +0 -318
package/lib/index.cjs CHANGED
@@ -3,8 +3,4041 @@
3
3
  Object.defineProperty(exports, '__esModule', {
4
4
  value: true
5
5
  });
6
- require('sanity');
7
- var index = require('./_chunks/index-39e38243.cjs');
8
- exports.defaultConfig = index.defaultConfig;
9
- exports.muxInput = index.muxInput;
6
+ var sanity = require('sanity');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+ var icons = require('@sanity/icons');
9
+ var ui = require('@sanity/ui');
10
+ var React = require('react');
11
+ var lodash = require('lodash');
12
+ var MuxPlayer = require('@mux/mux-player-react');
13
+ var suspendReact = require('suspend-react');
14
+ var styled = require('styled-components');
15
+ var desk = require('sanity/desk');
16
+ var router = require('sanity/router');
17
+ var reactRx = require('react-rx');
18
+ var useSWR = require('swr');
19
+ var rxjs = require('rxjs');
20
+ var operators = require('rxjs/operators');
21
+ var uuid = require('@sanity/uuid');
22
+ var upchunk = require('@mux/upchunk');
23
+ var reactIs = require('react-is');
24
+ var scrollIntoView = require('scroll-into-view-if-needed');
25
+ var useErrorBoundary = require('use-error-boundary');
26
+ function _interopDefaultCompat(e) {
27
+ return e && typeof e === 'object' && 'default' in e ? e : {
28
+ default: e
29
+ };
30
+ }
31
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
32
+ var MuxPlayer__default = /*#__PURE__*/_interopDefaultCompat(MuxPlayer);
33
+ var styled__default = /*#__PURE__*/_interopDefaultCompat(styled);
34
+ var useSWR__default = /*#__PURE__*/_interopDefaultCompat(useSWR);
35
+ var scrollIntoView__default = /*#__PURE__*/_interopDefaultCompat(scrollIntoView);
36
+ const ToolIcon = () => /* @__PURE__ */jsxRuntime.jsx("svg", {
37
+ stroke: "currentColor",
38
+ fill: "currentColor",
39
+ strokeWidth: "0",
40
+ viewBox: "0 0 24 24",
41
+ height: "1em",
42
+ width: "1em",
43
+ xmlns: "http://www.w3.org/2000/svg",
44
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
45
+ d: "M21 3H3c-1.11 0-2 .89-2 2v12c0 1.1.89 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.11-.9-2-2-2zm0 14H3V5h18v12zm-5-6l-7 4V7z"
46
+ })
47
+ });
48
+ const SANITY_API_VERSION = "2022-09-14";
49
+ function useClient() {
50
+ return sanity.useClient({
51
+ apiVersion: SANITY_API_VERSION
52
+ });
53
+ }
54
+ const SPECIAL_CHARS = /([^!@#$%^&*(),\\/?";:{}|[\]+<>\s-])+/g;
55
+ const STRIP_EDGE_CHARS = /(^[.]+)|([.]+$)/;
56
+ function tokenize(string) {
57
+ return (string.match(SPECIAL_CHARS) || []).map(token => token.replace(STRIP_EDGE_CHARS, ""));
58
+ }
59
+ function toGroqParams(terms) {
60
+ const params = {};
61
+ return terms.reduce((acc, term, i) => {
62
+ acc["t".concat(i)] = "*".concat(term, "*");
63
+ return acc;
64
+ }, params);
65
+ }
66
+ function extractTermsFromQuery(query) {
67
+ const quotedQueries = [];
68
+ const unquotedQuery = query.replace(/("[^"]*")/g, match => {
69
+ if (lodash.words(match).length > 1) {
70
+ quotedQueries.push(match);
71
+ return "";
72
+ }
73
+ return match;
74
+ });
75
+ const quotedTerms = quotedQueries.map(str => lodash.trim(lodash.toLower(str)));
76
+ const remainingTerms = lodash.uniq(lodash.compact(tokenize(lodash.toLower(unquotedQuery))));
77
+ return [...quotedTerms, ...remainingTerms];
78
+ }
79
+ const SEARCH_PATHS = ["filename", "assetId", "_id"];
80
+ function createConstraints(terms) {
81
+ const constraints = terms.map((_term, i) => SEARCH_PATHS.map(joinedPath => "".concat(joinedPath, " match $t").concat(i))).filter(constraint => constraint.length > 0);
82
+ return constraints.map(constraint => "(".concat(constraint.join(" || "), ")"));
83
+ }
84
+ function createSearchFilter(query) {
85
+ const terms = extractTermsFromQuery(query);
86
+ return {
87
+ filter: createConstraints(terms),
88
+ params: {
89
+ ...toGroqParams(terms)
90
+ }
91
+ };
92
+ }
93
+ const ASSET_SORT_OPTIONS = {
94
+ createdDesc: {
95
+ groq: "_createdAt desc",
96
+ label: "Newest first"
97
+ },
98
+ createdAsc: {
99
+ groq: "_createdAt asc",
100
+ label: "First created (oldest)"
101
+ },
102
+ filenameAsc: {
103
+ groq: "filename asc",
104
+ label: "By filename (A-Z)"
105
+ },
106
+ filenameDesc: {
107
+ groq: "filename desc",
108
+ label: "By filename (Z-A)"
109
+ }
110
+ };
111
+ const useAssetDocuments = sanity.createHookFromObservableFactory(_ref => {
112
+ let {
113
+ documentStore,
114
+ sort,
115
+ searchQuery
116
+ } = _ref;
117
+ const search = createSearchFilter(searchQuery);
118
+ const filter = ['_type == "mux.videoAsset"', ...search.filter].filter(Boolean).join(" && ");
119
+ const query = ASSET_SORT_OPTIONS[sort].groq;
120
+ return documentStore.listenQuery( /* groq */
121
+ "*[".concat(filter, "] | order(").concat(query, ")"), search.params, {
122
+ apiVersion: SANITY_API_VERSION
123
+ });
124
+ });
125
+ function useAssets() {
126
+ const documentStore = sanity.useDocumentStore();
127
+ const [sort, setSort] = React.useState("createdDesc");
128
+ const [searchQuery, setSearchQuery] = React.useState("");
129
+ const [assetDocuments = [], isLoading] = useAssetDocuments({
130
+ documentStore,
131
+ sort,
132
+ searchQuery
133
+ });
134
+ const assets = React.useMemo(() =>
135
+ // Avoid displaying both drafts & published assets by collating them together and giving preference to drafts
136
+ sanity.collate(assetDocuments).map(collated => ({
137
+ ...(collated.draft || collated.published || {}),
138
+ _id: collated.id
139
+ })), [assetDocuments]);
140
+ return {
141
+ assets,
142
+ isLoading,
143
+ sort,
144
+ searchQuery,
145
+ setSort,
146
+ setSearchQuery
147
+ };
148
+ }
149
+ const CONTEXT_MENU_POPOVER_PROPS = {
150
+ constrainSize: true,
151
+ placement: "bottom",
152
+ portal: true,
153
+ width: 0
154
+ };
155
+ function SelectSortOptions(props) {
156
+ const id = React.useId();
157
+ return /* @__PURE__ */jsxRuntime.jsx(ui.MenuButton, {
158
+ button: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
159
+ text: "Sort",
160
+ icon: icons.SortIcon,
161
+ mode: "bleed",
162
+ padding: 3,
163
+ style: {
164
+ cursor: "pointer"
165
+ }
166
+ }),
167
+ id,
168
+ menu: /* @__PURE__ */jsxRuntime.jsx(ui.Menu, {
169
+ children: Object.entries(ASSET_SORT_OPTIONS).map(_ref2 => {
170
+ let [type, {
171
+ label
172
+ }] = _ref2;
173
+ return /* @__PURE__ */jsxRuntime.jsx(ui.MenuItem, {
174
+ "data-as": "button",
175
+ onClick: () => props.setSort(type),
176
+ padding: 3,
177
+ tone: "default",
178
+ text: label,
179
+ pressed: type === props.sort
180
+ }, type);
181
+ })
182
+ }),
183
+ popover: CONTEXT_MENU_POPOVER_PROPS
184
+ });
185
+ }
186
+ const SpinnerBox = () => /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
187
+ style: {
188
+ display: "flex",
189
+ alignItems: "center",
190
+ justifyContent: "center",
191
+ minHeight: "150px"
192
+ },
193
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {})
194
+ });
195
+ const name$1 = "mux-input";
196
+ const cacheNs = "sanity-plugin-mux-input";
197
+ const muxSecretsDocumentId = "secrets.mux";
198
+ const DIALOGS_Z_INDEX = 6e4;
199
+ const THUMBNAIL_ASPECT_RATIO = 16 / 9;
200
+ const MIN_ASPECT_RATIO = 1;
201
+ function FormField(props) {
202
+ const {
203
+ children,
204
+ title,
205
+ description,
206
+ inputId
207
+ } = props;
208
+ return /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
209
+ space: 1,
210
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
211
+ align: "flex-end",
212
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
213
+ flex: 1,
214
+ paddingY: 2,
215
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
216
+ space: 2,
217
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Text, {
218
+ as: "label",
219
+ htmlFor: inputId,
220
+ weight: "semibold",
221
+ size: 1,
222
+ children: title || /* @__PURE__ */jsxRuntime.jsx("em", {
223
+ children: "Untitled"
224
+ })
225
+ }), description && /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
226
+ muted: true,
227
+ size: 1,
228
+ children: description
229
+ })]
230
+ })
231
+ })
232
+ }), /* @__PURE__ */jsxRuntime.jsx("div", {
233
+ children
234
+ })]
235
+ });
236
+ }
237
+ var FormField$1 = React.memo(FormField);
238
+ const IconInfo = props => {
239
+ const Icon = props.icon;
240
+ return /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
241
+ gap: 2,
242
+ align: "center",
243
+ padding: 1,
244
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Text, {
245
+ size: (props.size || 1) + 1,
246
+ muted: true,
247
+ children: /* @__PURE__ */jsxRuntime.jsx(Icon, {})
248
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
249
+ size: props.size || 1,
250
+ muted: props.muted,
251
+ children: props.text
252
+ })]
253
+ });
254
+ };
255
+ function ResolutionIcon(props) {
256
+ return /* @__PURE__ */jsxRuntime.jsx("svg", {
257
+ xmlns: "http://www.w3.org/2000/svg",
258
+ width: "1em",
259
+ height: "1em",
260
+ viewBox: "0 0 24 24",
261
+ ...props,
262
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
263
+ fill: "currentColor",
264
+ d: "M20 9V6h-3V4h5v5h-2ZM2 9V4h5v2H4v3H2Zm15 11v-2h3v-3h2v5h-5ZM2 20v-5h2v3h3v2H2Zm4-4V8h12v8H6Zm2-2h8v-4H8v4Zm0 0v-4v4Z"
265
+ })
266
+ });
267
+ }
268
+ function StopWatchIcon(props) {
269
+ return /* @__PURE__ */jsxRuntime.jsxs("svg", {
270
+ xmlns: "http://www.w3.org/2000/svg",
271
+ width: "1em",
272
+ height: "1em",
273
+ viewBox: "0 0 512 512",
274
+ ...props,
275
+ children: [/* @__PURE__ */jsxRuntime.jsx("path", {
276
+ d: "M232 306.667h48V176h-48v130.667z",
277
+ fill: "currentColor"
278
+ }), /* @__PURE__ */jsxRuntime.jsx("path", {
279
+ d: "M407.67 170.271l30.786-30.786-33.942-33.941-30.785 30.786C341.217 111.057 300.369 96 256 96 149.961 96 64 181.961 64 288s85.961 192 192 192 192-85.961 192-192c0-44.369-15.057-85.217-40.33-117.729zm-45.604 223.795C333.734 422.398 296.066 438 256 438s-77.735-15.602-106.066-43.934C121.602 365.735 106 328.066 106 288s15.602-77.735 43.934-106.066C178.265 153.602 215.934 138 256 138s77.734 15.602 106.066 43.934C390.398 210.265 406 247.934 406 288s-15.602 77.735-43.934 106.066z",
280
+ fill: "currentColor"
281
+ }), /* @__PURE__ */jsxRuntime.jsx("path", {
282
+ d: "M192 32h128v48H192z",
283
+ fill: "currentColor"
284
+ })]
285
+ });
286
+ }
287
+ const _id = "secrets.mux";
288
+ function readSecrets(client) {
289
+ const {
290
+ projectId,
291
+ dataset
292
+ } = client.config();
293
+ return suspendReact.suspend(async () => {
294
+ const data = await client.fetch( /* groq */
295
+ "*[_id == $_id][0]{\n token,\n secretKey,\n enableSignedUrls,\n signingKeyId,\n signingKeyPrivate\n }", {
296
+ _id
297
+ });
298
+ return {
299
+ token: (data == null ? void 0 : data.token) || null,
300
+ secretKey: (data == null ? void 0 : data.secretKey) || null,
301
+ enableSignedUrls: Boolean(data == null ? void 0 : data.enableSignedUrls) || false,
302
+ signingKeyId: (data == null ? void 0 : data.signingKeyId) || null,
303
+ signingKeyPrivate: (data == null ? void 0 : data.signingKeyPrivate) || null
304
+ };
305
+ }, [cacheNs, _id, projectId, dataset]);
306
+ }
307
+ function generateJwt(client, playbackId, aud, payload) {
308
+ const {
309
+ signingKeyId,
310
+ signingKeyPrivate
311
+ } = readSecrets(client);
312
+ if (!signingKeyId) {
313
+ throw new TypeError("Missing signingKeyId");
314
+ }
315
+ if (!signingKeyPrivate) {
316
+ throw new TypeError("Missing signingKeyPrivate");
317
+ }
318
+ const {
319
+ default: sign
320
+ } = suspendReact.suspend(() => import('jsonwebtoken-esm/sign'), ["jsonwebtoken-esm/sign"]);
321
+ return sign(payload ? JSON.parse(JSON.stringify(payload, (_, v) => v != null ? v : void 0)) : {}, atob(signingKeyPrivate), {
322
+ algorithm: "RS256",
323
+ keyid: signingKeyId,
324
+ audience: aud,
325
+ subject: playbackId,
326
+ noTimestamp: true,
327
+ expiresIn: "12h"
328
+ });
329
+ }
330
+ function getPlaybackId(asset) {
331
+ if (!(asset == null ? void 0 : asset.playbackId)) {
332
+ console.error("Asset is missing a playbackId", {
333
+ asset
334
+ });
335
+ throw new TypeError("Missing playbackId");
336
+ }
337
+ return asset.playbackId;
338
+ }
339
+ function getPlaybackPolicy(asset) {
340
+ var _a, _b, _c, _d;
341
+ return (_d = (_c = (_b = (_a = asset.data) == null ? void 0 : _a.playback_ids) == null ? void 0 : _b[0]) == null ? void 0 : _c.policy) != null ? _d : "public";
342
+ }
343
+ function getVideoSrc(_ref3) {
344
+ let {
345
+ asset,
346
+ client
347
+ } = _ref3;
348
+ const playbackId = getPlaybackId(asset);
349
+ const searchParams = new URLSearchParams();
350
+ if (getPlaybackPolicy(asset) === "signed") {
351
+ const token = generateJwt(client, playbackId, "v");
352
+ searchParams.set("token", token);
353
+ }
354
+ return "https://stream.mux.com/".concat(playbackId, ".m3u8?").concat(searchParams);
355
+ }
356
+ var name = "sanity-plugin-mux-input";
357
+ var version = "2.2.0";
358
+ var description = "An input component that integrates Sanity Studio with Mux video encoding/hosting service.";
359
+ var keywords = ["sanity", "video", "mux", "input", "plugin", "sanity-plugin", "media"];
360
+ var homepage = "https://github.com/sanity-io/sanity-plugin-mux-input#readme";
361
+ var bugs = {
362
+ url: "https://github.com/sanity-io/sanity-plugin-mux-input/issues"
363
+ };
364
+ var repository = {
365
+ type: "git",
366
+ url: "git@github.com:sanity-io/sanity-plugin-mux-input.git"
367
+ };
368
+ var license = "MIT";
369
+ var author = "Sanity.io <hello@sanity.io>";
370
+ var sideEffects = false;
371
+ var type = "module";
372
+ var exports$1 = {
373
+ ".": {
374
+ types: "./lib/index.d.ts",
375
+ source: "./src/index.ts",
376
+ require: "./lib/index.cjs",
377
+ node: {
378
+ "import": "./lib/index.cjs.js",
379
+ require: "./lib/index.cjs"
380
+ },
381
+ "import": "./lib/index.js",
382
+ "default": "./lib/index.js"
383
+ },
384
+ "./package.json": "./package.json"
385
+ };
386
+ var main = "./lib/index.cjs";
387
+ var module$1 = "./lib/index.js";
388
+ var source = "./src/index.ts";
389
+ var types = "./lib/index.d.ts";
390
+ var files = ["src", "lib", "sanity.json", "v2-incompatible.js"];
391
+ var scripts = {
392
+ build: "run-s clean && plugin-kit verify-package --silent && pkg-utils build --strict && pkg-utils --strict",
393
+ clean: "rimraf lib",
394
+ dev: "next dev",
395
+ format: "prettier --write --cache --ignore-unknown .",
396
+ "link-watch": "plugin-kit link-watch",
397
+ lint: "eslint .",
398
+ prepare: "husky install || true",
399
+ prepublishOnly: "run-s build",
400
+ test: "npm run lint && npm run type-check && npm run build",
401
+ "type-check": "tsc --noEmit",
402
+ watch: "pkg-utils watch --strict"
403
+ };
404
+ var dependencies = {
405
+ "@mux/mux-player-react": "^1.11.4",
406
+ "@mux/upchunk": "^3",
407
+ "@sanity/icons": "^2",
408
+ "@sanity/incompatible-plugin": "^1",
409
+ "@sanity/ui": "^1",
410
+ "@sanity/uuid": "^3",
411
+ "jsonwebtoken-esm": "^1.0.5",
412
+ lodash: "^4",
413
+ "react-rx": "^2.1.3",
414
+ rxjs: "^7",
415
+ "scroll-into-view-if-needed": "^3",
416
+ "suspend-react": "^0.1.0",
417
+ swr: "^2.1.0",
418
+ "type-fest": "^3.6.1",
419
+ "use-error-boundary": "^2.0.6"
420
+ };
421
+ var devDependencies = {
422
+ "@commitlint/cli": "^17.6.7",
423
+ "@commitlint/config-conventional": "^17.6.7",
424
+ "@sanity/pkg-utils": "^2.3.10",
425
+ "@sanity/plugin-kit": "^3.1.7",
426
+ "@sanity/semantic-release-preset": "^4.1.2",
427
+ "@sanity/vision": "^3.14.5",
428
+ "@types/react": "^18.2.18",
429
+ "@types/styled-components": "^5.1.26",
430
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
431
+ "@typescript-eslint/parser": "^5.62.0",
432
+ "cz-conventional-changelog": "^3.3.0",
433
+ eslint: "^8.46.0",
434
+ "eslint-config-prettier": "^8.10.0",
435
+ "eslint-config-react-app": "^7.0.1",
436
+ "eslint-config-sanity": "^6.0.0",
437
+ "eslint-plugin-import": "^2.28.0",
438
+ "eslint-plugin-prettier": "^4.2.1",
439
+ "eslint-plugin-react": "^7.33.1",
440
+ "eslint-plugin-react-hooks": "^4.6.0",
441
+ "eslint-plugin-simple-import-sort": "^10.0.0",
442
+ husky: "^8.0.3",
443
+ "lint-staged": "^13.2.3",
444
+ next: "^13.4.12",
445
+ "next-sanity": "^4.3.3",
446
+ "npm-run-all": "^4.1.5",
447
+ prettier: "^2.8.8",
448
+ "prettier-plugin-packagejson": "^2.4.5",
449
+ react: "^18.2.0",
450
+ "react-dom": "^18.2.0",
451
+ "react-is": "^18.2.0",
452
+ rimraf: "^5.0.0",
453
+ sanity: "^3.14.5",
454
+ "styled-components": "^5.3.11",
455
+ typescript: "^5.1.6"
456
+ };
457
+ var peerDependencies = {
458
+ react: "^18",
459
+ "react-is": "^18",
460
+ sanity: "^3",
461
+ "styled-components": "^5.2"
462
+ };
463
+ var engines = {
464
+ node: ">=14"
465
+ };
466
+ var publishConfig = {
467
+ access: "public"
468
+ };
469
+ var sanityExchangeUrl = "https://www.sanity.io/plugins/sanity-plugin-mux-input";
470
+ var pluginPkg = {
471
+ name: name,
472
+ version: version,
473
+ description: description,
474
+ keywords: keywords,
475
+ homepage: homepage,
476
+ bugs: bugs,
477
+ repository: repository,
478
+ license: license,
479
+ author: author,
480
+ sideEffects: sideEffects,
481
+ type: type,
482
+ exports: exports$1,
483
+ main: main,
484
+ module: module$1,
485
+ source: source,
486
+ types: types,
487
+ files: files,
488
+ scripts: scripts,
489
+ dependencies: dependencies,
490
+ devDependencies: devDependencies,
491
+ peerDependencies: peerDependencies,
492
+ engines: engines,
493
+ publishConfig: publishConfig,
494
+ sanityExchangeUrl: sanityExchangeUrl
495
+ };
496
+ function VideoPlayer(_ref4) {
497
+ let {
498
+ asset,
499
+ children,
500
+ ...props
501
+ } = _ref4;
502
+ var _a, _b;
503
+ const client = useClient();
504
+ const videoSrc = React.useMemo(() => (asset == null ? void 0 : asset.playbackId) && getVideoSrc({
505
+ client,
506
+ asset
507
+ }), [asset, client]);
508
+ const signedToken = React.useMemo(() => {
509
+ try {
510
+ const url = new URL(videoSrc);
511
+ return url.searchParams.get("token");
512
+ } catch {
513
+ return false;
514
+ }
515
+ }, [videoSrc]);
516
+ const [width, height] = ((_b = (_a = asset == null ? void 0 : asset.data) == null ? void 0 : _a.aspect_ratio) != null ? _b : "16:9").split(":").map(Number);
517
+ const targetAspectRatio = props.forceAspectRatio || (Number.isNaN(width) ? 16 / 9 : width / height);
518
+ const aspectRatio = Math.max(MIN_ASPECT_RATIO, targetAspectRatio);
519
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
520
+ tone: "transparent",
521
+ style: {
522
+ aspectRatio,
523
+ position: "relative"
524
+ },
525
+ children: videoSrc && /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
526
+ children: [/* @__PURE__ */jsxRuntime.jsx(MuxPlayer__default.default, {
527
+ ...props,
528
+ playsInline: true,
529
+ playbackId: asset.playbackId,
530
+ tokens: signedToken ? {
531
+ playback: signedToken,
532
+ thumbnail: signedToken,
533
+ storyboard: signedToken
534
+ } : void 0,
535
+ streamType: "on-demand",
536
+ preload: "metadata",
537
+ crossOrigin: "anonymous",
538
+ metadata: {
539
+ player_name: "Sanity Admin Dashboard",
540
+ player_version: pluginPkg.version,
541
+ page_type: "Preview Player"
542
+ },
543
+ style: {
544
+ height: "100%",
545
+ width: "100%",
546
+ display: "block",
547
+ objectFit: "contain"
548
+ }
549
+ }), children]
550
+ })
551
+ });
552
+ }
553
+ function deleteAssetOnMux(client, assetId) {
554
+ const {
555
+ dataset
556
+ } = client.config();
557
+ return client.request({
558
+ url: "/addons/mux/assets/".concat(dataset, "/").concat(assetId),
559
+ withCredentials: true,
560
+ method: "DELETE"
561
+ });
562
+ }
563
+ async function deleteAsset(_ref5) {
564
+ let {
565
+ client,
566
+ asset,
567
+ deleteOnMux
568
+ } = _ref5;
569
+ if (!(asset == null ? void 0 : asset._id)) return true;
570
+ try {
571
+ await client.delete(asset._id);
572
+ } catch (error) {
573
+ return "failed-sanity";
574
+ }
575
+ if (deleteOnMux && (asset == null ? void 0 : asset.assetId)) {
576
+ try {
577
+ await deleteAssetOnMux(client, asset.assetId);
578
+ } catch (error) {
579
+ return "failed-mux";
580
+ }
581
+ }
582
+ return true;
583
+ }
584
+ function getAsset(client, assetId) {
585
+ const {
586
+ dataset
587
+ } = client.config();
588
+ return client.request({
589
+ url: "/addons/mux/assets/".concat(dataset, "/data/").concat(assetId),
590
+ withCredentials: true,
591
+ method: "GET"
592
+ });
593
+ }
594
+ const getUnknownTypeFallback = (id, typeName) => ({
595
+ title: /* @__PURE__ */jsxRuntime.jsxs("em", {
596
+ children: ["No schema found for type ", /* @__PURE__ */jsxRuntime.jsx("code", {
597
+ children: typeName
598
+ })]
599
+ }),
600
+ subtitle: /* @__PURE__ */jsxRuntime.jsxs("em", {
601
+ children: ["Document: ", /* @__PURE__ */jsxRuntime.jsx("code", {
602
+ children: id
603
+ })]
604
+ }),
605
+ media: () => /* @__PURE__ */jsxRuntime.jsx(icons.WarningOutlineIcon, {})
606
+ });
607
+ function MissingSchemaType(props) {
608
+ const {
609
+ layout,
610
+ value
611
+ } = props;
612
+ return /* @__PURE__ */jsxRuntime.jsx(sanity.SanityDefaultPreview, {
613
+ ...getUnknownTypeFallback(value._id, value._type),
614
+ layout
615
+ });
616
+ }
617
+ function TimeAgo(_ref6) {
618
+ let {
619
+ time
620
+ } = _ref6;
621
+ const timeAgo = sanity.useTimeAgo(time);
622
+ return /* @__PURE__ */jsxRuntime.jsxs("span", {
623
+ title: timeAgo,
624
+ children: [timeAgo, " ago"]
625
+ });
626
+ }
627
+ function DraftStatus(props) {
628
+ const {
629
+ document
630
+ } = props;
631
+ const updatedAt = document && "_updatedAt" in document && document._updatedAt;
632
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Tooltip, {
633
+ portal: true,
634
+ content: /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
635
+ padding: 2,
636
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
637
+ size: 1,
638
+ children: document ? /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
639
+ children: ["Edited ", updatedAt && /* @__PURE__ */jsxRuntime.jsx(TimeAgo, {
640
+ time: updatedAt
641
+ })]
642
+ }) : /* @__PURE__ */jsxRuntime.jsx(jsxRuntime.Fragment, {
643
+ children: "No unpublished edits"
644
+ })
645
+ })
646
+ }),
647
+ children: /* @__PURE__ */jsxRuntime.jsx(sanity.TextWithTone, {
648
+ tone: "caution",
649
+ dimmed: !document,
650
+ muted: !document,
651
+ size: 1,
652
+ children: /* @__PURE__ */jsxRuntime.jsx(icons.EditIcon, {})
653
+ })
654
+ });
655
+ }
656
+ function PublishedStatus(props) {
657
+ const {
658
+ document
659
+ } = props;
660
+ const updatedAt = document && "_updatedAt" in document && document._updatedAt;
661
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Tooltip, {
662
+ portal: true,
663
+ content: /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
664
+ padding: 2,
665
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
666
+ size: 1,
667
+ children: document ? /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
668
+ children: ["Published ", updatedAt && /* @__PURE__ */jsxRuntime.jsx(TimeAgo, {
669
+ time: updatedAt
670
+ })]
671
+ }) : /* @__PURE__ */jsxRuntime.jsx(jsxRuntime.Fragment, {
672
+ children: "Not published"
673
+ })
674
+ })
675
+ }),
676
+ children: /* @__PURE__ */jsxRuntime.jsx(sanity.TextWithTone, {
677
+ tone: "positive",
678
+ dimmed: !document,
679
+ muted: !document,
680
+ size: 1,
681
+ children: /* @__PURE__ */jsxRuntime.jsx(icons.PublishIcon, {})
682
+ })
683
+ });
684
+ }
685
+ function PaneItemPreview(props) {
686
+ const {
687
+ icon,
688
+ layout,
689
+ presence,
690
+ schemaType,
691
+ value
692
+ } = props;
693
+ const title = sanity.isRecord(value.title) && React.isValidElement(value.title) || lodash.isString(value.title) || lodash.isNumber(value.title) ? value.title : null;
694
+ const {
695
+ draft,
696
+ published,
697
+ isLoading
698
+ } = reactRx.useMemoObservable(() => sanity.getPreviewStateObservable(props.documentPreviewStore, schemaType, value._id, title), [props.documentPreviewStore, schemaType, value._id, title]);
699
+ const status = isLoading ? null : /* @__PURE__ */jsxRuntime.jsxs(ui.Inline, {
700
+ space: 4,
701
+ children: [presence && presence.length > 0 && /* @__PURE__ */jsxRuntime.jsx(sanity.DocumentPreviewPresence, {
702
+ presence
703
+ }), /* @__PURE__ */jsxRuntime.jsx(PublishedStatus, {
704
+ document: published
705
+ }), /* @__PURE__ */jsxRuntime.jsx(DraftStatus, {
706
+ document: draft
707
+ })]
708
+ });
709
+ return /* @__PURE__ */jsxRuntime.jsx(sanity.SanityDefaultPreview, {
710
+ ...sanity.getPreviewValueWithFallback({
711
+ value,
712
+ draft,
713
+ published
714
+ }),
715
+ isPlaceholder: isLoading,
716
+ icon,
717
+ layout,
718
+ status
719
+ });
720
+ }
721
+ function getIconWithFallback(icon, schemaType, defaultIcon) {
722
+ if (icon === false) {
723
+ return false;
724
+ }
725
+ return icon || schemaType && schemaType.icon || defaultIcon || false;
726
+ }
727
+ function DocumentPreviewInInput(props) {
728
+ const {
729
+ ChildLink
730
+ } = desk.usePaneRouter();
731
+ return linkProps => /* @__PURE__ */jsxRuntime.jsx(ChildLink, {
732
+ childId: props.documentPair.id,
733
+ childParameters: {
734
+ type: props.documentPair.type
735
+ },
736
+ children: linkProps.children
737
+ });
738
+ }
739
+ function DocumentPreviewInRool(props) {
740
+ return linkProps => /* @__PURE__ */jsxRuntime.jsx(router.IntentLink, {
741
+ intent: "edit",
742
+ params: {
743
+ id: props.documentPair.id
744
+ },
745
+ children: linkProps.children
746
+ });
747
+ }
748
+ function DocumentPreview(props) {
749
+ const {
750
+ schemaType,
751
+ documentPair
752
+ } = props;
753
+ const doc = (documentPair == null ? void 0 : documentPair.draft) || (documentPair == null ? void 0 : documentPair.published);
754
+ const id = documentPair.id || "";
755
+ const documentPreviewStore = sanity.useDocumentPreviewStore();
756
+ const schema = sanity.useSchema();
757
+ const documentPresence = sanity.useDocumentPresence(id);
758
+ const hasSchemaType = Boolean(schemaType && schemaType.name && schema.get(schemaType.name));
759
+ const PreviewComponent = React.useMemo(() => {
760
+ if (!doc) return null;
761
+ if (!schemaType || !hasSchemaType) {
762
+ return /* @__PURE__ */jsxRuntime.jsx(MissingSchemaType, {
763
+ value: doc
764
+ });
765
+ }
766
+ return /* @__PURE__ */jsxRuntime.jsx(PaneItemPreview, {
767
+ documentPreviewStore,
768
+ icon: getIconWithFallback(void 0, schemaType, icons.DocumentIcon),
769
+ schemaType,
770
+ layout: "default",
771
+ value: doc,
772
+ presence: documentPresence
773
+ });
774
+ }, [hasSchemaType, schemaType, documentPresence, doc, documentPreviewStore]);
775
+ return /* @__PURE__ */jsxRuntime.jsx(sanity.PreviewCard, {
776
+ __unstable_focusRing: true,
777
+ as: props.placement === "input" ? DocumentPreviewInInput(props) : DocumentPreviewInRool(props),
778
+ "data-as": "a",
779
+ "data-ui": "PaneItem",
780
+ padding: 2,
781
+ radius: 2,
782
+ tone: "inherit",
783
+ children: PreviewComponent
784
+ });
785
+ }
786
+ var __freeze$b = Object.freeze;
787
+ var __defProp$c = Object.defineProperty;
788
+ var __template$b = (cooked, raw) => __freeze$b(__defProp$c(cooked, "raw", {
789
+ value: __freeze$b(raw || cooked.slice())
790
+ }));
791
+ var _a$b;
792
+ const Container = styled__default.default(ui.Box)(_a$b || (_a$b = __template$b(["\n * {\n color: ", ";\n }\n a {\n text-decoration: none;\n }\n h2 {\n font-size: ", ";\n }\n"])), props => props.theme.sanity.color.base.fg, props => props.theme.sanity.fonts.text.sizes[1]);
793
+ const FileReferences = props => {
794
+ var _a2;
795
+ const schema = sanity.useSchema();
796
+ if (!props.isLoaded) {
797
+ return /* @__PURE__ */jsxRuntime.jsx(SpinnerBox, {});
798
+ }
799
+ if (!((_a2 = props.references) == null ? void 0 : _a2.length)) {
800
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
801
+ size: 2,
802
+ weight: "bold",
803
+ muted: true,
804
+ style: {
805
+ marginTop: "1.5rem",
806
+ textAlign: "center"
807
+ },
808
+ children: "No documents are using this file"
809
+ });
810
+ }
811
+ const documentPairs = sanity.collate(props.references || []);
812
+ return /* @__PURE__ */jsxRuntime.jsx(Container, {
813
+ children: documentPairs == null ? void 0 : documentPairs.map(documentPair => {
814
+ const schemaType = schema.get(documentPair.type);
815
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
816
+ marginBottom: 2,
817
+ padding: 2,
818
+ radius: 2,
819
+ shadow: 1,
820
+ style: {
821
+ overflow: "hidden"
822
+ },
823
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
824
+ children: /* @__PURE__ */jsxRuntime.jsx(DocumentPreview, {
825
+ documentPair,
826
+ schemaType,
827
+ placement: props.placement
828
+ })
829
+ })
830
+ }, documentPair.id);
831
+ })
832
+ });
833
+ };
834
+ function DeleteDialog(_ref7) {
835
+ let {
836
+ asset,
837
+ references,
838
+ referencesLoading,
839
+ cancelDelete,
840
+ placement,
841
+ succeededDeleting
842
+ } = _ref7;
843
+ const client = useClient();
844
+ const [state, setState] = React.useState("checkingReferences");
845
+ const [deleteOnMux, setDeleteOnMux] = React.useState(true);
846
+ const toast = ui.useToast();
847
+ React.useEffect(() => {
848
+ if (state !== "checkingReferences" || referencesLoading) return;
849
+ setState((references == null ? void 0 : references.length) ? "cantDelete" : "confirm");
850
+ }, [state, references, referencesLoading]);
851
+ async function confirmDelete() {
852
+ if (state !== "confirm") return;
853
+ setState("processing_deletion");
854
+ const worked = await deleteAsset({
855
+ client,
856
+ asset,
857
+ deleteOnMux
858
+ });
859
+ if (worked === true) {
860
+ toast.push({
861
+ title: "Successfully deleted video",
862
+ status: "success"
863
+ });
864
+ succeededDeleting();
865
+ } else if (worked === "failed-mux") {
866
+ toast.push({
867
+ title: "Deleted video in Sanity",
868
+ description: "But it wasn't deleted in Mux",
869
+ status: "warning"
870
+ });
871
+ succeededDeleting();
872
+ } else {
873
+ toast.push({
874
+ title: "Failed deleting video",
875
+ status: "error"
876
+ });
877
+ setState("error_deleting");
878
+ }
879
+ }
880
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Dialog, {
881
+ header: "Delete file",
882
+ zOffset: DIALOGS_Z_INDEX,
883
+ id: "deleting-file-details-dialog",
884
+ onClose: cancelDelete,
885
+ onClickOutside: cancelDelete,
886
+ width: 1,
887
+ position: "fixed",
888
+ footer: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
889
+ padding: 3,
890
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
891
+ justify: "space-between",
892
+ align: "center",
893
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
894
+ icon: icons.TrashIcon,
895
+ fontSize: 2,
896
+ padding: 3,
897
+ text: "Delete file",
898
+ tone: "critical",
899
+ onClick: confirmDelete,
900
+ disabled: ["processing_deletion", "checkingReferences", "cantDelete"].some(s => s === state)
901
+ })
902
+ })
903
+ }),
904
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
905
+ padding: 5,
906
+ style: {
907
+ minHeight: "150px",
908
+ display: "flex",
909
+ alignItems: "center",
910
+ justifyContent: "center"
911
+ },
912
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
913
+ space: 3,
914
+ children: [state === "checkingReferences" && /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
915
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Heading, {
916
+ size: 2,
917
+ children: "Checking if file can be deleted"
918
+ }), /* @__PURE__ */jsxRuntime.jsx(SpinnerBox, {})]
919
+ }), state === "cantDelete" && /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
920
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Heading, {
921
+ size: 2,
922
+ children: "Video can't be deleted"
923
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
924
+ size: 2,
925
+ style: {
926
+ marginBottom: "2rem"
927
+ },
928
+ children: ["There are ", references == null ? void 0 : references.length, " document", references && references.length > 0 && "s", " ", "pointing to this file. Remove their references to this file or delete them before proceeding."]
929
+ }), /* @__PURE__ */jsxRuntime.jsx(FileReferences, {
930
+ references,
931
+ isLoaded: !referencesLoading,
932
+ placement
933
+ })]
934
+ }), state === "confirm" && /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
935
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Heading, {
936
+ size: 2,
937
+ children: "Are you sure you want to delete this file?"
938
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
939
+ size: 2,
940
+ children: "This action is irreversible"
941
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
942
+ space: 4,
943
+ marginTop: 4,
944
+ children: [/* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
945
+ align: "center",
946
+ as: "label",
947
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Checkbox, {
948
+ checked: deleteOnMux,
949
+ onChange: () => setDeleteOnMux(prev => !prev)
950
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
951
+ style: {
952
+ margin: "0 10px"
953
+ },
954
+ children: "Delete asset on Mux"
955
+ })]
956
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
957
+ align: "center",
958
+ as: "label",
959
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Checkbox, {
960
+ disabled: true,
961
+ checked: true
962
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
963
+ style: {
964
+ margin: "0 10px"
965
+ },
966
+ children: "Delete video from dataset"
967
+ })]
968
+ })]
969
+ })]
970
+ }), state === "processing_deletion" && /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
971
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Heading, {
972
+ size: 2,
973
+ children: "Deleting file..."
974
+ }), /* @__PURE__ */jsxRuntime.jsx(SpinnerBox, {})]
975
+ }), state === "error_deleting" && /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
976
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Heading, {
977
+ size: 2,
978
+ children: "Something went wrong!"
979
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
980
+ size: 2,
981
+ children: "Try deleting the file again by clicking the button below"
982
+ })]
983
+ })]
984
+ })
985
+ })
986
+ });
987
+ }
988
+ const useDocReferences = sanity.createHookFromObservableFactory(_ref8 => {
989
+ let {
990
+ documentStore,
991
+ id
992
+ } = _ref8;
993
+ return documentStore.listenQuery( /* groq */
994
+ "*[references($id)]{_id, _type, _rev, _updatedAt, _createdAt}", {
995
+ id
996
+ }, {
997
+ apiVersion: SANITY_API_VERSION
998
+ });
999
+ });
1000
+ function formatSeconds(seconds) {
1001
+ if (typeof seconds !== "number" || Number.isNaN(seconds)) {
1002
+ return "";
1003
+ }
1004
+ const hrs = ~~(seconds / 3600);
1005
+ const mins = ~~(seconds % 3600 / 60);
1006
+ const secs = ~~seconds % 60;
1007
+ let ret = "";
1008
+ if (hrs > 0) {
1009
+ ret += "" + hrs + ":" + (mins < 10 ? "0" : "");
1010
+ }
1011
+ ret += "" + mins + ":" + (secs < 10 ? "0" : "");
1012
+ ret += "" + secs;
1013
+ return ret;
1014
+ }
1015
+ function getVideoMetadata(doc) {
1016
+ var _a, _b, _c, _d, _e, _f;
1017
+ const id = doc.assetId || doc._id || "";
1018
+ const date = ((_a = doc.data) == null ? void 0 : _a.created_at) ? new Date(Number(doc.data.created_at) * 1e3) : new Date(doc._createdAt || doc._updatedAt || Date.now());
1019
+ return {
1020
+ title: doc.filename || id.slice(0, 10),
1021
+ createdAt: date,
1022
+ duration: ((_b = doc.data) == null ? void 0 : _b.duration) ? formatSeconds((_c = doc.data) == null ? void 0 : _c.duration) : void 0,
1023
+ aspect_ratio: (_d = doc.data) == null ? void 0 : _d.aspect_ratio,
1024
+ max_stored_resolution: (_e = doc.data) == null ? void 0 : _e.max_stored_resolution,
1025
+ max_stored_frame_rate: (_f = doc.data) == null ? void 0 : _f.max_stored_frame_rate
1026
+ };
1027
+ }
1028
+ function useFileDetails(props) {
1029
+ const documentStore = sanity.useDocumentStore();
1030
+ const toast = ui.useToast();
1031
+ const client = useClient();
1032
+ const [references, referencesLoading] = useDocReferences({
1033
+ documentStore,
1034
+ id: props.asset._id
1035
+ });
1036
+ const [originalAsset, setOriginalAsset] = React.useState(() => props.asset);
1037
+ const [filename, setFilename] = React.useState(props.asset.filename);
1038
+ const modified = filename !== originalAsset.filename;
1039
+ const displayInfo = getVideoMetadata({
1040
+ ...props.asset,
1041
+ filename
1042
+ });
1043
+ const [state, setState] = React.useState("idle");
1044
+ function handleClose() {
1045
+ if (state !== "idle") return;
1046
+ if (modified) {
1047
+ setState("closing");
1048
+ return;
1049
+ }
1050
+ props.closeDialog();
1051
+ }
1052
+ function confirmClose(shouldClose) {
1053
+ if (state !== "closing") return;
1054
+ if (shouldClose) props.closeDialog();
1055
+ setState("idle");
1056
+ }
1057
+ async function saveChanges() {
1058
+ if (state !== "idle") return;
1059
+ setState("saving");
1060
+ try {
1061
+ await client.patch(props.asset._id).set({
1062
+ filename
1063
+ }).commit();
1064
+ setOriginalAsset(prev => ({
1065
+ ...prev,
1066
+ filename
1067
+ }));
1068
+ toast.push({
1069
+ title: "File name updated",
1070
+ status: "success"
1071
+ });
1072
+ } catch (error) {
1073
+ toast.push({
1074
+ title: "Failed updating file name",
1075
+ status: "error",
1076
+ description: typeof error === "string" ? error : "Please try again"
1077
+ });
1078
+ setFilename(originalAsset.filename);
1079
+ }
1080
+ setState("idle");
1081
+ }
1082
+ return {
1083
+ references,
1084
+ referencesLoading,
1085
+ modified,
1086
+ filename,
1087
+ setFilename,
1088
+ displayInfo,
1089
+ state,
1090
+ setState,
1091
+ handleClose,
1092
+ confirmClose,
1093
+ saveChanges
1094
+ };
1095
+ }
1096
+ const AssetInput = props => /* @__PURE__ */jsxRuntime.jsx(FormField$1, {
1097
+ title: props.label,
1098
+ description: props.description,
1099
+ inputId: props.label,
1100
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.TextInput, {
1101
+ id: props.label,
1102
+ value: props.value,
1103
+ placeholder: props.placeholder,
1104
+ onInput: props.onInput,
1105
+ disabled: props.disabled
1106
+ })
1107
+ });
1108
+ const VideoDetails = props => {
1109
+ const [tab, setTab] = React.useState("details");
1110
+ const {
1111
+ displayInfo,
1112
+ filename,
1113
+ modified,
1114
+ references,
1115
+ referencesLoading,
1116
+ setFilename,
1117
+ state,
1118
+ setState,
1119
+ handleClose,
1120
+ confirmClose,
1121
+ saveChanges
1122
+ } = useFileDetails(props);
1123
+ const isSaving = state === "saving";
1124
+ const [containerHeight, setContainerHeight] = React.useState(null);
1125
+ const contentsRef = React__default.default.useRef(null);
1126
+ React.useEffect(() => {
1127
+ if (!contentsRef.current || !("getBoundingClientRect" in contentsRef.current)) return;
1128
+ setContainerHeight(contentsRef.current.getBoundingClientRect().height);
1129
+ }, []);
1130
+ return /* @__PURE__ */jsxRuntime.jsxs(ui.Dialog, {
1131
+ header: displayInfo.title,
1132
+ zOffset: DIALOGS_Z_INDEX,
1133
+ id: "file-details-dialog",
1134
+ onClose: handleClose,
1135
+ onClickOutside: handleClose,
1136
+ width: 2,
1137
+ style: {
1138
+ minHeight: "50vh"
1139
+ },
1140
+ position: "fixed",
1141
+ footer: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1142
+ padding: 3,
1143
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1144
+ justify: "space-between",
1145
+ align: "center",
1146
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1147
+ icon: icons.TrashIcon,
1148
+ fontSize: 2,
1149
+ padding: 3,
1150
+ mode: "bleed",
1151
+ text: "Delete",
1152
+ tone: "critical",
1153
+ onClick: () => setState("deleting"),
1154
+ disabled: isSaving
1155
+ }), modified && /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1156
+ icon: icons.CheckmarkIcon,
1157
+ fontSize: 2,
1158
+ padding: 3,
1159
+ mode: "ghost",
1160
+ text: "Save and close",
1161
+ tone: "positive",
1162
+ onClick: saveChanges,
1163
+ iconRight: isSaving && ui.Spinner,
1164
+ disabled: isSaving
1165
+ })]
1166
+ })
1167
+ }),
1168
+ children: [state === "deleting" && /* @__PURE__ */jsxRuntime.jsx(DeleteDialog, {
1169
+ asset: props.asset,
1170
+ cancelDelete: () => setState("idle"),
1171
+ placement: props.placement,
1172
+ referencesLoading,
1173
+ references,
1174
+ succeededDeleting: () => {
1175
+ props.closeDialog();
1176
+ }
1177
+ }), state === "closing" && /* @__PURE__ */jsxRuntime.jsx(ui.Dialog, {
1178
+ header: "You have unsaved changes",
1179
+ zOffset: DIALOGS_Z_INDEX,
1180
+ id: "closing-file-details-dialog",
1181
+ onClose: () => confirmClose(false),
1182
+ onClickOutside: () => confirmClose(false),
1183
+ width: 1,
1184
+ position: "fixed",
1185
+ footer: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1186
+ padding: 3,
1187
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1188
+ justify: "space-between",
1189
+ align: "center",
1190
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1191
+ icon: icons.ErrorOutlineIcon,
1192
+ fontSize: 2,
1193
+ padding: 3,
1194
+ text: "Discard changes",
1195
+ tone: "critical",
1196
+ onClick: () => confirmClose(true)
1197
+ }), modified && /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1198
+ icon: icons.RevertIcon,
1199
+ fontSize: 2,
1200
+ padding: 3,
1201
+ mode: "ghost",
1202
+ text: "Keep editing",
1203
+ tone: "primary",
1204
+ onClick: () => confirmClose(false)
1205
+ })]
1206
+ })
1207
+ }),
1208
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1209
+ padding: 5,
1210
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1211
+ style: {
1212
+ textAlign: "center"
1213
+ },
1214
+ space: 3,
1215
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Heading, {
1216
+ size: 2,
1217
+ children: "Unsaved changes will be lost"
1218
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
1219
+ size: 2,
1220
+ children: "Are you sure you want to discard them?"
1221
+ })]
1222
+ })
1223
+ })
1224
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1225
+ padding: 4,
1226
+ sizing: "border",
1227
+ style: {
1228
+ containerType: "inline-size"
1229
+ },
1230
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1231
+ sizing: "border",
1232
+ gap: 4,
1233
+ direction: ["column", "column", "row"],
1234
+ align: "flex-start",
1235
+ ref: contentsRef,
1236
+ style: typeof containerHeight === "number" ? {
1237
+ minHeight: containerHeight
1238
+ } : void 0,
1239
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Stack, {
1240
+ space: 4,
1241
+ flex: 1,
1242
+ sizing: "border",
1243
+ children: /* @__PURE__ */jsxRuntime.jsx(VideoPlayer, {
1244
+ asset: props.asset,
1245
+ autoPlay: props.asset.autoPlay || false
1246
+ })
1247
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1248
+ space: 4,
1249
+ flex: 1,
1250
+ sizing: "border",
1251
+ children: [/* @__PURE__ */jsxRuntime.jsxs(ui.TabList, {
1252
+ space: 2,
1253
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Tab, {
1254
+ "aria-controls": "details-panel",
1255
+ icon: icons.EditIcon,
1256
+ id: "details-tab",
1257
+ label: "Details",
1258
+ onClick: () => setTab("details"),
1259
+ selected: tab === "details"
1260
+ }), references && references.length > 0 && /* @__PURE__ */jsxRuntime.jsx(ui.Tab, {
1261
+ "aria-controls": "references-panel",
1262
+ icon: icons.SearchIcon,
1263
+ id: "references-tab",
1264
+ label: "Used by (".concat(references.length, ")"),
1265
+ onClick: () => setTab("references"),
1266
+ selected: tab === "references"
1267
+ })]
1268
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.TabPanel, {
1269
+ "aria-labelledby": "details-tab",
1270
+ id: "details-panel",
1271
+ hidden: tab !== "details",
1272
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1273
+ space: 4,
1274
+ children: [/* @__PURE__ */jsxRuntime.jsx(AssetInput, {
1275
+ label: "File name",
1276
+ description: "Not visible to users. Useful for finding files later.",
1277
+ value: filename || "",
1278
+ onInput: e => setFilename(e.currentTarget.value),
1279
+ disabled: state !== "idle"
1280
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1281
+ space: 3,
1282
+ children: [(displayInfo == null ? void 0 : displayInfo.duration) && /* @__PURE__ */jsxRuntime.jsx(IconInfo, {
1283
+ text: "Duration: ".concat(displayInfo.duration),
1284
+ icon: icons.ClockIcon,
1285
+ size: 2
1286
+ }), (displayInfo == null ? void 0 : displayInfo.max_stored_resolution) && /* @__PURE__ */jsxRuntime.jsx(IconInfo, {
1287
+ text: "Max Resolution: ".concat(displayInfo.max_stored_resolution),
1288
+ icon: ResolutionIcon,
1289
+ size: 2
1290
+ }), (displayInfo == null ? void 0 : displayInfo.max_stored_frame_rate) && /* @__PURE__ */jsxRuntime.jsx(IconInfo, {
1291
+ text: "Frame rate: ".concat(displayInfo.max_stored_frame_rate),
1292
+ icon: StopWatchIcon,
1293
+ size: 2
1294
+ }), (displayInfo == null ? void 0 : displayInfo.aspect_ratio) && /* @__PURE__ */jsxRuntime.jsx(IconInfo, {
1295
+ text: "Aspect Ratio: ".concat(displayInfo.aspect_ratio),
1296
+ icon: icons.CropIcon,
1297
+ size: 2
1298
+ }), /* @__PURE__ */jsxRuntime.jsx(IconInfo, {
1299
+ text: "Uploaded on: ".concat(displayInfo.createdAt.toLocaleDateString("en", {
1300
+ year: "numeric",
1301
+ month: "2-digit",
1302
+ day: "2-digit",
1303
+ hour: "2-digit",
1304
+ minute: "2-digit",
1305
+ hour12: true
1306
+ })),
1307
+ icon: icons.CalendarIcon,
1308
+ size: 2
1309
+ })]
1310
+ })]
1311
+ })
1312
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.TabPanel, {
1313
+ "aria-labelledby": "references-tab",
1314
+ id: "references-panel",
1315
+ hidden: tab !== "references",
1316
+ children: /* @__PURE__ */jsxRuntime.jsx(FileReferences, {
1317
+ references,
1318
+ isLoaded: !referencesLoading,
1319
+ placement: props.placement
1320
+ })
1321
+ })]
1322
+ })]
1323
+ })
1324
+ })]
1325
+ });
1326
+ };
1327
+ const VideoMetadata = props => {
1328
+ if (!props.asset) {
1329
+ return null;
1330
+ }
1331
+ const displayInfo = getVideoMetadata(props.asset);
1332
+ return /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1333
+ space: 2,
1334
+ children: [displayInfo.title && /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
1335
+ size: 1,
1336
+ weight: "semibold",
1337
+ style: {
1338
+ wordWrap: "break-word"
1339
+ },
1340
+ children: displayInfo.title
1341
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Inline, {
1342
+ space: 3,
1343
+ children: [(displayInfo == null ? void 0 : displayInfo.duration) && /* @__PURE__ */jsxRuntime.jsx(IconInfo, {
1344
+ text: displayInfo.duration,
1345
+ icon: icons.ClockIcon,
1346
+ size: 1,
1347
+ muted: true
1348
+ }), /* @__PURE__ */jsxRuntime.jsx(IconInfo, {
1349
+ text: displayInfo.createdAt.toISOString().split("T")[0],
1350
+ icon: icons.CalendarIcon,
1351
+ size: 1,
1352
+ muted: true
1353
+ })]
1354
+ })]
1355
+ });
1356
+ };
1357
+ function useInView() {
1358
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1359
+ const [inView, setInView] = React.useState(false);
1360
+ const ref = React.useRef(null);
1361
+ React.useEffect(() => {
1362
+ if (!ref.current) return;
1363
+ const observer = new IntersectionObserver((_ref9, obs) => {
1364
+ let [entry] = _ref9;
1365
+ var _a;
1366
+ const nowInView = entry.isIntersecting && obs.thresholds.some(threshold => entry.intersectionRatio >= threshold);
1367
+ setInView(nowInView);
1368
+ (_a = options == null ? void 0 : options.onChange) == null ? void 0 : _a.call(options, nowInView);
1369
+ }, options);
1370
+ const toObserve = ref.current;
1371
+ observer.observe(toObserve);
1372
+ return () => {
1373
+ if (toObserve) observer.unobserve(toObserve);
1374
+ };
1375
+ }, [options]);
1376
+ return {
1377
+ inView,
1378
+ ref
1379
+ };
1380
+ }
1381
+ function getAnimatedPosterSrc(_ref10) {
1382
+ let {
1383
+ asset,
1384
+ client,
1385
+ height,
1386
+ width,
1387
+ start = asset.thumbTime ? Math.max(0, asset.thumbTime - 2.5) : 0,
1388
+ end = start + 5,
1389
+ fps = 15
1390
+ } = _ref10;
1391
+ const params = {
1392
+ height,
1393
+ width,
1394
+ start,
1395
+ end,
1396
+ fps
1397
+ };
1398
+ const playbackId = getPlaybackId(asset);
1399
+ let searchParams = new URLSearchParams(JSON.parse(JSON.stringify(params, (_, v) => v != null ? v : void 0)));
1400
+ if (getPlaybackPolicy(asset) === "signed") {
1401
+ const token = generateJwt(client, playbackId, "g", params);
1402
+ searchParams = new URLSearchParams({
1403
+ token
1404
+ });
1405
+ }
1406
+ return "https://image.mux.com/".concat(playbackId, "/animated.gif?").concat(searchParams);
1407
+ }
1408
+ var __freeze$a = Object.freeze;
1409
+ var __defProp$b = Object.defineProperty;
1410
+ var __template$a = (cooked, raw) => __freeze$a(__defProp$b(cooked, "raw", {
1411
+ value: __freeze$a(raw || cooked.slice())
1412
+ }));
1413
+ var _a$a;
1414
+ const Image = styled__default.default.img(_a$a || (_a$a = __template$a(["\n transition: opacity 0.175s ease-out 0s;\n display: block;\n width: 100%;\n height: 100%;\n object-fit: contain;\n object-position: center center;\n"])));
1415
+ const STATUS_TO_TONE = {
1416
+ loading: "transparent",
1417
+ error: "critical",
1418
+ loaded: "default"
1419
+ };
1420
+ function VideoThumbnail(_ref11) {
1421
+ let {
1422
+ asset,
1423
+ width = 250
1424
+ } = _ref11;
1425
+ const {
1426
+ inView,
1427
+ ref
1428
+ } = useInView();
1429
+ const [status, setStatus] = React.useState("loading");
1430
+ const client = useClient();
1431
+ const animatedSrc = React.useMemo(() => {
1432
+ try {
1433
+ return getAnimatedPosterSrc({
1434
+ asset,
1435
+ client,
1436
+ width
1437
+ });
1438
+ } catch {
1439
+ if (status !== "error") setStatus("error");
1440
+ return void 0;
1441
+ }
1442
+ }, [asset, client, width, status, setStatus]);
1443
+ function handleLoad() {
1444
+ setStatus("loaded");
1445
+ }
1446
+ function handleError() {
1447
+ setStatus("error");
1448
+ }
1449
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1450
+ style: {
1451
+ aspectRatio: THUMBNAIL_ASPECT_RATIO,
1452
+ position: "relative"
1453
+ },
1454
+ border: true,
1455
+ radius: 2,
1456
+ ref,
1457
+ tone: STATUS_TO_TONE[status],
1458
+ children: inView ? /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
1459
+ children: [status === "loading" && /* @__PURE__ */jsxRuntime.jsx(SpinnerBox, {}), status === "error" && /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1460
+ space: 4,
1461
+ style: {
1462
+ position: "absolute",
1463
+ width: "100%",
1464
+ left: 0,
1465
+ top: "50%",
1466
+ transform: "translateY(-50%)",
1467
+ justifyItems: "center"
1468
+ },
1469
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Text, {
1470
+ size: 4,
1471
+ muted: true,
1472
+ children: /* @__PURE__ */jsxRuntime.jsx(icons.ErrorOutlineIcon, {
1473
+ style: {
1474
+ fontSize: "1.75em"
1475
+ }
1476
+ })
1477
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
1478
+ muted: true,
1479
+ align: "center",
1480
+ children: "Failed loading thumbnail"
1481
+ })]
1482
+ }), /* @__PURE__ */jsxRuntime.jsx(Image, {
1483
+ src: animatedSrc,
1484
+ alt: "Preview for video ".concat(asset.filename || asset.assetId),
1485
+ onLoad: handleLoad,
1486
+ onError: handleError,
1487
+ style: {
1488
+ opacity: status === "loaded" ? 1 : 0
1489
+ }
1490
+ })]
1491
+ }) : null
1492
+ });
1493
+ }
1494
+ var __freeze$9 = Object.freeze;
1495
+ var __defProp$a = Object.defineProperty;
1496
+ var __template$9 = (cooked, raw) => __freeze$9(__defProp$a(cooked, "raw", {
1497
+ value: __freeze$9(raw || cooked.slice())
1498
+ }));
1499
+ var _a$9;
1500
+ const PlayButton = styled__default.default.button(_a$9 || (_a$9 = __template$9(["\n display: block;\n padding: 0;\n margin: 0;\n border: none;\n border-radius: 0.1875rem;\n position: relative;\n cursor: pointer;\n\n &::after {\n content: '';\n background: var(--card-fg-color);\n opacity: 0;\n display: block;\n position: absolute;\n inset: 0;\n z-index: 10;\n transition: 0.15s ease-out;\n border-radius: inherit;\n }\n\n > div[data-play] {\n z-index: 11;\n opacity: 0;\n transition: 0.15s 0.05s ease-out;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n color: var(--card-fg-color);\n background: var(--card-bg-color);\n width: auto;\n height: 30%;\n aspect-ratio: 1;\n border-radius: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n box-sizing: border-box;\n > svg {\n display: block;\n width: 70%;\n height: auto;\n // Visual balance to center-align the icon\n transform: translateX(5%);\n }\n }\n\n &:hover,\n &:focus {\n &::after {\n opacity: 0.3;\n }\n > div[data-play] {\n opacity: 1;\n }\n }\n"])));
1501
+ function VideoInBrowser(_ref12) {
1502
+ let {
1503
+ onSelect,
1504
+ onEdit,
1505
+ asset
1506
+ } = _ref12;
1507
+ const [renderVideo, setRenderVideo] = React.useState(false);
1508
+ const select = React__default.default.useCallback(() => onSelect == null ? void 0 : onSelect(asset), [onSelect, asset]);
1509
+ const edit = React__default.default.useCallback(() => onEdit == null ? void 0 : onEdit(asset), [onEdit, asset]);
1510
+ if (!asset) {
1511
+ return null;
1512
+ }
1513
+ const playbackPolicy = getPlaybackPolicy(asset);
1514
+ return /* @__PURE__ */jsxRuntime.jsxs(ui.Card, {
1515
+ border: true,
1516
+ padding: 2,
1517
+ sizing: "border",
1518
+ radius: 2,
1519
+ style: {
1520
+ position: "relative"
1521
+ },
1522
+ children: [playbackPolicy === "signed" && /* @__PURE__ */jsxRuntime.jsx(ui.Tooltip, {
1523
+ content: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1524
+ padding: 2,
1525
+ radius: 2,
1526
+ children: /* @__PURE__ */jsxRuntime.jsx(IconInfo, {
1527
+ icon: icons.LockIcon,
1528
+ text: "Signed playback policy",
1529
+ size: 2
1530
+ })
1531
+ }),
1532
+ placement: "right",
1533
+ fallbackPlacements: ["top", "bottom"],
1534
+ portal: true,
1535
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1536
+ tone: "caution",
1537
+ style: {
1538
+ borderRadius: "100%",
1539
+ position: "absolute",
1540
+ left: "1em",
1541
+ top: "1em",
1542
+ zIndex: 10
1543
+ },
1544
+ padding: 2,
1545
+ border: true,
1546
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
1547
+ muted: true,
1548
+ size: 1,
1549
+ children: /* @__PURE__ */jsxRuntime.jsx(icons.LockIcon, {})
1550
+ })
1551
+ })
1552
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1553
+ space: 3,
1554
+ height: "fill",
1555
+ style: {
1556
+ gridTemplateRows: "min-content min-content 1fr"
1557
+ },
1558
+ children: [renderVideo ? /* @__PURE__ */jsxRuntime.jsx(VideoPlayer, {
1559
+ asset,
1560
+ autoPlay: true,
1561
+ forceAspectRatio: THUMBNAIL_ASPECT_RATIO
1562
+ }) : /* @__PURE__ */jsxRuntime.jsxs(PlayButton, {
1563
+ onClick: () => setRenderVideo(true),
1564
+ children: [/* @__PURE__ */jsxRuntime.jsx("div", {
1565
+ "data-play": true,
1566
+ children: /* @__PURE__ */jsxRuntime.jsx(icons.PlayIcon, {})
1567
+ }), /* @__PURE__ */jsxRuntime.jsx(VideoThumbnail, {
1568
+ asset
1569
+ })]
1570
+ }), /* @__PURE__ */jsxRuntime.jsx(VideoMetadata, {
1571
+ asset
1572
+ }), /* @__PURE__ */jsxRuntime.jsxs("div", {
1573
+ style: {
1574
+ display: "flex",
1575
+ width: "100%",
1576
+ alignItems: "flex-end",
1577
+ justifyContent: "flex-start",
1578
+ gap: ".35rem"
1579
+ },
1580
+ children: [onSelect && /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1581
+ icon: icons.CheckmarkIcon,
1582
+ fontSize: 2,
1583
+ padding: 2,
1584
+ mode: "ghost",
1585
+ text: "Select",
1586
+ style: {
1587
+ flex: 1
1588
+ },
1589
+ tone: "positive",
1590
+ onClick: select
1591
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1592
+ icon: icons.EditIcon,
1593
+ fontSize: 2,
1594
+ padding: 2,
1595
+ mode: "ghost",
1596
+ text: "Details",
1597
+ style: {
1598
+ flex: 1
1599
+ },
1600
+ onClick: edit
1601
+ })]
1602
+ })]
1603
+ })]
1604
+ });
1605
+ }
1606
+ function VideosBrowser(_ref13) {
1607
+ let {
1608
+ onSelect
1609
+ } = _ref13;
1610
+ const {
1611
+ assets,
1612
+ isLoading,
1613
+ searchQuery,
1614
+ setSearchQuery,
1615
+ setSort,
1616
+ sort
1617
+ } = useAssets();
1618
+ const [editedAsset, setEditedAsset] = React__default.default.useState(null);
1619
+ const freshEditedAsset = React__default.default.useMemo(() => assets.find(a => a._id === (editedAsset == null ? void 0 : editedAsset._id)) || editedAsset, [editedAsset, assets]);
1620
+ return /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
1621
+ children: [/* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1622
+ padding: 4,
1623
+ space: 4,
1624
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
1625
+ justify: "space-between",
1626
+ align: "center",
1627
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1628
+ align: "center",
1629
+ gap: 3,
1630
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.TextInput, {
1631
+ value: searchQuery,
1632
+ icon: icons.SearchIcon,
1633
+ onInput: e => setSearchQuery(e.currentTarget.value),
1634
+ placeholder: "Search files"
1635
+ }), /* @__PURE__ */jsxRuntime.jsx(SelectSortOptions, {
1636
+ setSort,
1637
+ sort
1638
+ })]
1639
+ })
1640
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1641
+ space: 3,
1642
+ children: [(assets == null ? void 0 : assets.length) > 0 && /* @__PURE__ */jsxRuntime.jsxs(ui.Label, {
1643
+ muted: true,
1644
+ children: [assets.length, " video", assets.length > 1 ? "s" : null, " ", searchQuery ? 'matching "'.concat(searchQuery, '"') : "found"]
1645
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Grid, {
1646
+ gap: 2,
1647
+ style: {
1648
+ gridTemplateColumns: "repeat(auto-fill, minmax(250px, 1fr))"
1649
+ },
1650
+ children: assets.map(asset => /* @__PURE__ */jsxRuntime.jsx(VideoInBrowser, {
1651
+ asset,
1652
+ onEdit: setEditedAsset,
1653
+ onSelect
1654
+ }, asset._id))
1655
+ })]
1656
+ }), isLoading && /* @__PURE__ */jsxRuntime.jsx(SpinnerBox, {}), !isLoading && assets.length === 0 && /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1657
+ padding: 2,
1658
+ marginY: 4,
1659
+ border: true,
1660
+ radius: 2,
1661
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
1662
+ align: "center",
1663
+ muted: true,
1664
+ children: searchQuery ? 'No videos found for "'.concat(searchQuery, '"') : "No videos in this dataset"
1665
+ })
1666
+ })]
1667
+ }), freshEditedAsset && /* @__PURE__ */jsxRuntime.jsx(VideoDetails, {
1668
+ closeDialog: () => setEditedAsset(null),
1669
+ asset: freshEditedAsset,
1670
+ placement: onSelect ? "input" : "tool"
1671
+ })]
1672
+ });
1673
+ }
1674
+ const StudioTool = () => {
1675
+ return /* @__PURE__ */jsxRuntime.jsx(VideosBrowser, {});
1676
+ };
1677
+ function createStudioTool(config) {
1678
+ const toolConfig = typeof config.tool === "object" ? config.tool : {};
1679
+ return {
1680
+ name: "mux",
1681
+ title: toolConfig.title || "Videos",
1682
+ component: props => /* @__PURE__ */jsxRuntime.jsx(StudioTool, {
1683
+ ...config,
1684
+ ...props
1685
+ }),
1686
+ icon: toolConfig.icon || ToolIcon
1687
+ };
1688
+ }
1689
+ const path$1 = ["assetId", "data", "playbackId", "status", "thumbTime", "filename"];
1690
+ const useAssetDocumentValues = asset => sanity.useDocumentValues(sanity.isReference(asset) ? asset._ref : "", path$1);
1691
+ function useDialogState() {
1692
+ return React.useState(false);
1693
+ }
1694
+ const useMuxPolling = asset => {
1695
+ var _a, _b;
1696
+ const client = useClient();
1697
+ const projectId = sanity.useProjectId();
1698
+ const dataset = sanity.useDataset();
1699
+ const shouldFetch = React.useMemo(() => {
1700
+ var _a2, _b2;
1701
+ return !!(asset == null ? void 0 : asset.assetId) && ((asset == null ? void 0 : asset.status) === "preparing" || ((_b2 = (_a2 = asset == null ? void 0 : asset.data) == null ? void 0 : _a2.static_renditions) == null ? void 0 : _b2.status) === "preparing");
1702
+ }, [asset == null ? void 0 : asset.assetId, (_b = (_a = asset == null ? void 0 : asset.data) == null ? void 0 : _a.static_renditions) == null ? void 0 : _b.status, asset == null ? void 0 : asset.status]);
1703
+ return useSWR__default.default(shouldFetch ? "/".concat(projectId, "/addons/mux/assets/").concat(dataset, "/data/").concat(asset == null ? void 0 : asset.assetId) : null, async () => {
1704
+ const {
1705
+ data
1706
+ } = await client.request({
1707
+ url: "/addons/mux/assets/".concat(dataset, "/data/").concat(asset.assetId),
1708
+ withCredentials: true,
1709
+ method: "GET"
1710
+ });
1711
+ client.patch(asset._id).set({
1712
+ status: data.status,
1713
+ data
1714
+ }).commit({
1715
+ returnDocuments: false
1716
+ });
1717
+ }, {
1718
+ refreshInterval: 2e3,
1719
+ refreshWhenHidden: true,
1720
+ dedupingInterval: 1e3
1721
+ });
1722
+ };
1723
+ const path = ["token", "secretKey", "enableSignedUrls", "signingKeyId", "signingKeyPrivate"];
1724
+ const useSecretsDocumentValues = () => {
1725
+ const {
1726
+ error,
1727
+ isLoading,
1728
+ value
1729
+ } = sanity.useDocumentValues(muxSecretsDocumentId, path);
1730
+ const cache = React.useMemo(() => {
1731
+ const exists = Boolean(value);
1732
+ const secrets = {
1733
+ token: (value == null ? void 0 : value.token) || null,
1734
+ secretKey: (value == null ? void 0 : value.secretKey) || null,
1735
+ enableSignedUrls: (value == null ? void 0 : value.enableSignedUrls) || false,
1736
+ signingKeyId: (value == null ? void 0 : value.signingKeyId) || null,
1737
+ signingKeyPrivate: (value == null ? void 0 : value.signingKeyPrivate) || null
1738
+ };
1739
+ return {
1740
+ isInitialSetup: !exists,
1741
+ needsSetup: !(secrets == null ? void 0 : secrets.token) || !(secrets == null ? void 0 : secrets.secretKey),
1742
+ secrets
1743
+ };
1744
+ }, [value]);
1745
+ return {
1746
+ error,
1747
+ isLoading,
1748
+ value: cache
1749
+ };
1750
+ };
1751
+ function createUpChunkObservable(uuid, uploadUrl, source) {
1752
+ return new rxjs.Observable(subscriber => {
1753
+ const upchunk$1 = upchunk.UpChunk.createUpload({
1754
+ endpoint: uploadUrl,
1755
+ file: source,
1756
+ dynamicChunkSize: true
1757
+ // changes the chunk size based on network speeds
1758
+ });
1759
+
1760
+ const successHandler = () => {
1761
+ subscriber.next({
1762
+ type: "success",
1763
+ id: uuid
1764
+ });
1765
+ subscriber.complete();
1766
+ };
1767
+ const errorHandler = data => subscriber.error(new Error(data.detail.message));
1768
+ const progressHandler = data => {
1769
+ return subscriber.next({
1770
+ type: "progress",
1771
+ percent: data.detail
1772
+ });
1773
+ };
1774
+ const offlineHandler = () => {
1775
+ upchunk$1.pause();
1776
+ subscriber.next({
1777
+ type: "pause",
1778
+ id: uuid
1779
+ });
1780
+ };
1781
+ const onlineHandler = () => {
1782
+ upchunk$1.resume();
1783
+ subscriber.next({
1784
+ type: "resume",
1785
+ id: uuid
1786
+ });
1787
+ };
1788
+ upchunk$1.on("success", successHandler);
1789
+ upchunk$1.on("error", errorHandler);
1790
+ upchunk$1.on("progress", progressHandler);
1791
+ upchunk$1.on("offline", offlineHandler);
1792
+ upchunk$1.on("online", onlineHandler);
1793
+ return () => upchunk$1.abort();
1794
+ });
1795
+ }
1796
+ function saveSecrets(client, token, secretKey, enableSignedUrls, signingKeyId, signingKeyPrivate) {
1797
+ const doc = {
1798
+ _id: "secrets.mux",
1799
+ _type: "mux.apiKey",
1800
+ token,
1801
+ secretKey,
1802
+ enableSignedUrls,
1803
+ signingKeyId,
1804
+ signingKeyPrivate
1805
+ };
1806
+ return client.createOrReplace(doc);
1807
+ }
1808
+ function createSigningKeys(client) {
1809
+ const {
1810
+ dataset
1811
+ } = client.config();
1812
+ return client.request({
1813
+ url: "/addons/mux/signing-keys/".concat(dataset),
1814
+ withCredentials: true,
1815
+ method: "POST"
1816
+ });
1817
+ }
1818
+ function testSecrets(client) {
1819
+ const {
1820
+ dataset
1821
+ } = client.config();
1822
+ return client.request({
1823
+ url: "/addons/mux/secrets/".concat(dataset, "/test"),
1824
+ withCredentials: true,
1825
+ method: "GET"
1826
+ });
1827
+ }
1828
+ async function haveValidSigningKeys(client, signingKeyId, signingKeyPrivate) {
1829
+ if (!(signingKeyId && signingKeyPrivate)) {
1830
+ return false;
1831
+ }
1832
+ const {
1833
+ dataset
1834
+ } = client.config();
1835
+ try {
1836
+ const res = await client.request({
1837
+ url: "/addons/mux/signing-keys/".concat(dataset, "/").concat(signingKeyId),
1838
+ withCredentials: true,
1839
+ method: "GET"
1840
+ });
1841
+ return !!(res.data && res.data.id);
1842
+ } catch (e) {
1843
+ console.error("Error fetching signingKeyId", signingKeyId, "assuming it is not valid");
1844
+ return false;
1845
+ }
1846
+ }
1847
+ function testSecretsObservable(client) {
1848
+ const {
1849
+ dataset
1850
+ } = client.config();
1851
+ return rxjs.defer(() => client.observable.request({
1852
+ url: "/addons/mux/secrets/".concat(dataset, "/test"),
1853
+ withCredentials: true,
1854
+ method: "GET"
1855
+ }));
1856
+ }
1857
+ function cancelUpload(client, uuid) {
1858
+ return client.observable.request({
1859
+ url: "/addons/mux/uploads/".concat(client.config().dataset, "/").concat(uuid),
1860
+ withCredentials: true,
1861
+ method: "DELETE"
1862
+ });
1863
+ }
1864
+ function uploadUrl(config, client, url) {
1865
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
1866
+ return testUrl(url).pipe(operators.switchMap(validUrl => {
1867
+ return rxjs.concat(rxjs.of({
1868
+ type: "url",
1869
+ url: validUrl
1870
+ }), testSecretsObservable(client).pipe(operators.switchMap(json => {
1871
+ if (!json || !json.status) {
1872
+ return rxjs.throwError(new Error("Invalid credentials"));
1873
+ }
1874
+ const uuid$1 = uuid.uuid();
1875
+ const {
1876
+ enableSignedUrls
1877
+ } = options;
1878
+ const muxBody = {
1879
+ input: validUrl,
1880
+ playback_policy: [enableSignedUrls ? "signed" : "public"],
1881
+ mp4_support: config.mp4_support
1882
+ };
1883
+ const query = {
1884
+ muxBody: JSON.stringify(muxBody),
1885
+ filename: validUrl.split("/").slice(-1)[0]
1886
+ };
1887
+ const dataset = client.config().dataset;
1888
+ return rxjs.defer(() => client.observable.request({
1889
+ url: "/addons/mux/assets/".concat(dataset),
1890
+ withCredentials: true,
1891
+ method: "POST",
1892
+ headers: {
1893
+ "MUX-Proxy-UUID": uuid$1,
1894
+ "Content-Type": "application/json"
1895
+ },
1896
+ query
1897
+ })).pipe(operators.mergeMap(result => {
1898
+ const asset = result && result.results && result.results[0] && result.results[0].document || null;
1899
+ if (!asset) {
1900
+ return rxjs.throwError(new Error("No asset document returned"));
1901
+ }
1902
+ return rxjs.of({
1903
+ type: "success",
1904
+ id: uuid$1,
1905
+ asset
1906
+ });
1907
+ }));
1908
+ })));
1909
+ }));
1910
+ }
1911
+ function uploadFile(config, client, file) {
1912
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
1913
+ return testFile(file).pipe(operators.switchMap(fileOptions => {
1914
+ return rxjs.concat(rxjs.of({
1915
+ type: "file",
1916
+ file: fileOptions
1917
+ }), testSecretsObservable(client).pipe(operators.switchMap(json => {
1918
+ if (!json || !json.status) {
1919
+ return rxjs.throwError(new Error("Invalid credentials"));
1920
+ }
1921
+ const uuid$1 = uuid.uuid();
1922
+ const {
1923
+ enableSignedUrls
1924
+ } = options;
1925
+ const body = {
1926
+ mp4_support: config.mp4_support,
1927
+ playback_policy: [enableSignedUrls ? "signed" : "public"]
1928
+ };
1929
+ return rxjs.concat(rxjs.of({
1930
+ type: "uuid",
1931
+ uuid: uuid$1
1932
+ }), rxjs.defer(() => client.observable.request({
1933
+ url: "/addons/mux/uploads/".concat(client.config().dataset),
1934
+ withCredentials: true,
1935
+ method: "POST",
1936
+ headers: {
1937
+ "MUX-Proxy-UUID": uuid$1,
1938
+ "Content-Type": "application/json"
1939
+ },
1940
+ body
1941
+ })).pipe(operators.mergeMap(result => {
1942
+ return createUpChunkObservable(uuid$1, result.upload.url, file).pipe(
1943
+ // eslint-disable-next-line no-warning-comments
1944
+ // @TODO type the observable events
1945
+ // eslint-disable-next-line max-nested-callbacks
1946
+ operators.mergeMap(event => {
1947
+ if (event.type !== "success") {
1948
+ return rxjs.of(event);
1949
+ }
1950
+ return rxjs.from(updateAssetDocumentFromUpload(client, uuid$1)).pipe(
1951
+ // eslint-disable-next-line max-nested-callbacks
1952
+ operators.mergeMap(doc => rxjs.of({
1953
+ ...event,
1954
+ asset: doc
1955
+ })));
1956
+ }),
1957
+ // eslint-disable-next-line max-nested-callbacks
1958
+ operators.catchError(err => {
1959
+ return cancelUpload(client, uuid$1).pipe(operators.mergeMapTo(rxjs.throwError(err)));
1960
+ }));
1961
+ })));
1962
+ })));
1963
+ }));
1964
+ }
1965
+ function getUpload(client, assetId) {
1966
+ const {
1967
+ dataset
1968
+ } = client.config();
1969
+ return client.request({
1970
+ url: "/addons/mux/uploads/".concat(dataset, "/").concat(assetId),
1971
+ withCredentials: true,
1972
+ method: "GET"
1973
+ });
1974
+ }
1975
+ function pollUpload(client, uuid) {
1976
+ const maxTries = 10;
1977
+ let pollInterval;
1978
+ let tries = 0;
1979
+ let assetId;
1980
+ let upload;
1981
+ return new Promise((resolve, reject) => {
1982
+ pollInterval = setInterval(async () => {
1983
+ try {
1984
+ upload = await getUpload(client, uuid);
1985
+ } catch (err) {
1986
+ reject(err);
1987
+ return;
1988
+ }
1989
+ assetId = upload && upload.data && upload.data.asset_id;
1990
+ if (assetId) {
1991
+ clearInterval(pollInterval);
1992
+ resolve(upload);
1993
+ }
1994
+ if (tries > maxTries) {
1995
+ clearInterval(pollInterval);
1996
+ reject(new Error("Upload did not finish"));
1997
+ }
1998
+ tries++;
1999
+ }, 2e3);
2000
+ });
2001
+ }
2002
+ async function updateAssetDocumentFromUpload(client, uuid) {
2003
+ let upload;
2004
+ let asset;
2005
+ try {
2006
+ upload = await pollUpload(client, uuid);
2007
+ } catch (err) {
2008
+ return Promise.reject(err);
2009
+ }
2010
+ try {
2011
+ asset = await getAsset(client, upload.data.asset_id);
2012
+ } catch (err) {
2013
+ return Promise.reject(err);
2014
+ }
2015
+ const doc = {
2016
+ _id: uuid,
2017
+ _type: "mux.videoAsset",
2018
+ status: asset.data.status,
2019
+ data: asset.data,
2020
+ assetId: asset.data.id,
2021
+ playbackId: asset.data.playback_ids[0].id,
2022
+ uploadId: upload.data.id
2023
+ };
2024
+ return client.createOrReplace(doc).then(() => {
2025
+ return doc;
2026
+ });
2027
+ }
2028
+ function testFile(file) {
2029
+ if (typeof window !== "undefined" && file instanceof window.File) {
2030
+ const fileOptions = optionsFromFile({}, file);
2031
+ return rxjs.of(fileOptions);
2032
+ }
2033
+ return rxjs.throwError(new Error("Invalid file"));
2034
+ }
2035
+ function testUrl(url) {
2036
+ const error = new Error("Invalid URL");
2037
+ if (typeof url !== "string") {
2038
+ return rxjs.throwError(error);
2039
+ }
2040
+ let parsed;
2041
+ try {
2042
+ parsed = new URL(url);
2043
+ } catch (err) {
2044
+ return rxjs.throwError(error);
2045
+ }
2046
+ if (parsed && !parsed.protocol.match(/http:|https:/)) {
2047
+ return rxjs.throwError(error);
2048
+ }
2049
+ return rxjs.of(url);
2050
+ }
2051
+ function optionsFromFile(opts, file) {
2052
+ if (typeof window === "undefined" || !(file instanceof window.File)) {
2053
+ return opts;
2054
+ }
2055
+ return {
2056
+ name: opts.preserveFilename === false ? void 0 : file.name,
2057
+ type: file.type
2058
+ };
2059
+ }
2060
+ function extractDroppedFiles(dataTransfer) {
2061
+ const files = Array.from(dataTransfer.files || []);
2062
+ const items = Array.from(dataTransfer.items || []);
2063
+ if (files && files.length > 0) {
2064
+ return Promise.resolve(files);
2065
+ }
2066
+ return normalizeItems(items).then(arr => arr.flat());
2067
+ }
2068
+ function normalizeItems(items) {
2069
+ return Promise.all(items.map(item => {
2070
+ if (item.kind === "file" && item.webkitGetAsEntry) {
2071
+ let entry;
2072
+ try {
2073
+ entry = item.webkitGetAsEntry();
2074
+ } catch (err) {
2075
+ return [item.getAsFile()];
2076
+ }
2077
+ if (!entry) {
2078
+ return [];
2079
+ }
2080
+ return entry.isDirectory ? walk(entry) : [item.getAsFile()];
2081
+ }
2082
+ if (item.kind === "file") {
2083
+ const file = item.getAsFile();
2084
+ return Promise.resolve(file ? [file] : []);
2085
+ }
2086
+ return new Promise(resolve => item.getAsString(resolve)).then(str => str ? [new File([str], "unknown.txt", {
2087
+ type: item.type
2088
+ })] : []);
2089
+ }));
2090
+ }
2091
+ function isFile(entry) {
2092
+ return entry.isFile;
2093
+ }
2094
+ function isDirectory(entry) {
2095
+ return entry.isDirectory;
2096
+ }
2097
+ function walk(entry) {
2098
+ if (isFile(entry)) {
2099
+ return new Promise(resolve => entry.file(resolve)).then(file => [file]);
2100
+ }
2101
+ if (isDirectory(entry)) {
2102
+ const dir = entry.createReader();
2103
+ return new Promise(resolve => dir.readEntries(resolve)).then(entries => entries.filter(entr => !entr.name.startsWith("."))).then(entries => Promise.all(entries.map(walk)).then(arr => arr.flat()));
2104
+ }
2105
+ return Promise.resolve([]);
2106
+ }
2107
+ function SelectAssets(_ref14) {
2108
+ let {
2109
+ asset: selectedAsset,
2110
+ onChange,
2111
+ setDialogState
2112
+ } = _ref14;
2113
+ const handleSelect = React.useCallback(chosenAsset => {
2114
+ if (!(chosenAsset == null ? void 0 : chosenAsset._id)) {
2115
+ onChange(sanity.PatchEvent.from([sanity.unset(["asset"])]));
2116
+ }
2117
+ if (chosenAsset._id !== (selectedAsset == null ? void 0 : selectedAsset._id)) {
2118
+ onChange(sanity.PatchEvent.from([sanity.setIfMissing({
2119
+ asset: {}
2120
+ }), sanity.set({
2121
+ _type: "reference",
2122
+ _weak: true,
2123
+ _ref: chosenAsset._id
2124
+ }, ["asset"])]));
2125
+ }
2126
+ setDialogState(false);
2127
+ }, [onChange, setDialogState, selectedAsset]);
2128
+ return /* @__PURE__ */jsxRuntime.jsx(VideosBrowser, {
2129
+ onSelect: handleSelect
2130
+ });
2131
+ }
2132
+ function InputBrowser(_ref15) {
2133
+ let {
2134
+ setDialogState,
2135
+ asset,
2136
+ onChange
2137
+ } = _ref15;
2138
+ const id = "InputBrowser".concat(React.useId());
2139
+ const handleClose = React.useCallback(() => setDialogState(false), [setDialogState]);
2140
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Dialog, {
2141
+ __unstable_autoFocus: true,
2142
+ header: "Select video",
2143
+ id,
2144
+ onClose: handleClose,
2145
+ width: 2,
2146
+ children: /* @__PURE__ */jsxRuntime.jsx(SelectAssets, {
2147
+ asset,
2148
+ onChange,
2149
+ setDialogState
2150
+ })
2151
+ });
2152
+ }
2153
+ const useCancelUpload = (asset, onChange) => {
2154
+ const client = useClient();
2155
+ return React.useCallback(() => {
2156
+ if (!asset) {
2157
+ return;
2158
+ }
2159
+ onChange(sanity.PatchEvent.from(sanity.unset()));
2160
+ if (asset.assetId) {
2161
+ deleteAssetOnMux(client, asset.assetId);
2162
+ }
2163
+ if (asset._id) {
2164
+ client.delete(asset._id);
2165
+ }
2166
+ }, [asset, client, onChange]);
2167
+ };
2168
+ var __freeze$8 = Object.freeze;
2169
+ var __defProp$9 = Object.defineProperty;
2170
+ var __template$8 = (cooked, raw) => __freeze$8(__defProp$9(cooked, "raw", {
2171
+ value: __freeze$8(raw || cooked.slice())
2172
+ }));
2173
+ var _a$8, _b$4;
2174
+ styled__default.default.div(_a$8 || (_a$8 = __template$8(["\n && {\n --media-background-color: transparent;\n --media-button-icon-width: 100%;\n --media-button-icon-height: auto;\n pointer-events: none;\n width: 100%;\n display: flex;\n flex-flow: row;\n align-items: center;\n justify-content: center;\n media-play-button {\n --media-control-background: transparent;\n --media-control-hover-background: transparent;\n padding: 0;\n width: max(27px, min(9%, 90px));\n }\n }\n"])));
2175
+ const TopControls = styled__default.default.div(_b$4 || (_b$4 = __template$8(["\n position: absolute;\n top: 0;\n right: 0;\n justify-content: flex-end;\n button {\n height: auto;\n }\n"])));
2176
+ var __freeze$7 = Object.freeze;
2177
+ var __defProp$8 = Object.defineProperty;
2178
+ var __template$7 = (cooked, raw) => __freeze$7(__defProp$8(cooked, "raw", {
2179
+ value: __freeze$7(raw || cooked.slice())
2180
+ }));
2181
+ var _a$7, _b$3, _c, _d;
2182
+ const CardWrapper = styled__default.default(ui.Card)(_a$7 || (_a$7 = __template$7(["\n min-height: 82px;\n box-sizing: border-box;\n"])));
2183
+ const FlexWrapper = styled__default.default(ui.Flex)(_b$3 || (_b$3 = __template$7(["\n text-overflow: ellipsis;\n overflow: hidden;\n"])));
2184
+ const LeftSection = styled__default.default(ui.Stack)(_c || (_c = __template$7(["\n position: relative;\n width: 60%;\n"])));
2185
+ const CodeWrapper = styled__default.default(ui.Code)(_d || (_d = __template$7(["\n position: relative;\n width: 100%;\n\n code {\n overflow: hidden;\n text-overflow: ellipsis;\n position: relative;\n max-width: 200px;\n }\n"])));
2186
+ const UploadProgress = _ref16 => {
2187
+ let {
2188
+ progress = 100,
2189
+ onCancel,
2190
+ filename,
2191
+ text = "Uploading"
2192
+ } = _ref16;
2193
+ return /* @__PURE__ */jsxRuntime.jsx(CardWrapper, {
2194
+ tone: "primary",
2195
+ padding: 4,
2196
+ border: true,
2197
+ height: "fill",
2198
+ children: /* @__PURE__ */jsxRuntime.jsxs(FlexWrapper, {
2199
+ align: "center",
2200
+ justify: "space-between",
2201
+ height: "fill",
2202
+ direction: "row",
2203
+ gap: 2,
2204
+ children: [/* @__PURE__ */jsxRuntime.jsxs(LeftSection, {
2205
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
2206
+ justify: "center",
2207
+ gap: [3, 3, 2, 2],
2208
+ direction: ["column", "column", "row"],
2209
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
2210
+ size: 1,
2211
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Inline, {
2212
+ space: 2,
2213
+ children: [text, /* @__PURE__ */jsxRuntime.jsx(CodeWrapper, {
2214
+ size: 1,
2215
+ children: filename ? filename : "..."
2216
+ })]
2217
+ })
2218
+ })
2219
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
2220
+ marginTop: 3,
2221
+ radius: 5,
2222
+ shadow: 1,
2223
+ children: /* @__PURE__ */jsxRuntime.jsx(sanity.LinearProgress, {
2224
+ value: progress
2225
+ })
2226
+ })]
2227
+ }), onCancel ? /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
2228
+ fontSize: 2,
2229
+ text: "Cancel upload",
2230
+ mode: "ghost",
2231
+ tone: "critical",
2232
+ onClick: onCancel
2233
+ }) : null]
2234
+ })
2235
+ });
2236
+ };
2237
+ const Player = _ref17 => {
2238
+ let {
2239
+ asset,
2240
+ buttons,
2241
+ readOnly,
2242
+ onChange
2243
+ } = _ref17;
2244
+ var _a, _b, _c, _d;
2245
+ const isLoading = React.useMemo(() => {
2246
+ if ((asset == null ? void 0 : asset.status) === "preparing") {
2247
+ return "Preparing the video";
2248
+ }
2249
+ if ((asset == null ? void 0 : asset.status) === "waiting_for_upload") {
2250
+ return "Waiting for upload to start";
2251
+ }
2252
+ if ((asset == null ? void 0 : asset.status) === "waiting") {
2253
+ return "Processing upload";
2254
+ }
2255
+ if ((asset == null ? void 0 : asset.status) === "ready") {
2256
+ return false;
2257
+ }
2258
+ if (typeof (asset == null ? void 0 : asset.status) === "undefined") {
2259
+ return false;
2260
+ }
2261
+ return true;
2262
+ }, [asset]);
2263
+ const isPreparingStaticRenditions = React.useMemo(() => {
2264
+ var _a2, _b2, _c2, _d2;
2265
+ if (((_b2 = (_a2 = asset == null ? void 0 : asset.data) == null ? void 0 : _a2.static_renditions) == null ? void 0 : _b2.status) === "preparing") {
2266
+ return true;
2267
+ }
2268
+ if (((_d2 = (_c2 = asset == null ? void 0 : asset.data) == null ? void 0 : _c2.static_renditions) == null ? void 0 : _d2.status) === "ready") {
2269
+ return false;
2270
+ }
2271
+ return false;
2272
+ }, [(_b = (_a = asset == null ? void 0 : asset.data) == null ? void 0 : _a.static_renditions) == null ? void 0 : _b.status]);
2273
+ const playRef = React.useRef(null);
2274
+ const muteRef = React.useRef(null);
2275
+ const handleCancelUpload = useCancelUpload(asset, onChange);
2276
+ React.useEffect(() => {
2277
+ var _a2, _b2;
2278
+ const style = document.createElement("style");
2279
+ style.innerHTML = "button svg { vertical-align: middle; }";
2280
+ if ((_a2 = playRef.current) == null ? void 0 : _a2.shadowRoot) {
2281
+ playRef.current.shadowRoot.appendChild(style);
2282
+ }
2283
+ if ((_b2 = muteRef == null ? void 0 : muteRef.current) == null ? void 0 : _b2.shadowRoot) {
2284
+ muteRef.current.shadowRoot.appendChild(style.cloneNode(true));
2285
+ }
2286
+ }, []);
2287
+ React.useEffect(() => {
2288
+ var _a2, _b2, _c2;
2289
+ if ((asset == null ? void 0 : asset.status) === "errored") {
2290
+ handleCancelUpload();
2291
+ throw new Error((_c2 = (_b2 = (_a2 = asset.data) == null ? void 0 : _a2.errors) == null ? void 0 : _b2.messages) == null ? void 0 : _c2.join(" "));
2292
+ }
2293
+ }, [(_d = (_c = asset.data) == null ? void 0 : _c.errors) == null ? void 0 : _d.messages, asset == null ? void 0 : asset.status, handleCancelUpload]);
2294
+ if (!asset || !asset.status) {
2295
+ return null;
2296
+ }
2297
+ if (isLoading) {
2298
+ return /* @__PURE__ */jsxRuntime.jsx(UploadProgress, {
2299
+ progress: 100,
2300
+ filename: asset == null ? void 0 : asset.filename,
2301
+ text: isLoading !== true && isLoading || "Waiting for Mux to complete the file",
2302
+ onCancel: readOnly ? void 0 : () => handleCancelUpload()
2303
+ });
2304
+ }
2305
+ return /* @__PURE__ */jsxRuntime.jsxs(VideoPlayer, {
2306
+ asset,
2307
+ children: [buttons && /* @__PURE__ */jsxRuntime.jsx(TopControls, {
2308
+ slot: "top-chrome",
2309
+ children: buttons
2310
+ }), isPreparingStaticRenditions && /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
2311
+ padding: 2,
2312
+ radius: 1,
2313
+ style: {
2314
+ background: "var(--card-fg-color)",
2315
+ position: "absolute",
2316
+ top: "0.5em",
2317
+ left: "0.5em"
2318
+ },
2319
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
2320
+ size: 1,
2321
+ style: {
2322
+ color: "var(--card-bg-color)"
2323
+ },
2324
+ children: "MUX is preparing static renditions, please stand by"
2325
+ })
2326
+ })]
2327
+ });
2328
+ };
2329
+ function focusRingBorderStyle(border) {
2330
+ return "inset 0 0 0 ".concat(border.width, "px ").concat(border.color);
2331
+ }
2332
+ function focusRingStyle(opts) {
2333
+ const {
2334
+ base,
2335
+ border,
2336
+ focusRing
2337
+ } = opts;
2338
+ const focusRingOutsetWidth = focusRing.offset + focusRing.width;
2339
+ const focusRingInsetWidth = 0 - focusRing.offset;
2340
+ const bgColor = base ? base.bg : "var(--card-bg-color)";
2341
+ return [focusRingInsetWidth > 0 && "inset 0 0 0 ".concat(focusRingInsetWidth, "px var(--card-focus-ring-color)"), border && focusRingBorderStyle(border), focusRingInsetWidth < 0 && "0 0 0 ".concat(0 - focusRingInsetWidth, "px ").concat(bgColor), focusRingOutsetWidth > 0 && "0 0 0 ".concat(focusRingOutsetWidth, "px var(--card-focus-ring-color)")].filter(Boolean).join(",");
2342
+ }
2343
+ var __freeze$6 = Object.freeze;
2344
+ var __defProp$7 = Object.defineProperty;
2345
+ var __template$6 = (cooked, raw) => __freeze$6(__defProp$7(cooked, "raw", {
2346
+ value: __freeze$6(raw || cooked.slice())
2347
+ }));
2348
+ var _a$6;
2349
+ const FileButton = styled__default.default(ui.MenuItem)(_ref18 => {
2350
+ let {
2351
+ theme
2352
+ } = _ref18;
2353
+ const {
2354
+ focusRing
2355
+ } = theme.sanity;
2356
+ const base = theme.sanity.color.base;
2357
+ const border = {
2358
+ width: 1,
2359
+ color: "var(--card-border-color)"
2360
+ };
2361
+ return styled.css(_a$6 || (_a$6 = __template$6(["\n position: relative;\n\n &:not([data-disabled='true']) {\n &:focus-within {\n box-shadow: ", ";\n }\n }\n\n & input {\n overflow: hidden;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n position: absolute;\n min-width: 0;\n display: block;\n appearance: none;\n padding: 0;\n margin: 0;\n border: 0;\n opacity: 0;\n }\n "])), focusRingStyle({
2362
+ base,
2363
+ border,
2364
+ focusRing
2365
+ }));
2366
+ });
2367
+ const FileInputMenuItem = React__default.default.forwardRef(function FileInputMenuItem2(props, forwardedRef) {
2368
+ const {
2369
+ icon,
2370
+ id: idProp,
2371
+ accept,
2372
+ capture,
2373
+ fontSize,
2374
+ multiple,
2375
+ onSelect,
2376
+ padding = 3,
2377
+ space = 3,
2378
+ textAlign,
2379
+ text,
2380
+ disabled,
2381
+ ...rest
2382
+ } = props;
2383
+ const idHook = React.useId();
2384
+ const id = idProp || idHook;
2385
+ const handleChange = React__default.default.useCallback(event => {
2386
+ if (onSelect && event.target.files) {
2387
+ onSelect(Array.from(event.target.files));
2388
+ }
2389
+ }, [onSelect]);
2390
+ const content = /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
2391
+ align: "center",
2392
+ justify: "flex-start",
2393
+ padding,
2394
+ children: [icon && /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2395
+ marginRight: text ? space : void 0,
2396
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
2397
+ size: fontSize,
2398
+ children: [React.isValidElement(icon) && icon, reactIs.isValidElementType(icon) && React.createElement(icon)]
2399
+ })
2400
+ }), text && /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
2401
+ align: textAlign,
2402
+ size: fontSize,
2403
+ textOverflow: "ellipsis",
2404
+ children: text
2405
+ })]
2406
+ });
2407
+ return /* @__PURE__ */jsxRuntime.jsxs(FileButton, {
2408
+ ...rest,
2409
+ htmlFor: id,
2410
+ padding: 0,
2411
+ fontSize: 2,
2412
+ disabled,
2413
+ ref: forwardedRef,
2414
+ children: [content, /* @__PURE__ */jsxRuntime.jsx("input", {
2415
+ "data-testid": "file-button-input",
2416
+ accept,
2417
+ capture,
2418
+ id,
2419
+ multiple,
2420
+ onChange: handleChange,
2421
+ type: "file",
2422
+ value: "",
2423
+ disabled
2424
+ })]
2425
+ });
2426
+ });
2427
+ var __freeze$5 = Object.freeze;
2428
+ var __defProp$6 = Object.defineProperty;
2429
+ var __template$5 = (cooked, raw) => __freeze$5(__defProp$6(cooked, "raw", {
2430
+ value: __freeze$5(raw || cooked.slice())
2431
+ }));
2432
+ var _a$5, _b$2;
2433
+ const LockCard = styled__default.default(ui.Card)(_a$5 || (_a$5 = __template$5(["\n position: absolute;\n top: 0;\n left: 0;\n opacity: 0.6;\n mix-blend-mode: screen;\n background: transparent;\n"])));
2434
+ const LockButton = styled__default.default(ui.Button)(_b$2 || (_b$2 = __template$5(["\n background: transparent;\n color: white;\n"])));
2435
+ function PlayerActionsMenu(props) {
2436
+ const {
2437
+ asset,
2438
+ readOnly,
2439
+ dialogState,
2440
+ setDialogState,
2441
+ onChange,
2442
+ onUpload
2443
+ } = props;
2444
+ const [open, setOpen] = React.useState(false);
2445
+ const [menuElement, setMenuRef] = React.useState(null);
2446
+ const isSigned = React.useMemo(() => getPlaybackPolicy(asset) === "signed", [asset]);
2447
+ const onReset = React.useCallback(() => onChange(sanity.PatchEvent.from(sanity.unset([]))), [onChange]);
2448
+ React.useEffect(() => {
2449
+ if (open && dialogState) {
2450
+ setOpen(false);
2451
+ }
2452
+ }, [dialogState, open]);
2453
+ ui.useClickOutside(React.useCallback(() => setOpen(false), []), [menuElement]);
2454
+ return /* @__PURE__ */jsxRuntime.jsxs(ui.Inline, {
2455
+ space: 1,
2456
+ padding: 2,
2457
+ children: [isSigned && /* @__PURE__ */jsxRuntime.jsx(ui.Tooltip, {
2458
+ content: /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2459
+ padding: 2,
2460
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
2461
+ muted: true,
2462
+ size: 1,
2463
+ children: "Signed playback policy"
2464
+ })
2465
+ }),
2466
+ placement: "right",
2467
+ portal: true,
2468
+ children: /* @__PURE__ */jsxRuntime.jsx(LockCard, {
2469
+ radius: 2,
2470
+ margin: 2,
2471
+ scheme: "dark",
2472
+ tone: "positive",
2473
+ children: /* @__PURE__ */jsxRuntime.jsx(LockButton, {
2474
+ icon: icons.LockIcon,
2475
+ mode: "bleed",
2476
+ tone: "positive"
2477
+ })
2478
+ })
2479
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Popover, {
2480
+ content: /* @__PURE__ */jsxRuntime.jsxs(ui.Menu, {
2481
+ ref: setMenuRef,
2482
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2483
+ padding: 2,
2484
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Label, {
2485
+ muted: true,
2486
+ size: 1,
2487
+ children: "Replace"
2488
+ })
2489
+ }), /* @__PURE__ */jsxRuntime.jsx(FileInputMenuItem, {
2490
+ accept: "video/*",
2491
+ icon: icons.UploadIcon,
2492
+ mode: "bleed",
2493
+ onSelect: onUpload,
2494
+ text: "Upload",
2495
+ disabled: readOnly,
2496
+ fontSize: 2
2497
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.MenuItem, {
2498
+ icon: icons.SearchIcon,
2499
+ text: "Browse",
2500
+ onClick: () => setDialogState("select-video")
2501
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.MenuDivider, {}), /* @__PURE__ */jsxRuntime.jsx(ui.MenuItem, {
2502
+ icon: icons.PlugIcon,
2503
+ text: "Configure API",
2504
+ onClick: () => setDialogState("secrets")
2505
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.MenuDivider, {}), /* @__PURE__ */jsxRuntime.jsx(ui.MenuItem, {
2506
+ tone: "critical",
2507
+ icon: icons.ResetIcon,
2508
+ text: "Clear field",
2509
+ onClick: onReset,
2510
+ disabled: readOnly
2511
+ })]
2512
+ }),
2513
+ portal: true,
2514
+ open,
2515
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
2516
+ icon: icons.EllipsisVerticalIcon,
2517
+ mode: "ghost",
2518
+ onClick: () => {
2519
+ setDialogState(false);
2520
+ setOpen(true);
2521
+ }
2522
+ })
2523
+ })]
2524
+ });
2525
+ }
2526
+ var PlayerActionsMenu$1 = React.memo(PlayerActionsMenu);
2527
+ var __freeze$4 = Object.freeze;
2528
+ var __defProp$5 = Object.defineProperty;
2529
+ var __template$4 = (cooked, raw) => __freeze$4(__defProp$5(cooked, "raw", {
2530
+ value: __freeze$4(raw || cooked.slice())
2531
+ }));
2532
+ var _a$4;
2533
+ function withFocusRing(component) {
2534
+ return styled__default.default(component)(props => {
2535
+ const border = {
2536
+ width: props.$border ? 1 : 0,
2537
+ color: "var(--card-border-color)"
2538
+ };
2539
+ return styled.css(_a$4 || (_a$4 = __template$4(["\n --card-focus-box-shadow: ", ";\n\n border-radius: ", ";\n outline: none;\n box-shadow: var(--card-focus-box-shadow);\n\n &:focus {\n --card-focus-box-shadow: ", ";\n }\n "])), focusRingBorderStyle(border), ui.rem(props.theme.sanity.radius[1]), focusRingStyle({
2540
+ base: props.theme.sanity.color.base,
2541
+ border,
2542
+ focusRing: props.theme.sanity.focusRing
2543
+ }));
2544
+ });
2545
+ }
2546
+ var __freeze$3 = Object.freeze;
2547
+ var __defProp$4 = Object.defineProperty;
2548
+ var __template$3 = (cooked, raw) => __freeze$3(__defProp$4(cooked, "raw", {
2549
+ value: __freeze$3(raw || cooked.slice())
2550
+ }));
2551
+ var _a$3;
2552
+ const ctrlKey = 17;
2553
+ const cmdKey = 91;
2554
+ const UploadCardWithFocusRing = withFocusRing(ui.Card);
2555
+ const UploadCard$1 = React.forwardRef((_ref19, forwardedRef) => {
2556
+ let {
2557
+ children,
2558
+ tone,
2559
+ onPaste,
2560
+ onDrop,
2561
+ onDragEnter,
2562
+ onDragLeave,
2563
+ onDragOver
2564
+ } = _ref19;
2565
+ const ctrlDown = React.useRef(false);
2566
+ const inputRef = React.useRef(null);
2567
+ const handleKeyDown = React.useCallback(event => {
2568
+ if (event.keyCode == ctrlKey || event.keyCode == cmdKey) {
2569
+ ctrlDown.current = true;
2570
+ }
2571
+ const vKey = 86;
2572
+ if (ctrlDown.current && event.keyCode == vKey) {
2573
+ inputRef.current.focus();
2574
+ }
2575
+ }, []);
2576
+ const handleKeyUp = React.useCallback(event => {
2577
+ if (event.keyCode == ctrlKey || event.keyCode == cmdKey) {
2578
+ ctrlDown.current = false;
2579
+ }
2580
+ }, []);
2581
+ return /* @__PURE__ */jsxRuntime.jsxs(UploadCardWithFocusRing, {
2582
+ tone,
2583
+ height: "fill",
2584
+ ref: forwardedRef,
2585
+ padding: 0,
2586
+ radius: 2,
2587
+ shadow: 0,
2588
+ tabIndex: 0,
2589
+ onKeyDown: handleKeyDown,
2590
+ onKeyUp: handleKeyUp,
2591
+ onPaste,
2592
+ onDrop,
2593
+ onDragEnter,
2594
+ onDragLeave,
2595
+ onDragOver,
2596
+ children: [/* @__PURE__ */jsxRuntime.jsx(HiddenInput$1, {
2597
+ ref: inputRef,
2598
+ onPaste
2599
+ }), children]
2600
+ });
2601
+ });
2602
+ const HiddenInput$1 = styled__default.default.input.attrs({
2603
+ type: "text"
2604
+ })(_a$3 || (_a$3 = __template$3(["\n position: absolute;\n border: 0;\n color: white;\n opacity: 0;\n\n &:focus {\n outline: none;\n }\n"])));
2605
+ var __freeze$2 = Object.freeze;
2606
+ var __defProp$3 = Object.defineProperty;
2607
+ var __template$2 = (cooked, raw) => __freeze$2(__defProp$3(cooked, "raw", {
2608
+ value: __freeze$2(raw || cooked.slice())
2609
+ }));
2610
+ var _a$2, _b$1;
2611
+ const HiddenInput = styled__default.default.input(_a$2 || (_a$2 = __template$2(["\n overflow: hidden;\n width: 0.1px;\n height: 0.1px;\n opacity: 0;\n position: absolute;\n z-index: -1;\n"])));
2612
+ const Label = styled__default.default.label(_b$1 || (_b$1 = __template$2(["\n position: relative;\n"])));
2613
+ const FileInputButton = _ref20 => {
2614
+ let {
2615
+ onSelect,
2616
+ ...props
2617
+ } = _ref20;
2618
+ const inputId = "FileSelect".concat(React.useId());
2619
+ const inputRef = React.useRef(null);
2620
+ const handleSelect = React.useCallback(event => {
2621
+ if (onSelect) {
2622
+ onSelect(event.target.files);
2623
+ }
2624
+ }, [onSelect]);
2625
+ const handleButtonClick = React.useCallback(() => {
2626
+ var _a2;
2627
+ return (_a2 = inputRef.current) == null ? void 0 : _a2.click();
2628
+ }, []);
2629
+ return /* @__PURE__ */jsxRuntime.jsxs(Label, {
2630
+ htmlFor: inputId,
2631
+ children: [/* @__PURE__ */jsxRuntime.jsx(HiddenInput, {
2632
+ accept: "video/*",
2633
+ ref: inputRef,
2634
+ tabIndex: 0,
2635
+ type: "file",
2636
+ id: inputId,
2637
+ onChange: handleSelect,
2638
+ value: ""
2639
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
2640
+ onClick: handleButtonClick,
2641
+ mode: "default",
2642
+ tone: "primary",
2643
+ style: {
2644
+ width: "100%"
2645
+ },
2646
+ ...props
2647
+ })]
2648
+ });
2649
+ };
2650
+ var __freeze$1 = Object.freeze;
2651
+ var __defProp$2 = Object.defineProperty;
2652
+ var __template$1 = (cooked, raw) => __freeze$1(__defProp$2(cooked, "raw", {
2653
+ value: __freeze$1(raw || cooked.slice())
2654
+ }));
2655
+ var _a$1, _b;
2656
+ const UploadCard = styled__default.default(ui.Card)(_a$1 || (_a$1 = __template$1(["\n && {\n border-style: dashed;\n }\n"])));
2657
+ const ConfigureApiBox = styled__default.default(ui.Box)(_b || (_b = __template$1(["\n position: absolute;\n top: 0;\n right: 0;\n"])));
2658
+ function UploadPlaceholder(props) {
2659
+ const {
2660
+ setDialogState,
2661
+ readOnly,
2662
+ onSelect,
2663
+ hovering,
2664
+ needsSetup
2665
+ } = props;
2666
+ const handleBrowse = React.useCallback(() => setDialogState("select-video"), [setDialogState]);
2667
+ const handleConfigureApi = React.useCallback(() => setDialogState("secrets"), [setDialogState]);
2668
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2669
+ style: {
2670
+ padding: 1,
2671
+ position: "relative"
2672
+ },
2673
+ height: "stretch",
2674
+ children: /* @__PURE__ */jsxRuntime.jsxs(UploadCard, {
2675
+ sizing: "border",
2676
+ height: "fill",
2677
+ tone: readOnly ? "transparent" : "inherit",
2678
+ border: true,
2679
+ padding: 3,
2680
+ style: hovering ? {
2681
+ borderColor: "transparent"
2682
+ } : void 0,
2683
+ children: [/* @__PURE__ */jsxRuntime.jsx(ConfigureApiBox, {
2684
+ padding: 3,
2685
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
2686
+ padding: 3,
2687
+ radius: 3,
2688
+ tone: needsSetup ? "critical" : void 0,
2689
+ onClick: handleConfigureApi,
2690
+ icon: icons.PlugIcon,
2691
+ mode: "bleed"
2692
+ })
2693
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
2694
+ align: "center",
2695
+ justify: "space-between",
2696
+ gap: 4,
2697
+ direction: ["column", "column", "row"],
2698
+ paddingY: [2, 2, 0],
2699
+ sizing: "border",
2700
+ height: "fill",
2701
+ children: [/* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
2702
+ align: "center",
2703
+ justify: "center",
2704
+ gap: 2,
2705
+ flex: 1,
2706
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
2707
+ justify: "center",
2708
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
2709
+ muted: true,
2710
+ children: /* @__PURE__ */jsxRuntime.jsx(icons.DocumentVideoIcon, {})
2711
+ })
2712
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
2713
+ justify: "center",
2714
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
2715
+ size: 1,
2716
+ muted: true,
2717
+ children: "Drag video or paste URL here"
2718
+ })
2719
+ })]
2720
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Inline, {
2721
+ space: 2,
2722
+ children: [/* @__PURE__ */jsxRuntime.jsx(FileInputButton, {
2723
+ mode: "ghost",
2724
+ tone: "default",
2725
+ icon: icons.UploadIcon,
2726
+ text: "Upload",
2727
+ onSelect
2728
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
2729
+ mode: "ghost",
2730
+ icon: icons.SearchIcon,
2731
+ text: "Select",
2732
+ onClick: handleBrowse
2733
+ })]
2734
+ })]
2735
+ })]
2736
+ })
2737
+ });
2738
+ }
2739
+ var __defProp$1 = Object.defineProperty;
2740
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp$1(obj, key, {
2741
+ enumerable: true,
2742
+ configurable: true,
2743
+ writable: true,
2744
+ value
2745
+ }) : obj[key] = value;
2746
+ var __publicField = (obj, key, value) => {
2747
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
2748
+ return value;
2749
+ };
2750
+ class MuxVideoInputUploader extends React.Component {
2751
+ constructor() {
2752
+ super(...arguments);
2753
+ __publicField(this, "state", {
2754
+ isDraggingOver: false,
2755
+ invalidPaste: false,
2756
+ invalidFile: false,
2757
+ uploadProgress: null,
2758
+ fileInfo: null,
2759
+ uuid: null,
2760
+ error: null,
2761
+ url: null
2762
+ });
2763
+ __publicField(this, "dragEnteredEls", []);
2764
+ __publicField(this, "ctrlDown", false);
2765
+ // eslint-disable-next-line no-warning-comments
2766
+ // @TODO add proper typings for the return values of uploadFile and uploadUrl
2767
+ __publicField(this, "upload", null);
2768
+ __publicField(this, "container", React__default.default.createRef());
2769
+ __publicField(this, "onCancelUploadButtonClick$");
2770
+ __publicField(this, "handleCancelUploadButtonClick");
2771
+ __publicField(this, "handleProgress", evt => {
2772
+ this.setState({
2773
+ uploadProgress: evt.percent
2774
+ });
2775
+ });
2776
+ __publicField(this, "onUpload", files => {
2777
+ this.setState({
2778
+ uploadProgress: 0,
2779
+ fileInfo: null,
2780
+ uuid: null
2781
+ });
2782
+ this.upload = uploadFile(this.props.config, this.props.client, files[0], {
2783
+ enableSignedUrls: this.props.secrets.enableSignedUrls
2784
+ }).pipe(operators.takeUntil(this.onCancelUploadButtonClick$.pipe(operators.tap(() => {
2785
+ if (this.state.uuid) {
2786
+ this.props.client.delete(this.state.uuid);
2787
+ }
2788
+ })))).subscribe({
2789
+ complete: () => {
2790
+ this.setState({
2791
+ error: null,
2792
+ uploadProgress: null,
2793
+ uuid: null
2794
+ });
2795
+ },
2796
+ next: event => {
2797
+ this.handleUploadEvent(event);
2798
+ },
2799
+ error: err => {
2800
+ this.setState({
2801
+ error: err,
2802
+ uploadProgress: null,
2803
+ uuid: null
2804
+ });
2805
+ }
2806
+ });
2807
+ });
2808
+ // eslint-disable-next-line no-warning-comments
2809
+ // @TODO add proper typings for the Observable events
2810
+ __publicField(this, "handleUploadEvent", event => {
2811
+ switch (event.type) {
2812
+ case "success":
2813
+ return this.handleUploadSuccess(event.asset);
2814
+ case "progress":
2815
+ return this.handleProgress(event);
2816
+ case "file":
2817
+ return this.setState({
2818
+ fileInfo: event.file
2819
+ });
2820
+ case "uuid":
2821
+ return this.setState({
2822
+ uuid: event.uuid
2823
+ });
2824
+ case "url":
2825
+ return this.setState({
2826
+ url: event.url,
2827
+ uploadProgress: 100
2828
+ });
2829
+ default:
2830
+ return null;
2831
+ }
2832
+ });
2833
+ __publicField(this, "handleUploadSuccess", asset => {
2834
+ this.setState({
2835
+ uploadProgress: 100
2836
+ });
2837
+ this.props.onChange(sanity.PatchEvent.from([sanity.setIfMissing({
2838
+ asset: {}
2839
+ }), sanity.set({
2840
+ _type: "reference",
2841
+ _weak: true,
2842
+ _ref: asset._id
2843
+ }, ["asset"])]));
2844
+ });
2845
+ __publicField(this, "handlePaste", event => {
2846
+ const clipboardData = event.clipboardData || window.clipboardData;
2847
+ const url = clipboardData.getData("text");
2848
+ const options = {
2849
+ enableSignedUrls: this.props.secrets.enableSignedUrls
2850
+ };
2851
+ this.upload = uploadUrl(this.props.config, this.props.client, url, options).subscribe({
2852
+ complete: () => {
2853
+ this.setState({
2854
+ error: null,
2855
+ uploadProgress: null,
2856
+ url: null
2857
+ });
2858
+ },
2859
+ next: sEvent => {
2860
+ this.handleUploadEvent(sEvent);
2861
+ },
2862
+ error: err => {
2863
+ let error;
2864
+ if (!err.message.toLowerCase().match("invalid url")) {
2865
+ error = err;
2866
+ }
2867
+ this.setState({
2868
+ invalidPaste: true,
2869
+ error
2870
+ }, () => {
2871
+ setTimeout(() => {
2872
+ this.setState({
2873
+ invalidPaste: false,
2874
+ uploadProgress: null
2875
+ });
2876
+ }, 2e3);
2877
+ });
2878
+ }
2879
+ });
2880
+ });
2881
+ __publicField(this, "handleDrop", event => {
2882
+ this.setState({
2883
+ isDraggingOver: false
2884
+ });
2885
+ event.preventDefault();
2886
+ event.stopPropagation();
2887
+ extractDroppedFiles(event.nativeEvent.dataTransfer).then(files => {
2888
+ if (files) {
2889
+ this.onUpload(files);
2890
+ }
2891
+ });
2892
+ });
2893
+ __publicField(this, "handleDragOver", event => {
2894
+ event.preventDefault();
2895
+ event.stopPropagation();
2896
+ });
2897
+ __publicField(this, "handleDragEnter", event => {
2898
+ var _a, _b;
2899
+ event.stopPropagation();
2900
+ this.dragEnteredEls.push(event.target);
2901
+ this.setState({
2902
+ isDraggingOver: true
2903
+ });
2904
+ const type = (_b = (_a = event.dataTransfer.items) == null ? void 0 : _a[0]) == null ? void 0 : _b.type;
2905
+ this.setState({
2906
+ invalidFile: !type.startsWith("video/")
2907
+ });
2908
+ });
2909
+ __publicField(this, "handleDragLeave", event => {
2910
+ event.stopPropagation();
2911
+ const idx = this.dragEnteredEls.indexOf(event.target);
2912
+ if (idx > -1) {
2913
+ this.dragEnteredEls.splice(idx, 1);
2914
+ }
2915
+ if (this.dragEnteredEls.length === 0) {
2916
+ this.setState({
2917
+ isDraggingOver: false
2918
+ });
2919
+ }
2920
+ });
2921
+ }
2922
+ componentWillUnmount() {
2923
+ this.unSubscribeToUpload();
2924
+ }
2925
+ componentDidMount() {
2926
+ const events$ = new rxjs.Subject();
2927
+ this.onCancelUploadButtonClick$ = events$.asObservable();
2928
+ this.handleCancelUploadButtonClick = event => events$.next(event);
2929
+ }
2930
+ unSubscribeToUpload() {
2931
+ if (this.upload && !this.upload.closed) {
2932
+ this.upload.unsubscribe();
2933
+ }
2934
+ }
2935
+ render() {
2936
+ var _a;
2937
+ if (this.state.uploadProgress !== null) {
2938
+ return /* @__PURE__ */jsxRuntime.jsx(UploadProgress, {
2939
+ onCancel: this.handleCancelUploadButtonClick,
2940
+ progress: this.state.uploadProgress,
2941
+ filename: ((_a = this.state.fileInfo) == null ? void 0 : _a.name) || this.state.url
2942
+ });
2943
+ }
2944
+ if (this.state.error) {
2945
+ throw this.state.error;
2946
+ }
2947
+ return /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
2948
+ children: [/* @__PURE__ */jsxRuntime.jsx(UploadCard$1, {
2949
+ tone: this.state.isDraggingOver && (this.state.invalidPaste || this.state.invalidFile) ? "critical" : this.state.isDraggingOver ? "positive" : void 0,
2950
+ onDrop: this.handleDrop,
2951
+ onDragOver: this.handleDragOver,
2952
+ onDragLeave: this.handleDragLeave,
2953
+ onDragEnter: this.handleDragEnter,
2954
+ onPaste: this.handlePaste,
2955
+ ref: this.container,
2956
+ children: this.props.asset ? /* @__PURE__ */jsxRuntime.jsx(Player, {
2957
+ readOnly: this.props.readOnly,
2958
+ asset: this.props.asset,
2959
+ onChange: this.props.onChange,
2960
+ buttons: /* @__PURE__ */jsxRuntime.jsx(PlayerActionsMenu$1, {
2961
+ asset: this.props.asset,
2962
+ dialogState: this.props.dialogState,
2963
+ setDialogState: this.props.setDialogState,
2964
+ onChange: this.props.onChange,
2965
+ onUpload: this.onUpload,
2966
+ readOnly: this.props.readOnly
2967
+ })
2968
+ }) : /* @__PURE__ */jsxRuntime.jsx(UploadPlaceholder, {
2969
+ hovering: this.state.isDraggingOver,
2970
+ onSelect: this.onUpload,
2971
+ readOnly: this.props.readOnly,
2972
+ setDialogState: this.props.setDialogState,
2973
+ needsSetup: this.props.needsSetup
2974
+ })
2975
+ }), this.props.dialogState === "select-video" && /* @__PURE__ */jsxRuntime.jsx(InputBrowser, {
2976
+ asset: this.props.asset,
2977
+ onChange: this.props.onChange,
2978
+ setDialogState: this.props.setDialogState
2979
+ })]
2980
+ });
2981
+ }
2982
+ }
2983
+ const useSaveSecrets = (client, secrets) => {
2984
+ return React.useCallback(async _ref21 => {
2985
+ let {
2986
+ token,
2987
+ secretKey,
2988
+ enableSignedUrls
2989
+ } = _ref21;
2990
+ let {
2991
+ signingKeyId,
2992
+ signingKeyPrivate
2993
+ } = secrets;
2994
+ try {
2995
+ await saveSecrets(client, token, secretKey, enableSignedUrls, signingKeyId, signingKeyPrivate);
2996
+ const valid = await testSecrets(client);
2997
+ if (!(valid == null ? void 0 : valid.status) && token && secretKey) {
2998
+ throw new Error("Invalid secrets");
2999
+ }
3000
+ } catch (err) {
3001
+ console.error("Error while trying to save secrets:", err);
3002
+ throw err;
3003
+ }
3004
+ if (enableSignedUrls) {
3005
+ const hasValidSigningKeys = await haveValidSigningKeys(client, signingKeyId, signingKeyPrivate);
3006
+ if (!hasValidSigningKeys) {
3007
+ try {
3008
+ const {
3009
+ data
3010
+ } = await createSigningKeys(client);
3011
+ signingKeyId = data.id;
3012
+ signingKeyPrivate = data.private_key;
3013
+ await saveSecrets(client, token, secretKey, enableSignedUrls, signingKeyId, signingKeyPrivate);
3014
+ } catch (err) {
3015
+ console.log("Error while creating and saving signing key:", err == null ? void 0 : err.message);
3016
+ throw err;
3017
+ }
3018
+ }
3019
+ }
3020
+ return {
3021
+ token,
3022
+ secretKey,
3023
+ enableSignedUrls,
3024
+ signingKeyId,
3025
+ signingKeyPrivate
3026
+ };
3027
+ }, [client, secrets]);
3028
+ };
3029
+ function init(_ref22) {
3030
+ let {
3031
+ token,
3032
+ secretKey,
3033
+ enableSignedUrls
3034
+ } = _ref22;
3035
+ return {
3036
+ submitting: false,
3037
+ error: null,
3038
+ // Form inputs don't set the state back to null when clearing a field, but uses empty strings
3039
+ // This ensures the `dirty` check works correctly
3040
+ token: token != null ? token : "",
3041
+ secretKey: secretKey != null ? secretKey : "",
3042
+ enableSignedUrls: enableSignedUrls != null ? enableSignedUrls : false
3043
+ };
3044
+ }
3045
+ function reducer(state, action) {
3046
+ switch (action == null ? void 0 : action.type) {
3047
+ case "submit":
3048
+ return {
3049
+ ...state,
3050
+ submitting: true,
3051
+ error: null
3052
+ };
3053
+ case "error":
3054
+ return {
3055
+ ...state,
3056
+ submitting: false,
3057
+ error: action.payload
3058
+ };
3059
+ case "reset":
3060
+ return init(action.payload);
3061
+ case "change":
3062
+ return {
3063
+ ...state,
3064
+ [action.payload.name]: action.payload.value
3065
+ };
3066
+ default:
3067
+ throw new Error("Unknown action type: ".concat(action == null ? void 0 : action.type));
3068
+ }
3069
+ }
3070
+ const useSecretsFormState = secrets => React.useReducer(reducer, secrets, init);
3071
+ const ids = ["title", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r"];
3072
+ function MuxLogo(_ref23) {
3073
+ let {
3074
+ height = 26
3075
+ } = _ref23;
3076
+ const id = React.useId();
3077
+ const [titleId, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r] = React.useMemo(() => ids.map(field => "".concat(id, "-").concat(field)), [id]);
3078
+ return /* @__PURE__ */jsxRuntime.jsxs("svg", {
3079
+ "aria-labelledby": titleId,
3080
+ role: "img",
3081
+ xmlns: "http://www.w3.org/2000/svg",
3082
+ xmlSpace: "preserve",
3083
+ viewBox: "92.08878326416016 102.66712188720703 692.76123046875 219.99948120117188",
3084
+ style: {
3085
+ height: "".concat(height, "px")
3086
+ },
3087
+ children: [/* @__PURE__ */jsxRuntime.jsx("title", {
3088
+ id: titleId,
3089
+ children: "Mux Logo"
3090
+ }), /* @__PURE__ */jsxRuntime.jsxs("defs", {
3091
+ children: [/* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3092
+ id: c,
3093
+ spreadMethod: "pad",
3094
+ gradientTransform: "matrix(528.38055 0 0 -528.38055 63.801 159.5)",
3095
+ gradientUnits: "userSpaceOnUse",
3096
+ y2: 0,
3097
+ x2: 1,
3098
+ y1: 0,
3099
+ x1: 0,
3100
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3101
+ offset: 0,
3102
+ style: {
3103
+ stopOpacity: 1,
3104
+ stopColor: "#ff4e00"
3105
+ }
3106
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3107
+ offset: 1,
3108
+ style: {
3109
+ stopOpacity: 1,
3110
+ stopColor: "#ff1791"
3111
+ }
3112
+ })]
3113
+ }), /* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3114
+ id: d,
3115
+ spreadMethod: "pad",
3116
+ gradientTransform: "matrix(523.66766 0 0 -523.66766 67.897 159.5)",
3117
+ gradientUnits: "userSpaceOnUse",
3118
+ y2: 0,
3119
+ x2: 1,
3120
+ y1: 0,
3121
+ x1: 0,
3122
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3123
+ offset: 0,
3124
+ style: {
3125
+ stopOpacity: 1,
3126
+ stopColor: "#ff4e00"
3127
+ }
3128
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3129
+ offset: 1,
3130
+ style: {
3131
+ stopOpacity: 1,
3132
+ stopColor: "#ff1791"
3133
+ }
3134
+ })]
3135
+ }), /* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3136
+ id: g,
3137
+ spreadMethod: "pad",
3138
+ gradientTransform: "rotate(180 296.075 79.75) scale(524.84045)",
3139
+ gradientUnits: "userSpaceOnUse",
3140
+ y2: 0,
3141
+ x2: 1,
3142
+ y1: 0,
3143
+ x1: 0,
3144
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3145
+ offset: 0,
3146
+ style: {
3147
+ stopOpacity: 1,
3148
+ stopColor: "#ff4e00"
3149
+ }
3150
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3151
+ offset: 1,
3152
+ style: {
3153
+ stopOpacity: 1,
3154
+ stopColor: "#ff1791"
3155
+ }
3156
+ })]
3157
+ }), /* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3158
+ id: i,
3159
+ spreadMethod: "pad",
3160
+ gradientTransform: "matrix(524.84045 0 0 -524.84045 63.801 159.5)",
3161
+ gradientUnits: "userSpaceOnUse",
3162
+ y2: 0,
3163
+ x2: 1,
3164
+ y1: 0,
3165
+ x1: 0,
3166
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3167
+ offset: 0,
3168
+ style: {
3169
+ stopOpacity: 1,
3170
+ stopColor: "#ff4e00"
3171
+ }
3172
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3173
+ offset: 1,
3174
+ style: {
3175
+ stopOpacity: 1,
3176
+ stopColor: "#ff1791"
3177
+ }
3178
+ })]
3179
+ }), /* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3180
+ id: j,
3181
+ spreadMethod: "pad",
3182
+ gradientTransform: "matrix(523.08514 0 0 -523.08514 67.897 224.446)",
3183
+ gradientUnits: "userSpaceOnUse",
3184
+ y2: 0,
3185
+ x2: 1,
3186
+ y1: 0,
3187
+ x1: 0,
3188
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3189
+ offset: 0,
3190
+ style: {
3191
+ stopOpacity: 1,
3192
+ stopColor: "#ff4e00"
3193
+ }
3194
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3195
+ offset: 1,
3196
+ style: {
3197
+ stopOpacity: 1,
3198
+ stopColor: "#ff1791"
3199
+ }
3200
+ })]
3201
+ }), /* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3202
+ id: k,
3203
+ spreadMethod: "pad",
3204
+ gradientTransform: "matrix(524.84045 0 0 -524.84045 63.801 94.553)",
3205
+ gradientUnits: "userSpaceOnUse",
3206
+ y2: 0,
3207
+ x2: 1,
3208
+ y1: 0,
3209
+ x1: 0,
3210
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3211
+ offset: 0,
3212
+ style: {
3213
+ stopOpacity: 1,
3214
+ stopColor: "#ff4e00"
3215
+ }
3216
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3217
+ offset: 1,
3218
+ style: {
3219
+ stopOpacity: 1,
3220
+ stopColor: "#ff1791"
3221
+ }
3222
+ })]
3223
+ }), /* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3224
+ id: l,
3225
+ spreadMethod: "pad",
3226
+ gradientTransform: "matrix(524.84045 0 0 -524.84045 63.801 159.5)",
3227
+ gradientUnits: "userSpaceOnUse",
3228
+ y2: 0,
3229
+ x2: 1,
3230
+ y1: 0,
3231
+ x1: 0,
3232
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3233
+ offset: 0,
3234
+ style: {
3235
+ stopOpacity: 1,
3236
+ stopColor: "#ff4e00"
3237
+ }
3238
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3239
+ offset: 1,
3240
+ style: {
3241
+ stopOpacity: 1,
3242
+ stopColor: "#ff1791"
3243
+ }
3244
+ })]
3245
+ }), /* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3246
+ id: m,
3247
+ spreadMethod: "pad",
3248
+ gradientTransform: "matrix(524.84045 0 0 -524.84045 63.801 94.554)",
3249
+ gradientUnits: "userSpaceOnUse",
3250
+ y2: 0,
3251
+ x2: 1,
3252
+ y1: 0,
3253
+ x1: 0,
3254
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3255
+ offset: 0,
3256
+ style: {
3257
+ stopOpacity: 1,
3258
+ stopColor: "#ff4e00"
3259
+ }
3260
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3261
+ offset: 1,
3262
+ style: {
3263
+ stopOpacity: 1,
3264
+ stopColor: "#ff1791"
3265
+ }
3266
+ })]
3267
+ }), /* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3268
+ id: p,
3269
+ spreadMethod: "pad",
3270
+ gradientTransform: "matrix(521.97632 0 0 -521.97632 69.067 191.973)",
3271
+ gradientUnits: "userSpaceOnUse",
3272
+ y2: 0,
3273
+ x2: 1,
3274
+ y1: 0,
3275
+ x1: 0,
3276
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3277
+ offset: 0,
3278
+ style: {
3279
+ stopOpacity: 1,
3280
+ stopColor: "#ff4e00"
3281
+ }
3282
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3283
+ offset: 1,
3284
+ style: {
3285
+ stopOpacity: 1,
3286
+ stopColor: "#ff1791"
3287
+ }
3288
+ })]
3289
+ }), /* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3290
+ id: q,
3291
+ spreadMethod: "pad",
3292
+ gradientTransform: "matrix(523.09039 0 0 -523.09039 67.312 191.973)",
3293
+ gradientUnits: "userSpaceOnUse",
3294
+ y2: 0,
3295
+ x2: 1,
3296
+ y1: 0,
3297
+ x1: 0,
3298
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3299
+ offset: 0,
3300
+ style: {
3301
+ stopOpacity: 1,
3302
+ stopColor: "#ff4e00"
3303
+ }
3304
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3305
+ offset: 1,
3306
+ style: {
3307
+ stopOpacity: 1,
3308
+ stopColor: "#ff1791"
3309
+ }
3310
+ })]
3311
+ }), /* @__PURE__ */jsxRuntime.jsxs("linearGradient", {
3312
+ id: r,
3313
+ spreadMethod: "pad",
3314
+ gradientTransform: "matrix(524.84045 0 0 -524.84045 63.801 159.5)",
3315
+ gradientUnits: "userSpaceOnUse",
3316
+ y2: 0,
3317
+ x2: 1,
3318
+ y1: 0,
3319
+ x1: 0,
3320
+ children: [/* @__PURE__ */jsxRuntime.jsx("stop", {
3321
+ offset: 0,
3322
+ style: {
3323
+ stopOpacity: 1,
3324
+ stopColor: "#ff4e00"
3325
+ }
3326
+ }), /* @__PURE__ */jsxRuntime.jsx("stop", {
3327
+ offset: 1,
3328
+ style: {
3329
+ stopOpacity: 1,
3330
+ stopColor: "#ff1791"
3331
+ }
3332
+ })]
3333
+ }), /* @__PURE__ */jsxRuntime.jsx("clipPath", {
3334
+ id: a,
3335
+ clipPathUnits: "userSpaceOnUse",
3336
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3337
+ d: "M0 319h657.706V0H0Z"
3338
+ })
3339
+ }), /* @__PURE__ */jsxRuntime.jsx("clipPath", {
3340
+ id: b,
3341
+ clipPathUnits: "userSpaceOnUse",
3342
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3343
+ d: "M423.64 242h164.999V77H423.64Z"
3344
+ })
3345
+ }), /* @__PURE__ */jsxRuntime.jsx("clipPath", {
3346
+ id: e,
3347
+ clipPathUnits: "userSpaceOnUse",
3348
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3349
+ d: "M0 319h657.706V0H0Z"
3350
+ })
3351
+ }), /* @__PURE__ */jsxRuntime.jsx("clipPath", {
3352
+ id: f,
3353
+ clipPathUnits: "userSpaceOnUse",
3354
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3355
+ d: "M311.3 242h93.031V77H311.3Z"
3356
+ })
3357
+ }), /* @__PURE__ */jsxRuntime.jsx("clipPath", {
3358
+ id: h,
3359
+ clipPathUnits: "userSpaceOnUse",
3360
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3361
+ d: "M198.96 242h35.106V77H198.96Z"
3362
+ })
3363
+ }), /* @__PURE__ */jsxRuntime.jsx("clipPath", {
3364
+ id: n,
3365
+ clipPathUnits: "userSpaceOnUse",
3366
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3367
+ d: "M0 319h657.706V0H0Z"
3368
+ })
3369
+ }), /* @__PURE__ */jsxRuntime.jsx("clipPath", {
3370
+ id: o,
3371
+ clipPathUnits: "userSpaceOnUse",
3372
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3373
+ d: "M69.067 242H169.12V141.947H69.067Z"
3374
+ })
3375
+ })]
3376
+ }), /* @__PURE__ */jsxRuntime.jsx("g", {
3377
+ clipPath: "url(#".concat(a, ")"),
3378
+ transform: "matrix(1.33333 0 0 -1.33333 0 425.333)",
3379
+ children: /* @__PURE__ */jsxRuntime.jsx("g", {
3380
+ style: {
3381
+ opacity: 0.69999701
3382
+ },
3383
+ clipPath: "url(#".concat(b, ")"),
3384
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3385
+ style: {
3386
+ fill: "url(#".concat(c, ")"),
3387
+ stroke: "none"
3388
+ },
3389
+ d: "M558.674 82.142c6.855-6.855 17.969-6.855 24.824 0 6.854 6.855 6.854 17.969 0 24.823L453.605 236.858c-6.855 6.855-17.969 6.855-24.824 0s-6.855-17.969 0-24.823z"
3390
+ })
3391
+ })
3392
+ }), /* @__PURE__ */jsxRuntime.jsx("path", {
3393
+ style: {
3394
+ fill: "url(#".concat(d, ")"),
3395
+ stroke: "none"
3396
+ },
3397
+ d: "M558.674 236.858 428.781 106.966c-6.855-6.855-6.855-17.969 0-24.825 6.855-6.854 17.969-6.854 24.823 0l129.894 129.894c6.854 6.855 6.854 17.968 0 24.823A17.498 17.498 0 0 1 571.086 242a17.495 17.495 0 0 1-12.412-5.142",
3398
+ transform: "matrix(1.33333 0 0 -1.33333 0 425.333)"
3399
+ }), /* @__PURE__ */jsxRuntime.jsxs("g", {
3400
+ clipPath: "url(#".concat(e, ")"),
3401
+ transform: "matrix(1.33333 0 0 -1.33333 0 425.333)",
3402
+ children: [/* @__PURE__ */jsxRuntime.jsx("g", {
3403
+ style: {
3404
+ opacity: 0.69999701
3405
+ },
3406
+ clipPath: "url(#".concat(f, ")"),
3407
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3408
+ style: {
3409
+ fill: "url(#".concat(g, ")"),
3410
+ stroke: "none"
3411
+ },
3412
+ d: "M328.853 112.107c22.297 0 40.372 18.075 40.372 40.372v71.315c0 10.054 7.505 18.206 17.554 18.206 10.048 0 17.552-8.152 17.552-18.206v-71.315c0-41.686-33.793-75.479-75.478-75.479-9.694 0-17.553 7.859-17.553 17.554 0 9.694 7.859 17.553 17.553 17.553"
3413
+ })
3414
+ }), /* @__PURE__ */jsxRuntime.jsx("g", {
3415
+ style: {
3416
+ opacity: 0.69999701
3417
+ },
3418
+ clipPath: "url(#".concat(h, ")"),
3419
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3420
+ style: {
3421
+ fill: "url(#".concat(i, ")"),
3422
+ stroke: "none"
3423
+ },
3424
+ d: "M216.513 242c-10.049 0-17.553-8.152-17.553-18.206V95.206c0-10.054 7.504-18.206 17.553-18.206 10.048 0 17.553 8.152 17.553 18.206v128.588c0 10.054-7.505 18.206-17.553 18.206"
3425
+ })
3426
+ })]
3427
+ }), /* @__PURE__ */jsxRuntime.jsx("path", {
3428
+ style: {
3429
+ fill: "url(#".concat(j, ")"),
3430
+ stroke: "none"
3431
+ },
3432
+ d: "M369.225 224.447c0-9.694 7.859-17.553 17.553-17.553 9.695 0 17.553 7.859 17.553 17.553s-7.858 17.552-17.553 17.552c-9.694 0-17.553-7.858-17.553-17.552",
3433
+ transform: "matrix(1.33333 0 0 -1.33333 0 425.333)"
3434
+ }), /* @__PURE__ */jsxRuntime.jsx("path", {
3435
+ style: {
3436
+ fill: "url(#".concat(k, ")"),
3437
+ stroke: "none"
3438
+ },
3439
+ d: "M553.532 94.554c0-9.695 7.859-17.554 17.553-17.554 9.695 0 17.554 7.859 17.554 17.554 0 9.694-7.859 17.552-17.554 17.552-9.694 0-17.553-7.858-17.553-17.552",
3440
+ transform: "matrix(1.33333 0 0 -1.33333 0 425.333)"
3441
+ }), /* @__PURE__ */jsxRuntime.jsx("path", {
3442
+ style: {
3443
+ fill: "url(#".concat(l, ")"),
3444
+ stroke: "none"
3445
+ },
3446
+ d: "M69.067 223.794V95.206C69.067 85.152 76.571 77 86.62 77c10.048 0 17.553 8.152 17.553 18.206v128.588c0 10.055-7.505 18.205-17.553 18.205-10.049 0-17.553-8.15-17.553-18.205",
3447
+ transform: "matrix(1.33333 0 0 -1.33333 0 425.333)"
3448
+ }), /* @__PURE__ */jsxRuntime.jsx("path", {
3449
+ style: {
3450
+ fill: "url(#".concat(m, ")"),
3451
+ stroke: "none"
3452
+ },
3453
+ d: "M198.96 94.554c0-9.695 7.859-17.554 17.553-17.554 9.695 0 17.554 7.859 17.554 17.554 0 9.694-7.859 17.553-17.554 17.553-9.694 0-17.553-7.859-17.553-17.553",
3454
+ transform: "matrix(1.33333 0 0 -1.33333 0 425.333)"
3455
+ }), /* @__PURE__ */jsxRuntime.jsx("g", {
3456
+ clipPath: "url(#".concat(n, ")"),
3457
+ transform: "matrix(1.33333 0 0 -1.33333 0 425.333)",
3458
+ children: /* @__PURE__ */jsxRuntime.jsx("g", {
3459
+ style: {
3460
+ opacity: 0.69999701
3461
+ },
3462
+ clipPath: "url(#".concat(o, ")"),
3463
+ children: /* @__PURE__ */jsxRuntime.jsx("path", {
3464
+ style: {
3465
+ fill: "url(#".concat(p, ")"),
3466
+ stroke: "none"
3467
+ },
3468
+ d: "M139.155 147.088c6.855-6.855 17.969-6.855 24.824 0s6.855 17.969 0 24.824l-64.947 64.946c-6.855 6.855-17.969 6.855-24.824 0s-6.855-17.969 0-24.823z"
3469
+ })
3470
+ })
3471
+ }), /* @__PURE__ */jsxRuntime.jsx("path", {
3472
+ style: {
3473
+ fill: "url(#".concat(q, ")"),
3474
+ stroke: "none"
3475
+ },
3476
+ d: "m204.101 236.858-64.947-64.946c-6.854-6.855-6.854-17.969 0-24.824 6.856-6.855 17.97-6.855 24.824 0l64.947 64.947c6.855 6.855 6.855 17.968 0 24.823A17.495 17.495 0 0 1 216.513 242a17.498 17.498 0 0 1-12.412-5.142",
3477
+ transform: "matrix(1.33333 0 0 -1.33333 0 425.333)"
3478
+ }), /* @__PURE__ */jsxRuntime.jsx("path", {
3479
+ style: {
3480
+ fill: "url(#".concat(r, ")"),
3481
+ stroke: "none"
3482
+ },
3483
+ d: "M253.374 223.794v-71.315c0-41.685 33.793-75.479 75.479-75.479 9.695 0 17.553 7.859 17.553 17.554 0 9.694-7.858 17.553-17.553 17.553-22.297 0-40.372 18.075-40.372 40.372v71.315c0 10.055-7.505 18.205-17.554 18.205s-17.553-8.15-17.553-18.205",
3484
+ transform: "matrix(1.33333 0 0 -1.33333 0 425.333)"
3485
+ })]
3486
+ });
3487
+ }
3488
+ var __freeze = Object.freeze;
3489
+ var __defProp = Object.defineProperty;
3490
+ var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", {
3491
+ value: __freeze(raw || cooked.slice())
3492
+ }));
3493
+ var _a;
3494
+ const Logo = styled__default.default.span(_a || (_a = __template(["\n display: inline-block;\n height: 0.8em;\n margin-right: 1em;\n transform: translate(0.3em, -0.2em);\n"])));
3495
+ const Header = () => /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
3496
+ children: [/* @__PURE__ */jsxRuntime.jsx(Logo, {
3497
+ children: /* @__PURE__ */jsxRuntime.jsx(MuxLogo, {
3498
+ height: 13
3499
+ })
3500
+ }), "API Credentials"]
3501
+ });
3502
+ const fieldNames = ["token", "secretKey", "enableSignedUrls"];
3503
+ function ConfigureApi(_ref24) {
3504
+ let {
3505
+ secrets,
3506
+ setDialogState
3507
+ } = _ref24;
3508
+ var _a, _b;
3509
+ const client = useClient();
3510
+ const [state, dispatch] = useSecretsFormState(secrets);
3511
+ const hasSecretsInitially = React.useMemo(() => secrets.token && secrets.secretKey, [secrets]);
3512
+ const handleClose = React.useCallback(() => setDialogState(false), [setDialogState]);
3513
+ const dirty = React.useMemo(() => secrets.token !== state.token || secrets.secretKey !== state.secretKey || secrets.enableSignedUrls !== state.enableSignedUrls, [secrets, state]);
3514
+ const id = "ConfigureApi".concat(React.useId());
3515
+ const [tokenId, secretKeyId, enableSignedUrlsId] = React.useMemo(() => fieldNames.map(field => "".concat(id, "-").concat(field)), [id]);
3516
+ const firstField = React.useRef(null);
3517
+ const handleSaveSecrets = useSaveSecrets(client, secrets);
3518
+ const saving = React.useRef(false);
3519
+ const handleSubmit = React.useCallback(event => {
3520
+ event.preventDefault();
3521
+ if (!saving.current && event.currentTarget.reportValidity()) {
3522
+ saving.current = true;
3523
+ dispatch({
3524
+ type: "submit"
3525
+ });
3526
+ const {
3527
+ token,
3528
+ secretKey,
3529
+ enableSignedUrls
3530
+ } = state;
3531
+ handleSaveSecrets({
3532
+ token,
3533
+ secretKey,
3534
+ enableSignedUrls
3535
+ }).then(savedSecrets => {
3536
+ const {
3537
+ projectId,
3538
+ dataset
3539
+ } = client.config();
3540
+ suspendReact.clear([cacheNs, _id, projectId, dataset]);
3541
+ suspendReact.preload(() => Promise.resolve(savedSecrets), [cacheNs, _id, projectId, dataset]);
3542
+ setDialogState(false);
3543
+ }).catch(err => dispatch({
3544
+ type: "error",
3545
+ payload: err.message
3546
+ })).finally(() => {
3547
+ saving.current = false;
3548
+ });
3549
+ }
3550
+ }, [client, dispatch, handleSaveSecrets, setDialogState, state]);
3551
+ const handleChangeToken = React.useCallback(event => {
3552
+ dispatch({
3553
+ type: "change",
3554
+ payload: {
3555
+ name: "token",
3556
+ value: event.currentTarget.value
3557
+ }
3558
+ });
3559
+ }, [dispatch]);
3560
+ const handleChangeSecretKey = React.useCallback(event => {
3561
+ dispatch({
3562
+ type: "change",
3563
+ payload: {
3564
+ name: "secretKey",
3565
+ value: event.currentTarget.value
3566
+ }
3567
+ });
3568
+ }, [dispatch]);
3569
+ const handleChangeEnableSignedUrls = React.useCallback(event => {
3570
+ dispatch({
3571
+ type: "change",
3572
+ payload: {
3573
+ name: "enableSignedUrls",
3574
+ value: event.currentTarget.checked
3575
+ }
3576
+ });
3577
+ }, [dispatch]);
3578
+ React.useEffect(() => {
3579
+ if (firstField.current) {
3580
+ firstField.current.focus();
3581
+ }
3582
+ }, [firstField]);
3583
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Dialog, {
3584
+ id,
3585
+ onClose: handleClose,
3586
+ header: /* @__PURE__ */jsxRuntime.jsx(Header, {}),
3587
+ width: 1,
3588
+ style: {
3589
+ maxWidth: "550px"
3590
+ },
3591
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
3592
+ padding: 4,
3593
+ style: {
3594
+ position: "relative"
3595
+ },
3596
+ children: /* @__PURE__ */jsxRuntime.jsx("form", {
3597
+ onSubmit: handleSubmit,
3598
+ noValidate: true,
3599
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
3600
+ space: 4,
3601
+ children: [!hasSecretsInitially && /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
3602
+ padding: [3, 3, 3],
3603
+ radius: 2,
3604
+ shadow: 1,
3605
+ tone: "primary",
3606
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
3607
+ space: 3,
3608
+ children: [/* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
3609
+ size: 1,
3610
+ children: ["To set up a new access token, go to your", " ", /* @__PURE__ */jsxRuntime.jsx("a", {
3611
+ href: "https://dashboard.mux.com/settings/access-tokens",
3612
+ target: "_blank",
3613
+ rel: "noreferrer noopener",
3614
+ children: "account on mux.com"
3615
+ }), "."]
3616
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
3617
+ size: 1,
3618
+ children: ["The access token needs permissions: ", /* @__PURE__ */jsxRuntime.jsx("strong", {
3619
+ children: "Mux Video "
3620
+ }), "(Full Access) and ", /* @__PURE__ */jsxRuntime.jsx("strong", {
3621
+ children: "Mux Data"
3622
+ }), " (Read)", /* @__PURE__ */jsxRuntime.jsx("br", {}), "The credentials will be stored safely in a hidden document only available to editors."]
3623
+ })]
3624
+ })
3625
+ }), /* @__PURE__ */jsxRuntime.jsx(FormField$1, {
3626
+ title: "Access Token",
3627
+ inputId: tokenId,
3628
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.TextInput, {
3629
+ id: tokenId,
3630
+ ref: firstField,
3631
+ onChange: handleChangeToken,
3632
+ type: "text",
3633
+ value: (_a = state.token) != null ? _a : "",
3634
+ required: !!state.secretKey || state.enableSignedUrls
3635
+ })
3636
+ }), /* @__PURE__ */jsxRuntime.jsx(FormField$1, {
3637
+ title: "Secret Key",
3638
+ inputId: secretKeyId,
3639
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.TextInput, {
3640
+ id: secretKeyId,
3641
+ onChange: handleChangeSecretKey,
3642
+ type: "text",
3643
+ value: (_b = state.secretKey) != null ? _b : "",
3644
+ required: !!state.token || state.enableSignedUrls
3645
+ })
3646
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
3647
+ space: 4,
3648
+ children: [/* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
3649
+ align: "center",
3650
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Checkbox, {
3651
+ id: enableSignedUrlsId,
3652
+ onChange: handleChangeEnableSignedUrls,
3653
+ checked: state.enableSignedUrls,
3654
+ style: {
3655
+ display: "block"
3656
+ }
3657
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
3658
+ flex: 1,
3659
+ paddingLeft: 3,
3660
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
3661
+ children: /* @__PURE__ */jsxRuntime.jsx("label", {
3662
+ htmlFor: enableSignedUrlsId,
3663
+ children: "Enable Signed Urls"
3664
+ })
3665
+ })
3666
+ })]
3667
+ }), secrets.signingKeyId && state.enableSignedUrls ? /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
3668
+ padding: [3, 3, 3],
3669
+ radius: 2,
3670
+ shadow: 1,
3671
+ tone: "caution",
3672
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
3673
+ space: 3,
3674
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Text, {
3675
+ size: 1,
3676
+ children: "The signing key ID that Sanity will use is:"
3677
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Code, {
3678
+ size: 1,
3679
+ children: secrets.signingKeyId
3680
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
3681
+ size: 1,
3682
+ children: ["This key is only used for previewing content in the Sanity UI.", /* @__PURE__ */jsxRuntime.jsx("br", {}), "You should generate a different key to use in your application server."]
3683
+ })]
3684
+ })
3685
+ }) : null]
3686
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Inline, {
3687
+ space: 2,
3688
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Button, {
3689
+ text: "Save",
3690
+ disabled: !dirty,
3691
+ loading: state.submitting,
3692
+ tone: "primary",
3693
+ mode: "default",
3694
+ type: "submit"
3695
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
3696
+ disabled: state.submitting,
3697
+ text: "Cancel",
3698
+ mode: "bleed",
3699
+ onClick: handleClose
3700
+ })]
3701
+ }), state.error && /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
3702
+ padding: [3, 3, 3],
3703
+ radius: 2,
3704
+ shadow: 1,
3705
+ tone: "critical",
3706
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
3707
+ children: state.error
3708
+ })
3709
+ })]
3710
+ })
3711
+ })
3712
+ })
3713
+ });
3714
+ }
3715
+ var ConfigureApi$1 = React.memo(ConfigureApi);
3716
+ function ErrorBoundaryCard(props) {
3717
+ const {
3718
+ children,
3719
+ schemaType
3720
+ } = props;
3721
+ const {
3722
+ push: pushToast
3723
+ } = ui.useToast();
3724
+ const errorRef = React.useRef(null);
3725
+ const {
3726
+ ErrorBoundary,
3727
+ didCatch,
3728
+ error,
3729
+ reset
3730
+ } = useErrorBoundary.useErrorBoundary({
3731
+ onDidCatch: (err, errorInfo) => {
3732
+ console.group(err.toString());
3733
+ console.groupCollapsed("console.error");
3734
+ console.error(err);
3735
+ console.groupEnd();
3736
+ if (err.stack) {
3737
+ console.groupCollapsed("error.stack");
3738
+ console.log(err.stack);
3739
+ console.groupEnd();
3740
+ }
3741
+ if (errorInfo == null ? void 0 : errorInfo.componentStack) {
3742
+ console.groupCollapsed("errorInfo.componentStack");
3743
+ console.log(errorInfo.componentStack);
3744
+ console.groupEnd();
3745
+ }
3746
+ console.groupEnd();
3747
+ pushToast({
3748
+ status: "error",
3749
+ title: "Plugin crashed",
3750
+ description: /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
3751
+ align: "center",
3752
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Inline, {
3753
+ space: 1,
3754
+ children: ["An error happened while rendering", /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
3755
+ padding: 1,
3756
+ fontSize: 1,
3757
+ style: {
3758
+ transform: "translateY(1px)"
3759
+ },
3760
+ mode: "ghost",
3761
+ text: schemaType.title,
3762
+ onClick: () => {
3763
+ if (errorRef.current) {
3764
+ scrollIntoView__default.default(errorRef.current, {
3765
+ behavior: "smooth",
3766
+ scrollMode: "if-needed",
3767
+ block: "center"
3768
+ });
3769
+ }
3770
+ }
3771
+ })]
3772
+ })
3773
+ })
3774
+ });
3775
+ }
3776
+ });
3777
+ const handleRetry = React.useCallback(() => {
3778
+ suspendReact.clear([name$1]);
3779
+ reset();
3780
+ }, [reset]);
3781
+ if (didCatch) {
3782
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
3783
+ ref: errorRef,
3784
+ paddingX: [2, 3, 4, 4],
3785
+ height: "fill",
3786
+ shadow: 1,
3787
+ overflow: "auto",
3788
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
3789
+ justify: "flex-start",
3790
+ align: "center",
3791
+ height: "fill",
3792
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Grid, {
3793
+ columns: 1,
3794
+ gap: [2, 3, 4, 4],
3795
+ children: [/* @__PURE__ */jsxRuntime.jsxs(ui.Heading, {
3796
+ as: "h1",
3797
+ children: ["The ", /* @__PURE__ */jsxRuntime.jsx("code", {
3798
+ children: name$1
3799
+ }), " plugin crashed"]
3800
+ }), (error == null ? void 0 : error.message) && /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
3801
+ padding: 3,
3802
+ tone: "critical",
3803
+ shadow: 1,
3804
+ radius: 2,
3805
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
3806
+ children: error.message
3807
+ })
3808
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Inline, {
3809
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
3810
+ onClick: handleRetry,
3811
+ text: "Retry"
3812
+ })
3813
+ })]
3814
+ })
3815
+ })
3816
+ });
3817
+ }
3818
+ return /* @__PURE__ */jsxRuntime.jsx(ErrorBoundary, {
3819
+ children
3820
+ });
3821
+ }
3822
+ var ErrorBoundaryCard$1 = React.memo(ErrorBoundaryCard);
3823
+ const InputFallback = () => {
3824
+ return /* @__PURE__ */jsxRuntime.jsx("div", {
3825
+ style: {
3826
+ padding: 1
3827
+ },
3828
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
3829
+ shadow: 1,
3830
+ sizing: "border",
3831
+ style: {
3832
+ aspectRatio: "16/9",
3833
+ width: "100%",
3834
+ borderRadius: "1px"
3835
+ },
3836
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
3837
+ align: "center",
3838
+ direction: "column",
3839
+ height: "fill",
3840
+ justify: "center",
3841
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {
3842
+ muted: true
3843
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
3844
+ marginTop: 3,
3845
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
3846
+ align: "center",
3847
+ muted: true,
3848
+ size: 1,
3849
+ children: "Loading\u2026"
3850
+ })
3851
+ })]
3852
+ })
3853
+ })
3854
+ });
3855
+ };
3856
+ function Onboard(props) {
3857
+ const {
3858
+ setDialogState
3859
+ } = props;
3860
+ const handleOpen = React.useCallback(() => setDialogState("secrets"), [setDialogState]);
3861
+ return /* @__PURE__ */jsxRuntime.jsx(jsxRuntime.Fragment, {
3862
+ children: /* @__PURE__ */jsxRuntime.jsx("div", {
3863
+ style: {
3864
+ padding: 2
3865
+ },
3866
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
3867
+ display: "flex",
3868
+ sizing: "border",
3869
+ style: {
3870
+ aspectRatio: "16/9",
3871
+ width: "100%",
3872
+ boxShadow: "var(--card-bg-color) 0 0 0 2px"
3873
+ },
3874
+ paddingX: [2, 3, 4, 4],
3875
+ radius: 1,
3876
+ tone: "transparent",
3877
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
3878
+ justify: "flex-start",
3879
+ align: "center",
3880
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Grid, {
3881
+ columns: 1,
3882
+ gap: [2, 3, 4, 4],
3883
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Inline, {
3884
+ paddingY: 1,
3885
+ children: /* @__PURE__ */jsxRuntime.jsx("div", {
3886
+ style: {
3887
+ height: "32px"
3888
+ },
3889
+ children: /* @__PURE__ */jsxRuntime.jsx(MuxLogo, {})
3890
+ })
3891
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Inline, {
3892
+ paddingY: 1,
3893
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Heading, {
3894
+ size: [0, 1, 2, 2],
3895
+ children: "Upload and preview videos directly from your studio."
3896
+ })
3897
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Inline, {
3898
+ paddingY: 1,
3899
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
3900
+ mode: "ghost",
3901
+ icon: icons.PlugIcon,
3902
+ text: "Configure API",
3903
+ onClick: handleOpen
3904
+ })
3905
+ })]
3906
+ })
3907
+ })
3908
+ })
3909
+ })
3910
+ });
3911
+ }
3912
+ const Input = props => {
3913
+ var _a;
3914
+ const client = useClient();
3915
+ const secretDocumentValues = useSecretsDocumentValues();
3916
+ const assetDocumentValues = useAssetDocumentValues((_a = props.value) == null ? void 0 : _a.asset);
3917
+ const poll = useMuxPolling(props.readOnly ? void 0 : (assetDocumentValues == null ? void 0 : assetDocumentValues.value) || void 0);
3918
+ const [dialogState, setDialogState] = useDialogState();
3919
+ const error = secretDocumentValues.error || assetDocumentValues.error || poll.error;
3920
+ if (error) {
3921
+ throw error;
3922
+ }
3923
+ const isLoading = secretDocumentValues.isLoading || assetDocumentValues.isLoading;
3924
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
3925
+ children: /* @__PURE__ */jsxRuntime.jsx(ErrorBoundaryCard$1, {
3926
+ schemaType: props.schemaType,
3927
+ children: /* @__PURE__ */jsxRuntime.jsx(React.Suspense, {
3928
+ fallback: /* @__PURE__ */jsxRuntime.jsx(InputFallback, {}),
3929
+ children: isLoading ? /* @__PURE__ */jsxRuntime.jsx(InputFallback, {}) : /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
3930
+ children: [secretDocumentValues.value.needsSetup && !assetDocumentValues.value ? /* @__PURE__ */jsxRuntime.jsx(Onboard, {
3931
+ setDialogState
3932
+ }) : /* @__PURE__ */jsxRuntime.jsx(MuxVideoInputUploader, {
3933
+ ...props,
3934
+ config: props.config,
3935
+ onChange: props.onChange,
3936
+ client,
3937
+ secrets: secretDocumentValues.value.secrets,
3938
+ asset: assetDocumentValues.value,
3939
+ dialogState,
3940
+ setDialogState,
3941
+ needsSetup: secretDocumentValues.value.needsSetup
3942
+ }), dialogState === "secrets" && /* @__PURE__ */jsxRuntime.jsx(ConfigureApi$1, {
3943
+ setDialogState,
3944
+ secrets: secretDocumentValues.value.secrets
3945
+ })]
3946
+ })
3947
+ })
3948
+ })
3949
+ });
3950
+ };
3951
+ var Input$1 = React.memo(Input);
3952
+ function muxVideoCustomRendering(config) {
3953
+ return {
3954
+ components: {
3955
+ input: props => /* @__PURE__ */jsxRuntime.jsx(Input$1, {
3956
+ config,
3957
+ ...props
3958
+ })
3959
+ },
3960
+ preview: {
3961
+ select: {
3962
+ filename: "asset.filename",
3963
+ playbackId: "asset.playbackId",
3964
+ status: "asset.status",
3965
+ assetId: "asset.assetId",
3966
+ thumbTime: "asset.thumbTime",
3967
+ data: "asset.data"
3968
+ },
3969
+ prepare: asset => {
3970
+ const {
3971
+ filename,
3972
+ playbackId,
3973
+ status
3974
+ } = asset;
3975
+ return {
3976
+ title: filename || playbackId || "",
3977
+ subtitle: status ? "status: ".concat(status) : null,
3978
+ media: asset.playbackId ? /* @__PURE__ */jsxRuntime.jsx(VideoThumbnail, {
3979
+ asset,
3980
+ width: 64
3981
+ }) : null
3982
+ };
3983
+ }
3984
+ }
3985
+ };
3986
+ }
3987
+ const muxVideo = {
3988
+ name: "mux.video",
3989
+ type: "object",
3990
+ title: "Video asset reference",
3991
+ fields: [{
3992
+ title: "Video",
3993
+ name: "asset",
3994
+ type: "reference",
3995
+ weak: true,
3996
+ to: [{
3997
+ type: "mux.videoAsset"
3998
+ }]
3999
+ }]
4000
+ };
4001
+ const muxVideoAsset = {
4002
+ name: "mux.videoAsset",
4003
+ type: "object",
4004
+ title: "Video asset",
4005
+ fields: [{
4006
+ type: "string",
4007
+ name: "status"
4008
+ }, {
4009
+ type: "string",
4010
+ name: "assetId"
4011
+ }, {
4012
+ type: "string",
4013
+ name: "playbackId"
4014
+ }, {
4015
+ type: "string",
4016
+ name: "filename"
4017
+ }, {
4018
+ type: "number",
4019
+ name: "thumbTime"
4020
+ }]
4021
+ };
4022
+ const defaultConfig = {
4023
+ mp4_support: "none"
4024
+ };
4025
+ const muxInput = sanity.definePlugin(userConfig => {
4026
+ const config = {
4027
+ ...defaultConfig,
4028
+ ...userConfig
4029
+ };
4030
+ return {
4031
+ name: "mux-input",
4032
+ schema: {
4033
+ types: [muxVideoAsset, {
4034
+ ...muxVideo,
4035
+ ...muxVideoCustomRendering(config)
4036
+ }]
4037
+ },
4038
+ tools: config.tool === false ? void 0 : [createStudioTool(config)]
4039
+ };
4040
+ });
4041
+ exports.defaultConfig = defaultConfig;
4042
+ exports.muxInput = muxInput;
10
4043
  //# sourceMappingURL=index.cjs.map