@cliff-studio/sanity-plugin-bunny-input 1.0.9 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { set, unset, defineType, defineField, definePlugin } from "sanity";
2
- import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
3
3
  import * as r from "react";
4
- import r__default, { createElement, forwardRef, useLayoutEffect, createContext, useRef, useEffect, useId, useContext, useInsertionEffect, useMemo, useCallback, Children, isValidElement, useState, Fragment as Fragment$1, Component, useImperativeHandle, lazy, memo as memo$1, cloneElement, Suspense, useSyncExternalStore, useDebugValue, useReducer } from "react";
4
+ import r__default, { createElement, forwardRef, useLayoutEffect, createContext, useRef, useEffect, useId, useContext, useInsertionEffect, useMemo, useCallback, Children, isValidElement, useState, Fragment as Fragment$1, Component, useImperativeHandle, useDebugValue, useSyncExternalStore, lazy, memo as memo$1, cloneElement, Suspense, useReducer } from "react";
5
5
  const COLOR_HUES = [
6
6
  "gray",
7
7
  "blue",
@@ -5096,6 +5096,29 @@ const CheckmarkIcon = /* @__PURE__ */ forwardRef(function(props, ref) {
5096
5096
  children: /* @__PURE__ */ jsx("path", { d: "M5 12.5H20", stroke: "currentColor", strokeWidth: 1.2, strokeLinejoin: "round" })
5097
5097
  }
5098
5098
  );
5099
+ }), SearchIcon = /* @__PURE__ */ forwardRef(function(props, ref) {
5100
+ return /* @__PURE__ */ jsx(
5101
+ "svg",
5102
+ {
5103
+ "data-sanity-icon": "search",
5104
+ width: "1em",
5105
+ height: "1em",
5106
+ viewBox: "0 0 25 25",
5107
+ fill: "none",
5108
+ xmlns: "http://www.w3.org/2000/svg",
5109
+ ...props,
5110
+ ref,
5111
+ children: /* @__PURE__ */ jsx(
5112
+ "path",
5113
+ {
5114
+ d: "M15.0355 15.0355L20 20M16.5 11.5C16.5 14.2614 14.2614 16.5 11.5 16.5C8.73858 16.5 6.5 14.2614 6.5 11.5C6.5 8.73858 8.73858 6.5 11.5 6.5C14.2614 6.5 16.5 8.73858 16.5 11.5Z",
5115
+ stroke: "currentColor",
5116
+ strokeWidth: 1.2,
5117
+ strokeLinejoin: "round"
5118
+ }
5119
+ )
5120
+ }
5121
+ );
5099
5122
  }), SpinnerIcon = /* @__PURE__ */ forwardRef(function(props, ref) {
5100
5123
  return /* @__PURE__ */ jsx(
5101
5124
  "svg",
@@ -5142,6 +5165,75 @@ const CheckmarkIcon = /* @__PURE__ */ forwardRef(function(props, ref) {
5142
5165
  )
5143
5166
  }
5144
5167
  );
5168
+ }), UploadIcon = /* @__PURE__ */ forwardRef(function(props, ref) {
5169
+ return /* @__PURE__ */ jsxs(
5170
+ "svg",
5171
+ {
5172
+ "data-sanity-icon": "upload",
5173
+ width: "1em",
5174
+ height: "1em",
5175
+ viewBox: "0 0 25 25",
5176
+ fill: "none",
5177
+ xmlns: "http://www.w3.org/2000/svg",
5178
+ ...props,
5179
+ ref,
5180
+ children: [
5181
+ /* @__PURE__ */ jsx(
5182
+ "path",
5183
+ {
5184
+ d: "M12.5 6V15.5M5.5 15.5H19.5V19.5H5.5V15.5Z",
5185
+ stroke: "currentColor",
5186
+ strokeWidth: 1.2,
5187
+ strokeLinejoin: "round"
5188
+ }
5189
+ ),
5190
+ /* @__PURE__ */ jsx(
5191
+ "path",
5192
+ {
5193
+ d: "M7.5 11L12.5 6L17.5 11",
5194
+ stroke: "currentColor",
5195
+ strokeWidth: 1.2,
5196
+ strokeLinejoin: "round"
5197
+ }
5198
+ )
5199
+ ]
5200
+ }
5201
+ );
5202
+ }), VideoIcon = /* @__PURE__ */ forwardRef(function(props, ref) {
5203
+ return /* @__PURE__ */ jsxs(
5204
+ "svg",
5205
+ {
5206
+ "data-sanity-icon": "video",
5207
+ width: "1em",
5208
+ height: "1em",
5209
+ viewBox: "0 0 25 25",
5210
+ fill: "none",
5211
+ xmlns: "http://www.w3.org/2000/svg",
5212
+ ...props,
5213
+ ref,
5214
+ children: [
5215
+ /* @__PURE__ */ jsx(
5216
+ "path",
5217
+ {
5218
+ d: "M19.5 18.5H5.5V6.5H19.5V18.5Z",
5219
+ stroke: "currentColor",
5220
+ strokeWidth: 1.2,
5221
+ strokeLinejoin: "round"
5222
+ }
5223
+ ),
5224
+ /* @__PURE__ */ jsx(
5225
+ "path",
5226
+ {
5227
+ d: "M11.5 14.5V10.5L14.5 12.5L11.5 14.5Z",
5228
+ fill: "currentColor",
5229
+ stroke: "currentColor",
5230
+ strokeWidth: 1.2,
5231
+ strokeLinejoin: "round"
5232
+ }
5233
+ )
5234
+ ]
5235
+ }
5236
+ );
5145
5237
  }), sides = ["top", "right", "bottom", "left"], alignments = ["start", "end"], placements = /* @__PURE__ */ sides.reduce((acc, side) => acc.concat(side, side + "-" + alignments[0], side + "-" + alignments[1]), []), min = Math.min, max = Math.max, round = Math.round, floor = Math.floor, createCoords = (v2) => ({
5146
5238
  x: v2,
5147
5239
  y: v2
@@ -18588,6 +18680,28 @@ async function getVideo(config, videoId) {
18588
18680
  }
18589
18681
  return response.json();
18590
18682
  }
18683
+ async function listVideos(config, { collectionId, search = "", page = 1, itemsPerPage = 50 } = {}) {
18684
+ const params = new URLSearchParams({
18685
+ page: String(page),
18686
+ itemsPerPage: String(itemsPerPage),
18687
+ orderBy: "date"
18688
+ });
18689
+ collectionId && params.set("collection", collectionId), search && params.set("search", search);
18690
+ const url = config.proxyEndpoint ? `${config.proxyEndpoint}/videos?${params}` : `${BUNNY_API_BASE}/library/${config.libraryId}/videos?${params}`, response = await fetch(url, {
18691
+ headers: createHeaders(config, !1, !config.proxyEndpoint || !!config.apiKey)
18692
+ });
18693
+ if (!response.ok) {
18694
+ const error = await response.text();
18695
+ throw new Error(`Failed to list videos: ${error}`);
18696
+ }
18697
+ const payload = await response.json();
18698
+ return {
18699
+ items: payload.items || [],
18700
+ totalItems: payload.totalItems ?? 0,
18701
+ currentPage: payload.currentPage ?? page,
18702
+ itemsPerPage: payload.itemsPerPage ?? itemsPerPage
18703
+ };
18704
+ }
18591
18705
  async function deleteVideo(config, videoId) {
18592
18706
  const url = config.proxyEndpoint ? `${config.proxyEndpoint}/video/${videoId}` : `${BUNNY_API_BASE}/library/${config.libraryId}/videos/${videoId}`, headers = createHeaders(config), response = await fetch(url, {
18593
18707
  method: "DELETE",
@@ -18599,8 +18713,197 @@ async function deleteVideo(config, videoId) {
18599
18713
  }
18600
18714
  return response.json();
18601
18715
  }
18716
+ const ITEMS_PER_PAGE = 48;
18717
+ function BunnyBrowserModal({ config, collectionId: collectionIdProp, onSelect, onClose }) {
18718
+ const [videos, setVideos] = useState([]), [search, setSearch] = useState(""), [page, setPage] = useState(1), [totalItems, setTotalItems] = useState(0), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), [resolvedCollectionId, setResolvedCollectionId] = useState(collectionIdProp || null), searchTimeoutRef = useRef(null), fetchVideos = useCallback(
18719
+ async (searchTerm, pageNum, collId) => {
18720
+ setIsLoading(!0), setError(null);
18721
+ try {
18722
+ const result = await listVideos(config, {
18723
+ collectionId: collId,
18724
+ search: searchTerm,
18725
+ page: pageNum,
18726
+ itemsPerPage: ITEMS_PER_PAGE
18727
+ });
18728
+ setVideos(result.items), setTotalItems(result.totalItems);
18729
+ } catch (err) {
18730
+ setError(err instanceof Error ? err.message : "Failed to load videos");
18731
+ } finally {
18732
+ setIsLoading(!1);
18733
+ }
18734
+ },
18735
+ [config]
18736
+ );
18737
+ useEffect(() => {
18738
+ async function init() {
18739
+ let collId = collectionIdProp || null;
18740
+ if (!collId && config.collectionName)
18741
+ try {
18742
+ collId = (await getOrCreateCollection(config, config.collectionName)).guid, setResolvedCollectionId(collId);
18743
+ } catch (err) {
18744
+ console.warn("Could not resolve collection, browsing full library:", err);
18745
+ }
18746
+ fetchVideos("", 1, collId);
18747
+ }
18748
+ init();
18749
+ }, []);
18750
+ const handleSearchChange = useCallback(
18751
+ (e) => {
18752
+ const value = e.target.value;
18753
+ setSearch(value), setPage(1), searchTimeoutRef.current && clearTimeout(searchTimeoutRef.current), searchTimeoutRef.current = setTimeout(() => {
18754
+ fetchVideos(value, 1, resolvedCollectionId);
18755
+ }, 400);
18756
+ },
18757
+ [fetchVideos, resolvedCollectionId]
18758
+ ), handlePageChange = useCallback(
18759
+ (newPage) => {
18760
+ setPage(newPage), fetchVideos(search, newPage, resolvedCollectionId);
18761
+ },
18762
+ [fetchVideos, search, resolvedCollectionId]
18763
+ ), handleSelect = useCallback(
18764
+ (video) => {
18765
+ if (mapBunnyStatus(video.status) !== "ready") return;
18766
+ const width = Number(video.width), height = Number(video.height), hasDims = Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0, ratio = hasDims ? Number((width / height).toFixed(6)) : null, orientation = hasDims ? width > height ? "landscape" : width < height ? "portrait" : "square" : null;
18767
+ onSelect({
18768
+ _type: "bunnyVideo",
18769
+ videoId: video.guid,
18770
+ libraryId: String(video.videoLibraryId),
18771
+ title: video.title,
18772
+ status: "ready",
18773
+ duration: video.length,
18774
+ width: hasDims ? width : null,
18775
+ height: hasDims ? height : null,
18776
+ ratio,
18777
+ orientation,
18778
+ thumbnailUrl: getThumbnailUrl(config.cdnHostname, video.guid),
18779
+ playbackUrl: getPlaybackUrl(config.cdnHostname, video.guid),
18780
+ mp4Url: getMp4Url(config.cdnHostname, video.guid, video.availableResolutions),
18781
+ ...resolvedCollectionId ? { collectionId: resolvedCollectionId } : {},
18782
+ ...video.collectionId ? { collectionId: video.collectionId } : {}
18783
+ });
18784
+ },
18785
+ [config, resolvedCollectionId, onSelect]
18786
+ ), totalPages = Math.ceil(totalItems / ITEMS_PER_PAGE);
18787
+ return /* @__PURE__ */ jsx(
18788
+ Dialog,
18789
+ {
18790
+ header: "Browse videos",
18791
+ id: "bunny-browser-modal",
18792
+ onClose,
18793
+ width: 3,
18794
+ children: /* @__PURE__ */ jsxs(Box, { padding: 4, children: [
18795
+ /* @__PURE__ */ jsx(Box, { marginBottom: 4, children: /* @__PURE__ */ jsx(
18796
+ TextInput,
18797
+ {
18798
+ icon: SearchIcon,
18799
+ placeholder: "Search videos\u2026",
18800
+ value: search,
18801
+ onChange: handleSearchChange
18802
+ }
18803
+ ) }),
18804
+ error && /* @__PURE__ */ jsx(Card, { padding: 3, radius: 2, tone: "critical", marginBottom: 4, children: /* @__PURE__ */ jsx(Text, { size: 1, children: error }) }),
18805
+ isLoading ? /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", padding: 6, children: /* @__PURE__ */ jsx(Spinner, {}) }) : videos.length === 0 ? /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", padding: 6, children: /* @__PURE__ */ jsx(Text, { muted: !0, size: 1, children: search ? "No videos found matching your search" : "No videos in this collection" }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
18806
+ /* @__PURE__ */ jsx(Grid, { columns: [2, 2, 3, 4], gap: 3, children: videos.map((video) => {
18807
+ const status = mapBunnyStatus(video.status), isReady = status === "ready", thumbUrl = getThumbnailUrl(config.cdnHostname, video.guid);
18808
+ return /* @__PURE__ */ jsxs(
18809
+ Card,
18810
+ {
18811
+ radius: 2,
18812
+ shadow: 1,
18813
+ style: {
18814
+ cursor: isReady ? "pointer" : "not-allowed",
18815
+ opacity: isReady ? 1 : 0.5
18816
+ },
18817
+ onClick: () => isReady && handleSelect(video),
18818
+ children: [
18819
+ /* @__PURE__ */ jsxs(
18820
+ Box,
18821
+ {
18822
+ style: {
18823
+ position: "relative",
18824
+ paddingBottom: "56.25%",
18825
+ backgroundColor: "#111",
18826
+ borderRadius: "2px",
18827
+ overflow: "hidden"
18828
+ },
18829
+ children: [
18830
+ /* @__PURE__ */ jsx(
18831
+ "img",
18832
+ {
18833
+ src: thumbUrl,
18834
+ alt: video.title || "Video thumbnail",
18835
+ style: {
18836
+ position: "absolute",
18837
+ top: 0,
18838
+ left: 0,
18839
+ width: "100%",
18840
+ height: "100%",
18841
+ objectFit: "cover"
18842
+ }
18843
+ }
18844
+ ),
18845
+ !isReady && /* @__PURE__ */ jsx(
18846
+ Flex,
18847
+ {
18848
+ align: "center",
18849
+ justify: "center",
18850
+ style: {
18851
+ position: "absolute",
18852
+ inset: 0,
18853
+ backgroundColor: "rgba(0,0,0,0.5)"
18854
+ },
18855
+ children: /* @__PURE__ */ jsx(Text, { size: 0, style: { color: "#fff" }, children: status === "processing" ? "Processing\u2026" : status })
18856
+ }
18857
+ )
18858
+ ]
18859
+ }
18860
+ ),
18861
+ /* @__PURE__ */ jsx(Box, { padding: 3, children: /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
18862
+ /* @__PURE__ */ jsx(Text, { size: 1, weight: "semibold", children: video.title || "Untitled" }),
18863
+ video.length > 0 && /* @__PURE__ */ jsxs(Text, { size: 1, muted: !0, children: [
18864
+ Math.floor(video.length / 60),
18865
+ ":",
18866
+ String(Math.floor(video.length % 60)).padStart(2, "0")
18867
+ ] })
18868
+ ] }) })
18869
+ ]
18870
+ },
18871
+ video.guid
18872
+ );
18873
+ }) }),
18874
+ totalPages > 1 && /* @__PURE__ */ jsxs(Flex, { align: "center", justify: "center", gap: 2, marginTop: 4, children: [
18875
+ /* @__PURE__ */ jsx(
18876
+ Button,
18877
+ {
18878
+ text: "Previous",
18879
+ mode: "ghost",
18880
+ disabled: page <= 1,
18881
+ onClick: () => handlePageChange(page - 1)
18882
+ }
18883
+ ),
18884
+ /* @__PURE__ */ jsxs(Text, { size: 1, muted: !0, children: [
18885
+ "Page ",
18886
+ page,
18887
+ " of ",
18888
+ totalPages
18889
+ ] }),
18890
+ /* @__PURE__ */ jsx(
18891
+ Button,
18892
+ {
18893
+ text: "Next",
18894
+ mode: "ghost",
18895
+ disabled: page >= totalPages,
18896
+ onClick: () => handlePageChange(page + 1)
18897
+ }
18898
+ )
18899
+ ] })
18900
+ ] })
18901
+ ] })
18902
+ }
18903
+ );
18904
+ }
18602
18905
  function BunnyInput(props) {
18603
- const { value, onChange, config } = props, [uploadProgress, setUploadProgress] = useState(0), [isUploading, setIsUploading] = useState(!1), [error, setError] = useState(null), fileInputRef = useRef(null), pollIntervalRef = useRef(null);
18906
+ const { value, onChange, config } = props, [uploadProgress, setUploadProgress] = useState(0), [isUploading, setIsUploading] = useState(!1), [error, setError] = useState(null), [isBrowserOpen, setIsBrowserOpen] = useState(!1), fileInputRef = useRef(null), pollIntervalRef = useRef(null);
18604
18907
  useEffect(() => (value?.videoId && value?.status === "processing" && (pollIntervalRef.current = window.setInterval(async () => {
18605
18908
  try {
18606
18909
  const videoData = await getVideo(config, value.videoId), status = mapBunnyStatus(videoData.status);
@@ -18687,6 +18990,11 @@ function BunnyInput(props) {
18687
18990
  file && handleFileSelect(file);
18688
18991
  },
18689
18992
  [handleFileSelect]
18993
+ ), handleBrowseSelect = useCallback(
18994
+ (videoData) => {
18995
+ setIsBrowserOpen(!1), onChange(set(videoData));
18996
+ },
18997
+ [onChange]
18690
18998
  ), handleRemove = useCallback(async () => {
18691
18999
  if (value?.videoId)
18692
19000
  try {
@@ -18696,46 +19004,67 @@ function BunnyInput(props) {
18696
19004
  }
18697
19005
  onChange(unset());
18698
19006
  }, [config, value, onChange]);
18699
- return value?.videoId && value?.status === "ready" ? /* @__PURE__ */ jsx(Card, { padding: 3, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
18700
- /* @__PURE__ */ jsx(
18701
- Box,
18702
- {
18703
- style: {
18704
- position: "relative",
18705
- paddingBottom: "56.25%",
18706
- backgroundColor: "#000",
18707
- borderRadius: "4px",
18708
- overflow: "hidden"
18709
- },
18710
- children: value.thumbnailUrl && /* @__PURE__ */ jsx(
18711
- "img",
18712
- {
18713
- src: value.thumbnailUrl,
18714
- alt: value.title || "Video thumbnail",
18715
- style: {
18716
- position: "absolute",
18717
- top: 0,
18718
- left: 0,
18719
- width: "100%",
18720
- height: "100%",
18721
- objectFit: "contain"
19007
+ return value?.videoId && value?.status === "ready" ? /* @__PURE__ */ jsxs(Fragment, { children: [
19008
+ /* @__PURE__ */ jsx(Card, { padding: 3, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
19009
+ /* @__PURE__ */ jsx(
19010
+ Box,
19011
+ {
19012
+ style: {
19013
+ position: "relative",
19014
+ paddingBottom: "56.25%",
19015
+ backgroundColor: "#000",
19016
+ borderRadius: "4px",
19017
+ overflow: "hidden"
19018
+ },
19019
+ children: value.thumbnailUrl && /* @__PURE__ */ jsx(
19020
+ "img",
19021
+ {
19022
+ src: value.thumbnailUrl,
19023
+ alt: value.title || "Video thumbnail",
19024
+ style: {
19025
+ position: "absolute",
19026
+ top: 0,
19027
+ left: 0,
19028
+ width: "100%",
19029
+ height: "100%",
19030
+ objectFit: "contain"
19031
+ }
18722
19032
  }
18723
- }
18724
- )
18725
- }
18726
- ),
18727
- /* @__PURE__ */ jsxs(Flex, { justify: "space-between", align: "center", children: [
18728
- /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
18729
- /* @__PURE__ */ jsx(Text, { size: 1, weight: "semibold", children: value.title }),
18730
- value.duration && /* @__PURE__ */ jsxs(Text, { size: 1, muted: !0, children: [
18731
- Math.floor(value.duration / 60),
18732
- ":",
18733
- String(Math.floor(value.duration % 60)).padStart(2, "0")
19033
+ )
19034
+ }
19035
+ ),
19036
+ /* @__PURE__ */ jsxs(Flex, { justify: "space-between", align: "center", children: [
19037
+ /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
19038
+ /* @__PURE__ */ jsx(Text, { size: 1, weight: "semibold", children: value.title }),
19039
+ value.duration && /* @__PURE__ */ jsxs(Text, { size: 1, muted: !0, children: [
19040
+ Math.floor(value.duration / 60),
19041
+ ":",
19042
+ String(Math.floor(value.duration % 60)).padStart(2, "0")
19043
+ ] })
19044
+ ] }),
19045
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
19046
+ /* @__PURE__ */ jsx(
19047
+ Button,
19048
+ {
19049
+ text: "Browse",
19050
+ mode: "ghost",
19051
+ onClick: () => setIsBrowserOpen(!0)
19052
+ }
19053
+ ),
19054
+ /* @__PURE__ */ jsx(Button, { text: "Remove", tone: "critical", mode: "ghost", onClick: handleRemove })
18734
19055
  ] })
18735
- ] }),
18736
- /* @__PURE__ */ jsx(Button, { text: "Remove", tone: "critical", mode: "ghost", onClick: handleRemove })
18737
- ] })
18738
- ] }) }) : value?.status === "processing" ? /* @__PURE__ */ jsx(Card, { padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", align: "center", justify: "center", gap: 3, children: [
19056
+ ] })
19057
+ ] }) }),
19058
+ isBrowserOpen && /* @__PURE__ */ jsx(
19059
+ BunnyBrowserModal,
19060
+ {
19061
+ config,
19062
+ collectionId: value.collectionId || config.collectionId,
19063
+ onSelect: handleBrowseSelect,
19064
+ onClose: () => setIsBrowserOpen(!1)
19065
+ }
19066
+ )
19067
+ ] }) : value?.status === "processing" ? /* @__PURE__ */ jsx(Card, { padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", align: "center", justify: "center", gap: 3, children: [
18739
19068
  /* @__PURE__ */ jsx(Spinner, {}),
18740
19069
  /* @__PURE__ */ jsx(Text, { size: 1, children: "Processing video..." }),
18741
19070
  /* @__PURE__ */ jsx(Text, { size: 0, muted: !0, children: "This may take a few minutes" })
@@ -18784,15 +19113,64 @@ function BunnyInput(props) {
18784
19113
  onChange: handleInputChange
18785
19114
  }
18786
19115
  )
18787
- ] }) : /* @__PURE__ */ jsx(
18788
- "input",
18789
- {
18790
- ref: fileInputRef,
18791
- type: "file",
18792
- accept: "video/*",
18793
- onChange: handleInputChange
18794
- }
18795
- );
19116
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
19117
+ /* @__PURE__ */ jsx("div", { style: { padding: 1 }, children: /* @__PURE__ */ jsx(Card, { tone: "inherit", border: !0, paddingX: 3, paddingY: 2, radius: 2, children: /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 4, justify: "space-between", children: [
19118
+ /* @__PURE__ */ jsxs(Flex, { flex: 1, align: "center", gap: 3, children: [
19119
+ /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: /* @__PURE__ */ jsx(VideoIcon, {}) }),
19120
+ /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "Drag or paste video here" })
19121
+ ] }),
19122
+ /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 1, children: [
19123
+ /* @__PURE__ */ jsxs("label", { style: { display: "contents" }, children: [
19124
+ /* @__PURE__ */ jsx(
19125
+ Button,
19126
+ {
19127
+ as: "span",
19128
+ icon: UploadIcon,
19129
+ text: "Upload",
19130
+ mode: "bleed",
19131
+ padding: 2,
19132
+ style: { cursor: "pointer" }
19133
+ }
19134
+ ),
19135
+ /* @__PURE__ */ jsx(
19136
+ "input",
19137
+ {
19138
+ ref: fileInputRef,
19139
+ type: "file",
19140
+ accept: "video/*",
19141
+ onChange: handleInputChange,
19142
+ style: {
19143
+ position: "absolute",
19144
+ width: "1px",
19145
+ height: "1px",
19146
+ overflow: "hidden",
19147
+ opacity: 0
19148
+ }
19149
+ }
19150
+ )
19151
+ ] }),
19152
+ /* @__PURE__ */ jsx(
19153
+ Button,
19154
+ {
19155
+ icon: SearchIcon,
19156
+ text: "Select",
19157
+ mode: "bleed",
19158
+ padding: 2,
19159
+ onClick: () => setIsBrowserOpen(!0)
19160
+ }
19161
+ )
19162
+ ] })
19163
+ ] }) }) }),
19164
+ isBrowserOpen && /* @__PURE__ */ jsx(
19165
+ BunnyBrowserModal,
19166
+ {
19167
+ config,
19168
+ collectionId: config.collectionId,
19169
+ onSelect: handleBrowseSelect,
19170
+ onClose: () => setIsBrowserOpen(!1)
19171
+ }
19172
+ )
19173
+ ] });
18796
19174
  }
18797
19175
  function BunnyPreview(props) {
18798
19176
  const { title, status, thumbnailUrl } = props, statusColors = {
@@ -18958,6 +19336,19 @@ const createBunnyVideoSchema = (config) => defineType({
18958
19336
  name: "ratio",
18959
19337
  readOnly: !0
18960
19338
  }),
19339
+ defineField({
19340
+ type: "string",
19341
+ title: "Orientation",
19342
+ name: "orientation",
19343
+ options: {
19344
+ list: [
19345
+ { title: "Landscape", value: "landscape" },
19346
+ { title: "Portrait", value: "portrait" },
19347
+ { title: "Square", value: "square" }
19348
+ ]
19349
+ },
19350
+ readOnly: !0
19351
+ }),
18961
19352
  defineField({
18962
19353
  type: "string",
18963
19354
  title: "Thumbnail URL",