sanity-plugin-r2-video 0.1.9 → 0.1.11

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 (2) hide show
  1. package/dist/studio/index.js +278 -60
  2. package/package.json +1 -1
@@ -1,19 +1,23 @@
1
1
  import { resolveRenditionPath } from '../chunk-D5VS4ED7.js';
2
2
  export { resolveRenditionPath } from '../chunk-D5VS4ED7.js';
3
- import { createContext, useState, useCallback, useEffect, useRef, useMemo, useId, useContext } from 'react';
3
+ import { createContext, useState, useCallback, useEffect, Fragment, useRef, useMemo, useId, useContext } from 'react';
4
4
  import { defineType, defineField, definePlugin, set, useClient } from 'sanity';
5
5
  import { jsx, jsxs } from 'react/jsx-runtime';
6
6
  import { PlayIcon } from '@sanity/icons/Play';
7
7
  import { UploadIcon } from '@sanity/icons/Upload';
8
- import { Stack, Flex, Box, Button, TextInput, Card, Text, Grid, Dialog, Spinner, Select, Switch } from '@sanity/ui';
8
+ import { Box, Stack, Flex, Button, TextInput, Card, Text, Select, Grid, Checkbox, Dialog, Spinner, Switch } from '@sanity/ui';
9
9
  import { AccessDeniedIcon } from '@sanity/icons/AccessDenied';
10
10
  import { canEncodeVideo } from 'mediabunny';
11
11
  import { WarningOutlineIcon } from '@sanity/icons/WarningOutline';
12
12
  import { ChevronDownIcon } from '@sanity/icons/ChevronDown';
13
13
  import { ChevronRightIcon } from '@sanity/icons/ChevronRight';
14
+ import { CheckmarkIcon } from '@sanity/icons/Checkmark';
15
+ import { FilterIcon } from '@sanity/icons/Filter';
14
16
  import { SearchIcon } from '@sanity/icons/Search';
15
17
  import { SyncIcon } from '@sanity/icons/Sync';
16
18
  import { TrashIcon } from '@sanity/icons/Trash';
19
+ import { MenuButton, Menu, MenuDivider, MenuItem } from '@sanity/ui/menu';
20
+ import styled from 'styled-components';
17
21
  import { FolderIcon } from '@sanity/icons/Folder';
18
22
 
19
23
  // studio/client.ts
@@ -1324,32 +1328,43 @@ var SCHEMA_R2_VIDEO = defineType({
1324
1328
  }
1325
1329
  }
1326
1330
  });
1327
- var DialogDelete = ({ asset, onDeleted, onClose }) => {
1331
+ var DialogDelete = ({ assets, onDeleted, onClose }) => {
1328
1332
  const { config, client } = useR2VideoClient();
1329
- const [blockers, setBlockers] = useState(null);
1333
+ const [blocked, setBlocked] = useState(null);
1330
1334
  const [isDeleting, setIsDeleting] = useState(false);
1331
1335
  const [error, setError] = useState(null);
1332
1336
  useEffect(() => {
1333
- findReferencingDocuments(client, asset._id).then(setBlockers).catch(() => {
1334
- setError("Could not check which documents use this video.");
1337
+ Promise.all(
1338
+ assets.map(async (asset) => ({
1339
+ asset,
1340
+ documents: await findReferencingDocuments(client, asset._id)
1341
+ }))
1342
+ ).then((checked) => {
1343
+ setBlocked(checked.filter((entry) => entry.documents.length > 0));
1344
+ }).catch(() => {
1345
+ setError("Could not check which documents use these videos.");
1335
1346
  });
1336
- }, [client, asset._id]);
1347
+ }, [client, assets]);
1337
1348
  const confirmed = async () => {
1338
1349
  setIsDeleting(true);
1339
1350
  setError(null);
1340
1351
  try {
1341
- await deleteVideoAsset(client, config, asset);
1352
+ for (const asset of assets) {
1353
+ await deleteVideoAsset(client, config, asset);
1354
+ }
1342
1355
  onDeleted();
1343
1356
  } catch (caught) {
1344
1357
  setError(toMessage(caught));
1345
1358
  setIsDeleting(false);
1346
1359
  }
1347
1360
  };
1348
- const isBlocked = blockers !== null && blockers.length > 0;
1361
+ const isBlocked = blocked !== null && blocked.length > 0;
1362
+ const renditions = assets.flatMap((asset) => asset.renditions);
1363
+ const isOne = assets.length === 1;
1349
1364
  return /* @__PURE__ */ jsx(
1350
1365
  Dialog,
1351
1366
  {
1352
- header: "Delete video",
1367
+ header: isOne ? "Delete video" : `Delete ${assets.length} videos`,
1353
1368
  id: "r2-video-delete",
1354
1369
  width: 1,
1355
1370
  onClose: isDeleting ? void 0 : onClose,
@@ -1360,32 +1375,42 @@ var DialogDelete = ({ asset, onDeleted, onClose }) => {
1360
1375
  confirm: {
1361
1376
  text: isDeleting ? "Deleting\u2026" : "Delete",
1362
1377
  tone: "critical",
1363
- disabled: isDeleting || isBlocked || blockers === null,
1378
+ disabled: isDeleting || isBlocked || blocked === null,
1364
1379
  onClick: confirmed
1365
1380
  }
1366
1381
  }
1367
1382
  ),
1368
1383
  children: /* @__PURE__ */ jsx(Card, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
1369
1384
  /* @__PURE__ */ jsxs(Text, { size: 1, children: [
1370
- asset.filename,
1371
- " - ",
1372
- asset.renditions.length,
1373
- " renditions,",
1385
+ isOne ? assets[0].filename : pluralize(assets.length, "video"),
1386
+ " -",
1387
+ " ",
1388
+ pluralize(renditions.length, "rendition"),
1389
+ ",",
1390
+ " ",
1391
+ formatSize(totalSize(renditions)),
1392
+ ", plus",
1374
1393
  " ",
1375
- formatSize(totalSize(asset.renditions)),
1376
- ", plus its poster."
1394
+ isOne ? "its poster" : "their posters",
1395
+ "."
1377
1396
  ] }),
1378
- blockers === null && !error && /* @__PURE__ */ jsx(Loading, { children: "Checking where it's used\u2026" }),
1397
+ blocked === null && !error && /* @__PURE__ */ jsx(Loading, { children: "Checking where they're used\u2026" }),
1379
1398
  isBlocked && /* @__PURE__ */ jsx(Notice, { title: "Still in use", tone: "caution", children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
1380
- /* @__PURE__ */ jsx(Text, { muted: true, size: 1, children: "Remove it from these documents first:" }),
1381
- blockers.map((blocker) => /* @__PURE__ */ jsxs(Text, { muted: true, size: 1, children: [
1382
- blocker.title || blocker._id,
1383
- " (",
1384
- blocker._type,
1385
- ")"
1386
- ] }, blocker._id))
1399
+ /* @__PURE__ */ jsxs(Text, { muted: true, size: 1, children: [
1400
+ "Remove ",
1401
+ isOne ? "it" : "these",
1402
+ " from these documents first:"
1403
+ ] }),
1404
+ blocked.map((entry) => /* @__PURE__ */ jsxs(Text, { muted: true, size: 1, children: [
1405
+ !isOne && `${entry.asset.filename}: `,
1406
+ entry.documents.map((document) => document.title || document._id).join(", ")
1407
+ ] }, entry.asset._id))
1387
1408
  ] }) }),
1388
- blockers !== null && blockers.length === 0 && /* @__PURE__ */ jsx(Text, { muted: true, size: 1, children: "Nothing references it. This can't be undone." }),
1409
+ blocked !== null && blocked.length === 0 && /* @__PURE__ */ jsxs(Text, { muted: true, size: 1, children: [
1410
+ "Nothing references ",
1411
+ isOne ? "it" : "them",
1412
+ ". This can't be undone."
1413
+ ] }),
1389
1414
  error && /* @__PURE__ */ jsx(Notice, { tone: "critical", children: error })
1390
1415
  ] }) })
1391
1416
  }
@@ -1404,6 +1429,7 @@ var DialogDetails = ({
1404
1429
  );
1405
1430
  const [filename, setFilename] = useState(asset.filename);
1406
1431
  const [isSaving, setIsSaving] = useState(false);
1432
+ const [isFlagged, setIsFlagged] = useState(false);
1407
1433
  const [error, setError] = useState(null);
1408
1434
  const isBroken = asset.renditions.length === 0;
1409
1435
  const trimmed = filename.trim();
@@ -1414,6 +1440,17 @@ var DialogDetails = ({
1414
1440
  const reset = () => {
1415
1441
  setFilename(asset.filename);
1416
1442
  setFolderId(savedFolderId);
1443
+ setIsFlagged(false);
1444
+ };
1445
+ const attemptClose = () => {
1446
+ if (isSaving) {
1447
+ return;
1448
+ }
1449
+ if (isDirty) {
1450
+ setIsFlagged(true);
1451
+ return;
1452
+ }
1453
+ onClose();
1417
1454
  };
1418
1455
  const save = async () => {
1419
1456
  if (!isDirty) {
@@ -1442,6 +1479,7 @@ var DialogDetails = ({
1442
1479
  mutation = mutation.unset(removals);
1443
1480
  }
1444
1481
  await mutation.commit();
1482
+ setIsFlagged(false);
1445
1483
  onChanged();
1446
1484
  } catch (caught) {
1447
1485
  reset();
@@ -1455,7 +1493,8 @@ var DialogDetails = ({
1455
1493
  header: asset.filename || "Untitled video",
1456
1494
  id: "r2-video-details",
1457
1495
  width: 1,
1458
- onClose: isSaving ? void 0 : onClose,
1496
+ onClickOutside: attemptClose,
1497
+ onClose: isSaving ? void 0 : attemptClose,
1459
1498
  footer: /* @__PURE__ */ jsx(
1460
1499
  DialogActions,
1461
1500
  {
@@ -1520,6 +1559,7 @@ var DialogDetails = ({
1520
1559
  }
1521
1560
  ) }) })
1522
1561
  ] }),
1562
+ isFlagged && /* @__PURE__ */ jsx(Notice, { tone: "caution", children: "Unsaved changes. Save them, or discard to close." }),
1523
1563
  error && /* @__PURE__ */ jsx(Notice, { tone: "critical", children: error }),
1524
1564
  /* @__PURE__ */ jsx(
1525
1565
  VideoSummary,
@@ -1716,6 +1756,7 @@ var QUERY_ASSETS = `*[_type == "r2Video.asset"] | order(uploadedAt desc){
1716
1756
  "hasAudio": coalesce(hasAudio, false),
1717
1757
  "renditions": coalesce(renditions, []),
1718
1758
  uploadedAt,
1759
+ "isUsed": count(*[references(^._id)]) > 0,
1719
1760
  "posterUrl": poster.asset->url,
1720
1761
  "folderName": folder->name
1721
1762
  }`;
@@ -1737,8 +1778,56 @@ var matches = (asset, search) => {
1737
1778
  const folderName = asset.folderName ?? "";
1738
1779
  return asset.filename.toLowerCase().includes(term) || folderName.toLowerCase().includes(term);
1739
1780
  };
1781
+ var FILTERS = [
1782
+ {
1783
+ key: "foldered",
1784
+ group: "folder",
1785
+ label: "In a folder",
1786
+ test: (asset) => Boolean(asset.folder)
1787
+ },
1788
+ {
1789
+ key: "unfoldered",
1790
+ group: "folder",
1791
+ label: "No folder",
1792
+ test: (asset) => !asset.folder
1793
+ },
1794
+ {
1795
+ key: "used",
1796
+ group: "usage",
1797
+ label: "In use",
1798
+ test: (asset) => asset.isUsed
1799
+ },
1800
+ {
1801
+ key: "unused",
1802
+ group: "usage",
1803
+ label: "Unused",
1804
+ test: (asset) => !asset.isUsed
1805
+ }
1806
+ ];
1807
+ var FILTER_GROUPS = [...new Set(FILTERS.map((filter) => filter.group))];
1808
+ var passesFilters = (asset, keys) => {
1809
+ const active = FILTERS.filter((filter) => keys.includes(filter.key));
1810
+ return FILTER_GROUPS.every((group) => {
1811
+ const inGroup = active.filter((filter) => filter.group === group);
1812
+ return inGroup.length === 0 || inGroup.some((filter) => filter.test(asset));
1813
+ });
1814
+ };
1815
+ var SelectableCard = styled(Box)`
1816
+ position: relative;
1817
+
1818
+ & [data-checkbox] {
1819
+ opacity: 0;
1820
+ }
1821
+
1822
+ &:hover [data-checkbox],
1823
+ & [data-checkbox]:focus-within,
1824
+ & [data-checkbox][data-selected="true"] {
1825
+ opacity: 1;
1826
+ }
1827
+ `;
1740
1828
  var ToolVideoLibrary = () => {
1741
1829
  const { config, client } = useR2VideoClient();
1830
+ const { paths: allPaths } = useFolders();
1742
1831
  const [assets, setAssets] = useState(null);
1743
1832
  const [folders, setFolders] = useState([]);
1744
1833
  const [search, setSearch] = useState("");
@@ -1748,6 +1837,9 @@ var ToolVideoLibrary = () => {
1748
1837
  const [droppedFiles, setDroppedFiles] = useState([]);
1749
1838
  const [detailing, setDetailing] = useState(null);
1750
1839
  const [deleting, setDeleting] = useState(null);
1840
+ const [filterKeys, setFilterKeys] = useState([]);
1841
+ const [selectedIds, setSelectedIds] = useState([]);
1842
+ const [isMoving, setIsMoving] = useState(false);
1751
1843
  const load = useCallback(() => {
1752
1844
  client.fetch(QUERY_ASSETS).then(setAssets);
1753
1845
  fetchFolders(client, config.folders.type).then(setFolders);
@@ -1777,8 +1869,33 @@ var ToolVideoLibrary = () => {
1777
1869
  };
1778
1870
  const visible = (assets ?? []).filter((asset) => {
1779
1871
  const inFolder = !folderId || asset.folder && asset.folder._ref === folderId;
1780
- return matches(asset, search) && inFolder;
1872
+ return matches(asset, search) && inFolder && passesFilters(asset, filterKeys);
1781
1873
  });
1874
+ const selected = visible.filter((asset) => selectedIds.includes(asset._id));
1875
+ const toggleFilter = (key) => {
1876
+ setFilterKeys((current) => {
1877
+ return current.includes(key) ? current.filter((entry) => entry !== key) : [...current, key];
1878
+ });
1879
+ };
1880
+ const toggleSelected = (id) => {
1881
+ setSelectedIds((current) => {
1882
+ return current.includes(id) ? current.filter((entry) => entry !== id) : [...current, id];
1883
+ });
1884
+ };
1885
+ const moveSelected = async (targetId) => {
1886
+ setIsMoving(true);
1887
+ let transaction = client.transaction();
1888
+ for (const asset of selected) {
1889
+ transaction = targetId ? transaction.patch(
1890
+ asset._id,
1891
+ (patch) => patch.set({ folder: { _type: "reference", _ref: targetId } })
1892
+ ) : transaction.patch(asset._id, (patch) => patch.unset(["folder"]));
1893
+ }
1894
+ await transaction.commit();
1895
+ setIsMoving(false);
1896
+ setSelectedIds([]);
1897
+ load();
1898
+ };
1782
1899
  return /* @__PURE__ */ jsxs(
1783
1900
  Flex,
1784
1901
  {
@@ -1806,6 +1923,34 @@ var ToolVideoLibrary = () => {
1806
1923
  onChange: (event) => setSearch(event.currentTarget.value)
1807
1924
  }
1808
1925
  ) }),
1926
+ /* @__PURE__ */ jsx(
1927
+ MenuButton,
1928
+ {
1929
+ button: /* @__PURE__ */ jsx(
1930
+ Button,
1931
+ {
1932
+ icon: FilterIcon,
1933
+ mode: filterKeys.length > 0 ? "default" : "ghost",
1934
+ text: filterKeys.length > 0 ? `Filters (${filterKeys.length})` : "Filters",
1935
+ tone: filterKeys.length > 0 ? "primary" : "default"
1936
+ }
1937
+ ),
1938
+ id: "r2-video-filters",
1939
+ menu: /* @__PURE__ */ jsx(Menu, { children: FILTERS.map((filter, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
1940
+ index > 0 && FILTERS[index - 1].group !== filter.group && /* @__PURE__ */ jsx(MenuDivider, {}),
1941
+ /* @__PURE__ */ jsx(
1942
+ MenuItem,
1943
+ {
1944
+ iconRight: filterKeys.includes(filter.key) ? CheckmarkIcon : void 0,
1945
+ pressed: filterKeys.includes(filter.key),
1946
+ text: filter.label,
1947
+ onClick: () => toggleFilter(filter.key)
1948
+ }
1949
+ )
1950
+ ] }, filter.key)) }),
1951
+ popover: { placement: "bottom-start" }
1952
+ }
1953
+ ),
1809
1954
  /* @__PURE__ */ jsx(
1810
1955
  Button,
1811
1956
  {
@@ -1825,42 +1970,115 @@ var ToolVideoLibrary = () => {
1825
1970
  }
1826
1971
  )
1827
1972
  ] }),
1973
+ selected.length > 0 && /* @__PURE__ */ jsx(Card, { border: true, padding: 2, radius: 2, tone: "primary", children: /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, children: [
1974
+ /* @__PURE__ */ jsx(Box, { paddingX: 2, children: /* @__PURE__ */ jsxs(Text, { size: 1, weight: "medium", children: [
1975
+ pluralize(selected.length, "video"),
1976
+ " selected"
1977
+ ] }) }),
1978
+ /* @__PURE__ */ jsx(Box, { flex: 1, children: /* @__PURE__ */ jsxs(
1979
+ Select,
1980
+ {
1981
+ "aria-label": "Move to folder",
1982
+ disabled: isMoving,
1983
+ value: "",
1984
+ onChange: (event) => moveSelected(event.currentTarget.value),
1985
+ children: [
1986
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Move to\u2026" }),
1987
+ /* @__PURE__ */ jsx("option", { value: "", children: "No folder" }),
1988
+ allPaths.map((entry) => /* @__PURE__ */ jsx("option", { value: entry.id, children: entry.path }, entry.id))
1989
+ ]
1990
+ }
1991
+ ) }),
1992
+ /* @__PURE__ */ jsx(
1993
+ Button,
1994
+ {
1995
+ disabled: isMoving,
1996
+ mode: "ghost",
1997
+ text: "Clear",
1998
+ onClick: () => setSelectedIds([])
1999
+ }
2000
+ ),
2001
+ /* @__PURE__ */ jsx(
2002
+ Button,
2003
+ {
2004
+ disabled: isMoving,
2005
+ icon: TrashIcon,
2006
+ mode: "ghost",
2007
+ text: "Delete",
2008
+ tone: "critical",
2009
+ onClick: () => setDeleting(selected)
2010
+ }
2011
+ )
2012
+ ] }) }),
1828
2013
  assets === null && /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsx(Loading, { children: "Loading library\u2026" }) }),
1829
2014
  assets !== null && visible.length === 0 && /* @__PURE__ */ jsx(Card, { padding: 5, radius: 2, tone: "transparent", children: /* @__PURE__ */ jsx(Text, { align: "center", muted: true, size: 1, children: "No videos here yet." }) }),
1830
- /* @__PURE__ */ jsx(Grid, { gridTemplateColumns: [1, 2, 3, 4], gap: 3, children: visible.map((asset) => /* @__PURE__ */ jsx(
1831
- Card,
1832
- {
1833
- as: "button",
1834
- border: true,
1835
- padding: 2,
1836
- radius: 2,
1837
- style: { cursor: "pointer", textAlign: "left" },
1838
- onClick: () => setDetailing(asset),
1839
- children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
1840
- /* @__PURE__ */ jsx(
1841
- Box,
2015
+ /* @__PURE__ */ jsx(Grid, { gridTemplateColumns: [1, 2, 3, 4], gap: 3, children: visible.map((asset) => /* @__PURE__ */ jsxs(SelectableCard, { children: [
2016
+ /* @__PURE__ */ jsx(
2017
+ Box,
2018
+ {
2019
+ "data-checkbox": true,
2020
+ "data-selected": selectedIds.includes(asset._id),
2021
+ style: {
2022
+ position: "absolute",
2023
+ top: 14,
2024
+ left: 14,
2025
+ zIndex: 1
2026
+ },
2027
+ children: /* @__PURE__ */ jsx(
2028
+ Checkbox,
1842
2029
  {
1843
- style: {
1844
- aspectRatio: "16 / 9",
1845
- backgroundImage: asset.posterUrl ? `url(${asset.posterUrl}?w=480&fit=crop&auto=format)` : void 0,
1846
- backgroundPosition: "center",
1847
- backgroundSize: "cover",
1848
- borderRadius: 2
1849
- }
2030
+ "aria-label": `Select ${asset.filename}`,
2031
+ checked: selectedIds.includes(asset._id),
2032
+ onChange: () => toggleSelected(asset._id)
1850
2033
  }
1851
- ),
1852
- /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
1853
- /* @__PURE__ */ jsx(Text, { size: 1, textOverflow: "ellipsis", weight: "medium", children: toTitle(asset, Boolean(folderId)) }),
1854
- /* @__PURE__ */ jsxs(Text, { muted: true, size: 1, children: [
1855
- asset.renditions.length,
1856
- " sizes",
1857
- asset.hasAudio ? " \xB7 audio" : ""
2034
+ )
2035
+ }
2036
+ ),
2037
+ /* @__PURE__ */ jsx(
2038
+ Card,
2039
+ {
2040
+ as: "button",
2041
+ border: true,
2042
+ padding: 2,
2043
+ radius: 2,
2044
+ style: {
2045
+ cursor: "pointer",
2046
+ textAlign: "left",
2047
+ width: "100%"
2048
+ },
2049
+ onClick: (event) => {
2050
+ if (event.shiftKey) {
2051
+ toggleSelected(asset._id);
2052
+ return;
2053
+ }
2054
+ setDetailing(asset);
2055
+ },
2056
+ children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
2057
+ /* @__PURE__ */ jsx(
2058
+ Box,
2059
+ {
2060
+ style: {
2061
+ aspectRatio: "16 / 9",
2062
+ backgroundImage: asset.posterUrl ? `url(${asset.posterUrl}?w=480&fit=crop&auto=format)` : void 0,
2063
+ backgroundPosition: "center",
2064
+ backgroundSize: "cover",
2065
+ borderRadius: 2
2066
+ }
2067
+ }
2068
+ ),
2069
+ /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
2070
+ /* @__PURE__ */ jsx(Text, { size: 1, textOverflow: "ellipsis", weight: "medium", children: toTitle(asset, Boolean(folderId)) }),
2071
+ /* @__PURE__ */ jsxs(Text, { muted: true, size: 1, children: [
2072
+ asset.renditions.length,
2073
+ " sizes",
2074
+ asset.hasAudio ? " \xB7 audio" : "",
2075
+ asset.isUsed ? "" : " \xB7 unused"
2076
+ ] })
1858
2077
  ] })
1859
2078
  ] })
1860
- ] })
1861
- },
1862
- asset._id
1863
- )) })
2079
+ }
2080
+ )
2081
+ ] }, asset._id)) })
1864
2082
  ] }) }) }),
1865
2083
  isDragging && /* @__PURE__ */ jsx(DropToUpload, { isRejected }),
1866
2084
  isUploadOpen && /* @__PURE__ */ jsx(
@@ -1885,7 +2103,7 @@ var ToolVideoLibrary = () => {
1885
2103
  asset: detailing,
1886
2104
  onChanged: load,
1887
2105
  onDelete: () => {
1888
- setDeleting(detailing);
2106
+ setDeleting([detailing]);
1889
2107
  setDetailing(null);
1890
2108
  },
1891
2109
  onClose: () => setDetailing(null)
@@ -1894,7 +2112,7 @@ var ToolVideoLibrary = () => {
1894
2112
  deleting && /* @__PURE__ */ jsx(
1895
2113
  DialogDelete,
1896
2114
  {
1897
- asset: deleting,
2115
+ assets: deleting,
1898
2116
  onClose: () => setDeleting(null),
1899
2117
  onDeleted: () => {
1900
2118
  setDeleting(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sanity-plugin-r2-video",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Video for Sanity Studio, encoded in the browser and stored in Cloudflare R2 as a ladder of plain MP4s.",
5
5
  "keywords": [
6
6
  "sanity",