sanity-plugin-mux-input 2.1.1 → 2.2.1

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